@mieweb/ui 0.11.0-dev.35 → 0.11.0-dev.36

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 (156) hide show
  1. package/MIGRATION.md +45 -11
  2. package/dist/{EncounterMdyEditor-73PTTIRY.cjs → EncounterMdyEditor-46WMYRFI.cjs} +6 -6
  3. package/dist/{EncounterMdyEditor-73PTTIRY.cjs.map → EncounterMdyEditor-46WMYRFI.cjs.map} +1 -1
  4. package/dist/{EncounterMdyEditor-3SQY4MK2.js → EncounterMdyEditor-L7RBLE7B.js} +3 -3
  5. package/dist/{EncounterMdyEditor-3SQY4MK2.js.map → EncounterMdyEditor-L7RBLE7B.js.map} +1 -1
  6. package/dist/{chunk-4SUEBKTY.js → chunk-2OTPQPJS.js} +52 -44
  7. package/dist/chunk-2OTPQPJS.js.map +1 -0
  8. package/dist/{chunk-MZR634HI.cjs → chunk-3M2BBOXF.cjs} +9 -9
  9. package/dist/{chunk-MZR634HI.cjs.map → chunk-3M2BBOXF.cjs.map} +1 -1
  10. package/dist/{chunk-6UYMO3PF.cjs → chunk-47AOS5EC.cjs} +10 -2
  11. package/dist/chunk-47AOS5EC.cjs.map +1 -0
  12. package/dist/{chunk-DXNVQQYN.cjs → chunk-6L7CTEX2.cjs} +51 -44
  13. package/dist/chunk-6L7CTEX2.cjs.map +1 -0
  14. package/dist/{chunk-RTADGBBN.js → chunk-AIO2GCTL.js} +3 -3
  15. package/dist/{chunk-RTADGBBN.js.map → chunk-AIO2GCTL.js.map} +1 -1
  16. package/dist/{chunk-EX7Q5545.js → chunk-AKC677ZF.js} +5 -5
  17. package/dist/{chunk-EX7Q5545.js.map → chunk-AKC677ZF.js.map} +1 -1
  18. package/dist/{chunk-XEHD2HA5.cjs → chunk-FRPELUI5.cjs} +3 -3
  19. package/dist/{chunk-XEHD2HA5.cjs.map → chunk-FRPELUI5.cjs.map} +1 -1
  20. package/dist/{chunk-DGHS5IVD.js → chunk-GJSLKD4Q.js} +3 -3
  21. package/dist/{chunk-DGHS5IVD.js.map → chunk-GJSLKD4Q.js.map} +1 -1
  22. package/dist/{chunk-VMEVLBI3.js → chunk-GKMMDKYY.js} +3 -3
  23. package/dist/{chunk-VMEVLBI3.js.map → chunk-GKMMDKYY.js.map} +1 -1
  24. package/dist/{chunk-46RYJYN2.cjs → chunk-GU6TPVXF.cjs} +6 -6
  25. package/dist/{chunk-46RYJYN2.cjs.map → chunk-GU6TPVXF.cjs.map} +1 -1
  26. package/dist/chunk-IALTKN3Y.js +1017 -0
  27. package/dist/chunk-IALTKN3Y.js.map +1 -0
  28. package/dist/{chunk-33Y3KQWL.js → chunk-IGRHPZOJ.js} +3 -3
  29. package/dist/{chunk-33Y3KQWL.js.map → chunk-IGRHPZOJ.js.map} +1 -1
  30. package/dist/{chunk-PLBWZW4F.js → chunk-KAQNYX7B.js} +3 -3
  31. package/dist/{chunk-PLBWZW4F.js.map → chunk-KAQNYX7B.js.map} +1 -1
  32. package/dist/{chunk-SPGP252Q.js → chunk-KB2PLV5Q.js} +4 -4
  33. package/dist/{chunk-SPGP252Q.js.map → chunk-KB2PLV5Q.js.map} +1 -1
  34. package/dist/{chunk-NCPDUJKJ.cjs → chunk-KQXD6BFO.cjs} +4 -4
  35. package/dist/{chunk-NCPDUJKJ.cjs.map → chunk-KQXD6BFO.cjs.map} +1 -1
  36. package/dist/{chunk-4VSK3EE5.cjs → chunk-L77XJPKC.cjs} +3 -3
  37. package/dist/{chunk-4VSK3EE5.cjs.map → chunk-L77XJPKC.cjs.map} +1 -1
  38. package/dist/{chunk-PGJLW2NO.cjs → chunk-LLIG4X6M.cjs} +7 -7
  39. package/dist/{chunk-PGJLW2NO.cjs.map → chunk-LLIG4X6M.cjs.map} +1 -1
  40. package/dist/{chunk-NW6D6AFL.js → chunk-LWLHCUDP.js} +10 -10
  41. package/dist/{chunk-NW6D6AFL.js.map → chunk-LWLHCUDP.js.map} +1 -1
  42. package/dist/{chunk-YR45POH2.js → chunk-MAEANAAJ.js} +3 -3
  43. package/dist/{chunk-YR45POH2.js.map → chunk-MAEANAAJ.js.map} +1 -1
  44. package/dist/{chunk-X5HLVACK.js → chunk-MLCIINXT.js} +4 -4
  45. package/dist/{chunk-X5HLVACK.js.map → chunk-MLCIINXT.js.map} +1 -1
  46. package/dist/{chunk-JEXEFWEM.js → chunk-MNXIN4MS.js} +10 -2
  47. package/dist/chunk-MNXIN4MS.js.map +1 -0
  48. package/dist/{chunk-PHUTJKHL.cjs → chunk-MXIIPFTA.cjs} +3 -3
  49. package/dist/{chunk-PHUTJKHL.cjs.map → chunk-MXIIPFTA.cjs.map} +1 -1
  50. package/dist/{chunk-QO4A6U73.cjs → chunk-NCG7NJAW.cjs} +93 -30
  51. package/dist/chunk-NCG7NJAW.cjs.map +1 -0
  52. package/dist/{chunk-25MPUVTM.js → chunk-NIE3WBJH.js} +94 -31
  53. package/dist/chunk-NIE3WBJH.js.map +1 -0
  54. package/dist/{chunk-4GSFVD5V.js → chunk-NUHHWELE.js} +3 -3
  55. package/dist/{chunk-4GSFVD5V.js.map → chunk-NUHHWELE.js.map} +1 -1
  56. package/dist/{chunk-4M2KE4O5.cjs → chunk-OGFSFUIX.cjs} +7 -7
  57. package/dist/{chunk-4M2KE4O5.cjs.map → chunk-OGFSFUIX.cjs.map} +1 -1
  58. package/dist/{chunk-YSIFPHLX.js → chunk-OJQMC426.js} +2 -2
  59. package/dist/{chunk-YSIFPHLX.js.map → chunk-OJQMC426.js.map} +1 -1
  60. package/dist/{chunk-SVC7NPQ6.cjs → chunk-PDLVSJMZ.cjs} +6 -6
  61. package/dist/{chunk-SVC7NPQ6.cjs.map → chunk-PDLVSJMZ.cjs.map} +1 -1
  62. package/dist/{chunk-KD7YD6US.cjs → chunk-QOQQVNP3.cjs} +2 -2
  63. package/dist/{chunk-KD7YD6US.cjs.map → chunk-QOQQVNP3.cjs.map} +1 -1
  64. package/dist/{chunk-6O6EYKOG.cjs → chunk-R4QWCP2T.cjs} +65 -65
  65. package/dist/{chunk-6O6EYKOG.cjs.map → chunk-R4QWCP2T.cjs.map} +1 -1
  66. package/dist/chunk-RCTIPBLU.cjs +1039 -0
  67. package/dist/chunk-RCTIPBLU.cjs.map +1 -0
  68. package/dist/{chunk-FSWHZY3T.cjs → chunk-RD2I67C4.cjs} +3 -3
  69. package/dist/{chunk-FSWHZY3T.cjs.map → chunk-RD2I67C4.cjs.map} +1 -1
  70. package/dist/{chunk-YGSPIDE4.js → chunk-RM4CBS7Y.js} +3 -3
  71. package/dist/{chunk-YGSPIDE4.js.map → chunk-RM4CBS7Y.js.map} +1 -1
  72. package/dist/{chunk-3O3Q3DX7.cjs → chunk-S3LTUSO5.cjs} +21 -21
  73. package/dist/{chunk-3O3Q3DX7.cjs.map → chunk-S3LTUSO5.cjs.map} +1 -1
  74. package/dist/{chunk-2OXNJJHJ.cjs → chunk-TERHGQ73.cjs} +3 -3
  75. package/dist/{chunk-2OXNJJHJ.cjs.map → chunk-TERHGQ73.cjs.map} +1 -1
  76. package/dist/{chunk-DO7EED3B.cjs → chunk-WZ7WTIVU.cjs} +3 -3
  77. package/dist/{chunk-DO7EED3B.cjs.map → chunk-WZ7WTIVU.cjs.map} +1 -1
  78. package/dist/{chunk-566FIEPE.js → chunk-YFZNSP7F.js} +3 -3
  79. package/dist/{chunk-566FIEPE.js.map → chunk-YFZNSP7F.js.map} +1 -1
  80. package/dist/{chunk-I6Y2KLTZ.js → chunk-ZP4H5HA4.js} +3 -3
  81. package/dist/{chunk-I6Y2KLTZ.js.map → chunk-ZP4H5HA4.js.map} +1 -1
  82. package/dist/components/ActionPlan/index.cjs +1 -1
  83. package/dist/components/ActionPlan/index.js +1 -1
  84. package/dist/components/AlertDialog/index.cjs +7 -7
  85. package/dist/components/AlertDialog/index.js +3 -3
  86. package/dist/components/CustomizableDashboard/index.cjs +1 -1
  87. package/dist/components/CustomizableDashboard/index.js +1 -1
  88. package/dist/components/DateInput/index.cjs +3 -3
  89. package/dist/components/DateInput/index.js +2 -2
  90. package/dist/components/EmailEditor/index.cjs +16 -13
  91. package/dist/components/EmailEditor/index.js +7 -4
  92. package/dist/components/KeyboardShortcutsOverlay/index.cjs +5 -5
  93. package/dist/components/KeyboardShortcutsOverlay/index.js +3 -3
  94. package/dist/components/Markdown/index.cjs +10 -10
  95. package/dist/components/Markdown/index.js +2 -2
  96. package/dist/components/MediaEditor/index.cjs +9 -9
  97. package/dist/components/MediaEditor/index.js +4 -4
  98. package/dist/components/MediaFeed/index.cjs +4 -4
  99. package/dist/components/MediaFeed/index.js +3 -3
  100. package/dist/components/Modal/index.cjs +10 -10
  101. package/dist/components/Modal/index.js +2 -2
  102. package/dist/components/RadialExplorer/index.cjs +3 -3
  103. package/dist/components/RadialExplorer/index.js +2 -2
  104. package/dist/components/RecordHeader/index.cjs +4 -4
  105. package/dist/components/RecordHeader/index.js +2 -2
  106. package/dist/components/RecordLayout/index.cjs +1 -1
  107. package/dist/components/RecordLayout/index.js +1 -1
  108. package/dist/components/Sheet/index.cjs +1 -1
  109. package/dist/components/Sheet/index.js +1 -1
  110. package/dist/components/SuperChat/index.cjs +6 -6
  111. package/dist/components/SuperChat/index.js +5 -5
  112. package/dist/components/SuperChat/plugins/index.cjs +1 -1
  113. package/dist/components/SuperChat/plugins/index.js +1 -1
  114. package/dist/components/TagEditor/index.cjs +4 -4
  115. package/dist/components/TagEditor/index.js +2 -2
  116. package/dist/components/Textarea/index.cjs +7 -4
  117. package/dist/components/Textarea/index.js +4 -1
  118. package/dist/esheet.cjs +122 -123
  119. package/dist/esheet.cjs.map +1 -1
  120. package/dist/esheet.js +25 -26
  121. package/dist/esheet.js.map +1 -1
  122. package/dist/hooks/index.cjs +15 -15
  123. package/dist/hooks/index.js +3 -3
  124. package/dist/index.cjs +456 -425
  125. package/dist/index.cjs.map +1 -1
  126. package/dist/index.d.cts +19 -10
  127. package/dist/index.d.ts +19 -10
  128. package/dist/index.js +80 -42
  129. package/dist/index.js.map +1 -1
  130. package/dist/kerebron.cjs +32 -62
  131. package/dist/kerebron.cjs.map +1 -1
  132. package/dist/kerebron.css +145 -8
  133. package/dist/kerebron.d.cts +299 -1
  134. package/dist/kerebron.d.ts +299 -1
  135. package/dist/kerebron.js +22 -63
  136. package/dist/kerebron.js.map +1 -1
  137. package/dist/{model-EFXX5JZN.cjs → model-5PB6KNYH.cjs} +20 -20
  138. package/dist/{model-EFXX5JZN.cjs.map → model-5PB6KNYH.cjs.map} +1 -1
  139. package/dist/{model-TAARSYDY.js → model-OGWTZEXR.js} +6 -6
  140. package/dist/{model-TAARSYDY.js.map → model-OGWTZEXR.js.map} +1 -1
  141. package/dist/styles.css +1 -1
  142. package/dist/tailwind-preset.cjs +4 -4
  143. package/dist/tailwind-preset.js +1 -1
  144. package/dist/templates.cjs +31 -31
  145. package/dist/templates.js +2 -2
  146. package/dist/utils/index.cjs +5 -5
  147. package/dist/utils/index.d.cts +12 -12
  148. package/dist/utils/index.d.ts +12 -12
  149. package/dist/utils/index.js +1 -1
  150. package/package.json +3 -13
  151. package/dist/chunk-25MPUVTM.js.map +0 -1
  152. package/dist/chunk-4SUEBKTY.js.map +0 -1
  153. package/dist/chunk-6UYMO3PF.cjs.map +0 -1
  154. package/dist/chunk-DXNVQQYN.cjs.map +0 -1
  155. package/dist/chunk-JEXEFWEM.js.map +0 -1
  156. package/dist/chunk-QO4A6U73.cjs.map +0 -1
@@ -1,8 +1,8 @@
1
1
  'use strict';
2
2
 
3
3
  var chunkNNEFAUHV_cjs = require('./chunk-NNEFAUHV.cjs');
4
- var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
5
4
  var chunkSCV7C55E_cjs = require('./chunk-SCV7C55E.cjs');
5
+ var chunkFHY3K6PL_cjs = require('./chunk-FHY3K6PL.cjs');
6
6
  var chunkIEY3ZJIT_cjs = require('./chunk-IEY3ZJIT.cjs');
7
7
  var chunkS5RVSXDV_cjs = require('./chunk-S5RVSXDV.cjs');
8
8
  var React = require('react');
@@ -335,5 +335,5 @@ exports.ModalHeader = ModalHeader;
335
335
  exports.ModalTitle = ModalTitle;
336
336
  exports.modalContentVariants = modalContentVariants;
337
337
  exports.modalOverlayVariants = modalOverlayVariants;
338
- //# sourceMappingURL=chunk-XEHD2HA5.cjs.map
339
- //# sourceMappingURL=chunk-XEHD2HA5.cjs.map
338
+ //# sourceMappingURL=chunk-FRPELUI5.cjs.map
339
+ //# sourceMappingURL=chunk-FRPELUI5.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Modal/Modal.tsx"],"names":["cva","React","useMotionRuntime","useFocusTrap","useEscapeKey","isStorybookDocsMode","jsx","AnimatedPresence","jsxs","Animated","cn"],"mappings":"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","file":"chunk-XEHD2HA5.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isStorybookDocsMode } from '../../utils/environment';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { Animated, AnimatedPresence, useMotionRuntime } from '../../motion';\n\n/**\n * Modal scroll lock state manager.\n * Uses a singleton pattern with ref-like storage to track open modals\n * and manage body scroll locking across multiple modal instances.\n * Includes reset capability for testing environments.\n */\nconst scrollLockState = {\n count: 0,\n originalOverflow: null as string | null,\n reset() {\n this.count = 0;\n this.originalOverflow = null;\n },\n};\n\n// Export for testing environments\nexport const __resetScrollLockState = () => scrollLockState.reset();\n\nconst modalOverlayVariants = cva(\n ['fixed inset-0', 'bg-black/50 backdrop-blur-sm'],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Entry keyframes for the CSS path only.\n *\n * Kept out of the `cva` base so they never run alongside the motion runtime —\n * both drive opacity and transform, and applied together they fight.\n *\n * Entry only: there is no CSS exit. The component unmounts the moment `open`\n * flips to false, so `data-state` is hardcoded `\"open\"` and closed keyframes\n * would be unreachable dead code. That missing exit is the clearest thing the\n * motion opt-in buys back.\n */\nconst MODAL_OVERLAY_FALLBACK_ANIMATION = 'animate-in fade-in-0';\n\nconst MODAL_CONTENT_FALLBACK_ANIMATION =\n 'duration-200 animate-in fade-in-0 zoom-in-95';\n\nconst modalContentVariants = cva(\n [\n 'relative w-full bg-card text-card-foreground',\n 'border border-border shadow-lg',\n // Full-screen on mobile, rounded on larger screens\n 'rounded-none sm:rounded-xl',\n 'flex flex-col',\n // Full viewport height on mobile, constrained on larger screens\n 'max-h-dvh sm:max-h-[calc(100dvh-2rem)]',\n 'min-h-dvh sm:min-h-0',\n // Full-screen on mobile covers the status bar and home indicator, so\n // clear the safe areas there. Overridable for tests and native shells.\n 'pt-[var(--mieweb-safe-area-top,env(safe-area-inset-top))] sm:pt-0',\n 'pb-[var(--mieweb-safe-area-bottom,env(safe-area-inset-bottom))] sm:pb-0',\n // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),\n // make it participate in the flex column layout so overflow constraints work.\n '[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n full: 'max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface ModalProps extends VariantProps<typeof modalContentVariants> {\n /** Whether the modal is open */\n open: boolean;\n /** Callback when the modal should close */\n onOpenChange: (open: boolean) => void;\n /** Modal content */\n children: React.ReactNode;\n /** Whether to close when clicking the overlay */\n closeOnOverlayClick?: boolean;\n /** Whether to close when pressing Escape */\n closeOnEscape?: boolean;\n /** Additional class name for the modal content */\n className?: string;\n /** ID for the modal, used for accessibility */\n id?: string;\n /** Accessible label for the modal */\n 'aria-label'?: string;\n /** ID of the element that labels the modal */\n 'aria-labelledby'?: string;\n /** ID of the element that describes the modal */\n 'aria-describedby'?: string;\n}\n\n/**\n * An accessible modal/dialog component.\n *\n * @example\n * ```tsx\n * <Modal open={isOpen} onOpenChange={setIsOpen} size=\"lg\">\n * <ModalHeader>\n * <ModalTitle>Confirm Action</ModalTitle>\n * <ModalClose />\n * </ModalHeader>\n * <ModalBody>\n * Are you sure you want to continue?\n * </ModalBody>\n * <ModalFooter>\n * <Button variant=\"secondary\" onClick={() => setIsOpen(false)}>Cancel</Button>\n * <Button onClick={handleConfirm}>Confirm</Button>\n * </ModalFooter>\n * </Modal>\n * ```\n */\nfunction Modal({\n open,\n onOpenChange,\n children,\n size,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}: ModalProps) {\n const generatedId = React.useId();\n const modalId = id || generatedId;\n\n /*\n * The dialog outlives `open`.\n *\n * With a motion runtime, `AnimatedPresence` keeps the subtree on screen until\n * its exit animation finishes. Guards keyed on `open` alone would therefore\n * release while a `role=\"dialog\" aria-modal=\"true\"` element is still visible:\n * Tab could reach the page behind it and body scrolling would resume under\n * it. `isGuarded` stays true until presence reports the exit is done.\n *\n * Only tracked when a runtime is actually animating. Without one the subtree\n * unmounts on the same frame, and `onExitComplete` would never fire to clear\n * the flag.\n */\n const runtime = useMotionRuntime();\n const animatesExit = Boolean(runtime?.enabled);\n const [isExiting, setIsExiting] = React.useState(false);\n const [prevOpen, setPrevOpen] = React.useState(open);\n\n // Derived synchronously during render (React's \"adjust state when props\n // change\" pattern), not in an effect. An effect runs after commit, which\n // would leave one committed frame with the dialog still on screen but\n // `isGuarded` false — the focus trap would tear down, restore focus, then\n // re-arm and yank focus into the closing dialog, with the scroll lock\n // flickering alongside. Setting state during render re-renders before\n // commit, so the guards never observe the gap.\n if (prevOpen !== open) {\n setPrevOpen(open);\n if (!open && animatesExit) {\n setIsExiting(true);\n }\n }\n\n // If the runtime disappears or is disabled mid-exit, `onExitComplete` will\n // never fire — the subtree is already gone. Without this reset the guards\n // (and the body scroll lock with them) would be held forever.\n React.useEffect(() => {\n if (!animatesExit && isExiting) {\n setIsExiting(false);\n }\n }, [animatesExit, isExiting]);\n\n const isGuarded = open || isExiting;\n\n // Focus trap. Typed as `HTMLElement` because the content element is supplied\n // by `Animated`, which is element-agnostic.\n const focusTrapRef = useFocusTrap<HTMLElement>(isGuarded);\n\n // Handle escape key\n useEscapeKey(() => {\n if (closeOnEscape && open) {\n onOpenChange(false);\n }\n }, open);\n\n // Handle overlay click\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onOpenChange(false);\n }\n },\n [closeOnOverlayClick, onOpenChange]\n );\n\n // Prevent body scroll while the modal is on screen (handles multiple modals).\n // Keyed on `isGuarded`, not `open`, so scrolling does not resume underneath a\n // dialog that is still animating out.\n // Skip scroll lock in Storybook docs mode where multiple stories render inline\n React.useEffect(() => {\n // Skip scroll lock entirely in Storybook docs mode\n if (!isGuarded || isStorybookDocsMode()) {\n return undefined;\n }\n\n scrollLockState.count++;\n // Only capture and set overflow when first modal opens\n if (scrollLockState.count === 1) {\n scrollLockState.originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n scrollLockState.count--;\n // Only restore overflow when last modal closes\n if (\n scrollLockState.count === 0 &&\n scrollLockState.originalOverflow !== null\n ) {\n document.body.style.overflow = scrollLockState.originalOverflow;\n scrollLockState.originalOverflow = null;\n }\n };\n }, [isGuarded]);\n\n return (\n <ModalContext.Provider\n value={{ onClose: () => onOpenChange(false), modalId }}\n >\n {/*\n The `open` check lives inside `AnimatedPresence` rather than as an early\n `return null` above. On the CSS path this is identical — the tree\n unmounts immediately. With a motion runtime the subtree is held on\n screen until the overlay and content finish their exit animations.\n */}\n <AnimatedPresence onExitComplete={() => setIsExiting(false)}>\n {open && (\n <div\n key=\"modal-root\"\n data-slot=\"modal-root\"\n className=\"fixed inset-0 z-50\"\n >\n {/* Overlay backdrop */}\n <Animated\n preset=\"overlay\"\n mode=\"presence\"\n className={cn(modalOverlayVariants())}\n fallbackClassName={MODAL_OVERLAY_FALLBACK_ANIMATION}\n data-state=\"open\"\n aria-hidden=\"true\"\n />\n {/* Scrollable centering container — click outside to close */}\n <div className=\"fixed inset-0 overflow-y-auto\">\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}\n <div\n className=\"flex min-h-full items-center justify-center p-0 sm:p-4\"\n onClick={handleOverlayClick}\n >\n {/* Content */}\n <Animated\n ref={focusTrapRef}\n preset=\"modalContent\"\n mode=\"presence\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy || `${modalId}-title`}\n aria-describedby={ariaDescribedBy}\n id={modalId}\n tabIndex={-1}\n data-state=\"open\"\n data-slot=\"modal\"\n className={cn(modalContentVariants({ size }), className)}\n fallbackClassName={MODAL_CONTENT_FALLBACK_ANIMATION}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </Animated>\n </div>\n </div>\n </div>\n )}\n </AnimatedPresence>\n </ModalContext.Provider>\n );\n}\n\nModal.displayName = 'Modal';\n\n// ============================================================================\n// Modal Context\n// ============================================================================\n\ninterface ModalContextValue {\n onClose: () => void;\n modalId: string;\n}\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\nfunction useModalContext() {\n const context = React.useContext(ModalContext);\n if (!context) {\n throw new Error('Modal components must be used within a Modal');\n }\n return context;\n}\n\n// ============================================================================\n// Modal Header\n// ============================================================================\n\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Header section of a Modal.\n */\nconst ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-header\"\n className={cn(\n 'flex shrink-0 items-center justify-between',\n 'border-border border-b px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalHeader.displayName = 'ModalHeader';\n\n// ============================================================================\n// Modal Title\n// ============================================================================\n\nexport type ModalTitleProps = React.HTMLAttributes<HTMLHeadingElement>;\n\n/**\n * Title for a Modal.\n */\nconst ModalTitle = React.forwardRef<HTMLHeadingElement, ModalTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { modalId } = useModalContext();\n return (\n <h2\n ref={ref}\n id={`${modalId}-title`}\n data-slot=\"modal-title\"\n className={cn(\n 'text-lg leading-none font-semibold tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </h2>\n );\n }\n);\n\nModalTitle.displayName = 'ModalTitle';\n\n// ============================================================================\n// Modal Close Button\n// ============================================================================\n\nexport type ModalCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for a Modal.\n */\nconst ModalClose = React.forwardRef<HTMLButtonElement, ModalCloseProps>(\n ({ className, children, onClick, ...props }, ref) => {\n const { onClose } = useModalContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (!e.defaultPrevented) {\n onClose();\n }\n },\n [onClick, onClose]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleClick}\n data-slot=\"modal-close\"\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-lg',\n 'text-muted-foreground hover:text-foreground',\n 'hover:bg-muted transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n className\n )}\n aria-label=\"Close\"\n {...props}\n >\n {children || <CloseIcon />}\n </button>\n );\n }\n);\n\nModalClose.displayName = 'ModalClose';\n\n// ============================================================================\n// Modal Body\n// ============================================================================\n\nexport type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Main content area of a Modal.\n */\nconst ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-body\"\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4', className)}\n {...props}\n />\n )\n);\n\nModalBody.displayName = 'ModalBody';\n\n// ============================================================================\n// Modal Footer\n// ============================================================================\n\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Footer section of a Modal, typically for action buttons.\n */\nconst ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-footer\"\n className={cn(\n 'flex shrink-0 items-center justify-end gap-3',\n 'border-border border-t px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalFooter.displayName = 'ModalFooter';\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nfunction CloseIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n modalContentVariants,\n modalOverlayVariants,\n};\n"]}
1
+ {"version":3,"sources":["../src/components/Modal/Modal.tsx"],"names":["cva","React","useMotionRuntime","useFocusTrap","useEscapeKey","isStorybookDocsMode","jsx","AnimatedPresence","jsxs","Animated","cn"],"mappings":"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","file":"chunk-FRPELUI5.cjs","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isStorybookDocsMode } from '../../utils/environment';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { Animated, AnimatedPresence, useMotionRuntime } from '../../motion';\n\n/**\n * Modal scroll lock state manager.\n * Uses a singleton pattern with ref-like storage to track open modals\n * and manage body scroll locking across multiple modal instances.\n * Includes reset capability for testing environments.\n */\nconst scrollLockState = {\n count: 0,\n originalOverflow: null as string | null,\n reset() {\n this.count = 0;\n this.originalOverflow = null;\n },\n};\n\n// Export for testing environments\nexport const __resetScrollLockState = () => scrollLockState.reset();\n\nconst modalOverlayVariants = cva(\n ['fixed inset-0', 'bg-black/50 backdrop-blur-sm'],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Entry keyframes for the CSS path only.\n *\n * Kept out of the `cva` base so they never run alongside the motion runtime —\n * both drive opacity and transform, and applied together they fight.\n *\n * Entry only: there is no CSS exit. The component unmounts the moment `open`\n * flips to false, so `data-state` is hardcoded `\"open\"` and closed keyframes\n * would be unreachable dead code. That missing exit is the clearest thing the\n * motion opt-in buys back.\n */\nconst MODAL_OVERLAY_FALLBACK_ANIMATION = 'animate-in fade-in-0';\n\nconst MODAL_CONTENT_FALLBACK_ANIMATION =\n 'duration-200 animate-in fade-in-0 zoom-in-95';\n\nconst modalContentVariants = cva(\n [\n 'relative w-full bg-card text-card-foreground',\n 'border border-border shadow-lg',\n // Full-screen on mobile, rounded on larger screens\n 'rounded-none sm:rounded-xl',\n 'flex flex-col',\n // Full viewport height on mobile, constrained on larger screens\n 'max-h-dvh sm:max-h-[calc(100dvh-2rem)]',\n 'min-h-dvh sm:min-h-0',\n // Full-screen on mobile covers the status bar and home indicator, so\n // clear the safe areas there. Overridable for tests and native shells.\n 'pt-[var(--mieweb-safe-area-top,env(safe-area-inset-top))] sm:pt-0',\n 'pb-[var(--mieweb-safe-area-bottom,env(safe-area-inset-bottom))] sm:pb-0',\n // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),\n // make it participate in the flex column layout so overflow constraints work.\n '[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n full: 'max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface ModalProps extends VariantProps<typeof modalContentVariants> {\n /** Whether the modal is open */\n open: boolean;\n /** Callback when the modal should close */\n onOpenChange: (open: boolean) => void;\n /** Modal content */\n children: React.ReactNode;\n /** Whether to close when clicking the overlay */\n closeOnOverlayClick?: boolean;\n /** Whether to close when pressing Escape */\n closeOnEscape?: boolean;\n /** Additional class name for the modal content */\n className?: string;\n /** ID for the modal, used for accessibility */\n id?: string;\n /** Accessible label for the modal */\n 'aria-label'?: string;\n /** ID of the element that labels the modal */\n 'aria-labelledby'?: string;\n /** ID of the element that describes the modal */\n 'aria-describedby'?: string;\n}\n\n/**\n * An accessible modal/dialog component.\n *\n * @example\n * ```tsx\n * <Modal open={isOpen} onOpenChange={setIsOpen} size=\"lg\">\n * <ModalHeader>\n * <ModalTitle>Confirm Action</ModalTitle>\n * <ModalClose />\n * </ModalHeader>\n * <ModalBody>\n * Are you sure you want to continue?\n * </ModalBody>\n * <ModalFooter>\n * <Button variant=\"secondary\" onClick={() => setIsOpen(false)}>Cancel</Button>\n * <Button onClick={handleConfirm}>Confirm</Button>\n * </ModalFooter>\n * </Modal>\n * ```\n */\nfunction Modal({\n open,\n onOpenChange,\n children,\n size,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}: ModalProps) {\n const generatedId = React.useId();\n const modalId = id || generatedId;\n\n /*\n * The dialog outlives `open`.\n *\n * With a motion runtime, `AnimatedPresence` keeps the subtree on screen until\n * its exit animation finishes. Guards keyed on `open` alone would therefore\n * release while a `role=\"dialog\" aria-modal=\"true\"` element is still visible:\n * Tab could reach the page behind it and body scrolling would resume under\n * it. `isGuarded` stays true until presence reports the exit is done.\n *\n * Only tracked when a runtime is actually animating. Without one the subtree\n * unmounts on the same frame, and `onExitComplete` would never fire to clear\n * the flag.\n */\n const runtime = useMotionRuntime();\n const animatesExit = Boolean(runtime?.enabled);\n const [isExiting, setIsExiting] = React.useState(false);\n const [prevOpen, setPrevOpen] = React.useState(open);\n\n // Derived synchronously during render (React's \"adjust state when props\n // change\" pattern), not in an effect. An effect runs after commit, which\n // would leave one committed frame with the dialog still on screen but\n // `isGuarded` false — the focus trap would tear down, restore focus, then\n // re-arm and yank focus into the closing dialog, with the scroll lock\n // flickering alongside. Setting state during render re-renders before\n // commit, so the guards never observe the gap.\n if (prevOpen !== open) {\n setPrevOpen(open);\n if (!open && animatesExit) {\n setIsExiting(true);\n }\n }\n\n // If the runtime disappears or is disabled mid-exit, `onExitComplete` will\n // never fire — the subtree is already gone. Without this reset the guards\n // (and the body scroll lock with them) would be held forever.\n React.useEffect(() => {\n if (!animatesExit && isExiting) {\n setIsExiting(false);\n }\n }, [animatesExit, isExiting]);\n\n const isGuarded = open || isExiting;\n\n // Focus trap. Typed as `HTMLElement` because the content element is supplied\n // by `Animated`, which is element-agnostic.\n const focusTrapRef = useFocusTrap<HTMLElement>(isGuarded);\n\n // Handle escape key\n useEscapeKey(() => {\n if (closeOnEscape && open) {\n onOpenChange(false);\n }\n }, open);\n\n // Handle overlay click\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onOpenChange(false);\n }\n },\n [closeOnOverlayClick, onOpenChange]\n );\n\n // Prevent body scroll while the modal is on screen (handles multiple modals).\n // Keyed on `isGuarded`, not `open`, so scrolling does not resume underneath a\n // dialog that is still animating out.\n // Skip scroll lock in Storybook docs mode where multiple stories render inline\n React.useEffect(() => {\n // Skip scroll lock entirely in Storybook docs mode\n if (!isGuarded || isStorybookDocsMode()) {\n return undefined;\n }\n\n scrollLockState.count++;\n // Only capture and set overflow when first modal opens\n if (scrollLockState.count === 1) {\n scrollLockState.originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n scrollLockState.count--;\n // Only restore overflow when last modal closes\n if (\n scrollLockState.count === 0 &&\n scrollLockState.originalOverflow !== null\n ) {\n document.body.style.overflow = scrollLockState.originalOverflow;\n scrollLockState.originalOverflow = null;\n }\n };\n }, [isGuarded]);\n\n return (\n <ModalContext.Provider\n value={{ onClose: () => onOpenChange(false), modalId }}\n >\n {/*\n The `open` check lives inside `AnimatedPresence` rather than as an early\n `return null` above. On the CSS path this is identical — the tree\n unmounts immediately. With a motion runtime the subtree is held on\n screen until the overlay and content finish their exit animations.\n */}\n <AnimatedPresence onExitComplete={() => setIsExiting(false)}>\n {open && (\n <div\n key=\"modal-root\"\n data-slot=\"modal-root\"\n className=\"fixed inset-0 z-50\"\n >\n {/* Overlay backdrop */}\n <Animated\n preset=\"overlay\"\n mode=\"presence\"\n className={cn(modalOverlayVariants())}\n fallbackClassName={MODAL_OVERLAY_FALLBACK_ANIMATION}\n data-state=\"open\"\n aria-hidden=\"true\"\n />\n {/* Scrollable centering container — click outside to close */}\n <div className=\"fixed inset-0 overflow-y-auto\">\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}\n <div\n className=\"flex min-h-full items-center justify-center p-0 sm:p-4\"\n onClick={handleOverlayClick}\n >\n {/* Content */}\n <Animated\n ref={focusTrapRef}\n preset=\"modalContent\"\n mode=\"presence\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy || `${modalId}-title`}\n aria-describedby={ariaDescribedBy}\n id={modalId}\n tabIndex={-1}\n data-state=\"open\"\n data-slot=\"modal\"\n className={cn(modalContentVariants({ size }), className)}\n fallbackClassName={MODAL_CONTENT_FALLBACK_ANIMATION}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </Animated>\n </div>\n </div>\n </div>\n )}\n </AnimatedPresence>\n </ModalContext.Provider>\n );\n}\n\nModal.displayName = 'Modal';\n\n// ============================================================================\n// Modal Context\n// ============================================================================\n\ninterface ModalContextValue {\n onClose: () => void;\n modalId: string;\n}\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\nfunction useModalContext() {\n const context = React.useContext(ModalContext);\n if (!context) {\n throw new Error('Modal components must be used within a Modal');\n }\n return context;\n}\n\n// ============================================================================\n// Modal Header\n// ============================================================================\n\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Header section of a Modal.\n */\nconst ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-header\"\n className={cn(\n 'flex shrink-0 items-center justify-between',\n 'border-border border-b px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalHeader.displayName = 'ModalHeader';\n\n// ============================================================================\n// Modal Title\n// ============================================================================\n\nexport type ModalTitleProps = React.HTMLAttributes<HTMLHeadingElement>;\n\n/**\n * Title for a Modal.\n */\nconst ModalTitle = React.forwardRef<HTMLHeadingElement, ModalTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { modalId } = useModalContext();\n return (\n <h2\n ref={ref}\n id={`${modalId}-title`}\n data-slot=\"modal-title\"\n className={cn(\n 'text-lg leading-none font-semibold tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </h2>\n );\n }\n);\n\nModalTitle.displayName = 'ModalTitle';\n\n// ============================================================================\n// Modal Close Button\n// ============================================================================\n\nexport type ModalCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for a Modal.\n */\nconst ModalClose = React.forwardRef<HTMLButtonElement, ModalCloseProps>(\n ({ className, children, onClick, ...props }, ref) => {\n const { onClose } = useModalContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (!e.defaultPrevented) {\n onClose();\n }\n },\n [onClick, onClose]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleClick}\n data-slot=\"modal-close\"\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-lg',\n 'text-muted-foreground hover:text-foreground',\n 'hover:bg-muted transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n className\n )}\n aria-label=\"Close\"\n {...props}\n >\n {children || <CloseIcon />}\n </button>\n );\n }\n);\n\nModalClose.displayName = 'ModalClose';\n\n// ============================================================================\n// Modal Body\n// ============================================================================\n\nexport type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Main content area of a Modal.\n */\nconst ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-body\"\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4', className)}\n {...props}\n />\n )\n);\n\nModalBody.displayName = 'ModalBody';\n\n// ============================================================================\n// Modal Footer\n// ============================================================================\n\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Footer section of a Modal, typically for action buttons.\n */\nconst ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-footer\"\n className={cn(\n 'flex shrink-0 items-center justify-end gap-3',\n 'border-border border-t px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalFooter.displayName = 'ModalFooter';\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nfunction CloseIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n modalContentVariants,\n modalOverlayVariants,\n};\n"]}
@@ -1,6 +1,6 @@
1
+ import { Badge } from './chunk-522WJIVI.js';
1
2
  import { useClickOutside } from './chunk-62ZOA6PX.js';
2
3
  import { useAnchoredPosition } from './chunk-WSNMQQ4P.js';
3
- import { Badge } from './chunk-522WJIVI.js';
4
4
  import { cn } from './chunk-TQONQSJO.js';
5
5
  import * as React from 'react';
6
6
  import { createPortal } from 'react-dom';
@@ -301,5 +301,5 @@ var TagEditor = React.forwardRef(
301
301
  TagEditor.displayName = "TagEditor";
302
302
 
303
303
  export { TagEditor, defaultTagEditorLabels };
304
- //# sourceMappingURL=chunk-DGHS5IVD.js.map
305
- //# sourceMappingURL=chunk-DGHS5IVD.js.map
304
+ //# sourceMappingURL=chunk-GJSLKD4Q.js.map
305
+ //# sourceMappingURL=chunk-GJSLKD4Q.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/TagEditor/TagEditor.tsx"],"names":["TagEditor"],"mappings":"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","file":"chunk-DGHS5IVD.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Loader2 } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Badge } from '../Badge';\nimport { useAnchoredPosition } from '../../hooks/useAnchoredPosition';\nimport { useClickOutside } from '../../hooks/useClickOutside';\n\nexport interface TagEditorLabels {\n /** Accessible name of the text input when no visible `label` is given. */\n input: string;\n placeholder: string;\n remove: (tag: string) => string;\n duplicate: (tag: string) => string;\n maxReached: (max: number) => string;\n saving: string;\n saveFailed: string;\n /** Accessible name of the suggestions list. */\n suggestions: string;\n}\n\nexport const defaultTagEditorLabels: TagEditorLabels = {\n input: 'Add tag',\n placeholder: 'Add a tag…',\n remove: (tag) => `Remove ${tag}`,\n duplicate: (tag) => `\"${tag}\" is already added`,\n maxReached: (max) => `You can add up to ${max} tags`,\n saving: 'Saving…',\n saveFailed: 'Could not save tags. Try again.',\n suggestions: 'Suggestions',\n};\n\nconst containerVariants = cva(\n [\n 'flex w-full flex-wrap items-center gap-1.5 rounded-lg border bg-background',\n 'focus-within:ring-ring focus-within:ring-2',\n ],\n {\n variants: {\n size: { sm: 'min-h-8 px-2 py-1 text-sm', md: 'min-h-10 px-3 py-1.5' },\n hasError: { true: 'border-destructive', false: 'border-input' },\n },\n defaultVariants: { size: 'md', hasError: false },\n }\n);\n\nexport interface TagEditorProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<VariantProps<typeof containerVariants>, 'hasError'> {\n /** Current tags (controlled). */\n value: string[];\n /** Receives the next tag list. May return a promise; a rejection shows an error. */\n onChange: (tags: string[]) => void | Promise<void>;\n /** Optional values offered while typing. */\n suggestions?: string[];\n /** Maximum number of tags. */\n maxTags?: number;\n /** Return an error message to reject a tag. */\n validate?: (tag: string) => string | undefined;\n /** Visible label for the field. */\n label?: string;\n readOnly?: boolean;\n disabled?: boolean;\n /** Translatable strings. */\n labels?: Partial<TagEditorLabels>;\n}\n\n/**\n * Edit a list of free-form tags: chips with remove buttons plus an input that\n * adds on Enter or comma, with optional suggestions.\n */\nexport const TagEditor = React.forwardRef<HTMLDivElement, TagEditorProps>(\n function TagEditor(\n {\n value,\n onChange,\n suggestions,\n maxTags,\n validate,\n label,\n readOnly,\n disabled,\n size,\n labels: labelOverrides,\n className,\n ...props\n },\n ref\n ) {\n const labels = { ...defaultTagEditorLabels, ...labelOverrides };\n const [draft, setDraft] = React.useState('');\n const [error, setError] = React.useState<string | null>(null);\n const [pending, setPending] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const [activeIndex, setActiveIndex] = React.useState(-1);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const id = React.useId();\n const inputId = `${id}-input`;\n const errorId = `${id}-error`;\n const listId = `${id}-list`;\n\n const { anchorRef, floatingRef, style } = useAnchoredPosition<\n HTMLDivElement,\n HTMLDivElement\n >({ open, matchWidth: true, maxHeight: 240 });\n const outsideRefs = React.useMemo(\n () => [containerRef, floatingRef],\n [floatingRef]\n );\n useClickOutside(outsideRefs, () => setOpen(false), open);\n\n const has = (tag: string) =>\n value.some((t) => t.toLowerCase() === tag.toLowerCase());\n const query = draft.trim().toLowerCase();\n const matches = (suggestions ?? []).filter(\n (s) => !has(s) && (!query || s.toLowerCase().includes(query))\n );\n const isOpen = open && matches.length > 0 && !pending;\n const interactive = !readOnly && !disabled && !pending;\n const atMax = maxTags !== undefined && value.length >= maxTags;\n // State lags a render behind; the ref blocks a second save from the same tick.\n const inFlight = React.useRef(false);\n\n const commit = async (next: string[], refocus = true) => {\n inFlight.current = true;\n setPending(true);\n try {\n await onChange(next);\n } catch {\n setError(labels.saveFailed);\n } finally {\n inFlight.current = false;\n setPending(false);\n if (refocus) inputRef.current?.focus();\n }\n };\n\n const add = (raw: string[], refocus = true) => {\n if (inFlight.current) return;\n const next = [...value];\n for (const piece of raw) {\n const tag = piece.trim();\n if (!tag) continue;\n if (next.some((t) => t.toLowerCase() === tag.toLowerCase())) {\n setError(labels.duplicate(tag));\n return;\n }\n if (maxTags !== undefined && next.length >= maxTags) {\n setError(labels.maxReached(maxTags));\n return;\n }\n const invalid = validate?.(tag);\n if (invalid) {\n setError(invalid);\n return;\n }\n next.push(tag);\n }\n setError(null);\n setDraft('');\n setActiveIndex(-1);\n if (next.length !== value.length) void commit(next, refocus);\n };\n\n const remove = (index: number) => {\n if (inFlight.current) return;\n setError(null);\n void commit(value.filter((_, i) => i !== index));\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n setOpen(true);\n if (!matches.length) return;\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setActiveIndex((i) => (i + step + matches.length) % matches.length);\n } else if (e.key === 'Enter' || e.key === ',') {\n if (e.key === 'Enter' && !draft.trim() && activeIndex < 0) return;\n e.preventDefault();\n add([isOpen && activeIndex >= 0 ? matches[activeIndex] : draft]);\n } else if (e.key === 'Backspace' && !draft && value.length) {\n remove(value.length - 1);\n } else if (e.key === 'Escape' && isOpen) {\n e.preventDefault();\n setOpen(false);\n setActiveIndex(-1);\n }\n };\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const parts = e.target.value.split(',');\n setOpen(true);\n setActiveIndex(-1);\n if (parts.length > 1) {\n add(parts.slice(0, -1));\n setDraft(parts[parts.length - 1]);\n } else {\n setDraft(e.target.value);\n if (error) setError(null);\n }\n };\n\n return (\n <div\n ref={ref}\n data-slot=\"tag-editor\"\n className={cn('w-full', className)}\n {...props}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"text-foreground mb-1.5 block text-sm font-medium\"\n >\n {label}\n </label>\n )}\n <div\n ref={(node) => {\n containerRef.current = node;\n anchorRef.current = node;\n }}\n data-slot=\"tag-editor-field\"\n aria-busy={pending || undefined}\n className={cn(\n containerVariants({ size, hasError: !!error }),\n disabled && 'cursor-not-allowed opacity-50',\n readOnly && 'focus-within:ring-0'\n )}\n >\n {value.length > 0 && (\n <ul\n aria-label={label ?? labels.input}\n className=\"flex max-w-full flex-wrap items-center gap-1.5\"\n >\n {value.map((tag, index) => (\n <li\n key={tag}\n data-slot=\"tag-editor-tag\"\n className=\"inline-flex max-w-full\"\n >\n <Badge\n className=\"max-w-full\"\n onRemove={\n readOnly\n ? undefined\n : (e) => {\n e.stopPropagation();\n remove(index);\n }\n }\n removeLabel={labels.remove(tag)}\n removeDisabled={!interactive}\n >\n <span className=\"truncate\">{tag}</span>\n </Badge>\n </li>\n ))}\n </ul>\n )}\n {!readOnly && (\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n aria-label={label ? undefined : labels.input}\n aria-expanded={isOpen}\n aria-controls={suggestions ? listId : undefined}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n isOpen && activeIndex >= 0\n ? `${listId}-${activeIndex}`\n : undefined\n }\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n autoComplete=\"off\"\n value={draft}\n placeholder={atMax ? undefined : labels.placeholder}\n disabled={disabled}\n readOnly={pending || atMax}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setOpen(true)}\n onBlur={() => {\n setOpen(false);\n if (draft.trim()) add([draft], false);\n }}\n className=\"placeholder:text-muted-foreground text-foreground min-w-24 flex-1 bg-transparent py-0.5 outline-none disabled:cursor-not-allowed\"\n />\n )}\n {pending && (\n <span role=\"status\" className=\"inline-flex\">\n <Loader2\n aria-hidden=\"true\"\n className=\"text-muted-foreground h-4 w-4 animate-spin motion-reduce:animate-none\"\n />\n <span className=\"sr-only\">{labels.saving}</span>\n </span>\n )}\n </div>\n {error && (\n <p\n id={errorId}\n role=\"alert\"\n data-slot=\"tag-editor-error\"\n className=\"text-destructive-700 dark:text-destructive-400 mt-1 text-sm\"\n >\n {error}\n </p>\n )}\n {isOpen &&\n createPortal(\n <div\n ref={floatingRef}\n style={style}\n id={listId}\n role=\"listbox\"\n aria-label={labels.suggestions}\n data-slot=\"tag-editor-suggestions\"\n className=\"border-border bg-card text-card-foreground overflow-auto rounded-md border py-1 shadow-lg\"\n >\n {matches.map((s, i) => (\n <button\n key={s}\n type=\"button\"\n tabIndex={-1}\n id={`${listId}-${i}`}\n role=\"option\"\n aria-selected={i === activeIndex}\n onMouseEnter={() => setActiveIndex(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => add([s])}\n className={cn(\n 'block w-full px-3 py-2 text-start text-sm',\n i === activeIndex ? 'bg-muted' : 'hover:bg-muted'\n )}\n >\n {s}\n </button>\n ))}\n </div>,\n document.body\n )}\n </div>\n );\n }\n);\n\nTagEditor.displayName = 'TagEditor';\n"]}
1
+ {"version":3,"sources":["../src/components/TagEditor/TagEditor.tsx"],"names":["TagEditor"],"mappings":"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","file":"chunk-GJSLKD4Q.js","sourcesContent":["'use client';\n\nimport * as React from 'react';\nimport { createPortal } from 'react-dom';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { Loader2 } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Badge } from '../Badge';\nimport { useAnchoredPosition } from '../../hooks/useAnchoredPosition';\nimport { useClickOutside } from '../../hooks/useClickOutside';\n\nexport interface TagEditorLabels {\n /** Accessible name of the text input when no visible `label` is given. */\n input: string;\n placeholder: string;\n remove: (tag: string) => string;\n duplicate: (tag: string) => string;\n maxReached: (max: number) => string;\n saving: string;\n saveFailed: string;\n /** Accessible name of the suggestions list. */\n suggestions: string;\n}\n\nexport const defaultTagEditorLabels: TagEditorLabels = {\n input: 'Add tag',\n placeholder: 'Add a tag…',\n remove: (tag) => `Remove ${tag}`,\n duplicate: (tag) => `\"${tag}\" is already added`,\n maxReached: (max) => `You can add up to ${max} tags`,\n saving: 'Saving…',\n saveFailed: 'Could not save tags. Try again.',\n suggestions: 'Suggestions',\n};\n\nconst containerVariants = cva(\n [\n 'flex w-full flex-wrap items-center gap-1.5 rounded-lg border bg-background',\n 'focus-within:ring-ring focus-within:ring-2',\n ],\n {\n variants: {\n size: { sm: 'min-h-8 px-2 py-1 text-sm', md: 'min-h-10 px-3 py-1.5' },\n hasError: { true: 'border-destructive', false: 'border-input' },\n },\n defaultVariants: { size: 'md', hasError: false },\n }\n);\n\nexport interface TagEditorProps\n extends\n Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'defaultValue'>,\n Omit<VariantProps<typeof containerVariants>, 'hasError'> {\n /** Current tags (controlled). */\n value: string[];\n /** Receives the next tag list. May return a promise; a rejection shows an error. */\n onChange: (tags: string[]) => void | Promise<void>;\n /** Optional values offered while typing. */\n suggestions?: string[];\n /** Maximum number of tags. */\n maxTags?: number;\n /** Return an error message to reject a tag. */\n validate?: (tag: string) => string | undefined;\n /** Visible label for the field. */\n label?: string;\n readOnly?: boolean;\n disabled?: boolean;\n /** Translatable strings. */\n labels?: Partial<TagEditorLabels>;\n}\n\n/**\n * Edit a list of free-form tags: chips with remove buttons plus an input that\n * adds on Enter or comma, with optional suggestions.\n */\nexport const TagEditor = React.forwardRef<HTMLDivElement, TagEditorProps>(\n function TagEditor(\n {\n value,\n onChange,\n suggestions,\n maxTags,\n validate,\n label,\n readOnly,\n disabled,\n size,\n labels: labelOverrides,\n className,\n ...props\n },\n ref\n ) {\n const labels = { ...defaultTagEditorLabels, ...labelOverrides };\n const [draft, setDraft] = React.useState('');\n const [error, setError] = React.useState<string | null>(null);\n const [pending, setPending] = React.useState(false);\n const [open, setOpen] = React.useState(false);\n const [activeIndex, setActiveIndex] = React.useState(-1);\n const inputRef = React.useRef<HTMLInputElement>(null);\n const containerRef = React.useRef<HTMLDivElement>(null);\n const id = React.useId();\n const inputId = `${id}-input`;\n const errorId = `${id}-error`;\n const listId = `${id}-list`;\n\n const { anchorRef, floatingRef, style } = useAnchoredPosition<\n HTMLDivElement,\n HTMLDivElement\n >({ open, matchWidth: true, maxHeight: 240 });\n const outsideRefs = React.useMemo(\n () => [containerRef, floatingRef],\n [floatingRef]\n );\n useClickOutside(outsideRefs, () => setOpen(false), open);\n\n const has = (tag: string) =>\n value.some((t) => t.toLowerCase() === tag.toLowerCase());\n const query = draft.trim().toLowerCase();\n const matches = (suggestions ?? []).filter(\n (s) => !has(s) && (!query || s.toLowerCase().includes(query))\n );\n const isOpen = open && matches.length > 0 && !pending;\n const interactive = !readOnly && !disabled && !pending;\n const atMax = maxTags !== undefined && value.length >= maxTags;\n // State lags a render behind; the ref blocks a second save from the same tick.\n const inFlight = React.useRef(false);\n\n const commit = async (next: string[], refocus = true) => {\n inFlight.current = true;\n setPending(true);\n try {\n await onChange(next);\n } catch {\n setError(labels.saveFailed);\n } finally {\n inFlight.current = false;\n setPending(false);\n if (refocus) inputRef.current?.focus();\n }\n };\n\n const add = (raw: string[], refocus = true) => {\n if (inFlight.current) return;\n const next = [...value];\n for (const piece of raw) {\n const tag = piece.trim();\n if (!tag) continue;\n if (next.some((t) => t.toLowerCase() === tag.toLowerCase())) {\n setError(labels.duplicate(tag));\n return;\n }\n if (maxTags !== undefined && next.length >= maxTags) {\n setError(labels.maxReached(maxTags));\n return;\n }\n const invalid = validate?.(tag);\n if (invalid) {\n setError(invalid);\n return;\n }\n next.push(tag);\n }\n setError(null);\n setDraft('');\n setActiveIndex(-1);\n if (next.length !== value.length) void commit(next, refocus);\n };\n\n const remove = (index: number) => {\n if (inFlight.current) return;\n setError(null);\n void commit(value.filter((_, i) => i !== index));\n };\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {\n if (e.key === 'ArrowDown' || e.key === 'ArrowUp') {\n e.preventDefault();\n setOpen(true);\n if (!matches.length) return;\n const step = e.key === 'ArrowDown' ? 1 : -1;\n setActiveIndex((i) => (i + step + matches.length) % matches.length);\n } else if (e.key === 'Enter' || e.key === ',') {\n if (e.key === 'Enter' && !draft.trim() && activeIndex < 0) return;\n e.preventDefault();\n add([isOpen && activeIndex >= 0 ? matches[activeIndex] : draft]);\n } else if (e.key === 'Backspace' && !draft && value.length) {\n remove(value.length - 1);\n } else if (e.key === 'Escape' && isOpen) {\n e.preventDefault();\n setOpen(false);\n setActiveIndex(-1);\n }\n };\n\n const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {\n const parts = e.target.value.split(',');\n setOpen(true);\n setActiveIndex(-1);\n if (parts.length > 1) {\n add(parts.slice(0, -1));\n setDraft(parts[parts.length - 1]);\n } else {\n setDraft(e.target.value);\n if (error) setError(null);\n }\n };\n\n return (\n <div\n ref={ref}\n data-slot=\"tag-editor\"\n className={cn('w-full', className)}\n {...props}\n >\n {label && (\n <label\n htmlFor={inputId}\n className=\"text-foreground mb-1.5 block text-sm font-medium\"\n >\n {label}\n </label>\n )}\n <div\n ref={(node) => {\n containerRef.current = node;\n anchorRef.current = node;\n }}\n data-slot=\"tag-editor-field\"\n aria-busy={pending || undefined}\n className={cn(\n containerVariants({ size, hasError: !!error }),\n disabled && 'cursor-not-allowed opacity-50',\n readOnly && 'focus-within:ring-0'\n )}\n >\n {value.length > 0 && (\n <ul\n aria-label={label ?? labels.input}\n className=\"flex max-w-full flex-wrap items-center gap-1.5\"\n >\n {value.map((tag, index) => (\n <li\n key={tag}\n data-slot=\"tag-editor-tag\"\n className=\"inline-flex max-w-full\"\n >\n <Badge\n className=\"max-w-full\"\n onRemove={\n readOnly\n ? undefined\n : (e) => {\n e.stopPropagation();\n remove(index);\n }\n }\n removeLabel={labels.remove(tag)}\n removeDisabled={!interactive}\n >\n <span className=\"truncate\">{tag}</span>\n </Badge>\n </li>\n ))}\n </ul>\n )}\n {!readOnly && (\n <input\n ref={inputRef}\n id={inputId}\n type=\"text\"\n role=\"combobox\"\n aria-label={label ? undefined : labels.input}\n aria-expanded={isOpen}\n aria-controls={suggestions ? listId : undefined}\n aria-autocomplete=\"list\"\n aria-activedescendant={\n isOpen && activeIndex >= 0\n ? `${listId}-${activeIndex}`\n : undefined\n }\n aria-invalid={error ? true : undefined}\n aria-describedby={error ? errorId : undefined}\n autoComplete=\"off\"\n value={draft}\n placeholder={atMax ? undefined : labels.placeholder}\n disabled={disabled}\n readOnly={pending || atMax}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onFocus={() => setOpen(true)}\n onBlur={() => {\n setOpen(false);\n if (draft.trim()) add([draft], false);\n }}\n className=\"placeholder:text-muted-foreground text-foreground min-w-24 flex-1 bg-transparent py-0.5 outline-none disabled:cursor-not-allowed\"\n />\n )}\n {pending && (\n <span role=\"status\" className=\"inline-flex\">\n <Loader2\n aria-hidden=\"true\"\n className=\"text-muted-foreground h-4 w-4 animate-spin motion-reduce:animate-none\"\n />\n <span className=\"sr-only\">{labels.saving}</span>\n </span>\n )}\n </div>\n {error && (\n <p\n id={errorId}\n role=\"alert\"\n data-slot=\"tag-editor-error\"\n className=\"text-destructive-700 dark:text-destructive-400 mt-1 text-sm\"\n >\n {error}\n </p>\n )}\n {isOpen &&\n createPortal(\n <div\n ref={floatingRef}\n style={style}\n id={listId}\n role=\"listbox\"\n aria-label={labels.suggestions}\n data-slot=\"tag-editor-suggestions\"\n className=\"border-border bg-card text-card-foreground overflow-auto rounded-md border py-1 shadow-lg\"\n >\n {matches.map((s, i) => (\n <button\n key={s}\n type=\"button\"\n tabIndex={-1}\n id={`${listId}-${i}`}\n role=\"option\"\n aria-selected={i === activeIndex}\n onMouseEnter={() => setActiveIndex(i)}\n onMouseDown={(e) => e.preventDefault()}\n onClick={() => add([s])}\n className={cn(\n 'block w-full px-3 py-2 text-start text-sm',\n i === activeIndex ? 'bg-muted' : 'hover:bg-muted'\n )}\n >\n {s}\n </button>\n ))}\n </div>,\n document.body\n )}\n </div>\n );\n }\n);\n\nTagEditor.displayName = 'TagEditor';\n"]}
@@ -1,6 +1,6 @@
1
1
  import { useFocusTrap } from './chunk-4SMSH4OY.js';
2
- import { useEscapeKey } from './chunk-T4ME7QCT.js';
3
2
  import { isStorybookDocsMode } from './chunk-VSQF22GL.js';
3
+ import { useEscapeKey } from './chunk-T4ME7QCT.js';
4
4
  import { useMotionRuntime, AnimatedPresence, Animated } from './chunk-F4N67NAF.js';
5
5
  import { cn } from './chunk-TQONQSJO.js';
6
6
  import * as React from 'react';
@@ -306,5 +306,5 @@ function CloseIcon() {
306
306
  }
307
307
 
308
308
  export { Modal, ModalBody, ModalClose, ModalFooter, ModalHeader, ModalTitle, modalContentVariants, modalOverlayVariants };
309
- //# sourceMappingURL=chunk-VMEVLBI3.js.map
310
- //# sourceMappingURL=chunk-VMEVLBI3.js.map
309
+ //# sourceMappingURL=chunk-GKMMDKYY.js.map
310
+ //# sourceMappingURL=chunk-GKMMDKYY.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/components/Modal/Modal.tsx"],"names":[],"mappings":"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","file":"chunk-VMEVLBI3.js","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isStorybookDocsMode } from '../../utils/environment';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { Animated, AnimatedPresence, useMotionRuntime } from '../../motion';\n\n/**\n * Modal scroll lock state manager.\n * Uses a singleton pattern with ref-like storage to track open modals\n * and manage body scroll locking across multiple modal instances.\n * Includes reset capability for testing environments.\n */\nconst scrollLockState = {\n count: 0,\n originalOverflow: null as string | null,\n reset() {\n this.count = 0;\n this.originalOverflow = null;\n },\n};\n\n// Export for testing environments\nexport const __resetScrollLockState = () => scrollLockState.reset();\n\nconst modalOverlayVariants = cva(\n ['fixed inset-0', 'bg-black/50 backdrop-blur-sm'],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Entry keyframes for the CSS path only.\n *\n * Kept out of the `cva` base so they never run alongside the motion runtime —\n * both drive opacity and transform, and applied together they fight.\n *\n * Entry only: there is no CSS exit. The component unmounts the moment `open`\n * flips to false, so `data-state` is hardcoded `\"open\"` and closed keyframes\n * would be unreachable dead code. That missing exit is the clearest thing the\n * motion opt-in buys back.\n */\nconst MODAL_OVERLAY_FALLBACK_ANIMATION = 'animate-in fade-in-0';\n\nconst MODAL_CONTENT_FALLBACK_ANIMATION =\n 'duration-200 animate-in fade-in-0 zoom-in-95';\n\nconst modalContentVariants = cva(\n [\n 'relative w-full bg-card text-card-foreground',\n 'border border-border shadow-lg',\n // Full-screen on mobile, rounded on larger screens\n 'rounded-none sm:rounded-xl',\n 'flex flex-col',\n // Full viewport height on mobile, constrained on larger screens\n 'max-h-dvh sm:max-h-[calc(100dvh-2rem)]',\n 'min-h-dvh sm:min-h-0',\n // Full-screen on mobile covers the status bar and home indicator, so\n // clear the safe areas there. Overridable for tests and native shells.\n 'pt-[var(--mieweb-safe-area-top,env(safe-area-inset-top))] sm:pt-0',\n 'pb-[var(--mieweb-safe-area-bottom,env(safe-area-inset-bottom))] sm:pb-0',\n // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),\n // make it participate in the flex column layout so overflow constraints work.\n '[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n full: 'max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface ModalProps extends VariantProps<typeof modalContentVariants> {\n /** Whether the modal is open */\n open: boolean;\n /** Callback when the modal should close */\n onOpenChange: (open: boolean) => void;\n /** Modal content */\n children: React.ReactNode;\n /** Whether to close when clicking the overlay */\n closeOnOverlayClick?: boolean;\n /** Whether to close when pressing Escape */\n closeOnEscape?: boolean;\n /** Additional class name for the modal content */\n className?: string;\n /** ID for the modal, used for accessibility */\n id?: string;\n /** Accessible label for the modal */\n 'aria-label'?: string;\n /** ID of the element that labels the modal */\n 'aria-labelledby'?: string;\n /** ID of the element that describes the modal */\n 'aria-describedby'?: string;\n}\n\n/**\n * An accessible modal/dialog component.\n *\n * @example\n * ```tsx\n * <Modal open={isOpen} onOpenChange={setIsOpen} size=\"lg\">\n * <ModalHeader>\n * <ModalTitle>Confirm Action</ModalTitle>\n * <ModalClose />\n * </ModalHeader>\n * <ModalBody>\n * Are you sure you want to continue?\n * </ModalBody>\n * <ModalFooter>\n * <Button variant=\"secondary\" onClick={() => setIsOpen(false)}>Cancel</Button>\n * <Button onClick={handleConfirm}>Confirm</Button>\n * </ModalFooter>\n * </Modal>\n * ```\n */\nfunction Modal({\n open,\n onOpenChange,\n children,\n size,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}: ModalProps) {\n const generatedId = React.useId();\n const modalId = id || generatedId;\n\n /*\n * The dialog outlives `open`.\n *\n * With a motion runtime, `AnimatedPresence` keeps the subtree on screen until\n * its exit animation finishes. Guards keyed on `open` alone would therefore\n * release while a `role=\"dialog\" aria-modal=\"true\"` element is still visible:\n * Tab could reach the page behind it and body scrolling would resume under\n * it. `isGuarded` stays true until presence reports the exit is done.\n *\n * Only tracked when a runtime is actually animating. Without one the subtree\n * unmounts on the same frame, and `onExitComplete` would never fire to clear\n * the flag.\n */\n const runtime = useMotionRuntime();\n const animatesExit = Boolean(runtime?.enabled);\n const [isExiting, setIsExiting] = React.useState(false);\n const [prevOpen, setPrevOpen] = React.useState(open);\n\n // Derived synchronously during render (React's \"adjust state when props\n // change\" pattern), not in an effect. An effect runs after commit, which\n // would leave one committed frame with the dialog still on screen but\n // `isGuarded` false — the focus trap would tear down, restore focus, then\n // re-arm and yank focus into the closing dialog, with the scroll lock\n // flickering alongside. Setting state during render re-renders before\n // commit, so the guards never observe the gap.\n if (prevOpen !== open) {\n setPrevOpen(open);\n if (!open && animatesExit) {\n setIsExiting(true);\n }\n }\n\n // If the runtime disappears or is disabled mid-exit, `onExitComplete` will\n // never fire — the subtree is already gone. Without this reset the guards\n // (and the body scroll lock with them) would be held forever.\n React.useEffect(() => {\n if (!animatesExit && isExiting) {\n setIsExiting(false);\n }\n }, [animatesExit, isExiting]);\n\n const isGuarded = open || isExiting;\n\n // Focus trap. Typed as `HTMLElement` because the content element is supplied\n // by `Animated`, which is element-agnostic.\n const focusTrapRef = useFocusTrap<HTMLElement>(isGuarded);\n\n // Handle escape key\n useEscapeKey(() => {\n if (closeOnEscape && open) {\n onOpenChange(false);\n }\n }, open);\n\n // Handle overlay click\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onOpenChange(false);\n }\n },\n [closeOnOverlayClick, onOpenChange]\n );\n\n // Prevent body scroll while the modal is on screen (handles multiple modals).\n // Keyed on `isGuarded`, not `open`, so scrolling does not resume underneath a\n // dialog that is still animating out.\n // Skip scroll lock in Storybook docs mode where multiple stories render inline\n React.useEffect(() => {\n // Skip scroll lock entirely in Storybook docs mode\n if (!isGuarded || isStorybookDocsMode()) {\n return undefined;\n }\n\n scrollLockState.count++;\n // Only capture and set overflow when first modal opens\n if (scrollLockState.count === 1) {\n scrollLockState.originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n scrollLockState.count--;\n // Only restore overflow when last modal closes\n if (\n scrollLockState.count === 0 &&\n scrollLockState.originalOverflow !== null\n ) {\n document.body.style.overflow = scrollLockState.originalOverflow;\n scrollLockState.originalOverflow = null;\n }\n };\n }, [isGuarded]);\n\n return (\n <ModalContext.Provider\n value={{ onClose: () => onOpenChange(false), modalId }}\n >\n {/*\n The `open` check lives inside `AnimatedPresence` rather than as an early\n `return null` above. On the CSS path this is identical — the tree\n unmounts immediately. With a motion runtime the subtree is held on\n screen until the overlay and content finish their exit animations.\n */}\n <AnimatedPresence onExitComplete={() => setIsExiting(false)}>\n {open && (\n <div\n key=\"modal-root\"\n data-slot=\"modal-root\"\n className=\"fixed inset-0 z-50\"\n >\n {/* Overlay backdrop */}\n <Animated\n preset=\"overlay\"\n mode=\"presence\"\n className={cn(modalOverlayVariants())}\n fallbackClassName={MODAL_OVERLAY_FALLBACK_ANIMATION}\n data-state=\"open\"\n aria-hidden=\"true\"\n />\n {/* Scrollable centering container — click outside to close */}\n <div className=\"fixed inset-0 overflow-y-auto\">\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}\n <div\n className=\"flex min-h-full items-center justify-center p-0 sm:p-4\"\n onClick={handleOverlayClick}\n >\n {/* Content */}\n <Animated\n ref={focusTrapRef}\n preset=\"modalContent\"\n mode=\"presence\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy || `${modalId}-title`}\n aria-describedby={ariaDescribedBy}\n id={modalId}\n tabIndex={-1}\n data-state=\"open\"\n data-slot=\"modal\"\n className={cn(modalContentVariants({ size }), className)}\n fallbackClassName={MODAL_CONTENT_FALLBACK_ANIMATION}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </Animated>\n </div>\n </div>\n </div>\n )}\n </AnimatedPresence>\n </ModalContext.Provider>\n );\n}\n\nModal.displayName = 'Modal';\n\n// ============================================================================\n// Modal Context\n// ============================================================================\n\ninterface ModalContextValue {\n onClose: () => void;\n modalId: string;\n}\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\nfunction useModalContext() {\n const context = React.useContext(ModalContext);\n if (!context) {\n throw new Error('Modal components must be used within a Modal');\n }\n return context;\n}\n\n// ============================================================================\n// Modal Header\n// ============================================================================\n\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Header section of a Modal.\n */\nconst ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-header\"\n className={cn(\n 'flex shrink-0 items-center justify-between',\n 'border-border border-b px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalHeader.displayName = 'ModalHeader';\n\n// ============================================================================\n// Modal Title\n// ============================================================================\n\nexport type ModalTitleProps = React.HTMLAttributes<HTMLHeadingElement>;\n\n/**\n * Title for a Modal.\n */\nconst ModalTitle = React.forwardRef<HTMLHeadingElement, ModalTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { modalId } = useModalContext();\n return (\n <h2\n ref={ref}\n id={`${modalId}-title`}\n data-slot=\"modal-title\"\n className={cn(\n 'text-lg leading-none font-semibold tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </h2>\n );\n }\n);\n\nModalTitle.displayName = 'ModalTitle';\n\n// ============================================================================\n// Modal Close Button\n// ============================================================================\n\nexport type ModalCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for a Modal.\n */\nconst ModalClose = React.forwardRef<HTMLButtonElement, ModalCloseProps>(\n ({ className, children, onClick, ...props }, ref) => {\n const { onClose } = useModalContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (!e.defaultPrevented) {\n onClose();\n }\n },\n [onClick, onClose]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleClick}\n data-slot=\"modal-close\"\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-lg',\n 'text-muted-foreground hover:text-foreground',\n 'hover:bg-muted transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n className\n )}\n aria-label=\"Close\"\n {...props}\n >\n {children || <CloseIcon />}\n </button>\n );\n }\n);\n\nModalClose.displayName = 'ModalClose';\n\n// ============================================================================\n// Modal Body\n// ============================================================================\n\nexport type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Main content area of a Modal.\n */\nconst ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-body\"\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4', className)}\n {...props}\n />\n )\n);\n\nModalBody.displayName = 'ModalBody';\n\n// ============================================================================\n// Modal Footer\n// ============================================================================\n\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Footer section of a Modal, typically for action buttons.\n */\nconst ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-footer\"\n className={cn(\n 'flex shrink-0 items-center justify-end gap-3',\n 'border-border border-t px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalFooter.displayName = 'ModalFooter';\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nfunction CloseIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n modalContentVariants,\n modalOverlayVariants,\n};\n"]}
1
+ {"version":3,"sources":["../src/components/Modal/Modal.tsx"],"names":[],"mappings":"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","file":"chunk-GKMMDKYY.js","sourcesContent":["import * as React from 'react';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { isStorybookDocsMode } from '../../utils/environment';\nimport { useFocusTrap } from '../../hooks/useFocusTrap';\nimport { useEscapeKey } from '../../hooks/useEscapeKey';\nimport { Animated, AnimatedPresence, useMotionRuntime } from '../../motion';\n\n/**\n * Modal scroll lock state manager.\n * Uses a singleton pattern with ref-like storage to track open modals\n * and manage body scroll locking across multiple modal instances.\n * Includes reset capability for testing environments.\n */\nconst scrollLockState = {\n count: 0,\n originalOverflow: null as string | null,\n reset() {\n this.count = 0;\n this.originalOverflow = null;\n },\n};\n\n// Export for testing environments\nexport const __resetScrollLockState = () => scrollLockState.reset();\n\nconst modalOverlayVariants = cva(\n ['fixed inset-0', 'bg-black/50 backdrop-blur-sm'],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Entry keyframes for the CSS path only.\n *\n * Kept out of the `cva` base so they never run alongside the motion runtime —\n * both drive opacity and transform, and applied together they fight.\n *\n * Entry only: there is no CSS exit. The component unmounts the moment `open`\n * flips to false, so `data-state` is hardcoded `\"open\"` and closed keyframes\n * would be unreachable dead code. That missing exit is the clearest thing the\n * motion opt-in buys back.\n */\nconst MODAL_OVERLAY_FALLBACK_ANIMATION = 'animate-in fade-in-0';\n\nconst MODAL_CONTENT_FALLBACK_ANIMATION =\n 'duration-200 animate-in fade-in-0 zoom-in-95';\n\nconst modalContentVariants = cva(\n [\n 'relative w-full bg-card text-card-foreground',\n 'border border-border shadow-lg',\n // Full-screen on mobile, rounded on larger screens\n 'rounded-none sm:rounded-xl',\n 'flex flex-col',\n // Full viewport height on mobile, constrained on larger screens\n 'max-h-dvh sm:max-h-[calc(100dvh-2rem)]',\n 'min-h-dvh sm:min-h-0',\n // Full-screen on mobile covers the status bar and home indicator, so\n // clear the safe areas there. Overridable for tests and native shells.\n 'pt-[var(--mieweb-safe-area-top,env(safe-area-inset-top))] sm:pt-0',\n 'pb-[var(--mieweb-safe-area-bottom,env(safe-area-inset-bottom))] sm:pb-0',\n // If a <form> is used as a direct child (wrapping ModalBody + ModalFooter),\n // make it participate in the flex column layout so overflow constraints work.\n '[&>form]:flex [&>form]:flex-col [&>form]:flex-1 [&>form]:min-h-0',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'sm:max-w-sm',\n md: 'sm:max-w-md',\n lg: 'sm:max-w-lg',\n xl: 'sm:max-w-xl',\n '2xl': 'sm:max-w-2xl',\n '3xl': 'sm:max-w-3xl',\n '4xl': 'sm:max-w-4xl',\n full: 'max-w-[calc(100vw-2rem)]',\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\nexport interface ModalProps extends VariantProps<typeof modalContentVariants> {\n /** Whether the modal is open */\n open: boolean;\n /** Callback when the modal should close */\n onOpenChange: (open: boolean) => void;\n /** Modal content */\n children: React.ReactNode;\n /** Whether to close when clicking the overlay */\n closeOnOverlayClick?: boolean;\n /** Whether to close when pressing Escape */\n closeOnEscape?: boolean;\n /** Additional class name for the modal content */\n className?: string;\n /** ID for the modal, used for accessibility */\n id?: string;\n /** Accessible label for the modal */\n 'aria-label'?: string;\n /** ID of the element that labels the modal */\n 'aria-labelledby'?: string;\n /** ID of the element that describes the modal */\n 'aria-describedby'?: string;\n}\n\n/**\n * An accessible modal/dialog component.\n *\n * @example\n * ```tsx\n * <Modal open={isOpen} onOpenChange={setIsOpen} size=\"lg\">\n * <ModalHeader>\n * <ModalTitle>Confirm Action</ModalTitle>\n * <ModalClose />\n * </ModalHeader>\n * <ModalBody>\n * Are you sure you want to continue?\n * </ModalBody>\n * <ModalFooter>\n * <Button variant=\"secondary\" onClick={() => setIsOpen(false)}>Cancel</Button>\n * <Button onClick={handleConfirm}>Confirm</Button>\n * </ModalFooter>\n * </Modal>\n * ```\n */\nfunction Modal({\n open,\n onOpenChange,\n children,\n size,\n closeOnOverlayClick = true,\n closeOnEscape = true,\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'aria-describedby': ariaDescribedBy,\n}: ModalProps) {\n const generatedId = React.useId();\n const modalId = id || generatedId;\n\n /*\n * The dialog outlives `open`.\n *\n * With a motion runtime, `AnimatedPresence` keeps the subtree on screen until\n * its exit animation finishes. Guards keyed on `open` alone would therefore\n * release while a `role=\"dialog\" aria-modal=\"true\"` element is still visible:\n * Tab could reach the page behind it and body scrolling would resume under\n * it. `isGuarded` stays true until presence reports the exit is done.\n *\n * Only tracked when a runtime is actually animating. Without one the subtree\n * unmounts on the same frame, and `onExitComplete` would never fire to clear\n * the flag.\n */\n const runtime = useMotionRuntime();\n const animatesExit = Boolean(runtime?.enabled);\n const [isExiting, setIsExiting] = React.useState(false);\n const [prevOpen, setPrevOpen] = React.useState(open);\n\n // Derived synchronously during render (React's \"adjust state when props\n // change\" pattern), not in an effect. An effect runs after commit, which\n // would leave one committed frame with the dialog still on screen but\n // `isGuarded` false — the focus trap would tear down, restore focus, then\n // re-arm and yank focus into the closing dialog, with the scroll lock\n // flickering alongside. Setting state during render re-renders before\n // commit, so the guards never observe the gap.\n if (prevOpen !== open) {\n setPrevOpen(open);\n if (!open && animatesExit) {\n setIsExiting(true);\n }\n }\n\n // If the runtime disappears or is disabled mid-exit, `onExitComplete` will\n // never fire — the subtree is already gone. Without this reset the guards\n // (and the body scroll lock with them) would be held forever.\n React.useEffect(() => {\n if (!animatesExit && isExiting) {\n setIsExiting(false);\n }\n }, [animatesExit, isExiting]);\n\n const isGuarded = open || isExiting;\n\n // Focus trap. Typed as `HTMLElement` because the content element is supplied\n // by `Animated`, which is element-agnostic.\n const focusTrapRef = useFocusTrap<HTMLElement>(isGuarded);\n\n // Handle escape key\n useEscapeKey(() => {\n if (closeOnEscape && open) {\n onOpenChange(false);\n }\n }, open);\n\n // Handle overlay click\n const handleOverlayClick = React.useCallback(\n (e: React.MouseEvent) => {\n if (closeOnOverlayClick && e.target === e.currentTarget) {\n onOpenChange(false);\n }\n },\n [closeOnOverlayClick, onOpenChange]\n );\n\n // Prevent body scroll while the modal is on screen (handles multiple modals).\n // Keyed on `isGuarded`, not `open`, so scrolling does not resume underneath a\n // dialog that is still animating out.\n // Skip scroll lock in Storybook docs mode where multiple stories render inline\n React.useEffect(() => {\n // Skip scroll lock entirely in Storybook docs mode\n if (!isGuarded || isStorybookDocsMode()) {\n return undefined;\n }\n\n scrollLockState.count++;\n // Only capture and set overflow when first modal opens\n if (scrollLockState.count === 1) {\n scrollLockState.originalOverflow = document.body.style.overflow;\n document.body.style.overflow = 'hidden';\n }\n\n return () => {\n scrollLockState.count--;\n // Only restore overflow when last modal closes\n if (\n scrollLockState.count === 0 &&\n scrollLockState.originalOverflow !== null\n ) {\n document.body.style.overflow = scrollLockState.originalOverflow;\n scrollLockState.originalOverflow = null;\n }\n };\n }, [isGuarded]);\n\n return (\n <ModalContext.Provider\n value={{ onClose: () => onOpenChange(false), modalId }}\n >\n {/*\n The `open` check lives inside `AnimatedPresence` rather than as an early\n `return null` above. On the CSS path this is identical — the tree\n unmounts immediately. With a motion runtime the subtree is held on\n screen until the overlay and content finish their exit animations.\n */}\n <AnimatedPresence onExitComplete={() => setIsExiting(false)}>\n {open && (\n <div\n key=\"modal-root\"\n data-slot=\"modal-root\"\n className=\"fixed inset-0 z-50\"\n >\n {/* Overlay backdrop */}\n <Animated\n preset=\"overlay\"\n mode=\"presence\"\n className={cn(modalOverlayVariants())}\n fallbackClassName={MODAL_OVERLAY_FALLBACK_ANIMATION}\n data-state=\"open\"\n aria-hidden=\"true\"\n />\n {/* Scrollable centering container — click outside to close */}\n <div className=\"fixed inset-0 overflow-y-auto\">\n {/* eslint-disable-next-line jsx-a11y/click-events-have-key-events, jsx-a11y/no-static-element-interactions */}\n <div\n className=\"flex min-h-full items-center justify-center p-0 sm:p-4\"\n onClick={handleOverlayClick}\n >\n {/* Content */}\n <Animated\n ref={focusTrapRef}\n preset=\"modalContent\"\n mode=\"presence\"\n role=\"dialog\"\n aria-modal=\"true\"\n aria-label={ariaLabel}\n aria-labelledby={ariaLabelledBy || `${modalId}-title`}\n aria-describedby={ariaDescribedBy}\n id={modalId}\n tabIndex={-1}\n data-state=\"open\"\n data-slot=\"modal\"\n className={cn(modalContentVariants({ size }), className)}\n fallbackClassName={MODAL_CONTENT_FALLBACK_ANIMATION}\n onClick={(e) => e.stopPropagation()}\n >\n {children}\n </Animated>\n </div>\n </div>\n </div>\n )}\n </AnimatedPresence>\n </ModalContext.Provider>\n );\n}\n\nModal.displayName = 'Modal';\n\n// ============================================================================\n// Modal Context\n// ============================================================================\n\ninterface ModalContextValue {\n onClose: () => void;\n modalId: string;\n}\n\nconst ModalContext = React.createContext<ModalContextValue | undefined>(\n undefined\n);\n\nfunction useModalContext() {\n const context = React.useContext(ModalContext);\n if (!context) {\n throw new Error('Modal components must be used within a Modal');\n }\n return context;\n}\n\n// ============================================================================\n// Modal Header\n// ============================================================================\n\nexport type ModalHeaderProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Header section of a Modal.\n */\nconst ModalHeader = React.forwardRef<HTMLDivElement, ModalHeaderProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-header\"\n className={cn(\n 'flex shrink-0 items-center justify-between',\n 'border-border border-b px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalHeader.displayName = 'ModalHeader';\n\n// ============================================================================\n// Modal Title\n// ============================================================================\n\nexport type ModalTitleProps = React.HTMLAttributes<HTMLHeadingElement>;\n\n/**\n * Title for a Modal.\n */\nconst ModalTitle = React.forwardRef<HTMLHeadingElement, ModalTitleProps>(\n ({ className, children, ...props }, ref) => {\n const { modalId } = useModalContext();\n return (\n <h2\n ref={ref}\n id={`${modalId}-title`}\n data-slot=\"modal-title\"\n className={cn(\n 'text-lg leading-none font-semibold tracking-tight',\n className\n )}\n {...props}\n >\n {children}\n </h2>\n );\n }\n);\n\nModalTitle.displayName = 'ModalTitle';\n\n// ============================================================================\n// Modal Close Button\n// ============================================================================\n\nexport type ModalCloseProps = React.ButtonHTMLAttributes<HTMLButtonElement>;\n\n/**\n * Close button for a Modal.\n */\nconst ModalClose = React.forwardRef<HTMLButtonElement, ModalCloseProps>(\n ({ className, children, onClick, ...props }, ref) => {\n const { onClose } = useModalContext();\n\n const handleClick = React.useCallback(\n (e: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(e);\n if (!e.defaultPrevented) {\n onClose();\n }\n },\n [onClick, onClose]\n );\n\n return (\n <button\n ref={ref}\n type=\"button\"\n onClick={handleClick}\n data-slot=\"modal-close\"\n className={cn(\n 'inline-flex h-8 w-8 items-center justify-center rounded-lg',\n 'text-muted-foreground hover:text-foreground',\n 'hover:bg-muted transition-colors',\n 'focus-visible:ring-ring focus-visible:ring-2 focus-visible:outline-none',\n className\n )}\n aria-label=\"Close\"\n {...props}\n >\n {children || <CloseIcon />}\n </button>\n );\n }\n);\n\nModalClose.displayName = 'ModalClose';\n\n// ============================================================================\n// Modal Body\n// ============================================================================\n\nexport type ModalBodyProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Main content area of a Modal.\n */\nconst ModalBody = React.forwardRef<HTMLDivElement, ModalBodyProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-body\"\n className={cn('min-h-0 flex-1 overflow-y-auto px-6 py-4', className)}\n {...props}\n />\n )\n);\n\nModalBody.displayName = 'ModalBody';\n\n// ============================================================================\n// Modal Footer\n// ============================================================================\n\nexport type ModalFooterProps = React.HTMLAttributes<HTMLDivElement>;\n\n/**\n * Footer section of a Modal, typically for action buttons.\n */\nconst ModalFooter = React.forwardRef<HTMLDivElement, ModalFooterProps>(\n ({ className, ...props }, ref) => (\n <div\n ref={ref}\n data-slot=\"modal-footer\"\n className={cn(\n 'flex shrink-0 items-center justify-end gap-3',\n 'border-border border-t px-6 py-4',\n className\n )}\n {...props}\n />\n )\n);\n\nModalFooter.displayName = 'ModalFooter';\n\n// ============================================================================\n// Close Icon\n// ============================================================================\n\nfunction CloseIcon() {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n aria-hidden=\"true\"\n >\n <path d=\"M18 6 6 18\" />\n <path d=\"m6 6 12 12\" />\n </svg>\n );\n}\n\nexport {\n Modal,\n ModalHeader,\n ModalTitle,\n ModalClose,\n ModalBody,\n ModalFooter,\n modalContentVariants,\n modalOverlayVariants,\n};\n"]}
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkNCPDUJKJ_cjs = require('./chunk-NCPDUJKJ.cjs');
3
+ var chunkKQXD6BFO_cjs = require('./chunk-KQXD6BFO.cjs');
4
4
  var luxon = require('luxon');
5
5
  var templit = require('@mieweb/templit');
6
6
  var markdown = require('@mieweb/templit/markdown');
@@ -1304,7 +1304,7 @@ async function renderEncounterMdy(source) {
1304
1304
  let parsed = parseEncounterMdy(source);
1305
1305
  let fields = fieldsFromFrontMatter(parsed.frontMatter ?? {});
1306
1306
  if (parsed.definition && parsed.response) {
1307
- const { createEncounterSnapshot: createEncounterSnapshot2 } = await import('./model-EFXX5JZN.cjs');
1307
+ const { createEncounterSnapshot: createEncounterSnapshot2 } = await import('./model-5PB6KNYH.cjs');
1308
1308
  const snapshot = createEncounterSnapshot2(parsed.definition, {
1309
1309
  ...parsed.response,
1310
1310
  [ENCOUNTER_DOCUMENT_FIELD_ID]: encounterDocumentResponse(source)
@@ -1940,7 +1940,7 @@ function validateCoding(section, parsed, fieldId, externalConcerns = []) {
1940
1940
  if (Array.isArray(parsed.concerns))
1941
1941
  parsed.concerns.forEach((entry, index) => {
1942
1942
  if (!record2(entry) || !Array.isArray(entry.assertions)) return;
1943
- const assertion = chunkNCPDUJKJ_cjs.currentAssertion(
1943
+ const assertion = chunkKQXD6BFO_cjs.currentAssertion(
1944
1944
  entry
1945
1945
  );
1946
1946
  if (!assertion?.coding?.some(coded)) add(`concerns.${index}.coding`);
@@ -2273,7 +2273,7 @@ function exportCustom(section, answer, externalConcerns = []) {
2273
2273
  }
2274
2274
  if (section.kind === "conditions") {
2275
2275
  return parsed.concerns.flatMap((concern) => {
2276
- const assertion = chunkNCPDUJKJ_cjs.currentAssertion(concern);
2276
+ const assertion = chunkKQXD6BFO_cjs.currentAssertion(concern);
2277
2277
  if (!assertion) return [];
2278
2278
  return [
2279
2279
  {
@@ -2453,5 +2453,5 @@ exports.validateEncounterMedicationValue = validateEncounterMedicationValue;
2453
2453
  exports.validateEncounterPlan = validateEncounterPlan;
2454
2454
  exports.validateEncounterResponses = validateEncounterResponses;
2455
2455
  exports.validateEncounterVitals = validateEncounterVitals;
2456
- //# sourceMappingURL=chunk-46RYJYN2.cjs.map
2457
- //# sourceMappingURL=chunk-46RYJYN2.cjs.map
2456
+ //# sourceMappingURL=chunk-GU6TPVXF.cjs.map
2457
+ //# sourceMappingURL=chunk-GU6TPVXF.cjs.map