2026-03-29 05:32:45 +07:00

72 lines
2.5 KiB
TypeScript

// packages/core/src/components/dialog/dialog-context.ts
import type { Accessor } from "solid-js";
import { createContext, useContext } from "solid-js";
// ─── Internal Context (used only by Dialog parts) ──────────────────────────
export interface InternalDialogContextValue {
isOpen: Accessor<boolean>;
setOpen: (open: boolean) => void;
modal: Accessor<boolean>;
/** SSR-safe ID for Dialog.Content element */
contentId: Accessor<string>;
/** Registered ID from Dialog.Title — used for aria-labelledby */
titleId: Accessor<string | undefined>;
setTitleId: (id: string | undefined) => void;
/** Registered ID from Dialog.Description — used for aria-describedby */
descriptionId: Accessor<string | undefined>;
setDescriptionId: (id: string | undefined) => void;
/** Whether Dialog.Trigger has been explicitly rendered */
hasTrigger: Accessor<boolean>;
setHasTrigger: (has: boolean) => void;
}
const InternalDialogContext = createContext<InternalDialogContextValue>();
/**
* Returns the internal Dialog context value.
* Throws if used outside of a Dialog root.
*/
export function useInternalDialogContext(): InternalDialogContextValue {
const ctx = useContext(InternalDialogContext);
if (!ctx) {
throw new Error(
"[PettyUI] Dialog parts must be used inside <Dialog>.\n" +
" Fix: Wrap your Dialog.Content, Dialog.Trigger, etc. inside <Dialog>.\n" +
" Docs: https://pettyui.dev/components/dialog#composition",
);
}
return ctx;
}
export const InternalDialogContextProvider = InternalDialogContext.Provider;
// ─── Public Context (exported via Dialog.useContext) ───────────────────────
export interface DialogContextValue {
/** Whether the dialog is currently open. */
open: Accessor<boolean>;
/** Whether the dialog renders as a modal (blocks outside interaction). */
modal: Accessor<boolean>;
}
const DialogContext = createContext<DialogContextValue>();
/**
* Returns the public Dialog context value.
* Throws if used outside of a Dialog root.
*/
export function useDialogContext(): DialogContextValue {
const ctx = useContext(DialogContext);
if (!ctx) {
throw new Error(
"[PettyUI] Dialog.useContext() was called outside of a <Dialog>.\n" +
" Fix: Call Dialog.useContext() inside a component rendered within <Dialog>.\n" +
" Docs: https://pettyui.dev/components/dialog#context",
);
}
return ctx;
}
export const DialogContextProvider = DialogContext.Provider;