Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/modern-cats-cross.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cube-dev/ui-kit': patch
---

Allow to pass props for DialogContainer in useDialogContainer hook.
50 changes: 43 additions & 7 deletions src/components/overlays/Dialog/dialog-container.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import React, { useState, useMemo } from 'react';
import {
useState,
useMemo,
ComponentProps,
ComponentType,
useRef,
} from 'react';

import { useEvent } from '../../../_internal/index';

Expand All @@ -10,30 +16,60 @@ import { DialogContainer } from './DialogContainer';
* @param Component - A React component that represents the dialog content. It must accept props of type P.
* @returns An object with `open` function to open the dialog with provided props and `rendered` JSX element to include in your component tree.
*/
export function useDialogContainer<P>(Component: React.ComponentType<P>) {
export function useDialogContainer<
P,
E = ComponentProps<typeof DialogContainer>,
>(Component: ComponentType<P>) {
const [isOpen, setIsOpen] = useState(false);
const [componentProps, setComponentProps] = useState<P | null>(null);
const [containerProps, setContainerProps] = useState<E | null>(null);
const setupRef = useRef(false);

// 'open' accepts props required by the Component and opens the dialog
const open = useEvent((props: P) => {
const open = useEvent((props: P, containerProps?: E) => {
setComponentProps(props);
setContainerProps(containerProps ?? null);
setIsOpen(true);
});

const update = useEvent((props: P, containerProps?: E) => {
setComponentProps(props);
setContainerProps(containerProps ?? null);
});

const close = useEvent(() => {
setIsOpen(false);
});

// Render the dialog only when componentProps is set
const rendered = useMemo(() => {
const renderedDialog = useMemo(() => {
if (!setupRef.current) {
throw new Error(
'useDialogContainer: DialogContainer must be rendered. Use `rendered` property to include it in your component tree.',
);
}

if (!componentProps) return null;

return (
<DialogContainer isOpen={isOpen} onDismiss={close}>
<DialogContainer
isOpen={isOpen}
onDismiss={close}
{...(containerProps ?? {})}
>
<Component {...componentProps} />
</DialogContainer>
);
}, [componentProps, isOpen]);
}, [componentProps, containerProps, isOpen]);

return {
open,
update,
close,
get rendered() {
setupRef.current = true;

return { open, close, rendered };
return renderedDialog;
},
};
}
Loading