@tribepad/themis 1.0.12 → 1.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/Tabs/Tabs.d.ts.map +1 -1
- package/dist/elements/Tabs/index.js +1 -1
- package/dist/elements/Tabs/index.js.map +1 -1
- package/dist/elements/Tabs/index.mjs +1 -1
- package/dist/elements/Tabs/index.mjs.map +1 -1
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -1
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/elements/Tabs/Tabs.tsx"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAEX,YAAY,EACZ,QAAQ,EACR,aAAa,EACd,MAAM,cAAc,CAAC;AAgEtB;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;
|
|
1
|
+
{"version":3,"file":"Tabs.d.ts","sourceRoot":"","sources":["../../../src/elements/Tabs/Tabs.tsx"],"names":[],"mappings":"AA+DA,OAAO,KAAK,EACV,SAAS,EACT,WAAW,EAEX,YAAY,EACZ,QAAQ,EACR,aAAa,EACd,MAAM,cAAc,CAAC;AAgEtB;;;;;GAKG;AACH,eAAO,MAAM,eAAe;;;8EA6B3B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,WAAW;;;8EAoDvB,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,2FAU5B,CAAC;AAMF;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,iBAAS,QAAQ,CAAC,EAChB,QAAQ,EACR,OAAmB,EACnB,WAAW,EACX,kBAAkB,EAClB,iBAAiB,EACjB,WAA0B,EAC1B,kBAAgC,EAChC,UAAkB,EAClB,YAAY,EACZ,QAAQ,EAAE,YAAY,EACtB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,SAAS,2CAwCX;kBArDQ,QAAQ;;;AAyDjB;;;;;;;;GAQG;AACH,iBAAS,gBAAgB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,YAAY,2CA2Cd;kBA/CQ,gBAAgB;;;AAmDzB;;;;;;;;;;GAUG;AACH,iBAAS,YAAY,CAAC,EACpB,QAAQ,EACR,EAAE,EACF,UAAkB,EAClB,IAAI,EACJ,MAAM,EACN,GAAG,EACH,QAAQ,EACR,SAAS,EACT,GAAG,KAAK,EACT,EAAE,QAAQ,2CAqIV;kBA/IQ,YAAY;;;AAmJrB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,iBAAS,iBAAiB,CAAC,EACzB,QAAQ,EACR,EAAE,EACF,gBAAwB,EACxB,aAAqB,EACrB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,aAAa,2CA2Ef;kBAlFQ,iBAAiB;;;AA0F1B;;;;;;;;;GASG;AACH,eAAO,MAAM,IAAI,iBAAW,CAAC;AAC7B,eAAO,MAAM,OAAO,yBAAmB,CAAC;AACxC,eAAO,MAAM,GAAG,qBAAe,CAAC;AAChC,eAAO,MAAM,QAAQ,0BAAoB,CAAC;AAG1C,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,CAAC"}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
'use strict';var react=require('react'),lucideReact=require('lucide-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
|
|
2
|
+
'use strict';var react=require('react'),lucideReact=require('lucide-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 p(...t){return tailwindMerge.twMerge(clsx.clsx(t))}function O(t,a){return !(t===false||a)}var F="(prefers-reduced-motion: reduce)";function le(){return typeof window>"u"?false:window.matchMedia(F).matches}function j(){let[t,a]=react.useState(le);return react.useEffect(()=>{let r=window.matchMedia(F);a(r.matches);let i=l=>{a(l.matches);};return r.addEventListener("change",i),()=>r.removeEventListener("change",i)},[]),t}var B=react.Activity??function({children:a,mode:r}){return jsxRuntime.jsx("div",{"data-activity-mode":r,children:a})},S;function ye(){return S!==void 0?Promise.resolve(S):import('motion/react').then(t=>(S=t.motion.span,S)).catch(()=>(S=null,null))}var I=react.createContext({variant:"default",orientation:"horizontal",animated:true}),Y=react.createContext({tabKeys:[]}),z=classVarianceAuthority.cva(["inline-flex items-center text-[var(--menu-muted)]"],{variants:{variant:{default:"border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0",block:"justify-center rounded-md p-1 bg-[var(--accent-background)]",stepper:"flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none"},orientation:{horizontal:"flex-row",vertical:"h-auto flex-col w-full"}},compoundVariants:[{variant:"block",orientation:"horizontal",class:"h-10 gap-0"},{variant:"block",orientation:"vertical",class:"gap-1"},{variant:"default",orientation:"vertical",class:"border-b-0 border-l"},{variant:"stepper",orientation:"vertical",class:"!flex-row gap-1"}],defaultVariants:{variant:"default",orientation:"horizontal"}}),D=classVarianceAuthority.cva(["inline-flex items-center justify-center gap-2 whitespace-nowrap","px-3 py-1.5 text-sm font-medium","ring-offset-[var(--content-background)] transition-all","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2","data-[disabled]:pointer-events-none data-[disabled]:opacity-50","min-h-[44px]"],{variants:{variant:{default:["rounded-none bg-transparent","data-[selected]:text-[var(--content-foreground)]","hover:text-[var(--content-foreground)]"],block:["rounded-sm","data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]","data-[selected]:shadow-sm"],stepper:["flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2"]},orientation:{horizontal:"",vertical:"w-full justify-start"}},compoundVariants:[{variant:"default",orientation:"horizontal",class:"relative -mb-px"},{variant:"default",orientation:"vertical",class:"relative -ml-px"}],defaultVariants:{variant:"default",orientation:"horizontal"}}),N=classVarianceAuthority.cva(["mt-2 ring-offset-[var(--content-background)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"],{variants:{},defaultVariants:{}});function _({children:t,variant:a="default",selectedKey:r,defaultSelectedKey:i,onSelectionChange:l,orientation:n="horizontal",keyboardActivation:b="automatic",isDisabled:c=false,disabledKeys:u,animated:d,className:y,...P}){let h=j(),A=O(d,h),[w,R]=react.useState(r??i),K=T=>{a==="stepper"&&R(T),l?.(T);},C=a==="stepper"?r??w:void 0;return jsxRuntime.jsx(I.Provider,{value:{variant:a,orientation:n,stepperSelectedKey:C,animated:A},children:jsxRuntime.jsx(reactAriaComponents.Tabs,{selectedKey:r,defaultSelectedKey:i,onSelectionChange:K,orientation:n,keyboardActivation:b,isDisabled:c,disabledKeys:u,className:p(y),...P,children:t})})}_.displayName="Tabs";function G({children:t,className:a,...r}){let{variant:i}=react.useContext(I);if(i==="stepper"){let l=[];return react.Children.forEach(t,n=>{react.isValidElement(n)&&n.props&&typeof n.props.id<"u"&&l.push(n.props.id);}),jsxRuntime.jsx(Y.Provider,{value:{tabKeys:l},children:jsxRuntime.jsx(reactAriaComponents.TabList,{className:reactAriaComponents.composeRenderProps(a,(n,b)=>p(z({variant:i,orientation:b.orientation}),n)),...r,children:t})})}return jsxRuntime.jsx(reactAriaComponents.TabList,{className:reactAriaComponents.composeRenderProps(a,(l,n)=>p(z({variant:i,orientation:n.orientation}),l)),...r,children:t})}G.displayName="TabList";function J({children:t,id:a,isDisabled:r=false,href:i,target:l,rel:n,download:b,className:c,...u}){process.env.NODE_ENV!=="production"&&!(typeof t=="string"||Array.isArray(t)&&t.some(x=>typeof x=="string"))&&!u["aria-label"]&&console.warn("Tabs: Icon-only tabs should have an aria-label for accessibility.");let{variant:d,orientation:y,stepperSelectedKey:P,animated:h}=react.useContext(I),A=react.useContext(Y),[w,R]=react.useState(null),K=react.useRef(false);if(react.useEffect(()=>{d!=="default"||!h||K.current||(K.current=true,ye().then(s=>{s&&R(()=>s);}));},[d,h]),d==="stepper"){let s=A.tabKeys.indexOf(a),x=P!==void 0?A.tabKeys.indexOf(P):-1,te=s===0,V=s>=0&&x>=0&&s<x,k=s>=0&&s===x,ae=y==="vertical";return jsxRuntime.jsxs(reactAriaComponents.Tab,{id:a,isDisabled:r,href:i,target:l,rel:n,download:b,className:reactAriaComponents.composeRenderProps(c,oe=>p(D({variant:d,orientation:y}),k&&"bg-[var(--primary-action)]/10 rounded-lg",oe)),...u,children:[!te&&!ae&&jsxRuntime.jsx("span",{className:"h-px w-6 bg-[var(--border)]","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:p("flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-xs font-bold",k||V?"bg-[var(--primary-action)] text-white":"bg-[var(--accent-background)] text-[var(--muted-foreground)]"),"aria-hidden":"true",children:V?jsxRuntime.jsx(lucideReact.Check,{className:"h-3.5 w-3.5"}):s+1}),jsxRuntime.jsx("span",{className:"sr-only",children:V?`Step ${s+1}, completed:`:`Step ${s+1}:`}),jsxRuntime.jsx("span",{className:p(k&&"font-semibold text-[var(--primary-action)]"),children:t})]})}let C=y==="horizontal",T=C?"absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]":"absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]";return jsxRuntime.jsx(reactAriaComponents.Tab,{id:a,isDisabled:r,href:i,target:l,rel:n,download:b,className:reactAriaComponents.composeRenderProps(c,s=>p(D({variant:d,orientation:y}),s)),...u,children:s=>jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[t,d==="default"&&s.isSelected&&(h&&w?jsxRuntime.jsx(w,{layoutId:`tab-indicator-${C?"h":"v"}`,className:T,transition:{type:"spring",stiffness:500,damping:30}}):jsxRuntime.jsx("span",{className:T}))]})})}J.displayName="Tab";function W({children:t,id:a,shouldForceMount:r=false,preserveState:i=false,className:l,...n}){let b=i||r;return typeof t=="function"?jsxRuntime.jsx(reactAriaComponents.TabPanel,{id:a,shouldForceMount:b,className:reactAriaComponents.composeRenderProps(l,c=>p(N(),c)),...n,children:c=>{let u=!c.isInert,d=t({isSelected:u});return i?jsxRuntime.jsx(B,{mode:u?"visible":"hidden",children:d}):d}}):i?jsxRuntime.jsx(reactAriaComponents.TabPanel,{id:a,shouldForceMount:b,className:reactAriaComponents.composeRenderProps(l,c=>p(N(),c)),...n,children:c=>{let u=!c.isInert;return jsxRuntime.jsx(B,{mode:u?"visible":"hidden",children:t})}}):jsxRuntime.jsx(reactAriaComponents.TabPanel,{id:a,shouldForceMount:b,className:reactAriaComponents.composeRenderProps(l,c=>p(N(),c)),...n,children:t})}W.displayName="TabPanel";var ge=_,ve=G,he=J,Te=W;var g=zod.z.object({className:zod.z.string().optional(),children:zod.z.any().optional(),id:zod.z.string().optional(),"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),"aria-describedby":zod.z.string().optional(),"aria-live":zod.z.enum(["off","polite","assertive"]).optional(),"aria-hidden":zod.z.boolean().optional(),"data-testid":zod.z.string().optional()});var Se=zod.z.enum(["default","block","stepper"]),X=zod.z.enum(["horizontal","vertical"]),Z=zod.z.enum(["automatic","manual"]),v=zod.z.union([zod.z.string(),zod.z.number()]),Pe=g.extend({variant:Se.optional().default("default"),selectedKey:v.optional(),defaultSelectedKey:v.optional(),onSelectionChange:zod.z.custom().optional(),orientation:X.optional().default("horizontal"),keyboardActivation:Z.optional().default("automatic"),isDisabled:zod.z.boolean().optional().default(false),disabledKeys:zod.z.array(v).optional(),children:zod.z.custom(),animated:zod.z.boolean().optional().default(true)}),Ae=g.extend({"aria-label":zod.z.string().optional(),"aria-labelledby":zod.z.string().optional(),children:zod.z.custom()}),we=g.extend({id:v,isDisabled:zod.z.boolean().optional().default(false),href:zod.z.string().optional(),target:zod.z.string().optional(),rel:zod.z.string().optional(),download:zod.z.union([zod.z.string(),zod.z.boolean()]).optional(),children:zod.z.custom()}),Ke=g.extend({id:v,shouldForceMount:zod.z.boolean().optional().default(false),preserveState:zod.z.boolean().optional().default(false),children:zod.z.custom()}),ee=zod.z.enum(["left","right","up","down"]),Ce=g.extend({direction:ee,isDisabled:zod.z.boolean().optional().default(false),onPress:zod.z.custom(),"aria-label":zod.z.string()});exports.KeySchema=v;exports.ScrollArrowDirectionSchema=ee;exports.ScrollArrowPropsSchema=Ce;exports.Tab=he;exports.TabList=ve;exports.TabListPropsSchema=Ae;exports.TabPanel=Te;exports.TabPanelPropsSchema=Ke;exports.TabPropsSchema=we;exports.Tabs=ge;exports.TabsKeyboardActivationSchema=Z;exports.TabsOrientationSchema=X;exports.TabsPropsSchema=Pe;exports.tabListVariants=z;exports.tabPanelVariants=N;exports.tabVariants=D;//# 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/elements/Tabs/Tabs.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Tabs/Tabs.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","Activity","ReactActivity","children","mode","jsx","cachedMotionSpan","loadMotionSpan","m","TabsInternalContext","createContext","StepperContext","tabListVariants","cva","tabVariants","tabPanelVariants","TabsRoot","variant","selectedKey","defaultSelectedKey","onSelectionChange","orientation","keyboardActivation","isDisabled","disabledKeys","animatedProp","className","props","doAnimate","trackedKey","setTrackedKey","handleSelectionChange","key","stepperSelectedKey","AriaTabs","TabListComponent","useContext","tabKeys","Children","child","isValidElement","AriaTabList","composeRenderProps","renderProps","TabComponent","id","href","target","rel","download","stepperCtx","MotionSpan","setMotionSpan","motionLoadedRef","useRef","component","tabIndex","selectedIndex","isFirst","isCompleted","isActive","jsxs","AriaTab","Check","isHorizontal","indicatorClasses","Fragment","TabPanelComponent","shouldForceMount","preserveState","forceMount","AriaTabPanel","isSelected","content","Tabs","TabList","Tab","TabPanel","BaseComponentPropsSchema","z","TabsVariantSchema","TabsOrientationSchema","TabsKeyboardActivationSchema","KeySchema","TabsPropsSchema","TabListPropsSchema","TabPropsSchema","TabPanelPropsSchema","ScrollArrowDirectionSchema","ScrollArrowPropsSchema"],"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","'use client';\n\n/**\n * Tabs Component - Implementation\n *\n * Accessible tabbed interface component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria Tabs for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for orientation styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Dual keyboard activation modes (automatic/manual)\n * - Support for icons, badges, and link-based tabs\n *\n * @see tabs-prd.md (Full requirements)\n * @see Tabs.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 Children,\n createContext,\n isValidElement,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n type Key,\n type ReactElement,\n} from 'react';\nimport { Check } from 'lucide-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\n// Note: ActivityFallback doesn't actually preserve state; it's just a pass-through\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n // When Activity is not available, just render children directly\n // mode is ignored in the fallback\n return <div data-activity-mode={mode}>{children}</div>;\n};\nimport {\n Tabs as AriaTabs,\n TabList as AriaTabList,\n Tab as AriaTab,\n TabPanel as AriaTabPanel,\n composeRenderProps,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport type {\n TabsProps,\n TabsVariant,\n TabsOrientation,\n TabListProps,\n TabProps,\n TabPanelProps,\n} from './Tabs.types';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype MotionSpanComponent = React.ComponentType<{\n layoutId?: string;\n className?: string;\n transition?: Record<string, unknown>;\n style?: React.CSSProperties;\n}>;\n\nlet cachedMotionSpan: MotionSpanComponent | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionSpan(): Promise<MotionSpanComponent | null> {\n if (cachedMotionSpan !== undefined) return Promise.resolve(cachedMotionSpan);\n\n return import('motion/react')\n .then((m) => {\n cachedMotionSpan = m.motion.span as unknown as MotionSpanComponent;\n return cachedMotionSpan;\n })\n .catch(() => {\n cachedMotionSpan = null;\n return null;\n });\n}\n\n// ============================================================================\n// Internal Context\n// ============================================================================\n\ninterface TabsContextValue {\n variant: TabsVariant;\n orientation: TabsOrientation;\n /** For stepper variant: tracked selected key from Tabs root */\n stepperSelectedKey?: Key;\n /** Whether the indicator should animate. Default: true */\n animated: boolean;\n}\n\nconst TabsInternalContext = createContext<TabsContextValue>({\n variant: 'default',\n orientation: 'horizontal',\n animated: true,\n});\n\n/**\n * Stepper context for tracking tab order.\n * Only used when variant=\"stepper\" to determine completed/active/inactive states.\n */\ninterface StepperContextValue {\n tabKeys: Key[];\n}\n\nconst StepperContext = createContext<StepperContextValue>({\n tabKeys: [],\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * TabList CVA variants\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md DS-001 (Design System - Layout)\n */\nexport const tabListVariants = cva(\n // Base styles\n [\n 'inline-flex items-center text-[var(--menu-muted)]',\n ],\n {\n variants: {\n variant: {\n default: 'border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0',\n block: 'justify-center rounded-md p-1 bg-[var(--accent-background)]',\n stepper: 'flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none',\n },\n orientation: {\n horizontal: 'flex-row',\n vertical: 'h-auto flex-col w-full',\n },\n },\n compoundVariants: [\n { variant: 'block', orientation: 'horizontal', class: 'h-10 gap-0' },\n { variant: 'block', orientation: 'vertical', class: 'gap-1' },\n { variant: 'default', orientation: 'vertical', class: 'border-b-0 border-l' },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * Tab CVA variants\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md DS-002 (Design System - Tab Styling)\n * @see PRD.md AR-001 (Accessibility - 44×44px touch targets)\n */\nexport const tabVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap',\n 'px-3 py-1.5 text-sm font-medium',\n 'ring-offset-[var(--content-background)] transition-all',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n // States via data attributes\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // WCAG 2.2 AAA: 44×44px minimum touch target\n 'min-h-[44px]',\n ],\n {\n variants: {\n variant: {\n default: [\n 'rounded-none bg-transparent',\n 'data-[selected]:text-[var(--content-foreground)]',\n 'hover:text-[var(--content-foreground)]',\n ],\n block: [\n 'rounded-sm',\n 'data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]',\n 'data-[selected]:shadow-sm',\n ],\n stepper: [\n 'flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2',\n ],\n },\n orientation: {\n horizontal: '',\n vertical: 'w-full justify-start',\n },\n },\n compoundVariants: [\n {\n variant: 'default',\n orientation: 'horizontal',\n class: 'relative -mb-px',\n },\n {\n variant: 'default',\n orientation: 'vertical',\n class: 'relative -ml-px',\n },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * TabPanel CVA variants\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n */\nexport const tabPanelVariants = cva(\n [\n 'mt-2 ring-offset-[var(--content-background)]',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n ],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Tabs Root Component\n *\n * Container for tabbed interface. Manages selection state and provides\n * context to child components.\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled\n * <Tabs defaultSelectedKey=\"tab1\">\n * <TabList aria-label=\"Navigation\">\n * <Tab id=\"tab1\">Tab 1</Tab>\n * <Tab id=\"tab2\">Tab 2</Tab>\n * </TabList>\n * <TabPanel id=\"tab1\">Content 1</TabPanel>\n * <TabPanel id=\"tab2\">Content 2</TabPanel>\n * </Tabs>\n *\n * @example\n * // Controlled\n * <Tabs selectedKey={selected} onSelectionChange={setSelected}>\n * ...\n * </Tabs>\n */\nfunction TabsRoot({\n children,\n variant = 'default',\n selectedKey,\n defaultSelectedKey,\n onSelectionChange,\n orientation = 'horizontal',\n keyboardActivation = 'automatic',\n isDisabled = false,\n disabledKeys,\n animated: animatedProp,\n className,\n ...props\n}: TabsProps) {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animatedProp, prefersReducedMotion);\n // For stepper variant, track the selected key internally so Tab children\n // can determine completed/active/inactive state. React Aria's internal\n // TabListStateContext is not accessible from our Tab wrapper since tabs\n // are rendered via the collection system.\n const [trackedKey, setTrackedKey] = useState<Key | undefined>(\n selectedKey ?? defaultSelectedKey\n );\n\n const handleSelectionChange = (key: Key) => {\n if (variant === 'stepper') {\n setTrackedKey(key);\n }\n onSelectionChange?.(key);\n };\n\n // For controlled mode, use the prop directly\n const stepperSelectedKey = variant === 'stepper'\n ? (selectedKey ?? trackedKey)\n : undefined;\n\n return (\n <TabsInternalContext.Provider value={{ variant, orientation, stepperSelectedKey, animated: doAnimate }}>\n <AriaTabs\n selectedKey={selectedKey}\n defaultSelectedKey={defaultSelectedKey}\n onSelectionChange={handleSelectionChange as (key: Key) => void}\n orientation={orientation}\n keyboardActivation={keyboardActivation}\n isDisabled={isDisabled}\n disabledKeys={disabledKeys as Iterable<AriaKey> | undefined}\n className={cn(className)}\n {...props}\n >\n {children}\n </AriaTabs>\n </TabsInternalContext.Provider>\n );\n}\n\nTabsRoot.displayName = 'Tabs';\n\n/**\n * TabList Component\n *\n * Container for tab buttons. Uses roving tabindex for keyboard navigation.\n * Receives orientation from parent Tabs via React Aria context.\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nfunction TabListComponent({\n children,\n className,\n ...props\n}: TabListProps) {\n const { variant } = useContext(TabsInternalContext);\n\n // For stepper variant, collect tab keys from children to determine order\n if (variant === 'stepper') {\n // Extract keys from Tab children to determine ordering\n const tabKeys: Key[] = [];\n Children.forEach(children as ReactNode, (child) => {\n if (isValidElement(child) && child.props && typeof (child.props as Record<string, unknown>).id !== 'undefined') {\n tabKeys.push((child.props as Record<string, unknown>).id as Key);\n }\n });\n\n return (\n <StepperContext.Provider value={{ tabKeys }}>\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n </StepperContext.Provider>\n );\n }\n\n return (\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n );\n}\n\nTabListComponent.displayName = 'TabList';\n\n/**\n * Tab Component\n *\n * Individual tab button. Can render as button or anchor (when href provided).\n * Supports icons and badges as children.\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-013 (Icon Support)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nfunction TabComponent({\n children,\n id,\n isDisabled = false,\n href,\n target,\n rel,\n download,\n className,\n ...props\n}: TabProps) {\n // Warn if icon-only tab without aria-label\n if (process.env.NODE_ENV !== 'production') {\n const hasTextContent =\n typeof children === 'string' ||\n (Array.isArray(children) &&\n children.some((child) => typeof child === 'string'));\n\n if (!hasTextContent && !props['aria-label']) {\n console.warn(\n 'Tabs: Icon-only tabs should have an aria-label for accessibility.'\n );\n }\n }\n\n const { variant, orientation, stepperSelectedKey, animated: doAnimate } = useContext(TabsInternalContext);\n const stepperCtx = useContext(StepperContext);\n\n // Motion.dev component for animated indicator (lazy-loaded)\n const [MotionSpan, setMotionSpan] = useState<MotionSpanComponent | null>(null);\n const motionLoadedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== 'default' || !doAnimate || motionLoadedRef.current) return;\n motionLoadedRef.current = true;\n loadMotionSpan().then((component) => {\n if (component) setMotionSpan(() => component);\n });\n }, [variant, doAnimate]);\n\n // For stepper variant, render numbered circle with connecting line\n if (variant === 'stepper') {\n const tabIndex = stepperCtx.tabKeys.indexOf(id);\n const selectedIndex = stepperSelectedKey !== undefined\n ? stepperCtx.tabKeys.indexOf(stepperSelectedKey)\n : -1;\n const isFirst = tabIndex === 0;\n const isCompleted = tabIndex >= 0 && selectedIndex >= 0 && tabIndex < selectedIndex;\n const isActive = tabIndex >= 0 && tabIndex === selectedIndex;\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {/* Connecting line before tab (except first) */}\n {!isFirst && (\n <span\n className=\"h-px w-6 bg-[var(--border)]\"\n aria-hidden=\"true\"\n />\n )}\n {/* Step circle */}\n <span\n className={cn(\n 'flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-medium',\n (isActive || isCompleted)\n ? 'bg-[var(--primary-action)] text-white'\n : 'bg-[var(--accent-background)] text-[var(--muted-foreground)]'\n )}\n aria-hidden=\"true\"\n >\n {isCompleted ? (\n <Check className=\"h-3.5 w-3.5\" />\n ) : (\n tabIndex + 1\n )}\n </span>\n {/* Visually hidden step number for screen readers */}\n <span className=\"sr-only\">\n {isCompleted ? `Step ${tabIndex + 1}, completed:` : `Step ${tabIndex + 1}:`}\n </span>\n {/* Tab label */}\n <span>{children}</span>\n </AriaTab>\n );\n }\n\n // Default variant: render with sliding indicator\n const isHorizontal = orientation === 'horizontal';\n const indicatorClasses = isHorizontal\n ? 'absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]'\n : 'absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {(renderProps) => (\n <>\n {children}\n {/* Tab indicator — animated slide or instant position */}\n {variant === 'default' && renderProps.isSelected && (\n doAnimate && MotionSpan ? (\n <MotionSpan\n layoutId={`tab-indicator-${isHorizontal ? 'h' : 'v'}`}\n className={indicatorClasses}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n />\n ) : (\n <span className={indicatorClasses} />\n )\n )}\n </>\n )}\n </AriaTab>\n );\n}\n\nTabComponent.displayName = 'Tab';\n\n/**\n * TabPanel Component\n *\n * Content panel associated with a tab. Only the selected panel is visible.\n * Supports preserveState for React Activity state preservation.\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n *\n * @example\n * // Default behavior - content unmounts when hidden\n * <TabPanel id=\"tab1\">Content</TabPanel>\n *\n * @example\n * // Legacy force mount - keeps content in DOM\n * <TabPanel id=\"tab1\" shouldForceMount>Form with state</TabPanel>\n *\n * @example\n * // React Activity - preserves state with proper effect cleanup\n * <TabPanel id=\"tab1\" preserveState>\n * <FormWithDraft />\n * </TabPanel>\n */\nfunction TabPanelComponent({\n children,\n id,\n shouldForceMount = false,\n preserveState = false,\n className,\n ...props\n}: TabPanelProps) {\n // preserveState takes precedence - both enable force mounting\n const forceMount = preserveState || shouldForceMount;\n\n // If children is a render function (for dynamic content based on selection state),\n // we need to use the render props pattern\n if (typeof children === 'function') {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n // React Aria TabPanelRenderProps includes: state, isInert\n // We derive isSelected from state - if state is undefined, panel is selected\n const isSelected = !renderProps.isInert;\n const content = (\n children as (renderProps: { isSelected: boolean }) => ReactNode\n )({ isSelected });\n\n if (preserveState) {\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {content}\n </Activity>\n );\n }\n\n return content;\n }}\n </AriaTabPanel>\n );\n }\n\n // For static children (not a function), render directly\n // If preserveState is enabled, wrap in Activity\n if (preserveState) {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n const isSelected = !renderProps.isInert;\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {children}\n </Activity>\n );\n }}\n </AriaTabPanel>\n );\n }\n\n // Default: render static children directly\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {children}\n </AriaTabPanel>\n );\n}\n\nTabPanelComponent.displayName = 'TabPanel';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Tabs follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components vs Dialog's 9)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Tabs, TabList, Tab, TabPanel } from '...'\n *\n * @see plan.md \"Why Direct Named Exports (Not Object.assign)?\"\n */\nexport const Tabs = TabsRoot;\nexport const TabList = TabListComponent;\nexport const Tab = TabComponent;\nexport const TabPanel = TabPanelComponent;\n\n// Re-export types for convenience\nexport type { TabsProps, TabsVariant, TabListProps, TabProps, TabPanelProps };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode, Key } from 'react';\n\n/**\n * Tab variant schema\n *\n * - 'default': Transparent background with bottom border indicator for active tab\n * - 'block': Pill/card style with accent background and shadow for active tab\n * - 'stepper': Numbered step circles with connecting lines (free navigation, not a wizard)\n */\nexport const TabsVariantSchema = z.enum(['default', 'block', 'stepper']);\nexport type TabsVariant = z.infer<typeof TabsVariantSchema>;\n\n/**\n * Tab orientation schema\n *\n * @see PRD.md FR-005 (Orientation Support)\n */\nexport const TabsOrientationSchema = z.enum(['horizontal', 'vertical']);\nexport type TabsOrientation = z.infer<typeof TabsOrientationSchema>;\n\n/**\n * Keyboard activation mode schema\n *\n * @see PRD.md FR-006 (Keyboard Activation Modes)\n */\nexport const TabsKeyboardActivationSchema = z.enum(['automatic', 'manual']);\nexport type TabsKeyboardActivation = z.infer<typeof TabsKeyboardActivationSchema>;\n\n/**\n * Key schema for tab identification\n * Supports both string and number keys per React Aria convention\n */\nexport const KeySchema = z.union([z.string(), z.number()]);\n\n/**\n * Tabs root component props schema\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nexport const TabsPropsSchema = BaseComponentPropsSchema.extend({\n // Visual variant: 'default' (underline) or 'block' (pill/card)\n variant: TabsVariantSchema.optional().default('default'),\n\n // Controlled mode: selected tab key\n selectedKey: KeySchema.optional(),\n\n // Uncontrolled mode: default selected tab key\n defaultSelectedKey: KeySchema.optional(),\n\n // Selection change handler\n onSelectionChange: z.custom<(key: Key) => void>().optional(),\n\n // Orientation: horizontal or vertical layout\n orientation: TabsOrientationSchema.optional().default('horizontal'),\n\n // Keyboard activation: automatic (arrows select) or manual (arrows focus, Enter selects)\n keyboardActivation: TabsKeyboardActivationSchema.optional().default('automatic'),\n\n // Disable all tabs\n isDisabled: z.boolean().optional().default(false),\n\n // Keys of tabs to disable individually\n disabledKeys: z.array(KeySchema).optional(),\n\n // Children: TabList and TabPanel components\n children: z.custom<ReactNode>(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n // When true, the tab indicator slides between tabs (default variant only)\n animated: z.boolean().optional().default(true),\n});\n\nexport interface TabsProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n variant?: TabsVariant;\n selectedKey?: string | number;\n defaultSelectedKey?: string | number;\n onSelectionChange?: (key: Key) => void;\n orientation?: TabsOrientation;\n keyboardActivation?: TabsKeyboardActivation;\n isDisabled?: boolean;\n disabledKeys?: (string | number)[];\n animated?: boolean;\n}\n\n/**\n * TabList component props schema\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nexport const TabListPropsSchema = BaseComponentPropsSchema.extend({\n // Accessible label (required for accessibility if no aria-labelledby)\n 'aria-label': z.string().optional(),\n\n // Reference to labelling element\n 'aria-labelledby': z.string().optional(),\n\n // Children: Tab components\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabListProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n}\n\n/**\n * Tab component props schema\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nexport const TabPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier for the tab (required)\n id: KeySchema,\n\n // Disable this specific tab\n isDisabled: z.boolean().optional().default(false),\n\n // Link tab: URL for navigation-style tabs\n href: z.string().optional(),\n\n // Link tab: target attribute\n target: z.string().optional(),\n\n // Link tab: rel attribute\n rel: z.string().optional(),\n\n // Link tab: download attribute\n download: z.union([z.string(), z.boolean()]).optional(),\n\n // Tab content (text, icons, badges)\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'data-testid'?: string;\n isDisabled?: boolean;\n href?: string;\n target?: string;\n rel?: string;\n download?: string | boolean;\n}\n\n/**\n * TabPanel component props schema\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n */\nexport const TabPanelPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier matching a Tab id (required)\n id: KeySchema,\n\n // Legacy: Force panel to stay in DOM when hidden\n // Use preserveState instead for proper effect cleanup\n shouldForceMount: z.boolean().optional().default(false),\n\n // React 19.2 Activity: Preserve state with proper effect cleanup\n // When true, wraps content in <Activity> component\n // Effects are cleaned up when hidden, restored when visible\n preserveState: z.boolean().optional().default(false),\n\n // Panel content\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabPanelProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n shouldForceMount?: boolean;\n preserveState?: boolean;\n}\n\n/**\n * Scroll arrow direction for overflow handling\n *\n * @see PRD.md FR-010 (Overflow Handling)\n */\nexport const ScrollArrowDirectionSchema = z.enum(['left', 'right', 'up', 'down']);\nexport type ScrollArrowDirection = z.infer<typeof ScrollArrowDirectionSchema>;\n\n/**\n * Internal props for scroll arrow buttons\n * Used by overflow handling implementation\n */\nexport const ScrollArrowPropsSchema = BaseComponentPropsSchema.extend({\n // Scroll direction\n direction: ScrollArrowDirectionSchema,\n\n // Disable when can't scroll further\n isDisabled: z.boolean().optional().default(false),\n\n // Click handler for scrolling\n onPress: z.custom<() => void>(),\n\n // Accessible label\n 'aria-label': z.string(),\n});\n\nexport interface ScrollArrowProps {\n className?: string;\n id?: string;\n 'aria-label': string;\n 'data-testid'?: string;\n direction: ScrollArrowDirection;\n isDisabled?: boolean;\n onPress: () => void;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/shouldAnimate.ts","../../../src/hooks/useReducedMotion.ts","../../../src/elements/Tabs/Tabs.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Tabs/Tabs.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","Activity","ReactActivity","children","mode","jsx","cachedMotionSpan","loadMotionSpan","m","TabsInternalContext","createContext","StepperContext","tabListVariants","cva","tabVariants","tabPanelVariants","TabsRoot","variant","selectedKey","defaultSelectedKey","onSelectionChange","orientation","keyboardActivation","isDisabled","disabledKeys","animatedProp","className","props","doAnimate","trackedKey","setTrackedKey","handleSelectionChange","key","stepperSelectedKey","AriaTabs","TabListComponent","useContext","tabKeys","Children","child","isValidElement","AriaTabList","composeRenderProps","renderProps","TabComponent","id","href","target","rel","download","stepperCtx","MotionSpan","setMotionSpan","motionLoadedRef","useRef","component","tabIndex","selectedIndex","isFirst","isCompleted","isActive","isVertical","jsxs","AriaTab","Check","isHorizontal","indicatorClasses","Fragment","TabPanelComponent","shouldForceMount","preserveState","forceMount","AriaTabPanel","isSelected","content","Tabs","TabList","Tab","TabPanel","BaseComponentPropsSchema","z","TabsVariantSchema","TabsOrientationSchema","TabsKeyboardActivationSchema","KeySchema","TabsPropsSchema","TabListPropsSchema","TabPropsSchema","TabPanelPropsSchema","ScrollArrowDirectionSchema","ScrollArrowPropsSchema"],"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","'use client';\n\n/**\n * Tabs Component - Implementation\n *\n * Accessible tabbed interface component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria Tabs for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for orientation styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Dual keyboard activation modes (automatic/manual)\n * - Support for icons, badges, and link-based tabs\n *\n * @see tabs-prd.md (Full requirements)\n * @see Tabs.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 Children,\n createContext,\n isValidElement,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n type Key,\n type ReactElement,\n} from 'react';\nimport { Check } from 'lucide-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\n// Note: ActivityFallback doesn't actually preserve state; it's just a pass-through\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n // When Activity is not available, just render children directly\n // mode is ignored in the fallback\n return <div data-activity-mode={mode}>{children}</div>;\n};\nimport {\n Tabs as AriaTabs,\n TabList as AriaTabList,\n Tab as AriaTab,\n TabPanel as AriaTabPanel,\n composeRenderProps,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport type {\n TabsProps,\n TabsVariant,\n TabsOrientation,\n TabListProps,\n TabProps,\n TabPanelProps,\n} from './Tabs.types';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype MotionSpanComponent = React.ComponentType<{\n layoutId?: string;\n className?: string;\n transition?: Record<string, unknown>;\n style?: React.CSSProperties;\n}>;\n\nlet cachedMotionSpan: MotionSpanComponent | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionSpan(): Promise<MotionSpanComponent | null> {\n if (cachedMotionSpan !== undefined) return Promise.resolve(cachedMotionSpan);\n\n return import('motion/react')\n .then((m) => {\n cachedMotionSpan = m.motion.span as unknown as MotionSpanComponent;\n return cachedMotionSpan;\n })\n .catch(() => {\n cachedMotionSpan = null;\n return null;\n });\n}\n\n// ============================================================================\n// Internal Context\n// ============================================================================\n\ninterface TabsContextValue {\n variant: TabsVariant;\n orientation: TabsOrientation;\n /** For stepper variant: tracked selected key from Tabs root */\n stepperSelectedKey?: Key;\n /** Whether the indicator should animate. Default: true */\n animated: boolean;\n}\n\nconst TabsInternalContext = createContext<TabsContextValue>({\n variant: 'default',\n orientation: 'horizontal',\n animated: true,\n});\n\n/**\n * Stepper context for tracking tab order.\n * Only used when variant=\"stepper\" to determine completed/active/inactive states.\n */\ninterface StepperContextValue {\n tabKeys: Key[];\n}\n\nconst StepperContext = createContext<StepperContextValue>({\n tabKeys: [],\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * TabList CVA variants\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md DS-001 (Design System - Layout)\n */\nexport const tabListVariants = cva(\n // Base styles\n [\n 'inline-flex items-center text-[var(--menu-muted)]',\n ],\n {\n variants: {\n variant: {\n default: 'border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0',\n block: 'justify-center rounded-md p-1 bg-[var(--accent-background)]',\n stepper: 'flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none',\n },\n orientation: {\n horizontal: 'flex-row',\n vertical: 'h-auto flex-col w-full',\n },\n },\n compoundVariants: [\n { variant: 'block', orientation: 'horizontal', class: 'h-10 gap-0' },\n { variant: 'block', orientation: 'vertical', class: 'gap-1' },\n { variant: 'default', orientation: 'vertical', class: 'border-b-0 border-l' },\n // Stepper vertical: undo the base flex-col so consumer controls direction via className\n { variant: 'stepper', orientation: 'vertical', class: '!flex-row gap-1' },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * Tab CVA variants\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md DS-002 (Design System - Tab Styling)\n * @see PRD.md AR-001 (Accessibility - 44×44px touch targets)\n */\nexport const tabVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap',\n 'px-3 py-1.5 text-sm font-medium',\n 'ring-offset-[var(--content-background)] transition-all',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n // States via data attributes\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // WCAG 2.2 AAA: 44×44px minimum touch target\n 'min-h-[44px]',\n ],\n {\n variants: {\n variant: {\n default: [\n 'rounded-none bg-transparent',\n 'data-[selected]:text-[var(--content-foreground)]',\n 'hover:text-[var(--content-foreground)]',\n ],\n block: [\n 'rounded-sm',\n 'data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]',\n 'data-[selected]:shadow-sm',\n ],\n stepper: [\n 'flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2',\n ],\n },\n orientation: {\n horizontal: '',\n vertical: 'w-full justify-start',\n },\n },\n compoundVariants: [\n {\n variant: 'default',\n orientation: 'horizontal',\n class: 'relative -mb-px',\n },\n {\n variant: 'default',\n orientation: 'vertical',\n class: 'relative -ml-px',\n },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * TabPanel CVA variants\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n */\nexport const tabPanelVariants = cva(\n [\n 'mt-2 ring-offset-[var(--content-background)]',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n ],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Tabs Root Component\n *\n * Container for tabbed interface. Manages selection state and provides\n * context to child components.\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled\n * <Tabs defaultSelectedKey=\"tab1\">\n * <TabList aria-label=\"Navigation\">\n * <Tab id=\"tab1\">Tab 1</Tab>\n * <Tab id=\"tab2\">Tab 2</Tab>\n * </TabList>\n * <TabPanel id=\"tab1\">Content 1</TabPanel>\n * <TabPanel id=\"tab2\">Content 2</TabPanel>\n * </Tabs>\n *\n * @example\n * // Controlled\n * <Tabs selectedKey={selected} onSelectionChange={setSelected}>\n * ...\n * </Tabs>\n */\nfunction TabsRoot({\n children,\n variant = 'default',\n selectedKey,\n defaultSelectedKey,\n onSelectionChange,\n orientation = 'horizontal',\n keyboardActivation = 'automatic',\n isDisabled = false,\n disabledKeys,\n animated: animatedProp,\n className,\n ...props\n}: TabsProps) {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animatedProp, prefersReducedMotion);\n // For stepper variant, track the selected key internally so Tab children\n // can determine completed/active/inactive state. React Aria's internal\n // TabListStateContext is not accessible from our Tab wrapper since tabs\n // are rendered via the collection system.\n const [trackedKey, setTrackedKey] = useState<Key | undefined>(\n selectedKey ?? defaultSelectedKey\n );\n\n const handleSelectionChange = (key: Key) => {\n if (variant === 'stepper') {\n setTrackedKey(key);\n }\n onSelectionChange?.(key);\n };\n\n // For controlled mode, use the prop directly\n const stepperSelectedKey = variant === 'stepper'\n ? (selectedKey ?? trackedKey)\n : undefined;\n\n return (\n <TabsInternalContext.Provider value={{ variant, orientation, stepperSelectedKey, animated: doAnimate }}>\n <AriaTabs\n selectedKey={selectedKey}\n defaultSelectedKey={defaultSelectedKey}\n onSelectionChange={handleSelectionChange as (key: Key) => void}\n orientation={orientation}\n keyboardActivation={keyboardActivation}\n isDisabled={isDisabled}\n disabledKeys={disabledKeys as Iterable<AriaKey> | undefined}\n className={cn(className)}\n {...props}\n >\n {children}\n </AriaTabs>\n </TabsInternalContext.Provider>\n );\n}\n\nTabsRoot.displayName = 'Tabs';\n\n/**\n * TabList Component\n *\n * Container for tab buttons. Uses roving tabindex for keyboard navigation.\n * Receives orientation from parent Tabs via React Aria context.\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nfunction TabListComponent({\n children,\n className,\n ...props\n}: TabListProps) {\n const { variant } = useContext(TabsInternalContext);\n\n // For stepper variant, collect tab keys from children to determine order\n if (variant === 'stepper') {\n // Extract keys from Tab children to determine ordering\n const tabKeys: Key[] = [];\n Children.forEach(children as ReactNode, (child) => {\n if (isValidElement(child) && child.props && typeof (child.props as Record<string, unknown>).id !== 'undefined') {\n tabKeys.push((child.props as Record<string, unknown>).id as Key);\n }\n });\n\n return (\n <StepperContext.Provider value={{ tabKeys }}>\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n </StepperContext.Provider>\n );\n }\n\n return (\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n );\n}\n\nTabListComponent.displayName = 'TabList';\n\n/**\n * Tab Component\n *\n * Individual tab button. Can render as button or anchor (when href provided).\n * Supports icons and badges as children.\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-013 (Icon Support)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nfunction TabComponent({\n children,\n id,\n isDisabled = false,\n href,\n target,\n rel,\n download,\n className,\n ...props\n}: TabProps) {\n // Warn if icon-only tab without aria-label\n if (process.env.NODE_ENV !== 'production') {\n const hasTextContent =\n typeof children === 'string' ||\n (Array.isArray(children) &&\n children.some((child) => typeof child === 'string'));\n\n if (!hasTextContent && !props['aria-label']) {\n console.warn(\n 'Tabs: Icon-only tabs should have an aria-label for accessibility.'\n );\n }\n }\n\n const { variant, orientation, stepperSelectedKey, animated: doAnimate } = useContext(TabsInternalContext);\n const stepperCtx = useContext(StepperContext);\n\n // Motion.dev component for animated indicator (lazy-loaded)\n const [MotionSpan, setMotionSpan] = useState<MotionSpanComponent | null>(null);\n const motionLoadedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== 'default' || !doAnimate || motionLoadedRef.current) return;\n motionLoadedRef.current = true;\n loadMotionSpan().then((component) => {\n if (component) setMotionSpan(() => component);\n });\n }, [variant, doAnimate]);\n\n // For stepper variant, render numbered circle with optional connecting line\n if (variant === 'stepper') {\n const tabIndex = stepperCtx.tabKeys.indexOf(id);\n const selectedIndex = stepperSelectedKey !== undefined\n ? stepperCtx.tabKeys.indexOf(stepperSelectedKey)\n : -1;\n const isFirst = tabIndex === 0;\n const isCompleted = tabIndex >= 0 && selectedIndex >= 0 && tabIndex < selectedIndex;\n const isActive = tabIndex >= 0 && tabIndex === selectedIndex;\n const isVertical = orientation === 'vertical';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(\n tabVariants({ variant, orientation }),\n isActive && 'bg-[var(--primary-action)]/10 rounded-lg',\n className,\n )\n )}\n {...props}\n >\n {/* Connecting line before tab (horizontal only, except first) */}\n {!isFirst && !isVertical && (\n <span\n className=\"h-px w-6 bg-[var(--border)]\"\n aria-hidden=\"true\"\n />\n )}\n {/* Step circle */}\n <span\n className={cn(\n 'flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-xs font-bold',\n isActive\n ? 'bg-[var(--primary-action)] text-white'\n : isCompleted\n ? 'bg-[var(--primary-action)] text-white'\n : 'bg-[var(--accent-background)] text-[var(--muted-foreground)]'\n )}\n aria-hidden=\"true\"\n >\n {isCompleted ? (\n <Check className=\"h-3.5 w-3.5\" />\n ) : (\n tabIndex + 1\n )}\n </span>\n {/* Visually hidden step number for screen readers */}\n <span className=\"sr-only\">\n {isCompleted ? `Step ${tabIndex + 1}, completed:` : `Step ${tabIndex + 1}:`}\n </span>\n {/* Tab label */}\n <span className={cn(\n isActive && 'font-semibold text-[var(--primary-action)]',\n )}>{children}</span>\n </AriaTab>\n );\n }\n\n // Default variant: render with sliding indicator\n const isHorizontal = orientation === 'horizontal';\n const indicatorClasses = isHorizontal\n ? 'absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]'\n : 'absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {(renderProps) => (\n <>\n {children}\n {/* Tab indicator — animated slide or instant position */}\n {variant === 'default' && renderProps.isSelected && (\n doAnimate && MotionSpan ? (\n <MotionSpan\n layoutId={`tab-indicator-${isHorizontal ? 'h' : 'v'}`}\n className={indicatorClasses}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n />\n ) : (\n <span className={indicatorClasses} />\n )\n )}\n </>\n )}\n </AriaTab>\n );\n}\n\nTabComponent.displayName = 'Tab';\n\n/**\n * TabPanel Component\n *\n * Content panel associated with a tab. Only the selected panel is visible.\n * Supports preserveState for React Activity state preservation.\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n *\n * @example\n * // Default behavior - content unmounts when hidden\n * <TabPanel id=\"tab1\">Content</TabPanel>\n *\n * @example\n * // Legacy force mount - keeps content in DOM\n * <TabPanel id=\"tab1\" shouldForceMount>Form with state</TabPanel>\n *\n * @example\n * // React Activity - preserves state with proper effect cleanup\n * <TabPanel id=\"tab1\" preserveState>\n * <FormWithDraft />\n * </TabPanel>\n */\nfunction TabPanelComponent({\n children,\n id,\n shouldForceMount = false,\n preserveState = false,\n className,\n ...props\n}: TabPanelProps) {\n // preserveState takes precedence - both enable force mounting\n const forceMount = preserveState || shouldForceMount;\n\n // If children is a render function (for dynamic content based on selection state),\n // we need to use the render props pattern\n if (typeof children === 'function') {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n // React Aria TabPanelRenderProps includes: state, isInert\n // We derive isSelected from state - if state is undefined, panel is selected\n const isSelected = !renderProps.isInert;\n const content = (\n children as (renderProps: { isSelected: boolean }) => ReactNode\n )({ isSelected });\n\n if (preserveState) {\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {content}\n </Activity>\n );\n }\n\n return content;\n }}\n </AriaTabPanel>\n );\n }\n\n // For static children (not a function), render directly\n // If preserveState is enabled, wrap in Activity\n if (preserveState) {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n const isSelected = !renderProps.isInert;\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {children}\n </Activity>\n );\n }}\n </AriaTabPanel>\n );\n }\n\n // Default: render static children directly\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {children}\n </AriaTabPanel>\n );\n}\n\nTabPanelComponent.displayName = 'TabPanel';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Tabs follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components vs Dialog's 9)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Tabs, TabList, Tab, TabPanel } from '...'\n *\n * @see plan.md \"Why Direct Named Exports (Not Object.assign)?\"\n */\nexport const Tabs = TabsRoot;\nexport const TabList = TabListComponent;\nexport const Tab = TabComponent;\nexport const TabPanel = TabPanelComponent;\n\n// Re-export types for convenience\nexport type { TabsProps, TabsVariant, TabListProps, TabProps, TabPanelProps };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode, Key } from 'react';\n\n/**\n * Tab variant schema\n *\n * - 'default': Transparent background with bottom border indicator for active tab\n * - 'block': Pill/card style with accent background and shadow for active tab\n * - 'stepper': Numbered step circles with connecting lines (free navigation, not a wizard)\n */\nexport const TabsVariantSchema = z.enum(['default', 'block', 'stepper']);\nexport type TabsVariant = z.infer<typeof TabsVariantSchema>;\n\n/**\n * Tab orientation schema\n *\n * @see PRD.md FR-005 (Orientation Support)\n */\nexport const TabsOrientationSchema = z.enum(['horizontal', 'vertical']);\nexport type TabsOrientation = z.infer<typeof TabsOrientationSchema>;\n\n/**\n * Keyboard activation mode schema\n *\n * @see PRD.md FR-006 (Keyboard Activation Modes)\n */\nexport const TabsKeyboardActivationSchema = z.enum(['automatic', 'manual']);\nexport type TabsKeyboardActivation = z.infer<typeof TabsKeyboardActivationSchema>;\n\n/**\n * Key schema for tab identification\n * Supports both string and number keys per React Aria convention\n */\nexport const KeySchema = z.union([z.string(), z.number()]);\n\n/**\n * Tabs root component props schema\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nexport const TabsPropsSchema = BaseComponentPropsSchema.extend({\n // Visual variant: 'default' (underline) or 'block' (pill/card)\n variant: TabsVariantSchema.optional().default('default'),\n\n // Controlled mode: selected tab key\n selectedKey: KeySchema.optional(),\n\n // Uncontrolled mode: default selected tab key\n defaultSelectedKey: KeySchema.optional(),\n\n // Selection change handler\n onSelectionChange: z.custom<(key: Key) => void>().optional(),\n\n // Orientation: horizontal or vertical layout\n orientation: TabsOrientationSchema.optional().default('horizontal'),\n\n // Keyboard activation: automatic (arrows select) or manual (arrows focus, Enter selects)\n keyboardActivation: TabsKeyboardActivationSchema.optional().default('automatic'),\n\n // Disable all tabs\n isDisabled: z.boolean().optional().default(false),\n\n // Keys of tabs to disable individually\n disabledKeys: z.array(KeySchema).optional(),\n\n // Children: TabList and TabPanel components\n children: z.custom<ReactNode>(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n // When true, the tab indicator slides between tabs (default variant only)\n animated: z.boolean().optional().default(true),\n});\n\nexport interface TabsProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n variant?: TabsVariant;\n selectedKey?: string | number;\n defaultSelectedKey?: string | number;\n onSelectionChange?: (key: Key) => void;\n orientation?: TabsOrientation;\n keyboardActivation?: TabsKeyboardActivation;\n isDisabled?: boolean;\n disabledKeys?: (string | number)[];\n animated?: boolean;\n}\n\n/**\n * TabList component props schema\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nexport const TabListPropsSchema = BaseComponentPropsSchema.extend({\n // Accessible label (required for accessibility if no aria-labelledby)\n 'aria-label': z.string().optional(),\n\n // Reference to labelling element\n 'aria-labelledby': z.string().optional(),\n\n // Children: Tab components\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabListProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n}\n\n/**\n * Tab component props schema\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nexport const TabPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier for the tab (required)\n id: KeySchema,\n\n // Disable this specific tab\n isDisabled: z.boolean().optional().default(false),\n\n // Link tab: URL for navigation-style tabs\n href: z.string().optional(),\n\n // Link tab: target attribute\n target: z.string().optional(),\n\n // Link tab: rel attribute\n rel: z.string().optional(),\n\n // Link tab: download attribute\n download: z.union([z.string(), z.boolean()]).optional(),\n\n // Tab content (text, icons, badges)\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'data-testid'?: string;\n isDisabled?: boolean;\n href?: string;\n target?: string;\n rel?: string;\n download?: string | boolean;\n}\n\n/**\n * TabPanel component props schema\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n */\nexport const TabPanelPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier matching a Tab id (required)\n id: KeySchema,\n\n // Legacy: Force panel to stay in DOM when hidden\n // Use preserveState instead for proper effect cleanup\n shouldForceMount: z.boolean().optional().default(false),\n\n // React 19.2 Activity: Preserve state with proper effect cleanup\n // When true, wraps content in <Activity> component\n // Effects are cleaned up when hidden, restored when visible\n preserveState: z.boolean().optional().default(false),\n\n // Panel content\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabPanelProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n shouldForceMount?: boolean;\n preserveState?: boolean;\n}\n\n/**\n * Scroll arrow direction for overflow handling\n *\n * @see PRD.md FR-010 (Overflow Handling)\n */\nexport const ScrollArrowDirectionSchema = z.enum(['left', 'right', 'up', 'down']);\nexport type ScrollArrowDirection = z.infer<typeof ScrollArrowDirectionSchema>;\n\n/**\n * Internal props for scroll arrow buttons\n * Used by overflow handling implementation\n */\nexport const ScrollArrowPropsSchema = BaseComponentPropsSchema.extend({\n // Scroll direction\n direction: ScrollArrowDirectionSchema,\n\n // Disable when can't scroll further\n isDisabled: z.boolean().optional().default(false),\n\n // Click handler for scrolling\n onPress: z.custom<() => void>(),\n\n // Accessible label\n 'aria-label': z.string(),\n});\n\nexport interface ScrollArrowProps {\n className?: string;\n id?: string;\n 'aria-label': string;\n 'data-testid'?: string;\n direction: ScrollArrowDirection;\n isDisabled?: boolean;\n onPress: () => void;\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {createContext,useState,useContext,Children,isValidElement,useRef,useEffect,Activity}from'react';import {Check}from'lucide-react';import {Tabs,TabList,composeRenderProps,Tab,TabPanel}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 as z$1}from'zod';function
|
|
2
|
+
import {createContext,useState,useContext,Children,isValidElement,useRef,useEffect,Activity}from'react';import {Check}from'lucide-react';import {Tabs,TabList,composeRenderProps,Tab,TabPanel}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 as z$1}from'zod';function p(...t){return twMerge(clsx(t))}function O(t,a){return !(t===false||a)}var F="(prefers-reduced-motion: reduce)";function le(){return typeof window>"u"?false:window.matchMedia(F).matches}function j(){let[t,a]=useState(le);return useEffect(()=>{let r=window.matchMedia(F);a(r.matches);let i=l=>{a(l.matches);};return r.addEventListener("change",i),()=>r.removeEventListener("change",i)},[]),t}var B=Activity??function({children:a,mode:r}){return jsx("div",{"data-activity-mode":r,children:a})},S;function ye(){return S!==void 0?Promise.resolve(S):import('motion/react').then(t=>(S=t.motion.span,S)).catch(()=>(S=null,null))}var I=createContext({variant:"default",orientation:"horizontal",animated:true}),Y=createContext({tabKeys:[]}),z=cva(["inline-flex items-center text-[var(--menu-muted)]"],{variants:{variant:{default:"border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0",block:"justify-center rounded-md p-1 bg-[var(--accent-background)]",stepper:"flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none"},orientation:{horizontal:"flex-row",vertical:"h-auto flex-col w-full"}},compoundVariants:[{variant:"block",orientation:"horizontal",class:"h-10 gap-0"},{variant:"block",orientation:"vertical",class:"gap-1"},{variant:"default",orientation:"vertical",class:"border-b-0 border-l"},{variant:"stepper",orientation:"vertical",class:"!flex-row gap-1"}],defaultVariants:{variant:"default",orientation:"horizontal"}}),D=cva(["inline-flex items-center justify-center gap-2 whitespace-nowrap","px-3 py-1.5 text-sm font-medium","ring-offset-[var(--content-background)] transition-all","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2","data-[disabled]:pointer-events-none data-[disabled]:opacity-50","min-h-[44px]"],{variants:{variant:{default:["rounded-none bg-transparent","data-[selected]:text-[var(--content-foreground)]","hover:text-[var(--content-foreground)]"],block:["rounded-sm","data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]","data-[selected]:shadow-sm"],stepper:["flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2"]},orientation:{horizontal:"",vertical:"w-full justify-start"}},compoundVariants:[{variant:"default",orientation:"horizontal",class:"relative -mb-px"},{variant:"default",orientation:"vertical",class:"relative -ml-px"}],defaultVariants:{variant:"default",orientation:"horizontal"}}),N=cva(["mt-2 ring-offset-[var(--content-background)]","focus-visible:outline-none focus-visible:ring-2","focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2"],{variants:{},defaultVariants:{}});function _({children:t,variant:a="default",selectedKey:r,defaultSelectedKey:i,onSelectionChange:l,orientation:n="horizontal",keyboardActivation:b="automatic",isDisabled:c=false,disabledKeys:u,animated:d,className:y,...P}){let h=j(),A=O(d,h),[w,R]=useState(r??i),K=T=>{a==="stepper"&&R(T),l?.(T);},C=a==="stepper"?r??w:void 0;return jsx(I.Provider,{value:{variant:a,orientation:n,stepperSelectedKey:C,animated:A},children:jsx(Tabs,{selectedKey:r,defaultSelectedKey:i,onSelectionChange:K,orientation:n,keyboardActivation:b,isDisabled:c,disabledKeys:u,className:p(y),...P,children:t})})}_.displayName="Tabs";function G({children:t,className:a,...r}){let{variant:i}=useContext(I);if(i==="stepper"){let l=[];return Children.forEach(t,n=>{isValidElement(n)&&n.props&&typeof n.props.id<"u"&&l.push(n.props.id);}),jsx(Y.Provider,{value:{tabKeys:l},children:jsx(TabList,{className:composeRenderProps(a,(n,b)=>p(z({variant:i,orientation:b.orientation}),n)),...r,children:t})})}return jsx(TabList,{className:composeRenderProps(a,(l,n)=>p(z({variant:i,orientation:n.orientation}),l)),...r,children:t})}G.displayName="TabList";function J({children:t,id:a,isDisabled:r=false,href:i,target:l,rel:n,download:b,className:c,...u}){process.env.NODE_ENV!=="production"&&!(typeof t=="string"||Array.isArray(t)&&t.some(x=>typeof x=="string"))&&!u["aria-label"]&&console.warn("Tabs: Icon-only tabs should have an aria-label for accessibility.");let{variant:d,orientation:y,stepperSelectedKey:P,animated:h}=useContext(I),A=useContext(Y),[w,R]=useState(null),K=useRef(false);if(useEffect(()=>{d!=="default"||!h||K.current||(K.current=true,ye().then(s=>{s&&R(()=>s);}));},[d,h]),d==="stepper"){let s=A.tabKeys.indexOf(a),x=P!==void 0?A.tabKeys.indexOf(P):-1,te=s===0,V=s>=0&&x>=0&&s<x,k=s>=0&&s===x,ae=y==="vertical";return jsxs(Tab,{id:a,isDisabled:r,href:i,target:l,rel:n,download:b,className:composeRenderProps(c,oe=>p(D({variant:d,orientation:y}),k&&"bg-[var(--primary-action)]/10 rounded-lg",oe)),...u,children:[!te&&!ae&&jsx("span",{className:"h-px w-6 bg-[var(--border)]","aria-hidden":"true"}),jsx("span",{className:p("flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-xs font-bold",k||V?"bg-[var(--primary-action)] text-white":"bg-[var(--accent-background)] text-[var(--muted-foreground)]"),"aria-hidden":"true",children:V?jsx(Check,{className:"h-3.5 w-3.5"}):s+1}),jsx("span",{className:"sr-only",children:V?`Step ${s+1}, completed:`:`Step ${s+1}:`}),jsx("span",{className:p(k&&"font-semibold text-[var(--primary-action)]"),children:t})]})}let C=y==="horizontal",T=C?"absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]":"absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]";return jsx(Tab,{id:a,isDisabled:r,href:i,target:l,rel:n,download:b,className:composeRenderProps(c,s=>p(D({variant:d,orientation:y}),s)),...u,children:s=>jsxs(Fragment,{children:[t,d==="default"&&s.isSelected&&(h&&w?jsx(w,{layoutId:`tab-indicator-${C?"h":"v"}`,className:T,transition:{type:"spring",stiffness:500,damping:30}}):jsx("span",{className:T}))]})})}J.displayName="Tab";function W({children:t,id:a,shouldForceMount:r=false,preserveState:i=false,className:l,...n}){let b=i||r;return typeof t=="function"?jsx(TabPanel,{id:a,shouldForceMount:b,className:composeRenderProps(l,c=>p(N(),c)),...n,children:c=>{let u=!c.isInert,d=t({isSelected:u});return i?jsx(B,{mode:u?"visible":"hidden",children:d}):d}}):i?jsx(TabPanel,{id:a,shouldForceMount:b,className:composeRenderProps(l,c=>p(N(),c)),...n,children:c=>{let u=!c.isInert;return jsx(B,{mode:u?"visible":"hidden",children:t})}}):jsx(TabPanel,{id:a,shouldForceMount:b,className:composeRenderProps(l,c=>p(N(),c)),...n,children:t})}W.displayName="TabPanel";var ge=_,ve=G,he=J,Te=W;var g=z$1.object({className:z$1.string().optional(),children:z$1.any().optional(),id:z$1.string().optional(),"aria-label":z$1.string().optional(),"aria-labelledby":z$1.string().optional(),"aria-describedby":z$1.string().optional(),"aria-live":z$1.enum(["off","polite","assertive"]).optional(),"aria-hidden":z$1.boolean().optional(),"data-testid":z$1.string().optional()});var Se=z$1.enum(["default","block","stepper"]),X=z$1.enum(["horizontal","vertical"]),Z=z$1.enum(["automatic","manual"]),v=z$1.union([z$1.string(),z$1.number()]),Pe=g.extend({variant:Se.optional().default("default"),selectedKey:v.optional(),defaultSelectedKey:v.optional(),onSelectionChange:z$1.custom().optional(),orientation:X.optional().default("horizontal"),keyboardActivation:Z.optional().default("automatic"),isDisabled:z$1.boolean().optional().default(false),disabledKeys:z$1.array(v).optional(),children:z$1.custom(),animated:z$1.boolean().optional().default(true)}),Ae=g.extend({"aria-label":z$1.string().optional(),"aria-labelledby":z$1.string().optional(),children:z$1.custom()}),we=g.extend({id:v,isDisabled:z$1.boolean().optional().default(false),href:z$1.string().optional(),target:z$1.string().optional(),rel:z$1.string().optional(),download:z$1.union([z$1.string(),z$1.boolean()]).optional(),children:z$1.custom()}),Ke=g.extend({id:v,shouldForceMount:z$1.boolean().optional().default(false),preserveState:z$1.boolean().optional().default(false),children:z$1.custom()}),ee=z$1.enum(["left","right","up","down"]),Ce=g.extend({direction:ee,isDisabled:z$1.boolean().optional().default(false),onPress:z$1.custom(),"aria-label":z$1.string()});export{v as KeySchema,ee as ScrollArrowDirectionSchema,Ce as ScrollArrowPropsSchema,he as Tab,ve as TabList,Ae as TabListPropsSchema,Te as TabPanel,Ke as TabPanelPropsSchema,we as TabPropsSchema,ge as Tabs,Z as TabsKeyboardActivationSchema,X as TabsOrientationSchema,Pe as TabsPropsSchema,z as tabListVariants,N as tabPanelVariants,D as tabVariants};//# sourceMappingURL=index.mjs.map
|
|
3
3
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/shouldAnimate.ts","../../../src/hooks/useReducedMotion.ts","../../../src/elements/Tabs/Tabs.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Tabs/Tabs.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","Activity","ReactActivity","children","mode","jsx","cachedMotionSpan","loadMotionSpan","m","TabsInternalContext","createContext","StepperContext","tabListVariants","cva","tabVariants","tabPanelVariants","TabsRoot","variant","selectedKey","defaultSelectedKey","onSelectionChange","orientation","keyboardActivation","isDisabled","disabledKeys","animatedProp","className","props","doAnimate","trackedKey","setTrackedKey","handleSelectionChange","key","stepperSelectedKey","AriaTabs","TabListComponent","useContext","tabKeys","Children","child","isValidElement","AriaTabList","composeRenderProps","renderProps","TabComponent","id","href","target","rel","download","stepperCtx","MotionSpan","setMotionSpan","motionLoadedRef","useRef","component","tabIndex","selectedIndex","isFirst","isCompleted","isActive","jsxs","AriaTab","Check","isHorizontal","indicatorClasses","Fragment","TabPanelComponent","shouldForceMount","preserveState","forceMount","AriaTabPanel","isSelected","content","Tabs","TabList","Tab","TabPanel","BaseComponentPropsSchema","z","TabsVariantSchema","TabsOrientationSchema","TabsKeyboardActivationSchema","KeySchema","TabsPropsSchema","TabListPropsSchema","TabPropsSchema","TabPanelPropsSchema","ScrollArrowDirectionSchema","ScrollArrowPropsSchema"],"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 * 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","'use client';\n\n/**\n * Tabs Component - Implementation\n *\n * Accessible tabbed interface component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria Tabs for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for orientation styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Dual keyboard activation modes (automatic/manual)\n * - Support for icons, badges, and link-based tabs\n *\n * @see tabs-prd.md (Full requirements)\n * @see Tabs.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 Children,\n createContext,\n isValidElement,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n type Key,\n type ReactElement,\n} from 'react';\nimport { Check } from 'lucide-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\n// Note: ActivityFallback doesn't actually preserve state; it's just a pass-through\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n // When Activity is not available, just render children directly\n // mode is ignored in the fallback\n return <div data-activity-mode={mode}>{children}</div>;\n};\nimport {\n Tabs as AriaTabs,\n TabList as AriaTabList,\n Tab as AriaTab,\n TabPanel as AriaTabPanel,\n composeRenderProps,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport type {\n TabsProps,\n TabsVariant,\n TabsOrientation,\n TabListProps,\n TabProps,\n TabPanelProps,\n} from './Tabs.types';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype MotionSpanComponent = React.ComponentType<{\n layoutId?: string;\n className?: string;\n transition?: Record<string, unknown>;\n style?: React.CSSProperties;\n}>;\n\nlet cachedMotionSpan: MotionSpanComponent | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionSpan(): Promise<MotionSpanComponent | null> {\n if (cachedMotionSpan !== undefined) return Promise.resolve(cachedMotionSpan);\n\n return import('motion/react')\n .then((m) => {\n cachedMotionSpan = m.motion.span as unknown as MotionSpanComponent;\n return cachedMotionSpan;\n })\n .catch(() => {\n cachedMotionSpan = null;\n return null;\n });\n}\n\n// ============================================================================\n// Internal Context\n// ============================================================================\n\ninterface TabsContextValue {\n variant: TabsVariant;\n orientation: TabsOrientation;\n /** For stepper variant: tracked selected key from Tabs root */\n stepperSelectedKey?: Key;\n /** Whether the indicator should animate. Default: true */\n animated: boolean;\n}\n\nconst TabsInternalContext = createContext<TabsContextValue>({\n variant: 'default',\n orientation: 'horizontal',\n animated: true,\n});\n\n/**\n * Stepper context for tracking tab order.\n * Only used when variant=\"stepper\" to determine completed/active/inactive states.\n */\ninterface StepperContextValue {\n tabKeys: Key[];\n}\n\nconst StepperContext = createContext<StepperContextValue>({\n tabKeys: [],\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * TabList CVA variants\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md DS-001 (Design System - Layout)\n */\nexport const tabListVariants = cva(\n // Base styles\n [\n 'inline-flex items-center text-[var(--menu-muted)]',\n ],\n {\n variants: {\n variant: {\n default: 'border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0',\n block: 'justify-center rounded-md p-1 bg-[var(--accent-background)]',\n stepper: 'flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none',\n },\n orientation: {\n horizontal: 'flex-row',\n vertical: 'h-auto flex-col w-full',\n },\n },\n compoundVariants: [\n { variant: 'block', orientation: 'horizontal', class: 'h-10 gap-0' },\n { variant: 'block', orientation: 'vertical', class: 'gap-1' },\n { variant: 'default', orientation: 'vertical', class: 'border-b-0 border-l' },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * Tab CVA variants\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md DS-002 (Design System - Tab Styling)\n * @see PRD.md AR-001 (Accessibility - 44×44px touch targets)\n */\nexport const tabVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap',\n 'px-3 py-1.5 text-sm font-medium',\n 'ring-offset-[var(--content-background)] transition-all',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n // States via data attributes\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // WCAG 2.2 AAA: 44×44px minimum touch target\n 'min-h-[44px]',\n ],\n {\n variants: {\n variant: {\n default: [\n 'rounded-none bg-transparent',\n 'data-[selected]:text-[var(--content-foreground)]',\n 'hover:text-[var(--content-foreground)]',\n ],\n block: [\n 'rounded-sm',\n 'data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]',\n 'data-[selected]:shadow-sm',\n ],\n stepper: [\n 'flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2',\n ],\n },\n orientation: {\n horizontal: '',\n vertical: 'w-full justify-start',\n },\n },\n compoundVariants: [\n {\n variant: 'default',\n orientation: 'horizontal',\n class: 'relative -mb-px',\n },\n {\n variant: 'default',\n orientation: 'vertical',\n class: 'relative -ml-px',\n },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * TabPanel CVA variants\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n */\nexport const tabPanelVariants = cva(\n [\n 'mt-2 ring-offset-[var(--content-background)]',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n ],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Tabs Root Component\n *\n * Container for tabbed interface. Manages selection state and provides\n * context to child components.\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled\n * <Tabs defaultSelectedKey=\"tab1\">\n * <TabList aria-label=\"Navigation\">\n * <Tab id=\"tab1\">Tab 1</Tab>\n * <Tab id=\"tab2\">Tab 2</Tab>\n * </TabList>\n * <TabPanel id=\"tab1\">Content 1</TabPanel>\n * <TabPanel id=\"tab2\">Content 2</TabPanel>\n * </Tabs>\n *\n * @example\n * // Controlled\n * <Tabs selectedKey={selected} onSelectionChange={setSelected}>\n * ...\n * </Tabs>\n */\nfunction TabsRoot({\n children,\n variant = 'default',\n selectedKey,\n defaultSelectedKey,\n onSelectionChange,\n orientation = 'horizontal',\n keyboardActivation = 'automatic',\n isDisabled = false,\n disabledKeys,\n animated: animatedProp,\n className,\n ...props\n}: TabsProps) {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animatedProp, prefersReducedMotion);\n // For stepper variant, track the selected key internally so Tab children\n // can determine completed/active/inactive state. React Aria's internal\n // TabListStateContext is not accessible from our Tab wrapper since tabs\n // are rendered via the collection system.\n const [trackedKey, setTrackedKey] = useState<Key | undefined>(\n selectedKey ?? defaultSelectedKey\n );\n\n const handleSelectionChange = (key: Key) => {\n if (variant === 'stepper') {\n setTrackedKey(key);\n }\n onSelectionChange?.(key);\n };\n\n // For controlled mode, use the prop directly\n const stepperSelectedKey = variant === 'stepper'\n ? (selectedKey ?? trackedKey)\n : undefined;\n\n return (\n <TabsInternalContext.Provider value={{ variant, orientation, stepperSelectedKey, animated: doAnimate }}>\n <AriaTabs\n selectedKey={selectedKey}\n defaultSelectedKey={defaultSelectedKey}\n onSelectionChange={handleSelectionChange as (key: Key) => void}\n orientation={orientation}\n keyboardActivation={keyboardActivation}\n isDisabled={isDisabled}\n disabledKeys={disabledKeys as Iterable<AriaKey> | undefined}\n className={cn(className)}\n {...props}\n >\n {children}\n </AriaTabs>\n </TabsInternalContext.Provider>\n );\n}\n\nTabsRoot.displayName = 'Tabs';\n\n/**\n * TabList Component\n *\n * Container for tab buttons. Uses roving tabindex for keyboard navigation.\n * Receives orientation from parent Tabs via React Aria context.\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nfunction TabListComponent({\n children,\n className,\n ...props\n}: TabListProps) {\n const { variant } = useContext(TabsInternalContext);\n\n // For stepper variant, collect tab keys from children to determine order\n if (variant === 'stepper') {\n // Extract keys from Tab children to determine ordering\n const tabKeys: Key[] = [];\n Children.forEach(children as ReactNode, (child) => {\n if (isValidElement(child) && child.props && typeof (child.props as Record<string, unknown>).id !== 'undefined') {\n tabKeys.push((child.props as Record<string, unknown>).id as Key);\n }\n });\n\n return (\n <StepperContext.Provider value={{ tabKeys }}>\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n </StepperContext.Provider>\n );\n }\n\n return (\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n );\n}\n\nTabListComponent.displayName = 'TabList';\n\n/**\n * Tab Component\n *\n * Individual tab button. Can render as button or anchor (when href provided).\n * Supports icons and badges as children.\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-013 (Icon Support)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nfunction TabComponent({\n children,\n id,\n isDisabled = false,\n href,\n target,\n rel,\n download,\n className,\n ...props\n}: TabProps) {\n // Warn if icon-only tab without aria-label\n if (process.env.NODE_ENV !== 'production') {\n const hasTextContent =\n typeof children === 'string' ||\n (Array.isArray(children) &&\n children.some((child) => typeof child === 'string'));\n\n if (!hasTextContent && !props['aria-label']) {\n console.warn(\n 'Tabs: Icon-only tabs should have an aria-label for accessibility.'\n );\n }\n }\n\n const { variant, orientation, stepperSelectedKey, animated: doAnimate } = useContext(TabsInternalContext);\n const stepperCtx = useContext(StepperContext);\n\n // Motion.dev component for animated indicator (lazy-loaded)\n const [MotionSpan, setMotionSpan] = useState<MotionSpanComponent | null>(null);\n const motionLoadedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== 'default' || !doAnimate || motionLoadedRef.current) return;\n motionLoadedRef.current = true;\n loadMotionSpan().then((component) => {\n if (component) setMotionSpan(() => component);\n });\n }, [variant, doAnimate]);\n\n // For stepper variant, render numbered circle with connecting line\n if (variant === 'stepper') {\n const tabIndex = stepperCtx.tabKeys.indexOf(id);\n const selectedIndex = stepperSelectedKey !== undefined\n ? stepperCtx.tabKeys.indexOf(stepperSelectedKey)\n : -1;\n const isFirst = tabIndex === 0;\n const isCompleted = tabIndex >= 0 && selectedIndex >= 0 && tabIndex < selectedIndex;\n const isActive = tabIndex >= 0 && tabIndex === selectedIndex;\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {/* Connecting line before tab (except first) */}\n {!isFirst && (\n <span\n className=\"h-px w-6 bg-[var(--border)]\"\n aria-hidden=\"true\"\n />\n )}\n {/* Step circle */}\n <span\n className={cn(\n 'flex h-6 w-6 shrink-0 items-center justify-center rounded-full text-xs font-medium',\n (isActive || isCompleted)\n ? 'bg-[var(--primary-action)] text-white'\n : 'bg-[var(--accent-background)] text-[var(--muted-foreground)]'\n )}\n aria-hidden=\"true\"\n >\n {isCompleted ? (\n <Check className=\"h-3.5 w-3.5\" />\n ) : (\n tabIndex + 1\n )}\n </span>\n {/* Visually hidden step number for screen readers */}\n <span className=\"sr-only\">\n {isCompleted ? `Step ${tabIndex + 1}, completed:` : `Step ${tabIndex + 1}:`}\n </span>\n {/* Tab label */}\n <span>{children}</span>\n </AriaTab>\n );\n }\n\n // Default variant: render with sliding indicator\n const isHorizontal = orientation === 'horizontal';\n const indicatorClasses = isHorizontal\n ? 'absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]'\n : 'absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {(renderProps) => (\n <>\n {children}\n {/* Tab indicator — animated slide or instant position */}\n {variant === 'default' && renderProps.isSelected && (\n doAnimate && MotionSpan ? (\n <MotionSpan\n layoutId={`tab-indicator-${isHorizontal ? 'h' : 'v'}`}\n className={indicatorClasses}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n />\n ) : (\n <span className={indicatorClasses} />\n )\n )}\n </>\n )}\n </AriaTab>\n );\n}\n\nTabComponent.displayName = 'Tab';\n\n/**\n * TabPanel Component\n *\n * Content panel associated with a tab. Only the selected panel is visible.\n * Supports preserveState for React Activity state preservation.\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n *\n * @example\n * // Default behavior - content unmounts when hidden\n * <TabPanel id=\"tab1\">Content</TabPanel>\n *\n * @example\n * // Legacy force mount - keeps content in DOM\n * <TabPanel id=\"tab1\" shouldForceMount>Form with state</TabPanel>\n *\n * @example\n * // React Activity - preserves state with proper effect cleanup\n * <TabPanel id=\"tab1\" preserveState>\n * <FormWithDraft />\n * </TabPanel>\n */\nfunction TabPanelComponent({\n children,\n id,\n shouldForceMount = false,\n preserveState = false,\n className,\n ...props\n}: TabPanelProps) {\n // preserveState takes precedence - both enable force mounting\n const forceMount = preserveState || shouldForceMount;\n\n // If children is a render function (for dynamic content based on selection state),\n // we need to use the render props pattern\n if (typeof children === 'function') {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n // React Aria TabPanelRenderProps includes: state, isInert\n // We derive isSelected from state - if state is undefined, panel is selected\n const isSelected = !renderProps.isInert;\n const content = (\n children as (renderProps: { isSelected: boolean }) => ReactNode\n )({ isSelected });\n\n if (preserveState) {\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {content}\n </Activity>\n );\n }\n\n return content;\n }}\n </AriaTabPanel>\n );\n }\n\n // For static children (not a function), render directly\n // If preserveState is enabled, wrap in Activity\n if (preserveState) {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n const isSelected = !renderProps.isInert;\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {children}\n </Activity>\n );\n }}\n </AriaTabPanel>\n );\n }\n\n // Default: render static children directly\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {children}\n </AriaTabPanel>\n );\n}\n\nTabPanelComponent.displayName = 'TabPanel';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Tabs follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components vs Dialog's 9)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Tabs, TabList, Tab, TabPanel } from '...'\n *\n * @see plan.md \"Why Direct Named Exports (Not Object.assign)?\"\n */\nexport const Tabs = TabsRoot;\nexport const TabList = TabListComponent;\nexport const Tab = TabComponent;\nexport const TabPanel = TabPanelComponent;\n\n// Re-export types for convenience\nexport type { TabsProps, TabsVariant, TabListProps, TabProps, TabPanelProps };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode, Key } from 'react';\n\n/**\n * Tab variant schema\n *\n * - 'default': Transparent background with bottom border indicator for active tab\n * - 'block': Pill/card style with accent background and shadow for active tab\n * - 'stepper': Numbered step circles with connecting lines (free navigation, not a wizard)\n */\nexport const TabsVariantSchema = z.enum(['default', 'block', 'stepper']);\nexport type TabsVariant = z.infer<typeof TabsVariantSchema>;\n\n/**\n * Tab orientation schema\n *\n * @see PRD.md FR-005 (Orientation Support)\n */\nexport const TabsOrientationSchema = z.enum(['horizontal', 'vertical']);\nexport type TabsOrientation = z.infer<typeof TabsOrientationSchema>;\n\n/**\n * Keyboard activation mode schema\n *\n * @see PRD.md FR-006 (Keyboard Activation Modes)\n */\nexport const TabsKeyboardActivationSchema = z.enum(['automatic', 'manual']);\nexport type TabsKeyboardActivation = z.infer<typeof TabsKeyboardActivationSchema>;\n\n/**\n * Key schema for tab identification\n * Supports both string and number keys per React Aria convention\n */\nexport const KeySchema = z.union([z.string(), z.number()]);\n\n/**\n * Tabs root component props schema\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nexport const TabsPropsSchema = BaseComponentPropsSchema.extend({\n // Visual variant: 'default' (underline) or 'block' (pill/card)\n variant: TabsVariantSchema.optional().default('default'),\n\n // Controlled mode: selected tab key\n selectedKey: KeySchema.optional(),\n\n // Uncontrolled mode: default selected tab key\n defaultSelectedKey: KeySchema.optional(),\n\n // Selection change handler\n onSelectionChange: z.custom<(key: Key) => void>().optional(),\n\n // Orientation: horizontal or vertical layout\n orientation: TabsOrientationSchema.optional().default('horizontal'),\n\n // Keyboard activation: automatic (arrows select) or manual (arrows focus, Enter selects)\n keyboardActivation: TabsKeyboardActivationSchema.optional().default('automatic'),\n\n // Disable all tabs\n isDisabled: z.boolean().optional().default(false),\n\n // Keys of tabs to disable individually\n disabledKeys: z.array(KeySchema).optional(),\n\n // Children: TabList and TabPanel components\n children: z.custom<ReactNode>(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n // When true, the tab indicator slides between tabs (default variant only)\n animated: z.boolean().optional().default(true),\n});\n\nexport interface TabsProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n variant?: TabsVariant;\n selectedKey?: string | number;\n defaultSelectedKey?: string | number;\n onSelectionChange?: (key: Key) => void;\n orientation?: TabsOrientation;\n keyboardActivation?: TabsKeyboardActivation;\n isDisabled?: boolean;\n disabledKeys?: (string | number)[];\n animated?: boolean;\n}\n\n/**\n * TabList component props schema\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nexport const TabListPropsSchema = BaseComponentPropsSchema.extend({\n // Accessible label (required for accessibility if no aria-labelledby)\n 'aria-label': z.string().optional(),\n\n // Reference to labelling element\n 'aria-labelledby': z.string().optional(),\n\n // Children: Tab components\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabListProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n}\n\n/**\n * Tab component props schema\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nexport const TabPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier for the tab (required)\n id: KeySchema,\n\n // Disable this specific tab\n isDisabled: z.boolean().optional().default(false),\n\n // Link tab: URL for navigation-style tabs\n href: z.string().optional(),\n\n // Link tab: target attribute\n target: z.string().optional(),\n\n // Link tab: rel attribute\n rel: z.string().optional(),\n\n // Link tab: download attribute\n download: z.union([z.string(), z.boolean()]).optional(),\n\n // Tab content (text, icons, badges)\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'data-testid'?: string;\n isDisabled?: boolean;\n href?: string;\n target?: string;\n rel?: string;\n download?: string | boolean;\n}\n\n/**\n * TabPanel component props schema\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n */\nexport const TabPanelPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier matching a Tab id (required)\n id: KeySchema,\n\n // Legacy: Force panel to stay in DOM when hidden\n // Use preserveState instead for proper effect cleanup\n shouldForceMount: z.boolean().optional().default(false),\n\n // React 19.2 Activity: Preserve state with proper effect cleanup\n // When true, wraps content in <Activity> component\n // Effects are cleaned up when hidden, restored when visible\n preserveState: z.boolean().optional().default(false),\n\n // Panel content\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabPanelProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n shouldForceMount?: boolean;\n preserveState?: boolean;\n}\n\n/**\n * Scroll arrow direction for overflow handling\n *\n * @see PRD.md FR-010 (Overflow Handling)\n */\nexport const ScrollArrowDirectionSchema = z.enum(['left', 'right', 'up', 'down']);\nexport type ScrollArrowDirection = z.infer<typeof ScrollArrowDirectionSchema>;\n\n/**\n * Internal props for scroll arrow buttons\n * Used by overflow handling implementation\n */\nexport const ScrollArrowPropsSchema = BaseComponentPropsSchema.extend({\n // Scroll direction\n direction: ScrollArrowDirectionSchema,\n\n // Disable when can't scroll further\n isDisabled: z.boolean().optional().default(false),\n\n // Click handler for scrolling\n onPress: z.custom<() => void>(),\n\n // Accessible label\n 'aria-label': z.string(),\n});\n\nexport interface ScrollArrowProps {\n className?: string;\n id?: string;\n 'aria-label': string;\n 'data-testid'?: string;\n direction: ScrollArrowDirection;\n isDisabled?: boolean;\n onPress: () => void;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/utils/shouldAnimate.ts","../../../src/hooks/useReducedMotion.ts","../../../src/elements/Tabs/Tabs.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Tabs/Tabs.types.ts"],"names":["cn","inputs","twMerge","clsx","shouldAnimate","animated","prefersReducedMotion","QUERY","getInitialState","useReducedMotion","setPrefersReducedMotion","useState","useEffect","mql","handler","event","Activity","ReactActivity","children","mode","jsx","cachedMotionSpan","loadMotionSpan","m","TabsInternalContext","createContext","StepperContext","tabListVariants","cva","tabVariants","tabPanelVariants","TabsRoot","variant","selectedKey","defaultSelectedKey","onSelectionChange","orientation","keyboardActivation","isDisabled","disabledKeys","animatedProp","className","props","doAnimate","trackedKey","setTrackedKey","handleSelectionChange","key","stepperSelectedKey","AriaTabs","TabListComponent","useContext","tabKeys","Children","child","isValidElement","AriaTabList","composeRenderProps","renderProps","TabComponent","id","href","target","rel","download","stepperCtx","MotionSpan","setMotionSpan","motionLoadedRef","useRef","component","tabIndex","selectedIndex","isFirst","isCompleted","isActive","isVertical","jsxs","AriaTab","Check","isHorizontal","indicatorClasses","Fragment","TabPanelComponent","shouldForceMount","preserveState","forceMount","AriaTabPanel","isSelected","content","Tabs","TabList","Tab","TabPanel","BaseComponentPropsSchema","z","TabsVariantSchema","TabsOrientationSchema","TabsKeyboardActivationSchema","KeySchema","TabsPropsSchema","TabListPropsSchema","TabPropsSchema","TabPanelPropsSchema","ScrollArrowDirectionSchema","ScrollArrowPropsSchema"],"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 * 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","'use client';\n\n/**\n * Tabs Component - Implementation\n *\n * Accessible tabbed interface component combining React Aria primitives with ShadCN styling.\n * Follows Themis library patterns with compound component structure and direct named exports.\n *\n * Key Features:\n * - React Aria Tabs for full accessibility (WCAG 2.2 AAA)\n * - CVA variants for orientation styling\n * - React 19.2 Activity API for state preservation (preserveState prop)\n * - Dual keyboard activation modes (automatic/manual)\n * - Support for icons, badges, and link-based tabs\n *\n * @see tabs-prd.md (Full requirements)\n * @see Tabs.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 Children,\n createContext,\n isValidElement,\n useContext,\n useEffect,\n useRef,\n useState,\n type ReactNode,\n type Key,\n type ReactElement,\n} from 'react';\nimport { Check } from 'lucide-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\n// Note: ActivityFallback doesn't actually preserve state; it's just a pass-through\nconst Activity = ReactActivity ?? function ActivityFallback({\n children,\n mode,\n}: {\n children: ReactNode;\n mode: 'visible' | 'hidden';\n}): ReactElement {\n // When Activity is not available, just render children directly\n // mode is ignored in the fallback\n return <div data-activity-mode={mode}>{children}</div>;\n};\nimport {\n Tabs as AriaTabs,\n TabList as AriaTabList,\n Tab as AriaTab,\n TabPanel as AriaTabPanel,\n composeRenderProps,\n type Key as AriaKey,\n} from 'react-aria-components';\nimport { cva } from 'class-variance-authority';\nimport { cn } from '../../utils/cn';\nimport { shouldAnimate } from '../../utils/shouldAnimate';\nimport { useReducedMotion } from '../../hooks/useReducedMotion';\nimport type {\n TabsProps,\n TabsVariant,\n TabsOrientation,\n TabListProps,\n TabProps,\n TabPanelProps,\n} from './Tabs.types';\n\n// ---------------------------------------------------------------------------\n// Motion lazy-loader — avoids hard dep on optional peer\n// ---------------------------------------------------------------------------\n\ntype MotionSpanComponent = React.ComponentType<{\n layoutId?: string;\n className?: string;\n transition?: Record<string, unknown>;\n style?: React.CSSProperties;\n}>;\n\nlet cachedMotionSpan: MotionSpanComponent | null | undefined; // undefined = pending, null = unavailable\n\nfunction loadMotionSpan(): Promise<MotionSpanComponent | null> {\n if (cachedMotionSpan !== undefined) return Promise.resolve(cachedMotionSpan);\n\n return import('motion/react')\n .then((m) => {\n cachedMotionSpan = m.motion.span as unknown as MotionSpanComponent;\n return cachedMotionSpan;\n })\n .catch(() => {\n cachedMotionSpan = null;\n return null;\n });\n}\n\n// ============================================================================\n// Internal Context\n// ============================================================================\n\ninterface TabsContextValue {\n variant: TabsVariant;\n orientation: TabsOrientation;\n /** For stepper variant: tracked selected key from Tabs root */\n stepperSelectedKey?: Key;\n /** Whether the indicator should animate. Default: true */\n animated: boolean;\n}\n\nconst TabsInternalContext = createContext<TabsContextValue>({\n variant: 'default',\n orientation: 'horizontal',\n animated: true,\n});\n\n/**\n * Stepper context for tracking tab order.\n * Only used when variant=\"stepper\" to determine completed/active/inactive states.\n */\ninterface StepperContextValue {\n tabKeys: Key[];\n}\n\nconst StepperContext = createContext<StepperContextValue>({\n tabKeys: [],\n});\n\n// ============================================================================\n// CVA Variants\n// ============================================================================\n\n/**\n * TabList CVA variants\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md DS-001 (Design System - Layout)\n */\nexport const tabListVariants = cva(\n // Base styles\n [\n 'inline-flex items-center text-[var(--menu-muted)]',\n ],\n {\n variants: {\n variant: {\n default: 'border-b border-[var(--border)] bg-transparent rounded-none p-0 gap-0',\n block: 'justify-center rounded-md p-1 bg-[var(--accent-background)]',\n stepper: 'flex items-center justify-center gap-0 border-none bg-[var(--content-background)] p-2 rounded-none',\n },\n orientation: {\n horizontal: 'flex-row',\n vertical: 'h-auto flex-col w-full',\n },\n },\n compoundVariants: [\n { variant: 'block', orientation: 'horizontal', class: 'h-10 gap-0' },\n { variant: 'block', orientation: 'vertical', class: 'gap-1' },\n { variant: 'default', orientation: 'vertical', class: 'border-b-0 border-l' },\n // Stepper vertical: undo the base flex-col so consumer controls direction via className\n { variant: 'stepper', orientation: 'vertical', class: '!flex-row gap-1' },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * Tab CVA variants\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md DS-002 (Design System - Tab Styling)\n * @see PRD.md AR-001 (Accessibility - 44×44px touch targets)\n */\nexport const tabVariants = cva(\n // Base styles\n [\n 'inline-flex items-center justify-center gap-2 whitespace-nowrap',\n 'px-3 py-1.5 text-sm font-medium',\n 'ring-offset-[var(--content-background)] transition-all',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n // States via data attributes\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n // WCAG 2.2 AAA: 44×44px minimum touch target\n 'min-h-[44px]',\n ],\n {\n variants: {\n variant: {\n default: [\n 'rounded-none bg-transparent',\n 'data-[selected]:text-[var(--content-foreground)]',\n 'hover:text-[var(--content-foreground)]',\n ],\n block: [\n 'rounded-sm',\n 'data-[selected]:bg-[var(--content-background)] data-[selected]:text-[var(--content-foreground)]',\n 'data-[selected]:shadow-sm',\n ],\n stepper: [\n 'flex items-center gap-2 rounded-none border-none bg-transparent px-3 py-2',\n ],\n },\n orientation: {\n horizontal: '',\n vertical: 'w-full justify-start',\n },\n },\n compoundVariants: [\n {\n variant: 'default',\n orientation: 'horizontal',\n class: 'relative -mb-px',\n },\n {\n variant: 'default',\n orientation: 'vertical',\n class: 'relative -ml-px',\n },\n ],\n defaultVariants: {\n variant: 'default',\n orientation: 'horizontal',\n },\n }\n);\n\n/**\n * TabPanel CVA variants\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n */\nexport const tabPanelVariants = cva(\n [\n 'mt-2 ring-offset-[var(--content-background)]',\n 'focus-visible:outline-none focus-visible:ring-2',\n 'focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2',\n ],\n {\n variants: {},\n defaultVariants: {},\n }\n);\n\n// ============================================================================\n// Components\n// ============================================================================\n\n/**\n * Tabs Root Component\n *\n * Container for tabbed interface. Manages selection state and provides\n * context to child components.\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n *\n * @example\n * // Uncontrolled\n * <Tabs defaultSelectedKey=\"tab1\">\n * <TabList aria-label=\"Navigation\">\n * <Tab id=\"tab1\">Tab 1</Tab>\n * <Tab id=\"tab2\">Tab 2</Tab>\n * </TabList>\n * <TabPanel id=\"tab1\">Content 1</TabPanel>\n * <TabPanel id=\"tab2\">Content 2</TabPanel>\n * </Tabs>\n *\n * @example\n * // Controlled\n * <Tabs selectedKey={selected} onSelectionChange={setSelected}>\n * ...\n * </Tabs>\n */\nfunction TabsRoot({\n children,\n variant = 'default',\n selectedKey,\n defaultSelectedKey,\n onSelectionChange,\n orientation = 'horizontal',\n keyboardActivation = 'automatic',\n isDisabled = false,\n disabledKeys,\n animated: animatedProp,\n className,\n ...props\n}: TabsProps) {\n const prefersReducedMotion = useReducedMotion();\n const doAnimate = shouldAnimate(animatedProp, prefersReducedMotion);\n // For stepper variant, track the selected key internally so Tab children\n // can determine completed/active/inactive state. React Aria's internal\n // TabListStateContext is not accessible from our Tab wrapper since tabs\n // are rendered via the collection system.\n const [trackedKey, setTrackedKey] = useState<Key | undefined>(\n selectedKey ?? defaultSelectedKey\n );\n\n const handleSelectionChange = (key: Key) => {\n if (variant === 'stepper') {\n setTrackedKey(key);\n }\n onSelectionChange?.(key);\n };\n\n // For controlled mode, use the prop directly\n const stepperSelectedKey = variant === 'stepper'\n ? (selectedKey ?? trackedKey)\n : undefined;\n\n return (\n <TabsInternalContext.Provider value={{ variant, orientation, stepperSelectedKey, animated: doAnimate }}>\n <AriaTabs\n selectedKey={selectedKey}\n defaultSelectedKey={defaultSelectedKey}\n onSelectionChange={handleSelectionChange as (key: Key) => void}\n orientation={orientation}\n keyboardActivation={keyboardActivation}\n isDisabled={isDisabled}\n disabledKeys={disabledKeys as Iterable<AriaKey> | undefined}\n className={cn(className)}\n {...props}\n >\n {children}\n </AriaTabs>\n </TabsInternalContext.Provider>\n );\n}\n\nTabsRoot.displayName = 'Tabs';\n\n/**\n * TabList Component\n *\n * Container for tab buttons. Uses roving tabindex for keyboard navigation.\n * Receives orientation from parent Tabs via React Aria context.\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nfunction TabListComponent({\n children,\n className,\n ...props\n}: TabListProps) {\n const { variant } = useContext(TabsInternalContext);\n\n // For stepper variant, collect tab keys from children to determine order\n if (variant === 'stepper') {\n // Extract keys from Tab children to determine ordering\n const tabKeys: Key[] = [];\n Children.forEach(children as ReactNode, (child) => {\n if (isValidElement(child) && child.props && typeof (child.props as Record<string, unknown>).id !== 'undefined') {\n tabKeys.push((child.props as Record<string, unknown>).id as Key);\n }\n });\n\n return (\n <StepperContext.Provider value={{ tabKeys }}>\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n </StepperContext.Provider>\n );\n }\n\n return (\n <AriaTabList\n className={composeRenderProps(className, (className, renderProps) =>\n cn(\n tabListVariants({ variant, orientation: renderProps.orientation }),\n className\n )\n )}\n {...props}\n >\n {children}\n </AriaTabList>\n );\n}\n\nTabListComponent.displayName = 'TabList';\n\n/**\n * Tab Component\n *\n * Individual tab button. Can render as button or anchor (when href provided).\n * Supports icons and badges as children.\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-013 (Icon Support)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nfunction TabComponent({\n children,\n id,\n isDisabled = false,\n href,\n target,\n rel,\n download,\n className,\n ...props\n}: TabProps) {\n // Warn if icon-only tab without aria-label\n if (process.env.NODE_ENV !== 'production') {\n const hasTextContent =\n typeof children === 'string' ||\n (Array.isArray(children) &&\n children.some((child) => typeof child === 'string'));\n\n if (!hasTextContent && !props['aria-label']) {\n console.warn(\n 'Tabs: Icon-only tabs should have an aria-label for accessibility.'\n );\n }\n }\n\n const { variant, orientation, stepperSelectedKey, animated: doAnimate } = useContext(TabsInternalContext);\n const stepperCtx = useContext(StepperContext);\n\n // Motion.dev component for animated indicator (lazy-loaded)\n const [MotionSpan, setMotionSpan] = useState<MotionSpanComponent | null>(null);\n const motionLoadedRef = useRef(false);\n\n useEffect(() => {\n if (variant !== 'default' || !doAnimate || motionLoadedRef.current) return;\n motionLoadedRef.current = true;\n loadMotionSpan().then((component) => {\n if (component) setMotionSpan(() => component);\n });\n }, [variant, doAnimate]);\n\n // For stepper variant, render numbered circle with optional connecting line\n if (variant === 'stepper') {\n const tabIndex = stepperCtx.tabKeys.indexOf(id);\n const selectedIndex = stepperSelectedKey !== undefined\n ? stepperCtx.tabKeys.indexOf(stepperSelectedKey)\n : -1;\n const isFirst = tabIndex === 0;\n const isCompleted = tabIndex >= 0 && selectedIndex >= 0 && tabIndex < selectedIndex;\n const isActive = tabIndex >= 0 && tabIndex === selectedIndex;\n const isVertical = orientation === 'vertical';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(\n tabVariants({ variant, orientation }),\n isActive && 'bg-[var(--primary-action)]/10 rounded-lg',\n className,\n )\n )}\n {...props}\n >\n {/* Connecting line before tab (horizontal only, except first) */}\n {!isFirst && !isVertical && (\n <span\n className=\"h-px w-6 bg-[var(--border)]\"\n aria-hidden=\"true\"\n />\n )}\n {/* Step circle */}\n <span\n className={cn(\n 'flex h-7 w-7 shrink-0 items-center justify-center rounded-lg text-xs font-bold',\n isActive\n ? 'bg-[var(--primary-action)] text-white'\n : isCompleted\n ? 'bg-[var(--primary-action)] text-white'\n : 'bg-[var(--accent-background)] text-[var(--muted-foreground)]'\n )}\n aria-hidden=\"true\"\n >\n {isCompleted ? (\n <Check className=\"h-3.5 w-3.5\" />\n ) : (\n tabIndex + 1\n )}\n </span>\n {/* Visually hidden step number for screen readers */}\n <span className=\"sr-only\">\n {isCompleted ? `Step ${tabIndex + 1}, completed:` : `Step ${tabIndex + 1}:`}\n </span>\n {/* Tab label */}\n <span className={cn(\n isActive && 'font-semibold text-[var(--primary-action)]',\n )}>{children}</span>\n </AriaTab>\n );\n }\n\n // Default variant: render with sliding indicator\n const isHorizontal = orientation === 'horizontal';\n const indicatorClasses = isHorizontal\n ? 'absolute bottom-0 left-0 right-0 h-0.5 bg-[var(--primary-action)]'\n : 'absolute top-0 bottom-0 left-0 w-0.5 bg-[var(--primary-action)]';\n\n return (\n <AriaTab\n id={id}\n isDisabled={isDisabled}\n href={href}\n target={target}\n rel={rel}\n download={download}\n className={composeRenderProps(className, (className) =>\n cn(tabVariants({ variant, orientation }), className)\n )}\n {...props}\n >\n {(renderProps) => (\n <>\n {children}\n {/* Tab indicator — animated slide or instant position */}\n {variant === 'default' && renderProps.isSelected && (\n doAnimate && MotionSpan ? (\n <MotionSpan\n layoutId={`tab-indicator-${isHorizontal ? 'h' : 'v'}`}\n className={indicatorClasses}\n transition={{ type: 'spring', stiffness: 500, damping: 30 }}\n />\n ) : (\n <span className={indicatorClasses} />\n )\n )}\n </>\n )}\n </AriaTab>\n );\n}\n\nTabComponent.displayName = 'Tab';\n\n/**\n * TabPanel Component\n *\n * Content panel associated with a tab. Only the selected panel is visible.\n * Supports preserveState for React Activity state preservation.\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n *\n * @example\n * // Default behavior - content unmounts when hidden\n * <TabPanel id=\"tab1\">Content</TabPanel>\n *\n * @example\n * // Legacy force mount - keeps content in DOM\n * <TabPanel id=\"tab1\" shouldForceMount>Form with state</TabPanel>\n *\n * @example\n * // React Activity - preserves state with proper effect cleanup\n * <TabPanel id=\"tab1\" preserveState>\n * <FormWithDraft />\n * </TabPanel>\n */\nfunction TabPanelComponent({\n children,\n id,\n shouldForceMount = false,\n preserveState = false,\n className,\n ...props\n}: TabPanelProps) {\n // preserveState takes precedence - both enable force mounting\n const forceMount = preserveState || shouldForceMount;\n\n // If children is a render function (for dynamic content based on selection state),\n // we need to use the render props pattern\n if (typeof children === 'function') {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n // React Aria TabPanelRenderProps includes: state, isInert\n // We derive isSelected from state - if state is undefined, panel is selected\n const isSelected = !renderProps.isInert;\n const content = (\n children as (renderProps: { isSelected: boolean }) => ReactNode\n )({ isSelected });\n\n if (preserveState) {\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {content}\n </Activity>\n );\n }\n\n return content;\n }}\n </AriaTabPanel>\n );\n }\n\n // For static children (not a function), render directly\n // If preserveState is enabled, wrap in Activity\n if (preserveState) {\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {(renderProps) => {\n const isSelected = !renderProps.isInert;\n return (\n <Activity mode={isSelected ? 'visible' : 'hidden'}>\n {children}\n </Activity>\n );\n }}\n </AriaTabPanel>\n );\n }\n\n // Default: render static children directly\n return (\n <AriaTabPanel\n id={id}\n shouldForceMount={forceMount}\n className={composeRenderProps(className, (className) =>\n cn(tabPanelVariants(), className)\n )}\n {...props}\n >\n {children}\n </AriaTabPanel>\n );\n}\n\nTabPanelComponent.displayName = 'TabPanel';\n\n// ============================================================================\n// Exports\n// ============================================================================\n\n/**\n * Direct named exports (not Object.assign compound pattern)\n *\n * Tabs follows React Aria's direct export pattern because:\n * - Simpler structure (only 4 components vs Dialog's 9)\n * - Better tree-shaking with named exports\n * - Clearer imports: import { Tabs, TabList, Tab, TabPanel } from '...'\n *\n * @see plan.md \"Why Direct Named Exports (Not Object.assign)?\"\n */\nexport const Tabs = TabsRoot;\nexport const TabList = TabListComponent;\nexport const Tab = TabComponent;\nexport const TabPanel = TabPanelComponent;\n\n// Re-export types for convenience\nexport type { TabsProps, TabsVariant, TabListProps, TabProps, TabPanelProps };\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\nimport type { ReactNode, Key } from 'react';\n\n/**\n * Tab variant schema\n *\n * - 'default': Transparent background with bottom border indicator for active tab\n * - 'block': Pill/card style with accent background and shadow for active tab\n * - 'stepper': Numbered step circles with connecting lines (free navigation, not a wizard)\n */\nexport const TabsVariantSchema = z.enum(['default', 'block', 'stepper']);\nexport type TabsVariant = z.infer<typeof TabsVariantSchema>;\n\n/**\n * Tab orientation schema\n *\n * @see PRD.md FR-005 (Orientation Support)\n */\nexport const TabsOrientationSchema = z.enum(['horizontal', 'vertical']);\nexport type TabsOrientation = z.infer<typeof TabsOrientationSchema>;\n\n/**\n * Keyboard activation mode schema\n *\n * @see PRD.md FR-006 (Keyboard Activation Modes)\n */\nexport const TabsKeyboardActivationSchema = z.enum(['automatic', 'manual']);\nexport type TabsKeyboardActivation = z.infer<typeof TabsKeyboardActivationSchema>;\n\n/**\n * Key schema for tab identification\n * Supports both string and number keys per React Aria convention\n */\nexport const KeySchema = z.union([z.string(), z.number()]);\n\n/**\n * Tabs root component props schema\n *\n * @see PRD.md FR-001 (Compound Component Pattern)\n * @see PRD.md FR-012 (Controlled Mode)\n * @see PRD.md FR-013 (Uncontrolled Mode)\n */\nexport const TabsPropsSchema = BaseComponentPropsSchema.extend({\n // Visual variant: 'default' (underline) or 'block' (pill/card)\n variant: TabsVariantSchema.optional().default('default'),\n\n // Controlled mode: selected tab key\n selectedKey: KeySchema.optional(),\n\n // Uncontrolled mode: default selected tab key\n defaultSelectedKey: KeySchema.optional(),\n\n // Selection change handler\n onSelectionChange: z.custom<(key: Key) => void>().optional(),\n\n // Orientation: horizontal or vertical layout\n orientation: TabsOrientationSchema.optional().default('horizontal'),\n\n // Keyboard activation: automatic (arrows select) or manual (arrows focus, Enter selects)\n keyboardActivation: TabsKeyboardActivationSchema.optional().default('automatic'),\n\n // Disable all tabs\n isDisabled: z.boolean().optional().default(false),\n\n // Keys of tabs to disable individually\n disabledKeys: z.array(KeySchema).optional(),\n\n // Children: TabList and TabPanel components\n children: z.custom<ReactNode>(),\n\n // Animation (ADR 020 - Micro-Interaction Animation System)\n // When true, the tab indicator slides between tabs (default variant only)\n animated: z.boolean().optional().default(true),\n});\n\nexport interface TabsProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'aria-live'?: 'off' | 'polite' | 'assertive';\n 'aria-hidden'?: boolean;\n 'data-testid'?: string;\n variant?: TabsVariant;\n selectedKey?: string | number;\n defaultSelectedKey?: string | number;\n onSelectionChange?: (key: Key) => void;\n orientation?: TabsOrientation;\n keyboardActivation?: TabsKeyboardActivation;\n isDisabled?: boolean;\n disabledKeys?: (string | number)[];\n animated?: boolean;\n}\n\n/**\n * TabList component props schema\n *\n * @see PRD.md FR-002 (TabList Requirements)\n * @see PRD.md AR-001 (ARIA Requirements)\n */\nexport const TabListPropsSchema = BaseComponentPropsSchema.extend({\n // Accessible label (required for accessibility if no aria-labelledby)\n 'aria-label': z.string().optional(),\n\n // Reference to labelling element\n 'aria-labelledby': z.string().optional(),\n\n // Children: Tab components\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabListProps {\n className?: string;\n children?: ReactNode;\n id?: string;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n}\n\n/**\n * Tab component props schema\n *\n * @see PRD.md FR-003 (Tab Requirements)\n * @see PRD.md FR-007 (Disabled States)\n * @see PRD.md FR-014 (Link-based Tabs)\n */\nexport const TabPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier for the tab (required)\n id: KeySchema,\n\n // Disable this specific tab\n isDisabled: z.boolean().optional().default(false),\n\n // Link tab: URL for navigation-style tabs\n href: z.string().optional(),\n\n // Link tab: target attribute\n target: z.string().optional(),\n\n // Link tab: rel attribute\n rel: z.string().optional(),\n\n // Link tab: download attribute\n download: z.union([z.string(), z.boolean()]).optional(),\n\n // Tab content (text, icons, badges)\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'aria-describedby'?: string;\n 'data-testid'?: string;\n isDisabled?: boolean;\n href?: string;\n target?: string;\n rel?: string;\n download?: string | boolean;\n}\n\n/**\n * TabPanel component props schema\n *\n * @see PRD.md FR-004 (TabPanel Requirements)\n * @see PRD.md FR-015 (Force Mount Panels)\n * @see PRD.md FR-016 (React Activity State Preservation)\n */\nexport const TabPanelPropsSchema = BaseComponentPropsSchema.extend({\n // Unique identifier matching a Tab id (required)\n id: KeySchema,\n\n // Legacy: Force panel to stay in DOM when hidden\n // Use preserveState instead for proper effect cleanup\n shouldForceMount: z.boolean().optional().default(false),\n\n // React 19.2 Activity: Preserve state with proper effect cleanup\n // When true, wraps content in <Activity> component\n // Effects are cleaned up when hidden, restored when visible\n preserveState: z.boolean().optional().default(false),\n\n // Panel content\n children: z.custom<ReactNode>(),\n});\n\nexport interface TabPanelProps {\n className?: string;\n children?: ReactNode;\n id: string | number;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n 'data-testid'?: string;\n shouldForceMount?: boolean;\n preserveState?: boolean;\n}\n\n/**\n * Scroll arrow direction for overflow handling\n *\n * @see PRD.md FR-010 (Overflow Handling)\n */\nexport const ScrollArrowDirectionSchema = z.enum(['left', 'right', 'up', 'down']);\nexport type ScrollArrowDirection = z.infer<typeof ScrollArrowDirectionSchema>;\n\n/**\n * Internal props for scroll arrow buttons\n * Used by overflow handling implementation\n */\nexport const ScrollArrowPropsSchema = BaseComponentPropsSchema.extend({\n // Scroll direction\n direction: ScrollArrowDirectionSchema,\n\n // Disable when can't scroll further\n isDisabled: z.boolean().optional().default(false),\n\n // Click handler for scrolling\n onPress: z.custom<() => void>(),\n\n // Accessible label\n 'aria-label': z.string(),\n});\n\nexport interface ScrollArrowProps {\n className?: string;\n id?: string;\n 'aria-label': string;\n 'data-testid'?: string;\n direction: ScrollArrowDirection;\n isDisabled?: boolean;\n onPress: () => void;\n}\n"]}
|