@tribepad/themis 1.0.10 → 1.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/elements/Accordion/Accordion.types.d.ts +44 -4
- package/dist/elements/Accordion/Accordion.types.d.ts.map +1 -1
- package/dist/elements/Accordion/index.js +1 -1
- package/dist/elements/Accordion/index.js.map +1 -1
- package/dist/elements/Accordion/index.mjs +1 -1
- package/dist/elements/Accordion/index.mjs.map +1 -1
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts +19 -2
- package/dist/elements/AlertDialog/AlertDialog.types.d.ts.map +1 -1
- package/dist/elements/AlertDialog/index.js +1 -1
- package/dist/elements/AlertDialog/index.js.map +1 -1
- package/dist/elements/AlertDialog/index.mjs +1 -1
- package/dist/elements/AlertDialog/index.mjs.map +1 -1
- package/dist/elements/Avatar/Avatar.d.ts +1 -21
- package/dist/elements/Avatar/Avatar.d.ts.map +1 -1
- package/dist/elements/Avatar/Avatar.types.d.ts +30 -11
- package/dist/elements/Avatar/Avatar.types.d.ts.map +1 -1
- package/dist/elements/Avatar/AvatarGroup.d.ts +1 -17
- package/dist/elements/Avatar/AvatarGroup.d.ts.map +1 -1
- package/dist/elements/Avatar/index.js +1 -1
- package/dist/elements/Avatar/index.js.map +1 -1
- package/dist/elements/Avatar/index.mjs +1 -1
- package/dist/elements/Avatar/index.mjs.map +1 -1
- package/dist/elements/Badge/Badge.types.d.ts +16 -9
- package/dist/elements/Badge/Badge.types.d.ts.map +1 -1
- package/dist/elements/Badge/index.js +1 -1
- package/dist/elements/Badge/index.js.map +1 -1
- package/dist/elements/Badge/index.mjs +1 -1
- package/dist/elements/Badge/index.mjs.map +1 -1
- package/dist/elements/Breadcrumbs/Breadcrumbs.d.ts +2 -34
- package/dist/elements/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/elements/Breadcrumbs/Breadcrumbs.types.d.ts +25 -2
- package/dist/elements/Breadcrumbs/Breadcrumbs.types.d.ts.map +1 -1
- package/dist/elements/Breadcrumbs/index.js +1 -1
- package/dist/elements/Breadcrumbs/index.js.map +1 -1
- package/dist/elements/Breadcrumbs/index.mjs +1 -1
- package/dist/elements/Breadcrumbs/index.mjs.map +1 -1
- package/dist/elements/Button/Button.d.ts +1 -24
- package/dist/elements/Button/Button.d.ts.map +1 -1
- package/dist/elements/Button/Button.types.d.ts +28 -7
- package/dist/elements/Button/Button.types.d.ts.map +1 -1
- package/dist/elements/ButtonGroup/ButtonGroup.d.ts +3 -14
- package/dist/elements/ButtonGroup/ButtonGroup.d.ts.map +1 -1
- package/dist/elements/ButtonGroup/ButtonGroup.types.d.ts +14 -5
- package/dist/elements/ButtonGroup/ButtonGroup.types.d.ts.map +1 -1
- package/dist/elements/ButtonGroup/index.js +1 -1
- package/dist/elements/ButtonGroup/index.js.map +1 -1
- package/dist/elements/ButtonGroup/index.mjs +1 -1
- package/dist/elements/ButtonGroup/index.mjs.map +1 -1
- package/dist/elements/Card/Card.d.ts +9 -94
- package/dist/elements/Card/Card.d.ts.map +1 -1
- package/dist/elements/Card/Card.types.d.ts +69 -17
- package/dist/elements/Card/Card.types.d.ts.map +1 -1
- package/dist/elements/Card/index.js +1 -1
- package/dist/elements/Card/index.js.map +1 -1
- package/dist/elements/Card/index.mjs +1 -1
- package/dist/elements/Card/index.mjs.map +1 -1
- package/dist/elements/Carousel/Carousel.types.d.ts +26 -7
- package/dist/elements/Carousel/Carousel.types.d.ts.map +1 -1
- package/dist/elements/Chart/Chart.d.ts +2 -40
- package/dist/elements/Chart/Chart.d.ts.map +1 -1
- package/dist/elements/Chart/Chart.types.d.ts +25 -10
- package/dist/elements/Chart/Chart.types.d.ts.map +1 -1
- package/dist/elements/Chart/index.js +1 -1
- package/dist/elements/Chart/index.js.map +1 -1
- package/dist/elements/Chart/index.mjs +1 -1
- package/dist/elements/Chart/index.mjs.map +1 -1
- package/dist/elements/Checkbox/Checkbox.d.ts +1 -31
- package/dist/elements/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/elements/Checkbox/Checkbox.types.d.ts +33 -1
- package/dist/elements/Checkbox/Checkbox.types.d.ts.map +1 -1
- package/dist/elements/Checkbox/index.js +1 -1
- package/dist/elements/Checkbox/index.js.map +1 -1
- package/dist/elements/Checkbox/index.mjs +1 -1
- package/dist/elements/Checkbox/index.mjs.map +1 -1
- package/dist/elements/CheckboxGroup/CheckboxGroup.d.ts +1 -26
- package/dist/elements/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
- package/dist/elements/CheckboxGroup/CheckboxGroup.types.d.ts +48 -4
- package/dist/elements/CheckboxGroup/CheckboxGroup.types.d.ts.map +1 -1
- package/dist/elements/CheckboxGroup/index.js +1 -1
- package/dist/elements/CheckboxGroup/index.js.map +1 -1
- package/dist/elements/CheckboxGroup/index.mjs +1 -1
- package/dist/elements/CheckboxGroup/index.mjs.map +1 -1
- package/dist/elements/Combobox/Combobox.d.ts +1 -30
- package/dist/elements/Combobox/Combobox.d.ts.map +1 -1
- package/dist/elements/Combobox/Combobox.types.d.ts +38 -4
- package/dist/elements/Combobox/Combobox.types.d.ts.map +1 -1
- package/dist/elements/Combobox/index.js +1 -1
- package/dist/elements/Combobox/index.js.map +1 -1
- package/dist/elements/Combobox/index.mjs +1 -1
- package/dist/elements/Combobox/index.mjs.map +1 -1
- package/dist/elements/Dropdown/Dropdown.d.ts +10 -124
- package/dist/elements/Dropdown/Dropdown.d.ts.map +1 -1
- package/dist/elements/Dropdown/Dropdown.types.d.ts +53 -8
- package/dist/elements/Dropdown/Dropdown.types.d.ts.map +1 -1
- package/dist/elements/FileField/FileField.d.ts +2 -39
- package/dist/elements/FileField/FileField.d.ts.map +1 -1
- package/dist/elements/FileField/FileField.types.d.ts +31 -13
- package/dist/elements/FileField/FileField.types.d.ts.map +1 -1
- package/dist/elements/FileField/index.js +1 -1
- package/dist/elements/FileField/index.js.map +1 -1
- package/dist/elements/FileField/index.mjs +1 -1
- package/dist/elements/FileField/index.mjs.map +1 -1
- package/dist/elements/FormLayout/FormLayout.d.ts +2 -37
- package/dist/elements/FormLayout/FormLayout.d.ts.map +1 -1
- package/dist/elements/FormLayout/FormLayout.types.d.ts +19 -3
- package/dist/elements/FormLayout/FormLayout.types.d.ts.map +1 -1
- package/dist/elements/MatrixGrid/MatrixGrid.d.ts +2 -29
- package/dist/elements/MatrixGrid/MatrixGrid.d.ts.map +1 -1
- package/dist/elements/MatrixGrid/MatrixGrid.types.d.ts +22 -1
- package/dist/elements/MatrixGrid/MatrixGrid.types.d.ts.map +1 -1
- package/dist/elements/MatrixGrid/index.js +1 -1
- package/dist/elements/MatrixGrid/index.js.map +1 -1
- package/dist/elements/MatrixGrid/index.mjs +1 -1
- package/dist/elements/MatrixGrid/index.mjs.map +1 -1
- package/dist/elements/Modal/Modal.types.d.ts +69 -9
- package/dist/elements/Modal/Modal.types.d.ts.map +1 -1
- package/dist/elements/Pagination/Pagination.d.ts +2 -28
- package/dist/elements/Pagination/Pagination.d.ts.map +1 -1
- package/dist/elements/Pagination/Pagination.types.d.ts +26 -1
- package/dist/elements/Pagination/Pagination.types.d.ts.map +1 -1
- package/dist/elements/Pagination/index.js +1 -1
- package/dist/elements/Pagination/index.js.map +1 -1
- package/dist/elements/Pagination/index.mjs +1 -1
- package/dist/elements/Pagination/index.mjs.map +1 -1
- package/dist/elements/Panel/Panel.types.d.ts +67 -9
- package/dist/elements/Panel/Panel.types.d.ts.map +1 -1
- package/dist/elements/PasswordField/PasswordField.d.ts +2 -26
- package/dist/elements/PasswordField/PasswordField.d.ts.map +1 -1
- package/dist/elements/PasswordField/PasswordField.types.d.ts +27 -2
- package/dist/elements/PasswordField/PasswordField.types.d.ts.map +1 -1
- package/dist/elements/PasswordField/index.js +1 -1
- package/dist/elements/PasswordField/index.js.map +1 -1
- package/dist/elements/PasswordField/index.mjs +1 -1
- package/dist/elements/PasswordField/index.mjs.map +1 -1
- package/dist/elements/Progress/Progress.types.d.ts +25 -3
- package/dist/elements/Progress/Progress.types.d.ts.map +1 -1
- package/dist/elements/Progress/index.js +1 -1
- package/dist/elements/Progress/index.js.map +1 -1
- package/dist/elements/Progress/index.mjs +1 -1
- package/dist/elements/Progress/index.mjs.map +1 -1
- package/dist/elements/RadioGroup/RadioGroup.d.ts +1 -26
- package/dist/elements/RadioGroup/RadioGroup.d.ts.map +1 -1
- package/dist/elements/RadioGroup/RadioGroup.types.d.ts +43 -4
- package/dist/elements/RadioGroup/RadioGroup.types.d.ts.map +1 -1
- package/dist/elements/RadioGroup/index.js +1 -1
- package/dist/elements/RadioGroup/index.js.map +1 -1
- package/dist/elements/RadioGroup/index.mjs +1 -1
- package/dist/elements/RadioGroup/index.mjs.map +1 -1
- package/dist/elements/RatingScale/RatingScale.d.ts +2 -30
- package/dist/elements/RatingScale/RatingScale.d.ts.map +1 -1
- package/dist/elements/RatingScale/RatingScale.types.d.ts +29 -1
- package/dist/elements/RatingScale/RatingScale.types.d.ts.map +1 -1
- package/dist/elements/RatingScale/index.js +1 -1
- package/dist/elements/RatingScale/index.js.map +1 -1
- package/dist/elements/RatingScale/index.mjs +1 -1
- package/dist/elements/RatingScale/index.mjs.map +1 -1
- package/dist/elements/SearchField/SearchField.d.ts +2 -26
- package/dist/elements/SearchField/SearchField.d.ts.map +1 -1
- package/dist/elements/SearchField/SearchField.types.d.ts +26 -2
- package/dist/elements/SearchField/SearchField.types.d.ts.map +1 -1
- package/dist/elements/SearchField/index.js +1 -1
- package/dist/elements/SearchField/index.js.map +1 -1
- package/dist/elements/SearchField/index.mjs +1 -1
- package/dist/elements/SearchField/index.mjs.map +1 -1
- package/dist/elements/Select/Select.d.ts +3 -61
- package/dist/elements/Select/Select.d.ts.map +1 -1
- package/dist/elements/Select/Select.types.d.ts +52 -4
- package/dist/elements/Select/Select.types.d.ts.map +1 -1
- package/dist/elements/Select/index.js +1 -1
- package/dist/elements/Select/index.js.map +1 -1
- package/dist/elements/Select/index.mjs +1 -1
- package/dist/elements/Select/index.mjs.map +1 -1
- package/dist/elements/SituationalJudgement/SituationalJudgement.d.ts +2 -28
- package/dist/elements/SituationalJudgement/SituationalJudgement.d.ts.map +1 -1
- package/dist/elements/SituationalJudgement/SituationalJudgement.types.d.ts +23 -1
- package/dist/elements/SituationalJudgement/SituationalJudgement.types.d.ts.map +1 -1
- package/dist/elements/SituationalJudgement/index.js +1 -1
- package/dist/elements/SituationalJudgement/index.js.map +1 -1
- package/dist/elements/SituationalJudgement/index.mjs +1 -1
- package/dist/elements/SituationalJudgement/index.mjs.map +1 -1
- package/dist/elements/Skeleton/Skeleton.types.d.ts +11 -6
- package/dist/elements/Skeleton/Skeleton.types.d.ts.map +1 -1
- package/dist/elements/Skeleton/index.js +1 -1
- package/dist/elements/Skeleton/index.js.map +1 -1
- package/dist/elements/Skeleton/index.mjs +1 -1
- package/dist/elements/Skeleton/index.mjs.map +1 -1
- package/dist/elements/Switch/Switch.types.d.ts +31 -7
- package/dist/elements/Switch/Switch.types.d.ts.map +1 -1
- package/dist/elements/Switch/index.js +1 -1
- package/dist/elements/Switch/index.js.map +1 -1
- package/dist/elements/Switch/index.mjs +1 -1
- package/dist/elements/Switch/index.mjs.map +1 -1
- package/dist/elements/Table/Table.d.ts +7 -79
- package/dist/elements/Table/Table.d.ts.map +1 -1
- package/dist/elements/Table/Table.types.d.ts +82 -17
- package/dist/elements/Table/Table.types.d.ts.map +1 -1
- package/dist/elements/Table/index.js +1 -1
- package/dist/elements/Table/index.js.map +1 -1
- package/dist/elements/Table/index.mjs +1 -1
- package/dist/elements/Table/index.mjs.map +1 -1
- package/dist/elements/Tabs/Tabs.types.d.ts +61 -5
- package/dist/elements/Tabs/Tabs.types.d.ts.map +1 -1
- package/dist/elements/Tabs/index.js +1 -1
- package/dist/elements/Tabs/index.js.map +1 -1
- package/dist/elements/Tabs/index.mjs +1 -1
- package/dist/elements/Tabs/index.mjs.map +1 -1
- package/dist/elements/TextField/TextField.d.ts +6 -71
- package/dist/elements/TextField/TextField.d.ts.map +1 -1
- package/dist/elements/TextField/TextField.types.d.ts +76 -12
- package/dist/elements/TextField/TextField.types.d.ts.map +1 -1
- package/dist/elements/TextField/index.js +1 -1
- package/dist/elements/TextField/index.js.map +1 -1
- package/dist/elements/TextField/index.mjs +1 -1
- package/dist/elements/TextField/index.mjs.map +1 -1
- package/dist/elements/Toast/Toast.types.d.ts +12 -20
- package/dist/elements/Toast/Toast.types.d.ts.map +1 -1
- package/dist/elements/Toast/Toaster.d.ts +2 -5
- package/dist/elements/Toast/Toaster.d.ts.map +1 -1
- package/dist/elements/Toast/index.js +1 -1
- package/dist/elements/Toast/index.js.map +1 -1
- package/dist/elements/Toast/index.mjs +1 -1
- package/dist/elements/Toast/index.mjs.map +1 -1
- package/dist/elements/Tooltip/Tooltip.types.d.ts +39 -4
- package/dist/elements/Tooltip/Tooltip.types.d.ts.map +1 -1
- package/dist/elements/Tooltip/index.js +1 -1
- package/dist/elements/Tooltip/index.js.map +1 -1
- package/dist/elements/Tooltip/index.mjs +1 -1
- package/dist/elements/Tooltip/index.mjs.map +1 -1
- package/dist/elements/index.js +1 -1
- package/dist/elements/index.js.map +1 -1
- package/dist/elements/index.mjs +1 -1
- package/dist/elements/index.mjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["cn","inputs","twMerge","clsx","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupVariants","cva","buttonGroupItemVariants","buttonGroupSeparatorVariants","isButtonElement","child","isValidElement","isSeparatorElement","getPosition","index","total","filterButtonChildren","children","getButtonIndex","buttonChildren","ButtonGroup","forwardRef","orientation","variant","size","isDisabled","className","props","ref","childArray","Children","totalButtons","groupContextValue","wrappedChildren","buttonIndex","position","jsx","Toolbar","ButtonGroupSeparator","ButtonGroupPropsSchema","z","ButtonGroupSeparatorPropsSchema"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\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","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport type ButtonGroupProps = z.infer<typeof ButtonGroupPropsSchema>;\n\n/**\n * Props for the ButtonGroupSeparator component\n */\nexport type ButtonGroupSeparatorProps = z.infer<\n typeof ButtonGroupSeparatorPropsSchema\n>;\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["cn","inputs","twMerge","clsx","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupVariants","cva","buttonGroupItemVariants","buttonGroupSeparatorVariants","isButtonElement","child","isValidElement","isSeparatorElement","getPosition","index","total","filterButtonChildren","children","getButtonIndex","buttonChildren","ButtonGroup","forwardRef","orientation","variant","size","isDisabled","className","props","ref","childArray","Children","totalButtons","groupContextValue","wrappedChildren","buttonIndex","position","jsx","Toolbar","ButtonGroupSeparator","ButtonGroupPropsSchema","z","ButtonGroupSeparatorPropsSchema"],"mappings":"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","file":"index.js","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\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","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport interface ButtonGroupProps {\n orientation?: ButtonGroupOrientation;\n variant?: ButtonGroupVariant;\n size?: ButtonGroupSize;\n isDisabled?: boolean;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n children?: ReactNode;\n}\n\nexport interface ButtonGroupSeparatorProps {\n className?: string;\n 'data-testid'?: string;\n}\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
import {createContext,forwardRef,Children,isValidElement,useContext}from'react';import {Toolbar}from'react-aria-components';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx}from'react/jsx-runtime';import {z}from'zod';function s(...t){return twMerge(clsx(t))}var a=createContext(null);a.displayName="ButtonGroupContext";function m(){return useContext(a)}var
|
|
2
|
+
import {createContext,forwardRef,Children,isValidElement,useContext}from'react';import {Toolbar}from'react-aria-components';import {clsx}from'clsx';import {twMerge}from'tailwind-merge';import {cva}from'class-variance-authority';import {jsx}from'react/jsx-runtime';import {z}from'zod';function s(...t){return twMerge(clsx(t))}var a=createContext(null);a.displayName="ButtonGroupContext";function m(){return useContext(a)}var i=createContext(null);i.displayName="ButtonGroupItemContext";function M(){return useContext(i)}var d=cva("inline-flex items-center gap-0",{variants:{orientation:{horizontal:"flex-row",vertical:"flex-col w-full"}},defaultVariants:{orientation:"horizontal"}}),A=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"}}),B=cva("bg-[var(--border)]",{variants:{orientation:{horizontal:"w-px h-6 mx-1",vertical:"h-px w-full my-1"}},defaultVariants:{orientation:"horizontal"}});var n=t=>isValidElement(t)?t.type?.displayName==="Button":false,H=t=>isValidElement(t)?t.type?.displayName==="ButtonGroupSeparator":false,x=(t,e)=>e===1?"only":t===0?"first":t===e-1?"last":"middle",L=t=>t.filter(n),j=(t,e)=>e.indexOf(t);var g=forwardRef(({orientation:t="horizontal",variant:e,size:p,isDisabled:f,className:l,children:P,...G},S)=>{let b=Children.toArray(P),y=b.filter(n),z=y.length,I={orientation:t,variant:e,size:p,isDisabled:f},R=b.map((r,E)=>{if(n(r)){let T=y.indexOf(r),w=x(T,z);return jsx(i.Provider,{value:{position:w},children:r},E)}return r});return jsx(Toolbar,{ref:S,orientation:t,"aria-label":G["aria-label"],"aria-labelledby":G["aria-labelledby"],className:s(d({orientation:t}),l),children:jsx(a.Provider,{value:I,children:R})})});g.displayName="ButtonGroup";var v=forwardRef(({className:t,...e},p)=>{let l=m()?.orientation??"horizontal";return jsx("div",{ref:p,role:"separator","aria-hidden":"true",className:s(B({orientation:l}),t),...e})});v.displayName="ButtonGroupSeparator";var F=z.object({orientation:z.enum(["horizontal","vertical"]).optional().default("horizontal"),variant:z.enum(["default","destructive","outline","secondary","ghost"]).optional(),size:z.enum(["sm","default","lg","icon"]).optional(),isDisabled:z.boolean().optional(),"aria-label":z.string().optional(),"aria-labelledby":z.string().optional(),className:z.string().optional(),children:z.custom()}),J=z.object({className:z.string().optional(),"data-testid":z.string().optional()});export{g as ButtonGroup,F as ButtonGroupPropsSchema,v as ButtonGroupSeparator,J as ButtonGroupSeparatorPropsSchema,A as buttonGroupItemVariants,B as buttonGroupSeparatorVariants,d as buttonGroupVariants,L as filterButtonChildren,j as getButtonIndex,x as getPosition,n as isButtonElement,H as isSeparatorElement,m as useButtonGroupContext,M as useButtonGroupItemContext};//# sourceMappingURL=index.mjs.map
|
|
3
3
|
//# sourceMappingURL=index.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["cn","inputs","twMerge","clsx","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupVariants","cva","buttonGroupItemVariants","buttonGroupSeparatorVariants","isButtonElement","child","isValidElement","isSeparatorElement","getPosition","index","total","filterButtonChildren","children","getButtonIndex","buttonChildren","ButtonGroup","forwardRef","orientation","variant","size","isDisabled","className","props","ref","childArray","Children","totalButtons","groupContextValue","wrappedChildren","buttonIndex","position","jsx","Toolbar","ButtonGroupSeparator","ButtonGroupPropsSchema","z","ButtonGroupSeparatorPropsSchema"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"use client\";\n\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","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport type ButtonGroupProps = z.infer<typeof ButtonGroupPropsSchema>;\n\n/**\n * Props for the ButtonGroupSeparator component\n */\nexport type ButtonGroupSeparatorProps = z.infer<\n typeof ButtonGroupSeparatorPropsSchema\n>;\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../../src/utils/cn.ts","../../../src/elements/ButtonGroup/ButtonGroupContext.tsx","../../../src/elements/ButtonGroup/ButtonGroup.variants.ts","../../../src/elements/ButtonGroup/ButtonGroup.utils.ts","../../../src/elements/ButtonGroup/ButtonGroup.tsx","../../../src/elements/ButtonGroup/ButtonGroup.types.ts"],"names":["cn","inputs","twMerge","clsx","ButtonGroupContext","createContext","useButtonGroupContext","useContext","ButtonGroupItemContext","useButtonGroupItemContext","buttonGroupVariants","cva","buttonGroupItemVariants","buttonGroupSeparatorVariants","isButtonElement","child","isValidElement","isSeparatorElement","getPosition","index","total","filterButtonChildren","children","getButtonIndex","buttonChildren","ButtonGroup","forwardRef","orientation","variant","size","isDisabled","className","props","ref","childArray","Children","totalButtons","groupContextValue","wrappedChildren","buttonIndex","position","jsx","Toolbar","ButtonGroupSeparator","ButtonGroupPropsSchema","z","ButtonGroupSeparatorPropsSchema"],"mappings":"4RAcO,SAASA,CAAAA,CAAAA,GAAMC,CAAAA,CAA8B,CAClD,OAAOC,OAAAA,CAAQC,IAAAA,CAAKF,CAAM,CAAC,CAC7B,CCoBA,IAAMG,CAAAA,CAAqBC,aAAAA,CAA8C,IAAI,CAAA,CAE7ED,CAAAA,CAAmB,WAAA,CAAc,oBAAA,CAM1B,SAASE,CAAAA,EAAwD,CACtE,OAAOC,UAAAA,CAAWH,CAAkB,CACtC,CAUA,IAAMI,CAAAA,CACJH,aAAAA,CAAkD,IAAI,CAAA,CAExDG,CAAAA,CAAuB,WAAA,CAAc,wBAAA,CAM9B,SAASC,CAAAA,EAAgE,CAC9E,OAAOF,UAAAA,CAAWC,CAAsB,CAC1C,CC5CO,IAAME,CAAAA,CAAsBC,GAAAA,CAAI,gCAAA,CAAkC,CACvE,QAAA,CAAU,CACR,WAAA,CAAa,CACX,UAAA,CAAY,UAAA,CACZ,QAAA,CAAU,iBACZ,CACF,CAAA,CACA,eAAA,CAAiB,CACf,WAAA,CAAa,YACf,CACF,CAAC,CAAA,CAcYC,CAAAA,CAA0BD,GAAAA,CAAI,GAAI,CAC7C,QAAA,CAAU,CACR,WAAA,CAAa,CAEX,UAAA,CAAY,cAAA,CAGZ,QAAA,CAAU,mBACZ,CAAA,CACA,QAAA,CAAU,CACR,KAAA,CAAO,EAAA,CACP,MAAA,CAAQ,EAAA,CACR,IAAA,CAAM,EAAA,CACN,IAAA,CAAM,EACR,CACF,CAAA,CACA,gBAAA,CAAkB,CAIhB,CACE,WAAA,CAAa,YAAA,CACb,QAAA,CAAU,OAAA,CACV,SAAA,CAAW,2BACb,CAAA,CACA,CACE,WAAA,CAAa,YAAA,CACb,QAAA,CAAU,QAAA,CACV,SAAA,CAAW,yBACb,CAAA,CACA,CACE,WAAA,CAAa,YAAA,CACb,QAAA,CAAU,MAAA,CACV,SAAA,CAAW,gBACb,CAAA,CAKA,CACE,WAAA,CAAa,UAAA,CACb,QAAA,CAAU,OAAA,CACV,SAAA,CAAW,2BACb,CAAA,CACA,CACE,WAAA,CAAa,UAAA,CACb,QAAA,CAAU,QAAA,CACV,SAAA,CAAW,yBACb,CAAA,CACA,CACE,YAAa,UAAA,CACb,QAAA,CAAU,MAAA,CACV,SAAA,CAAW,gBACb,CACF,CAAA,CACA,eAAA,CAAiB,CACf,WAAA,CAAa,YAAA,CACb,QAAA,CAAU,MACZ,CACF,CAAC,CAAA,CAUYE,CAAAA,CAA+BF,GAAAA,CAAI,oBAAA,CAAsB,CACpE,QAAA,CAAU,CACR,WAAA,CAAa,CACX,UAAA,CAAY,eAAA,CACZ,QAAA,CAAU,kBACZ,CACF,CAAA,CACA,eAAA,CAAiB,CACf,YAAa,YACf,CACF,CAAC,ECtGM,IAAMG,CAAAA,CAAmBC,CAAAA,EACzBC,cAAAA,CAAeD,CAAK,CAAA,CAEHA,CAAAA,CAAM,IAAA,EACN,WAAA,GAAgB,QAAA,CAHH,KAAA,CAaxBE,CAAAA,CAAsBF,CAAAA,EAC5BC,cAAAA,CAAeD,CAAK,CAAA,CAEHA,CAAAA,CAAM,IAAA,EACN,WAAA,GAAgB,sBAAA,CAHH,KAAA,CAwBxBG,CAAAA,CAAc,CAACC,CAAAA,CAAeC,IACrCA,CAAAA,GAAU,CAAA,CAAU,MAAA,CACpBD,CAAAA,GAAU,CAAA,CAAU,OAAA,CACpBA,CAAAA,GAAUC,CAAAA,CAAQ,CAAA,CAAU,MAAA,CACzB,QAAA,CAUIC,CAAAA,CAAwBC,CAAAA,EAC5BA,CAAAA,CAAS,MAAA,CAAOR,CAAe,CAAA,CAW3BS,CAAAA,CAAiB,CAC5BR,CAAAA,CACAS,CAAAA,GAEOA,CAAAA,CAAe,OAAA,CAAQT,CAAK,EC7CrC,IAAMU,CAAAA,CAAcC,UAAAA,CAClB,CACE,CACE,WAAA,CAAAC,CAAAA,CAAc,YAAA,CACd,OAAA,CAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CAAAA,CACA,SAAA,CAAAC,CAAAA,CACA,QAAA,CAAAT,CAAAA,CACA,GAAGU,CACL,CAAA,CACAC,CAAAA,GACiB,CAEjB,IAAMC,CAAAA,CAAaC,QAAAA,CAAS,OAAA,CAAQb,CAAQ,CAAA,CAGtCE,CAAAA,CAAiBU,CAAAA,CAAW,MAAA,CAAOpB,CAAe,CAAA,CAClDsB,CAAAA,CAAeZ,CAAAA,CAAe,MAAA,CAG9Ba,EAAoB,CACxB,WAAA,CAAAV,CAAAA,CACA,OAAA,CAAAC,CAAAA,CACA,IAAA,CAAAC,CAAAA,CACA,UAAA,CAAAC,CACF,CAAA,CAGMQ,CAAAA,CAAkBJ,CAAAA,CAAW,GAAA,CAAI,CAACnB,CAAAA,CAAOI,CAAAA,GAAU,CAEvD,GAAIL,CAAAA,CAAgBC,CAAK,CAAA,CAAG,CAC1B,IAAMwB,CAAAA,CAAcf,CAAAA,CAAe,OAAA,CAAQT,CAAK,CAAA,CAC1CyB,CAAAA,CAAWtB,CAAAA,CAAYqB,CAAAA,CAAaH,CAAY,EAEtD,OACEK,GAAAA,CAACjC,CAAAA,CAAuB,QAAA,CAAvB,CAEC,KAAA,CAAO,CAAE,QAAA,CAAAgC,CAAS,CAAA,CAEjB,QAAA,CAAAzB,CAAAA,CAAAA,CAHII,CAIP,CAEJ,CAGA,OAAOJ,CACT,CAAC,CAAA,CAED,OACE0B,GAAAA,CAACC,OAAAA,CAAA,CACC,GAAA,CAAKT,CAAAA,CACL,WAAA,CAAaN,CAAAA,CACb,YAAA,CAAYK,CAAAA,CAAM,YAAY,CAAA,CAC9B,iBAAA,CAAiBA,EAAM,iBAAiB,CAAA,CACxC,SAAA,CAAWhC,CAAAA,CAAGU,CAAAA,CAAoB,CAAE,WAAA,CAAAiB,CAAY,CAAC,CAAA,CAAGI,CAAS,CAAA,CAE7D,QAAA,CAAAU,GAAAA,CAACrC,CAAAA,CAAmB,QAAA,CAAnB,CAA4B,KAAA,CAAOiC,CAAAA,CACjC,QAAA,CAAAC,CAAAA,CACH,CAAA,CACF,CAEJ,CACF,EAEAb,CAAAA,CAAY,WAAA,CAAc,aAAA,CAyB1B,IAAMkB,CAAAA,CAAuBjB,UAAAA,CAC3B,CAAC,CAAE,SAAA,CAAAK,CAAAA,CAAW,GAAGC,CAAM,CAAA,CAAGC,CAAAA,GAAsB,CAE9C,IAAMN,CAAAA,CADerB,CAAAA,EAAsB,EACT,WAAA,EAAe,YAAA,CAEjD,OACEmC,GAAAA,CAAC,KAAA,CAAA,CACC,GAAA,CAAKR,CAAAA,CACL,IAAA,CAAK,WAAA,CACL,aAAA,CAAY,MAAA,CACZ,SAAA,CAAWjC,CAAAA,CACTa,CAAAA,CAA6B,CAAE,WAAA,CAAAc,CAAY,CAAC,CAAA,CAC5CI,CACF,CAAA,CACC,GAAGC,CAAAA,CACN,CAEJ,CACF,EAEAW,CAAAA,CAAqB,WAAA,CAAc,sBAAA,CCxG5B,IAAMC,CAAAA,CAAyBC,CAAAA,CAAE,MAAA,CAAO,CAE7C,WAAA,CAAaA,CAAAA,CACV,IAAA,CAAK,CAAC,YAAA,CAAc,UAAU,CAAC,CAAA,CAC/B,QAAA,EAAS,CACT,OAAA,CAAQ,YAAY,CAAA,CAGvB,OAAA,CAASA,CAAAA,CACN,IAAA,CAAK,CAAC,SAAA,CAAW,aAAA,CAAe,SAAA,CAAW,WAAA,CAAa,OAAO,CAAC,CAAA,CAChE,QAAA,EAAS,CAGZ,IAAA,CAAMA,CAAAA,CAAE,IAAA,CAAK,CAAC,IAAA,CAAM,SAAA,CAAW,IAAA,CAAM,MAAM,CAAC,CAAA,CAAE,QAAA,EAAS,CAGvD,UAAA,CAAYA,CAAAA,CAAE,OAAA,EAAQ,CAAE,QAAA,EAAS,CAGjC,YAAA,CAAcA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,GAGzB,iBAAA,CAAmBA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAGvC,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAG/B,QAAA,CAAUA,CAAAA,CAAE,MAAA,EACd,CAAC,CAAA,CAMYC,CAAAA,CAAkCD,CAAAA,CAAE,MAAA,CAAO,CAEtD,SAAA,CAAWA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAAS,CAE/B,aAAA,CAAeA,CAAAA,CAAE,MAAA,EAAO,CAAE,QAAA,EAC5B,CAAC","file":"index.mjs","sourcesContent":["/**\n * Class Name Utility\n * Merges Tailwind CSS classes with conflict resolution\n *\n * Combines clsx for conditional classes and tailwind-merge for deduplication\n *\n * @example\n * cn('px-2 py-1', 'px-4') // => 'py-1 px-4' (px-4 overrides px-2)\n * cn('text-red-500', condition && 'text-blue-500') // => conditional application\n */\n\nimport { clsx, type ClassValue } from 'clsx';\nimport { twMerge } from 'tailwind-merge';\n\nexport function cn(...inputs: ClassValue[]): string {\n return twMerge(clsx(inputs));\n}\n","\"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","import { isValidElement, type ReactNode, type ComponentType } from 'react';\nimport type { ButtonPosition } from './ButtonGroup.types';\n\n/**\n * ButtonGroup Utility Functions\n *\n * Provides helper functions for:\n * - Child element detection (Button vs Separator vs other)\n * - Position calculation for border-radius styling\n *\n * @see plan.md Decision 6: Non-Button Child Handling\n */\n\n// =============================================================================\n// Child Detection Functions\n// =============================================================================\n\n/**\n * Checks if a React child is a Themis Button component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a Button component\n */\nexport const isButtonElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'Button';\n};\n\n/**\n * Checks if a React child is a ButtonGroupSeparator component\n * Uses displayName for reliable detection across module boundaries\n *\n * @param child - React child element to check\n * @returns true if the child is a ButtonGroupSeparator component\n */\nexport const isSeparatorElement = (child: ReactNode): boolean => {\n if (!isValidElement(child)) return false;\n\n const componentType = child.type as ComponentType;\n return componentType?.displayName === 'ButtonGroupSeparator';\n};\n\n// =============================================================================\n// Position Calculation\n// =============================================================================\n\n/**\n * Calculates the position of a button within a group\n * Used for applying position-aware border-radius styling\n *\n * @param index - Zero-based index of the button\n * @param total - Total number of buttons in the group\n * @returns Position enum: 'only' | 'first' | 'last' | 'middle'\n *\n * @example\n * getPosition(0, 1) // 'only' - single button\n * getPosition(0, 3) // 'first'\n * getPosition(1, 3) // 'middle'\n * getPosition(2, 3) // 'last'\n */\nexport const getPosition = (index: number, total: number): ButtonPosition => {\n if (total === 1) return 'only';\n if (index === 0) return 'first';\n if (index === total - 1) return 'last';\n return 'middle';\n};\n\n/**\n * Filters an array of React children to only include Button elements\n * Non-Button children (Separators, custom elements) are excluded\n *\n * @param children - Array of React children\n * @returns Array containing only Button elements\n */\nexport const filterButtonChildren = (children: ReactNode[]): ReactNode[] => {\n return children.filter(isButtonElement);\n};\n\n/**\n * Gets the index of a button within the filtered button array\n * Used when the child array contains non-Button elements (Separators, etc.)\n *\n * @param child - The button element to find\n * @param buttonChildren - Array of only Button elements\n * @returns Index of the button, or -1 if not found\n */\nexport const getButtonIndex = (\n child: ReactNode,\n buttonChildren: ReactNode[]\n): number => {\n return buttonChildren.indexOf(child);\n};\n","\"use client\";\n\n/**\n * ButtonGroup Component\n *\n * A container that groups related Themis Button components with:\n * - Consistent styling (connected borders, position-aware radii)\n * - Accessible keyboard navigation (React Aria Toolbar)\n * - WCAG 2.2 AAA compliance\n *\n * @see plan.md for architecture details\n * @see buttongroup-prd.md for requirements\n */\n\nimport { forwardRef, Children, type ReactElement } from 'react';\nimport { Toolbar } from 'react-aria-components';\nimport { cn } from '../../utils/cn';\nimport {\n ButtonGroupContext,\n ButtonGroupItemContext,\n useButtonGroupContext,\n} from './ButtonGroupContext';\nimport { buttonGroupVariants, buttonGroupSeparatorVariants } from './ButtonGroup.variants';\nimport { isButtonElement, getPosition } from './ButtonGroup.utils';\nimport type { ButtonGroupProps, ButtonGroupSeparatorProps } from './ButtonGroup.types';\n\n// =============================================================================\n// ButtonGroup Component\n// =============================================================================\n\n/**\n * ButtonGroup - Groups related buttons with connected styling and keyboard navigation\n *\n * Uses React Aria's Toolbar for:\n * - Roving tabindex (single tab stop)\n * - Arrow key navigation\n * - Home/End key support\n * - RTL support\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Text formatting\">\n * <Button variant=\"outline\">Bold</Button>\n * <Button variant=\"outline\">Italic</Button>\n * <Button variant=\"outline\">Underline</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroup = forwardRef<HTMLDivElement, ButtonGroupProps>(\n (\n {\n orientation = 'horizontal',\n variant,\n size,\n isDisabled,\n className,\n children,\n ...props\n },\n ref\n ): ReactElement => {\n // Convert children to array for enumeration\n const childArray = Children.toArray(children);\n\n // Filter to get only Button elements for position calculation\n const buttonChildren = childArray.filter(isButtonElement);\n const totalButtons = buttonChildren.length;\n\n // Create context value for group-level props\n const groupContextValue = {\n orientation,\n variant,\n size,\n isDisabled,\n };\n\n // Wrap each child with appropriate context\n const wrappedChildren = childArray.map((child, index) => {\n // If it's a Button, wrap with item context for position\n if (isButtonElement(child)) {\n const buttonIndex = buttonChildren.indexOf(child);\n const position = getPosition(buttonIndex, totalButtons);\n\n return (\n <ButtonGroupItemContext.Provider\n key={index}\n value={{ position }}\n >\n {child}\n </ButtonGroupItemContext.Provider>\n );\n }\n\n // Non-Button children (Separators, etc.) pass through without item context\n return child;\n });\n\n return (\n <Toolbar\n ref={ref}\n orientation={orientation}\n aria-label={props['aria-label']}\n aria-labelledby={props['aria-labelledby']}\n className={cn(buttonGroupVariants({ orientation }), className)}\n >\n <ButtonGroupContext.Provider value={groupContextValue}>\n {wrappedChildren}\n </ButtonGroupContext.Provider>\n </Toolbar>\n );\n }\n);\n\nButtonGroup.displayName = 'ButtonGroup';\n\n// =============================================================================\n// ButtonGroupSeparator Component\n// =============================================================================\n\n/**\n * ButtonGroupSeparator - Visual divider between button groups\n *\n * Renders a decorative separator that:\n * - Adapts to orientation (vertical line for horizontal, horizontal for vertical)\n * - Is hidden from screen readers (aria-hidden)\n * - Is excluded from keyboard navigation\n *\n * @example\n * ```tsx\n * <ButtonGroup aria-label=\"Editor actions\">\n * <Button>Undo</Button>\n * <Button>Redo</Button>\n * <ButtonGroupSeparator />\n * <Button>Cut</Button>\n * <Button>Copy</Button>\n * </ButtonGroup>\n * ```\n */\nconst ButtonGroupSeparator = forwardRef<HTMLDivElement, ButtonGroupSeparatorProps>(\n ({ className, ...props }, ref): ReactElement => {\n const groupContext = useButtonGroupContext();\n const orientation = groupContext?.orientation ?? 'horizontal';\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n aria-hidden=\"true\"\n className={cn(\n buttonGroupSeparatorVariants({ orientation }),\n className\n )}\n {...props}\n />\n );\n }\n);\n\nButtonGroupSeparator.displayName = 'ButtonGroupSeparator';\n\n// =============================================================================\n// Exports\n// =============================================================================\n\nexport { ButtonGroup, ButtonGroupSeparator };\n","import { z } from 'zod';\nimport type { ReactNode } from 'react';\n\n/**\n * ButtonGroup Component Types\n *\n * Defines Zod schemas and TypeScript types for the ButtonGroup component.\n * Uses a two-level context pattern:\n * - ButtonGroupContext: Group-level props (orientation, variant, size, isDisabled)\n * - ButtonGroupItemContext: Per-button position information\n *\n * @see plan.md for architecture details\n * @see constitution.md Principle II (Type Safety First)\n */\n\n// =============================================================================\n// Core Types\n// =============================================================================\n\n/**\n * Orientation of the button group\n */\nexport type ButtonGroupOrientation = 'horizontal' | 'vertical';\n\n/**\n * Position of a button within the group\n * Used for position-aware border-radius styling\n */\nexport type ButtonPosition = 'first' | 'middle' | 'last' | 'only';\n\n/**\n * Button variants (matches Themis Button variants, excluding 'link')\n * Link variant is excluded as it doesn't make sense in a grouped context\n */\nexport type ButtonGroupVariant =\n | 'default'\n | 'destructive'\n | 'outline'\n | 'secondary'\n | 'ghost';\n\n/**\n * Button sizes (matches Themis Button sizes)\n */\nexport type ButtonGroupSize = 'sm' | 'default' | 'lg' | 'icon';\n\n// =============================================================================\n// Zod Schemas\n// =============================================================================\n\n/**\n * ButtonGroup props schema\n * Validates all props for the ButtonGroup container component\n */\nexport const ButtonGroupPropsSchema = z.object({\n /** Orientation of the button group layout */\n orientation: z\n .enum(['horizontal', 'vertical'])\n .optional()\n .default('horizontal'),\n\n /** Default variant for all child buttons (can be overridden per-button) */\n variant: z\n .enum(['default', 'destructive', 'outline', 'secondary', 'ghost'])\n .optional(),\n\n /** Default size for all child buttons (can be overridden per-button) */\n size: z.enum(['sm', 'default', 'lg', 'icon']).optional(),\n\n /** Disable all buttons in the group */\n isDisabled: z.boolean().optional(),\n\n /** Accessible label for the toolbar (recommended) */\n 'aria-label': z.string().optional(),\n\n /** ID of element that labels the toolbar */\n 'aria-labelledby': z.string().optional(),\n\n /** Additional CSS classes */\n className: z.string().optional(),\n\n /** Child elements (Buttons, Separators, etc.) */\n children: z.custom<ReactNode>(),\n});\n\n/**\n * ButtonGroupSeparator props schema\n * Validates props for the visual separator between button groups\n */\nexport const ButtonGroupSeparatorPropsSchema = z.object({\n /** Additional CSS classes */\n className: z.string().optional(),\n /** Test ID for testing */\n 'data-testid': z.string().optional(),\n});\n\n// =============================================================================\n// TypeScript Types (inferred from schemas)\n// =============================================================================\n\n/**\n * Props for the ButtonGroup container component\n */\nexport interface ButtonGroupProps {\n orientation?: ButtonGroupOrientation;\n variant?: ButtonGroupVariant;\n size?: ButtonGroupSize;\n isDisabled?: boolean;\n 'aria-label'?: string;\n 'aria-labelledby'?: string;\n className?: string;\n children?: ReactNode;\n}\n\nexport interface ButtonGroupSeparatorProps {\n className?: string;\n 'data-testid'?: string;\n}\n\n// =============================================================================\n// Context Types\n// =============================================================================\n\n/**\n * Group-level context value\n * Provides inherited props to all child buttons\n */\nexport interface ButtonGroupContextValue {\n /** Orientation of the group (affects keyboard navigation and styling) */\n orientation: ButtonGroupOrientation;\n /** Default variant for buttons (can be overridden) */\n variant?: ButtonGroupVariant;\n /** Default size for buttons (can be overridden) */\n size?: ButtonGroupSize;\n /** Whether all buttons in the group are disabled */\n isDisabled?: boolean;\n}\n\n/**\n * Item-level context value\n * Provides position information to each button for border-radius styling\n */\nexport interface ButtonGroupItemContextValue {\n /** Position of this button in the group */\n position: ButtonPosition;\n}\n"]}
|
|
@@ -7,98 +7,13 @@
|
|
|
7
7
|
* @see card-prd.md (Product Requirements)
|
|
8
8
|
* @see plan.md (Implementation Plan)
|
|
9
9
|
*/
|
|
10
|
-
import { type HTMLAttributes
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
'aria-hidden'?: boolean | undefined;
|
|
20
|
-
'data-testid'?: string | undefined;
|
|
21
|
-
flippable?: boolean | undefined;
|
|
22
|
-
backContent?: ReactNode;
|
|
23
|
-
isFlipped?: boolean | undefined;
|
|
24
|
-
defaultFlipped?: boolean | undefined;
|
|
25
|
-
onFlipChange?: ((isFlipped: boolean) => void) | undefined;
|
|
26
|
-
flipButtonPosition?: "top-right" | "top-left" | "bottom-right" | "bottom-left" | undefined;
|
|
27
|
-
flipButtonLabel?: {
|
|
28
|
-
show?: string | undefined;
|
|
29
|
-
hide?: string | undefined;
|
|
30
|
-
} | undefined;
|
|
31
|
-
flipButtonIcon?: {
|
|
32
|
-
front?: ReactNode;
|
|
33
|
-
back?: ReactNode;
|
|
34
|
-
} | undefined;
|
|
35
|
-
flipDuration?: number | undefined;
|
|
36
|
-
} & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
37
|
-
export declare const CardHeader: import("react").ForwardRefExoticComponent<{
|
|
38
|
-
children: ReactNode;
|
|
39
|
-
className?: string | undefined;
|
|
40
|
-
id?: string | undefined;
|
|
41
|
-
'aria-label'?: string | undefined;
|
|
42
|
-
'aria-labelledby'?: string | undefined;
|
|
43
|
-
'aria-describedby'?: string | undefined;
|
|
44
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
45
|
-
'aria-hidden'?: boolean | undefined;
|
|
46
|
-
'data-testid'?: string | undefined;
|
|
47
|
-
} & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
48
|
-
export declare const CardTitle: import("react").ForwardRefExoticComponent<{
|
|
49
|
-
children: ReactNode;
|
|
50
|
-
className?: string | undefined;
|
|
51
|
-
id?: string | undefined;
|
|
52
|
-
'aria-label'?: string | undefined;
|
|
53
|
-
'aria-labelledby'?: string | undefined;
|
|
54
|
-
'aria-describedby'?: string | undefined;
|
|
55
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
56
|
-
'aria-hidden'?: boolean | undefined;
|
|
57
|
-
'data-testid'?: string | undefined;
|
|
58
|
-
as?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | undefined;
|
|
59
|
-
} & HTMLAttributes<HTMLHeadingElement> & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
60
|
-
export declare const CardDescription: import("react").ForwardRefExoticComponent<{
|
|
61
|
-
children: ReactNode;
|
|
62
|
-
className?: string | undefined;
|
|
63
|
-
id?: string | undefined;
|
|
64
|
-
'aria-label'?: string | undefined;
|
|
65
|
-
'aria-labelledby'?: string | undefined;
|
|
66
|
-
'aria-describedby'?: string | undefined;
|
|
67
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
68
|
-
'aria-hidden'?: boolean | undefined;
|
|
69
|
-
'data-testid'?: string | undefined;
|
|
70
|
-
} & HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
71
|
-
export declare const CardContent: import("react").ForwardRefExoticComponent<{
|
|
72
|
-
children: ReactNode;
|
|
73
|
-
className?: string | undefined;
|
|
74
|
-
id?: string | undefined;
|
|
75
|
-
'aria-label'?: string | undefined;
|
|
76
|
-
'aria-labelledby'?: string | undefined;
|
|
77
|
-
'aria-describedby'?: string | undefined;
|
|
78
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
79
|
-
'aria-hidden'?: boolean | undefined;
|
|
80
|
-
'data-testid'?: string | undefined;
|
|
81
|
-
} & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
82
|
-
export declare const CardFooter: import("react").ForwardRefExoticComponent<{
|
|
83
|
-
children: ReactNode;
|
|
84
|
-
className?: string | undefined;
|
|
85
|
-
id?: string | undefined;
|
|
86
|
-
'aria-label'?: string | undefined;
|
|
87
|
-
'aria-labelledby'?: string | undefined;
|
|
88
|
-
'aria-describedby'?: string | undefined;
|
|
89
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
90
|
-
'aria-hidden'?: boolean | undefined;
|
|
91
|
-
'data-testid'?: string | undefined;
|
|
92
|
-
} & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
93
|
-
export declare const CardAction: import("react").ForwardRefExoticComponent<{
|
|
94
|
-
children: ReactNode;
|
|
95
|
-
className?: string | undefined;
|
|
96
|
-
id?: string | undefined;
|
|
97
|
-
'aria-label'?: string | undefined;
|
|
98
|
-
'aria-labelledby'?: string | undefined;
|
|
99
|
-
'aria-describedby'?: string | undefined;
|
|
100
|
-
'aria-live'?: "off" | "polite" | "assertive" | undefined;
|
|
101
|
-
'aria-hidden'?: boolean | undefined;
|
|
102
|
-
'data-testid'?: string | undefined;
|
|
103
|
-
} & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
10
|
+
import { type HTMLAttributes } from 'react';
|
|
11
|
+
import { type CardProps, type CardHeaderProps, type CardTitleProps, type CardDescriptionProps, type CardContentProps, type CardFooterProps, type CardActionProps } from './Card.types';
|
|
12
|
+
export declare const Card: import("react").ForwardRefExoticComponent<CardProps & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
13
|
+
export declare const CardHeader: import("react").ForwardRefExoticComponent<CardHeaderProps & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
14
|
+
export declare const CardTitle: import("react").ForwardRefExoticComponent<CardTitleProps & HTMLAttributes<HTMLHeadingElement> & import("react").RefAttributes<HTMLHeadingElement>>;
|
|
15
|
+
export declare const CardDescription: import("react").ForwardRefExoticComponent<CardDescriptionProps & HTMLAttributes<HTMLParagraphElement> & import("react").RefAttributes<HTMLParagraphElement>>;
|
|
16
|
+
export declare const CardContent: import("react").ForwardRefExoticComponent<CardContentProps & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export declare const CardFooter: import("react").ForwardRefExoticComponent<CardFooterProps & HTMLAttributes<HTMLElement> & import("react").RefAttributes<HTMLElement>>;
|
|
18
|
+
export declare const CardAction: import("react").ForwardRefExoticComponent<CardActionProps & HTMLAttributes<HTMLDivElement> & import("react").RefAttributes<HTMLDivElement>>;
|
|
104
19
|
//# sourceMappingURL=Card.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/elements/Card/Card.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAqC,KAAK,cAAc,
|
|
1
|
+
{"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/elements/Card/Card.tsx"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AAEH,OAAO,EAAqC,KAAK,cAAc,EAAkB,MAAM,OAAO,CAAC;AAI/F,OAAO,EAEL,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,eAAe,EACpB,KAAK,eAAe,EACrB,MAAM,cAAc,CAAC;AAMtB,eAAO,MAAM,IAAI,iIAqHhB,CAAC;AAQF,eAAO,MAAM,UAAU,uIAUtB,CAAC;AAQF,eAAO,MAAM,SAAS,oJAUrB,CAAC;AAQF,eAAO,MAAM,eAAe,8JAU3B,CAAC;AAQF,eAAO,MAAM,WAAW,8IAMvB,CAAC;AAQF,eAAO,MAAM,UAAU,uIAUtB,CAAC;AAQF,eAAO,MAAM,UAAU,6IAUtB,CAAC"}
|
|
@@ -54,17 +54,17 @@ export declare const CardPropsSchema: z.ZodObject<{
|
|
|
54
54
|
}>>;
|
|
55
55
|
'aria-hidden': z.ZodOptional<z.ZodBoolean>;
|
|
56
56
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
57
|
-
flippable: z.
|
|
57
|
+
flippable: z.ZodOptional<z.ZodBoolean>;
|
|
58
58
|
backContent: z.ZodOptional<z.ZodCustom<ReactNode, ReactNode>>;
|
|
59
59
|
isFlipped: z.ZodOptional<z.ZodBoolean>;
|
|
60
|
-
defaultFlipped: z.
|
|
60
|
+
defaultFlipped: z.ZodOptional<z.ZodBoolean>;
|
|
61
61
|
onFlipChange: z.ZodOptional<z.ZodCustom<(isFlipped: boolean) => void, (isFlipped: boolean) => void>>;
|
|
62
|
-
flipButtonPosition: z.
|
|
62
|
+
flipButtonPosition: z.ZodOptional<z.ZodEnum<{
|
|
63
63
|
"top-right": "top-right";
|
|
64
64
|
"top-left": "top-left";
|
|
65
65
|
"bottom-right": "bottom-right";
|
|
66
66
|
"bottom-left": "bottom-left";
|
|
67
|
-
}
|
|
67
|
+
}>>;
|
|
68
68
|
flipButtonLabel: z.ZodOptional<z.ZodObject<{
|
|
69
69
|
show: z.ZodOptional<z.ZodString>;
|
|
70
70
|
hide: z.ZodOptional<z.ZodString>;
|
|
@@ -73,14 +73,32 @@ export declare const CardPropsSchema: z.ZodObject<{
|
|
|
73
73
|
front: z.ZodOptional<z.ZodCustom<ReactNode, ReactNode>>;
|
|
74
74
|
back: z.ZodOptional<z.ZodCustom<ReactNode, ReactNode>>;
|
|
75
75
|
}, z.core.$strip>>;
|
|
76
|
-
flipDuration: z.
|
|
76
|
+
flipDuration: z.ZodOptional<z.ZodNumber>;
|
|
77
77
|
}, z.core.$strip>;
|
|
78
78
|
/**
|
|
79
|
-
*
|
|
80
|
-
* z.infer
|
|
81
|
-
* should not need to pass flippable, flipDuration, etc. on every Card.
|
|
79
|
+
* Explicit interface to avoid Zod 4 d.ts inference issues where
|
|
80
|
+
* z.infer resolves optional fields as required through complex generics.
|
|
82
81
|
*/
|
|
83
|
-
export
|
|
82
|
+
export interface CardProps {
|
|
83
|
+
className?: string;
|
|
84
|
+
children?: ReactNode;
|
|
85
|
+
id?: string;
|
|
86
|
+
'aria-label'?: string;
|
|
87
|
+
'aria-labelledby'?: string;
|
|
88
|
+
'aria-describedby'?: string;
|
|
89
|
+
'aria-live'?: 'off' | 'polite' | 'assertive';
|
|
90
|
+
'aria-hidden'?: boolean;
|
|
91
|
+
'data-testid'?: string;
|
|
92
|
+
flippable?: boolean;
|
|
93
|
+
backContent?: ReactNode;
|
|
94
|
+
isFlipped?: boolean;
|
|
95
|
+
defaultFlipped?: boolean;
|
|
96
|
+
onFlipChange?: (isFlipped: boolean) => void;
|
|
97
|
+
flipButtonPosition?: FlipButtonPosition;
|
|
98
|
+
flipButtonLabel?: FlipButtonLabel;
|
|
99
|
+
flipButtonIcon?: FlipButtonIcon;
|
|
100
|
+
flipDuration?: number;
|
|
101
|
+
}
|
|
84
102
|
/**
|
|
85
103
|
* CardHeader props schema
|
|
86
104
|
*
|
|
@@ -101,7 +119,15 @@ export declare const CardHeaderPropsSchema: z.ZodObject<{
|
|
|
101
119
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
102
120
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
103
121
|
}, z.core.$strip>;
|
|
104
|
-
export
|
|
122
|
+
export interface CardHeaderProps {
|
|
123
|
+
className?: string;
|
|
124
|
+
children?: ReactNode;
|
|
125
|
+
id?: string;
|
|
126
|
+
'aria-label'?: string;
|
|
127
|
+
'aria-labelledby'?: string;
|
|
128
|
+
'aria-describedby'?: string;
|
|
129
|
+
'data-testid'?: string;
|
|
130
|
+
}
|
|
105
131
|
/**
|
|
106
132
|
* CardTitle props schema
|
|
107
133
|
*
|
|
@@ -120,17 +146,23 @@ export declare const CardTitlePropsSchema: z.ZodObject<{
|
|
|
120
146
|
}>>;
|
|
121
147
|
'aria-hidden': z.ZodOptional<z.ZodBoolean>;
|
|
122
148
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
123
|
-
as: z.
|
|
149
|
+
as: z.ZodOptional<z.ZodEnum<{
|
|
124
150
|
h1: "h1";
|
|
125
151
|
h2: "h2";
|
|
126
152
|
h3: "h3";
|
|
127
153
|
h4: "h4";
|
|
128
154
|
h5: "h5";
|
|
129
155
|
h6: "h6";
|
|
130
|
-
}
|
|
156
|
+
}>>;
|
|
131
157
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
132
158
|
}, z.core.$strip>;
|
|
133
|
-
export
|
|
159
|
+
export interface CardTitleProps {
|
|
160
|
+
className?: string;
|
|
161
|
+
children?: ReactNode;
|
|
162
|
+
as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
|
163
|
+
id?: string;
|
|
164
|
+
'data-testid'?: string;
|
|
165
|
+
}
|
|
134
166
|
/**
|
|
135
167
|
* CardDescription props schema
|
|
136
168
|
*
|
|
@@ -151,7 +183,12 @@ export declare const CardDescriptionPropsSchema: z.ZodObject<{
|
|
|
151
183
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
152
184
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
153
185
|
}, z.core.$strip>;
|
|
154
|
-
export
|
|
186
|
+
export interface CardDescriptionProps {
|
|
187
|
+
className?: string;
|
|
188
|
+
children?: ReactNode;
|
|
189
|
+
id?: string;
|
|
190
|
+
'data-testid'?: string;
|
|
191
|
+
}
|
|
155
192
|
/**
|
|
156
193
|
* CardContent props schema
|
|
157
194
|
*
|
|
@@ -172,7 +209,12 @@ export declare const CardContentPropsSchema: z.ZodObject<{
|
|
|
172
209
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
173
210
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
174
211
|
}, z.core.$strip>;
|
|
175
|
-
export
|
|
212
|
+
export interface CardContentProps {
|
|
213
|
+
className?: string;
|
|
214
|
+
children?: ReactNode;
|
|
215
|
+
id?: string;
|
|
216
|
+
'data-testid'?: string;
|
|
217
|
+
}
|
|
176
218
|
/**
|
|
177
219
|
* CardFooter props schema
|
|
178
220
|
*
|
|
@@ -193,7 +235,12 @@ export declare const CardFooterPropsSchema: z.ZodObject<{
|
|
|
193
235
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
194
236
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
195
237
|
}, z.core.$strip>;
|
|
196
|
-
export
|
|
238
|
+
export interface CardFooterProps {
|
|
239
|
+
className?: string;
|
|
240
|
+
children?: ReactNode;
|
|
241
|
+
id?: string;
|
|
242
|
+
'data-testid'?: string;
|
|
243
|
+
}
|
|
197
244
|
/**
|
|
198
245
|
* CardAction props schema
|
|
199
246
|
*
|
|
@@ -214,7 +261,12 @@ export declare const CardActionPropsSchema: z.ZodObject<{
|
|
|
214
261
|
'data-testid': z.ZodOptional<z.ZodString>;
|
|
215
262
|
children: z.ZodCustom<ReactNode, ReactNode>;
|
|
216
263
|
}, z.core.$strip>;
|
|
217
|
-
export
|
|
264
|
+
export interface CardActionProps {
|
|
265
|
+
className?: string;
|
|
266
|
+
children?: ReactNode;
|
|
267
|
+
id?: string;
|
|
268
|
+
'data-testid'?: string;
|
|
269
|
+
}
|
|
218
270
|
/**
|
|
219
271
|
* CVA variants for flip button positioning
|
|
220
272
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Card.types.d.ts","sourceRoot":"","sources":["../../../src/elements/Card/Card.types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAGxB,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC;;;;;GAKG;AACH,eAAO,MAAM,wBAAwB;;;;;EAKnC,CAAC;AACH,MAAM,MAAM,kBAAkB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC;AAE1E;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB;;;iBAGhC,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC;AAEpE;;;GAGG;AACH,eAAO,MAAM,oBAAoB;;;iBAK/B,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;wDAeS,OAAO,KAAK,IAAI,cAAhB,OAAO,KAAK,IAAI;;;;;;;;;;;;;;;;iBAcnD,CAAC;AAEH
|
|
1
|
+
{"version":3,"file":"Card.types.d.ts","sourceRoot":"","sources":["../../../src/elements/Card/Card.types.ts"],"names":[],"mappings":"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"}
|