@tribepad/themis 1.5.7 → 1.5.9

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 (179) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/elements/AlertDialog/index.js +1 -1
  3. package/dist/elements/AlertDialog/index.js.map +1 -1
  4. package/dist/elements/AlertDialog/index.mjs +1 -1
  5. package/dist/elements/AlertDialog/index.mjs.map +1 -1
  6. package/dist/elements/Badge/index.js +1 -1
  7. package/dist/elements/Badge/index.js.map +1 -1
  8. package/dist/elements/Badge/index.mjs +1 -1
  9. package/dist/elements/Badge/index.mjs.map +1 -1
  10. package/dist/elements/Breadcrumbs/index.js +1 -1
  11. package/dist/elements/Breadcrumbs/index.js.map +1 -1
  12. package/dist/elements/Breadcrumbs/index.mjs +1 -1
  13. package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
  14. package/dist/elements/Button/index.js +1 -1
  15. package/dist/elements/Button/index.js.map +1 -1
  16. package/dist/elements/Button/index.mjs +1 -1
  17. package/dist/elements/Button/index.mjs.map +1 -1
  18. package/dist/elements/Card/index.js +1 -1
  19. package/dist/elements/Card/index.js.map +1 -1
  20. package/dist/elements/Card/index.mjs +1 -1
  21. package/dist/elements/Card/index.mjs.map +1 -1
  22. package/dist/elements/Carousel/index.js +1 -1
  23. package/dist/elements/Carousel/index.js.map +1 -1
  24. package/dist/elements/Carousel/index.mjs +1 -1
  25. package/dist/elements/Carousel/index.mjs.map +1 -1
  26. package/dist/elements/Chart/index.js +1 -1
  27. package/dist/elements/Chart/index.js.map +1 -1
  28. package/dist/elements/Chart/index.mjs +1 -1
  29. package/dist/elements/Chart/index.mjs.map +1 -1
  30. package/dist/elements/ChatInterface/index.js +1 -1
  31. package/dist/elements/ChatInterface/index.js.map +1 -1
  32. package/dist/elements/ChatInterface/index.mjs +1 -1
  33. package/dist/elements/ChatInterface/index.mjs.map +1 -1
  34. package/dist/elements/Checkbox/index.js +1 -1
  35. package/dist/elements/Checkbox/index.js.map +1 -1
  36. package/dist/elements/Checkbox/index.mjs +1 -1
  37. package/dist/elements/Checkbox/index.mjs.map +1 -1
  38. package/dist/elements/CheckboxGroup/index.js +1 -1
  39. package/dist/elements/CheckboxGroup/index.js.map +1 -1
  40. package/dist/elements/CheckboxGroup/index.mjs +1 -1
  41. package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
  42. package/dist/elements/ColorPicker/index.js +1 -1
  43. package/dist/elements/ColorPicker/index.js.map +1 -1
  44. package/dist/elements/ColorPicker/index.mjs +1 -1
  45. package/dist/elements/ColorPicker/index.mjs.map +1 -1
  46. package/dist/elements/Combobox/Combobox.styles.d.ts.map +1 -1
  47. package/dist/elements/Combobox/index.js +1 -1
  48. package/dist/elements/Combobox/index.js.map +1 -1
  49. package/dist/elements/Combobox/index.mjs +1 -1
  50. package/dist/elements/Combobox/index.mjs.map +1 -1
  51. package/dist/elements/DatePicker/index.js +1 -1
  52. package/dist/elements/DatePicker/index.js.map +1 -1
  53. package/dist/elements/DatePicker/index.mjs +1 -1
  54. package/dist/elements/DatePicker/index.mjs.map +1 -1
  55. package/dist/elements/Dropdown/index.js +1 -1
  56. package/dist/elements/Dropdown/index.js.map +1 -1
  57. package/dist/elements/Dropdown/index.mjs +1 -1
  58. package/dist/elements/Dropdown/index.mjs.map +1 -1
  59. package/dist/elements/FileField/index.js +1 -1
  60. package/dist/elements/FileField/index.js.map +1 -1
  61. package/dist/elements/FileField/index.mjs +1 -1
  62. package/dist/elements/FileField/index.mjs.map +1 -1
  63. package/dist/elements/Modal/Modal.styles.d.ts.map +1 -1
  64. package/dist/elements/Modal/index.js +1 -1
  65. package/dist/elements/Modal/index.js.map +1 -1
  66. package/dist/elements/Modal/index.mjs +1 -1
  67. package/dist/elements/Modal/index.mjs.map +1 -1
  68. package/dist/elements/NumberField/index.js +1 -1
  69. package/dist/elements/NumberField/index.js.map +1 -1
  70. package/dist/elements/NumberField/index.mjs +1 -1
  71. package/dist/elements/NumberField/index.mjs.map +1 -1
  72. package/dist/elements/PageTitle/PageTitle.d.ts.map +1 -1
  73. package/dist/elements/PageTitle/PageTitle.styles.d.ts.map +1 -1
  74. package/dist/elements/PageTitle/index.js +1 -1
  75. package/dist/elements/PageTitle/index.js.map +1 -1
  76. package/dist/elements/PageTitle/index.mjs +1 -1
  77. package/dist/elements/PageTitle/index.mjs.map +1 -1
  78. package/dist/elements/Pagination/index.js +1 -1
  79. package/dist/elements/Pagination/index.js.map +1 -1
  80. package/dist/elements/Pagination/index.mjs +1 -1
  81. package/dist/elements/Pagination/index.mjs.map +1 -1
  82. package/dist/elements/Panel/Panel.d.ts.map +1 -1
  83. package/dist/elements/Panel/index.js +1 -1
  84. package/dist/elements/Panel/index.js.map +1 -1
  85. package/dist/elements/Panel/index.mjs +1 -1
  86. package/dist/elements/Panel/index.mjs.map +1 -1
  87. package/dist/elements/PasswordField/index.js +1 -1
  88. package/dist/elements/PasswordField/index.js.map +1 -1
  89. package/dist/elements/PasswordField/index.mjs +1 -1
  90. package/dist/elements/PasswordField/index.mjs.map +1 -1
  91. package/dist/elements/RadioGroup/index.js +1 -1
  92. package/dist/elements/RadioGroup/index.js.map +1 -1
  93. package/dist/elements/RadioGroup/index.mjs +1 -1
  94. package/dist/elements/RadioGroup/index.mjs.map +1 -1
  95. package/dist/elements/RatingScale/RatingScale.styles.d.ts.map +1 -1
  96. package/dist/elements/RatingScale/index.js +1 -1
  97. package/dist/elements/RatingScale/index.js.map +1 -1
  98. package/dist/elements/RatingScale/index.mjs +1 -1
  99. package/dist/elements/RatingScale/index.mjs.map +1 -1
  100. package/dist/elements/Resizable/components/ResizablePopover.d.ts.map +1 -1
  101. package/dist/elements/Resizable/index.js +1 -1
  102. package/dist/elements/Resizable/index.js.map +1 -1
  103. package/dist/elements/Resizable/index.mjs +1 -1
  104. package/dist/elements/Resizable/index.mjs.map +1 -1
  105. package/dist/elements/SearchField/index.js +1 -1
  106. package/dist/elements/SearchField/index.js.map +1 -1
  107. package/dist/elements/SearchField/index.mjs +1 -1
  108. package/dist/elements/SearchField/index.mjs.map +1 -1
  109. package/dist/elements/Select/Select.styles.d.ts.map +1 -1
  110. package/dist/elements/Select/index.js +1 -1
  111. package/dist/elements/Select/index.js.map +1 -1
  112. package/dist/elements/Select/index.mjs +1 -1
  113. package/dist/elements/Select/index.mjs.map +1 -1
  114. package/dist/elements/Sidebar/Sidebar.styles.d.ts +34 -3
  115. package/dist/elements/Sidebar/Sidebar.styles.d.ts.map +1 -1
  116. package/dist/elements/Sidebar/Sidebar.types.d.ts +6 -0
  117. package/dist/elements/Sidebar/Sidebar.types.d.ts.map +1 -1
  118. package/dist/elements/Sidebar/SidebarPanel.d.ts.map +1 -1
  119. package/dist/elements/Sidebar/SidebarRail.d.ts.map +1 -1
  120. package/dist/elements/Sidebar/index.js +1 -1
  121. package/dist/elements/Sidebar/index.js.map +1 -1
  122. package/dist/elements/Sidebar/index.mjs +1 -1
  123. package/dist/elements/Sidebar/index.mjs.map +1 -1
  124. package/dist/elements/SituationalJudgement/index.js +1 -1
  125. package/dist/elements/SituationalJudgement/index.js.map +1 -1
  126. package/dist/elements/SituationalJudgement/index.mjs +1 -1
  127. package/dist/elements/SituationalJudgement/index.mjs.map +1 -1
  128. package/dist/elements/Switch/index.js +1 -1
  129. package/dist/elements/Switch/index.js.map +1 -1
  130. package/dist/elements/Switch/index.mjs +1 -1
  131. package/dist/elements/Switch/index.mjs.map +1 -1
  132. package/dist/elements/Table/index.js +1 -1
  133. package/dist/elements/Table/index.js.map +1 -1
  134. package/dist/elements/Table/index.mjs +1 -1
  135. package/dist/elements/Table/index.mjs.map +1 -1
  136. package/dist/elements/Tabs/Tabs.d.ts.map +1 -1
  137. package/dist/elements/Tabs/index.js +1 -1
  138. package/dist/elements/Tabs/index.js.map +1 -1
  139. package/dist/elements/Tabs/index.mjs +1 -1
  140. package/dist/elements/Tabs/index.mjs.map +1 -1
  141. package/dist/elements/TextField/index.js +1 -1
  142. package/dist/elements/TextField/index.js.map +1 -1
  143. package/dist/elements/TextField/index.mjs +1 -1
  144. package/dist/elements/TextField/index.mjs.map +1 -1
  145. package/dist/elements/Toast/Toast.d.ts.map +1 -1
  146. package/dist/elements/Toast/index.js +1 -1
  147. package/dist/elements/Toast/index.js.map +1 -1
  148. package/dist/elements/Toast/index.mjs +1 -1
  149. package/dist/elements/Toast/index.mjs.map +1 -1
  150. package/dist/elements/Tooltip/index.js +1 -1
  151. package/dist/elements/Tooltip/index.js.map +1 -1
  152. package/dist/elements/Tooltip/index.mjs +1 -1
  153. package/dist/elements/Tooltip/index.mjs.map +1 -1
  154. package/dist/elements/Wizard/Wizard.types.d.ts +19 -0
  155. package/dist/elements/Wizard/Wizard.types.d.ts.map +1 -1
  156. package/dist/elements/Wizard/WizardContent.d.ts +17 -8
  157. package/dist/elements/Wizard/WizardContent.d.ts.map +1 -1
  158. package/dist/elements/Wizard/index.js +1 -1
  159. package/dist/elements/Wizard/index.js.map +1 -1
  160. package/dist/elements/Wizard/index.mjs +1 -1
  161. package/dist/elements/Wizard/index.mjs.map +1 -1
  162. package/dist/elements/index.js +1 -1
  163. package/dist/elements/index.js.map +1 -1
  164. package/dist/elements/index.mjs +1 -1
  165. package/dist/elements/index.mjs.map +1 -1
  166. package/dist/index.js +2 -2
  167. package/dist/index.js.map +1 -1
  168. package/dist/index.mjs +2 -2
  169. package/dist/index.mjs.map +1 -1
  170. package/dist/styles/index.js +1 -1
  171. package/dist/styles/index.js.map +1 -1
  172. package/dist/styles/index.mjs +1 -1
  173. package/dist/styles/index.mjs.map +1 -1
  174. package/dist/styles/interaction-states.d.ts +2 -2
  175. package/dist/styles/interaction-states.d.ts.map +1 -1
  176. package/package.json +1 -1
  177. package/src/elements/PageTitle/PageTitle.stories.tsx +15 -19
  178. package/src/elements/Sidebar/Sidebar.stories.tsx +13 -2
  179. package/src/elements/Wizard/Wizard.stories.tsx +95 -0
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),classVarianceAuthority=require('class-variance-authority'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function d(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var B=classVarianceAuthority.cva(["flex flex-col h-full overflow-hidden","bg-[var(--content-background)] text-[var(--content-foreground)]","shadow-lg"],{variants:{position:{right:"border-l border-[var(--border)]",left:"border-r border-[var(--border)]"},width:{sm:"w-[300px]",md:"w-[400px]",lg:"w-[500px]",xl:"w-[600px]",auto:"w-auto"}},defaultVariants:{position:"right",width:"md"}}),O=classVarianceAuthority.cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),I=classVarianceAuthority.cva(["flex-1 overflow-y-auto","px-4 py-4"]),D=classVarianceAuthority.cva(["flex items-center justify-end gap-2","px-4 py-4","border-t border-[var(--border)]"]),H=classVarianceAuthority.cva(["inline-flex items-center justify-center rounded-md","min-h-[44px] min-w-[44px]","text-[var(--menu-muted)]","hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"]),A=react.createContext(null);function f(){let e=react.useContext(A);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function re(e){let[n,t]=react.useState(()=>typeof window>"u"?false:window.matchMedia(e).matches);return react.useEffect(()=>{if(typeof window>"u")return;let o=window.matchMedia(e);o.matches!==n&&t(o.matches);let r=s=>t(s.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function F({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:s="right",width:p="md",mobileBreakpoint:l=768}){let[i,g]=react.useState(t),c=n!==void 0,x=c?n:i,v=react.useRef(null),w=react.useId(),U=`panel-${w}`,X=`panel-title-${w}`,b=re(`(max-width: ${l-1}px)`),y=react.useCallback(u=>{c||g(u),o?.(u);},[c,o]),h=react.useCallback(()=>{y(false),r?.(),v.current&&window.requestAnimationFrame(()=>{v.current?.focus();});},[y,r]);react.useEffect(()=>{if(!x||b)return;let u=C=>{C.key==="Escape"&&(C.preventDefault(),h());};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[x,b,h]);let q={isOpen:x,setIsOpen:y,panelId:U,titleId:X,triggerRef:v,position:s,width:p,mobileBreakpoint:l,isMobile:b,handleClose:h};return jsxRuntime.jsx(A.Provider,{value:q,children:e})}F.displayName="Panel";function L({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:s}=f(),p=react.useCallback(i=>{s.current=i;},[s]),l=react.useCallback(()=>{o(!t);},[o,t]);if(n&&react.isValidElement(e)){let i=e.props;return react.cloneElement(e,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:l,onClick:i.onClick?()=>{i.onClick?.(),l();}:l})}return jsxRuntime.jsx(reactAriaComponents.Button,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:l,"data-testid":"panel-trigger",children:e})}L.displayName="PanelTrigger";function E(){let{handleClose:e}=f();return jsxRuntime.jsx(reactAriaComponents.Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsxRuntime.jsx(lucideReact.X,{className:"h-5 w-5"})})}function j({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:s,titleId:p,position:l,width:i,handleClose:g}=f();return o?r?jsxRuntime.jsx(reactAriaComponents.ModalOverlay,{isDismissable:true,isOpen:o,onOpenChange:c=>!c&&g(),className:"fixed inset-0 z-50 bg-black/50",children:jsxRuntime.jsx(reactAriaComponents.Modal,{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:jsxRuntime.jsxs(reactAriaComponents.Dialog,{"aria-labelledby":p,className:d("w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none","flex max-h-[90vh] flex-col",t),children:[n&&jsxRuntime.jsx("div",{className:"absolute right-2 top-2",children:jsxRuntime.jsx(E,{})}),e]})})}):jsxRuntime.jsxs("aside",{id:s,"aria-labelledby":p,"data-testid":"panel-content",className:d(B({position:l,width:i}),t),children:[e,n&&jsxRuntime.jsx("div",{className:"absolute right-2 top-2",children:jsxRuntime.jsx(E,{})})]}):null}j.displayName="PanelContent";function W({children:e,className:n}){return jsxRuntime.jsx("header",{className:d(O(),n),children:jsxRuntime.jsx("div",{className:"flex flex-col gap-1",children:e})})}W.displayName="PanelHeader";function $({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsxRuntime.jsx(n,{id:o,"aria-live":"polite",className:d("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}$.displayName="PanelTitle";function z({children:e,className:n}){return jsxRuntime.jsx("p",{className:d("text-sm text-[var(--menu-muted)]",n),children:e})}z.displayName="PanelDescription";function K({children:e,className:n}){return jsxRuntime.jsx("div",{className:d(I(),n),children:e})}K.displayName="PanelBody";function Q({children:e,className:n}){return jsxRuntime.jsx("footer",{className:d(D(),n),children:e})}Q.displayName="PanelFooter";function S({children:e}){let{handleClose:n}=f();if(!react.isValidElement(e))return null;let t=e.props;return react.cloneElement(e,{onPress:()=>{t.onPress?.(),n();},onClick:()=>{t.onClick?.(),n();}})}S.displayName="PanelClose";var le=Object.assign(F,{Trigger:L,Content:j,Header:W,Title:$,Description:z,Body:K,Footer:Q,Close:S});exports.Panel=le;exports.panelBodyVariants=I;exports.panelCloseButtonVariants=H;exports.panelContentVariants=B;exports.panelFooterVariants=D;exports.panelHeaderVariants=O;//# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),classVarianceAuthority=require('class-variance-authority'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime');function d(...e){return tailwindMerge.twMerge(clsx.clsx(e))}var B=classVarianceAuthority.cva(["flex flex-col h-full overflow-hidden","bg-[var(--content-background)] text-[var(--content-foreground)]"],{variants:{position:{right:"border-l border-[var(--border)]",left:"border-r border-[var(--border)]"},width:{sm:"w-[300px]",md:"w-[400px]",lg:"w-[500px]",xl:"w-[600px]",auto:"w-auto"}},defaultVariants:{position:"right",width:"md"}}),O=classVarianceAuthority.cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),I=classVarianceAuthority.cva(["flex-1 overflow-y-auto","px-4 py-4"]),D=classVarianceAuthority.cva(["flex items-center justify-end gap-2","px-4 py-4","border-t border-[var(--border)]"]),H=classVarianceAuthority.cva(["inline-flex items-center justify-center rounded-md","min-h-[44px] min-w-[44px]","text-[var(--menu-muted)]","hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"]),A=react.createContext(null);function f(){let e=react.useContext(A);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function re(e){let[n,t]=react.useState(()=>typeof window>"u"?false:window.matchMedia(e).matches);return react.useEffect(()=>{if(typeof window>"u")return;let o=window.matchMedia(e);o.matches!==n&&t(o.matches);let r=s=>t(s.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function F({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:s="right",width:p="md",mobileBreakpoint:l=768}){let[i,g]=react.useState(t),c=n!==void 0,x=c?n:i,v=react.useRef(null),h=react.useId(),U=`panel-${h}`,X=`panel-title-${h}`,b=re(`(max-width: ${l-1}px)`),y=react.useCallback(u=>{c||g(u),o?.(u);},[c,o]),C=react.useCallback(()=>{y(false),r?.(),v.current&&window.requestAnimationFrame(()=>{v.current?.focus();});},[y,r]);react.useEffect(()=>{if(!x||b)return;let u=w=>{w.key==="Escape"&&(w.preventDefault(),C());};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[x,b,C]);let q={isOpen:x,setIsOpen:y,panelId:U,titleId:X,triggerRef:v,position:s,width:p,mobileBreakpoint:l,isMobile:b,handleClose:C};return jsxRuntime.jsx(A.Provider,{value:q,children:e})}F.displayName="Panel";function L({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:s}=f(),p=react.useCallback(i=>{s.current=i;},[s]),l=react.useCallback(()=>{o(!t);},[o,t]);if(n&&react.isValidElement(e)){let i=e.props;return react.cloneElement(e,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:l,onClick:i.onClick?()=>{i.onClick?.(),l();}:l})}return jsxRuntime.jsx(reactAriaComponents.Button,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:l,"data-testid":"panel-trigger",children:e})}L.displayName="PanelTrigger";function E(){let{handleClose:e}=f();return jsxRuntime.jsx(reactAriaComponents.Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsxRuntime.jsx(lucideReact.X,{className:"h-5 w-5"})})}function j({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:s,titleId:p,position:l,width:i,handleClose:g}=f();return o?r?jsxRuntime.jsx(reactAriaComponents.ModalOverlay,{isDismissable:true,isOpen:o,onOpenChange:c=>!c&&g(),className:"fixed inset-0 z-50 bg-black/50",children:jsxRuntime.jsx(reactAriaComponents.Modal,{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:jsxRuntime.jsxs(reactAriaComponents.Dialog,{"aria-labelledby":p,className:d("w-full max-w-lg rounded-lg bg-[var(--content-background)] outline-none","flex max-h-[90vh] flex-col",t),children:[n&&jsxRuntime.jsx("div",{className:"absolute right-2 top-2",children:jsxRuntime.jsx(E,{})}),e]})})}):jsxRuntime.jsxs("aside",{id:s,"aria-labelledby":p,"data-testid":"panel-content",className:d(B({position:l,width:i}),t),children:[e,n&&jsxRuntime.jsx("div",{className:"absolute right-2 top-2",children:jsxRuntime.jsx(E,{})})]}):null}j.displayName="PanelContent";function W({children:e,className:n}){return jsxRuntime.jsx("header",{className:d(O(),n),children:jsxRuntime.jsx("div",{className:"flex flex-col gap-1",children:e})})}W.displayName="PanelHeader";function $({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsxRuntime.jsx(n,{id:o,"aria-live":"polite",className:d("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}$.displayName="PanelTitle";function z({children:e,className:n}){return jsxRuntime.jsx("p",{className:d("text-sm text-[var(--menu-muted)]",n),children:e})}z.displayName="PanelDescription";function K({children:e,className:n}){return jsxRuntime.jsx("div",{className:d(I(),n),children:e})}K.displayName="PanelBody";function Q({children:e,className:n}){return jsxRuntime.jsx("footer",{className:d(D(),n),children:e})}Q.displayName="PanelFooter";function S({children:e}){let{handleClose:n}=f();if(!react.isValidElement(e))return null;let t=e.props;return react.cloneElement(e,{onPress:()=>{t.onPress?.(),n();},onClick:()=>{t.onClick?.(),n();}})}S.displayName="PanelClose";var le=Object.assign(F,{Trigger:L,Content:j,Header:W,Title:$,Description:z,Body:K,Footer:Q,Close:S});exports.Panel=le;exports.panelBodyVariants=I;exports.panelCloseButtonVariants=H;exports.panelContentVariants=B;exports.panelFooterVariants=D;exports.panelHeaderVariants=O;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","panelContentVariants","cva","panelHeaderVariants","panelBodyVariants","panelFooterVariants","panelCloseButtonVariants","PanelContext","createContext","usePanelContext","context","useContext","useMediaQuery","query","matches","setMatches","useState","useEffect","media","listener","e","PanelRoot","children","controlledIsOpen","defaultOpen","onOpenChange","onClose","position","width","mobileBreakpoint","uncontrolledIsOpen","setUncontrolledIsOpen","isControlled","isOpen","triggerRef","useRef","uniqueId","useId","panelId","titleId","isMobile","setIsOpen","useCallback","open","handleClose","handleKeyDown","contextValue","jsx","PanelTrigger","asChild","setRef","element","handlePress","isValidElement","childProps","cloneElement","AriaButton","BuiltInCloseButton","X","PanelContent","showClose","className","AriaModalOverlay","AriaModal","jsxs","AriaDialog","PanelHeader","PanelTitle","Tag","PanelDescription","PanelBody","PanelFooter","PanelClose","Panel"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full overflow-hidden\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n \"shadow-lg\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","panelContentVariants","cva","panelHeaderVariants","panelBodyVariants","panelFooterVariants","panelCloseButtonVariants","PanelContext","createContext","usePanelContext","context","useContext","useMediaQuery","query","matches","setMatches","useState","useEffect","media","listener","e","PanelRoot","children","controlledIsOpen","defaultOpen","onOpenChange","onClose","position","width","mobileBreakpoint","uncontrolledIsOpen","setUncontrolledIsOpen","isControlled","isOpen","triggerRef","useRef","uniqueId","useId","panelId","titleId","isMobile","setIsOpen","useCallback","open","handleClose","handleKeyDown","contextValue","jsx","PanelTrigger","asChild","setRef","element","handlePress","isValidElement","childProps","cloneElement","AriaButton","BuiltInCloseButton","X","PanelContent","showClose","className","AriaModalOverlay","AriaModal","jsxs","AriaDialog","PanelHeader","PanelTitle","Tag","PanelDescription","PanelBody","PanelFooter","PanelClose","Panel"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full overflow-hidden\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import {createContext,useState,useRef,useId,useCallback,useEffect,isValidElement,cloneElement,useContext}from'react';import {ModalOverlay,Modal,Dialog,Button}from'react-aria-components';import {cva}from'class-variance-authority';import {X}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs}from'react/jsx-runtime';function d(...e){return twMerge(clsx(e))}var B=cva(["flex flex-col h-full overflow-hidden","bg-[var(--content-background)] text-[var(--content-foreground)]","shadow-lg"],{variants:{position:{right:"border-l border-[var(--border)]",left:"border-r border-[var(--border)]"},width:{sm:"w-[300px]",md:"w-[400px]",lg:"w-[500px]",xl:"w-[600px]",auto:"w-auto"}},defaultVariants:{position:"right",width:"md"}}),O=cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),I=cva(["flex-1 overflow-y-auto","px-4 py-4"]),D=cva(["flex items-center justify-end gap-2","px-4 py-4","border-t border-[var(--border)]"]),H=cva(["inline-flex items-center justify-center rounded-md","min-h-[44px] min-w-[44px]","text-[var(--menu-muted)]","hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"]),A=createContext(null);function f(){let e=useContext(A);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function re(e){let[n,t]=useState(()=>typeof window>"u"?false:window.matchMedia(e).matches);return useEffect(()=>{if(typeof window>"u")return;let o=window.matchMedia(e);o.matches!==n&&t(o.matches);let r=s=>t(s.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function F({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:s="right",width:p="md",mobileBreakpoint:l=768}){let[i,g]=useState(t),c=n!==void 0,x=c?n:i,v=useRef(null),w=useId(),U=`panel-${w}`,X=`panel-title-${w}`,b=re(`(max-width: ${l-1}px)`),y=useCallback(u=>{c||g(u),o?.(u);},[c,o]),h=useCallback(()=>{y(false),r?.(),v.current&&window.requestAnimationFrame(()=>{v.current?.focus();});},[y,r]);useEffect(()=>{if(!x||b)return;let u=C=>{C.key==="Escape"&&(C.preventDefault(),h());};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[x,b,h]);let q={isOpen:x,setIsOpen:y,panelId:U,titleId:X,triggerRef:v,position:s,width:p,mobileBreakpoint:l,isMobile:b,handleClose:h};return jsx(A.Provider,{value:q,children:e})}F.displayName="Panel";function L({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:s}=f(),p=useCallback(i=>{s.current=i;},[s]),l=useCallback(()=>{o(!t);},[o,t]);if(n&&isValidElement(e)){let i=e.props;return cloneElement(e,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:l,onClick:i.onClick?()=>{i.onClick?.(),l();}:l})}return jsx(Button,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:l,"data-testid":"panel-trigger",children:e})}L.displayName="PanelTrigger";function E(){let{handleClose:e}=f();return jsx(Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsx(X,{className:"h-5 w-5"})})}function j({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:s,titleId:p,position:l,width:i,handleClose:g}=f();return o?r?jsx(ModalOverlay,{isDismissable:true,isOpen:o,onOpenChange:c=>!c&&g(),className:"fixed inset-0 z-50 bg-black/50",children:jsx(Modal,{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:jsxs(Dialog,{"aria-labelledby":p,className:d("w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none","flex max-h-[90vh] flex-col",t),children:[n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})}),e]})})}):jsxs("aside",{id:s,"aria-labelledby":p,"data-testid":"panel-content",className:d(B({position:l,width:i}),t),children:[e,n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})})]}):null}j.displayName="PanelContent";function W({children:e,className:n}){return jsx("header",{className:d(O(),n),children:jsx("div",{className:"flex flex-col gap-1",children:e})})}W.displayName="PanelHeader";function $({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsx(n,{id:o,"aria-live":"polite",className:d("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}$.displayName="PanelTitle";function z({children:e,className:n}){return jsx("p",{className:d("text-sm text-[var(--menu-muted)]",n),children:e})}z.displayName="PanelDescription";function K({children:e,className:n}){return jsx("div",{className:d(I(),n),children:e})}K.displayName="PanelBody";function Q({children:e,className:n}){return jsx("footer",{className:d(D(),n),children:e})}Q.displayName="PanelFooter";function S({children:e}){let{handleClose:n}=f();if(!isValidElement(e))return null;let t=e.props;return cloneElement(e,{onPress:()=>{t.onPress?.(),n();},onClick:()=>{t.onClick?.(),n();}})}S.displayName="PanelClose";var le=Object.assign(F,{Trigger:L,Content:j,Header:W,Title:$,Description:z,Body:K,Footer:Q,Close:S});export{le as Panel,I as panelBodyVariants,H as panelCloseButtonVariants,B as panelContentVariants,D as panelFooterVariants,O as panelHeaderVariants};//# sourceMappingURL=index.mjs.map
2
+ import {createContext,useState,useRef,useId,useCallback,useEffect,isValidElement,cloneElement,useContext}from'react';import {ModalOverlay,Modal,Dialog,Button}from'react-aria-components';import {cva}from'class-variance-authority';import {X}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs}from'react/jsx-runtime';function d(...e){return twMerge(clsx(e))}var B=cva(["flex flex-col h-full overflow-hidden","bg-[var(--content-background)] text-[var(--content-foreground)]"],{variants:{position:{right:"border-l border-[var(--border)]",left:"border-r border-[var(--border)]"},width:{sm:"w-[300px]",md:"w-[400px]",lg:"w-[500px]",xl:"w-[600px]",auto:"w-auto"}},defaultVariants:{position:"right",width:"md"}}),O=cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),I=cva(["flex-1 overflow-y-auto","px-4 py-4"]),D=cva(["flex items-center justify-end gap-2","px-4 py-4","border-t border-[var(--border)]"]),H=cva(["inline-flex items-center justify-center rounded-md","min-h-[44px] min-w-[44px]","text-[var(--menu-muted)]","hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"]),A=createContext(null);function f(){let e=useContext(A);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function re(e){let[n,t]=useState(()=>typeof window>"u"?false:window.matchMedia(e).matches);return useEffect(()=>{if(typeof window>"u")return;let o=window.matchMedia(e);o.matches!==n&&t(o.matches);let r=s=>t(s.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function F({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:s="right",width:p="md",mobileBreakpoint:l=768}){let[i,g]=useState(t),c=n!==void 0,x=c?n:i,v=useRef(null),h=useId(),U=`panel-${h}`,X=`panel-title-${h}`,b=re(`(max-width: ${l-1}px)`),y=useCallback(u=>{c||g(u),o?.(u);},[c,o]),C=useCallback(()=>{y(false),r?.(),v.current&&window.requestAnimationFrame(()=>{v.current?.focus();});},[y,r]);useEffect(()=>{if(!x||b)return;let u=w=>{w.key==="Escape"&&(w.preventDefault(),C());};return document.addEventListener("keydown",u),()=>document.removeEventListener("keydown",u)},[x,b,C]);let q={isOpen:x,setIsOpen:y,panelId:U,titleId:X,triggerRef:v,position:s,width:p,mobileBreakpoint:l,isMobile:b,handleClose:C};return jsx(A.Provider,{value:q,children:e})}F.displayName="Panel";function L({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:s}=f(),p=useCallback(i=>{s.current=i;},[s]),l=useCallback(()=>{o(!t);},[o,t]);if(n&&isValidElement(e)){let i=e.props;return cloneElement(e,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:l,onClick:i.onClick?()=>{i.onClick?.(),l();}:l})}return jsx(Button,{ref:p,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:l,"data-testid":"panel-trigger",children:e})}L.displayName="PanelTrigger";function E(){let{handleClose:e}=f();return jsx(Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsx(X,{className:"h-5 w-5"})})}function j({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:s,titleId:p,position:l,width:i,handleClose:g}=f();return o?r?jsx(ModalOverlay,{isDismissable:true,isOpen:o,onOpenChange:c=>!c&&g(),className:"fixed inset-0 z-50 bg-black/50",children:jsx(Modal,{className:"fixed inset-0 z-50 flex items-center justify-center p-4",children:jsxs(Dialog,{"aria-labelledby":p,className:d("w-full max-w-lg rounded-lg bg-[var(--content-background)] outline-none","flex max-h-[90vh] flex-col",t),children:[n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})}),e]})})}):jsxs("aside",{id:s,"aria-labelledby":p,"data-testid":"panel-content",className:d(B({position:l,width:i}),t),children:[e,n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(E,{})})]}):null}j.displayName="PanelContent";function W({children:e,className:n}){return jsx("header",{className:d(O(),n),children:jsx("div",{className:"flex flex-col gap-1",children:e})})}W.displayName="PanelHeader";function $({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsx(n,{id:o,"aria-live":"polite",className:d("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}$.displayName="PanelTitle";function z({children:e,className:n}){return jsx("p",{className:d("text-sm text-[var(--menu-muted)]",n),children:e})}z.displayName="PanelDescription";function K({children:e,className:n}){return jsx("div",{className:d(I(),n),children:e})}K.displayName="PanelBody";function Q({children:e,className:n}){return jsx("footer",{className:d(D(),n),children:e})}Q.displayName="PanelFooter";function S({children:e}){let{handleClose:n}=f();if(!isValidElement(e))return null;let t=e.props;return cloneElement(e,{onPress:()=>{t.onPress?.(),n();},onClick:()=>{t.onClick?.(),n();}})}S.displayName="PanelClose";var le=Object.assign(F,{Trigger:L,Content:j,Header:W,Title:$,Description:z,Body:K,Footer:Q,Close:S});export{le as Panel,I as panelBodyVariants,H as panelCloseButtonVariants,B as panelContentVariants,D as panelFooterVariants,O as panelHeaderVariants};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","panelContentVariants","cva","panelHeaderVariants","panelBodyVariants","panelFooterVariants","panelCloseButtonVariants","PanelContext","createContext","usePanelContext","context","useContext","useMediaQuery","query","matches","setMatches","useState","useEffect","media","listener","e","PanelRoot","children","controlledIsOpen","defaultOpen","onOpenChange","onClose","position","width","mobileBreakpoint","uncontrolledIsOpen","setUncontrolledIsOpen","isControlled","isOpen","triggerRef","useRef","uniqueId","useId","panelId","titleId","isMobile","setIsOpen","useCallback","open","handleClose","handleKeyDown","contextValue","jsx","PanelTrigger","asChild","setRef","element","handlePress","isValidElement","childProps","cloneElement","AriaButton","BuiltInCloseButton","X","PanelContent","showClose","className","AriaModalOverlay","AriaModal","jsxs","AriaDialog","PanelHeader","PanelTitle","Tag","PanelDescription","PanelBody","PanelFooter","PanelClose","Panel"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full overflow-hidden\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n \"shadow-lg\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] shadow-lg outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","panelContentVariants","cva","panelHeaderVariants","panelBodyVariants","panelFooterVariants","panelCloseButtonVariants","PanelContext","createContext","usePanelContext","context","useContext","useMediaQuery","query","matches","setMatches","useState","useEffect","media","listener","e","PanelRoot","children","controlledIsOpen","defaultOpen","onOpenChange","onClose","position","width","mobileBreakpoint","uncontrolledIsOpen","setUncontrolledIsOpen","isControlled","isOpen","triggerRef","useRef","uniqueId","useId","panelId","titleId","isMobile","setIsOpen","useCallback","open","handleClose","handleKeyDown","contextValue","jsx","PanelTrigger","asChild","setRef","element","handlePress","isValidElement","childProps","cloneElement","AriaButton","BuiltInCloseButton","X","PanelContent","showClose","className","AriaModalOverlay","AriaModal","jsxs","AriaDialog","PanelHeader","PanelTitle","Tag","PanelDescription","PanelBody","PanelFooter","PanelClose","Panel"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\n/**\n * Panel Component - Accessible Non-Modal Sidebar\n * Disclosure pattern + Complementary region for WCAG 2.2 AAA\n *\n * @see plan.md for architecture details\n * @see panel-prd.md for requirements\n * @see ADR 0007 for accessibility decisions\n */\n\nimport {\n type ReactElement,\n type MutableRefObject,\n createContext,\n useContext,\n useState,\n useId,\n useRef,\n useCallback,\n useEffect,\n cloneElement,\n isValidElement,\n} from \"react\";\nimport {\n Button as AriaButton,\n Modal as AriaModal,\n ModalOverlay as AriaModalOverlay,\n Dialog as AriaDialog,\n} from \"react-aria-components\";\nimport { cva, type VariantProps } from \"class-variance-authority\";\nimport { X } from \"lucide-react\";\nimport { cn } from \"../../utils/cn\";\nimport type {\n PanelProps,\n PanelTriggerProps,\n PanelContentProps,\n PanelHeaderProps,\n PanelTitleProps,\n PanelDescriptionProps,\n PanelBodyProps,\n PanelFooterProps,\n PanelCloseProps,\n PanelPosition,\n PanelWidth,\n} from \"./Panel.types\";\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Panel content variants\n * Controls position-based styling and width\n */\nexport const panelContentVariants = cva(\n [\n \"flex flex-col h-full overflow-hidden\",\n \"bg-[var(--content-background)] text-[var(--content-foreground)]\",\n ],\n {\n variants: {\n position: {\n right: \"border-l border-[var(--border)]\",\n left: \"border-r border-[var(--border)]\",\n },\n width: {\n sm: \"w-[300px]\",\n md: \"w-[400px]\",\n lg: \"w-[500px]\",\n xl: \"w-[600px]\",\n auto: \"w-auto\",\n },\n },\n defaultVariants: {\n position: \"right\",\n width: \"md\",\n },\n }\n);\n\n/**\n * Panel header variants\n */\nexport const panelHeaderVariants = cva([\n \"flex items-start justify-between\",\n \"px-4 py-4\",\n \"border-b border-[var(--border)]\",\n]);\n\n/**\n * Panel body variants\n */\nexport const panelBodyVariants = cva([\"flex-1 overflow-y-auto\", \"px-4 py-4\"]);\n\n/**\n * Panel footer variants\n */\nexport const panelFooterVariants = cva([\n \"flex items-center justify-end gap-2\",\n \"px-4 py-4\",\n \"border-t border-[var(--border)]\",\n]);\n\n/**\n * Close button variants\n */\nexport const panelCloseButtonVariants = cva([\n \"inline-flex items-center justify-center rounded-md\",\n \"min-h-[44px] min-w-[44px]\",\n \"text-[var(--menu-muted)]\",\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]\",\n \"focus-visible:outline-none focus-visible:ring-2\",\n \"focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2\",\n // No transition - instant state changes (v1)\n]);\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface PanelContextValue {\n isOpen: boolean;\n setIsOpen: (open: boolean) => void;\n panelId: string;\n titleId: string;\n triggerRef: MutableRefObject<HTMLElement | null>;\n position: PanelPosition;\n width: PanelWidth;\n mobileBreakpoint: number;\n isMobile: boolean;\n handleClose: () => void;\n}\n\nconst PanelContext = createContext<PanelContextValue | null>(null);\n\nfunction usePanelContext(): PanelContextValue {\n const context = useContext(PanelContext);\n if (!context) {\n throw new Error(\"Panel compound components must be used within a Panel\");\n }\n return context;\n}\n\n// ============================================================================\n// Hooks\n// ============================================================================\n\n/**\n * SSR-safe media query hook\n * Defaults to false on server (desktop mode)\n */\nfunction useMediaQuery(query: string): boolean {\n const [matches, setMatches] = useState(() => {\n // Default to false on server (desktop mode)\n if (typeof window === \"undefined\") return false;\n return window.matchMedia(query).matches;\n });\n\n useEffect(() => {\n if (typeof window === \"undefined\") return;\n const media = window.matchMedia(query);\n // Sync state after mount (handles SSR mismatch)\n if (media.matches !== matches) {\n setMatches(media.matches);\n }\n const listener = (e: MediaQueryListEvent) => setMatches(e.matches);\n media.addEventListener(\"change\", listener);\n return () => media.removeEventListener(\"change\", listener);\n }, [query, matches]);\n\n return matches;\n}\n\n// ============================================================================\n// Panel Root\n// ============================================================================\n\nfunction PanelRoot({\n children,\n isOpen: controlledIsOpen,\n defaultOpen = false,\n onOpenChange,\n onClose,\n position = \"right\",\n width = \"md\",\n mobileBreakpoint = 768,\n}: PanelProps): ReactElement {\n // State management (controlled/uncontrolled)\n const [uncontrolledIsOpen, setUncontrolledIsOpen] = useState(defaultOpen);\n const isControlled = controlledIsOpen !== undefined;\n const isOpen = isControlled ? controlledIsOpen : uncontrolledIsOpen;\n\n // Refs\n const triggerRef = useRef<HTMLElement | null>(null);\n\n // IDs for ARIA\n const uniqueId = useId();\n const panelId = `panel-${uniqueId}`;\n const titleId = `panel-title-${uniqueId}`;\n\n // Responsive detection\n const isMobile = useMediaQuery(`(max-width: ${mobileBreakpoint - 1}px)`);\n\n // State setter\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (!isControlled) {\n setUncontrolledIsOpen(open);\n }\n onOpenChange?.(open);\n },\n [isControlled, onOpenChange]\n );\n\n // Close handler with focus restoration\n const handleClose = useCallback(() => {\n setIsOpen(false);\n onClose?.();\n // Return focus to trigger if it still exists in DOM\n if (triggerRef.current) {\n window.requestAnimationFrame(() => {\n triggerRef.current?.focus();\n });\n }\n }, [setIsOpen, onClose]);\n\n // Escape key handler (desktop only - mobile handled by React Aria)\n useEffect(() => {\n if (!isOpen || isMobile) return;\n\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.key === \"Escape\") {\n e.preventDefault();\n handleClose();\n }\n };\n document.addEventListener(\"keydown\", handleKeyDown);\n return () => document.removeEventListener(\"keydown\", handleKeyDown);\n }, [isOpen, isMobile, handleClose]);\n\n const contextValue: PanelContextValue = {\n isOpen,\n setIsOpen,\n panelId,\n titleId,\n triggerRef,\n position,\n width,\n mobileBreakpoint,\n isMobile,\n handleClose,\n };\n\n return (\n <PanelContext.Provider value={contextValue}>\n {children}\n </PanelContext.Provider>\n );\n}\nPanelRoot.displayName = \"Panel\";\n\n// ============================================================================\n// Panel.Trigger\n// ============================================================================\n\nfunction PanelTrigger({\n children,\n asChild = true,\n}: PanelTriggerProps): ReactElement | null {\n const { isOpen, setIsOpen, panelId, triggerRef } = usePanelContext();\n\n // Capture ref via callback ref pattern\n const setRef = useCallback(\n (element: HTMLElement | null) => {\n triggerRef.current = element;\n },\n [triggerRef]\n );\n\n const handlePress = useCallback(() => {\n setIsOpen(!isOpen);\n }, [setIsOpen, isOpen]);\n\n // If asChild, clone the child element and add props\n if (asChild && isValidElement(children)) {\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n return cloneElement(children, {\n ref: setRef,\n \"aria-expanded\": isOpen,\n \"aria-controls\": isOpen ? panelId : undefined,\n \"data-testid\": \"panel-trigger\",\n onPress: handlePress,\n onClick: childProps.onClick\n ? () => {\n childProps.onClick?.();\n handlePress();\n }\n : handlePress,\n } as unknown as Record<string, unknown>);\n }\n\n // Fallback: wrap in AriaButton\n return (\n <AriaButton\n ref={setRef}\n aria-expanded={isOpen}\n aria-controls={isOpen ? panelId : undefined}\n onPress={handlePress}\n data-testid=\"panel-trigger\"\n >\n {children}\n </AriaButton>\n );\n}\nPanelTrigger.displayName = \"PanelTrigger\";\n\n// ============================================================================\n// Built-in Close Button\n// ============================================================================\n\nfunction BuiltInCloseButton(): ReactElement {\n const { handleClose } = usePanelContext();\n\n return (\n <AriaButton\n aria-label=\"Close panel\"\n data-testid=\"panel-close\"\n onPress={handleClose}\n className={panelCloseButtonVariants()}\n >\n <X className=\"h-5 w-5\" />\n </AriaButton>\n );\n}\n\n// ============================================================================\n// Panel.Content\n// ============================================================================\n\nfunction PanelContent({\n children,\n showClose = true,\n className,\n}: PanelContentProps): ReactElement | null {\n const { isOpen, isMobile, panelId, titleId, position, width, handleClose } =\n usePanelContext();\n\n if (!isOpen) return null;\n\n // Mobile: Use React Aria Modal primitives\n if (isMobile) {\n return (\n <AriaModalOverlay\n isDismissable\n isOpen={isOpen}\n onOpenChange={(open) => !open && handleClose()}\n className=\"fixed inset-0 z-50 bg-black/50\"\n >\n <AriaModal className=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <AriaDialog\n aria-labelledby={titleId}\n className={cn(\n \"w-full max-w-lg rounded-lg bg-[var(--content-background)] outline-none\",\n \"flex max-h-[90vh] flex-col\",\n className\n )}\n >\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n {children}\n </AriaDialog>\n </AriaModal>\n </AriaModalOverlay>\n );\n }\n\n // Desktop: Render aside in-place\n return (\n <aside\n id={panelId}\n aria-labelledby={titleId}\n data-testid=\"panel-content\"\n className={cn(panelContentVariants({ position, width }), className)}\n >\n {children}\n {showClose && (\n <div className=\"absolute right-2 top-2\">\n <BuiltInCloseButton />\n </div>\n )}\n </aside>\n );\n}\nPanelContent.displayName = \"PanelContent\";\n\n// ============================================================================\n// Panel.Header\n// ============================================================================\n\nfunction PanelHeader({\n children,\n className,\n}: PanelHeaderProps): ReactElement | null {\n // Note: We use a <header> element but DON'T add role=\"banner\"\n // because banner landmarks should not be contained in other landmarks (like aside)\n // The header element still provides structural meaning for the panel\n return (\n <header className={cn(panelHeaderVariants(), className)}>\n <div className=\"flex flex-col gap-1\">{children}</div>\n </header>\n );\n}\nPanelHeader.displayName = \"PanelHeader\";\n\n// ============================================================================\n// Panel.Title\n// ============================================================================\n\nfunction PanelTitle({\n children,\n as: Tag = \"h2\",\n className,\n}: PanelTitleProps): ReactElement | null {\n const { titleId } = usePanelContext();\n\n return (\n <Tag\n id={titleId}\n // aria-live=\"polite\" announces title changes to screen readers\n // This is important for master-detail patterns where panel content\n // updates when selecting different items (e.g., candidate profiles)\n aria-live=\"polite\"\n className={cn(\n \"text-lg font-semibold text-[var(--content-foreground)]\",\n className\n )}\n >\n {children}\n </Tag>\n );\n}\nPanelTitle.displayName = \"PanelTitle\";\n\n// ============================================================================\n// Panel.Description\n// ============================================================================\n\nfunction PanelDescription({\n children,\n className,\n}: PanelDescriptionProps): ReactElement | null {\n return (\n <p className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </p>\n );\n}\nPanelDescription.displayName = \"PanelDescription\";\n\n// ============================================================================\n// Panel.Body\n// ============================================================================\n\nfunction PanelBody({ children, className }: PanelBodyProps): ReactElement | null {\n return <div className={cn(panelBodyVariants(), className)}>{children}</div>;\n}\nPanelBody.displayName = \"PanelBody\";\n\n// ============================================================================\n// Panel.Footer\n// ============================================================================\n\nfunction PanelFooter({\n children,\n className,\n}: PanelFooterProps): ReactElement | null {\n // Note: We use a <footer> element but DON'T add role=\"contentinfo\"\n // because contentinfo landmarks should not be contained in other landmarks (like aside)\n // The footer element still provides structural meaning for the panel\n return (\n <footer className={cn(panelFooterVariants(), className)}>\n {children}\n </footer>\n );\n}\nPanelFooter.displayName = \"PanelFooter\";\n\n// ============================================================================\n// Panel.Close\n// ============================================================================\n\nfunction PanelClose({ children }: PanelCloseProps): ReactElement | null {\n const { handleClose } = usePanelContext();\n\n if (!isValidElement(children)) {\n return null;\n }\n\n // Clone the child and add onPress/onClick handler\n const childProps = children.props as unknown as {\n onPress?: () => void;\n onClick?: () => void;\n };\n\n return cloneElement(children, {\n onPress: () => {\n childProps.onPress?.();\n handleClose();\n },\n onClick: () => {\n childProps.onClick?.();\n handleClose();\n },\n } as unknown as Record<string, unknown>);\n}\nPanelClose.displayName = \"PanelClose\";\n\n// ============================================================================\n// Compound Component Export\n// ============================================================================\n\n/**\n * Panel Component\n *\n * Accessible non-modal sidebar panel using the disclosure pattern with\n * a complementary region for WCAG 2.2 AAA compliance.\n *\n * @example\n * ```tsx\n * <Panel>\n * <Panel.Trigger>\n * <Button>Open Panel</Button>\n * </Panel.Trigger>\n * <Panel.Content>\n * <Panel.Header>\n * <Panel.Title>Panel Title</Panel.Title>\n * <Panel.Description>Optional description</Panel.Description>\n * </Panel.Header>\n * <Panel.Body>\n * Panel content here\n * </Panel.Body>\n * <Panel.Footer>\n * <Button>Action</Button>\n * </Panel.Footer>\n * </Panel.Content>\n * </Panel>\n * ```\n */\nexport const Panel = Object.assign(PanelRoot, {\n Trigger: PanelTrigger,\n Content: PanelContent,\n Header: PanelHeader,\n Title: PanelTitle,\n Description: PanelDescription,\n Body: PanelBody,\n Footer: PanelFooter,\n Close: PanelClose,\n});\n\n// Named exports for individual components\nexport {\n PanelRoot,\n PanelTrigger,\n PanelContent,\n PanelHeader,\n PanelTitle,\n PanelDescription,\n PanelBody,\n PanelFooter,\n PanelClose,\n};\n\n// Export CVA variant types for customization\nexport type PanelContentVariants = VariantProps<typeof panelContentVariants>;\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),lucideReact=require('lucide-react'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function c(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var se="data-[pressed]:scale-[0.97]";var ie="data-[hovered]:shadow-md";var W="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",Y="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground",de="disabled:pointer-events-none disabled:opacity-50";var q={sm:"h-9",default:"h-10",lg:"h-11"},D={sm:`${q.sm} px-2 text-xs`,default:`${q.default} px-3 text-sm`,lg:`${q.lg} px-4 text-base`},ce="min-h-[44px] flex items-center";var ue=classVarianceAuthority.cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),pe=classVarianceAuthority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background motion-safe:transition-transform motion-safe:duration-200 motion-safe:[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] hover:-translate-y-1",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] shadow-md hover:bg-[var(--destructive-background-hover,var(--destructive-background))] motion-safe:hover:btn-warn-shake",outline:"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)]",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] shadow-md hover:bg-[var(--secondary-hover,var(--secondary))]",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]",link:"text-[var(--text-link)] underline underline-offset-4 hover:bg-[var(--accent)] hover:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-8",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] !shadow-md hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var Le=react.createContext(null);Le.displayName="ButtonGroupContext";function Ve(){return react.useContext(Le)}var De=react.createContext(null);De.displayName="ButtonGroupItemContext";function Be(){return react.useContext(De)}classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var Me=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var M=react.memo(react.forwardRef(({className:t,buttonVisualClassName:o,variant:n,size:a,visualSize:s,fullWidth:p,loading:d=false,loadingText:u="Loading...",shortcut:b,children:x,isDisabled:f,paywall:i=false,paywallRedirect:I,paywallDescription:ee,onPress:te,...k},oe)=>{let y=react.useId(),N=Ve(),G=Be(),P=n??N?.variant??"default",S=a??N?.size,z=f??N?.isDisabled??false,C=N?.orientation==="vertical",h=p||C,U=G?Me({orientation:N?.orientation??"horizontal",position:G.position}):"",_=s??S??"default";return process.env.NODE_ENV!=="production"&&(_==="dot"||_==="icon")&&!k["aria-label"]&&!x&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsxRuntime.jsx(reactAriaComponents.Button,{ref:oe,isDisabled:z||d||void 0,"aria-disabled":i?true:void 0,"aria-describedby":i?y:void 0,onPress:E=>{if(i){I&&window.open(I,"_blank","noopener,noreferrer");return}te?.(E);},className:c(ue({fullWidth:h,inVerticalGroup:C}),t),...k,children:E=>jsxRuntime.jsxs("span",{className:c(pe({variant:P,visualSize:_,paywall:i,fullWidth:h}),U,o,se,ie,W,Y),"data-pressed":E.isPressed||void 0,children:[d&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"sr-only","aria-live":"polite",children:u})]}),!d&&x,i&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),i&&jsxRuntime.jsxs("span",{id:y,className:"sr-only",children:["Premium feature: ",ee||"Upgrade required to access this feature"]}),E.isFocusVisible&&b&&jsxRuntime.jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:b})]})})}));M.displayName="Button";var He=()=>jsxRuntime.jsxs("svg",{"data-testid":"password-toggle-icon-show",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[jsxRuntime.jsx("path",{d:"M1 8s3-5 7-5 7 5 7 5-3 5-7 5-7-5-7-5z"}),jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"2"})]}),ke=()=>jsxRuntime.jsxs("svg",{"data-testid":"password-toggle-icon-hide",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[jsxRuntime.jsx("path",{d:"M10.5 5.5l-5 5"}),jsxRuntime.jsx("path",{d:"M1 8s3-5 7-5c1.5 0 2.8.6 4 1.5M15 8s-1.5 2.5-4 4"}),jsxRuntime.jsx("path",{d:"M3 13l2-2m7-7l2-2"}),jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"2"})]});var xe=classVarianceAuthority.cva("flex w-full rounded-md border bg-[var(--content-background)] shadow-xs px-3 py-2 text-sm ring-offset-[var(--content-background)] file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-[var(--content-foreground)] placeholder:text-[var(--menu-muted)] transition-all duration-200",{variants:{size:{sm:`${D.sm} py-1`,default:`${D.default} py-2`,lg:`${D.lg} py-3`},state:{default:"border-[var(--input-border)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2",error:"border-[var(--destructive-background)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--destructive-background)] focus-visible:ring-offset-2",success:"border-[var(--success-background)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--success-ring)] focus-visible:ring-offset-2",disabled:"cursor-not-allowed opacity-50",readonly:"cursor-default bg-[var(--content-background)] opacity-70"}},defaultVariants:{size:"default",state:"default"}}),ge=classVarianceAuthority.cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",{variants:{state:{default:"text-[var(--content-foreground)]",disabled:"opacity-50 cursor-not-allowed"}},defaultVariants:{state:"default"}}),be=classVarianceAuthority.cva("text-sm text-[var(--content-foreground)]"),ze=classVarianceAuthority.cva("text-sm text-[var(--destructive-background)] font-medium"),ve=classVarianceAuthority.cva("text-sm text-[var(--success-foreground)] font-medium");function $e({expandOnFocus:t,collapsedWidth:o,value:n,defaultValue:a,userOnFocus:s,userOnBlur:p}){let[d,u]=react.useState(false),b=react.useCallback(i=>{t&&u(true),s?.(i);},[t,s]),x=react.useCallback(i=>{t&&i.target.value===""&&u(false),p?.(i);},[t,p]),f=react.useMemo(()=>t?d||(n!==void 0?n!=="":a!==void 0&&a!=="")?"100%":o:void 0,[t,d,n,a,o]);return {handleFocus:b,handleBlur:x,inputWidth:f}}function We({disableCopyPaste:t}){let[o,n]=react.useState(false),[a,s]=react.useState("");react.useEffect(()=>{t&&typeof process<"u"&&process.env.NODE_ENV==="development"&&console.warn("[TextField] Copy/paste prevention should only be used for security-critical fields like password confirmation. This feature can break assistive technology workflows and password managers.");},[t]);let p=react.useCallback(d=>{t&&(d.preventDefault(),n(true),s("Pasting is not allowed in this field. Please type your entry."),setTimeout(()=>{n(false),s("");},250));},[t]);return {isShaking:o,screenReaderMessage:a,handlePaste:p}}function Ye({type:t,showPasswordToggle:o}){let[n,a]=react.useState(false),s=react.useCallback(()=>{a(d=>!d);},[]),p=react.useMemo(()=>t==="password"&&o&&n?"text":t,[t,o,n]);return {showPassword:n,actualType:p,handlePasswordToggle:s}}var wt=react.forwardRef(({className:t,state:o="default",children:n,...a},s)=>jsxRuntime.jsx(reactAriaComponents.Label,{ref:s,className:c(ge({state:o}),t),...a,children:n}));wt.displayName="TextFieldLabel";var Ot=react.forwardRef(({className:t,size:o="default",state:n="default",...a},s)=>jsxRuntime.jsx(reactAriaComponents.Input,{ref:s,className:c(xe({size:o,state:n}),de,t),...a}));Ot.displayName="TextFieldInput";var Ct=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.Text,{ref:a,slot:"description",className:c(be(),t),...n,children:o}));Ct.displayName="TextFieldDescription";var Xe=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.FieldError,{ref:a,...n,className:c(ze(),t),children:o}));Xe.displayName="TextFieldError";var Rt=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.Text,{ref:a,slot:"description",className:c(ve(),t),...n,children:o}));Rt.displayName="TextFieldSuccess";var Te=react.forwardRef(({className:t,size:o="default",label:n,labelHint:a,description:s,errorMessage:p,successMessage:d,type:u="text",isRequired:b=false,isReadOnly:x=false,isDisabled:f=false,isInvalid:i=false,isValid:I=false,id:ee,autoComplete:te,disableCopyPaste:k=false,pattern:oe,patternDescription:y,expandOnFocus:N=false,collapsedWidth:G="200px",prefix:P,suffix:S,prefixSize:z=16,suffixSize:C=16,showPasswordToggle:h,isIconHidden:U=false,onSubmit:_,onClear:ne,value:R,defaultValue:E,onFocus:Qe,onBlur:Je,...L},et)=>{let Ee=react.useId(),tt=react.useId(),ot=ee||tt,{handleFocus:nt,handleBlur:at,inputWidth:rt}=$e({expandOnFocus:N,collapsedWidth:G,value:R,defaultValue:E,userOnFocus:Qe,userOnBlur:Je}),{isShaking:st,screenReaderMessage:Ie,handlePaste:it}=We({disableCopyPaste:k}),{showPassword:ae,actualType:lt,handlePasswordToggle:ye}=Ye({type:u,showPasswordToggle:h}),g=u==="search",[dt,Ne]=react.useState(E??""),V=R!==void 0,T=V?R:dt,ct=react.useCallback(l=>{V||Ne(l),L.onChange?.(l);},[V,L]),$=react.useCallback(()=>{V||Ne(""),L.onChange?.(""),ne?.();},[V,L,ne]),ut=react.useCallback(l=>{l.key==="Enter"&&_&&_(T),l.key==="Escape"&&T&&(l.preventDefault(),$());},[T,_,$]),pt=react.useMemo(()=>f?"disabled":x?"readonly":i?"error":I?"success":"default",[f,x,i,I]),ft=react.useMemo(()=>f?"disabled":"default",[f]),_e=react.useMemo(()=>s&&y?`${s} ${y}`:s||y,[s,y]),A=react.useMemo(()=>g&&!U&&!P?jsxRuntime.jsx(lucideReact.Search,{className:o==="sm"?"h-3.5 w-3.5":o==="lg"?"h-5 w-5":"h-4 w-4"}):P,[g,U,P,o]),Pe=react.useMemo(()=>{let l={left:12,right:12};if(A){let re=typeof A=="string"?A.length*8+16:z+16;l.left=re;}if(u==="password"&&h)l.right=32;else if(g&&T)l.right=44;else if(S){let re=typeof S=="string"?S.length*8+16:C+16;l.right=re;}return l},[A,P,S,z,C,u,h,g,T]),Ae=react.useMemo(()=>u==="password"&&h?jsxRuntime.jsx(M,{variant:"ghost",visualSize:"icon",onPress:ye,"aria-label":ae?"Hide password":"Show password",className:"!min-h-0 !min-w-0 h-8 w-8",children:ae?jsxRuntime.jsx(ke,{}):jsxRuntime.jsx(He,{})}):g&&T?jsxRuntime.jsx(M,{variant:"ghost",visualSize:"icon",onPress:$,"aria-label":"Clear search",className:"!min-h-0 !min-w-0 h-8 w-8",children:jsxRuntime.jsx(lucideReact.X,{className:o==="sm"?"h-3 w-3":o==="lg"?"h-5 w-5":"h-4 w-4"})}):S,[u,h,ae,S,ye,g,T,o,$]),Fe=u==="password"&&h||g&&!!T;return jsxRuntime.jsxs(reactAriaComponents.TextField,{ref:et,className:c("flex flex-col gap-1.5",t),isRequired:b,isReadOnly:x,isDisabled:f,isInvalid:i,value:g?T:R,defaultValue:g?void 0:E,onChange:g?ct:void 0,...L,children:[n&&jsxRuntime.jsxs(reactAriaComponents.Label,{className:c(ge({state:ft}),a&&"flex items-baseline justify-between"),children:[jsxRuntime.jsxs("span",{children:[n,b&&jsxRuntime.jsx("span",{className:"ml-1 text-[var(--destructive-background)]","aria-hidden":"true",children:jsxRuntime.jsx("strong",{children:"*"})})]}),a&&jsxRuntime.jsx("span",{className:"text-xs font-normal text-[var(--muted-foreground)]",children:a})]}),_e&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(be()),children:_e}),jsxRuntime.jsxs("div",{className:c(ce,"relative cursor-text motion-safe:transition-colors motion-safe:duration-200"),style:{width:rt},onClick:l=>{l.target===l.currentTarget&&l.currentTarget.querySelector("input")?.focus();},children:[A&&jsxRuntime.jsx("div",{"data-testid":"textfield-prefix",className:"absolute left-3 flex items-center justify-center pointer-events-none text-[var(--content-foreground)]","aria-hidden":"true",children:A}),jsxRuntime.jsx(reactAriaComponents.Input,{type:lt,id:ot,className:c(xe({size:o,state:pt}),de,st&&"shake"),style:{width:"100%",paddingLeft:`${Pe.left}px`,paddingRight:`${Pe.right}px`},autoComplete:te,pattern:oe,onPaste:it,onFocus:nt,onBlur:at,onKeyDown:g?ut:void 0,"aria-required":b?"true":void 0,"aria-readonly":x?"true":void 0,"aria-errormessage":i&&p?Ee:void 0}),Ae&&jsxRuntime.jsx("div",{"data-testid":"textfield-suffix",className:c("absolute right-3 flex items-center justify-center text-[var(--content-foreground)]",Fe?"":"pointer-events-none"),"aria-hidden":Fe?void 0:"true",children:Ae})]}),I&&d&&!i&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(ve()),children:d}),i&&p&&jsxRuntime.jsx(Xe,{id:Ee,children:p}),Ie&&jsxRuntime.jsx("div",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:Ie})]})});Te.displayName="TextField";var Ke=react.forwardRef(({label:t,description:o,errorMessage:n,successMessage:a,hasToggle:s=true,autoComplete:p="current-password","aria-label":d,"aria-labelledby":u,...b},x)=>{process.env.NODE_ENV!=="production"&&!t&&!d&&!u&&console.warn("[PasswordField] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)");let f=!!n;return jsxRuntime.jsx(Te,{ref:x,type:"password",showPasswordToggle:s,autoComplete:p,label:t,description:f?void 0:o,errorMessage:n,successMessage:f?void 0:a,isInvalid:f,isValid:!!a&&!f,"aria-label":t?void 0:d,"aria-labelledby":u,...b})});Ke.displayName="PasswordField";var Q=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var Se=zod.z.enum(["off","on","name","honorific-prefix","given-name","additional-name","family-name","honorific-suffix","nickname","email","username","new-password","current-password","one-time-code","organization-title","organization","street-address","address-line1","address-line2","address-line3","address-level4","address-level3","address-level2","address-level1","country","country-name","postal-code","cc-name","cc-given-name","cc-additional-name","cc-family-name","cc-number","cc-exp","cc-exp-month","cc-exp-year","cc-csc","cc-type","transaction-currency","transaction-amount","language","bday","bday-day","bday-month","bday-year","sex","tel","tel-country-code","tel-national","tel-area-code","tel-local","tel-extension","impp","url","photo"]),Dt=[/\(\.\*\)\+/,/\(\.\+\)\+/,/\([^)]*\)\{.*,.*\}/,/\(\?!\)/,/\(\?<=\)/],Bt=t=>{for(let n of Dt)if(n.test(t))return false;return !((t.match(/[*+{}]/g)||[]).length>5)};Q.extend({size:zod.z.enum(["sm","default","lg"]).optional().default("default"),label:zod.z.string().optional(),labelHint:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),type:zod.z.enum(["text","email","password","url","search"]).optional().default("text"),isRequired:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isInvalid:zod.z.boolean().optional(),isValid:zod.z.boolean().optional(),placeholder:zod.z.string().optional(),value:zod.z.string().optional(),defaultValue:zod.z.string().optional(),name:zod.z.string().optional(),autoFocus:zod.z.boolean().optional(),autoComplete:Se.optional(),maxLength:zod.z.number().optional(),minLength:zod.z.number().optional(),pattern:zod.z.string().optional(),patternDescription:zod.z.string().optional(),disableCopyPaste:zod.z.boolean().optional().default(false),prefix:zod.z.any().optional(),suffix:zod.z.any().optional(),prefixSize:zod.z.number().optional().default(16),suffixSize:zod.z.number().optional().default(16),expandOnFocus:zod.z.boolean().optional().default(false),collapsedWidth:zod.z.string().optional().default("200px"),showPasswordToggle:zod.z.boolean().optional(),isIconHidden:zod.z.boolean().optional().default(false),onSubmit:zod.z.custom().optional(),onClear:zod.z.custom().optional()}).refine(t=>!t.pattern||t.patternDescription,{message:"patternDescription is required when pattern is provided",path:["patternDescription"]}).refine(t=>!t.pattern||Bt(t.pattern),{message:"Unsafe regex pattern detected. Pattern may cause ReDoS vulnerability. Avoid patterns like (.*)+, (.+)+, or excessive quantifiers.",path:["pattern"]}).refine(t=>!(t.successMessage&&t.errorMessage),{message:"Cannot provide both successMessage and errorMessage. Use one based on validation state.",path:["successMessage"]}).refine(t=>(typeof process<"u"&&process.env.NODE_ENV==="development"&&t.isValid&&t.isInvalid&&console.error("[TextField] Both isValid and isInvalid are true. isInvalid takes precedence."),true));zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional(),htmlFor:zod.z.string().optional(),state:zod.z.enum(["default","disabled"]).optional().default("default")});zod.z.object({className:zod.z.string().optional(),size:zod.z.enum(["sm","default","lg"]).optional().default("default"),state:zod.z.enum(["default","error","success","disabled","readonly"]).optional().default("default")});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});var Mt=Q.extend({size:zod.z.enum(["sm","default","lg"]).optional().default("default"),label:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),placeholder:zod.z.string().optional(),value:zod.z.string().optional(),defaultValue:zod.z.string().optional(),name:zod.z.string().optional(),autoComplete:Se.optional(),hasToggle:zod.z.boolean().optional().default(true),onChange:zod.z.custom().optional()});var Ht=classVarianceAuthority.cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),kt=classVarianceAuthority.cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Gt=classVarianceAuthority.cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),zt=classVarianceAuthority.cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});exports.PasswordField=Ke;exports.PasswordFieldPropsSchema=Mt;exports.passwordFieldDescriptionVariants=Gt;exports.passwordFieldErrorVariants=zt;exports.passwordFieldLabelVariants=kt;exports.passwordFieldVariants=Ht;//# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),lucideReact=require('lucide-react'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function c(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var se="data-[pressed]:scale-[0.97]";var W="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",Y="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground",le="disabled:pointer-events-none disabled:opacity-50";var q={sm:"h-9",default:"h-10",lg:"h-11"},D={sm:`${q.sm} px-2 text-xs`,default:`${q.default} px-3 text-sm`,lg:`${q.lg} px-4 text-base`},de="min-h-[44px] flex items-center";var ce=classVarianceAuthority.cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),ue=classVarianceAuthority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-normal ring-offset-background motion-safe:transition-transform motion-safe:duration-200 motion-safe:[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)] motion-reduce:transition-none [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] hover:-translate-y-1",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] hover:bg-[var(--destructive-background-hover,var(--destructive-background))] motion-safe:hover:btn-warn-shake",outline:"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)]",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] hover:bg-[var(--secondary-hover,var(--secondary))]",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)]",link:"text-[var(--text-link)] underline underline-offset-4 hover:bg-[var(--accent)] hover:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-6 text-base",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var Re=react.createContext(null);Re.displayName="ButtonGroupContext";function Le(){return react.useContext(Re)}var Ve=react.createContext(null);Ve.displayName="ButtonGroupItemContext";function De(){return react.useContext(Ve)}classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var Be=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var M=react.memo(react.forwardRef(({className:t,buttonVisualClassName:o,variant:n,size:a,visualSize:s,fullWidth:p,loading:d=false,loadingText:u="Loading...",shortcut:b,children:x,isDisabled:f,paywall:i=false,paywallRedirect:I,paywallDescription:ee,onPress:te,...k},oe)=>{let y=react.useId(),N=Le(),G=De(),P=n??N?.variant??"default",S=a??N?.size,z=f??N?.isDisabled??false,C=N?.orientation==="vertical",T=p||C,U=G?Be({orientation:N?.orientation??"horizontal",position:G.position}):"",_=s??S??"default";return process.env.NODE_ENV!=="production"&&(_==="dot"||_==="icon")&&!k["aria-label"]&&!x&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsxRuntime.jsx(reactAriaComponents.Button,{ref:oe,isDisabled:z||d||void 0,"aria-disabled":i?true:void 0,"aria-describedby":i?y:void 0,onPress:E=>{if(i){I&&window.open(I,"_blank","noopener,noreferrer");return}te?.(E);},className:c(ce({fullWidth:T,inVerticalGroup:C}),t),...k,children:E=>jsxRuntime.jsxs("span",{className:c(ue({variant:P,visualSize:_,paywall:i,fullWidth:T}),U,o,se,"",W,Y),"data-pressed":E.isPressed||void 0,children:[d&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"sr-only","aria-live":"polite",children:u})]}),!d&&x,i&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),i&&jsxRuntime.jsxs("span",{id:y,className:"sr-only",children:["Premium feature: ",ee||"Upgrade required to access this feature"]}),E.isFocusVisible&&b&&jsxRuntime.jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:b})]})})}));M.displayName="Button";var Me=()=>jsxRuntime.jsxs("svg",{"data-testid":"password-toggle-icon-show",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[jsxRuntime.jsx("path",{d:"M1 8s3-5 7-5 7 5 7 5-3 5-7 5-7-5-7-5z"}),jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"2"})]}),He=()=>jsxRuntime.jsxs("svg",{"data-testid":"password-toggle-icon-hide",width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",stroke:"currentColor",strokeWidth:"2",strokeLinecap:"round",strokeLinejoin:"round",children:[jsxRuntime.jsx("path",{d:"M10.5 5.5l-5 5"}),jsxRuntime.jsx("path",{d:"M1 8s3-5 7-5c1.5 0 2.8.6 4 1.5M15 8s-1.5 2.5-4 4"}),jsxRuntime.jsx("path",{d:"M3 13l2-2m7-7l2-2"}),jsxRuntime.jsx("circle",{cx:"8",cy:"8",r:"2"})]});var me=classVarianceAuthority.cva("flex w-full rounded-md border bg-[var(--content-background)] px-3 py-2 text-sm ring-offset-[var(--content-background)] file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-[var(--content-foreground)] placeholder:text-[var(--menu-muted)] transition-all duration-200",{variants:{size:{sm:`${D.sm} py-1`,default:`${D.default} py-2`,lg:`${D.lg} py-3`},state:{default:"border-[var(--input-border)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2",error:"border-[var(--destructive-background)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--destructive-background)] focus-visible:ring-offset-2",success:"border-[var(--success-background)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--success-ring)] focus-visible:ring-offset-2",disabled:"cursor-not-allowed opacity-50",readonly:"cursor-default bg-[var(--content-background)] opacity-70"}},defaultVariants:{size:"default",state:"default"}}),xe=classVarianceAuthority.cva("text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",{variants:{state:{default:"text-[var(--content-foreground)]",disabled:"opacity-50 cursor-not-allowed"}},defaultVariants:{state:"default"}}),ge=classVarianceAuthority.cva("text-sm text-[var(--content-foreground)]"),Ge=classVarianceAuthority.cva("text-sm text-[var(--destructive-background)] font-medium"),be=classVarianceAuthority.cva("text-sm text-[var(--success-foreground)] font-medium");function Ue({expandOnFocus:t,collapsedWidth:o,value:n,defaultValue:a,userOnFocus:s,userOnBlur:p}){let[d,u]=react.useState(false),b=react.useCallback(i=>{t&&u(true),s?.(i);},[t,s]),x=react.useCallback(i=>{t&&i.target.value===""&&u(false),p?.(i);},[t,p]),f=react.useMemo(()=>t?d||(n!==void 0?n!=="":a!==void 0&&a!=="")?"100%":o:void 0,[t,d,n,a,o]);return {handleFocus:b,handleBlur:x,inputWidth:f}}function $e({disableCopyPaste:t}){let[o,n]=react.useState(false),[a,s]=react.useState("");react.useEffect(()=>{t&&typeof process<"u"&&process.env.NODE_ENV==="development"&&console.warn("[TextField] Copy/paste prevention should only be used for security-critical fields like password confirmation. This feature can break assistive technology workflows and password managers.");},[t]);let p=react.useCallback(d=>{t&&(d.preventDefault(),n(true),s("Pasting is not allowed in this field. Please type your entry."),setTimeout(()=>{n(false),s("");},250));},[t]);return {isShaking:o,screenReaderMessage:a,handlePaste:p}}function We({type:t,showPasswordToggle:o}){let[n,a]=react.useState(false),s=react.useCallback(()=>{a(d=>!d);},[]),p=react.useMemo(()=>t==="password"&&o&&n?"text":t,[t,o,n]);return {showPassword:n,actualType:p,handlePasswordToggle:s}}var wt=react.forwardRef(({className:t,state:o="default",children:n,...a},s)=>jsxRuntime.jsx(reactAriaComponents.Label,{ref:s,className:c(xe({state:o}),t),...a,children:n}));wt.displayName="TextFieldLabel";var Ot=react.forwardRef(({className:t,size:o="default",state:n="default",...a},s)=>jsxRuntime.jsx(reactAriaComponents.Input,{ref:s,className:c(me({size:o,state:n}),le,t),...a}));Ot.displayName="TextFieldInput";var Ct=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.Text,{ref:a,slot:"description",className:c(ge(),t),...n,children:o}));Ct.displayName="TextFieldDescription";var je=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.FieldError,{ref:a,...n,className:c(Ge(),t),children:o}));je.displayName="TextFieldError";var Rt=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.Text,{ref:a,slot:"description",className:c(be(),t),...n,children:o}));Rt.displayName="TextFieldSuccess";var Te=react.forwardRef(({className:t,size:o="default",label:n,labelHint:a,description:s,errorMessage:p,successMessage:d,type:u="text",isRequired:b=false,isReadOnly:x=false,isDisabled:f=false,isInvalid:i=false,isValid:I=false,id:ee,autoComplete:te,disableCopyPaste:k=false,pattern:oe,patternDescription:y,expandOnFocus:N=false,collapsedWidth:G="200px",prefix:P,suffix:S,prefixSize:z=16,suffixSize:C=16,showPasswordToggle:T,isIconHidden:U=false,onSubmit:_,onClear:ne,value:R,defaultValue:E,onFocus:Ke,onBlur:Qe,...L},Je)=>{let Se=react.useId(),et=react.useId(),tt=ee||et,{handleFocus:ot,handleBlur:nt,inputWidth:at}=Ue({expandOnFocus:N,collapsedWidth:G,value:R,defaultValue:E,userOnFocus:Ke,userOnBlur:Qe}),{isShaking:rt,screenReaderMessage:Ee,handlePaste:st}=$e({disableCopyPaste:k}),{showPassword:ae,actualType:it,handlePasswordToggle:Ie}=We({type:u,showPasswordToggle:T}),g=u==="search",[lt,ye]=react.useState(E??""),V=R!==void 0,h=V?R:lt,dt=react.useCallback(l=>{V||ye(l),L.onChange?.(l);},[V,L]),$=react.useCallback(()=>{V||ye(""),L.onChange?.(""),ne?.();},[V,L,ne]),ct=react.useCallback(l=>{l.key==="Enter"&&_&&_(h),l.key==="Escape"&&h&&(l.preventDefault(),$());},[h,_,$]),ut=react.useMemo(()=>f?"disabled":x?"readonly":i?"error":I?"success":"default",[f,x,i,I]),pt=react.useMemo(()=>f?"disabled":"default",[f]),Ne=react.useMemo(()=>s&&y?`${s} ${y}`:s||y,[s,y]),A=react.useMemo(()=>g&&!U&&!P?jsxRuntime.jsx(lucideReact.Search,{className:o==="sm"?"h-3.5 w-3.5":o==="lg"?"h-5 w-5":"h-4 w-4"}):P,[g,U,P,o]),_e=react.useMemo(()=>{let l={left:12,right:12};if(A){let re=typeof A=="string"?A.length*8+16:z+16;l.left=re;}if(u==="password"&&T)l.right=32;else if(g&&h)l.right=44;else if(S){let re=typeof S=="string"?S.length*8+16:C+16;l.right=re;}return l},[A,P,S,z,C,u,T,g,h]),Pe=react.useMemo(()=>u==="password"&&T?jsxRuntime.jsx(M,{variant:"ghost",visualSize:"icon",onPress:Ie,"aria-label":ae?"Hide password":"Show password",className:"!min-h-0 !min-w-0 h-8 w-8",children:ae?jsxRuntime.jsx(He,{}):jsxRuntime.jsx(Me,{})}):g&&h?jsxRuntime.jsx(M,{variant:"ghost",visualSize:"icon",onPress:$,"aria-label":"Clear search",className:"!min-h-0 !min-w-0 h-8 w-8",children:jsxRuntime.jsx(lucideReact.X,{className:o==="sm"?"h-3 w-3":o==="lg"?"h-5 w-5":"h-4 w-4"})}):S,[u,T,ae,S,Ie,g,h,o,$]),Ae=u==="password"&&T||g&&!!h;return jsxRuntime.jsxs(reactAriaComponents.TextField,{ref:Je,className:c("flex flex-col gap-1.5",t),isRequired:b,isReadOnly:x,isDisabled:f,isInvalid:i,value:g?h:R,defaultValue:g?void 0:E,onChange:g?dt:void 0,...L,children:[n&&jsxRuntime.jsxs(reactAriaComponents.Label,{className:c(xe({state:pt}),a&&"flex items-baseline justify-between"),children:[jsxRuntime.jsxs("span",{children:[n,b&&jsxRuntime.jsx("span",{className:"ml-1 text-[var(--destructive-background)]","aria-hidden":"true",children:jsxRuntime.jsx("strong",{children:"*"})})]}),a&&jsxRuntime.jsx("span",{className:"text-xs font-normal text-[var(--muted-foreground)]",children:a})]}),Ne&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(ge()),children:Ne}),jsxRuntime.jsxs("div",{className:c(de,"relative cursor-text motion-safe:transition-colors motion-safe:duration-200"),style:{width:at},onClick:l=>{l.target===l.currentTarget&&l.currentTarget.querySelector("input")?.focus();},children:[A&&jsxRuntime.jsx("div",{"data-testid":"textfield-prefix",className:"absolute left-3 flex items-center justify-center pointer-events-none text-[var(--content-foreground)]","aria-hidden":"true",children:A}),jsxRuntime.jsx(reactAriaComponents.Input,{type:it,id:tt,className:c(me({size:o,state:ut}),le,rt&&"shake"),style:{width:"100%",paddingLeft:`${_e.left}px`,paddingRight:`${_e.right}px`},autoComplete:te,pattern:oe,onPaste:st,onFocus:ot,onBlur:nt,onKeyDown:g?ct:void 0,"aria-required":b?"true":void 0,"aria-readonly":x?"true":void 0,"aria-errormessage":i&&p?Se:void 0}),Pe&&jsxRuntime.jsx("div",{"data-testid":"textfield-suffix",className:c("absolute right-3 flex items-center justify-center text-[var(--content-foreground)]",Ae?"":"pointer-events-none"),"aria-hidden":Ae?void 0:"true",children:Pe})]}),I&&d&&!i&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(be()),children:d}),i&&p&&jsxRuntime.jsx(je,{id:Se,children:p}),Ee&&jsxRuntime.jsx("div",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:Ee})]})});Te.displayName="TextField";var Xe=react.forwardRef(({label:t,description:o,errorMessage:n,successMessage:a,hasToggle:s=true,autoComplete:p="current-password","aria-label":d,"aria-labelledby":u,...b},x)=>{process.env.NODE_ENV!=="production"&&!t&&!d&&!u&&console.warn("[PasswordField] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)");let f=!!n;return jsxRuntime.jsx(Te,{ref:x,type:"password",showPasswordToggle:s,autoComplete:p,label:t,description:f?void 0:o,errorMessage:n,successMessage:f?void 0:a,isInvalid:f,isValid:!!a&&!f,"aria-label":t?void 0:d,"aria-labelledby":u,...b})});Xe.displayName="PasswordField";var Q=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var he=zod.z.enum(["off","on","name","honorific-prefix","given-name","additional-name","family-name","honorific-suffix","nickname","email","username","new-password","current-password","one-time-code","organization-title","organization","street-address","address-line1","address-line2","address-line3","address-level4","address-level3","address-level2","address-level1","country","country-name","postal-code","cc-name","cc-given-name","cc-additional-name","cc-family-name","cc-number","cc-exp","cc-exp-month","cc-exp-year","cc-csc","cc-type","transaction-currency","transaction-amount","language","bday","bday-day","bday-month","bday-year","sex","tel","tel-country-code","tel-national","tel-area-code","tel-local","tel-extension","impp","url","photo"]),Dt=[/\(\.\*\)\+/,/\(\.\+\)\+/,/\([^)]*\)\{.*,.*\}/,/\(\?!\)/,/\(\?<=\)/],Bt=t=>{for(let n of Dt)if(n.test(t))return false;return !((t.match(/[*+{}]/g)||[]).length>5)};Q.extend({size:zod.z.enum(["sm","default","lg"]).optional().default("default"),label:zod.z.string().optional(),labelHint:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),type:zod.z.enum(["text","email","password","url","search"]).optional().default("text"),isRequired:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isInvalid:zod.z.boolean().optional(),isValid:zod.z.boolean().optional(),placeholder:zod.z.string().optional(),value:zod.z.string().optional(),defaultValue:zod.z.string().optional(),name:zod.z.string().optional(),autoFocus:zod.z.boolean().optional(),autoComplete:he.optional(),maxLength:zod.z.number().optional(),minLength:zod.z.number().optional(),pattern:zod.z.string().optional(),patternDescription:zod.z.string().optional(),disableCopyPaste:zod.z.boolean().optional().default(false),prefix:zod.z.any().optional(),suffix:zod.z.any().optional(),prefixSize:zod.z.number().optional().default(16),suffixSize:zod.z.number().optional().default(16),expandOnFocus:zod.z.boolean().optional().default(false),collapsedWidth:zod.z.string().optional().default("200px"),showPasswordToggle:zod.z.boolean().optional(),isIconHidden:zod.z.boolean().optional().default(false),onSubmit:zod.z.custom().optional(),onClear:zod.z.custom().optional()}).refine(t=>!t.pattern||t.patternDescription,{message:"patternDescription is required when pattern is provided",path:["patternDescription"]}).refine(t=>!t.pattern||Bt(t.pattern),{message:"Unsafe regex pattern detected. Pattern may cause ReDoS vulnerability. Avoid patterns like (.*)+, (.+)+, or excessive quantifiers.",path:["pattern"]}).refine(t=>!(t.successMessage&&t.errorMessage),{message:"Cannot provide both successMessage and errorMessage. Use one based on validation state.",path:["successMessage"]}).refine(t=>(typeof process<"u"&&process.env.NODE_ENV==="development"&&t.isValid&&t.isInvalid&&console.error("[TextField] Both isValid and isInvalid are true. isInvalid takes precedence."),true));zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional(),htmlFor:zod.z.string().optional(),state:zod.z.enum(["default","disabled"]).optional().default("default")});zod.z.object({className:zod.z.string().optional(),size:zod.z.enum(["sm","default","lg"]).optional().default("default"),state:zod.z.enum(["default","error","success","disabled","readonly"]).optional().default("default")});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});zod.z.object({children:zod.z.any().optional(),className:zod.z.string().optional()});var Mt=Q.extend({size:zod.z.enum(["sm","default","lg"]).optional().default("default"),label:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),successMessage:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),placeholder:zod.z.string().optional(),value:zod.z.string().optional(),defaultValue:zod.z.string().optional(),name:zod.z.string().optional(),autoComplete:he.optional(),hasToggle:zod.z.boolean().optional().default(true),onChange:zod.z.custom().optional()});var Ht=classVarianceAuthority.cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),kt=classVarianceAuthority.cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),Gt=classVarianceAuthority.cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),zt=classVarianceAuthority.cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});exports.PasswordField=Xe;exports.PasswordFieldPropsSchema=Mt;exports.passwordFieldDescriptionVariants=Gt;exports.passwordFieldErrorVariants=zt;exports.passwordFieldLabelVariants=kt;exports.passwordFieldVariants=Ht;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map