@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":"Card.js","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n *\n * All color styles are handled via CSS classes for easy customization.\n */\n\nimport { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n variant = 'elevated',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n `brycks-card--padding-${padding}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={style}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx('brycks-card__header', divider && 'brycks-card__header--divider', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n return (\n <div ref={ref} className={cx('brycks-card__body', className)} style={style} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card__footer',\n divider && 'brycks-card__footer--divider',\n `brycks-card__footer--${align}`,\n className\n )}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","jsx","cx","CardHeader","divider","CardBody","CardFooter","align"],"mappings":";;;AAmDO,MAAMA,IAAOC,EAAsC,SACxD;AAAA,EACE,SAAAC,IAAU;AAAA,EACV,SAAAC,IAAU;AAAA,EACV,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACA,gBAAgBX,CAAO;AAAA,QACvB,wBAAwBC,CAAO;AAAA,QAC/BC,KAAe;AAAA,QACfC,KAAY;AAAA,QACZC;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACA,eAAaE;AAAA,MACZ,GAAGC;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDR,EAAK,cAAc;AAEZ,MAAMc,IAAab,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,WAAAT,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GAClDC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE,EAAG,uBAAuBE,KAAW,gCAAgCT,CAAS;AAAA,MACzF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDM,EAAW,cAAc;AAElB,MAAME,IAAWf,EAA0C,SAChE,EAAE,WAAAK,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACjCC,GACA;AACA,SACE,gBAAAC,EAAC,OAAA,EAAI,KAAAD,GAAU,WAAWE,EAAG,qBAAqBP,CAAS,GAAG,OAAAC,GAAe,GAAGG,GAC7E,UAAAF,EAAA,CACH;AAEJ,CAAC;AAEDQ,EAAS,cAAc;AAEhB,MAAMC,IAAahB,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,OAAAG,IAAQ,SAAS,WAAAZ,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACnEC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACAE,KAAW;AAAA,QACX,wBAAwBG,CAAK;AAAA,QAC7BZ;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDS,EAAW,cAAc;"}
1
+ {"version":3,"file":"Card.js","sources":["../../../../src/components/layout/Card/Card.tsx"],"sourcesContent":["/**\n * Card Component\n *\n * A flexible card container with optional header, footer, and body sections.\n * Supports different variants and padding sizes.\n *\n * All color styles are handled via CSS classes for easy customization.\n */\n\nimport { forwardRef, type HTMLAttributes } from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport type CardVariant = 'elevated' | 'outline' | 'filled' | 'ghost'\nexport type CardPadding = 'none' | 'sm' | 'md' | 'lg' | 'xl'\n\nexport interface CardProps extends HTMLAttributes<HTMLDivElement> {\n /** Card variant */\n variant?: CardVariant\n /** Card padding */\n padding?: CardPadding\n /** Whether the card is interactive (adds hover effect) */\n interactive?: boolean\n /** Whether the card is selected */\n selected?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider below the header */\n divider?: boolean\n /** Custom class name */\n className?: string\n}\n\nexport interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {\n /** Custom class name */\n className?: string\n}\n\nexport interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {\n /** Whether to show a divider above the footer */\n divider?: boolean\n /** Footer alignment */\n align?: 'left' | 'center' | 'right' | 'between'\n /** Custom class name */\n className?: string\n}\n\nexport const Card = forwardRef<HTMLDivElement, CardProps>(function Card(\n {\n // Flat-by-default: a 1px border conveys depth. Opt into shadow with\n // `variant=\"elevated\"`.\n variant = 'outline',\n padding = 'md',\n interactive = false,\n selected = false,\n className,\n style,\n children,\n testId,\n ...props\n },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card',\n `brycks-card--${variant}`,\n `brycks-card--padding-${padding}`,\n interactive && 'brycks-card--interactive',\n selected && 'brycks-card--selected',\n className\n )}\n style={style}\n data-testid={testId}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCard.displayName = 'Card'\n\nexport const CardHeader = forwardRef<HTMLDivElement, CardHeaderProps>(function CardHeader(\n { divider = false, className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx('brycks-card__header', divider && 'brycks-card__header--divider', className)}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardHeader.displayName = 'CardHeader'\n\nexport const CardBody = forwardRef<HTMLDivElement, CardBodyProps>(function CardBody(\n { className, style, children, ...props },\n ref\n) {\n return (\n <div ref={ref} className={cx('brycks-card__body', className)} style={style} {...props}>\n {children}\n </div>\n )\n})\n\nCardBody.displayName = 'CardBody'\n\nexport const CardFooter = forwardRef<HTMLDivElement, CardFooterProps>(function CardFooter(\n { divider = false, align = 'right', className, style, children, ...props },\n ref\n) {\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-card__footer',\n divider && 'brycks-card__footer--divider',\n `brycks-card__footer--${align}`,\n className\n )}\n style={style}\n {...props}\n >\n {children}\n </div>\n )\n})\n\nCardFooter.displayName = 'CardFooter'\n"],"names":["Card","forwardRef","variant","padding","interactive","selected","className","style","children","testId","props","ref","jsx","cx","CardHeader","divider","CardBody","CardFooter","align"],"mappings":";;;AAmDO,MAAMA,IAAOC,EAAsC,SACxD;AAAA;AAAA;AAAA,EAGE,SAAAC,IAAU;AAAA,EACV,SAAAC,IAAU;AAAA,EACV,aAAAC,IAAc;AAAA,EACd,UAAAC,IAAW;AAAA,EACX,WAAAC;AAAA,EACA,OAAAC;AAAA,EACA,UAAAC;AAAA,EACA,QAAAC;AAAA,EACA,GAAGC;AACL,GACAC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACA,gBAAgBX,CAAO;AAAA,QACvB,wBAAwBC,CAAO;AAAA,QAC/BC,KAAe;AAAA,QACfC,KAAY;AAAA,QACZC;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACA,eAAaE;AAAA,MACZ,GAAGC;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDR,EAAK,cAAc;AAEZ,MAAMc,IAAab,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,WAAAT,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GAClDC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE,EAAG,uBAAuBE,KAAW,gCAAgCT,CAAS;AAAA,MACzF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDM,EAAW,cAAc;AAElB,MAAME,IAAWf,EAA0C,SAChE,EAAE,WAAAK,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACjCC,GACA;AACA,SACE,gBAAAC,EAAC,OAAA,EAAI,KAAAD,GAAU,WAAWE,EAAG,qBAAqBP,CAAS,GAAG,OAAAC,GAAe,GAAGG,GAC7E,UAAAF,EAAA,CACH;AAEJ,CAAC;AAEDQ,EAAS,cAAc;AAEhB,MAAMC,IAAahB,EAA4C,SACpE,EAAE,SAAAc,IAAU,IAAO,OAAAG,IAAQ,SAAS,WAAAZ,GAAW,OAAAC,GAAO,UAAAC,GAAU,GAAGE,EAAA,GACnEC,GACA;AACA,SACE,gBAAAC;AAAA,IAAC;AAAA,IAAA;AAAA,MACC,KAAAD;AAAA,MACA,WAAWE;AAAA,QACT;AAAA,QACAE,KAAW;AAAA,QACX,wBAAwBG,CAAK;AAAA,QAC7BZ;AAAA,MAAA;AAAA,MAEF,OAAAC;AAAA,MACC,GAAGG;AAAA,MAEH,UAAAF;AAAA,IAAA;AAAA,EAAA;AAGP,CAAC;AAEDS,EAAW,cAAc;"}
@@ -1 +1 @@
1
- {"version":3,"file":"Collapse.cjs","sources":["../../../../src/components/layout/Collapse/Collapse.tsx"],"sourcesContent":["/**\n * Collapse Component\n *\n * A component for expandable/collapsible content with smooth animations.\n * Supports controlled and uncontrolled modes.\n *\n * @module components/layout/Collapse\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { durations, easings } from '../../../design-system'\n\nexport interface CollapseProps {\n /** Whether the content is expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Content to show when collapsed */\n children: ReactNode\n /** Animation duration in milliseconds */\n duration?: number\n /** Easing function */\n easing?: string\n /** Whether to animate on initial render */\n animateOnMount?: boolean\n /** Whether to unmount content when collapsed */\n unmountOnCollapse?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapse = forwardRef<HTMLDivElement, CollapseProps>(function Collapse(\n {\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n children,\n duration = durations.normal,\n easing = easings.easeOut,\n animateOnMount = false,\n unmountOnCollapse = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n const [height, setHeight] = useState<number | 'auto'>(defaultIsOpen ? 'auto' : 0)\n const [isAnimating, setIsAnimating] = useState(false)\n const [shouldRender, setShouldRender] = useState(defaultIsOpen || !unmountOnCollapse)\n\n const contentRef = useRef<HTMLDivElement>(null)\n const isInitialRender = useRef(true)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n // Sync internal state with controlled value changes\n useEffect(() => {\n if (controlledIsOpen !== undefined && controlledIsOpen !== internalIsOpen) {\n setInternalIsOpen(controlledIsOpen)\n }\n }, [controlledIsOpen, internalIsOpen])\n\n // Handle animation\n useEffect(() => {\n if (isInitialRender.current) {\n isInitialRender.current = false\n if (!animateOnMount) {\n setHeight(isOpen ? 'auto' : 0)\n setShouldRender(isOpen || !unmountOnCollapse)\n return\n }\n }\n\n const content = contentRef.current\n if (!content) return\n\n if (isOpen) {\n // Expanding\n setShouldRender(true)\n setIsAnimating(true)\n\n // Get the natural height\n const naturalHeight = content.scrollHeight\n\n // Start from 0\n setHeight(0)\n\n // Force reflow\n content.offsetHeight\n\n // Animate to natural height\n requestAnimationFrame(() => {\n setHeight(naturalHeight)\n })\n\n // After animation, set to auto\n const timer = setTimeout(() => {\n setHeight('auto')\n setIsAnimating(false)\n }, duration)\n\n return () => clearTimeout(timer)\n } else {\n // Collapsing\n setIsAnimating(true)\n\n // Get current height\n const currentHeight = content.scrollHeight\n setHeight(currentHeight)\n\n // Force reflow\n content.offsetHeight\n\n // Animate to 0\n requestAnimationFrame(() => {\n setHeight(0)\n })\n\n // After animation, optionally unmount\n const timer = setTimeout(() => {\n setIsAnimating(false)\n if (unmountOnCollapse) {\n setShouldRender(false)\n }\n }, duration)\n\n return () => clearTimeout(timer)\n }\n }, [isOpen, duration, animateOnMount, unmountOnCollapse])\n\n const containerStyle: CSSProperties = {\n overflow: 'hidden',\n height: height,\n transition: isAnimating ? `height ${duration}ms ${easing}` : undefined,\n willChange: isAnimating ? 'height' : undefined,\n }\n\n const contentStyle: CSSProperties = {\n // Prevent margin collapse\n display: 'flow-root',\n }\n\n if (!shouldRender && unmountOnCollapse) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapse',\n isOpen && 'brycks-collapse--open',\n isAnimating && 'brycks-collapse--animating',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n aria-hidden={!isOpen}\n >\n <div ref={contentRef} style={contentStyle}>\n {children}\n </div>\n </div>\n )\n})\n\nCollapse.displayName = 'Collapse'\n\n// Helper component for creating collapsible sections with header\nexport interface CollapsibleProps {\n /** Header content (always visible) */\n header: ReactNode\n /** Collapsible content */\n children: ReactNode\n /** Whether expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Callback when expanded state changes */\n onToggle?: (isOpen: boolean) => void\n /** Whether the collapsible is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n {\n header,\n children,\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n onToggle,\n disabled = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n\n const newIsOpen = !isOpen\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(newIsOpen)\n }\n onToggle?.(newIsOpen)\n }, [disabled, isOpen, controlledIsOpen, onToggle])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle]\n )\n\n const containerStyle: CSSProperties = {\n width: '100%',\n }\n\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n userSelect: 'none',\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapsible',\n isOpen && 'brycks-collapsible--open',\n disabled && 'brycks-collapsible--disabled',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-expanded={isOpen}\n aria-disabled={disabled}\n style={headerStyle}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {header}\n </div>\n <Collapse isOpen={isOpen}>\n {children}\n </Collapse>\n </div>\n )\n})\n\nCollapsible.displayName = 'Collapsible'\n"],"names":["Collapse","forwardRef","controlledIsOpen","defaultIsOpen","children","duration","durations","easing","easings","animateOnMount","unmountOnCollapse","className","testId","ref","internalIsOpen","setInternalIsOpen","useState","height","setHeight","isAnimating","setIsAnimating","shouldRender","setShouldRender","contentRef","useRef","isInitialRender","isOpen","useEffect","content","naturalHeight","timer","currentHeight","containerStyle","contentStyle","jsx","cx","Collapsible","header","onToggle","disabled","handleToggle","useCallback","newIsOpen","handleKeyDown","e","headerStyle","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Collapse.cjs","sources":["../../../../src/components/layout/Collapse/Collapse.tsx"],"sourcesContent":["/**\n * Collapse Component\n *\n * A component for expandable/collapsible content with smooth animations.\n * Supports controlled and uncontrolled modes.\n *\n * @module components/layout/Collapse\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { durations, easings } from '../../../design-system'\n\nexport interface CollapseProps {\n /** Whether the content is expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Content to show when collapsed */\n children: ReactNode\n /** Animation duration in milliseconds */\n duration?: number\n /** Easing function */\n easing?: string\n /** Whether to animate on initial render */\n animateOnMount?: boolean\n /** Whether to unmount content when collapsed */\n unmountOnCollapse?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapse = forwardRef<HTMLDivElement, CollapseProps>(function Collapse(\n {\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n children,\n duration = durations.normal,\n easing = easings.easeOut,\n animateOnMount = false,\n unmountOnCollapse = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n const [height, setHeight] = useState<number | 'auto'>(defaultIsOpen ? 'auto' : 0)\n const [isAnimating, setIsAnimating] = useState(false)\n const [shouldRender, setShouldRender] = useState(defaultIsOpen || !unmountOnCollapse)\n\n const contentRef = useRef<HTMLDivElement>(null)\n const isInitialRender = useRef(true)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n // Sync internal state with controlled value changes\n useEffect(() => {\n if (controlledIsOpen !== undefined && controlledIsOpen !== internalIsOpen) {\n setInternalIsOpen(controlledIsOpen)\n }\n }, [controlledIsOpen, internalIsOpen])\n\n // Handle animation\n useEffect(() => {\n if (isInitialRender.current) {\n isInitialRender.current = false\n if (!animateOnMount) {\n setHeight(isOpen ? 'auto' : 0)\n setShouldRender(isOpen || !unmountOnCollapse)\n return\n }\n }\n\n const content = contentRef.current\n if (!content) return\n\n if (isOpen) {\n // Expanding\n setShouldRender(true)\n setIsAnimating(true)\n\n // Get the natural height\n const naturalHeight = content.scrollHeight\n\n // Start from 0\n setHeight(0)\n\n // Force reflow\n void content.offsetHeight\n\n // Animate to natural height\n requestAnimationFrame(() => {\n setHeight(naturalHeight)\n })\n\n // After animation, set to auto\n const timer = setTimeout(() => {\n setHeight('auto')\n setIsAnimating(false)\n }, duration)\n\n return () => clearTimeout(timer)\n } else {\n // Collapsing\n setIsAnimating(true)\n\n // Get current height\n const currentHeight = content.scrollHeight\n setHeight(currentHeight)\n\n // Force reflow\n void content.offsetHeight\n\n // Animate to 0\n requestAnimationFrame(() => {\n setHeight(0)\n })\n\n // After animation, optionally unmount\n const timer = setTimeout(() => {\n setIsAnimating(false)\n if (unmountOnCollapse) {\n setShouldRender(false)\n }\n }, duration)\n\n return () => clearTimeout(timer)\n }\n }, [isOpen, duration, animateOnMount, unmountOnCollapse])\n\n const containerStyle: CSSProperties = {\n overflow: 'hidden',\n height: height,\n transition: isAnimating ? `height ${duration}ms ${easing}` : undefined,\n willChange: isAnimating ? 'height' : undefined,\n }\n\n const contentStyle: CSSProperties = {\n // Prevent margin collapse\n display: 'flow-root',\n }\n\n if (!shouldRender && unmountOnCollapse) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapse',\n isOpen && 'brycks-collapse--open',\n isAnimating && 'brycks-collapse--animating',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n aria-hidden={!isOpen}\n >\n <div ref={contentRef} style={contentStyle}>\n {children}\n </div>\n </div>\n )\n})\n\nCollapse.displayName = 'Collapse'\n\n// Helper component for creating collapsible sections with header\nexport interface CollapsibleProps {\n /** Header content (always visible) */\n header: ReactNode\n /** Collapsible content */\n children: ReactNode\n /** Whether expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Callback when expanded state changes */\n onToggle?: (isOpen: boolean) => void\n /** Whether the collapsible is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n {\n header,\n children,\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n onToggle,\n disabled = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n\n const newIsOpen = !isOpen\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(newIsOpen)\n }\n onToggle?.(newIsOpen)\n }, [disabled, isOpen, controlledIsOpen, onToggle])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle]\n )\n\n const containerStyle: CSSProperties = {\n width: '100%',\n }\n\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n userSelect: 'none',\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapsible',\n isOpen && 'brycks-collapsible--open',\n disabled && 'brycks-collapsible--disabled',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-expanded={isOpen}\n aria-disabled={disabled}\n style={headerStyle}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {header}\n </div>\n <Collapse isOpen={isOpen}>\n {children}\n </Collapse>\n </div>\n )\n})\n\nCollapsible.displayName = 'Collapsible'\n"],"names":["Collapse","forwardRef","controlledIsOpen","defaultIsOpen","children","duration","durations","easing","easings","animateOnMount","unmountOnCollapse","className","testId","ref","internalIsOpen","setInternalIsOpen","useState","height","setHeight","isAnimating","setIsAnimating","shouldRender","setShouldRender","contentRef","useRef","isInitialRender","isOpen","useEffect","content","naturalHeight","timer","currentHeight","containerStyle","contentStyle","jsx","cx","Collapsible","header","onToggle","disabled","handleToggle","useCallback","newIsOpen","handleKeyDown","e","headerStyle","jsxs"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"Collapse.js","sources":["../../../../src/components/layout/Collapse/Collapse.tsx"],"sourcesContent":["/**\n * Collapse Component\n *\n * A component for expandable/collapsible content with smooth animations.\n * Supports controlled and uncontrolled modes.\n *\n * @module components/layout/Collapse\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { durations, easings } from '../../../design-system'\n\nexport interface CollapseProps {\n /** Whether the content is expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Content to show when collapsed */\n children: ReactNode\n /** Animation duration in milliseconds */\n duration?: number\n /** Easing function */\n easing?: string\n /** Whether to animate on initial render */\n animateOnMount?: boolean\n /** Whether to unmount content when collapsed */\n unmountOnCollapse?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapse = forwardRef<HTMLDivElement, CollapseProps>(function Collapse(\n {\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n children,\n duration = durations.normal,\n easing = easings.easeOut,\n animateOnMount = false,\n unmountOnCollapse = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n const [height, setHeight] = useState<number | 'auto'>(defaultIsOpen ? 'auto' : 0)\n const [isAnimating, setIsAnimating] = useState(false)\n const [shouldRender, setShouldRender] = useState(defaultIsOpen || !unmountOnCollapse)\n\n const contentRef = useRef<HTMLDivElement>(null)\n const isInitialRender = useRef(true)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n // Sync internal state with controlled value changes\n useEffect(() => {\n if (controlledIsOpen !== undefined && controlledIsOpen !== internalIsOpen) {\n setInternalIsOpen(controlledIsOpen)\n }\n }, [controlledIsOpen, internalIsOpen])\n\n // Handle animation\n useEffect(() => {\n if (isInitialRender.current) {\n isInitialRender.current = false\n if (!animateOnMount) {\n setHeight(isOpen ? 'auto' : 0)\n setShouldRender(isOpen || !unmountOnCollapse)\n return\n }\n }\n\n const content = contentRef.current\n if (!content) return\n\n if (isOpen) {\n // Expanding\n setShouldRender(true)\n setIsAnimating(true)\n\n // Get the natural height\n const naturalHeight = content.scrollHeight\n\n // Start from 0\n setHeight(0)\n\n // Force reflow\n content.offsetHeight\n\n // Animate to natural height\n requestAnimationFrame(() => {\n setHeight(naturalHeight)\n })\n\n // After animation, set to auto\n const timer = setTimeout(() => {\n setHeight('auto')\n setIsAnimating(false)\n }, duration)\n\n return () => clearTimeout(timer)\n } else {\n // Collapsing\n setIsAnimating(true)\n\n // Get current height\n const currentHeight = content.scrollHeight\n setHeight(currentHeight)\n\n // Force reflow\n content.offsetHeight\n\n // Animate to 0\n requestAnimationFrame(() => {\n setHeight(0)\n })\n\n // After animation, optionally unmount\n const timer = setTimeout(() => {\n setIsAnimating(false)\n if (unmountOnCollapse) {\n setShouldRender(false)\n }\n }, duration)\n\n return () => clearTimeout(timer)\n }\n }, [isOpen, duration, animateOnMount, unmountOnCollapse])\n\n const containerStyle: CSSProperties = {\n overflow: 'hidden',\n height: height,\n transition: isAnimating ? `height ${duration}ms ${easing}` : undefined,\n willChange: isAnimating ? 'height' : undefined,\n }\n\n const contentStyle: CSSProperties = {\n // Prevent margin collapse\n display: 'flow-root',\n }\n\n if (!shouldRender && unmountOnCollapse) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapse',\n isOpen && 'brycks-collapse--open',\n isAnimating && 'brycks-collapse--animating',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n aria-hidden={!isOpen}\n >\n <div ref={contentRef} style={contentStyle}>\n {children}\n </div>\n </div>\n )\n})\n\nCollapse.displayName = 'Collapse'\n\n// Helper component for creating collapsible sections with header\nexport interface CollapsibleProps {\n /** Header content (always visible) */\n header: ReactNode\n /** Collapsible content */\n children: ReactNode\n /** Whether expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Callback when expanded state changes */\n onToggle?: (isOpen: boolean) => void\n /** Whether the collapsible is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n {\n header,\n children,\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n onToggle,\n disabled = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n\n const newIsOpen = !isOpen\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(newIsOpen)\n }\n onToggle?.(newIsOpen)\n }, [disabled, isOpen, controlledIsOpen, onToggle])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle]\n )\n\n const containerStyle: CSSProperties = {\n width: '100%',\n }\n\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n userSelect: 'none',\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapsible',\n isOpen && 'brycks-collapsible--open',\n disabled && 'brycks-collapsible--disabled',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-expanded={isOpen}\n aria-disabled={disabled}\n style={headerStyle}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {header}\n </div>\n <Collapse isOpen={isOpen}>\n {children}\n </Collapse>\n </div>\n )\n})\n\nCollapsible.displayName = 'Collapsible'\n"],"names":["Collapse","forwardRef","controlledIsOpen","defaultIsOpen","children","duration","durations","easing","easings","animateOnMount","unmountOnCollapse","className","testId","ref","internalIsOpen","setInternalIsOpen","useState","height","setHeight","isAnimating","setIsAnimating","shouldRender","setShouldRender","contentRef","useRef","isInitialRender","isOpen","useEffect","content","naturalHeight","timer","currentHeight","containerStyle","contentStyle","jsx","cx","Collapsible","header","onToggle","disabled","handleToggle","useCallback","newIsOpen","handleKeyDown","e","headerStyle","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Collapse.js","sources":["../../../../src/components/layout/Collapse/Collapse.tsx"],"sourcesContent":["/**\n * Collapse Component\n *\n * A component for expandable/collapsible content with smooth animations.\n * Supports controlled and uncontrolled modes.\n *\n * @module components/layout/Collapse\n */\n\nimport {\n forwardRef,\n useState,\n useCallback,\n useRef,\n useEffect,\n type CSSProperties,\n type ReactNode,\n} from 'react'\nimport { cx } from '../../../utils/styles'\nimport { durations, easings } from '../../../design-system'\n\nexport interface CollapseProps {\n /** Whether the content is expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Content to show when collapsed */\n children: ReactNode\n /** Animation duration in milliseconds */\n duration?: number\n /** Easing function */\n easing?: string\n /** Whether to animate on initial render */\n animateOnMount?: boolean\n /** Whether to unmount content when collapsed */\n unmountOnCollapse?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapse = forwardRef<HTMLDivElement, CollapseProps>(function Collapse(\n {\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n children,\n duration = durations.normal,\n easing = easings.easeOut,\n animateOnMount = false,\n unmountOnCollapse = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n const [height, setHeight] = useState<number | 'auto'>(defaultIsOpen ? 'auto' : 0)\n const [isAnimating, setIsAnimating] = useState(false)\n const [shouldRender, setShouldRender] = useState(defaultIsOpen || !unmountOnCollapse)\n\n const contentRef = useRef<HTMLDivElement>(null)\n const isInitialRender = useRef(true)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n // Sync internal state with controlled value changes\n useEffect(() => {\n if (controlledIsOpen !== undefined && controlledIsOpen !== internalIsOpen) {\n setInternalIsOpen(controlledIsOpen)\n }\n }, [controlledIsOpen, internalIsOpen])\n\n // Handle animation\n useEffect(() => {\n if (isInitialRender.current) {\n isInitialRender.current = false\n if (!animateOnMount) {\n setHeight(isOpen ? 'auto' : 0)\n setShouldRender(isOpen || !unmountOnCollapse)\n return\n }\n }\n\n const content = contentRef.current\n if (!content) return\n\n if (isOpen) {\n // Expanding\n setShouldRender(true)\n setIsAnimating(true)\n\n // Get the natural height\n const naturalHeight = content.scrollHeight\n\n // Start from 0\n setHeight(0)\n\n // Force reflow\n void content.offsetHeight\n\n // Animate to natural height\n requestAnimationFrame(() => {\n setHeight(naturalHeight)\n })\n\n // After animation, set to auto\n const timer = setTimeout(() => {\n setHeight('auto')\n setIsAnimating(false)\n }, duration)\n\n return () => clearTimeout(timer)\n } else {\n // Collapsing\n setIsAnimating(true)\n\n // Get current height\n const currentHeight = content.scrollHeight\n setHeight(currentHeight)\n\n // Force reflow\n void content.offsetHeight\n\n // Animate to 0\n requestAnimationFrame(() => {\n setHeight(0)\n })\n\n // After animation, optionally unmount\n const timer = setTimeout(() => {\n setIsAnimating(false)\n if (unmountOnCollapse) {\n setShouldRender(false)\n }\n }, duration)\n\n return () => clearTimeout(timer)\n }\n }, [isOpen, duration, animateOnMount, unmountOnCollapse])\n\n const containerStyle: CSSProperties = {\n overflow: 'hidden',\n height: height,\n transition: isAnimating ? `height ${duration}ms ${easing}` : undefined,\n willChange: isAnimating ? 'height' : undefined,\n }\n\n const contentStyle: CSSProperties = {\n // Prevent margin collapse\n display: 'flow-root',\n }\n\n if (!shouldRender && unmountOnCollapse) {\n return null\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapse',\n isOpen && 'brycks-collapse--open',\n isAnimating && 'brycks-collapse--animating',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n aria-hidden={!isOpen}\n >\n <div ref={contentRef} style={contentStyle}>\n {children}\n </div>\n </div>\n )\n})\n\nCollapse.displayName = 'Collapse'\n\n// Helper component for creating collapsible sections with header\nexport interface CollapsibleProps {\n /** Header content (always visible) */\n header: ReactNode\n /** Collapsible content */\n children: ReactNode\n /** Whether expanded (controlled) */\n isOpen?: boolean\n /** Default expanded state (uncontrolled) */\n defaultIsOpen?: boolean\n /** Callback when expanded state changes */\n onToggle?: (isOpen: boolean) => void\n /** Whether the collapsible is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nexport const Collapsible = forwardRef<HTMLDivElement, CollapsibleProps>(function Collapsible(\n {\n header,\n children,\n isOpen: controlledIsOpen,\n defaultIsOpen = false,\n onToggle,\n disabled = false,\n className,\n testId,\n },\n ref\n) {\n const [internalIsOpen, setInternalIsOpen] = useState(defaultIsOpen)\n\n const isOpen = controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen\n\n const handleToggle = useCallback(() => {\n if (disabled) return\n\n const newIsOpen = !isOpen\n if (controlledIsOpen === undefined) {\n setInternalIsOpen(newIsOpen)\n }\n onToggle?.(newIsOpen)\n }, [disabled, isOpen, controlledIsOpen, onToggle])\n\n const handleKeyDown = useCallback(\n (e: React.KeyboardEvent) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleToggle()\n }\n },\n [handleToggle]\n )\n\n const containerStyle: CSSProperties = {\n width: '100%',\n }\n\n const headerStyle: CSSProperties = {\n display: 'flex',\n alignItems: 'center',\n width: '100%',\n cursor: disabled ? 'not-allowed' : 'pointer',\n opacity: disabled ? 0.5 : 1,\n userSelect: 'none',\n }\n\n return (\n <div\n ref={ref}\n className={cx(\n 'brycks-collapsible',\n isOpen && 'brycks-collapsible--open',\n disabled && 'brycks-collapsible--disabled',\n className\n )}\n style={containerStyle}\n data-testid={testId}\n >\n <div\n role=\"button\"\n tabIndex={disabled ? -1 : 0}\n aria-expanded={isOpen}\n aria-disabled={disabled}\n style={headerStyle}\n onClick={handleToggle}\n onKeyDown={handleKeyDown}\n >\n {header}\n </div>\n <Collapse isOpen={isOpen}>\n {children}\n </Collapse>\n </div>\n )\n})\n\nCollapsible.displayName = 'Collapsible'\n"],"names":["Collapse","forwardRef","controlledIsOpen","defaultIsOpen","children","duration","durations","easing","easings","animateOnMount","unmountOnCollapse","className","testId","ref","internalIsOpen","setInternalIsOpen","useState","height","setHeight","isAnimating","setIsAnimating","shouldRender","setShouldRender","contentRef","useRef","isInitialRender","isOpen","useEffect","content","naturalHeight","timer","currentHeight","containerStyle","contentStyle","jsx","cx","Collapsible","header","onToggle","disabled","handleToggle","useCallback","newIsOpen","handleKeyDown","e","headerStyle","jsxs"],"mappings":"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"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),u=require("react"),h=require("../../../utils/styles.cjs"),N={none:"0",sm:"var(--brycks-radius-sm)",md:"var(--brycks-radius-md)",lg:"var(--brycks-radius-lg)",xl:"var(--brycks-radius-xl)",full:"var(--brycks-radius-full)"};function M(e){if(e===void 0)return;if(typeof e=="number")return e;const o=e.split(/[:/]/);if(o.length===2){const n=parseFloat(o[0]),s=parseFloat(o[1]);if(!isNaN(n)&&!isNaN(s)&&s!==0)return n/s}const r=parseFloat(e);return isNaN(r)?void 0:r}const S=u.forwardRef(function({src:o,alt:r,aspectRatio:n,fit:s="cover",loading:R="lazy",fallback:d,placeholder:c,radius:C="none",showBackground:F=!0,onLoad:p,onError:k,className:g,style:y,testId:m,...f},q){const[i,x]=u.useState("loading"),I=u.useCallback(v=>{x("loaded"),p?.(v)},[p]),B=u.useCallback(v=>{x("error"),k?.(v)},[k]),a=M(n),l=N[C]??N.none,b={position:"relative",overflow:"hidden",borderRadius:l,backgroundColor:F&&i==="loading"?"var(--brycks-background-muted)":void 0,...a?{width:"100%",paddingBottom:`${1/a*100}%`}:{}},j={display:"block",objectFit:s,borderRadius:l,...a?{position:"absolute",top:0,left:0,width:"100%",height:"100%"}:{width:y?.width??"100%",height:y?.height??"auto"},opacity:i==="loaded"?1:0,transition:"opacity var(--brycks-duration-normal, 200ms) var(--brycks-easing-out, ease-out)",...y},w={position:"absolute",top:0,left:0,right:0,bottom:0,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:l};return i==="error"?typeof d=="string"?t.jsx("div",{className:h.cx("brycks-image","brycks-image--fallback",g),style:b,"data-testid":m,children:t.jsx("img",{src:d,alt:r,style:{...j,opacity:1},...f})}):t.jsxs("div",{className:h.cx("brycks-image","brycks-image--error",g),style:{...b,backgroundColor:"var(--brycks-background-muted)"},"data-testid":m,role:"img","aria-label":r,children:[a&&t.jsx("div",{style:{paddingBottom:`${1/a*100}%`}}),d&&t.jsx("div",{style:w,children:d})]}):t.jsxs("div",{className:h.cx("brycks-image",i==="loading"&&"brycks-image--loading",i==="loaded"&&"brycks-image--loaded",g),style:a?b:{position:"relative",borderRadius:l},"data-testid":m,children:[i==="loading"&&c&&t.jsx("div",{style:w,children:typeof c=="string"?t.jsx("img",{src:c,alt:"","aria-hidden":"true",style:{width:"100%",height:"100%",objectFit:s,filter:"blur(10px)",transform:"scale(1.1)"}}):c}),t.jsx("img",{ref:q,src:o,alt:r,loading:R,onLoad:I,onError:B,style:j,...f})]})});S.displayName="Image";exports.Image=S;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),u=require("react"),h=require("../../../utils/styles.cjs"),N={none:"0",sm:"var(--brycks-radius-sm)",md:"var(--brycks-radius-md)",lg:"var(--brycks-radius-lg)",xl:"var(--brycks-radius-xl)",full:"var(--brycks-radius-full)"};function M(e){if(e===void 0)return;if(typeof e=="number")return e;const o=e.split(/[:/]/);if(o.length===2){const n=parseFloat(o[0]),s=parseFloat(o[1]);if(!isNaN(n)&&!isNaN(s)&&s!==0)return n/s}const r=parseFloat(e);return isNaN(r)?void 0:r}const S=u.forwardRef(function({src:o,alt:r,aspectRatio:n,fit:s="cover",loading:R="lazy",fallback:d,placeholder:c,radius:C="none",showBackground:F=!0,onLoad:p,onError:k,className:g,style:y,testId:m,...f},q){const[i,x]=u.useState("loading"),I=u.useCallback(v=>{x("loaded"),p?.(v)},[p]),B=u.useCallback(v=>{x("error"),k?.(v)},[k]),a=M(n),l=N[C]??N.none,b={position:"relative",overflow:"hidden",borderRadius:l,backgroundColor:F&&i==="loading"?"var(--brycks-background-muted)":void 0,...a?{width:"100%",paddingBottom:`${1/a*100}%`}:{}},j={display:"block",objectFit:s,borderRadius:l,...a?{position:"absolute",top:0,left:0,width:"100%",height:"100%"}:{width:y?.width??"100%",height:y?.height??"auto"},opacity:i==="loaded"?1:0,transition:"opacity var(--brycks-duration-normal, 200ms) var(--brycks-ease-out, ease-out)",...y},w={position:"absolute",top:0,left:0,right:0,bottom:0,display:"flex",alignItems:"center",justifyContent:"center",borderRadius:l};return i==="error"?typeof d=="string"?t.jsx("div",{className:h.cx("brycks-image","brycks-image--fallback",g),style:b,"data-testid":m,children:t.jsx("img",{src:d,alt:r,style:{...j,opacity:1},...f})}):t.jsxs("div",{className:h.cx("brycks-image","brycks-image--error",g),style:{...b,backgroundColor:"var(--brycks-background-muted)"},"data-testid":m,role:"img","aria-label":r,children:[a&&t.jsx("div",{style:{paddingBottom:`${1/a*100}%`}}),d&&t.jsx("div",{style:w,children:d})]}):t.jsxs("div",{className:h.cx("brycks-image",i==="loading"&&"brycks-image--loading",i==="loaded"&&"brycks-image--loaded",g),style:a?b:{position:"relative",borderRadius:l},"data-testid":m,children:[i==="loading"&&c&&t.jsx("div",{style:w,children:typeof c=="string"?t.jsx("img",{src:c,alt:"","aria-hidden":"true",style:{width:"100%",height:"100%",objectFit:s,filter:"blur(10px)",transform:"scale(1.1)"}}):c}),t.jsx("img",{ref:q,src:o,alt:r,loading:R,onLoad:I,onError:B,style:j,...f})]})});S.displayName="Image";exports.Image=S;
2
2
  //# sourceMappingURL=Image.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Image.cjs","sources":["../../../../src/components/media/Image/Image.tsx"],"sourcesContent":["/**\r\n * Image Component\r\n *\r\n * Responsive image with lazy loading, fallback support, and aspect ratio control.\r\n * Follows accessibility best practices and design system conventions.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useState,\r\n useCallback,\r\n type CSSProperties,\r\n type ImgHTMLAttributes,\r\n type ReactNode,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\n\r\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type ImageLoading = 'lazy' | 'eager'\r\n\r\nexport interface ImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\r\n /** Image source URL */\r\n src: string\r\n /** Alternative text for accessibility (required) */\r\n alt: string\r\n /** Aspect ratio (width/height). If set, maintains ratio */\r\n aspectRatio?: number | string\r\n /** How the image should fit within its container */\r\n fit?: ImageFit\r\n /** Loading strategy */\r\n loading?: ImageLoading\r\n /** Fallback content or URL when image fails to load */\r\n fallback?: ReactNode | string\r\n /** Placeholder shown while loading */\r\n placeholder?: ReactNode | string\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Whether to show a subtle background while loading */\r\n showBackground?: boolean\r\n /** Callback when image loads successfully */\r\n onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Callback when image fails to load */\r\n onError?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n // Handle string formats like \"16:9\" or \"16/9\"\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\r\n {\r\n src,\r\n alt,\r\n aspectRatio,\r\n fit = 'cover',\r\n loading = 'lazy',\r\n fallback,\r\n placeholder,\r\n radius = 'none',\r\n showBackground = true,\r\n onLoad,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const [status, setStatus] = useState<'loading' | 'loaded' | 'error'>('loading')\r\n\r\n const handleLoad = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('loaded')\r\n onLoad?.(event)\r\n },\r\n [onLoad]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('error')\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n // Container styles for aspect ratio support\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor:\r\n showBackground && status === 'loading'\r\n ? 'var(--brycks-background-muted)'\r\n : undefined,\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n }\r\n\r\n const imageStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: style?.width ?? '100%',\r\n height: style?.height ?? 'auto',\r\n }),\r\n opacity: status === 'loaded' ? 1 : 0,\r\n transition: 'opacity var(--brycks-duration-normal, 200ms) var(--brycks-easing-out, ease-out)',\r\n ...style,\r\n }\r\n\r\n const overlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n borderRadius,\r\n }\r\n\r\n // Render fallback content\r\n if (status === 'error') {\r\n if (typeof fallback === 'string') {\r\n // Fallback is an image URL\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--fallback', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n >\r\n <img\r\n src={fallback}\r\n alt={alt}\r\n style={{\r\n ...imageStyle,\r\n opacity: 1,\r\n }}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n // Fallback is a ReactNode\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--error', className)}\r\n style={{\r\n ...containerStyle,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n }}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label={alt}\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n {fallback && <div style={overlayStyle}>{fallback}</div>}\r\n </div>\r\n )\r\n }\r\n\r\n // Render image with optional placeholder\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-image',\r\n status === 'loading' && 'brycks-image--loading',\r\n status === 'loaded' && 'brycks-image--loaded',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n {/* Placeholder */}\r\n {status === 'loading' && placeholder && (\r\n <div style={overlayStyle}>\r\n {typeof placeholder === 'string' ? (\r\n <img\r\n src={placeholder}\r\n alt=\"\"\r\n aria-hidden=\"true\"\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n objectFit: fit,\r\n filter: 'blur(10px)',\r\n transform: 'scale(1.1)',\r\n }}\r\n />\r\n ) : (\r\n placeholder\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Main image */}\r\n <img\r\n ref={ref}\r\n src={src}\r\n alt={alt}\r\n loading={loading}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nImage.displayName = 'Image'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Image","forwardRef","src","alt","aspectRatio","fit","loading","fallback","placeholder","radius","showBackground","onLoad","onError","className","style","testId","props","ref","status","setStatus","useState","handleLoad","useCallback","event","handleError","parsedRatio","borderRadius","containerStyle","imageStyle","overlayStyle","jsx","cx","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Image.cjs","sources":["../../../../src/components/media/Image/Image.tsx"],"sourcesContent":["/**\r\n * Image Component\r\n *\r\n * Responsive image with lazy loading, fallback support, and aspect ratio control.\r\n * Follows accessibility best practices and design system conventions.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useState,\r\n useCallback,\r\n type CSSProperties,\r\n type ImgHTMLAttributes,\r\n type ReactNode,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\n\r\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type ImageLoading = 'lazy' | 'eager'\r\n\r\nexport interface ImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\r\n /** Image source URL */\r\n src: string\r\n /** Alternative text for accessibility (required) */\r\n alt: string\r\n /** Aspect ratio (width/height). If set, maintains ratio */\r\n aspectRatio?: number | string\r\n /** How the image should fit within its container */\r\n fit?: ImageFit\r\n /** Loading strategy */\r\n loading?: ImageLoading\r\n /** Fallback content or URL when image fails to load */\r\n fallback?: ReactNode | string\r\n /** Placeholder shown while loading */\r\n placeholder?: ReactNode | string\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Whether to show a subtle background while loading */\r\n showBackground?: boolean\r\n /** Callback when image loads successfully */\r\n onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Callback when image fails to load */\r\n onError?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n // Handle string formats like \"16:9\" or \"16/9\"\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\r\n {\r\n src,\r\n alt,\r\n aspectRatio,\r\n fit = 'cover',\r\n loading = 'lazy',\r\n fallback,\r\n placeholder,\r\n radius = 'none',\r\n showBackground = true,\r\n onLoad,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const [status, setStatus] = useState<'loading' | 'loaded' | 'error'>('loading')\r\n\r\n const handleLoad = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('loaded')\r\n onLoad?.(event)\r\n },\r\n [onLoad]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('error')\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n // Container styles for aspect ratio support\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor:\r\n showBackground && status === 'loading'\r\n ? 'var(--brycks-background-muted)'\r\n : undefined,\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n }\r\n\r\n const imageStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: style?.width ?? '100%',\r\n height: style?.height ?? 'auto',\r\n }),\r\n opacity: status === 'loaded' ? 1 : 0,\r\n transition: 'opacity var(--brycks-duration-normal, 200ms) var(--brycks-ease-out, ease-out)',\r\n ...style,\r\n }\r\n\r\n const overlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n borderRadius,\r\n }\r\n\r\n // Render fallback content\r\n if (status === 'error') {\r\n if (typeof fallback === 'string') {\r\n // Fallback is an image URL\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--fallback', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n >\r\n <img\r\n src={fallback}\r\n alt={alt}\r\n style={{\r\n ...imageStyle,\r\n opacity: 1,\r\n }}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n // Fallback is a ReactNode\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--error', className)}\r\n style={{\r\n ...containerStyle,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n }}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label={alt}\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n {fallback && <div style={overlayStyle}>{fallback}</div>}\r\n </div>\r\n )\r\n }\r\n\r\n // Render image with optional placeholder\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-image',\r\n status === 'loading' && 'brycks-image--loading',\r\n status === 'loaded' && 'brycks-image--loaded',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n {/* Placeholder */}\r\n {status === 'loading' && placeholder && (\r\n <div style={overlayStyle}>\r\n {typeof placeholder === 'string' ? (\r\n <img\r\n src={placeholder}\r\n alt=\"\"\r\n aria-hidden=\"true\"\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n objectFit: fit,\r\n filter: 'blur(10px)',\r\n transform: 'scale(1.1)',\r\n }}\r\n />\r\n ) : (\r\n placeholder\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Main image */}\r\n <img\r\n ref={ref}\r\n src={src}\r\n alt={alt}\r\n loading={loading}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nImage.displayName = 'Image'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Image","forwardRef","src","alt","aspectRatio","fit","loading","fallback","placeholder","radius","showBackground","onLoad","onError","className","style","testId","props","ref","status","setStatus","useState","handleLoad","useCallback","event","handleError","parsedRatio","borderRadius","containerStyle","imageStyle","overlayStyle","jsx","cx","jsxs"],"mappings":"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"}
@@ -33,8 +33,8 @@ const L = z(function({
33
33
  showBackground: R = !0,
34
34
  onLoad: h,
35
35
  onError: v,
36
- className: g,
37
- style: u,
36
+ className: u,
37
+ style: g,
38
38
  testId: y,
39
39
  ...f
40
40
  }, B) {
@@ -68,12 +68,12 @@ const L = z(function({
68
68
  width: "100%",
69
69
  height: "100%"
70
70
  } : {
71
- width: u?.width ?? "100%",
72
- height: u?.height ?? "auto"
71
+ width: g?.width ?? "100%",
72
+ height: g?.height ?? "auto"
73
73
  },
74
74
  opacity: o === "loaded" ? 1 : 0,
75
- transition: "opacity var(--brycks-duration-normal, 200ms) var(--brycks-easing-out, ease-out)",
76
- ...u
75
+ transition: "opacity var(--brycks-duration-normal, 200ms) var(--brycks-ease-out, ease-out)",
76
+ ...g
77
77
  }, x = {
78
78
  position: "absolute",
79
79
  top: 0,
@@ -88,7 +88,7 @@ const L = z(function({
88
88
  return o === "error" ? typeof d == "string" ? /* @__PURE__ */ t(
89
89
  "div",
90
90
  {
91
- className: p("brycks-image", "brycks-image--fallback", g),
91
+ className: p("brycks-image", "brycks-image--fallback", u),
92
92
  style: m,
93
93
  "data-testid": y,
94
94
  children: /* @__PURE__ */ t(
@@ -107,7 +107,7 @@ const L = z(function({
107
107
  ) : /* @__PURE__ */ N(
108
108
  "div",
109
109
  {
110
- className: p("brycks-image", "brycks-image--error", g),
110
+ className: p("brycks-image", "brycks-image--error", u),
111
111
  style: {
112
112
  ...m,
113
113
  backgroundColor: "var(--brycks-background-muted)"
@@ -127,7 +127,7 @@ const L = z(function({
127
127
  "brycks-image",
128
128
  o === "loading" && "brycks-image--loading",
129
129
  o === "loaded" && "brycks-image--loaded",
130
- g
130
+ u
131
131
  ),
132
132
  style: a ? m : { position: "relative", borderRadius: c },
133
133
  "data-testid": y,
@@ -1 +1 @@
1
- {"version":3,"file":"Image.js","sources":["../../../../src/components/media/Image/Image.tsx"],"sourcesContent":["/**\r\n * Image Component\r\n *\r\n * Responsive image with lazy loading, fallback support, and aspect ratio control.\r\n * Follows accessibility best practices and design system conventions.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useState,\r\n useCallback,\r\n type CSSProperties,\r\n type ImgHTMLAttributes,\r\n type ReactNode,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\n\r\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type ImageLoading = 'lazy' | 'eager'\r\n\r\nexport interface ImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\r\n /** Image source URL */\r\n src: string\r\n /** Alternative text for accessibility (required) */\r\n alt: string\r\n /** Aspect ratio (width/height). If set, maintains ratio */\r\n aspectRatio?: number | string\r\n /** How the image should fit within its container */\r\n fit?: ImageFit\r\n /** Loading strategy */\r\n loading?: ImageLoading\r\n /** Fallback content or URL when image fails to load */\r\n fallback?: ReactNode | string\r\n /** Placeholder shown while loading */\r\n placeholder?: ReactNode | string\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Whether to show a subtle background while loading */\r\n showBackground?: boolean\r\n /** Callback when image loads successfully */\r\n onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Callback when image fails to load */\r\n onError?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n // Handle string formats like \"16:9\" or \"16/9\"\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\r\n {\r\n src,\r\n alt,\r\n aspectRatio,\r\n fit = 'cover',\r\n loading = 'lazy',\r\n fallback,\r\n placeholder,\r\n radius = 'none',\r\n showBackground = true,\r\n onLoad,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const [status, setStatus] = useState<'loading' | 'loaded' | 'error'>('loading')\r\n\r\n const handleLoad = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('loaded')\r\n onLoad?.(event)\r\n },\r\n [onLoad]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('error')\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n // Container styles for aspect ratio support\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor:\r\n showBackground && status === 'loading'\r\n ? 'var(--brycks-background-muted)'\r\n : undefined,\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n }\r\n\r\n const imageStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: style?.width ?? '100%',\r\n height: style?.height ?? 'auto',\r\n }),\r\n opacity: status === 'loaded' ? 1 : 0,\r\n transition: 'opacity var(--brycks-duration-normal, 200ms) var(--brycks-easing-out, ease-out)',\r\n ...style,\r\n }\r\n\r\n const overlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n borderRadius,\r\n }\r\n\r\n // Render fallback content\r\n if (status === 'error') {\r\n if (typeof fallback === 'string') {\r\n // Fallback is an image URL\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--fallback', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n >\r\n <img\r\n src={fallback}\r\n alt={alt}\r\n style={{\r\n ...imageStyle,\r\n opacity: 1,\r\n }}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n // Fallback is a ReactNode\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--error', className)}\r\n style={{\r\n ...containerStyle,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n }}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label={alt}\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n {fallback && <div style={overlayStyle}>{fallback}</div>}\r\n </div>\r\n )\r\n }\r\n\r\n // Render image with optional placeholder\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-image',\r\n status === 'loading' && 'brycks-image--loading',\r\n status === 'loaded' && 'brycks-image--loaded',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n {/* Placeholder */}\r\n {status === 'loading' && placeholder && (\r\n <div style={overlayStyle}>\r\n {typeof placeholder === 'string' ? (\r\n <img\r\n src={placeholder}\r\n alt=\"\"\r\n aria-hidden=\"true\"\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n objectFit: fit,\r\n filter: 'blur(10px)',\r\n transform: 'scale(1.1)',\r\n }}\r\n />\r\n ) : (\r\n placeholder\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Main image */}\r\n <img\r\n ref={ref}\r\n src={src}\r\n alt={alt}\r\n loading={loading}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nImage.displayName = 'Image'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Image","forwardRef","src","alt","aspectRatio","fit","loading","fallback","placeholder","radius","showBackground","onLoad","onError","className","style","testId","props","ref","status","setStatus","useState","handleLoad","useCallback","event","handleError","parsedRatio","borderRadius","containerStyle","imageStyle","overlayStyle","jsx","cx","jsxs"],"mappings":"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"}
1
+ {"version":3,"file":"Image.js","sources":["../../../../src/components/media/Image/Image.tsx"],"sourcesContent":["/**\r\n * Image Component\r\n *\r\n * Responsive image with lazy loading, fallback support, and aspect ratio control.\r\n * Follows accessibility best practices and design system conventions.\r\n */\r\n\r\nimport {\r\n forwardRef,\r\n useState,\r\n useCallback,\r\n type CSSProperties,\r\n type ImgHTMLAttributes,\r\n type ReactNode,\r\n type SyntheticEvent,\r\n} from 'react'\r\nimport { cx } from '../../../utils/styles'\r\n\r\nexport type ImageFit = 'cover' | 'contain' | 'fill' | 'none' | 'scale-down'\r\nexport type ImageLoading = 'lazy' | 'eager'\r\n\r\nexport interface ImageProps\r\n extends Omit<ImgHTMLAttributes<HTMLImageElement>, 'placeholder'> {\r\n /** Image source URL */\r\n src: string\r\n /** Alternative text for accessibility (required) */\r\n alt: string\r\n /** Aspect ratio (width/height). If set, maintains ratio */\r\n aspectRatio?: number | string\r\n /** How the image should fit within its container */\r\n fit?: ImageFit\r\n /** Loading strategy */\r\n loading?: ImageLoading\r\n /** Fallback content or URL when image fails to load */\r\n fallback?: ReactNode | string\r\n /** Placeholder shown while loading */\r\n placeholder?: ReactNode | string\r\n /** Border radius using design tokens */\r\n radius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full'\r\n /** Whether to show a subtle background while loading */\r\n showBackground?: boolean\r\n /** Callback when image loads successfully */\r\n onLoad?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Callback when image fails to load */\r\n onError?: (event: SyntheticEvent<HTMLImageElement>) => void\r\n /** Custom class name */\r\n className?: string\r\n /** Test ID */\r\n testId?: string\r\n}\r\n\r\nconst radiusMap: Record<string, string> = {\r\n none: '0',\r\n sm: 'var(--brycks-radius-sm)',\r\n md: 'var(--brycks-radius-md)',\r\n lg: 'var(--brycks-radius-lg)',\r\n xl: 'var(--brycks-radius-xl)',\r\n full: 'var(--brycks-radius-full)',\r\n}\r\n\r\nfunction parseAspectRatio(ratio: number | string | undefined): number | undefined {\r\n if (ratio === undefined) return undefined\r\n if (typeof ratio === 'number') return ratio\r\n\r\n // Handle string formats like \"16:9\" or \"16/9\"\r\n const parts = ratio.split(/[:/]/)\r\n if (parts.length === 2) {\r\n const width = parseFloat(parts[0])\r\n const height = parseFloat(parts[1])\r\n if (!isNaN(width) && !isNaN(height) && height !== 0) {\r\n return width / height\r\n }\r\n }\r\n\r\n const parsed = parseFloat(ratio)\r\n return isNaN(parsed) ? undefined : parsed\r\n}\r\n\r\nexport const Image = forwardRef<HTMLImageElement, ImageProps>(function Image(\r\n {\r\n src,\r\n alt,\r\n aspectRatio,\r\n fit = 'cover',\r\n loading = 'lazy',\r\n fallback,\r\n placeholder,\r\n radius = 'none',\r\n showBackground = true,\r\n onLoad,\r\n onError,\r\n className,\r\n style,\r\n testId,\r\n ...props\r\n },\r\n ref\r\n) {\r\n const [status, setStatus] = useState<'loading' | 'loaded' | 'error'>('loading')\r\n\r\n const handleLoad = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('loaded')\r\n onLoad?.(event)\r\n },\r\n [onLoad]\r\n )\r\n\r\n const handleError = useCallback(\r\n (event: SyntheticEvent<HTMLImageElement>) => {\r\n setStatus('error')\r\n onError?.(event)\r\n },\r\n [onError]\r\n )\r\n\r\n const parsedRatio = parseAspectRatio(aspectRatio)\r\n const borderRadius = radiusMap[radius] ?? radiusMap.none\r\n\r\n // Container styles for aspect ratio support\r\n const containerStyle: CSSProperties = {\r\n position: 'relative',\r\n overflow: 'hidden',\r\n borderRadius,\r\n backgroundColor:\r\n showBackground && status === 'loading'\r\n ? 'var(--brycks-background-muted)'\r\n : undefined,\r\n ...(parsedRatio\r\n ? {\r\n width: '100%',\r\n paddingBottom: `${(1 / parsedRatio) * 100}%`,\r\n }\r\n : {}),\r\n }\r\n\r\n const imageStyle: CSSProperties = {\r\n display: 'block',\r\n objectFit: fit,\r\n borderRadius,\r\n ...(parsedRatio\r\n ? {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n width: '100%',\r\n height: '100%',\r\n }\r\n : {\r\n width: style?.width ?? '100%',\r\n height: style?.height ?? 'auto',\r\n }),\r\n opacity: status === 'loaded' ? 1 : 0,\r\n transition: 'opacity var(--brycks-duration-normal, 200ms) var(--brycks-ease-out, ease-out)',\r\n ...style,\r\n }\r\n\r\n const overlayStyle: CSSProperties = {\r\n position: 'absolute',\r\n top: 0,\r\n left: 0,\r\n right: 0,\r\n bottom: 0,\r\n display: 'flex',\r\n alignItems: 'center',\r\n justifyContent: 'center',\r\n borderRadius,\r\n }\r\n\r\n // Render fallback content\r\n if (status === 'error') {\r\n if (typeof fallback === 'string') {\r\n // Fallback is an image URL\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--fallback', className)}\r\n style={containerStyle}\r\n data-testid={testId}\r\n >\r\n <img\r\n src={fallback}\r\n alt={alt}\r\n style={{\r\n ...imageStyle,\r\n opacity: 1,\r\n }}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n }\r\n\r\n // Fallback is a ReactNode\r\n return (\r\n <div\r\n className={cx('brycks-image', 'brycks-image--error', className)}\r\n style={{\r\n ...containerStyle,\r\n backgroundColor: 'var(--brycks-background-muted)',\r\n }}\r\n data-testid={testId}\r\n role=\"img\"\r\n aria-label={alt}\r\n >\r\n {parsedRatio && <div style={{ paddingBottom: `${(1 / parsedRatio) * 100}%` }} />}\r\n {fallback && <div style={overlayStyle}>{fallback}</div>}\r\n </div>\r\n )\r\n }\r\n\r\n // Render image with optional placeholder\r\n return (\r\n <div\r\n className={cx(\r\n 'brycks-image',\r\n status === 'loading' && 'brycks-image--loading',\r\n status === 'loaded' && 'brycks-image--loaded',\r\n className\r\n )}\r\n style={parsedRatio ? containerStyle : { position: 'relative', borderRadius }}\r\n data-testid={testId}\r\n >\r\n {/* Placeholder */}\r\n {status === 'loading' && placeholder && (\r\n <div style={overlayStyle}>\r\n {typeof placeholder === 'string' ? (\r\n <img\r\n src={placeholder}\r\n alt=\"\"\r\n aria-hidden=\"true\"\r\n style={{\r\n width: '100%',\r\n height: '100%',\r\n objectFit: fit,\r\n filter: 'blur(10px)',\r\n transform: 'scale(1.1)',\r\n }}\r\n />\r\n ) : (\r\n placeholder\r\n )}\r\n </div>\r\n )}\r\n\r\n {/* Main image */}\r\n <img\r\n ref={ref}\r\n src={src}\r\n alt={alt}\r\n loading={loading}\r\n onLoad={handleLoad}\r\n onError={handleError}\r\n style={imageStyle}\r\n {...props}\r\n />\r\n </div>\r\n )\r\n})\r\n\r\nImage.displayName = 'Image'\r\n"],"names":["radiusMap","parseAspectRatio","ratio","parts","width","height","parsed","Image","forwardRef","src","alt","aspectRatio","fit","loading","fallback","placeholder","radius","showBackground","onLoad","onError","className","style","testId","props","ref","status","setStatus","useState","handleLoad","useCallback","event","handleError","parsedRatio","borderRadius","containerStyle","imageStyle","overlayStyle","jsx","cx","jsxs"],"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"),w=require("react"),x=require("../../../utils/styles.cjs"),S={sm:{width:60,deleteSize:18},md:{width:80,deleteSize:20},lg:{width:100,deleteSize:24}},l=w.forwardRef(function({src:d,alt:c,isSelected:r=!1,badge:o,onClick:u,onDelete:s,size:i="md",aspectRatio:b="1",disabled:e=!1,className:m,testId:g},y){const t=S[i],h={position:"relative",width:t.width,aspectRatio:b,padding:0,border:r?"2px solid var(--brycks-primary-default)":"2px solid transparent",borderRadius:"var(--brycks-radius-md)",overflow:"hidden",cursor:e?"not-allowed":"pointer",background:"var(--brycks-background-muted)",opacity:e?.5:1,transition:"border-color var(--brycks-duration-fast) var(--brycks-easing-out)"},p={width:"100%",height:"100%",objectFit:"cover",display:"block"},k={position:"absolute",top:4,right:4,width:t.deleteSize,height:t.deleteSize,borderRadius:"50%",background:"rgba(0, 0, 0, 0.7)",color:"white",border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",fontSize:t.deleteSize*.6,fontWeight:600,lineHeight:1,padding:0,transition:"background var(--brycks-duration-fast) var(--brycks-easing-out)"},f={position:"absolute",bottom:4,left:4,background:"var(--brycks-primary-default)",color:"white",padding:"2px 6px",borderRadius:"var(--brycks-radius-sm)",fontSize:i==="sm"?8:i==="md"?10:11,fontWeight:600,lineHeight:1,textTransform:"uppercase"},v=n=>{n.stopPropagation(),s?.(n)};return a.jsxs("button",{ref:y,type:"button",className:x.cx("brycks-image-thumbnail",r&&"brycks-image-thumbnail--selected",e&&"brycks-image-thumbnail--disabled",m),style:h,onClick:u,disabled:e,"data-testid":g,"aria-pressed":r,children:[a.jsx("img",{src:d,alt:c,style:p}),s&&!e&&a.jsx("button",{type:"button",className:"brycks-image-thumbnail__delete",style:k,onClick:v,"aria-label":"Remove image",children:"×"}),o&&a.jsx("span",{className:"brycks-image-thumbnail__badge",style:f,children:o})]})});l.displayName="ImageThumbnail";exports.ImageThumbnail=l;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const a=require("react/jsx-runtime"),w=require("react"),x=require("../../../utils/styles.cjs"),S={sm:{width:60,deleteSize:18},md:{width:80,deleteSize:20},lg:{width:100,deleteSize:24}},l=w.forwardRef(function({src:d,alt:c,isSelected:r=!1,badge:o,onClick:u,onDelete:s,size:i="md",aspectRatio:b="1",disabled:e=!1,className:m,testId:g},y){const t=S[i],h={position:"relative",width:t.width,aspectRatio:b,padding:0,border:r?"2px solid var(--brycks-primary-default)":"2px solid transparent",borderRadius:"var(--brycks-radius-md)",overflow:"hidden",cursor:e?"not-allowed":"pointer",background:"var(--brycks-background-muted)",opacity:e?.5:1,transition:"border-color var(--brycks-duration-fast) var(--brycks-ease-out)"},p={width:"100%",height:"100%",objectFit:"cover",display:"block"},k={position:"absolute",top:4,right:4,width:t.deleteSize,height:t.deleteSize,borderRadius:"50%",background:"rgba(0, 0, 0, 0.7)",color:"white",border:"none",cursor:"pointer",display:"flex",alignItems:"center",justifyContent:"center",fontSize:t.deleteSize*.6,fontWeight:600,lineHeight:1,padding:0,transition:"background var(--brycks-duration-fast) var(--brycks-ease-out)"},f={position:"absolute",bottom:4,left:4,background:"var(--brycks-primary-default)",color:"white",padding:"2px 6px",borderRadius:"var(--brycks-radius-sm)",fontSize:i==="sm"?8:i==="md"?10:11,fontWeight:600,lineHeight:1,textTransform:"uppercase"},v=n=>{n.stopPropagation(),s?.(n)};return a.jsxs("button",{ref:y,type:"button",className:x.cx("brycks-image-thumbnail",r&&"brycks-image-thumbnail--selected",e&&"brycks-image-thumbnail--disabled",m),style:h,onClick:u,disabled:e,"data-testid":g,"aria-pressed":r,children:[a.jsx("img",{src:d,alt:c,style:p}),s&&!e&&a.jsx("button",{type:"button",className:"brycks-image-thumbnail__delete",style:k,onClick:v,"aria-label":"Remove image",children:"×"}),o&&a.jsx("span",{className:"brycks-image-thumbnail__badge",style:f,children:o})]})});l.displayName="ImageThumbnail";exports.ImageThumbnail=l;
2
2
  //# sourceMappingURL=ImageThumbnail.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ImageThumbnail.cjs","sources":["../../../../src/components/media/ImageThumbnail/ImageThumbnail.tsx"],"sourcesContent":["/**\n * ImageThumbnail Component\n *\n * Thumbnail image with selection state, optional badge, and delete action.\n * Designed for image galleries and media selection interfaces.\n */\n\nimport {\n forwardRef,\n type CSSProperties,\n type ReactNode,\n type MouseEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport interface ImageThumbnailProps {\n /** Image source URL */\n src: string\n /** Alternative text for accessibility */\n alt: string\n /** Whether this thumbnail is selected */\n isSelected?: boolean\n /** Badge content (e.g., \"COVER\", \"PRIMARY\") */\n badge?: ReactNode\n /** Callback when thumbnail is clicked */\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Callback when delete button is clicked */\n onDelete?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Size of the thumbnail */\n size?: 'sm' | 'md' | 'lg'\n /** Aspect ratio of the thumbnail */\n aspectRatio?: '1' | '4/3' | '16/9'\n /** Whether the thumbnail is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeMap: Record<string, { width: number; deleteSize: number }> = {\n sm: { width: 60, deleteSize: 18 },\n md: { width: 80, deleteSize: 20 },\n lg: { width: 100, deleteSize: 24 },\n}\n\nexport const ImageThumbnail = forwardRef<HTMLButtonElement, ImageThumbnailProps>(\n function ImageThumbnail(\n {\n src,\n alt,\n isSelected = false,\n badge,\n onClick,\n onDelete,\n size = 'md',\n aspectRatio = '1',\n disabled = false,\n className,\n testId,\n },\n ref\n ) {\n const sizeValue = sizeMap[size]\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n width: sizeValue.width,\n aspectRatio,\n padding: 0,\n border: isSelected\n ? '2px solid var(--brycks-primary-default)'\n : '2px solid transparent',\n borderRadius: 'var(--brycks-radius-md)',\n overflow: 'hidden',\n cursor: disabled ? 'not-allowed' : 'pointer',\n background: 'var(--brycks-background-muted)',\n opacity: disabled ? 0.5 : 1,\n transition: 'border-color var(--brycks-duration-fast) var(--brycks-easing-out)',\n }\n\n const imageStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n display: 'block',\n }\n\n const deleteButtonStyle: CSSProperties = {\n position: 'absolute',\n top: 4,\n right: 4,\n width: sizeValue.deleteSize,\n height: sizeValue.deleteSize,\n borderRadius: '50%',\n background: 'rgba(0, 0, 0, 0.7)',\n color: 'white',\n border: 'none',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: sizeValue.deleteSize * 0.6,\n fontWeight: 600,\n lineHeight: 1,\n padding: 0,\n transition: 'background var(--brycks-duration-fast) var(--brycks-easing-out)',\n }\n\n const badgeStyle: CSSProperties = {\n position: 'absolute',\n bottom: 4,\n left: 4,\n background: 'var(--brycks-primary-default)',\n color: 'white',\n padding: '2px 6px',\n borderRadius: 'var(--brycks-radius-sm)',\n fontSize: size === 'sm' ? 8 : size === 'md' ? 10 : 11,\n fontWeight: 600,\n lineHeight: 1,\n textTransform: 'uppercase',\n }\n\n const handleDelete = (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onDelete?.(e)\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cx(\n 'brycks-image-thumbnail',\n isSelected && 'brycks-image-thumbnail--selected',\n disabled && 'brycks-image-thumbnail--disabled',\n className\n )}\n style={containerStyle}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n aria-pressed={isSelected}\n >\n <img src={src} alt={alt} style={imageStyle} />\n\n {onDelete && !disabled && (\n <button\n type=\"button\"\n className=\"brycks-image-thumbnail__delete\"\n style={deleteButtonStyle}\n onClick={handleDelete}\n aria-label=\"Remove image\"\n >\n ×\n </button>\n )}\n\n {badge && (\n <span className=\"brycks-image-thumbnail__badge\" style={badgeStyle}>\n {badge}\n </span>\n )}\n </button>\n )\n }\n)\n\nImageThumbnail.displayName = 'ImageThumbnail'\n"],"names":["sizeMap","ImageThumbnail","forwardRef","src","alt","isSelected","badge","onClick","onDelete","size","aspectRatio","disabled","className","testId","ref","sizeValue","containerStyle","imageStyle","deleteButtonStyle","badgeStyle","handleDelete","e","jsxs","cx","jsx"],"mappings":"+KAwCMA,EAAiE,CACrE,GAAI,CAAE,MAAO,GAAI,WAAY,EAAA,EAC7B,GAAI,CAAE,MAAO,GAAI,WAAY,EAAA,EAC7B,GAAI,CAAE,MAAO,IAAK,WAAY,EAAA,CAChC,EAEaC,EAAiBC,EAAAA,WAC5B,SACE,CACE,IAAAC,EACA,IAAAC,EACA,WAAAC,EAAa,GACb,MAAAC,EACA,QAAAC,EACA,SAAAC,EACA,KAAAC,EAAO,KACP,YAAAC,EAAc,IACd,SAAAC,EAAW,GACX,UAAAC,EACA,OAAAC,CAAA,EAEFC,EACA,CACA,MAAMC,EAAYf,EAAQS,CAAI,EAExBO,EAAgC,CACpC,SAAU,WACV,MAAOD,EAAU,MACjB,YAAAL,EACA,QAAS,EACT,OAAQL,EACJ,0CACA,wBACJ,aAAc,0BACd,SAAU,SACV,OAAQM,EAAW,cAAgB,UACnC,WAAY,iCACZ,QAASA,EAAW,GAAM,EAC1B,WAAY,mEAAA,EAGRM,EAA4B,CAChC,MAAO,OACP,OAAQ,OACR,UAAW,QACX,QAAS,OAAA,EAGLC,EAAmC,CACvC,SAAU,WACV,IAAK,EACL,MAAO,EACP,MAAOH,EAAU,WACjB,OAAQA,EAAU,WAClB,aAAc,MACd,WAAY,qBACZ,MAAO,QACP,OAAQ,OACR,OAAQ,UACR,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,SAAUA,EAAU,WAAa,GACjC,WAAY,IACZ,WAAY,EACZ,QAAS,EACT,WAAY,iEAAA,EAGRI,EAA4B,CAChC,SAAU,WACV,OAAQ,EACR,KAAM,EACN,WAAY,gCACZ,MAAO,QACP,QAAS,UACT,aAAc,0BACd,SAAUV,IAAS,KAAO,EAAIA,IAAS,KAAO,GAAK,GACnD,WAAY,IACZ,WAAY,EACZ,cAAe,WAAA,EAGXW,EAAgBC,GAAqC,CACzDA,EAAE,gBAAA,EACFb,IAAWa,CAAC,CACd,EAEA,OACEC,EAAAA,KAAC,SAAA,CACC,IAAAR,EACA,KAAK,SACL,UAAWS,EAAAA,GACT,yBACAlB,GAAc,mCACdM,GAAY,mCACZC,CAAA,EAEF,MAAOI,EACP,QAAAT,EACA,SAAAI,EACA,cAAaE,EACb,eAAcR,EAEd,SAAA,CAAAmB,EAAAA,IAAC,MAAA,CAAI,IAAArB,EAAU,IAAAC,EAAU,MAAOa,EAAY,EAE3CT,GAAY,CAACG,GACZa,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAU,iCACV,MAAON,EACP,QAASE,EACT,aAAW,eACZ,SAAA,GAAA,CAAA,EAKFd,GACCkB,EAAAA,IAAC,OAAA,CAAK,UAAU,gCAAgC,MAAOL,EACpD,SAAAb,CAAA,CACH,CAAA,CAAA,CAAA,CAIR,CACF,EAEAL,EAAe,YAAc"}
1
+ {"version":3,"file":"ImageThumbnail.cjs","sources":["../../../../src/components/media/ImageThumbnail/ImageThumbnail.tsx"],"sourcesContent":["/**\n * ImageThumbnail Component\n *\n * Thumbnail image with selection state, optional badge, and delete action.\n * Designed for image galleries and media selection interfaces.\n */\n\nimport {\n forwardRef,\n type CSSProperties,\n type ReactNode,\n type MouseEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport interface ImageThumbnailProps {\n /** Image source URL */\n src: string\n /** Alternative text for accessibility */\n alt: string\n /** Whether this thumbnail is selected */\n isSelected?: boolean\n /** Badge content (e.g., \"COVER\", \"PRIMARY\") */\n badge?: ReactNode\n /** Callback when thumbnail is clicked */\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Callback when delete button is clicked */\n onDelete?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Size of the thumbnail */\n size?: 'sm' | 'md' | 'lg'\n /** Aspect ratio of the thumbnail */\n aspectRatio?: '1' | '4/3' | '16/9'\n /** Whether the thumbnail is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeMap: Record<string, { width: number; deleteSize: number }> = {\n sm: { width: 60, deleteSize: 18 },\n md: { width: 80, deleteSize: 20 },\n lg: { width: 100, deleteSize: 24 },\n}\n\nexport const ImageThumbnail = forwardRef<HTMLButtonElement, ImageThumbnailProps>(\n function ImageThumbnail(\n {\n src,\n alt,\n isSelected = false,\n badge,\n onClick,\n onDelete,\n size = 'md',\n aspectRatio = '1',\n disabled = false,\n className,\n testId,\n },\n ref\n ) {\n const sizeValue = sizeMap[size]\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n width: sizeValue.width,\n aspectRatio,\n padding: 0,\n border: isSelected\n ? '2px solid var(--brycks-primary-default)'\n : '2px solid transparent',\n borderRadius: 'var(--brycks-radius-md)',\n overflow: 'hidden',\n cursor: disabled ? 'not-allowed' : 'pointer',\n background: 'var(--brycks-background-muted)',\n opacity: disabled ? 0.5 : 1,\n transition: 'border-color var(--brycks-duration-fast) var(--brycks-ease-out)',\n }\n\n const imageStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n display: 'block',\n }\n\n const deleteButtonStyle: CSSProperties = {\n position: 'absolute',\n top: 4,\n right: 4,\n width: sizeValue.deleteSize,\n height: sizeValue.deleteSize,\n borderRadius: '50%',\n background: 'rgba(0, 0, 0, 0.7)',\n color: 'white',\n border: 'none',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: sizeValue.deleteSize * 0.6,\n fontWeight: 600,\n lineHeight: 1,\n padding: 0,\n transition: 'background var(--brycks-duration-fast) var(--brycks-ease-out)',\n }\n\n const badgeStyle: CSSProperties = {\n position: 'absolute',\n bottom: 4,\n left: 4,\n background: 'var(--brycks-primary-default)',\n color: 'white',\n padding: '2px 6px',\n borderRadius: 'var(--brycks-radius-sm)',\n fontSize: size === 'sm' ? 8 : size === 'md' ? 10 : 11,\n fontWeight: 600,\n lineHeight: 1,\n textTransform: 'uppercase',\n }\n\n const handleDelete = (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onDelete?.(e)\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cx(\n 'brycks-image-thumbnail',\n isSelected && 'brycks-image-thumbnail--selected',\n disabled && 'brycks-image-thumbnail--disabled',\n className\n )}\n style={containerStyle}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n aria-pressed={isSelected}\n >\n <img src={src} alt={alt} style={imageStyle} />\n\n {onDelete && !disabled && (\n <button\n type=\"button\"\n className=\"brycks-image-thumbnail__delete\"\n style={deleteButtonStyle}\n onClick={handleDelete}\n aria-label=\"Remove image\"\n >\n ×\n </button>\n )}\n\n {badge && (\n <span className=\"brycks-image-thumbnail__badge\" style={badgeStyle}>\n {badge}\n </span>\n )}\n </button>\n )\n }\n)\n\nImageThumbnail.displayName = 'ImageThumbnail'\n"],"names":["sizeMap","ImageThumbnail","forwardRef","src","alt","isSelected","badge","onClick","onDelete","size","aspectRatio","disabled","className","testId","ref","sizeValue","containerStyle","imageStyle","deleteButtonStyle","badgeStyle","handleDelete","e","jsxs","cx","jsx"],"mappings":"+KAwCMA,EAAiE,CACrE,GAAI,CAAE,MAAO,GAAI,WAAY,EAAA,EAC7B,GAAI,CAAE,MAAO,GAAI,WAAY,EAAA,EAC7B,GAAI,CAAE,MAAO,IAAK,WAAY,EAAA,CAChC,EAEaC,EAAiBC,EAAAA,WAC5B,SACE,CACE,IAAAC,EACA,IAAAC,EACA,WAAAC,EAAa,GACb,MAAAC,EACA,QAAAC,EACA,SAAAC,EACA,KAAAC,EAAO,KACP,YAAAC,EAAc,IACd,SAAAC,EAAW,GACX,UAAAC,EACA,OAAAC,CAAA,EAEFC,EACA,CACA,MAAMC,EAAYf,EAAQS,CAAI,EAExBO,EAAgC,CACpC,SAAU,WACV,MAAOD,EAAU,MACjB,YAAAL,EACA,QAAS,EACT,OAAQL,EACJ,0CACA,wBACJ,aAAc,0BACd,SAAU,SACV,OAAQM,EAAW,cAAgB,UACnC,WAAY,iCACZ,QAASA,EAAW,GAAM,EAC1B,WAAY,iEAAA,EAGRM,EAA4B,CAChC,MAAO,OACP,OAAQ,OACR,UAAW,QACX,QAAS,OAAA,EAGLC,EAAmC,CACvC,SAAU,WACV,IAAK,EACL,MAAO,EACP,MAAOH,EAAU,WACjB,OAAQA,EAAU,WAClB,aAAc,MACd,WAAY,qBACZ,MAAO,QACP,OAAQ,OACR,OAAQ,UACR,QAAS,OACT,WAAY,SACZ,eAAgB,SAChB,SAAUA,EAAU,WAAa,GACjC,WAAY,IACZ,WAAY,EACZ,QAAS,EACT,WAAY,+DAAA,EAGRI,EAA4B,CAChC,SAAU,WACV,OAAQ,EACR,KAAM,EACN,WAAY,gCACZ,MAAO,QACP,QAAS,UACT,aAAc,0BACd,SAAUV,IAAS,KAAO,EAAIA,IAAS,KAAO,GAAK,GACnD,WAAY,IACZ,WAAY,EACZ,cAAe,WAAA,EAGXW,EAAgBC,GAAqC,CACzDA,EAAE,gBAAA,EACFb,IAAWa,CAAC,CACd,EAEA,OACEC,EAAAA,KAAC,SAAA,CACC,IAAAR,EACA,KAAK,SACL,UAAWS,EAAAA,GACT,yBACAlB,GAAc,mCACdM,GAAY,mCACZC,CAAA,EAEF,MAAOI,EACP,QAAAT,EACA,SAAAI,EACA,cAAaE,EACb,eAAcR,EAEd,SAAA,CAAAmB,EAAAA,IAAC,MAAA,CAAI,IAAArB,EAAU,IAAAC,EAAU,MAAOa,EAAY,EAE3CT,GAAY,CAACG,GACZa,EAAAA,IAAC,SAAA,CACC,KAAK,SACL,UAAU,iCACV,MAAON,EACP,QAASE,EACT,aAAW,eACZ,SAAA,GAAA,CAAA,EAKFd,GACCkB,EAAAA,IAAC,OAAA,CAAK,UAAU,gCAAgC,MAAOL,EACpD,SAAAb,CAAA,CACH,CAAA,CAAA,CAAA,CAIR,CACF,EAEAL,EAAe,YAAc"}
@@ -18,8 +18,8 @@ const S = {
18
18
  disabled: e = !1,
19
19
  className: b,
20
20
  testId: u
21
- }, g) {
22
- const t = S[a], p = {
21
+ }, p) {
22
+ const t = S[a], g = {
23
23
  position: "relative",
24
24
  width: t.width,
25
25
  aspectRatio: m,
@@ -30,7 +30,7 @@ const S = {
30
30
  cursor: e ? "not-allowed" : "pointer",
31
31
  background: "var(--brycks-background-muted)",
32
32
  opacity: e ? 0.5 : 1,
33
- transition: "border-color var(--brycks-duration-fast) var(--brycks-easing-out)"
33
+ transition: "border-color var(--brycks-duration-fast) var(--brycks-ease-out)"
34
34
  }, h = {
35
35
  width: "100%",
36
36
  height: "100%",
@@ -54,7 +54,7 @@ const S = {
54
54
  fontWeight: 600,
55
55
  lineHeight: 1,
56
56
  padding: 0,
57
- transition: "background var(--brycks-duration-fast) var(--brycks-easing-out)"
57
+ transition: "background var(--brycks-duration-fast) var(--brycks-ease-out)"
58
58
  }, f = {
59
59
  position: "absolute",
60
60
  bottom: 4,
@@ -73,7 +73,7 @@ const S = {
73
73
  return /* @__PURE__ */ v(
74
74
  "button",
75
75
  {
76
- ref: g,
76
+ ref: p,
77
77
  type: "button",
78
78
  className: x(
79
79
  "brycks-image-thumbnail",
@@ -81,7 +81,7 @@ const S = {
81
81
  e && "brycks-image-thumbnail--disabled",
82
82
  b
83
83
  ),
84
- style: p,
84
+ style: g,
85
85
  onClick: c,
86
86
  disabled: e,
87
87
  "data-testid": u,
@@ -1 +1 @@
1
- {"version":3,"file":"ImageThumbnail.js","sources":["../../../../src/components/media/ImageThumbnail/ImageThumbnail.tsx"],"sourcesContent":["/**\n * ImageThumbnail Component\n *\n * Thumbnail image with selection state, optional badge, and delete action.\n * Designed for image galleries and media selection interfaces.\n */\n\nimport {\n forwardRef,\n type CSSProperties,\n type ReactNode,\n type MouseEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport interface ImageThumbnailProps {\n /** Image source URL */\n src: string\n /** Alternative text for accessibility */\n alt: string\n /** Whether this thumbnail is selected */\n isSelected?: boolean\n /** Badge content (e.g., \"COVER\", \"PRIMARY\") */\n badge?: ReactNode\n /** Callback when thumbnail is clicked */\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Callback when delete button is clicked */\n onDelete?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Size of the thumbnail */\n size?: 'sm' | 'md' | 'lg'\n /** Aspect ratio of the thumbnail */\n aspectRatio?: '1' | '4/3' | '16/9'\n /** Whether the thumbnail is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeMap: Record<string, { width: number; deleteSize: number }> = {\n sm: { width: 60, deleteSize: 18 },\n md: { width: 80, deleteSize: 20 },\n lg: { width: 100, deleteSize: 24 },\n}\n\nexport const ImageThumbnail = forwardRef<HTMLButtonElement, ImageThumbnailProps>(\n function ImageThumbnail(\n {\n src,\n alt,\n isSelected = false,\n badge,\n onClick,\n onDelete,\n size = 'md',\n aspectRatio = '1',\n disabled = false,\n className,\n testId,\n },\n ref\n ) {\n const sizeValue = sizeMap[size]\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n width: sizeValue.width,\n aspectRatio,\n padding: 0,\n border: isSelected\n ? '2px solid var(--brycks-primary-default)'\n : '2px solid transparent',\n borderRadius: 'var(--brycks-radius-md)',\n overflow: 'hidden',\n cursor: disabled ? 'not-allowed' : 'pointer',\n background: 'var(--brycks-background-muted)',\n opacity: disabled ? 0.5 : 1,\n transition: 'border-color var(--brycks-duration-fast) var(--brycks-easing-out)',\n }\n\n const imageStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n display: 'block',\n }\n\n const deleteButtonStyle: CSSProperties = {\n position: 'absolute',\n top: 4,\n right: 4,\n width: sizeValue.deleteSize,\n height: sizeValue.deleteSize,\n borderRadius: '50%',\n background: 'rgba(0, 0, 0, 0.7)',\n color: 'white',\n border: 'none',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: sizeValue.deleteSize * 0.6,\n fontWeight: 600,\n lineHeight: 1,\n padding: 0,\n transition: 'background var(--brycks-duration-fast) var(--brycks-easing-out)',\n }\n\n const badgeStyle: CSSProperties = {\n position: 'absolute',\n bottom: 4,\n left: 4,\n background: 'var(--brycks-primary-default)',\n color: 'white',\n padding: '2px 6px',\n borderRadius: 'var(--brycks-radius-sm)',\n fontSize: size === 'sm' ? 8 : size === 'md' ? 10 : 11,\n fontWeight: 600,\n lineHeight: 1,\n textTransform: 'uppercase',\n }\n\n const handleDelete = (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onDelete?.(e)\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cx(\n 'brycks-image-thumbnail',\n isSelected && 'brycks-image-thumbnail--selected',\n disabled && 'brycks-image-thumbnail--disabled',\n className\n )}\n style={containerStyle}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n aria-pressed={isSelected}\n >\n <img src={src} alt={alt} style={imageStyle} />\n\n {onDelete && !disabled && (\n <button\n type=\"button\"\n className=\"brycks-image-thumbnail__delete\"\n style={deleteButtonStyle}\n onClick={handleDelete}\n aria-label=\"Remove image\"\n >\n ×\n </button>\n )}\n\n {badge && (\n <span className=\"brycks-image-thumbnail__badge\" style={badgeStyle}>\n {badge}\n </span>\n )}\n </button>\n )\n }\n)\n\nImageThumbnail.displayName = 'ImageThumbnail'\n"],"names":["sizeMap","ImageThumbnail","forwardRef","src","alt","isSelected","badge","onClick","onDelete","size","aspectRatio","disabled","className","testId","ref","sizeValue","containerStyle","imageStyle","deleteButtonStyle","badgeStyle","handleDelete","e","jsxs","cx","jsx"],"mappings":";;;AAwCA,MAAMA,IAAiE;AAAA,EACrE,IAAI,EAAE,OAAO,IAAI,YAAY,GAAA;AAAA,EAC7B,IAAI,EAAE,OAAO,IAAI,YAAY,GAAA;AAAA,EAC7B,IAAI,EAAE,OAAO,KAAK,YAAY,GAAA;AAChC,GAEaC,IAAiBC;AAAA,EAC5B,SACE;AAAA,IACE,KAAAC;AAAA,IACA,KAAAC;AAAA,IACA,YAAAC,IAAa;AAAA,IACb,OAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,aAAAC,IAAc;AAAA,IACd,UAAAC,IAAW;AAAA,IACX,WAAAC;AAAA,IACA,QAAAC;AAAA,EAAA,GAEFC,GACA;AACA,UAAMC,IAAYf,EAAQS,CAAI,GAExBO,IAAgC;AAAA,MACpC,UAAU;AAAA,MACV,OAAOD,EAAU;AAAA,MACjB,aAAAL;AAAA,MACA,SAAS;AAAA,MACT,QAAQL,IACJ,4CACA;AAAA,MACJ,cAAc;AAAA,MACd,UAAU;AAAA,MACV,QAAQM,IAAW,gBAAgB;AAAA,MACnC,YAAY;AAAA,MACZ,SAASA,IAAW,MAAM;AAAA,MAC1B,YAAY;AAAA,IAAA,GAGRM,IAA4B;AAAA,MAChC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS;AAAA,IAAA,GAGLC,IAAmC;AAAA,MACvC,UAAU;AAAA,MACV,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAOH,EAAU;AAAA,MACjB,QAAQA,EAAU;AAAA,MAClB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAUA,EAAU,aAAa;AAAA,MACjC,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,IAAA,GAGRI,IAA4B;AAAA,MAChC,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAUV,MAAS,OAAO,IAAIA,MAAS,OAAO,KAAK;AAAA,MACnD,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA,GAGXW,IAAe,CAACC,MAAqC;AACzD,MAAAA,EAAE,gBAAA,GACFb,IAAWa,CAAC;AAAA,IACd;AAEA,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAR;AAAA,QACA,MAAK;AAAA,QACL,WAAWS;AAAA,UACT;AAAA,UACAlB,KAAc;AAAA,UACdM,KAAY;AAAA,UACZC;AAAA,QAAA;AAAA,QAEF,OAAOI;AAAA,QACP,SAAAT;AAAA,QACA,UAAAI;AAAA,QACA,eAAaE;AAAA,QACb,gBAAcR;AAAA,QAEd,UAAA;AAAA,UAAA,gBAAAmB,EAAC,OAAA,EAAI,KAAArB,GAAU,KAAAC,GAAU,OAAOa,GAAY;AAAA,UAE3CT,KAAY,CAACG,KACZ,gBAAAa;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,OAAON;AAAA,cACP,SAASE;AAAA,cACT,cAAW;AAAA,cACZ,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAKFd,KACC,gBAAAkB,EAAC,QAAA,EAAK,WAAU,iCAAgC,OAAOL,GACpD,UAAAb,EAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEAL,EAAe,cAAc;"}
1
+ {"version":3,"file":"ImageThumbnail.js","sources":["../../../../src/components/media/ImageThumbnail/ImageThumbnail.tsx"],"sourcesContent":["/**\n * ImageThumbnail Component\n *\n * Thumbnail image with selection state, optional badge, and delete action.\n * Designed for image galleries and media selection interfaces.\n */\n\nimport {\n forwardRef,\n type CSSProperties,\n type ReactNode,\n type MouseEvent,\n} from 'react'\nimport { cx } from '../../../utils/styles'\n\nexport interface ImageThumbnailProps {\n /** Image source URL */\n src: string\n /** Alternative text for accessibility */\n alt: string\n /** Whether this thumbnail is selected */\n isSelected?: boolean\n /** Badge content (e.g., \"COVER\", \"PRIMARY\") */\n badge?: ReactNode\n /** Callback when thumbnail is clicked */\n onClick?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Callback when delete button is clicked */\n onDelete?: (event: MouseEvent<HTMLButtonElement>) => void\n /** Size of the thumbnail */\n size?: 'sm' | 'md' | 'lg'\n /** Aspect ratio of the thumbnail */\n aspectRatio?: '1' | '4/3' | '16/9'\n /** Whether the thumbnail is disabled */\n disabled?: boolean\n /** Custom class name */\n className?: string\n /** Test ID */\n testId?: string\n}\n\nconst sizeMap: Record<string, { width: number; deleteSize: number }> = {\n sm: { width: 60, deleteSize: 18 },\n md: { width: 80, deleteSize: 20 },\n lg: { width: 100, deleteSize: 24 },\n}\n\nexport const ImageThumbnail = forwardRef<HTMLButtonElement, ImageThumbnailProps>(\n function ImageThumbnail(\n {\n src,\n alt,\n isSelected = false,\n badge,\n onClick,\n onDelete,\n size = 'md',\n aspectRatio = '1',\n disabled = false,\n className,\n testId,\n },\n ref\n ) {\n const sizeValue = sizeMap[size]\n\n const containerStyle: CSSProperties = {\n position: 'relative',\n width: sizeValue.width,\n aspectRatio,\n padding: 0,\n border: isSelected\n ? '2px solid var(--brycks-primary-default)'\n : '2px solid transparent',\n borderRadius: 'var(--brycks-radius-md)',\n overflow: 'hidden',\n cursor: disabled ? 'not-allowed' : 'pointer',\n background: 'var(--brycks-background-muted)',\n opacity: disabled ? 0.5 : 1,\n transition: 'border-color var(--brycks-duration-fast) var(--brycks-ease-out)',\n }\n\n const imageStyle: CSSProperties = {\n width: '100%',\n height: '100%',\n objectFit: 'cover',\n display: 'block',\n }\n\n const deleteButtonStyle: CSSProperties = {\n position: 'absolute',\n top: 4,\n right: 4,\n width: sizeValue.deleteSize,\n height: sizeValue.deleteSize,\n borderRadius: '50%',\n background: 'rgba(0, 0, 0, 0.7)',\n color: 'white',\n border: 'none',\n cursor: 'pointer',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n fontSize: sizeValue.deleteSize * 0.6,\n fontWeight: 600,\n lineHeight: 1,\n padding: 0,\n transition: 'background var(--brycks-duration-fast) var(--brycks-ease-out)',\n }\n\n const badgeStyle: CSSProperties = {\n position: 'absolute',\n bottom: 4,\n left: 4,\n background: 'var(--brycks-primary-default)',\n color: 'white',\n padding: '2px 6px',\n borderRadius: 'var(--brycks-radius-sm)',\n fontSize: size === 'sm' ? 8 : size === 'md' ? 10 : 11,\n fontWeight: 600,\n lineHeight: 1,\n textTransform: 'uppercase',\n }\n\n const handleDelete = (e: MouseEvent<HTMLButtonElement>) => {\n e.stopPropagation()\n onDelete?.(e)\n }\n\n return (\n <button\n ref={ref}\n type=\"button\"\n className={cx(\n 'brycks-image-thumbnail',\n isSelected && 'brycks-image-thumbnail--selected',\n disabled && 'brycks-image-thumbnail--disabled',\n className\n )}\n style={containerStyle}\n onClick={onClick}\n disabled={disabled}\n data-testid={testId}\n aria-pressed={isSelected}\n >\n <img src={src} alt={alt} style={imageStyle} />\n\n {onDelete && !disabled && (\n <button\n type=\"button\"\n className=\"brycks-image-thumbnail__delete\"\n style={deleteButtonStyle}\n onClick={handleDelete}\n aria-label=\"Remove image\"\n >\n ×\n </button>\n )}\n\n {badge && (\n <span className=\"brycks-image-thumbnail__badge\" style={badgeStyle}>\n {badge}\n </span>\n )}\n </button>\n )\n }\n)\n\nImageThumbnail.displayName = 'ImageThumbnail'\n"],"names":["sizeMap","ImageThumbnail","forwardRef","src","alt","isSelected","badge","onClick","onDelete","size","aspectRatio","disabled","className","testId","ref","sizeValue","containerStyle","imageStyle","deleteButtonStyle","badgeStyle","handleDelete","e","jsxs","cx","jsx"],"mappings":";;;AAwCA,MAAMA,IAAiE;AAAA,EACrE,IAAI,EAAE,OAAO,IAAI,YAAY,GAAA;AAAA,EAC7B,IAAI,EAAE,OAAO,IAAI,YAAY,GAAA;AAAA,EAC7B,IAAI,EAAE,OAAO,KAAK,YAAY,GAAA;AAChC,GAEaC,IAAiBC;AAAA,EAC5B,SACE;AAAA,IACE,KAAAC;AAAA,IACA,KAAAC;AAAA,IACA,YAAAC,IAAa;AAAA,IACb,OAAAC;AAAA,IACA,SAAAC;AAAA,IACA,UAAAC;AAAA,IACA,MAAAC,IAAO;AAAA,IACP,aAAAC,IAAc;AAAA,IACd,UAAAC,IAAW;AAAA,IACX,WAAAC;AAAA,IACA,QAAAC;AAAA,EAAA,GAEFC,GACA;AACA,UAAMC,IAAYf,EAAQS,CAAI,GAExBO,IAAgC;AAAA,MACpC,UAAU;AAAA,MACV,OAAOD,EAAU;AAAA,MACjB,aAAAL;AAAA,MACA,SAAS;AAAA,MACT,QAAQL,IACJ,4CACA;AAAA,MACJ,cAAc;AAAA,MACd,UAAU;AAAA,MACV,QAAQM,IAAW,gBAAgB;AAAA,MACnC,YAAY;AAAA,MACZ,SAASA,IAAW,MAAM;AAAA,MAC1B,YAAY;AAAA,IAAA,GAGRM,IAA4B;AAAA,MAChC,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,WAAW;AAAA,MACX,SAAS;AAAA,IAAA,GAGLC,IAAmC;AAAA,MACvC,UAAU;AAAA,MACV,KAAK;AAAA,MACL,OAAO;AAAA,MACP,OAAOH,EAAU;AAAA,MACjB,QAAQA,EAAU;AAAA,MAClB,cAAc;AAAA,MACd,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,QAAQ;AAAA,MACR,QAAQ;AAAA,MACR,SAAS;AAAA,MACT,YAAY;AAAA,MACZ,gBAAgB;AAAA,MAChB,UAAUA,EAAU,aAAa;AAAA,MACjC,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,SAAS;AAAA,MACT,YAAY;AAAA,IAAA,GAGRI,IAA4B;AAAA,MAChC,UAAU;AAAA,MACV,QAAQ;AAAA,MACR,MAAM;AAAA,MACN,YAAY;AAAA,MACZ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,cAAc;AAAA,MACd,UAAUV,MAAS,OAAO,IAAIA,MAAS,OAAO,KAAK;AAAA,MACnD,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,eAAe;AAAA,IAAA,GAGXW,IAAe,CAACC,MAAqC;AACzD,MAAAA,EAAE,gBAAA,GACFb,IAAWa,CAAC;AAAA,IACd;AAEA,WACE,gBAAAC;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,KAAAR;AAAA,QACA,MAAK;AAAA,QACL,WAAWS;AAAA,UACT;AAAA,UACAlB,KAAc;AAAA,UACdM,KAAY;AAAA,UACZC;AAAA,QAAA;AAAA,QAEF,OAAOI;AAAA,QACP,SAAAT;AAAA,QACA,UAAAI;AAAA,QACA,eAAaE;AAAA,QACb,gBAAcR;AAAA,QAEd,UAAA;AAAA,UAAA,gBAAAmB,EAAC,OAAA,EAAI,KAAArB,GAAU,KAAAC,GAAU,OAAOa,GAAY;AAAA,UAE3CT,KAAY,CAACG,KACZ,gBAAAa;AAAA,YAAC;AAAA,YAAA;AAAA,cACC,MAAK;AAAA,cACL,WAAU;AAAA,cACV,OAAON;AAAA,cACP,SAASE;AAAA,cACT,cAAW;AAAA,cACZ,UAAA;AAAA,YAAA;AAAA,UAAA;AAAA,UAKFd,KACC,gBAAAkB,EAAC,QAAA,EAAK,WAAU,iCAAgC,OAAOL,GACpD,UAAAb,EAAA,CACH;AAAA,QAAA;AAAA,MAAA;AAAA,IAAA;AAAA,EAIR;AACF;AAEAL,EAAe,cAAc;"}
@@ -1,2 +1,2 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),c=require("react"),p=require("../../../utils/styles.cjs"),v=c.createContext(null);function h(){const o=c.useContext(v);if(!o)throw new Error("AccordionItem must be used within an Accordion");return o}const A=c.forwardRef(function({value:t,defaultValue:l=[],onChange:a,allowMultiple:i=!1,variant:d="default",className:s,style:u,children:f,testId:n,...e},x){const[k,g]=c.useState(l),m=t??k,N=c.useCallback(b=>{const E=m.includes(b);let y;E?y=m.filter(R=>R!==b):i?y=[...m,b]:y=[b],t===void 0&&g(y),a?.(y)},[m,i,t,a]),T={display:"flex",flexDirection:"column",gap:d==="separated"?8:0,...u};return r.jsx(v.Provider,{value:{expandedItems:m,toggleItem:N,allowMultiple:i,variant:d},children:r.jsx("div",{ref:x,className:p.cx("brycks-accordion",`brycks-accordion--${d}`,s),style:T,"data-testid":n,...e,children:f})})});A.displayName="Accordion";const C=c.createContext(null);function w(){const o=c.useContext(C);if(!o)throw new Error("AccordionTrigger/AccordionContent must be used within an AccordionItem");return o}const j=c.forwardRef(function({value:t,disabled:l=!1,className:a,style:i,children:d,...s},u){const{expandedItems:f,variant:n}=h(),e=f.includes(t),x={borderBottom:n==="default"?"1px solid var(--brycks-border-muted)":void 0,border:n==="bordered"||n==="separated"?"1px solid var(--brycks-border-default)":void 0,borderRadius:n==="separated"?"var(--brycks-radius-lg)":void 0,overflow:"hidden",...i};return n==="bordered"&&!e&&(x.borderBottom="1px solid var(--brycks-border-default)"),r.jsx(C.Provider,{value:{value:t,isExpanded:e,disabled:l},children:r.jsx("div",{ref:u,className:p.cx("brycks-accordion-item",e&&"brycks-accordion-item--expanded",a),style:x,...s,children:d})})});j.displayName="AccordionItem";function L({isExpanded:o}){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",style:{transform:o?"rotate(180deg)":"rotate(0deg)",transition:"transform 200ms ease-out"},children:r.jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const I=c.forwardRef(function({icon:t,className:l,style:a,children:i,...d},s){const{toggleItem:u}=h(),{value:f,isExpanded:n,disabled:e}=w(),x=()=>{e||u(f)},k={display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"16px",fontSize:15,fontWeight:500,color:e?"var(--brycks-foreground-muted)":"var(--brycks-foreground-default)",backgroundColor:"transparent",border:"none",cursor:e?"not-allowed":"pointer",textAlign:"left",transition:"background-color 150ms ease-out",outline:"none",...a};return r.jsxs("button",{ref:s,type:"button","aria-expanded":n,"aria-disabled":e,disabled:e,className:p.cx("brycks-accordion-trigger",l),style:k,onClick:x,onMouseEnter:g=>{e||(g.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:g=>{g.currentTarget.style.backgroundColor="transparent"},...d,children:[i,r.jsx("span",{style:{color:"var(--brycks-foreground-muted)",flexShrink:0,marginLeft:12},children:t??r.jsx(L,{isExpanded:n})})]})});I.displayName="AccordionTrigger";const S=c.forwardRef(function({className:t,style:l,children:a,...i},d){const{isExpanded:s}=w(),u={overflow:"hidden",transition:"max-height 200ms ease-out, opacity 200ms ease-out",maxHeight:s?"1000px":"0",opacity:s?1:0},f={padding:"0 16px 16px 16px",color:"var(--brycks-foreground-muted)",fontSize:14,lineHeight:1.6,...l};return r.jsx("div",{ref:d,role:"region","aria-hidden":!s,className:p.cx("brycks-accordion-content",t),style:u,...i,children:r.jsx("div",{style:f,children:a})})});S.displayName="AccordionContent";exports.Accordion=A;exports.AccordionContent=S;exports.AccordionItem=j;exports.AccordionTrigger=I;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const r=require("react/jsx-runtime"),c=require("react"),p=require("../../../utils/styles.cjs"),v=c.createContext(null);function h(){const o=c.useContext(v);if(!o)throw new Error("AccordionItem must be used within an Accordion");return o}const A=c.forwardRef(function({value:t,defaultValue:l=[],onChange:a,allowMultiple:i=!1,variant:d="default",className:s,style:u,children:f,testId:n,...e},x){const[k,g]=c.useState(l),m=t??k,N=c.useCallback(b=>{const E=m.includes(b);let y;E?y=m.filter(R=>R!==b):i?y=[...m,b]:y=[b],t===void 0&&g(y),a?.(y)},[m,i,t,a]),T={display:"flex",flexDirection:"column",gap:d==="separated"?8:0,...u};return r.jsx(v.Provider,{value:{expandedItems:m,toggleItem:N,allowMultiple:i,variant:d},children:r.jsx("div",{ref:x,className:p.cx("brycks-accordion",`brycks-accordion--${d}`,s),style:T,"data-testid":n,...e,children:f})})});A.displayName="Accordion";const C=c.createContext(null);function w(){const o=c.useContext(C);if(!o)throw new Error("AccordionTrigger/AccordionContent must be used within an AccordionItem");return o}const j=c.forwardRef(function({value:t,disabled:l=!1,className:a,style:i,children:d,...s},u){const{expandedItems:f,variant:n}=h(),e=f.includes(t),x={borderBottom:n==="default"?"1px solid var(--brycks-border-muted)":void 0,border:n==="bordered"||n==="separated"?"1px solid var(--brycks-border-default)":void 0,borderRadius:n==="separated"?"var(--brycks-radius-lg)":void 0,overflow:"hidden",...i};return n==="bordered"&&!e&&(x.borderBottom="1px solid var(--brycks-border-default)"),r.jsx(C.Provider,{value:{value:t,isExpanded:e,disabled:l},children:r.jsx("div",{ref:u,className:p.cx("brycks-accordion-item",e&&"brycks-accordion-item--expanded",a),style:x,...s,children:d})})});j.displayName="AccordionItem";function L({isExpanded:o}){return r.jsx("svg",{width:"16",height:"16",viewBox:"0 0 16 16",fill:"none",style:{transform:o?"rotate(180deg)":"rotate(0deg)",transition:"transform 200ms ease-out"},children:r.jsx("path",{d:"M4 6l4 4 4-4",stroke:"currentColor",strokeWidth:"1.5",strokeLinecap:"round",strokeLinejoin:"round"})})}const I=c.forwardRef(function({icon:t,className:l,style:a,children:i,...d},s){const{toggleItem:u}=h(),{value:f,isExpanded:n,disabled:e}=w(),x=()=>{e||u(f)},k={display:"flex",alignItems:"center",justifyContent:"space-between",width:"100%",padding:"16px",fontSize:15,fontWeight:500,color:e?"var(--brycks-foreground-muted)":"var(--brycks-foreground-default)",backgroundColor:"transparent",border:"none",cursor:e?"not-allowed":"pointer",textAlign:"left",transition:"background-color 150ms ease-out",...a};return r.jsxs("button",{ref:s,type:"button","aria-expanded":n,"aria-disabled":e,disabled:e,className:p.cx("brycks-accordion-trigger",l),style:k,onClick:x,onMouseEnter:g=>{e||(g.currentTarget.style.backgroundColor="var(--brycks-background-muted)")},onMouseLeave:g=>{g.currentTarget.style.backgroundColor="transparent"},...d,children:[i,r.jsx("span",{style:{color:"var(--brycks-foreground-muted)",flexShrink:0,marginLeft:12},children:t??r.jsx(L,{isExpanded:n})})]})});I.displayName="AccordionTrigger";const S=c.forwardRef(function({className:t,style:l,children:a,...i},d){const{isExpanded:s}=w(),u={overflow:"hidden",transition:"max-height 200ms ease-out, opacity 200ms ease-out",maxHeight:s?"1000px":"0",opacity:s?1:0},f={padding:"0 16px 16px 16px",color:"var(--brycks-foreground-muted)",fontSize:14,lineHeight:1.6,...l};return r.jsx("div",{ref:d,role:"region","aria-hidden":!s,className:p.cx("brycks-accordion-content",t),style:u,...i,children:r.jsx("div",{style:f,children:a})})});S.displayName="AccordionContent";exports.Accordion=A;exports.AccordionContent=S;exports.AccordionItem=j;exports.AccordionTrigger=I;
2
2
  //# sourceMappingURL=Accordion.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Accordion.cjs","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.cjs","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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"}
@@ -115,7 +115,6 @@ const R = b(function({ icon: r, className: a, style: s, children: c, ...i }, d)
115
115
  cursor: e ? "not-allowed" : "pointer",
116
116
  textAlign: "left",
117
117
  transition: "background-color 150ms ease-out",
118
- outline: "none",
119
118
  ...s
120
119
  };
121
120
  return /* @__PURE__ */ j(