72 lines
2.5 KiB
TypeScript
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;
|