@tribepad/themis 1.6.4 → 1.6.6

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 (127) 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/Breadcrumbs/index.js +1 -1
  7. package/dist/elements/Breadcrumbs/index.js.map +1 -1
  8. package/dist/elements/Breadcrumbs/index.mjs +1 -1
  9. package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
  10. package/dist/elements/ColorPicker/index.js +1 -1
  11. package/dist/elements/ColorPicker/index.js.map +1 -1
  12. package/dist/elements/ColorPicker/index.mjs +1 -1
  13. package/dist/elements/ColorPicker/index.mjs.map +1 -1
  14. package/dist/elements/Combobox/Combobox.d.ts.map +1 -1
  15. package/dist/elements/Combobox/index.js +1 -1
  16. package/dist/elements/Combobox/index.js.map +1 -1
  17. package/dist/elements/Combobox/index.mjs +1 -1
  18. package/dist/elements/Combobox/index.mjs.map +1 -1
  19. package/dist/elements/DatePicker/DatePicker.d.ts.map +1 -1
  20. package/dist/elements/DatePicker/DateRangePicker.d.ts.map +1 -1
  21. package/dist/elements/DatePicker/index.js +1 -1
  22. package/dist/elements/DatePicker/index.js.map +1 -1
  23. package/dist/elements/DatePicker/index.mjs +1 -1
  24. package/dist/elements/DatePicker/index.mjs.map +1 -1
  25. package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -1
  26. package/dist/elements/Dropdown/index.js +1 -1
  27. package/dist/elements/Dropdown/index.js.map +1 -1
  28. package/dist/elements/Dropdown/index.mjs +1 -1
  29. package/dist/elements/Dropdown/index.mjs.map +1 -1
  30. package/dist/elements/FileField/index.js +1 -1
  31. package/dist/elements/FileField/index.js.map +1 -1
  32. package/dist/elements/FileField/index.mjs +1 -1
  33. package/dist/elements/FileField/index.mjs.map +1 -1
  34. package/dist/elements/Filters/FilterPopover.d.ts.map +1 -1
  35. package/dist/elements/Filters/index.js +1 -1
  36. package/dist/elements/Filters/index.js.map +1 -1
  37. package/dist/elements/Filters/index.mjs +1 -1
  38. package/dist/elements/Filters/index.mjs.map +1 -1
  39. package/dist/elements/Modal/Modal.d.ts +2 -2
  40. package/dist/elements/Modal/Modal.d.ts.map +1 -1
  41. package/dist/elements/Modal/Modal.styles.d.ts +25 -0
  42. package/dist/elements/Modal/Modal.styles.d.ts.map +1 -1
  43. package/dist/elements/Modal/Modal.types.d.ts +29 -0
  44. package/dist/elements/Modal/Modal.types.d.ts.map +1 -1
  45. package/dist/elements/Modal/index.d.ts +3 -3
  46. package/dist/elements/Modal/index.d.ts.map +1 -1
  47. package/dist/elements/Modal/index.js +1 -1
  48. package/dist/elements/Modal/index.js.map +1 -1
  49. package/dist/elements/Modal/index.mjs +1 -1
  50. package/dist/elements/Modal/index.mjs.map +1 -1
  51. package/dist/elements/NumberField/index.js +1 -1
  52. package/dist/elements/NumberField/index.js.map +1 -1
  53. package/dist/elements/NumberField/index.mjs +1 -1
  54. package/dist/elements/NumberField/index.mjs.map +1 -1
  55. package/dist/elements/PageTitle/index.js +1 -1
  56. package/dist/elements/PageTitle/index.js.map +1 -1
  57. package/dist/elements/PageTitle/index.mjs +1 -1
  58. package/dist/elements/PageTitle/index.mjs.map +1 -1
  59. package/dist/elements/Panel/Panel.d.ts.map +1 -1
  60. package/dist/elements/Panel/index.js +1 -1
  61. package/dist/elements/Panel/index.js.map +1 -1
  62. package/dist/elements/Panel/index.mjs +1 -1
  63. package/dist/elements/Panel/index.mjs.map +1 -1
  64. package/dist/elements/PasswordField/index.js +1 -1
  65. package/dist/elements/PasswordField/index.js.map +1 -1
  66. package/dist/elements/PasswordField/index.mjs +1 -1
  67. package/dist/elements/PasswordField/index.mjs.map +1 -1
  68. package/dist/elements/Resizable/components/ResizablePopover.d.ts.map +1 -1
  69. package/dist/elements/Resizable/index.js +1 -1
  70. package/dist/elements/Resizable/index.js.map +1 -1
  71. package/dist/elements/Resizable/index.mjs +1 -1
  72. package/dist/elements/Resizable/index.mjs.map +1 -1
  73. package/dist/elements/SearchField/index.js +1 -1
  74. package/dist/elements/SearchField/index.js.map +1 -1
  75. package/dist/elements/SearchField/index.mjs +1 -1
  76. package/dist/elements/SearchField/index.mjs.map +1 -1
  77. package/dist/elements/Select/Select.d.ts.map +1 -1
  78. package/dist/elements/Select/index.js +1 -1
  79. package/dist/elements/Select/index.js.map +1 -1
  80. package/dist/elements/Select/index.mjs +1 -1
  81. package/dist/elements/Select/index.mjs.map +1 -1
  82. package/dist/elements/Sidebar/SidebarMobileDrawer.d.ts.map +1 -1
  83. package/dist/elements/Sidebar/index.js +1 -1
  84. package/dist/elements/Sidebar/index.js.map +1 -1
  85. package/dist/elements/Sidebar/index.mjs +1 -1
  86. package/dist/elements/Sidebar/index.mjs.map +1 -1
  87. package/dist/elements/Table/index.js +1 -1
  88. package/dist/elements/Table/index.js.map +1 -1
  89. package/dist/elements/Table/index.mjs +1 -1
  90. package/dist/elements/Table/index.mjs.map +1 -1
  91. package/dist/elements/TextField/index.js +1 -1
  92. package/dist/elements/TextField/index.js.map +1 -1
  93. package/dist/elements/TextField/index.mjs +1 -1
  94. package/dist/elements/TextField/index.mjs.map +1 -1
  95. package/dist/elements/TimeField/index.js +1 -1
  96. package/dist/elements/TimeField/index.js.map +1 -1
  97. package/dist/elements/TimeField/index.mjs +1 -1
  98. package/dist/elements/TimeField/index.mjs.map +1 -1
  99. package/dist/elements/Wizard/index.js +1 -1
  100. package/dist/elements/Wizard/index.js.map +1 -1
  101. package/dist/elements/Wizard/index.mjs +1 -1
  102. package/dist/elements/Wizard/index.mjs.map +1 -1
  103. package/dist/elements/index.js +1 -1
  104. package/dist/elements/index.js.map +1 -1
  105. package/dist/elements/index.mjs +1 -1
  106. package/dist/elements/index.mjs.map +1 -1
  107. package/dist/index.js +2 -2
  108. package/dist/index.js.map +1 -1
  109. package/dist/index.mjs +2 -2
  110. package/dist/index.mjs.map +1 -1
  111. package/dist/styles/animations.css +32 -0
  112. package/dist/styles/index.js +1 -1
  113. package/dist/styles/index.js.map +1 -1
  114. package/dist/styles/index.mjs +1 -1
  115. package/dist/styles/index.mjs.map +1 -1
  116. package/dist/styles/shared-variants.d.ts +17 -0
  117. package/dist/styles/shared-variants.d.ts.map +1 -1
  118. package/dist/utils/browserExtensionOverlay.d.ts +36 -0
  119. package/dist/utils/browserExtensionOverlay.d.ts.map +1 -0
  120. package/dist/utils/index.d.ts +1 -0
  121. package/dist/utils/index.d.ts.map +1 -1
  122. package/dist/utils/index.js +1 -1
  123. package/dist/utils/index.js.map +1 -1
  124. package/dist/utils/index.mjs +1 -1
  125. package/dist/utils/index.mjs.map +1 -1
  126. package/package.json +1 -1
  127. package/src/elements/Modal/Modal.stories.tsx +106 -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)]"],{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
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 c(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function Y(e){if(!(e instanceof Element))return false;let n=e;for(let r=0;n&&r<100;r++){let l=n.tagName?.toLowerCase()??"";if(l.startsWith("grammarly-")||l.startsWith("lt-")||n.hasAttribute("data-grammarly-shadow-root"))return true;if(n.parentElement)n=n.parentElement;else {let s=n.getRootNode();n=s instanceof ShadowRoot?s.host:null;}}let t=e;for(;t&&!t.tagName.includes("-");)t=t.parentElement;if(!t)return false;let o=t.parentElement;return o===document.body||o===document.documentElement}function E(e){return n=>!Y(n)&&(e?.(n)??true)}var I=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"}}),B=classVarianceAuthority.cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),A=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"]),F=react.createContext(null);function f(){let e=react.useContext(F);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function se(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=l=>t(l.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function L({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:l="right",width:s="md",mobileBreakpoint:i=768}){let[d,g]=react.useState(t),u=n!==void 0,x=u?n:d,b=react.useRef(null),C=react.useId(),K=`panel-${C}`,Q=`panel-title-${C}`,v=se(`(max-width: ${i-1}px)`),h=react.useCallback(p=>{u||g(p),o?.(p);},[u,o]),y=react.useCallback(()=>{h(false),r?.(),b.current&&window.requestAnimationFrame(()=>{b.current?.focus();});},[h,r]);react.useEffect(()=>{if(!x||v)return;let p=w=>{w.key==="Escape"&&(w.preventDefault(),y());};return document.addEventListener("keydown",p),()=>document.removeEventListener("keydown",p)},[x,v,y]);let U={isOpen:x,setIsOpen:h,panelId:K,titleId:Q,triggerRef:b,position:l,width:s,mobileBreakpoint:i,isMobile:v,handleClose:y};return jsxRuntime.jsx(F.Provider,{value:U,children:e})}L.displayName="Panel";function j({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:l}=f(),s=react.useCallback(d=>{l.current=d;},[l]),i=react.useCallback(()=>{o(!t);},[o,t]);if(n&&react.isValidElement(e)){let d=e.props;return react.cloneElement(e,{ref:s,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:i,onClick:d.onClick?()=>{d.onClick?.(),i();}:i})}return jsxRuntime.jsx(reactAriaComponents.Button,{ref:s,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:i,"data-testid":"panel-trigger",children:e})}j.displayName="PanelTrigger";function N(){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 W({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:l,titleId:s,position:i,width:d,handleClose:g}=f();return o?r?jsxRuntime.jsx(reactAriaComponents.ModalOverlay,{isDismissable:true,shouldCloseOnInteractOutside:E(),isOpen:o,onOpenChange:u=>!u&&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":s,className:c("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(N,{})}),e]})})}):jsxRuntime.jsxs("aside",{id:l,"aria-labelledby":s,"data-testid":"panel-content",className:c(I({position:i,width:d}),t),children:[e,n&&jsxRuntime.jsx("div",{className:"absolute right-2 top-2",children:jsxRuntime.jsx(N,{})})]}):null}W.displayName="PanelContent";function S({children:e,className:n}){return jsxRuntime.jsx("header",{className:c(B(),n),children:jsxRuntime.jsx("div",{className:"flex flex-col gap-1",children:e})})}S.displayName="PanelHeader";function _({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsxRuntime.jsx(n,{id:o,"aria-live":"polite",className:c("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}_.displayName="PanelTitle";function X({children:e,className:n}){return jsxRuntime.jsx("p",{className:c("text-sm text-[var(--menu-muted)]",n),children:e})}X.displayName="PanelDescription";function $({children:e,className:n}){return jsxRuntime.jsx("div",{className:c(A(),n),children:e})}$.displayName="PanelBody";function z({children:e,className:n}){return jsxRuntime.jsx("footer",{className:c(D(),n),children:e})}z.displayName="PanelFooter";function G({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();}})}G.displayName="PanelClose";var ie=Object.assign(L,{Trigger:j,Content:W,Header:S,Title:_,Description:X,Body:$,Footer:z,Close:G});exports.Panel=ie;exports.panelBodyVariants=A;exports.panelCloseButtonVariants=H;exports.panelContentVariants=I;exports.panelFooterVariants=D;exports.panelHeaderVariants=B;//# 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 ],\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
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","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","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","/**\n * Detection + dismissal guard for in-page writing-assistant browser extensions\n * (Grammarly, LanguageTool, Wordtune, …).\n *\n * These extensions inject their suggestion UI as elements appended to `<body>`,\n * outside any open overlay's DOM subtree. React Aria's `isDismissable` behaviour\n * treats a click on that injected UI as an \"outside click\" and dismisses the\n * overlay — so clicking a spelling suggestion silently closes the form pop-up\n * and discards the user's in-progress correction.\n *\n * The guard below lets overlays keep open when the interaction lands on an\n * extension-injected node, while every other outside click, Escape, and the\n * close button behave exactly as before.\n */\n\nconst MAX_ANCESTOR_DEPTH = 100;\n\n/**\n * Returns `true` when `element` belongs to an injected in-page writing\n * assistant (Grammarly, LanguageTool, Wordtune, …).\n *\n * UX-ONLY heuristic. This is a deliberately spoofable DOM sniff used solely to\n * keep a form pop-up open when a writing-assistant suggestion is clicked. It is\n * NOT a security/authorization control and must never gate access to data or\n * actions (the frontend is not a security boundary). Pure function — never log\n * the element (it can reference arbitrary DOM / user content).\n */\nexport function isExtensionInjectedElement(element: Element): boolean {\n if (!(element instanceof Element)) return false;\n\n // 1. Known-vendor markers (authoritative). Walk up via parentElement, and\n // climb shadow boundaries via getRootNode().host so detection still finds\n // the <grammarly-extension> host if React Aria's shadowDOM flag is ever\n // enabled (it defaults to false today → the document-level listener\n // already receives the retargeted host, so the parentElement walk alone\n // suffices currently). Depth-bounded as a defensive guard against a\n // crafted/overridden getRootNode/host returning a cycle (which would\n // otherwise hang the tab — a client-side DoS).\n let node: Element | null = element;\n for (let depth = 0; node && depth < MAX_ANCESTOR_DEPTH; depth++) {\n const tag = node.tagName?.toLowerCase() ?? '';\n if (tag.startsWith('grammarly-')) return true; // Grammarly\n if (tag.startsWith('lt-')) return true; // LanguageTool\n if (node.hasAttribute('data-grammarly-shadow-root')) return true;\n\n if (node.parentElement) {\n node = node.parentElement;\n } else {\n const root = node.getRootNode();\n node = root instanceof ShadowRoot ? root.host : null;\n }\n }\n\n // 2. Structural fallback (best-effort, future-proofs the long tail).\n // Extensions inject their UI as a custom element (hyphenated tag name)\n // mounted as a top-level sibling of the React root — i.e. a direct child\n // of <body>/<html>. Our app never renders body-level custom elements, and\n // React Aria portals render plain <div>s, so this stays safe for any\n // future first-party web component nested inside the app tree.\n let custom: Element | null = element;\n while (custom && !custom.tagName.includes('-')) {\n custom = custom.parentElement;\n }\n if (!custom) return false;\n\n const parent = custom.parentElement;\n return parent === document.body || parent === document.documentElement;\n}\n\n/**\n * Builds a `shouldCloseOnInteractOutside` predicate for React Aria overlays\n * that keeps the overlay open when the interaction targets an extension-injected\n * element, while preserving any consumer-supplied predicate.\n *\n * React Aria semantics: the predicate returns `true` ⇒ the overlay should\n * close. So we close only when the element is NOT extension-injected AND the\n * consumer (if any) also agrees it should close.\n */\nexport function createInteractOutsideGuard(\n consumerShouldClose?: (element: Element) => boolean,\n): (element: Element) => boolean {\n return (element: Element): boolean =>\n !isExtensionInjectedElement(element) && (consumerShouldClose?.(element) ?? true);\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 { createInteractOutsideGuard } from \"../../utils/browserExtensionOverlay\";\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 shouldCloseOnInteractOutside={createInteractOutsideGuard()}\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)]"],{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
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 as X$1}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs}from'react/jsx-runtime';function c(...e){return twMerge(clsx(e))}function Y(e){if(!(e instanceof Element))return false;let n=e;for(let r=0;n&&r<100;r++){let l=n.tagName?.toLowerCase()??"";if(l.startsWith("grammarly-")||l.startsWith("lt-")||n.hasAttribute("data-grammarly-shadow-root"))return true;if(n.parentElement)n=n.parentElement;else {let s=n.getRootNode();n=s instanceof ShadowRoot?s.host:null;}}let t=e;for(;t&&!t.tagName.includes("-");)t=t.parentElement;if(!t)return false;let o=t.parentElement;return o===document.body||o===document.documentElement}function E(e){return n=>!Y(n)&&(e?.(n)??true)}var I=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"}}),B=cva(["flex items-start justify-between","px-4 py-4","border-b border-[var(--border)]"]),A=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"]),F=createContext(null);function f(){let e=useContext(F);if(!e)throw new Error("Panel compound components must be used within a Panel");return e}function se(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=l=>t(l.matches);return o.addEventListener("change",r),()=>o.removeEventListener("change",r)},[e,n]),n}function L({children:e,isOpen:n,defaultOpen:t=false,onOpenChange:o,onClose:r,position:l="right",width:s="md",mobileBreakpoint:i=768}){let[d,g]=useState(t),u=n!==void 0,x=u?n:d,b=useRef(null),C=useId(),K=`panel-${C}`,Q=`panel-title-${C}`,v=se(`(max-width: ${i-1}px)`),h=useCallback(p=>{u||g(p),o?.(p);},[u,o]),y=useCallback(()=>{h(false),r?.(),b.current&&window.requestAnimationFrame(()=>{b.current?.focus();});},[h,r]);useEffect(()=>{if(!x||v)return;let p=w=>{w.key==="Escape"&&(w.preventDefault(),y());};return document.addEventListener("keydown",p),()=>document.removeEventListener("keydown",p)},[x,v,y]);let U={isOpen:x,setIsOpen:h,panelId:K,titleId:Q,triggerRef:b,position:l,width:s,mobileBreakpoint:i,isMobile:v,handleClose:y};return jsx(F.Provider,{value:U,children:e})}L.displayName="Panel";function j({children:e,asChild:n=true}){let{isOpen:t,setIsOpen:o,panelId:r,triggerRef:l}=f(),s=useCallback(d=>{l.current=d;},[l]),i=useCallback(()=>{o(!t);},[o,t]);if(n&&isValidElement(e)){let d=e.props;return cloneElement(e,{ref:s,"aria-expanded":t,"aria-controls":t?r:void 0,"data-testid":"panel-trigger",onPress:i,onClick:d.onClick?()=>{d.onClick?.(),i();}:i})}return jsx(Button,{ref:s,"aria-expanded":t,"aria-controls":t?r:void 0,onPress:i,"data-testid":"panel-trigger",children:e})}j.displayName="PanelTrigger";function N(){let{handleClose:e}=f();return jsx(Button,{"aria-label":"Close panel","data-testid":"panel-close",onPress:e,className:H(),children:jsx(X$1,{className:"h-5 w-5"})})}function W({children:e,showClose:n=true,className:t}){let{isOpen:o,isMobile:r,panelId:l,titleId:s,position:i,width:d,handleClose:g}=f();return o?r?jsx(ModalOverlay,{isDismissable:true,shouldCloseOnInteractOutside:E(),isOpen:o,onOpenChange:u=>!u&&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":s,className:c("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(N,{})}),e]})})}):jsxs("aside",{id:l,"aria-labelledby":s,"data-testid":"panel-content",className:c(I({position:i,width:d}),t),children:[e,n&&jsx("div",{className:"absolute right-2 top-2",children:jsx(N,{})})]}):null}W.displayName="PanelContent";function S({children:e,className:n}){return jsx("header",{className:c(B(),n),children:jsx("div",{className:"flex flex-col gap-1",children:e})})}S.displayName="PanelHeader";function _({children:e,as:n="h2",className:t}){let{titleId:o}=f();return jsx(n,{id:o,"aria-live":"polite",className:c("text-lg font-semibold text-[var(--content-foreground)]",t),children:e})}_.displayName="PanelTitle";function X({children:e,className:n}){return jsx("p",{className:c("text-sm text-[var(--menu-muted)]",n),children:e})}X.displayName="PanelDescription";function $({children:e,className:n}){return jsx("div",{className:c(A(),n),children:e})}$.displayName="PanelBody";function z({children:e,className:n}){return jsx("footer",{className:c(D(),n),children:e})}z.displayName="PanelFooter";function G({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();}})}G.displayName="PanelClose";var ie=Object.assign(L,{Trigger:j,Content:W,Header:S,Title:_,Description:X,Body:$,Footer:z,Close:G});export{ie as Panel,A as panelBodyVariants,H as panelCloseButtonVariants,I as panelContentVariants,D as panelFooterVariants,B 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 ],\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
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/elements/Panel/Panel.tsx"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","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","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","/**\n * Detection + dismissal guard for in-page writing-assistant browser extensions\n * (Grammarly, LanguageTool, Wordtune, …).\n *\n * These extensions inject their suggestion UI as elements appended to `<body>`,\n * outside any open overlay's DOM subtree. React Aria's `isDismissable` behaviour\n * treats a click on that injected UI as an \"outside click\" and dismisses the\n * overlay — so clicking a spelling suggestion silently closes the form pop-up\n * and discards the user's in-progress correction.\n *\n * The guard below lets overlays keep open when the interaction lands on an\n * extension-injected node, while every other outside click, Escape, and the\n * close button behave exactly as before.\n */\n\nconst MAX_ANCESTOR_DEPTH = 100;\n\n/**\n * Returns `true` when `element` belongs to an injected in-page writing\n * assistant (Grammarly, LanguageTool, Wordtune, …).\n *\n * UX-ONLY heuristic. This is a deliberately spoofable DOM sniff used solely to\n * keep a form pop-up open when a writing-assistant suggestion is clicked. It is\n * NOT a security/authorization control and must never gate access to data or\n * actions (the frontend is not a security boundary). Pure function — never log\n * the element (it can reference arbitrary DOM / user content).\n */\nexport function isExtensionInjectedElement(element: Element): boolean {\n if (!(element instanceof Element)) return false;\n\n // 1. Known-vendor markers (authoritative). Walk up via parentElement, and\n // climb shadow boundaries via getRootNode().host so detection still finds\n // the <grammarly-extension> host if React Aria's shadowDOM flag is ever\n // enabled (it defaults to false today → the document-level listener\n // already receives the retargeted host, so the parentElement walk alone\n // suffices currently). Depth-bounded as a defensive guard against a\n // crafted/overridden getRootNode/host returning a cycle (which would\n // otherwise hang the tab — a client-side DoS).\n let node: Element | null = element;\n for (let depth = 0; node && depth < MAX_ANCESTOR_DEPTH; depth++) {\n const tag = node.tagName?.toLowerCase() ?? '';\n if (tag.startsWith('grammarly-')) return true; // Grammarly\n if (tag.startsWith('lt-')) return true; // LanguageTool\n if (node.hasAttribute('data-grammarly-shadow-root')) return true;\n\n if (node.parentElement) {\n node = node.parentElement;\n } else {\n const root = node.getRootNode();\n node = root instanceof ShadowRoot ? root.host : null;\n }\n }\n\n // 2. Structural fallback (best-effort, future-proofs the long tail).\n // Extensions inject their UI as a custom element (hyphenated tag name)\n // mounted as a top-level sibling of the React root — i.e. a direct child\n // of <body>/<html>. Our app never renders body-level custom elements, and\n // React Aria portals render plain <div>s, so this stays safe for any\n // future first-party web component nested inside the app tree.\n let custom: Element | null = element;\n while (custom && !custom.tagName.includes('-')) {\n custom = custom.parentElement;\n }\n if (!custom) return false;\n\n const parent = custom.parentElement;\n return parent === document.body || parent === document.documentElement;\n}\n\n/**\n * Builds a `shouldCloseOnInteractOutside` predicate for React Aria overlays\n * that keeps the overlay open when the interaction targets an extension-injected\n * element, while preserving any consumer-supplied predicate.\n *\n * React Aria semantics: the predicate returns `true` ⇒ the overlay should\n * close. So we close only when the element is NOT extension-injected AND the\n * consumer (if any) also agrees it should close.\n */\nexport function createInteractOutsideGuard(\n consumerShouldClose?: (element: Element) => boolean,\n): (element: Element) => boolean {\n return (element: Element): boolean =>\n !isExtensionInjectedElement(element) && (consumerShouldClose?.(element) ?? true);\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 { createInteractOutsideGuard } from \"../../utils/browserExtensionOverlay\";\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 shouldCloseOnInteractOutside={createInteractOutsideGuard()}\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 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
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 ie="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"},V={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 Le=react.createContext(null);Le.displayName="ButtonGroupContext";function Re(){return react.useContext(Le)}var De=react.createContext(null);De.displayName="ButtonGroupItemContext";function Ve(){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 B=react.memo(react.forwardRef(({className:t,buttonVisualClassName:o,variant:n,size:a,visualSize:i,fullWidth:p,loading:d=false,loadingText:u="Loading...",shortcut:b,children:x,isDisabled:f,paywall:s=false,paywallRedirect:I,paywallDescription:ee,onPress:te,...k},oe)=>{let _=react.useId(),y=Re(),G=Ve(),A=n??y?.variant??"default",S=a??y?.size,z=f??y?.isDisabled??false,C=y?.orientation==="vertical",T=p||C,U=G?Me({orientation:y?.orientation??"horizontal",position:G.position}):"",N=i??S??"default";return process.env.NODE_ENV!=="production"&&(N==="dot"||N==="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":s?true:void 0,"aria-describedby":s?_:void 0,onPress:E=>{if(s){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:A,visualSize:N,paywall:s,fullWidth:T}),U,o,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,s&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),s&&jsxRuntime.jsxs("span",{id:_,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})]})})}));B.displayName="Button";var Be=()=>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:`${V.sm} py-1`,default:`${V.default} py-2`,lg:`${V.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:i,userOnBlur:p}){let[d,u]=react.useState(false),b=react.useCallback(s=>{t&&u(true),i?.(s);},[t,i]),x=react.useCallback(s=>{t&&s.target.value===""&&u(false),p?.(s);},[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,i]=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),i("Pasting is not allowed in this field. Please type your entry."),setTimeout(()=>{n(false),i("");},250));},[t]);return {isShaking:o,screenReaderMessage:a,handlePaste:p}}function We({type:t,showPasswordToggle:o}){let[n,a]=react.useState(false),i=react.useCallback(()=>{a(d=>!d);},[]),p=react.useMemo(()=>t==="password"&&o&&n?"text":t,[t,o,n]);return {showPassword:n,actualType:p,handlePasswordToggle:i}}var Ft=react.forwardRef(({className:t,state:o="default",children:n,...a},i)=>jsxRuntime.jsx(reactAriaComponents.Label,{ref:i,className:c(xe({state:o}),t),...a,children:n}));Ft.displayName="TextFieldLabel";var wt=react.forwardRef(({className:t,size:o="default",state:n="default",...a},i)=>jsxRuntime.jsx(reactAriaComponents.Input,{ref:i,className:c(me({size:o,state:n}),le,t),...a}));wt.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 Lt=react.forwardRef(({className:t,children:o,...n},a)=>jsxRuntime.jsx(reactAriaComponents.Text,{ref:a,slot:"description",className:c(be(),t),...n,children:o}));Lt.displayName="TextFieldSuccess";var Te=react.forwardRef(({className:t,size:o="default",label:n,labelHint:a,description:i,errorMessage:p,successMessage:d,type:u="text",isRequired:b=false,isReadOnly:x=false,isDisabled:f=false,isInvalid:s=false,isValid:I=false,id:ee,autoComplete:te,disableCopyPaste:k=false,pattern:oe,patternDescription:_,expandOnFocus:y=false,collapsedWidth:G="200px",prefix:A,suffix:S,prefixSize:z=16,suffixSize:C=16,showPasswordToggle:T,isIconHidden:U=false,onSubmit:N,onClear:ne,value:L,defaultValue:E,onFocus:Ke,onBlur:Qe,...R},Je)=>{let Se=react.useId(),et=react.useId(),tt=ee||et,{handleFocus:ot,handleBlur:nt,inputWidth:at}=Ue({expandOnFocus:y,collapsedWidth:G,value:L,defaultValue:E,userOnFocus:Ke,userOnBlur:Qe}),{isShaking:rt,screenReaderMessage:Ee,handlePaste:it}=$e({disableCopyPaste:k}),{showPassword:ae,actualType:st,handlePasswordToggle:Ie}=We({type:u,showPasswordToggle:T}),g=u==="search",[lt,_e]=react.useState(E??""),D=L!==void 0,h=D?L:lt,dt=react.useCallback(l=>{D||_e(l),R.onChange?.(l);},[D,R]),$=react.useCallback(()=>{D||_e(""),R.onChange?.(""),ne?.();},[D,R,ne]),ct=react.useCallback(l=>{l.key==="Enter"&&N&&N(h),l.key==="Escape"&&h&&(l.preventDefault(),$());},[h,N,$]),ut=react.useMemo(()=>f?"disabled":x?"readonly":s?"error":I?"success":"default",[f,x,s,I]),pt=react.useMemo(()=>f?"disabled":"default",[f]),ye=react.useMemo(()=>i&&_?`${i} ${_}`:i||_,[i,_]),O=react.useMemo(()=>g&&!U&&!A?jsxRuntime.jsx(lucideReact.Search,{className:o==="sm"?"h-3.5 w-3.5":o==="lg"?"h-5 w-5":"h-4 w-4"}):A,[g,U,A,o]),Ne=react.useMemo(()=>{let l={left:12,right:12};if(O){let re=typeof O=="string"?O.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},[O,A,S,z,C,u,T,g,h]),Ae=react.useMemo(()=>u==="password"&&T?jsxRuntime.jsx(B,{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(Be,{})}):g&&h?jsxRuntime.jsx(B,{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,$]),Oe=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:s,value:g?h:L,defaultValue:g?void 0:E,onChange:g?dt:void 0,...R,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})]}),ye&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(ge()),children:ye}),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:[O&&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:O}),jsxRuntime.jsx(reactAriaComponents.Input,{type:st,id:tt,className:c(me({size:o,state:ut}),le,rt&&"shake"),style:{width:"100%",paddingLeft:`${Ne.left}px`,paddingRight:`${Ne.right}px`},autoComplete:te,pattern:oe,onPaste:it,onFocus:ot,onBlur:nt,onKeyDown:g?ct:void 0,"aria-required":b?"true":void 0,"aria-readonly":x?"true":void 0,"aria-errormessage":s&&p?Se:void 0}),Ae&&jsxRuntime.jsx("div",{"data-testid":"textfield-suffix",className:c("absolute right-3 flex items-center justify-center text-[var(--content-foreground)]",Oe?"":"pointer-events-none"),"aria-hidden":Oe?void 0:"true",children:Ae})]}),I&&d&&!s&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:c(be()),children:d}),s&&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:i=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:i,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"]),Vt=[/\(\.\*\)\+/,/\(\.\+\)\+/,/\([^)]*\)\{.*,.*\}/,/\(\?!\)/,/\(\?<=\)/],Mt=t=>{for(let n of Vt)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||Mt(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 Bt=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=Bt;exports.passwordFieldDescriptionVariants=Gt;exports.passwordFieldErrorVariants=zt;exports.passwordFieldLabelVariants=kt;exports.passwordFieldVariants=Ht;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map