@tribepad/themis 1.6.4 → 1.6.5

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 (94) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/elements/AlertDialog/index.js +1 -1
  3. package/dist/elements/AlertDialog/index.js.map +1 -1
  4. package/dist/elements/AlertDialog/index.mjs +1 -1
  5. package/dist/elements/AlertDialog/index.mjs.map +1 -1
  6. package/dist/elements/ColorPicker/index.js +1 -1
  7. package/dist/elements/ColorPicker/index.js.map +1 -1
  8. package/dist/elements/ColorPicker/index.mjs +1 -1
  9. package/dist/elements/ColorPicker/index.mjs.map +1 -1
  10. package/dist/elements/Combobox/index.js +1 -1
  11. package/dist/elements/Combobox/index.js.map +1 -1
  12. package/dist/elements/Combobox/index.mjs +1 -1
  13. package/dist/elements/Combobox/index.mjs.map +1 -1
  14. package/dist/elements/DatePicker/index.js +1 -1
  15. package/dist/elements/DatePicker/index.js.map +1 -1
  16. package/dist/elements/DatePicker/index.mjs +1 -1
  17. package/dist/elements/DatePicker/index.mjs.map +1 -1
  18. package/dist/elements/FileField/index.js +1 -1
  19. package/dist/elements/FileField/index.js.map +1 -1
  20. package/dist/elements/FileField/index.mjs +1 -1
  21. package/dist/elements/FileField/index.mjs.map +1 -1
  22. package/dist/elements/Filters/index.js +1 -1
  23. package/dist/elements/Filters/index.js.map +1 -1
  24. package/dist/elements/Filters/index.mjs +1 -1
  25. package/dist/elements/Filters/index.mjs.map +1 -1
  26. package/dist/elements/Modal/Modal.d.ts +2 -2
  27. package/dist/elements/Modal/Modal.d.ts.map +1 -1
  28. package/dist/elements/Modal/Modal.styles.d.ts +25 -0
  29. package/dist/elements/Modal/Modal.styles.d.ts.map +1 -1
  30. package/dist/elements/Modal/Modal.types.d.ts +27 -0
  31. package/dist/elements/Modal/Modal.types.d.ts.map +1 -1
  32. package/dist/elements/Modal/index.d.ts +3 -3
  33. package/dist/elements/Modal/index.d.ts.map +1 -1
  34. package/dist/elements/Modal/index.js +1 -1
  35. package/dist/elements/Modal/index.js.map +1 -1
  36. package/dist/elements/Modal/index.mjs +1 -1
  37. package/dist/elements/Modal/index.mjs.map +1 -1
  38. package/dist/elements/NumberField/index.js +1 -1
  39. package/dist/elements/NumberField/index.js.map +1 -1
  40. package/dist/elements/NumberField/index.mjs +1 -1
  41. package/dist/elements/NumberField/index.mjs.map +1 -1
  42. package/dist/elements/PasswordField/index.js +1 -1
  43. package/dist/elements/PasswordField/index.js.map +1 -1
  44. package/dist/elements/PasswordField/index.mjs +1 -1
  45. package/dist/elements/PasswordField/index.mjs.map +1 -1
  46. package/dist/elements/Resizable/index.js +1 -1
  47. package/dist/elements/Resizable/index.js.map +1 -1
  48. package/dist/elements/Resizable/index.mjs +1 -1
  49. package/dist/elements/Resizable/index.mjs.map +1 -1
  50. package/dist/elements/SearchField/index.js +1 -1
  51. package/dist/elements/SearchField/index.js.map +1 -1
  52. package/dist/elements/SearchField/index.mjs +1 -1
  53. package/dist/elements/SearchField/index.mjs.map +1 -1
  54. package/dist/elements/Select/index.js +1 -1
  55. package/dist/elements/Select/index.js.map +1 -1
  56. package/dist/elements/Select/index.mjs +1 -1
  57. package/dist/elements/Select/index.mjs.map +1 -1
  58. package/dist/elements/Sidebar/index.js +1 -1
  59. package/dist/elements/Sidebar/index.js.map +1 -1
  60. package/dist/elements/Sidebar/index.mjs +1 -1
  61. package/dist/elements/Sidebar/index.mjs.map +1 -1
  62. package/dist/elements/Table/index.js +1 -1
  63. package/dist/elements/Table/index.js.map +1 -1
  64. package/dist/elements/Table/index.mjs +1 -1
  65. package/dist/elements/Table/index.mjs.map +1 -1
  66. package/dist/elements/TextField/index.js +1 -1
  67. package/dist/elements/TextField/index.js.map +1 -1
  68. package/dist/elements/TextField/index.mjs +1 -1
  69. package/dist/elements/TextField/index.mjs.map +1 -1
  70. package/dist/elements/TimeField/index.js +1 -1
  71. package/dist/elements/TimeField/index.js.map +1 -1
  72. package/dist/elements/TimeField/index.mjs +1 -1
  73. package/dist/elements/TimeField/index.mjs.map +1 -1
  74. package/dist/elements/Wizard/index.js +1 -1
  75. package/dist/elements/Wizard/index.js.map +1 -1
  76. package/dist/elements/Wizard/index.mjs +1 -1
  77. package/dist/elements/Wizard/index.mjs.map +1 -1
  78. package/dist/elements/index.js +1 -1
  79. package/dist/elements/index.js.map +1 -1
  80. package/dist/elements/index.mjs +1 -1
  81. package/dist/elements/index.mjs.map +1 -1
  82. package/dist/index.js +2 -2
  83. package/dist/index.js.map +1 -1
  84. package/dist/index.mjs +2 -2
  85. package/dist/index.mjs.map +1 -1
  86. package/dist/styles/animations.css +32 -0
  87. package/dist/styles/index.js +1 -1
  88. package/dist/styles/index.js.map +1 -1
  89. package/dist/styles/index.mjs +1 -1
  90. package/dist/styles/index.mjs.map +1 -1
  91. package/dist/styles/shared-variants.d.ts +17 -0
  92. package/dist/styles/shared-variants.d.ts.map +1 -1
  93. package/package.json +1 -1
  94. package/src/elements/Modal/Modal.stories.tsx +106 -0
@@ -56,7 +56,7 @@ declare namespace ModalTrigger {
56
56
  * @see PRD.md TR-001 (CVA Variant Styling)
57
57
  * @see RESEARCH.md Section 2 (React Aria Integration)
58
58
  */
59
- declare function ModalContent({ children, size, animation, animationDuration, isDismissable, isKeyboardDismissDisabled, showClose, className, }: ModalContentProps): ReactElement;
59
+ declare function ModalContent({ children, size, animation, position, mobileBreakpoint, animationDuration, isDismissable, isKeyboardDismissDisabled, showClose, className, }: ModalContentProps): ReactElement;
60
60
  declare namespace ModalContent {
61
61
  var displayName: string;
62
62
  }
@@ -137,7 +137,7 @@ declare namespace ModalClose {
137
137
  * Consumers importing { modalContentVariants, modalOverlayVariants } from './Modal'
138
138
  * will continue to work.
139
139
  */
140
- export { modalContentVariants, modalOverlayVariants } from './Modal.styles';
140
+ export { modalContentVariants, modalOverlayVariants, modalPanelVariants } from './Modal.styles';
141
141
  /**
142
142
  * Compound Component Export
143
143
  *
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAML,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AAaf,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AAYvB;;;;;;;;;;;;GAYG;AACH,iBAAS,SAAS,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,IAAe,EAAE,EAAE,UAAU,GAAG,YAAY,CAsE7G;kBAtEQ,SAAS;;;AA0ElB;;;;;;;;;;;;;GAaG;AACH,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,YAAY,CAInE;kBAJQ,YAAY;;;AAQrB;;;;;;;;;;GAUG;AACH,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,IAAW,EACX,SAAuB,EACvB,iBAAuB,EACvB,aAAoB,EACpB,yBAAiC,EACjC,SAAgB,EAChB,SAAS,GACV,EAAE,iBAAiB,GAAG,YAAY,CA2ClC;kBApDQ,YAAY;;;AAwDrB;;;GAGG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAErD;kBAFQ,YAAY;;;AAMrB;;;;;;;GAOG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAE5E;kBAFQ,WAAW;;;AAMpB;;;;;;;;GAQG;AACH,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAS,EAAE,SAAS,EAAE,EAAE,eAAe,GAAG,YAAY,CAMrF;kBANQ,UAAU;;;AAUnB;;;;;;;;GAQG;AACH,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAMtF;kBANQ,gBAAgB;;;AAUzB;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAE5E;kBAFQ,WAAW;;;AAMpB;;;;;;;GAOG;AACH,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,YAAY,CA+B/D;kBA/BQ,UAAU;;;AAmCnB;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE5E;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK;;;;;;;;;CAShB,CAAC;AAGH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,GACX,CAAC"}
1
+ {"version":3,"file":"Modal.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;GASG;AAEH,OAAO,EAML,KAAK,YAAY,EAElB,MAAM,OAAO,CAAC;AAmBf,OAAO,KAAK,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EAChB,MAAM,eAAe,CAAC;AAYvB;;;;;;;;;;;;GAYG;AACH,iBAAS,SAAS,CAAC,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,IAAe,EAAE,EAAE,UAAU,GAAG,YAAY,CAsE7G;kBAtEQ,SAAS;;;AA0ElB;;;;;;;;;;;;;GAaG;AACH,iBAAS,YAAY,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,GAAG,YAAY,CAInE;kBAJQ,YAAY;;;AAQrB;;;;;;;;;;GAUG;AACH,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,IAAW,EACX,SAAuB,EACvB,QAAmB,EACnB,gBAAsB,EACtB,iBAAuB,EACvB,aAAoB,EACpB,yBAAiC,EACjC,SAAgB,EAChB,SAAS,GACV,EAAE,iBAAiB,GAAG,YAAY,CA+DlC;kBA1EQ,YAAY;;;AA8ErB;;;GAGG;AACH,iBAAS,YAAY,CAAC,MAAM,EAAE,iBAAiB,GAAG,IAAI,CAErD;kBAFQ,YAAY;;;AAMrB;;;;;;;GAOG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAE5E;kBAFQ,WAAW;;;AAMpB;;;;;;;;GAQG;AACH,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAS,EAAE,SAAS,EAAE,EAAE,eAAe,GAAG,YAAY,CAMrF;kBANQ,UAAU;;;AAUnB;;;;;;;;GAQG;AACH,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,qBAAqB,GAAG,YAAY,CAMtF;kBANQ,gBAAgB;;;AAUzB;;;;;;;;;GASG;AACH,iBAAS,WAAW,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,GAAG,YAAY,CAE5E;kBAFQ,WAAW;;;AAMpB;;;;;;;GAOG;AACH,iBAAS,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,eAAe,GAAG,YAAY,CA+B/D;kBA/BQ,UAAU;;;AAmCnB;;;;GAIG;AACH,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAEhG;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,KAAK;;;;;;;;;CAShB,CAAC;AAGH,OAAO,EACL,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,GACX,CAAC"}
@@ -21,11 +21,36 @@ export declare const modalContentVariants: (props?: ({
21
21
  */
22
22
  export declare const modalOverlayVariants: (props?: ({
23
23
  animation?: "none" | "slide" | "fade-zoom" | "fade" | null | undefined;
24
+ position?: "center" | "top" | "bottom" | "left" | "right" | null | undefined;
24
25
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
26
+ /**
27
+ * CVA Variants for an edge-anchored Modal drawer/sheet (Modal.Content `position`)
28
+ *
29
+ * The box styling for `position` ∈ {left, right, top, bottom}. `position` sets the
30
+ * full extent on the anchored axis plus the inner-edge border; `size` sets the
31
+ * cross-axis dimension (width for left/right, height for top/bottom) via compound
32
+ * variants. The directional slide animation is applied separately (see
33
+ * MODAL_PANEL_SLIDE) so it can be suppressed for `animation="none"`.
34
+ */
35
+ export declare const modalPanelVariants: (props?: ({
36
+ position?: "top" | "bottom" | "left" | "right" | null | undefined;
37
+ size?: "sm" | "lg" | "md" | "xl" | "full" | null | undefined;
38
+ } & import("class-variance-authority/types").ClassProp) | undefined) => string;
39
+ /**
40
+ * Directional slide classes per anchored edge, keyed by position.
41
+ * Applied to the drawer box unless `animation="none"`.
42
+ */
43
+ export declare const MODAL_PANEL_SLIDE: {
44
+ readonly left: readonly ["data-[entering]:animate-in", "data-[entering]:slide-in-from-left", "data-[entering]:duration-200", "data-[entering]:ease-out", "data-[exiting]:animate-out", "data-[exiting]:slide-out-to-left", "data-[exiting]:duration-150", "data-[exiting]:ease-in"];
45
+ readonly right: readonly ["data-[entering]:animate-in", "data-[entering]:slide-in-from-right", "data-[entering]:duration-200", "data-[entering]:ease-out", "data-[exiting]:animate-out", "data-[exiting]:slide-out-to-right", "data-[exiting]:duration-150", "data-[exiting]:ease-in"];
46
+ readonly top: readonly ["data-[entering]:animate-in", "data-[entering]:slide-in-from-top", "data-[entering]:duration-200", "data-[entering]:ease-out", "data-[exiting]:animate-out", "data-[exiting]:slide-out-to-top", "data-[exiting]:duration-150", "data-[exiting]:ease-in"];
47
+ readonly bottom: readonly ["data-[entering]:animate-in", "data-[entering]:slide-in-from-bottom", "data-[entering]:duration-200", "data-[entering]:ease-out", "data-[exiting]:animate-out", "data-[exiting]:slide-out-to-bottom", "data-[exiting]:duration-150", "data-[exiting]:ease-in"];
48
+ };
25
49
  /**
26
50
  * Type exports for variant props
27
51
  * Allows TypeScript inference of variant combinations
28
52
  */
29
53
  export type ModalContentVariantProps = VariantProps<typeof modalContentVariants>;
30
54
  export type ModalOverlayVariantProps = VariantProps<typeof modalOverlayVariants>;
55
+ export type ModalPanelVariantProps = VariantProps<typeof modalPanelVariants>;
31
56
  //# sourceMappingURL=Modal.styles.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAWlE;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;;;8EAoDhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;8EA2BhC,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjF,MAAM,MAAM,wBAAwB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC"}
1
+ {"version":3,"file":"Modal.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAmBlE;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;;;8EAoDhC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB;;;8EAkChC,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,kBAAkB;;;8EAkD9B,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB;;;;;CAKpB,CAAC;AAEX;;;GAGG;AACH,MAAM,MAAM,wBAAwB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjF,MAAM,MAAM,wBAAwB,GAAG,YAAY,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACjF,MAAM,MAAM,sBAAsB,GAAG,YAAY,CAAC,OAAO,kBAAkB,CAAC,CAAC"}
@@ -89,6 +89,23 @@ export declare const ModalAnimationSchema: z.ZodEnum<{
89
89
  fade: "fade";
90
90
  }>;
91
91
  export type ModalAnimation = z.infer<typeof ModalAnimationSchema>;
92
+ /**
93
+ * Modal position variants
94
+ *
95
+ * - `center` (default): the classic centred dialog.
96
+ * - `left` / `right`: a full-height drawer anchored to that edge (width from `size`).
97
+ * - `top` / `bottom`: a full-width sheet anchored to that edge (height from `size`).
98
+ *
99
+ * Below `mobileBreakpoint`, every edge-anchored variant collapses to a bottom sheet.
100
+ */
101
+ export declare const ModalPositionSchema: z.ZodEnum<{
102
+ center: "center";
103
+ top: "top";
104
+ bottom: "bottom";
105
+ left: "left";
106
+ right: "right";
107
+ }>;
108
+ export type ModalPosition = z.infer<typeof ModalPositionSchema>;
92
109
  /**
93
110
  * Modal.Content props schema
94
111
  *
@@ -122,6 +139,14 @@ export declare const ModalContentPropsSchema: z.ZodObject<{
122
139
  "fade-zoom": "fade-zoom";
123
140
  fade: "fade";
124
141
  }>>>;
142
+ position: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
143
+ center: "center";
144
+ top: "top";
145
+ bottom: "bottom";
146
+ left: "left";
147
+ right: "right";
148
+ }>>>;
149
+ mobileBreakpoint: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
125
150
  animationDuration: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
126
151
  isDismissable: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
127
152
  isKeyboardDismissDisabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
@@ -137,6 +162,8 @@ export interface ModalContentProps {
137
162
  'data-testid'?: string;
138
163
  size?: ModalSize;
139
164
  animation?: ModalAnimation;
165
+ position?: ModalPosition;
166
+ mobileBreakpoint?: number;
140
167
  animationDuration?: number;
141
168
  isDismissable?: boolean;
142
169
  isKeyboardDismissDisabled?: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"Modal.types.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"Modal.types.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/Modal.types.ts"],"names":[],"mappings":"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"}
@@ -9,7 +9,7 @@
9
9
  * @see PLAN.md (Implementation Plan)
10
10
  * @see RESEARCH.md (React Aria Patterns)
11
11
  */
12
- export { Modal, ModalTrigger, ModalContent, ModalOverlay, ModalHeader, ModalTitle, ModalDescription, ModalFooter, ModalClose, modalContentVariants, modalOverlayVariants, } from './Modal';
13
- export type { ModalProps, ModalTriggerProps, ModalContentProps, ModalOverlayProps, ModalHeaderProps, ModalTitleProps, ModalDescriptionProps, ModalFooterProps, ModalCloseProps, ModalSize, ModalAnimation, } from './Modal.types';
14
- export type { ModalContentVariantProps, ModalOverlayVariantProps, } from './Modal.styles';
12
+ export { Modal, ModalTrigger, ModalContent, ModalOverlay, ModalHeader, ModalTitle, ModalDescription, ModalFooter, ModalClose, modalContentVariants, modalOverlayVariants, modalPanelVariants, } from './Modal';
13
+ export type { ModalProps, ModalTriggerProps, ModalContentProps, ModalOverlayProps, ModalHeaderProps, ModalTitleProps, ModalDescriptionProps, ModalFooterProps, ModalCloseProps, ModalSize, ModalAnimation, ModalPosition, } from './Modal.types';
14
+ export type { ModalContentVariantProps, ModalOverlayVariantProps, ModalPanelVariantProps, } from './Modal.styles';
15
15
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,oBAAoB,GACrB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,cAAc,GACf,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,wBAAwB,EACxB,wBAAwB,GACzB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/Modal/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EACL,KAAK,EACL,YAAY,EACZ,YAAY,EACZ,YAAY,EACZ,WAAW,EACX,UAAU,EACV,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,oBAAoB,EACpB,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,SAAS,CAAC;AAEjB,YAAY,EACV,UAAU,EACV,iBAAiB,EACjB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,eAAe,EACf,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,SAAS,EACT,cAAc,EACd,aAAa,GACd,MAAM,eAAe,CAAC;AAEvB,YAAY,EACV,wBAAwB,EACxB,wBAAwB,EACxB,sBAAsB,GACvB,MAAM,gBAAgB,CAAC"}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime');function l(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var S=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:zoom-in-95","data-[entering]:duration-200","data-[entering]:ease-out"],b=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:zoom-out-95","data-[exiting]:duration-150","data-[exiting]:ease-in"],L=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:slide-in-from-bottom-4","data-[entering]:duration-200","data-[entering]:ease-out"],V=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:slide-out-to-bottom-4","data-[exiting]:duration-150","data-[exiting]:ease-in"],u=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200"],x=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150"],A=["motion-reduce:transition-none","motion-reduce:animate-none"];var f=classVarianceAuthority.cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","rounded-lg","p-6","w-full","outline-none","mx-4","sm:mx-0",...A],{variants:{size:{sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-2xl",full:"max-w-full min-h-screen rounded-none"},animation:{"fade-zoom":[...S,...b],fade:["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200","data-[entering]:ease-out","data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150","data-[exiting]:ease-in"],slide:[...L,...V],none:""}},defaultVariants:{size:"md",animation:"fade-zoom"}}),M=classVarianceAuthority.cva(["fixed","inset-0","z-50","flex","items-center","justify-center","bg-black/50","backdrop-blur-sm",...A],{variants:{animation:{"fade-zoom":[...u,...x],fade:[...u,...x],slide:[...u,...x],none:""}},defaultVariants:{animation:"fade-zoom"}});var C=react.createContext(void 0);function H({children:t,defaultOpen:e,isOpen:o,onOpenChange:r,role:s="dialog"}){let i=react.Children.toArray(t);if(process.env.NODE_ENV!=="production"&&!i.some(d=>react.isValidElement(d)&&(d.type===p||d.type.displayName==="ModalContent")))throw new Error("Modal requires a Modal.Content as a child");let m=i.find(n=>react.isValidElement(n)&&(n.type===O||n.type.displayName==="ModalTrigger")),E=i.find(n=>react.isValidElement(n)&&(n.type===p||n.type.displayName==="ModalContent"));if(!m)return jsxRuntime.jsx(C.Provider,{value:{role:s},children:jsxRuntime.jsx(reactAriaComponents.DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:r,children:E})});let g=m,y=react.isValidElement(g)?g.props.children:null;return jsxRuntime.jsx(C.Provider,{value:{role:s},children:jsxRuntime.jsxs(reactAriaComponents.DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:r,children:[y,E]})})}H.displayName="Modal";function O({children:t}){return t}O.displayName="ModalTrigger";function p({children:t,size:e="md",animation:o="fade-zoom",animationDuration:r=250,isDismissable:s=true,isKeyboardDismissDisabled:i=false,showClose:m=true,className:R}){let g=react.useContext(C)?.role??"dialog",y=M({animation:o}),n=f({size:e,animation:o}),d=l(n,R);return jsxRuntime.jsx(reactAriaComponents.ModalOverlay,{isDismissable:s,isKeyboardDismissDisabled:i,className:y,children:jsxRuntime.jsx(reactAriaComponents.Modal,{className:d,style:{transitionDuration:`${r}ms`},children:jsxRuntime.jsx(reactAriaComponents.Dialog,{role:g,className:"outline-none",children:({close:z})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[m&&jsxRuntime.jsx(reactAriaComponents.Button,{onPress:z,className:"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]","aria-label":"Close modal",children:jsxRuntime.jsx(lucideReact.X,{className:"h-4 w-4","aria-hidden":"true"})}),t]})})})})}p.displayName="ModalContent";function N(t){return null}N.displayName="ModalOverlay";function _({children:t,className:e}){return jsxRuntime.jsx("div",{className:l("flex flex-col space-y-1.5 text-center sm:text-left",e),children:t})}_.displayName="ModalHeader";function T({children:t,as:e="h2",className:o}){return jsxRuntime.jsx(reactAriaComponents.Heading,{slot:"title",level:parseInt(e[1]??"2"),className:l("text-lg font-semibold leading-none tracking-tight",o),children:t})}T.displayName="ModalTitle";function I({children:t,className:e}){return jsxRuntime.jsx("p",{slot:"description",className:l("text-sm text-[var(--menu-muted)]",e),children:t})}I.displayName="ModalDescription";function D({children:t,className:e}){return jsxRuntime.jsx("div",{className:l("flex flex-col-reverse sm:flex-row sm:justify-end gap-2",e),children:t})}D.displayName="ModalFooter";function P({children:t}){let e=react.useContext(reactAriaComponents.OverlayTriggerStateContext);if(!e)throw new Error("Modal.Close must be used inside Modal.Content");if(!react.isValidElement(t))throw new Error("Modal.Close requires a valid React element as a child");let o=t,r=()=>{e.close();},s=o.props?.onPress;return react.cloneElement(o,{onPress:s?()=>{s(),r();}:r})}P.displayName="ModalClose";var J=Object.assign(H,{Trigger:O,Content:p,Overlay:N,Header:_,Title:T,Description:I,Footer:D,Close:P});exports.Modal=J;exports.ModalClose=P;exports.ModalContent=p;exports.ModalDescription=I;exports.ModalFooter=D;exports.ModalHeader=_;exports.ModalOverlay=N;exports.ModalTitle=T;exports.ModalTrigger=O;exports.modalContentVariants=f;exports.modalOverlayVariants=M;//# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime');function d(...t){return tailwindMerge.twMerge(clsx.clsx(t))}function z(t){let e=react.useCallback(i=>{let s=window.matchMedia(t);return s.addEventListener("change",i),()=>s.removeEventListener("change",i)},[t]),o=react.useCallback(()=>window.matchMedia(t).matches,[t]),n=react.useCallback(()=>false,[]);return react.useSyncExternalStore(e,o,n)}var H=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:zoom-in-95","data-[entering]:duration-200","data-[entering]:ease-out"],F=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:zoom-out-95","data-[exiting]:duration-150","data-[exiting]:ease-in"],B=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:slide-in-from-bottom-4","data-[entering]:duration-200","data-[entering]:ease-out"],G=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:slide-out-to-bottom-4","data-[exiting]:duration-150","data-[exiting]:ease-in"],k=["data-[entering]:animate-in","data-[entering]:slide-in-from-left","data-[entering]:duration-200","data-[entering]:ease-out"],j=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-left","data-[exiting]:duration-150","data-[exiting]:ease-in"],$=["data-[entering]:animate-in","data-[entering]:slide-in-from-right","data-[entering]:duration-200","data-[entering]:ease-out"],Y=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-right","data-[exiting]:duration-150","data-[exiting]:ease-in"],Z=["data-[entering]:animate-in","data-[entering]:slide-in-from-top","data-[entering]:duration-200","data-[entering]:ease-out"],Q=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-top","data-[exiting]:duration-150","data-[exiting]:ease-in"],X=["data-[entering]:animate-in","data-[entering]:slide-in-from-bottom","data-[entering]:duration-200","data-[entering]:ease-out"],K=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-bottom","data-[exiting]:duration-150","data-[exiting]:ease-in"],M=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200"],_=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150"],O=["motion-reduce:transition-none","motion-reduce:animate-none"];var E=classVarianceAuthority.cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","rounded-lg","p-6","w-full","outline-none","mx-4","sm:mx-0",...O],{variants:{size:{sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-2xl",full:"max-w-full min-h-screen rounded-none"},animation:{"fade-zoom":[...H,...F],fade:["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200","data-[entering]:ease-out","data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150","data-[exiting]:ease-in"],slide:[...B,...G],none:""}},defaultVariants:{size:"md",animation:"fade-zoom"}}),v=classVarianceAuthority.cva(["fixed","inset-0","z-50","flex","bg-black/50","backdrop-blur-sm",...O],{variants:{animation:{"fade-zoom":[...M,..._],fade:[...M,..._],slide:[...M,..._],none:""},position:{center:"items-center justify-center",left:"items-stretch justify-start",right:"items-stretch justify-end",top:"items-start justify-center",bottom:"items-end justify-center"}},defaultVariants:{animation:"fade-zoom",position:"center"}}),p=classVarianceAuthority.cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","p-6","outline-none","overflow-y-auto",...O],{variants:{position:{left:"h-full border-r border-[var(--border)] rounded-r-lg",right:"h-full border-l border-[var(--border)] rounded-l-lg",top:"w-full border-b border-[var(--border)] rounded-b-lg",bottom:"w-full border-t border-[var(--border)] rounded-t-lg"},size:{sm:"",md:"",lg:"",xl:"",full:""}},compoundVariants:[{position:["left","right"],size:"sm",class:"w-[300px] max-w-[90vw]"},{position:["left","right"],size:"md",class:"w-[400px] max-w-[90vw]"},{position:["left","right"],size:"lg",class:"w-[500px] max-w-[90vw]"},{position:["left","right"],size:"xl",class:"w-[600px] max-w-[90vw]"},{position:["left","right"],size:"full",class:"w-screen"},{position:["top","bottom"],size:"sm",class:"h-[200px] max-h-[90vh]"},{position:["top","bottom"],size:"md",class:"h-[320px] max-h-[90vh]"},{position:["top","bottom"],size:"lg",class:"h-[440px] max-h-[90vh]"},{position:["top","bottom"],size:"xl",class:"h-[560px] max-h-[90vh]"},{position:["top","bottom"],size:"full",class:"h-screen"}],defaultVariants:{position:"right",size:"md"}}),W={left:[...k,...j],right:[...$,...Y],top:[...Z,...Q],bottom:[...X,...K]};var L=react.createContext(void 0);function tt({children:t,defaultOpen:e,isOpen:o,onOpenChange:n,role:i="dialog"}){let s=react.Children.toArray(t);if(process.env.NODE_ENV!=="production"&&!s.some(l=>react.isValidElement(l)&&(l.type===g||l.type.displayName==="ModalContent")))throw new Error("Modal requires a Modal.Content as a child");let u=s.find(r=>react.isValidElement(r)&&(r.type===T||r.type.displayName==="ModalTrigger")),x=s.find(r=>react.isValidElement(r)&&(r.type===g||r.type.displayName==="ModalContent"));if(!u)return jsxRuntime.jsx(L.Provider,{value:{role:i},children:jsxRuntime.jsx(reactAriaComponents.DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:n,children:x})});let c=u,R=react.isValidElement(c)?c.props.children:null;return jsxRuntime.jsx(L.Provider,{value:{role:i},children:jsxRuntime.jsxs(reactAriaComponents.DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:n,children:[R,x]})})}tt.displayName="Modal";function T({children:t}){return t}T.displayName="ModalTrigger";function g({children:t,size:e="md",animation:o="fade-zoom",position:n="center",mobileBreakpoint:i=768,animationDuration:s=250,isDismissable:u=true,isKeyboardDismissDisabled:w=false,showClose:x=true,className:c}){let r=react.useContext(L)?.role??"dialog",l=n!=="center",V=z(`(max-width: ${i-1}px)`),U=l&&V?"bottom":n,ot=v({animation:o,position:U}),A;if(l){let f=U,at=V?d(p({position:"bottom",size:e}),"h-auto max-h-[85vh]"):p({position:f,size:e}),nt=o==="none"?void 0:W[f];A=d(at,nt,c);}else A=d(E({size:e,animation:o}),c);return jsxRuntime.jsx(reactAriaComponents.ModalOverlay,{isDismissable:u,isKeyboardDismissDisabled:w,className:ot,children:jsxRuntime.jsx(reactAriaComponents.Modal,{className:A,style:{transitionDuration:`${s}ms`},children:jsxRuntime.jsx(reactAriaComponents.Dialog,{role:r,className:"outline-none",children:({close:f})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[x&&jsxRuntime.jsx(reactAriaComponents.Button,{onPress:f,className:"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]","aria-label":"Close modal",children:jsxRuntime.jsx(lucideReact.X,{className:"h-4 w-4","aria-hidden":"true"})}),t]})})})})}g.displayName="ModalContent";function N(t){return null}N.displayName="ModalOverlay";function h({children:t,className:e}){return jsxRuntime.jsx("div",{className:d("flex flex-col space-y-1.5 text-center sm:text-left",e),children:t})}h.displayName="ModalHeader";function P({children:t,as:e="h2",className:o}){return jsxRuntime.jsx(reactAriaComponents.Heading,{slot:"title",level:parseInt(e[1]??"2"),className:d("text-lg font-semibold leading-none tracking-tight",o),children:t})}P.displayName="ModalTitle";function b({children:t,className:e}){return jsxRuntime.jsx("p",{slot:"description",className:d("text-sm text-[var(--menu-muted)]",e),children:t})}b.displayName="ModalDescription";function C({children:t,className:e}){return jsxRuntime.jsx("div",{className:d("flex flex-col-reverse sm:flex-row sm:justify-end gap-2",e),children:t})}C.displayName="ModalFooter";function S({children:t}){let e=react.useContext(reactAriaComponents.OverlayTriggerStateContext);if(!e)throw new Error("Modal.Close must be used inside Modal.Content");if(!react.isValidElement(t))throw new Error("Modal.Close requires a valid React element as a child");let o=t,n=()=>{e.close();},i=o.props?.onPress;return react.cloneElement(o,{onPress:i?()=>{i(),n();}:n})}S.displayName="ModalClose";var _t=Object.assign(tt,{Trigger:T,Content:g,Overlay:N,Header:h,Title:P,Description:b,Footer:C,Close:S});exports.Modal=_t;exports.ModalClose=S;exports.ModalContent=g;exports.ModalDescription=b;exports.ModalFooter=C;exports.ModalHeader=h;exports.ModalOverlay=N;exports.ModalTitle=P;exports.ModalTrigger=T;exports.modalContentVariants=E;exports.modalOverlayVariants=v;exports.modalPanelVariants=p;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Modal/Modal.styles.ts","../../../src/elements/Modal/Modal.tsx"],"names":["cn","inputs","twMerge","clsx","MODAL_ANIMATION_IN","MODAL_ANIMATION_OUT","MODAL_SLIDE_IN","MODAL_SLIDE_OUT","MODAL_OVERLAY_IN","MODAL_OVERLAY_OUT","REDUCED_MOTION","modalContentVariants","cva","modalOverlayVariants","ModalContext","createContext","ModalRoot","children","defaultOpen","isOpen","onOpenChange","role","childArray","Children","child","isValidElement","ModalContent","triggerChild","ModalTrigger","unwrappedContent","jsx","AriaDialogTrigger","triggerElement","unwrappedTrigger","jsxs","size","animation","animationDuration","isDismissable","isKeyboardDismissDisabled","showClose","className","useContext","overlayClasses","modalClasses","mergedModalClasses","AriaModalOverlay","AriaModal","AriaDialog","close","Fragment","AriaButton","X","ModalOverlay","_props","ModalHeader","ModalTitle","as","Heading","ModalDescription","ModalFooter","ModalClose","state","OverlayTriggerStateContext","childElement","handlePress","existingOnPress","cloneElement","Modal"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\nimport {\n MODAL_ANIMATION_IN,\n MODAL_ANIMATION_OUT,\n MODAL_SLIDE_IN,\n MODAL_SLIDE_OUT,\n MODAL_OVERLAY_IN,\n MODAL_OVERLAY_OUT,\n REDUCED_MOTION,\n} from '../../styles/shared-variants';\n\n/**\n * CVA Variants for Modal.Content\n *\n * Size and animation variant definitions for the modal content container.\n * Uses React Aria data-[entering]/data-[exiting] attributes for enter+exit animations.\n * Uses CSS custom properties for all colours to support theming.\n *\n * @see Modal.types.ts (ModalSize, ModalAnimation)\n */\nexport const modalContentVariants = cva(\n [\n // Base styles\n 'relative',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'rounded-lg',\n 'p-6',\n 'w-full',\n 'outline-none',\n // Responsive: full-width on mobile with padding, constrained on desktop\n 'mx-4',\n 'sm:mx-0',\n // Reduced motion support\n ...REDUCED_MOTION,\n ],\n {\n variants: {\n size: {\n sm: 'max-w-sm', // 300px\n md: 'max-w-md', // 425px\n lg: 'max-w-lg', // 600px\n xl: 'max-w-2xl', // 800px\n full: 'max-w-full min-h-screen rounded-none', // Full screen\n },\n animation: {\n 'fade-zoom': [\n ...MODAL_ANIMATION_IN,\n ...MODAL_ANIMATION_OUT,\n ],\n fade: [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n ],\n slide: [\n ...MODAL_SLIDE_IN,\n ...MODAL_SLIDE_OUT,\n ],\n none: '',\n },\n },\n defaultVariants: {\n size: 'md',\n animation: 'fade-zoom',\n },\n }\n);\n\n/**\n * CVA Variants for Modal Overlay\n *\n * Animation variant definitions for the modal backdrop overlay.\n * Uses React Aria data-[entering]/data-[exiting] attributes for enter+exit animations.\n * Uses CSS custom properties for all colours to support theming.\n */\nexport const modalOverlayVariants = cva(\n [\n // Base overlay styles\n 'fixed',\n 'inset-0',\n 'z-50',\n 'flex',\n 'items-center',\n 'justify-center',\n 'bg-black/50',\n 'backdrop-blur-sm',\n // Reduced motion support\n ...REDUCED_MOTION,\n ],\n {\n variants: {\n animation: {\n 'fade-zoom': [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n fade: [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n slide: [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n none: '',\n },\n },\n defaultVariants: {\n animation: 'fade-zoom',\n },\n }\n);\n\n/**\n * Type exports for variant props\n * Allows TypeScript inference of variant combinations\n */\nexport type ModalContentVariantProps = VariantProps<typeof modalContentVariants>;\nexport type ModalOverlayVariantProps = VariantProps<typeof modalOverlayVariants>;\n","'use client';\n\n/**\n * Modal Component - Implementation\n *\n * Accessible modal dialog component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure.\n *\n * @see PRD.md (Full requirements)\n * @see Modal.types.ts (Zod schemas)\n * @see RESEARCH.md (React Aria patterns)\n */\n\nimport {\n Children,\n isValidElement,\n cloneElement,\n useContext,\n createContext,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n DialogTrigger as AriaDialogTrigger,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n Heading,\n Button as AriaButton,\n OverlayTriggerStateContext,\n} from 'react-aria-components';\nimport { X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { modalContentVariants, modalOverlayVariants } from './Modal.styles';\nimport type {\n ModalProps,\n ModalTriggerProps,\n ModalContentProps,\n ModalOverlayProps,\n ModalHeaderProps,\n ModalTitleProps,\n ModalDescriptionProps,\n ModalFooterProps,\n ModalCloseProps,\n} from './Modal.types';\n\n/**\n * Modal Context\n * Passes role prop from Modal root to Modal.Content\n */\ninterface ModalContextValue {\n role?: 'dialog' | 'alertdialog';\n}\n\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\n\n/**\n * Modal Root Component\n *\n * Manages modal open/close state and validates required children structure.\n * Must contain one Modal.Content. Modal.Trigger is optional — when omitted,\n * use controlled mode (isOpen + onOpenChange) to manage the modal.\n *\n * Unwraps compound component children and passes them to React Aria's DialogTrigger.\n *\n * @see PRD.md FR-001 (Modal Root Requirements)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nfunction ModalRoot({ children, defaultOpen, isOpen, onOpenChange, role = 'dialog' }: ModalProps): ReactElement {\n const childArray = Children.toArray(children);\n\n // Validate children structure in development only\n if (process.env.NODE_ENV !== 'production') {\n const hasContent = childArray.some(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalContent ||\n (child.type as { displayName?: string }).displayName === 'ModalContent')\n );\n\n if (!hasContent) {\n throw new Error(\n 'Modal requires a Modal.Content as a child'\n );\n }\n }\n\n // Find trigger and content children\n const triggerChild = childArray.find(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalTrigger ||\n (child.type as { displayName?: string }).displayName === 'ModalTrigger')\n );\n\n const contentChild = childArray.find(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalContent ||\n (child.type as { displayName?: string }).displayName === 'ModalContent')\n );\n\n const unwrappedContent = contentChild as ReactElement;\n\n // When no trigger is provided, render content directly (controlled mode)\n if (!triggerChild) {\n return (\n <ModalContext.Provider value={{ role }}>\n <AriaDialogTrigger\n defaultOpen={defaultOpen}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n >\n {unwrappedContent}\n </AriaDialogTrigger>\n </ModalContext.Provider>\n );\n }\n\n // Extract the actual children from Modal.Trigger\n // React Aria's DialogTrigger expects direct Button and Modal children\n const triggerElement = triggerChild as ReactElement;\n const unwrappedTrigger = isValidElement(triggerElement)\n ? ((triggerElement.props as unknown as { children?: ReactNode }).children as ReactNode)\n : null;\n\n return (\n <ModalContext.Provider value={{ role }}>\n <AriaDialogTrigger\n defaultOpen={defaultOpen}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n >\n {unwrappedTrigger}\n {unwrappedContent}\n </AriaDialogTrigger>\n </ModalContext.Provider>\n );\n}\n\nModalRoot.displayName = 'Modal';\n\n/**\n * Modal.Trigger Component\n *\n * Wraps a single child element (typically Button) with modal trigger behavior.\n * Handles click events to open modal and manages ARIA attributes.\n *\n * React Aria's DialogTrigger (used in Modal root) automatically applies:\n * - aria-haspopup=\"dialog\"\n * - aria-expanded (true/false based on state)\n * - onClick handler to toggle modal\n *\n * @see PRD.md FR-002 (Trigger Requirements)\n * @see RESEARCH.md Section 2 (React Aria Integration)\n */\nfunction ModalTrigger({ children }: ModalTriggerProps): ReactElement {\n // React Aria's DialogTrigger (in Modal root) automatically adds ARIA attributes\n // to the first child component. We pass through the child element directly.\n return children as ReactElement;\n}\n\nModalTrigger.displayName = 'ModalTrigger';\n\n/**\n * Modal.Content Component\n *\n * Renders the modal content with overlay backdrop.\n * Uses React Aria's Modal and ModalOverlay for accessibility.\n * Applies CVA variants for size and animation.\n *\n * @see PRD.md FR-003 (Content Requirements)\n * @see PRD.md TR-001 (CVA Variant Styling)\n * @see RESEARCH.md Section 2 (React Aria Integration)\n */\nfunction ModalContent({\n children,\n size = 'md',\n animation = 'fade-zoom',\n animationDuration = 250,\n isDismissable = true,\n isKeyboardDismissDisabled = false,\n showClose = true,\n className,\n}: ModalContentProps): ReactElement {\n // Get role from context\n const context = useContext(ModalContext);\n const role = context?.role ?? 'dialog';\n\n // Generate overlay classes with animation variant\n const overlayClasses = modalOverlayVariants({ animation });\n\n // Generate modal classes with size and animation variants, merged with custom className\n const modalClasses = modalContentVariants({ size, animation });\n const mergedModalClasses = cn(modalClasses, className);\n\n return (\n <AriaModalOverlay\n isDismissable={isDismissable}\n isKeyboardDismissDisabled={isKeyboardDismissDisabled}\n className={overlayClasses}\n >\n <AriaModal\n className={mergedModalClasses}\n style={{\n transitionDuration: `${animationDuration}ms`,\n }}\n >\n <AriaDialog role={role} className=\"outline-none\">\n {({ close }) => (\n <>\n {showClose && (\n <AriaButton\n onPress={close}\n className=\"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]\"\n aria-label=\"Close modal\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </AriaButton>\n )}\n {children}\n </>\n )}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n}\n\nModalContent.displayName = 'ModalContent';\n\n/**\n * Modal.Overlay Component (Placeholder - not exposed in public API)\n * Overlay is managed internally by Modal.Content via AriaModalOverlay\n */\nfunction ModalOverlay(_props: ModalOverlayProps): null {\n return null;\n}\n\nModalOverlay.displayName = 'ModalOverlay';\n\n/**\n * Modal.Header Component\n *\n * Container for modal header content (typically Title and Description).\n * Applies consistent spacing and layout.\n *\n * @see PRD.md FR-005 (Header Requirements)\n */\nfunction ModalHeader({ children, className }: ModalHeaderProps): ReactElement {\n return <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}>{children}</div>;\n}\n\nModalHeader.displayName = 'ModalHeader';\n\n/**\n * Modal.Title Component\n *\n * Renders modal title using React Aria's Heading component.\n * Automatically links to modal via aria-labelledby.\n *\n * @see PRD.md FR-006 (Title Requirements)\n * @see PRD.md AR-002 (ARIA Attributes - auto-labelledby)\n */\nfunction ModalTitle({ children, as = 'h2', className }: ModalTitleProps): ReactElement {\n return (\n <Heading slot=\"title\" level={parseInt(as[1] ?? '2')} className={cn('text-lg font-semibold leading-none tracking-tight', className)}>\n {children}\n </Heading>\n );\n}\n\nModalTitle.displayName = 'ModalTitle';\n\n/**\n * Modal.Description Component\n *\n * Renders description text that automatically links to modal via aria-describedby.\n * Uses muted text color for visual hierarchy.\n *\n * @see PRD.md FR-007 (Description Requirements)\n * @see PRD.md AR-002 (ARIA Attributes - auto-describedby)\n */\nfunction ModalDescription({ children, className }: ModalDescriptionProps): ReactElement {\n return (\n <p slot=\"description\" className={cn('text-sm text-[var(--menu-muted)]', className)}>\n {children}\n </p>\n );\n}\n\nModalDescription.displayName = 'ModalDescription';\n\n/**\n * Modal.Footer Component\n *\n * Container for modal action buttons (Cancel, Confirm, etc.).\n * Aligns buttons to the right with consistent spacing.\n * Responsive: stacks vertically on mobile, horizontal on desktop.\n *\n * @see PRD.md FR-008 (Footer Requirements)\n * @see PRD.md DS-003 (Spacing - footer button gap)\n */\nfunction ModalFooter({ children, className }: ModalFooterProps): ReactElement {\n return <div className={cn('flex flex-col-reverse sm:flex-row sm:justify-end gap-2', className)}>{children}</div>;\n}\n\nModalFooter.displayName = 'ModalFooter';\n\n/**\n * Modal.Close Component\n *\n * Wraps a child element (typically Button) with modal close behavior.\n * Uses OverlayTriggerStateContext from React Aria to access close function.\n *\n * @see PRD.md FR-009 (Close Requirements)\n */\nfunction ModalClose({ children }: ModalCloseProps): ReactElement {\n // Access the overlay trigger state from React Aria context\n const state = useContext(OverlayTriggerStateContext);\n\n if (!state) {\n throw new Error('Modal.Close must be used inside Modal.Content');\n }\n\n // Clone the child element and add/merge the onPress handler to close the modal\n if (!isValidElement(children)) {\n throw new Error('Modal.Close requires a valid React element as a child');\n }\n\n // Cast to ReactElement after validation\n const childElement = children as ReactElement;\n\n const handlePress = (): void => {\n state.close();\n };\n\n // Merge with existing onPress if present\n const existingOnPress = (childElement.props as unknown as { onPress?: () => void })?.onPress;\n const mergedOnPress = existingOnPress\n ? (): void => {\n existingOnPress();\n handlePress();\n }\n : handlePress;\n\n // cloneElement with onPress override - use unknown for flexible typing\n return cloneElement(childElement, { onPress: mergedOnPress } as unknown as Partial<typeof childElement.props>);\n}\n\nModalClose.displayName = 'ModalClose';\n\n/**\n * Re-export CVA variants from Modal.styles.ts for backwards compatibility.\n * Consumers importing { modalContentVariants, modalOverlayVariants } from './Modal'\n * will continue to work.\n */\nexport { modalContentVariants, modalOverlayVariants } from './Modal.styles';\n\n/**\n * Compound Component Export\n *\n * Follows Themis library pattern using Object.assign() for compound components.\n * Enables usage like Modal.Trigger, Modal.Content, etc.\n *\n * @deprecated The Object.assign compound pattern will be removed in v2.\n * Use the direct named exports (ModalTrigger, ModalContent, etc.) instead.\n * This pattern is kept for backwards compatibility only.\n *\n * @see RESEARCH.md Section 1 (Compound Component Pattern)\n */\nexport const Modal = Object.assign(ModalRoot, {\n Trigger: ModalTrigger,\n Content: ModalContent,\n Overlay: ModalOverlay,\n Header: ModalHeader,\n Title: ModalTitle,\n Description: ModalDescription,\n Footer: ModalFooter,\n Close: ModalClose,\n});\n\n// Named exports for individual components\nexport {\n ModalRoot,\n ModalTrigger,\n ModalContent,\n ModalOverlay,\n ModalHeader,\n ModalTitle,\n ModalDescription,\n ModalFooter,\n ModalClose,\n};\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/hooks/useMediaQuery.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Modal/Modal.styles.ts","../../../src/elements/Modal/Modal.tsx"],"names":["cn","inputs","twMerge","clsx","useMediaQuery","query","subscribe","useCallback","callback","mql","getSnapshot","getServerSnapshot","useSyncExternalStore","MODAL_ANIMATION_IN","MODAL_ANIMATION_OUT","MODAL_SLIDE_IN","MODAL_SLIDE_OUT","MODAL_SLIDE_IN_LEFT","MODAL_SLIDE_OUT_LEFT","MODAL_SLIDE_IN_RIGHT","MODAL_SLIDE_OUT_RIGHT","MODAL_SLIDE_IN_TOP","MODAL_SLIDE_OUT_TOP","MODAL_SLIDE_IN_BOTTOM","MODAL_SLIDE_OUT_BOTTOM","MODAL_OVERLAY_IN","MODAL_OVERLAY_OUT","REDUCED_MOTION","modalContentVariants","cva","modalOverlayVariants","modalPanelVariants","MODAL_PANEL_SLIDE","ModalContext","createContext","ModalRoot","children","defaultOpen","isOpen","onOpenChange","role","childArray","Children","child","isValidElement","ModalContent","triggerChild","ModalTrigger","unwrappedContent","jsx","AriaDialogTrigger","triggerElement","unwrappedTrigger","jsxs","size","animation","position","mobileBreakpoint","animationDuration","isDismissable","isKeyboardDismissDisabled","showClose","className","useContext","isPanel","isMobile","effectivePosition","overlayClasses","mergedModalClasses","edge","box","slide","AriaModalOverlay","AriaModal","AriaDialog","close","Fragment","AriaButton","X","ModalOverlay","_props","ModalHeader","ModalTitle","as","Heading","ModalDescription","ModalFooter","ModalClose","state","OverlayTriggerStateContext","childElement","handlePress","existingOnPress","cloneElement","Modal"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","'use client';\n\nimport { useCallback, useSyncExternalStore } from 'react';\n\n/**\n * SSR-safe media query hook using useSyncExternalStore.\n *\n * - No hydration mismatch flicker (getServerSnapshot returns false)\n * - Listener registered once per query value (no dependency bugs)\n * - Reacts to changes in real time\n *\n * @param query - CSS media query string, e.g. '(max-width: 767px)'\n * @returns Whether the media query currently matches\n */\nexport function useMediaQuery(query: string): boolean {\n const subscribe = useCallback(\n (callback: () => void) => {\n const mql = window.matchMedia(query);\n mql.addEventListener('change', callback);\n return () => mql.removeEventListener('change', callback);\n },\n [query],\n );\n\n const getSnapshot = useCallback(\n () => window.matchMedia(query).matches,\n [query],\n );\n\n const getServerSnapshot = useCallback(() => false, []);\n\n return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot);\n}\n","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\nimport {\n MODAL_ANIMATION_IN,\n MODAL_ANIMATION_OUT,\n MODAL_SLIDE_IN,\n MODAL_SLIDE_OUT,\n MODAL_SLIDE_IN_LEFT,\n MODAL_SLIDE_OUT_LEFT,\n MODAL_SLIDE_IN_RIGHT,\n MODAL_SLIDE_OUT_RIGHT,\n MODAL_SLIDE_IN_TOP,\n MODAL_SLIDE_OUT_TOP,\n MODAL_SLIDE_IN_BOTTOM,\n MODAL_SLIDE_OUT_BOTTOM,\n MODAL_OVERLAY_IN,\n MODAL_OVERLAY_OUT,\n REDUCED_MOTION,\n} from '../../styles/shared-variants';\n\n/**\n * CVA Variants for Modal.Content\n *\n * Size and animation variant definitions for the modal content container.\n * Uses React Aria data-[entering]/data-[exiting] attributes for enter+exit animations.\n * Uses CSS custom properties for all colours to support theming.\n *\n * @see Modal.types.ts (ModalSize, ModalAnimation)\n */\nexport const modalContentVariants = cva(\n [\n // Base styles\n 'relative',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'rounded-lg',\n 'p-6',\n 'w-full',\n 'outline-none',\n // Responsive: full-width on mobile with padding, constrained on desktop\n 'mx-4',\n 'sm:mx-0',\n // Reduced motion support\n ...REDUCED_MOTION,\n ],\n {\n variants: {\n size: {\n sm: 'max-w-sm', // 300px\n md: 'max-w-md', // 425px\n lg: 'max-w-lg', // 600px\n xl: 'max-w-2xl', // 800px\n full: 'max-w-full min-h-screen rounded-none', // Full screen\n },\n animation: {\n 'fade-zoom': [\n ...MODAL_ANIMATION_IN,\n ...MODAL_ANIMATION_OUT,\n ],\n fade: [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n ],\n slide: [\n ...MODAL_SLIDE_IN,\n ...MODAL_SLIDE_OUT,\n ],\n none: '',\n },\n },\n defaultVariants: {\n size: 'md',\n animation: 'fade-zoom',\n },\n }\n);\n\n/**\n * CVA Variants for Modal Overlay\n *\n * Animation variant definitions for the modal backdrop overlay.\n * Uses React Aria data-[entering]/data-[exiting] attributes for enter+exit animations.\n * Uses CSS custom properties for all colours to support theming.\n */\nexport const modalOverlayVariants = cva(\n [\n // Base overlay styles\n 'fixed',\n 'inset-0',\n 'z-50',\n 'flex',\n 'bg-black/50',\n 'backdrop-blur-sm',\n // Reduced motion support\n ...REDUCED_MOTION,\n ],\n {\n variants: {\n animation: {\n 'fade-zoom': [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n fade: [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n slide: [...MODAL_OVERLAY_IN, ...MODAL_OVERLAY_OUT],\n none: '',\n },\n // How the dialog is anchored within the full-screen backdrop.\n position: {\n center: 'items-center justify-center',\n left: 'items-stretch justify-start',\n right: 'items-stretch justify-end',\n top: 'items-start justify-center',\n bottom: 'items-end justify-center',\n },\n },\n defaultVariants: {\n animation: 'fade-zoom',\n position: 'center',\n },\n }\n);\n\n/**\n * CVA Variants for an edge-anchored Modal drawer/sheet (Modal.Content `position`)\n *\n * The box styling for `position` ∈ {left, right, top, bottom}. `position` sets the\n * full extent on the anchored axis plus the inner-edge border; `size` sets the\n * cross-axis dimension (width for left/right, height for top/bottom) via compound\n * variants. The directional slide animation is applied separately (see\n * MODAL_PANEL_SLIDE) so it can be suppressed for `animation=\"none\"`.\n */\nexport const modalPanelVariants = cva(\n [\n // Base styles — `relative` anchors the absolute close button (as the centred box does)\n 'relative',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'p-6',\n 'outline-none',\n 'overflow-y-auto',\n // Reduced motion support\n ...REDUCED_MOTION,\n ],\n {\n variants: {\n // Only the two exposed corners are rounded (`rounded-lg`, matching the\n // centred modal); the anchored edge stays square against the viewport.\n position: {\n left: 'h-full border-r border-[var(--border)] rounded-r-lg',\n right: 'h-full border-l border-[var(--border)] rounded-l-lg',\n top: 'w-full border-b border-[var(--border)] rounded-b-lg',\n bottom: 'w-full border-t border-[var(--border)] rounded-t-lg',\n },\n // Cross-axis dimension; meaning depends on `position` (see compoundVariants).\n size: {\n sm: '',\n md: '',\n lg: '',\n xl: '',\n full: '',\n },\n },\n compoundVariants: [\n // left/right → width\n { position: ['left', 'right'], size: 'sm', class: 'w-[300px] max-w-[90vw]' },\n { position: ['left', 'right'], size: 'md', class: 'w-[400px] max-w-[90vw]' },\n { position: ['left', 'right'], size: 'lg', class: 'w-[500px] max-w-[90vw]' },\n { position: ['left', 'right'], size: 'xl', class: 'w-[600px] max-w-[90vw]' },\n { position: ['left', 'right'], size: 'full', class: 'w-screen' },\n // top/bottom → height\n { position: ['top', 'bottom'], size: 'sm', class: 'h-[200px] max-h-[90vh]' },\n { position: ['top', 'bottom'], size: 'md', class: 'h-[320px] max-h-[90vh]' },\n { position: ['top', 'bottom'], size: 'lg', class: 'h-[440px] max-h-[90vh]' },\n { position: ['top', 'bottom'], size: 'xl', class: 'h-[560px] max-h-[90vh]' },\n { position: ['top', 'bottom'], size: 'full', class: 'h-screen' },\n ],\n defaultVariants: {\n position: 'right',\n size: 'md',\n },\n }\n);\n\n/**\n * Directional slide classes per anchored edge, keyed by position.\n * Applied to the drawer box unless `animation=\"none\"`.\n */\nexport const MODAL_PANEL_SLIDE = {\n left: [...MODAL_SLIDE_IN_LEFT, ...MODAL_SLIDE_OUT_LEFT],\n right: [...MODAL_SLIDE_IN_RIGHT, ...MODAL_SLIDE_OUT_RIGHT],\n top: [...MODAL_SLIDE_IN_TOP, ...MODAL_SLIDE_OUT_TOP],\n bottom: [...MODAL_SLIDE_IN_BOTTOM, ...MODAL_SLIDE_OUT_BOTTOM],\n} as const;\n\n/**\n * Type exports for variant props\n * Allows TypeScript inference of variant combinations\n */\nexport type ModalContentVariantProps = VariantProps<typeof modalContentVariants>;\nexport type ModalOverlayVariantProps = VariantProps<typeof modalOverlayVariants>;\nexport type ModalPanelVariantProps = VariantProps<typeof modalPanelVariants>;\n","'use client';\n\n/**\n * Modal Component - Implementation\n *\n * Accessible modal dialog component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure.\n *\n * @see PRD.md (Full requirements)\n * @see Modal.types.ts (Zod schemas)\n * @see RESEARCH.md (React Aria patterns)\n */\n\nimport {\n Children,\n isValidElement,\n cloneElement,\n useContext,\n createContext,\n type ReactElement,\n type ReactNode,\n} from 'react';\nimport {\n DialogTrigger as AriaDialogTrigger,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n Heading,\n Button as AriaButton,\n OverlayTriggerStateContext,\n} from 'react-aria-components';\nimport { X } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { useMediaQuery } from '../../hooks/useMediaQuery';\nimport {\n modalContentVariants,\n modalOverlayVariants,\n modalPanelVariants,\n MODAL_PANEL_SLIDE,\n} from './Modal.styles';\nimport type {\n ModalProps,\n ModalTriggerProps,\n ModalContentProps,\n ModalOverlayProps,\n ModalHeaderProps,\n ModalTitleProps,\n ModalDescriptionProps,\n ModalFooterProps,\n ModalCloseProps,\n} from './Modal.types';\n\n/**\n * Modal Context\n * Passes role prop from Modal root to Modal.Content\n */\ninterface ModalContextValue {\n role?: 'dialog' | 'alertdialog';\n}\n\nconst ModalContext = createContext<ModalContextValue | undefined>(undefined);\n\n/**\n * Modal Root Component\n *\n * Manages modal open/close state and validates required children structure.\n * Must contain one Modal.Content. Modal.Trigger is optional — when omitted,\n * use controlled mode (isOpen + onOpenChange) to manage the modal.\n *\n * Unwraps compound component children and passes them to React Aria's DialogTrigger.\n *\n * @see PRD.md FR-001 (Modal Root Requirements)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nfunction ModalRoot({ children, defaultOpen, isOpen, onOpenChange, role = 'dialog' }: ModalProps): ReactElement {\n const childArray = Children.toArray(children);\n\n // Validate children structure in development only\n if (process.env.NODE_ENV !== 'production') {\n const hasContent = childArray.some(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalContent ||\n (child.type as { displayName?: string }).displayName === 'ModalContent')\n );\n\n if (!hasContent) {\n throw new Error(\n 'Modal requires a Modal.Content as a child'\n );\n }\n }\n\n // Find trigger and content children\n const triggerChild = childArray.find(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalTrigger ||\n (child.type as { displayName?: string }).displayName === 'ModalTrigger')\n );\n\n const contentChild = childArray.find(\n (child) =>\n isValidElement(child) &&\n (child.type === ModalContent ||\n (child.type as { displayName?: string }).displayName === 'ModalContent')\n );\n\n const unwrappedContent = contentChild as ReactElement;\n\n // When no trigger is provided, render content directly (controlled mode)\n if (!triggerChild) {\n return (\n <ModalContext.Provider value={{ role }}>\n <AriaDialogTrigger\n defaultOpen={defaultOpen}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n >\n {unwrappedContent}\n </AriaDialogTrigger>\n </ModalContext.Provider>\n );\n }\n\n // Extract the actual children from Modal.Trigger\n // React Aria's DialogTrigger expects direct Button and Modal children\n const triggerElement = triggerChild as ReactElement;\n const unwrappedTrigger = isValidElement(triggerElement)\n ? ((triggerElement.props as unknown as { children?: ReactNode }).children as ReactNode)\n : null;\n\n return (\n <ModalContext.Provider value={{ role }}>\n <AriaDialogTrigger\n defaultOpen={defaultOpen}\n isOpen={isOpen}\n onOpenChange={onOpenChange}\n >\n {unwrappedTrigger}\n {unwrappedContent}\n </AriaDialogTrigger>\n </ModalContext.Provider>\n );\n}\n\nModalRoot.displayName = 'Modal';\n\n/**\n * Modal.Trigger Component\n *\n * Wraps a single child element (typically Button) with modal trigger behavior.\n * Handles click events to open modal and manages ARIA attributes.\n *\n * React Aria's DialogTrigger (used in Modal root) automatically applies:\n * - aria-haspopup=\"dialog\"\n * - aria-expanded (true/false based on state)\n * - onClick handler to toggle modal\n *\n * @see PRD.md FR-002 (Trigger Requirements)\n * @see RESEARCH.md Section 2 (React Aria Integration)\n */\nfunction ModalTrigger({ children }: ModalTriggerProps): ReactElement {\n // React Aria's DialogTrigger (in Modal root) automatically adds ARIA attributes\n // to the first child component. We pass through the child element directly.\n return children as ReactElement;\n}\n\nModalTrigger.displayName = 'ModalTrigger';\n\n/**\n * Modal.Content Component\n *\n * Renders the modal content with overlay backdrop.\n * Uses React Aria's Modal and ModalOverlay for accessibility.\n * Applies CVA variants for size and animation.\n *\n * @see PRD.md FR-003 (Content Requirements)\n * @see PRD.md TR-001 (CVA Variant Styling)\n * @see RESEARCH.md Section 2 (React Aria Integration)\n */\nfunction ModalContent({\n children,\n size = 'md',\n animation = 'fade-zoom',\n position = 'center',\n mobileBreakpoint = 768,\n animationDuration = 250,\n isDismissable = true,\n isKeyboardDismissDisabled = false,\n showClose = true,\n className,\n}: ModalContentProps): ReactElement {\n // Get role from context\n const context = useContext(ModalContext);\n const role = context?.role ?? 'dialog';\n\n // Edge-anchored drawer/sheet when position is not 'center'. Below the\n // breakpoint every drawer collapses to a bottom sheet (matching Panel).\n const isPanel = position !== 'center';\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n const effectivePosition = isPanel && isMobile ? 'bottom' : position;\n\n // Overlay anchors the dialog to the effective edge (or centres it).\n const overlayClasses = modalOverlayVariants({ animation, position: effectivePosition });\n\n // Box classes: the centred dialog keeps its size→max-width behaviour; a drawer\n // uses the panel variant (full extent on the anchored axis + size→cross-axis),\n // with the directional slide applied unless animation is disabled. On mobile the\n // drawer renders as a content-height bottom sheet with a rounded top edge.\n let mergedModalClasses: string;\n if (isPanel) {\n // Within this branch position is never 'center', so effectivePosition is a\n // concrete edge — narrow it for the edge-keyed CVA + slide map.\n const edge = effectivePosition as 'left' | 'right' | 'top' | 'bottom';\n const box = isMobile\n ? cn(modalPanelVariants({ position: 'bottom', size }), 'h-auto max-h-[85vh]')\n : modalPanelVariants({ position: edge, size });\n const slide = animation === 'none' ? undefined : MODAL_PANEL_SLIDE[edge];\n mergedModalClasses = cn(box, slide, className);\n } else {\n mergedModalClasses = cn(modalContentVariants({ size, animation }), className);\n }\n\n return (\n <AriaModalOverlay\n isDismissable={isDismissable}\n isKeyboardDismissDisabled={isKeyboardDismissDisabled}\n className={overlayClasses}\n >\n <AriaModal\n className={mergedModalClasses}\n style={{\n transitionDuration: `${animationDuration}ms`,\n }}\n >\n <AriaDialog role={role} className=\"outline-none\">\n {({ close }) => (\n <>\n {showClose && (\n <AriaButton\n onPress={close}\n className=\"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]\"\n aria-label=\"Close modal\"\n >\n <X className=\"h-4 w-4\" aria-hidden=\"true\" />\n </AriaButton>\n )}\n {children}\n </>\n )}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n}\n\nModalContent.displayName = 'ModalContent';\n\n/**\n * Modal.Overlay Component (Placeholder - not exposed in public API)\n * Overlay is managed internally by Modal.Content via AriaModalOverlay\n */\nfunction ModalOverlay(_props: ModalOverlayProps): null {\n return null;\n}\n\nModalOverlay.displayName = 'ModalOverlay';\n\n/**\n * Modal.Header Component\n *\n * Container for modal header content (typically Title and Description).\n * Applies consistent spacing and layout.\n *\n * @see PRD.md FR-005 (Header Requirements)\n */\nfunction ModalHeader({ children, className }: ModalHeaderProps): ReactElement {\n return <div className={cn('flex flex-col space-y-1.5 text-center sm:text-left', className)}>{children}</div>;\n}\n\nModalHeader.displayName = 'ModalHeader';\n\n/**\n * Modal.Title Component\n *\n * Renders modal title using React Aria's Heading component.\n * Automatically links to modal via aria-labelledby.\n *\n * @see PRD.md FR-006 (Title Requirements)\n * @see PRD.md AR-002 (ARIA Attributes - auto-labelledby)\n */\nfunction ModalTitle({ children, as = 'h2', className }: ModalTitleProps): ReactElement {\n return (\n <Heading slot=\"title\" level={parseInt(as[1] ?? '2')} className={cn('text-lg font-semibold leading-none tracking-tight', className)}>\n {children}\n </Heading>\n );\n}\n\nModalTitle.displayName = 'ModalTitle';\n\n/**\n * Modal.Description Component\n *\n * Renders description text that automatically links to modal via aria-describedby.\n * Uses muted text color for visual hierarchy.\n *\n * @see PRD.md FR-007 (Description Requirements)\n * @see PRD.md AR-002 (ARIA Attributes - auto-describedby)\n */\nfunction ModalDescription({ children, className }: ModalDescriptionProps): ReactElement {\n return (\n <p slot=\"description\" className={cn('text-sm text-[var(--menu-muted)]', className)}>\n {children}\n </p>\n );\n}\n\nModalDescription.displayName = 'ModalDescription';\n\n/**\n * Modal.Footer Component\n *\n * Container for modal action buttons (Cancel, Confirm, etc.).\n * Aligns buttons to the right with consistent spacing.\n * Responsive: stacks vertically on mobile, horizontal on desktop.\n *\n * @see PRD.md FR-008 (Footer Requirements)\n * @see PRD.md DS-003 (Spacing - footer button gap)\n */\nfunction ModalFooter({ children, className }: ModalFooterProps): ReactElement {\n return <div className={cn('flex flex-col-reverse sm:flex-row sm:justify-end gap-2', className)}>{children}</div>;\n}\n\nModalFooter.displayName = 'ModalFooter';\n\n/**\n * Modal.Close Component\n *\n * Wraps a child element (typically Button) with modal close behavior.\n * Uses OverlayTriggerStateContext from React Aria to access close function.\n *\n * @see PRD.md FR-009 (Close Requirements)\n */\nfunction ModalClose({ children }: ModalCloseProps): ReactElement {\n // Access the overlay trigger state from React Aria context\n const state = useContext(OverlayTriggerStateContext);\n\n if (!state) {\n throw new Error('Modal.Close must be used inside Modal.Content');\n }\n\n // Clone the child element and add/merge the onPress handler to close the modal\n if (!isValidElement(children)) {\n throw new Error('Modal.Close requires a valid React element as a child');\n }\n\n // Cast to ReactElement after validation\n const childElement = children as ReactElement;\n\n const handlePress = (): void => {\n state.close();\n };\n\n // Merge with existing onPress if present\n const existingOnPress = (childElement.props as unknown as { onPress?: () => void })?.onPress;\n const mergedOnPress = existingOnPress\n ? (): void => {\n existingOnPress();\n handlePress();\n }\n : handlePress;\n\n // cloneElement with onPress override - use unknown for flexible typing\n return cloneElement(childElement, { onPress: mergedOnPress } as unknown as Partial<typeof childElement.props>);\n}\n\nModalClose.displayName = 'ModalClose';\n\n/**\n * Re-export CVA variants from Modal.styles.ts for backwards compatibility.\n * Consumers importing { modalContentVariants, modalOverlayVariants } from './Modal'\n * will continue to work.\n */\nexport { modalContentVariants, modalOverlayVariants, modalPanelVariants } from './Modal.styles';\n\n/**\n * Compound Component Export\n *\n * Follows Themis library pattern using Object.assign() for compound components.\n * Enables usage like Modal.Trigger, Modal.Content, etc.\n *\n * @deprecated The Object.assign compound pattern will be removed in v2.\n * Use the direct named exports (ModalTrigger, ModalContent, etc.) instead.\n * This pattern is kept for backwards compatibility only.\n *\n * @see RESEARCH.md Section 1 (Compound Component Pattern)\n */\nexport const Modal = Object.assign(ModalRoot, {\n Trigger: ModalTrigger,\n Content: ModalContent,\n Overlay: ModalOverlay,\n Header: ModalHeader,\n Title: ModalTitle,\n Description: ModalDescription,\n Footer: ModalFooter,\n Close: ModalClose,\n});\n\n// Named exports for individual components\nexport {\n ModalRoot,\n ModalTrigger,\n ModalContent,\n ModalOverlay,\n ModalHeader,\n ModalTitle,\n ModalDescription,\n ModalFooter,\n ModalClose,\n};\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import {createContext,Children,isValidElement,useContext,cloneElement}from'react';import {DialogTrigger,OverlayTriggerStateContext,Heading,ModalOverlay,Modal,Dialog,Button}from'react-aria-components';import {X}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx,jsxs,Fragment}from'react/jsx-runtime';function l(...t){return twMerge(clsx(t))}var S=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:zoom-in-95","data-[entering]:duration-200","data-[entering]:ease-out"],b=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:zoom-out-95","data-[exiting]:duration-150","data-[exiting]:ease-in"],L=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:slide-in-from-bottom-4","data-[entering]:duration-200","data-[entering]:ease-out"],V=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:slide-out-to-bottom-4","data-[exiting]:duration-150","data-[exiting]:ease-in"],u=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200"],x=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150"],A=["motion-reduce:transition-none","motion-reduce:animate-none"];var f=cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","rounded-lg","p-6","w-full","outline-none","mx-4","sm:mx-0",...A],{variants:{size:{sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-2xl",full:"max-w-full min-h-screen rounded-none"},animation:{"fade-zoom":[...S,...b],fade:["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200","data-[entering]:ease-out","data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150","data-[exiting]:ease-in"],slide:[...L,...V],none:""}},defaultVariants:{size:"md",animation:"fade-zoom"}}),M=cva(["fixed","inset-0","z-50","flex","items-center","justify-center","bg-black/50","backdrop-blur-sm",...A],{variants:{animation:{"fade-zoom":[...u,...x],fade:[...u,...x],slide:[...u,...x],none:""}},defaultVariants:{animation:"fade-zoom"}});var C=createContext(void 0);function H({children:t,defaultOpen:e,isOpen:o,onOpenChange:r,role:s="dialog"}){let i=Children.toArray(t);if(process.env.NODE_ENV!=="production"&&!i.some(d=>isValidElement(d)&&(d.type===p||d.type.displayName==="ModalContent")))throw new Error("Modal requires a Modal.Content as a child");let m=i.find(n=>isValidElement(n)&&(n.type===O||n.type.displayName==="ModalTrigger")),E=i.find(n=>isValidElement(n)&&(n.type===p||n.type.displayName==="ModalContent"));if(!m)return jsx(C.Provider,{value:{role:s},children:jsx(DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:r,children:E})});let g=m,y=isValidElement(g)?g.props.children:null;return jsx(C.Provider,{value:{role:s},children:jsxs(DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:r,children:[y,E]})})}H.displayName="Modal";function O({children:t}){return t}O.displayName="ModalTrigger";function p({children:t,size:e="md",animation:o="fade-zoom",animationDuration:r=250,isDismissable:s=true,isKeyboardDismissDisabled:i=false,showClose:m=true,className:R}){let g=useContext(C)?.role??"dialog",y=M({animation:o}),n=f({size:e,animation:o}),d=l(n,R);return jsx(ModalOverlay,{isDismissable:s,isKeyboardDismissDisabled:i,className:y,children:jsx(Modal,{className:d,style:{transitionDuration:`${r}ms`},children:jsx(Dialog,{role:g,className:"outline-none",children:({close:z})=>jsxs(Fragment,{children:[m&&jsx(Button,{onPress:z,className:"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]","aria-label":"Close modal",children:jsx(X,{className:"h-4 w-4","aria-hidden":"true"})}),t]})})})})}p.displayName="ModalContent";function N(t){return null}N.displayName="ModalOverlay";function _({children:t,className:e}){return jsx("div",{className:l("flex flex-col space-y-1.5 text-center sm:text-left",e),children:t})}_.displayName="ModalHeader";function T({children:t,as:e="h2",className:o}){return jsx(Heading,{slot:"title",level:parseInt(e[1]??"2"),className:l("text-lg font-semibold leading-none tracking-tight",o),children:t})}T.displayName="ModalTitle";function I({children:t,className:e}){return jsx("p",{slot:"description",className:l("text-sm text-[var(--menu-muted)]",e),children:t})}I.displayName="ModalDescription";function D({children:t,className:e}){return jsx("div",{className:l("flex flex-col-reverse sm:flex-row sm:justify-end gap-2",e),children:t})}D.displayName="ModalFooter";function P({children:t}){let e=useContext(OverlayTriggerStateContext);if(!e)throw new Error("Modal.Close must be used inside Modal.Content");if(!isValidElement(t))throw new Error("Modal.Close requires a valid React element as a child");let o=t,r=()=>{e.close();},s=o.props?.onPress;return cloneElement(o,{onPress:s?()=>{s(),r();}:r})}P.displayName="ModalClose";var J=Object.assign(H,{Trigger:O,Content:p,Overlay:N,Header:_,Title:T,Description:I,Footer:D,Close:P});export{J as Modal,P as ModalClose,p as ModalContent,I as ModalDescription,D as ModalFooter,_ as ModalHeader,N as ModalOverlay,T as ModalTitle,O as ModalTrigger,f as modalContentVariants,M as modalOverlayVariants};//# sourceMappingURL=index.mjs.map
2
+ import {createContext,Children,isValidElement,useContext,cloneElement,useCallback,useSyncExternalStore}from'react';import {DialogTrigger,OverlayTriggerStateContext,Heading,ModalOverlay,Modal,Dialog,Button}from'react-aria-components';import {X as X$1}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx,jsxs,Fragment}from'react/jsx-runtime';function d(...t){return twMerge(clsx(t))}function z(t){let e=useCallback(i=>{let s=window.matchMedia(t);return s.addEventListener("change",i),()=>s.removeEventListener("change",i)},[t]),o=useCallback(()=>window.matchMedia(t).matches,[t]),n=useCallback(()=>false,[]);return useSyncExternalStore(e,o,n)}var H=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:zoom-in-95","data-[entering]:duration-200","data-[entering]:ease-out"],F=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:zoom-out-95","data-[exiting]:duration-150","data-[exiting]:ease-in"],B=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:slide-in-from-bottom-4","data-[entering]:duration-200","data-[entering]:ease-out"],G=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:slide-out-to-bottom-4","data-[exiting]:duration-150","data-[exiting]:ease-in"],k=["data-[entering]:animate-in","data-[entering]:slide-in-from-left","data-[entering]:duration-200","data-[entering]:ease-out"],j=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-left","data-[exiting]:duration-150","data-[exiting]:ease-in"],$=["data-[entering]:animate-in","data-[entering]:slide-in-from-right","data-[entering]:duration-200","data-[entering]:ease-out"],Y=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-right","data-[exiting]:duration-150","data-[exiting]:ease-in"],Z=["data-[entering]:animate-in","data-[entering]:slide-in-from-top","data-[entering]:duration-200","data-[entering]:ease-out"],Q=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-top","data-[exiting]:duration-150","data-[exiting]:ease-in"],X=["data-[entering]:animate-in","data-[entering]:slide-in-from-bottom","data-[entering]:duration-200","data-[entering]:ease-out"],K=["data-[exiting]:animate-out","data-[exiting]:slide-out-to-bottom","data-[exiting]:duration-150","data-[exiting]:ease-in"],M=["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200"],_=["data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150"],O=["motion-reduce:transition-none","motion-reduce:animate-none"];var E=cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","rounded-lg","p-6","w-full","outline-none","mx-4","sm:mx-0",...O],{variants:{size:{sm:"max-w-sm",md:"max-w-md",lg:"max-w-lg",xl:"max-w-2xl",full:"max-w-full min-h-screen rounded-none"},animation:{"fade-zoom":[...H,...F],fade:["data-[entering]:animate-in","data-[entering]:fade-in-0","data-[entering]:duration-200","data-[entering]:ease-out","data-[exiting]:animate-out","data-[exiting]:fade-out-0","data-[exiting]:duration-150","data-[exiting]:ease-in"],slide:[...B,...G],none:""}},defaultVariants:{size:"md",animation:"fade-zoom"}}),v=cva(["fixed","inset-0","z-50","flex","bg-black/50","backdrop-blur-sm",...O],{variants:{animation:{"fade-zoom":[...M,..._],fade:[...M,..._],slide:[...M,..._],none:""},position:{center:"items-center justify-center",left:"items-stretch justify-start",right:"items-stretch justify-end",top:"items-start justify-center",bottom:"items-end justify-center"}},defaultVariants:{animation:"fade-zoom",position:"center"}}),p=cva(["relative","bg-[var(--content-background)]","text-[var(--content-foreground)]","p-6","outline-none","overflow-y-auto",...O],{variants:{position:{left:"h-full border-r border-[var(--border)] rounded-r-lg",right:"h-full border-l border-[var(--border)] rounded-l-lg",top:"w-full border-b border-[var(--border)] rounded-b-lg",bottom:"w-full border-t border-[var(--border)] rounded-t-lg"},size:{sm:"",md:"",lg:"",xl:"",full:""}},compoundVariants:[{position:["left","right"],size:"sm",class:"w-[300px] max-w-[90vw]"},{position:["left","right"],size:"md",class:"w-[400px] max-w-[90vw]"},{position:["left","right"],size:"lg",class:"w-[500px] max-w-[90vw]"},{position:["left","right"],size:"xl",class:"w-[600px] max-w-[90vw]"},{position:["left","right"],size:"full",class:"w-screen"},{position:["top","bottom"],size:"sm",class:"h-[200px] max-h-[90vh]"},{position:["top","bottom"],size:"md",class:"h-[320px] max-h-[90vh]"},{position:["top","bottom"],size:"lg",class:"h-[440px] max-h-[90vh]"},{position:["top","bottom"],size:"xl",class:"h-[560px] max-h-[90vh]"},{position:["top","bottom"],size:"full",class:"h-screen"}],defaultVariants:{position:"right",size:"md"}}),W={left:[...k,...j],right:[...$,...Y],top:[...Z,...Q],bottom:[...X,...K]};var L=createContext(void 0);function tt({children:t,defaultOpen:e,isOpen:o,onOpenChange:n,role:i="dialog"}){let s=Children.toArray(t);if(process.env.NODE_ENV!=="production"&&!s.some(l=>isValidElement(l)&&(l.type===g||l.type.displayName==="ModalContent")))throw new Error("Modal requires a Modal.Content as a child");let u=s.find(r=>isValidElement(r)&&(r.type===T||r.type.displayName==="ModalTrigger")),x=s.find(r=>isValidElement(r)&&(r.type===g||r.type.displayName==="ModalContent"));if(!u)return jsx(L.Provider,{value:{role:i},children:jsx(DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:n,children:x})});let c=u,R=isValidElement(c)?c.props.children:null;return jsx(L.Provider,{value:{role:i},children:jsxs(DialogTrigger,{defaultOpen:e,isOpen:o,onOpenChange:n,children:[R,x]})})}tt.displayName="Modal";function T({children:t}){return t}T.displayName="ModalTrigger";function g({children:t,size:e="md",animation:o="fade-zoom",position:n="center",mobileBreakpoint:i=768,animationDuration:s=250,isDismissable:u=true,isKeyboardDismissDisabled:w=false,showClose:x=true,className:c}){let r=useContext(L)?.role??"dialog",l=n!=="center",V=z(`(max-width: ${i-1}px)`),U=l&&V?"bottom":n,ot=v({animation:o,position:U}),A;if(l){let f=U,at=V?d(p({position:"bottom",size:e}),"h-auto max-h-[85vh]"):p({position:f,size:e}),nt=o==="none"?void 0:W[f];A=d(at,nt,c);}else A=d(E({size:e,animation:o}),c);return jsx(ModalOverlay,{isDismissable:u,isKeyboardDismissDisabled:w,className:ot,children:jsx(Modal,{className:A,style:{transitionDuration:`${s}ms`},children:jsx(Dialog,{role:r,className:"outline-none",children:({close:f})=>jsxs(Fragment,{children:[x&&jsx(Button,{onPress:f,className:"absolute right-0 top-0 flex items-center justify-center rounded-sm opacity-70 ring-offset-[var(--content-background)] transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-[var(--ring)] focus:ring-offset-2 disabled:pointer-events-none min-h-[44px] min-w-[44px]","aria-label":"Close modal",children:jsx(X$1,{className:"h-4 w-4","aria-hidden":"true"})}),t]})})})})}g.displayName="ModalContent";function N(t){return null}N.displayName="ModalOverlay";function h({children:t,className:e}){return jsx("div",{className:d("flex flex-col space-y-1.5 text-center sm:text-left",e),children:t})}h.displayName="ModalHeader";function P({children:t,as:e="h2",className:o}){return jsx(Heading,{slot:"title",level:parseInt(e[1]??"2"),className:d("text-lg font-semibold leading-none tracking-tight",o),children:t})}P.displayName="ModalTitle";function b({children:t,className:e}){return jsx("p",{slot:"description",className:d("text-sm text-[var(--menu-muted)]",e),children:t})}b.displayName="ModalDescription";function C({children:t,className:e}){return jsx("div",{className:d("flex flex-col-reverse sm:flex-row sm:justify-end gap-2",e),children:t})}C.displayName="ModalFooter";function S({children:t}){let e=useContext(OverlayTriggerStateContext);if(!e)throw new Error("Modal.Close must be used inside Modal.Content");if(!isValidElement(t))throw new Error("Modal.Close requires a valid React element as a child");let o=t,n=()=>{e.close();},i=o.props?.onPress;return cloneElement(o,{onPress:i?()=>{i(),n();}:n})}S.displayName="ModalClose";var _t=Object.assign(tt,{Trigger:T,Content:g,Overlay:N,Header:h,Title:P,Description:b,Footer:C,Close:S});export{_t as Modal,S as ModalClose,g as ModalContent,b as ModalDescription,C as ModalFooter,h as ModalHeader,N as ModalOverlay,P as ModalTitle,T as ModalTrigger,E as modalContentVariants,v as modalOverlayVariants,p as modalPanelVariants};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map