@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.
- package/dist/accordion.css +3 -1
- package/dist/badge.css +28 -3
- package/dist/banner.css +2 -0
- package/dist/breadcrumb.css +63 -0
- package/dist/button.css +103 -35
- package/dist/card.css +39 -0
- package/dist/checkbox.css +3 -3
- package/dist/combo-box.css +2 -0
- package/dist/components/accordion/Accordion.d.ts +3 -4
- package/dist/components/accordion/Accordion.d.ts.map +1 -1
- package/dist/components/accordion/Accordion.js +37 -23
- package/dist/components/accordion/Accordion.js.map +1 -1
- package/dist/components/accordion/Accordion.types.d.ts +7 -2
- package/dist/components/accordion/Accordion.types.d.ts.map +1 -1
- package/dist/components/accordion/Accordion.types.js +7 -1
- package/dist/components/accordion/Accordion.types.js.map +1 -1
- package/dist/components/accordion-group/AccordionGroup.d.ts.map +1 -1
- package/dist/components/accordion-group/AccordionGroup.js +1 -0
- package/dist/components/accordion-group/AccordionGroup.js.map +1 -1
- package/dist/components/avatar/Avatar.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.js +1 -0
- package/dist/components/avatar/Avatar.js.map +1 -1
- package/dist/components/avatar/Avatar.types.d.ts +9 -1
- package/dist/components/avatar/Avatar.types.d.ts.map +1 -1
- package/dist/components/avatar/Avatar.types.js +17 -0
- package/dist/components/avatar/Avatar.types.js.map +1 -0
- package/dist/components/avatar-group/AvatarGroup.d.ts.map +1 -1
- package/dist/components/avatar-group/AvatarGroup.js +4 -3
- package/dist/components/avatar-group/AvatarGroup.js.map +1 -1
- package/dist/components/badge/Badge.d.ts.map +1 -1
- package/dist/components/badge/Badge.js +1 -0
- package/dist/components/badge/Badge.js.map +1 -1
- package/dist/components/badge/Badge.types.d.ts +13 -0
- package/dist/components/badge/Badge.types.d.ts.map +1 -1
- package/dist/components/badge/Badge.types.js +16 -1
- package/dist/components/badge/Badge.types.js.map +1 -1
- package/dist/components/banner/Banner.d.ts.map +1 -1
- package/dist/components/banner/Banner.js +1 -0
- package/dist/components/banner/Banner.js.map +1 -1
- package/dist/components/banner/Banner.types.d.ts +7 -0
- package/dist/components/banner/Banner.types.d.ts.map +1 -1
- package/dist/components/banner/Banner.types.js +9 -1
- package/dist/components/banner/Banner.types.js.map +1 -1
- package/dist/components/breadcrumb/Breadcrumb.d.ts +4 -0
- package/dist/components/breadcrumb/Breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb/Breadcrumb.js +35 -0
- package/dist/components/breadcrumb/Breadcrumb.js.map +1 -0
- package/dist/components/breadcrumb/Breadcrumb.types.d.ts +13 -0
- package/dist/components/breadcrumb/Breadcrumb.types.d.ts.map +1 -0
- package/dist/components/button/Button.d.ts.map +1 -1
- package/dist/components/button/Button.js +1 -0
- package/dist/components/button/Button.js.map +1 -1
- package/dist/components/button/Button.types.d.ts +7 -0
- package/dist/components/button/Button.types.d.ts.map +1 -1
- package/dist/components/button/Button.types.js +9 -1
- package/dist/components/button/Button.types.js.map +1 -1
- package/dist/components/button/button-icon/ButtonIcon.d.ts.map +1 -1
- package/dist/components/button/button-icon/ButtonIcon.js +7 -3
- package/dist/components/button/button-icon/ButtonIcon.js.map +1 -1
- package/dist/components/card/Card.d.ts.map +1 -1
- package/dist/components/card/Card.js +2 -0
- package/dist/components/card/Card.js.map +1 -1
- package/dist/components/checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/checkbox/Checkbox.js +1 -0
- package/dist/components/checkbox/Checkbox.js.map +1 -1
- package/dist/components/combo-box/ComboBox.d.ts.map +1 -1
- package/dist/components/combo-box/ComboBox.js +27 -8
- package/dist/components/combo-box/ComboBox.js.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.js +31 -239
- package/dist/components/date-time-picker/DateTimePicker.js.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.types.d.ts +12 -0
- package/dist/components/date-time-picker/DateTimePicker.types.d.ts.map +1 -1
- package/dist/components/date-time-picker/DateTimePicker.types.js +15 -1
- package/dist/components/date-time-picker/DateTimePicker.types.js.map +1 -1
- package/dist/components/date-time-picker/date-time-picker-utils.d.ts +4 -0
- package/dist/components/date-time-picker/date-time-picker-utils.d.ts.map +1 -0
- package/dist/components/date-time-picker/date-time-picker-utils.js +19 -0
- package/dist/components/date-time-picker/date-time-picker-utils.js.map +1 -0
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.d.ts +37 -0
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.d.ts.map +1 -0
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js +156 -0
- package/dist/components/date-time-picker/hooks/useDateTimePickerValue.js.map +1 -0
- package/dist/components/date-time-picker/sizer/PickerSizer.d.ts +7 -0
- package/dist/components/date-time-picker/sizer/PickerSizer.d.ts.map +1 -0
- package/dist/components/date-time-picker/sizer/PickerSizer.js +15 -0
- package/dist/components/date-time-picker/sizer/PickerSizer.js.map +1 -0
- package/dist/components/date-time-picker/wheel/Wheel.d.ts +14 -0
- package/dist/components/date-time-picker/wheel/Wheel.d.ts.map +1 -0
- package/dist/components/date-time-picker/wheel/Wheel.js +136 -0
- package/dist/components/date-time-picker/wheel/Wheel.js.map +1 -0
- package/dist/components/icon-button/IconButton.d.ts.map +1 -1
- package/dist/components/icon-button/IconButton.js +1 -0
- package/dist/components/icon-button/IconButton.js.map +1 -1
- package/dist/components/list/List.d.ts +15 -10
- package/dist/components/list/List.d.ts.map +1 -1
- package/dist/components/list/List.js +19 -7
- package/dist/components/list/List.js.map +1 -1
- package/dist/components/list/List.types.d.ts +2 -2
- package/dist/components/list/List.types.d.ts.map +1 -1
- package/dist/components/pagination/Pagination.d.ts +4 -0
- package/dist/components/pagination/Pagination.d.ts.map +1 -0
- package/dist/components/pagination/Pagination.js +57 -0
- package/dist/components/pagination/Pagination.js.map +1 -0
- package/dist/components/pagination/Pagination.types.d.ts +15 -0
- package/dist/components/pagination/Pagination.types.d.ts.map +1 -0
- package/dist/components/pagination/pagination-pages.d.ts +2 -0
- package/dist/components/pagination/pagination-pages.d.ts.map +1 -0
- package/dist/components/pagination/pagination-pages.js +35 -0
- package/dist/components/pagination/pagination-pages.js.map +1 -0
- package/dist/components/popup/Popup.d.ts +4 -1
- package/dist/components/popup/Popup.d.ts.map +1 -1
- package/dist/components/popup/Popup.js +25 -18
- package/dist/components/popup/Popup.js.map +1 -1
- package/dist/components/popup/PopupList.d.ts +4 -1
- package/dist/components/popup/PopupList.d.ts.map +1 -1
- package/dist/components/popup/PopupList.js +7 -1
- package/dist/components/popup/PopupList.js.map +1 -1
- package/dist/components/progress/Progress.d.ts.map +1 -1
- package/dist/components/progress/Progress.js +1 -0
- package/dist/components/progress/Progress.js.map +1 -1
- package/dist/components/progress/Progress.types.d.ts +1 -1
- package/dist/components/progress/Progress.types.d.ts.map +1 -1
- package/dist/components/radio-group/RadioGroup.d.ts.map +1 -1
- package/dist/components/radio-group/RadioGroup.js +2 -0
- package/dist/components/radio-group/RadioGroup.js.map +1 -1
- package/dist/components/segmented-control/SegmentedControl.d.ts.map +1 -1
- package/dist/components/segmented-control/SegmentedControl.js +78 -25
- package/dist/components/segmented-control/SegmentedControl.js.map +1 -1
- package/dist/components/segmented-control/SegmentedControl.types.d.ts +1 -1
- package/dist/components/segmented-control/SegmentedControl.types.d.ts.map +1 -1
- package/dist/components/segmented-control/SegmentedControlContext.d.ts +2 -0
- package/dist/components/segmented-control/SegmentedControlContext.d.ts.map +1 -1
- package/dist/components/segmented-control/SegmentedControlContext.js.map +1 -1
- package/dist/components/skeleton/Skeleton.d.ts.map +1 -1
- package/dist/components/skeleton/Skeleton.js +1 -0
- package/dist/components/skeleton/Skeleton.js.map +1 -1
- package/dist/components/skeleton/Skeleton.types.d.ts +6 -0
- package/dist/components/skeleton/Skeleton.types.d.ts.map +1 -1
- package/dist/components/skeleton/Skeleton.types.js +8 -1
- package/dist/components/skeleton/Skeleton.types.js.map +1 -1
- package/dist/components/slider/Slider.d.ts +4 -0
- package/dist/components/slider/Slider.d.ts.map +1 -0
- package/dist/components/slider/Slider.js +61 -0
- package/dist/components/slider/Slider.js.map +1 -0
- package/dist/components/slider/Slider.types.d.ts +10 -0
- package/dist/components/slider/Slider.types.d.ts.map +1 -0
- package/dist/components/spinner/Spinner.d.ts.map +1 -1
- package/dist/components/spinner/Spinner.js +1 -0
- package/dist/components/spinner/Spinner.js.map +1 -1
- package/dist/components/split-button/SplitButton.d.ts.map +1 -1
- package/dist/components/split-button/SplitButton.js +2 -1
- package/dist/components/split-button/SplitButton.js.map +1 -1
- package/dist/components/stepper/Stepper.d.ts +4 -0
- package/dist/components/stepper/Stepper.d.ts.map +1 -0
- package/dist/components/stepper/Stepper.js +60 -0
- package/dist/components/stepper/Stepper.js.map +1 -0
- package/dist/components/stepper/Stepper.types.d.ts +27 -0
- package/dist/components/stepper/Stepper.types.d.ts.map +1 -0
- package/dist/components/stepper/Stepper.types.js +25 -0
- package/dist/components/stepper/Stepper.types.js.map +1 -0
- package/dist/components/stepper/stepper-values.d.ts +6 -0
- package/dist/components/stepper/stepper-values.d.ts.map +1 -0
- package/dist/components/stepper/stepper-values.js +26 -0
- package/dist/components/stepper/stepper-values.js.map +1 -0
- package/dist/components/switch/Switch.d.ts.map +1 -1
- package/dist/components/switch/Switch.js +1 -0
- package/dist/components/switch/Switch.js.map +1 -1
- package/dist/components/text-area/TextArea.d.ts.map +1 -1
- package/dist/components/text-area/TextArea.js +1 -0
- package/dist/components/text-area/TextArea.js.map +1 -1
- package/dist/components/text-field/TextField.d.ts.map +1 -1
- package/dist/components/text-field/TextField.js +1 -0
- package/dist/components/text-field/TextField.js.map +1 -1
- package/dist/components/tooltip/Tooltip.d.ts +4 -0
- package/dist/components/tooltip/Tooltip.d.ts.map +1 -0
- package/dist/components/tooltip/Tooltip.js +75 -0
- package/dist/components/tooltip/Tooltip.js.map +1 -0
- package/dist/components/tooltip/Tooltip.types.d.ts +12 -0
- package/dist/components/tooltip/Tooltip.types.d.ts.map +1 -0
- package/dist/components/tooltip/hooks/useTooltipInteraction.d.ts +11 -0
- package/dist/components/tooltip/hooks/useTooltipInteraction.d.ts.map +1 -0
- package/dist/components/tooltip/hooks/useTooltipInteraction.js +59 -0
- package/dist/components/tooltip/hooks/useTooltipInteraction.js.map +1 -0
- package/dist/components/tooltip/tooltip-trigger-props.d.ts +4 -0
- package/dist/components/tooltip/tooltip-trigger-props.d.ts.map +1 -0
- package/dist/components/tooltip/tooltip-trigger-props.js +25 -0
- package/dist/components/tooltip/tooltip-trigger-props.js.map +1 -0
- package/dist/date-time-picker.css +33 -2
- package/dist/hooks/useOverlayPosition.d.ts +4 -0
- package/dist/hooks/useOverlayPosition.d.ts.map +1 -0
- package/dist/hooks/useOverlayPosition.js +60 -0
- package/dist/hooks/useOverlayPosition.js.map +1 -0
- package/dist/index.d.ts +21 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -7
- package/dist/pagination.css +54 -0
- package/dist/popup.css +4 -0
- package/dist/progress.css +1 -1
- package/dist/segmented-control.css +2 -0
- package/dist/slider.css +109 -0
- package/dist/split-button.css +2 -79
- package/dist/stepper.css +77 -0
- package/dist/styles.css +5 -0
- package/dist/tooltip.css +68 -0
- package/dist/utils/native-ref.d.ts +4 -0
- package/dist/utils/native-ref.d.ts.map +1 -0
- package/dist/utils/native-ref.js +24 -0
- package/dist/utils/native-ref.js.map +1 -0
- 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;
|
|
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;
|
|
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"}
|
|
@@ -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":"
|
|
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: "
|
|
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
|
|
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
|
-
|
|
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
|
|
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":"
|
|
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
|
|
145
|
-
|
|
146
|
-
|
|
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:
|
|
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
|
|
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
|
|