@brycks/core-front 0.3.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (168) hide show
  1. package/dist/components/data/List/List.cjs +1 -1
  2. package/dist/components/data/List/List.cjs.map +1 -1
  3. package/dist/components/data/List/List.js +1 -1
  4. package/dist/components/data/List/List.js.map +1 -1
  5. package/dist/components/data/Table/Table.cjs +1 -1
  6. package/dist/components/data/Table/Table.cjs.map +1 -1
  7. package/dist/components/data/Table/Table.js +196 -166
  8. package/dist/components/data/Table/Table.js.map +1 -1
  9. package/dist/components/data/TreeView/TreeView.cjs +1 -1
  10. package/dist/components/data/TreeView/TreeView.cjs.map +1 -1
  11. package/dist/components/data/TreeView/TreeView.js +1 -1
  12. package/dist/components/data/TreeView/TreeView.js.map +1 -1
  13. package/dist/components/data.cjs +1 -1
  14. package/dist/components/data.js +23 -21
  15. package/dist/components/feedback/Alert/Alert.cjs +1 -1
  16. package/dist/components/feedback/Alert/Alert.cjs.map +1 -1
  17. package/dist/components/feedback/Alert/Alert.js +20 -19
  18. package/dist/components/feedback/Alert/Alert.js.map +1 -1
  19. package/dist/components/feedback/Banner/Banner.cjs +2 -0
  20. package/dist/components/feedback/Banner/Banner.cjs.map +1 -0
  21. package/dist/components/feedback/Banner/Banner.js +77 -0
  22. package/dist/components/feedback/Banner/Banner.js.map +1 -0
  23. package/dist/components/feedback/ConfirmDialog/ConfirmDialog.cjs +2 -0
  24. package/dist/components/feedback/ConfirmDialog/ConfirmDialog.cjs.map +1 -0
  25. package/dist/components/feedback/ConfirmDialog/ConfirmDialog.js +68 -0
  26. package/dist/components/feedback/ConfirmDialog/ConfirmDialog.js.map +1 -0
  27. package/dist/components/feedback/Drawer/Drawer.cjs +2 -2
  28. package/dist/components/feedback/Drawer/Drawer.cjs.map +1 -1
  29. package/dist/components/feedback/Drawer/Drawer.js +58 -57
  30. package/dist/components/feedback/Drawer/Drawer.js.map +1 -1
  31. package/dist/components/feedback/Modal/Modal.cjs +1 -1
  32. package/dist/components/feedback/Modal/Modal.cjs.map +1 -1
  33. package/dist/components/feedback/Modal/Modal.js +101 -91
  34. package/dist/components/feedback/Modal/Modal.js.map +1 -1
  35. package/dist/components/feedback/Popover/Popover.cjs +2 -2
  36. package/dist/components/feedback/Popover/Popover.cjs.map +1 -1
  37. package/dist/components/feedback/Popover/Popover.js +93 -85
  38. package/dist/components/feedback/Popover/Popover.js.map +1 -1
  39. package/dist/components/feedback/Toast/Toast.cjs +2 -2
  40. package/dist/components/feedback/Toast/Toast.cjs.map +1 -1
  41. package/dist/components/feedback/Toast/Toast.js +102 -93
  42. package/dist/components/feedback/Toast/Toast.js.map +1 -1
  43. package/dist/components/feedback.cjs +1 -1
  44. package/dist/components/feedback.js +17 -13
  45. package/dist/components/feedback.js.map +1 -1
  46. package/dist/components/form/Combobox/Combobox.cjs +2 -2
  47. package/dist/components/form/Combobox/Combobox.cjs.map +1 -1
  48. package/dist/components/form/Combobox/Combobox.js +187 -167
  49. package/dist/components/form/Combobox/Combobox.js.map +1 -1
  50. package/dist/components/form/DateInput/DateInput.cjs +1 -1
  51. package/dist/components/form/DateInput/DateInput.cjs.map +1 -1
  52. package/dist/components/form/DateInput/DateInput.js +2 -2
  53. package/dist/components/form/DateInput/DateInput.js.map +1 -1
  54. package/dist/components/form/DateRangePicker/DateRangePicker.cjs +1 -1
  55. package/dist/components/form/DateRangePicker/DateRangePicker.cjs.map +1 -1
  56. package/dist/components/form/DateRangePicker/DateRangePicker.js +34 -34
  57. package/dist/components/form/DateRangePicker/DateRangePicker.js.map +1 -1
  58. package/dist/components/form/DropZone/DropZone.cjs +1 -1
  59. package/dist/components/form/DropZone/DropZone.cjs.map +1 -1
  60. package/dist/components/form/DropZone/DropZone.js +10 -10
  61. package/dist/components/form/DropZone/DropZone.js.map +1 -1
  62. package/dist/components/form/FileInput/FileInput.cjs +1 -1
  63. package/dist/components/form/FileInput/FileInput.cjs.map +1 -1
  64. package/dist/components/form/FileInput/FileInput.js +1 -1
  65. package/dist/components/form/FileInput/FileInput.js.map +1 -1
  66. package/dist/components/form/FormCard/FormCard.cjs +1 -1
  67. package/dist/components/form/FormCard/FormCard.cjs.map +1 -1
  68. package/dist/components/form/FormCard/FormCard.js +9 -9
  69. package/dist/components/form/FormCard/FormCard.js.map +1 -1
  70. package/dist/components/form/FormField/FormField.cjs +1 -1
  71. package/dist/components/form/FormField/FormField.cjs.map +1 -1
  72. package/dist/components/form/FormField/FormField.js +67 -55
  73. package/dist/components/form/FormField/FormField.js.map +1 -1
  74. package/dist/components/form/MultiSelect/MultiSelect.cjs +1 -1
  75. package/dist/components/form/MultiSelect/MultiSelect.cjs.map +1 -1
  76. package/dist/components/form/MultiSelect/MultiSelect.js +2 -3
  77. package/dist/components/form/MultiSelect/MultiSelect.js.map +1 -1
  78. package/dist/components/form/Radio/Radio.cjs +1 -1
  79. package/dist/components/form/Radio/Radio.cjs.map +1 -1
  80. package/dist/components/form/Radio/Radio.js +20 -20
  81. package/dist/components/form/Radio/Radio.js.map +1 -1
  82. package/dist/components/form/SearchInput/SearchInput.cjs +2 -0
  83. package/dist/components/form/SearchInput/SearchInput.cjs.map +1 -0
  84. package/dist/components/form/SearchInput/SearchInput.js +68 -0
  85. package/dist/components/form/SearchInput/SearchInput.js.map +1 -0
  86. package/dist/components/form/TagInput/TagInput.cjs +1 -1
  87. package/dist/components/form/TagInput/TagInput.cjs.map +1 -1
  88. package/dist/components/form/TagInput/TagInput.js +104 -102
  89. package/dist/components/form/TagInput/TagInput.js.map +1 -1
  90. package/dist/components/form/TimePicker/TimePicker.cjs +1 -1
  91. package/dist/components/form/TimePicker/TimePicker.cjs.map +1 -1
  92. package/dist/components/form/TimePicker/TimePicker.js +29 -30
  93. package/dist/components/form/TimePicker/TimePicker.js.map +1 -1
  94. package/dist/components/form.cjs +1 -1
  95. package/dist/components/form.js +15 -13
  96. package/dist/components/form.js.map +1 -1
  97. package/dist/components/layout/Card/Card.cjs +1 -1
  98. package/dist/components/layout/Card/Card.cjs.map +1 -1
  99. package/dist/components/layout/Card/Card.js +7 -5
  100. package/dist/components/layout/Card/Card.js.map +1 -1
  101. package/dist/components/layout/Collapse/Collapse.cjs.map +1 -1
  102. package/dist/components/layout/Collapse/Collapse.js.map +1 -1
  103. package/dist/components/media/Image/Image.cjs +1 -1
  104. package/dist/components/media/Image/Image.cjs.map +1 -1
  105. package/dist/components/media/Image/Image.js +9 -9
  106. package/dist/components/media/Image/Image.js.map +1 -1
  107. package/dist/components/media/ImageThumbnail/ImageThumbnail.cjs +1 -1
  108. package/dist/components/media/ImageThumbnail/ImageThumbnail.cjs.map +1 -1
  109. package/dist/components/media/ImageThumbnail/ImageThumbnail.js +6 -6
  110. package/dist/components/media/ImageThumbnail/ImageThumbnail.js.map +1 -1
  111. package/dist/components/navigation/Accordion/Accordion.cjs +1 -1
  112. package/dist/components/navigation/Accordion/Accordion.cjs.map +1 -1
  113. package/dist/components/navigation/Accordion/Accordion.js +0 -1
  114. package/dist/components/navigation/Accordion/Accordion.js.map +1 -1
  115. package/dist/components/navigation/Menu/Menu.cjs +1 -1
  116. package/dist/components/navigation/Menu/Menu.cjs.map +1 -1
  117. package/dist/components/navigation/Menu/Menu.js +87 -86
  118. package/dist/components/navigation/Menu/Menu.js.map +1 -1
  119. package/dist/components/navigation/Pagination/Pagination.cjs +1 -1
  120. package/dist/components/navigation/Pagination/Pagination.cjs.map +1 -1
  121. package/dist/components/navigation/Pagination/Pagination.js +107 -99
  122. package/dist/components/navigation/Pagination/Pagination.js.map +1 -1
  123. package/dist/components/navigation/SegmentedControl/SegmentedControl.cjs +2 -0
  124. package/dist/components/navigation/SegmentedControl/SegmentedControl.cjs.map +1 -0
  125. package/dist/components/navigation/SegmentedControl/SegmentedControl.js +90 -0
  126. package/dist/components/navigation/SegmentedControl/SegmentedControl.js.map +1 -0
  127. package/dist/components/navigation.cjs +1 -1
  128. package/dist/components/navigation.js +25 -23
  129. package/dist/components/navigation.js.map +1 -1
  130. package/dist/components/utility/Avatar/Avatar.cjs +1 -1
  131. package/dist/components/utility/Avatar/Avatar.cjs.map +1 -1
  132. package/dist/components/utility/Avatar/Avatar.js +18 -18
  133. package/dist/components/utility/Avatar/Avatar.js.map +1 -1
  134. package/dist/components/utility/Badge/Badge.cjs +1 -1
  135. package/dist/components/utility/Badge/Badge.cjs.map +1 -1
  136. package/dist/components/utility/Badge/Badge.js +31 -23
  137. package/dist/components/utility/Badge/Badge.js.map +1 -1
  138. package/dist/components/utility/Kbd/Kbd.cjs +2 -0
  139. package/dist/components/utility/Kbd/Kbd.cjs.map +1 -0
  140. package/dist/components/utility/Kbd/Kbd.js +20 -0
  141. package/dist/components/utility/Kbd/Kbd.js.map +1 -0
  142. package/dist/components/utility/Logo/Logo.cjs +1 -1
  143. package/dist/components/utility/Logo/Logo.cjs.map +1 -1
  144. package/dist/components/utility/Logo/Logo.js +21 -21
  145. package/dist/components/utility/Logo/Logo.js.map +1 -1
  146. package/dist/components/utility.cjs +1 -1
  147. package/dist/components/utility.js +9 -7
  148. package/dist/components/utility.js.map +1 -1
  149. package/dist/data.d.ts +34 -1
  150. package/dist/design-system/themes/ThemeProvider.cjs +1 -1
  151. package/dist/design-system/themes/ThemeProvider.cjs.map +1 -1
  152. package/dist/design-system/themes/ThemeProvider.js +46 -46
  153. package/dist/design-system/themes/ThemeProvider.js.map +1 -1
  154. package/dist/design-system/tokens/zIndex.cjs +1 -1
  155. package/dist/design-system/tokens/zIndex.cjs.map +1 -1
  156. package/dist/design-system/tokens/zIndex.js +2 -0
  157. package/dist/design-system/tokens/zIndex.js.map +1 -1
  158. package/dist/feedback.d.ts +75 -2
  159. package/dist/form.d.ts +41 -0
  160. package/dist/index.cjs +1 -1
  161. package/dist/index.d.ts +213 -3
  162. package/dist/index.js +177 -165
  163. package/dist/index.js.map +1 -1
  164. package/dist/navigation.d.ts +58 -0
  165. package/dist/styles.css +1 -1
  166. package/dist/tokens.d.ts +2 -0
  167. package/dist/utility.d.ts +19 -0
  168. package/package.json +2 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.js","sources":["../../../../src/components/navigation/Accordion/Accordion.tsx"],"sourcesContent":["/**\n * Accordion Component\n *\n * Collapsible content panels for organizing information.\n * Supports single or multiple expanded panels.\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type AccordionVariant = 'default' | 'bordered' | 'separated'\n\ninterface AccordionContextValue {\n expandedItems: string[]\n toggleItem: (value: string) => void\n allowMultiple: boolean\n variant: AccordionVariant\n}\n\nconst AccordionContext = createContext<AccordionContextValue | null>(null)\n\nfunction useAccordionContext() {\n const context = useContext(AccordionContext)\n if (!context) {\n throw new Error('AccordionItem must be used within an Accordion')\n }\n return context\n}\n\nexport interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Expanded items (controlled) */\n value?: string[]\n /** Default expanded items (uncontrolled) */\n defaultValue?: string[]\n /** Callback when items change */\n onChange?: (value: string[]) => void\n /** Allow multiple items to be expanded */\n allowMultiple?: boolean\n /** Accordion variant */\n variant?: AccordionVariant\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n {\n value: controlledValue,\n defaultValue = [],\n onChange,\n allowMultiple = false,\n variant = 'default',\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalValue, setInternalValue] = useState(defaultValue)\n const expandedItems = controlledValue ?? internalValue\n\n const toggleItem = useCallback(\n (itemValue: string) => {\n const isExpanded = expandedItems.includes(itemValue)\n let newValue: string[]\n\n if (isExpanded) {\n newValue = expandedItems.filter((v) => v !== itemValue)\n } else if (allowMultiple) {\n newValue = [...expandedItems, itemValue]\n } else {\n newValue = [itemValue]\n }\n\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n onChange?.(newValue)\n },\n [expandedItems, allowMultiple, controlledValue, onChange]\n )\n\n const containerStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: variant === 'separated' ? 8 : 0,\n ...style,\n }\n\n return (\n <AccordionContext.Provider value={{ expandedItems, toggleItem, allowMultiple, variant }}>\n <div\n ref={ref}\n className={cx('brycks-accordion', `brycks-accordion--${variant}`, className)}\n style={containerStyle}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n </AccordionContext.Provider>\n )\n})\n\nAccordion.displayName = 'Accordion'\n\n// AccordionItem\nexport interface AccordionItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Item value (unique identifier) */\n value: string\n /** Whether the item is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n}\n\ninterface AccordionItemContextValue {\n value: string\n isExpanded: boolean\n disabled: boolean\n}\n\nconst AccordionItemContext = createContext<AccordionItemContextValue | null>(null)\n\nfunction useAccordionItemContext() {\n const context = useContext(AccordionItemContext)\n if (!context) {\n throw new Error('AccordionTrigger/AccordionContent must be used within an AccordionItem')\n }\n return context\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(function AccordionItem(\n { value, disabled = false, className, style, children, ...props },\n ref\n) {\n const { expandedItems, variant } = useAccordionContext()\n const isExpanded = expandedItems.includes(value)\n\n const itemStyle: CSSProperties = {\n borderBottom: variant === 'default' ? '1px solid var(--brycks-border-muted)' : undefined,\n border: variant === 'bordered' || variant === 'separated' ? '1px solid var(--brycks-border-default)' : undefined,\n borderRadius: variant === 'separated' ? 'var(--brycks-radius-lg)' : undefined,\n overflow: 'hidden',\n ...style,\n }\n\n // Remove bottom border for separated variant (each item has full border)\n if (variant === 'bordered' && !isExpanded) {\n itemStyle.borderBottom = '1px solid var(--brycks-border-default)'\n }\n\n return (\n <AccordionItemContext.Provider value={{ value, isExpanded, disabled }}>\n <div\n ref={ref}\n className={cx('brycks-accordion-item', isExpanded && 'brycks-accordion-item--expanded', className)}\n style={itemStyle}\n {...props}\n >\n {children}\n </div>\n </AccordionItemContext.Provider>\n )\n})\n\nAccordionItem.displayName = 'AccordionItem'\n\n// AccordionTrigger\nexport interface AccordionTriggerProps extends HTMLAttributes<HTMLButtonElement> {\n /** Icon to show (replaces default chevron) */\n icon?: ReactNode\n /** Custom class name */\n className?: string\n}\n\nfunction ChevronIcon({ isExpanded }: { isExpanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-out',\n }}\n >\n <path\n d=\"M4 6l4 4 4-4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n\nexport const AccordionTrigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(function AccordionTrigger(\n { icon, className, style, children, ...props },\n ref\n) {\n const { toggleItem } = useAccordionContext()\n const { value, isExpanded, disabled } = useAccordionItemContext()\n\n const handleClick = () => {\n if (!disabled) {\n toggleItem(value)\n }\n }\n\n const triggerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n padding: '16px',\n fontSize: 15,\n fontWeight: 500,\n color: disabled ? 'var(--brycks-foreground-muted)' : 'var(--brycks-foreground-default)',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: disabled ? 'not-allowed' : 'pointer',\n textAlign: 'left',\n transition: 'background-color 150ms ease-out',\n outline: 'none',\n ...style,\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-expanded={isExpanded}\n aria-disabled={disabled}\n disabled={disabled}\n className={cx('brycks-accordion-trigger', className)}\n style={triggerStyle}\n onClick={handleClick}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n {...props}\n >\n {children}\n <span style={{ color: 'var(--brycks-foreground-muted)', flexShrink: 0, marginLeft: 12 }}>\n {icon ?? <ChevronIcon isExpanded={isExpanded} />}\n </span>\n </button>\n )\n})\n\nAccordionTrigger.displayName = 'AccordionTrigger'\n\n// AccordionContent\nexport interface AccordionContentProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(function AccordionContent(\n { className, style, children, ...props },\n ref\n) {\n const { isExpanded } = useAccordionItemContext()\n\n const contentStyle: CSSProperties = {\n overflow: 'hidden',\n transition: 'max-height 200ms ease-out, opacity 200ms ease-out',\n maxHeight: isExpanded ? '1000px' : '0',\n opacity: isExpanded ? 1 : 0,\n }\n\n const innerStyle: CSSProperties = {\n padding: '0 16px 16px 16px',\n color: 'var(--brycks-foreground-muted)',\n fontSize: 14,\n lineHeight: 1.6,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-hidden={!isExpanded}\n className={cx('brycks-accordion-content', className)}\n style={contentStyle}\n {...props}\n >\n <div style={innerStyle}>{children}</div>\n </div>\n )\n})\n\nAccordionContent.displayName = 'AccordionContent'\n"],"names":["AccordionContext","createContext","useAccordionContext","context","useContext","Accordion","forwardRef","controlledValue","defaultValue","onChange","allowMultiple","variant","className","style","children","testId","props","ref","internalValue","setInternalValue","useState","expandedItems","toggleItem","useCallback","itemValue","isExpanded","newValue","v","containerStyle","jsx","cx","AccordionItemContext","useAccordionItemContext","AccordionItem","value","disabled","itemStyle","ChevronIcon","AccordionTrigger","icon","handleClick","triggerStyle","jsxs","e","AccordionContent","contentStyle","innerStyle"],"mappings":"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"}
1
+ {"version":3,"file":"Accordion.js","sources":["../../../../src/components/navigation/Accordion/Accordion.tsx"],"sourcesContent":["/**\n * Accordion Component\n *\n * Collapsible content panels for organizing information.\n * Supports single or multiple expanded panels.\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type AccordionVariant = 'default' | 'bordered' | 'separated'\n\ninterface AccordionContextValue {\n expandedItems: string[]\n toggleItem: (value: string) => void\n allowMultiple: boolean\n variant: AccordionVariant\n}\n\nconst AccordionContext = createContext<AccordionContextValue | null>(null)\n\nfunction useAccordionContext() {\n const context = useContext(AccordionContext)\n if (!context) {\n throw new Error('AccordionItem must be used within an Accordion')\n }\n return context\n}\n\nexport interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {\n /** Expanded items (controlled) */\n value?: string[]\n /** Default expanded items (uncontrolled) */\n defaultValue?: string[]\n /** Callback when items change */\n onChange?: (value: string[]) => void\n /** Allow multiple items to be expanded */\n allowMultiple?: boolean\n /** Accordion variant */\n variant?: AccordionVariant\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Accordion = forwardRef<HTMLDivElement, AccordionProps>(function Accordion(\n {\n value: controlledValue,\n defaultValue = [],\n onChange,\n allowMultiple = false,\n variant = 'default',\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalValue, setInternalValue] = useState(defaultValue)\n const expandedItems = controlledValue ?? internalValue\n\n const toggleItem = useCallback(\n (itemValue: string) => {\n const isExpanded = expandedItems.includes(itemValue)\n let newValue: string[]\n\n if (isExpanded) {\n newValue = expandedItems.filter((v) => v !== itemValue)\n } else if (allowMultiple) {\n newValue = [...expandedItems, itemValue]\n } else {\n newValue = [itemValue]\n }\n\n if (controlledValue === undefined) {\n setInternalValue(newValue)\n }\n onChange?.(newValue)\n },\n [expandedItems, allowMultiple, controlledValue, onChange]\n )\n\n const containerStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: variant === 'separated' ? 8 : 0,\n ...style,\n }\n\n return (\n <AccordionContext.Provider value={{ expandedItems, toggleItem, allowMultiple, variant }}>\n <div\n ref={ref}\n className={cx('brycks-accordion', `brycks-accordion--${variant}`, className)}\n style={containerStyle}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n </AccordionContext.Provider>\n )\n})\n\nAccordion.displayName = 'Accordion'\n\n// AccordionItem\nexport interface AccordionItemProps extends HTMLAttributes<HTMLDivElement> {\n /** Item value (unique identifier) */\n value: string\n /** Whether the item is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n}\n\ninterface AccordionItemContextValue {\n value: string\n isExpanded: boolean\n disabled: boolean\n}\n\nconst AccordionItemContext = createContext<AccordionItemContextValue | null>(null)\n\nfunction useAccordionItemContext() {\n const context = useContext(AccordionItemContext)\n if (!context) {\n throw new Error('AccordionTrigger/AccordionContent must be used within an AccordionItem')\n }\n return context\n}\n\nexport const AccordionItem = forwardRef<HTMLDivElement, AccordionItemProps>(function AccordionItem(\n { value, disabled = false, className, style, children, ...props },\n ref\n) {\n const { expandedItems, variant } = useAccordionContext()\n const isExpanded = expandedItems.includes(value)\n\n const itemStyle: CSSProperties = {\n borderBottom: variant === 'default' ? '1px solid var(--brycks-border-muted)' : undefined,\n border: variant === 'bordered' || variant === 'separated' ? '1px solid var(--brycks-border-default)' : undefined,\n borderRadius: variant === 'separated' ? 'var(--brycks-radius-lg)' : undefined,\n overflow: 'hidden',\n ...style,\n }\n\n // Remove bottom border for separated variant (each item has full border)\n if (variant === 'bordered' && !isExpanded) {\n itemStyle.borderBottom = '1px solid var(--brycks-border-default)'\n }\n\n return (\n <AccordionItemContext.Provider value={{ value, isExpanded, disabled }}>\n <div\n ref={ref}\n className={cx('brycks-accordion-item', isExpanded && 'brycks-accordion-item--expanded', className)}\n style={itemStyle}\n {...props}\n >\n {children}\n </div>\n </AccordionItemContext.Provider>\n )\n})\n\nAccordionItem.displayName = 'AccordionItem'\n\n// AccordionTrigger\nexport interface AccordionTriggerProps extends HTMLAttributes<HTMLButtonElement> {\n /** Icon to show (replaces default chevron) */\n icon?: ReactNode\n /** Custom class name */\n className?: string\n}\n\nfunction ChevronIcon({ isExpanded }: { isExpanded: boolean }) {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n style={{\n transform: isExpanded ? 'rotate(180deg)' : 'rotate(0deg)',\n transition: 'transform 200ms ease-out',\n }}\n >\n <path\n d=\"M4 6l4 4 4-4\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n )\n}\n\nexport const AccordionTrigger = forwardRef<HTMLButtonElement, AccordionTriggerProps>(function AccordionTrigger(\n { icon, className, style, children, ...props },\n ref\n) {\n const { toggleItem } = useAccordionContext()\n const { value, isExpanded, disabled } = useAccordionItemContext()\n\n const handleClick = () => {\n if (!disabled) {\n toggleItem(value)\n }\n }\n\n const triggerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n width: '100%',\n padding: '16px',\n fontSize: 15,\n fontWeight: 500,\n color: disabled ? 'var(--brycks-foreground-muted)' : 'var(--brycks-foreground-default)',\n backgroundColor: 'transparent',\n border: 'none',\n cursor: disabled ? 'not-allowed' : 'pointer',\n textAlign: 'left',\n transition: 'background-color 150ms ease-out',\n ...style,\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n aria-expanded={isExpanded}\n aria-disabled={disabled}\n disabled={disabled}\n className={cx('brycks-accordion-trigger', className)}\n style={triggerStyle}\n onClick={handleClick}\n onMouseEnter={(e) => {\n if (!disabled) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n e.currentTarget.style.backgroundColor = 'transparent'\n }}\n {...props}\n >\n {children}\n <span style={{ color: 'var(--brycks-foreground-muted)', flexShrink: 0, marginLeft: 12 }}>\n {icon ?? <ChevronIcon isExpanded={isExpanded} />}\n </span>\n </button>\n )\n})\n\nAccordionTrigger.displayName = 'AccordionTrigger'\n\n// AccordionContent\nexport interface AccordionContentProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const AccordionContent = forwardRef<HTMLDivElement, AccordionContentProps>(function AccordionContent(\n { className, style, children, ...props },\n ref\n) {\n const { isExpanded } = useAccordionItemContext()\n\n const contentStyle: CSSProperties = {\n overflow: 'hidden',\n transition: 'max-height 200ms ease-out, opacity 200ms ease-out',\n maxHeight: isExpanded ? '1000px' : '0',\n opacity: isExpanded ? 1 : 0,\n }\n\n const innerStyle: CSSProperties = {\n padding: '0 16px 16px 16px',\n color: 'var(--brycks-foreground-muted)',\n fontSize: 14,\n lineHeight: 1.6,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"region\"\n aria-hidden={!isExpanded}\n className={cx('brycks-accordion-content', className)}\n style={contentStyle}\n {...props}\n >\n <div style={innerStyle}>{children}</div>\n </div>\n )\n})\n\nAccordionContent.displayName = 'AccordionContent'\n"],"names":["AccordionContext","createContext","useAccordionContext","context","useContext","Accordion","forwardRef","controlledValue","defaultValue","onChange","allowMultiple","variant","className","style","children","testId","props","ref","internalValue","setInternalValue","useState","expandedItems","toggleItem","useCallback","itemValue","isExpanded","newValue","v","containerStyle","jsx","cx","AccordionItemContext","useAccordionItemContext","AccordionItem","value","disabled","itemStyle","ChevronIcon","AccordionTrigger","icon","handleClick","triggerStyle","jsxs","e","AccordionContent","contentStyle","innerStyle"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),r=require("react"),j=require("../../../utils/styles.cjs"),i=require("../../../design-system/primitives/sizing.cjs"),m=require("../../../design-system/tokens/spacing.cjs"),N=require("../../../design-system/tokens/motion.cjs"),C=require("../../../design-system/tokens/typography.cjs"),A=r.createContext(null);function G(){const f=r.useContext(A);if(!f)throw new Error("Menu components must be used within a Menu");return f}const H=r.forwardRef(function({activeItem:t,onChange:u,size:c="md",collapsed:s=!1,className:p,style:b,children:S,testId:g,...v},y){const[D,R]=r.useState(null),[x,o]=r.useState(-1),k=r.useRef([]),I=r.useRef(null),q=t!==void 0?t:D,l=e=>{t===void 0&&R(e),u?.(e)},d=r.useCallback(e=>{const n=k.current.indexOf(e);return n===-1?(k.current.push(e),k.current.length-1):n},[]),M=r.useCallback(e=>{const n=I.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');if(!n?.length)return;const z=x>=0?x:0;switch(e.key){case"ArrowDown":e.preventDefault();const w=(z+1)%n.length;o(w),n[w]?.focus();break;case"ArrowUp":e.preventDefault();const h=(z-1+n.length)%n.length;o(h),n[h]?.focus();break;case"Home":e.preventDefault(),o(0),n[0]?.focus();break;case"End":e.preventDefault(),o(n.length-1),n[n.length-1]?.focus();break}},[x]),$={display:"flex",flexDirection:"column",gap:m.spacing[.5],padding:m.spacing[2],...b};return a.jsx(A.Provider,{value:{size:c,activeItem:q,setActiveItem:l,collapsed:s,focusedIndex:x,setFocusedIndex:o,registerItem:d},children:a.jsx("nav",{ref:e=>{I.current=e,typeof y=="function"?y(e):y&&(y.current=e)},role:"menu",className:j.cx("brycks-menu",`brycks-menu--${c}`,s&&"brycks-menu--collapsed",p),style:$,onKeyDown:M,"data-testid":g,...v,children:S})})});H.displayName="Menu";const E={sm:{height:i.componentHeights.sm,fontSize:C.fontSizes.base-1,iconSize:i.iconSizes.sm,padding:i.componentGap.lg},md:{height:i.componentHeights.md,fontSize:C.fontSizes.base,iconSize:i.iconSizes.md-2,padding:i.componentPaddingX.sm},lg:{height:i.componentHeights.lg,fontSize:C.fontSizes.md,iconSize:i.iconSizes.md,padding:m.spacing[3.5]}},F=r.forwardRef(function({value:t,icon:u,badge:c,disabled:s=!1,onClick:p,className:b,style:S,children:g,...v},y){const{size:D,activeItem:R,setActiveItem:x,collapsed:o,focusedIndex:k,setFocusedIndex:I,registerItem:q}=G(),l=R===t,d=E[D],M=q(t),$=()=>{s||(x(t),p?.(t))},e=()=>{I(M)},n={display:"flex",alignItems:"center",gap:i.componentGap.lg,width:"100%",minHeight:d.height,padding:o?d.padding:`0 ${d.padding}px`,fontSize:d.fontSize,fontWeight:l?600:500,color:s?"var(--brycks-foreground-disabled)":l?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:l?"var(--brycks-primary-50)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:s?"not-allowed":"pointer",transition:`all ${N.durations.quick}ms ${N.easings.easeOut}`,textAlign:"left",outline:"none",justifyContent:o?"center":"flex-start",...S},z={width:d.iconSize,height:d.iconSize,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center"},w={marginLeft:"auto"};return a.jsxs("button",{ref:y,type:"button",role:"menuitem",disabled:s,tabIndex:k===M?0:-1,className:j.cx("brycks-menu-item",l&&"brycks-menu-item--active",b),style:n,onClick:$,onFocus:e,onMouseEnter:h=>{!s&&!l&&(h.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:h=>{l||(h.currentTarget.style.backgroundColor="transparent")},title:o?String(g):void 0,...v,children:[u&&a.jsx("span",{style:z,children:u}),!o&&a.jsx("span",{style:{flex:1},children:g}),!o&&c&&a.jsx("span",{style:w,children:c})]})});F.displayName="MenuItem";const P=r.forwardRef(function({label:t,className:u,style:c,children:s,...p},b){const{collapsed:S}=G(),g={display:"flex",flexDirection:"column",gap:m.spacing[.5],...c},v={padding:`${m.spacing[3]}px ${m.spacing[3]}px ${i.componentPaddingY.sm}px ${m.spacing[3]}px`,fontSize:C.fontSizes.xs,fontWeight:600,color:"var(--brycks-foreground-muted)",textTransform:"uppercase",letterSpacing:"0.05em"};return a.jsxs("div",{ref:b,className:j.cx("brycks-menu-group",u),style:g,...p,children:[t&&!S&&a.jsx("div",{style:v,children:t}),s]})});P.displayName="MenuGroup";const T=r.forwardRef(function({className:t,style:u,...c},s){const p={height:1,backgroundColor:"var(--brycks-border-muted)",margin:`${m.spacing[2]}px 0`,...u};return a.jsx("div",{ref:s,role:"separator",className:j.cx("brycks-menu-divider",t),style:p,...c})});T.displayName="MenuDivider";exports.Menu=H;exports.MenuDivider=T;exports.MenuGroup=P;exports.MenuItem=F;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),r=require("react"),j=require("../../../utils/styles.cjs"),i=require("../../../design-system/primitives/sizing.cjs"),m=require("../../../design-system/tokens/spacing.cjs"),N=require("../../../design-system/tokens/motion.cjs"),C=require("../../../design-system/tokens/typography.cjs"),A=r.createContext(null);function G(){const g=r.useContext(A);if(!g)throw new Error("Menu components must be used within a Menu");return g}const H=r.forwardRef(function({activeItem:t,onChange:l,size:c="md",collapsed:s=!1,className:p,style:S,children:v,testId:y,...k},x){const[D,M]=r.useState(null),[h,o]=r.useState(-1),b=r.useRef([]),z=r.useRef(null),R=t!==void 0?t:D,a=e=>{t===void 0&&M(e),l?.(e)},d=r.useCallback(e=>{const n=b.current.indexOf(e);return n===-1?(b.current.push(e),b.current.length-1):n},[]),I=r.useCallback(e=>{const n=z.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');if(!n?.length)return;const w=h>=0?h:0;switch(e.key){case"ArrowDown":{e.preventDefault();const f=(w+1)%n.length;o(f),n[f]?.focus();break}case"ArrowUp":{e.preventDefault();const f=(w-1+n.length)%n.length;o(f),n[f]?.focus();break}case"Home":e.preventDefault(),o(0),n[0]?.focus();break;case"End":e.preventDefault(),o(n.length-1),n[n.length-1]?.focus();break}},[h]),q={display:"flex",flexDirection:"column",gap:m.spacing[.5],padding:m.spacing[2],...S};return u.jsx(A.Provider,{value:{size:c,activeItem:R,setActiveItem:a,collapsed:s,focusedIndex:h,setFocusedIndex:o,registerItem:d},children:u.jsx("nav",{ref:e=>{z.current=e,typeof x=="function"?x(e):x&&(x.current=e)},role:"menu",className:j.cx("brycks-menu",`brycks-menu--${c}`,s&&"brycks-menu--collapsed",p),style:q,onKeyDown:I,"data-testid":y,...k,children:v})})});H.displayName="Menu";const O={sm:{height:i.componentHeights.sm,fontSize:C.fontSizes.base-1,iconSize:i.iconSizes.sm,padding:i.componentGap.lg},md:{height:i.componentHeights.md,fontSize:C.fontSizes.base,iconSize:i.iconSizes.md-2,padding:i.componentPaddingX.sm},lg:{height:i.componentHeights.lg,fontSize:C.fontSizes.md,iconSize:i.iconSizes.md,padding:m.spacing[3.5]}},T=r.forwardRef(function({value:t,icon:l,badge:c,disabled:s=!1,onClick:p,className:S,style:v,children:y,...k},x){const{size:D,activeItem:M,setActiveItem:h,collapsed:o,focusedIndex:b,setFocusedIndex:z,registerItem:R}=G(),a=M===t,d=O[D],I=R(t),q=()=>{s||(h(t),p?.(t))},e=()=>{z(I)},n={display:"flex",alignItems:"center",gap:i.componentGap.lg,width:"100%",minHeight:d.height,padding:o?d.padding:`0 ${d.padding}px`,fontSize:d.fontSize,fontWeight:a?600:500,color:s?"var(--brycks-foreground-disabled)":a?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:a?"var(--brycks-primary-muted)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:s?"not-allowed":"pointer",transition:`all ${N.durations.quick}ms ${N.easings.easeOut}`,textAlign:"left",justifyContent:o?"center":"flex-start",...v},w={width:d.iconSize,height:d.iconSize,flexShrink:0,display:"flex",alignItems:"center",justifyContent:"center"},f={marginLeft:"auto"},E=b>=0?b===I:M?a:I===0;return u.jsxs("button",{ref:x,type:"button",role:"menuitem",disabled:s,tabIndex:E?0:-1,className:j.cx("brycks-menu-item",a&&"brycks-menu-item--active",S),style:n,onClick:q,onFocus:e,onMouseEnter:$=>{!s&&!a&&($.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:$=>{a||($.currentTarget.style.backgroundColor="transparent")},title:o?String(y):void 0,...k,children:[l&&u.jsx("span",{style:w,children:l}),!o&&u.jsx("span",{style:{flex:1},children:y}),!o&&c&&u.jsx("span",{style:f,children:c})]})});T.displayName="MenuItem";const F=r.forwardRef(function({label:t,className:l,style:c,children:s,...p},S){const{collapsed:v}=G(),y={display:"flex",flexDirection:"column",gap:m.spacing[.5],...c},k={padding:`${m.spacing[3]}px ${m.spacing[3]}px ${i.componentPaddingY.sm}px ${m.spacing[3]}px`,fontSize:C.fontSizes.xs,fontWeight:600,color:"var(--brycks-foreground-muted)",textTransform:"uppercase",letterSpacing:"0.05em"};return u.jsxs("div",{ref:S,className:j.cx("brycks-menu-group",l),style:y,...p,children:[t&&!v&&u.jsx("div",{style:k,children:t}),s]})});F.displayName="MenuGroup";const P=r.forwardRef(function({className:t,style:l,...c},s){const p={height:1,backgroundColor:"var(--brycks-border-muted)",margin:`${m.spacing[2]}px 0`,...l};return u.jsx("div",{ref:s,role:"separator",className:j.cx("brycks-menu-divider",t),style:p,...c})});P.displayName="MenuDivider";exports.Menu=H;exports.MenuDivider=P;exports.MenuGroup=F;exports.MenuItem=T;
2
2
  //# sourceMappingURL=Menu.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.cjs","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n case 'ArrowUp':\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-50)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n outline: 'none',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={focusedIndex === itemIndex ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":"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"}
1
+ {"version":3,"file":"Menu.cjs","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-muted)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","isTabStop","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":"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"}
@@ -1,48 +1,50 @@
1
- import { jsx as d, jsxs as H } from "react/jsx-runtime";
2
- import { forwardRef as C, useState as F, useRef as G, useCallback as E, createContext as K, useContext as L } from "react";
1
+ import { jsx as m, jsxs as E } from "react/jsx-runtime";
2
+ import { forwardRef as C, useState as F, useRef as G, useCallback as T, createContext as L, useContext as O } from "react";
3
3
  import { cx as w } from "../../../utils/styles.js";
4
- import { iconSizes as R, componentHeights as j, componentPaddingX as O, componentGap as P, componentPaddingY as W } from "../../../design-system/primitives/sizing.js";
4
+ import { iconSizes as R, componentHeights as j, componentPaddingX as W, componentGap as H, componentPaddingY as U } from "../../../design-system/primitives/sizing.js";
5
5
  import { spacing as u } from "../../../design-system/tokens/spacing.js";
6
- import { durations as U, easings as X } from "../../../design-system/tokens/motion.js";
6
+ import { durations as X, easings as Y } from "../../../design-system/tokens/motion.js";
7
7
  import { fontSizes as z } from "../../../design-system/tokens/typography.js";
8
- const T = K(null);
8
+ const P = L(null);
9
9
  function q() {
10
- const m = L(T);
11
- if (!m)
10
+ const f = O(P);
11
+ if (!f)
12
12
  throw new Error("Menu components must be used within a Menu");
13
- return m;
13
+ return f;
14
14
  }
15
- const Y = C(function({
15
+ const B = C(function({
16
16
  activeItem: n,
17
- onChange: i,
17
+ onChange: c,
18
18
  size: s = "md",
19
19
  collapsed: r = !1,
20
20
  className: l,
21
- style: x,
22
- children: h,
23
- testId: f,
24
- ...b
25
- }, p) {
26
- const [D, $] = F(null), [g, o] = F(-1), k = G([]), v = G(null), N = n !== void 0 ? n : D, c = (e) => {
27
- n === void 0 && $(e), i?.(e);
28
- }, a = E((e) => {
29
- const t = k.current.indexOf(e);
30
- return t === -1 ? (k.current.push(e), k.current.length - 1) : t;
31
- }, []), S = E((e) => {
32
- const t = v.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');
21
+ style: h,
22
+ children: b,
23
+ testId: p,
24
+ ...k
25
+ }, g) {
26
+ const [D, S] = F(null), [y, o] = F(-1), x = G([]), I = G(null), $ = n !== void 0 ? n : D, i = (e) => {
27
+ n === void 0 && S(e), c?.(e);
28
+ }, a = T((e) => {
29
+ const t = x.current.indexOf(e);
30
+ return t === -1 ? (x.current.push(e), x.current.length - 1) : t;
31
+ }, []), v = T((e) => {
32
+ const t = I.current?.querySelectorAll('[role="menuitem"]:not(:disabled)');
33
33
  if (!t?.length) return;
34
- const I = g >= 0 ? g : 0;
34
+ const M = y >= 0 ? y : 0;
35
35
  switch (e.key) {
36
- case "ArrowDown":
36
+ case "ArrowDown": {
37
37
  e.preventDefault();
38
- const M = (I + 1) % t.length;
39
- o(M), t[M]?.focus();
38
+ const d = (M + 1) % t.length;
39
+ o(d), t[d]?.focus();
40
40
  break;
41
- case "ArrowUp":
41
+ }
42
+ case "ArrowUp": {
42
43
  e.preventDefault();
43
- const y = (I - 1 + t.length) % t.length;
44
- o(y), t[y]?.focus();
44
+ const d = (M - 1 + t.length) % t.length;
45
+ o(d), t[d]?.focus();
45
46
  break;
47
+ }
46
48
  case "Home":
47
49
  e.preventDefault(), o(0), t[0]?.focus();
48
50
  break;
@@ -50,125 +52,124 @@ const Y = C(function({
50
52
  e.preventDefault(), o(t.length - 1), t[t.length - 1]?.focus();
51
53
  break;
52
54
  }
53
- }, [g]), A = {
55
+ }, [y]), N = {
54
56
  display: "flex",
55
57
  flexDirection: "column",
56
58
  gap: u[0.5],
57
59
  padding: u[2],
58
- ...x
60
+ ...h
59
61
  };
60
- return /* @__PURE__ */ d(T.Provider, { value: { size: s, activeItem: N, setActiveItem: c, collapsed: r, focusedIndex: g, setFocusedIndex: o, registerItem: a }, children: /* @__PURE__ */ d(
62
+ return /* @__PURE__ */ m(P.Provider, { value: { size: s, activeItem: $, setActiveItem: i, collapsed: r, focusedIndex: y, setFocusedIndex: o, registerItem: a }, children: /* @__PURE__ */ m(
61
63
  "nav",
62
64
  {
63
65
  ref: (e) => {
64
- v.current = e, typeof p == "function" ? p(e) : p && (p.current = e);
66
+ I.current = e, typeof g == "function" ? g(e) : g && (g.current = e);
65
67
  },
66
68
  role: "menu",
67
69
  className: w("brycks-menu", `brycks-menu--${s}`, r && "brycks-menu--collapsed", l),
68
- style: A,
69
- onKeyDown: S,
70
- "data-testid": f,
71
- ...b,
72
- children: h
70
+ style: N,
71
+ onKeyDown: v,
72
+ "data-testid": p,
73
+ ...k,
74
+ children: b
73
75
  }
74
76
  ) });
75
77
  });
76
- Y.displayName = "Menu";
77
- const B = {
78
- sm: { height: j.sm, fontSize: z.base - 1, iconSize: R.sm, padding: P.lg },
79
- md: { height: j.md, fontSize: z.base, iconSize: R.md - 2, padding: O.sm },
78
+ B.displayName = "Menu";
79
+ const J = {
80
+ sm: { height: j.sm, fontSize: z.base - 1, iconSize: R.sm, padding: H.lg },
81
+ md: { height: j.md, fontSize: z.base, iconSize: R.md - 2, padding: W.sm },
80
82
  lg: { height: j.lg, fontSize: z.md, iconSize: R.md, padding: u[3.5] }
81
- }, J = C(function({ value: n, icon: i, badge: s, disabled: r = !1, onClick: l, className: x, style: h, children: f, ...b }, p) {
82
- const { size: D, activeItem: $, setActiveItem: g, collapsed: o, focusedIndex: k, setFocusedIndex: v, registerItem: N } = q(), c = $ === n, a = B[D], S = N(n), A = () => {
83
- r || (g(n), l?.(n));
83
+ }, Q = C(function({ value: n, icon: c, badge: s, disabled: r = !1, onClick: l, className: h, style: b, children: p, ...k }, g) {
84
+ const { size: D, activeItem: S, setActiveItem: y, collapsed: o, focusedIndex: x, setFocusedIndex: I, registerItem: $ } = q(), i = S === n, a = J[D], v = $(n), N = () => {
85
+ r || (y(n), l?.(n));
84
86
  }, e = () => {
85
- v(S);
87
+ I(v);
86
88
  }, t = {
87
89
  display: "flex",
88
90
  alignItems: "center",
89
- gap: P.lg,
91
+ gap: H.lg,
90
92
  width: "100%",
91
93
  minHeight: a.height,
92
94
  padding: o ? a.padding : `0 ${a.padding}px`,
93
95
  fontSize: a.fontSize,
94
- fontWeight: c ? 600 : 500,
95
- color: r ? "var(--brycks-foreground-disabled)" : c ? "var(--brycks-primary-default)" : "var(--brycks-foreground-default)",
96
- backgroundColor: c ? "var(--brycks-primary-50)" : "transparent",
96
+ fontWeight: i ? 600 : 500,
97
+ color: r ? "var(--brycks-foreground-disabled)" : i ? "var(--brycks-primary-default)" : "var(--brycks-foreground-default)",
98
+ backgroundColor: i ? "var(--brycks-primary-muted)" : "transparent",
97
99
  border: "none",
98
100
  borderRadius: "var(--brycks-radius-md)",
99
101
  cursor: r ? "not-allowed" : "pointer",
100
- transition: `all ${U.quick}ms ${X.easeOut}`,
102
+ transition: `all ${X.quick}ms ${Y.easeOut}`,
101
103
  textAlign: "left",
102
- outline: "none",
103
104
  justifyContent: o ? "center" : "flex-start",
104
- ...h
105
- }, I = {
105
+ ...b
106
+ }, M = {
106
107
  width: a.iconSize,
107
108
  height: a.iconSize,
108
109
  flexShrink: 0,
109
110
  display: "flex",
110
111
  alignItems: "center",
111
112
  justifyContent: "center"
112
- }, M = {
113
+ }, d = {
113
114
  marginLeft: "auto"
114
- };
115
- return /* @__PURE__ */ H(
115
+ }, K = x >= 0 ? x === v : S ? i : v === 0;
116
+ return /* @__PURE__ */ E(
116
117
  "button",
117
118
  {
118
- ref: p,
119
+ ref: g,
119
120
  type: "button",
120
121
  role: "menuitem",
121
122
  disabled: r,
122
- tabIndex: k === S ? 0 : -1,
123
- className: w("brycks-menu-item", c && "brycks-menu-item--active", x),
123
+ tabIndex: K ? 0 : -1,
124
+ className: w("brycks-menu-item", i && "brycks-menu-item--active", h),
124
125
  style: t,
125
- onClick: A,
126
+ onClick: N,
126
127
  onFocus: e,
127
- onMouseEnter: (y) => {
128
- !r && !c && (y.currentTarget.style.backgroundColor = "var(--brycks-background-muted)");
128
+ onMouseEnter: (A) => {
129
+ !r && !i && (A.currentTarget.style.backgroundColor = "var(--brycks-background-muted)");
129
130
  },
130
- onMouseLeave: (y) => {
131
- c || (y.currentTarget.style.backgroundColor = "transparent");
131
+ onMouseLeave: (A) => {
132
+ i || (A.currentTarget.style.backgroundColor = "transparent");
132
133
  },
133
- title: o ? String(f) : void 0,
134
- ...b,
134
+ title: o ? String(p) : void 0,
135
+ ...k,
135
136
  children: [
136
- i && /* @__PURE__ */ d("span", { style: I, children: i }),
137
- !o && /* @__PURE__ */ d("span", { style: { flex: 1 }, children: f }),
138
- !o && s && /* @__PURE__ */ d("span", { style: M, children: s })
137
+ c && /* @__PURE__ */ m("span", { style: M, children: c }),
138
+ !o && /* @__PURE__ */ m("span", { style: { flex: 1 }, children: p }),
139
+ !o && s && /* @__PURE__ */ m("span", { style: d, children: s })
139
140
  ]
140
141
  }
141
142
  );
142
143
  });
143
- J.displayName = "MenuItem";
144
- const Q = C(function({ label: n, className: i, style: s, children: r, ...l }, x) {
145
- const { collapsed: h } = q(), f = {
144
+ Q.displayName = "MenuItem";
145
+ const V = C(function({ label: n, className: c, style: s, children: r, ...l }, h) {
146
+ const { collapsed: b } = q(), p = {
146
147
  display: "flex",
147
148
  flexDirection: "column",
148
149
  gap: u[0.5],
149
150
  ...s
150
- }, b = {
151
- padding: `${u[3]}px ${u[3]}px ${W.sm}px ${u[3]}px`,
151
+ }, k = {
152
+ padding: `${u[3]}px ${u[3]}px ${U.sm}px ${u[3]}px`,
152
153
  fontSize: z.xs,
153
154
  fontWeight: 600,
154
155
  color: "var(--brycks-foreground-muted)",
155
156
  textTransform: "uppercase",
156
157
  letterSpacing: "0.05em"
157
158
  };
158
- return /* @__PURE__ */ H("div", { ref: x, className: w("brycks-menu-group", i), style: f, ...l, children: [
159
- n && !h && /* @__PURE__ */ d("div", { style: b, children: n }),
159
+ return /* @__PURE__ */ E("div", { ref: h, className: w("brycks-menu-group", c), style: p, ...l, children: [
160
+ n && !b && /* @__PURE__ */ m("div", { style: k, children: n }),
160
161
  r
161
162
  ] });
162
163
  });
163
- Q.displayName = "MenuGroup";
164
- const V = C(function({ className: n, style: i, ...s }, r) {
164
+ V.displayName = "MenuGroup";
165
+ const Z = C(function({ className: n, style: c, ...s }, r) {
165
166
  const l = {
166
167
  height: 1,
167
168
  backgroundColor: "var(--brycks-border-muted)",
168
169
  margin: `${u[2]}px 0`,
169
- ...i
170
+ ...c
170
171
  };
171
- return /* @__PURE__ */ d(
172
+ return /* @__PURE__ */ m(
172
173
  "div",
173
174
  {
174
175
  ref: r,
@@ -179,11 +180,11 @@ const V = C(function({ className: n, style: i, ...s }, r) {
179
180
  }
180
181
  );
181
182
  });
182
- V.displayName = "MenuDivider";
183
+ Z.displayName = "MenuDivider";
183
184
  export {
184
- Y as Menu,
185
- V as MenuDivider,
186
- Q as MenuGroup,
187
- J as MenuItem
185
+ B as Menu,
186
+ Z as MenuDivider,
187
+ V as MenuGroup,
188
+ Q as MenuItem
188
189
  };
189
190
  //# sourceMappingURL=Menu.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Menu.js","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown':\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n case 'ArrowUp':\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-50)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n outline: 'none',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={focusedIndex === itemIndex ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":"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"}
1
+ {"version":3,"file":"Menu.js","sources":["../../../../src/components/navigation/Menu/Menu.tsx"],"sourcesContent":["/**\n * Menu Component\n *\n * A vertical navigation menu with support for nested items.\n * Suitable for sidebars and navigation panels.\n */\n\nimport {\n forwardRef,\n useState,\n useRef,\n useCallback,\n createContext,\n useContext,\n type CSSProperties,\n type ReactNode,\n type HTMLAttributes,\n type KeyboardEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { spacing, fontSizes, durations, easings } from '../../../design-system'\nimport { componentHeights, componentGap, componentPaddingX, componentPaddingY, iconSizes } from '../../../design-system/primitives'\n\nexport type MenuSize = 'sm' | 'md' | 'lg'\n\ninterface MenuContextValue {\n size: MenuSize\n activeItem: string | null\n setActiveItem: (value: string | null) => void\n collapsed: boolean\n focusedIndex: number\n setFocusedIndex: (index: number) => void\n registerItem: (value: string) => number\n}\n\nconst MenuContext = createContext<MenuContextValue | null>(null)\n\nfunction useMenuContext() {\n const context = useContext(MenuContext)\n if (!context) {\n throw new Error('Menu components must be used within a Menu')\n }\n return context\n}\n\nexport interface MenuProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {\n /** Currently active item */\n activeItem?: string | null\n /** Callback when active item changes */\n onChange?: (value: string | null) => void\n /** Menu size */\n size?: MenuSize\n /** Whether the menu is collapsed (icons only) */\n collapsed?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Menu = forwardRef<HTMLElement, MenuProps>(function Menu(\n {\n activeItem: controlledActiveItem,\n onChange,\n size = 'md',\n collapsed = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n const [internalActiveItem, setInternalActiveItem] = useState<string | null>(null)\n const [focusedIndex, setFocusedIndex] = useState(-1)\n const itemsRef = useRef<string[]>([])\n const menuRef = useRef<HTMLElement>(null)\n const activeItem = controlledActiveItem !== undefined ? controlledActiveItem : internalActiveItem\n\n const setActiveItem = (value: string | null) => {\n if (controlledActiveItem === undefined) {\n setInternalActiveItem(value)\n }\n onChange?.(value)\n }\n\n // Register items for keyboard navigation\n const registerItem = useCallback((value: string) => {\n const index = itemsRef.current.indexOf(value)\n if (index === -1) {\n itemsRef.current.push(value)\n return itemsRef.current.length - 1\n }\n return index\n }, [])\n\n // Keyboard navigation\n const handleKeyDown = useCallback((e: KeyboardEvent<HTMLElement>) => {\n const items = menuRef.current?.querySelectorAll<HTMLButtonElement>('[role=\"menuitem\"]:not(:disabled)')\n if (!items?.length) return\n\n const currentIndex = focusedIndex >= 0 ? focusedIndex : 0\n\n switch (e.key) {\n case 'ArrowDown': {\n e.preventDefault()\n const nextIndex = (currentIndex + 1) % items.length\n setFocusedIndex(nextIndex)\n items[nextIndex]?.focus()\n break\n }\n case 'ArrowUp': {\n e.preventDefault()\n const prevIndex = (currentIndex - 1 + items.length) % items.length\n setFocusedIndex(prevIndex)\n items[prevIndex]?.focus()\n break\n }\n case 'Home':\n e.preventDefault()\n setFocusedIndex(0)\n items[0]?.focus()\n break\n case 'End':\n e.preventDefault()\n setFocusedIndex(items.length - 1)\n items[items.length - 1]?.focus()\n break\n }\n }, [focusedIndex])\n\n const menuStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n padding: spacing[2],\n ...style,\n }\n\n return (\n <MenuContext.Provider value={{ size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem }}>\n <nav\n ref={(node) => {\n (menuRef as React.MutableRefObject<HTMLElement | null>).current = node\n if (typeof ref === 'function') ref(node)\n else if (ref) (ref as React.MutableRefObject<HTMLElement | null>).current = node\n }}\n role=\"menu\"\n className={cx('brycks-menu', `brycks-menu--${size}`, collapsed && 'brycks-menu--collapsed', className)}\n style={menuStyle}\n onKeyDown={handleKeyDown}\n data-testid={testId}\n {...props}\n >\n {children}\n </nav>\n </MenuContext.Provider>\n )\n})\n\nMenu.displayName = 'Menu'\n\n// MenuItem\nexport interface MenuItemProps extends Omit<HTMLAttributes<HTMLButtonElement>, 'onClick'> {\n /** Item value (unique identifier) */\n value: string\n /** Icon before the label */\n icon?: ReactNode\n /** Badge/count after the label */\n badge?: ReactNode\n /** Whether the item is disabled */\n disabled?: boolean\n /** Callback when clicked */\n onClick?: (value: string) => void\n /** Custom class name */\n className?: string\n}\n\nconst sizeConfig: Record<MenuSize, { height: number; fontSize: number; iconSize: number; padding: number }> = {\n sm: { height: componentHeights.sm, fontSize: fontSizes.base - 1, iconSize: iconSizes.sm, padding: componentGap.lg },\n md: { height: componentHeights.md, fontSize: fontSizes.base, iconSize: iconSizes.md - 2, padding: componentPaddingX.sm },\n lg: { height: componentHeights.lg, fontSize: fontSizes.md, iconSize: iconSizes.md, padding: spacing[3.5] },\n}\n\nexport const MenuItem = forwardRef<HTMLButtonElement, MenuItemProps>(function MenuItem(\n { value, icon, badge, disabled = false, onClick, className, style, children, ...props },\n ref\n) {\n const { size, activeItem, setActiveItem, collapsed, focusedIndex, setFocusedIndex, registerItem } = useMenuContext()\n const isActive = activeItem === value\n const config = sizeConfig[size]\n const itemIndex = registerItem(value)\n\n const handleClick = () => {\n if (disabled) return\n setActiveItem(value)\n onClick?.(value)\n }\n\n const handleFocus = () => {\n setFocusedIndex(itemIndex)\n }\n\n const itemStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n gap: componentGap.lg,\n width: '100%',\n minHeight: config.height,\n padding: collapsed ? config.padding : `0 ${config.padding}px`,\n fontSize: config.fontSize,\n fontWeight: isActive ? 600 : 500,\n color: disabled\n ? 'var(--brycks-foreground-disabled)'\n : isActive\n ? 'var(--brycks-primary-default)'\n : 'var(--brycks-foreground-default)',\n backgroundColor: isActive ? 'var(--brycks-primary-muted)' : 'transparent',\n border: 'none',\n borderRadius: 'var(--brycks-radius-md)',\n cursor: disabled ? 'not-allowed' : 'pointer',\n transition: `all ${durations.quick}ms ${easings.easeOut}`,\n textAlign: 'left',\n justifyContent: collapsed ? 'center' : 'flex-start',\n ...style,\n }\n\n const iconStyle: CSSProperties = {\n width: config.iconSize,\n height: config.iconSize,\n flexShrink: 0,\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n }\n\n const badgeStyle: CSSProperties = {\n marginLeft: 'auto',\n }\n\n // Roving tabindex: before any item is focused (focusedIndex -1), Tab must\n // still be able to enter the menu through the active item or the first one.\n const isTabStop =\n focusedIndex >= 0 ? focusedIndex === itemIndex : activeItem ? isActive : itemIndex === 0\n\n return (\n <button\n ref={ref}\n type=\"button\"\n role=\"menuitem\"\n disabled={disabled}\n tabIndex={isTabStop ? 0 : -1}\n className={cx('brycks-menu-item', isActive && 'brycks-menu-item--active', className)}\n style={itemStyle}\n onClick={handleClick}\n onFocus={handleFocus}\n onMouseEnter={(e) => {\n if (!disabled && !isActive) {\n e.currentTarget.style.backgroundColor = 'var(--brycks-background-muted)'\n }\n }}\n onMouseLeave={(e) => {\n if (!isActive) {\n e.currentTarget.style.backgroundColor = 'transparent'\n }\n }}\n title={collapsed ? String(children) : undefined}\n {...props}\n >\n {icon && <span style={iconStyle}>{icon}</span>}\n {!collapsed && <span style={{ flex: 1 }}>{children}</span>}\n {!collapsed && badge && <span style={badgeStyle}>{badge}</span>}\n </button>\n )\n})\n\nMenuItem.displayName = 'MenuItem'\n\n// MenuGroup\nexport interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {\n /** Group label */\n label?: string\n /** Custom class name */\n className?: string\n}\n\nexport const MenuGroup = forwardRef<HTMLDivElement, MenuGroupProps>(function MenuGroup(\n { label, className, style, children, ...props },\n ref\n) {\n const { collapsed } = useMenuContext()\n\n const groupStyle: CSSProperties = {\n display: 'flex',\n flexDirection: 'column',\n gap: spacing[0.5],\n ...style,\n }\n\n const labelStyle: CSSProperties = {\n padding: `${spacing[3]}px ${spacing[3]}px ${componentPaddingY.sm}px ${spacing[3]}px`,\n fontSize: fontSizes.xs,\n fontWeight: 600,\n color: 'var(--brycks-foreground-muted)',\n textTransform: 'uppercase',\n letterSpacing: '0.05em',\n }\n\n return (\n <div ref={ref} className={cx('brycks-menu-group', className)} style={groupStyle} {...props}>\n {label && !collapsed && <div style={labelStyle}>{label}</div>}\n {children}\n </div>\n )\n})\n\nMenuGroup.displayName = 'MenuGroup'\n\n// MenuDivider\nexport interface MenuDividerProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport const MenuDivider = forwardRef<HTMLDivElement, MenuDividerProps>(function MenuDivider(\n { className, style, ...props },\n ref\n) {\n const dividerStyle: CSSProperties = {\n height: 1,\n backgroundColor: 'var(--brycks-border-muted)',\n margin: `${spacing[2]}px 0`,\n ...style,\n }\n\n return (\n <div\n ref={ref}\n role=\"separator\"\n className={cx('brycks-menu-divider', className)}\n style={dividerStyle}\n {...props}\n />\n )\n})\n\nMenuDivider.displayName = 'MenuDivider'\n"],"names":["MenuContext","createContext","useMenuContext","context","useContext","Menu","forwardRef","controlledActiveItem","onChange","size","collapsed","className","style","children","testId","props","ref","internalActiveItem","setInternalActiveItem","useState","focusedIndex","setFocusedIndex","itemsRef","useRef","menuRef","activeItem","setActiveItem","value","registerItem","useCallback","index","handleKeyDown","items","currentIndex","nextIndex","prevIndex","menuStyle","spacing","jsx","node","cx","sizeConfig","componentHeights","fontSizes","iconSizes","componentGap","componentPaddingX","MenuItem","icon","badge","disabled","onClick","isActive","config","itemIndex","handleClick","handleFocus","itemStyle","durations","easings","iconStyle","badgeStyle","isTabStop","jsxs","e","MenuGroup","label","groupStyle","labelStyle","componentPaddingY","MenuDivider","dividerStyle"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),b=require("react"),E=require("../../../utils/styles.cjs"),u=require("../../../design-system/tokens/spacing.cjs"),g=require("../../../design-system/tokens/typography.cjs"),I=require("../../../design-system/primitives/sizing.cjs"),x=require("../../../design-system/tokens/motion.cjs"),R={sm:{height:u.spacing[7],fontSize:g.fontSizes.sm,gap:u.spacing[1],minWidth:u.spacing[7]},md:{height:u.spacing[9],fontSize:g.fontSizes.base,gap:I.componentGap.sm,minWidth:u.spacing[9]},lg:{height:u.spacing[11],fontSize:g.fontSizes.md,gap:u.spacing[2],minWidth:u.spacing[11]}};function B(){return e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e.jsx("path",{d:"M10 12L6 8l4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function N(){return e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function O(){return e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e.jsx("path",{d:"M11 12l-4-4 4-4M7 12l-4-4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function G(){return e.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:e.jsx("path",{d:"M5 4l4 4-4 4M9 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const j=b.forwardRef(function({page:r,totalPages:t,onChange:C,size:y="md",variant:c="default",siblingCount:h=1,showFirstLast:p=!0,showPrevNext:k=!0,disabled:o=!1,className:v,style:M,testId:S,...L},z){const s=R[y],W=b.useMemo(()=>{if(c==="minimal"||c==="simple")return[];const n=[],l=Math.max(r-h,1),a=Math.min(r+h,t),w=l>2,m=a<t-1;if(w)if(m){n.push(1),n.push("ellipsis");for(let i=l;i<=a;i++)n.push(i);n.push("ellipsis"),n.push(t)}else{n.push(1),n.push("ellipsis");for(let i=Math.max(t-2-h,1);i<=t;i++)n.push(i)}else{for(let i=1;i<=Math.min(3+h,t);i++)n.push(i);m&&(n.push("ellipsis"),n.push(t))}return n},[r,t,h,c]),$={display:"flex",alignItems:"center",gap:s.gap,...M},d=(n,l)=>({display:"inline-flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,padding:`0 ${s.gap+4}px`,fontSize:s.fontSize,fontWeight:n?600:500,color:l?"var(--brycks-foreground-disabled)":n?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:n?"var(--brycks-primary-50)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:l?"not-allowed":"pointer",transition:`all ${x.durations.quick}ms ${x.easings.easeOut}`,outline:"none"}),T={display:"flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,color:"var(--brycks-foreground-muted)",fontSize:s.fontSize},q={fontSize:s.fontSize,color:"var(--brycks-foreground-muted)",padding:`0 ${s.gap}px`},f=n=>{n>=1&&n<=t&&n!==r&&!o&&C(n)};return e.jsxs("nav",{ref:z,role:"navigation","aria-label":"Pagination",className:E.cx("brycks-pagination",`brycks-pagination--${y}`,`brycks-pagination--${c}`,v),style:$,"data-testid":S,...L,children:[p&&c!=="minimal"&&e.jsx("button",{type:"button","aria-label":"First page",disabled:r===1||o,style:d(!1,r===1||o),onClick:()=>f(1),onMouseEnter:n=>{r!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:e.jsx(O,{})}),k&&e.jsx("button",{type:"button","aria-label":"Previous page",disabled:r===1||o,style:d(!1,r===1||o),onClick:()=>f(r-1),onMouseEnter:n=>{r!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:e.jsx(B,{})}),c==="simple"||c==="minimal"?e.jsx("span",{style:q,children:c==="minimal"?`${r} / ${t}`:`Page ${r} of ${t}`}):W.map((n,l)=>n==="ellipsis"?e.jsx("span",{style:T,children:"..."},`ellipsis-${l}`):e.jsx("button",{type:"button","aria-label":`Page ${n}`,"aria-current":n===r?"page":void 0,disabled:o,style:d(n===r,o),onClick:()=>f(n),onMouseEnter:a=>{n!==r&&!o&&(a.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:a=>{n!==r&&(a.currentTarget.style.backgroundColor="transparent")},children:n},n)),k&&e.jsx("button",{type:"button","aria-label":"Next page",disabled:r===t||o,style:d(!1,r===t||o),onClick:()=>f(r+1),onMouseEnter:n=>{r!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:e.jsx(N,{})}),p&&c!=="minimal"&&e.jsx("button",{type:"button","aria-label":"Last page",disabled:r===t||o,style:d(!1,r===t||o),onClick:()=>f(t),onMouseEnter:n=>{r!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:e.jsx(G,{})})]})});j.displayName="Pagination";exports.Pagination=j;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),j=require("react"),B=require("../../../utils/styles.cjs"),u=require("../../../design-system/tokens/spacing.cjs"),y=require("../../../design-system/tokens/typography.cjs"),N=require("../../../design-system/primitives/sizing.cjs"),v=require("../../../design-system/tokens/motion.cjs"),O={navigation:"Pagination",first:"First page",previous:"Previous page",next:"Next page",last:"Last page",page:p=>`Page ${p}`,of:(p,e)=>`Page ${p} of ${e}`},G={sm:{height:u.spacing[7],fontSize:y.fontSizes.sm,gap:u.spacing[1],minWidth:u.spacing[7]},md:{height:u.spacing[9],fontSize:y.fontSizes.base,gap:N.componentGap.sm,minWidth:u.spacing[9]},lg:{height:u.spacing[11],fontSize:y.fontSizes.md,gap:u.spacing[2],minWidth:u.spacing[11]}};function F(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M10 12L6 8l4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function H(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M6 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function J(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M11 12l-4-4 4-4M7 12l-4-4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}function K(){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",children:r.jsx("path",{d:"M5 4l4 4-4 4M9 4l4 4-4 4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const C=j.forwardRef(function({page:e,totalPages:t,onChange:M,size:k="md",variant:c="default",siblingCount:d=1,showFirstLast:m=!0,showPrevNext:b=!0,disabled:o=!1,labels:S,className:L,style:z,testId:W,...$},T){const s=G[k],l={...O,...S},q=j.useMemo(()=>{if(c==="minimal"||c==="simple")return[];const n=[],a=Math.max(e-d,1),h=Math.min(e+d,t),R=a>2,x=h<t-1;if(R)if(x){n.push(1),n.push("ellipsis");for(let i=a;i<=h;i++)n.push(i);n.push("ellipsis"),n.push(t)}else{n.push(1),n.push("ellipsis");for(let i=Math.max(t-2-d,1);i<=t;i++)n.push(i)}else{for(let i=1;i<=Math.min(3+d,t);i++)n.push(i);x&&(n.push("ellipsis"),n.push(t))}return n},[e,t,d,c]),w={display:"flex",alignItems:"center",gap:s.gap,...z},f=(n,a)=>({display:"inline-flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,padding:`0 ${s.gap+4}px`,fontSize:s.fontSize,fontWeight:n?600:500,color:a?"var(--brycks-foreground-disabled)":n?"var(--brycks-primary-default)":"var(--brycks-foreground-default)",backgroundColor:n?"var(--brycks-primary-muted)":"transparent",border:"none",borderRadius:"var(--brycks-radius-md)",cursor:a?"not-allowed":"pointer",transition:`all ${v.durations.quick}ms ${v.easings.easeOut}`}),E={display:"flex",alignItems:"center",justifyContent:"center",minWidth:s.minWidth,height:s.height,color:"var(--brycks-foreground-muted)",fontSize:s.fontSize},I={fontSize:s.fontSize,color:"var(--brycks-foreground-muted)",padding:`0 ${s.gap}px`},g=n=>{n>=1&&n<=t&&n!==e&&!o&&M(n)};return r.jsxs("nav",{ref:T,role:"navigation","aria-label":l.navigation,className:B.cx("brycks-pagination",`brycks-pagination--${k}`,`brycks-pagination--${c}`,L),style:w,"data-testid":W,...$,children:[m&&c!=="minimal"&&r.jsx("button",{type:"button","aria-label":l.first,disabled:e===1||o,style:f(!1,e===1||o),onClick:()=>g(1),onMouseEnter:n=>{e!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(J,{})}),b&&r.jsx("button",{type:"button","aria-label":l.previous,disabled:e===1||o,style:f(!1,e===1||o),onClick:()=>g(e-1),onMouseEnter:n=>{e!==1&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(F,{})}),c==="simple"||c==="minimal"?r.jsx("span",{style:I,children:c==="minimal"?`${e} / ${t}`:l.of(e,t)}):q.map((n,a)=>n==="ellipsis"?r.jsx("span",{style:E,children:"..."},`ellipsis-${a}`):r.jsx("button",{type:"button","aria-label":l.page(n),"aria-current":n===e?"page":void 0,disabled:o,style:f(n===e,o),onClick:()=>g(n),onMouseEnter:h=>{n!==e&&!o&&(h.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:h=>{n!==e&&(h.currentTarget.style.backgroundColor="transparent")},children:n},n)),b&&r.jsx("button",{type:"button","aria-label":l.next,disabled:e===t||o,style:f(!1,e===t||o),onClick:()=>g(e+1),onMouseEnter:n=>{e!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(H,{})}),m&&c!=="minimal"&&r.jsx("button",{type:"button","aria-label":l.last,disabled:e===t||o,style:f(!1,e===t||o),onClick:()=>g(t),onMouseEnter:n=>{e!==t&&!o&&(n.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:n=>{n.currentTarget.style.backgroundColor="transparent"},children:r.jsx(K,{})})]})});C.displayName="Pagination";exports.Pagination=C;
2
2
  //# sourceMappingURL=Pagination.cjs.map