@tribepad/themis 1.6.10 → 1.6.12

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,16 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.6.12] - 2026-06-22
9
+
10
+ ### Fixed
11
+ - **`Combobox` dropdown indicator icon is smaller, thinner, and right-aligned.** The `ChevronsUpDown` icon was sized `h-full w-full`, so it stretched to fill the entire 44×44 touch-target button and rendered oversized; it is now a fixed `h-4 w-4` (16px) with `strokeWidth={1.5}`. The trigger button also centred the icon within its 44px touch-target column, leaving a wide gap before the right border; the icon is now aligned to the right edge (`justify-end`) so only the field's `px-3` padding remains. The 44px touch target is preserved — visual-only change, no API changes.
12
+
13
+ ## [1.6.11] - 2026-06-16
14
+
15
+ ### Changed
16
+ - **`Tabs` stepper variant (vertical orientation) now matches the `Wizard` stepper look.** The vertical stepper renders round step circles (`rounded-full`, 36×36) with a primary fill + ring on the active/completed step and a bordered, unfilled circle for upcoming steps, a vertical connector between steps (primary once completed), and the label + optional `sublabel` stacked alongside with Wizard-style weight/colour states. The **horizontal** stepper is unchanged (inline numbered pills with line/chevron separators). Visual-only change to the existing `stepper` variant — no API changes; `completed`/`sublabel`/`separator` behave as before.
17
+
8
18
  ## [1.6.10] - 2026-06-15
9
19
 
10
20
  ### Added
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function d(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function ot(e){if(!(e instanceof Element))return false;let o=e;for(let s=0;o&&s<100;s++){let c=o.tagName?.toLowerCase()??"";if(c.startsWith("grammarly-")||c.startsWith("lt-")||o.hasAttribute("data-grammarly-shadow-root"))return true;if(o.parentElement)o=o.parentElement;else {let u=o.getRootNode();o=u instanceof ShadowRoot?u.host:null;}}let a=e;for(;a&&!a.tagName.includes("-");)a=a.parentElement;if(!a)return false;let l=a.parentElement;return l===document.body||l===document.documentElement}function D(e){return o=>!ot(o)&&(e?.(o)??true)}var b={sm:"text-xs",default:"text-sm",lg:"text-base"};var p={sm:"h-9",default:"h-10",lg:"h-11"},m={sm:`${p.sm} px-2 text-xs`,default:`${p.default} px-3 text-sm`,lg:`${p.lg} px-4 text-base`},g="min-h-[44px] flex items-center";var f=classVarianceAuthority.cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=classVarianceAuthority.cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),E=classVarianceAuthority.cva(["flex-1 bg-transparent outline-none","placeholder:text-[var(--muted-foreground)]","disabled:cursor-not-allowed"],{variants:{size:b},defaultVariants:{size:"default"}}),I=classVarianceAuthority.cva(["flex items-center w-full rounded-md border","bg-[var(--input-background)] text-[var(--content-foreground)]","border-[var(--input-border)]","transition-colors duration-[var(--transition-fast)]","focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[invalid]:border-[var(--destructive-background)]"],{variants:{size:{sm:`${m.sm} gap-1`,default:`${m.default} gap-2`,lg:`${m.lg} gap-2`}},defaultVariants:{size:"default"}}),_=classVarianceAuthority.cva(["flex items-center justify-center shrink-0","text-[var(--muted-foreground)]","hover:text-[var(--text-primary)]","transition-colors","focus:outline-none"],{variants:{size:{sm:"h-4 w-4 min-h-[44px] min-w-[44px]",default:"h-5 w-5 min-h-[44px] min-w-[44px]",lg:"h-6 w-6 min-h-[44px] min-w-[44px]"}},defaultVariants:{size:"default"}}),T=classVarianceAuthority.cva(["w-[var(--trigger-width)] overflow-auto","rounded-md border border-[var(--border)]","bg-[var(--content-background)] text-[var(--content-foreground)]","data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"]),A=classVarianceAuthority.cva("p-1 outline-none max-h-[300px] overflow-auto"),C=classVarianceAuthority.cva(["flex items-center gap-2 w-full rounded-sm px-2 py-1.5","text-[var(--content-foreground)]","cursor-pointer outline-none","data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]","data-[selected]:font-medium","data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"],{variants:{size:{sm:"text-xs min-h-[44px]",default:"text-sm min-h-[44px]",lg:"text-base min-h-[44px]"}},defaultVariants:{size:"default"}}),N=classVarianceAuthority.cva("pt-1"),O=classVarianceAuthority.cva("px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]"),L=classVarianceAuthority.cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),R=classVarianceAuthority.cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});var y=react.forwardRef(({className:e,size:o="default",label:a,description:l,errorMessage:s,isRequired:c,isDisabled:u,isReadOnly:H,placeholder:U,name:G,allowsCustomValue:z=false,menuTrigger:F="input",defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,children:$,"aria-label":v,"aria-labelledby":h,"data-testid":j,...q},Q)=>(process.env.NODE_ENV!=="production"&&!a&&!v&&!h&&console.warn("[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)"),jsxRuntime.jsxs(reactAriaComponents.ComboBox,{ref:Q,className:d(f({size:o}),e),isRequired:c,isDisabled:u,isReadOnly:H,name:G,allowsCustomValue:z,menuTrigger:F,defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,"aria-label":a?void 0:v,"aria-labelledby":h,"data-testid":j,...q,children:[a&&jsxRuntime.jsxs(reactAriaComponents.Label,{className:S({size:o}),children:[a,c&&jsxRuntime.jsx("span",{className:"text-[var(--destructive-background)] ml-1","aria-hidden":"true",children:"*"})]}),jsxRuntime.jsxs("div",{className:d(g,I({size:o})),children:[jsxRuntime.jsx(reactAriaComponents.Input,{className:E({size:o}),placeholder:U}),jsxRuntime.jsx(reactAriaComponents.Button,{className:_({size:o}),children:jsxRuntime.jsx(lucideReact.ChevronsUpDown,{className:"h-full w-full","aria-hidden":"true"})})]}),l&&!s&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:L({size:o}),children:l}),s&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"errorMessage",className:R({size:o}),children:s}),jsxRuntime.jsx(reactAriaComponents.Popover,{shouldCloseOnInteractOutside:D(),className:T(),children:jsxRuntime.jsx(reactAriaComponents.ListBox,{className:A(),children:$})})]})));y.displayName="Combobox";function P({children:e,className:o,textValue:a,...l}){let s=a||(typeof e=="string"?e:void 0);return jsxRuntime.jsx(reactAriaComponents.ListBoxItem,{className:d(C({size:"default"}),o),textValue:s,...l,children:({isSelected:c})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("span",{className:"flex-1",children:e}),c&&jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 shrink-0 text-[var(--primary)]","aria-hidden":"true"})]})})}P.displayName="ComboboxItem";function B({header:e,children:o,className:a}){return jsxRuntime.jsxs(reactAriaComponents.ListBoxSection,{className:d(N(),a),children:[e&&jsxRuntime.jsx(reactAriaComponents.Header,{className:O(),children:e}),o]})}B.displayName="ComboboxSection";var w=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 M=zod.z.enum(["sm","default","lg"]),bt=w.extend({label:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),size:M.optional().default("default"),placeholder:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),name:zod.z.string().optional(),allowsCustomValue:zod.z.boolean().optional().default(false),menuTrigger:zod.z.enum(["input","focus","manual"]).optional().default("input"),defaultInputValue:zod.z.string().optional(),inputValue:zod.z.string().optional(),defaultSelectedKey:zod.z.union([zod.z.string(),zod.z.number()]).optional(),selectedKey:zod.z.union([zod.z.string(),zod.z.number(),zod.z.null()]).optional()}),gt=zod.z.object({id:zod.z.union([zod.z.string(),zod.z.number()]).optional(),textValue:zod.z.string().optional(),isDisabled:zod.z.boolean().optional(),children:zod.z.custom(),className:zod.z.string().optional()}),ft=zod.z.object({header:zod.z.string().optional(),children:zod.z.custom(),className:zod.z.string().optional()});exports.Combobox=y;exports.ComboboxItem=P;exports.ComboboxItemPropsSchema=gt;exports.ComboboxPropsSchema=bt;exports.ComboboxSection=B;exports.ComboboxSectionPropsSchema=ft;exports.ComboboxSizeSchema=M;exports.comboboxButtonVariants=_;exports.comboboxDescriptionVariants=L;exports.comboboxErrorVariants=R;exports.comboboxInputVariants=E;exports.comboboxItemVariants=C;exports.comboboxLabelVariants=S;exports.comboboxListBoxVariants=A;exports.comboboxPopoverVariants=T;exports.comboboxSectionHeaderVariants=O;exports.comboboxSectionVariants=N;exports.comboboxTriggerWrapperVariants=I;exports.comboboxVariants=f;//# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function l(...e){return tailwindMerge.twMerge(clsx.clsx(e))}function ot(e){if(!(e instanceof Element))return false;let o=e;for(let s=0;o&&s<100;s++){let c=o.tagName?.toLowerCase()??"";if(c.startsWith("grammarly-")||c.startsWith("lt-")||o.hasAttribute("data-grammarly-shadow-root"))return true;if(o.parentElement)o=o.parentElement;else {let u=o.getRootNode();o=u instanceof ShadowRoot?u.host:null;}}let a=e;for(;a&&!a.tagName.includes("-");)a=a.parentElement;if(!a)return false;let d=a.parentElement;return d===document.body||d===document.documentElement}function D(e){return o=>!ot(o)&&(e?.(o)??true)}var b={sm:"text-xs",default:"text-sm",lg:"text-base"};var p={sm:"h-9",default:"h-10",lg:"h-11"},m={sm:`${p.sm} px-2 text-xs`,default:`${p.default} px-3 text-sm`,lg:`${p.lg} px-4 text-base`},g="min-h-[44px] flex items-center";var f=classVarianceAuthority.cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=classVarianceAuthority.cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),E=classVarianceAuthority.cva(["flex-1 bg-transparent outline-none","placeholder:text-[var(--muted-foreground)]","disabled:cursor-not-allowed"],{variants:{size:b},defaultVariants:{size:"default"}}),I=classVarianceAuthority.cva(["flex items-center w-full rounded-md border","bg-[var(--input-background)] text-[var(--content-foreground)]","border-[var(--input-border)]","transition-colors duration-[var(--transition-fast)]","focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[invalid]:border-[var(--destructive-background)]"],{variants:{size:{sm:`${m.sm} gap-1`,default:`${m.default} gap-2`,lg:`${m.lg} gap-2`}},defaultVariants:{size:"default"}}),_=classVarianceAuthority.cva(["flex items-center justify-end shrink-0","text-[var(--muted-foreground)]","hover:text-[var(--text-primary)]","transition-colors","focus:outline-none"],{variants:{size:{sm:"h-4 w-4 min-h-[44px] min-w-[44px]",default:"h-5 w-5 min-h-[44px] min-w-[44px]",lg:"h-6 w-6 min-h-[44px] min-w-[44px]"}},defaultVariants:{size:"default"}}),T=classVarianceAuthority.cva(["w-[var(--trigger-width)] overflow-auto","rounded-md border border-[var(--border)]","bg-[var(--content-background)] text-[var(--content-foreground)]","data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"]),A=classVarianceAuthority.cva("p-1 outline-none max-h-[300px] overflow-auto"),C=classVarianceAuthority.cva(["flex items-center gap-2 w-full rounded-sm px-2 py-1.5","text-[var(--content-foreground)]","cursor-pointer outline-none","data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]","data-[selected]:font-medium","data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"],{variants:{size:{sm:"text-xs min-h-[44px]",default:"text-sm min-h-[44px]",lg:"text-base min-h-[44px]"}},defaultVariants:{size:"default"}}),N=classVarianceAuthority.cva("pt-1"),O=classVarianceAuthority.cva("px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]"),L=classVarianceAuthority.cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),R=classVarianceAuthority.cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});var y=react.forwardRef(({className:e,size:o="default",label:a,description:d,errorMessage:s,isRequired:c,isDisabled:u,isReadOnly:H,placeholder:U,name:G,allowsCustomValue:z=false,menuTrigger:F="input",defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,children:$,"aria-label":v,"aria-labelledby":h,"data-testid":j,...q},Q)=>(process.env.NODE_ENV!=="production"&&!a&&!v&&!h&&console.warn("[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)"),jsxRuntime.jsxs(reactAriaComponents.ComboBox,{ref:Q,className:l(f({size:o}),e),isRequired:c,isDisabled:u,isReadOnly:H,name:G,allowsCustomValue:z,menuTrigger:F,defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,"aria-label":a?void 0:v,"aria-labelledby":h,"data-testid":j,...q,children:[a&&jsxRuntime.jsxs(reactAriaComponents.Label,{className:S({size:o}),children:[a,c&&jsxRuntime.jsx("span",{className:"text-[var(--destructive-background)] ml-1","aria-hidden":"true",children:"*"})]}),jsxRuntime.jsxs("div",{className:l(g,I({size:o})),children:[jsxRuntime.jsx(reactAriaComponents.Input,{className:E({size:o}),placeholder:U}),jsxRuntime.jsx(reactAriaComponents.Button,{className:_({size:o}),children:jsxRuntime.jsx(lucideReact.ChevronsUpDown,{className:"h-4 w-4",strokeWidth:1.5,"aria-hidden":"true"})})]}),d&&!s&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"description",className:L({size:o}),children:d}),s&&jsxRuntime.jsx(reactAriaComponents.Text,{slot:"errorMessage",className:R({size:o}),children:s}),jsxRuntime.jsx(reactAriaComponents.Popover,{shouldCloseOnInteractOutside:D(),className:T(),children:jsxRuntime.jsx(reactAriaComponents.ListBox,{className:A(),children:$})})]})));y.displayName="Combobox";function P({children:e,className:o,textValue:a,...d}){let s=a||(typeof e=="string"?e:void 0);return jsxRuntime.jsx(reactAriaComponents.ListBoxItem,{className:l(C({size:"default"}),o),textValue:s,...d,children:({isSelected:c})=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("span",{className:"flex-1",children:e}),c&&jsxRuntime.jsx(lucideReact.Check,{className:"h-4 w-4 shrink-0 text-[var(--primary)]","aria-hidden":"true"})]})})}P.displayName="ComboboxItem";function B({header:e,children:o,className:a}){return jsxRuntime.jsxs(reactAriaComponents.ListBoxSection,{className:l(N(),a),children:[e&&jsxRuntime.jsx(reactAriaComponents.Header,{className:O(),children:e}),o]})}B.displayName="ComboboxSection";var w=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 M=zod.z.enum(["sm","default","lg"]),bt=w.extend({label:zod.z.string().optional(),description:zod.z.string().optional(),errorMessage:zod.z.string().optional(),size:M.optional().default("default"),placeholder:zod.z.string().optional(),isRequired:zod.z.boolean().optional(),isDisabled:zod.z.boolean().optional(),isReadOnly:zod.z.boolean().optional(),name:zod.z.string().optional(),allowsCustomValue:zod.z.boolean().optional().default(false),menuTrigger:zod.z.enum(["input","focus","manual"]).optional().default("input"),defaultInputValue:zod.z.string().optional(),inputValue:zod.z.string().optional(),defaultSelectedKey:zod.z.union([zod.z.string(),zod.z.number()]).optional(),selectedKey:zod.z.union([zod.z.string(),zod.z.number(),zod.z.null()]).optional()}),gt=zod.z.object({id:zod.z.union([zod.z.string(),zod.z.number()]).optional(),textValue:zod.z.string().optional(),isDisabled:zod.z.boolean().optional(),children:zod.z.custom(),className:zod.z.string().optional()}),ft=zod.z.object({header:zod.z.string().optional(),children:zod.z.custom(),className:zod.z.string().optional()});exports.Combobox=y;exports.ComboboxItem=P;exports.ComboboxItemPropsSchema=gt;exports.ComboboxPropsSchema=bt;exports.ComboboxSection=B;exports.ComboboxSectionPropsSchema=ft;exports.ComboboxSizeSchema=M;exports.comboboxButtonVariants=_;exports.comboboxDescriptionVariants=L;exports.comboboxErrorVariants=R;exports.comboboxInputVariants=E;exports.comboboxItemVariants=C;exports.comboboxLabelVariants=S;exports.comboboxListBoxVariants=A;exports.comboboxPopoverVariants=T;exports.comboboxSectionHeaderVariants=O;exports.comboboxSectionVariants=N;exports.comboboxTriggerWrapperVariants=I;exports.comboboxVariants=f;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Combobox/Combobox.styles.ts","../../../src/elements/Combobox/Combobox.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Combobox/Combobox.types.ts"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","TEXT_SIZE_SMALL_SCALE","FIELD_HEIGHTS","FIELD_INPUT_SIZES","FIELD_TOUCH_TARGET","comboboxVariants","cva","comboboxLabelVariants","comboboxInputVariants","comboboxTriggerWrapperVariants","comboboxButtonVariants","comboboxPopoverVariants","comboboxListBoxVariants","comboboxItemVariants","comboboxSectionVariants","comboboxSectionHeaderVariants","comboboxDescriptionVariants","comboboxErrorVariants","Combobox","forwardRef","className","size","label","description","errorMessage","isRequired","isDisabled","isReadOnly","placeholder","name","allowsCustomValue","menuTrigger","defaultInputValue","inputValue","defaultSelectedKey","selectedKey","onInputChange","onSelectionChange","children","ariaLabel","ariaLabelledBy","dataTestId","props","ref","jsxs","AriaComboBox","AriaLabel","jsx","AriaInput","AriaButton","ChevronsUpDown","AriaText","AriaPopover","AriaListBox","ComboboxItem","textValue","computedTextValue","AriaListBoxItem","isSelected","Fragment","Check","ComboboxSection","header","AriaListBoxSection","AriaHeader","BaseComponentPropsSchema","z","ComboboxSizeSchema","ComboboxPropsSchema","ComboboxItemPropsSchema","ComboboxSectionPropsSchema"],"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","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport { FIELD_INPUT_SIZES, TEXT_SIZE_SMALL_SCALE } from '../../styles';\n\nexport const comboboxVariants = cva(\n 'group flex flex-col gap-1.5 w-full',\n {\n variants: {\n size: {\n sm: '',\n default: '',\n lg: '',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxLabelVariants = cva(\n 'text-[var(--text-primary)] font-medium',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxInputVariants = cva(\n [\n 'flex-1 bg-transparent outline-none',\n 'placeholder:text-[var(--muted-foreground)]',\n 'disabled:cursor-not-allowed',\n ],\n {\n variants: {\n size: TEXT_SIZE_SMALL_SCALE,\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxTriggerWrapperVariants = cva(\n [\n 'flex items-center w-full rounded-md border',\n 'bg-[var(--input-background)] text-[var(--content-foreground)]',\n 'border-[var(--input-border)]',\n 'transition-colors duration-[var(--transition-fast)]',\n 'focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n 'data-[invalid]:border-[var(--destructive-background)]',\n ],\n {\n variants: {\n size: {\n sm: `${FIELD_INPUT_SIZES.sm} gap-1`,\n default: `${FIELD_INPUT_SIZES.default} gap-2`,\n lg: `${FIELD_INPUT_SIZES.lg} gap-2`,\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxButtonVariants = cva(\n [\n 'flex items-center justify-center shrink-0',\n 'text-[var(--muted-foreground)]',\n 'hover:text-[var(--text-primary)]',\n 'transition-colors',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'h-4 w-4 min-h-[44px] min-w-[44px]',\n default: 'h-5 w-5 min-h-[44px] min-w-[44px]',\n lg: 'h-6 w-6 min-h-[44px] min-w-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxPopoverVariants = cva(\n [\n 'w-[var(--trigger-width)] overflow-auto',\n 'rounded-md border border-[var(--border)]',\n 'bg-[var(--content-background)] text-[var(--content-foreground)]',\n 'data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0',\n 'data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0',\n ]\n);\n\nexport const comboboxListBoxVariants = cva(\n 'p-1 outline-none max-h-[300px] overflow-auto'\n);\n\nexport const comboboxItemVariants = cva(\n [\n 'flex items-center gap-2 w-full rounded-sm px-2 py-1.5',\n 'text-[var(--content-foreground)]',\n 'cursor-pointer outline-none',\n 'data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]',\n 'data-[selected]:font-medium',\n 'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',\n ],\n {\n variants: {\n size: {\n sm: 'text-xs min-h-[44px]',\n default: 'text-sm min-h-[44px]',\n lg: 'text-base min-h-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxSectionVariants = cva('pt-1');\n\nexport const comboboxSectionHeaderVariants = cva(\n 'px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]'\n);\n\nexport const comboboxDescriptionVariants = cva(\n 'text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxErrorVariants = cva(\n 'text-[var(--destructive-background)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n","'use client';\n\nimport { forwardRef, type ReactElement } from 'react';\nimport {\n ComboBox as AriaComboBox,\n Label as AriaLabel,\n Input as AriaInput,\n Button as AriaButton,\n Popover as AriaPopover,\n ListBox as AriaListBox,\n ListBoxItem as AriaListBoxItem,\n ListBoxSection as AriaListBoxSection,\n Header as AriaHeader,\n Text as AriaText,\n} from 'react-aria-components';\nimport { ChevronsUpDown, Check } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { createInteractOutsideGuard } from '../../utils/browserExtensionOverlay';\nimport { FIELD_TOUCH_TARGET } from '../../styles';\nimport type {\n ComboboxProps,\n ComboboxItemProps,\n ComboboxSectionProps,\n} from './Combobox.types';\nimport {\n comboboxVariants,\n comboboxLabelVariants,\n comboboxInputVariants,\n comboboxTriggerWrapperVariants,\n comboboxButtonVariants,\n comboboxPopoverVariants,\n comboboxListBoxVariants,\n comboboxItemVariants,\n comboboxSectionVariants,\n comboboxSectionHeaderVariants,\n comboboxDescriptionVariants,\n comboboxErrorVariants,\n} from './Combobox.styles';\n\n// ============================================================================\n// Combobox\n// ============================================================================\n\n/**\n * Combobox Component\n *\n * A filterable select/autocomplete component built on React Aria's ComboBox.\n * Supports type-to-filter, keyboard navigation, and optional custom values.\n *\n * @example\n * ```tsx\n * <Combobox label=\"Framework\">\n * <ComboboxItem id=\"react\">React</ComboboxItem>\n * <ComboboxItem id=\"vue\">Vue</ComboboxItem>\n * <ComboboxItem id=\"angular\">Angular</ComboboxItem>\n * </Combobox>\n * ```\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n className,\n size = 'default',\n label,\n description,\n errorMessage,\n isRequired,\n isDisabled,\n isReadOnly,\n placeholder,\n name,\n allowsCustomValue = false,\n menuTrigger = 'input',\n defaultInputValue,\n inputValue,\n defaultSelectedKey,\n selectedKey,\n onInputChange,\n onSelectionChange,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ): ReactElement => {\n // Warn if no accessible label\n if (process.env.NODE_ENV !== 'production') {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)'\n );\n }\n }\n\n return (\n <AriaComboBox\n ref={ref}\n className={cn(comboboxVariants({ size }), className)}\n isRequired={isRequired}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n name={name}\n allowsCustomValue={allowsCustomValue}\n menuTrigger={menuTrigger}\n defaultInputValue={defaultInputValue}\n inputValue={inputValue}\n defaultSelectedKey={defaultSelectedKey}\n selectedKey={selectedKey}\n onInputChange={onInputChange}\n onSelectionChange={onSelectionChange}\n aria-label={!label ? ariaLabel : undefined}\n aria-labelledby={ariaLabelledBy}\n data-testid={dataTestId}\n {...props}\n >\n {label && (\n <AriaLabel className={comboboxLabelVariants({ size })}>\n {label}\n {isRequired && (\n <span className=\"text-[var(--destructive-background)] ml-1\" aria-hidden=\"true\">\n *\n </span>\n )}\n </AriaLabel>\n )}\n\n <div className={cn(FIELD_TOUCH_TARGET, comboboxTriggerWrapperVariants({ size }))}>\n <AriaInput\n className={comboboxInputVariants({ size })}\n placeholder={placeholder}\n />\n <AriaButton className={comboboxButtonVariants({ size })}>\n <ChevronsUpDown className=\"h-full w-full\" aria-hidden=\"true\" />\n </AriaButton>\n </div>\n\n {description && !errorMessage && (\n <AriaText slot=\"description\" className={comboboxDescriptionVariants({ size })}>\n {description}\n </AriaText>\n )}\n\n {errorMessage && (\n <AriaText slot=\"errorMessage\" className={comboboxErrorVariants({ size })}>\n {errorMessage}\n </AriaText>\n )}\n\n <AriaPopover\n shouldCloseOnInteractOutside={createInteractOutsideGuard()}\n className={comboboxPopoverVariants()}\n >\n <AriaListBox className={comboboxListBoxVariants()}>\n {children}\n </AriaListBox>\n </AriaPopover>\n </AriaComboBox>\n );\n }\n);\n\nCombobox.displayName = 'Combobox';\n\n// ============================================================================\n// ComboboxItem\n// ============================================================================\n\nexport function ComboboxItem({\n children,\n className,\n textValue,\n ...props\n}: ComboboxItemProps): ReactElement {\n // Compute textValue from string children if not explicitly provided\n const computedTextValue = textValue || (typeof children === 'string' ? children : undefined);\n\n return (\n <AriaListBoxItem\n className={cn(comboboxItemVariants({ size: 'default' }), className)}\n textValue={computedTextValue}\n {...props}\n >\n {({ isSelected }) => (\n <>\n <span className=\"flex-1\">{children}</span>\n {isSelected && (\n <Check className=\"h-4 w-4 shrink-0 text-[var(--primary)]\" aria-hidden=\"true\" />\n )}\n </>\n )}\n </AriaListBoxItem>\n );\n}\n\nComboboxItem.displayName = 'ComboboxItem';\n\n// ============================================================================\n// ComboboxSection\n// ============================================================================\n\nexport function ComboboxSection({\n header,\n children,\n className,\n}: ComboboxSectionProps): ReactElement {\n return (\n <AriaListBoxSection className={cn(comboboxSectionVariants(), className)}>\n {header && (\n <AriaHeader className={comboboxSectionHeaderVariants()}>\n {header}\n </AriaHeader>\n )}\n {children}\n </AriaListBoxSection>\n );\n}\n\nComboboxSection.displayName = 'ComboboxSection';\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\nimport type { ComboBoxProps as AriaComboBoxProps } from 'react-aria-components';\n\nexport const ComboboxSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type ComboboxSize = z.infer<typeof ComboboxSizeSchema>;\n\nexport const ComboboxPropsSchema = BaseComponentPropsSchema.extend({\n /** Label text */\n label: z.string().optional(),\n\n /** Description/help text */\n description: z.string().optional(),\n\n /** Error message */\n errorMessage: z.string().optional(),\n\n /** Size variant */\n size: ComboboxSizeSchema.optional().default('default'),\n\n /** Placeholder text */\n placeholder: z.string().optional(),\n\n /** Whether the field is required */\n isRequired: z.boolean().optional(),\n\n /** Whether the field is disabled */\n isDisabled: z.boolean().optional(),\n\n /** Whether the field is read-only */\n isReadOnly: z.boolean().optional(),\n\n /** Field name for form submission */\n name: z.string().optional(),\n\n /** Whether to allow custom values (not in the list) */\n allowsCustomValue: z.boolean().optional().default(false),\n\n /** The menu trigger behavior */\n menuTrigger: z.enum(['input', 'focus', 'manual']).optional().default('input'),\n\n /** Default input value (uncontrolled) */\n defaultInputValue: z.string().optional(),\n\n /** Input value (controlled) */\n inputValue: z.string().optional(),\n\n /** Default selected key (uncontrolled) */\n defaultSelectedKey: z.union([z.string(), z.number()]).optional(),\n\n /** Selected key (controlled) */\n selectedKey: z.union([z.string(), z.number(), z.null()]).optional(),\n});\n\nexport interface ComboboxPropsOwn {\n className?: string;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n label?: string;\n description?: string;\n errorMessage?: string;\n size?: ComboboxSize;\n placeholder?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n name?: string;\n allowsCustomValue?: boolean;\n menuTrigger?: 'input' | 'focus' | 'manual';\n defaultInputValue?: string;\n inputValue?: string;\n defaultSelectedKey?: string | number;\n selectedKey?: string | number | null;\n children: ReactNode;\n onInputChange?: (value: string) => void;\n onSelectionChange?: (key: string | number | null) => void;\n}\n\nexport type ComboboxProps = ComboboxPropsOwn &\n Omit<AriaComboBoxProps<object>, keyof ComboboxPropsOwn>;\n\nexport const ComboboxItemPropsSchema = z.object({\n /** Unique key/value for the item */\n id: z.union([z.string(), z.number()]).optional(),\n /** Text value for filtering */\n textValue: z.string().optional(),\n /** Whether this item is disabled */\n isDisabled: z.boolean().optional(),\n /** Item content */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxItemProps {\n id?: string | number;\n textValue?: string;\n isDisabled?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\nexport const ComboboxSectionPropsSchema = z.object({\n /** Section header text */\n header: z.string().optional(),\n /** Section items */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxSectionProps {\n header?: string;\n children?: ReactNode;\n className?: string;\n}\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Combobox/Combobox.styles.ts","../../../src/elements/Combobox/Combobox.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Combobox/Combobox.types.ts"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","TEXT_SIZE_SMALL_SCALE","FIELD_HEIGHTS","FIELD_INPUT_SIZES","FIELD_TOUCH_TARGET","comboboxVariants","cva","comboboxLabelVariants","comboboxInputVariants","comboboxTriggerWrapperVariants","comboboxButtonVariants","comboboxPopoverVariants","comboboxListBoxVariants","comboboxItemVariants","comboboxSectionVariants","comboboxSectionHeaderVariants","comboboxDescriptionVariants","comboboxErrorVariants","Combobox","forwardRef","className","size","label","description","errorMessage","isRequired","isDisabled","isReadOnly","placeholder","name","allowsCustomValue","menuTrigger","defaultInputValue","inputValue","defaultSelectedKey","selectedKey","onInputChange","onSelectionChange","children","ariaLabel","ariaLabelledBy","dataTestId","props","ref","jsxs","AriaComboBox","AriaLabel","jsx","AriaInput","AriaButton","ChevronsUpDown","AriaText","AriaPopover","AriaListBox","ComboboxItem","textValue","computedTextValue","AriaListBoxItem","isSelected","Fragment","Check","ComboboxSection","header","AriaListBoxSection","AriaHeader","BaseComponentPropsSchema","z","ComboboxSizeSchema","ComboboxPropsSchema","ComboboxItemPropsSchema","ComboboxSectionPropsSchema"],"mappings":"oTAcO,SAASA,CAAAA,CAAAA,GAAMC,CAAAA,CAA8B,CAClD,OAAOC,qBAAAA,CAAQC,UAAKF,CAAM,CAAC,CAC7B,CCWO,SAASG,EAAAA,CAA2BC,CAAAA,CAA2B,CACpE,GAAI,EAAEA,CAAAA,YAAmB,OAAA,CAAA,CAAU,OAAO,MAAA,CAU1C,IAAIC,CAAAA,CAAuBD,EAC3B,IAAA,IAASE,CAAAA,CAAQ,CAAA,CAAGD,CAAAA,EAAQC,CAAAA,CAAQ,GAAA,CAAoBA,CAAAA,EAAAA,CAAS,CAC/D,IAAMC,CAAAA,CAAMF,CAAAA,CAAK,OAAA,EAAS,WAAA,EAAY,EAAK,EAAA,CAG3C,GAFIE,EAAI,UAAA,CAAW,YAAY,CAAA,EAC3BA,CAAAA,CAAI,UAAA,CAAW,KAAK,CAAA,EACpBF,CAAAA,CAAK,YAAA,CAAa,4BAA4B,CAAA,CAAG,OAAO,KAAA,CAE5D,GAAIA,CAAAA,CAAK,aAAA,CACPA,EAAOA,CAAAA,CAAK,aAAA,CAAA,KACP,CACL,IAAMG,CAAAA,CAAOH,CAAAA,CAAK,WAAA,EAAY,CAC9BA,CAAAA,CAAOG,CAAAA,YAAgB,UAAA,CAAaA,CAAAA,CAAK,IAAA,CAAO,KAClD,CACF,CAQA,IAAIC,CAAAA,CAAyBL,CAAAA,CAC7B,KAAOK,CAAAA,EAAU,CAACA,CAAAA,CAAO,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAC3CA,CAAAA,CAASA,CAAAA,CAAO,aAAA,CAElB,GAAI,CAACA,CAAAA,CAAQ,OAAO,MAAA,CAEpB,IAAMC,CAAAA,CAASD,CAAAA,CAAO,aAAA,CACtB,OAAOC,CAAAA,GAAW,QAAA,CAAS,IAAA,EAAQA,CAAAA,GAAW,QAAA,CAAS,eACzD,CAWO,SAASC,CAAAA,CACdC,CAAAA,CAC+B,CAC/B,OAAQR,CAAAA,EACN,CAACD,EAAAA,CAA2BC,CAAO,CAAA,GAAMQ,CAAAA,GAAsBR,CAAO,CAAA,EAAK,IAAA,CAC/E,CCDO,IAAMS,CAAAA,CAAwB,CACnC,EAAA,CAAI,UACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,WACN,CAAA,CAmCO,IAAMC,CAAAA,CAAgB,CAC3B,EAAA,CAAI,KAAA,CACJ,OAAA,CAAS,MAAA,CACT,EAAA,CAAI,MACN,CAAA,CAQaC,CAAAA,CAAoB,CAC/B,EAAA,CAAI,CAAA,EAAGD,CAAAA,CAAc,EAAE,CAAA,aAAA,CAAA,CACvB,OAAA,CAAS,CAAA,EAAGA,CAAAA,CAAc,OAAO,CAAA,aAAA,CAAA,CACjC,EAAA,CAAI,CAAA,EAAGA,CAAAA,CAAc,EAAE,CAAA,eAAA,CACzB,CAAA,CASaE,EAAqB,gCAAA,CC/I3B,IAAMC,CAAAA,CAAmBC,0BAAAA,CAC9B,oCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,EAAA,CACJ,QAAS,EAAA,CACT,EAAA,CAAI,EACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaC,CAAAA,CAAwBD,0BAAAA,CACnC,wCAAA,CACA,CACE,SAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,SAAA,CACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,WACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaE,CAAAA,CAAwBF,0BAAAA,CACnC,CACE,oCAAA,CACA,4CAAA,CACA,6BACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAML,CACR,CAAA,CACA,eAAA,CAAiB,CAAE,KAAM,SAAU,CACrC,CACF,CAAA,CAEaQ,CAAAA,CAAiCH,0BAAAA,CAC5C,CACE,4CAAA,CACA,+DAAA,CACA,8BAAA,CACA,qDAAA,CACA,mGAAA,CACA,+DAAA,CACA,uDACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,CAAA,EAAGH,CAAAA,CAAkB,EAAE,CAAA,MAAA,CAAA,CAC3B,OAAA,CAAS,CAAA,EAAGA,CAAAA,CAAkB,OAAO,CAAA,MAAA,CAAA,CACrC,EAAA,CAAI,CAAA,EAAGA,EAAkB,EAAE,CAAA,MAAA,CAC7B,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaO,CAAAA,CAAyBJ,0BAAAA,CACpC,CACE,wCAAA,CACA,gCAAA,CACA,mCACA,mBAAA,CACA,oBACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,mCAAA,CACJ,OAAA,CAAS,mCAAA,CACT,EAAA,CAAI,mCACN,CACF,CAAA,CACA,gBAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaK,CAAAA,CAA0BL,0BAAAA,CACrC,CACE,wCAAA,CACA,0CAAA,CACA,iEAAA,CACA,8EAAA,CACA,8EACF,CACF,CAAA,CAEaM,EAA0BN,0BAAAA,CACrC,8CACF,CAAA,CAEaO,CAAAA,CAAuBP,0BAAAA,CAClC,CACE,uDAAA,CACA,kCAAA,CACA,6BAAA,CACA,6FAAA,CACA,6BAAA,CACA,+DACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,KAAM,CACJ,EAAA,CAAI,sBAAA,CACJ,OAAA,CAAS,sBAAA,CACT,EAAA,CAAI,wBACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaQ,EAA0BR,0BAAAA,CAAI,MAAM,CAAA,CAEpCS,CAAAA,CAAgCT,0BAAAA,CAC3C,kEACF,CAAA,CAEaU,CAAAA,CAA8BV,0BAAAA,CACzC,gCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,UACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,SACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaW,CAAAA,CAAwBX,0BAAAA,CACnC,sCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,SAAA,CACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,SACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,EChGO,IAAMY,CAAAA,CAAWC,gBAAAA,CACtB,CACE,CACE,UAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CAAO,SAAA,CACP,KAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,YAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,YAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CAAoB,KAAA,CACpB,WAAA,CAAAC,CAAAA,CAAc,OAAA,CACd,iBAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,EACA,aAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,YAAA,CAAcC,CAAAA,CACd,iBAAA,CAAmBC,CAAAA,CACnB,aAAA,CAAeC,CAAAA,CACf,GAAGC,CACL,CAAA,CACAC,CAAAA,IAGI,QAAQ,GAAA,CAAI,QAAA,GAAa,YAAA,EACvB,CAACrB,CAAAA,EAAS,CAACiB,CAAAA,EAAa,CAACC,CAAAA,EAC3B,OAAA,CAAQ,IAAA,CACN,oGACF,CAAA,CAKFI,eAAAA,CAACC,4BAAAA,CAAA,CACC,IAAKF,CAAAA,CACL,SAAA,CAAWxD,CAAAA,CAAGkB,CAAAA,CAAiB,CAAE,IAAA,CAAAgB,CAAK,CAAC,CAAA,CAAGD,CAAS,CAAA,CACnD,UAAA,CAAYK,CAAAA,CACZ,UAAA,CAAYC,CAAAA,CACZ,UAAA,CAAYC,EACZ,IAAA,CAAME,CAAAA,CACN,iBAAA,CAAmBC,CAAAA,CACnB,WAAA,CAAaC,CAAAA,CACb,iBAAA,CAAmBC,CAAAA,CACnB,UAAA,CAAYC,CAAAA,CACZ,kBAAA,CAAoBC,CAAAA,CACpB,WAAA,CAAaC,CAAAA,CACb,aAAA,CAAeC,CAAAA,CACf,iBAAA,CAAmBC,CAAAA,CACnB,YAAA,CAAaf,CAAAA,CAAoB,MAAA,CAAZiB,CAAAA,CACrB,iBAAA,CAAiBC,CAAAA,CACjB,aAAA,CAAaC,CAAAA,CACZ,GAAGC,CAAAA,CAEH,QAAA,CAAA,CAAApB,CAAAA,EACCsB,eAAAA,CAACE,yBAAAA,CAAA,CAAU,SAAA,CAAWvC,CAAAA,CAAsB,CAAE,IAAA,CAAAc,CAAK,CAAC,CAAA,CACjD,QAAA,CAAA,CAAAC,CAAAA,CACAG,CAAAA,EACCsB,cAAAA,CAAC,MAAA,CAAA,CAAK,SAAA,CAAU,2CAAA,CAA4C,aAAA,CAAY,MAAA,CAAO,aAE/E,CAAA,CAAA,CAEJ,CAAA,CAGFH,eAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAWzD,CAAAA,CAAGiB,CAAAA,CAAoBK,CAAAA,CAA+B,CAAE,IAAA,CAAAY,CAAK,CAAC,CAAC,CAAA,CAC7E,QAAA,CAAA,CAAA0B,cAAAA,CAACC,0BAAA,CACC,SAAA,CAAWxC,CAAAA,CAAsB,CAAE,IAAA,CAAAa,CAAK,CAAC,CAAA,CACzC,WAAA,CAAaO,CAAAA,CACf,CAAA,CACAmB,cAAAA,CAACE,0BAAAA,CAAA,CAAW,SAAA,CAAWvC,CAAAA,CAAuB,CAAE,IAAA,CAAAW,CAAK,CAAC,CAAA,CACpD,QAAA,CAAA0B,cAAAA,CAACG,0BAAAA,CAAA,CAAe,SAAA,CAAU,SAAA,CAAU,WAAA,CAAa,GAAA,CAAK,aAAA,CAAY,MAAA,CAAO,CAAA,CAC3E,CAAA,CAAA,CACF,EAEC3B,CAAAA,EAAe,CAACC,CAAAA,EACfuB,cAAAA,CAACI,wBAAAA,CAAA,CAAS,IAAA,CAAK,aAAA,CAAc,SAAA,CAAWnC,CAAAA,CAA4B,CAAE,IAAA,CAAAK,CAAK,CAAC,CAAA,CACzE,QAAA,CAAAE,EACH,CAAA,CAGDC,CAAAA,EACCuB,cAAAA,CAACI,wBAAAA,CAAA,CAAS,IAAA,CAAK,cAAA,CAAe,SAAA,CAAWlC,CAAAA,CAAsB,CAAE,IAAA,CAAAI,CAAK,CAAC,CAAA,CACpE,QAAA,CAAAG,CAAAA,CACH,EAGFuB,cAAAA,CAACK,2BAAAA,CAAA,CACC,4BAAA,CAA8BrD,CAAAA,EAA2B,CACzD,SAAA,CAAWY,CAAAA,EAAwB,CAEnC,QAAA,CAAAoC,cAAAA,CAACM,2BAAAA,CAAA,CAAY,SAAA,CAAWzC,CAAAA,EAAwB,CAC7C,QAAA,CAAA0B,CAAAA,CACH,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAGN,EAEApB,CAAAA,CAAS,WAAA,CAAc,UAAA,CAMhB,SAASoC,CAAAA,CAAa,CAC3B,QAAA,CAAAhB,CAAAA,CACA,SAAA,CAAAlB,CAAAA,CACA,UAAAmC,CAAAA,CACA,GAAGb,CACL,CAAA,CAAoC,CAElC,IAAMc,CAAAA,CAAoBD,CAAAA,GAAc,OAAOjB,CAAAA,EAAa,QAAA,CAAWA,CAAAA,CAAW,MAAA,CAAA,CAElF,OACES,cAAAA,CAACU,+BAAAA,CAAA,CACC,SAAA,CAAWtE,CAAAA,CAAG0B,CAAAA,CAAqB,CAAE,IAAA,CAAM,SAAU,CAAC,CAAA,CAAGO,CAAS,CAAA,CAClE,SAAA,CAAWoC,CAAAA,CACV,GAAGd,CAAAA,CAEH,QAAA,CAAA,CAAC,CAAE,WAAAgB,CAAW,CAAA,GACbd,eAAAA,CAAAe,mBAAAA,CAAA,CACE,QAAA,CAAA,CAAAZ,cAAAA,CAAC,MAAA,CAAA,CAAK,SAAA,CAAU,QAAA,CAAU,QAAA,CAAAT,CAAAA,CAAS,CAAA,CAClCoB,CAAAA,EACCX,cAAAA,CAACa,iBAAAA,CAAA,CAAM,SAAA,CAAU,wCAAA,CAAyC,aAAA,CAAY,MAAA,CAAO,CAAA,CAAA,CAEjF,CAAA,CAEJ,CAEJ,CAEAN,CAAAA,CAAa,WAAA,CAAc,cAAA,CAMpB,SAASO,CAAAA,CAAgB,CAC9B,MAAA,CAAAC,CAAAA,CACA,SAAAxB,CAAAA,CACA,SAAA,CAAAlB,CACF,CAAA,CAAuC,CACrC,OACEwB,eAAAA,CAACmB,kCAAAA,CAAA,CAAmB,SAAA,CAAW5E,CAAAA,CAAG2B,CAAAA,EAAwB,CAAGM,CAAS,CAAA,CACnE,QAAA,CAAA,CAAA0C,GACCf,cAAAA,CAACiB,0BAAAA,CAAA,CAAW,SAAA,CAAWjD,CAAAA,EAA8B,CAClD,QAAA,CAAA+C,CAAAA,CACH,CAAA,CAEDxB,CAAAA,CAAAA,CACH,CAEJ,CAEAuB,CAAAA,CAAgB,WAAA,CAAc,iBAAA,CClNvB,IAAMI,CAAAA,CAA2BC,KAAAA,CAAE,MAAA,CAAO,CAE/C,SAAA,CAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG/B,QAAA,CAAUA,KAAAA,CAAE,GAAA,EAAI,CAAE,QAAA,EAAS,CAC3B,EAAA,CAAIA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGxB,YAAA,CAAcA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAClC,iBAAA,CAAmBA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CACvC,kBAAA,CAAoBA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CACxC,WAAA,CAAaA,KAAAA,CAAE,KAAK,CAAC,KAAA,CAAO,QAAA,CAAU,WAAW,CAAC,CAAA,CAAE,QAAA,EAAS,CAC7D,aAAA,CAAeA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGpC,aAAA,CAAeA,KAAAA,CAAE,QAAO,CAAE,QAAA,EAC5B,CAAC,CAAA,CCrBM,IAAMC,CAAAA,CAAqBD,KAAAA,CAAE,IAAA,CAAK,CAAC,IAAA,CAAM,SAAA,CAAW,IAAI,CAAC,CAAA,CAGnDE,EAAAA,CAAsBH,EAAyB,MAAA,CAAO,CAEjE,KAAA,CAAOC,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG3B,WAAA,CAAaA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGjC,YAAA,CAAcA,KAAAA,CAAE,QAAO,CAAE,QAAA,EAAS,CAGlC,IAAA,CAAMC,CAAAA,CAAmB,QAAA,EAAS,CAAE,OAAA,CAAQ,SAAS,CAAA,CAGrD,WAAA,CAAaD,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGjC,WAAYA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGjC,UAAA,CAAYA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGjC,UAAA,CAAYA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,GAGxB,IAAA,CAAMA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG1B,iBAAA,CAAmBA,KAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,KAAK,CAAA,CAGvD,WAAA,CAAaA,MAAE,IAAA,CAAK,CAAC,OAAA,CAAS,OAAA,CAAS,QAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,OAAO,CAAA,CAG5E,iBAAA,CAAmBA,KAAAA,CAAE,MAAA,EAAO,CAAE,UAAS,CAGvC,UAAA,CAAYA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGhC,kBAAA,CAAoBA,KAAAA,CAAE,KAAA,CAAM,CAACA,KAAAA,CAAE,MAAA,EAAO,CAAGA,KAAAA,CAAE,MAAA,EAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAG/D,WAAA,CAAaA,KAAAA,CAAE,KAAA,CAAM,CAACA,KAAAA,CAAE,MAAA,EAAO,CAAGA,KAAAA,CAAE,MAAA,EAAO,CAAGA,KAAAA,CAAE,IAAA,EAAM,CAAC,CAAA,CAAE,QAAA,EAC3D,CAAC,CAAA,CAkCYG,EAAAA,CAA0BH,KAAAA,CAAE,MAAA,CAAO,CAE9C,EAAA,CAAIA,KAAAA,CAAE,KAAA,CAAM,CAACA,KAAAA,CAAE,MAAA,GAAUA,KAAAA,CAAE,MAAA,EAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAE/C,SAAA,CAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAE/B,UAAA,CAAYA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAEjC,QAAA,CAAUA,KAAAA,CAAE,MAAA,EAAkB,CAC9B,SAAA,CAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EACxB,CAAC,CAAA,CAUYI,EAAAA,CAA6BJ,KAAAA,CAAE,OAAO,CAEjD,MAAA,CAAQA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAE5B,QAAA,CAAUA,KAAAA,CAAE,MAAA,EAAkB,CAC9B,SAAA,CAAWA,KAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EACxB,CAAC","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","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport { FIELD_INPUT_SIZES, TEXT_SIZE_SMALL_SCALE } from '../../styles';\n\nexport const comboboxVariants = cva(\n 'group flex flex-col gap-1.5 w-full',\n {\n variants: {\n size: {\n sm: '',\n default: '',\n lg: '',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxLabelVariants = cva(\n 'text-[var(--text-primary)] font-medium',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxInputVariants = cva(\n [\n 'flex-1 bg-transparent outline-none',\n 'placeholder:text-[var(--muted-foreground)]',\n 'disabled:cursor-not-allowed',\n ],\n {\n variants: {\n size: TEXT_SIZE_SMALL_SCALE,\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxTriggerWrapperVariants = cva(\n [\n 'flex items-center w-full rounded-md border',\n 'bg-[var(--input-background)] text-[var(--content-foreground)]',\n 'border-[var(--input-border)]',\n 'transition-colors duration-[var(--transition-fast)]',\n 'focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n 'data-[invalid]:border-[var(--destructive-background)]',\n ],\n {\n variants: {\n size: {\n sm: `${FIELD_INPUT_SIZES.sm} gap-1`,\n default: `${FIELD_INPUT_SIZES.default} gap-2`,\n lg: `${FIELD_INPUT_SIZES.lg} gap-2`,\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxButtonVariants = cva(\n [\n 'flex items-center justify-end shrink-0',\n 'text-[var(--muted-foreground)]',\n 'hover:text-[var(--text-primary)]',\n 'transition-colors',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'h-4 w-4 min-h-[44px] min-w-[44px]',\n default: 'h-5 w-5 min-h-[44px] min-w-[44px]',\n lg: 'h-6 w-6 min-h-[44px] min-w-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxPopoverVariants = cva(\n [\n 'w-[var(--trigger-width)] overflow-auto',\n 'rounded-md border border-[var(--border)]',\n 'bg-[var(--content-background)] text-[var(--content-foreground)]',\n 'data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0',\n 'data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0',\n ]\n);\n\nexport const comboboxListBoxVariants = cva(\n 'p-1 outline-none max-h-[300px] overflow-auto'\n);\n\nexport const comboboxItemVariants = cva(\n [\n 'flex items-center gap-2 w-full rounded-sm px-2 py-1.5',\n 'text-[var(--content-foreground)]',\n 'cursor-pointer outline-none',\n 'data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]',\n 'data-[selected]:font-medium',\n 'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',\n ],\n {\n variants: {\n size: {\n sm: 'text-xs min-h-[44px]',\n default: 'text-sm min-h-[44px]',\n lg: 'text-base min-h-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxSectionVariants = cva('pt-1');\n\nexport const comboboxSectionHeaderVariants = cva(\n 'px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]'\n);\n\nexport const comboboxDescriptionVariants = cva(\n 'text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxErrorVariants = cva(\n 'text-[var(--destructive-background)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n","'use client';\n\nimport { forwardRef, type ReactElement } from 'react';\nimport {\n ComboBox as AriaComboBox,\n Label as AriaLabel,\n Input as AriaInput,\n Button as AriaButton,\n Popover as AriaPopover,\n ListBox as AriaListBox,\n ListBoxItem as AriaListBoxItem,\n ListBoxSection as AriaListBoxSection,\n Header as AriaHeader,\n Text as AriaText,\n} from 'react-aria-components';\nimport { ChevronsUpDown, Check } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { createInteractOutsideGuard } from '../../utils/browserExtensionOverlay';\nimport { FIELD_TOUCH_TARGET } from '../../styles';\nimport type {\n ComboboxProps,\n ComboboxItemProps,\n ComboboxSectionProps,\n} from './Combobox.types';\nimport {\n comboboxVariants,\n comboboxLabelVariants,\n comboboxInputVariants,\n comboboxTriggerWrapperVariants,\n comboboxButtonVariants,\n comboboxPopoverVariants,\n comboboxListBoxVariants,\n comboboxItemVariants,\n comboboxSectionVariants,\n comboboxSectionHeaderVariants,\n comboboxDescriptionVariants,\n comboboxErrorVariants,\n} from './Combobox.styles';\n\n// ============================================================================\n// Combobox\n// ============================================================================\n\n/**\n * Combobox Component\n *\n * A filterable select/autocomplete component built on React Aria's ComboBox.\n * Supports type-to-filter, keyboard navigation, and optional custom values.\n *\n * @example\n * ```tsx\n * <Combobox label=\"Framework\">\n * <ComboboxItem id=\"react\">React</ComboboxItem>\n * <ComboboxItem id=\"vue\">Vue</ComboboxItem>\n * <ComboboxItem id=\"angular\">Angular</ComboboxItem>\n * </Combobox>\n * ```\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n className,\n size = 'default',\n label,\n description,\n errorMessage,\n isRequired,\n isDisabled,\n isReadOnly,\n placeholder,\n name,\n allowsCustomValue = false,\n menuTrigger = 'input',\n defaultInputValue,\n inputValue,\n defaultSelectedKey,\n selectedKey,\n onInputChange,\n onSelectionChange,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ): ReactElement => {\n // Warn if no accessible label\n if (process.env.NODE_ENV !== 'production') {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)'\n );\n }\n }\n\n return (\n <AriaComboBox\n ref={ref}\n className={cn(comboboxVariants({ size }), className)}\n isRequired={isRequired}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n name={name}\n allowsCustomValue={allowsCustomValue}\n menuTrigger={menuTrigger}\n defaultInputValue={defaultInputValue}\n inputValue={inputValue}\n defaultSelectedKey={defaultSelectedKey}\n selectedKey={selectedKey}\n onInputChange={onInputChange}\n onSelectionChange={onSelectionChange}\n aria-label={!label ? ariaLabel : undefined}\n aria-labelledby={ariaLabelledBy}\n data-testid={dataTestId}\n {...props}\n >\n {label && (\n <AriaLabel className={comboboxLabelVariants({ size })}>\n {label}\n {isRequired && (\n <span className=\"text-[var(--destructive-background)] ml-1\" aria-hidden=\"true\">\n *\n </span>\n )}\n </AriaLabel>\n )}\n\n <div className={cn(FIELD_TOUCH_TARGET, comboboxTriggerWrapperVariants({ size }))}>\n <AriaInput\n className={comboboxInputVariants({ size })}\n placeholder={placeholder}\n />\n <AriaButton className={comboboxButtonVariants({ size })}>\n <ChevronsUpDown className=\"h-4 w-4\" strokeWidth={1.5} aria-hidden=\"true\" />\n </AriaButton>\n </div>\n\n {description && !errorMessage && (\n <AriaText slot=\"description\" className={comboboxDescriptionVariants({ size })}>\n {description}\n </AriaText>\n )}\n\n {errorMessage && (\n <AriaText slot=\"errorMessage\" className={comboboxErrorVariants({ size })}>\n {errorMessage}\n </AriaText>\n )}\n\n <AriaPopover\n shouldCloseOnInteractOutside={createInteractOutsideGuard()}\n className={comboboxPopoverVariants()}\n >\n <AriaListBox className={comboboxListBoxVariants()}>\n {children}\n </AriaListBox>\n </AriaPopover>\n </AriaComboBox>\n );\n }\n);\n\nCombobox.displayName = 'Combobox';\n\n// ============================================================================\n// ComboboxItem\n// ============================================================================\n\nexport function ComboboxItem({\n children,\n className,\n textValue,\n ...props\n}: ComboboxItemProps): ReactElement {\n // Compute textValue from string children if not explicitly provided\n const computedTextValue = textValue || (typeof children === 'string' ? children : undefined);\n\n return (\n <AriaListBoxItem\n className={cn(comboboxItemVariants({ size: 'default' }), className)}\n textValue={computedTextValue}\n {...props}\n >\n {({ isSelected }) => (\n <>\n <span className=\"flex-1\">{children}</span>\n {isSelected && (\n <Check className=\"h-4 w-4 shrink-0 text-[var(--primary)]\" aria-hidden=\"true\" />\n )}\n </>\n )}\n </AriaListBoxItem>\n );\n}\n\nComboboxItem.displayName = 'ComboboxItem';\n\n// ============================================================================\n// ComboboxSection\n// ============================================================================\n\nexport function ComboboxSection({\n header,\n children,\n className,\n}: ComboboxSectionProps): ReactElement {\n return (\n <AriaListBoxSection className={cn(comboboxSectionVariants(), className)}>\n {header && (\n <AriaHeader className={comboboxSectionHeaderVariants()}>\n {header}\n </AriaHeader>\n )}\n {children}\n </AriaListBoxSection>\n );\n}\n\nComboboxSection.displayName = 'ComboboxSection';\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\nimport type { ComboBoxProps as AriaComboBoxProps } from 'react-aria-components';\n\nexport const ComboboxSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type ComboboxSize = z.infer<typeof ComboboxSizeSchema>;\n\nexport const ComboboxPropsSchema = BaseComponentPropsSchema.extend({\n /** Label text */\n label: z.string().optional(),\n\n /** Description/help text */\n description: z.string().optional(),\n\n /** Error message */\n errorMessage: z.string().optional(),\n\n /** Size variant */\n size: ComboboxSizeSchema.optional().default('default'),\n\n /** Placeholder text */\n placeholder: z.string().optional(),\n\n /** Whether the field is required */\n isRequired: z.boolean().optional(),\n\n /** Whether the field is disabled */\n isDisabled: z.boolean().optional(),\n\n /** Whether the field is read-only */\n isReadOnly: z.boolean().optional(),\n\n /** Field name for form submission */\n name: z.string().optional(),\n\n /** Whether to allow custom values (not in the list) */\n allowsCustomValue: z.boolean().optional().default(false),\n\n /** The menu trigger behavior */\n menuTrigger: z.enum(['input', 'focus', 'manual']).optional().default('input'),\n\n /** Default input value (uncontrolled) */\n defaultInputValue: z.string().optional(),\n\n /** Input value (controlled) */\n inputValue: z.string().optional(),\n\n /** Default selected key (uncontrolled) */\n defaultSelectedKey: z.union([z.string(), z.number()]).optional(),\n\n /** Selected key (controlled) */\n selectedKey: z.union([z.string(), z.number(), z.null()]).optional(),\n});\n\nexport interface ComboboxPropsOwn {\n className?: string;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n label?: string;\n description?: string;\n errorMessage?: string;\n size?: ComboboxSize;\n placeholder?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n name?: string;\n allowsCustomValue?: boolean;\n menuTrigger?: 'input' | 'focus' | 'manual';\n defaultInputValue?: string;\n inputValue?: string;\n defaultSelectedKey?: string | number;\n selectedKey?: string | number | null;\n children: ReactNode;\n onInputChange?: (value: string) => void;\n onSelectionChange?: (key: string | number | null) => void;\n}\n\nexport type ComboboxProps = ComboboxPropsOwn &\n Omit<AriaComboBoxProps<object>, keyof ComboboxPropsOwn>;\n\nexport const ComboboxItemPropsSchema = z.object({\n /** Unique key/value for the item */\n id: z.union([z.string(), z.number()]).optional(),\n /** Text value for filtering */\n textValue: z.string().optional(),\n /** Whether this item is disabled */\n isDisabled: z.boolean().optional(),\n /** Item content */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxItemProps {\n id?: string | number;\n textValue?: string;\n isDisabled?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\nexport const ComboboxSectionPropsSchema = z.object({\n /** Section header text */\n header: z.string().optional(),\n /** Section items */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxSectionProps {\n header?: string;\n children?: ReactNode;\n className?: string;\n}\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import {forwardRef}from'react';import {ComboBox,Label,Input,Button,Text,Popover,ListBox,ListBoxItem,ListBoxSection,Header}from'react-aria-components';import {ChevronsUpDown,Check}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {z}from'zod';function d(...e){return twMerge(clsx(e))}function ot(e){if(!(e instanceof Element))return false;let o=e;for(let s=0;o&&s<100;s++){let c=o.tagName?.toLowerCase()??"";if(c.startsWith("grammarly-")||c.startsWith("lt-")||o.hasAttribute("data-grammarly-shadow-root"))return true;if(o.parentElement)o=o.parentElement;else {let u=o.getRootNode();o=u instanceof ShadowRoot?u.host:null;}}let a=e;for(;a&&!a.tagName.includes("-");)a=a.parentElement;if(!a)return false;let l=a.parentElement;return l===document.body||l===document.documentElement}function D(e){return o=>!ot(o)&&(e?.(o)??true)}var b={sm:"text-xs",default:"text-sm",lg:"text-base"};var p={sm:"h-9",default:"h-10",lg:"h-11"},m={sm:`${p.sm} px-2 text-xs`,default:`${p.default} px-3 text-sm`,lg:`${p.lg} px-4 text-base`},g="min-h-[44px] flex items-center";var f=cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),E=cva(["flex-1 bg-transparent outline-none","placeholder:text-[var(--muted-foreground)]","disabled:cursor-not-allowed"],{variants:{size:b},defaultVariants:{size:"default"}}),I=cva(["flex items-center w-full rounded-md border","bg-[var(--input-background)] text-[var(--content-foreground)]","border-[var(--input-border)]","transition-colors duration-[var(--transition-fast)]","focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[invalid]:border-[var(--destructive-background)]"],{variants:{size:{sm:`${m.sm} gap-1`,default:`${m.default} gap-2`,lg:`${m.lg} gap-2`}},defaultVariants:{size:"default"}}),_=cva(["flex items-center justify-center shrink-0","text-[var(--muted-foreground)]","hover:text-[var(--text-primary)]","transition-colors","focus:outline-none"],{variants:{size:{sm:"h-4 w-4 min-h-[44px] min-w-[44px]",default:"h-5 w-5 min-h-[44px] min-w-[44px]",lg:"h-6 w-6 min-h-[44px] min-w-[44px]"}},defaultVariants:{size:"default"}}),T=cva(["w-[var(--trigger-width)] overflow-auto","rounded-md border border-[var(--border)]","bg-[var(--content-background)] text-[var(--content-foreground)]","data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"]),A=cva("p-1 outline-none max-h-[300px] overflow-auto"),C=cva(["flex items-center gap-2 w-full rounded-sm px-2 py-1.5","text-[var(--content-foreground)]","cursor-pointer outline-none","data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]","data-[selected]:font-medium","data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"],{variants:{size:{sm:"text-xs min-h-[44px]",default:"text-sm min-h-[44px]",lg:"text-base min-h-[44px]"}},defaultVariants:{size:"default"}}),N=cva("pt-1"),O=cva("px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]"),L=cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),R=cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});var y=forwardRef(({className:e,size:o="default",label:a,description:l,errorMessage:s,isRequired:c,isDisabled:u,isReadOnly:H,placeholder:U,name:G,allowsCustomValue:z=false,menuTrigger:F="input",defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,children:$,"aria-label":v,"aria-labelledby":h,"data-testid":j,...q},Q)=>(process.env.NODE_ENV!=="production"&&!a&&!v&&!h&&console.warn("[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)"),jsxs(ComboBox,{ref:Q,className:d(f({size:o}),e),isRequired:c,isDisabled:u,isReadOnly:H,name:G,allowsCustomValue:z,menuTrigger:F,defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,"aria-label":a?void 0:v,"aria-labelledby":h,"data-testid":j,...q,children:[a&&jsxs(Label,{className:S({size:o}),children:[a,c&&jsx("span",{className:"text-[var(--destructive-background)] ml-1","aria-hidden":"true",children:"*"})]}),jsxs("div",{className:d(g,I({size:o})),children:[jsx(Input,{className:E({size:o}),placeholder:U}),jsx(Button,{className:_({size:o}),children:jsx(ChevronsUpDown,{className:"h-full w-full","aria-hidden":"true"})})]}),l&&!s&&jsx(Text,{slot:"description",className:L({size:o}),children:l}),s&&jsx(Text,{slot:"errorMessage",className:R({size:o}),children:s}),jsx(Popover,{shouldCloseOnInteractOutside:D(),className:T(),children:jsx(ListBox,{className:A(),children:$})})]})));y.displayName="Combobox";function P({children:e,className:o,textValue:a,...l}){let s=a||(typeof e=="string"?e:void 0);return jsx(ListBoxItem,{className:d(C({size:"default"}),o),textValue:s,...l,children:({isSelected:c})=>jsxs(Fragment,{children:[jsx("span",{className:"flex-1",children:e}),c&&jsx(Check,{className:"h-4 w-4 shrink-0 text-[var(--primary)]","aria-hidden":"true"})]})})}P.displayName="ComboboxItem";function B({header:e,children:o,className:a}){return jsxs(ListBoxSection,{className:d(N(),a),children:[e&&jsx(Header,{className:O(),children:e}),o]})}B.displayName="ComboboxSection";var w=z.object({className:z.string().optional(),children:z.any().optional(),id:z.string().optional(),"aria-label":z.string().optional(),"aria-labelledby":z.string().optional(),"aria-describedby":z.string().optional(),"aria-live":z.enum(["off","polite","assertive"]).optional(),"aria-hidden":z.boolean().optional(),"data-testid":z.string().optional()});var M=z.enum(["sm","default","lg"]),bt=w.extend({label:z.string().optional(),description:z.string().optional(),errorMessage:z.string().optional(),size:M.optional().default("default"),placeholder:z.string().optional(),isRequired:z.boolean().optional(),isDisabled:z.boolean().optional(),isReadOnly:z.boolean().optional(),name:z.string().optional(),allowsCustomValue:z.boolean().optional().default(false),menuTrigger:z.enum(["input","focus","manual"]).optional().default("input"),defaultInputValue:z.string().optional(),inputValue:z.string().optional(),defaultSelectedKey:z.union([z.string(),z.number()]).optional(),selectedKey:z.union([z.string(),z.number(),z.null()]).optional()}),gt=z.object({id:z.union([z.string(),z.number()]).optional(),textValue:z.string().optional(),isDisabled:z.boolean().optional(),children:z.custom(),className:z.string().optional()}),ft=z.object({header:z.string().optional(),children:z.custom(),className:z.string().optional()});export{y as Combobox,P as ComboboxItem,gt as ComboboxItemPropsSchema,bt as ComboboxPropsSchema,B as ComboboxSection,ft as ComboboxSectionPropsSchema,M as ComboboxSizeSchema,_ as comboboxButtonVariants,L as comboboxDescriptionVariants,R as comboboxErrorVariants,E as comboboxInputVariants,C as comboboxItemVariants,S as comboboxLabelVariants,A as comboboxListBoxVariants,T as comboboxPopoverVariants,O as comboboxSectionHeaderVariants,N as comboboxSectionVariants,I as comboboxTriggerWrapperVariants,f as comboboxVariants};//# sourceMappingURL=index.mjs.map
2
+ import {forwardRef}from'react';import {ComboBox,Label,Input,Button,Text,Popover,ListBox,ListBoxItem,ListBoxSection,Header}from'react-aria-components';import {ChevronsUpDown,Check}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsxs,jsx,Fragment}from'react/jsx-runtime';import {z}from'zod';function l(...e){return twMerge(clsx(e))}function ot(e){if(!(e instanceof Element))return false;let o=e;for(let s=0;o&&s<100;s++){let c=o.tagName?.toLowerCase()??"";if(c.startsWith("grammarly-")||c.startsWith("lt-")||o.hasAttribute("data-grammarly-shadow-root"))return true;if(o.parentElement)o=o.parentElement;else {let u=o.getRootNode();o=u instanceof ShadowRoot?u.host:null;}}let a=e;for(;a&&!a.tagName.includes("-");)a=a.parentElement;if(!a)return false;let d=a.parentElement;return d===document.body||d===document.documentElement}function D(e){return o=>!ot(o)&&(e?.(o)??true)}var b={sm:"text-xs",default:"text-sm",lg:"text-base"};var p={sm:"h-9",default:"h-10",lg:"h-11"},m={sm:`${p.sm} px-2 text-xs`,default:`${p.default} px-3 text-sm`,lg:`${p.lg} px-4 text-base`},g="min-h-[44px] flex items-center";var f=cva("group flex flex-col gap-1.5 w-full",{variants:{size:{sm:"",default:"",lg:""}},defaultVariants:{size:"default"}}),S=cva("text-[var(--text-primary)] font-medium",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}}),E=cva(["flex-1 bg-transparent outline-none","placeholder:text-[var(--muted-foreground)]","disabled:cursor-not-allowed"],{variants:{size:b},defaultVariants:{size:"default"}}),I=cva(["flex items-center w-full rounded-md border","bg-[var(--input-background)] text-[var(--content-foreground)]","border-[var(--input-border)]","transition-colors duration-[var(--transition-fast)]","focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]","data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50","data-[invalid]:border-[var(--destructive-background)]"],{variants:{size:{sm:`${m.sm} gap-1`,default:`${m.default} gap-2`,lg:`${m.lg} gap-2`}},defaultVariants:{size:"default"}}),_=cva(["flex items-center justify-end shrink-0","text-[var(--muted-foreground)]","hover:text-[var(--text-primary)]","transition-colors","focus:outline-none"],{variants:{size:{sm:"h-4 w-4 min-h-[44px] min-w-[44px]",default:"h-5 w-5 min-h-[44px] min-w-[44px]",lg:"h-6 w-6 min-h-[44px] min-w-[44px]"}},defaultVariants:{size:"default"}}),T=cva(["w-[var(--trigger-width)] overflow-auto","rounded-md border border-[var(--border)]","bg-[var(--content-background)] text-[var(--content-foreground)]","data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0","data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0"]),A=cva("p-1 outline-none max-h-[300px] overflow-auto"),C=cva(["flex items-center gap-2 w-full rounded-sm px-2 py-1.5","text-[var(--content-foreground)]","cursor-pointer outline-none","data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]","data-[selected]:font-medium","data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed"],{variants:{size:{sm:"text-xs min-h-[44px]",default:"text-sm min-h-[44px]",lg:"text-base min-h-[44px]"}},defaultVariants:{size:"default"}}),N=cva("pt-1"),O=cva("px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]"),L=cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}}),R=cva("text-[var(--destructive-background)]",{variants:{size:{sm:"text-xs",default:"text-xs",lg:"text-sm"}},defaultVariants:{size:"default"}});var y=forwardRef(({className:e,size:o="default",label:a,description:d,errorMessage:s,isRequired:c,isDisabled:u,isReadOnly:H,placeholder:U,name:G,allowsCustomValue:z=false,menuTrigger:F="input",defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,children:$,"aria-label":v,"aria-labelledby":h,"data-testid":j,...q},Q)=>(process.env.NODE_ENV!=="production"&&!a&&!v&&!h&&console.warn("[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)"),jsxs(ComboBox,{ref:Q,className:l(f({size:o}),e),isRequired:c,isDisabled:u,isReadOnly:H,name:G,allowsCustomValue:z,menuTrigger:F,defaultInputValue:k,inputValue:Z,defaultSelectedKey:W,selectedKey:Y,onInputChange:X,onSelectionChange:K,"aria-label":a?void 0:v,"aria-labelledby":h,"data-testid":j,...q,children:[a&&jsxs(Label,{className:S({size:o}),children:[a,c&&jsx("span",{className:"text-[var(--destructive-background)] ml-1","aria-hidden":"true",children:"*"})]}),jsxs("div",{className:l(g,I({size:o})),children:[jsx(Input,{className:E({size:o}),placeholder:U}),jsx(Button,{className:_({size:o}),children:jsx(ChevronsUpDown,{className:"h-4 w-4",strokeWidth:1.5,"aria-hidden":"true"})})]}),d&&!s&&jsx(Text,{slot:"description",className:L({size:o}),children:d}),s&&jsx(Text,{slot:"errorMessage",className:R({size:o}),children:s}),jsx(Popover,{shouldCloseOnInteractOutside:D(),className:T(),children:jsx(ListBox,{className:A(),children:$})})]})));y.displayName="Combobox";function P({children:e,className:o,textValue:a,...d}){let s=a||(typeof e=="string"?e:void 0);return jsx(ListBoxItem,{className:l(C({size:"default"}),o),textValue:s,...d,children:({isSelected:c})=>jsxs(Fragment,{children:[jsx("span",{className:"flex-1",children:e}),c&&jsx(Check,{className:"h-4 w-4 shrink-0 text-[var(--primary)]","aria-hidden":"true"})]})})}P.displayName="ComboboxItem";function B({header:e,children:o,className:a}){return jsxs(ListBoxSection,{className:l(N(),a),children:[e&&jsx(Header,{className:O(),children:e}),o]})}B.displayName="ComboboxSection";var w=z.object({className:z.string().optional(),children:z.any().optional(),id:z.string().optional(),"aria-label":z.string().optional(),"aria-labelledby":z.string().optional(),"aria-describedby":z.string().optional(),"aria-live":z.enum(["off","polite","assertive"]).optional(),"aria-hidden":z.boolean().optional(),"data-testid":z.string().optional()});var M=z.enum(["sm","default","lg"]),bt=w.extend({label:z.string().optional(),description:z.string().optional(),errorMessage:z.string().optional(),size:M.optional().default("default"),placeholder:z.string().optional(),isRequired:z.boolean().optional(),isDisabled:z.boolean().optional(),isReadOnly:z.boolean().optional(),name:z.string().optional(),allowsCustomValue:z.boolean().optional().default(false),menuTrigger:z.enum(["input","focus","manual"]).optional().default("input"),defaultInputValue:z.string().optional(),inputValue:z.string().optional(),defaultSelectedKey:z.union([z.string(),z.number()]).optional(),selectedKey:z.union([z.string(),z.number(),z.null()]).optional()}),gt=z.object({id:z.union([z.string(),z.number()]).optional(),textValue:z.string().optional(),isDisabled:z.boolean().optional(),children:z.custom(),className:z.string().optional()}),ft=z.object({header:z.string().optional(),children:z.custom(),className:z.string().optional()});export{y as Combobox,P as ComboboxItem,gt as ComboboxItemPropsSchema,bt as ComboboxPropsSchema,B as ComboboxSection,ft as ComboboxSectionPropsSchema,M as ComboboxSizeSchema,_ as comboboxButtonVariants,L as comboboxDescriptionVariants,R as comboboxErrorVariants,E as comboboxInputVariants,C as comboboxItemVariants,S as comboboxLabelVariants,A as comboboxListBoxVariants,T as comboboxPopoverVariants,O as comboboxSectionHeaderVariants,N as comboboxSectionVariants,I as comboboxTriggerWrapperVariants,f as comboboxVariants};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Combobox/Combobox.styles.ts","../../../src/elements/Combobox/Combobox.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Combobox/Combobox.types.ts"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","TEXT_SIZE_SMALL_SCALE","FIELD_HEIGHTS","FIELD_INPUT_SIZES","FIELD_TOUCH_TARGET","comboboxVariants","cva","comboboxLabelVariants","comboboxInputVariants","comboboxTriggerWrapperVariants","comboboxButtonVariants","comboboxPopoverVariants","comboboxListBoxVariants","comboboxItemVariants","comboboxSectionVariants","comboboxSectionHeaderVariants","comboboxDescriptionVariants","comboboxErrorVariants","Combobox","forwardRef","className","size","label","description","errorMessage","isRequired","isDisabled","isReadOnly","placeholder","name","allowsCustomValue","menuTrigger","defaultInputValue","inputValue","defaultSelectedKey","selectedKey","onInputChange","onSelectionChange","children","ariaLabel","ariaLabelledBy","dataTestId","props","ref","jsxs","AriaComboBox","AriaLabel","jsx","AriaInput","AriaButton","ChevronsUpDown","AriaText","AriaPopover","AriaListBox","ComboboxItem","textValue","computedTextValue","AriaListBoxItem","isSelected","Fragment","Check","ComboboxSection","header","AriaListBoxSection","AriaHeader","BaseComponentPropsSchema","z","ComboboxSizeSchema","ComboboxPropsSchema","ComboboxItemPropsSchema","ComboboxSectionPropsSchema"],"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","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport { FIELD_INPUT_SIZES, TEXT_SIZE_SMALL_SCALE } from '../../styles';\n\nexport const comboboxVariants = cva(\n 'group flex flex-col gap-1.5 w-full',\n {\n variants: {\n size: {\n sm: '',\n default: '',\n lg: '',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxLabelVariants = cva(\n 'text-[var(--text-primary)] font-medium',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxInputVariants = cva(\n [\n 'flex-1 bg-transparent outline-none',\n 'placeholder:text-[var(--muted-foreground)]',\n 'disabled:cursor-not-allowed',\n ],\n {\n variants: {\n size: TEXT_SIZE_SMALL_SCALE,\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxTriggerWrapperVariants = cva(\n [\n 'flex items-center w-full rounded-md border',\n 'bg-[var(--input-background)] text-[var(--content-foreground)]',\n 'border-[var(--input-border)]',\n 'transition-colors duration-[var(--transition-fast)]',\n 'focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n 'data-[invalid]:border-[var(--destructive-background)]',\n ],\n {\n variants: {\n size: {\n sm: `${FIELD_INPUT_SIZES.sm} gap-1`,\n default: `${FIELD_INPUT_SIZES.default} gap-2`,\n lg: `${FIELD_INPUT_SIZES.lg} gap-2`,\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxButtonVariants = cva(\n [\n 'flex items-center justify-center shrink-0',\n 'text-[var(--muted-foreground)]',\n 'hover:text-[var(--text-primary)]',\n 'transition-colors',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'h-4 w-4 min-h-[44px] min-w-[44px]',\n default: 'h-5 w-5 min-h-[44px] min-w-[44px]',\n lg: 'h-6 w-6 min-h-[44px] min-w-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxPopoverVariants = cva(\n [\n 'w-[var(--trigger-width)] overflow-auto',\n 'rounded-md border border-[var(--border)]',\n 'bg-[var(--content-background)] text-[var(--content-foreground)]',\n 'data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0',\n 'data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0',\n ]\n);\n\nexport const comboboxListBoxVariants = cva(\n 'p-1 outline-none max-h-[300px] overflow-auto'\n);\n\nexport const comboboxItemVariants = cva(\n [\n 'flex items-center gap-2 w-full rounded-sm px-2 py-1.5',\n 'text-[var(--content-foreground)]',\n 'cursor-pointer outline-none',\n 'data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]',\n 'data-[selected]:font-medium',\n 'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',\n ],\n {\n variants: {\n size: {\n sm: 'text-xs min-h-[44px]',\n default: 'text-sm min-h-[44px]',\n lg: 'text-base min-h-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxSectionVariants = cva('pt-1');\n\nexport const comboboxSectionHeaderVariants = cva(\n 'px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]'\n);\n\nexport const comboboxDescriptionVariants = cva(\n 'text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxErrorVariants = cva(\n 'text-[var(--destructive-background)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n","'use client';\n\nimport { forwardRef, type ReactElement } from 'react';\nimport {\n ComboBox as AriaComboBox,\n Label as AriaLabel,\n Input as AriaInput,\n Button as AriaButton,\n Popover as AriaPopover,\n ListBox as AriaListBox,\n ListBoxItem as AriaListBoxItem,\n ListBoxSection as AriaListBoxSection,\n Header as AriaHeader,\n Text as AriaText,\n} from 'react-aria-components';\nimport { ChevronsUpDown, Check } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { createInteractOutsideGuard } from '../../utils/browserExtensionOverlay';\nimport { FIELD_TOUCH_TARGET } from '../../styles';\nimport type {\n ComboboxProps,\n ComboboxItemProps,\n ComboboxSectionProps,\n} from './Combobox.types';\nimport {\n comboboxVariants,\n comboboxLabelVariants,\n comboboxInputVariants,\n comboboxTriggerWrapperVariants,\n comboboxButtonVariants,\n comboboxPopoverVariants,\n comboboxListBoxVariants,\n comboboxItemVariants,\n comboboxSectionVariants,\n comboboxSectionHeaderVariants,\n comboboxDescriptionVariants,\n comboboxErrorVariants,\n} from './Combobox.styles';\n\n// ============================================================================\n// Combobox\n// ============================================================================\n\n/**\n * Combobox Component\n *\n * A filterable select/autocomplete component built on React Aria's ComboBox.\n * Supports type-to-filter, keyboard navigation, and optional custom values.\n *\n * @example\n * ```tsx\n * <Combobox label=\"Framework\">\n * <ComboboxItem id=\"react\">React</ComboboxItem>\n * <ComboboxItem id=\"vue\">Vue</ComboboxItem>\n * <ComboboxItem id=\"angular\">Angular</ComboboxItem>\n * </Combobox>\n * ```\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n className,\n size = 'default',\n label,\n description,\n errorMessage,\n isRequired,\n isDisabled,\n isReadOnly,\n placeholder,\n name,\n allowsCustomValue = false,\n menuTrigger = 'input',\n defaultInputValue,\n inputValue,\n defaultSelectedKey,\n selectedKey,\n onInputChange,\n onSelectionChange,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ): ReactElement => {\n // Warn if no accessible label\n if (process.env.NODE_ENV !== 'production') {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)'\n );\n }\n }\n\n return (\n <AriaComboBox\n ref={ref}\n className={cn(comboboxVariants({ size }), className)}\n isRequired={isRequired}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n name={name}\n allowsCustomValue={allowsCustomValue}\n menuTrigger={menuTrigger}\n defaultInputValue={defaultInputValue}\n inputValue={inputValue}\n defaultSelectedKey={defaultSelectedKey}\n selectedKey={selectedKey}\n onInputChange={onInputChange}\n onSelectionChange={onSelectionChange}\n aria-label={!label ? ariaLabel : undefined}\n aria-labelledby={ariaLabelledBy}\n data-testid={dataTestId}\n {...props}\n >\n {label && (\n <AriaLabel className={comboboxLabelVariants({ size })}>\n {label}\n {isRequired && (\n <span className=\"text-[var(--destructive-background)] ml-1\" aria-hidden=\"true\">\n *\n </span>\n )}\n </AriaLabel>\n )}\n\n <div className={cn(FIELD_TOUCH_TARGET, comboboxTriggerWrapperVariants({ size }))}>\n <AriaInput\n className={comboboxInputVariants({ size })}\n placeholder={placeholder}\n />\n <AriaButton className={comboboxButtonVariants({ size })}>\n <ChevronsUpDown className=\"h-full w-full\" aria-hidden=\"true\" />\n </AriaButton>\n </div>\n\n {description && !errorMessage && (\n <AriaText slot=\"description\" className={comboboxDescriptionVariants({ size })}>\n {description}\n </AriaText>\n )}\n\n {errorMessage && (\n <AriaText slot=\"errorMessage\" className={comboboxErrorVariants({ size })}>\n {errorMessage}\n </AriaText>\n )}\n\n <AriaPopover\n shouldCloseOnInteractOutside={createInteractOutsideGuard()}\n className={comboboxPopoverVariants()}\n >\n <AriaListBox className={comboboxListBoxVariants()}>\n {children}\n </AriaListBox>\n </AriaPopover>\n </AriaComboBox>\n );\n }\n);\n\nCombobox.displayName = 'Combobox';\n\n// ============================================================================\n// ComboboxItem\n// ============================================================================\n\nexport function ComboboxItem({\n children,\n className,\n textValue,\n ...props\n}: ComboboxItemProps): ReactElement {\n // Compute textValue from string children if not explicitly provided\n const computedTextValue = textValue || (typeof children === 'string' ? children : undefined);\n\n return (\n <AriaListBoxItem\n className={cn(comboboxItemVariants({ size: 'default' }), className)}\n textValue={computedTextValue}\n {...props}\n >\n {({ isSelected }) => (\n <>\n <span className=\"flex-1\">{children}</span>\n {isSelected && (\n <Check className=\"h-4 w-4 shrink-0 text-[var(--primary)]\" aria-hidden=\"true\" />\n )}\n </>\n )}\n </AriaListBoxItem>\n );\n}\n\nComboboxItem.displayName = 'ComboboxItem';\n\n// ============================================================================\n// ComboboxSection\n// ============================================================================\n\nexport function ComboboxSection({\n header,\n children,\n className,\n}: ComboboxSectionProps): ReactElement {\n return (\n <AriaListBoxSection className={cn(comboboxSectionVariants(), className)}>\n {header && (\n <AriaHeader className={comboboxSectionHeaderVariants()}>\n {header}\n </AriaHeader>\n )}\n {children}\n </AriaListBoxSection>\n );\n}\n\nComboboxSection.displayName = 'ComboboxSection';\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\nimport type { ComboBoxProps as AriaComboBoxProps } from 'react-aria-components';\n\nexport const ComboboxSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type ComboboxSize = z.infer<typeof ComboboxSizeSchema>;\n\nexport const ComboboxPropsSchema = BaseComponentPropsSchema.extend({\n /** Label text */\n label: z.string().optional(),\n\n /** Description/help text */\n description: z.string().optional(),\n\n /** Error message */\n errorMessage: z.string().optional(),\n\n /** Size variant */\n size: ComboboxSizeSchema.optional().default('default'),\n\n /** Placeholder text */\n placeholder: z.string().optional(),\n\n /** Whether the field is required */\n isRequired: z.boolean().optional(),\n\n /** Whether the field is disabled */\n isDisabled: z.boolean().optional(),\n\n /** Whether the field is read-only */\n isReadOnly: z.boolean().optional(),\n\n /** Field name for form submission */\n name: z.string().optional(),\n\n /** Whether to allow custom values (not in the list) */\n allowsCustomValue: z.boolean().optional().default(false),\n\n /** The menu trigger behavior */\n menuTrigger: z.enum(['input', 'focus', 'manual']).optional().default('input'),\n\n /** Default input value (uncontrolled) */\n defaultInputValue: z.string().optional(),\n\n /** Input value (controlled) */\n inputValue: z.string().optional(),\n\n /** Default selected key (uncontrolled) */\n defaultSelectedKey: z.union([z.string(), z.number()]).optional(),\n\n /** Selected key (controlled) */\n selectedKey: z.union([z.string(), z.number(), z.null()]).optional(),\n});\n\nexport interface ComboboxPropsOwn {\n className?: string;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n label?: string;\n description?: string;\n errorMessage?: string;\n size?: ComboboxSize;\n placeholder?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n name?: string;\n allowsCustomValue?: boolean;\n menuTrigger?: 'input' | 'focus' | 'manual';\n defaultInputValue?: string;\n inputValue?: string;\n defaultSelectedKey?: string | number;\n selectedKey?: string | number | null;\n children: ReactNode;\n onInputChange?: (value: string) => void;\n onSelectionChange?: (key: string | number | null) => void;\n}\n\nexport type ComboboxProps = ComboboxPropsOwn &\n Omit<AriaComboBoxProps<object>, keyof ComboboxPropsOwn>;\n\nexport const ComboboxItemPropsSchema = z.object({\n /** Unique key/value for the item */\n id: z.union([z.string(), z.number()]).optional(),\n /** Text value for filtering */\n textValue: z.string().optional(),\n /** Whether this item is disabled */\n isDisabled: z.boolean().optional(),\n /** Item content */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxItemProps {\n id?: string | number;\n textValue?: string;\n isDisabled?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\nexport const ComboboxSectionPropsSchema = z.object({\n /** Section header text */\n header: z.string().optional(),\n /** Section items */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxSectionProps {\n header?: string;\n children?: ReactNode;\n className?: string;\n}\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/browserExtensionOverlay.ts","../../../src/styles/shared-variants.ts","../../../src/elements/Combobox/Combobox.styles.ts","../../../src/elements/Combobox/Combobox.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Combobox/Combobox.types.ts"],"names":["cn","inputs","twMerge","clsx","isExtensionInjectedElement","element","node","depth","tag","root","custom","parent","createInteractOutsideGuard","consumerShouldClose","TEXT_SIZE_SMALL_SCALE","FIELD_HEIGHTS","FIELD_INPUT_SIZES","FIELD_TOUCH_TARGET","comboboxVariants","cva","comboboxLabelVariants","comboboxInputVariants","comboboxTriggerWrapperVariants","comboboxButtonVariants","comboboxPopoverVariants","comboboxListBoxVariants","comboboxItemVariants","comboboxSectionVariants","comboboxSectionHeaderVariants","comboboxDescriptionVariants","comboboxErrorVariants","Combobox","forwardRef","className","size","label","description","errorMessage","isRequired","isDisabled","isReadOnly","placeholder","name","allowsCustomValue","menuTrigger","defaultInputValue","inputValue","defaultSelectedKey","selectedKey","onInputChange","onSelectionChange","children","ariaLabel","ariaLabelledBy","dataTestId","props","ref","jsxs","AriaComboBox","AriaLabel","jsx","AriaInput","AriaButton","ChevronsUpDown","AriaText","AriaPopover","AriaListBox","ComboboxItem","textValue","computedTextValue","AriaListBoxItem","isSelected","Fragment","Check","ComboboxSection","header","AriaListBoxSection","AriaHeader","BaseComponentPropsSchema","z","ComboboxSizeSchema","ComboboxPropsSchema","ComboboxItemPropsSchema","ComboboxSectionPropsSchema"],"mappings":"oXAcO,SAASA,CAAAA,CAAAA,GAAMC,CAAAA,CAA8B,CAClD,OAAOC,OAAAA,CAAQC,KAAKF,CAAM,CAAC,CAC7B,CCWO,SAASG,EAAAA,CAA2BC,CAAAA,CAA2B,CACpE,GAAI,EAAEA,CAAAA,YAAmB,OAAA,CAAA,CAAU,OAAO,MAAA,CAU1C,IAAIC,CAAAA,CAAuBD,EAC3B,IAAA,IAASE,CAAAA,CAAQ,CAAA,CAAGD,CAAAA,EAAQC,CAAAA,CAAQ,GAAA,CAAoBA,CAAAA,EAAAA,CAAS,CAC/D,IAAMC,CAAAA,CAAMF,CAAAA,CAAK,OAAA,EAAS,WAAA,EAAY,EAAK,EAAA,CAG3C,GAFIE,EAAI,UAAA,CAAW,YAAY,CAAA,EAC3BA,CAAAA,CAAI,UAAA,CAAW,KAAK,CAAA,EACpBF,CAAAA,CAAK,YAAA,CAAa,4BAA4B,CAAA,CAAG,OAAO,KAAA,CAE5D,GAAIA,CAAAA,CAAK,aAAA,CACPA,EAAOA,CAAAA,CAAK,aAAA,CAAA,KACP,CACL,IAAMG,CAAAA,CAAOH,CAAAA,CAAK,WAAA,EAAY,CAC9BA,CAAAA,CAAOG,CAAAA,YAAgB,UAAA,CAAaA,CAAAA,CAAK,IAAA,CAAO,KAClD,CACF,CAQA,IAAIC,CAAAA,CAAyBL,CAAAA,CAC7B,KAAOK,CAAAA,EAAU,CAACA,CAAAA,CAAO,OAAA,CAAQ,QAAA,CAAS,GAAG,CAAA,EAC3CA,CAAAA,CAASA,CAAAA,CAAO,aAAA,CAElB,GAAI,CAACA,CAAAA,CAAQ,OAAO,MAAA,CAEpB,IAAMC,CAAAA,CAASD,CAAAA,CAAO,aAAA,CACtB,OAAOC,CAAAA,GAAW,QAAA,CAAS,IAAA,EAAQA,CAAAA,GAAW,QAAA,CAAS,eACzD,CAWO,SAASC,CAAAA,CACdC,CAAAA,CAC+B,CAC/B,OAAQR,CAAAA,EACN,CAACD,EAAAA,CAA2BC,CAAO,CAAA,GAAMQ,CAAAA,GAAsBR,CAAO,CAAA,EAAK,IAAA,CAC/E,CCDO,IAAMS,CAAAA,CAAwB,CACnC,EAAA,CAAI,UACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,WACN,CAAA,CAmCO,IAAMC,CAAAA,CAAgB,CAC3B,EAAA,CAAI,KAAA,CACJ,OAAA,CAAS,MAAA,CACT,EAAA,CAAI,MACN,CAAA,CAQaC,CAAAA,CAAoB,CAC/B,EAAA,CAAI,CAAA,EAAGD,CAAAA,CAAc,EAAE,CAAA,aAAA,CAAA,CACvB,OAAA,CAAS,CAAA,EAAGA,CAAAA,CAAc,OAAO,CAAA,aAAA,CAAA,CACjC,EAAA,CAAI,CAAA,EAAGA,CAAAA,CAAc,EAAE,CAAA,eAAA,CACzB,CAAA,CASaE,EAAqB,gCAAA,CC/I3B,IAAMC,CAAAA,CAAmBC,GAAAA,CAC9B,oCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,EAAA,CACJ,QAAS,EAAA,CACT,EAAA,CAAI,EACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaC,CAAAA,CAAwBD,GAAAA,CACnC,wCAAA,CACA,CACE,SAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,SAAA,CACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,WACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaE,CAAAA,CAAwBF,GAAAA,CACnC,CACE,oCAAA,CACA,4CAAA,CACA,6BACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAML,CACR,CAAA,CACA,eAAA,CAAiB,CAAE,KAAM,SAAU,CACrC,CACF,CAAA,CAEaQ,CAAAA,CAAiCH,GAAAA,CAC5C,CACE,4CAAA,CACA,+DAAA,CACA,8BAAA,CACA,qDAAA,CACA,mGAAA,CACA,+DAAA,CACA,uDACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,CAAA,EAAGH,CAAAA,CAAkB,EAAE,CAAA,MAAA,CAAA,CAC3B,OAAA,CAAS,CAAA,EAAGA,CAAAA,CAAkB,OAAO,CAAA,MAAA,CAAA,CACrC,EAAA,CAAI,CAAA,EAAGA,EAAkB,EAAE,CAAA,MAAA,CAC7B,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaO,CAAAA,CAAyBJ,GAAAA,CACpC,CACE,wCAAA,CACA,gCAAA,CACA,mCACA,mBAAA,CACA,oBACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,mCAAA,CACJ,OAAA,CAAS,mCAAA,CACT,EAAA,CAAI,mCACN,CACF,CAAA,CACA,gBAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaK,CAAAA,CAA0BL,GAAAA,CACrC,CACE,wCAAA,CACA,0CAAA,CACA,iEAAA,CACA,8EAAA,CACA,8EACF,CACF,CAAA,CAEaM,EAA0BN,GAAAA,CACrC,8CACF,CAAA,CAEaO,CAAAA,CAAuBP,GAAAA,CAClC,CACE,uDAAA,CACA,kCAAA,CACA,6BAAA,CACA,6FAAA,CACA,6BAAA,CACA,+DACF,CAAA,CACA,CACE,QAAA,CAAU,CACR,KAAM,CACJ,EAAA,CAAI,sBAAA,CACJ,OAAA,CAAS,sBAAA,CACT,EAAA,CAAI,wBACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaQ,EAA0BR,GAAAA,CAAI,MAAM,CAAA,CAEpCS,CAAAA,CAAgCT,GAAAA,CAC3C,kEACF,CAAA,CAEaU,CAAAA,CAA8BV,GAAAA,CACzC,gCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,UACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,SACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,CAAA,CAEaW,CAAAA,CAAwBX,GAAAA,CACnC,sCAAA,CACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CACJ,EAAA,CAAI,SAAA,CACJ,OAAA,CAAS,SAAA,CACT,EAAA,CAAI,SACN,CACF,CAAA,CACA,eAAA,CAAiB,CAAE,IAAA,CAAM,SAAU,CACrC,CACF,EChGO,IAAMY,CAAAA,CAAWC,UAAAA,CACtB,CACE,CACE,UAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CAAO,SAAA,CACP,KAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,CAAAA,CACA,YAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,YAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CAAoB,KAAA,CACpB,WAAA,CAAAC,CAAAA,CAAc,OAAA,CACd,iBAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,kBAAA,CAAAC,CAAAA,CACA,WAAA,CAAAC,EACA,aAAA,CAAAC,CAAAA,CACA,iBAAA,CAAAC,CAAAA,CACA,QAAA,CAAAC,CAAAA,CACA,YAAA,CAAcC,CAAAA,CACd,iBAAA,CAAmBC,CAAAA,CACnB,aAAA,CAAeC,CAAAA,CACf,GAAGC,CACL,CAAA,CACAC,CAAAA,IAGI,QAAQ,GAAA,CAAI,QAAA,GAAa,YAAA,EACvB,CAACrB,CAAAA,EAAS,CAACiB,CAAAA,EAAa,CAACC,CAAAA,EAC3B,OAAA,CAAQ,IAAA,CACN,oGACF,CAAA,CAKFI,IAAAA,CAACC,QAAAA,CAAA,CACC,IAAKF,CAAAA,CACL,SAAA,CAAWxD,CAAAA,CAAGkB,CAAAA,CAAiB,CAAE,IAAA,CAAAgB,CAAK,CAAC,CAAA,CAAGD,CAAS,CAAA,CACnD,UAAA,CAAYK,CAAAA,CACZ,UAAA,CAAYC,CAAAA,CACZ,UAAA,CAAYC,EACZ,IAAA,CAAME,CAAAA,CACN,iBAAA,CAAmBC,CAAAA,CACnB,WAAA,CAAaC,CAAAA,CACb,iBAAA,CAAmBC,CAAAA,CACnB,UAAA,CAAYC,CAAAA,CACZ,kBAAA,CAAoBC,CAAAA,CACpB,WAAA,CAAaC,CAAAA,CACb,aAAA,CAAeC,CAAAA,CACf,iBAAA,CAAmBC,CAAAA,CACnB,YAAA,CAAaf,CAAAA,CAAoB,MAAA,CAAZiB,CAAAA,CACrB,iBAAA,CAAiBC,CAAAA,CACjB,aAAA,CAAaC,CAAAA,CACZ,GAAGC,CAAAA,CAEH,QAAA,CAAA,CAAApB,CAAAA,EACCsB,IAAAA,CAACE,KAAAA,CAAA,CAAU,SAAA,CAAWvC,CAAAA,CAAsB,CAAE,IAAA,CAAAc,CAAK,CAAC,CAAA,CACjD,QAAA,CAAA,CAAAC,CAAAA,CACAG,CAAAA,EACCsB,GAAAA,CAAC,MAAA,CAAA,CAAK,SAAA,CAAU,2CAAA,CAA4C,aAAA,CAAY,MAAA,CAAO,aAE/E,CAAA,CAAA,CAEJ,CAAA,CAGFH,IAAAA,CAAC,KAAA,CAAA,CAAI,SAAA,CAAWzD,CAAAA,CAAGiB,CAAAA,CAAoBK,CAAAA,CAA+B,CAAE,IAAA,CAAAY,CAAK,CAAC,CAAC,CAAA,CAC7E,QAAA,CAAA,CAAA0B,GAAAA,CAACC,MAAA,CACC,SAAA,CAAWxC,CAAAA,CAAsB,CAAE,IAAA,CAAAa,CAAK,CAAC,CAAA,CACzC,WAAA,CAAaO,CAAAA,CACf,CAAA,CACAmB,GAAAA,CAACE,MAAAA,CAAA,CAAW,SAAA,CAAWvC,CAAAA,CAAuB,CAAE,IAAA,CAAAW,CAAK,CAAC,CAAA,CACpD,QAAA,CAAA0B,GAAAA,CAACG,cAAAA,CAAA,CAAe,SAAA,CAAU,SAAA,CAAU,WAAA,CAAa,GAAA,CAAK,aAAA,CAAY,MAAA,CAAO,CAAA,CAC3E,CAAA,CAAA,CACF,EAEC3B,CAAAA,EAAe,CAACC,CAAAA,EACfuB,GAAAA,CAACI,IAAAA,CAAA,CAAS,IAAA,CAAK,aAAA,CAAc,SAAA,CAAWnC,CAAAA,CAA4B,CAAE,IAAA,CAAAK,CAAK,CAAC,CAAA,CACzE,QAAA,CAAAE,EACH,CAAA,CAGDC,CAAAA,EACCuB,GAAAA,CAACI,IAAAA,CAAA,CAAS,IAAA,CAAK,cAAA,CAAe,SAAA,CAAWlC,CAAAA,CAAsB,CAAE,IAAA,CAAAI,CAAK,CAAC,CAAA,CACpE,QAAA,CAAAG,CAAAA,CACH,EAGFuB,GAAAA,CAACK,OAAAA,CAAA,CACC,4BAAA,CAA8BrD,CAAAA,EAA2B,CACzD,SAAA,CAAWY,CAAAA,EAAwB,CAEnC,QAAA,CAAAoC,GAAAA,CAACM,OAAAA,CAAA,CAAY,SAAA,CAAWzC,CAAAA,EAAwB,CAC7C,QAAA,CAAA0B,CAAAA,CACH,CAAA,CACF,CAAA,CAAA,CACF,CAAA,CAGN,EAEApB,CAAAA,CAAS,WAAA,CAAc,UAAA,CAMhB,SAASoC,CAAAA,CAAa,CAC3B,QAAA,CAAAhB,CAAAA,CACA,SAAA,CAAAlB,CAAAA,CACA,UAAAmC,CAAAA,CACA,GAAGb,CACL,CAAA,CAAoC,CAElC,IAAMc,CAAAA,CAAoBD,CAAAA,GAAc,OAAOjB,CAAAA,EAAa,QAAA,CAAWA,CAAAA,CAAW,MAAA,CAAA,CAElF,OACES,GAAAA,CAACU,WAAAA,CAAA,CACC,SAAA,CAAWtE,CAAAA,CAAG0B,CAAAA,CAAqB,CAAE,IAAA,CAAM,SAAU,CAAC,CAAA,CAAGO,CAAS,CAAA,CAClE,SAAA,CAAWoC,CAAAA,CACV,GAAGd,CAAAA,CAEH,QAAA,CAAA,CAAC,CAAE,WAAAgB,CAAW,CAAA,GACbd,IAAAA,CAAAe,QAAAA,CAAA,CACE,QAAA,CAAA,CAAAZ,GAAAA,CAAC,MAAA,CAAA,CAAK,SAAA,CAAU,QAAA,CAAU,QAAA,CAAAT,CAAAA,CAAS,CAAA,CAClCoB,CAAAA,EACCX,GAAAA,CAACa,KAAAA,CAAA,CAAM,SAAA,CAAU,wCAAA,CAAyC,aAAA,CAAY,MAAA,CAAO,CAAA,CAAA,CAEjF,CAAA,CAEJ,CAEJ,CAEAN,CAAAA,CAAa,WAAA,CAAc,cAAA,CAMpB,SAASO,CAAAA,CAAgB,CAC9B,MAAA,CAAAC,CAAAA,CACA,SAAAxB,CAAAA,CACA,SAAA,CAAAlB,CACF,CAAA,CAAuC,CACrC,OACEwB,IAAAA,CAACmB,cAAAA,CAAA,CAAmB,SAAA,CAAW5E,CAAAA,CAAG2B,CAAAA,EAAwB,CAAGM,CAAS,CAAA,CACnE,QAAA,CAAA,CAAA0C,GACCf,GAAAA,CAACiB,MAAAA,CAAA,CAAW,SAAA,CAAWjD,CAAAA,EAA8B,CAClD,QAAA,CAAA+C,CAAAA,CACH,CAAA,CAEDxB,CAAAA,CAAAA,CACH,CAEJ,CAEAuB,CAAAA,CAAgB,WAAA,CAAc,iBAAA,CClNvB,IAAMI,CAAAA,CAA2BC,CAAAA,CAAE,MAAA,CAAO,CAE/C,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG/B,QAAA,CAAUA,CAAAA,CAAE,GAAA,EAAI,CAAE,QAAA,EAAS,CAC3B,EAAA,CAAIA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGxB,YAAA,CAAcA,CAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAClC,iBAAA,CAAmBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CACvC,kBAAA,CAAoBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CACxC,WAAA,CAAaA,CAAAA,CAAE,KAAK,CAAC,KAAA,CAAO,QAAA,CAAU,WAAW,CAAC,CAAA,CAAE,QAAA,EAAS,CAC7D,aAAA,CAAeA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGpC,aAAA,CAAeA,CAAAA,CAAE,QAAO,CAAE,QAAA,EAC5B,CAAC,CAAA,CCrBM,IAAMC,CAAAA,CAAqBD,CAAAA,CAAE,IAAA,CAAK,CAAC,IAAA,CAAM,SAAA,CAAW,IAAI,CAAC,CAAA,CAGnDE,EAAAA,CAAsBH,EAAyB,MAAA,CAAO,CAEjE,KAAA,CAAOC,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG3B,WAAA,CAAaA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGjC,YAAA,CAAcA,CAAAA,CAAE,QAAO,CAAE,QAAA,EAAS,CAGlC,IAAA,CAAMC,CAAAA,CAAmB,QAAA,EAAS,CAAE,OAAA,CAAQ,SAAS,CAAA,CAGrD,WAAA,CAAaD,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGjC,WAAYA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGjC,UAAA,CAAYA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGjC,UAAA,CAAYA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,GAGxB,IAAA,CAAMA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG1B,iBAAA,CAAmBA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,KAAK,CAAA,CAGvD,WAAA,CAAaA,EAAE,IAAA,CAAK,CAAC,OAAA,CAAS,OAAA,CAAS,QAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAAE,OAAA,CAAQ,OAAO,CAAA,CAG5E,iBAAA,CAAmBA,CAAAA,CAAE,MAAA,EAAO,CAAE,UAAS,CAGvC,UAAA,CAAYA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGhC,kBAAA,CAAoBA,CAAAA,CAAE,KAAA,CAAM,CAACA,CAAAA,CAAE,MAAA,EAAO,CAAGA,CAAAA,CAAE,MAAA,EAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAG/D,WAAA,CAAaA,CAAAA,CAAE,KAAA,CAAM,CAACA,CAAAA,CAAE,MAAA,EAAO,CAAGA,CAAAA,CAAE,MAAA,EAAO,CAAGA,CAAAA,CAAE,IAAA,EAAM,CAAC,CAAA,CAAE,QAAA,EAC3D,CAAC,CAAA,CAkCYG,EAAAA,CAA0BH,CAAAA,CAAE,MAAA,CAAO,CAE9C,EAAA,CAAIA,CAAAA,CAAE,KAAA,CAAM,CAACA,CAAAA,CAAE,MAAA,GAAUA,CAAAA,CAAE,MAAA,EAAQ,CAAC,CAAA,CAAE,QAAA,EAAS,CAE/C,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAE/B,UAAA,CAAYA,CAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAEjC,QAAA,CAAUA,CAAAA,CAAE,MAAA,EAAkB,CAC9B,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EACxB,CAAC,CAAA,CAUYI,EAAAA,CAA6BJ,CAAAA,CAAE,OAAO,CAEjD,MAAA,CAAQA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAE5B,QAAA,CAAUA,CAAAA,CAAE,MAAA,EAAkB,CAC9B,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EACxB,CAAC","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","/**\n * Shared CVA Variant Utilities\n *\n * Common patterns extracted from component variants for consistency and reduced bundle size.\n * Use these constants in CVA definitions to ensure consistent styling across Themis.\n *\n * @see interaction-states.ts for interaction-specific styles (focus, hover, pressed)\n */\n\n// =============================================================================\n// Focus Ring Patterns\n// =============================================================================\n\n/**\n * Focus-within ring (for container elements with focusable children)\n * Use when the container should show focus when any child is focused\n */\nexport const FOCUS_WITHIN_RING = [\n 'focus-within:outline-none',\n 'focus-within:ring-2',\n 'focus-within:ring-[var(--ring)]',\n 'focus-within:ring-offset-2',\n] as const;\n\n/**\n * Focus-visible ring (for directly focusable elements)\n * Use for buttons, inputs, and other interactive elements\n */\nexport const FOCUS_VISIBLE_RING = [\n 'focus-visible:outline-none',\n 'focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)]',\n 'focus-visible:ring-offset-2',\n] as const;\n\n/**\n * Standard focus ring (for elements using :focus pseudo-class)\n * Prefer focus-visible when possible for better UX\n */\nexport const FOCUS_RING = [\n 'focus:outline-none',\n 'focus:ring-2',\n 'focus:ring-[var(--ring)]',\n] as const;\n\n/**\n * Focus with background change (for segments, cells, menu items)\n */\nexport const FOCUS_HIGHLIGHT = [\n 'focus:outline-none',\n 'focus:bg-[var(--accent)]',\n 'focus:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Disabled State Patterns\n// =============================================================================\n\n/**\n * Standard disabled state using disabled attribute\n */\nexport const DISABLED_STANDARD = [\n 'disabled:pointer-events-none',\n 'disabled:opacity-50',\n] as const;\n\n/**\n * Disabled state using data attribute (React Aria pattern)\n */\nexport const DISABLED_DATA_ATTR = [\n 'data-[disabled]:pointer-events-none',\n 'data-[disabled]:opacity-50',\n 'data-[disabled]:cursor-not-allowed',\n] as const;\n\n// =============================================================================\n// Size-Based Text Variants\n// =============================================================================\n\n/**\n * Small text size scale (xs -> sm -> base)\n */\nexport const TEXT_SIZE_SMALL_SCALE = {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n} as const;\n\n/**\n * Medium text size scale (sm -> base -> lg)\n */\nexport const TEXT_SIZE_MEDIUM_SCALE = {\n sm: 'text-sm',\n default: 'text-base',\n lg: 'text-lg',\n} as const;\n\n// =============================================================================\n// Touch Target Utilities\n// =============================================================================\n\n/**\n * WCAG 2.2 AAA minimum touch target (44x44px)\n */\nexport const TOUCH_TARGET_MIN = [\n 'min-h-[44px]',\n 'min-w-[44px]',\n] as const;\n\n/**\n * Common button/cell sizes with touch target compliance\n */\nexport const INTERACTIVE_SIZES = {\n sm: 'h-9 w-9', // 36px - desktop only, NOT AAA compliant\n default: 'h-11 w-11', // 44px - AAA compliant\n lg: 'h-14 w-14', // 56px - AAA compliant, enhanced\n} as const;\n\n/**\n * Height-only sizes for fields and inputs\n */\nexport const FIELD_HEIGHTS = {\n sm: 'h-9', // 36px\n default: 'h-10', // 40px\n lg: 'h-11', // 44px\n} as const;\n\n/**\n * Layer 2: Visual sizing for form field inputs (height + padding + font).\n * Use on the <input>, <select>, or trigger element itself.\n *\n * Components may append additional classes (e.g. gap-* for segmented fields, py-* for text inputs).\n */\nexport const FIELD_INPUT_SIZES = {\n sm: `${FIELD_HEIGHTS.sm} px-2 text-xs`,\n default: `${FIELD_HEIGHTS.default} px-3 text-sm`,\n lg: `${FIELD_HEIGHTS.lg} px-4 text-base`,\n} as const;\n\n/**\n * Layer 1: Invisible touch target wrapper for form fields.\n * Apply to a <label> (or wrapper div) around the input element.\n * The <label> natively routes clicks/taps to the contained input\n * without JavaScript — achieving a 44px touch target while the\n * input stays at its visual height (h-9/h-10/h-11).\n */\nexport const FIELD_TOUCH_TARGET = 'min-h-[44px] flex items-center' as const;\n\n// =============================================================================\n// Message/Feedback Patterns\n// =============================================================================\n\n/**\n * Error message styling\n */\nexport const ERROR_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--destructive-background)]',\n] as const;\n\n/**\n * Success message styling\n */\nexport const SUCCESS_MESSAGE_BASE = [\n 'flex',\n 'items-center',\n 'gap-1.5',\n 'text-[var(--success-background)]',\n] as const;\n\n/**\n * Description/helper text styling\n */\nexport const DESCRIPTION_BASE = [\n 'text-[var(--menu-muted)]',\n] as const;\n\n/**\n * Label base styling\n */\nexport const LABEL_BASE = [\n 'font-medium',\n 'text-[var(--content-foreground)]',\n] as const;\n\n/**\n * Required indicator pattern\n */\nexport const REQUIRED_INDICATOR = \"after:content-['*'] after:ml-0.5 after:text-[var(--destructive-background)]\";\n\n// =============================================================================\n// Animation Patterns\n// =============================================================================\n\n/**\n * Popover/dropdown entry animation\n */\nexport const POPOVER_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n] as const;\n\n/**\n * Popover/dropdown exit animation\n */\nexport const POPOVER_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n] as const;\n\n/**\n * Modal content enter animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:zoom-in-95',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal content exit animation (fade + zoom)\n * Uses React Aria data-[entering]/data-[exiting] attributes\n */\nexport const MODAL_ANIMATION_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:zoom-out-95',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal slide enter animation (fade + slide up)\n */\nexport const MODAL_SLIDE_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:slide-in-from-bottom-4',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\n/**\n * Modal slide exit animation (fade + slide down)\n */\nexport const MODAL_SLIDE_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:slide-out-to-bottom-4',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Directional slide animations for edge-anchored drawers (Modal `position` variant).\n *\n * Unitless `slide-in-from-*` / `slide-out-to-*` translate the full extent of the\n * element (100%), so the drawer slides all the way in from / out to its anchored\n * edge — distinct from `MODAL_SLIDE_*` above, which is the small 1rem nudge used by\n * the centred `slide` animation. No `fade` is paired here: a drawer slides, it\n * does not fade. Honour `prefers-reduced-motion` via REDUCED_MOTION on the element.\n */\nexport const MODAL_SLIDE_IN_LEFT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-left',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_LEFT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-left',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_RIGHT = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-right',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_RIGHT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-right',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_TOP = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-top',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_TOP = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-top',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\nexport const MODAL_SLIDE_IN_BOTTOM = [\n 'data-[entering]:animate-in',\n 'data-[entering]:slide-in-from-bottom',\n 'data-[entering]:duration-200',\n 'data-[entering]:ease-out',\n] as const;\n\nexport const MODAL_SLIDE_OUT_BOTTOM = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:slide-out-to-bottom',\n 'data-[exiting]:duration-150',\n 'data-[exiting]:ease-in',\n] as const;\n\n/**\n * Modal overlay enter/exit animation (fade only)\n */\nexport const MODAL_OVERLAY_IN = [\n 'data-[entering]:animate-in',\n 'data-[entering]:fade-in-0',\n 'data-[entering]:duration-200',\n] as const;\n\nexport const MODAL_OVERLAY_OUT = [\n 'data-[exiting]:animate-out',\n 'data-[exiting]:fade-out-0',\n 'data-[exiting]:duration-150',\n] as const;\n\n/**\n * Reduced motion support (WCAG 2.2)\n */\nexport const REDUCED_MOTION = [\n 'motion-reduce:transition-none',\n 'motion-reduce:animate-none',\n] as const;\n\n/**\n * Standard transition for colors\n */\nexport const TRANSITION_COLORS = [\n 'transition-colors',\n 'duration-200',\n] as const;\n\n/**\n * Fast transition for interactions\n */\nexport const TRANSITION_FAST = [\n 'transition-colors',\n 'duration-150',\n] as const;\n\n// =============================================================================\n// Hover State Patterns\n// =============================================================================\n\n/**\n * Accent background on hover (for interactive items)\n */\nexport const HOVER_ACCENT = [\n 'hover:bg-[var(--accent)]',\n 'hover:text-[var(--accent-foreground)]',\n] as const;\n\n// =============================================================================\n// Helper Functions\n// =============================================================================\n\n/**\n * Combines multiple style arrays into a flat array for CVA base styles\n */\nexport function combineStyles(...styles: (readonly string[] | string)[]): string[] {\n return styles.flatMap(s => Array.isArray(s) ? [...s] : [s]);\n}\n","import { cva } from 'class-variance-authority';\nimport { FIELD_INPUT_SIZES, TEXT_SIZE_SMALL_SCALE } from '../../styles';\n\nexport const comboboxVariants = cva(\n 'group flex flex-col gap-1.5 w-full',\n {\n variants: {\n size: {\n sm: '',\n default: '',\n lg: '',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxLabelVariants = cva(\n 'text-[var(--text-primary)] font-medium',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxInputVariants = cva(\n [\n 'flex-1 bg-transparent outline-none',\n 'placeholder:text-[var(--muted-foreground)]',\n 'disabled:cursor-not-allowed',\n ],\n {\n variants: {\n size: TEXT_SIZE_SMALL_SCALE,\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxTriggerWrapperVariants = cva(\n [\n 'flex items-center w-full rounded-md border',\n 'bg-[var(--input-background)] text-[var(--content-foreground)]',\n 'border-[var(--input-border)]',\n 'transition-colors duration-[var(--transition-fast)]',\n 'focus-within:ring-2 focus-within:ring-[var(--ring)] focus-within:ring-offset-[var(--ring-offset)]',\n 'data-[disabled]:cursor-not-allowed data-[disabled]:opacity-50',\n 'data-[invalid]:border-[var(--destructive-background)]',\n ],\n {\n variants: {\n size: {\n sm: `${FIELD_INPUT_SIZES.sm} gap-1`,\n default: `${FIELD_INPUT_SIZES.default} gap-2`,\n lg: `${FIELD_INPUT_SIZES.lg} gap-2`,\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxButtonVariants = cva(\n [\n 'flex items-center justify-end shrink-0',\n 'text-[var(--muted-foreground)]',\n 'hover:text-[var(--text-primary)]',\n 'transition-colors',\n 'focus:outline-none',\n ],\n {\n variants: {\n size: {\n sm: 'h-4 w-4 min-h-[44px] min-w-[44px]',\n default: 'h-5 w-5 min-h-[44px] min-w-[44px]',\n lg: 'h-6 w-6 min-h-[44px] min-w-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxPopoverVariants = cva(\n [\n 'w-[var(--trigger-width)] overflow-auto',\n 'rounded-md border border-[var(--border)]',\n 'bg-[var(--content-background)] text-[var(--content-foreground)]',\n 'data-[entering]:motion-safe:animate-in data-[entering]:motion-safe:fade-in-0',\n 'data-[exiting]:motion-safe:animate-out data-[exiting]:motion-safe:fade-out-0',\n ]\n);\n\nexport const comboboxListBoxVariants = cva(\n 'p-1 outline-none max-h-[300px] overflow-auto'\n);\n\nexport const comboboxItemVariants = cva(\n [\n 'flex items-center gap-2 w-full rounded-sm px-2 py-1.5',\n 'text-[var(--content-foreground)]',\n 'cursor-pointer outline-none',\n 'data-[focused]:bg-[var(--accent-background)] data-[focused]:text-[var(--accent-foreground)]',\n 'data-[selected]:font-medium',\n 'data-[disabled]:opacity-50 data-[disabled]:cursor-not-allowed',\n ],\n {\n variants: {\n size: {\n sm: 'text-xs min-h-[44px]',\n default: 'text-sm min-h-[44px]',\n lg: 'text-base min-h-[44px]',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxSectionVariants = cva('pt-1');\n\nexport const comboboxSectionHeaderVariants = cva(\n 'px-2 py-1.5 text-xs font-semibold text-[var(--muted-foreground)]'\n);\n\nexport const comboboxDescriptionVariants = cva(\n 'text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const comboboxErrorVariants = cva(\n 'text-[var(--destructive-background)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-xs',\n lg: 'text-sm',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n","'use client';\n\nimport { forwardRef, type ReactElement } from 'react';\nimport {\n ComboBox as AriaComboBox,\n Label as AriaLabel,\n Input as AriaInput,\n Button as AriaButton,\n Popover as AriaPopover,\n ListBox as AriaListBox,\n ListBoxItem as AriaListBoxItem,\n ListBoxSection as AriaListBoxSection,\n Header as AriaHeader,\n Text as AriaText,\n} from 'react-aria-components';\nimport { ChevronsUpDown, Check } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { createInteractOutsideGuard } from '../../utils/browserExtensionOverlay';\nimport { FIELD_TOUCH_TARGET } from '../../styles';\nimport type {\n ComboboxProps,\n ComboboxItemProps,\n ComboboxSectionProps,\n} from './Combobox.types';\nimport {\n comboboxVariants,\n comboboxLabelVariants,\n comboboxInputVariants,\n comboboxTriggerWrapperVariants,\n comboboxButtonVariants,\n comboboxPopoverVariants,\n comboboxListBoxVariants,\n comboboxItemVariants,\n comboboxSectionVariants,\n comboboxSectionHeaderVariants,\n comboboxDescriptionVariants,\n comboboxErrorVariants,\n} from './Combobox.styles';\n\n// ============================================================================\n// Combobox\n// ============================================================================\n\n/**\n * Combobox Component\n *\n * A filterable select/autocomplete component built on React Aria's ComboBox.\n * Supports type-to-filter, keyboard navigation, and optional custom values.\n *\n * @example\n * ```tsx\n * <Combobox label=\"Framework\">\n * <ComboboxItem id=\"react\">React</ComboboxItem>\n * <ComboboxItem id=\"vue\">Vue</ComboboxItem>\n * <ComboboxItem id=\"angular\">Angular</ComboboxItem>\n * </Combobox>\n * ```\n */\nexport const Combobox = forwardRef<HTMLDivElement, ComboboxProps>(\n (\n {\n className,\n size = 'default',\n label,\n description,\n errorMessage,\n isRequired,\n isDisabled,\n isReadOnly,\n placeholder,\n name,\n allowsCustomValue = false,\n menuTrigger = 'input',\n defaultInputValue,\n inputValue,\n defaultSelectedKey,\n selectedKey,\n onInputChange,\n onSelectionChange,\n children,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ): ReactElement => {\n // Warn if no accessible label\n if (process.env.NODE_ENV !== 'production') {\n if (!label && !ariaLabel && !ariaLabelledBy) {\n console.warn(\n '[Combobox] Either label, aria-label, or aria-labelledby is required for accessibility (WCAG 1.1.1)'\n );\n }\n }\n\n return (\n <AriaComboBox\n ref={ref}\n className={cn(comboboxVariants({ size }), className)}\n isRequired={isRequired}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n name={name}\n allowsCustomValue={allowsCustomValue}\n menuTrigger={menuTrigger}\n defaultInputValue={defaultInputValue}\n inputValue={inputValue}\n defaultSelectedKey={defaultSelectedKey}\n selectedKey={selectedKey}\n onInputChange={onInputChange}\n onSelectionChange={onSelectionChange}\n aria-label={!label ? ariaLabel : undefined}\n aria-labelledby={ariaLabelledBy}\n data-testid={dataTestId}\n {...props}\n >\n {label && (\n <AriaLabel className={comboboxLabelVariants({ size })}>\n {label}\n {isRequired && (\n <span className=\"text-[var(--destructive-background)] ml-1\" aria-hidden=\"true\">\n *\n </span>\n )}\n </AriaLabel>\n )}\n\n <div className={cn(FIELD_TOUCH_TARGET, comboboxTriggerWrapperVariants({ size }))}>\n <AriaInput\n className={comboboxInputVariants({ size })}\n placeholder={placeholder}\n />\n <AriaButton className={comboboxButtonVariants({ size })}>\n <ChevronsUpDown className=\"h-4 w-4\" strokeWidth={1.5} aria-hidden=\"true\" />\n </AriaButton>\n </div>\n\n {description && !errorMessage && (\n <AriaText slot=\"description\" className={comboboxDescriptionVariants({ size })}>\n {description}\n </AriaText>\n )}\n\n {errorMessage && (\n <AriaText slot=\"errorMessage\" className={comboboxErrorVariants({ size })}>\n {errorMessage}\n </AriaText>\n )}\n\n <AriaPopover\n shouldCloseOnInteractOutside={createInteractOutsideGuard()}\n className={comboboxPopoverVariants()}\n >\n <AriaListBox className={comboboxListBoxVariants()}>\n {children}\n </AriaListBox>\n </AriaPopover>\n </AriaComboBox>\n );\n }\n);\n\nCombobox.displayName = 'Combobox';\n\n// ============================================================================\n// ComboboxItem\n// ============================================================================\n\nexport function ComboboxItem({\n children,\n className,\n textValue,\n ...props\n}: ComboboxItemProps): ReactElement {\n // Compute textValue from string children if not explicitly provided\n const computedTextValue = textValue || (typeof children === 'string' ? children : undefined);\n\n return (\n <AriaListBoxItem\n className={cn(comboboxItemVariants({ size: 'default' }), className)}\n textValue={computedTextValue}\n {...props}\n >\n {({ isSelected }) => (\n <>\n <span className=\"flex-1\">{children}</span>\n {isSelected && (\n <Check className=\"h-4 w-4 shrink-0 text-[var(--primary)]\" aria-hidden=\"true\" />\n )}\n </>\n )}\n </AriaListBoxItem>\n );\n}\n\nComboboxItem.displayName = 'ComboboxItem';\n\n// ============================================================================\n// ComboboxSection\n// ============================================================================\n\nexport function ComboboxSection({\n header,\n children,\n className,\n}: ComboboxSectionProps): ReactElement {\n return (\n <AriaListBoxSection className={cn(comboboxSectionVariants(), className)}>\n {header && (\n <AriaHeader className={comboboxSectionHeaderVariants()}>\n {header}\n </AriaHeader>\n )}\n {children}\n </AriaListBoxSection>\n );\n}\n\nComboboxSection.displayName = 'ComboboxSection';\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode } from 'react';\nimport type { ComboBoxProps as AriaComboBoxProps } from 'react-aria-components';\n\nexport const ComboboxSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type ComboboxSize = z.infer<typeof ComboboxSizeSchema>;\n\nexport const ComboboxPropsSchema = BaseComponentPropsSchema.extend({\n /** Label text */\n label: z.string().optional(),\n\n /** Description/help text */\n description: z.string().optional(),\n\n /** Error message */\n errorMessage: z.string().optional(),\n\n /** Size variant */\n size: ComboboxSizeSchema.optional().default('default'),\n\n /** Placeholder text */\n placeholder: z.string().optional(),\n\n /** Whether the field is required */\n isRequired: z.boolean().optional(),\n\n /** Whether the field is disabled */\n isDisabled: z.boolean().optional(),\n\n /** Whether the field is read-only */\n isReadOnly: z.boolean().optional(),\n\n /** Field name for form submission */\n name: z.string().optional(),\n\n /** Whether to allow custom values (not in the list) */\n allowsCustomValue: z.boolean().optional().default(false),\n\n /** The menu trigger behavior */\n menuTrigger: z.enum(['input', 'focus', 'manual']).optional().default('input'),\n\n /** Default input value (uncontrolled) */\n defaultInputValue: z.string().optional(),\n\n /** Input value (controlled) */\n inputValue: z.string().optional(),\n\n /** Default selected key (uncontrolled) */\n defaultSelectedKey: z.union([z.string(), z.number()]).optional(),\n\n /** Selected key (controlled) */\n selectedKey: z.union([z.string(), z.number(), z.null()]).optional(),\n});\n\nexport interface ComboboxPropsOwn {\n className?: string;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n label?: string;\n description?: string;\n errorMessage?: string;\n size?: ComboboxSize;\n placeholder?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n name?: string;\n allowsCustomValue?: boolean;\n menuTrigger?: 'input' | 'focus' | 'manual';\n defaultInputValue?: string;\n inputValue?: string;\n defaultSelectedKey?: string | number;\n selectedKey?: string | number | null;\n children: ReactNode;\n onInputChange?: (value: string) => void;\n onSelectionChange?: (key: string | number | null) => void;\n}\n\nexport type ComboboxProps = ComboboxPropsOwn &\n Omit<AriaComboBoxProps<object>, keyof ComboboxPropsOwn>;\n\nexport const ComboboxItemPropsSchema = z.object({\n /** Unique key/value for the item */\n id: z.union([z.string(), z.number()]).optional(),\n /** Text value for filtering */\n textValue: z.string().optional(),\n /** Whether this item is disabled */\n isDisabled: z.boolean().optional(),\n /** Item content */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxItemProps {\n id?: string | number;\n textValue?: string;\n isDisabled?: boolean;\n children?: ReactNode;\n className?: string;\n}\n\nexport const ComboboxSectionPropsSchema = z.object({\n /** Section header text */\n header: z.string().optional(),\n /** Section items */\n children: z.custom<ReactNode>(),\n className: z.string().optional(),\n});\n\nexport interface ComboboxSectionProps {\n header?: string;\n children?: ReactNode;\n className?: string;\n}\n"]}