@tribepad/themis 1.9.1 → 1.9.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG.md +5 -0
  2. package/dist/elements/Checkbox/Checkbox.d.ts.map +1 -1
  3. package/dist/elements/Checkbox/index.js +1 -1
  4. package/dist/elements/Checkbox/index.js.map +1 -1
  5. package/dist/elements/Checkbox/index.mjs +1 -1
  6. package/dist/elements/Checkbox/index.mjs.map +1 -1
  7. package/dist/elements/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
  8. package/dist/elements/CheckboxGroup/index.js +1 -1
  9. package/dist/elements/CheckboxGroup/index.js.map +1 -1
  10. package/dist/elements/CheckboxGroup/index.mjs +1 -1
  11. package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
  12. package/dist/elements/Filters/index.js +1 -1
  13. package/dist/elements/Filters/index.js.map +1 -1
  14. package/dist/elements/Filters/index.mjs +1 -1
  15. package/dist/elements/Filters/index.mjs.map +1 -1
  16. package/dist/elements/RadioGroup/RadioGroup.d.ts.map +1 -1
  17. package/dist/elements/RadioGroup/index.js +1 -1
  18. package/dist/elements/RadioGroup/index.js.map +1 -1
  19. package/dist/elements/RadioGroup/index.mjs +1 -1
  20. package/dist/elements/RadioGroup/index.mjs.map +1 -1
  21. package/dist/elements/SituationalJudgement/index.js +1 -1
  22. package/dist/elements/SituationalJudgement/index.js.map +1 -1
  23. package/dist/elements/SituationalJudgement/index.mjs +1 -1
  24. package/dist/elements/SituationalJudgement/index.mjs.map +1 -1
  25. package/dist/elements/Switch/Switch.d.ts.map +1 -1
  26. package/dist/elements/Switch/index.js +1 -1
  27. package/dist/elements/Switch/index.js.map +1 -1
  28. package/dist/elements/Switch/index.mjs +1 -1
  29. package/dist/elements/Switch/index.mjs.map +1 -1
  30. package/dist/elements/Table/index.js +1 -1
  31. package/dist/elements/Table/index.js.map +1 -1
  32. package/dist/elements/Table/index.mjs +1 -1
  33. package/dist/elements/Table/index.mjs.map +1 -1
  34. package/dist/elements/index.js +1 -1
  35. package/dist/elements/index.js.map +1 -1
  36. package/dist/elements/index.mjs +1 -1
  37. package/dist/elements/index.mjs.map +1 -1
  38. package/dist/index.js +1 -1
  39. package/dist/index.js.map +1 -1
  40. package/dist/index.mjs +1 -1
  41. package/dist/index.mjs.map +1 -1
  42. package/package.json +1 -1
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/styles/interaction-states.ts","../../../src/elements/RadioGroup/RadioGroup.tsx","../../../src/elements/Accordion/Accordion.tsx","../../../src/elements/SituationalJudgement/SituationalJudgement.styles.ts","../../../src/elements/SituationalJudgement/SituationalJudgement.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/SituationalJudgement/SituationalJudgement.types.ts"],"names":["cn","inputs","twMerge","clsx","FOCUS_STYLES","HIGH_CONTRAST_FOCUS","RadioGroupContext","createContext","radioGroupVariants","cva","radioItemVariants","radioIndicatorVariants","radioInnerDotVariants","RadioLabel","children","className","jsx","RadioDescription","RadioComponent","value","isDisabled","variant","size","isInvalid","useContext","AriaRadio","renderProps","jsxs","Fragment","Radio","RadioGroup","forwardRef","props","ref","label","description","errorMessage","defaultValue","isReadOnly","isRequired","orientation","name","onChange","onFocusChange","id","ariaLabel","ariaLabelledby","ariaDescribedby","dataTestId","restProps","generatedId","useId","radioGroupId","labelId","descriptionId","errorId","describedByParts","computedAriaDescribedBy","AriaRadioGroup","Label","Text","FieldError","Activity","ReactActivity","mode","AccordionContext","accordionVariants","accordionItemVariants","accordionTriggerVariants","accordionChevronVariants","accordionContentVariants","accordionContentInnerVariants","getHeadingLevel","level","getFirstAccordionItemId","childArray","Children","child","isValidElement","childProps","AccordionRoot","type","collapsible","expandedKeys","defaultExpandedKeys","onExpandedChange","disabledKeys","allowsMultipleExpanded","effectiveDefaultExpandedKeys","useMemo","firstItemId","contextValue","DisclosureGroup","AccordionItemComponent","isDisabledProp","disabledKeysSet","isDisabledFromKeys","Disclosure","composeRenderProps","AccordionTriggerComponent","headingLevel","icon","hideIcon","isExpanded","DisclosureStateContext","Heading","Button","ChevronDown","AccordionContentInner","preserveState","AccordionContentComponent","DisclosurePanel","Accordion","AccordionItem","AccordionTrigger","AccordionContent","sjtContainerVariants","sjtScenarioVariants","sjtOrdinalVariants","ALLOWED_TAGS","sanitiseHtml","html","doc","walkNode","node","escapeHtml","el","tagName","childHtml","result","text","ordinalToLetter","ordinal","SituationalJudgement","scenarioText","collapsibleScenario","responses","groupId","scenarioId","sortedResponses","a","b","sanitisedScenario","response","BaseComponentPropsSchema","z","SJTSizeSchema","SJTResponseSchema","SituationalJudgementPropsSchema","data","values","r"],"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 * Global Interaction State Styles\n *\n * Consistent interaction patterns across all Themis components.\n * These styles ensure WCAG 2.2 AAA compliance and predictable UX.\n *\n * @see spec.md FR-010 (Visible focus ring for keyboard navigation)\n * @see spec.md FR-031 (Pressed state feedback)\n * @see spec.md FR-012 (High contrast mode support)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\n/**\n * Focus state styles (FR-010)\n * Visible focus ring for keyboard navigation - WCAG 2.2 Level AAA\n *\n * Components can override by extending these styles:\n * @example\n * cn(FOCUS_STYLES, \"ring-4\") // Increases ring width to 4px\n */\nexport const FOCUS_STYLES = \"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2\";\n\n/**\n * Pressed/Active state styles (FR-031)\n * Visual feedback for press interactions\n *\n * Components can override the scale amount:\n * @example\n * cn(PRESSED_STYLES_BASE, \"data-[pressed]:scale-[0.95]\") // More pronounced scale\n */\nexport const PRESSED_STYLES = \"data-[pressed]:scale-[0.97]\";\n\n/**\n * Base pressed styles without scale (for components that need different feedback)\n */\nexport const PRESSED_STYLES_BASE = \"data-[pressed]:transition-transform data-[pressed]:duration-100\";\n\n/**\n * Hover state styles\n * Elevation change on hover for better affordance\n *\n * Components can override shadow depth:\n * @example\n * cn(HOVER_STYLES_BASE, \"data-[hovered]:shadow-lg\") // Larger shadow\n */\nexport const HOVER_STYLES = \"\";\n\n/**\n * Base hover styles without shadow (for components that use different hover effects)\n */\nexport const HOVER_STYLES_BASE = \"data-[hovered]:transition-shadow data-[hovered]:duration-200\";\n\n/**\n * High contrast mode focus (FR-012)\n * Enhanced outlines for users requiring high contrast\n *\n * Uses 'hc:' prefix for prefers-contrast: more media query\n */\nexport const HIGH_CONTRAST_FOCUS = \"hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground\";\n\n/**\n * High contrast mode hover (FR-012)\n * Enhanced outlines for hover in high contrast mode\n */\nexport const HIGH_CONTRAST_HOVER = \"hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground\";\n\n/**\n * High contrast mode pressed state\n * Enhanced outlines for pressed state in high contrast mode\n */\nexport const HIGH_CONTRAST_PRESSED = \"hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground\";\n\n/**\n * Combined high contrast styles\n * Use this for components that need all high contrast interaction states\n */\nexport const HIGH_CONTRAST_INTERACTIONS = `${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Disabled state styles\n * Consistent disabled appearance across all components\n */\nexport const DISABLED_STYLES = \"disabled:pointer-events-none disabled:opacity-50\";\n\n/**\n * Default interaction bundle\n * Most common combination for interactive components\n *\n * Includes: focus ring, pressed scale, hover shadow, high contrast enhancements\n *\n * @example\n * <button className={cn(DEFAULT_INTERACTIONS, \"bg-primary\")}>Click</button>\n */\nexport const DEFAULT_INTERACTIONS = `${FOCUS_STYLES} ${PRESSED_STYLES} ${HOVER_STYLES} ${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Subtle interaction bundle\n * For components that need less pronounced feedback\n *\n * Includes: focus ring and high contrast, but no hover shadow or pressed scale\n */\nexport const SUBTLE_INTERACTIONS = `${FOCUS_STYLES} ${HIGH_CONTRAST_FOCUS}`;\n\n/**\n * Non-interactive element styles\n * For elements that should indicate they are not interactive\n */\nexport const NON_INTERACTIVE = \"cursor-default select-none\";\n","\"use client\";\n\n/**\n * RadioGroup Component\n * Accessible single-selection radio group with React Aria primitives and CVA styling\n *\n * Key Features:\n * - Bordered container design with explicit 44px+ touch targets\n * - 2 variants: default, destructive (no outline per clarification)\n * - 3 sizes: sm (44px), default (48px), lg (56px)\n * - Arrow keys move focus AND select (WAI-ARIA standard selection-follows-focus)\n * - Error styling on ALL items (cognitive accessibility)\n * - Spring animation for selection indicator\n * - RTL support (indicator auto-flips)\n * - Radio.Label and Radio.Description sub-components\n *\n * @see radiogroup-prd.md (Product Requirements)\n * @see plan.md (11 Key Clarifications)\n * @see React Aria RadioGroup: https://react-spectrum.adobe.com/react-aria/RadioGroup.html\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AAA)\n */\n\nimport {\n forwardRef,\n createContext,\n useContext,\n useId,\n type ReactNode,\n type ForwardedRef,\n} from 'react';\nimport {\n RadioGroup as AriaRadioGroup,\n Radio as AriaRadio,\n Label,\n Text,\n FieldError,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { FOCUS_STYLES, HIGH_CONTRAST_FOCUS } from '../../styles/interaction-states';\nimport type {\n RadioGroupProps,\n RadioProps,\n RadioLabelProps,\n RadioDescriptionProps,\n RadioGroupVariant,\n RadioGroupSize,\n} from './RadioGroup.types';\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface RadioGroupContextValue {\n variant: RadioGroupVariant;\n size: RadioGroupSize;\n isInvalid: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue>({\n variant: 'default',\n size: 'default',\n isInvalid: false,\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * RadioGroup container variants\n * Controls orientation and spacing (gap-2 = 8px per clarification)\n */\nconst radioGroupVariants = cva(\n // Base: flex container\n \"flex\",\n {\n variants: {\n orientation: {\n vertical: \"flex-col gap-2\",\n horizontal: \"flex-row flex-wrap gap-2\",\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n }\n);\n\n/**\n * Radio item bordered container variants\n * Bordered container design with explicit touch targets\n * All sizes maintain 44px minimum height (WCAG 2.2 AAA)\n * All sizes use rounded-md (6px) per clarification\n */\nconst radioItemVariants = cva(\n // Base: bordered container with flex layout, RTL support\n [\n \"flex items-center gap-3 rounded-md border cursor-pointer\",\n \"transition-colors duration-200\",\n \"rtl:flex-row-reverse\", // RTL: indicator flips to right\n // Focus ring on entire container\n FOCUS_STYLES,\n HIGH_CONTRAST_FOCUS,\n ].join(\" \"),\n {\n variants: {\n variant: {\n default: [\n \"border-[var(--border)]\",\n \"data-[hovered]:bg-[var(--accent)]/10\",\n \"data-[selected]:border-[var(--primary)]\",\n \"data-[selected]:bg-[var(--primary)]/10\",\n ].join(\" \"),\n destructive: [\n \"border-[var(--border)]\",\n \"data-[hovered]:bg-[var(--destructive-background)]/10\",\n \"data-[selected]:border-[var(--destructive-background)]\",\n \"data-[selected]:bg-[var(--destructive-background)]/10\",\n ].join(\" \"),\n },\n size: {\n sm: \"min-h-[44px] py-2 px-3 text-sm\",\n default: \"min-h-[48px] py-3 px-4 text-sm\",\n lg: \"min-h-[56px] py-4 px-5 text-base\",\n },\n isDisabled: {\n true: \"opacity-50 cursor-not-allowed\",\n false: \"\",\n },\n isInvalid: {\n // Error: ALL items get destructive border (cognitive accessibility)\n true: \"border-[var(--destructive-background)]\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n isDisabled: false,\n isInvalid: false,\n },\n }\n);\n\n/**\n * Circle indicator (outer ring) variants\n */\nconst radioIndicatorVariants = cva(\n // Base: circle with border, flex-shrink-0 to prevent squishing\n \"flex-shrink-0 rounded-full border-2 flex items-center justify-center transition-colors duration-200\",\n {\n variants: {\n variant: {\n default: [\n \"border-[var(--border)]\",\n \"data-[selected]:border-[var(--primary)]\",\n ].join(\" \"),\n destructive: [\n \"border-[var(--border)]\",\n \"data-[selected]:border-[var(--destructive-background)]\",\n ].join(\" \"),\n },\n size: {\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n/**\n * Inner dot variants (appears when selected)\n * Spring animation: cubic-bezier(0.34, 1.56, 0.64, 1) with slight overshoot\n */\nconst radioInnerDotVariants = cva(\n // Base: centered dot with spring animation\n [\n \"rounded-full transition-transform duration-200\",\n // Spring animation with overshoot\n \"[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)]\",\n // Respect reduced motion preference\n \"motion-reduce:transition-none\",\n // Scale from 0 to 1 on selection\n \"scale-0 data-[selected]:scale-100\",\n ].join(\" \"),\n {\n variants: {\n variant: {\n default: \"bg-[var(--primary)]\",\n destructive: \"bg-[var(--destructive-background)]\",\n },\n size: {\n sm: \"h-2 w-2\",\n default: \"h-2.5 w-2.5\",\n lg: \"h-3 w-3\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\n/**\n * Radio.Label - Styled label for radio item content\n */\nfunction RadioLabel({ children, className }: RadioLabelProps): ReactNode {\n return (\n <span className={cn(\"font-medium text-[var(--content-foreground)]\", className)}>\n {children}\n </span>\n );\n}\n\nRadioLabel.displayName = \"Radio.Label\";\n\n/**\n * Radio.Description - Styled description for radio item content (muted)\n */\nfunction RadioDescription({ children, className }: RadioDescriptionProps): ReactNode {\n return (\n <span className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </span>\n );\n}\n\nRadioDescription.displayName = \"Radio.Description\";\n\n// ============================================================================\n// Radio Component\n// ============================================================================\n\n/**\n * Radio item component with bordered container design\n */\nfunction RadioComponent({ value, isDisabled, children, className }: RadioProps): ReactNode {\n const { variant, size, isInvalid } = useContext(RadioGroupContext);\n\n return (\n <AriaRadio\n value={value}\n isDisabled={isDisabled}\n className={(renderProps) =>\n cn(\n radioItemVariants({\n variant,\n size,\n isDisabled: renderProps.isDisabled,\n isInvalid,\n }),\n className\n )\n }\n >\n {(renderProps) => (\n <>\n {/* Circle indicator */}\n <div\n className={radioIndicatorVariants({ variant, size })}\n data-selected={renderProps.isSelected || undefined}\n >\n {/* Inner dot with spring animation */}\n <div\n className={radioInnerDotVariants({ variant, size })}\n data-selected={renderProps.isSelected || undefined}\n />\n </div>\n\n {/* Children content (flexible - text, icons, complex layouts) */}\n <div className=\"flex-1 flex flex-col\">\n {children}\n </div>\n </>\n )}\n </AriaRadio>\n );\n}\n\n// Attach sub-components\nconst Radio = Object.assign(RadioComponent, {\n Label: RadioLabel,\n Description: RadioDescription,\n}) as typeof RadioComponent & {\n Label: typeof RadioLabel;\n Description: typeof RadioDescription;\n displayName: string;\n};\n\nRadio.displayName = \"Radio\";\n\n// ============================================================================\n// RadioGroup Component\n// ============================================================================\n\n/**\n * RadioGroup root component\n * Accessible single-selection control with bordered container design\n */\nconst RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup(props: RadioGroupProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n // Display props\n label,\n description,\n errorMessage,\n // Selection props\n value,\n defaultValue,\n // State props\n isDisabled = false,\n isReadOnly = false,\n isRequired = false,\n isInvalid = false,\n // Layout props\n orientation = 'vertical',\n // Variant props\n variant = 'default',\n size = 'default',\n // Form props\n name,\n // Event handlers\n onChange,\n onFocusChange,\n // Standard props\n className,\n children,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n ...restProps\n } = props;\n\n // Generate unique IDs for accessibility\n const generatedId = useId();\n const radioGroupId = id ?? generatedId;\n const labelId = `${radioGroupId}-label`;\n const descriptionId = `${radioGroupId}-description`;\n const errorId = `${radioGroupId}-error`;\n\n // Build aria-describedby from description and error\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n const computedAriaDescribedBy = describedByParts.length > 0\n ? describedByParts.join(' ')\n : undefined;\n\n return (\n <RadioGroupContext.Provider value={{ variant, size, isInvalid }}>\n <AriaRadioGroup\n ref={ref}\n id={radioGroupId}\n name={name}\n value={value ?? undefined}\n defaultValue={defaultValue ?? undefined}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n isRequired={isRequired}\n isInvalid={isInvalid}\n orientation={orientation}\n onChange={onChange}\n onFocusChange={onFocusChange}\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : ariaLabelledby}\n aria-describedby={computedAriaDescribedBy}\n data-testid={dataTestId}\n data-orientation={orientation}\n className={cn(\"flex flex-col gap-1.5\", className)}\n {...restProps}\n >\n {/* Label with optional required asterisk */}\n {label && (\n <Label id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </Label>\n )}\n\n {/* Description */}\n {description && (\n <Text\n id={descriptionId}\n slot=\"description\"\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </Text>\n )}\n\n {/* Radio items container with orientation */}\n <div className={radioGroupVariants({ orientation })}>\n {children}\n </div>\n\n {/* Error message with role=\"alert\" for screen reader announcements */}\n {isInvalid && errorMessage && (\n <FieldError\n id={errorId}\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n <span role=\"alert\">{errorMessage}</span>\n </FieldError>\n )}\n </AriaRadioGroup>\n </RadioGroupContext.Provider>\n );\n }\n);\n\nRadioGroup.displayName = \"RadioGroup\";\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n RadioGroup,\n Radio,\n radioGroupVariants,\n radioItemVariants,\n radioIndicatorVariants,\n radioInnerDotVariants,\n};\n","'use client';\n\n/**\n * Accordion Component - Implementation\n *\n * Accessible accordion/disclosure group component combining React Aria primitives with CVA styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria DisclosureGroup for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for consistent styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Single/Multiple expansion modes\n * - Controlled and uncontrolled state management\n * - Configurable heading levels for document structure\n * - Custom icon support\n *\n * @see accordion-prd.md (Full requirements)\n * @see Accordion.types.ts (Zod schemas)\n * @see plan.md (Implementation approach)\n */\n\n// React 19.2 Activity API - may not be available in all builds\n// Import conditionally to support environments where Activity is unavailable\nimport {\n Activity as ReactActivity,\n type ReactNode,\n type ReactElement,\n useMemo,\n useContext,\n createContext,\n Children,\n isValidElement,\n} from 'react';\n\n// Activity component with fallback for environments where it's not available\n// The fallback simply renders children directly - no state preservation when Activity unavailable\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n return <div data-activity-mode={mode}>{children}</div>;\n};\n\nimport {\n DisclosureGroup,\n Disclosure,\n DisclosurePanel,\n Heading,\n Button,\n composeRenderProps,\n DisclosureStateContext,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { ChevronDown } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport type {\n AccordionProps,\n AccordionItemProps,\n AccordionTriggerProps,\n AccordionContentProps,\n HeadingLevel,\n} from './Accordion.types';\n\n// ============================================================================\n// Context for disabledKeys\n// ============================================================================\n\n/**\n * Context to pass disabledKeys from Accordion to AccordionItem\n * Since DisclosureGroup doesn't support disabledKeys directly, we handle it via context\n */\ninterface AccordionContextValue {\n disabledKeysSet?: Set<string | number>;\n}\n\nconst AccordionContext = createContext<AccordionContextValue>({});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Accordion root CVA variants\n *\n * @see accordion-prd.md FR-001 (Accordion Root)\n */\nexport const accordionVariants = cva('w-full', {\n variants: {},\n defaultVariants: {},\n});\n\n/**\n * AccordionItem CVA variants\n *\n * @see accordion-prd.md FR-002 (AccordionItem)\n * @see accordion-prd.md DS-001 (Visual Design - borders)\n */\nexport const accordionItemVariants = cva(\n [\n 'border-b border-[var(--border)]',\n // Last item has no border (handled by last:border-b-0)\n 'last:border-b-0',\n ].join(' '),\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * AccordionTrigger CVA variants\n *\n * @see accordion-prd.md FR-003 (AccordionTrigger)\n * @see accordion-prd.md AR-006 (Touch Target Size - 44x44px)\n * @see accordion-prd.md DS-002 (Typography)\n */\nexport const accordionTriggerVariants = cva(\n [\n // Layout\n 'flex flex-1 items-center justify-between py-4 font-medium w-full',\n // Text styling\n 'text-sm text-[var(--content-foreground)]',\n // Hover state\n 'hover:underline',\n // Focus visible ring (WCAG 2.4.13)\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n 'focus-visible:ring-offset-[var(--content-background)]',\n // WCAG 2.2 AAA: 44px minimum touch target\n 'min-h-[44px]',\n // Disabled state\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // Transition for smooth interactions\n 'transition-colors',\n ].join(' '),\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Chevron icon CVA variants\n *\n * @see accordion-prd.md FR-010 (Animated Transitions)\n */\nexport const accordionChevronVariants = cva(\n [\n 'h-4 w-4 shrink-0',\n 'text-[var(--menu-muted)]',\n // Smooth rotation transition\n 'transition-transform duration-200 ease-out',\n // Reduced motion support\n 'motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n isExpanded: {\n true: 'rotate-180',\n false: 'rotate-0',\n },\n },\n defaultVariants: {\n isExpanded: false,\n },\n }\n);\n\n/**\n * AccordionContent CVA variants\n *\n * @see accordion-prd.md FR-004 (AccordionContent)\n * @see accordion-prd.md FR-010 (Animated Transitions)\n */\nexport const accordionContentVariants = cva(\n [\n 'overflow-hidden',\n 'text-sm text-[var(--menu-muted)]',\n ].join(' '),\n {\n variants: {\n isExpanded: {\n true: 'motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-2 motion-safe:[animation-duration:250ms] motion-safe:[animation-timing-function:cubic-bezier(0.16,1,0.3,1)]',\n false: '',\n },\n },\n defaultVariants: {\n isExpanded: false,\n },\n }\n);\n\n/**\n * AccordionContent inner wrapper CVA variants\n */\nexport const accordionContentInnerVariants = cva('pb-4 pt-0', {\n variants: {},\n defaultVariants: {},\n});\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Convert heading level string to number for React Aria Heading\n */\nfunction getHeadingLevel(level: HeadingLevel): 1 | 2 | 3 | 4 | 5 | 6 {\n const levelMap: Record<HeadingLevel, 1 | 2 | 3 | 4 | 5 | 6> = {\n h1: 1,\n h2: 2,\n h3: 3,\n h4: 4,\n h5: 5,\n h6: 6,\n };\n return levelMap[level];\n}\n\n/**\n * Get the first AccordionItem id from children\n * Used for auto-expanding first item when collapsible={false}\n */\nfunction getFirstAccordionItemId(children: ReactNode): AriaKey | undefined {\n const childArray = Children.toArray(children);\n for (const child of childArray) {\n if (isValidElement(child)) {\n const childProps = child.props as Record<string, unknown>;\n if (childProps && typeof childProps === 'object' && 'id' in childProps) {\n return childProps.id as AriaKey;\n }\n }\n }\n return undefined;\n}\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Accordion Root Component\n *\n * Container for accordion items. Manages expansion state and provides\n * context to child components.\n *\n * @see accordion-prd.md FR-001 (Accordion Root Component)\n * @see accordion-prd.md FR-005 (Single Expansion Mode)\n * @see accordion-prd.md FR-006 (Multiple Expansion Mode)\n * @see accordion-prd.md FR-007 (Controlled Mode)\n * @see accordion-prd.md FR-008 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled single mode\n * <Accordion type=\"single\" collapsible>\n * <AccordionItem id=\"item-1\">\n * <AccordionTrigger>Section 1</AccordionTrigger>\n * <AccordionContent>Content 1</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n *\n * @example\n * // Controlled multiple mode\n * <Accordion\n * type=\"multiple\"\n * expandedKeys={expandedKeys}\n * onExpandedChange={setExpandedKeys}\n * >\n * ...\n * </Accordion>\n */\nfunction AccordionRoot({\n type = 'single',\n collapsible = false,\n expandedKeys,\n defaultExpandedKeys,\n onExpandedChange,\n isDisabled = false,\n disabledKeys,\n className,\n children,\n ...props\n}: AccordionProps) {\n // Map type prop to React Aria's allowsMultipleExpanded\n const allowsMultipleExpanded = type === 'multiple';\n\n // Auto-expand first item when collapsible={false} and no default provided\n // This ensures one item is always expanded in non-collapsible single mode\n const effectiveDefaultExpandedKeys = useMemo(() => {\n if (!collapsible && type === 'single' && !defaultExpandedKeys && !expandedKeys) {\n const firstItemId = getFirstAccordionItemId(children);\n return firstItemId ? [firstItemId] : undefined;\n }\n return defaultExpandedKeys;\n }, [collapsible, type, defaultExpandedKeys, expandedKeys, children]);\n\n // Context value for passing disabledKeys to AccordionItem (Set for O(1) lookups)\n const contextValue = useMemo(\n () => ({ disabledKeysSet: disabledKeys ? new Set(disabledKeys) : undefined }),\n [disabledKeys]\n );\n\n return (\n <AccordionContext.Provider value={contextValue}>\n <DisclosureGroup\n allowsMultipleExpanded={allowsMultipleExpanded}\n expandedKeys={expandedKeys as Set<AriaKey> | undefined}\n defaultExpandedKeys={effectiveDefaultExpandedKeys as Iterable<AriaKey> | undefined}\n onExpandedChange={onExpandedChange as ((keys: Set<AriaKey>) => void) | undefined}\n isDisabled={isDisabled}\n className={cn(accordionVariants(), className)}\n {...props}\n >\n {children}\n </DisclosureGroup>\n </AccordionContext.Provider>\n );\n}\n\nAccordionRoot.displayName = 'Accordion';\n\n/**\n * AccordionItem Component\n *\n * Wrapper for each expandable disclosure section.\n *\n * @see accordion-prd.md FR-002 (AccordionItem Component)\n *\n * @example\n * <AccordionItem id=\"faq-1\" isDisabled={!isAuthenticated}>\n * <AccordionTrigger>Members-only FAQ</AccordionTrigger>\n * <AccordionContent>This content is for members only.</AccordionContent>\n * </AccordionItem>\n */\nfunction AccordionItemComponent({\n id,\n isDisabled: isDisabledProp,\n className,\n children,\n ...props\n}: AccordionItemProps) {\n // Check if this item is in the disabledKeys set (O(1) lookup)\n const { disabledKeysSet } = useContext(AccordionContext);\n const isDisabledFromKeys = disabledKeysSet?.has(id as string | number) ?? false;\n const isDisabled = isDisabledProp || isDisabledFromKeys;\n\n return (\n <Disclosure\n id={id}\n isDisabled={isDisabled}\n className={composeRenderProps(className, (className) =>\n cn(accordionItemVariants(), className)\n )}\n {...props}\n >\n {children}\n </Disclosure>\n );\n}\n\nAccordionItemComponent.displayName = 'AccordionItem';\n\n/**\n * AccordionTrigger Component\n *\n * Clickable button that toggles accordion content visibility.\n * Wrapped in a Heading for proper document structure.\n *\n * @see accordion-prd.md FR-003 (AccordionTrigger Component)\n * @see accordion-prd.md AR-002 (ARIA Attributes)\n * @see accordion-prd.md AR-003 (Keyboard Navigation)\n *\n * @example\n * // Default with chevron\n * <AccordionTrigger>Is it accessible?</AccordionTrigger>\n *\n * @example\n * // Custom heading level\n * <AccordionTrigger as=\"h2\">Important Section</AccordionTrigger>\n *\n * @example\n * // Custom icon\n * <AccordionTrigger icon={<PlusIcon className=\"h-4 w-4\" />}>\n * Click to expand\n * </AccordionTrigger>\n */\nfunction AccordionTriggerComponent({\n as: headingLevel = 'h3',\n icon,\n hideIcon = false,\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n // Access disclosure state from context\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n return (\n <Heading level={getHeadingLevel(headingLevel)}>\n <Button\n slot=\"trigger\"\n className={composeRenderProps(className, (className) =>\n cn(accordionTriggerVariants(), className)\n )}\n {...props}\n >\n <span className=\"flex-1 text-left\">{children}</span>\n {!hideIcon && (\n icon ?? (\n <ChevronDown\n aria-hidden=\"true\"\n className={cn(accordionChevronVariants({ isExpanded }))}\n />\n )\n )}\n </Button>\n </Heading>\n );\n}\n\nAccordionTriggerComponent.displayName = 'AccordionTrigger';\n\n/**\n * AccordionContent Component\n *\n * Expandable container for accordion content.\n * Supports animated height transitions and React Activity state preservation.\n *\n * @see accordion-prd.md FR-004 (AccordionContent Component)\n * @see accordion-prd.md FR-010 (Animated Transitions)\n *\n * @example\n * // Standard content\n * <AccordionContent>\n * Yes. It adheres to the WAI-ARIA design pattern.\n * </AccordionContent>\n *\n * @example\n * // With state preservation\n * <AccordionContent preserveState>\n * <form>\n * <input name=\"email\" />\n * </form>\n * </AccordionContent>\n */\n/**\n * Inner component for AccordionContent with state preservation\n * Uses DisclosureStateContext to get isExpanded state\n */\nfunction AccordionContentInner({\n preserveState,\n children,\n}: {\n preserveState: boolean;\n children: ReactNode;\n}) {\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n if (preserveState) {\n return (\n <Activity mode={isExpanded ? 'visible' : 'hidden'}>\n <div className={accordionContentInnerVariants()}>{children}</div>\n </Activity>\n );\n }\n\n return <div className={accordionContentInnerVariants()}>{children}</div>;\n}\n\nfunction AccordionContentComponent({\n preserveState = false,\n className,\n children,\n ...props\n}: AccordionContentProps) {\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n return (\n <DisclosurePanel\n className={composeRenderProps(className, (className) =>\n cn(accordionContentVariants({ isExpanded }), className)\n )}\n {...props}\n >\n <AccordionContentInner preserveState={preserveState}>\n {children}\n </AccordionContentInner>\n </DisclosurePanel>\n );\n}\n\nAccordionContentComponent.displayName = 'AccordionContent';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Accordion follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '...'\n */\nexport const Accordion = AccordionRoot;\nexport const AccordionItem = AccordionItemComponent;\nexport const AccordionTrigger = AccordionTriggerComponent;\nexport const AccordionContent = AccordionContentComponent;\n\n// Re-export types for convenience\nexport type {\n AccordionProps,\n AccordionItemProps,\n AccordionTriggerProps,\n AccordionContentProps,\n};\n","import { cva } from 'class-variance-authority';\n\n/**\n * SituationalJudgement CVA Variant Definitions\n *\n * Minimal styling since this component composes existing RadioGroup, Radio,\n * and Accordion components. These variants cover the container and scenario panel.\n */\n\n// =============================================================================\n// Container\n// =============================================================================\n\n/** Root wrapper */\nexport const sjtContainerVariants = cva(\"flex flex-col gap-3\", {\n variants: {\n size: {\n sm: \"text-sm\",\n default: \"text-sm\",\n lg: \"text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n});\n\n// =============================================================================\n// Scenario Panel\n// =============================================================================\n\n/** Scenario text panel (non-collapsible mode) */\nexport const sjtScenarioVariants = cva(\n [\n \"rounded-md border border-[var(--border)]\",\n \"bg-[var(--muted)] text-[var(--content-foreground)]\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"p-3 text-sm\",\n default: \"p-4 text-sm\",\n lg: \"p-5 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Ordinal letter label (\"A.\", \"B.\", etc.) */\nexport const sjtOrdinalVariants = cva(\n \"font-semibold text-[var(--muted-foreground)] flex-shrink-0\",\n {\n variants: {\n size: {\n sm: \"text-xs w-5\",\n default: \"text-sm w-6\",\n lg: \"text-base w-7\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n","\"use client\";\n\n/**\n * SituationalJudgement Component\n *\n * Assessment component presenting a scenario with 3-6 response options.\n * Composes existing Themis RadioGroup + Radio for response selection\n * and Accordion for collapsible scenario panel.\n *\n * Features:\n * - HTML scenario text with built-in sanitiser (XSS protection)\n * - Collapsible scenario via Accordion\n * - Responses sorted by ordinal, labeled with letters (A, B, C, ...)\n * - Standard radio group behaviour (no deselection)\n *\n * @see WCAG 2.2 AAA — 44x44px touch targets, keyboard navigation\n */\n\nimport {\n forwardRef,\n useId,\n useMemo,\n type ForwardedRef,\n} from 'react';\nimport { Label, Text } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport { RadioGroup, Radio } from '../RadioGroup/RadioGroup';\nimport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from '../Accordion/Accordion';\nimport type { SituationalJudgementProps, SJTResponse } from './SituationalJudgement.types';\nimport {\n sjtContainerVariants,\n sjtScenarioVariants,\n sjtOrdinalVariants,\n} from './SituationalJudgement.styles';\n\n// =============================================================================\n// HTML Sanitiser\n// =============================================================================\n\nconst ALLOWED_TAGS = new Set([\n 'b', 'strong', 'i', 'em', 'ul', 'ol', 'li', 'p', 'br',\n]);\n\n/**\n * Sanitise HTML string using DOMParser.\n * Only preserves allowed tags, strips ALL attributes.\n * Returns clean HTML safe for dangerouslySetInnerHTML.\n */\nfunction sanitiseHtml(html: string): string {\n if (typeof window === 'undefined' || typeof DOMParser === 'undefined') {\n // SSR fallback: strip all HTML tags\n return html.replace(/<[^>]*>/g, '');\n }\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n\n function walkNode(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) {\n return escapeHtml(node.textContent ?? '');\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n const tagName = el.tagName.toLowerCase();\n\n if (!ALLOWED_TAGS.has(tagName)) {\n // Strip disallowed tag but process children\n let childHtml = '';\n for (const child of Array.from(el.childNodes)) {\n childHtml += walkNode(child);\n }\n return childHtml;\n }\n\n // Allowed tag — render without attributes\n let childHtml = '';\n for (const child of Array.from(el.childNodes)) {\n childHtml += walkNode(child);\n }\n\n if (tagName === 'br') {\n return '<br />';\n }\n\n return `<${tagName}>${childHtml}</${tagName}>`;\n }\n\n return '';\n }\n\n let result = '';\n for (const child of Array.from(doc.body.childNodes)) {\n result += walkNode(child);\n }\n return result;\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** Convert ordinal index to letter: 0 → \"A\", 1 → \"B\", etc. */\nfunction ordinalToLetter(ordinal: number): string {\n return String.fromCharCode(65 + ordinal);\n}\n\n// =============================================================================\n// SituationalJudgement Component\n// =============================================================================\n\nconst SituationalJudgement = forwardRef<HTMLDivElement, SituationalJudgementProps>(\n function SituationalJudgement(\n props: SituationalJudgementProps,\n ref: ForwardedRef<HTMLDivElement>,\n ) {\n const {\n // Value\n value,\n onChange,\n // Scenario\n scenarioText,\n collapsibleScenario = false,\n // Responses\n responses,\n // Labels\n label,\n description,\n errorMessage,\n // State\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n isInvalid = false,\n // Sizing\n size = 'default',\n // Standard\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n } = props;\n\n const generatedId = useId();\n const groupId = id ?? generatedId;\n const labelId = `${groupId}-label`;\n const descriptionId = `${groupId}-description`;\n const errorId = `${groupId}-error`;\n const scenarioId = `${groupId}-scenario`;\n\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (scenarioText) describedByParts.push(scenarioId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n\n // Sort responses by ordinal\n const sortedResponses = useMemo(\n () => [...responses].sort((a, b) => a.ordinal - b.ordinal),\n [responses],\n );\n\n // Sanitise scenario HTML\n const sanitisedScenario = useMemo(\n () => sanitiseHtml(scenarioText),\n [scenarioText],\n );\n\n return (\n <div\n ref={ref}\n id={groupId}\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n data-testid={dataTestId}\n className={cn(sjtContainerVariants({ size }), className)}\n >\n {/* Label */}\n {label && (\n <Label id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </Label>\n )}\n\n {/* Description */}\n {description && (\n <Text\n id={descriptionId}\n slot=\"description\"\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </Text>\n )}\n\n {/* Scenario Panel */}\n {collapsibleScenario ? (\n <Accordion type=\"single\" collapsible isDisabled={false} defaultExpandedKeys={['scenario']}>\n <AccordionItem id=\"scenario\">\n <AccordionTrigger as=\"h3\" hideIcon={false}>Scenario</AccordionTrigger>\n <AccordionContent preserveState={false}>\n <div\n id={scenarioId}\n className={sjtScenarioVariants({ size })}\n dangerouslySetInnerHTML={{ __html: sanitisedScenario }}\n />\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n ) : (\n <div\n id={scenarioId}\n role=\"document\"\n className={sjtScenarioVariants({ size })}\n dangerouslySetInnerHTML={{ __html: sanitisedScenario }}\n />\n )}\n\n {/* Response options via existing RadioGroup + Radio */}\n <RadioGroup\n label={undefined}\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={describedByParts.length > 0 ? describedByParts.join(' ') : undefined}\n value={value ?? undefined}\n onChange={onChange}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n isRequired={isRequired}\n isInvalid={isInvalid}\n orientation=\"vertical\"\n variant=\"default\"\n size={size}\n >\n {sortedResponses.map((response: SJTResponse) => (\n <Radio key={response.value} value={response.value} isDisabled={false}>\n <div className=\"flex items-start gap-2\">\n <span className={sjtOrdinalVariants({ size })}>\n {ordinalToLetter(response.ordinal)}.\n </span>\n <span className=\"flex-1\">{response.text}</span>\n </div>\n </Radio>\n ))}\n </RadioGroup>\n\n {/* Error message */}\n {isInvalid && errorMessage && (\n <div\n id={errorId}\n role=\"alert\"\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n {errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\n\nSituationalJudgement.displayName = \"SituationalJudgement\";\n\nexport { SituationalJudgement, sanitiseHtml };\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';\n\n/**\n * SituationalJudgement size schema\n */\nexport const SJTSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type SJTSize = z.infer<typeof SJTSizeSchema>;\n\n/**\n * Individual response option schema\n */\nexport const SJTResponseSchema = z.object({\n value: z.string(),\n text: z.string(),\n ordinal: z.number(),\n});\n\nexport type SJTResponse = z.infer<typeof SJTResponseSchema>;\n\n/**\n * SituationalJudgement props schema\n *\n * Assessment component presenting a scenario with 3-6 response options.\n * Composes existing RadioGroup + Radio for response selection\n * and Accordion for collapsible scenario panel.\n *\n * Uses .refine() to enforce unique response values — requires getShape()\n * helper from test-utils.ts in contract tests.\n */\nexport const SituationalJudgementPropsSchema = BaseComponentPropsSchema.extend({\n // Value — the selected response value\n value: z.string().nullable().optional(),\n onChange: z.custom<(value: string) => void>().optional(),\n\n // Scenario\n scenarioText: z.string(),\n collapsibleScenario: z.boolean().optional().default(false),\n\n // Responses (3-6 options)\n responses: z.array(SJTResponseSchema).min(3).max(6),\n\n // Labels\n label: z.string().optional(),\n description: z.string().optional(),\n errorMessage: z.string().optional(),\n\n // State\n isRequired: z.boolean().optional().default(false),\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n isInvalid: z.boolean().optional().default(false),\n\n // Sizing\n size: SJTSizeSchema.optional().default('default'),\n}).refine(\n (data) => {\n const values = data.responses.map((r) => r.value);\n return new Set(values).size === values.length;\n },\n { message: 'Response values must be unique', path: ['responses'] },\n);\n\nexport interface SituationalJudgementProps {\n className?: string;\n children?: unknown;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n value?: string | null;\n onChange?: (value: string) => void;\n scenarioText: string;\n collapsibleScenario?: boolean;\n responses: SJTResponse[];\n label?: string;\n description?: string;\n errorMessage?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n isInvalid?: boolean;\n size?: SJTSize;\n}\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/styles/interaction-states.ts","../../../src/elements/RadioGroup/RadioGroup.tsx","../../../src/elements/Accordion/Accordion.tsx","../../../src/elements/SituationalJudgement/SituationalJudgement.styles.ts","../../../src/elements/SituationalJudgement/SituationalJudgement.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/SituationalJudgement/SituationalJudgement.types.ts"],"names":["cn","inputs","twMerge","clsx","FOCUS_STYLES","HIGH_CONTRAST_FOCUS","RadioGroupContext","createContext","radioGroupVariants","cva","radioItemVariants","radioIndicatorVariants","radioInnerDotVariants","RadioLabel","children","className","jsx","RadioDescription","RadioComponent","value","isDisabled","variant","size","isInvalid","useContext","AriaRadio","renderProps","jsxs","Fragment","Radio","RadioGroup","forwardRef","props","ref","label","description","errorMessage","defaultValue","isReadOnly","isRequired","orientation","name","onChange","onFocusChange","id","ariaLabel","ariaLabelledby","ariaDescribedby","dataTestId","restProps","generatedId","useId","radioGroupId","labelId","descriptionId","errorId","describedByParts","computedAriaDescribedBy","AriaRadioGroup","Label","Text","FieldError","Activity","ReactActivity","mode","AccordionContext","accordionVariants","accordionItemVariants","accordionTriggerVariants","accordionChevronVariants","accordionContentVariants","accordionContentInnerVariants","getHeadingLevel","level","getFirstAccordionItemId","childArray","Children","child","isValidElement","childProps","AccordionRoot","type","collapsible","expandedKeys","defaultExpandedKeys","onExpandedChange","disabledKeys","allowsMultipleExpanded","effectiveDefaultExpandedKeys","useMemo","firstItemId","contextValue","DisclosureGroup","AccordionItemComponent","isDisabledProp","disabledKeysSet","isDisabledFromKeys","Disclosure","composeRenderProps","AccordionTriggerComponent","headingLevel","icon","hideIcon","isExpanded","DisclosureStateContext","Heading","Button","ChevronDown","AccordionContentInner","preserveState","AccordionContentComponent","DisclosurePanel","Accordion","AccordionItem","AccordionTrigger","AccordionContent","sjtContainerVariants","sjtScenarioVariants","sjtOrdinalVariants","ALLOWED_TAGS","sanitiseHtml","html","doc","walkNode","node","escapeHtml","el","tagName","childHtml","result","text","ordinalToLetter","ordinal","SituationalJudgement","scenarioText","collapsibleScenario","responses","groupId","scenarioId","sortedResponses","a","b","sanitisedScenario","response","BaseComponentPropsSchema","z","SJTSizeSchema","SJTResponseSchema","SituationalJudgementPropsSchema","data","values","r"],"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 * Global Interaction State Styles\n *\n * Consistent interaction patterns across all Themis components.\n * These styles ensure WCAG 2.2 AAA compliance and predictable UX.\n *\n * @see spec.md FR-010 (Visible focus ring for keyboard navigation)\n * @see spec.md FR-031 (Pressed state feedback)\n * @see spec.md FR-012 (High contrast mode support)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\n/**\n * Focus state styles (FR-010)\n * Visible focus ring for keyboard navigation - WCAG 2.2 Level AAA\n *\n * Components can override by extending these styles:\n * @example\n * cn(FOCUS_STYLES, \"ring-4\") // Increases ring width to 4px\n */\nexport const FOCUS_STYLES = \"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2\";\n\n/**\n * Pressed/Active state styles (FR-031)\n * Visual feedback for press interactions\n *\n * Components can override the scale amount:\n * @example\n * cn(PRESSED_STYLES_BASE, \"data-[pressed]:scale-[0.95]\") // More pronounced scale\n */\nexport const PRESSED_STYLES = \"data-[pressed]:scale-[0.97]\";\n\n/**\n * Base pressed styles without scale (for components that need different feedback)\n */\nexport const PRESSED_STYLES_BASE = \"data-[pressed]:transition-transform data-[pressed]:duration-100\";\n\n/**\n * Hover state styles\n * Elevation change on hover for better affordance\n *\n * Components can override shadow depth:\n * @example\n * cn(HOVER_STYLES_BASE, \"data-[hovered]:shadow-lg\") // Larger shadow\n */\nexport const HOVER_STYLES = \"\";\n\n/**\n * Base hover styles without shadow (for components that use different hover effects)\n */\nexport const HOVER_STYLES_BASE = \"data-[hovered]:transition-shadow data-[hovered]:duration-200\";\n\n/**\n * High contrast mode focus (FR-012)\n * Enhanced outlines for users requiring high contrast\n *\n * Uses 'hc:' prefix for prefers-contrast: more media query\n */\nexport const HIGH_CONTRAST_FOCUS = \"hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground\";\n\n/**\n * High contrast mode hover (FR-012)\n * Enhanced outlines for hover in high contrast mode\n */\nexport const HIGH_CONTRAST_HOVER = \"hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground\";\n\n/**\n * High contrast mode pressed state\n * Enhanced outlines for pressed state in high contrast mode\n */\nexport const HIGH_CONTRAST_PRESSED = \"hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground\";\n\n/**\n * Combined high contrast styles\n * Use this for components that need all high contrast interaction states\n */\nexport const HIGH_CONTRAST_INTERACTIONS = `${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Disabled state styles\n * Consistent disabled appearance across all components\n */\nexport const DISABLED_STYLES = \"disabled:pointer-events-none disabled:opacity-50\";\n\n/**\n * Default interaction bundle\n * Most common combination for interactive components\n *\n * Includes: focus ring, pressed scale, hover shadow, high contrast enhancements\n *\n * @example\n * <button className={cn(DEFAULT_INTERACTIONS, \"bg-primary\")}>Click</button>\n */\nexport const DEFAULT_INTERACTIONS = `${FOCUS_STYLES} ${PRESSED_STYLES} ${HOVER_STYLES} ${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Subtle interaction bundle\n * For components that need less pronounced feedback\n *\n * Includes: focus ring and high contrast, but no hover shadow or pressed scale\n */\nexport const SUBTLE_INTERACTIONS = `${FOCUS_STYLES} ${HIGH_CONTRAST_FOCUS}`;\n\n/**\n * Non-interactive element styles\n * For elements that should indicate they are not interactive\n */\nexport const NON_INTERACTIVE = \"cursor-default select-none\";\n","\"use client\";\n\n/**\n * RadioGroup Component\n * Accessible single-selection radio group with React Aria primitives and CVA styling\n *\n * Key Features:\n * - Bordered container design with explicit 44px+ touch targets\n * - 2 variants: default, destructive (no outline per clarification)\n * - 3 sizes: sm (44px), default (48px), lg (56px)\n * - Arrow keys move focus AND select (WAI-ARIA standard selection-follows-focus)\n * - Error styling on ALL items (cognitive accessibility)\n * - Spring animation for selection indicator\n * - RTL support (indicator auto-flips)\n * - Radio.Label and Radio.Description sub-components\n *\n * @see radiogroup-prd.md (Product Requirements)\n * @see plan.md (11 Key Clarifications)\n * @see React Aria RadioGroup: https://react-spectrum.adobe.com/react-aria/RadioGroup.html\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AAA)\n */\n\nimport {\n forwardRef,\n createContext,\n useContext,\n useId,\n type ReactNode,\n type ForwardedRef,\n} from 'react';\nimport {\n RadioGroup as AriaRadioGroup,\n Radio as AriaRadio,\n Label,\n Text,\n FieldError,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { FOCUS_STYLES, HIGH_CONTRAST_FOCUS } from '../../styles/interaction-states';\nimport type {\n RadioGroupProps,\n RadioProps,\n RadioLabelProps,\n RadioDescriptionProps,\n RadioGroupVariant,\n RadioGroupSize,\n} from './RadioGroup.types';\n\n// ============================================================================\n// Context\n// ============================================================================\n\ninterface RadioGroupContextValue {\n variant: RadioGroupVariant;\n size: RadioGroupSize;\n isInvalid: boolean;\n}\n\nconst RadioGroupContext = createContext<RadioGroupContextValue>({\n variant: 'default',\n size: 'default',\n isInvalid: false,\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * RadioGroup container variants\n * Controls orientation and spacing (gap-2 = 8px per clarification)\n */\nconst radioGroupVariants = cva(\n // Base: flex container\n \"flex\",\n {\n variants: {\n orientation: {\n vertical: \"flex-col gap-2\",\n horizontal: \"flex-row flex-wrap gap-2\",\n },\n },\n defaultVariants: {\n orientation: \"vertical\",\n },\n }\n);\n\n/**\n * Radio item bordered container variants\n * Bordered container design with explicit touch targets\n * All sizes maintain 44px minimum height (WCAG 2.2 AAA)\n * All sizes use rounded-md (6px) per clarification\n */\nconst radioItemVariants = cva(\n // Base: bordered container with flex layout, RTL support.\n // `relative` is load-bearing: React Aria renders the real <input> inside a\n // VisuallyHidden span (position:absolute, auto offsets). Without a positioned\n // ancestor its containing block becomes the document, so the input is laid out\n // at its static Y deep in tall scroll content and EXTENDS the page's scroll\n // height — a phantom blank band + a second (window) scrollbar. `relative`\n // confines the hidden input to this radio item box.\n [\n \"relative flex items-center gap-3 rounded-md border cursor-pointer\",\n \"transition-colors duration-200\",\n \"rtl:flex-row-reverse\", // RTL: indicator flips to right\n // Focus ring on entire container\n FOCUS_STYLES,\n HIGH_CONTRAST_FOCUS,\n ].join(\" \"),\n {\n variants: {\n variant: {\n default: [\n \"border-[var(--border)]\",\n \"data-[hovered]:bg-[var(--accent)]/10\",\n \"data-[selected]:border-[var(--primary)]\",\n \"data-[selected]:bg-[var(--primary)]/10\",\n ].join(\" \"),\n destructive: [\n \"border-[var(--border)]\",\n \"data-[hovered]:bg-[var(--destructive-background)]/10\",\n \"data-[selected]:border-[var(--destructive-background)]\",\n \"data-[selected]:bg-[var(--destructive-background)]/10\",\n ].join(\" \"),\n },\n size: {\n sm: \"min-h-[44px] py-2 px-3 text-sm\",\n default: \"min-h-[48px] py-3 px-4 text-sm\",\n lg: \"min-h-[56px] py-4 px-5 text-base\",\n },\n isDisabled: {\n true: \"opacity-50 cursor-not-allowed\",\n false: \"\",\n },\n isInvalid: {\n // Error: ALL items get destructive border (cognitive accessibility)\n true: \"border-[var(--destructive-background)]\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n isDisabled: false,\n isInvalid: false,\n },\n }\n);\n\n/**\n * Circle indicator (outer ring) variants\n */\nconst radioIndicatorVariants = cva(\n // Base: circle with border, flex-shrink-0 to prevent squishing\n \"flex-shrink-0 rounded-full border-2 flex items-center justify-center transition-colors duration-200\",\n {\n variants: {\n variant: {\n default: [\n \"border-[var(--border)]\",\n \"data-[selected]:border-[var(--primary)]\",\n ].join(\" \"),\n destructive: [\n \"border-[var(--border)]\",\n \"data-[selected]:border-[var(--destructive-background)]\",\n ].join(\" \"),\n },\n size: {\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n/**\n * Inner dot variants (appears when selected)\n * Spring animation: cubic-bezier(0.34, 1.56, 0.64, 1) with slight overshoot\n */\nconst radioInnerDotVariants = cva(\n // Base: centered dot with spring animation\n [\n \"rounded-full transition-transform duration-200\",\n // Spring animation with overshoot\n \"[transition-timing-function:cubic-bezier(0.34,1.56,0.64,1)]\",\n // Respect reduced motion preference\n \"motion-reduce:transition-none\",\n // Scale from 0 to 1 on selection\n \"scale-0 data-[selected]:scale-100\",\n ].join(\" \"),\n {\n variants: {\n variant: {\n default: \"bg-[var(--primary)]\",\n destructive: \"bg-[var(--destructive-background)]\",\n },\n size: {\n sm: \"h-2 w-2\",\n default: \"h-2.5 w-2.5\",\n lg: \"h-3 w-3\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n// ============================================================================\n// Sub-components\n// ============================================================================\n\n/**\n * Radio.Label - Styled label for radio item content\n */\nfunction RadioLabel({ children, className }: RadioLabelProps): ReactNode {\n return (\n <span className={cn(\"font-medium text-[var(--content-foreground)]\", className)}>\n {children}\n </span>\n );\n}\n\nRadioLabel.displayName = \"Radio.Label\";\n\n/**\n * Radio.Description - Styled description for radio item content (muted)\n */\nfunction RadioDescription({ children, className }: RadioDescriptionProps): ReactNode {\n return (\n <span className={cn(\"text-sm text-[var(--menu-muted)]\", className)}>\n {children}\n </span>\n );\n}\n\nRadioDescription.displayName = \"Radio.Description\";\n\n// ============================================================================\n// Radio Component\n// ============================================================================\n\n/**\n * Radio item component with bordered container design\n */\nfunction RadioComponent({ value, isDisabled, children, className }: RadioProps): ReactNode {\n const { variant, size, isInvalid } = useContext(RadioGroupContext);\n\n return (\n <AriaRadio\n value={value}\n isDisabled={isDisabled}\n className={(renderProps) =>\n cn(\n radioItemVariants({\n variant,\n size,\n isDisabled: renderProps.isDisabled,\n isInvalid,\n }),\n className\n )\n }\n >\n {(renderProps) => (\n <>\n {/* Circle indicator */}\n <div\n className={radioIndicatorVariants({ variant, size })}\n data-selected={renderProps.isSelected || undefined}\n >\n {/* Inner dot with spring animation */}\n <div\n className={radioInnerDotVariants({ variant, size })}\n data-selected={renderProps.isSelected || undefined}\n />\n </div>\n\n {/* Children content (flexible - text, icons, complex layouts) */}\n <div className=\"flex-1 flex flex-col\">\n {children}\n </div>\n </>\n )}\n </AriaRadio>\n );\n}\n\n// Attach sub-components\nconst Radio = Object.assign(RadioComponent, {\n Label: RadioLabel,\n Description: RadioDescription,\n}) as typeof RadioComponent & {\n Label: typeof RadioLabel;\n Description: typeof RadioDescription;\n displayName: string;\n};\n\nRadio.displayName = \"Radio\";\n\n// ============================================================================\n// RadioGroup Component\n// ============================================================================\n\n/**\n * RadioGroup root component\n * Accessible single-selection control with bordered container design\n */\nconst RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(\n function RadioGroup(props: RadioGroupProps, ref: ForwardedRef<HTMLDivElement>) {\n const {\n // Display props\n label,\n description,\n errorMessage,\n // Selection props\n value,\n defaultValue,\n // State props\n isDisabled = false,\n isReadOnly = false,\n isRequired = false,\n isInvalid = false,\n // Layout props\n orientation = 'vertical',\n // Variant props\n variant = 'default',\n size = 'default',\n // Form props\n name,\n // Event handlers\n onChange,\n onFocusChange,\n // Standard props\n className,\n children,\n id,\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledby,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n ...restProps\n } = props;\n\n // Generate unique IDs for accessibility\n const generatedId = useId();\n const radioGroupId = id ?? generatedId;\n const labelId = `${radioGroupId}-label`;\n const descriptionId = `${radioGroupId}-description`;\n const errorId = `${radioGroupId}-error`;\n\n // Build aria-describedby from description and error\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n const computedAriaDescribedBy = describedByParts.length > 0\n ? describedByParts.join(' ')\n : undefined;\n\n return (\n <RadioGroupContext.Provider value={{ variant, size, isInvalid }}>\n <AriaRadioGroup\n ref={ref}\n id={radioGroupId}\n name={name}\n value={value ?? undefined}\n defaultValue={defaultValue ?? undefined}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n isRequired={isRequired}\n isInvalid={isInvalid}\n orientation={orientation}\n onChange={onChange}\n onFocusChange={onFocusChange}\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : ariaLabelledby}\n aria-describedby={computedAriaDescribedBy}\n data-testid={dataTestId}\n data-orientation={orientation}\n className={cn(\"flex flex-col gap-1.5\", className)}\n {...restProps}\n >\n {/* Label with optional required asterisk */}\n {label && (\n <Label id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </Label>\n )}\n\n {/* Description */}\n {description && (\n <Text\n id={descriptionId}\n slot=\"description\"\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </Text>\n )}\n\n {/* Radio items container with orientation */}\n <div className={radioGroupVariants({ orientation })}>\n {children}\n </div>\n\n {/* Error message with role=\"alert\" for screen reader announcements */}\n {isInvalid && errorMessage && (\n <FieldError\n id={errorId}\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n <span role=\"alert\">{errorMessage}</span>\n </FieldError>\n )}\n </AriaRadioGroup>\n </RadioGroupContext.Provider>\n );\n }\n);\n\nRadioGroup.displayName = \"RadioGroup\";\n\n// ============================================================================\n// Exports\n// ============================================================================\n\nexport {\n RadioGroup,\n Radio,\n radioGroupVariants,\n radioItemVariants,\n radioIndicatorVariants,\n radioInnerDotVariants,\n};\n","'use client';\n\n/**\n * Accordion Component - Implementation\n *\n * Accessible accordion/disclosure group component combining React Aria primitives with CVA styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria DisclosureGroup for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for consistent styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Single/Multiple expansion modes\n * - Controlled and uncontrolled state management\n * - Configurable heading levels for document structure\n * - Custom icon support\n *\n * @see accordion-prd.md (Full requirements)\n * @see Accordion.types.ts (Zod schemas)\n * @see plan.md (Implementation approach)\n */\n\n// React 19.2 Activity API - may not be available in all builds\n// Import conditionally to support environments where Activity is unavailable\nimport {\n Activity as ReactActivity,\n type ReactNode,\n type ReactElement,\n useMemo,\n useContext,\n createContext,\n Children,\n isValidElement,\n} from 'react';\n\n// Activity component with fallback for environments where it's not available\n// The fallback simply renders children directly - no state preservation when Activity unavailable\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n return <div data-activity-mode={mode}>{children}</div>;\n};\n\nimport {\n DisclosureGroup,\n Disclosure,\n DisclosurePanel,\n Heading,\n Button,\n composeRenderProps,\n DisclosureStateContext,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { ChevronDown } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport type {\n AccordionProps,\n AccordionItemProps,\n AccordionTriggerProps,\n AccordionContentProps,\n HeadingLevel,\n} from './Accordion.types';\n\n// ============================================================================\n// Context for disabledKeys\n// ============================================================================\n\n/**\n * Context to pass disabledKeys from Accordion to AccordionItem\n * Since DisclosureGroup doesn't support disabledKeys directly, we handle it via context\n */\ninterface AccordionContextValue {\n disabledKeysSet?: Set<string | number>;\n}\n\nconst AccordionContext = createContext<AccordionContextValue>({});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * Accordion root CVA variants\n *\n * @see accordion-prd.md FR-001 (Accordion Root)\n */\nexport const accordionVariants = cva('w-full', {\n variants: {},\n defaultVariants: {},\n});\n\n/**\n * AccordionItem CVA variants\n *\n * @see accordion-prd.md FR-002 (AccordionItem)\n * @see accordion-prd.md DS-001 (Visual Design - borders)\n */\nexport const accordionItemVariants = cva(\n [\n 'border-b border-[var(--border)]',\n // Last item has no border (handled by last:border-b-0)\n 'last:border-b-0',\n ].join(' '),\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * AccordionTrigger CVA variants\n *\n * @see accordion-prd.md FR-003 (AccordionTrigger)\n * @see accordion-prd.md AR-006 (Touch Target Size - 44x44px)\n * @see accordion-prd.md DS-002 (Typography)\n */\nexport const accordionTriggerVariants = cva(\n [\n // Layout\n 'flex flex-1 items-center justify-between py-4 font-medium w-full',\n // Text styling\n 'text-sm text-[var(--content-foreground)]',\n // Hover state\n 'hover:underline',\n // Focus visible ring (WCAG 2.4.13)\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n 'focus-visible:ring-offset-[var(--content-background)]',\n // WCAG 2.2 AAA: 44px minimum touch target\n 'min-h-[44px]',\n // Disabled state\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // Transition for smooth interactions\n 'transition-colors',\n ].join(' '),\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Chevron icon CVA variants\n *\n * @see accordion-prd.md FR-010 (Animated Transitions)\n */\nexport const accordionChevronVariants = cva(\n [\n 'h-4 w-4 shrink-0',\n 'text-[var(--menu-muted)]',\n // Smooth rotation transition\n 'transition-transform duration-200 ease-out',\n // Reduced motion support\n 'motion-reduce:transition-none',\n ].join(' '),\n {\n variants: {\n isExpanded: {\n true: 'rotate-180',\n false: 'rotate-0',\n },\n },\n defaultVariants: {\n isExpanded: false,\n },\n }\n);\n\n/**\n * AccordionContent CVA variants\n *\n * @see accordion-prd.md FR-004 (AccordionContent)\n * @see accordion-prd.md FR-010 (Animated Transitions)\n */\nexport const accordionContentVariants = cva(\n [\n 'overflow-hidden',\n 'text-sm text-[var(--menu-muted)]',\n ].join(' '),\n {\n variants: {\n isExpanded: {\n true: 'motion-safe:animate-in motion-safe:fade-in-0 motion-safe:slide-in-from-top-2 motion-safe:[animation-duration:250ms] motion-safe:[animation-timing-function:cubic-bezier(0.16,1,0.3,1)]',\n false: '',\n },\n },\n defaultVariants: {\n isExpanded: false,\n },\n }\n);\n\n/**\n * AccordionContent inner wrapper CVA variants\n */\nexport const accordionContentInnerVariants = cva('pb-4 pt-0', {\n variants: {},\n defaultVariants: {},\n});\n\n// ============================================================================\n// Helper Functions\n// ============================================================================\n\n/**\n * Convert heading level string to number for React Aria Heading\n */\nfunction getHeadingLevel(level: HeadingLevel): 1 | 2 | 3 | 4 | 5 | 6 {\n const levelMap: Record<HeadingLevel, 1 | 2 | 3 | 4 | 5 | 6> = {\n h1: 1,\n h2: 2,\n h3: 3,\n h4: 4,\n h5: 5,\n h6: 6,\n };\n return levelMap[level];\n}\n\n/**\n * Get the first AccordionItem id from children\n * Used for auto-expanding first item when collapsible={false}\n */\nfunction getFirstAccordionItemId(children: ReactNode): AriaKey | undefined {\n const childArray = Children.toArray(children);\n for (const child of childArray) {\n if (isValidElement(child)) {\n const childProps = child.props as Record<string, unknown>;\n if (childProps && typeof childProps === 'object' && 'id' in childProps) {\n return childProps.id as AriaKey;\n }\n }\n }\n return undefined;\n}\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Accordion Root Component\n *\n * Container for accordion items. Manages expansion state and provides\n * context to child components.\n *\n * @see accordion-prd.md FR-001 (Accordion Root Component)\n * @see accordion-prd.md FR-005 (Single Expansion Mode)\n * @see accordion-prd.md FR-006 (Multiple Expansion Mode)\n * @see accordion-prd.md FR-007 (Controlled Mode)\n * @see accordion-prd.md FR-008 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled single mode\n * <Accordion type=\"single\" collapsible>\n * <AccordionItem id=\"item-1\">\n * <AccordionTrigger>Section 1</AccordionTrigger>\n * <AccordionContent>Content 1</AccordionContent>\n * </AccordionItem>\n * </Accordion>\n *\n * @example\n * // Controlled multiple mode\n * <Accordion\n * type=\"multiple\"\n * expandedKeys={expandedKeys}\n * onExpandedChange={setExpandedKeys}\n * >\n * ...\n * </Accordion>\n */\nfunction AccordionRoot({\n type = 'single',\n collapsible = false,\n expandedKeys,\n defaultExpandedKeys,\n onExpandedChange,\n isDisabled = false,\n disabledKeys,\n className,\n children,\n ...props\n}: AccordionProps) {\n // Map type prop to React Aria's allowsMultipleExpanded\n const allowsMultipleExpanded = type === 'multiple';\n\n // Auto-expand first item when collapsible={false} and no default provided\n // This ensures one item is always expanded in non-collapsible single mode\n const effectiveDefaultExpandedKeys = useMemo(() => {\n if (!collapsible && type === 'single' && !defaultExpandedKeys && !expandedKeys) {\n const firstItemId = getFirstAccordionItemId(children);\n return firstItemId ? [firstItemId] : undefined;\n }\n return defaultExpandedKeys;\n }, [collapsible, type, defaultExpandedKeys, expandedKeys, children]);\n\n // Context value for passing disabledKeys to AccordionItem (Set for O(1) lookups)\n const contextValue = useMemo(\n () => ({ disabledKeysSet: disabledKeys ? new Set(disabledKeys) : undefined }),\n [disabledKeys]\n );\n\n return (\n <AccordionContext.Provider value={contextValue}>\n <DisclosureGroup\n allowsMultipleExpanded={allowsMultipleExpanded}\n expandedKeys={expandedKeys as Set<AriaKey> | undefined}\n defaultExpandedKeys={effectiveDefaultExpandedKeys as Iterable<AriaKey> | undefined}\n onExpandedChange={onExpandedChange as ((keys: Set<AriaKey>) => void) | undefined}\n isDisabled={isDisabled}\n className={cn(accordionVariants(), className)}\n {...props}\n >\n {children}\n </DisclosureGroup>\n </AccordionContext.Provider>\n );\n}\n\nAccordionRoot.displayName = 'Accordion';\n\n/**\n * AccordionItem Component\n *\n * Wrapper for each expandable disclosure section.\n *\n * @see accordion-prd.md FR-002 (AccordionItem Component)\n *\n * @example\n * <AccordionItem id=\"faq-1\" isDisabled={!isAuthenticated}>\n * <AccordionTrigger>Members-only FAQ</AccordionTrigger>\n * <AccordionContent>This content is for members only.</AccordionContent>\n * </AccordionItem>\n */\nfunction AccordionItemComponent({\n id,\n isDisabled: isDisabledProp,\n className,\n children,\n ...props\n}: AccordionItemProps) {\n // Check if this item is in the disabledKeys set (O(1) lookup)\n const { disabledKeysSet } = useContext(AccordionContext);\n const isDisabledFromKeys = disabledKeysSet?.has(id as string | number) ?? false;\n const isDisabled = isDisabledProp || isDisabledFromKeys;\n\n return (\n <Disclosure\n id={id}\n isDisabled={isDisabled}\n className={composeRenderProps(className, (className) =>\n cn(accordionItemVariants(), className)\n )}\n {...props}\n >\n {children}\n </Disclosure>\n );\n}\n\nAccordionItemComponent.displayName = 'AccordionItem';\n\n/**\n * AccordionTrigger Component\n *\n * Clickable button that toggles accordion content visibility.\n * Wrapped in a Heading for proper document structure.\n *\n * @see accordion-prd.md FR-003 (AccordionTrigger Component)\n * @see accordion-prd.md AR-002 (ARIA Attributes)\n * @see accordion-prd.md AR-003 (Keyboard Navigation)\n *\n * @example\n * // Default with chevron\n * <AccordionTrigger>Is it accessible?</AccordionTrigger>\n *\n * @example\n * // Custom heading level\n * <AccordionTrigger as=\"h2\">Important Section</AccordionTrigger>\n *\n * @example\n * // Custom icon\n * <AccordionTrigger icon={<PlusIcon className=\"h-4 w-4\" />}>\n * Click to expand\n * </AccordionTrigger>\n */\nfunction AccordionTriggerComponent({\n as: headingLevel = 'h3',\n icon,\n hideIcon = false,\n className,\n children,\n ...props\n}: AccordionTriggerProps) {\n // Access disclosure state from context\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n return (\n <Heading level={getHeadingLevel(headingLevel)}>\n <Button\n slot=\"trigger\"\n className={composeRenderProps(className, (className) =>\n cn(accordionTriggerVariants(), className)\n )}\n {...props}\n >\n <span className=\"flex-1 text-left\">{children}</span>\n {!hideIcon && (\n icon ?? (\n <ChevronDown\n aria-hidden=\"true\"\n className={cn(accordionChevronVariants({ isExpanded }))}\n />\n )\n )}\n </Button>\n </Heading>\n );\n}\n\nAccordionTriggerComponent.displayName = 'AccordionTrigger';\n\n/**\n * AccordionContent Component\n *\n * Expandable container for accordion content.\n * Supports animated height transitions and React Activity state preservation.\n *\n * @see accordion-prd.md FR-004 (AccordionContent Component)\n * @see accordion-prd.md FR-010 (Animated Transitions)\n *\n * @example\n * // Standard content\n * <AccordionContent>\n * Yes. It adheres to the WAI-ARIA design pattern.\n * </AccordionContent>\n *\n * @example\n * // With state preservation\n * <AccordionContent preserveState>\n * <form>\n * <input name=\"email\" />\n * </form>\n * </AccordionContent>\n */\n/**\n * Inner component for AccordionContent with state preservation\n * Uses DisclosureStateContext to get isExpanded state\n */\nfunction AccordionContentInner({\n preserveState,\n children,\n}: {\n preserveState: boolean;\n children: ReactNode;\n}) {\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n if (preserveState) {\n return (\n <Activity mode={isExpanded ? 'visible' : 'hidden'}>\n <div className={accordionContentInnerVariants()}>{children}</div>\n </Activity>\n );\n }\n\n return <div className={accordionContentInnerVariants()}>{children}</div>;\n}\n\nfunction AccordionContentComponent({\n preserveState = false,\n className,\n children,\n ...props\n}: AccordionContentProps) {\n const state = useContext(DisclosureStateContext);\n const isExpanded = state?.isExpanded ?? false;\n\n return (\n <DisclosurePanel\n className={composeRenderProps(className, (className) =>\n cn(accordionContentVariants({ isExpanded }), className)\n )}\n {...props}\n >\n <AccordionContentInner preserveState={preserveState}>\n {children}\n </AccordionContentInner>\n </DisclosurePanel>\n );\n}\n\nAccordionContentComponent.displayName = 'AccordionContent';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Accordion follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Accordion, AccordionItem, AccordionTrigger, AccordionContent } from '...'\n */\nexport const Accordion = AccordionRoot;\nexport const AccordionItem = AccordionItemComponent;\nexport const AccordionTrigger = AccordionTriggerComponent;\nexport const AccordionContent = AccordionContentComponent;\n\n// Re-export types for convenience\nexport type {\n AccordionProps,\n AccordionItemProps,\n AccordionTriggerProps,\n AccordionContentProps,\n};\n","import { cva } from 'class-variance-authority';\n\n/**\n * SituationalJudgement CVA Variant Definitions\n *\n * Minimal styling since this component composes existing RadioGroup, Radio,\n * and Accordion components. These variants cover the container and scenario panel.\n */\n\n// =============================================================================\n// Container\n// =============================================================================\n\n/** Root wrapper */\nexport const sjtContainerVariants = cva(\"flex flex-col gap-3\", {\n variants: {\n size: {\n sm: \"text-sm\",\n default: \"text-sm\",\n lg: \"text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n});\n\n// =============================================================================\n// Scenario Panel\n// =============================================================================\n\n/** Scenario text panel (non-collapsible mode) */\nexport const sjtScenarioVariants = cva(\n [\n \"rounded-md border border-[var(--border)]\",\n \"bg-[var(--muted)] text-[var(--content-foreground)]\",\n ].join(\" \"),\n {\n variants: {\n size: {\n sm: \"p-3 text-sm\",\n default: \"p-4 text-sm\",\n lg: \"p-5 text-base\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n\n/** Ordinal letter label (\"A.\", \"B.\", etc.) */\nexport const sjtOrdinalVariants = cva(\n \"font-semibold text-[var(--muted-foreground)] flex-shrink-0\",\n {\n variants: {\n size: {\n sm: \"text-xs w-5\",\n default: \"text-sm w-6\",\n lg: \"text-base w-7\",\n },\n },\n defaultVariants: { size: \"default\" },\n }\n);\n","\"use client\";\n\n/**\n * SituationalJudgement Component\n *\n * Assessment component presenting a scenario with 3-6 response options.\n * Composes existing Themis RadioGroup + Radio for response selection\n * and Accordion for collapsible scenario panel.\n *\n * Features:\n * - HTML scenario text with built-in sanitiser (XSS protection)\n * - Collapsible scenario via Accordion\n * - Responses sorted by ordinal, labeled with letters (A, B, C, ...)\n * - Standard radio group behaviour (no deselection)\n *\n * @see WCAG 2.2 AAA — 44x44px touch targets, keyboard navigation\n */\n\nimport {\n forwardRef,\n useId,\n useMemo,\n type ForwardedRef,\n} from 'react';\nimport { Label, Text } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport { RadioGroup, Radio } from '../RadioGroup/RadioGroup';\nimport {\n Accordion,\n AccordionItem,\n AccordionTrigger,\n AccordionContent,\n} from '../Accordion/Accordion';\nimport type { SituationalJudgementProps, SJTResponse } from './SituationalJudgement.types';\nimport {\n sjtContainerVariants,\n sjtScenarioVariants,\n sjtOrdinalVariants,\n} from './SituationalJudgement.styles';\n\n// =============================================================================\n// HTML Sanitiser\n// =============================================================================\n\nconst ALLOWED_TAGS = new Set([\n 'b', 'strong', 'i', 'em', 'ul', 'ol', 'li', 'p', 'br',\n]);\n\n/**\n * Sanitise HTML string using DOMParser.\n * Only preserves allowed tags, strips ALL attributes.\n * Returns clean HTML safe for dangerouslySetInnerHTML.\n */\nfunction sanitiseHtml(html: string): string {\n if (typeof window === 'undefined' || typeof DOMParser === 'undefined') {\n // SSR fallback: strip all HTML tags\n return html.replace(/<[^>]*>/g, '');\n }\n\n const parser = new DOMParser();\n const doc = parser.parseFromString(html, 'text/html');\n\n function walkNode(node: Node): string {\n if (node.nodeType === Node.TEXT_NODE) {\n return escapeHtml(node.textContent ?? '');\n }\n\n if (node.nodeType === Node.ELEMENT_NODE) {\n const el = node as Element;\n const tagName = el.tagName.toLowerCase();\n\n if (!ALLOWED_TAGS.has(tagName)) {\n // Strip disallowed tag but process children\n let childHtml = '';\n for (const child of Array.from(el.childNodes)) {\n childHtml += walkNode(child);\n }\n return childHtml;\n }\n\n // Allowed tag — render without attributes\n let childHtml = '';\n for (const child of Array.from(el.childNodes)) {\n childHtml += walkNode(child);\n }\n\n if (tagName === 'br') {\n return '<br />';\n }\n\n return `<${tagName}>${childHtml}</${tagName}>`;\n }\n\n return '';\n }\n\n let result = '';\n for (const child of Array.from(doc.body.childNodes)) {\n result += walkNode(child);\n }\n return result;\n}\n\nfunction escapeHtml(text: string): string {\n return text\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;');\n}\n\n// =============================================================================\n// Helpers\n// =============================================================================\n\n/** Convert ordinal index to letter: 0 → \"A\", 1 → \"B\", etc. */\nfunction ordinalToLetter(ordinal: number): string {\n return String.fromCharCode(65 + ordinal);\n}\n\n// =============================================================================\n// SituationalJudgement Component\n// =============================================================================\n\nconst SituationalJudgement = forwardRef<HTMLDivElement, SituationalJudgementProps>(\n function SituationalJudgement(\n props: SituationalJudgementProps,\n ref: ForwardedRef<HTMLDivElement>,\n ) {\n const {\n // Value\n value,\n onChange,\n // Scenario\n scenarioText,\n collapsibleScenario = false,\n // Responses\n responses,\n // Labels\n label,\n description,\n errorMessage,\n // State\n isRequired = false,\n isDisabled = false,\n isReadOnly = false,\n isInvalid = false,\n // Sizing\n size = 'default',\n // Standard\n className,\n id,\n 'aria-label': ariaLabel,\n 'aria-describedby': ariaDescribedby,\n 'data-testid': dataTestId,\n } = props;\n\n const generatedId = useId();\n const groupId = id ?? generatedId;\n const labelId = `${groupId}-label`;\n const descriptionId = `${groupId}-description`;\n const errorId = `${groupId}-error`;\n const scenarioId = `${groupId}-scenario`;\n\n const describedByParts: string[] = [];\n if (ariaDescribedby) describedByParts.push(ariaDescribedby);\n if (description) describedByParts.push(descriptionId);\n if (scenarioText) describedByParts.push(scenarioId);\n if (isInvalid && errorMessage) describedByParts.push(errorId);\n\n // Sort responses by ordinal\n const sortedResponses = useMemo(\n () => [...responses].sort((a, b) => a.ordinal - b.ordinal),\n [responses],\n );\n\n // Sanitise scenario HTML\n const sanitisedScenario = useMemo(\n () => sanitiseHtml(scenarioText),\n [scenarioText],\n );\n\n return (\n <div\n ref={ref}\n id={groupId}\n aria-label={ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n data-testid={dataTestId}\n className={cn(sjtContainerVariants({ size }), className)}\n >\n {/* Label */}\n {label && (\n <Label id={labelId} className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n {isRequired && (\n <span className=\"ml-1 text-[var(--destructive-background)]\" aria-hidden=\"true\">\n *\n </span>\n )}\n </Label>\n )}\n\n {/* Description */}\n {description && (\n <Text\n id={descriptionId}\n slot=\"description\"\n className=\"text-sm text-[var(--menu-muted)]\"\n >\n {description}\n </Text>\n )}\n\n {/* Scenario Panel */}\n {collapsibleScenario ? (\n <Accordion type=\"single\" collapsible isDisabled={false} defaultExpandedKeys={['scenario']}>\n <AccordionItem id=\"scenario\">\n <AccordionTrigger as=\"h3\" hideIcon={false}>Scenario</AccordionTrigger>\n <AccordionContent preserveState={false}>\n <div\n id={scenarioId}\n className={sjtScenarioVariants({ size })}\n dangerouslySetInnerHTML={{ __html: sanitisedScenario }}\n />\n </AccordionContent>\n </AccordionItem>\n </Accordion>\n ) : (\n <div\n id={scenarioId}\n role=\"document\"\n className={sjtScenarioVariants({ size })}\n dangerouslySetInnerHTML={{ __html: sanitisedScenario }}\n />\n )}\n\n {/* Response options via existing RadioGroup + Radio */}\n <RadioGroup\n label={undefined}\n aria-label={label ? undefined : ariaLabel}\n aria-labelledby={label ? labelId : undefined}\n aria-describedby={describedByParts.length > 0 ? describedByParts.join(' ') : undefined}\n value={value ?? undefined}\n onChange={onChange}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n isRequired={isRequired}\n isInvalid={isInvalid}\n orientation=\"vertical\"\n variant=\"default\"\n size={size}\n >\n {sortedResponses.map((response: SJTResponse) => (\n <Radio key={response.value} value={response.value} isDisabled={false}>\n <div className=\"flex items-start gap-2\">\n <span className={sjtOrdinalVariants({ size })}>\n {ordinalToLetter(response.ordinal)}.\n </span>\n <span className=\"flex-1\">{response.text}</span>\n </div>\n </Radio>\n ))}\n </RadioGroup>\n\n {/* Error message */}\n {isInvalid && errorMessage && (\n <div\n id={errorId}\n role=\"alert\"\n className=\"text-sm text-[var(--destructive-background)]\"\n >\n {errorMessage}\n </div>\n )}\n </div>\n );\n },\n);\n\nSituationalJudgement.displayName = \"SituationalJudgement\";\n\nexport { SituationalJudgement, sanitiseHtml };\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';\n\n/**\n * SituationalJudgement size schema\n */\nexport const SJTSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type SJTSize = z.infer<typeof SJTSizeSchema>;\n\n/**\n * Individual response option schema\n */\nexport const SJTResponseSchema = z.object({\n value: z.string(),\n text: z.string(),\n ordinal: z.number(),\n});\n\nexport type SJTResponse = z.infer<typeof SJTResponseSchema>;\n\n/**\n * SituationalJudgement props schema\n *\n * Assessment component presenting a scenario with 3-6 response options.\n * Composes existing RadioGroup + Radio for response selection\n * and Accordion for collapsible scenario panel.\n *\n * Uses .refine() to enforce unique response values — requires getShape()\n * helper from test-utils.ts in contract tests.\n */\nexport const SituationalJudgementPropsSchema = BaseComponentPropsSchema.extend({\n // Value — the selected response value\n value: z.string().nullable().optional(),\n onChange: z.custom<(value: string) => void>().optional(),\n\n // Scenario\n scenarioText: z.string(),\n collapsibleScenario: z.boolean().optional().default(false),\n\n // Responses (3-6 options)\n responses: z.array(SJTResponseSchema).min(3).max(6),\n\n // Labels\n label: z.string().optional(),\n description: z.string().optional(),\n errorMessage: z.string().optional(),\n\n // State\n isRequired: z.boolean().optional().default(false),\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n isInvalid: z.boolean().optional().default(false),\n\n // Sizing\n size: SJTSizeSchema.optional().default('default'),\n}).refine(\n (data) => {\n const values = data.responses.map((r) => r.value);\n return new Set(values).size === values.length;\n },\n { message: 'Response values must be unique', path: ['responses'] },\n);\n\nexport interface SituationalJudgementProps {\n className?: string;\n children?: unknown;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n value?: string | null;\n onChange?: (value: string) => void;\n scenarioText: string;\n collapsibleScenario?: boolean;\n responses: SJTResponse[];\n label?: string;\n description?: string;\n errorMessage?: string;\n isRequired?: boolean;\n isDisabled?: boolean;\n isReadOnly?: boolean;\n isInvalid?: boolean;\n size?: SJTSize;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../src/elements/Switch/Switch.tsx"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,WAAW,IAAI,eAAe,EACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAsCzE;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,2FAOxB,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,mBAAmB;;;8EA2BxB,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB;;;8EAuBxB,CAAC;AAMF,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,UAAU,CAAC,EACrD,YAAY,CAAC,OAAO,mBAAmB,CAAC,EACxC,aAAa;IACf,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACpC,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;GAKG;AACH,QAAA,MAAM,MAAM,qGAuIV,CAAC;AAIH,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,CAAC"}
1
+ {"version":3,"file":"Switch.d.ts","sourceRoot":"","sources":["../../../src/elements/Switch/Switch.tsx"],"names":[],"mappings":"AAcA,OAAO,EAEL,KAAK,WAAW,IAAI,eAAe,EACpC,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAKlE,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAsCzE;;;;GAIG;AACH,QAAA,MAAM,mBAAmB,2FAOxB,CAAC;AAEF;;;;GAIG;AACH,QAAA,MAAM,mBAAmB;;;8EA2BxB,CAAC;AAEF;;;;;GAKG;AACH,QAAA,MAAM,mBAAmB;;;8EAuBxB,CAAC;AAMF,MAAM,WAAW,WACf,SAAQ,IAAI,CAAC,eAAe,EAAE,WAAW,GAAG,UAAU,CAAC,EACrD,YAAY,CAAC,OAAO,mBAAmB,CAAC,EACxC,aAAa;IACf,OAAO,CAAC,EAAE,SAAS,GAAG,aAAa,CAAC;IACpC,IAAI,CAAC,EAAE,IAAI,GAAG,SAAS,GAAG,IAAI,CAAC;IAC/B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,6EAA6E;IAC7E,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B;AAED;;;;;GAKG;AACH,QAAA,MAAM,MAAM,qGA+IV,CAAC;AAIH,OAAO,EAAE,MAAM,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,CAAC"}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),classVarianceAuthority=require('class-variance-authority'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function u(...a){return tailwindMerge.twMerge(clsx.clsx(a))}function y(a,o){return !(a===false||o)}var T="(prefers-reduced-motion: reduce)";function Q(){return typeof window>"u"?false:window.matchMedia(T).matches}function A(){let[a,o]=react.useState(Q);return react.useEffect(()=>{let i=window.matchMedia(T);o(i.matches);let r=c=>{o(c.matches);};return i.addEventListener("change",r),()=>i.removeEventListener("change",r)},[]),a}var R="data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2",X="data-[pressed]:scale-[0.97]";var S="hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground",P="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",N="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var C=`${R} ${X} ${S} ${P} ${N}`;var f;function ee(){return f!==void 0?Promise.resolve(f):import('motion').then(a=>(f=a.animate,f)).catch(()=>(f=null,null))}var te={stiffness:500,damping:30},_=classVarianceAuthority.cva("inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default",{variants:{},defaultVariants:{}}),k=classVarianceAuthority.cva("relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background",{variants:{variant:{default:"bg-[var(--border)] data-[selected]:bg-[var(--primary)]",destructive:"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]"},size:{sm:"h-6 w-10",default:"h-7 w-12",lg:"h-8 w-14"}},defaultVariants:{variant:"default",size:"default"}}),V=classVarianceAuthority.cva("pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0",{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},animated:{false:"transition-transform data-[selected]:translate-x-full",true:""}},defaultVariants:{size:"default",animated:false}}),L=react.memo(react.forwardRef(({className:a,variant:o,size:i,label:r,description:c,isDisabled:b,isReadOnly:w,animated:F,springConfig:p=te,onChange:v,...H},M)=>{let z=A(),d=y(F,z),s=react.useRef(null),x=react.useRef(false),h=react.useRef(null),E=react.useRef(null);react.useEffect(()=>{d&&ee().then(t=>{if(t&&(h.current=t,x.current=true,s.current)){let B=s.current.hasAttribute("data-selected");s.current.style.transform=B?"translateX(100%)":"translateX(0)";}});},[d]);let D=react.useCallback(t=>{v?.(t),d&&x.current&&h.current&&s.current&&(E.current?.stop(),E.current=h.current(s.current,{x:t?"100%":"0%"},{type:"spring",stiffness:p.stiffness,damping:p.damping}));},[d,p.stiffness,p.damping,v]),$=d;return jsxRuntime.jsx(reactAriaComponents.Switch,{ref:M,isDisabled:b,isReadOnly:w,onChange:D,className:t=>u("group inline-flex items-center gap-2",b&&"cursor-not-allowed opacity-50",a),...H,children:t=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:u(_()),"data-selected":t.isSelected||void 0,"data-readonly":w||void 0,children:jsxRuntime.jsx("div",{className:u(k({variant:o,size:i}),C),"data-selected":t.isSelected||void 0,children:jsxRuntime.jsx("div",{ref:s,className:u(V({size:i,animated:$})),"data-selected":t.isSelected||void 0})})}),(r||c)&&jsxRuntime.jsxs("div",{className:"flex flex-col",children:[r&&jsxRuntime.jsx("span",{className:"text-sm font-medium text-[var(--content-foreground)]",children:r}),c&&jsxRuntime.jsx("span",{className:"text-xs text-[var(--menu-muted)]",children:c})]})]})})}));L.displayName="Switch";var I=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 ae=I.extend({isSelected:zod.z.boolean().optional(),defaultSelected:zod.z.boolean().optional().default(false),onChange:zod.z.function().optional(),variant:zod.z.enum(["default","destructive"]).optional().default("default"),size:zod.z.enum(["sm","default","lg"]).optional().default("default"),isDisabled:zod.z.boolean().optional().default(false),isReadOnly:zod.z.boolean().optional().default(false),label:zod.z.string().optional(),description:zod.z.string().optional(),onFocus:zod.z.function().optional(),onBlur:zod.z.function().optional(),onFocusChange:zod.z.function().optional(),autoFocus:zod.z.boolean().optional(),animated:zod.z.boolean().optional().default(true),springConfig:zod.z.object({stiffness:zod.z.number(),damping:zod.z.number()}).optional()});exports.Switch=L;exports.SwitchPropsSchema=ae;exports.switchOuterVariants=_;exports.switchThumbVariants=V;exports.switchTrackVariants=k;//# sourceMappingURL=index.js.map
2
+ 'use strict';var react=require('react'),reactAriaComponents=require('react-aria-components'),classVarianceAuthority=require('class-variance-authority'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function u(...a){return tailwindMerge.twMerge(clsx.clsx(a))}function y(a,o){return !(a===false||o)}var T="(prefers-reduced-motion: reduce)";function Q(){return typeof window>"u"?false:window.matchMedia(T).matches}function A(){let[a,o]=react.useState(Q);return react.useEffect(()=>{let i=window.matchMedia(T);o(i.matches);let r=c=>{o(c.matches);};return i.addEventListener("change",r),()=>i.removeEventListener("change",r)},[]),a}var R="data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2",X="data-[pressed]:scale-[0.97]";var S="hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground",P="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",N="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var C=`${R} ${X} ${S} ${P} ${N}`;var f;function ee(){return f!==void 0?Promise.resolve(f):import('motion').then(a=>(f=a.animate,f)).catch(()=>(f=null,null))}var te={stiffness:500,damping:30},_=classVarianceAuthority.cva("inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default",{variants:{},defaultVariants:{}}),k=classVarianceAuthority.cva("relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background",{variants:{variant:{default:"bg-[var(--border)] data-[selected]:bg-[var(--primary)]",destructive:"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]"},size:{sm:"h-6 w-10",default:"h-7 w-12",lg:"h-8 w-14"}},defaultVariants:{variant:"default",size:"default"}}),V=classVarianceAuthority.cva("pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0",{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},animated:{false:"transition-transform data-[selected]:translate-x-full",true:""}},defaultVariants:{size:"default",animated:false}}),L=react.memo(react.forwardRef(({className:a,variant:o,size:i,label:r,description:c,isDisabled:b,isReadOnly:w,animated:F,springConfig:p=te,onChange:v,...H},M)=>{let z=A(),d=y(F,z),s=react.useRef(null),x=react.useRef(false),h=react.useRef(null),E=react.useRef(null);react.useEffect(()=>{d&&ee().then(t=>{if(t&&(h.current=t,x.current=true,s.current)){let B=s.current.hasAttribute("data-selected");s.current.style.transform=B?"translateX(100%)":"translateX(0)";}});},[d]);let D=react.useCallback(t=>{v?.(t),d&&x.current&&h.current&&s.current&&(E.current?.stop(),E.current=h.current(s.current,{x:t?"100%":"0%"},{type:"spring",stiffness:p.stiffness,damping:p.damping}));},[d,p.stiffness,p.damping,v]),$=d;return jsxRuntime.jsx(reactAriaComponents.Switch,{ref:M,isDisabled:b,isReadOnly:w,onChange:D,className:t=>u("group relative inline-flex items-center gap-2",b&&"cursor-not-allowed opacity-50",a),...H,children:t=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx("div",{className:u(_()),"data-selected":t.isSelected||void 0,"data-readonly":w||void 0,children:jsxRuntime.jsx("div",{className:u(k({variant:o,size:i}),C),"data-selected":t.isSelected||void 0,children:jsxRuntime.jsx("div",{ref:s,className:u(V({size:i,animated:$})),"data-selected":t.isSelected||void 0})})}),(r||c)&&jsxRuntime.jsxs("div",{className:"flex flex-col",children:[r&&jsxRuntime.jsx("span",{className:"text-sm font-medium text-[var(--content-foreground)]",children:r}),c&&jsxRuntime.jsx("span",{className:"text-xs text-[var(--menu-muted)]",children:c})]})]})})}));L.displayName="Switch";var I=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 ae=I.extend({isSelected:zod.z.boolean().optional(),defaultSelected:zod.z.boolean().optional().default(false),onChange:zod.z.function().optional(),variant:zod.z.enum(["default","destructive"]).optional().default("default"),size:zod.z.enum(["sm","default","lg"]).optional().default("default"),isDisabled:zod.z.boolean().optional().default(false),isReadOnly:zod.z.boolean().optional().default(false),label:zod.z.string().optional(),description:zod.z.string().optional(),onFocus:zod.z.function().optional(),onBlur:zod.z.function().optional(),onFocusChange:zod.z.function().optional(),autoFocus:zod.z.boolean().optional(),animated:zod.z.boolean().optional().default(true),springConfig:zod.z.object({stiffness:zod.z.number(),damping:zod.z.number()}).optional()});exports.Switch=L;exports.SwitchPropsSchema=ae;exports.switchOuterVariants=_;exports.switchThumbVariants=V;exports.switchTrackVariants=k;//# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/shouldAnimate.ts","../../../src/hooks/useReducedMotion.ts","../../../src/styles/interaction-states.ts","../../../src/elements/Switch/Switch.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Switch/Switch.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","FOCUS_STYLES","PRESSED_STYLES","HIGH_CONTRAST_FOCUS","HIGH_CONTRAST_HOVER","HIGH_CONTRAST_PRESSED","DEFAULT_INTERACTIONS","cachedAnimate","loadMotionAnimate","m","DEFAULT_SPRING","switchOuterVariants","cva","switchTrackVariants","switchThumbVariants","Switch","memo","forwardRef","className","variant","size","label","description","isDisabled","isReadOnly","springConfig","onChangeProp","props","ref","doAnimate","thumbRef","useRef","motionReady","animateRef","activeAnimation","fn","isCurrentlySelected","handleChange","useCallback","isSelected","useMotionThumb","jsx","AriaSwitch","_classNameProps","renderProps","jsxs","Fragment","BaseComponentPropsSchema","z","SwitchPropsSchema"],"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 * Determines whether a component should animate.\n *\n * Returns `false` if:\n * - The `animated` prop is explicitly `false`\n * - The user prefers reduced motion\n *\n * @param animated - The component's `animated` prop value (default: `true`)\n * @param prefersReducedMotion - Whether the user prefers reduced motion\n */\nexport function shouldAnimate(\n animated: boolean | undefined,\n prefersReducedMotion: boolean,\n): boolean {\n if (animated === false) return false;\n if (prefersReducedMotion) return false;\n return true;\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\nconst QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction getInitialState(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia(QUERY).matches;\n}\n\n/**\n * Detects whether the user prefers reduced motion.\n *\n * - SSR-safe (returns `false` on the server)\n * - Reacts to changes in the OS preference\n * - Cleans up the listener on unmount\n */\nexport function useReducedMotion(): boolean {\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(getInitialState);\n\n useEffect(() => {\n const mql = window.matchMedia(QUERY);\n setPrefersReducedMotion(mql.matches);\n\n const handler = (event: MediaQueryListEvent): void => {\n setPrefersReducedMotion(event.matches);\n };\n\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, []);\n\n return prefersReducedMotion;\n}\n","/**\n * Global Interaction State Styles\n *\n * Consistent interaction patterns across all Themis components.\n * These styles ensure WCAG 2.2 AAA compliance and predictable UX.\n *\n * @see spec.md FR-010 (Visible focus ring for keyboard navigation)\n * @see spec.md FR-031 (Pressed state feedback)\n * @see spec.md FR-012 (High contrast mode support)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\n/**\n * Focus state styles (FR-010)\n * Visible focus ring for keyboard navigation - WCAG 2.2 Level AAA\n *\n * Components can override by extending these styles:\n * @example\n * cn(FOCUS_STYLES, \"ring-4\") // Increases ring width to 4px\n */\nexport const FOCUS_STYLES = \"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2\";\n\n/**\n * Pressed/Active state styles (FR-031)\n * Visual feedback for press interactions\n *\n * Components can override the scale amount:\n * @example\n * cn(PRESSED_STYLES_BASE, \"data-[pressed]:scale-[0.95]\") // More pronounced scale\n */\nexport const PRESSED_STYLES = \"data-[pressed]:scale-[0.97]\";\n\n/**\n * Base pressed styles without scale (for components that need different feedback)\n */\nexport const PRESSED_STYLES_BASE = \"data-[pressed]:transition-transform data-[pressed]:duration-100\";\n\n/**\n * Hover state styles\n * Elevation change on hover for better affordance\n *\n * Components can override shadow depth:\n * @example\n * cn(HOVER_STYLES_BASE, \"data-[hovered]:shadow-lg\") // Larger shadow\n */\nexport const HOVER_STYLES = \"\";\n\n/**\n * Base hover styles without shadow (for components that use different hover effects)\n */\nexport const HOVER_STYLES_BASE = \"data-[hovered]:transition-shadow data-[hovered]:duration-200\";\n\n/**\n * High contrast mode focus (FR-012)\n * Enhanced outlines for users requiring high contrast\n *\n * Uses 'hc:' prefix for prefers-contrast: more media query\n */\nexport const HIGH_CONTRAST_FOCUS = \"hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground\";\n\n/**\n * High contrast mode hover (FR-012)\n * Enhanced outlines for hover in high contrast mode\n */\nexport const HIGH_CONTRAST_HOVER = \"hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground\";\n\n/**\n * High contrast mode pressed state\n * Enhanced outlines for pressed state in high contrast mode\n */\nexport const HIGH_CONTRAST_PRESSED = \"hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground\";\n\n/**\n * Combined high contrast styles\n * Use this for components that need all high contrast interaction states\n */\nexport const HIGH_CONTRAST_INTERACTIONS = `${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Disabled state styles\n * Consistent disabled appearance across all components\n */\nexport const DISABLED_STYLES = \"disabled:pointer-events-none disabled:opacity-50\";\n\n/**\n * Default interaction bundle\n * Most common combination for interactive components\n *\n * Includes: focus ring, pressed scale, hover shadow, high contrast enhancements\n *\n * @example\n * <button className={cn(DEFAULT_INTERACTIONS, \"bg-primary\")}>Click</button>\n */\nexport const DEFAULT_INTERACTIONS = `${FOCUS_STYLES} ${PRESSED_STYLES} ${HOVER_STYLES} ${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Subtle interaction bundle\n * For components that need less pronounced feedback\n *\n * Includes: focus ring and high contrast, but no hover shadow or pressed scale\n */\nexport const SUBTLE_INTERACTIONS = `${FOCUS_STYLES} ${HIGH_CONTRAST_FOCUS}`;\n\n/**\n * Non-interactive element styles\n * For elements that should indicate they are not interactive\n */\nexport const NON_INTERACTIVE = \"cursor-default select-none\";\n","\"use client\";\n\n/**\n * Switch Component\n * Accessible toggle switch with React Aria primitives and CVA styling.\n * Supports optional spring animation via motion.dev.\n *\n * @see React Aria Switch: https://react-spectrum.adobe.com/react-aria/Switch.html\n * @see ShadCN Switch: https://ui.shadcn.com/docs/components/switch\n * @see spec.md (WCAG 2.2 AAA - 7:1 contrast ratio, 44x44px touch targets)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\nimport { forwardRef, memo, useRef, useEffect, useCallback } from 'react';\nimport {\n Switch as AriaSwitch,\n type SwitchProps as AriaSwitchProps,\n} from 'react-aria-components';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport { DEFAULT_INTERACTIONS } from '../../styles/interaction-states';\nimport type { AnimatedProps, SpringConfig } from '../../types/animation';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype AnimateFn = (\n element: Element,\n keyframes: Record<string, string | number>,\n options?: Record<string, unknown>,\n) => { stop: () => void };\n\nlet cachedAnimate: AnimateFn | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionAnimate(): Promise<AnimateFn | null> {\n if (cachedAnimate !== undefined) return Promise.resolve(cachedAnimate);\n\n return import('motion')\n .then((m) => {\n cachedAnimate = m.animate as unknown as AnimateFn;\n return cachedAnimate;\n })\n .catch(() => {\n cachedAnimate = null;\n return null;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Default spring configuration\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SPRING: SpringConfig = { stiffness: 500, damping: 30 };\n\n// ---------------------------------------------------------------------------\n// CVA Variants\n// ---------------------------------------------------------------------------\n\n/**\n * Layer 1: Transparent outer touch target (44x44px minimum)\n * This layer handles the WCAG 2.2 AAA touch target requirement\n * Always invisible, centers the visual switch inside\n */\nconst switchOuterVariants = cva(\n // Base styles - WCAG 2.2 AAA: 44x44px minimum touch target\n \"inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default\",\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Layer 2: Visual switch track/background (adjustable size)\n * This layer provides the visual appearance and size flexibility\n * Background color changes based on variant and selection state\n */\nconst switchTrackVariants = cva(\n // Base styles - visual track with transitions and focus states\n \"relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n variants: {\n variant: {\n // Default variant: Uses primary color when selected\n default:\n \"bg-[var(--border)] data-[selected]:bg-[var(--primary)]\",\n // Destructive variant: Uses destructive/error color when selected\n destructive:\n \"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]\",\n },\n size: {\n // Small: h-6 w-10 (visual track size)\n sm: \"h-6 w-10\",\n // Default: h-7 w-12\n default: \"h-7 w-12\",\n // Large: h-8 w-14\n lg: \"h-8 w-14\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n/**\n * Layer 3: Switch thumb (sliding circle)\n * Inner visual element that slides horizontally when switch is selected.\n * When spring animation is active, CSS transition is removed and\n * motion.dev controls the translateX via inline transform.\n */\nconst switchThumbVariants = cva(\n // Base styles: rounded circle with shadow\n \"pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0\",\n {\n variants: {\n size: {\n // Thumb is slightly smaller than track height for proper padding\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n animated: {\n // When CSS handles the animation (motion.dev unavailable or disabled)\n false: \"transition-transform data-[selected]:translate-x-full\",\n // When motion.dev handles the animation — no CSS transition\n true: \"\",\n },\n },\n defaultVariants: {\n size: \"default\",\n animated: false,\n },\n }\n);\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport interface SwitchProps\n extends Omit<AriaSwitchProps, 'className' | 'children'>,\n VariantProps<typeof switchTrackVariants>,\n AnimatedProps {\n variant?: 'default' | 'destructive';\n size?: 'sm' | 'default' | 'lg';\n label?: string;\n description?: string;\n className?: string;\n /** Spring physics configuration. Default: { stiffness: 500, damping: 30 } */\n springConfig?: SpringConfig;\n}\n\n/**\n * Switch Component\n * Fully accessible toggle switch with React Aria and themed styling.\n * When `animated` is true (default) and motion.dev is installed,\n * the thumb uses spring physics for a natural bounce effect.\n */\nconst Switch = memo(forwardRef<HTMLLabelElement, SwitchProps>(\n (\n {\n className,\n variant,\n size,\n label,\n description,\n isDisabled,\n isReadOnly,\n animated,\n springConfig = DEFAULT_SPRING,\n onChange: onChangeProp,\n ...props\n },\n ref\n ) => {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animated, prefersReducedMotion);\n\n const thumbRef = useRef<HTMLDivElement>(null);\n const motionReady = useRef(false);\n const animateRef = useRef<AnimateFn | null>(null);\n const activeAnimation = useRef<{ stop: () => void } | null>(null);\n\n // Preload motion.dev when animation is desired\n useEffect(() => {\n if (!doAnimate) return;\n\n loadMotionAnimate().then((fn) => {\n if (fn) {\n animateRef.current = fn;\n motionReady.current = true;\n\n // Set initial thumb position if already selected (no animation)\n if (thumbRef.current) {\n const isCurrentlySelected = thumbRef.current.hasAttribute('data-selected');\n thumbRef.current.style.transform = isCurrentlySelected\n ? 'translateX(100%)'\n : 'translateX(0)';\n }\n }\n });\n }, [doAnimate]);\n\n const handleChange = useCallback(\n (isSelected: boolean) => {\n // Forward to consumer's onChange\n onChangeProp?.(isSelected);\n\n // Trigger spring animation if motion is ready\n if (doAnimate && motionReady.current && animateRef.current && thumbRef.current) {\n // Stop any in-progress animation\n activeAnimation.current?.stop();\n\n activeAnimation.current = animateRef.current(\n thumbRef.current,\n { x: isSelected ? '100%' : '0%' },\n {\n type: 'spring',\n stiffness: springConfig.stiffness,\n damping: springConfig.damping,\n },\n );\n }\n },\n [doAnimate, springConfig.stiffness, springConfig.damping, onChangeProp],\n );\n\n // Use motion for thumb position when motion.dev is handling it\n const useMotionThumb = doAnimate;\n\n return (\n <AriaSwitch\n ref={ref}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n onChange={handleChange}\n className={(_classNameProps) =>\n cn(\n \"group inline-flex items-center gap-2\",\n isDisabled && \"cursor-not-allowed opacity-50\",\n className\n )\n }\n {...props}\n >\n {(renderProps) => (\n <>\n {/* Layer 1: Transparent outer touch target (44x44px WCAG compliant) */}\n <div\n className={cn(switchOuterVariants())}\n data-selected={renderProps.isSelected || undefined}\n data-readonly={isReadOnly || undefined}\n >\n {/* Layer 2: Visual switch track (adjustable size with variants) */}\n <div\n className={cn(\n switchTrackVariants({ variant, size }),\n DEFAULT_INTERACTIONS\n )}\n data-selected={renderProps.isSelected || undefined}\n >\n {/* Layer 3: Thumb (sliding circle, absolutely positioned) */}\n <div\n ref={thumbRef}\n className={cn(switchThumbVariants({\n size,\n animated: useMotionThumb,\n }))}\n data-selected={renderProps.isSelected || undefined}\n />\n </div>\n </div>\n\n {/* Optional label and description */}\n {(label || description) && (\n <div className=\"flex flex-col\">\n {label && (\n <span className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n </span>\n )}\n {description && (\n <span className=\"text-xs text-[var(--menu-muted)]\">\n {description}\n </span>\n )}\n </div>\n )}\n </>\n )}\n </AriaSwitch>\n );\n }\n));\n\nSwitch.displayName = \"Switch\";\n\nexport { Switch, switchOuterVariants, switchTrackVariants, switchThumbVariants };\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 { SwitchProps as AriaSwitchProps } from 'react-aria-components';\n\n/**\n * Switch props schema extending BaseComponentProps\n *\n * @see React Aria Switch: https://react-spectrum.adobe.com/react-aria/Switch.html\n * @see ShadCN Switch: https://ui.shadcn.com/docs/components/switch\n * @see spec.md (WCAG 2.2 AAA - 7:1 contrast, 44x44px touch targets)\n * @see constitution.md Principle IV (Accessibility First)\n */\nexport const SwitchPropsSchema = BaseComponentPropsSchema.extend({\n // State management (controlled/uncontrolled)\n isSelected: z.boolean().optional(),\n defaultSelected: z.boolean().optional().default(false),\n onChange: z.function().optional(),\n\n // Variants (matching Button pattern)\n variant: z\n .enum(['default', 'destructive'])\n .optional()\n .default('default'),\n\n // Sizes (3 sizes for consistency)\n size: z.enum(['sm', 'default', 'lg']).optional().default('default'),\n\n // States\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n\n // Labels (optional built-in labeling)\n label: z.string().optional(),\n description: z.string().optional(),\n\n // React Aria SwitchProps integration\n onFocus: z.function().optional(),\n onBlur: z.function().optional(),\n onFocusChange: z.function().optional(),\n autoFocus: z.boolean().optional(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n animated: z.boolean().optional().default(true),\n springConfig: z\n .object({\n stiffness: z.number(),\n damping: z.number(),\n })\n .optional(),\n});\n\nexport interface SwitchPropsOwn {\n className?: string;\n children?: unknown;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n isSelected?: boolean;\n defaultSelected?: boolean;\n onChange?: (...args: unknown[]) => unknown;\n variant?: 'default' | 'destructive';\n size?: 'sm' | 'default' | 'lg';\n isDisabled?: boolean;\n isReadOnly?: boolean;\n label?: string;\n description?: string;\n onFocus?: (...args: unknown[]) => unknown;\n onBlur?: (...args: unknown[]) => unknown;\n onFocusChange?: (...args: unknown[]) => unknown;\n autoFocus?: boolean;\n animated?: boolean;\n springConfig?: { stiffness: number; damping: number };\n}\n\nexport type SwitchProps = SwitchPropsOwn &\n Omit<AriaSwitchProps, keyof SwitchPropsOwn>;\n\nexport type SwitchVariant = SwitchPropsOwn['variant'];\nexport type SwitchSize = SwitchPropsOwn['size'];\n"]}
1
+ {"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/shouldAnimate.ts","../../../src/hooks/useReducedMotion.ts","../../../src/styles/interaction-states.ts","../../../src/elements/Switch/Switch.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Switch/Switch.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","FOCUS_STYLES","PRESSED_STYLES","HIGH_CONTRAST_FOCUS","HIGH_CONTRAST_HOVER","HIGH_CONTRAST_PRESSED","DEFAULT_INTERACTIONS","cachedAnimate","loadMotionAnimate","m","DEFAULT_SPRING","switchOuterVariants","cva","switchTrackVariants","switchThumbVariants","Switch","memo","forwardRef","className","variant","size","label","description","isDisabled","isReadOnly","springConfig","onChangeProp","props","ref","doAnimate","thumbRef","useRef","motionReady","animateRef","activeAnimation","fn","isCurrentlySelected","handleChange","useCallback","isSelected","useMotionThumb","jsx","AriaSwitch","_classNameProps","renderProps","jsxs","Fragment","BaseComponentPropsSchema","z","SwitchPropsSchema"],"mappings":"gRAcO,SAASA,CAAAA,CAAAA,GAAMC,CAAAA,CAA8B,CAClD,OAAOC,qBAAAA,CAAQC,UAAKF,CAAM,CAAC,CAC7B,CCNO,SAASG,EACdC,CAAAA,CACAC,CAAAA,CACS,CAET,OADI,EAAAD,IAAa,KAAA,EACbC,CAAAA,CAEN,CCbA,IAAMC,CAAAA,CAAQ,mCAEd,SAASC,CAAAA,EAA2B,CAClC,OAAI,OAAO,OAAW,GAAA,CAAoB,KAAA,CACnC,OAAO,UAAA,CAAWD,CAAK,EAAE,OAClC,CASO,SAASE,CAAAA,EAA4B,CAC1C,GAAM,CAACH,CAAAA,CAAsBI,CAAuB,CAAA,CAAIC,cAAAA,CAASH,CAAe,CAAA,CAEhF,OAAAI,gBAAU,IAAM,CACd,IAAMC,CAAAA,CAAM,MAAA,CAAO,WAAWN,CAAK,CAAA,CACnCG,CAAAA,CAAwBG,CAAAA,CAAI,OAAO,CAAA,CAEnC,IAAMC,EAAWC,CAAAA,EAAqC,CACpDL,EAAwBK,CAAAA,CAAM,OAAO,EACvC,CAAA,CAEA,OAAAF,EAAI,gBAAA,CAAiB,QAAA,CAAUC,CAAO,CAAA,CAC/B,IAAMD,EAAI,mBAAA,CAAoB,QAAA,CAAUC,CAAO,CACxD,CAAA,CAAG,EAAE,CAAA,CAEER,CACT,CCdO,IAAMU,EAAe,+GAAA,CAUfC,CAAAA,CAAiB,8BA4BvB,IAAMC,CAAAA,CAAsB,wJAMtBC,CAAAA,CAAsB,4FAAA,CAMtBC,EAAwB,+HAAA,CAuB9B,IAAMC,CAAAA,CAAuB,GAAGL,CAAY,CAAA,CAAA,EAAIC,CAAc,CAAA,EAAA,EAAoBC,CAAmB,IAAIC,CAAmB,CAAA,CAAA,EAAIC,CAAqB,CAAA,CAAA,CC1D5J,IAAIE,CAAAA,CAEJ,SAASC,IAA+C,CACtD,OAAID,IAAkB,MAAA,CAAkB,OAAA,CAAQ,QAAQA,CAAa,CAAA,CAE9D,OAAO,QAAQ,CAAA,CACnB,KAAME,CAAAA,GACLF,CAAAA,CAAgBE,CAAAA,CAAE,OAAA,CACXF,EACR,CAAA,CACA,KAAA,CAAM,KACLA,CAAAA,CAAgB,IAAA,CACT,KACR,CACL,KAMMG,EAAAA,CAA+B,CAAE,UAAW,GAAA,CAAK,OAAA,CAAS,EAAG,CAAA,CAW7DC,CAAAA,CAAsBC,2BAE1B,0KAAA,CACA,CACE,SAAU,EAAC,CACX,gBAAiB,EACnB,CACF,CAAA,CAOMC,CAAAA,CAAsBD,2BAE1B,yPAAA,CACA,CACE,SAAU,CACR,OAAA,CAAS,CAEP,OAAA,CACE,wDAAA,CAEF,YACE,uEACJ,CAAA,CACA,KAAM,CAEJ,EAAA,CAAI,WAEJ,OAAA,CAAS,UAAA,CAET,GAAI,UACN,CACF,EACA,eAAA,CAAiB,CACf,QAAS,SAAA,CACT,IAAA,CAAM,SACR,CACF,CACF,EAQME,CAAAA,CAAsBF,0BAAAA,CAE1B,2FACA,CACE,QAAA,CAAU,CACR,IAAA,CAAM,CAEJ,GAAI,SAAA,CACJ,OAAA,CAAS,UACT,EAAA,CAAI,SACN,EACA,QAAA,CAAU,CAER,MAAO,uDAAA,CAEP,IAAA,CAAM,EACR,CACF,CAAA,CACA,gBAAiB,CACf,IAAA,CAAM,UACN,QAAA,CAAU,KACZ,CACF,CACF,CAAA,CAyBMG,CAAAA,CAASC,UAAAA,CAAKC,iBAClB,CACE,CACE,UAAAC,CAAAA,CACA,OAAA,CAAAC,EACA,IAAA,CAAAC,CAAAA,CACA,MAAAC,CAAAA,CACA,WAAA,CAAAC,EACA,UAAA,CAAAC,CAAAA,CACA,WAAAC,CAAAA,CACA,QAAA,CAAAlC,EACA,YAAA,CAAAmC,CAAAA,CAAef,GACf,QAAA,CAAUgB,CAAAA,CACV,GAAGC,CACL,CAAA,CACAC,IACG,CACH,IAAMrC,EAAuBG,CAAAA,EAAiB,CACxCmC,EAAYxC,CAAAA,CAAcC,CAAAA,CAAUC,CAAoB,CAAA,CAExDuC,CAAAA,CAAWC,aAAuB,IAAI,CAAA,CACtCC,EAAcD,YAAAA,CAAO,KAAK,EAC1BE,CAAAA,CAAaF,YAAAA,CAAyB,IAAI,CAAA,CAC1CG,CAAAA,CAAkBH,aAAoC,IAAI,CAAA,CAGhElC,gBAAU,IAAM,CACTgC,GAELrB,EAAAA,EAAkB,CAAE,KAAM2B,CAAAA,EAAO,CAC/B,GAAIA,CAAAA,GACFF,CAAAA,CAAW,QAAUE,CAAAA,CACrBH,CAAAA,CAAY,QAAU,IAAA,CAGlBF,CAAAA,CAAS,SAAS,CACpB,IAAMM,EAAsBN,CAAAA,CAAS,OAAA,CAAQ,aAAa,eAAe,CAAA,CACzEA,EAAS,OAAA,CAAQ,KAAA,CAAM,UAAYM,CAAAA,CAC/B,kBAAA,CACA,gBACN,CAEJ,CAAC,EACH,CAAA,CAAG,CAACP,CAAS,CAAC,EAEd,IAAMQ,CAAAA,CAAeC,kBAClBC,CAAAA,EAAwB,CAEvBb,IAAea,CAAU,CAAA,CAGrBV,GAAaG,CAAAA,CAAY,OAAA,EAAWC,EAAW,OAAA,EAAWH,CAAAA,CAAS,UAErEI,CAAAA,CAAgB,OAAA,EAAS,MAAK,CAE9BA,CAAAA,CAAgB,QAAUD,CAAAA,CAAW,OAAA,CACnCH,EAAS,OAAA,CACT,CAAE,EAAGS,CAAAA,CAAa,MAAA,CAAS,IAAK,CAAA,CAChC,CACE,KAAM,QAAA,CACN,SAAA,CAAWd,EAAa,SAAA,CACxB,OAAA,CAASA,EAAa,OACxB,CACF,GAEJ,CAAA,CACA,CAACI,EAAWJ,CAAAA,CAAa,SAAA,CAAWA,EAAa,OAAA,CAASC,CAAY,CACxE,CAAA,CAGMc,CAAAA,CAAiBX,EAEvB,OACEY,cAAAA,CAACC,2BAAA,CACC,GAAA,CAAKd,EACL,UAAA,CAAYL,CAAAA,CACZ,WAAYC,CAAAA,CACZ,QAAA,CAAUa,EACV,SAAA,CAAYM,CAAAA,EACV1D,EASE,+CAAA,CACAsC,CAAAA,EAAc,gCACdL,CACF,CAAA,CAED,GAAGS,CAAAA,CAEH,QAAA,CAACiB,GACAC,eAAAA,CAAAC,mBAAAA,CAAA,CAEE,QAAA,CAAA,CAAAL,cAAAA,CAAC,OACC,SAAA,CAAWxD,CAAAA,CAAG0B,GAAqB,CAAA,CACnC,gBAAeiC,CAAAA,CAAY,UAAA,EAAc,MAAA,CACzC,eAAA,CAAepB,GAAc,MAAA,CAG7B,QAAA,CAAAiB,eAAC,KAAA,CAAA,CACC,SAAA,CAAWxD,EACT4B,CAAAA,CAAoB,CAAE,QAAAM,CAAAA,CAAS,IAAA,CAAAC,CAAK,CAAC,CAAA,CACrCd,CACF,CAAA,CACA,eAAA,CAAesC,EAAY,UAAA,EAAc,MAAA,CAGzC,SAAAH,cAAAA,CAAC,KAAA,CAAA,CACC,IAAKX,CAAAA,CACL,SAAA,CAAW7C,EAAG6B,CAAAA,CAAoB,CAChC,KAAAM,CAAAA,CACA,QAAA,CAAUoB,CACZ,CAAC,CAAC,EACF,eAAA,CAAeI,CAAAA,CAAY,YAAc,MAAA,CAC3C,CAAA,CACF,EACF,CAAA,CAAA,CAGEvB,CAAAA,EAASC,IACTuB,eAAAA,CAAC,KAAA,CAAA,CAAI,UAAU,eAAA,CACZ,QAAA,CAAA,CAAAxB,GACCoB,cAAAA,CAAC,MAAA,CAAA,CAAK,UAAU,sDAAA,CACb,QAAA,CAAApB,EACH,CAAA,CAEDC,CAAAA,EACCmB,eAAC,MAAA,CAAA,CAAK,SAAA,CAAU,mCACb,QAAA,CAAAnB,CAAAA,CACH,GAEJ,CAAA,CAAA,CAEJ,CAAA,CAEJ,CAEJ,CACF,CAAC,EAEDP,CAAAA,CAAO,WAAA,CAAc,SC3Sd,IAAMgC,CAAAA,CAA2BC,KAAAA,CAAE,OAAO,CAE/C,SAAA,CAAWA,MAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG/B,SAAUA,KAAAA,CAAE,GAAA,GAAM,QAAA,EAAS,CAC3B,GAAIA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAGxB,aAAcA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAClC,kBAAmBA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CACvC,mBAAoBA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CACxC,YAAaA,KAAAA,CAAE,IAAA,CAAK,CAAC,KAAA,CAAO,QAAA,CAAU,WAAW,CAAC,CAAA,CAAE,UAAS,CAC7D,aAAA,CAAeA,MAAE,OAAA,EAAQ,CAAE,UAAS,CAGpC,aAAA,CAAeA,MAAE,MAAA,EAAO,CAAE,UAC5B,CAAC,ECdM,IAAMC,EAAAA,CAAoBF,EAAyB,MAAA,CAAO,CAE/D,WAAYC,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CACjC,gBAAiBA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,KAAK,CAAA,CACrD,SAAUA,KAAAA,CAAE,QAAA,GAAW,QAAA,EAAS,CAGhC,QAASA,KAAAA,CACN,IAAA,CAAK,CAAC,SAAA,CAAW,aAAa,CAAC,CAAA,CAC/B,QAAA,GACA,OAAA,CAAQ,SAAS,EAGpB,IAAA,CAAMA,KAAAA,CAAE,KAAK,CAAC,IAAA,CAAM,UAAW,IAAI,CAAC,EAAE,QAAA,EAAS,CAAE,QAAQ,SAAS,CAAA,CAGlE,WAAYA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,KAAK,CAAA,CAChD,WAAYA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,KAAK,CAAA,CAGhD,MAAOA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAC3B,YAAaA,KAAAA,CAAE,MAAA,GAAS,QAAA,EAAS,CAGjC,QAASA,KAAAA,CAAE,QAAA,GAAW,QAAA,EAAS,CAC/B,OAAQA,KAAAA,CAAE,QAAA,GAAW,QAAA,EAAS,CAC9B,cAAeA,KAAAA,CAAE,QAAA,GAAW,QAAA,EAAS,CACrC,UAAWA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAGhC,SAAUA,KAAAA,CAAE,OAAA,GAAU,QAAA,EAAS,CAAE,QAAQ,IAAI,CAAA,CAC7C,aAAcA,KAAAA,CACX,MAAA,CAAO,CACN,SAAA,CAAWA,KAAAA,CAAE,QAAO,CACpB,OAAA,CAASA,MAAE,MAAA,EACb,CAAC,CAAA,CACA,QAAA,EACL,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 * Determines whether a component should animate.\n *\n * Returns `false` if:\n * - The `animated` prop is explicitly `false`\n * - The user prefers reduced motion\n *\n * @param animated - The component's `animated` prop value (default: `true`)\n * @param prefersReducedMotion - Whether the user prefers reduced motion\n */\nexport function shouldAnimate(\n animated: boolean | undefined,\n prefersReducedMotion: boolean,\n): boolean {\n if (animated === false) return false;\n if (prefersReducedMotion) return false;\n return true;\n}\n","'use client';\n\nimport { useState, useEffect } from 'react';\n\nconst QUERY = '(prefers-reduced-motion: reduce)';\n\nfunction getInitialState(): boolean {\n if (typeof window === 'undefined') return false;\n return window.matchMedia(QUERY).matches;\n}\n\n/**\n * Detects whether the user prefers reduced motion.\n *\n * - SSR-safe (returns `false` on the server)\n * - Reacts to changes in the OS preference\n * - Cleans up the listener on unmount\n */\nexport function useReducedMotion(): boolean {\n const [prefersReducedMotion, setPrefersReducedMotion] = useState(getInitialState);\n\n useEffect(() => {\n const mql = window.matchMedia(QUERY);\n setPrefersReducedMotion(mql.matches);\n\n const handler = (event: MediaQueryListEvent): void => {\n setPrefersReducedMotion(event.matches);\n };\n\n mql.addEventListener('change', handler);\n return () => mql.removeEventListener('change', handler);\n }, []);\n\n return prefersReducedMotion;\n}\n","/**\n * Global Interaction State Styles\n *\n * Consistent interaction patterns across all Themis components.\n * These styles ensure WCAG 2.2 AAA compliance and predictable UX.\n *\n * @see spec.md FR-010 (Visible focus ring for keyboard navigation)\n * @see spec.md FR-031 (Pressed state feedback)\n * @see spec.md FR-012 (High contrast mode support)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\n/**\n * Focus state styles (FR-010)\n * Visible focus ring for keyboard navigation - WCAG 2.2 Level AAA\n *\n * Components can override by extending these styles:\n * @example\n * cn(FOCUS_STYLES, \"ring-4\") // Increases ring width to 4px\n */\nexport const FOCUS_STYLES = \"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2\";\n\n/**\n * Pressed/Active state styles (FR-031)\n * Visual feedback for press interactions\n *\n * Components can override the scale amount:\n * @example\n * cn(PRESSED_STYLES_BASE, \"data-[pressed]:scale-[0.95]\") // More pronounced scale\n */\nexport const PRESSED_STYLES = \"data-[pressed]:scale-[0.97]\";\n\n/**\n * Base pressed styles without scale (for components that need different feedback)\n */\nexport const PRESSED_STYLES_BASE = \"data-[pressed]:transition-transform data-[pressed]:duration-100\";\n\n/**\n * Hover state styles\n * Elevation change on hover for better affordance\n *\n * Components can override shadow depth:\n * @example\n * cn(HOVER_STYLES_BASE, \"data-[hovered]:shadow-lg\") // Larger shadow\n */\nexport const HOVER_STYLES = \"\";\n\n/**\n * Base hover styles without shadow (for components that use different hover effects)\n */\nexport const HOVER_STYLES_BASE = \"data-[hovered]:transition-shadow data-[hovered]:duration-200\";\n\n/**\n * High contrast mode focus (FR-012)\n * Enhanced outlines for users requiring high contrast\n *\n * Uses 'hc:' prefix for prefers-contrast: more media query\n */\nexport const HIGH_CONTRAST_FOCUS = \"hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground\";\n\n/**\n * High contrast mode hover (FR-012)\n * Enhanced outlines for hover in high contrast mode\n */\nexport const HIGH_CONTRAST_HOVER = \"hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground\";\n\n/**\n * High contrast mode pressed state\n * Enhanced outlines for pressed state in high contrast mode\n */\nexport const HIGH_CONTRAST_PRESSED = \"hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground\";\n\n/**\n * Combined high contrast styles\n * Use this for components that need all high contrast interaction states\n */\nexport const HIGH_CONTRAST_INTERACTIONS = `${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Disabled state styles\n * Consistent disabled appearance across all components\n */\nexport const DISABLED_STYLES = \"disabled:pointer-events-none disabled:opacity-50\";\n\n/**\n * Default interaction bundle\n * Most common combination for interactive components\n *\n * Includes: focus ring, pressed scale, hover shadow, high contrast enhancements\n *\n * @example\n * <button className={cn(DEFAULT_INTERACTIONS, \"bg-primary\")}>Click</button>\n */\nexport const DEFAULT_INTERACTIONS = `${FOCUS_STYLES} ${PRESSED_STYLES} ${HOVER_STYLES} ${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Subtle interaction bundle\n * For components that need less pronounced feedback\n *\n * Includes: focus ring and high contrast, but no hover shadow or pressed scale\n */\nexport const SUBTLE_INTERACTIONS = `${FOCUS_STYLES} ${HIGH_CONTRAST_FOCUS}`;\n\n/**\n * Non-interactive element styles\n * For elements that should indicate they are not interactive\n */\nexport const NON_INTERACTIVE = \"cursor-default select-none\";\n","\"use client\";\n\n/**\n * Switch Component\n * Accessible toggle switch with React Aria primitives and CVA styling.\n * Supports optional spring animation via motion.dev.\n *\n * @see React Aria Switch: https://react-spectrum.adobe.com/react-aria/Switch.html\n * @see ShadCN Switch: https://ui.shadcn.com/docs/components/switch\n * @see spec.md (WCAG 2.2 AAA - 7:1 contrast ratio, 44x44px touch targets)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\nimport { forwardRef, memo, useRef, useEffect, useCallback } from 'react';\nimport {\n Switch as AriaSwitch,\n type SwitchProps as AriaSwitchProps,\n} from 'react-aria-components';\nimport { cva, type VariantProps } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport { DEFAULT_INTERACTIONS } from '../../styles/interaction-states';\nimport type { AnimatedProps, SpringConfig } from '../../types/animation';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype AnimateFn = (\n element: Element,\n keyframes: Record<string, string | number>,\n options?: Record<string, unknown>,\n) => { stop: () => void };\n\nlet cachedAnimate: AnimateFn | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionAnimate(): Promise<AnimateFn | null> {\n if (cachedAnimate !== undefined) return Promise.resolve(cachedAnimate);\n\n return import('motion')\n .then((m) => {\n cachedAnimate = m.animate as unknown as AnimateFn;\n return cachedAnimate;\n })\n .catch(() => {\n cachedAnimate = null;\n return null;\n });\n}\n\n// ---------------------------------------------------------------------------\n// Default spring configuration\n// ---------------------------------------------------------------------------\n\nconst DEFAULT_SPRING: SpringConfig = { stiffness: 500, damping: 30 };\n\n// ---------------------------------------------------------------------------\n// CVA Variants\n// ---------------------------------------------------------------------------\n\n/**\n * Layer 1: Transparent outer touch target (44x44px minimum)\n * This layer handles the WCAG 2.2 AAA touch target requirement\n * Always invisible, centers the visual switch inside\n */\nconst switchOuterVariants = cva(\n // Base styles - WCAG 2.2 AAA: 44x44px minimum touch target\n \"inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default\",\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n/**\n * Layer 2: Visual switch track/background (adjustable size)\n * This layer provides the visual appearance and size flexibility\n * Background color changes based on variant and selection state\n */\nconst switchTrackVariants = cva(\n // Base styles - visual track with transitions and focus states\n \"relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background\",\n {\n variants: {\n variant: {\n // Default variant: Uses primary color when selected\n default:\n \"bg-[var(--border)] data-[selected]:bg-[var(--primary)]\",\n // Destructive variant: Uses destructive/error color when selected\n destructive:\n \"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]\",\n },\n size: {\n // Small: h-6 w-10 (visual track size)\n sm: \"h-6 w-10\",\n // Default: h-7 w-12\n default: \"h-7 w-12\",\n // Large: h-8 w-14\n lg: \"h-8 w-14\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n size: \"default\",\n },\n }\n);\n\n/**\n * Layer 3: Switch thumb (sliding circle)\n * Inner visual element that slides horizontally when switch is selected.\n * When spring animation is active, CSS transition is removed and\n * motion.dev controls the translateX via inline transform.\n */\nconst switchThumbVariants = cva(\n // Base styles: rounded circle with shadow\n \"pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0\",\n {\n variants: {\n size: {\n // Thumb is slightly smaller than track height for proper padding\n sm: \"h-4 w-4\",\n default: \"h-5 w-5\",\n lg: \"h-6 w-6\",\n },\n animated: {\n // When CSS handles the animation (motion.dev unavailable or disabled)\n false: \"transition-transform data-[selected]:translate-x-full\",\n // When motion.dev handles the animation — no CSS transition\n true: \"\",\n },\n },\n defaultVariants: {\n size: \"default\",\n animated: false,\n },\n }\n);\n\n// ---------------------------------------------------------------------------\n// Component\n// ---------------------------------------------------------------------------\n\nexport interface SwitchProps\n extends Omit<AriaSwitchProps, 'className' | 'children'>,\n VariantProps<typeof switchTrackVariants>,\n AnimatedProps {\n variant?: 'default' | 'destructive';\n size?: 'sm' | 'default' | 'lg';\n label?: string;\n description?: string;\n className?: string;\n /** Spring physics configuration. Default: { stiffness: 500, damping: 30 } */\n springConfig?: SpringConfig;\n}\n\n/**\n * Switch Component\n * Fully accessible toggle switch with React Aria and themed styling.\n * When `animated` is true (default) and motion.dev is installed,\n * the thumb uses spring physics for a natural bounce effect.\n */\nconst Switch = memo(forwardRef<HTMLLabelElement, SwitchProps>(\n (\n {\n className,\n variant,\n size,\n label,\n description,\n isDisabled,\n isReadOnly,\n animated,\n springConfig = DEFAULT_SPRING,\n onChange: onChangeProp,\n ...props\n },\n ref\n ) => {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animated, prefersReducedMotion);\n\n const thumbRef = useRef<HTMLDivElement>(null);\n const motionReady = useRef(false);\n const animateRef = useRef<AnimateFn | null>(null);\n const activeAnimation = useRef<{ stop: () => void } | null>(null);\n\n // Preload motion.dev when animation is desired\n useEffect(() => {\n if (!doAnimate) return;\n\n loadMotionAnimate().then((fn) => {\n if (fn) {\n animateRef.current = fn;\n motionReady.current = true;\n\n // Set initial thumb position if already selected (no animation)\n if (thumbRef.current) {\n const isCurrentlySelected = thumbRef.current.hasAttribute('data-selected');\n thumbRef.current.style.transform = isCurrentlySelected\n ? 'translateX(100%)'\n : 'translateX(0)';\n }\n }\n });\n }, [doAnimate]);\n\n const handleChange = useCallback(\n (isSelected: boolean) => {\n // Forward to consumer's onChange\n onChangeProp?.(isSelected);\n\n // Trigger spring animation if motion is ready\n if (doAnimate && motionReady.current && animateRef.current && thumbRef.current) {\n // Stop any in-progress animation\n activeAnimation.current?.stop();\n\n activeAnimation.current = animateRef.current(\n thumbRef.current,\n { x: isSelected ? '100%' : '0%' },\n {\n type: 'spring',\n stiffness: springConfig.stiffness,\n damping: springConfig.damping,\n },\n );\n }\n },\n [doAnimate, springConfig.stiffness, springConfig.damping, onChangeProp],\n );\n\n // Use motion for thumb position when motion.dev is handling it\n const useMotionThumb = doAnimate;\n\n return (\n <AriaSwitch\n ref={ref}\n isDisabled={isDisabled}\n isReadOnly={isReadOnly}\n onChange={handleChange}\n className={(_classNameProps) =>\n cn(\n // `relative` is load-bearing: React Aria renders the real <input>\n // inside a VisuallyHidden span (position:absolute, auto offsets).\n // Without a positioned ancestor its containing block becomes the\n // document, so the input is laid out at its static Y deep in tall\n // scroll content and EXTENDS the page's scroll height — a phantom\n // blank band + a second (window) scrollbar. `relative` confines the\n // hidden input to this switch's box. (The `relative` on the track\n // sub-element is a sibling of the span, so it doesn't help here.)\n \"group relative inline-flex items-center gap-2\",\n isDisabled && \"cursor-not-allowed opacity-50\",\n className\n )\n }\n {...props}\n >\n {(renderProps) => (\n <>\n {/* Layer 1: Transparent outer touch target (44x44px WCAG compliant) */}\n <div\n className={cn(switchOuterVariants())}\n data-selected={renderProps.isSelected || undefined}\n data-readonly={isReadOnly || undefined}\n >\n {/* Layer 2: Visual switch track (adjustable size with variants) */}\n <div\n className={cn(\n switchTrackVariants({ variant, size }),\n DEFAULT_INTERACTIONS\n )}\n data-selected={renderProps.isSelected || undefined}\n >\n {/* Layer 3: Thumb (sliding circle, absolutely positioned) */}\n <div\n ref={thumbRef}\n className={cn(switchThumbVariants({\n size,\n animated: useMotionThumb,\n }))}\n data-selected={renderProps.isSelected || undefined}\n />\n </div>\n </div>\n\n {/* Optional label and description */}\n {(label || description) && (\n <div className=\"flex flex-col\">\n {label && (\n <span className=\"text-sm font-medium text-[var(--content-foreground)]\">\n {label}\n </span>\n )}\n {description && (\n <span className=\"text-xs text-[var(--menu-muted)]\">\n {description}\n </span>\n )}\n </div>\n )}\n </>\n )}\n </AriaSwitch>\n );\n }\n));\n\nSwitch.displayName = \"Switch\";\n\nexport { Switch, switchOuterVariants, switchTrackVariants, switchThumbVariants };\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 { SwitchProps as AriaSwitchProps } from 'react-aria-components';\n\n/**\n * Switch props schema extending BaseComponentProps\n *\n * @see React Aria Switch: https://react-spectrum.adobe.com/react-aria/Switch.html\n * @see ShadCN Switch: https://ui.shadcn.com/docs/components/switch\n * @see spec.md (WCAG 2.2 AAA - 7:1 contrast, 44x44px touch targets)\n * @see constitution.md Principle IV (Accessibility First)\n */\nexport const SwitchPropsSchema = BaseComponentPropsSchema.extend({\n // State management (controlled/uncontrolled)\n isSelected: z.boolean().optional(),\n defaultSelected: z.boolean().optional().default(false),\n onChange: z.function().optional(),\n\n // Variants (matching Button pattern)\n variant: z\n .enum(['default', 'destructive'])\n .optional()\n .default('default'),\n\n // Sizes (3 sizes for consistency)\n size: z.enum(['sm', 'default', 'lg']).optional().default('default'),\n\n // States\n isDisabled: z.boolean().optional().default(false),\n isReadOnly: z.boolean().optional().default(false),\n\n // Labels (optional built-in labeling)\n label: z.string().optional(),\n description: z.string().optional(),\n\n // React Aria SwitchProps integration\n onFocus: z.function().optional(),\n onBlur: z.function().optional(),\n onFocusChange: z.function().optional(),\n autoFocus: z.boolean().optional(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n animated: z.boolean().optional().default(true),\n springConfig: z\n .object({\n stiffness: z.number(),\n damping: z.number(),\n })\n .optional(),\n});\n\nexport interface SwitchPropsOwn {\n className?: string;\n children?: unknown;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n isSelected?: boolean;\n defaultSelected?: boolean;\n onChange?: (...args: unknown[]) => unknown;\n variant?: 'default' | 'destructive';\n size?: 'sm' | 'default' | 'lg';\n isDisabled?: boolean;\n isReadOnly?: boolean;\n label?: string;\n description?: string;\n onFocus?: (...args: unknown[]) => unknown;\n onBlur?: (...args: unknown[]) => unknown;\n onFocusChange?: (...args: unknown[]) => unknown;\n autoFocus?: boolean;\n animated?: boolean;\n springConfig?: { stiffness: number; damping: number };\n}\n\nexport type SwitchProps = SwitchPropsOwn &\n Omit<AriaSwitchProps, keyof SwitchPropsOwn>;\n\nexport type SwitchVariant = SwitchPropsOwn['variant'];\nexport type SwitchSize = SwitchPropsOwn['size'];\n"]}
@@ -1,3 +1,3 @@
1
1
  "use client";
2
- import {memo,forwardRef,useRef,useEffect,useCallback,useState}from'react';import {Switch}from'react-aria-components';import {cva}from'class-variance-authority';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {z}from'zod';function u(...a){return twMerge(clsx(a))}function y(a,o){return !(a===false||o)}var T="(prefers-reduced-motion: reduce)";function Q(){return typeof window>"u"?false:window.matchMedia(T).matches}function A(){let[a,o]=useState(Q);return useEffect(()=>{let i=window.matchMedia(T);o(i.matches);let r=c=>{o(c.matches);};return i.addEventListener("change",r),()=>i.removeEventListener("change",r)},[]),a}var R="data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2",X="data-[pressed]:scale-[0.97]";var S="hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground",P="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",N="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var C=`${R} ${X} ${S} ${P} ${N}`;var f;function ee(){return f!==void 0?Promise.resolve(f):import('motion').then(a=>(f=a.animate,f)).catch(()=>(f=null,null))}var te={stiffness:500,damping:30},_=cva("inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default",{variants:{},defaultVariants:{}}),k=cva("relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background",{variants:{variant:{default:"bg-[var(--border)] data-[selected]:bg-[var(--primary)]",destructive:"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]"},size:{sm:"h-6 w-10",default:"h-7 w-12",lg:"h-8 w-14"}},defaultVariants:{variant:"default",size:"default"}}),V=cva("pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0",{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},animated:{false:"transition-transform data-[selected]:translate-x-full",true:""}},defaultVariants:{size:"default",animated:false}}),L=memo(forwardRef(({className:a,variant:o,size:i,label:r,description:c,isDisabled:b,isReadOnly:w,animated:F,springConfig:p=te,onChange:v,...H},M)=>{let z=A(),d=y(F,z),s=useRef(null),x=useRef(false),h=useRef(null),E=useRef(null);useEffect(()=>{d&&ee().then(t=>{if(t&&(h.current=t,x.current=true,s.current)){let B=s.current.hasAttribute("data-selected");s.current.style.transform=B?"translateX(100%)":"translateX(0)";}});},[d]);let D=useCallback(t=>{v?.(t),d&&x.current&&h.current&&s.current&&(E.current?.stop(),E.current=h.current(s.current,{x:t?"100%":"0%"},{type:"spring",stiffness:p.stiffness,damping:p.damping}));},[d,p.stiffness,p.damping,v]),$=d;return jsx(Switch,{ref:M,isDisabled:b,isReadOnly:w,onChange:D,className:t=>u("group inline-flex items-center gap-2",b&&"cursor-not-allowed opacity-50",a),...H,children:t=>jsxs(Fragment,{children:[jsx("div",{className:u(_()),"data-selected":t.isSelected||void 0,"data-readonly":w||void 0,children:jsx("div",{className:u(k({variant:o,size:i}),C),"data-selected":t.isSelected||void 0,children:jsx("div",{ref:s,className:u(V({size:i,animated:$})),"data-selected":t.isSelected||void 0})})}),(r||c)&&jsxs("div",{className:"flex flex-col",children:[r&&jsx("span",{className:"text-sm font-medium text-[var(--content-foreground)]",children:r}),c&&jsx("span",{className:"text-xs text-[var(--menu-muted)]",children:c})]})]})})}));L.displayName="Switch";var I=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 ae=I.extend({isSelected:z.boolean().optional(),defaultSelected:z.boolean().optional().default(false),onChange:z.function().optional(),variant:z.enum(["default","destructive"]).optional().default("default"),size:z.enum(["sm","default","lg"]).optional().default("default"),isDisabled:z.boolean().optional().default(false),isReadOnly:z.boolean().optional().default(false),label:z.string().optional(),description:z.string().optional(),onFocus:z.function().optional(),onBlur:z.function().optional(),onFocusChange:z.function().optional(),autoFocus:z.boolean().optional(),animated:z.boolean().optional().default(true),springConfig:z.object({stiffness:z.number(),damping:z.number()}).optional()});export{L as Switch,ae as SwitchPropsSchema,_ as switchOuterVariants,V as switchThumbVariants,k as switchTrackVariants};//# sourceMappingURL=index.mjs.map
2
+ import {memo,forwardRef,useRef,useEffect,useCallback,useState}from'react';import {Switch}from'react-aria-components';import {cva}from'class-variance-authority';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {z}from'zod';function u(...a){return twMerge(clsx(a))}function y(a,o){return !(a===false||o)}var T="(prefers-reduced-motion: reduce)";function Q(){return typeof window>"u"?false:window.matchMedia(T).matches}function A(){let[a,o]=useState(Q);return useEffect(()=>{let i=window.matchMedia(T);o(i.matches);let r=c=>{o(c.matches);};return i.addEventListener("change",r),()=>i.removeEventListener("change",r)},[]),a}var R="data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2",X="data-[pressed]:scale-[0.97]";var S="hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground",P="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",N="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var C=`${R} ${X} ${S} ${P} ${N}`;var f;function ee(){return f!==void 0?Promise.resolve(f):import('motion').then(a=>(f=a.animate,f)).catch(()=>(f=null,null))}var te={stiffness:500,damping:30},_=cva("inline-flex shrink-0 cursor-pointer items-center justify-center min-h-[44px] min-w-[44px] disabled:cursor-not-allowed disabled:opacity-50 data-[readonly]:cursor-default",{variants:{},defaultVariants:{}}),k=cva("relative inline-flex shrink-0 items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background",{variants:{variant:{default:"bg-[var(--border)] data-[selected]:bg-[var(--primary)]",destructive:"bg-[var(--border)] data-[selected]:bg-[var(--destructive-background)]"},size:{sm:"h-6 w-10",default:"h-7 w-12",lg:"h-8 w-14"}},defaultVariants:{variant:"default",size:"default"}}),V=cva("pointer-events-none absolute left-0.5 rounded-full bg-[var(--content-background)] ring-0",{variants:{size:{sm:"h-4 w-4",default:"h-5 w-5",lg:"h-6 w-6"},animated:{false:"transition-transform data-[selected]:translate-x-full",true:""}},defaultVariants:{size:"default",animated:false}}),L=memo(forwardRef(({className:a,variant:o,size:i,label:r,description:c,isDisabled:b,isReadOnly:w,animated:F,springConfig:p=te,onChange:v,...H},M)=>{let z=A(),d=y(F,z),s=useRef(null),x=useRef(false),h=useRef(null),E=useRef(null);useEffect(()=>{d&&ee().then(t=>{if(t&&(h.current=t,x.current=true,s.current)){let B=s.current.hasAttribute("data-selected");s.current.style.transform=B?"translateX(100%)":"translateX(0)";}});},[d]);let D=useCallback(t=>{v?.(t),d&&x.current&&h.current&&s.current&&(E.current?.stop(),E.current=h.current(s.current,{x:t?"100%":"0%"},{type:"spring",stiffness:p.stiffness,damping:p.damping}));},[d,p.stiffness,p.damping,v]),$=d;return jsx(Switch,{ref:M,isDisabled:b,isReadOnly:w,onChange:D,className:t=>u("group relative inline-flex items-center gap-2",b&&"cursor-not-allowed opacity-50",a),...H,children:t=>jsxs(Fragment,{children:[jsx("div",{className:u(_()),"data-selected":t.isSelected||void 0,"data-readonly":w||void 0,children:jsx("div",{className:u(k({variant:o,size:i}),C),"data-selected":t.isSelected||void 0,children:jsx("div",{ref:s,className:u(V({size:i,animated:$})),"data-selected":t.isSelected||void 0})})}),(r||c)&&jsxs("div",{className:"flex flex-col",children:[r&&jsx("span",{className:"text-sm font-medium text-[var(--content-foreground)]",children:r}),c&&jsx("span",{className:"text-xs text-[var(--menu-muted)]",children:c})]})]})})}));L.displayName="Switch";var I=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 ae=I.extend({isSelected:z.boolean().optional(),defaultSelected:z.boolean().optional().default(false),onChange:z.function().optional(),variant:z.enum(["default","destructive"]).optional().default("default"),size:z.enum(["sm","default","lg"]).optional().default("default"),isDisabled:z.boolean().optional().default(false),isReadOnly:z.boolean().optional().default(false),label:z.string().optional(),description:z.string().optional(),onFocus:z.function().optional(),onBlur:z.function().optional(),onFocusChange:z.function().optional(),autoFocus:z.boolean().optional(),animated:z.boolean().optional().default(true),springConfig:z.object({stiffness:z.number(),damping:z.number()}).optional()});export{L as Switch,ae as SwitchPropsSchema,_ as switchOuterVariants,V as switchThumbVariants,k as switchTrackVariants};//# sourceMappingURL=index.mjs.map
3
3
  //# sourceMappingURL=index.mjs.map