@chayns-ui/core 0.9.4 → 0.10.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 (210) hide show
  1. package/dist/accordion.css +3 -1
  2. package/dist/badge.css +28 -3
  3. package/dist/banner.css +2 -0
  4. package/dist/breadcrumb.css +63 -0
  5. package/dist/button.css +103 -35
  6. package/dist/card.css +39 -0
  7. package/dist/checkbox.css +3 -3
  8. package/dist/combo-box.css +2 -0
  9. package/dist/components/accordion/Accordion.d.ts +3 -4
  10. package/dist/components/accordion/Accordion.d.ts.map +1 -1
  11. package/dist/components/accordion/Accordion.js +37 -23
  12. package/dist/components/accordion/Accordion.js.map +1 -1
  13. package/dist/components/accordion/Accordion.types.d.ts +7 -2
  14. package/dist/components/accordion/Accordion.types.d.ts.map +1 -1
  15. package/dist/components/accordion/Accordion.types.js +7 -1
  16. package/dist/components/accordion/Accordion.types.js.map +1 -1
  17. package/dist/components/accordion-group/AccordionGroup.d.ts.map +1 -1
  18. package/dist/components/accordion-group/AccordionGroup.js +1 -0
  19. package/dist/components/accordion-group/AccordionGroup.js.map +1 -1
  20. package/dist/components/avatar/Avatar.d.ts.map +1 -1
  21. package/dist/components/avatar/Avatar.js +1 -0
  22. package/dist/components/avatar/Avatar.js.map +1 -1
  23. package/dist/components/avatar/Avatar.types.d.ts +9 -1
  24. package/dist/components/avatar/Avatar.types.d.ts.map +1 -1
  25. package/dist/components/avatar/Avatar.types.js +17 -0
  26. package/dist/components/avatar/Avatar.types.js.map +1 -0
  27. package/dist/components/avatar-group/AvatarGroup.d.ts.map +1 -1
  28. package/dist/components/avatar-group/AvatarGroup.js +4 -3
  29. package/dist/components/avatar-group/AvatarGroup.js.map +1 -1
  30. package/dist/components/badge/Badge.d.ts.map +1 -1
  31. package/dist/components/badge/Badge.js +1 -0
  32. package/dist/components/badge/Badge.js.map +1 -1
  33. package/dist/components/badge/Badge.types.d.ts +13 -0
  34. package/dist/components/badge/Badge.types.d.ts.map +1 -1
  35. package/dist/components/badge/Badge.types.js +16 -1
  36. package/dist/components/badge/Badge.types.js.map +1 -1
  37. package/dist/components/banner/Banner.d.ts.map +1 -1
  38. package/dist/components/banner/Banner.js +1 -0
  39. package/dist/components/banner/Banner.js.map +1 -1
  40. package/dist/components/banner/Banner.types.d.ts +7 -0
  41. package/dist/components/banner/Banner.types.d.ts.map +1 -1
  42. package/dist/components/banner/Banner.types.js +9 -1
  43. package/dist/components/banner/Banner.types.js.map +1 -1
  44. package/dist/components/breadcrumb/Breadcrumb.d.ts +4 -0
  45. package/dist/components/breadcrumb/Breadcrumb.d.ts.map +1 -0
  46. package/dist/components/breadcrumb/Breadcrumb.js +35 -0
  47. package/dist/components/breadcrumb/Breadcrumb.js.map +1 -0
  48. package/dist/components/breadcrumb/Breadcrumb.types.d.ts +13 -0
  49. package/dist/components/breadcrumb/Breadcrumb.types.d.ts.map +1 -0
  50. package/dist/components/button/Button.d.ts.map +1 -1
  51. package/dist/components/button/Button.js +1 -0
  52. package/dist/components/button/Button.js.map +1 -1
  53. package/dist/components/button/Button.types.d.ts +7 -0
  54. package/dist/components/button/Button.types.d.ts.map +1 -1
  55. package/dist/components/button/Button.types.js +9 -1
  56. package/dist/components/button/Button.types.js.map +1 -1
  57. package/dist/components/button/button-icon/ButtonIcon.d.ts.map +1 -1
  58. package/dist/components/button/button-icon/ButtonIcon.js +7 -3
  59. package/dist/components/button/button-icon/ButtonIcon.js.map +1 -1
  60. package/dist/components/card/Card.d.ts.map +1 -1
  61. package/dist/components/card/Card.js +2 -0
  62. package/dist/components/card/Card.js.map +1 -1
  63. package/dist/components/checkbox/Checkbox.d.ts.map +1 -1
  64. package/dist/components/checkbox/Checkbox.js +1 -0
  65. package/dist/components/checkbox/Checkbox.js.map +1 -1
  66. package/dist/components/combo-box/ComboBox.d.ts.map +1 -1
  67. package/dist/components/combo-box/ComboBox.js +27 -8
  68. package/dist/components/combo-box/ComboBox.js.map +1 -1
  69. package/dist/components/date-time-picker/DateTimePicker.d.ts.map +1 -1
  70. package/dist/components/date-time-picker/DateTimePicker.js +31 -239
  71. package/dist/components/date-time-picker/DateTimePicker.js.map +1 -1
  72. package/dist/components/date-time-picker/DateTimePicker.types.d.ts +12 -0
  73. package/dist/components/date-time-picker/DateTimePicker.types.d.ts.map +1 -1
  74. package/dist/components/date-time-picker/DateTimePicker.types.js +15 -1
  75. package/dist/components/date-time-picker/DateTimePicker.types.js.map +1 -1
  76. package/dist/components/date-time-picker/date-time-picker-utils.d.ts +4 -0
  77. package/dist/components/date-time-picker/date-time-picker-utils.d.ts.map +1 -0
  78. package/dist/components/date-time-picker/date-time-picker-utils.js +19 -0
  79. package/dist/components/date-time-picker/date-time-picker-utils.js.map +1 -0
  80. package/dist/components/date-time-picker/hooks/useDateTimePickerValue.d.ts +37 -0
  81. package/dist/components/date-time-picker/hooks/useDateTimePickerValue.d.ts.map +1 -0
  82. package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js +156 -0
  83. package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js.map +1 -0
  84. package/dist/components/date-time-picker/sizer/PickerSizer.d.ts +7 -0
  85. package/dist/components/date-time-picker/sizer/PickerSizer.d.ts.map +1 -0
  86. package/dist/components/date-time-picker/sizer/PickerSizer.js +15 -0
  87. package/dist/components/date-time-picker/sizer/PickerSizer.js.map +1 -0
  88. package/dist/components/date-time-picker/wheel/Wheel.d.ts +14 -0
  89. package/dist/components/date-time-picker/wheel/Wheel.d.ts.map +1 -0
  90. package/dist/components/date-time-picker/wheel/Wheel.js +136 -0
  91. package/dist/components/date-time-picker/wheel/Wheel.js.map +1 -0
  92. package/dist/components/icon-button/IconButton.d.ts.map +1 -1
  93. package/dist/components/icon-button/IconButton.js +1 -0
  94. package/dist/components/icon-button/IconButton.js.map +1 -1
  95. package/dist/components/list/List.d.ts +15 -10
  96. package/dist/components/list/List.d.ts.map +1 -1
  97. package/dist/components/list/List.js +19 -7
  98. package/dist/components/list/List.js.map +1 -1
  99. package/dist/components/list/List.types.d.ts +2 -2
  100. package/dist/components/list/List.types.d.ts.map +1 -1
  101. package/dist/components/pagination/Pagination.d.ts +4 -0
  102. package/dist/components/pagination/Pagination.d.ts.map +1 -0
  103. package/dist/components/pagination/Pagination.js +57 -0
  104. package/dist/components/pagination/Pagination.js.map +1 -0
  105. package/dist/components/pagination/Pagination.types.d.ts +15 -0
  106. package/dist/components/pagination/Pagination.types.d.ts.map +1 -0
  107. package/dist/components/pagination/pagination-pages.d.ts +2 -0
  108. package/dist/components/pagination/pagination-pages.d.ts.map +1 -0
  109. package/dist/components/pagination/pagination-pages.js +35 -0
  110. package/dist/components/pagination/pagination-pages.js.map +1 -0
  111. package/dist/components/popup/Popup.d.ts +4 -1
  112. package/dist/components/popup/Popup.d.ts.map +1 -1
  113. package/dist/components/popup/Popup.js +25 -18
  114. package/dist/components/popup/Popup.js.map +1 -1
  115. package/dist/components/popup/PopupList.d.ts +4 -1
  116. package/dist/components/popup/PopupList.d.ts.map +1 -1
  117. package/dist/components/popup/PopupList.js +7 -1
  118. package/dist/components/popup/PopupList.js.map +1 -1
  119. package/dist/components/progress/Progress.d.ts.map +1 -1
  120. package/dist/components/progress/Progress.js +1 -0
  121. package/dist/components/progress/Progress.js.map +1 -1
  122. package/dist/components/progress/Progress.types.d.ts +1 -1
  123. package/dist/components/progress/Progress.types.d.ts.map +1 -1
  124. package/dist/components/radio-group/RadioGroup.d.ts.map +1 -1
  125. package/dist/components/radio-group/RadioGroup.js +2 -0
  126. package/dist/components/radio-group/RadioGroup.js.map +1 -1
  127. package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -1
  128. package/dist/components/segmented-control/SegmentedControl.js +78 -25
  129. package/dist/components/segmented-control/SegmentedControl.js.map +1 -1
  130. package/dist/components/segmented-control/SegmentedControl.types.d.ts +1 -1
  131. package/dist/components/segmented-control/SegmentedControl.types.d.ts.map +1 -1
  132. package/dist/components/segmented-control/SegmentedControlContext.d.ts +2 -0
  133. package/dist/components/segmented-control/SegmentedControlContext.d.ts.map +1 -1
  134. package/dist/components/segmented-control/SegmentedControlContext.js.map +1 -1
  135. package/dist/components/skeleton/Skeleton.d.ts.map +1 -1
  136. package/dist/components/skeleton/Skeleton.js +1 -0
  137. package/dist/components/skeleton/Skeleton.js.map +1 -1
  138. package/dist/components/skeleton/Skeleton.types.d.ts +6 -0
  139. package/dist/components/skeleton/Skeleton.types.d.ts.map +1 -1
  140. package/dist/components/skeleton/Skeleton.types.js +8 -1
  141. package/dist/components/skeleton/Skeleton.types.js.map +1 -1
  142. package/dist/components/slider/Slider.d.ts +4 -0
  143. package/dist/components/slider/Slider.d.ts.map +1 -0
  144. package/dist/components/slider/Slider.js +61 -0
  145. package/dist/components/slider/Slider.js.map +1 -0
  146. package/dist/components/slider/Slider.types.d.ts +10 -0
  147. package/dist/components/slider/Slider.types.d.ts.map +1 -0
  148. package/dist/components/spinner/Spinner.d.ts.map +1 -1
  149. package/dist/components/spinner/Spinner.js +1 -0
  150. package/dist/components/spinner/Spinner.js.map +1 -1
  151. package/dist/components/split-button/SplitButton.d.ts.map +1 -1
  152. package/dist/components/split-button/SplitButton.js +2 -1
  153. package/dist/components/split-button/SplitButton.js.map +1 -1
  154. package/dist/components/stepper/Stepper.d.ts +4 -0
  155. package/dist/components/stepper/Stepper.d.ts.map +1 -0
  156. package/dist/components/stepper/Stepper.js +60 -0
  157. package/dist/components/stepper/Stepper.js.map +1 -0
  158. package/dist/components/stepper/Stepper.types.d.ts +27 -0
  159. package/dist/components/stepper/Stepper.types.d.ts.map +1 -0
  160. package/dist/components/stepper/Stepper.types.js +25 -0
  161. package/dist/components/stepper/Stepper.types.js.map +1 -0
  162. package/dist/components/stepper/stepper-values.d.ts +6 -0
  163. package/dist/components/stepper/stepper-values.d.ts.map +1 -0
  164. package/dist/components/stepper/stepper-values.js +26 -0
  165. package/dist/components/stepper/stepper-values.js.map +1 -0
  166. package/dist/components/switch/Switch.d.ts.map +1 -1
  167. package/dist/components/switch/Switch.js +1 -0
  168. package/dist/components/switch/Switch.js.map +1 -1
  169. package/dist/components/text-area/TextArea.d.ts.map +1 -1
  170. package/dist/components/text-area/TextArea.js +1 -0
  171. package/dist/components/text-area/TextArea.js.map +1 -1
  172. package/dist/components/text-field/TextField.d.ts.map +1 -1
  173. package/dist/components/text-field/TextField.js +1 -0
  174. package/dist/components/text-field/TextField.js.map +1 -1
  175. package/dist/components/tooltip/Tooltip.d.ts +4 -0
  176. package/dist/components/tooltip/Tooltip.d.ts.map +1 -0
  177. package/dist/components/tooltip/Tooltip.js +75 -0
  178. package/dist/components/tooltip/Tooltip.js.map +1 -0
  179. package/dist/components/tooltip/Tooltip.types.d.ts +12 -0
  180. package/dist/components/tooltip/Tooltip.types.d.ts.map +1 -0
  181. package/dist/components/tooltip/hooks/useTooltipInteraction.d.ts +11 -0
  182. package/dist/components/tooltip/hooks/useTooltipInteraction.d.ts.map +1 -0
  183. package/dist/components/tooltip/hooks/useTooltipInteraction.js +59 -0
  184. package/dist/components/tooltip/hooks/useTooltipInteraction.js.map +1 -0
  185. package/dist/components/tooltip/tooltip-trigger-props.d.ts +4 -0
  186. package/dist/components/tooltip/tooltip-trigger-props.d.ts.map +1 -0
  187. package/dist/components/tooltip/tooltip-trigger-props.js +25 -0
  188. package/dist/components/tooltip/tooltip-trigger-props.js.map +1 -0
  189. package/dist/date-time-picker.css +33 -2
  190. package/dist/hooks/useOverlayPosition.d.ts +4 -0
  191. package/dist/hooks/useOverlayPosition.d.ts.map +1 -0
  192. package/dist/hooks/useOverlayPosition.js +60 -0
  193. package/dist/hooks/useOverlayPosition.js.map +1 -0
  194. package/dist/index.d.ts +21 -7
  195. package/dist/index.d.ts.map +1 -1
  196. package/dist/index.js +14 -7
  197. package/dist/pagination.css +54 -0
  198. package/dist/popup.css +4 -0
  199. package/dist/progress.css +1 -1
  200. package/dist/segmented-control.css +2 -0
  201. package/dist/slider.css +109 -0
  202. package/dist/split-button.css +2 -79
  203. package/dist/stepper.css +77 -0
  204. package/dist/styles.css +5 -0
  205. package/dist/tooltip.css +68 -0
  206. package/dist/utils/native-ref.d.ts +4 -0
  207. package/dist/utils/native-ref.d.ts.map +1 -0
  208. package/dist/utils/native-ref.js +24 -0
  209. package/dist/utils/native-ref.js.map +1 -0
  210. package/package.json +7 -2
@@ -1 +1 @@
1
- {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAiClE,QAAA,MAAM,IAAI;;CAAkD,CAAC;AAE7D,eAAe,IAAI,CAAC"}
1
+ {"version":3,"file":"Card.d.ts","sourceRoot":"","sources":["../../../src/components/card/Card.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAiClE,QAAA,MAAM,IAAI;;CAAkD,CAAC;AAK7D,eAAe,IAAI,CAAC"}
@@ -28,6 +28,8 @@ var CardRoot = forwardRef(function Card({ children, className, ...cardProps }, r
28
28
  });
29
29
  });
30
30
  var Card = Object.assign(CardRoot, { Header: CardHeader });
31
+ CardHeader.displayName = "Card.Header";
32
+ CardRoot.displayName = "Card";
31
33
  //#endregion
32
34
  export { Card as default };
33
35
 
@@ -1 +1 @@
1
- {"version":3,"file":"Card.js","names":[],"sources":["../../../src/components/card/Card.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport type { CardHeaderProps, CardProps } from './Card.types.js';\n\nconst CardHeader = forwardRef<HTMLElement, CardHeaderProps>(function CardHeader(\n { children, className, icon, ...headerProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card__header', className].filter(Boolean).join(' ');\n\n return (\n <header {...headerProps} className={resolvedClassName} ref={ref}>\n {icon ? (\n <span aria-hidden=\"true\" className=\"chayns-card__header-icon\">\n <ButtonIcon icon={icon} />\n </span>\n ) : null}\n <span className=\"chayns-card__header-content\">{children}</span>\n </header>\n );\n});\n\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n { children, className, ...cardProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card', className].filter(Boolean).join(' ');\n\n return (\n <div {...cardProps} className={resolvedClassName} ref={ref}>\n {children}\n </div>\n );\n});\n\nconst Card = Object.assign(CardRoot, { Header: CardHeader });\n\nexport default Card;\n"],"mappings":";;;;AAKA,IAAM,aAAa,WAAyC,SAAS,WACnE,EAAE,UAAU,WAAW,MAAM,GAAG,eAChC,KACA;CACA,MAAM,oBAAoB,CAAC,uBAAuB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAErF,OACE,qBAAC,UAAD;EAAQ,GAAI;EAAa,WAAW;EAAwB;EAA5D,UAAA,CACG,OACC,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GACjC,UAAA,oBAAC,YAAD,EAAkB,KAAO,CAAA;EACrB,CAAA,IACJ,MACJ,oBAAC,QAAD;GAAM,WAAU;GAA+B;EAAe,CAAA,CACxD;;AAEZ,CAAC;AAED,IAAM,WAAW,WAAsC,SAAS,KAC9D,EAAE,UAAU,WAAW,GAAG,aAC1B,KACA;CACA,MAAM,oBAAoB,CAAC,eAAe,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAE7E,OACE,oBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAwB;EACpD;CACE,CAAA;AAET,CAAC;AAED,IAAM,OAAO,OAAO,OAAO,UAAU,EAAE,QAAQ,WAAW,CAAC"}
1
+ {"version":3,"file":"Card.js","names":[],"sources":["../../../src/components/card/Card.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport type { CardHeaderProps, CardProps } from './Card.types.js';\n\nconst CardHeader = forwardRef<HTMLElement, CardHeaderProps>(function CardHeader(\n { children, className, icon, ...headerProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card__header', className].filter(Boolean).join(' ');\n\n return (\n <header {...headerProps} className={resolvedClassName} ref={ref}>\n {icon ? (\n <span aria-hidden=\"true\" className=\"chayns-card__header-icon\">\n <ButtonIcon icon={icon} />\n </span>\n ) : null}\n <span className=\"chayns-card__header-content\">{children}</span>\n </header>\n );\n});\n\nconst CardRoot = forwardRef<HTMLDivElement, CardProps>(function Card(\n { children, className, ...cardProps },\n ref,\n) {\n const resolvedClassName = ['chayns-card', className].filter(Boolean).join(' ');\n\n return (\n <div {...cardProps} className={resolvedClassName} ref={ref}>\n {children}\n </div>\n );\n});\n\nconst Card = Object.assign(CardRoot, { Header: CardHeader });\n\nCardHeader.displayName = 'Card.Header';\nCardRoot.displayName = 'Card';\n\nexport default Card;\n"],"mappings":";;;;AAKA,IAAM,aAAa,WAAyC,SAAS,WACnE,EAAE,UAAU,WAAW,MAAM,GAAG,eAChC,KACA;CACA,MAAM,oBAAoB,CAAC,uBAAuB,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAErF,OACE,qBAAC,UAAD;EAAQ,GAAI;EAAa,WAAW;EAAwB;EAA5D,UAAA,CACG,OACC,oBAAC,QAAD;GAAM,eAAY;GAAO,WAAU;GACjC,UAAA,oBAAC,YAAD,EAAkB,KAAO,CAAA;EACrB,CAAA,IACJ,MACJ,oBAAC,QAAD;GAAM,WAAU;GAA+B;EAAe,CAAA,CACxD;;AAEZ,CAAC;AAED,IAAM,WAAW,WAAsC,SAAS,KAC9D,EAAE,UAAU,WAAW,GAAG,aAC1B,KACA;CACA,MAAM,oBAAoB,CAAC,eAAe,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAE7E,OACE,oBAAC,OAAD;EAAK,GAAI;EAAW,WAAW;EAAwB;EACpD;CACE,CAAA;AAET,CAAC;AAED,IAAM,OAAO,OAAO,OAAO,UAAU,EAAE,QAAQ,WAAW,CAAC;AAE3D,WAAW,cAAc;AACzB,SAAS,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/checkbox/Checkbox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,QAAA,MAAM,QAAQ,yHAoBZ,CAAC;AAEH,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"Checkbox.d.ts","sourceRoot":"","sources":["../../../src/components/checkbox/Checkbox.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,QAAA,MAAM,QAAQ,yHAoBZ,CAAC;AAIH,eAAe,QAAQ,CAAC"}
@@ -30,6 +30,7 @@ var Checkbox = forwardRef(function Checkbox({ children, className, description,
30
30
  ]
31
31
  });
32
32
  });
33
+ Checkbox.displayName = "Checkbox";
33
34
  //#endregion
34
35
  export { Checkbox as default };
35
36
 
@@ -1 +1 @@
1
- {"version":3,"file":"Checkbox.js","names":[],"sources":["../../../src/components/checkbox/Checkbox.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport type { CheckboxProps } from './Checkbox.types.js';\n\nconst Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { children, className, description, ...inputProps },\n ref,\n) {\n const inputClassName = ['chayns-checkbox__input', className].filter(Boolean).join(' ');\n\n return (\n <label className=\"chayns-checkbox\">\n <input {...inputProps} className={inputClassName} ref={ref} type=\"checkbox\" />\n <span aria-hidden=\"true\" className=\"chayns-checkbox__control\">\n <i className=\"far fa-check\" />\n </span>\n <span className=\"chayns-checkbox__content\">\n <span className=\"chayns-checkbox__label\">{children}</span>\n {description !== undefined ? (\n <span className=\"chayns-checkbox__description\">{description}</span>\n ) : null}\n </span>\n </label>\n );\n});\n\nexport default Checkbox;\n"],"mappings":";;;AAIA,IAAM,WAAW,WAA4C,SAAS,SACpE,EAAE,UAAU,WAAW,aAAa,GAAG,cACvC,KACA;CACA,MAAM,iBAAiB,CAAC,0BAA0B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAErF,OACE,qBAAC,SAAD;EAAO,WAAU;EAAjB,UAAA;GACE,oBAAC,SAAD;IAAO,GAAI;IAAY,WAAW;IAAqB;IAAK,MAAK;GAAY,CAAA;GAC7E,oBAAC,QAAD;IAAM,eAAY;IAAO,WAAU;IACjC,UAAA,oBAAC,KAAD,EAAG,WAAU,eAAgB,CAAA;GACzB,CAAA;GACN,qBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA0B;IAAe,CAAA,GACxD,gBAAgB,KAAA,IACf,oBAAC,QAAD;KAAM,WAAU;KAAgC,UAAA;IAAkB,CAAA,IAChE,IACA;;EACD;;AAEX,CAAC"}
1
+ {"version":3,"file":"Checkbox.js","names":[],"sources":["../../../src/components/checkbox/Checkbox.tsx"],"sourcesContent":["import { forwardRef } from 'react';\n\nimport type { CheckboxProps } from './Checkbox.types.js';\n\nconst Checkbox = forwardRef<HTMLInputElement, CheckboxProps>(function Checkbox(\n { children, className, description, ...inputProps },\n ref,\n) {\n const inputClassName = ['chayns-checkbox__input', className].filter(Boolean).join(' ');\n\n return (\n <label className=\"chayns-checkbox\">\n <input {...inputProps} className={inputClassName} ref={ref} type=\"checkbox\" />\n <span aria-hidden=\"true\" className=\"chayns-checkbox__control\">\n <i className=\"far fa-check\" />\n </span>\n <span className=\"chayns-checkbox__content\">\n <span className=\"chayns-checkbox__label\">{children}</span>\n {description !== undefined ? (\n <span className=\"chayns-checkbox__description\">{description}</span>\n ) : null}\n </span>\n </label>\n );\n});\n\nCheckbox.displayName = 'Checkbox';\n\nexport default Checkbox;\n"],"mappings":";;;AAIA,IAAM,WAAW,WAA4C,SAAS,SACpE,EAAE,UAAU,WAAW,aAAa,GAAG,cACvC,KACA;CACA,MAAM,iBAAiB,CAAC,0BAA0B,SAAS,CAAC,CAAC,OAAO,OAAO,CAAC,CAAC,KAAK,GAAG;CAErF,OACE,qBAAC,SAAD;EAAO,WAAU;EAAjB,UAAA;GACE,oBAAC,SAAD;IAAO,GAAI;IAAY,WAAW;IAAqB;IAAK,MAAK;GAAY,CAAA;GAC7E,oBAAC,QAAD;IAAM,eAAY;IAAO,WAAU;IACjC,UAAA,oBAAC,KAAD,EAAG,WAAU,eAAgB,CAAA;GACzB,CAAA;GACN,qBAAC,QAAD;IAAM,WAAU;IAAhB,UAAA,CACE,oBAAC,QAAD;KAAM,WAAU;KAA0B;IAAe,CAAA,GACxD,gBAAgB,KAAA,IACf,oBAAC,QAAD;KAAM,WAAU;KAAgC,UAAA;IAAkB,CAAA,IAChE,IACA;;EACD;;AAEX,CAAC;AAED,SAAS,cAAc"}
@@ -1 +1 @@
1
- {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../src/components/combo-box/ComboBox.tsx"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,qBAAqB,CAAC;AAua9E,QAAA,MAAM,QAAQ;;CAA0C,CAAC;AAEzD,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"ComboBox.d.ts","sourceRoot":"","sources":["../../../src/components/combo-box/ComboBox.tsx"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,mBAAmB,EAAiB,MAAM,qBAAqB,CAAC;AAsb9E,QAAA,MAAM,QAAQ;;CAA0C,CAAC;AAKzD,eAAe,QAAQ,CAAC"}
@@ -1,4 +1,5 @@
1
1
  import ButtonIcon from "../button/button-icon/ButtonIcon.js";
2
+ import { composeNativeRefs } from "../../utils/native-ref.js";
2
3
  import { ComboBoxContext, getOptionLabel, useComboBoxContext } from "./ComboBoxContext.js";
3
4
  import { Children, Fragment, forwardRef, isValidElement, useEffect, useId, useMemo, useRef, useState } from "react";
4
5
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -55,7 +56,7 @@ var Option = forwardRef(function Option({ children, className, disabled = false,
55
56
  !comboBox.multiple && isSelected ? /* @__PURE__ */ jsx("span", {
56
57
  "aria-hidden": "true",
57
58
  className: "chayns-combo-box__checkmark",
58
- children: /* @__PURE__ */ jsx("i", { className: "fas fa-check" })
59
+ children: /* @__PURE__ */ jsx("i", { className: "far fa-check" })
59
60
  }) : null
60
61
  ]
61
62
  });
@@ -108,9 +109,27 @@ var ComboBoxRoot = forwardRef(function ComboBoxRoot(props, ref) {
108
109
  popupClosing,
109
110
  popupMounted
110
111
  ]);
112
+ useEffect(() => {
113
+ if (open || !popupClosing || !popupMounted) return void 0;
114
+ const popup = popupRef.current;
115
+ if (popup === null) return void 0;
116
+ const style = window.getComputedStyle(popup);
117
+ const durations = style.transitionDuration.split(",").map((duration) => Number.parseFloat(duration) * 1e3 || 0);
118
+ const delays = style.transitionDelay.split(",").map((delay) => Number.parseFloat(delay) * 1e3 || 0);
119
+ const duration = Math.max(...durations.map((time, index) => time + (delays[index % delays.length] ?? 0)));
120
+ const timeout = window.setTimeout(() => {
121
+ setPopupMounted(false);
122
+ setPopupClosing(false);
123
+ }, duration);
124
+ return () => window.clearTimeout(timeout);
125
+ }, [
126
+ open,
127
+ popupClosing,
128
+ popupMounted
129
+ ]);
111
130
  useEffect(() => {
112
131
  if (!open || activeValue === void 0) return;
113
- document.getElementById(`${listboxId}-${activeValue.replace(/[^a-zA-Z0-9_-]/g, "-")}`)?.focus();
132
+ document.getElementById(`${listboxId}-${encodeURIComponent(activeValue)}`)?.focus();
114
133
  }, [
115
134
  activeValue,
116
135
  listboxId,
@@ -145,11 +164,7 @@ var ComboBoxRoot = forwardRef(function ComboBoxRoot(props, ref) {
145
164
  document.removeEventListener("pointerdown", closeOnOutsidePress);
146
165
  };
147
166
  }, [open]);
148
- function setTriggerElement(element) {
149
- triggerRef.current = element;
150
- if (typeof ref === "function") ref(element);
151
- else if (ref !== null) ref.current = element;
152
- }
167
+ const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);
153
168
  function emitValue(nextValue) {
154
169
  if (!isControlled) setUncontrolledValue(nextValue);
155
170
  onValueChange?.(nextValue);
@@ -222,7 +237,7 @@ var ComboBoxRoot = forwardRef(function ComboBoxRoot(props, ref) {
222
237
  activeValue,
223
238
  isSelected: (optionValue) => multiple ? selectedValues.includes(optionValue) : selectedValue === optionValue,
224
239
  multiple,
225
- optionId: (optionValue) => `${listboxId}-${optionValue.replace(/[^a-zA-Z0-9_-]/g, "-")}`,
240
+ optionId: (optionValue) => `${listboxId}-${encodeURIComponent(optionValue)}`,
226
241
  select
227
242
  },
228
243
  children: /* @__PURE__ */ jsxs("div", {
@@ -259,6 +274,8 @@ var ComboBoxRoot = forwardRef(function ComboBoxRoot(props, ref) {
259
274
  }) : null,
260
275
  popupMounted && typeof document !== "undefined" ? createPortal(/* @__PURE__ */ jsx("div", {
261
276
  "aria-hidden": !open && popupClosing ? true : void 0,
277
+ "aria-label": ariaLabel,
278
+ "aria-labelledby": accessibleName,
262
279
  "aria-multiselectable": multiple || void 0,
263
280
  className: "chayns-combo-box__popup",
264
281
  "data-state": popupClosing ? "closed" : "open",
@@ -282,6 +299,8 @@ var ComboBoxRoot = forwardRef(function ComboBoxRoot(props, ref) {
282
299
  });
283
300
  });
284
301
  var ComboBox = Object.assign(ComboBoxRoot, { Option });
302
+ Option.displayName = "ComboBox.Option";
303
+ ComboBoxRoot.displayName = "ComboBox";
285
304
  //#endregion
286
305
  export { ComboBox as default };
287
306
 
@@ -1 +1 @@
1
- {"version":3,"file":"ComboBox.js","names":[],"sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import {\n Children,\n forwardRef,\n Fragment,\n isValidElement,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport type { CSSProperties, KeyboardEvent, MouseEvent, ReactElement, ReactNode } from 'react';\n\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport { ComboBoxContext, getOptionLabel, useComboBoxContext } from './ComboBoxContext.js';\nimport type { ComboBoxOptionProps, ComboBoxProps } from './ComboBox.types.js';\n\nfunction getOptionElements(children: ComboBoxProps['children']) {\n const options: ReactElement<ComboBoxOptionProps>[] = [];\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n return;\n }\n\n const element = child as ReactElement<{ children?: ReactNode; value?: string }>;\n\n if (element.type === Fragment) {\n options.push(...getOptionElements(element.props.children));\n } else if (typeof element.props.value === 'string') {\n options.push(element as ReactElement<ComboBoxOptionProps>);\n }\n });\n\n return options;\n}\n\nconst Option = forwardRef<HTMLDivElement, ComboBoxOptionProps>(function Option(\n { children, className, disabled = false, value, ...optionProps },\n ref,\n) {\n const comboBox = useComboBoxContext();\n const isSelected = comboBox.isSelected(value);\n const isActive = comboBox.activeValue === value;\n const resolvedClassName = [\n 'chayns-combo-box__option',\n isSelected ? 'chayns-combo-box__option--selected' : '',\n isActive ? 'chayns-combo-box__option--active' : '',\n disabled ? 'chayns-combo-box__option--disabled' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n {...optionProps}\n aria-disabled={disabled || undefined}\n aria-selected={isSelected}\n className={resolvedClassName}\n id={comboBox.optionId(value)}\n onClick={(event) => {\n optionProps.onClick?.(event);\n if (!event.defaultPrevented && !disabled) {\n comboBox.select(value);\n }\n }}\n onKeyDown={(event) => {\n optionProps.onKeyDown?.(event);\n if (!event.defaultPrevented && !disabled && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n comboBox.select(value);\n }\n }}\n ref={ref}\n role=\"option\"\n tabIndex={isActive && !disabled ? 0 : -1}\n >\n {comboBox.multiple ? (\n <span\n aria-hidden=\"true\"\n className=\"chayns-combo-box__checkbox\"\n data-checked={isSelected || undefined}\n />\n ) : null}\n {children}\n {!comboBox.multiple && isSelected ? (\n <span aria-hidden=\"true\" className=\"chayns-combo-box__checkmark\">\n <i className=\"fas fa-check\" />\n </span>\n ) : null}\n </div>\n );\n});\n\nconst ComboBoxRoot = forwardRef<HTMLButtonElement, ComboBoxProps>(\n function ComboBoxRoot(props, ref) {\n const {\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n children,\n className,\n defaultValue,\n disabled,\n id,\n multiple = false,\n onClick,\n onKeyDown,\n onValueChange,\n placeholder,\n value,\n ...buttonProps\n } = props;\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const listboxId = `${triggerId}-listbox`;\n const labelId = `${triggerId}-label`;\n const rootRef = useRef<HTMLDivElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [popupStyle, setPopupStyle] = useState<CSSProperties>();\n const optionElements = useMemo(() => getOptionElements(children), [children]);\n const optionMap = useMemo(\n () => new Map(optionElements.map((option) => [option.props.value, option])),\n [optionElements],\n );\n const focusableValues = optionElements\n .filter((option) => !option.props.disabled)\n .map((option) => option.props.value);\n const defaultValues = multiple\n ? ((defaultValue as ReactElement<ComboBoxOptionProps>[] | undefined)?.map(\n (option) => option.props.value,\n ) ?? [])\n : [];\n const controlledValues = multiple\n ? ((value as ReactElement<ComboBoxOptionProps>[] | undefined)?.map(\n (option) => option.props.value,\n ) ?? [])\n : [];\n const [uncontrolledValue, setUncontrolledValue] = useState(\n multiple ? '' : ((defaultValue as string | undefined) ?? ''),\n );\n const [uncontrolledValues, setUncontrolledValues] = useState(defaultValues);\n const [open, setOpen] = useState(false);\n const [popupMounted, setPopupMounted] = useState(false);\n const [popupClosing, setPopupClosing] = useState(false);\n const [activeValue, setActiveValue] = useState<string>();\n const isControlled = value !== undefined;\n const selectedValue = multiple ? '' : isControlled ? (value as string) : uncontrolledValue;\n const selectedValues = multiple ? (isControlled ? controlledValues : uncontrolledValues) : [];\n const selectedOptions = selectedValues\n .map((selected) => optionMap.get(selected))\n .filter((option): option is ReactElement<ComboBoxOptionProps> => option !== undefined);\n const selectedOption = optionMap.get(selectedValue);\n const displayValue = multiple\n ? selectedOptions.map((option) => getOptionLabel(option.props.children)).join(', ')\n : selectedOption === undefined\n ? ''\n : getOptionLabel(selectedOption.props.children);\n const resolvedClassName = ['chayns-combo-box', open ? 'chayns-combo-box--open' : '']\n .filter(Boolean)\n .join(' ');\n const triggerClassName = ['chayns-combo-box__trigger', className].filter(Boolean).join(' ');\n const accessibleName =\n ariaLabelledBy ??\n (ariaLabel === undefined && placeholder !== undefined ? labelId : undefined);\n\n if (ariaLabel === undefined && ariaLabelledBy === undefined && placeholder === undefined) {\n throw new Error('ComboBox requires placeholder, aria-label or aria-labelledby.');\n }\n\n useEffect(() => {\n if (open) {\n if (!popupMounted) {\n setPopupMounted(true);\n setPopupClosing(true);\n return undefined;\n }\n\n if (popupClosing) {\n const frame = requestAnimationFrame(() => setPopupClosing(false));\n return () => cancelAnimationFrame(frame);\n }\n } else if (popupMounted) {\n setPopupClosing(true);\n }\n\n return undefined;\n }, [open, popupClosing, popupMounted]);\n\n useEffect(() => {\n if (!open || activeValue === undefined) {\n return;\n }\n\n document\n .getElementById(`${listboxId}-${activeValue.replace(/[^a-zA-Z0-9_-]/g, '-')}`)\n ?.focus();\n }, [activeValue, listboxId, open, popupMounted]);\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n function updatePopupPosition() {\n const trigger = triggerRef.current;\n if (!trigger) {\n return;\n }\n\n const { bottom, left, width } = trigger.getBoundingClientRect();\n setPopupStyle({\n insetBlockStart: `calc(${bottom}px + var(--k4))`,\n insetInlineStart: left,\n inlineSize: width,\n });\n }\n\n function closeOnOutsidePress(event: PointerEvent) {\n if (\n event.target instanceof Node &&\n !rootRef.current?.contains(event.target) &&\n !popupRef.current?.contains(event.target)\n ) {\n setOpen(false);\n setActiveValue(undefined);\n }\n }\n\n updatePopupPosition();\n window.addEventListener('resize', updatePopupPosition);\n window.addEventListener('scroll', updatePopupPosition, true);\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => {\n window.removeEventListener('resize', updatePopupPosition);\n window.removeEventListener('scroll', updatePopupPosition, true);\n document.removeEventListener('pointerdown', closeOnOutsidePress);\n };\n }, [open]);\n\n function setTriggerElement(element: HTMLButtonElement | null) {\n triggerRef.current = element;\n\n if (typeof ref === 'function') {\n ref(element);\n } else if (ref !== null) {\n ref.current = element;\n }\n }\n\n function emitValue(nextValue: string) {\n if (!isControlled) {\n setUncontrolledValue(nextValue);\n }\n\n (onValueChange as ((next: string) => void) | undefined)?.(nextValue);\n }\n\n function emitValues(nextValues: string[]) {\n if (!isControlled) {\n setUncontrolledValues(nextValues);\n }\n\n const nextOptions = nextValues\n .map((nextValue) => optionMap.get(nextValue))\n .filter((option): option is ReactElement<ComboBoxOptionProps> => option !== undefined);\n (onValueChange as ((next: ReactElement<ComboBoxOptionProps>[]) => void) | undefined)?.(\n nextOptions,\n );\n }\n\n function closeAndFocusTrigger() {\n setOpen(false);\n setActiveValue(undefined);\n triggerRef.current?.focus();\n }\n\n function select(nextValue: string) {\n if (multiple) {\n const nextValues = selectedValues.includes(nextValue)\n ? selectedValues.filter((selected) => selected !== nextValue)\n : [...selectedValues, nextValue];\n emitValues(nextValues);\n } else {\n emitValue(nextValue);\n }\n\n closeAndFocusTrigger();\n }\n\n function openPopup() {\n if (disabled || focusableValues.length === 0) {\n return;\n }\n\n const selectedFocusableValue = focusableValues.find((optionValue) =>\n multiple ? selectedValues.includes(optionValue) : selectedValue === optionValue,\n );\n setActiveValue(selectedFocusableValue ?? focusableValues[0]);\n setOpen(true);\n }\n\n function moveActive(direction: 1 | -1) {\n if (focusableValues.length === 0) {\n return;\n }\n\n const currentIndex = activeValue === undefined ? -1 : focusableValues.indexOf(activeValue);\n const nextIndex =\n currentIndex === -1\n ? direction === 1\n ? 0\n : focusableValues.length - 1\n : (currentIndex + direction + focusableValues.length) % focusableValues.length;\n setActiveValue(focusableValues[nextIndex]);\n }\n\n function handleTriggerClick(event: MouseEvent<HTMLButtonElement>) {\n onClick?.(event);\n if (!event.defaultPrevented) {\n if (open) {\n closeAndFocusTrigger();\n } else {\n openPopup();\n }\n }\n }\n\n function handleTriggerKeyDown(event: KeyboardEvent<HTMLButtonElement>) {\n onKeyDown?.(event);\n if (event.defaultPrevented) {\n return;\n }\n\n if (\n event.key === 'Enter' ||\n event.key === ' ' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp' ||\n (event.key === 'ArrowDown' && event.altKey)\n ) {\n event.preventDefault();\n openPopup();\n }\n }\n\n function handleListboxKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n moveActive(1);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n moveActive(-1);\n } else if (event.key === 'Home') {\n event.preventDefault();\n setActiveValue(focusableValues[0]);\n } else if (event.key === 'End') {\n event.preventDefault();\n setActiveValue(focusableValues.at(-1));\n } else if (event.key === 'Escape') {\n event.preventDefault();\n closeAndFocusTrigger();\n } else if (event.key === 'Tab') {\n setOpen(false);\n setActiveValue(undefined);\n }\n }\n\n return (\n <ComboBoxContext.Provider\n value={{\n activeValue,\n isSelected: (optionValue) =>\n multiple ? selectedValues.includes(optionValue) : selectedValue === optionValue,\n multiple,\n optionId: (optionValue) => `${listboxId}-${optionValue.replace(/[^a-zA-Z0-9_-]/g, '-')}`,\n select,\n }}\n >\n <div className={resolvedClassName} ref={rootRef}>\n <button\n {...buttonProps}\n aria-controls={listboxId}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label={ariaLabel}\n aria-labelledby={accessibleName}\n className={triggerClassName}\n disabled={disabled}\n id={triggerId}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n ref={setTriggerElement}\n type=\"button\"\n >\n <span className=\"chayns-combo-box__value\">{displayValue || placeholder}</span>\n <span aria-hidden=\"true\" className=\"chayns-combo-box__chevron\">\n <ButtonIcon icon=\"fa-chevron-down\" />\n </span>\n </button>\n {placeholder !== undefined ? (\n <span className=\"chayns-combo-box__label\" id={labelId}>\n {placeholder}\n </span>\n ) : null}\n {popupMounted && typeof document !== 'undefined'\n ? createPortal(\n <div\n aria-hidden={!open && popupClosing ? true : undefined}\n aria-multiselectable={multiple || undefined}\n className=\"chayns-combo-box__popup\"\n data-state={popupClosing ? 'closed' : 'open'}\n id={listboxId}\n inert={!open && popupClosing}\n onKeyDown={handleListboxKeyDown}\n onTransitionEnd={(event) => {\n if (popupClosing && event.propertyName === 'opacity') {\n setPopupMounted(false);\n setPopupClosing(false);\n }\n }}\n ref={popupRef}\n role=\"listbox\"\n style={popupStyle}\n tabIndex={-1}\n >\n {children}\n </div>,\n document.body,\n )\n : null}\n </div>\n </ComboBoxContext.Provider>\n );\n },\n);\n\nconst ComboBox = Object.assign(ComboBoxRoot, { Option });\n\nexport default ComboBox;\n"],"mappings":"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"}
1
+ {"version":3,"file":"ComboBox.js","names":[],"sources":["../../../src/components/combo-box/ComboBox.tsx"],"sourcesContent":["import {\n Children,\n forwardRef,\n Fragment,\n isValidElement,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from 'react';\nimport { createPortal } from 'react-dom';\nimport type { CSSProperties, KeyboardEvent, MouseEvent, ReactElement, ReactNode } from 'react';\n\nimport { composeNativeRefs } from '../../utils/native-ref.js';\nimport ButtonIcon from '../button/button-icon/ButtonIcon.js';\nimport { ComboBoxContext, getOptionLabel, useComboBoxContext } from './ComboBoxContext.js';\nimport type { ComboBoxOptionProps, ComboBoxProps } from './ComboBox.types.js';\n\nfunction getOptionElements(children: ComboBoxProps['children']) {\n const options: ReactElement<ComboBoxOptionProps>[] = [];\n\n Children.forEach(children, (child) => {\n if (!isValidElement(child)) {\n return;\n }\n\n const element = child as ReactElement<{ children?: ReactNode; value?: string }>;\n\n if (element.type === Fragment) {\n options.push(...getOptionElements(element.props.children));\n } else if (typeof element.props.value === 'string') {\n options.push(element as ReactElement<ComboBoxOptionProps>);\n }\n });\n\n return options;\n}\n\nconst Option = forwardRef<HTMLDivElement, ComboBoxOptionProps>(function Option(\n { children, className, disabled = false, value, ...optionProps },\n ref,\n) {\n const comboBox = useComboBoxContext();\n const isSelected = comboBox.isSelected(value);\n const isActive = comboBox.activeValue === value;\n const resolvedClassName = [\n 'chayns-combo-box__option',\n isSelected ? 'chayns-combo-box__option--selected' : '',\n isActive ? 'chayns-combo-box__option--active' : '',\n disabled ? 'chayns-combo-box__option--disabled' : '',\n className,\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div\n {...optionProps}\n aria-disabled={disabled || undefined}\n aria-selected={isSelected}\n className={resolvedClassName}\n id={comboBox.optionId(value)}\n onClick={(event) => {\n optionProps.onClick?.(event);\n if (!event.defaultPrevented && !disabled) {\n comboBox.select(value);\n }\n }}\n onKeyDown={(event) => {\n optionProps.onKeyDown?.(event);\n if (!event.defaultPrevented && !disabled && (event.key === 'Enter' || event.key === ' ')) {\n event.preventDefault();\n comboBox.select(value);\n }\n }}\n ref={ref}\n role=\"option\"\n tabIndex={isActive && !disabled ? 0 : -1}\n >\n {comboBox.multiple ? (\n <span\n aria-hidden=\"true\"\n className=\"chayns-combo-box__checkbox\"\n data-checked={isSelected || undefined}\n />\n ) : null}\n {children}\n {!comboBox.multiple && isSelected ? (\n <span aria-hidden=\"true\" className=\"chayns-combo-box__checkmark\">\n <i className=\"far fa-check\" />\n </span>\n ) : null}\n </div>\n );\n});\n\nconst ComboBoxRoot = forwardRef<HTMLButtonElement, ComboBoxProps>(\n function ComboBoxRoot(props, ref) {\n const {\n 'aria-label': ariaLabel,\n 'aria-labelledby': ariaLabelledBy,\n children,\n className,\n defaultValue,\n disabled,\n id,\n multiple = false,\n onClick,\n onKeyDown,\n onValueChange,\n placeholder,\n value,\n ...buttonProps\n } = props;\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const listboxId = `${triggerId}-listbox`;\n const labelId = `${triggerId}-label`;\n const rootRef = useRef<HTMLDivElement>(null);\n const popupRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [popupStyle, setPopupStyle] = useState<CSSProperties>();\n const optionElements = useMemo(() => getOptionElements(children), [children]);\n const optionMap = useMemo(\n () => new Map(optionElements.map((option) => [option.props.value, option])),\n [optionElements],\n );\n const focusableValues = optionElements\n .filter((option) => !option.props.disabled)\n .map((option) => option.props.value);\n const defaultValues = multiple\n ? ((defaultValue as ReactElement<ComboBoxOptionProps>[] | undefined)?.map(\n (option) => option.props.value,\n ) ?? [])\n : [];\n const controlledValues = multiple\n ? ((value as ReactElement<ComboBoxOptionProps>[] | undefined)?.map(\n (option) => option.props.value,\n ) ?? [])\n : [];\n const [uncontrolledValue, setUncontrolledValue] = useState(\n multiple ? '' : ((defaultValue as string | undefined) ?? ''),\n );\n const [uncontrolledValues, setUncontrolledValues] = useState(defaultValues);\n const [open, setOpen] = useState(false);\n const [popupMounted, setPopupMounted] = useState(false);\n const [popupClosing, setPopupClosing] = useState(false);\n const [activeValue, setActiveValue] = useState<string>();\n const isControlled = value !== undefined;\n const selectedValue = multiple ? '' : isControlled ? (value as string) : uncontrolledValue;\n const selectedValues = multiple ? (isControlled ? controlledValues : uncontrolledValues) : [];\n const selectedOptions = selectedValues\n .map((selected) => optionMap.get(selected))\n .filter((option): option is ReactElement<ComboBoxOptionProps> => option !== undefined);\n const selectedOption = optionMap.get(selectedValue);\n const displayValue = multiple\n ? selectedOptions.map((option) => getOptionLabel(option.props.children)).join(', ')\n : selectedOption === undefined\n ? ''\n : getOptionLabel(selectedOption.props.children);\n const resolvedClassName = ['chayns-combo-box', open ? 'chayns-combo-box--open' : '']\n .filter(Boolean)\n .join(' ');\n const triggerClassName = ['chayns-combo-box__trigger', className].filter(Boolean).join(' ');\n const accessibleName =\n ariaLabelledBy ??\n (ariaLabel === undefined && placeholder !== undefined ? labelId : undefined);\n\n if (ariaLabel === undefined && ariaLabelledBy === undefined && placeholder === undefined) {\n throw new Error('ComboBox requires placeholder, aria-label or aria-labelledby.');\n }\n\n useEffect(() => {\n if (open) {\n if (!popupMounted) {\n setPopupMounted(true);\n setPopupClosing(true);\n return undefined;\n }\n\n if (popupClosing) {\n const frame = requestAnimationFrame(() => setPopupClosing(false));\n return () => cancelAnimationFrame(frame);\n }\n } else if (popupMounted) {\n setPopupClosing(true);\n }\n\n return undefined;\n }, [open, popupClosing, popupMounted]);\n\n useEffect(() => {\n if (open || !popupClosing || !popupMounted) return undefined;\n\n const popup = popupRef.current;\n if (popup === null) return undefined;\n const style = window.getComputedStyle(popup);\n const durations = style.transitionDuration\n .split(',')\n .map((duration) => Number.parseFloat(duration) * 1000 || 0);\n const delays = style.transitionDelay\n .split(',')\n .map((delay) => Number.parseFloat(delay) * 1000 || 0);\n const duration = Math.max(\n ...durations.map((time, index) => time + (delays[index % delays.length] ?? 0)),\n );\n const timeout = window.setTimeout(() => {\n setPopupMounted(false);\n setPopupClosing(false);\n }, duration);\n\n return () => window.clearTimeout(timeout);\n }, [open, popupClosing, popupMounted]);\n\n useEffect(() => {\n if (!open || activeValue === undefined) {\n return;\n }\n\n document.getElementById(`${listboxId}-${encodeURIComponent(activeValue)}`)?.focus();\n }, [activeValue, listboxId, open, popupMounted]);\n\n useEffect(() => {\n if (!open) {\n return undefined;\n }\n\n function updatePopupPosition() {\n const trigger = triggerRef.current;\n if (!trigger) {\n return;\n }\n\n const { bottom, left, width } = trigger.getBoundingClientRect();\n setPopupStyle({\n insetBlockStart: `calc(${bottom}px + var(--k4))`,\n insetInlineStart: left,\n inlineSize: width,\n });\n }\n\n function closeOnOutsidePress(event: PointerEvent) {\n if (\n event.target instanceof Node &&\n !rootRef.current?.contains(event.target) &&\n !popupRef.current?.contains(event.target)\n ) {\n setOpen(false);\n setActiveValue(undefined);\n }\n }\n\n updatePopupPosition();\n window.addEventListener('resize', updatePopupPosition);\n window.addEventListener('scroll', updatePopupPosition, true);\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => {\n window.removeEventListener('resize', updatePopupPosition);\n window.removeEventListener('scroll', updatePopupPosition, true);\n document.removeEventListener('pointerdown', closeOnOutsidePress);\n };\n }, [open]);\n\n const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);\n\n function emitValue(nextValue: string) {\n if (!isControlled) {\n setUncontrolledValue(nextValue);\n }\n\n (onValueChange as ((next: string) => void) | undefined)?.(nextValue);\n }\n\n function emitValues(nextValues: string[]) {\n if (!isControlled) {\n setUncontrolledValues(nextValues);\n }\n\n const nextOptions = nextValues\n .map((nextValue) => optionMap.get(nextValue))\n .filter((option): option is ReactElement<ComboBoxOptionProps> => option !== undefined);\n (onValueChange as ((next: ReactElement<ComboBoxOptionProps>[]) => void) | undefined)?.(\n nextOptions,\n );\n }\n\n function closeAndFocusTrigger() {\n setOpen(false);\n setActiveValue(undefined);\n triggerRef.current?.focus();\n }\n\n function select(nextValue: string) {\n if (multiple) {\n const nextValues = selectedValues.includes(nextValue)\n ? selectedValues.filter((selected) => selected !== nextValue)\n : [...selectedValues, nextValue];\n emitValues(nextValues);\n } else {\n emitValue(nextValue);\n }\n\n closeAndFocusTrigger();\n }\n\n function openPopup() {\n if (disabled || focusableValues.length === 0) {\n return;\n }\n\n const selectedFocusableValue = focusableValues.find((optionValue) =>\n multiple ? selectedValues.includes(optionValue) : selectedValue === optionValue,\n );\n setActiveValue(selectedFocusableValue ?? focusableValues[0]);\n setOpen(true);\n }\n\n function moveActive(direction: 1 | -1) {\n if (focusableValues.length === 0) {\n return;\n }\n\n const currentIndex = activeValue === undefined ? -1 : focusableValues.indexOf(activeValue);\n const nextIndex =\n currentIndex === -1\n ? direction === 1\n ? 0\n : focusableValues.length - 1\n : (currentIndex + direction + focusableValues.length) % focusableValues.length;\n setActiveValue(focusableValues[nextIndex]);\n }\n\n function handleTriggerClick(event: MouseEvent<HTMLButtonElement>) {\n onClick?.(event);\n if (!event.defaultPrevented) {\n if (open) {\n closeAndFocusTrigger();\n } else {\n openPopup();\n }\n }\n }\n\n function handleTriggerKeyDown(event: KeyboardEvent<HTMLButtonElement>) {\n onKeyDown?.(event);\n if (event.defaultPrevented) {\n return;\n }\n\n if (\n event.key === 'Enter' ||\n event.key === ' ' ||\n event.key === 'ArrowDown' ||\n event.key === 'ArrowUp' ||\n (event.key === 'ArrowDown' && event.altKey)\n ) {\n event.preventDefault();\n openPopup();\n }\n }\n\n function handleListboxKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'ArrowDown') {\n event.preventDefault();\n moveActive(1);\n } else if (event.key === 'ArrowUp') {\n event.preventDefault();\n moveActive(-1);\n } else if (event.key === 'Home') {\n event.preventDefault();\n setActiveValue(focusableValues[0]);\n } else if (event.key === 'End') {\n event.preventDefault();\n setActiveValue(focusableValues.at(-1));\n } else if (event.key === 'Escape') {\n event.preventDefault();\n closeAndFocusTrigger();\n } else if (event.key === 'Tab') {\n setOpen(false);\n setActiveValue(undefined);\n }\n }\n\n return (\n <ComboBoxContext.Provider\n value={{\n activeValue,\n isSelected: (optionValue) =>\n multiple ? selectedValues.includes(optionValue) : selectedValue === optionValue,\n multiple,\n optionId: (optionValue) => `${listboxId}-${encodeURIComponent(optionValue)}`,\n select,\n }}\n >\n <div className={resolvedClassName} ref={rootRef}>\n <button\n {...buttonProps}\n aria-controls={listboxId}\n aria-expanded={open}\n aria-haspopup=\"listbox\"\n aria-label={ariaLabel}\n aria-labelledby={accessibleName}\n className={triggerClassName}\n disabled={disabled}\n id={triggerId}\n onClick={handleTriggerClick}\n onKeyDown={handleTriggerKeyDown}\n ref={setTriggerElement}\n type=\"button\"\n >\n <span className=\"chayns-combo-box__value\">{displayValue || placeholder}</span>\n <span aria-hidden=\"true\" className=\"chayns-combo-box__chevron\">\n <ButtonIcon icon=\"fa-chevron-down\" />\n </span>\n </button>\n {placeholder !== undefined ? (\n <span className=\"chayns-combo-box__label\" id={labelId}>\n {placeholder}\n </span>\n ) : null}\n {popupMounted && typeof document !== 'undefined'\n ? createPortal(\n <div\n aria-hidden={!open && popupClosing ? true : undefined}\n aria-label={ariaLabel}\n aria-labelledby={accessibleName}\n aria-multiselectable={multiple || undefined}\n className=\"chayns-combo-box__popup\"\n data-state={popupClosing ? 'closed' : 'open'}\n id={listboxId}\n inert={!open && popupClosing}\n onKeyDown={handleListboxKeyDown}\n onTransitionEnd={(event) => {\n if (popupClosing && event.propertyName === 'opacity') {\n setPopupMounted(false);\n setPopupClosing(false);\n }\n }}\n ref={popupRef}\n role=\"listbox\"\n style={popupStyle}\n tabIndex={-1}\n >\n {children}\n </div>,\n document.body,\n )\n : null}\n </div>\n </ComboBoxContext.Provider>\n );\n },\n);\n\nconst ComboBox = Object.assign(ComboBoxRoot, { Option });\n\nOption.displayName = 'ComboBox.Option';\nComboBoxRoot.displayName = 'ComboBox';\n\nexport default ComboBox;\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAiC,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AA8LpG,QAAA,MAAM,cAAc,gIAyRlB,CAAC;AAEH,eAAe,cAAc,CAAC"}
1
+ {"version":3,"file":"DateTimePicker.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAiC,KAAK,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AAEpG,QAAA,MAAM,cAAc,gIA+KlB,CAAC;AAIH,eAAe,cAAc,CAAC"}
@@ -1,137 +1,12 @@
1
+ import { composeNativeRefs } from "../../utils/native-ref.js";
2
+ import { dateAtMidnight } from "./date-time-picker-utils.js";
3
+ import { useDateTimePickerValue } from "./hooks/useDateTimePickerValue.js";
4
+ import Wheel from "./wheel/Wheel.js";
5
+ import PickerSizer from "./sizer/PickerSizer.js";
1
6
  import { DATE_TIME_PICKER_MINUTE_STEPS } from "./DateTimePicker.types.js";
2
7
  import { forwardRef, useEffect, useId, useMemo, useRef, useState } from "react";
3
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
4
9
  //#region src/components/date-time-picker/DateTimePicker.tsx
5
- var WHEEL_LOOP_CYCLES = 11;
6
- var WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);
7
- function dateAtMidnight(value) {
8
- return new Date(value.getFullYear(), value.getMonth(), value.getDate());
9
- }
10
- function clampDate(value, minDate, maxDate) {
11
- const date = dateAtMidnight(value);
12
- if (minDate !== void 0 && date < dateAtMidnight(minDate)) return new Date(minDate);
13
- if (maxDate !== void 0 && date > dateAtMidnight(maxDate)) return new Date(maxDate);
14
- return value;
15
- }
16
- function normalizeMinute(value, minuteStep) {
17
- const normalized = new Date(value);
18
- normalized.setMinutes(Math.floor(normalized.getMinutes() / minuteStep) * minuteStep);
19
- return normalized;
20
- }
21
- function Wheel({ ariaLabel, onEscape, onSelect, options, selected }) {
22
- const wheelRef = useRef(null);
23
- const selectedRef = useRef(null);
24
- const dragRef = useRef(void 0);
25
- const ignoreClickRef = useRef(false);
26
- useEffect(() => {
27
- if (typeof selectedRef.current?.scrollIntoView === "function") selectedRef.current.scrollIntoView({ block: "center" });
28
- }, []);
29
- function applyPerspective() {
30
- const wheel = wheelRef.current;
31
- const itemHeight = selectedRef.current?.offsetHeight;
32
- if (!wheel || !itemHeight) return;
33
- const position = wheel.scrollTop / itemHeight;
34
- for (const option of wheel.querySelectorAll(".chayns-date-time-picker__wheel-option")) {
35
- const index = Number(option.dataset.wheelIndex);
36
- const distance = Math.max(-2.5, Math.min(2.5, index - position));
37
- const progress = Math.min(1, Math.abs(distance) / 2.5);
38
- option.style.color = progress < .2 ? "var(--text)" : "var(--text-3)";
39
- option.style.fontWeight = progress < .2 ? "600" : "400";
40
- option.style.opacity = String(1 - progress * .7);
41
- option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * .24})`;
42
- }
43
- }
44
- function selectCenteredValue() {
45
- const wheel = wheelRef.current;
46
- const itemHeight = selectedRef.current?.offsetHeight;
47
- if (!wheel || !itemHeight) return;
48
- const option = options[(Math.round(wheel.scrollTop / itemHeight) % options.length + options.length) % options.length];
49
- if (option !== void 0 && option.value !== selected) onSelect(option.value);
50
- }
51
- function handleScroll() {
52
- const wheel = wheelRef.current;
53
- const itemHeight = selectedRef.current?.offsetHeight;
54
- if (!wheel || !itemHeight) return;
55
- const index = Math.round(wheel.scrollTop / itemHeight);
56
- const normalizedIndex = (index % options.length + options.length) % options.length;
57
- if (index < options.length * 2 || index >= options.length * 9) wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;
58
- applyPerspective();
59
- selectCenteredValue();
60
- }
61
- function handleKeyDown(event) {
62
- if (event.key === "Escape") {
63
- event.preventDefault();
64
- onEscape();
65
- return;
66
- }
67
- const index = options.findIndex((option) => option.value === selected);
68
- let nextIndex = index;
69
- if (event.key === "ArrowDown") nextIndex = Math.min(index + 1, options.length - 1);
70
- if (event.key === "ArrowUp") nextIndex = Math.max(index - 1, 0);
71
- if (event.key === "Home") nextIndex = 0;
72
- if (event.key === "End") nextIndex = options.length - 1;
73
- const nextOption = options[nextIndex];
74
- if (nextIndex !== index && nextOption !== void 0) {
75
- event.preventDefault();
76
- onSelect(nextOption.value);
77
- }
78
- }
79
- function handlePointerDown(event) {
80
- if (event.button !== 0) return;
81
- if (typeof event.currentTarget.setPointerCapture === "function") event.currentTarget.setPointerCapture(event.pointerId);
82
- dragRef.current = {
83
- pointerId: event.pointerId,
84
- scrollTop: event.currentTarget.scrollTop,
85
- startY: event.clientY
86
- };
87
- ignoreClickRef.current = false;
88
- }
89
- function handlePointerMove(event) {
90
- const drag = dragRef.current;
91
- if (drag?.pointerId !== event.pointerId) return;
92
- const distance = event.clientY - drag.startY;
93
- if (Math.abs(distance) > 3) {
94
- ignoreClickRef.current = true;
95
- event.currentTarget.scrollTop = drag.scrollTop - distance;
96
- }
97
- }
98
- function handlePointerUp(event) {
99
- if (dragRef.current?.pointerId !== event.pointerId) return;
100
- dragRef.current = void 0;
101
- if (typeof event.currentTarget.releasePointerCapture === "function") event.currentTarget.releasePointerCapture(event.pointerId);
102
- selectCenteredValue();
103
- }
104
- return /* @__PURE__ */ jsx("div", {
105
- "aria-label": ariaLabel,
106
- className: "chayns-date-time-picker__wheel",
107
- onKeyDown: handleKeyDown,
108
- onPointerDown: handlePointerDown,
109
- onPointerMove: handlePointerMove,
110
- onPointerUp: handlePointerUp,
111
- onScroll: handleScroll,
112
- ref: wheelRef,
113
- role: "listbox",
114
- tabIndex: 0,
115
- children: Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) => options.map((option, optionIndex) => /* @__PURE__ */ jsx("button", {
116
- "aria-selected": option.value === selected,
117
- className: "chayns-date-time-picker__wheel-option",
118
- "data-wheel-index": cycle * options.length + optionIndex,
119
- onClick: (event) => {
120
- if (ignoreClickRef.current) {
121
- event.preventDefault();
122
- event.stopPropagation();
123
- ignoreClickRef.current = false;
124
- return;
125
- }
126
- onSelect(option.value);
127
- },
128
- ref: cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : void 0,
129
- role: "option",
130
- type: "button",
131
- children: option.label
132
- }, `${cycle}-${option.value}`)))
133
- });
134
- }
135
10
  var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, id, label, locale, maxDate, minDate, minuteStep = 1, mode = "time", onChange, onClick, onKeyDown, placeholder, value, wheelLabels, ...buttonProps }, ref) {
136
11
  if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) throw new Error("DateTimePicker minuteStep must be one of: 1, 5, 15, 30.");
137
12
  if (minDate !== void 0 && maxDate !== void 0 && dateAtMidnight(minDate) > dateAtMidnight(maxDate)) throw new Error("DateTimePicker requires minDate to be earlier than or equal to maxDate.");
@@ -140,10 +15,23 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
140
15
  const popupId = `${triggerId}-popup`;
141
16
  const rootRef = useRef(null);
142
17
  const triggerRef = useRef(null);
18
+ const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);
143
19
  const [open, setOpen] = useState(false);
144
- const displayValue = value === null ? null : mode === "date" ? clampDate(value, minDate, maxDate) : normalizeMinute(value, minuteStep);
145
- const activeValue = displayValue ?? /* @__PURE__ */ new Date();
146
- const isTwelveHour = new Intl.DateTimeFormat(locale, { hour: "numeric" }).resolvedOptions().hour12 === true;
20
+ const { displayValue, formattedValue, activeValue, isTwelveHour, hours, minutes, dayPeriods, datePartOrder, dateOptions, dateValue, dateLabel, updateDate, updateTime, updatePeriod, sizingValues } = useDateTimePickerValue({
21
+ value,
22
+ locale,
23
+ maxDate,
24
+ minDate,
25
+ onChange,
26
+ placeholder,
27
+ wheelLabels,
28
+ minuteStep,
29
+ mode
30
+ });
31
+ function close() {
32
+ setOpen(false);
33
+ triggerRef.current?.focus();
34
+ }
147
35
  useEffect(() => {
148
36
  if (!open) return void 0;
149
37
  function closeOnOutsidePress(event) {
@@ -152,104 +40,6 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
152
40
  document.addEventListener("pointerdown", closeOnOutsidePress);
153
41
  return () => document.removeEventListener("pointerdown", closeOnOutsidePress);
154
42
  });
155
- const years = useMemo(() => {
156
- const today = (/* @__PURE__ */ new Date()).getFullYear();
157
- const first = minDate?.getFullYear() ?? today - 100;
158
- const last = maxDate?.getFullYear() ?? today + 100;
159
- return Array.from({ length: last - first + 1 }, (_, index) => first + index);
160
- }, [maxDate, minDate]);
161
- function close() {
162
- setOpen(false);
163
- triggerRef.current?.focus();
164
- }
165
- function emit(nextValue) {
166
- onChange(mode === "date" ? clampDate(nextValue, minDate, maxDate) : nextValue);
167
- }
168
- function updateTime(part, nextValue) {
169
- const next = new Date(activeValue);
170
- if (part === "hours") {
171
- const hour = isTwelveHour ? nextValue % 12 + (next.getHours() >= 12 ? 12 : 0) : nextValue;
172
- next.setHours(hour);
173
- } else next.setMinutes(nextValue);
174
- emit(next);
175
- }
176
- function updatePeriod(period) {
177
- const next = new Date(activeValue);
178
- next.setHours(next.getHours() % 12 + period * 12);
179
- emit(next);
180
- }
181
- function updateDate(part, nextValue) {
182
- const next = new Date(activeValue);
183
- const originalDay = next.getDate();
184
- next.setDate(1);
185
- if (part === "fullYear") next.setFullYear(nextValue);
186
- if (part === "month") next.setMonth(nextValue);
187
- if (part === "date") next.setDate(nextValue);
188
- if (part !== "date") next.setDate(Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()));
189
- emit(next);
190
- }
191
- const formattedValue = displayValue === null ? placeholder : mode === "time" ? `${new Intl.DateTimeFormat(locale, {
192
- hour: "numeric",
193
- minute: "2-digit"
194
- }).format(displayValue)}${locale.toLowerCase().startsWith("de") ? " Uhr" : ""}` : new Intl.DateTimeFormat(locale, {
195
- day: "numeric",
196
- month: "long",
197
- year: "numeric"
198
- }).format(displayValue);
199
- const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) => isTwelveHour ? index + 1 : index).map((hour) => ({
200
- label: String(hour).padStart(2, "0"),
201
- value: hour
202
- }));
203
- const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {
204
- const minute = index * minuteStep;
205
- return {
206
- label: String(minute).padStart(2, "0"),
207
- value: minute
208
- };
209
- });
210
- const months = Array.from({ length: 12 }, (_, month) => ({
211
- label: new Intl.DateTimeFormat(locale, { month: "long" }).format(new Date(2026, month, 1)),
212
- value: month
213
- })).filter((month) => {
214
- const first = new Date(activeValue.getFullYear(), month.value, 1);
215
- const last = new Date(activeValue.getFullYear(), month.value + 1, 0);
216
- return (minDate === void 0 || last >= dateAtMidnight(minDate)) && (maxDate === void 0 || first <= dateAtMidnight(maxDate));
217
- });
218
- const days = Array.from({ length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() }, (_, index) => ({
219
- label: String(index + 1).padStart(2, "0"),
220
- value: index + 1
221
- })).filter((day) => {
222
- const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);
223
- return (minDate === void 0 || candidate >= dateAtMidnight(minDate)) && (maxDate === void 0 || candidate <= dateAtMidnight(maxDate));
224
- });
225
- const datePartOrder = new Intl.DateTimeFormat(locale, {
226
- day: "numeric",
227
- month: "numeric",
228
- year: "numeric"
229
- }).formatToParts(activeValue).flatMap((part) => {
230
- if (part.type === "day") return ["date"];
231
- if (part.type === "month") return ["month"];
232
- if (part.type === "year") return ["fullYear"];
233
- return [];
234
- });
235
- const yearOptions = years.map((year) => ({
236
- label: String(year),
237
- value: year
238
- }));
239
- function dateOptions(part) {
240
- if (part === "date") return days;
241
- if (part === "month") return months;
242
- return yearOptions;
243
- }
244
- function dateValue(part) {
245
- if (part === "date") return activeValue.getDate();
246
- if (part === "month") return activeValue.getMonth();
247
- return activeValue.getFullYear();
248
- }
249
- const dayPeriods = [0, 1].map((period) => ({
250
- label: new Intl.DateTimeFormat(locale, { hour: "numeric" }).formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13)).find((part) => part.type === "dayPeriod")?.value ?? (period === 0 ? "AM" : "PM"),
251
- value: period
252
- }));
253
43
  const resolvedClassName = [
254
44
  "chayns-date-time-picker",
255
45
  `chayns-date-time-picker--${mode}`,
@@ -260,11 +50,16 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
260
50
  className: resolvedClassName,
261
51
  ref: rootRef,
262
52
  children: [
53
+ /* @__PURE__ */ jsx(PickerSizer, {
54
+ values: sizingValues,
55
+ placeholder: displayValue === null ? placeholder : null
56
+ }),
263
57
  /* @__PURE__ */ jsx("button", {
264
58
  ...buttonProps,
265
59
  "aria-controls": open ? popupId : void 0,
266
60
  "aria-expanded": open,
267
61
  "aria-haspopup": "dialog",
62
+ "aria-label": label,
268
63
  className: ["chayns-date-time-picker__trigger", className].filter(Boolean).join(" "),
269
64
  disabled,
270
65
  id: triggerId,
@@ -279,19 +74,15 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
279
74
  close();
280
75
  }
281
76
  },
282
- ref: (element) => {
283
- triggerRef.current = element;
284
- if (typeof ref === "function") ref(element);
285
- else if (ref !== null) ref.current = element;
286
- },
77
+ ref: setTriggerElement,
287
78
  type: "button",
288
79
  children: formattedValue
289
80
  }),
290
- /* @__PURE__ */ jsx("label", {
81
+ displayValue === null ? /* @__PURE__ */ jsx("label", {
291
82
  className: "chayns-date-time-picker__label",
292
83
  htmlFor: triggerId,
293
84
  children: label
294
- }),
85
+ }) : null,
295
86
  open && !disabled ? /* @__PURE__ */ jsxs("div", {
296
87
  "aria-label": label,
297
88
  className: "chayns-date-time-picker__popup",
@@ -322,7 +113,7 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
322
113
  selected: activeValue.getHours() >= 12 ? 1 : 0
323
114
  }) : null
324
115
  ] }) : datePartOrder.map((part) => /* @__PURE__ */ jsx(Wheel, {
325
- ariaLabel: part === "date" ? wheelLabels.day : part === "month" ? wheelLabels.month : wheelLabels.year,
116
+ ariaLabel: dateLabel(part),
326
117
  onEscape: close,
327
118
  onSelect: (nextValue) => updateDate(part, nextValue),
328
119
  options: dateOptions(part),
@@ -333,6 +124,7 @@ var DateTimePicker = forwardRef(function DateTimePicker({ className, disabled, i
333
124
  ]
334
125
  });
335
126
  });
127
+ DateTimePicker.displayName = "DateTimePicker";
336
128
  //#endregion
337
129
  export { DateTimePicker as default };
338
130