@compa11y/react 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/chunk-36S2JYVF.cjs +1 -0
  2. package/dist/chunk-AJ7JSWUT.cjs +1 -0
  3. package/dist/chunk-DDFEION3.cjs +1 -0
  4. package/dist/chunk-DWU3PTJO.cjs +1 -0
  5. package/dist/chunk-FD4F6ONU.cjs +1 -0
  6. package/dist/chunk-FOVHQAY5.cjs +1 -0
  7. package/dist/chunk-GITBIGD4.js +1 -0
  8. package/dist/chunk-HEA4NAOM.js +1 -0
  9. package/dist/chunk-IZ7LLPPV.js +1 -0
  10. package/dist/chunk-JS3UD7KS.cjs +1 -0
  11. package/dist/chunk-MAR6RBHF.cjs +1 -0
  12. package/dist/chunk-MD4AVTLT.js +1 -0
  13. package/dist/chunk-SB6ASQ36.js +1 -0
  14. package/dist/chunk-VMM4K2K4.js +1 -0
  15. package/dist/chunk-XEJXACWE.js +1 -0
  16. package/dist/chunk-ZB3SYGHE.js +1 -0
  17. package/dist/components/combobox/index.cjs +1 -31
  18. package/dist/components/combobox/index.js +1 -6
  19. package/dist/components/dialog/index.cjs +1 -46
  20. package/dist/components/dialog/index.js +1 -5
  21. package/dist/components/menu/index.cjs +1 -46
  22. package/dist/components/menu/index.js +1 -5
  23. package/dist/components/tabs/index.cjs +1 -35
  24. package/dist/components/tabs/index.js +1 -6
  25. package/dist/components/toast/index.cjs +1 -24
  26. package/dist/components/toast/index.js +1 -3
  27. package/dist/index.cjs +1 -3714
  28. package/dist/index.js +1 -3408
  29. package/package.json +2 -2
  30. package/dist/chunk-2S4C6FGA.js +0 -380
  31. package/dist/chunk-2S4C6FGA.js.map +0 -1
  32. package/dist/chunk-52J4Z3QD.cjs +0 -45
  33. package/dist/chunk-52J4Z3QD.cjs.map +0 -1
  34. package/dist/chunk-C7QK2I7H.js +0 -373
  35. package/dist/chunk-C7QK2I7H.js.map +0 -1
  36. package/dist/chunk-D2UMS62N.cjs +0 -245
  37. package/dist/chunk-D2UMS62N.cjs.map +0 -1
  38. package/dist/chunk-E265U2RK.js +0 -234
  39. package/dist/chunk-E265U2RK.js.map +0 -1
  40. package/dist/chunk-E4XJRXWM.js +0 -215
  41. package/dist/chunk-E4XJRXWM.js.map +0 -1
  42. package/dist/chunk-GDLOJH6K.cjs +0 -110
  43. package/dist/chunk-GDLOJH6K.cjs.map +0 -1
  44. package/dist/chunk-IR46CNNY.cjs +0 -329
  45. package/dist/chunk-IR46CNNY.cjs.map +0 -1
  46. package/dist/chunk-JXYOE7SH.js +0 -103
  47. package/dist/chunk-JXYOE7SH.js.map +0 -1
  48. package/dist/chunk-O3YYQZ5O.js +0 -317
  49. package/dist/chunk-O3YYQZ5O.js.map +0 -1
  50. package/dist/chunk-OIVTOU4Z.cjs +0 -386
  51. package/dist/chunk-OIVTOU4Z.cjs.map +0 -1
  52. package/dist/chunk-OND5B7UG.js +0 -85
  53. package/dist/chunk-OND5B7UG.js.map +0 -1
  54. package/dist/chunk-R4FR6M6I.cjs +0 -383
  55. package/dist/chunk-R4FR6M6I.cjs.map +0 -1
  56. package/dist/chunk-RBDQCIS7.cjs +0 -89
  57. package/dist/chunk-RBDQCIS7.cjs.map +0 -1
  58. package/dist/chunk-SOBS7MIH.cjs +0 -220
  59. package/dist/chunk-SOBS7MIH.cjs.map +0 -1
  60. package/dist/chunk-WURPAE3R.js +0 -41
  61. package/dist/chunk-WURPAE3R.js.map +0 -1
  62. package/dist/components/combobox/index.cjs.map +0 -1
  63. package/dist/components/combobox/index.js.map +0 -1
  64. package/dist/components/dialog/index.cjs.map +0 -1
  65. package/dist/components/dialog/index.js.map +0 -1
  66. package/dist/components/menu/index.cjs.map +0 -1
  67. package/dist/components/menu/index.js.map +0 -1
  68. package/dist/components/tabs/index.cjs.map +0 -1
  69. package/dist/components/tabs/index.js.map +0 -1
  70. package/dist/components/toast/index.cjs.map +0 -1
  71. package/dist/components/toast/index.js.map +0 -1
  72. package/dist/index.cjs.map +0 -1
  73. package/dist/index.js.map +0 -1
@@ -1,317 +0,0 @@
1
- import { useAnnouncer } from './chunk-OND5B7UG.js';
2
- import { useId } from './chunk-WURPAE3R.js';
3
- import { createContext, forwardRef, useEffect, useContext, useState, useCallback, useRef } from 'react';
4
- import { createPortal } from 'react-dom';
5
- import { createComponentWarnings, createFocusTrap } from '@compa11y/core';
6
- import { jsx } from 'react/jsx-runtime';
7
-
8
- function useFocusTrap(options = {}) {
9
- const { active = true, ...trapOptions } = options;
10
- const containerRef = useRef(null);
11
- const trapRef = useRef(null);
12
- useEffect(() => {
13
- const container = containerRef.current;
14
- if (!container) return;
15
- trapRef.current = createFocusTrap(container, trapOptions);
16
- if (active) {
17
- trapRef.current.activate();
18
- }
19
- return () => {
20
- trapRef.current?.destroy();
21
- trapRef.current = null;
22
- };
23
- }, [
24
- trapOptions.initialFocus,
25
- trapOptions.returnFocus,
26
- trapOptions.clickOutsideDeactivates,
27
- trapOptions.escapeDeactivates,
28
- trapOptions.onDeactivate
29
- ]);
30
- useEffect(() => {
31
- if (!trapRef.current) return;
32
- if (active) {
33
- trapRef.current.activate();
34
- } else {
35
- trapRef.current.deactivate();
36
- }
37
- }, [active]);
38
- return containerRef;
39
- }
40
- function useFocusTrapControls(options = {}) {
41
- const containerRef = useRef(null);
42
- const trapRef = useRef(null);
43
- const activate = useCallback(() => {
44
- const container = containerRef.current;
45
- if (!container) return;
46
- if (!trapRef.current) {
47
- trapRef.current = createFocusTrap(container, options);
48
- }
49
- trapRef.current.activate();
50
- }, [options]);
51
- const deactivate = useCallback(() => {
52
- trapRef.current?.deactivate();
53
- }, []);
54
- const pause = useCallback(() => {
55
- trapRef.current?.pause();
56
- }, []);
57
- const unpause = useCallback(() => {
58
- trapRef.current?.unpause();
59
- }, []);
60
- useEffect(() => {
61
- return () => {
62
- trapRef.current?.destroy();
63
- trapRef.current = null;
64
- };
65
- }, []);
66
- return {
67
- ref: containerRef,
68
- activate,
69
- deactivate,
70
- pause,
71
- unpause,
72
- isActive: () => trapRef.current?.isActive() ?? false,
73
- isPaused: () => trapRef.current?.isPaused() ?? false
74
- };
75
- }
76
- var DialogContext = createContext(null);
77
- function useDialogContext() {
78
- const context = useContext(DialogContext);
79
- if (!context) {
80
- throw new Error(
81
- "Dialog compound components must be used within a Dialog component"
82
- );
83
- }
84
- return context;
85
- }
86
- var DialogProvider = DialogContext.Provider;
87
- var warnings = createComponentWarnings("Dialog");
88
- function Dialog({
89
- open,
90
- onOpenChange,
91
- children,
92
- className,
93
- initialFocus,
94
- closeOnOutsideClick = true,
95
- closeOnEscape = true,
96
- container,
97
- "aria-label": ariaLabel,
98
- "aria-labelledby": ariaLabelledBy,
99
- unstyled = false
100
- }) {
101
- const dialogId = useId("dialog");
102
- const titleId = useId("dialog-title");
103
- const descriptionId = useId("dialog-desc");
104
- const [hasTitle, setHasTitle] = useState(false);
105
- const [hasDescription, setHasDescription] = useState(false);
106
- const close = useCallback(() => {
107
- onOpenChange(false);
108
- }, [onOpenChange]);
109
- useEffect(() => {
110
- if (open && !hasTitle && !ariaLabel && !ariaLabelledBy) {
111
- warnings.warning(
112
- "Dialog has no accessible title. Add a DialogTitle or aria-label prop.",
113
- 'Use <Dialog.Title> or provide aria-label="..."'
114
- );
115
- }
116
- }, [open, hasTitle, ariaLabel, ariaLabelledBy]);
117
- const contextValue = {
118
- isOpen: open,
119
- close,
120
- dialogId,
121
- titleId,
122
- descriptionId,
123
- hasTitle,
124
- hasDescription,
125
- setHasTitle,
126
- setHasDescription
127
- };
128
- if (!open) {
129
- return null;
130
- }
131
- const dialogContent = /* @__PURE__ */ jsx(DialogProvider, { value: contextValue, children: /* @__PURE__ */ jsx(
132
- DialogOverlay,
133
- {
134
- className,
135
- closeOnOutsideClick,
136
- closeOnEscape,
137
- initialFocus,
138
- ariaLabel,
139
- ariaLabelledBy,
140
- unstyled,
141
- children
142
- }
143
- ) });
144
- const portalContainer = container ?? document.body;
145
- return createPortal(dialogContent, portalContainer);
146
- }
147
- function DialogOverlay({
148
- children,
149
- className,
150
- closeOnOutsideClick,
151
- closeOnEscape,
152
- initialFocus,
153
- ariaLabel,
154
- ariaLabelledBy,
155
- unstyled
156
- }) {
157
- const { close, dialogId, titleId, descriptionId, hasTitle, hasDescription } = useDialogContext();
158
- const { announce } = useAnnouncer();
159
- const trapRef = useFocusTrap({
160
- active: true,
161
- initialFocus: initialFocus?.current ?? void 0,
162
- escapeDeactivates: closeOnEscape,
163
- // Don't use clickOutsideDeactivates - we handle this in handleOverlayClick
164
- clickOutsideDeactivates: false,
165
- onDeactivate: close
166
- });
167
- useEffect(() => {
168
- announce("Dialog opened", { politeness: "polite" });
169
- return () => {
170
- announce("Dialog closed", { politeness: "polite" });
171
- };
172
- }, [announce]);
173
- useEffect(() => {
174
- const originalOverflow = document.body.style.overflow;
175
- document.body.style.overflow = "hidden";
176
- return () => {
177
- document.body.style.overflow = originalOverflow;
178
- };
179
- }, []);
180
- const handleOverlayClick = (event) => {
181
- if (closeOnOutsideClick && event.target === event.currentTarget) {
182
- close();
183
- }
184
- };
185
- const labelledBy = ariaLabelledBy ?? (hasTitle ? titleId : void 0);
186
- const describedBy = hasDescription ? descriptionId : void 0;
187
- const handleDialogClick = (event) => {
188
- event.stopPropagation();
189
- };
190
- const overlayStructuralStyles = {
191
- position: "fixed",
192
- inset: 0,
193
- display: "flex",
194
- alignItems: "center",
195
- justifyContent: "center",
196
- zIndex: 9999
197
- };
198
- const overlayVisualStyles = unstyled ? {} : {
199
- backgroundColor: "rgba(0, 0, 0, 0.5)"
200
- };
201
- const overlayStyles = {
202
- ...overlayStructuralStyles,
203
- ...overlayVisualStyles
204
- };
205
- const dialogStyles = unstyled ? {} : {
206
- backgroundColor: "white",
207
- borderRadius: "8px",
208
- padding: "1.5rem",
209
- minWidth: "300px",
210
- maxWidth: "500px",
211
- boxShadow: "0 10px 25px rgba(0, 0, 0, 0.2)"
212
- };
213
- return /* @__PURE__ */ jsx(
214
- "div",
215
- {
216
- className,
217
- style: overlayStyles,
218
- onClick: handleOverlayClick,
219
- "data-compa11y-dialog-overlay": true,
220
- children: /* @__PURE__ */ jsx(
221
- "div",
222
- {
223
- ref: trapRef,
224
- id: dialogId,
225
- role: "dialog",
226
- "aria-modal": "true",
227
- "aria-label": ariaLabel,
228
- "aria-labelledby": labelledBy,
229
- "aria-describedby": describedBy,
230
- onClick: handleDialogClick,
231
- style: dialogStyles,
232
- "data-compa11y-dialog": true,
233
- children
234
- }
235
- )
236
- }
237
- );
238
- }
239
- var DialogTrigger = forwardRef(
240
- function DialogTrigger2({ children, ...props }, ref) {
241
- return /* @__PURE__ */ jsx(
242
- "button",
243
- {
244
- ref,
245
- type: "button",
246
- tabIndex: 0,
247
- "data-compa11y-dialog-trigger": true,
248
- ...props,
249
- children
250
- }
251
- );
252
- }
253
- );
254
- var DialogTitle = forwardRef(
255
- function DialogTitle2({ as: Component = "h2", children, ...props }, ref) {
256
- const { titleId, setHasTitle } = useDialogContext();
257
- useEffect(() => {
258
- setHasTitle(true);
259
- return () => setHasTitle(false);
260
- }, [setHasTitle]);
261
- return /* @__PURE__ */ jsx(Component, { ref, id: titleId, "data-compa11y-dialog-title": true, ...props, children });
262
- }
263
- );
264
- var DialogDescription = forwardRef(function DialogDescription2({ children, ...props }, ref) {
265
- const { descriptionId, setHasDescription } = useDialogContext();
266
- useEffect(() => {
267
- setHasDescription(true);
268
- return () => setHasDescription(false);
269
- }, [setHasDescription]);
270
- return /* @__PURE__ */ jsx("p", { ref, id: descriptionId, "data-compa11y-dialog-description": true, ...props, children });
271
- });
272
- var DialogClose = forwardRef(
273
- function DialogClose2({ children, onClick, ...props }, ref) {
274
- const { close } = useDialogContext();
275
- const handleClick = (event) => {
276
- onClick?.(event);
277
- if (!event.defaultPrevented) {
278
- close();
279
- }
280
- };
281
- return /* @__PURE__ */ jsx(
282
- "button",
283
- {
284
- ref,
285
- type: "button",
286
- tabIndex: 0,
287
- onClick: handleClick,
288
- "aria-label": children ? void 0 : "Close dialog",
289
- "data-compa11y-dialog-close": true,
290
- ...props,
291
- children: children ?? "\xD7"
292
- }
293
- );
294
- }
295
- );
296
- var DialogContent = forwardRef(
297
- function DialogContent2({ children, ...props }, ref) {
298
- return /* @__PURE__ */ jsx("div", { ref, "data-compa11y-dialog-content": true, ...props, children });
299
- }
300
- );
301
- var DialogActions = forwardRef(
302
- function DialogActions2({ children, ...props }, ref) {
303
- return /* @__PURE__ */ jsx("div", { ref, "data-compa11y-dialog-actions": true, ...props, children });
304
- }
305
- );
306
- var DialogCompound = Object.assign(Dialog, {
307
- Trigger: DialogTrigger,
308
- Title: DialogTitle,
309
- Description: DialogDescription,
310
- Close: DialogClose,
311
- Content: DialogContent,
312
- Actions: DialogActions
313
- });
314
-
315
- export { Dialog, DialogActions, DialogClose, DialogCompound, DialogContent, DialogDescription, DialogTitle, DialogTrigger, useDialogContext, useFocusTrap, useFocusTrapControls };
316
- //# sourceMappingURL=chunk-O3YYQZ5O.js.map
317
- //# sourceMappingURL=chunk-O3YYQZ5O.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/hooks/use-focus-trap.ts","../src/components/dialog/dialog-context.ts","../src/components/dialog/dialog.tsx"],"names":["useCallback","useEffect","DialogTrigger","DialogTitle","DialogDescription","DialogClose","DialogContent","DialogActions"],"mappings":"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","file":"chunk-O3YYQZ5O.js","sourcesContent":["import { useEffect, useRef, useCallback } from 'react';\nimport { createFocusTrap, type FocusTrapOptions } from '@compa11y/core';\n\nexport interface UseFocusTrapOptions extends FocusTrapOptions {\n /** Whether the focus trap is active */\n active?: boolean;\n}\n\n/**\n * Hook to create a focus trap for modals, dialogs, etc.\n *\n * @example\n * ```tsx\n * function Modal({ isOpen, onClose }) {\n * const trapRef = useFocusTrap({\n * active: isOpen,\n * onDeactivate: onClose,\n * });\n *\n * return (\n * <div ref={trapRef} role=\"dialog\">\n * <button>Close</button>\n * </div>\n * );\n * }\n * ```\n */\nexport function useFocusTrap<T extends HTMLElement = HTMLDivElement>(\n options: UseFocusTrapOptions = {}\n): React.RefObject<T> {\n const { active = true, ...trapOptions } = options;\n const containerRef = useRef<T>(null);\n const trapRef = useRef<ReturnType<typeof createFocusTrap> | null>(null);\n\n useEffect(() => {\n const container = containerRef.current;\n if (!container) return;\n\n trapRef.current = createFocusTrap(container, trapOptions);\n\n if (active) {\n trapRef.current.activate();\n }\n\n return () => {\n // Use destroy() instead of deactivate() to avoid calling onDeactivate\n // during cleanup (which would cause issues with React Strict Mode)\n trapRef.current?.destroy();\n trapRef.current = null;\n };\n }, [\n trapOptions.initialFocus,\n trapOptions.returnFocus,\n trapOptions.clickOutsideDeactivates,\n trapOptions.escapeDeactivates,\n trapOptions.onDeactivate,\n ]);\n\n useEffect(() => {\n if (!trapRef.current) return;\n\n if (active) {\n trapRef.current.activate();\n } else {\n trapRef.current.deactivate();\n }\n }, [active]);\n\n return containerRef;\n}\n\n/**\n * Imperative focus trap controls\n */\nexport function useFocusTrapControls<T extends HTMLElement = HTMLDivElement>(\n options: Omit<FocusTrapOptions, 'onDeactivate'> = {}\n) {\n const containerRef = useRef<T | null>(null);\n const trapRef = useRef<ReturnType<typeof createFocusTrap> | null>(null);\n\n const activate = useCallback(() => {\n const container = containerRef.current;\n if (!container) return;\n\n if (!trapRef.current) {\n trapRef.current = createFocusTrap(container, options);\n }\n trapRef.current.activate();\n }, [options]);\n\n const deactivate = useCallback(() => {\n trapRef.current?.deactivate();\n }, []);\n\n const pause = useCallback(() => {\n trapRef.current?.pause();\n }, []);\n\n const unpause = useCallback(() => {\n trapRef.current?.unpause();\n }, []);\n\n useEffect(() => {\n return () => {\n // Use destroy() for cleanup to avoid calling onDeactivate during unmount\n trapRef.current?.destroy();\n trapRef.current = null;\n };\n }, []);\n\n return {\n ref: containerRef,\n activate,\n deactivate,\n pause,\n unpause,\n isActive: () => trapRef.current?.isActive() ?? false,\n isPaused: () => trapRef.current?.isPaused() ?? false,\n };\n}\n","import { createContext, useContext } from 'react';\n\nexport interface DialogContextValue {\n /** Whether the dialog is open */\n isOpen: boolean;\n /** Close the dialog */\n close: () => void;\n /** ID for the dialog element */\n dialogId: string;\n /** ID for the title element */\n titleId: string;\n /** ID for the description element */\n descriptionId: string;\n /** Whether the dialog has a visible title */\n hasTitle: boolean;\n /** Whether the dialog has a visible description */\n hasDescription: boolean;\n /** Set whether title is rendered */\n setHasTitle: (value: boolean) => void;\n /** Set whether description is rendered */\n setHasDescription: (value: boolean) => void;\n}\n\nconst DialogContext = createContext<DialogContextValue | null>(null);\n\nexport function useDialogContext(): DialogContextValue {\n const context = useContext(DialogContext);\n if (!context) {\n throw new Error(\n 'Dialog compound components must be used within a Dialog component'\n );\n }\n return context;\n}\n\nexport const DialogProvider = DialogContext.Provider;\n","import React, { forwardRef, useCallback, useEffect, useState } from 'react';\nimport { createPortal } from 'react-dom';\nimport { useId } from '../../hooks/use-id';\nimport { useFocusTrap } from '../../hooks/use-focus-trap';\nimport { useAnnouncer } from '../../hooks/use-announcer';\nimport { DialogProvider, useDialogContext } from './dialog-context';\nimport { createComponentWarnings } from '@compa11y/core';\n\nconst warnings = createComponentWarnings('Dialog');\n\nexport interface DialogProps {\n /** Whether the dialog is open */\n open: boolean;\n /** Called when the dialog should close */\n onOpenChange: (open: boolean) => void;\n /** The dialog content */\n children: React.ReactNode;\n /** Custom class name */\n className?: string;\n /** Element to focus when dialog opens */\n initialFocus?: React.RefObject<HTMLElement>;\n /** Whether clicking outside closes the dialog */\n closeOnOutsideClick?: boolean;\n /** Whether pressing Escape closes the dialog */\n closeOnEscape?: boolean;\n /** Portal container (defaults to document.body) */\n container?: HTMLElement;\n /** Accessible label (required if no DialogTitle) */\n 'aria-label'?: string;\n /** ID of element that labels the dialog */\n 'aria-labelledby'?: string;\n /** Remove default styles to allow full customization via className */\n unstyled?: boolean;\n}\n\nexport function Dialog({\n open,\n onOpenChange,\n children,\n className,\n initialFocus,\n closeOnOutsideClick = true,\n closeOnEscape = true,\n container,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n unstyled = false,\n}: DialogProps) {\n const dialogId = useId('dialog');\n const titleId = useId('dialog-title');\n const descriptionId = useId('dialog-desc');\n\n const [hasTitle, setHasTitle] = useState(false);\n const [hasDescription, setHasDescription] = useState(false);\n\n const close = useCallback(() => {\n onOpenChange(false);\n }, [onOpenChange]);\n\n // Warn if no accessible label\n useEffect(() => {\n if (open && !hasTitle && !ariaLabel && !ariaLabelledBy) {\n warnings.warning(\n 'Dialog has no accessible title. Add a DialogTitle or aria-label prop.',\n 'Use <Dialog.Title> or provide aria-label=\"...\"'\n );\n }\n }, [open, hasTitle, ariaLabel, ariaLabelledBy]);\n\n const contextValue = {\n isOpen: open,\n close,\n dialogId,\n titleId,\n descriptionId,\n hasTitle,\n hasDescription,\n setHasTitle,\n setHasDescription,\n };\n\n if (!open) {\n return null;\n }\n\n const dialogContent = (\n <DialogProvider value={contextValue}>\n <DialogOverlay\n className={className}\n closeOnOutsideClick={closeOnOutsideClick}\n closeOnEscape={closeOnEscape}\n initialFocus={initialFocus}\n ariaLabel={ariaLabel}\n ariaLabelledBy={ariaLabelledBy}\n unstyled={unstyled}\n >\n {children}\n </DialogOverlay>\n </DialogProvider>\n );\n\n const portalContainer = container ?? document.body;\n return createPortal(dialogContent, portalContainer);\n}\n\ninterface DialogOverlayProps {\n children: React.ReactNode;\n className?: string;\n closeOnOutsideClick: boolean;\n closeOnEscape: boolean;\n initialFocus?: React.RefObject<HTMLElement>;\n ariaLabel?: string;\n ariaLabelledBy?: string;\n unstyled: boolean;\n}\n\nfunction DialogOverlay({\n children,\n className,\n closeOnOutsideClick,\n closeOnEscape,\n initialFocus,\n ariaLabel,\n ariaLabelledBy,\n unstyled,\n}: DialogOverlayProps) {\n const { close, dialogId, titleId, descriptionId, hasTitle, hasDescription } =\n useDialogContext();\n const { announce } = useAnnouncer();\n\n const trapRef = useFocusTrap<HTMLDivElement>({\n active: true,\n initialFocus: initialFocus?.current ?? undefined,\n escapeDeactivates: closeOnEscape,\n // Don't use clickOutsideDeactivates - we handle this in handleOverlayClick\n clickOutsideDeactivates: false,\n onDeactivate: close,\n });\n\n useEffect(() => {\n announce('Dialog opened', { politeness: 'polite' });\n return () => {\n announce('Dialog closed', { politeness: 'polite' });\n };\n }, [announce]);\n\n useEffect(() => {\n const originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n return () => {\n document.body.style.overflow = originalOverflow;\n };\n }, []);\n\n const handleOverlayClick = (event: React.MouseEvent) => {\n if (closeOnOutsideClick && event.target === event.currentTarget) {\n close();\n }\n };\n\n const labelledBy = ariaLabelledBy ?? (hasTitle ? titleId : undefined);\n const describedBy = hasDescription ? descriptionId : undefined;\n\n const handleDialogClick = (event: React.MouseEvent) => {\n // Prevent clicks inside dialog from bubbling to overlay\n event.stopPropagation();\n };\n\n const overlayStructuralStyles: React.CSSProperties = {\n position: 'fixed',\n inset: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 9999,\n };\n\n // Visual styles - only applied when not unstyled\n const overlayVisualStyles: React.CSSProperties = unstyled\n ? {}\n : {\n backgroundColor: 'rgba(0, 0, 0, 0.5)',\n };\n\n const overlayStyles: React.CSSProperties = {\n ...overlayStructuralStyles,\n ...overlayVisualStyles,\n };\n\n // Visual styles for dialog panel - only applied when not unstyled\n const dialogStyles: React.CSSProperties = unstyled\n ? {}\n : {\n backgroundColor: 'white',\n borderRadius: '8px',\n padding: '1.5rem',\n minWidth: '300px',\n maxWidth: '500px',\n boxShadow: '0 10px 25px rgba(0, 0, 0, 0.2)',\n };\n\n return (\n <div\n className={className}\n style={overlayStyles}\n onClick={handleOverlayClick}\n data-compa11y-dialog-overlay\n >\n <div\n ref={trapRef}\n id={dialogId}\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={labelledBy}\n aria-describedby={describedBy}\n onClick={handleDialogClick}\n style={dialogStyles}\n data-compa11y-dialog\n >\n {children}\n </div>\n </div>\n );\n}\n\nexport interface DialogTriggerProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children: React.ReactNode;\n}\n\nexport const DialogTrigger = forwardRef<HTMLButtonElement, DialogTriggerProps>(\n function DialogTrigger({ children, ...props }, ref) {\n return (\n <button\n ref={ref}\n type=\"button\"\n // Safari fix: Ensure button is in tab order (Safari skips buttons by default)\n tabIndex={0}\n data-compa11y-dialog-trigger\n {...props}\n >\n {children}\n </button>\n );\n }\n);\n\nexport interface DialogTitleProps extends React.HTMLAttributes<HTMLHeadingElement> {\n as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';\n children: React.ReactNode;\n}\n\nexport const DialogTitle = forwardRef<HTMLHeadingElement, DialogTitleProps>(\n function DialogTitle({ as: Component = 'h2', children, ...props }, ref) {\n const { titleId, setHasTitle } = useDialogContext();\n\n useEffect(() => {\n setHasTitle(true);\n return () => setHasTitle(false);\n }, [setHasTitle]);\n\n return (\n <Component ref={ref} id={titleId} data-compa11y-dialog-title {...props}>\n {children}\n </Component>\n );\n }\n);\n\nexport interface DialogDescriptionProps extends React.HTMLAttributes<HTMLParagraphElement> {\n children: React.ReactNode;\n}\n\nexport const DialogDescription = forwardRef<\n HTMLParagraphElement,\n DialogDescriptionProps\n>(function DialogDescription({ children, ...props }, ref) {\n const { descriptionId, setHasDescription } = useDialogContext();\n\n useEffect(() => {\n setHasDescription(true);\n return () => setHasDescription(false);\n }, [setHasDescription]);\n\n return (\n <p ref={ref} id={descriptionId} data-compa11y-dialog-description {...props}>\n {children}\n </p>\n );\n});\n\nexport interface DialogCloseProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {\n children?: React.ReactNode;\n}\n\nexport const DialogClose = forwardRef<HTMLButtonElement, DialogCloseProps>(\n function DialogClose({ children, onClick, ...props }, ref) {\n const { close } = useDialogContext();\n\n const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event);\n if (!event.defaultPrevented) {\n close();\n }\n };\n\n return (\n <button\n ref={ref}\n type=\"button\"\n // Safari fix: Ensure button is in tab order (Safari skips buttons by default)\n tabIndex={0}\n onClick={handleClick}\n aria-label={children ? undefined : 'Close dialog'}\n data-compa11y-dialog-close\n {...props}\n >\n {children ?? '×'}\n </button>\n );\n }\n);\n\nexport interface DialogContentProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport const DialogContent = forwardRef<HTMLDivElement, DialogContentProps>(\n function DialogContent({ children, ...props }, ref) {\n return (\n <div ref={ref} data-compa11y-dialog-content {...props}>\n {children}\n </div>\n );\n }\n);\n\nexport interface DialogActionsProps extends React.HTMLAttributes<HTMLDivElement> {\n children: React.ReactNode;\n}\n\nexport const DialogActions = forwardRef<HTMLDivElement, DialogActionsProps>(\n function DialogActions({ children, ...props }, ref) {\n return (\n <div ref={ref} data-compa11y-dialog-actions {...props}>\n {children}\n </div>\n );\n }\n);\n\nexport const DialogCompound = Object.assign(Dialog, {\n Trigger: DialogTrigger,\n Title: DialogTitle,\n Description: DialogDescription,\n Close: DialogClose,\n Content: DialogContent,\n Actions: DialogActions,\n});\n"]}