@tribepad/themis 1.0.1 → 1.0.3
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/Accordion/index.js +1 -335
- package/dist/elements/Accordion/index.js.map +1 -1
- package/dist/elements/Accordion/index.mjs +1 -317
- package/dist/elements/Accordion/index.mjs.map +1 -1
- package/dist/elements/AlertDialog/AlertDialog.d.ts +43 -0
- package/dist/elements/AlertDialog/AlertDialog.d.ts.map +1 -0
- package/dist/elements/AlertDialog/AlertDialog.styles.d.ts +15 -0
- package/dist/elements/AlertDialog/AlertDialog.styles.d.ts.map +1 -0
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts +72 -0
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts.map +1 -0
- package/dist/elements/AlertDialog/index.d.ts +25 -0
- package/dist/elements/AlertDialog/index.d.ts.map +1 -0
- package/dist/elements/AlertDialog/index.js +3 -0
- package/dist/elements/AlertDialog/index.js.map +1 -0
- package/dist/elements/AlertDialog/index.mjs +3 -0
- package/dist/elements/AlertDialog/index.mjs.map +1 -0
- package/dist/elements/Avatar/index.js +1 -468
- package/dist/elements/Avatar/index.js.map +1 -1
- package/dist/elements/Avatar/index.mjs +1 -456
- package/dist/elements/Avatar/index.mjs.map +1 -1
- package/dist/elements/Badge/index.js +1 -243
- package/dist/elements/Badge/index.js.map +1 -1
- package/dist/elements/Badge/index.mjs +1 -234
- package/dist/elements/Badge/index.mjs.map +1 -1
- package/dist/elements/Breadcrumbs/index.js +1 -821
- package/dist/elements/Breadcrumbs/index.js.map +1 -1
- package/dist/elements/Breadcrumbs/index.mjs +1 -810
- package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
- package/dist/elements/Button/Button.d.ts +26 -81
- package/dist/elements/Button/Button.d.ts.map +1 -1
- package/dist/elements/Button/Button.styles.d.ts +35 -0
- package/dist/elements/Button/Button.styles.d.ts.map +1 -0
- package/dist/elements/Button/Button.types.d.ts +20 -8
- package/dist/elements/Button/Button.types.d.ts.map +1 -1
- package/dist/elements/Button/index.js +1 -288
- package/dist/elements/Button/index.js.map +1 -1
- package/dist/elements/Button/index.mjs +1 -283
- package/dist/elements/Button/index.mjs.map +1 -1
- package/dist/elements/ButtonGroup/index.js +1 -237
- package/dist/elements/ButtonGroup/index.js.map +1 -1
- package/dist/elements/ButtonGroup/index.mjs +1 -222
- package/dist/elements/ButtonGroup/index.mjs.map +1 -1
- package/dist/elements/Card/index.js +1 -579
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/Card/index.mjs +1 -560
- package/dist/elements/Card/index.mjs.map +1 -1
- package/dist/elements/Carousel/Carousel.d.ts +1 -11
- package/dist/elements/Carousel/Carousel.d.ts.map +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts +1 -1
- package/dist/elements/Carousel/LazyCarousel.d.ts.map +1 -1
- package/dist/elements/Carousel/index.js +1 -789
- package/dist/elements/Carousel/index.js.map +1 -1
- package/dist/elements/Carousel/index.mjs +1 -786
- package/dist/elements/Carousel/index.mjs.map +1 -1
- package/dist/elements/Chart/ChartContext.d.ts.map +1 -1
- package/dist/elements/Chart/index.js +1 -1842
- package/dist/elements/Chart/index.js.map +1 -1
- package/dist/elements/Chart/index.mjs +1 -1832
- package/dist/elements/Chart/index.mjs.map +1 -1
- package/dist/elements/Checkbox/index.js +1 -316
- package/dist/elements/Checkbox/index.js.map +1 -1
- package/dist/elements/Checkbox/index.mjs +1 -306
- package/dist/elements/Checkbox/index.mjs.map +1 -1
- package/dist/elements/CheckboxGroup/index.js +1 -455
- package/dist/elements/CheckboxGroup/index.js.map +1 -1
- package/dist/elements/CheckboxGroup/index.mjs +1 -439
- package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
- package/dist/elements/Combobox/Combobox.d.ts +56 -0
- package/dist/elements/Combobox/Combobox.d.ts.map +1 -0
- package/dist/elements/Combobox/Combobox.styles.d.ts +29 -0
- package/dist/elements/Combobox/Combobox.styles.d.ts.map +1 -0
- package/dist/elements/Combobox/Combobox.types.d.ts +67 -0
- package/dist/elements/Combobox/Combobox.types.d.ts.map +1 -0
- package/dist/elements/Combobox/index.d.ts +20 -0
- package/dist/elements/Combobox/index.d.ts.map +1 -0
- package/dist/elements/Combobox/index.js +3 -0
- package/dist/elements/Combobox/index.js.map +1 -0
- package/dist/elements/Combobox/index.mjs +3 -0
- package/dist/elements/Combobox/index.mjs.map +1 -0
- package/dist/elements/DatePicker/DatePicker.d.ts +1 -1
- package/dist/elements/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/elements/DatePicker/index.js +1 -903
- package/dist/elements/DatePicker/index.js.map +1 -1
- package/dist/elements/DatePicker/index.mjs +1 -853
- package/dist/elements/DatePicker/index.mjs.map +1 -1
- package/dist/elements/Dropdown/Dropdown.d.ts +7 -15
- package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/elements/Dropdown/Dropdown.styles.d.ts +22 -0
- package/dist/elements/Dropdown/Dropdown.styles.d.ts.map +1 -0
- package/dist/elements/Dropdown/index.d.ts +1 -0
- package/dist/elements/Dropdown/index.d.ts.map +1 -1
- package/dist/elements/Dropdown/index.js +1 -193
- package/dist/elements/Dropdown/index.js.map +1 -1
- package/dist/elements/Dropdown/index.mjs +1 -184
- package/dist/elements/Dropdown/index.mjs.map +1 -1
- package/dist/elements/FileField/index.js +1 -1539
- package/dist/elements/FileField/index.js.map +1 -1
- package/dist/elements/FileField/index.mjs +1 -1507
- package/dist/elements/FileField/index.mjs.map +1 -1
- package/dist/elements/FormLayout/index.js +1 -170
- package/dist/elements/FormLayout/index.js.map +1 -1
- package/dist/elements/FormLayout/index.mjs +1 -167
- package/dist/elements/FormLayout/index.mjs.map +1 -1
- package/dist/elements/Modal/Modal.d.ts +9 -14
- package/dist/elements/Modal/Modal.d.ts.map +1 -1
- package/dist/elements/Modal/Modal.styles.d.ts +29 -0
- package/dist/elements/Modal/Modal.styles.d.ts.map +1 -0
- package/dist/elements/Modal/index.d.ts +1 -0
- package/dist/elements/Modal/index.d.ts.map +1 -1
- package/dist/elements/Modal/index.js +1 -232
- package/dist/elements/Modal/index.js.map +1 -1
- package/dist/elements/Modal/index.mjs +1 -220
- package/dist/elements/Modal/index.mjs.map +1 -1
- package/dist/elements/NumberField/NumberField.variants.d.ts +1 -1
- package/dist/elements/NumberField/index.js +1 -666
- package/dist/elements/NumberField/index.js.map +1 -1
- package/dist/elements/NumberField/index.mjs +1 -654
- package/dist/elements/NumberField/index.mjs.map +1 -1
- package/dist/elements/OTPInput/OTPInput.d.ts.map +1 -1
- package/dist/elements/OTPInput/index.js +1 -734
- package/dist/elements/OTPInput/index.js.map +1 -1
- package/dist/elements/OTPInput/index.mjs +1 -732
- package/dist/elements/OTPInput/index.mjs.map +1 -1
- package/dist/elements/Pagination/Pagination.d.ts +45 -0
- package/dist/elements/Pagination/Pagination.d.ts.map +1 -0
- package/dist/elements/Pagination/Pagination.styles.d.ts +10 -0
- package/dist/elements/Pagination/Pagination.styles.d.ts.map +1 -0
- package/dist/elements/Pagination/Pagination.types.d.ts +55 -0
- package/dist/elements/Pagination/Pagination.types.d.ts.map +1 -0
- package/dist/elements/Pagination/index.d.ts +21 -0
- package/dist/elements/Pagination/index.d.ts.map +1 -0
- package/dist/elements/Pagination/index.js +3 -0
- package/dist/elements/Pagination/index.js.map +1 -0
- package/dist/elements/Pagination/index.mjs +3 -0
- package/dist/elements/Pagination/index.mjs.map +1 -0
- package/dist/elements/Panel/index.js +1 -330
- package/dist/elements/Panel/index.js.map +1 -1
- package/dist/elements/Panel/index.mjs +1 -323
- package/dist/elements/Panel/index.mjs.map +1 -1
- package/dist/elements/PasswordField/PasswordField.d.ts +27 -0
- package/dist/elements/PasswordField/PasswordField.d.ts.map +1 -0
- package/dist/elements/PasswordField/PasswordField.styles.d.ts +32 -0
- package/dist/elements/PasswordField/PasswordField.styles.d.ts.map +1 -0
- package/dist/elements/PasswordField/PasswordField.types.d.ts +100 -0
- package/dist/elements/PasswordField/PasswordField.types.d.ts.map +1 -0
- package/dist/elements/PasswordField/index.css +2 -0
- package/dist/elements/PasswordField/index.css.map +1 -0
- package/dist/elements/PasswordField/index.d.ts +20 -0
- package/dist/elements/PasswordField/index.d.ts.map +1 -0
- package/dist/elements/PasswordField/index.js +3 -0
- package/dist/elements/PasswordField/index.js.map +1 -0
- package/dist/elements/PasswordField/index.mjs +3 -0
- package/dist/elements/PasswordField/index.mjs.map +1 -0
- package/dist/elements/Progress/index.js +1 -187
- package/dist/elements/Progress/index.js.map +1 -1
- package/dist/elements/Progress/index.mjs +1 -181
- package/dist/elements/Progress/index.mjs.map +1 -1
- package/dist/elements/RadioGroup/index.js +1 -369
- package/dist/elements/RadioGroup/index.js.map +1 -1
- package/dist/elements/RadioGroup/index.mjs +1 -359
- package/dist/elements/RadioGroup/index.mjs.map +1 -1
- package/dist/elements/Resizable/index.js +1 -1580
- package/dist/elements/Resizable/index.js.map +1 -1
- package/dist/elements/Resizable/index.mjs +1 -1566
- package/dist/elements/Resizable/index.mjs.map +1 -1
- package/dist/elements/SearchField/SearchField.d.ts +27 -0
- package/dist/elements/SearchField/SearchField.d.ts.map +1 -0
- package/dist/elements/SearchField/SearchField.styles.d.ts +32 -0
- package/dist/elements/SearchField/SearchField.styles.d.ts.map +1 -0
- package/dist/elements/SearchField/SearchField.types.d.ts +45 -0
- package/dist/elements/SearchField/SearchField.types.d.ts.map +1 -0
- package/dist/elements/SearchField/index.css +2 -0
- package/dist/elements/SearchField/index.css.map +1 -0
- package/dist/elements/SearchField/index.d.ts +21 -0
- package/dist/elements/SearchField/index.d.ts.map +1 -0
- package/dist/elements/SearchField/index.js +3 -0
- package/dist/elements/SearchField/index.js.map +1 -0
- package/dist/elements/SearchField/index.mjs +3 -0
- package/dist/elements/SearchField/index.mjs.map +1 -0
- package/dist/elements/Select/Select.d.ts +19 -48
- package/dist/elements/Select/Select.d.ts.map +1 -1
- package/dist/elements/Select/Select.styles.d.ts +55 -0
- package/dist/elements/Select/Select.styles.d.ts.map +1 -0
- package/dist/elements/Select/index.js +1 -589
- package/dist/elements/Select/index.js.map +1 -1
- package/dist/elements/Select/index.mjs +1 -582
- package/dist/elements/Select/index.mjs.map +1 -1
- package/dist/elements/Skeleton/index.js +1 -82
- package/dist/elements/Skeleton/index.js.map +1 -1
- package/dist/elements/Skeleton/index.mjs +1 -78
- package/dist/elements/Skeleton/index.mjs.map +1 -1
- package/dist/elements/Switch/index.js +1 -179
- package/dist/elements/Switch/index.js.map +1 -1
- package/dist/elements/Switch/index.mjs +1 -173
- package/dist/elements/Switch/index.mjs.map +1 -1
- package/dist/elements/Table/Table.d.ts +3 -24
- package/dist/elements/Table/Table.d.ts.map +1 -1
- package/dist/elements/Table/Table.styles.d.ts +24 -0
- package/dist/elements/Table/Table.styles.d.ts.map +1 -0
- package/dist/elements/Table/index.js +1 -595
- package/dist/elements/Table/index.js.map +1 -1
- package/dist/elements/Table/index.mjs +1 -578
- package/dist/elements/Table/index.mjs.map +1 -1
- package/dist/elements/Tabs/Tabs.d.ts +5 -3
- package/dist/elements/Tabs/Tabs.d.ts.map +1 -1
- package/dist/elements/Tabs/Tabs.types.d.ts +15 -0
- package/dist/elements/Tabs/Tabs.types.d.ts.map +1 -1
- package/dist/elements/Tabs/index.js +1 -337
- package/dist/elements/Tabs/index.js.map +1 -1
- package/dist/elements/Tabs/index.mjs +1 -320
- package/dist/elements/Tabs/index.mjs.map +1 -1
- package/dist/elements/TextField/TextField.d.ts +6 -42
- package/dist/elements/TextField/TextField.d.ts.map +1 -1
- package/dist/elements/TextField/TextField.hooks.d.ts +63 -0
- package/dist/elements/TextField/TextField.hooks.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.icons.d.ts +19 -0
- package/dist/elements/TextField/TextField.icons.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.styles.d.ts +37 -0
- package/dist/elements/TextField/TextField.styles.d.ts.map +1 -0
- package/dist/elements/TextField/TextField.types.d.ts +3 -0
- package/dist/elements/TextField/TextField.types.d.ts.map +1 -1
- package/dist/elements/TextField/index.css +1 -22
- package/dist/elements/TextField/index.css.map +1 -1
- package/dist/elements/TextField/index.js +1 -902
- package/dist/elements/TextField/index.js.map +1 -1
- package/dist/elements/TextField/index.mjs +1 -882
- package/dist/elements/TextField/index.mjs.map +1 -1
- package/dist/elements/TimeField/index.js +1 -254
- package/dist/elements/TimeField/index.js.map +1 -1
- package/dist/elements/TimeField/index.mjs +1 -238
- package/dist/elements/TimeField/index.mjs.map +1 -1
- package/dist/elements/Toast/Toast.d.ts +0 -22
- package/dist/elements/Toast/Toast.d.ts.map +1 -1
- package/dist/elements/Toast/index.js +1 -737
- package/dist/elements/Toast/index.js.map +1 -1
- package/dist/elements/Toast/index.mjs +1 -724
- package/dist/elements/Toast/index.mjs.map +1 -1
- package/dist/elements/Tooltip/index.js +1 -323
- package/dist/elements/Tooltip/index.js.map +1 -1
- package/dist/elements/Tooltip/index.mjs +1 -310
- package/dist/elements/Tooltip/index.mjs.map +1 -1
- package/dist/elements/index.css +1 -22
- package/dist/elements/index.css.map +1 -1
- package/dist/elements/index.d.ts +13 -1
- package/dist/elements/index.d.ts.map +1 -1
- package/dist/elements/index.js +1 -12455
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -12233
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.css +1 -22
- package/dist/index.css.map +1 -1
- package/dist/index.js +2 -12490
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -12262
- package/dist/index.mjs.map +1 -1
- package/dist/schemas/index.js +2 -54
- package/dist/schemas/index.js.map +1 -1
- package/dist/schemas/index.mjs +2 -48
- package/dist/schemas/index.mjs.map +1 -1
- package/dist/styles/defaults.css +151 -0
- package/dist/styles/index.js +1 -166
- package/dist/styles/index.js.map +1 -1
- package/dist/styles/index.mjs +1 -129
- package/dist/styles/index.mjs.map +1 -1
- package/dist/styles/shared-variants.d.ts +3 -3
- package/dist/styles/shared-variants.d.ts.map +1 -1
- package/dist/utils/index.js +1 -12
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/index.mjs +1 -10
- package/dist/utils/index.mjs.map +1 -1
- package/package.json +9 -7
- package/src/elements/Accordion/Accordion.stories.tsx +1 -1
- package/src/elements/AlertDialog/AlertDialog.stories.tsx +124 -0
- package/src/elements/Avatar/Avatar.stories.tsx +1 -1
- package/src/elements/Badge/Badge.stories.tsx +1 -1
- package/src/elements/Breadcrumbs/Breadcrumbs.stories.tsx +1 -1
- package/src/elements/Button/Button.stories.tsx +1 -1
- package/src/elements/ButtonGroup/ButtonGroup.stories.tsx +1 -1
- package/src/elements/Card/Card.stories.tsx +1 -1
- package/src/elements/Carousel/Carousel.stories.tsx +1 -1
- package/src/elements/Chart/Chart.stories.tsx +1 -1
- package/src/elements/Checkbox/Checkbox.stories.tsx +1 -1
- package/src/elements/CheckboxGroup/CheckboxGroup.stories.tsx +4 -4
- package/src/elements/Combobox/Combobox.stories.tsx +133 -0
- package/src/elements/DatePicker/DatePicker.stories.tsx +1 -1
- package/src/elements/Dropdown/Dropdown.stories.tsx +1 -1
- package/src/elements/FileField/FileField.stories.tsx +2 -2
- package/src/elements/FileField/FileProgress.stories.tsx +1 -1
- package/src/elements/FormLayout/FormLayout.stories.tsx +1 -1
- package/src/elements/Modal/Modal.stories.tsx +1 -1
- package/src/elements/NumberField/NumberField.stories.tsx +1 -1
- package/src/elements/OTPInput/OTPInput.stories.tsx +1 -1
- package/src/elements/Pagination/Pagination.stories.tsx +203 -0
- package/src/elements/Panel/Panel.stories.tsx +1 -1
- package/src/elements/PasswordField/PasswordField.stories.tsx +167 -0
- package/src/elements/Progress/Progress.stories.tsx +7 -2
- package/src/elements/RadioGroup/RadioGroup.stories.tsx +3 -3
- package/src/elements/Resizable/Resizable.stories.tsx +1 -1
- package/src/elements/SearchField/SearchField.stories.tsx +146 -0
- package/src/elements/Select/Select.stories.tsx +1 -1
- package/src/elements/Skeleton/Skeleton.stories.tsx +1 -1
- package/src/elements/Switch/Switch.stories.tsx +1 -1
- package/src/elements/Table/Table.stories.tsx +1 -1
- package/src/elements/Tabs/Tabs.stories.tsx +46 -2
- package/src/elements/TextField/TextField.stories.tsx +1 -1
- package/src/elements/TimeField/TimeField.stories.tsx +1 -1
- package/src/elements/Toast/Toast.stories.tsx +1 -1
- package/src/elements/Tooltip/Tooltip.stories.tsx +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/OTPInput/hooks/useOTPKeyboard.ts","../../../src/elements/OTPInput/hooks/useOTPInput.ts","../../../src/elements/OTPInput/OTPInput.styles.ts","../../../src/elements/OTPInput/components/OTPDigit.tsx","../../../src/elements/OTPInput/OTPInput.tsx"],"names":["useCallback","isComplete","useRef","jsx"],"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","import { useCallback, type KeyboardEvent } from 'react';\n\n/**\n * Options for useOTPKeyboard hook\n */\nexport interface UseOTPKeyboardOptions {\n /**\n * Current OTP value (string with underscores for empty)\n */\n value: string;\n\n /**\n * Total number of digits\n */\n length: number;\n\n /**\n * Currently focused digit index\n */\n focusedIndex: number;\n\n /**\n * Callback to update OTP value\n */\n onChange: (value: string) => void;\n\n /**\n * Callback to update focused index\n */\n setFocusedIndex: (index: number) => void;\n\n /**\n * Whether the input is disabled\n */\n disabled?: boolean;\n\n /**\n * Whether the input is read-only\n */\n readOnly?: boolean;\n}\n\n/**\n * Return type for useOTPKeyboard hook\n */\nexport interface UseOTPKeyboardReturn {\n /**\n * Keyboard event handler\n */\n handleKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;\n}\n\n/**\n * useOTPKeyboard Hook\n *\n * Handles keyboard navigation for OTP input:\n * - Arrow Left/Right: Navigate between digits\n * - Backspace: Delete current digit and move left\n * - Delete: Clear current digit\n * - Home: Move to first digit\n * - End: Move to last digit\n * - Ctrl/Cmd+A: Select all (native browser behavior)\n *\n * @param options Configuration options\n * @returns Keyboard event handler\n */\nexport function useOTPKeyboard(options: UseOTPKeyboardOptions): UseOTPKeyboardReturn {\n const {\n value,\n length,\n focusedIndex,\n onChange,\n setFocusedIndex,\n disabled = false,\n readOnly = false,\n } = options;\n\n /**\n * Handle Arrow Left - Move to previous digit\n */\n const handleArrowLeft = useCallback((): void => {\n if (focusedIndex > 0) {\n setFocusedIndex(focusedIndex - 1);\n }\n }, [focusedIndex, setFocusedIndex]);\n\n /**\n * Handle Arrow Right - Move to next digit\n */\n const handleArrowRight = useCallback((): void => {\n if (focusedIndex < length - 1) {\n setFocusedIndex(focusedIndex + 1);\n }\n }, [focusedIndex, length, setFocusedIndex]);\n\n /**\n * Handle Backspace - Delete current digit and move left\n */\n const handleBackspace = useCallback((): void => {\n if (readOnly) return;\n\n const digits = value.split('');\n const currentDigit = digits[focusedIndex];\n\n // If current digit is empty, move to previous digit\n if (currentDigit === '_') {\n if (focusedIndex > 0) {\n // Move left and clear that digit\n const newIndex = focusedIndex - 1;\n digits[newIndex] = '_';\n onChange(digits.join(''));\n setFocusedIndex(newIndex);\n }\n } else {\n // Clear current digit\n digits[focusedIndex] = '_';\n onChange(digits.join(''));\n // Move to previous digit if not at start\n if (focusedIndex > 0) {\n setFocusedIndex(focusedIndex - 1);\n }\n }\n }, [value, focusedIndex, readOnly, onChange, setFocusedIndex]);\n\n /**\n * Handle Delete - Clear current digit (stay in place)\n */\n const handleDelete = useCallback((): void => {\n if (readOnly) return;\n\n const digits = value.split('');\n digits[focusedIndex] = '_';\n onChange(digits.join(''));\n // Stay on current digit (don't move)\n }, [value, focusedIndex, readOnly, onChange]);\n\n /**\n * Handle Home - Move to first digit\n */\n const handleHome = useCallback((): void => {\n setFocusedIndex(0);\n }, [setFocusedIndex]);\n\n /**\n * Handle End - Move to last digit\n */\n const handleEnd = useCallback((): void => {\n setFocusedIndex(length - 1);\n }, [length, setFocusedIndex]);\n\n /**\n * Main keyboard event handler\n */\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>): void => {\n if (disabled) return;\n\n // Handle different key presses\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n handleArrowLeft();\n break;\n\n case 'ArrowRight':\n e.preventDefault();\n handleArrowRight();\n break;\n\n case 'Backspace':\n e.preventDefault();\n handleBackspace();\n break;\n\n case 'Delete':\n e.preventDefault();\n handleDelete();\n break;\n\n case 'Home':\n e.preventDefault();\n handleHome();\n break;\n\n case 'End':\n e.preventDefault();\n handleEnd();\n break;\n\n // Ctrl/Cmd+A (Select All) - Allow native behavior\n case 'a':\n case 'A':\n if (e.ctrlKey || e.metaKey) {\n // Let browser handle select all natively\n // The hidden input will select its entire value\n return;\n }\n break;\n\n // Prevent Enter from submitting the form\n // Form submission should be handled by onComplete callback when all digits are filled\n case 'Enter':\n e.preventDefault();\n break;\n\n // Allow digits and other printable characters\n // (handled by onChange in useOTPInput)\n default:\n // Don't prevent default for normal character input\n break;\n }\n },\n [\n disabled,\n handleArrowLeft,\n handleArrowRight,\n handleBackspace,\n handleDelete,\n handleHome,\n handleEnd,\n ]\n );\n\n return {\n handleKeyDown,\n };\n}\n","'use client';\n\nimport { useState, useCallback, useEffect, useRef, type ChangeEvent, type KeyboardEvent, type ClipboardEvent } from 'react';\nimport type { OTPInputProps } from '../OTPInput.types';\nimport { useOTPKeyboard } from './useOTPKeyboard';\n\n/**\n * Return type for useOTPInput hook\n */\nexport interface UseOTPInputReturn {\n value: string;\n focusedIndex: number;\n error: string | null;\n isComplete: boolean;\n handleChange: (e: ChangeEvent<HTMLInputElement>) => void;\n handleKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;\n handlePaste: (e: ClipboardEvent<HTMLInputElement>) => void;\n setFocusedIndex: (index: number) => void;\n clear: () => void;\n setValue: (value: string) => void;\n validate: () => string | null;\n}\n\n/**\n * useOTPInput Hook\n *\n * Core logic hook for OTP input management.\n * Handles state, validation, and user interactions.\n *\n * Features:\n * - Controlled and uncontrolled modes\n * - Auto-advance on digit entry\n * - Custom validation support\n * - Error state management\n * - Focus management\n *\n * @param props OTPInput component props\n * @returns State and handlers for OTP input\n */\nexport function useOTPInput(props: OTPInputProps): UseOTPInputReturn {\n const {\n value: controlledValue,\n defaultValue = '',\n length = 6,\n type = 'numeric',\n pattern,\n onChange,\n onComplete,\n validate,\n error: controlledError,\n disabled = false,\n readOnly = false,\n } = props;\n\n // Determine if component is controlled\n const isControlled = controlledValue !== undefined;\n\n // Internal state (used in uncontrolled mode)\n const [internalValue, setInternalValue] = useState<string>(() => {\n // Initialize with defaultValue padded to length with underscores\n return (defaultValue || '').padEnd(length, '_');\n });\n\n const [internalError, setInternalError] = useState<string | null>(null);\n const [focusedIndex, setFocusedIndex] = useState<number>(0);\n\n // Track if onComplete has been called for current value\n const completedRef = useRef<string | null>(null);\n \n // Debounce timer for onComplete callback\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\n\n // Current value (controlled or uncontrolled)\n const currentValue = isControlled ? controlledValue || ''.padEnd(length, '_') : internalValue;\n\n // Current error (controlled or uncontrolled)\n const currentError = controlledError !== undefined ? controlledError : internalError;\n\n // Validation function\n const runValidation = useCallback(\n (value: string): string | null => {\n // Don't validate empty or partial input\n const filledLength = value.replace(/_/g, '').length;\n if (filledLength < length) {\n return null;\n }\n\n // Run custom validation if provided\n if (validate) {\n return validate(value);\n }\n\n // Built-in validation based on type\n if (type === 'numeric') {\n const numericPattern = /^\\d+$/;\n const cleanValue = value.replace(/_/g, '');\n if (!numericPattern.test(cleanValue)) {\n return 'Code must contain only digits';\n }\n } else if (type === 'alphanumeric') {\n const alphanumericPattern = /^[A-Za-z0-9]+$/;\n const cleanValue = value.replace(/_/g, '');\n if (!alphanumericPattern.test(cleanValue)) {\n return 'Code must contain only letters and numbers';\n }\n } else if (type === 'custom' && pattern) {\n const cleanValue = value.replace(/_/g, '');\n for (const char of cleanValue) {\n if (!pattern.test(char)) {\n return 'Invalid character in code';\n }\n }\n }\n\n return null;\n },\n [length, type, pattern, validate]\n );\n\n // Update value (handles both controlled and uncontrolled)\n const updateValue = useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n\n // Run validation\n const validationError = runValidation(newValue);\n if (!isControlled) {\n setInternalError(validationError);\n }\n\n // Check if complete\n const filledLength = newValue.replace(/_/g, '').length;\n const isComplete = filledLength === length;\n\n // Trigger onComplete if:\n // 1. All digits filled\n // 2. No validation errors\n // 3. Haven't already called onComplete for this value\n if (isComplete && !validationError && completedRef.current !== newValue) {\n completedRef.current = newValue;\n \n // Debounce onComplete callback by 200ms\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(() => {\n onComplete?.(newValue.replace(/_/g, ''));\n }, 200);\n }\n\n // Reset completion tracking if value changes after completion\n if (!isComplete && completedRef.current) {\n completedRef.current = null;\n }\n },\n [isControlled, length, onChange, onComplete, runValidation]\n );\n\n // Handle digit entry\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>): void => {\n if (disabled) return;\n\n const inputValue = e.target.value;\n const newChar = inputValue[inputValue.length - 1] || '';\n\n // Validate character based on type\n let isValid = false;\n if (type === 'numeric') {\n isValid = /^\\d$/.test(newChar);\n } else if (type === 'alphanumeric') {\n isValid = /^[A-Za-z0-9]$/.test(newChar);\n } else if (type === 'custom' && pattern) {\n isValid = pattern.test(newChar);\n } else {\n isValid = true; // Default: accept any character\n }\n\n if (!isValid) {\n // Reject invalid character\n return;\n }\n\n // Update value at focused index\n const valueArray = currentValue.split('');\n valueArray[focusedIndex] = newChar;\n const newValue = valueArray.join('');\n\n updateValue(newValue);\n\n // Auto-advance to next digit if not at end\n if (focusedIndex < length - 1) {\n setFocusedIndex(focusedIndex + 1);\n }\n },\n [disabled, type, pattern, currentValue, focusedIndex, length, updateValue]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n async (e: ClipboardEvent<HTMLInputElement>): Promise<void> => {\n if (disabled || readOnly) return;\n\n e.preventDefault();\n\n // Get pasted text\n const pastedText = e.clipboardData.getData('text/plain').trim();\n if (!pastedText) return;\n\n // Call onPaste callback if provided\n if (props.onPaste) {\n const shouldProceed = await props.onPaste(pastedText);\n if (shouldProceed === false) return;\n }\n\n // Validate pasted content character by character\n let validChars = '';\n for (const char of pastedText) {\n if (validChars.length >= length) break;\n\n let isValid = false;\n if (type === 'numeric') {\n isValid = /^\\d$/.test(char);\n } else if (type === 'alphanumeric') {\n isValid = /^[A-Za-z0-9]$/.test(char);\n } else if (type === 'custom' && pattern) {\n isValid = pattern.test(char);\n } else {\n isValid = true;\n }\n\n if (isValid) {\n validChars += char;\n }\n }\n\n // Pad with underscores to fill length\n const newValue = validChars.padEnd(length, '_');\n updateValue(newValue);\n\n // Move focus to first empty position or end\n const firstEmptyIndex = newValue.indexOf('_');\n setFocusedIndex(firstEmptyIndex === -1 ? length - 1 : firstEmptyIndex);\n },\n [disabled, readOnly, props, length, type, pattern, updateValue]\n );\n\n // Clear all digits\n const clear = useCallback((): void => {\n const emptyValue = ''.padEnd(length, '_');\n updateValue(emptyValue);\n setFocusedIndex(0);\n if (!isControlled) {\n setInternalError(null);\n }\n completedRef.current = null;\n }, [length, updateValue, isControlled]);\n\n // Set value programmatically\n const setValue = useCallback(\n (newValue: string): void => {\n // Pad or truncate to length\n const paddedValue = newValue.padEnd(length, '_').slice(0, length);\n updateValue(paddedValue);\n\n // Move focus to last filled digit or first empty\n const firstEmptyIndex = paddedValue.indexOf('_');\n setFocusedIndex(firstEmptyIndex === -1 ? length - 1 : firstEmptyIndex);\n },\n [length, updateValue]\n );\n\n // Validate current value\n const validateCurrent = useCallback((): string | null => {\n return runValidation(currentValue);\n }, [currentValue, runValidation]);\n\n // Check if complete\n const isComplete = currentValue.replace(/_/g, '').length === length;\n\n // Keyboard navigation hook\n const { handleKeyDown } = useOTPKeyboard({\n value: currentValue,\n length,\n focusedIndex,\n onChange: updateValue,\n setFocusedIndex,\n disabled,\n readOnly,\n });\n\n // Sync controlled value changes\n useEffect(() => {\n if (isControlled && controlledValue !== undefined) {\n // Update focused index when controlled value changes\n const firstEmptyIndex = controlledValue.indexOf('_');\n if (firstEmptyIndex !== -1) {\n setFocusedIndex(firstEmptyIndex);\n }\n }\n }, [isControlled, controlledValue]);\n\n // Cleanup debounce timer on unmount\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, []);\n\n return {\n value: currentValue,\n focusedIndex,\n error: currentError,\n isComplete,\n handleChange,\n handleKeyDown,\n handlePaste,\n setFocusedIndex,\n clear,\n setValue,\n validate: validateCurrent,\n };\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\n\n/**\n * OTP Digit Box Variants\n *\n * Styling for individual digit display boxes using ShadCN CSS variables.\n * Ensures WCAG 2.2 AAA compliance (7:1 contrast, 44x44px touch targets).\n *\n * CSS Variables used (from ShadCN):\n * - --background: Base background color\n * - --foreground: Text color\n * - --border: Border color\n * - --primary: Primary brand color (focus state)\n * - --ring: Focus ring color\n * - --destructive: Error state color\n * - --destructive-foreground: Error text color\n * - --success: Success state color (if available)\n * - --muted: Muted background color\n * - --muted-foreground: Placeholder/disabled text color\n */\nexport const otpDigitVariants = cva(\n // Base styles - Applied to all variants\n [\n 'inline-flex',\n 'items-center',\n 'justify-center',\n 'rounded-md',\n 'border-2',\n 'font-semibold',\n 'transition-all',\n 'duration-200',\n 'ease-in-out',\n 'select-none',\n 'tabindex-[-1]', // Not tabbable (hidden input handles focus)\n ],\n {\n variants: {\n /**\n * Size Variants\n * All sizes meet WCAG AAA touch target minimum (44x44px)\n */\n size: {\n /**\n * Small: 40×40px base + 4px padding = 44×44px touch target\n * Font: 16px (base size)\n * Use case: Compact layouts, mobile optimization\n */\n sm: [\n 'h-10', // 40px\n 'w-10', // 40px\n 'text-base', // 16px\n 'p-1', // 4px padding for touch target\n ],\n\n /**\n * Medium (default): 48×56px\n * Font: 20px (comfortable reading size)\n * Use case: Standard desktop/mobile layouts\n */\n md: [\n 'h-14', // 56px\n 'w-10 sm:w-12 md:w-14', // 48px\n 'text-xl', // 20px\n ],\n\n /**\n * Large: 56×64px\n * Font: 24px (large reading size)\n * Use case: Accessibility focus, high-visibility needs\n */\n lg: [\n 'h-16', // 64px\n 'w-10 sm:w-12 md:w-16', // 56px\n 'text-2xl', // 24px\n ],\n },\n\n /**\n * State Variants\n * All states meet WCAG AAA contrast (7:1 minimum)\n */\n state: {\n /**\n * Default: Standard input appearance\n * Border: --border\n * Background: --background\n * Text: --foreground\n */\n default: [\n 'border-[var(--input)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'hover:border-[var(--input-hover)]',\n ],\n\n /**\n * Focus: Active digit being edited\n * Border: --primary\n * Ring: --ring (2px, 2px offset)\n * Contrast: 7:1 minimum\n */\n focus: [\n 'border-[var(--input)]',\n 'ring-2',\n 'ring-[var(--primary)]',\n 'ring-offset-2',\n 'ring-offset-background',\n 'outline-none',\n ],\n\n /**\n * Filled: Digit has been entered\n * Border: --primary with 50% opacity\n * Text: Bold weight for emphasis\n */\n filled: [\n 'border-[var(--primary)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'font-bold',\n ],\n\n /**\n * Error: Validation failed\n * Border: --destructive\n * Background: --destructive with 10% opacity\n * Text: --destructive-foreground\n * Animation: Shake on error\n */\n error: [\n 'border-[var(--destructive)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--destructive-foreground)]',\n 'animate-shake',\n ],\n\n /**\n * Success: Validation passed (optional)\n * Border: Green (or --success if available)\n * Background: Green with 10% opacity\n * May include checkmark icon\n */\n success: [\n 'border-green-600',\n 'bg-green-50',\n 'text-green-900',\n 'dark:border-green-500',\n 'dark:bg-green-900/20',\n 'dark:text-green-100',\n ],\n\n /**\n * Disabled: Input not interactive\n * Border: --border with 50% opacity\n * Background: --muted with 50% opacity\n * Text: --muted-foreground\n * Cursor: not-allowed\n * Opacity: 60%\n * Contrast: 4.5:1 minimum (AA standard for disabled)\n */\n disabled: [\n 'border-[var(--accent-background)]',\n 'bg-[var(--accent-background)]',\n 'text-[var(--menu-muted)]',\n 'cursor-not-allowed',\n 'opacity-60',\n 'hover:border-[var(--accent-background)]', // Prevent hover effect\n ],\n },\n },\n defaultVariants: {\n size: 'md',\n state: 'default',\n },\n }\n);\n\n/**\n * OTP Container Variants\n *\n * Styling for the main container that holds all digit boxes\n */\nexport const otpContainerVariants = cva(\n [\n 'inline-flex',\n 'flex-col',\n 'gap-2',\n ],\n {\n variants: {\n /**\n * Container size variants\n * Affects spacing and layout\n */\n size: {\n sm: ['gap-1.5'],\n md: ['gap-2'],\n lg: ['gap-3'],\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\n/**\n * OTP Digit Group Variants\n *\n * Styling for the row of digit boxes\n */\nexport const otpDigitGroupVariants = cva(\n [\n 'flex',\n 'items-center',\n ],\n {\n variants: {\n /**\n * Gap between digits\n */\n size: {\n sm: ['gap-1.5'], // 6px\n md: ['gap-2'], // 8px\n lg: ['gap-3'], // 12px\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\n/**\n * OTP Error Message Variants\n *\n * Styling for error messages displayed below input\n */\nexport const otpErrorVariants = cva([\n 'text-sm',\n 'font-medium',\n 'text-[var(--destructive)]',\n 'mt-1.5',\n 'text-center',\n]);\n\n/**\n * OTP Description Variants\n *\n * Styling for description/help text\n */\nexport const otpDescriptionVariants = cva([\n 'text-sm',\n 'text-[var(--menu-muted)]',\n 'mt-1',\n]);\n\n/**\n * Type export for variant props\n * Allows TypeScript inference of variant combinations\n */\nexport type OTPDigitVariantProps = VariantProps<typeof otpDigitVariants>;\nexport type OTPContainerVariantProps = VariantProps<typeof otpContainerVariants>;\nexport type OTPDigitGroupVariantProps = VariantProps<typeof otpDigitGroupVariants>;\n\n/**\n * Animation: Shake effect for errors\n *\n * Add this to tailwind.config.ts animations:\n *\n * ```ts\n * module.exports = {\n * theme: {\n * extend: {\n * keyframes: {\n * shake: {\n * '0%, 100%': { transform: 'translateX(0)' },\n * '25%': { transform: 'translateX(-8px)' },\n * '75%': { transform: 'translateX(8px)' },\n * },\n * },\n * animation: {\n * shake: 'shake 200ms ease-in-out',\n * },\n * },\n * },\n * };\n * ```\n */\n","import { memo, type ReactElement } from 'react';\nimport { cn } from '../../../utils/cn';\nimport { otpDigitVariants, type OTPDigitVariantProps } from '../OTPInput.styles';\n\n/**\n * Props for the OTPDigit component\n */\nexport interface OTPDigitProps {\n /**\n * Single character value or underscore for empty\n * @example \"1\" | \"A\" | \"_\"\n */\n value: string;\n\n /**\n * Whether this digit is currently focused\n * Determines visual focus indicator display\n */\n focused: boolean;\n\n /**\n * Size variant\n * @default 'md'\n */\n size?: OTPDigitVariantProps['size'];\n\n /**\n * State variant\n * Determines visual styling (default, focus, error, success, disabled)\n */\n state?: OTPDigitVariantProps['state'];\n\n /**\n * Mask the digit (show as bullet point)\n * Useful for sensitive codes\n * @default false\n */\n masked?: boolean;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n\n /**\n * Index of this digit (for debugging)\n */\n index?: number;\n}\n\n/**\n * OTPDigit Component\n *\n * Displays a single digit of the OTP input with visual styling.\n * This is a presentational component - it does not handle input logic.\n *\n * Features:\n * - Memoized for performance (prevents unnecessary re-renders)\n * - WCAG AAA compliant (7:1 contrast, 44x44px touch targets)\n * - Supports masking for sensitive codes\n * - Visual focus indicators\n * - State-based styling (error, success, disabled)\n *\n * @example\n * ```tsx\n * <OTPDigit\n * value=\"5\"\n * focused={true}\n * size=\"md\"\n * state=\"focus\"\n * />\n * ```\n */\nconst OTPDigitComponent = ({\n value,\n focused,\n size = 'md',\n state = 'default',\n masked = false,\n className,\n index,\n}: OTPDigitProps): ReactElement => {\n // Determine if digit is filled\n const isFilled = value !== '_' && value !== '';\n\n // Determine state based on props\n const computedState = focused && !state ? 'focus' : isFilled && state === 'default' ? 'filled' : state;\n\n // Display value (masked or actual)\n const displayValue = masked && isFilled ? '•' : value === '_' ? '' : value;\n\n return (\n <div\n className={cn(\n otpDigitVariants({ size, state: computedState }),\n className\n )}\n role=\"presentation\"\n aria-hidden=\"true\"\n data-focused={focused}\n data-filled={isFilled}\n data-index={index}\n >\n {displayValue || (\n <span className=\"text-[var(--menu-muted)] opacity-40\">\n •\n </span>\n )}\n </div>\n );\n};\n\n/**\n * Memoized OTPDigit Component\n *\n * Prevents re-renders when other digits change.\n * Only re-renders when its own props change.\n *\n * Performance optimization for components with 6-10 digits.\n */\nexport const OTPDigit = memo(OTPDigitComponent);\n\nOTPDigit.displayName = 'OTPDigit';\n","'use client';\n\nimport { forwardRef, useImperativeHandle, useRef, type FocusEvent, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport { type OTPInputProps, type OTPInputRef } from './OTPInput.types';\nimport { useOTPInput } from './hooks/useOTPInput';\nimport { OTPDigit } from './components/OTPDigit';\nimport {\n otpContainerVariants,\n otpDigitGroupVariants,\n otpErrorVariants,\n otpDescriptionVariants,\n} from './OTPInput.styles';\n\n/**\n * OTPInput Component\n *\n * A fully accessible, WCAG 2.2 AAA-compliant OTP (One-Time Password) input component.\n *\n * Key Features:\n * - Single hidden input for screen readers (not multiple separate inputs)\n * - Visual digit boxes for optimal UX\n * - WCAG 2.2 AAA compliant (7:1 contrast, 44x44px touch targets)\n * - Auto-advance on digit entry\n * - Paste support with validation\n * - Controlled and uncontrolled modes\n * - Custom validation\n * - React Hook Form compatible\n *\n * Accessibility:\n * - Single tab stop (entire OTP is one field)\n * - Proper ARIA attributes (label, describedby, invalid, errormessage)\n * - Screen reader announcements for digit count and errors\n * - Visible focus indicators (7:1 contrast)\n * - Keyboard navigation (arrows, home, end, backspace, delete)\n *\n * @example Basic usage\n * ```tsx\n * <OTPInput\n * label=\"Enter verification code\"\n * length={6}\n * onChange={(value) => console.log(value)}\n * onComplete={(code) => console.log('Complete:', code)}\n * />\n * ```\n *\n * @example Controlled mode with validation\n * ```tsx\n * const [otp, setOtp] = useState('');\n * const [error, setError] = useState('');\n *\n * <OTPInput\n * label=\"Enter 6-digit code sent to your email\"\n * value={otp}\n * onChange={setOtp}\n * error={error}\n * validate={(value) => {\n * if (value === '000000') return 'Invalid code';\n * return null;\n * }}\n * />\n * ```\n *\n * @example With ref API\n * ```tsx\n * const otpRef = useRef<OTPInputRef>(null);\n *\n * <OTPInput\n * ref={otpRef}\n * label=\"Enter verification code\"\n * />\n *\n * // Programmatic control\n * otpRef.current?.clear();\n * otpRef.current?.setValue('123456');\n * ```\n */\nexport const OTPInput = forwardRef<OTPInputRef, OTPInputProps>((props, ref) => {\n // Validate serializable props with Zod schema (skip function validation)\n // Functions are type-checked by TypeScript, not runtime-validated\n const {\n label,\n description,\n size = 'md',\n disabled = false,\n readOnly = false,\n mask = false,\n showSuccess = false,\n className,\n digitClassName,\n onFocus,\n onBlur,\n inputMode = 'numeric',\n length = 6,\n } = props;\n\n // Main logic hook\n const {\n value,\n focusedIndex,\n error,\n isComplete,\n handleChange,\n handleKeyDown,\n handlePaste,\n setFocusedIndex,\n clear,\n setValue,\n validate,\n } = useOTPInput(props);\n\n // Ref to the hidden input element\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Expose imperative API via ref\n useImperativeHandle(ref, (): OTPInputRef => ({\n focus: (): void => inputRef.current?.focus(),\n blur: (): void => inputRef.current?.blur(),\n clear,\n setValue,\n getValue: (): string => value.replace(/_/g, ''),\n isComplete: (): boolean => isComplete,\n validate,\n getElement: (): HTMLInputElement | null => inputRef.current,\n }));\n\n // Split value into individual digits\n const digits = value.split('');\n\n // Determine state for digit styling\n const getDigitState = (index: number): 'default' | 'focus' | 'filled' | 'error' | 'success' | 'disabled' => {\n if (disabled) return 'disabled';\n if (error) return 'error';\n if (showSuccess && isComplete && !error) return 'success';\n if (index === focusedIndex) return 'focus';\n if (digits[index] !== '_') return 'filled';\n return 'default';\n };\n\n // Handle focus events\n const handleFocusEvent = (e: FocusEvent<HTMLInputElement>): void => {\n onFocus?.(e);\n };\n\n const handleBlurEvent = (e: FocusEvent<HTMLInputElement>): void => {\n onBlur?.(e);\n };\n\n // Handle click/keyboard on digit boxes (focus hidden input)\n const handleDigitClick = (index: number): void => {\n if (disabled || readOnly) return;\n setFocusedIndex(index);\n inputRef.current?.focus();\n };\n\n const handleDigitKeyDown = (e: KeyboardEvent, index: number): void => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleDigitClick(index);\n }\n };\n\n // Generate IDs for ARIA\n const descriptionId = description ? `otp-description-${Math.random().toString(36).slice(2, 9)}` : undefined;\n const errorId = error ? `otp-error-${Math.random().toString(36).slice(2, 9)}` : undefined;\n\n return (\n <div className={cn(otpContainerVariants({ size }), className)}>\n {/* Hidden accessible input */}\n <input\n ref={inputRef}\n type=\"text\"\n inputMode={inputMode}\n value={value.replace(/_/g, '')}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onFocus={handleFocusEvent}\n onBlur={handleBlurEvent}\n disabled={disabled}\n readOnly={readOnly}\n aria-label={label}\n aria-describedby={[descriptionId, errorId].filter(Boolean).join(' ')}\n aria-invalid={!!error}\n aria-errormessage={errorId}\n className=\"sr-only\"\n autoComplete=\"one-time-code\"\n maxLength={length}\n />\n\n {/* Visual digit display */}\n <div\n className={cn(otpDigitGroupVariants({ size }))}\n role=\"presentation\"\n aria-hidden=\"true\"\n >\n {digits.map((digit, index) => (\n <div\n key={index}\n onClick={() => handleDigitClick(index)}\n onKeyDown={(e) => handleDigitKeyDown(e, index)}\n role=\"button\"\n tabIndex={-1}\n className=\"cursor-text\"\n >\n <OTPDigit\n value={digit}\n focused={index === focusedIndex}\n size={size}\n state={getDigitState(index)}\n masked={mask}\n className={digitClassName}\n index={index}\n />\n </div>\n ))}\n </div>\n\n {/* Description text */}\n {description && (\n <p id={descriptionId} className={otpDescriptionVariants()}>\n {description}\n </p>\n )}\n\n {/* Error message */}\n {error && (\n <p\n id={errorId}\n className={otpErrorVariants()}\n role=\"alert\"\n aria-live=\"assertive\"\n >\n {error}\n </p>\n )}\n\n {/* Screen reader live region for digit count */}\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"sr-only\"\n >\n {!isComplete && !error && (\n <>\n {value.replace(/_/g, '').length} of {length} digits entered\n </>\n )}\n {isComplete && !error && <>Verification code complete</>}\n </div>\n </div>\n );\n});\n\nOTPInput.displayName = 'OTPInput';\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/OTPInput/hooks/useOTPKeyboard.ts","../../../src/elements/OTPInput/hooks/useOTPInput.ts","../../../src/elements/OTPInput/OTPInput.styles.ts","../../../src/elements/OTPInput/components/OTPDigit.tsx","../../../src/elements/OTPInput/OTPInput.tsx"],"names":["cn","inputs","twMerge","clsx","useOTPKeyboard","options","value","length","focusedIndex","onChange","setFocusedIndex","disabled","readOnly","handleArrowLeft","useCallback","handleArrowRight","handleBackspace","digits","newIndex","handleDelete","handleHome","handleEnd","e","useOTPInput","props","controlledValue","defaultValue","type","pattern","onComplete","validate","controlledError","isControlled","internalValue","setInternalValue","useState","internalError","setInternalError","completedRef","useRef","debounceTimerRef","currentValue","currentError","runValidation","numericPattern","cleanValue","alphanumericPattern","char","updateValue","newValue","validationError","isComplete","handleChange","inputValue","newChar","isValid","valueArray","handlePaste","pastedText","validChars","firstEmptyIndex","clear","emptyValue","setValue","paddedValue","validateCurrent","handleKeyDown","useEffect","otpDigitVariants","cva","otpContainerVariants","otpDigitGroupVariants","otpErrorVariants","otpDescriptionVariants","OTPDigitComponent","focused","size","state","masked","className","index","isFilled","computedState","displayValue","jsx","OTPDigit","memo","OTPInput","forwardRef","ref","label","description","mask","showSuccess","digitClassName","onFocus","onBlur","inputMode","error","inputRef","useImperativeHandle","getDigitState","handleFocusEvent","handleBlurEvent","handleDigitClick","handleDigitKeyDown","baseId","useId","descriptionId","errorId","jsxs","digit","Fragment"],"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","import { useCallback, type KeyboardEvent } from 'react';\n\n/**\n * Options for useOTPKeyboard hook\n */\nexport interface UseOTPKeyboardOptions {\n /**\n * Current OTP value (string with underscores for empty)\n */\n value: string;\n\n /**\n * Total number of digits\n */\n length: number;\n\n /**\n * Currently focused digit index\n */\n focusedIndex: number;\n\n /**\n * Callback to update OTP value\n */\n onChange: (value: string) => void;\n\n /**\n * Callback to update focused index\n */\n setFocusedIndex: (index: number) => void;\n\n /**\n * Whether the input is disabled\n */\n disabled?: boolean;\n\n /**\n * Whether the input is read-only\n */\n readOnly?: boolean;\n}\n\n/**\n * Return type for useOTPKeyboard hook\n */\nexport interface UseOTPKeyboardReturn {\n /**\n * Keyboard event handler\n */\n handleKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;\n}\n\n/**\n * useOTPKeyboard Hook\n *\n * Handles keyboard navigation for OTP input:\n * - Arrow Left/Right: Navigate between digits\n * - Backspace: Delete current digit and move left\n * - Delete: Clear current digit\n * - Home: Move to first digit\n * - End: Move to last digit\n * - Ctrl/Cmd+A: Select all (native browser behavior)\n *\n * @param options Configuration options\n * @returns Keyboard event handler\n */\nexport function useOTPKeyboard(options: UseOTPKeyboardOptions): UseOTPKeyboardReturn {\n const {\n value,\n length,\n focusedIndex,\n onChange,\n setFocusedIndex,\n disabled = false,\n readOnly = false,\n } = options;\n\n /**\n * Handle Arrow Left - Move to previous digit\n */\n const handleArrowLeft = useCallback((): void => {\n if (focusedIndex > 0) {\n setFocusedIndex(focusedIndex - 1);\n }\n }, [focusedIndex, setFocusedIndex]);\n\n /**\n * Handle Arrow Right - Move to next digit\n */\n const handleArrowRight = useCallback((): void => {\n if (focusedIndex < length - 1) {\n setFocusedIndex(focusedIndex + 1);\n }\n }, [focusedIndex, length, setFocusedIndex]);\n\n /**\n * Handle Backspace - Delete current digit and move left\n */\n const handleBackspace = useCallback((): void => {\n if (readOnly) return;\n\n const digits = value.split('');\n const currentDigit = digits[focusedIndex];\n\n // If current digit is empty, move to previous digit\n if (currentDigit === '_') {\n if (focusedIndex > 0) {\n // Move left and clear that digit\n const newIndex = focusedIndex - 1;\n digits[newIndex] = '_';\n onChange(digits.join(''));\n setFocusedIndex(newIndex);\n }\n } else {\n // Clear current digit\n digits[focusedIndex] = '_';\n onChange(digits.join(''));\n // Move to previous digit if not at start\n if (focusedIndex > 0) {\n setFocusedIndex(focusedIndex - 1);\n }\n }\n }, [value, focusedIndex, readOnly, onChange, setFocusedIndex]);\n\n /**\n * Handle Delete - Clear current digit (stay in place)\n */\n const handleDelete = useCallback((): void => {\n if (readOnly) return;\n\n const digits = value.split('');\n digits[focusedIndex] = '_';\n onChange(digits.join(''));\n // Stay on current digit (don't move)\n }, [value, focusedIndex, readOnly, onChange]);\n\n /**\n * Handle Home - Move to first digit\n */\n const handleHome = useCallback((): void => {\n setFocusedIndex(0);\n }, [setFocusedIndex]);\n\n /**\n * Handle End - Move to last digit\n */\n const handleEnd = useCallback((): void => {\n setFocusedIndex(length - 1);\n }, [length, setFocusedIndex]);\n\n /**\n * Main keyboard event handler\n */\n const handleKeyDown = useCallback(\n (e: KeyboardEvent<HTMLInputElement>): void => {\n if (disabled) return;\n\n // Handle different key presses\n switch (e.key) {\n case 'ArrowLeft':\n e.preventDefault();\n handleArrowLeft();\n break;\n\n case 'ArrowRight':\n e.preventDefault();\n handleArrowRight();\n break;\n\n case 'Backspace':\n e.preventDefault();\n handleBackspace();\n break;\n\n case 'Delete':\n e.preventDefault();\n handleDelete();\n break;\n\n case 'Home':\n e.preventDefault();\n handleHome();\n break;\n\n case 'End':\n e.preventDefault();\n handleEnd();\n break;\n\n // Ctrl/Cmd+A (Select All) - Allow native behavior\n case 'a':\n case 'A':\n if (e.ctrlKey || e.metaKey) {\n // Let browser handle select all natively\n // The hidden input will select its entire value\n return;\n }\n break;\n\n // Prevent Enter from submitting the form\n // Form submission should be handled by onComplete callback when all digits are filled\n case 'Enter':\n e.preventDefault();\n break;\n\n // Allow digits and other printable characters\n // (handled by onChange in useOTPInput)\n default:\n // Don't prevent default for normal character input\n break;\n }\n },\n [\n disabled,\n handleArrowLeft,\n handleArrowRight,\n handleBackspace,\n handleDelete,\n handleHome,\n handleEnd,\n ]\n );\n\n return {\n handleKeyDown,\n };\n}\n","'use client';\n\nimport { useState, useCallback, useEffect, useRef, type ChangeEvent, type KeyboardEvent, type ClipboardEvent } from 'react';\nimport type { OTPInputProps } from '../OTPInput.types';\nimport { useOTPKeyboard } from './useOTPKeyboard';\n\n/**\n * Return type for useOTPInput hook\n */\nexport interface UseOTPInputReturn {\n value: string;\n focusedIndex: number;\n error: string | null;\n isComplete: boolean;\n handleChange: (e: ChangeEvent<HTMLInputElement>) => void;\n handleKeyDown: (e: KeyboardEvent<HTMLInputElement>) => void;\n handlePaste: (e: ClipboardEvent<HTMLInputElement>) => void;\n setFocusedIndex: (index: number) => void;\n clear: () => void;\n setValue: (value: string) => void;\n validate: () => string | null;\n}\n\n/**\n * useOTPInput Hook\n *\n * Core logic hook for OTP input management.\n * Handles state, validation, and user interactions.\n *\n * Features:\n * - Controlled and uncontrolled modes\n * - Auto-advance on digit entry\n * - Custom validation support\n * - Error state management\n * - Focus management\n *\n * @param props OTPInput component props\n * @returns State and handlers for OTP input\n */\nexport function useOTPInput(props: OTPInputProps): UseOTPInputReturn {\n const {\n value: controlledValue,\n defaultValue = '',\n length = 6,\n type = 'numeric',\n pattern,\n onChange,\n onComplete,\n validate,\n error: controlledError,\n disabled = false,\n readOnly = false,\n } = props;\n\n // Determine if component is controlled\n const isControlled = controlledValue !== undefined;\n\n // Internal state (used in uncontrolled mode)\n const [internalValue, setInternalValue] = useState<string>(() => {\n // Initialize with defaultValue padded to length with underscores\n return (defaultValue || '').padEnd(length, '_');\n });\n\n const [internalError, setInternalError] = useState<string | null>(null);\n const [focusedIndex, setFocusedIndex] = useState<number>(0);\n\n // Track if onComplete has been called for current value\n const completedRef = useRef<string | null>(null);\n \n // Debounce timer for onComplete callback\n const debounceTimerRef = useRef<NodeJS.Timeout | null>(null);\n\n // Current value (controlled or uncontrolled)\n const currentValue = isControlled ? controlledValue || ''.padEnd(length, '_') : internalValue;\n\n // Current error (controlled or uncontrolled)\n const currentError = controlledError !== undefined ? controlledError : internalError;\n\n // Validation function\n const runValidation = useCallback(\n (value: string): string | null => {\n // Don't validate empty or partial input\n const filledLength = value.replace(/_/g, '').length;\n if (filledLength < length) {\n return null;\n }\n\n // Run custom validation if provided\n if (validate) {\n return validate(value);\n }\n\n // Built-in validation based on type\n if (type === 'numeric') {\n const numericPattern = /^\\d+$/;\n const cleanValue = value.replace(/_/g, '');\n if (!numericPattern.test(cleanValue)) {\n return 'Code must contain only digits';\n }\n } else if (type === 'alphanumeric') {\n const alphanumericPattern = /^[A-Za-z0-9]+$/;\n const cleanValue = value.replace(/_/g, '');\n if (!alphanumericPattern.test(cleanValue)) {\n return 'Code must contain only letters and numbers';\n }\n } else if (type === 'custom' && pattern) {\n const cleanValue = value.replace(/_/g, '');\n for (const char of cleanValue) {\n if (!pattern.test(char)) {\n return 'Invalid character in code';\n }\n }\n }\n\n return null;\n },\n [length, type, pattern, validate]\n );\n\n // Update value (handles both controlled and uncontrolled)\n const updateValue = useCallback(\n (newValue: string) => {\n if (!isControlled) {\n setInternalValue(newValue);\n }\n onChange?.(newValue);\n\n // Run validation\n const validationError = runValidation(newValue);\n if (!isControlled) {\n setInternalError(validationError);\n }\n\n // Check if complete\n const filledLength = newValue.replace(/_/g, '').length;\n const isComplete = filledLength === length;\n\n // Trigger onComplete if:\n // 1. All digits filled\n // 2. No validation errors\n // 3. Haven't already called onComplete for this value\n if (isComplete && !validationError && completedRef.current !== newValue) {\n completedRef.current = newValue;\n \n // Debounce onComplete callback by 200ms\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n debounceTimerRef.current = setTimeout(() => {\n onComplete?.(newValue.replace(/_/g, ''));\n }, 200);\n }\n\n // Reset completion tracking if value changes after completion\n if (!isComplete && completedRef.current) {\n completedRef.current = null;\n }\n },\n [isControlled, length, onChange, onComplete, runValidation]\n );\n\n // Handle digit entry\n const handleChange = useCallback(\n (e: ChangeEvent<HTMLInputElement>): void => {\n if (disabled) return;\n\n const inputValue = e.target.value;\n const newChar = inputValue[inputValue.length - 1] || '';\n\n // Validate character based on type\n let isValid = false;\n if (type === 'numeric') {\n isValid = /^\\d$/.test(newChar);\n } else if (type === 'alphanumeric') {\n isValid = /^[A-Za-z0-9]$/.test(newChar);\n } else if (type === 'custom' && pattern) {\n isValid = pattern.test(newChar);\n } else {\n isValid = true; // Default: accept any character\n }\n\n if (!isValid) {\n // Reject invalid character\n return;\n }\n\n // Update value at focused index\n const valueArray = currentValue.split('');\n valueArray[focusedIndex] = newChar;\n const newValue = valueArray.join('');\n\n updateValue(newValue);\n\n // Auto-advance to next digit if not at end\n if (focusedIndex < length - 1) {\n setFocusedIndex(focusedIndex + 1);\n }\n },\n [disabled, type, pattern, currentValue, focusedIndex, length, updateValue]\n );\n\n // Handle paste\n const handlePaste = useCallback(\n async (e: ClipboardEvent<HTMLInputElement>): Promise<void> => {\n if (disabled || readOnly) return;\n\n e.preventDefault();\n\n // Get pasted text\n const pastedText = e.clipboardData.getData('text/plain').trim();\n if (!pastedText) return;\n\n // Call onPaste callback if provided\n if (props.onPaste) {\n const shouldProceed = await props.onPaste(pastedText);\n if (shouldProceed === false) return;\n }\n\n // Validate pasted content character by character\n let validChars = '';\n for (const char of pastedText) {\n if (validChars.length >= length) break;\n\n let isValid = false;\n if (type === 'numeric') {\n isValid = /^\\d$/.test(char);\n } else if (type === 'alphanumeric') {\n isValid = /^[A-Za-z0-9]$/.test(char);\n } else if (type === 'custom' && pattern) {\n isValid = pattern.test(char);\n } else {\n isValid = true;\n }\n\n if (isValid) {\n validChars += char;\n }\n }\n\n // Pad with underscores to fill length\n const newValue = validChars.padEnd(length, '_');\n updateValue(newValue);\n\n // Move focus to first empty position or end\n const firstEmptyIndex = newValue.indexOf('_');\n setFocusedIndex(firstEmptyIndex === -1 ? length - 1 : firstEmptyIndex);\n },\n [disabled, readOnly, props, length, type, pattern, updateValue]\n );\n\n // Clear all digits\n const clear = useCallback((): void => {\n const emptyValue = ''.padEnd(length, '_');\n updateValue(emptyValue);\n setFocusedIndex(0);\n if (!isControlled) {\n setInternalError(null);\n }\n completedRef.current = null;\n }, [length, updateValue, isControlled]);\n\n // Set value programmatically\n const setValue = useCallback(\n (newValue: string): void => {\n // Pad or truncate to length\n const paddedValue = newValue.padEnd(length, '_').slice(0, length);\n updateValue(paddedValue);\n\n // Move focus to last filled digit or first empty\n const firstEmptyIndex = paddedValue.indexOf('_');\n setFocusedIndex(firstEmptyIndex === -1 ? length - 1 : firstEmptyIndex);\n },\n [length, updateValue]\n );\n\n // Validate current value\n const validateCurrent = useCallback((): string | null => {\n return runValidation(currentValue);\n }, [currentValue, runValidation]);\n\n // Check if complete\n const isComplete = currentValue.replace(/_/g, '').length === length;\n\n // Keyboard navigation hook\n const { handleKeyDown } = useOTPKeyboard({\n value: currentValue,\n length,\n focusedIndex,\n onChange: updateValue,\n setFocusedIndex,\n disabled,\n readOnly,\n });\n\n // Sync controlled value changes\n useEffect(() => {\n if (isControlled && controlledValue !== undefined) {\n // Update focused index when controlled value changes\n const firstEmptyIndex = controlledValue.indexOf('_');\n if (firstEmptyIndex !== -1) {\n setFocusedIndex(firstEmptyIndex);\n }\n }\n }, [isControlled, controlledValue]);\n\n // Cleanup debounce timer on unmount\n useEffect(() => {\n return () => {\n if (debounceTimerRef.current) {\n clearTimeout(debounceTimerRef.current);\n }\n };\n }, []);\n\n return {\n value: currentValue,\n focusedIndex,\n error: currentError,\n isComplete,\n handleChange,\n handleKeyDown,\n handlePaste,\n setFocusedIndex,\n clear,\n setValue,\n validate: validateCurrent,\n };\n}\n","import { cva, type VariantProps } from 'class-variance-authority';\n\n/**\n * OTP Digit Box Variants\n *\n * Styling for individual digit display boxes using ShadCN CSS variables.\n * Ensures WCAG 2.2 AAA compliance (7:1 contrast, 44x44px touch targets).\n *\n * CSS Variables used (from ShadCN):\n * - --background: Base background color\n * - --foreground: Text color\n * - --border: Border color\n * - --primary: Primary brand color (focus state)\n * - --ring: Focus ring color\n * - --destructive: Error state color\n * - --destructive-foreground: Error text color\n * - --success: Success state color (if available)\n * - --muted: Muted background color\n * - --muted-foreground: Placeholder/disabled text color\n */\nexport const otpDigitVariants = cva(\n // Base styles - Applied to all variants\n [\n 'inline-flex',\n 'items-center',\n 'justify-center',\n 'rounded-md',\n 'border-2',\n 'font-semibold',\n 'transition-all',\n 'duration-200',\n 'ease-in-out',\n 'select-none',\n 'tabindex-[-1]', // Not tabbable (hidden input handles focus)\n ],\n {\n variants: {\n /**\n * Size Variants\n * All sizes meet WCAG AAA touch target minimum (44x44px)\n */\n size: {\n /**\n * Small: 40×40px base + 4px padding = 44×44px touch target\n * Font: 16px (base size)\n * Use case: Compact layouts, mobile optimization\n */\n sm: [\n 'h-10', // 40px\n 'w-10', // 40px\n 'text-base', // 16px\n 'p-1', // 4px padding for touch target\n ],\n\n /**\n * Medium (default): 48×56px\n * Font: 20px (comfortable reading size)\n * Use case: Standard desktop/mobile layouts\n */\n md: [\n 'h-14', // 56px\n 'w-10 sm:w-12 md:w-14', // 48px\n 'text-xl', // 20px\n ],\n\n /**\n * Large: 56×64px\n * Font: 24px (large reading size)\n * Use case: Accessibility focus, high-visibility needs\n */\n lg: [\n 'h-16', // 64px\n 'w-10 sm:w-12 md:w-16', // 56px\n 'text-2xl', // 24px\n ],\n },\n\n /**\n * State Variants\n * All states meet WCAG AAA contrast (7:1 minimum)\n */\n state: {\n /**\n * Default: Standard input appearance\n * Border: --border\n * Background: --background\n * Text: --foreground\n */\n default: [\n 'border-[var(--input-border)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'hover:border-[var(--input-border)]/80',\n ],\n\n /**\n * Focus: Active digit being edited\n * Border: --primary\n * Ring: --ring (2px, 2px offset)\n * Contrast: 7:1 minimum\n */\n focus: [\n 'border-[var(--input-border)]',\n 'ring-2',\n 'ring-[var(--primary)]',\n 'ring-offset-2',\n 'ring-offset-background',\n 'outline-none',\n ],\n\n /**\n * Filled: Digit has been entered\n * Border: --primary with 50% opacity\n * Text: Bold weight for emphasis\n */\n filled: [\n 'border-[var(--primary)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--content-foreground)]',\n 'font-bold',\n ],\n\n /**\n * Error: Validation failed\n * Border: --destructive\n * Background: --destructive with 10% opacity\n * Text: --destructive-foreground\n * Animation: Shake on error\n */\n error: [\n 'border-[var(--destructive-background)]',\n 'bg-[var(--content-background)]',\n 'text-[var(--destructive-foreground)]',\n 'animate-shake',\n ],\n\n /**\n * Success: Validation passed (optional)\n * Border: Green (or --success if available)\n * Background: Green with 10% opacity\n * May include checkmark icon\n */\n success: [\n 'border-green-600',\n 'bg-green-50',\n 'text-green-900',\n 'dark:border-green-500',\n 'dark:bg-green-900/20',\n 'dark:text-green-100',\n ],\n\n /**\n * Disabled: Input not interactive\n * Border: --border with 50% opacity\n * Background: --muted with 50% opacity\n * Text: --muted-foreground\n * Cursor: not-allowed\n * Opacity: 60%\n * Contrast: 4.5:1 minimum (AA standard for disabled)\n */\n disabled: [\n 'border-[var(--accent-background)]',\n 'bg-[var(--accent-background)]',\n 'text-[var(--menu-muted)]',\n 'cursor-not-allowed',\n 'opacity-60',\n 'hover:border-[var(--accent-background)]', // Prevent hover effect\n ],\n },\n },\n defaultVariants: {\n size: 'md',\n state: 'default',\n },\n }\n);\n\n/**\n * OTP Container Variants\n *\n * Styling for the main container that holds all digit boxes\n */\nexport const otpContainerVariants = cva(\n [\n 'inline-flex',\n 'flex-col',\n 'gap-2',\n ],\n {\n variants: {\n /**\n * Container size variants\n * Affects spacing and layout\n */\n size: {\n sm: ['gap-1.5'],\n md: ['gap-2'],\n lg: ['gap-3'],\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\n/**\n * OTP Digit Group Variants\n *\n * Styling for the row of digit boxes\n */\nexport const otpDigitGroupVariants = cva(\n [\n 'flex',\n 'items-center',\n ],\n {\n variants: {\n /**\n * Gap between digits\n */\n size: {\n sm: ['gap-1.5'], // 6px\n md: ['gap-2'], // 8px\n lg: ['gap-3'], // 12px\n },\n },\n defaultVariants: {\n size: 'md',\n },\n }\n);\n\n/**\n * OTP Error Message Variants\n *\n * Styling for error messages displayed below input\n */\nexport const otpErrorVariants = cva([\n 'text-sm',\n 'font-medium',\n 'text-[var(--destructive-background)]',\n 'mt-1.5',\n 'text-center',\n]);\n\n/**\n * OTP Description Variants\n *\n * Styling for description/help text\n */\nexport const otpDescriptionVariants = cva([\n 'text-sm',\n 'text-[var(--menu-muted)]',\n 'mt-1',\n]);\n\n/**\n * Type export for variant props\n * Allows TypeScript inference of variant combinations\n */\nexport type OTPDigitVariantProps = VariantProps<typeof otpDigitVariants>;\nexport type OTPContainerVariantProps = VariantProps<typeof otpContainerVariants>;\nexport type OTPDigitGroupVariantProps = VariantProps<typeof otpDigitGroupVariants>;\n\n/**\n * Animation: Shake effect for errors\n *\n * Add this to tailwind.config.ts animations:\n *\n * ```ts\n * module.exports = {\n * theme: {\n * extend: {\n * keyframes: {\n * shake: {\n * '0%, 100%': { transform: 'translateX(0)' },\n * '25%': { transform: 'translateX(-8px)' },\n * '75%': { transform: 'translateX(8px)' },\n * },\n * },\n * animation: {\n * shake: 'shake 200ms ease-in-out',\n * },\n * },\n * },\n * };\n * ```\n */\n","import { memo, type ReactElement } from 'react';\nimport { cn } from '../../../utils/cn';\nimport { otpDigitVariants, type OTPDigitVariantProps } from '../OTPInput.styles';\n\n/**\n * Props for the OTPDigit component\n */\nexport interface OTPDigitProps {\n /**\n * Single character value or underscore for empty\n * @example \"1\" | \"A\" | \"_\"\n */\n value: string;\n\n /**\n * Whether this digit is currently focused\n * Determines visual focus indicator display\n */\n focused: boolean;\n\n /**\n * Size variant\n * @default 'md'\n */\n size?: OTPDigitVariantProps['size'];\n\n /**\n * State variant\n * Determines visual styling (default, focus, error, success, disabled)\n */\n state?: OTPDigitVariantProps['state'];\n\n /**\n * Mask the digit (show as bullet point)\n * Useful for sensitive codes\n * @default false\n */\n masked?: boolean;\n\n /**\n * Additional CSS classes\n */\n className?: string;\n\n /**\n * Index of this digit (for debugging)\n */\n index?: number;\n}\n\n/**\n * OTPDigit Component\n *\n * Displays a single digit of the OTP input with visual styling.\n * This is a presentational component - it does not handle input logic.\n *\n * Features:\n * - Memoized for performance (prevents unnecessary re-renders)\n * - WCAG AAA compliant (7:1 contrast, 44x44px touch targets)\n * - Supports masking for sensitive codes\n * - Visual focus indicators\n * - State-based styling (error, success, disabled)\n *\n * @example\n * ```tsx\n * <OTPDigit\n * value=\"5\"\n * focused={true}\n * size=\"md\"\n * state=\"focus\"\n * />\n * ```\n */\nconst OTPDigitComponent = ({\n value,\n focused,\n size = 'md',\n state = 'default',\n masked = false,\n className,\n index,\n}: OTPDigitProps): ReactElement => {\n // Determine if digit is filled\n const isFilled = value !== '_' && value !== '';\n\n // Determine state based on props\n const computedState = focused && !state ? 'focus' : isFilled && state === 'default' ? 'filled' : state;\n\n // Display value (masked or actual)\n const displayValue = masked && isFilled ? '•' : value === '_' ? '' : value;\n\n return (\n <div\n className={cn(\n otpDigitVariants({ size, state: computedState }),\n className\n )}\n role=\"presentation\"\n aria-hidden=\"true\"\n data-focused={focused}\n data-filled={isFilled}\n data-index={index}\n >\n {displayValue || (\n <span className=\"text-[var(--menu-muted)] opacity-40\">\n •\n </span>\n )}\n </div>\n );\n};\n\n/**\n * Memoized OTPDigit Component\n *\n * Prevents re-renders when other digits change.\n * Only re-renders when its own props change.\n *\n * Performance optimization for components with 6-10 digits.\n */\nexport const OTPDigit = memo(OTPDigitComponent);\n\nOTPDigit.displayName = 'OTPDigit';\n","'use client';\n\nimport { forwardRef, useId, useImperativeHandle, useRef, type FocusEvent, type KeyboardEvent } from 'react';\nimport { cn } from '../../utils/cn';\nimport { type OTPInputProps, type OTPInputRef } from './OTPInput.types';\nimport { useOTPInput } from './hooks/useOTPInput';\nimport { OTPDigit } from './components/OTPDigit';\nimport {\n otpContainerVariants,\n otpDigitGroupVariants,\n otpErrorVariants,\n otpDescriptionVariants,\n} from './OTPInput.styles';\n\n/**\n * OTPInput Component\n *\n * A fully accessible, WCAG 2.2 AAA-compliant OTP (One-Time Password) input component.\n *\n * Key Features:\n * - Single hidden input for screen readers (not multiple separate inputs)\n * - Visual digit boxes for optimal UX\n * - WCAG 2.2 AAA compliant (7:1 contrast, 44x44px touch targets)\n * - Auto-advance on digit entry\n * - Paste support with validation\n * - Controlled and uncontrolled modes\n * - Custom validation\n * - React Hook Form compatible\n *\n * Accessibility:\n * - Single tab stop (entire OTP is one field)\n * - Proper ARIA attributes (label, describedby, invalid, errormessage)\n * - Screen reader announcements for digit count and errors\n * - Visible focus indicators (7:1 contrast)\n * - Keyboard navigation (arrows, home, end, backspace, delete)\n *\n * @example Basic usage\n * ```tsx\n * <OTPInput\n * label=\"Enter verification code\"\n * length={6}\n * onChange={(value) => console.log(value)}\n * onComplete={(code) => console.log('Complete:', code)}\n * />\n * ```\n *\n * @example Controlled mode with validation\n * ```tsx\n * const [otp, setOtp] = useState('');\n * const [error, setError] = useState('');\n *\n * <OTPInput\n * label=\"Enter 6-digit code sent to your email\"\n * value={otp}\n * onChange={setOtp}\n * error={error}\n * validate={(value) => {\n * if (value === '000000') return 'Invalid code';\n * return null;\n * }}\n * />\n * ```\n *\n * @example With ref API\n * ```tsx\n * const otpRef = useRef<OTPInputRef>(null);\n *\n * <OTPInput\n * ref={otpRef}\n * label=\"Enter verification code\"\n * />\n *\n * // Programmatic control\n * otpRef.current?.clear();\n * otpRef.current?.setValue('123456');\n * ```\n */\nexport const OTPInput = forwardRef<OTPInputRef, OTPInputProps>((props, ref) => {\n // Validate serializable props with Zod schema (skip function validation)\n // Functions are type-checked by TypeScript, not runtime-validated\n const {\n label,\n description,\n size = 'md',\n disabled = false,\n readOnly = false,\n mask = false,\n showSuccess = false,\n className,\n digitClassName,\n onFocus,\n onBlur,\n inputMode = 'numeric',\n length = 6,\n } = props;\n\n // Main logic hook\n const {\n value,\n focusedIndex,\n error,\n isComplete,\n handleChange,\n handleKeyDown,\n handlePaste,\n setFocusedIndex,\n clear,\n setValue,\n validate,\n } = useOTPInput(props);\n\n // Ref to the hidden input element\n const inputRef = useRef<HTMLInputElement>(null);\n\n // Expose imperative API via ref\n useImperativeHandle(ref, (): OTPInputRef => ({\n focus: (): void => inputRef.current?.focus(),\n blur: (): void => inputRef.current?.blur(),\n clear,\n setValue,\n getValue: (): string => value.replace(/_/g, ''),\n isComplete: (): boolean => isComplete,\n validate,\n getElement: (): HTMLInputElement | null => inputRef.current,\n }));\n\n // Split value into individual digits\n const digits = value.split('');\n\n // Determine state for digit styling\n const getDigitState = (index: number): 'default' | 'focus' | 'filled' | 'error' | 'success' | 'disabled' => {\n if (disabled) return 'disabled';\n if (error) return 'error';\n if (showSuccess && isComplete && !error) return 'success';\n if (index === focusedIndex) return 'focus';\n if (digits[index] !== '_') return 'filled';\n return 'default';\n };\n\n // Handle focus events\n const handleFocusEvent = (e: FocusEvent<HTMLInputElement>): void => {\n onFocus?.(e);\n };\n\n const handleBlurEvent = (e: FocusEvent<HTMLInputElement>): void => {\n onBlur?.(e);\n };\n\n // Handle click/keyboard on digit boxes (focus hidden input)\n const handleDigitClick = (index: number): void => {\n if (disabled || readOnly) return;\n setFocusedIndex(index);\n inputRef.current?.focus();\n };\n\n const handleDigitKeyDown = (e: KeyboardEvent, index: number): void => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault();\n handleDigitClick(index);\n }\n };\n\n // Generate stable IDs for ARIA (SSR-safe)\n const baseId = useId();\n const descriptionId = description ? `${baseId}-description` : undefined;\n const errorId = error ? `${baseId}-error` : undefined;\n\n return (\n <div className={cn(otpContainerVariants({ size }), className)}>\n {/* Hidden accessible input */}\n <input\n ref={inputRef}\n type=\"text\"\n inputMode={inputMode}\n value={value.replace(/_/g, '')}\n onChange={handleChange}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n onFocus={handleFocusEvent}\n onBlur={handleBlurEvent}\n disabled={disabled}\n readOnly={readOnly}\n aria-label={label}\n aria-describedby={[descriptionId, errorId].filter(Boolean).join(' ')}\n aria-invalid={!!error}\n aria-errormessage={errorId}\n className=\"sr-only\"\n autoComplete=\"one-time-code\"\n maxLength={length}\n />\n\n {/* Visual digit display */}\n <div\n className={cn(otpDigitGroupVariants({ size }))}\n role=\"presentation\"\n aria-hidden=\"true\"\n >\n {digits.map((digit, index) => (\n <div\n key={index}\n onClick={() => handleDigitClick(index)}\n onKeyDown={(e) => handleDigitKeyDown(e, index)}\n role=\"button\"\n tabIndex={-1}\n className=\"cursor-text\"\n >\n <OTPDigit\n value={digit}\n focused={index === focusedIndex}\n size={size}\n state={getDigitState(index)}\n masked={mask}\n className={digitClassName}\n index={index}\n />\n </div>\n ))}\n </div>\n\n {/* Description text */}\n {description && (\n <p id={descriptionId} className={otpDescriptionVariants()}>\n {description}\n </p>\n )}\n\n {/* Error message */}\n {error && (\n <p\n id={errorId}\n className={otpErrorVariants()}\n role=\"alert\"\n aria-live=\"assertive\"\n >\n {error}\n </p>\n )}\n\n {/* Screen reader live region for digit count */}\n <div\n role=\"status\"\n aria-live=\"polite\"\n aria-atomic=\"true\"\n className=\"sr-only\"\n >\n {!isComplete && !error && (\n <>\n {value.replace(/_/g, '').length} of {length} digits entered\n </>\n )}\n {isComplete && !error && <>Verification code complete</>}\n </div>\n </div>\n );\n});\n\nOTPInput.displayName = 'OTPInput';\n"]}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination Component
|
|
3
|
+
*
|
|
4
|
+
* Navigation for paginated content with page numbers, prev/next,
|
|
5
|
+
* and first/last buttons. Uses the Themis Button component for
|
|
6
|
+
* three-layer architecture and WCAG 2.2 AAA 44x44px touch targets.
|
|
7
|
+
*
|
|
8
|
+
* @example
|
|
9
|
+
* ```tsx
|
|
10
|
+
* <Pagination
|
|
11
|
+
* page={currentPage}
|
|
12
|
+
* totalPages={10}
|
|
13
|
+
* onPageChange={setCurrentPage}
|
|
14
|
+
* />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const Pagination: import("react").ForwardRefExoticComponent<{
|
|
18
|
+
page: number;
|
|
19
|
+
totalPages: number;
|
|
20
|
+
onPageChange: (page: number) => void;
|
|
21
|
+
size: "default" | "sm" | "lg";
|
|
22
|
+
variant: "default" | "outline" | "ghost";
|
|
23
|
+
siblingCount: number;
|
|
24
|
+
showFirstLast: boolean;
|
|
25
|
+
showPrevNext: boolean;
|
|
26
|
+
isDisabled: boolean;
|
|
27
|
+
className?: string | undefined;
|
|
28
|
+
children?: any;
|
|
29
|
+
id?: string | undefined;
|
|
30
|
+
'aria-label'?: string | undefined;
|
|
31
|
+
'aria-labelledby'?: string | undefined;
|
|
32
|
+
'aria-describedby'?: string | undefined;
|
|
33
|
+
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
34
|
+
'aria-hidden'?: boolean | undefined;
|
|
35
|
+
'data-testid'?: string | undefined;
|
|
36
|
+
labels?: {
|
|
37
|
+
previous: string;
|
|
38
|
+
next: string;
|
|
39
|
+
first: string;
|
|
40
|
+
last: string;
|
|
41
|
+
page: string;
|
|
42
|
+
of: string;
|
|
43
|
+
} | undefined;
|
|
44
|
+
} & import("react").RefAttributes<HTMLElement>>;
|
|
45
|
+
//# sourceMappingURL=Pagination.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.d.ts","sourceRoot":"","sources":["../../../src/elements/Pagination/Pagination.tsx"],"names":[],"mappings":"AAoFA;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,UAAU;;;;;;;;;;;;;;;;;;;;;;;;;;;+CAgJtB,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare const paginationNavVariants: (props?: ({
|
|
2
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
3
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
4
|
+
export declare const paginationEllipsisVariants: (props?: ({
|
|
5
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
6
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
7
|
+
export declare const paginationInfoVariants: (props?: ({
|
|
8
|
+
size?: "default" | "sm" | "lg" | null | undefined;
|
|
9
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
10
|
+
//# sourceMappingURL=Pagination.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.styles.d.ts","sourceRoot":"","sources":["../../../src/elements/Pagination/Pagination.styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,qBAAqB;;8EAYjC,CAAC;AAEF,eAAO,MAAM,0BAA0B;;8EAYtC,CAAC;AAEF,eAAO,MAAM,sBAAsB;;8EAYlC,CAAC"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const PaginationSizeSchema: z.ZodEnum<{
|
|
3
|
+
default: "default";
|
|
4
|
+
sm: "sm";
|
|
5
|
+
lg: "lg";
|
|
6
|
+
}>;
|
|
7
|
+
export type PaginationSize = z.infer<typeof PaginationSizeSchema>;
|
|
8
|
+
export declare const PaginationVariantSchema: z.ZodEnum<{
|
|
9
|
+
default: "default";
|
|
10
|
+
outline: "outline";
|
|
11
|
+
ghost: "ghost";
|
|
12
|
+
}>;
|
|
13
|
+
export type PaginationVariant = z.infer<typeof PaginationVariantSchema>;
|
|
14
|
+
export declare const PaginationPropsSchema: z.ZodObject<{
|
|
15
|
+
className: z.ZodOptional<z.ZodString>;
|
|
16
|
+
children: z.ZodOptional<z.ZodAny>;
|
|
17
|
+
id: z.ZodOptional<z.ZodString>;
|
|
18
|
+
'aria-label': z.ZodOptional<z.ZodString>;
|
|
19
|
+
'aria-labelledby': z.ZodOptional<z.ZodString>;
|
|
20
|
+
'aria-describedby': z.ZodOptional<z.ZodString>;
|
|
21
|
+
'aria-live': z.ZodOptional<z.ZodEnum<{
|
|
22
|
+
off: "off";
|
|
23
|
+
polite: "polite";
|
|
24
|
+
assertive: "assertive";
|
|
25
|
+
}>>;
|
|
26
|
+
'aria-hidden': z.ZodOptional<z.ZodBoolean>;
|
|
27
|
+
'data-testid': z.ZodOptional<z.ZodString>;
|
|
28
|
+
page: z.ZodNumber;
|
|
29
|
+
totalPages: z.ZodNumber;
|
|
30
|
+
onPageChange: z.ZodCustom<(page: number) => void, (page: number) => void>;
|
|
31
|
+
size: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
32
|
+
default: "default";
|
|
33
|
+
sm: "sm";
|
|
34
|
+
lg: "lg";
|
|
35
|
+
}>>>;
|
|
36
|
+
variant: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
37
|
+
default: "default";
|
|
38
|
+
outline: "outline";
|
|
39
|
+
ghost: "ghost";
|
|
40
|
+
}>>>;
|
|
41
|
+
siblingCount: z.ZodDefault<z.ZodOptional<z.ZodNumber>>;
|
|
42
|
+
showFirstLast: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
43
|
+
showPrevNext: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
44
|
+
isDisabled: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
45
|
+
labels: z.ZodOptional<z.ZodObject<{
|
|
46
|
+
previous: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
47
|
+
next: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
48
|
+
first: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
49
|
+
last: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
50
|
+
page: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
51
|
+
of: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
52
|
+
}, z.core.$strip>>;
|
|
53
|
+
}, z.core.$strip>;
|
|
54
|
+
export type PaginationProps = z.infer<typeof PaginationPropsSchema>;
|
|
55
|
+
//# sourceMappingURL=Pagination.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Pagination.types.d.ts","sourceRoot":"","sources":["../../../src/elements/Pagination/Pagination.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,eAAO,MAAM,oBAAoB;;;;EAAkC,CAAC;AACpE,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,eAAO,MAAM,uBAAuB;;;;EAA0C,CAAC;AAC/E,MAAM,MAAM,iBAAiB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,uBAAuB,CAAC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;;;;;;;;;;qCAQF,MAAM,KAAK,IAAI,SAAf,MAAM,KAAK,IAAI;;;;;;;;;;;;;;;;;;;;;;;iBA6B7C,CAAC;AAEH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pagination Component Exports
|
|
3
|
+
*
|
|
4
|
+
* Navigation for paginated content with page numbers and prev/next.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```tsx
|
|
8
|
+
* import { Pagination } from '@tribepad/themis/elements/Pagination';
|
|
9
|
+
*
|
|
10
|
+
* <Pagination
|
|
11
|
+
* page={currentPage}
|
|
12
|
+
* totalPages={10}
|
|
13
|
+
* onPageChange={setCurrentPage}
|
|
14
|
+
* />
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export { Pagination } from './Pagination';
|
|
18
|
+
export type { PaginationProps, PaginationSize, PaginationVariant, } from './Pagination.types';
|
|
19
|
+
export { PaginationPropsSchema, PaginationSizeSchema, PaginationVariantSchema, } from './Pagination.types';
|
|
20
|
+
export { paginationNavVariants, paginationEllipsisVariants, paginationInfoVariants, } from './Pagination.styles';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/elements/Pagination/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,YAAY,EACV,eAAe,EACf,cAAc,EACd,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,0BAA0B,EAC1B,sBAAsB,GACvB,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';var react=require('react'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge'),reactAriaComponents=require('react-aria-components'),classVarianceAuthority=require('class-variance-authority'),jsxRuntime=require('react/jsx-runtime'),zod=require('zod');function N(...t){return tailwindMerge.twMerge(clsx.clsx(t))}var W=classVarianceAuthority.cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),U=classVarianceAuthority.cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] data-[pressed]:bg-[var(--primary-action)]/80",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] shadow-md hover:bg-[var(--destructive-background)]/90 data-[pressed]:bg-[var(--destructive-background)]/80",outline:"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)] data-[pressed]:bg-[var(--input-border)]",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] shadow-md hover:bg-[var(--secondary)]/80 data-[pressed]:bg-[var(--secondary)]/70",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] data-[pressed]:bg-[var(--accent)]",link:"text-[var(--text-link)] underline-offset-4 hover:underline data-[pressed]:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-8",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] !shadow-md hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var I="data-[pressed]:scale-[0.97]";var L="data-[hovered]:shadow-md";var z="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",C="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var J=react.createContext(null);J.displayName="ButtonGroupContext";function K(){return react.useContext(J)}var Q=react.createContext(null);Q.displayName="ButtonGroupItemContext";function X(){return react.useContext(Q)}classVarianceAuthority.cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var tt=classVarianceAuthority.cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});classVarianceAuthority.cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var x=react.memo(react.forwardRef(({className:t,buttonVisualClassName:e,variant:l,size:h,visualSize:u,fullWidth:g,loading:c=false,loadingText:b="Loading...",shortcut:i,children:o,isDisabled:s,paywall:r=false,paywallRedirect:S,paywallDescription:T,onPress:_,...p},G)=>{let m=react.useId(),v=K(),y=X(),R=l??v?.variant??"default",n=h??v?.size,P=s??v?.isDisabled??false,F=v?.orientation==="vertical",Y=g||F,rt=y?tt({orientation:v?.orientation??"horizontal",position:y.position}):"",w=u??n??"default";return process.env.NODE_ENV!=="production"&&(w==="dot"||w==="icon")&&!p["aria-label"]&&!o&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsxRuntime.jsx(reactAriaComponents.Button,{ref:G,isDisabled:P||c||void 0,"aria-disabled":r?true:void 0,"aria-describedby":r?m:void 0,onPress:B=>{if(r){S&&window.open(S,"_blank","noopener,noreferrer");return}_?.(B);},className:N(W({fullWidth:Y,inVerticalGroup:F}),t),...p,children:B=>jsxRuntime.jsxs("span",{className:N(U({variant:R,visualSize:w,paywall:r,fullWidth:Y}),rt,e,I,L,z,C),"data-pressed":B.isPressed||void 0,children:[c&&jsxRuntime.jsxs(jsxRuntime.Fragment,{children:[jsxRuntime.jsx(lucideReact.Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsxRuntime.jsx("span",{className:"sr-only","aria-live":"polite",children:b})]}),!c&&o,r&&jsxRuntime.jsx(lucideReact.Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),r&&jsxRuntime.jsxs("span",{id:m,className:"sr-only",children:["Premium feature: ",T||"Upgrade required to access this feature"]}),B.isFocusVisible&&i&&jsxRuntime.jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:i}),B.isPressed&&jsxRuntime.jsx("span",{className:"absolute inset-0 rounded-[inherit] bg-current opacity-10 motion-safe:animate-in motion-safe:zoom-in-95","aria-hidden":"true"})]})})}));x.displayName="Button";var k=classVarianceAuthority.cva("flex items-center justify-center",{variants:{size:{sm:"gap-0.5",default:"gap-1",lg:"gap-1.5"}},defaultVariants:{size:"default"}}),$=classVarianceAuthority.cva("inline-flex items-center justify-center text-[var(--muted-foreground)]",{variants:{size:{sm:"h-8 w-8 text-xs",default:"h-10 w-10 text-sm",lg:"h-12 w-12 text-base"}},defaultVariants:{size:"default"}}),ht=classVarianceAuthority.cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}});function Bt(t,e,l){let h=l*2+5;if(e<=h)return Array.from({length:e},(o,s)=>s+1);let u=Math.max(t-l,1),g=Math.min(t+l,e),c=u>2,b=g<e-1;if(!c&&b){let o=l*2+3,s=Array.from({length:o},(r,S)=>S+1);return s.push("ellipsis-end"),s.push(e),s}if(c&&!b){let o=l*2+3,s=[1,"ellipsis-start"];for(let r=e-o+1;r<=e;r++)s.push(r);return s}let i=[1,"ellipsis-start"];for(let o=u;o<=g;o++)i.push(o);return i.push("ellipsis-end"),i.push(e),i}function E(t,e){return e?"default":t==="outline"?"outline":"ghost"}function Nt(t){return t==="sm"?"sm":t==="lg"?"lg":"default"}var ot=react.forwardRef(({page:t,totalPages:e,onPageChange:l,size:h="default",variant:u="default",siblingCount:g=1,showFirstLast:c=true,showPrevNext:b=true,isDisabled:i=false,labels:o,className:s,"aria-label":r,"data-testid":S,...T},_)=>{let p={previous:o?.previous??"Previous",next:o?.next??"Next",first:o?.first??"First page",last:o?.last??"Last page",page:o?.page??"Page",of:o?.of??"of"},G=react.useMemo(()=>Bt(t,e,g),[t,e,g]),m=react.useCallback(n=>{n>=1&&n<=e&&n!==t&&l(n);},[t,e,l]),v=t===1,y=t===e,R=Nt(h);return jsxRuntime.jsxs("nav",{ref:_,"aria-label":r??"Pagination",className:N(k({size:h}),s),"data-testid":S,...T,children:[c&&jsxRuntime.jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||v,"aria-label":p.first,onPress:()=>m(1),children:jsxRuntime.jsx(lucideReact.ChevronsLeft,{"aria-hidden":"true"})}),b&&jsxRuntime.jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||v,"aria-label":p.previous,onPress:()=>m(t-1),children:jsxRuntime.jsx(lucideReact.ChevronLeft,{"aria-hidden":"true"})}),G.map(n=>{if(n==="ellipsis-start"||n==="ellipsis-end")return jsxRuntime.jsx("span",{className:$({size:h}),"aria-hidden":"true",children:"..."},n);let P=n===t;return jsxRuntime.jsx(x,{variant:E(u,P),visualSize:R,isDisabled:i||P,"aria-label":`${p.page} ${n}`,"aria-current":P?"page":void 0,onPress:()=>m(n),children:n},n)}),b&&jsxRuntime.jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||y,"aria-label":p.next,onPress:()=>m(t+1),children:jsxRuntime.jsx(lucideReact.ChevronRight,{"aria-hidden":"true"})}),c&&jsxRuntime.jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||y,"aria-label":p.last,onPress:()=>m(e),children:jsxRuntime.jsx(lucideReact.ChevronsRight,{"aria-hidden":"true"})}),jsxRuntime.jsxs("span",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:[p.page," ",t," ",p.of," ",e]})]})});ot.displayName="Pagination";var at=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 nt=zod.z.enum(["sm","default","lg"]),it=zod.z.enum(["default","outline","ghost"]),Et=at.extend({page:zod.z.number().min(1),totalPages:zod.z.number().min(1),onPageChange:zod.z.custom(),size:nt.optional().default("default"),variant:it.optional().default("default"),siblingCount:zod.z.number().min(0).optional().default(1),showFirstLast:zod.z.boolean().optional().default(true),showPrevNext:zod.z.boolean().optional().default(true),isDisabled:zod.z.boolean().optional().default(false),labels:zod.z.object({previous:zod.z.string().optional().default("Previous"),next:zod.z.string().optional().default("Next"),first:zod.z.string().optional().default("First page"),last:zod.z.string().optional().default("Last page"),page:zod.z.string().optional().default("Page"),of:zod.z.string().optional().default("of")}).optional()});exports.Pagination=ot;exports.PaginationPropsSchema=Et;exports.PaginationSizeSchema=nt;exports.PaginationVariantSchema=it;exports.paginationEllipsisVariants=$;exports.paginationInfoVariants=ht;exports.paginationNavVariants=k;//# sourceMappingURL=index.js.map
|
|
3
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/Button/Button.styles.ts","../../../src/styles/interaction-states.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/Button/Button.tsx","../../../src/elements/Pagination/Pagination.styles.ts","../../../src/elements/Pagination/Pagination.tsx","../../../src/schemas/BaseComponentProps.ts","../../../src/elements/Pagination/Pagination.types.ts"],"names":["cn","inputs","twMerge","clsx","buttonOuterVariants","cva","buttonVisualVariants","PRESSED_STYLES","HOVER_STYLES","HIGH_CONTRAST_HOVER","HIGH_CONTRAST_PRESSED","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupItemVariants","Button","memo","forwardRef","className","buttonVisualClassName","variant","size","visualSize","fullWidth","loading","loadingText","shortcut","children","isDisabled","paywall","paywallRedirect","paywallDescription","onPress","props","ref","paywallDescriptionId","useId","groupContext","itemContext","effectiveVariant","effectiveSize","effectiveIsDisabled","isInVerticalGroup","effectiveFullWidth","positionClassName","effectiveVisualSize","jsx","AriaButton","e","renderProps","jsxs","Fragment","Loader2","Zap","paginationNavVariants","paginationEllipsisVariants","paginationInfoVariants","generatePageNumbers","currentPage","totalPages","siblingCount","totalPageNumbers","_","i","leftSiblingIndex","rightSiblingIndex","showLeftEllipsis","showRightEllipsis","leftRange","pages","rightRange","getButtonVariant","paginationVariant","isActive","getButtonVisualSize","Pagination","page","onPageChange","showFirstLast","showPrevNext","labels","ariaLabel","dataTestId","resolvedLabels","useMemo","handlePageChange","useCallback","newPage","isFirstPage","isLastPage","ChevronsLeft","ChevronLeft","pageItem","ChevronRight","ChevronsRight","BaseComponentPropsSchema","z","PaginationSizeSchema","PaginationVariantSchema","PaginationPropsSchema"],"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","import { cva } from 'class-variance-authority';\n\n/**\n * Layer 1: Transparent outer touch target (44x44px minimum)\n * Handles WCAG 2.2 AAA touch target requirement\n * Always transparent, centers the visual button inside\n * IMPORTANT: Focus ring stays on Layer 1 for AAA compliance (2.4.13)\n *\n * In vertical ButtonGroups, uses items-stretch so the visual layer (Layer 2)\n * can fill the full touch target height, eliminating gaps between buttons.\n */\nexport const buttonOuterVariants = cva(\n \"inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50\",\n {\n variants: {\n fullWidth: {\n true: \"w-full\",\n false: \"\",\n },\n inVerticalGroup: {\n true: \"items-stretch\",\n false: \"items-center\",\n },\n },\n defaultVariants: {\n fullWidth: false,\n inVerticalGroup: false,\n },\n }\n);\n\n/**\n * Layer 2: Visual button appearance (adjustable size)\n * Provides the visual appearance with configurable size\n * Can be smaller than touch target for use cases like carousel dots\n * NOTE: NO focus-visible styles here - focus ring is on Layer 1\n */\nexport const buttonVisualVariants = cva(\n \"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer\",\n {\n variants: {\n variant: {\n default:\n \"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] data-[pressed]:bg-[var(--primary-action)]/80\",\n destructive:\n \"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] shadow-md hover:bg-[var(--destructive-background)]/90 data-[pressed]:bg-[var(--destructive-background)]/80\",\n outline:\n \"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)] data-[pressed]:bg-[var(--input-border)]\",\n secondary:\n \"bg-[var(--secondary)] text-[var(--secondary-foreground)] shadow-md hover:bg-[var(--secondary)]/80 data-[pressed]:bg-[var(--secondary)]/70\",\n ghost:\n \"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] data-[pressed]:bg-[var(--accent)]\",\n link: \"text-[var(--text-link)] underline-offset-4 hover:underline data-[pressed]:text-[var(--text-link-hover)]\",\n },\n fullWidth: {\n true: \"w-full\",\n false: \"\",\n },\n visualSize: {\n default: \"h-10 px-4 py-2\",\n sm: \"h-9 rounded-md px-3 text-xs\",\n lg: \"h-11 rounded-md px-8\",\n icon: \"h-10 w-10\",\n dot: \"h-5 w-5 rounded-full p-0 min-h-0 min-w-0\",\n },\n paywall: {\n true: \"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] !shadow-md hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent\",\n false: \"\",\n },\n },\n defaultVariants: {\n variant: \"default\",\n visualSize: \"default\",\n paywall: false,\n },\n }\n);\n\n/**\n * @deprecated Use buttonVisualVariants instead. This alias is kept for backward compatibility.\n */\nexport const buttonVariants = buttonVisualVariants;\n","/**\n * Global Interaction State Styles\n *\n * Consistent interaction patterns across all Themis components.\n * These styles ensure WCAG 2.2 AAA compliance and predictable UX.\n *\n * @see spec.md FR-010 (Visible focus ring for keyboard navigation)\n * @see spec.md FR-031 (Pressed state feedback)\n * @see spec.md FR-012 (High contrast mode support)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\n/**\n * Focus state styles (FR-010)\n * Visible focus ring for keyboard navigation - WCAG 2.2 Level AAA\n *\n * Components can override by extending these styles:\n * @example\n * cn(FOCUS_STYLES, \"ring-4\") // Increases ring width to 4px\n */\nexport const FOCUS_STYLES = \"data-[focus-visible]:ring-2 data-[focus-visible]:ring-[var(--themis-ring)] data-[focus-visible]:ring-offset-2\";\n\n/**\n * Pressed/Active state styles (FR-031)\n * Visual feedback for press interactions\n *\n * Components can override the scale amount:\n * @example\n * cn(PRESSED_STYLES_BASE, \"data-[pressed]:scale-[0.95]\") // More pronounced scale\n */\nexport const PRESSED_STYLES = \"data-[pressed]:scale-[0.97]\";\n\n/**\n * Base pressed styles without scale (for components that need different feedback)\n */\nexport const PRESSED_STYLES_BASE = \"data-[pressed]:transition-transform data-[pressed]:duration-100\";\n\n/**\n * Hover state styles\n * Elevation change on hover for better affordance\n *\n * Components can override shadow depth:\n * @example\n * cn(HOVER_STYLES_BASE, \"data-[hovered]:shadow-lg\") // Larger shadow\n */\nexport const HOVER_STYLES = \"data-[hovered]:shadow-md\";\n\n/**\n * Base hover styles without shadow (for components that use different hover effects)\n */\nexport const HOVER_STYLES_BASE = \"data-[hovered]:transition-shadow data-[hovered]:duration-200\";\n\n/**\n * High contrast mode focus (FR-012)\n * Enhanced outlines for users requiring high contrast\n *\n * Uses 'hc:' prefix for prefers-contrast: more media query\n */\nexport const HIGH_CONTRAST_FOCUS = \"hc:data-[focus-visible]:outline hc:data-[focus-visible]:outline-4 hc:data-[focus-visible]:outline-offset-2 hc:data-[focus-visible]:outline-foreground\";\n\n/**\n * High contrast mode hover (FR-012)\n * Enhanced outlines for hover in high contrast mode\n */\nexport const HIGH_CONTRAST_HOVER = \"hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground\";\n\n/**\n * High contrast mode pressed state\n * Enhanced outlines for pressed state in high contrast mode\n */\nexport const HIGH_CONTRAST_PRESSED = \"hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground\";\n\n/**\n * Combined high contrast styles\n * Use this for components that need all high contrast interaction states\n */\nexport const HIGH_CONTRAST_INTERACTIONS = `${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Disabled state styles\n * Consistent disabled appearance across all components\n */\nexport const DISABLED_STYLES = \"disabled:pointer-events-none disabled:opacity-50\";\n\n/**\n * Default interaction bundle\n * Most common combination for interactive components\n *\n * Includes: focus ring, pressed scale, hover shadow, high contrast enhancements\n *\n * @example\n * <button className={cn(DEFAULT_INTERACTIONS, \"bg-primary\")}>Click</button>\n */\nexport const DEFAULT_INTERACTIONS = `${FOCUS_STYLES} ${PRESSED_STYLES} ${HOVER_STYLES} ${HIGH_CONTRAST_FOCUS} ${HIGH_CONTRAST_HOVER} ${HIGH_CONTRAST_PRESSED}`;\n\n/**\n * Subtle interaction bundle\n * For components that need less pronounced feedback\n *\n * Includes: focus ring and high contrast, but no hover shadow or pressed scale\n */\nexport const SUBTLE_INTERACTIONS = `${FOCUS_STYLES} ${HIGH_CONTRAST_FOCUS}`;\n\n/**\n * Non-interactive element styles\n * For elements that should indicate they are not interactive\n */\nexport const NON_INTERACTIVE = \"cursor-default select-none\";\n","\"use client\";\n\nimport { createContext, useContext } from 'react';\nimport type {\n ButtonGroupContextValue,\n ButtonGroupItemContextValue,\n} from './ButtonGroup.types';\n\n/**\n * ButtonGroup Context System (Two-Level)\n *\n * Provides a two-level context pattern for ButtonGroup:\n *\n * 1. ButtonGroupContext (group-level):\n * - Provides: orientation, variant, size, isDisabled\n * - Consumed by: Button (for prop inheritance), Separator (for orientation)\n *\n * 2. ButtonGroupItemContext (item-level):\n * - Provides: position ('first' | 'middle' | 'last' | 'only')\n * - Consumed by: Button (for border-radius styling)\n *\n * Both contexts return null when not in a provider, allowing Button\n * to work standalone without any group context.\n *\n * @see plan.md for architecture details\n * @see ButtonGroup.tsx for Provider implementation\n */\n\n// =============================================================================\n// Group-Level Context\n// =============================================================================\n\n/**\n * Context for group-level props (orientation, variant, size, isDisabled)\n * Default value is null to indicate \"not in a group\"\n */\nconst ButtonGroupContext = createContext<ButtonGroupContextValue | null>(null);\n\nButtonGroupContext.displayName = 'ButtonGroupContext';\n\n/**\n * Hook to access group-level context\n * @returns ButtonGroupContextValue if inside a ButtonGroup, null otherwise\n */\nexport function useButtonGroupContext(): ButtonGroupContextValue | null {\n return useContext(ButtonGroupContext);\n}\n\n// =============================================================================\n// Item-Level Context\n// =============================================================================\n\n/**\n * Context for per-button position information\n * Default value is null to indicate \"not wrapped with position context\"\n */\nconst ButtonGroupItemContext =\n createContext<ButtonGroupItemContextValue | null>(null);\n\nButtonGroupItemContext.displayName = 'ButtonGroupItemContext';\n\n/**\n * Hook to access item-level context (position)\n * @returns ButtonGroupItemContextValue if wrapped with position context, null otherwise\n */\nexport function useButtonGroupItemContext(): ButtonGroupItemContextValue | null {\n return useContext(ButtonGroupItemContext);\n}\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroupContext, ButtonGroupItemContext };\n","import { cva } from 'class-variance-authority';\n\n/**\n * ButtonGroup CVA Variants\n *\n * Defines Class Variance Authority (CVA) variants for:\n * - ButtonGroup container (orientation-based layout)\n * - ButtonGroupItem (position-based border-radius)\n * - ButtonGroupSeparator (orientation-based styling)\n *\n * @see plan.md Phase 1: Design & Contracts - CVA Variants\n * @see constitution.md Principle V (Component Quality Standards)\n */\n\n// =============================================================================\n// Container Variants\n// =============================================================================\n\n/**\n * ButtonGroup container variants\n * Controls the layout direction based on orientation\n * Uses gap-0 to ensure buttons are connected (share borders)\n */\nexport const buttonGroupVariants = cva('inline-flex items-center gap-0', {\n variants: {\n orientation: {\n horizontal: 'flex-row',\n vertical: 'flex-col w-full',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n\n// =============================================================================\n// Item Position Variants\n// =============================================================================\n\n/**\n * ButtonGroupItem position variants\n * Applied to Button's visual layer (Layer 2) for position-aware border-radius\n *\n * Compound variants handle both orientation and position combinations:\n * - Horizontal: left/right borders and radii\n * - Vertical: top/bottom borders and radii\n */\nexport const buttonGroupItemVariants = cva('', {\n variants: {\n orientation: {\n // min-w-[44px] ensures visual layer fills touch target width (for icon buttons)\n horizontal: 'min-w-[44px]',\n // flex (overrides inline-flex) + min-h-[44px] makes visual layer fill touch target,\n // eliminating gaps between stacked buttons in vertical orientation\n vertical: 'flex min-h-[44px]',\n },\n position: {\n first: '',\n middle: '',\n last: '',\n only: '', // Single button - no modifications needed\n },\n },\n compoundVariants: [\n // ==========================================================================\n // Horizontal Orientation\n // ==========================================================================\n {\n orientation: 'horizontal',\n position: 'first',\n className: 'rounded-r-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'middle',\n className: 'rounded-none border-r-0',\n },\n {\n orientation: 'horizontal',\n position: 'last',\n className: 'rounded-l-none',\n },\n // ==========================================================================\n // Vertical Orientation\n // Note: w-full is handled by Button's effectiveFullWidth for both layers\n // ==========================================================================\n {\n orientation: 'vertical',\n position: 'first',\n className: 'rounded-b-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'middle',\n className: 'rounded-none border-b-0',\n },\n {\n orientation: 'vertical',\n position: 'last',\n className: 'rounded-t-none',\n },\n ],\n defaultVariants: {\n orientation: 'horizontal',\n position: 'only',\n },\n});\n\n// =============================================================================\n// Separator Variants\n// =============================================================================\n\n/**\n * ButtonGroupSeparator variants\n * Orientation-aware visual divider between button groups\n */\nexport const buttonGroupSeparatorVariants = cva('bg-[var(--border)]', {\n variants: {\n orientation: {\n horizontal: 'w-px h-6 mx-1',\n vertical: 'h-px w-full my-1',\n },\n },\n defaultVariants: {\n orientation: 'horizontal',\n },\n});\n","\"use client\";\n\n/**\n * Button Component - 3-Layer Architecture\n * Accessible button with React Aria primitives and CVA styling\n *\n * Architecture:\n * - Layer 1: Touch Target (44x44px WCAG AAA compliant, transparent)\n * - Layer 2: Visual Button (configurable size, colors, borders)\n * - Layer 3: Content & Effects (text, icons, ripple, loading spinner)\n *\n * @see 3layer-plan.md for architecture details\n * @see spec.md FR-029 to FR-037 (Button Component Requirements)\n * @see spec.md FR-009 (WCAG 2.2 AAA - 7:1 contrast ratio)\n * @see spec.md FR-014 (44x44px minimum touch targets)\n * @see constitution.md Principle IV (Accessibility First)\n */\n\nimport { forwardRef, memo, useId } from 'react';\nimport {\n Button as AriaButton,\n type ButtonProps as AriaButtonProps,\n} from 'react-aria-components';\nimport { Loader2, Zap } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport type { ButtonProps } from './Button.types';\nimport { buttonOuterVariants, buttonVisualVariants, buttonVariants } from './Button.styles';\nimport { PRESSED_STYLES, HOVER_STYLES, HIGH_CONTRAST_HOVER, HIGH_CONTRAST_PRESSED } from '../../styles/interaction-states';\nimport {\n useButtonGroupContext,\n useButtonGroupItemContext,\n} from '../ButtonGroup/ButtonGroupContext';\nimport { buttonGroupItemVariants } from '../ButtonGroup/ButtonGroup.variants';\n\n/**\n * Button Component - 3-Layer Architecture\n * Fully accessible button with React Aria and themed styling\n *\n * Layer 1: Touch Target (AriaButton) - 44x44px WCAG AAA compliant\n * Layer 2: Visual Button (span) - configurable appearance\n * Layer 3: Content (children) - text, icons, effects\n */\nconst Button = memo(forwardRef<HTMLButtonElement, ButtonProps>(\n (\n {\n className,\n buttonVisualClassName,\n variant,\n size,\n visualSize,\n fullWidth,\n loading = false,\n loadingText = \"Loading...\",\n shortcut,\n children,\n isDisabled,\n paywall = false,\n paywallRedirect,\n paywallDescription,\n onPress,\n ...props\n },\n ref\n ) => {\n const paywallDescriptionId = useId();\n\n // ==========================================================================\n // ButtonGroup Context Integration\n // ==========================================================================\n\n // Consume group-level context (variant, size, isDisabled, orientation)\n const groupContext = useButtonGroupContext();\n\n // Consume item-level context (position for border-radius styling)\n const itemContext = useButtonGroupItemContext();\n\n // Merge context values with props (props take precedence)\n const effectiveVariant = variant ?? groupContext?.variant ?? 'default';\n const effectiveSize = size ?? groupContext?.size;\n const effectiveIsDisabled = isDisabled ?? groupContext?.isDisabled ?? false;\n\n // In vertical groups, buttons should be full width automatically\n const isInVerticalGroup = groupContext?.orientation === 'vertical';\n const effectiveFullWidth = fullWidth || isInVerticalGroup;\n\n // Position styling for ButtonGroup (only applied when in a group)\n const positionClassName = itemContext\n ? buttonGroupItemVariants({\n orientation: groupContext?.orientation ?? 'horizontal',\n position: itemContext.position,\n })\n : '';\n\n // Default visualSize to size for backward compatibility\n const effectiveVisualSize = visualSize ?? effectiveSize ?? 'default';\n\n // AAA Accessibility: Warn in dev/test if icon/dot variant lacks accessible name\n if (process.env.NODE_ENV !== 'production') {\n if (\n (effectiveVisualSize === 'dot' || effectiveVisualSize === 'icon') &&\n !props['aria-label'] &&\n !children\n ) {\n console.warn(\n '[Button] visualSize=\"dot\" or \"icon\" requires aria-label when no visible text is provided (WCAG 1.1.1)'\n );\n }\n }\n\n /**\n * Handle button press - intercepts action when paywalled\n * If paywalled with redirect URL, opens in new tab\n * Otherwise, calls the normal onPress handler\n */\n const handlePress = (e: Parameters<NonNullable<AriaButtonProps['onPress']>>[0]): void => {\n if (paywall) {\n if (paywallRedirect) {\n window.open(paywallRedirect, '_blank', 'noopener,noreferrer');\n }\n // Don't call onPress when paywalled\n return;\n }\n onPress?.(e);\n };\n\n // Only set isDisabled when we have a reason to disable\n // Otherwise, let slot system control disabled state (e.g., in NumberField)\n const computedIsDisabled = effectiveIsDisabled || loading || undefined;\n\n return (\n <AriaButton\n ref={ref}\n isDisabled={computedIsDisabled}\n aria-disabled={paywall ? true : undefined}\n aria-describedby={paywall ? paywallDescriptionId : undefined}\n onPress={handlePress}\n className={cn(buttonOuterVariants({ fullWidth: effectiveFullWidth, inVerticalGroup: isInVerticalGroup }), className)}\n {...props}\n >\n {(renderProps) => (\n /* Layer 2: Visual Button */\n <span\n className={cn(\n buttonVisualVariants({\n variant: effectiveVariant,\n visualSize: effectiveVisualSize,\n paywall,\n fullWidth: effectiveFullWidth,\n }),\n // Position styling from ButtonGroup context (border-radius adjustments)\n positionClassName,\n buttonVisualClassName,\n // Layer 2 interaction styles (no focus - focus ring is on Layer 1)\n PRESSED_STYLES,\n HOVER_STYLES,\n HIGH_CONTRAST_HOVER,\n HIGH_CONTRAST_PRESSED\n )}\n data-pressed={renderProps.isPressed || undefined}\n >\n {/* Layer 3: Content & Effects */}\n\n {/* FR-033: Loading spinner with screen reader announcement */}\n {/* Uses motion-safe: for WCAG 2.3.3 AAA (Animation from Interactions) */}\n {loading && (\n <>\n <Loader2 className=\"motion-safe:animate-spin\" aria-hidden=\"true\" />\n <span className=\"sr-only\" aria-live=\"polite\">\n {loadingText}\n </span>\n </>\n )}\n\n {/* Hide children during loading */}\n {!loading && children}\n\n {/* Paywall: Lightning bolt icon */}\n {paywall && (\n <Zap\n data-testid=\"zap-icon\"\n aria-hidden=\"true\"\n className=\"ml-1\"\n />\n )}\n\n {/* Paywall: Screen reader description */}\n {paywall && (\n <span id={paywallDescriptionId} className=\"sr-only\">\n Premium feature: {paywallDescription || \"Upgrade required to access this feature\"}\n </span>\n )}\n\n {/* FR-034: Keyboard shortcut display on focus */}\n {renderProps.isFocusVisible && shortcut && (\n <kbd className=\"ml-auto hidden text-xs opacity-60 lg:inline\">\n {shortcut}\n </kbd>\n )}\n\n {/* Touch/press ripple effect - FR-031: Pressed state feedback */}\n {/* Uses motion-safe: for WCAG 2.3.3 AAA (Animation from Interactions) */}\n {renderProps.isPressed && (\n <span\n className=\"absolute inset-0 rounded-[inherit] bg-current opacity-10 motion-safe:animate-in motion-safe:zoom-in-95\"\n aria-hidden=\"true\"\n />\n )}\n </span>\n )}\n </AriaButton>\n );\n }\n));\n\nButton.displayName = \"Button\";\n\nexport { Button, buttonVariants, buttonOuterVariants, buttonVisualVariants };\nexport type { ButtonProps } from './Button.types';\n","import { cva } from 'class-variance-authority';\n\nexport const paginationNavVariants = cva(\n 'flex items-center justify-center',\n {\n variants: {\n size: {\n sm: 'gap-0.5',\n default: 'gap-1',\n lg: 'gap-1.5',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const paginationEllipsisVariants = cva(\n 'inline-flex items-center justify-center text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'h-8 w-8 text-xs',\n default: 'h-10 w-10 text-sm',\n lg: 'h-12 w-12 text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n\nexport const paginationInfoVariants = cva(\n 'text-[var(--muted-foreground)]',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-base',\n },\n },\n defaultVariants: { size: 'default' },\n }\n);\n","'use client';\n\nimport { forwardRef, useMemo, useCallback, type ReactElement } from 'react';\nimport { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight } from 'lucide-react';\nimport { cn } from '../../utils/cn';\nimport { Button } from '../Button/Button';\nimport type { ButtonProps } from '../Button/Button.types';\nimport type { PaginationProps, PaginationVariant } from './Pagination.types';\nimport {\n paginationNavVariants,\n paginationEllipsisVariants,\n} from './Pagination.styles';\n\n/**\n * Generate page numbers array with ellipsis\n * Returns array like: [1, '...', 4, 5, 6, '...', 10]\n */\nfunction generatePageNumbers(\n currentPage: number,\n totalPages: number,\n siblingCount: number\n): (number | 'ellipsis-start' | 'ellipsis-end')[] {\n // Total page numbers to show (first + last + current + siblings + 2 ellipses)\n const totalPageNumbers = siblingCount * 2 + 5;\n\n // If total pages is less than the numbers we want to show, show all\n if (totalPages <= totalPageNumbers) {\n return Array.from({ length: totalPages }, (_, i) => i + 1);\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);\n const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPages);\n\n const showLeftEllipsis = leftSiblingIndex > 2;\n const showRightEllipsis = rightSiblingIndex < totalPages - 1;\n\n if (!showLeftEllipsis && showRightEllipsis) {\n const leftRange = siblingCount * 2 + 3;\n const pages: (number | 'ellipsis-start' | 'ellipsis-end')[] = Array.from(\n { length: leftRange },\n (_, i) => i + 1\n );\n pages.push('ellipsis-end');\n pages.push(totalPages);\n return pages;\n }\n\n if (showLeftEllipsis && !showRightEllipsis) {\n const rightRange = siblingCount * 2 + 3;\n const pages: (number | 'ellipsis-start' | 'ellipsis-end')[] = [1, 'ellipsis-start'];\n for (let i = totalPages - rightRange + 1; i <= totalPages; i++) {\n pages.push(i);\n }\n return pages;\n }\n\n // Both ellipses\n const pages: (number | 'ellipsis-start' | 'ellipsis-end')[] = [1, 'ellipsis-start'];\n for (let i = leftSiblingIndex; i <= rightSiblingIndex; i++) {\n pages.push(i);\n }\n pages.push('ellipsis-end');\n pages.push(totalPages);\n return pages;\n}\n\n/**\n * Map Pagination variant to Button variant for inactive buttons\n */\nfunction getButtonVariant(paginationVariant: PaginationVariant, isActive: boolean): ButtonProps['variant'] {\n if (isActive) return 'default';\n if (paginationVariant === 'outline') return 'outline';\n return 'ghost';\n}\n\n/**\n * Map Pagination size to Button visualSize\n */\nfunction getButtonVisualSize(size: 'sm' | 'default' | 'lg'): ButtonProps['visualSize'] {\n if (size === 'sm') return 'sm';\n if (size === 'lg') return 'lg';\n return 'default';\n}\n\n/**\n * Pagination Component\n *\n * Navigation for paginated content with page numbers, prev/next,\n * and first/last buttons. Uses the Themis Button component for\n * three-layer architecture and WCAG 2.2 AAA 44x44px touch targets.\n *\n * @example\n * ```tsx\n * <Pagination\n * page={currentPage}\n * totalPages={10}\n * onPageChange={setCurrentPage}\n * />\n * ```\n */\nexport const Pagination = forwardRef<HTMLElement, PaginationProps>(\n (\n {\n page,\n totalPages,\n onPageChange,\n size = 'default',\n variant = 'default',\n siblingCount = 1,\n showFirstLast = true,\n showPrevNext = true,\n isDisabled = false,\n labels,\n className,\n 'aria-label': ariaLabel,\n 'data-testid': dataTestId,\n ...props\n },\n ref\n ): ReactElement => {\n const resolvedLabels = {\n previous: labels?.previous ?? 'Previous',\n next: labels?.next ?? 'Next',\n first: labels?.first ?? 'First page',\n last: labels?.last ?? 'Last page',\n page: labels?.page ?? 'Page',\n of: labels?.of ?? 'of',\n };\n\n const pages = useMemo(\n () => generatePageNumbers(page, totalPages, siblingCount),\n [page, totalPages, siblingCount]\n );\n\n const handlePageChange = useCallback(\n (newPage: number) => {\n if (newPage >= 1 && newPage <= totalPages && newPage !== page) {\n onPageChange(newPage);\n }\n },\n [page, totalPages, onPageChange]\n );\n\n const isFirstPage = page === 1;\n const isLastPage = page === totalPages;\n const visualSize = getButtonVisualSize(size);\n\n return (\n <nav\n ref={ref as React.Ref<HTMLElement>}\n aria-label={ariaLabel ?? 'Pagination'}\n className={cn(paginationNavVariants({ size }), className)}\n data-testid={dataTestId}\n {...props}\n >\n {/* First Page Button */}\n {showFirstLast && (\n <Button\n variant={getButtonVariant(variant, false)}\n visualSize=\"icon\"\n isDisabled={isDisabled || isFirstPage}\n aria-label={resolvedLabels.first}\n onPress={() => handlePageChange(1)}\n >\n <ChevronsLeft aria-hidden=\"true\" />\n </Button>\n )}\n\n {/* Previous Button */}\n {showPrevNext && (\n <Button\n variant={getButtonVariant(variant, false)}\n visualSize=\"icon\"\n isDisabled={isDisabled || isFirstPage}\n aria-label={resolvedLabels.previous}\n onPress={() => handlePageChange(page - 1)}\n >\n <ChevronLeft aria-hidden=\"true\" />\n </Button>\n )}\n\n {/* Page Numbers */}\n {pages.map((pageItem) => {\n if (pageItem === 'ellipsis-start' || pageItem === 'ellipsis-end') {\n return (\n <span\n key={pageItem}\n className={paginationEllipsisVariants({ size })}\n aria-hidden=\"true\"\n >\n ...\n </span>\n );\n }\n\n const isActive = pageItem === page;\n return (\n <Button\n key={pageItem}\n variant={getButtonVariant(variant, isActive)}\n visualSize={visualSize}\n isDisabled={isDisabled || isActive}\n aria-label={`${resolvedLabels.page} ${pageItem}`}\n aria-current={isActive ? 'page' : undefined}\n onPress={() => handlePageChange(pageItem)}\n >\n {pageItem}\n </Button>\n );\n })}\n\n {/* Next Button */}\n {showPrevNext && (\n <Button\n variant={getButtonVariant(variant, false)}\n visualSize=\"icon\"\n isDisabled={isDisabled || isLastPage}\n aria-label={resolvedLabels.next}\n onPress={() => handlePageChange(page + 1)}\n >\n <ChevronRight aria-hidden=\"true\" />\n </Button>\n )}\n\n {/* Last Page Button */}\n {showFirstLast && (\n <Button\n variant={getButtonVariant(variant, false)}\n visualSize=\"icon\"\n isDisabled={isDisabled || isLastPage}\n aria-label={resolvedLabels.last}\n onPress={() => handlePageChange(totalPages)}\n >\n <ChevronsRight aria-hidden=\"true\" />\n </Button>\n )}\n\n {/* Screen reader announcement for page context */}\n <span className=\"sr-only\" role=\"status\" aria-live=\"polite\" aria-atomic=\"true\">\n {resolvedLabels.page} {page} {resolvedLabels.of} {totalPages}\n </span>\n </nav>\n );\n }\n);\n\nPagination.displayName = 'Pagination';\n","import { z } from 'zod';\n\n/**\n * Base props schema for all Themis components\n * Ensures consistent accessibility and styling APIs across the library\n *\n * @see spec.md FR-009 to FR-014 (Accessibility Requirements)\n * @see constitution.md Principle IV (Accessibility First - WCAG 2.2 AA minimum)\n */\nexport const BaseComponentPropsSchema = z.object({\n // Styling\n className: z.string().optional(),\n\n // React\n children: z.any().optional(), // ReactNode not directly supported by Zod\n id: z.string().optional(),\n\n // Accessibility (WCAG 2.2 AA requirements)\n 'aria-label': z.string().optional(),\n 'aria-labelledby': z.string().optional(),\n 'aria-describedby': z.string().optional(),\n 'aria-live': z.enum(['off', 'polite', 'assertive']).optional(),\n 'aria-hidden': z.boolean().optional(),\n\n // Testing & Development\n 'data-testid': z.string().optional(),\n});\n\nexport type BaseComponentProps = z.infer<typeof BaseComponentPropsSchema>;\n","import { z } from 'zod';\nimport { BaseComponentPropsSchema } from '../../schemas/BaseComponentProps';\n\nexport const PaginationSizeSchema = z.enum(['sm', 'default', 'lg']);\nexport type PaginationSize = z.infer<typeof PaginationSizeSchema>;\n\nexport const PaginationVariantSchema = z.enum(['default', 'outline', 'ghost']);\nexport type PaginationVariant = z.infer<typeof PaginationVariantSchema>;\n\nexport const PaginationPropsSchema = BaseComponentPropsSchema.extend({\n /** Current page (1-indexed) */\n page: z.number().min(1),\n\n /** Total number of pages */\n totalPages: z.number().min(1),\n\n /** Callback when page changes */\n onPageChange: z.custom<(page: number) => void>(),\n\n /** Size variant */\n size: PaginationSizeSchema.optional().default('default'),\n\n /** Visual variant */\n variant: PaginationVariantSchema.optional().default('default'),\n\n /** Number of sibling pages to show around current page */\n siblingCount: z.number().min(0).optional().default(1),\n\n /** Whether to show first/last page buttons */\n showFirstLast: z.boolean().optional().default(true),\n\n /** Whether to show previous/next buttons */\n showPrevNext: z.boolean().optional().default(true),\n\n /** Whether the pagination is disabled */\n isDisabled: z.boolean().optional().default(false),\n\n /** Custom labels */\n labels: z.object({\n previous: z.string().optional().default('Previous'),\n next: z.string().optional().default('Next'),\n first: z.string().optional().default('First page'),\n last: z.string().optional().default('Last page'),\n page: z.string().optional().default('Page'),\n of: z.string().optional().default('of'),\n }).optional(),\n});\n\nexport type PaginationProps = z.infer<typeof PaginationPropsSchema>;\n"]}
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {createContext,memo,forwardRef,useId,useMemo,useCallback,useContext}from'react';import {Loader2,Zap,ChevronsLeft,ChevronLeft,ChevronRight,ChevronsRight}from'lucide-react';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {Button}from'react-aria-components';import {cva}from'class-variance-authority';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {z as z$1}from'zod';function N(...t){return twMerge(clsx(t))}var W=cva("inline-flex justify-center min-h-[44px] min-w-[44px] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ring)] focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50",{variants:{fullWidth:{true:"w-full",false:""},inVerticalGroup:{true:"items-stretch",false:"items-center"}},defaultVariants:{fullWidth:false,inVerticalGroup:false}}),U=cva("inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium ring-offset-background transition-colors [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0 relative cursor-pointer",{variants:{variant:{default:"bg-[var(--primary-action)] text-[var(--primary-action-foreground)] shadow-md hover:bg-[var(--primary-action-hover)] data-[pressed]:bg-[var(--primary-action)]/80",destructive:"bg-[var(--destructive-background)] text-[var(--destructive-foreground)] shadow-md hover:bg-[var(--destructive-background)]/90 data-[pressed]:bg-[var(--destructive-background)]/80",outline:"border border-[var(--input-border)] bg-[var(--page-background)] hover:bg-[var(--input-border)] data-[pressed]:bg-[var(--input-border)]",secondary:"bg-[var(--secondary)] text-[var(--secondary-foreground)] shadow-md hover:bg-[var(--secondary)]/80 data-[pressed]:bg-[var(--secondary)]/70",ghost:"hover:bg-[var(--accent)] hover:text-[var(--accent-foreground)] data-[pressed]:bg-[var(--accent)]",link:"text-[var(--text-link)] underline-offset-4 hover:underline data-[pressed]:text-[var(--text-link-hover)]"},fullWidth:{true:"w-full",false:""},visualSize:{default:"h-10 px-4 py-2",sm:"h-9 rounded-md px-3 text-xs",lg:"h-11 rounded-md px-8",icon:"h-10 w-10",dot:"h-5 w-5 rounded-full p-0 min-h-0 min-w-0"},paywall:{true:"!bg-[var(--paywall)] !text-[var(--paywall-foreground)] !shadow-md hover:!bg-[var(--paywall)]/90 !cursor-not-allowed !border-transparent",false:""}},defaultVariants:{variant:"default",visualSize:"default",paywall:false}});var I="data-[pressed]:scale-[0.97]";var L="data-[hovered]:shadow-md";var z="hc:data-[hovered]:outline hc:data-[hovered]:outline-2 hc:data-[hovered]:outline-foreground",C="hc:data-[pressed]:outline hc:data-[pressed]:outline-2 hc:data-[pressed]:outline-offset-1 hc:data-[pressed]:outline-foreground";var J=createContext(null);J.displayName="ButtonGroupContext";function K(){return useContext(J)}var Q=createContext(null);Q.displayName="ButtonGroupItemContext";function X(){return useContext(Q)}cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}});var tt=cva("",{variants:{orientation:{horizontal:"min-w-[44px]",vertical:"flex min-h-[44px]"},position:{first:"",middle:"",last:"",only:""}},compoundVariants:[{orientation:"horizontal",position:"first",className:"rounded-r-none border-r-0"},{orientation:"horizontal",position:"middle",className:"rounded-none border-r-0"},{orientation:"horizontal",position:"last",className:"rounded-l-none"},{orientation:"vertical",position:"first",className:"rounded-b-none border-b-0"},{orientation:"vertical",position:"middle",className:"rounded-none border-b-0"},{orientation:"vertical",position:"last",className:"rounded-t-none"}],defaultVariants:{orientation:"horizontal",position:"only"}});cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var x=memo(forwardRef(({className:t,buttonVisualClassName:e,variant:l,size:h,visualSize:u,fullWidth:g,loading:c=false,loadingText:b="Loading...",shortcut:i,children:o,isDisabled:s,paywall:r=false,paywallRedirect:S,paywallDescription:T,onPress:_,...p},G)=>{let m=useId(),v=K(),y=X(),R=l??v?.variant??"default",n=h??v?.size,P=s??v?.isDisabled??false,F=v?.orientation==="vertical",Y=g||F,rt=y?tt({orientation:v?.orientation??"horizontal",position:y.position}):"",w=u??n??"default";return process.env.NODE_ENV!=="production"&&(w==="dot"||w==="icon")&&!p["aria-label"]&&!o&&console.warn('[Button] visualSize="dot" or "icon" requires aria-label when no visible text is provided (WCAG 1.1.1)'),jsx(Button,{ref:G,isDisabled:P||c||void 0,"aria-disabled":r?true:void 0,"aria-describedby":r?m:void 0,onPress:B=>{if(r){S&&window.open(S,"_blank","noopener,noreferrer");return}_?.(B);},className:N(W({fullWidth:Y,inVerticalGroup:F}),t),...p,children:B=>jsxs("span",{className:N(U({variant:R,visualSize:w,paywall:r,fullWidth:Y}),rt,e,I,L,z,C),"data-pressed":B.isPressed||void 0,children:[c&&jsxs(Fragment,{children:[jsx(Loader2,{className:"motion-safe:animate-spin","aria-hidden":"true"}),jsx("span",{className:"sr-only","aria-live":"polite",children:b})]}),!c&&o,r&&jsx(Zap,{"data-testid":"zap-icon","aria-hidden":"true",className:"ml-1"}),r&&jsxs("span",{id:m,className:"sr-only",children:["Premium feature: ",T||"Upgrade required to access this feature"]}),B.isFocusVisible&&i&&jsx("kbd",{className:"ml-auto hidden text-xs opacity-60 lg:inline",children:i}),B.isPressed&&jsx("span",{className:"absolute inset-0 rounded-[inherit] bg-current opacity-10 motion-safe:animate-in motion-safe:zoom-in-95","aria-hidden":"true"})]})})}));x.displayName="Button";var k=cva("flex items-center justify-center",{variants:{size:{sm:"gap-0.5",default:"gap-1",lg:"gap-1.5"}},defaultVariants:{size:"default"}}),$=cva("inline-flex items-center justify-center text-[var(--muted-foreground)]",{variants:{size:{sm:"h-8 w-8 text-xs",default:"h-10 w-10 text-sm",lg:"h-12 w-12 text-base"}},defaultVariants:{size:"default"}}),ht=cva("text-[var(--muted-foreground)]",{variants:{size:{sm:"text-xs",default:"text-sm",lg:"text-base"}},defaultVariants:{size:"default"}});function Bt(t,e,l){let h=l*2+5;if(e<=h)return Array.from({length:e},(o,s)=>s+1);let u=Math.max(t-l,1),g=Math.min(t+l,e),c=u>2,b=g<e-1;if(!c&&b){let o=l*2+3,s=Array.from({length:o},(r,S)=>S+1);return s.push("ellipsis-end"),s.push(e),s}if(c&&!b){let o=l*2+3,s=[1,"ellipsis-start"];for(let r=e-o+1;r<=e;r++)s.push(r);return s}let i=[1,"ellipsis-start"];for(let o=u;o<=g;o++)i.push(o);return i.push("ellipsis-end"),i.push(e),i}function E(t,e){return e?"default":t==="outline"?"outline":"ghost"}function Nt(t){return t==="sm"?"sm":t==="lg"?"lg":"default"}var ot=forwardRef(({page:t,totalPages:e,onPageChange:l,size:h="default",variant:u="default",siblingCount:g=1,showFirstLast:c=true,showPrevNext:b=true,isDisabled:i=false,labels:o,className:s,"aria-label":r,"data-testid":S,...T},_)=>{let p={previous:o?.previous??"Previous",next:o?.next??"Next",first:o?.first??"First page",last:o?.last??"Last page",page:o?.page??"Page",of:o?.of??"of"},G=useMemo(()=>Bt(t,e,g),[t,e,g]),m=useCallback(n=>{n>=1&&n<=e&&n!==t&&l(n);},[t,e,l]),v=t===1,y=t===e,R=Nt(h);return jsxs("nav",{ref:_,"aria-label":r??"Pagination",className:N(k({size:h}),s),"data-testid":S,...T,children:[c&&jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||v,"aria-label":p.first,onPress:()=>m(1),children:jsx(ChevronsLeft,{"aria-hidden":"true"})}),b&&jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||v,"aria-label":p.previous,onPress:()=>m(t-1),children:jsx(ChevronLeft,{"aria-hidden":"true"})}),G.map(n=>{if(n==="ellipsis-start"||n==="ellipsis-end")return jsx("span",{className:$({size:h}),"aria-hidden":"true",children:"..."},n);let P=n===t;return jsx(x,{variant:E(u,P),visualSize:R,isDisabled:i||P,"aria-label":`${p.page} ${n}`,"aria-current":P?"page":void 0,onPress:()=>m(n),children:n},n)}),b&&jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||y,"aria-label":p.next,onPress:()=>m(t+1),children:jsx(ChevronRight,{"aria-hidden":"true"})}),c&&jsx(x,{variant:E(u,false),visualSize:"icon",isDisabled:i||y,"aria-label":p.last,onPress:()=>m(e),children:jsx(ChevronsRight,{"aria-hidden":"true"})}),jsxs("span",{className:"sr-only",role:"status","aria-live":"polite","aria-atomic":"true",children:[p.page," ",t," ",p.of," ",e]})]})});ot.displayName="Pagination";var at=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 nt=z$1.enum(["sm","default","lg"]),it=z$1.enum(["default","outline","ghost"]),Et=at.extend({page:z$1.number().min(1),totalPages:z$1.number().min(1),onPageChange:z$1.custom(),size:nt.optional().default("default"),variant:it.optional().default("default"),siblingCount:z$1.number().min(0).optional().default(1),showFirstLast:z$1.boolean().optional().default(true),showPrevNext:z$1.boolean().optional().default(true),isDisabled:z$1.boolean().optional().default(false),labels:z$1.object({previous:z$1.string().optional().default("Previous"),next:z$1.string().optional().default("Next"),first:z$1.string().optional().default("First page"),last:z$1.string().optional().default("Last page"),page:z$1.string().optional().default("Page"),of:z$1.string().optional().default("of")}).optional()});export{ot as Pagination,Et as PaginationPropsSchema,nt as PaginationSizeSchema,it as PaginationVariantSchema,$ as paginationEllipsisVariants,ht as paginationInfoVariants,k as paginationNavVariants};//# sourceMappingURL=index.mjs.map
|
|
3
|
+
//# sourceMappingURL=index.mjs.map
|