@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":"DateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport type { KeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\n\nimport { DATE_TIME_PICKER_MINUTE_STEPS, type DateTimePickerProps } from './DateTimePicker.types.js';\n\nconst WHEEL_LOOP_CYCLES = 11;\nconst WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);\ntype DatePart = 'date' | 'fullYear' | 'month';\n\ninterface WheelOption {\n label: string;\n value: number;\n}\n\ninterface WheelProps {\n ariaLabel: string;\n onEscape: () => void;\n onSelect: (value: number) => void;\n options: readonly WheelOption[];\n selected: number;\n}\n\nfunction dateAtMidnight(value: Date) {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate());\n}\n\nfunction clampDate(value: Date, minDate?: Date, maxDate?: Date) {\n const date = dateAtMidnight(value);\n if (minDate !== undefined && date < dateAtMidnight(minDate)) return new Date(minDate);\n if (maxDate !== undefined && date > dateAtMidnight(maxDate)) return new Date(maxDate);\n return value;\n}\n\nfunction normalizeMinute(value: Date, minuteStep: number) {\n const normalized = new Date(value);\n normalized.setMinutes(Math.floor(normalized.getMinutes() / minuteStep) * minuteStep);\n return normalized;\n}\n\nfunction Wheel({ ariaLabel, onEscape, onSelect, options, selected }: WheelProps) {\n const wheelRef = useRef<HTMLDivElement>(null);\n const selectedRef = useRef<HTMLButtonElement>(null);\n const dragRef = useRef<{ pointerId: number; scrollTop: number; startY: number } | undefined>(\n undefined,\n );\n const ignoreClickRef = useRef(false);\n\n useEffect(() => {\n if (typeof selectedRef.current?.scrollIntoView === 'function') {\n selectedRef.current.scrollIntoView({ block: 'center' });\n }\n }, []);\n\n function applyPerspective() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const position = wheel.scrollTop / itemHeight;\n for (const option of wheel.querySelectorAll<HTMLButtonElement>(\n '.chayns-date-time-picker__wheel-option',\n )) {\n const index = Number(option.dataset.wheelIndex);\n const distance = Math.max(-2.5, Math.min(2.5, index - position));\n const progress = Math.min(1, Math.abs(distance) / 2.5);\n\n option.style.color = progress < 0.2 ? 'var(--text)' : 'var(--text-3)';\n option.style.fontWeight = progress < 0.2 ? '600' : '400';\n option.style.opacity = String(1 - progress * 0.7);\n option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * 0.24})`;\n }\n }\n\n function selectCenteredValue() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const option = options[((index % options.length) + options.length) % options.length];\n if (option !== undefined && option.value !== selected) onSelect(option.value);\n }\n\n function handleScroll() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const normalizedIndex = ((index % options.length) + options.length) % options.length;\n if (index < options.length * 2 || index >= options.length * (WHEEL_LOOP_CYCLES - 2)) {\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;\n }\n\n applyPerspective();\n selectCenteredValue();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onEscape();\n return;\n }\n\n const index = options.findIndex((option) => option.value === selected);\n let nextIndex = index;\n if (event.key === 'ArrowDown') nextIndex = Math.min(index + 1, options.length - 1);\n if (event.key === 'ArrowUp') nextIndex = Math.max(index - 1, 0);\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = options.length - 1;\n const nextOption = options[nextIndex];\n if (nextIndex !== index && nextOption !== undefined) {\n event.preventDefault();\n onSelect(nextOption.value);\n }\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n if (event.button !== 0) return;\n if (typeof event.currentTarget.setPointerCapture === 'function') {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n dragRef.current = {\n pointerId: event.pointerId,\n scrollTop: event.currentTarget.scrollTop,\n startY: event.clientY,\n };\n ignoreClickRef.current = false;\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (drag?.pointerId !== event.pointerId) return;\n const distance = event.clientY - drag.startY;\n if (Math.abs(distance) > 3) {\n ignoreClickRef.current = true;\n event.currentTarget.scrollTop = drag.scrollTop - distance;\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>) {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = undefined;\n if (typeof event.currentTarget.releasePointerCapture === 'function') {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n selectCenteredValue();\n }\n\n return (\n <div\n aria-label={ariaLabel}\n className=\"chayns-date-time-picker__wheel\"\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerUp={handlePointerUp}\n onScroll={handleScroll}\n ref={wheelRef}\n role=\"listbox\"\n tabIndex={0}\n >\n {Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) =>\n options.map((option, optionIndex) => (\n <button\n aria-selected={option.value === selected}\n className=\"chayns-date-time-picker__wheel-option\"\n data-wheel-index={cycle * options.length + optionIndex}\n key={`${cycle}-${option.value}`}\n onClick={(event) => {\n if (ignoreClickRef.current) {\n event.preventDefault();\n event.stopPropagation();\n ignoreClickRef.current = false;\n return;\n }\n onSelect(option.value);\n }}\n ref={\n cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : undefined\n }\n role=\"option\"\n type=\"button\"\n >\n {option.label}\n </button>\n )),\n )}\n </div>\n );\n}\n\nconst DateTimePicker = forwardRef<HTMLButtonElement, DateTimePickerProps>(function DateTimePicker(\n {\n className,\n disabled,\n id,\n label,\n locale,\n maxDate,\n minDate,\n minuteStep = 1,\n mode = 'time',\n onChange,\n onClick,\n onKeyDown,\n placeholder,\n value,\n wheelLabels,\n ...buttonProps\n },\n ref,\n) {\n if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) {\n throw new Error('DateTimePicker minuteStep must be one of: 1, 5, 15, 30.');\n }\n\n if (\n minDate !== undefined &&\n maxDate !== undefined &&\n dateAtMidnight(minDate) > dateAtMidnight(maxDate)\n ) {\n throw new Error('DateTimePicker requires minDate to be earlier than or equal to maxDate.');\n }\n\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const popupId = `${triggerId}-popup`;\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const [open, setOpen] = useState(false);\n const displayValue =\n value === null\n ? null\n : mode === 'date'\n ? clampDate(value, minDate, maxDate)\n : normalizeMinute(value, minuteStep);\n const activeValue = displayValue ?? new Date();\n const isTwelveHour =\n new Intl.DateTimeFormat(locale, { hour: 'numeric' }).resolvedOptions().hour12 === true;\n\n useEffect(() => {\n if (!open) return undefined;\n function closeOnOutsidePress(event: PointerEvent) {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) close();\n }\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => document.removeEventListener('pointerdown', closeOnOutsidePress);\n });\n\n const years = useMemo(() => {\n const today = new Date().getFullYear();\n const first = minDate?.getFullYear() ?? today - 100;\n const last = maxDate?.getFullYear() ?? today + 100;\n return Array.from({ length: last - first + 1 }, (_, index) => first + index);\n }, [maxDate, minDate]);\n\n function close() {\n setOpen(false);\n triggerRef.current?.focus();\n }\n\n function emit(nextValue: Date) {\n onChange(mode === 'date' ? clampDate(nextValue, minDate, maxDate) : nextValue);\n }\n\n function updateTime(part: 'hours' | 'minutes', nextValue: number) {\n const next = new Date(activeValue);\n if (part === 'hours') {\n const hour = isTwelveHour ? (nextValue % 12) + (next.getHours() >= 12 ? 12 : 0) : nextValue;\n next.setHours(hour);\n } else {\n next.setMinutes(nextValue);\n }\n emit(next);\n }\n\n function updatePeriod(period: number) {\n const next = new Date(activeValue);\n next.setHours((next.getHours() % 12) + period * 12);\n emit(next);\n }\n\n function updateDate(part: DatePart, nextValue: number) {\n const next = new Date(activeValue);\n const originalDay = next.getDate();\n next.setDate(1);\n if (part === 'fullYear') next.setFullYear(nextValue);\n if (part === 'month') next.setMonth(nextValue);\n if (part === 'date') next.setDate(nextValue);\n if (part !== 'date') {\n next.setDate(\n Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()),\n );\n }\n emit(next);\n }\n\n const formattedValue =\n displayValue === null\n ? placeholder\n : mode === 'time'\n ? `${new Intl.DateTimeFormat(locale, {\n hour: 'numeric',\n minute: '2-digit',\n }).format(displayValue)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`\n : new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }).format(displayValue);\n const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) =>\n isTwelveHour ? index + 1 : index,\n ).map((hour) => ({ label: String(hour).padStart(2, '0'), value: hour }));\n const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {\n const minute = index * minuteStep;\n return { label: String(minute).padStart(2, '0'), value: minute };\n });\n const months = Array.from({ length: 12 }, (_, month) => ({\n label: new Intl.DateTimeFormat(locale, { month: 'long' }).format(new Date(2026, month, 1)),\n value: month,\n })).filter((month) => {\n const first = new Date(activeValue.getFullYear(), month.value, 1);\n const last = new Date(activeValue.getFullYear(), month.value + 1, 0);\n return (\n (minDate === undefined || last >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || first <= dateAtMidnight(maxDate))\n );\n });\n const days = Array.from(\n { length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() },\n (_, index) => ({ label: String(index + 1).padStart(2, '0'), value: index + 1 }),\n ).filter((day) => {\n const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);\n return (\n (minDate === undefined || candidate >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || candidate <= dateAtMidnight(maxDate))\n );\n });\n const datePartOrder = new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n })\n .formatToParts(activeValue)\n .flatMap<DatePart>((part) => {\n if (part.type === 'day') return ['date'];\n if (part.type === 'month') return ['month'];\n if (part.type === 'year') return ['fullYear'];\n return [];\n });\n const yearOptions = years.map((year) => ({ label: String(year), value: year }));\n\n function dateOptions(part: DatePart) {\n if (part === 'date') return days;\n if (part === 'month') return months;\n return yearOptions;\n }\n\n function dateValue(part: DatePart) {\n if (part === 'date') return activeValue.getDate();\n if (part === 'month') return activeValue.getMonth();\n return activeValue.getFullYear();\n }\n const dayPeriods = [0, 1].map((period) => ({\n label:\n new Intl.DateTimeFormat(locale, { hour: 'numeric' })\n .formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13))\n .find((part) => part.type === 'dayPeriod')?.value ?? (period === 0 ? 'AM' : 'PM'),\n value: period,\n }));\n const resolvedClassName = [\n 'chayns-date-time-picker',\n `chayns-date-time-picker--${mode}`,\n open ? 'chayns-date-time-picker--open' : '',\n displayValue !== null ? 'chayns-date-time-picker--filled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={resolvedClassName} ref={rootRef}>\n <button\n {...buttonProps}\n aria-controls={open ? popupId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n className={['chayns-date-time-picker__trigger', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={triggerId}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((current) => !current);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key === 'Escape' && open && !event.defaultPrevented) {\n event.preventDefault();\n close();\n }\n }}\n ref={(element) => {\n triggerRef.current = element;\n if (typeof ref === 'function') ref(element);\n else if (ref !== null) ref.current = element;\n }}\n type=\"button\"\n >\n {formattedValue}\n </button>\n <label className=\"chayns-date-time-picker__label\" htmlFor={triggerId}>\n {label}\n </label>\n {open && !disabled ? (\n <div\n aria-label={label}\n className=\"chayns-date-time-picker__popup\"\n id={popupId}\n role=\"dialog\"\n >\n <div className=\"chayns-date-time-picker__selection\" />\n <div className=\"chayns-date-time-picker__wheels\">\n {mode === 'time' ? (\n <>\n <Wheel\n ariaLabel={wheelLabels.hour}\n onEscape={close}\n onSelect={(hour) => updateTime('hours', hour)}\n options={hours}\n selected={\n isTwelveHour ? activeValue.getHours() % 12 || 12 : activeValue.getHours()\n }\n />\n <Wheel\n ariaLabel={wheelLabels.minute}\n onEscape={close}\n onSelect={(minute) => updateTime('minutes', minute)}\n options={minutes}\n selected={activeValue.getMinutes()}\n />\n {isTwelveHour ? (\n <Wheel\n ariaLabel={wheelLabels.dayPeriod}\n onEscape={close}\n onSelect={updatePeriod}\n options={dayPeriods}\n selected={activeValue.getHours() >= 12 ? 1 : 0}\n />\n ) : null}\n </>\n ) : (\n datePartOrder.map((part) => (\n <Wheel\n ariaLabel={\n part === 'date'\n ? wheelLabels.day\n : part === 'month'\n ? wheelLabels.month\n : wheelLabels.year\n }\n key={part}\n onEscape={close}\n onSelect={(nextValue) => updateDate(part, nextValue)}\n options={dateOptions(part)}\n selected={dateValue(part)}\n />\n ))\n )}\n </div>\n </div>\n ) : null}\n </div>\n );\n});\n\nexport default DateTimePicker;\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DateTimePicker.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.tsx"],"sourcesContent":["import { forwardRef, useEffect, useId, useMemo, useRef, useState } from 'react';\nimport { composeNativeRefs } from '../../utils/native-ref.js';\nimport { dateAtMidnight } from './date-time-picker-utils.js';\nimport { useDateTimePickerValue } from './hooks/useDateTimePickerValue.js';\nimport Wheel from './wheel/Wheel.js';\nimport PickerSizer from './sizer/PickerSizer.js';\nimport { DATE_TIME_PICKER_MINUTE_STEPS, type DateTimePickerProps } from './DateTimePicker.types.js';\n\nconst DateTimePicker = forwardRef<HTMLButtonElement, DateTimePickerProps>(function DateTimePicker(\n {\n className,\n disabled,\n id,\n label,\n locale,\n maxDate,\n minDate,\n minuteStep = 1,\n mode = 'time',\n onChange,\n onClick,\n onKeyDown,\n placeholder,\n value,\n wheelLabels,\n ...buttonProps\n },\n ref,\n) {\n if (!DATE_TIME_PICKER_MINUTE_STEPS.includes(minuteStep)) {\n throw new Error('DateTimePicker minuteStep must be one of: 1, 5, 15, 30.');\n }\n\n if (\n minDate !== undefined &&\n maxDate !== undefined &&\n dateAtMidnight(minDate) > dateAtMidnight(maxDate)\n ) {\n throw new Error('DateTimePicker requires minDate to be earlier than or equal to maxDate.');\n }\n\n const generatedId = useId();\n const triggerId = id ?? generatedId;\n const popupId = `${triggerId}-popup`;\n const rootRef = useRef<HTMLDivElement>(null);\n const triggerRef = useRef<HTMLButtonElement>(null);\n const setTriggerElement = useMemo(() => composeNativeRefs(triggerRef, ref), [ref]);\n const [open, setOpen] = useState(false);\n const {\n displayValue,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n sizingValues,\n } = useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n });\n function close() {\n setOpen(false);\n triggerRef.current?.focus();\n }\n useEffect(() => {\n if (!open) return undefined;\n function closeOnOutsidePress(event: PointerEvent) {\n if (event.target instanceof Node && !rootRef.current?.contains(event.target)) close();\n }\n document.addEventListener('pointerdown', closeOnOutsidePress);\n return () => document.removeEventListener('pointerdown', closeOnOutsidePress);\n });\n const resolvedClassName = [\n 'chayns-date-time-picker',\n `chayns-date-time-picker--${mode}`,\n open ? 'chayns-date-time-picker--open' : '',\n displayValue !== null ? 'chayns-date-time-picker--filled' : '',\n ]\n .filter(Boolean)\n .join(' ');\n\n return (\n <div className={resolvedClassName} ref={rootRef}>\n <PickerSizer values={sizingValues} placeholder={displayValue === null ? placeholder : null} />\n <button\n {...buttonProps}\n aria-controls={open ? popupId : undefined}\n aria-expanded={open}\n aria-haspopup=\"dialog\"\n aria-label={label}\n className={['chayns-date-time-picker__trigger', className].filter(Boolean).join(' ')}\n disabled={disabled}\n id={triggerId}\n onClick={(event) => {\n onClick?.(event);\n if (!event.defaultPrevented) setOpen((current) => !current);\n }}\n onKeyDown={(event) => {\n onKeyDown?.(event);\n if (event.key === 'Escape' && open && !event.defaultPrevented) {\n event.preventDefault();\n close();\n }\n }}\n ref={setTriggerElement}\n type=\"button\"\n >\n {formattedValue}\n </button>\n {displayValue === null ? (\n <label className=\"chayns-date-time-picker__label\" htmlFor={triggerId}>\n {label}\n </label>\n ) : null}\n {open && !disabled ? (\n <div\n aria-label={label}\n className=\"chayns-date-time-picker__popup\"\n id={popupId}\n role=\"dialog\"\n >\n <div className=\"chayns-date-time-picker__selection\" />\n <div className=\"chayns-date-time-picker__wheels\">\n {mode === 'time' ? (\n <>\n <Wheel\n ariaLabel={wheelLabels.hour}\n onEscape={close}\n onSelect={(hour) => updateTime('hours', hour)}\n options={hours}\n selected={\n isTwelveHour ? activeValue.getHours() % 12 || 12 : activeValue.getHours()\n }\n />\n <Wheel\n ariaLabel={wheelLabels.minute}\n onEscape={close}\n onSelect={(minute) => updateTime('minutes', minute)}\n options={minutes}\n selected={activeValue.getMinutes()}\n />\n {isTwelveHour ? (\n <Wheel\n ariaLabel={wheelLabels.dayPeriod}\n onEscape={close}\n onSelect={updatePeriod}\n options={dayPeriods}\n selected={activeValue.getHours() >= 12 ? 1 : 0}\n />\n ) : null}\n </>\n ) : (\n datePartOrder.map((part) => (\n <Wheel\n ariaLabel={dateLabel(part)}\n key={part}\n onEscape={close}\n onSelect={(nextValue) => updateDate(part, nextValue)}\n options={dateOptions(part)}\n selected={dateValue(part)}\n />\n ))\n )}\n </div>\n </div>\n ) : null}\n </div>\n );\n});\n\nDateTimePicker.displayName = 'DateTimePicker';\n\nexport default DateTimePicker;\n"],"mappings":"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"}
|
|
@@ -1,4 +1,16 @@
|
|
|
1
1
|
import type { ComponentPropsWithRef } from 'react';
|
|
2
|
+
/** Named configuration values; existing literal props and value lists remain supported. */
|
|
3
|
+
export declare enum DateTimePickerMinuteSteps {
|
|
4
|
+
One = 1,
|
|
5
|
+
Five = 5,
|
|
6
|
+
Fifteen = 15,
|
|
7
|
+
Thirty = 30
|
|
8
|
+
}
|
|
9
|
+
/** Named configuration values; existing literal props and value lists remain supported. */
|
|
10
|
+
export declare enum DateTimePickerModes {
|
|
11
|
+
Date = "date",
|
|
12
|
+
Time = "time"
|
|
13
|
+
}
|
|
2
14
|
export declare const DATE_TIME_PICKER_MODES: readonly ["date", "time"];
|
|
3
15
|
export declare const DATE_TIME_PICKER_MINUTE_STEPS: readonly [1, 5, 15, 30];
|
|
4
16
|
export type DateTimePickerMode = (typeof DATE_TIME_PICKER_MODES)[number];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimePicker.types.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,eAAO,MAAM,sBAAsB,2BAA4B,CAAC;AAChE,eAAO,MAAM,6BAA6B,yBAA0B,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AACzE,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtF,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,qBAAqB,CAAC,QAAQ,CAAC,EAC7B,eAAe,GACf,eAAe,GACf,eAAe,GACf,YAAY,GACZ,iBAAiB,GACjB,UAAU,GACV,UAAU,GACV,MAAM,GACN,OAAO,CACV;IACC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,WAAW,EAAE,yBAAyB,CAAC;CACxC"}
|
|
1
|
+
{"version":3,"file":"DateTimePicker.types.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/DateTimePicker.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,OAAO,CAAC;AAEnD,2FAA2F;AAC3F,oBAAY,yBAAyB;IACnC,GAAG,IAAI;IACP,IAAI,IAAI;IACR,OAAO,KAAK;IACZ,MAAM,KAAK;CACZ;AAED,2FAA2F;AAC3F,oBAAY,mBAAmB;IAC7B,IAAI,SAAS;IACb,IAAI,SAAS;CACd;AAED,eAAO,MAAM,sBAAsB,2BAA4B,CAAC;AAChE,eAAO,MAAM,6BAA6B,yBAA0B,CAAC;AAErE,MAAM,MAAM,kBAAkB,GAAG,CAAC,OAAO,sBAAsB,CAAC,CAAC,MAAM,CAAC,CAAC;AACzE,MAAM,MAAM,wBAAwB,GAAG,CAAC,OAAO,6BAA6B,CAAC,CAAC,MAAM,CAAC,CAAC;AAEtF,MAAM,WAAW,yBAAyB;IACxC,GAAG,EAAE,MAAM,CAAC;IACZ,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,mBAAoB,SAAQ,IAAI,CAC/C,qBAAqB,CAAC,QAAQ,CAAC,EAC7B,eAAe,GACf,eAAe,GACf,eAAe,GACf,YAAY,GACZ,iBAAiB,GACjB,UAAU,GACV,UAAU,GACV,MAAM,GACN,OAAO,CACV;IACC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,OAAO,CAAC,EAAE,IAAI,CAAC;IACf,UAAU,CAAC,EAAE,wBAAwB,CAAC;IACtC,IAAI,CAAC,EAAE,kBAAkB,CAAC;IAC1B,QAAQ,EAAE,CAAC,KAAK,EAAE,IAAI,KAAK,IAAI,CAAC;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE,IAAI,GAAG,IAAI,CAAC;IACnB,WAAW,EAAE,yBAAyB,CAAC;CACxC"}
|
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
//#region src/components/date-time-picker/DateTimePicker.types.ts
|
|
2
|
+
/** Named configuration values; existing literal props and value lists remain supported. */
|
|
3
|
+
var DateTimePickerMinuteSteps = /* @__PURE__ */ function(DateTimePickerMinuteSteps) {
|
|
4
|
+
DateTimePickerMinuteSteps[DateTimePickerMinuteSteps["One"] = 1] = "One";
|
|
5
|
+
DateTimePickerMinuteSteps[DateTimePickerMinuteSteps["Five"] = 5] = "Five";
|
|
6
|
+
DateTimePickerMinuteSteps[DateTimePickerMinuteSteps["Fifteen"] = 15] = "Fifteen";
|
|
7
|
+
DateTimePickerMinuteSteps[DateTimePickerMinuteSteps["Thirty"] = 30] = "Thirty";
|
|
8
|
+
return DateTimePickerMinuteSteps;
|
|
9
|
+
}({});
|
|
10
|
+
/** Named configuration values; existing literal props and value lists remain supported. */
|
|
11
|
+
var DateTimePickerModes = /* @__PURE__ */ function(DateTimePickerModes) {
|
|
12
|
+
DateTimePickerModes["Date"] = "date";
|
|
13
|
+
DateTimePickerModes["Time"] = "time";
|
|
14
|
+
return DateTimePickerModes;
|
|
15
|
+
}({});
|
|
2
16
|
var DATE_TIME_PICKER_MODES = ["date", "time"];
|
|
3
17
|
var DATE_TIME_PICKER_MINUTE_STEPS = [
|
|
4
18
|
1,
|
|
@@ -7,6 +21,6 @@ var DATE_TIME_PICKER_MINUTE_STEPS = [
|
|
|
7
21
|
30
|
|
8
22
|
];
|
|
9
23
|
//#endregion
|
|
10
|
-
export { DATE_TIME_PICKER_MINUTE_STEPS, DATE_TIME_PICKER_MODES };
|
|
24
|
+
export { DATE_TIME_PICKER_MINUTE_STEPS, DATE_TIME_PICKER_MODES, DateTimePickerMinuteSteps, DateTimePickerModes };
|
|
11
25
|
|
|
12
26
|
//# sourceMappingURL=DateTimePicker.types.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DateTimePicker.types.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.types.ts"],"sourcesContent":["import type { ComponentPropsWithRef } from 'react';\n\nexport const DATE_TIME_PICKER_MODES = ['date', 'time'] as const;\nexport const DATE_TIME_PICKER_MINUTE_STEPS = [1, 5, 15, 30] as const;\n\nexport type DateTimePickerMode = (typeof DATE_TIME_PICKER_MODES)[number];\nexport type DateTimePickerMinuteStep = (typeof DATE_TIME_PICKER_MINUTE_STEPS)[number];\n\nexport interface DateTimePickerWheelLabels {\n day: string;\n dayPeriod: string;\n hour: string;\n minute: string;\n month: string;\n year: string;\n}\n\nexport interface DateTimePickerProps extends Omit<\n ComponentPropsWithRef<'button'>,\n | 'aria-controls'\n | 'aria-expanded'\n | 'aria-haspopup'\n | 'aria-label'\n | 'aria-labelledby'\n | 'children'\n | 'onChange'\n | 'type'\n | 'value'\n> {\n label: string;\n locale: string;\n minDate?: Date;\n maxDate?: Date;\n minuteStep?: DateTimePickerMinuteStep;\n mode?: DateTimePickerMode;\n onChange: (value: Date) => void;\n placeholder: string;\n value: Date | null;\n wheelLabels: DateTimePickerWheelLabels;\n}\n"],"mappings":";AAEA,IAAa,yBAAyB,CAAC,QAAQ,MAAM;AACrD,IAAa,gCAAgC;CAAC;CAAG;CAAG;CAAI;AAAE"}
|
|
1
|
+
{"version":3,"file":"DateTimePicker.types.js","names":[],"sources":["../../../src/components/date-time-picker/DateTimePicker.types.ts"],"sourcesContent":["import type { ComponentPropsWithRef } from 'react';\n\n/** Named configuration values; existing literal props and value lists remain supported. */\nexport enum DateTimePickerMinuteSteps {\n One = 1,\n Five = 5,\n Fifteen = 15,\n Thirty = 30,\n}\n\n/** Named configuration values; existing literal props and value lists remain supported. */\nexport enum DateTimePickerModes {\n Date = 'date',\n Time = 'time',\n}\n\nexport const DATE_TIME_PICKER_MODES = ['date', 'time'] as const;\nexport const DATE_TIME_PICKER_MINUTE_STEPS = [1, 5, 15, 30] as const;\n\nexport type DateTimePickerMode = (typeof DATE_TIME_PICKER_MODES)[number];\nexport type DateTimePickerMinuteStep = (typeof DATE_TIME_PICKER_MINUTE_STEPS)[number];\n\nexport interface DateTimePickerWheelLabels {\n day: string;\n dayPeriod: string;\n hour: string;\n minute: string;\n month: string;\n year: string;\n}\n\nexport interface DateTimePickerProps extends Omit<\n ComponentPropsWithRef<'button'>,\n | 'aria-controls'\n | 'aria-expanded'\n | 'aria-haspopup'\n | 'aria-label'\n | 'aria-labelledby'\n | 'children'\n | 'onChange'\n | 'type'\n | 'value'\n> {\n label: string;\n locale: string;\n minDate?: Date;\n maxDate?: Date;\n minuteStep?: DateTimePickerMinuteStep;\n mode?: DateTimePickerMode;\n onChange: (value: Date) => void;\n placeholder: string;\n value: Date | null;\n wheelLabels: DateTimePickerWheelLabels;\n}\n"],"mappings":";;AAGA,IAAY,4BAAL,yBAAA,2BAAA;CACL,0BAAA,0BAAA,SAAA,KAAA;CACA,0BAAA,0BAAA,UAAA,KAAA;CACA,0BAAA,0BAAA,aAAA,MAAA;CACA,0BAAA,0BAAA,YAAA,MAAA;;AACF,EAAA,CAAA,CAAA;;AAGA,IAAY,sBAAL,yBAAA,qBAAA;CACL,oBAAA,UAAA;CACA,oBAAA,UAAA;;AACF,EAAA,CAAA,CAAA;AAEA,IAAa,yBAAyB,CAAC,QAAQ,MAAM;AACrD,IAAa,gCAAgC;CAAC;CAAG;CAAG;CAAI;AAAE"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare function dateAtMidnight(value: Date): Date;
|
|
2
|
+
export declare function clampDate(value: Date, minDate?: Date, maxDate?: Date): Date;
|
|
3
|
+
export declare function normalizeMinute(value: Date, minuteStep: number): Date;
|
|
4
|
+
//# sourceMappingURL=date-time-picker-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-time-picker-utils.d.ts","sourceRoot":"","sources":["../../../src/components/date-time-picker/date-time-picker-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,cAAc,CAAC,KAAK,EAAE,IAAI,QAEzC;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,EAAE,IAAI,QAKpE;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,QAI9D"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
//#region src/components/date-time-picker/date-time-picker-utils.ts
|
|
2
|
+
function dateAtMidnight(value) {
|
|
3
|
+
return new Date(value.getFullYear(), value.getMonth(), value.getDate());
|
|
4
|
+
}
|
|
5
|
+
function clampDate(value, minDate, maxDate) {
|
|
6
|
+
const date = dateAtMidnight(value);
|
|
7
|
+
if (minDate !== void 0 && date < dateAtMidnight(minDate)) return new Date(minDate);
|
|
8
|
+
if (maxDate !== void 0 && date > dateAtMidnight(maxDate)) return new Date(maxDate);
|
|
9
|
+
return value;
|
|
10
|
+
}
|
|
11
|
+
function normalizeMinute(value, minuteStep) {
|
|
12
|
+
const normalized = new Date(value);
|
|
13
|
+
normalized.setMinutes(Math.floor(normalized.getMinutes() / minuteStep) * minuteStep);
|
|
14
|
+
return normalized;
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { clampDate, dateAtMidnight, normalizeMinute };
|
|
18
|
+
|
|
19
|
+
//# sourceMappingURL=date-time-picker-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"date-time-picker-utils.js","names":[],"sources":["../../../src/components/date-time-picker/date-time-picker-utils.ts"],"sourcesContent":["export function dateAtMidnight(value: Date) {\n return new Date(value.getFullYear(), value.getMonth(), value.getDate());\n}\n\nexport function clampDate(value: Date, minDate?: Date, maxDate?: Date) {\n const date = dateAtMidnight(value);\n if (minDate !== undefined && date < dateAtMidnight(minDate)) return new Date(minDate);\n if (maxDate !== undefined && date > dateAtMidnight(maxDate)) return new Date(maxDate);\n return value;\n}\n\nexport function normalizeMinute(value: Date, minuteStep: number) {\n const normalized = new Date(value);\n normalized.setMinutes(Math.floor(normalized.getMinutes() / minuteStep) * minuteStep);\n return normalized;\n}\n"],"mappings":";AAAA,SAAgB,eAAe,OAAa;CAC1C,OAAO,IAAI,KAAK,MAAM,YAAY,GAAG,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC;AACxE;AAEA,SAAgB,UAAU,OAAa,SAAgB,SAAgB;CACrE,MAAM,OAAO,eAAe,KAAK;CACjC,IAAI,YAAY,KAAA,KAAa,OAAO,eAAe,OAAO,GAAG,OAAO,IAAI,KAAK,OAAO;CACpF,IAAI,YAAY,KAAA,KAAa,OAAO,eAAe,OAAO,GAAG,OAAO,IAAI,KAAK,OAAO;CACpF,OAAO;AACT;AAEA,SAAgB,gBAAgB,OAAa,YAAoB;CAC/D,MAAM,aAAa,IAAI,KAAK,KAAK;CACjC,WAAW,WAAW,KAAK,MAAM,WAAW,WAAW,IAAI,UAAU,IAAI,UAAU;CACnF,OAAO;AACT"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { DateTimePickerProps } from '../DateTimePicker.types.js';
|
|
2
|
+
type DatePart = 'date' | 'fullYear' | 'month';
|
|
3
|
+
type ValueProps = Pick<DateTimePickerProps, 'value' | 'locale' | 'onChange' | 'placeholder' | 'wheelLabels'> & Required<Pick<DateTimePickerProps, 'minuteStep' | 'mode'>> & {
|
|
4
|
+
minDate: Date | undefined;
|
|
5
|
+
maxDate: Date | undefined;
|
|
6
|
+
};
|
|
7
|
+
export declare function useDateTimePickerValue({ value, locale, maxDate, minDate, onChange, placeholder, wheelLabels, minuteStep, mode, }: ValueProps): {
|
|
8
|
+
displayValue: Date | null;
|
|
9
|
+
sizingValues: string[];
|
|
10
|
+
formattedValue: string;
|
|
11
|
+
activeValue: Date;
|
|
12
|
+
isTwelveHour: boolean;
|
|
13
|
+
hours: {
|
|
14
|
+
label: string;
|
|
15
|
+
value: number;
|
|
16
|
+
}[];
|
|
17
|
+
minutes: {
|
|
18
|
+
label: string;
|
|
19
|
+
value: number;
|
|
20
|
+
}[];
|
|
21
|
+
dayPeriods: {
|
|
22
|
+
label: string;
|
|
23
|
+
value: number;
|
|
24
|
+
}[];
|
|
25
|
+
datePartOrder: DatePart[];
|
|
26
|
+
dateOptions: (part: DatePart) => {
|
|
27
|
+
label: string;
|
|
28
|
+
value: number;
|
|
29
|
+
}[];
|
|
30
|
+
dateValue: (part: DatePart) => number;
|
|
31
|
+
dateLabel: (part: DatePart) => string;
|
|
32
|
+
updateDate: (part: DatePart, nextValue: number) => void;
|
|
33
|
+
updateTime: (part: "hours" | "minutes", nextValue: number) => void;
|
|
34
|
+
updatePeriod: (period: number) => void;
|
|
35
|
+
};
|
|
36
|
+
export {};
|
|
37
|
+
//# sourceMappingURL=useDateTimePickerValue.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDateTimePickerValue.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AACtE,KAAK,QAAQ,GAAG,MAAM,GAAG,UAAU,GAAG,OAAO,CAAC;AAC9C,KAAK,UAAU,GAAG,IAAI,CACpB,mBAAmB,EACnB,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,aAAa,GAAG,aAAa,CAChE,GACC,QAAQ,CAAC,IAAI,CAAC,mBAAmB,EAAE,YAAY,GAAG,MAAM,CAAC,CAAC,GAAG;IAC3D,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;IAC1B,OAAO,EAAE,IAAI,GAAG,SAAS,CAAC;CAC3B,CAAC;AAEJ,wBAAgB,sBAAsB,CAAC,EACrC,KAAK,EACL,MAAM,EACN,OAAO,EACP,OAAO,EACP,QAAQ,EACR,WAAW,EACX,WAAW,EACX,UAAU,EACV,IAAI,GACL,EAAE,UAAU;;;;;;;;;;;;;;;;;;;wBA6HgB,QAAQ;;;;sBAMV,QAAQ;sBAYR,QAAQ;uBAvFP,QAAQ,aAAa,MAAM;uBAjB3B,OAAO,GAAG,SAAS,aAAa,MAAM;2BAWlC,MAAM;EAmHrC"}
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { clampDate, dateAtMidnight, normalizeMinute } from "../date-time-picker-utils.js";
|
|
2
|
+
import { useMemo } from "react";
|
|
3
|
+
//#region src/components/date-time-picker/hooks/useDateTimePickerValue.ts
|
|
4
|
+
function useDateTimePickerValue({ value, locale, maxDate, minDate, onChange, placeholder, wheelLabels, minuteStep, mode }) {
|
|
5
|
+
const { hourFormatter, monthFormatter, timeFormatter, dateFormatter, dateOrderFormatter } = useMemo(() => ({
|
|
6
|
+
hourFormatter: new Intl.DateTimeFormat(locale, { hour: "numeric" }),
|
|
7
|
+
monthFormatter: new Intl.DateTimeFormat(locale, { month: "long" }),
|
|
8
|
+
timeFormatter: new Intl.DateTimeFormat(locale, {
|
|
9
|
+
hour: "numeric",
|
|
10
|
+
minute: "2-digit"
|
|
11
|
+
}),
|
|
12
|
+
dateFormatter: new Intl.DateTimeFormat(locale, {
|
|
13
|
+
day: "numeric",
|
|
14
|
+
month: "long",
|
|
15
|
+
year: "numeric"
|
|
16
|
+
}),
|
|
17
|
+
dateOrderFormatter: new Intl.DateTimeFormat(locale, {
|
|
18
|
+
day: "numeric",
|
|
19
|
+
month: "numeric",
|
|
20
|
+
year: "numeric"
|
|
21
|
+
})
|
|
22
|
+
}), [locale]);
|
|
23
|
+
let displayValue = value;
|
|
24
|
+
if (value !== null) displayValue = mode === "date" ? clampDate(value, minDate, maxDate) : normalizeMinute(value, minuteStep);
|
|
25
|
+
const activeValue = displayValue ?? /* @__PURE__ */ new Date();
|
|
26
|
+
const isTwelveHour = hourFormatter.resolvedOptions().hour12 === true;
|
|
27
|
+
const years = useMemo(() => {
|
|
28
|
+
const today = (/* @__PURE__ */ new Date()).getFullYear();
|
|
29
|
+
const first = minDate?.getFullYear() ?? today - 100;
|
|
30
|
+
const last = maxDate?.getFullYear() ?? today + 100;
|
|
31
|
+
return Array.from({ length: last - first + 1 }, (_, index) => first + index);
|
|
32
|
+
}, [maxDate, minDate]);
|
|
33
|
+
function emit(nextValue) {
|
|
34
|
+
onChange(mode === "date" ? clampDate(nextValue, minDate, maxDate) : nextValue);
|
|
35
|
+
}
|
|
36
|
+
function updateTime(part, nextValue) {
|
|
37
|
+
const next = new Date(activeValue);
|
|
38
|
+
if (part === "hours") {
|
|
39
|
+
const hour = isTwelveHour ? nextValue % 12 + (next.getHours() >= 12 ? 12 : 0) : nextValue;
|
|
40
|
+
next.setHours(hour);
|
|
41
|
+
} else next.setMinutes(nextValue);
|
|
42
|
+
emit(next);
|
|
43
|
+
}
|
|
44
|
+
function updatePeriod(period) {
|
|
45
|
+
const next = new Date(activeValue);
|
|
46
|
+
next.setHours(next.getHours() % 12 + period * 12);
|
|
47
|
+
emit(next);
|
|
48
|
+
}
|
|
49
|
+
function updateDate(part, nextValue) {
|
|
50
|
+
const next = new Date(activeValue);
|
|
51
|
+
const originalDay = next.getDate();
|
|
52
|
+
next.setDate(1);
|
|
53
|
+
if (part === "fullYear") next.setFullYear(nextValue);
|
|
54
|
+
if (part === "month") next.setMonth(nextValue);
|
|
55
|
+
if (part === "date") next.setDate(nextValue);
|
|
56
|
+
if (part !== "date") next.setDate(Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()));
|
|
57
|
+
emit(next);
|
|
58
|
+
}
|
|
59
|
+
let formattedValue = placeholder;
|
|
60
|
+
if (displayValue !== null) {
|
|
61
|
+
if (mode === "time") formattedValue = `${timeFormatter.format(displayValue)}${locale.toLowerCase().startsWith("de") ? " Uhr" : ""}`;
|
|
62
|
+
else formattedValue = dateFormatter.format(displayValue);
|
|
63
|
+
}
|
|
64
|
+
const timeSizingValues = useMemo(() => {
|
|
65
|
+
if (mode !== "time") return [];
|
|
66
|
+
return Array.from({ length: 24 * (60 / minuteStep) }, (_, index) => {
|
|
67
|
+
const candidate = new Date(2026, 0, 1);
|
|
68
|
+
candidate.setHours(Math.floor(index / (60 / minuteStep)));
|
|
69
|
+
candidate.setMinutes(index % (60 / minuteStep) * minuteStep);
|
|
70
|
+
return `${timeFormatter.format(candidate)}${locale.toLowerCase().startsWith("de") ? " Uhr" : ""}`;
|
|
71
|
+
});
|
|
72
|
+
}, [
|
|
73
|
+
locale,
|
|
74
|
+
minuteStep,
|
|
75
|
+
mode,
|
|
76
|
+
timeFormatter
|
|
77
|
+
]);
|
|
78
|
+
const dateSizingValues = useMemo(() => [formattedValue], [formattedValue]);
|
|
79
|
+
const sizingValues = mode === "time" ? timeSizingValues : dateSizingValues;
|
|
80
|
+
const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) => isTwelveHour ? index + 1 : index).map((hour) => ({
|
|
81
|
+
label: String(hour).padStart(2, "0"),
|
|
82
|
+
value: hour
|
|
83
|
+
}));
|
|
84
|
+
const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {
|
|
85
|
+
const minute = index * minuteStep;
|
|
86
|
+
return {
|
|
87
|
+
label: String(minute).padStart(2, "0"),
|
|
88
|
+
value: minute
|
|
89
|
+
};
|
|
90
|
+
});
|
|
91
|
+
const months = Array.from({ length: 12 }, (_, month) => ({
|
|
92
|
+
label: monthFormatter.format(new Date(2026, month, 1)),
|
|
93
|
+
value: month
|
|
94
|
+
})).filter((month) => {
|
|
95
|
+
const first = new Date(activeValue.getFullYear(), month.value, 1);
|
|
96
|
+
const last = new Date(activeValue.getFullYear(), month.value + 1, 0);
|
|
97
|
+
return (minDate === void 0 || last >= dateAtMidnight(minDate)) && (maxDate === void 0 || first <= dateAtMidnight(maxDate));
|
|
98
|
+
});
|
|
99
|
+
const days = Array.from({ length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() }, (_, index) => ({
|
|
100
|
+
label: String(index + 1).padStart(2, "0"),
|
|
101
|
+
value: index + 1
|
|
102
|
+
})).filter((day) => {
|
|
103
|
+
const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);
|
|
104
|
+
return (minDate === void 0 || candidate >= dateAtMidnight(minDate)) && (maxDate === void 0 || candidate <= dateAtMidnight(maxDate));
|
|
105
|
+
});
|
|
106
|
+
const datePartOrder = dateOrderFormatter.formatToParts(activeValue).flatMap((part) => {
|
|
107
|
+
if (part.type === "day") return ["date"];
|
|
108
|
+
if (part.type === "month") return ["month"];
|
|
109
|
+
if (part.type === "year") return ["fullYear"];
|
|
110
|
+
return [];
|
|
111
|
+
});
|
|
112
|
+
const yearOptions = years.map((year) => ({
|
|
113
|
+
label: String(year),
|
|
114
|
+
value: year
|
|
115
|
+
}));
|
|
116
|
+
function dateOptions(part) {
|
|
117
|
+
if (part === "date") return days;
|
|
118
|
+
if (part === "month") return months;
|
|
119
|
+
return yearOptions;
|
|
120
|
+
}
|
|
121
|
+
function dateValue(part) {
|
|
122
|
+
if (part === "date") return activeValue.getDate();
|
|
123
|
+
if (part === "month") return activeValue.getMonth();
|
|
124
|
+
return activeValue.getFullYear();
|
|
125
|
+
}
|
|
126
|
+
const dayPeriods = [0, 1].map((period) => ({
|
|
127
|
+
label: hourFormatter.formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13)).find((part) => part.type === "dayPeriod")?.value ?? (period === 0 ? "AM" : "PM"),
|
|
128
|
+
value: period
|
|
129
|
+
}));
|
|
130
|
+
function dateLabel(part) {
|
|
131
|
+
if (part === "date") return wheelLabels.day;
|
|
132
|
+
if (part === "month") return wheelLabels.month;
|
|
133
|
+
return wheelLabels.year;
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
displayValue,
|
|
137
|
+
sizingValues,
|
|
138
|
+
formattedValue,
|
|
139
|
+
activeValue,
|
|
140
|
+
isTwelveHour,
|
|
141
|
+
hours,
|
|
142
|
+
minutes,
|
|
143
|
+
dayPeriods,
|
|
144
|
+
datePartOrder,
|
|
145
|
+
dateOptions,
|
|
146
|
+
dateValue,
|
|
147
|
+
dateLabel,
|
|
148
|
+
updateDate,
|
|
149
|
+
updateTime,
|
|
150
|
+
updatePeriod
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { useDateTimePickerValue };
|
|
155
|
+
|
|
156
|
+
//# sourceMappingURL=useDateTimePickerValue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDateTimePickerValue.js","names":[],"sources":["../../../../src/components/date-time-picker/hooks/useDateTimePickerValue.ts"],"sourcesContent":["import { useMemo } from 'react';\nimport { clampDate, dateAtMidnight, normalizeMinute } from '../date-time-picker-utils.js';\nimport type { DateTimePickerProps } from '../DateTimePicker.types.js';\ntype DatePart = 'date' | 'fullYear' | 'month';\ntype ValueProps = Pick<\n DateTimePickerProps,\n 'value' | 'locale' | 'onChange' | 'placeholder' | 'wheelLabels'\n> &\n Required<Pick<DateTimePickerProps, 'minuteStep' | 'mode'>> & {\n minDate: Date | undefined;\n maxDate: Date | undefined;\n };\n\nexport function useDateTimePickerValue({\n value,\n locale,\n maxDate,\n minDate,\n onChange,\n placeholder,\n wheelLabels,\n minuteStep,\n mode,\n}: ValueProps) {\n const { hourFormatter, monthFormatter, timeFormatter, dateFormatter, dateOrderFormatter } =\n useMemo(\n () => ({\n hourFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric' }),\n monthFormatter: new Intl.DateTimeFormat(locale, { month: 'long' }),\n timeFormatter: new Intl.DateTimeFormat(locale, { hour: 'numeric', minute: '2-digit' }),\n dateFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'long',\n year: 'numeric',\n }),\n dateOrderFormatter: new Intl.DateTimeFormat(locale, {\n day: 'numeric',\n month: 'numeric',\n year: 'numeric',\n }),\n }),\n [locale],\n );\n let displayValue = value;\n if (value !== null) {\n displayValue =\n mode === 'date' ? clampDate(value, minDate, maxDate) : normalizeMinute(value, minuteStep);\n }\n const activeValue = displayValue ?? new Date();\n const isTwelveHour = hourFormatter.resolvedOptions().hour12 === true;\n\n const years = useMemo(() => {\n const today = new Date().getFullYear();\n const first = minDate?.getFullYear() ?? today - 100;\n const last = maxDate?.getFullYear() ?? today + 100;\n return Array.from({ length: last - first + 1 }, (_, index) => first + index);\n }, [maxDate, minDate]);\n\n function emit(nextValue: Date) {\n onChange(mode === 'date' ? clampDate(nextValue, minDate, maxDate) : nextValue);\n }\n\n function updateTime(part: 'hours' | 'minutes', nextValue: number) {\n const next = new Date(activeValue);\n if (part === 'hours') {\n const hour = isTwelveHour ? (nextValue % 12) + (next.getHours() >= 12 ? 12 : 0) : nextValue;\n next.setHours(hour);\n } else {\n next.setMinutes(nextValue);\n }\n emit(next);\n }\n\n function updatePeriod(period: number) {\n const next = new Date(activeValue);\n next.setHours((next.getHours() % 12) + period * 12);\n emit(next);\n }\n\n function updateDate(part: DatePart, nextValue: number) {\n const next = new Date(activeValue);\n const originalDay = next.getDate();\n next.setDate(1);\n if (part === 'fullYear') next.setFullYear(nextValue);\n if (part === 'month') next.setMonth(nextValue);\n if (part === 'date') next.setDate(nextValue);\n if (part !== 'date') {\n next.setDate(\n Math.min(originalDay, new Date(next.getFullYear(), next.getMonth() + 1, 0).getDate()),\n );\n }\n emit(next);\n }\n\n let formattedValue = placeholder;\n if (displayValue !== null) {\n if (mode === 'time')\n formattedValue = `${timeFormatter.format(displayValue)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n else formattedValue = dateFormatter.format(displayValue);\n }\n const timeSizingValues = useMemo(() => {\n if (mode !== 'time') return [];\n return Array.from({ length: 24 * (60 / minuteStep) }, (_, index) => {\n const candidate = new Date(2026, 0, 1);\n candidate.setHours(Math.floor(index / (60 / minuteStep)));\n candidate.setMinutes((index % (60 / minuteStep)) * minuteStep);\n return `${timeFormatter.format(candidate)}${locale.toLowerCase().startsWith('de') ? ' Uhr' : ''}`;\n });\n }, [locale, minuteStep, mode, timeFormatter]);\n const dateSizingValues = useMemo(() => [formattedValue], [formattedValue]);\n const sizingValues = mode === 'time' ? timeSizingValues : dateSizingValues;\n\n const hours = Array.from({ length: isTwelveHour ? 12 : 24 }, (_, index) =>\n isTwelveHour ? index + 1 : index,\n ).map((hour) => ({ label: String(hour).padStart(2, '0'), value: hour }));\n const minutes = Array.from({ length: 60 / minuteStep }, (_, index) => {\n const minute = index * minuteStep;\n return { label: String(minute).padStart(2, '0'), value: minute };\n });\n const months = Array.from({ length: 12 }, (_, month) => ({\n label: monthFormatter.format(new Date(2026, month, 1)),\n value: month,\n })).filter((month) => {\n const first = new Date(activeValue.getFullYear(), month.value, 1);\n const last = new Date(activeValue.getFullYear(), month.value + 1, 0);\n return (\n (minDate === undefined || last >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || first <= dateAtMidnight(maxDate))\n );\n });\n const days = Array.from(\n { length: new Date(activeValue.getFullYear(), activeValue.getMonth() + 1, 0).getDate() },\n (_, index) => ({ label: String(index + 1).padStart(2, '0'), value: index + 1 }),\n ).filter((day) => {\n const candidate = new Date(activeValue.getFullYear(), activeValue.getMonth(), day.value);\n return (\n (minDate === undefined || candidate >= dateAtMidnight(minDate)) &&\n (maxDate === undefined || candidate <= dateAtMidnight(maxDate))\n );\n });\n const datePartOrder = dateOrderFormatter.formatToParts(activeValue).flatMap<DatePart>((part) => {\n if (part.type === 'day') return ['date'];\n if (part.type === 'month') return ['month'];\n if (part.type === 'year') return ['fullYear'];\n return [];\n });\n const yearOptions = years.map((year) => ({ label: String(year), value: year }));\n\n function dateOptions(part: DatePart) {\n if (part === 'date') return days;\n if (part === 'month') return months;\n return yearOptions;\n }\n\n function dateValue(part: DatePart) {\n if (part === 'date') return activeValue.getDate();\n if (part === 'month') return activeValue.getMonth();\n return activeValue.getFullYear();\n }\n const dayPeriods = [0, 1].map((period) => ({\n label:\n hourFormatter\n .formatToParts(new Date(2026, 0, 1, period === 0 ? 1 : 13))\n .find((part) => part.type === 'dayPeriod')?.value ?? (period === 0 ? 'AM' : 'PM'),\n value: period,\n }));\n function dateLabel(part: DatePart) {\n if (part === 'date') return wheelLabels.day;\n if (part === 'month') return wheelLabels.month;\n return wheelLabels.year;\n }\n return {\n displayValue,\n sizingValues,\n formattedValue,\n activeValue,\n isTwelveHour,\n hours,\n minutes,\n dayPeriods,\n datePartOrder,\n dateOptions,\n dateValue,\n dateLabel,\n updateDate,\n updateTime,\n updatePeriod,\n };\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface PickerSizerProps {
|
|
2
|
+
values: readonly string[];
|
|
3
|
+
placeholder: string | null;
|
|
4
|
+
}
|
|
5
|
+
declare const PickerSizer: import("react").MemoExoticComponent<({ values, placeholder }: PickerSizerProps) => import("react").JSX.Element>;
|
|
6
|
+
export default PickerSizer;
|
|
7
|
+
//# sourceMappingURL=PickerSizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickerSizer.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/sizer/PickerSizer.tsx"],"names":[],"mappings":"AAEA,UAAU,gBAAgB;IACxB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,QAAA,MAAM,WAAW,gEAAsD,gBAAgB,iCASrF,CAAC;AAEH,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { memo } from "react";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/date-time-picker/sizer/PickerSizer.tsx
|
|
4
|
+
var PickerSizer = memo(function PickerSizer({ values, placeholder }) {
|
|
5
|
+
return /* @__PURE__ */ jsxs("span", {
|
|
6
|
+
"aria-hidden": "true",
|
|
7
|
+
className: "chayns-date-time-picker__sizer",
|
|
8
|
+
children: [placeholder === null ? null : /* @__PURE__ */ jsx("span", { children: placeholder }), values.map((value) => /* @__PURE__ */ jsx("span", { children: value }, value))]
|
|
9
|
+
});
|
|
10
|
+
});
|
|
11
|
+
PickerSizer.displayName = "DateTimePicker.Sizer";
|
|
12
|
+
//#endregion
|
|
13
|
+
export { PickerSizer as default };
|
|
14
|
+
|
|
15
|
+
//# sourceMappingURL=PickerSizer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PickerSizer.js","names":[],"sources":["../../../../src/components/date-time-picker/sizer/PickerSizer.tsx"],"sourcesContent":["import { memo } from 'react';\n\ninterface PickerSizerProps {\n values: readonly string[];\n placeholder: string | null;\n}\n\nconst PickerSizer = memo(function PickerSizer({ values, placeholder }: PickerSizerProps) {\n return (\n <span aria-hidden=\"true\" className=\"chayns-date-time-picker__sizer\">\n {placeholder === null ? null : <span>{placeholder}</span>}\n {values.map((value) => (\n <span key={value}>{value}</span>\n ))}\n </span>\n );\n});\nPickerSizer.displayName = 'DateTimePicker.Sizer';\nexport default PickerSizer;\n"],"mappings":";;;AAOA,IAAM,cAAc,KAAK,SAAS,YAAY,EAAE,QAAQ,eAAiC;CACvF,OACE,qBAAC,QAAD;EAAM,eAAY;EAAO,WAAU;EAAnC,UAAA,CACG,gBAAgB,OAAO,OAAO,oBAAC,QAAD,EAAA,UAAO,YAAkB,CAAA,GACvD,OAAO,KAAK,UACX,oBAAC,QAAD,EAAA,UAAmB,MAAY,GAApB,KAAoB,CAChC,CACG;;AAEV,CAAC;AACD,YAAY,cAAc"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
interface WheelOption {
|
|
2
|
+
label: string;
|
|
3
|
+
value: number;
|
|
4
|
+
}
|
|
5
|
+
interface WheelProps {
|
|
6
|
+
ariaLabel: string;
|
|
7
|
+
onEscape: () => void;
|
|
8
|
+
onSelect: (value: number) => void;
|
|
9
|
+
options: readonly WheelOption[];
|
|
10
|
+
selected: number;
|
|
11
|
+
}
|
|
12
|
+
declare function Wheel({ ariaLabel, onEscape, onSelect, options, selected }: WheelProps): import("react").JSX.Element;
|
|
13
|
+
export default Wheel;
|
|
14
|
+
//# sourceMappingURL=Wheel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wheel.d.ts","sourceRoot":"","sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"names":[],"mappings":"AAMA,UAAU,WAAW;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,UAAU;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,OAAO,EAAE,SAAS,WAAW,EAAE,CAAC;IAChC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,iBAAS,KAAK,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,UAAU,+BAmK9E;AAGD,eAAe,KAAK,CAAC"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { useId, useLayoutEffect, useRef } from "react";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/date-time-picker/wheel/Wheel.tsx
|
|
4
|
+
var WHEEL_LOOP_CYCLES = 11;
|
|
5
|
+
var WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);
|
|
6
|
+
function Wheel({ ariaLabel, onEscape, onSelect, options, selected }) {
|
|
7
|
+
const wheelId = useId();
|
|
8
|
+
const wheelRef = useRef(null);
|
|
9
|
+
const selectedRef = useRef(null);
|
|
10
|
+
const dragRef = useRef(void 0);
|
|
11
|
+
const ignoreClickRef = useRef(false);
|
|
12
|
+
useLayoutEffect(() => {
|
|
13
|
+
const wheel = wheelRef.current;
|
|
14
|
+
const itemHeight = selectedRef.current?.offsetHeight;
|
|
15
|
+
const selectedIndex = options.findIndex((option) => option.value === selected);
|
|
16
|
+
if (!wheel || !itemHeight || selectedIndex < 0) return;
|
|
17
|
+
wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + selectedIndex) * itemHeight;
|
|
18
|
+
applyPerspective();
|
|
19
|
+
}, [options, selected]);
|
|
20
|
+
function applyPerspective() {
|
|
21
|
+
const wheel = wheelRef.current;
|
|
22
|
+
const itemHeight = selectedRef.current?.offsetHeight;
|
|
23
|
+
if (!wheel || !itemHeight) return;
|
|
24
|
+
const position = wheel.scrollTop / itemHeight;
|
|
25
|
+
for (const option of wheel.querySelectorAll(".chayns-date-time-picker__wheel-option")) {
|
|
26
|
+
const index = Number(option.dataset.wheelIndex);
|
|
27
|
+
const distance = Math.max(-2.5, Math.min(2.5, index - position));
|
|
28
|
+
const progress = Math.min(1, Math.abs(distance) / 2.5);
|
|
29
|
+
option.style.color = progress < .2 ? "var(--text)" : "var(--text-3)";
|
|
30
|
+
option.style.fontWeight = progress < .2 ? "600" : "400";
|
|
31
|
+
option.style.opacity = String(1 - progress * .7);
|
|
32
|
+
option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * .24})`;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function selectCenteredValue() {
|
|
36
|
+
const wheel = wheelRef.current;
|
|
37
|
+
const itemHeight = selectedRef.current?.offsetHeight;
|
|
38
|
+
if (!wheel || !itemHeight) return;
|
|
39
|
+
const option = options[(Math.round(wheel.scrollTop / itemHeight) % options.length + options.length) % options.length];
|
|
40
|
+
if (option !== void 0 && option.value !== selected) onSelect(option.value);
|
|
41
|
+
}
|
|
42
|
+
function handleScroll() {
|
|
43
|
+
const wheel = wheelRef.current;
|
|
44
|
+
const itemHeight = selectedRef.current?.offsetHeight;
|
|
45
|
+
if (!wheel || !itemHeight) return;
|
|
46
|
+
const index = Math.round(wheel.scrollTop / itemHeight);
|
|
47
|
+
const normalizedIndex = (index % options.length + options.length) % options.length;
|
|
48
|
+
if (index < options.length * 2 || index >= options.length * 9) wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;
|
|
49
|
+
applyPerspective();
|
|
50
|
+
selectCenteredValue();
|
|
51
|
+
}
|
|
52
|
+
function handleKeyDown(event) {
|
|
53
|
+
if (event.key === "Escape") {
|
|
54
|
+
event.preventDefault();
|
|
55
|
+
onEscape();
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
const index = options.findIndex((option) => option.value === selected);
|
|
59
|
+
let nextIndex = index;
|
|
60
|
+
if (event.key === "ArrowDown") nextIndex = Math.min(index + 1, options.length - 1);
|
|
61
|
+
if (event.key === "ArrowUp") nextIndex = Math.max(index - 1, 0);
|
|
62
|
+
if (event.key === "Home") nextIndex = 0;
|
|
63
|
+
if (event.key === "End") nextIndex = options.length - 1;
|
|
64
|
+
const nextOption = options[nextIndex];
|
|
65
|
+
if (nextIndex !== index && nextOption !== void 0) {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
onSelect(nextOption.value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function handlePointerDown(event) {
|
|
71
|
+
if (event.button !== 0) return;
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
if (typeof event.currentTarget.setPointerCapture === "function") event.currentTarget.setPointerCapture(event.pointerId);
|
|
74
|
+
dragRef.current = {
|
|
75
|
+
pointerId: event.pointerId,
|
|
76
|
+
scrollTop: event.currentTarget.scrollTop,
|
|
77
|
+
startY: event.clientY
|
|
78
|
+
};
|
|
79
|
+
ignoreClickRef.current = false;
|
|
80
|
+
}
|
|
81
|
+
function handlePointerMove(event) {
|
|
82
|
+
const drag = dragRef.current;
|
|
83
|
+
if (drag?.pointerId !== event.pointerId) return;
|
|
84
|
+
const distance = event.clientY - drag.startY;
|
|
85
|
+
if (Math.abs(distance) > 3) {
|
|
86
|
+
ignoreClickRef.current = true;
|
|
87
|
+
event.currentTarget.scrollTop = drag.scrollTop - distance;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function handlePointerUp(event) {
|
|
91
|
+
if (dragRef.current?.pointerId !== event.pointerId) return;
|
|
92
|
+
dragRef.current = void 0;
|
|
93
|
+
if (typeof event.currentTarget.releasePointerCapture === "function") event.currentTarget.releasePointerCapture(event.pointerId);
|
|
94
|
+
selectCenteredValue();
|
|
95
|
+
}
|
|
96
|
+
return /* @__PURE__ */ jsx("div", {
|
|
97
|
+
"aria-activedescendant": `${wheelId}-${selected}`,
|
|
98
|
+
"aria-label": ariaLabel,
|
|
99
|
+
className: "chayns-date-time-picker__wheel",
|
|
100
|
+
onKeyDown: handleKeyDown,
|
|
101
|
+
onPointerDown: handlePointerDown,
|
|
102
|
+
onPointerMove: handlePointerMove,
|
|
103
|
+
onPointerCancel: handlePointerUp,
|
|
104
|
+
onPointerUp: handlePointerUp,
|
|
105
|
+
onScroll: handleScroll,
|
|
106
|
+
ref: wheelRef,
|
|
107
|
+
role: "listbox",
|
|
108
|
+
tabIndex: 0,
|
|
109
|
+
children: Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) => options.map((option, optionIndex) => /* @__PURE__ */ jsx("button", {
|
|
110
|
+
"aria-hidden": cycle !== WHEEL_CENTER_CYCLE || void 0,
|
|
111
|
+
"aria-selected": option.value === selected,
|
|
112
|
+
id: cycle === WHEEL_CENTER_CYCLE ? `${wheelId}-${option.value}` : void 0,
|
|
113
|
+
className: "chayns-date-time-picker__wheel-option",
|
|
114
|
+
"data-wheel-index": cycle * options.length + optionIndex,
|
|
115
|
+
onClick: (event) => {
|
|
116
|
+
if (ignoreClickRef.current) {
|
|
117
|
+
event.preventDefault();
|
|
118
|
+
event.stopPropagation();
|
|
119
|
+
ignoreClickRef.current = false;
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
onSelect(option.value);
|
|
123
|
+
},
|
|
124
|
+
ref: cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : void 0,
|
|
125
|
+
role: "option",
|
|
126
|
+
tabIndex: -1,
|
|
127
|
+
type: "button",
|
|
128
|
+
children: option.label
|
|
129
|
+
}, `${cycle}-${option.value}`)))
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
Object.assign(Wheel, { displayName: "DateTimePicker.Wheel" });
|
|
133
|
+
//#endregion
|
|
134
|
+
export { Wheel as default };
|
|
135
|
+
|
|
136
|
+
//# sourceMappingURL=Wheel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Wheel.js","names":[],"sources":["../../../../src/components/date-time-picker/wheel/Wheel.tsx"],"sourcesContent":["import { useLayoutEffect, useId, useRef } from 'react';\nimport type { KeyboardEvent, PointerEvent as ReactPointerEvent } from 'react';\n\nconst WHEEL_LOOP_CYCLES = 11;\nconst WHEEL_CENTER_CYCLE = Math.floor(WHEEL_LOOP_CYCLES / 2);\n\ninterface WheelOption {\n label: string;\n value: number;\n}\n\ninterface WheelProps {\n ariaLabel: string;\n onEscape: () => void;\n onSelect: (value: number) => void;\n options: readonly WheelOption[];\n selected: number;\n}\n\nfunction Wheel({ ariaLabel, onEscape, onSelect, options, selected }: WheelProps) {\n const wheelId = useId();\n const wheelRef = useRef<HTMLDivElement>(null);\n const selectedRef = useRef<HTMLButtonElement>(null);\n const dragRef = useRef<{ pointerId: number; scrollTop: number; startY: number } | undefined>(\n undefined,\n );\n const ignoreClickRef = useRef(false);\n\n useLayoutEffect(() => {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n const selectedIndex = options.findIndex((option) => option.value === selected);\n if (!wheel || !itemHeight || selectedIndex < 0) return;\n\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + selectedIndex) * itemHeight;\n applyPerspective();\n }, [options, selected]);\n\n function applyPerspective() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const position = wheel.scrollTop / itemHeight;\n for (const option of wheel.querySelectorAll<HTMLButtonElement>(\n '.chayns-date-time-picker__wheel-option',\n )) {\n const index = Number(option.dataset.wheelIndex);\n const distance = Math.max(-2.5, Math.min(2.5, index - position));\n const progress = Math.min(1, Math.abs(distance) / 2.5);\n\n option.style.color = progress < 0.2 ? 'var(--text)' : 'var(--text-3)';\n option.style.fontWeight = progress < 0.2 ? '600' : '400';\n option.style.opacity = String(1 - progress * 0.7);\n option.style.transform = `rotateX(${distance * 22}deg) scale(${1 - progress * 0.24})`;\n }\n }\n\n function selectCenteredValue() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const option = options[((index % options.length) + options.length) % options.length];\n if (option !== undefined && option.value !== selected) onSelect(option.value);\n }\n\n function handleScroll() {\n const wheel = wheelRef.current;\n const itemHeight = selectedRef.current?.offsetHeight;\n if (!wheel || !itemHeight) return;\n\n const index = Math.round(wheel.scrollTop / itemHeight);\n const normalizedIndex = ((index % options.length) + options.length) % options.length;\n if (index < options.length * 2 || index >= options.length * (WHEEL_LOOP_CYCLES - 2)) {\n wheel.scrollTop = (WHEEL_CENTER_CYCLE * options.length + normalizedIndex) * itemHeight;\n }\n\n applyPerspective();\n selectCenteredValue();\n }\n\n function handleKeyDown(event: KeyboardEvent<HTMLDivElement>) {\n if (event.key === 'Escape') {\n event.preventDefault();\n onEscape();\n return;\n }\n\n const index = options.findIndex((option) => option.value === selected);\n let nextIndex = index;\n if (event.key === 'ArrowDown') nextIndex = Math.min(index + 1, options.length - 1);\n if (event.key === 'ArrowUp') nextIndex = Math.max(index - 1, 0);\n if (event.key === 'Home') nextIndex = 0;\n if (event.key === 'End') nextIndex = options.length - 1;\n const nextOption = options[nextIndex];\n if (nextIndex !== index && nextOption !== undefined) {\n event.preventDefault();\n onSelect(nextOption.value);\n }\n }\n\n function handlePointerDown(event: ReactPointerEvent<HTMLDivElement>) {\n if (event.button !== 0) return;\n event.preventDefault();\n if (typeof event.currentTarget.setPointerCapture === 'function') {\n event.currentTarget.setPointerCapture(event.pointerId);\n }\n dragRef.current = {\n pointerId: event.pointerId,\n scrollTop: event.currentTarget.scrollTop,\n startY: event.clientY,\n };\n ignoreClickRef.current = false;\n }\n\n function handlePointerMove(event: ReactPointerEvent<HTMLDivElement>) {\n const drag = dragRef.current;\n if (drag?.pointerId !== event.pointerId) return;\n const distance = event.clientY - drag.startY;\n if (Math.abs(distance) > 3) {\n ignoreClickRef.current = true;\n event.currentTarget.scrollTop = drag.scrollTop - distance;\n }\n }\n\n function handlePointerUp(event: ReactPointerEvent<HTMLDivElement>) {\n if (dragRef.current?.pointerId !== event.pointerId) return;\n dragRef.current = undefined;\n if (typeof event.currentTarget.releasePointerCapture === 'function') {\n event.currentTarget.releasePointerCapture(event.pointerId);\n }\n selectCenteredValue();\n }\n\n return (\n <div\n aria-activedescendant={`${wheelId}-${selected}`}\n aria-label={ariaLabel}\n className=\"chayns-date-time-picker__wheel\"\n onKeyDown={handleKeyDown}\n onPointerDown={handlePointerDown}\n onPointerMove={handlePointerMove}\n onPointerCancel={handlePointerUp}\n onPointerUp={handlePointerUp}\n onScroll={handleScroll}\n ref={wheelRef}\n role=\"listbox\"\n tabIndex={0}\n >\n {Array.from({ length: WHEEL_LOOP_CYCLES }, (_, cycle) =>\n options.map((option, optionIndex) => (\n <button\n aria-hidden={cycle !== WHEEL_CENTER_CYCLE || undefined}\n aria-selected={option.value === selected}\n id={cycle === WHEEL_CENTER_CYCLE ? `${wheelId}-${option.value}` : undefined}\n className=\"chayns-date-time-picker__wheel-option\"\n data-wheel-index={cycle * options.length + optionIndex}\n key={`${cycle}-${option.value}`}\n onClick={(event) => {\n if (ignoreClickRef.current) {\n event.preventDefault();\n event.stopPropagation();\n ignoreClickRef.current = false;\n return;\n }\n onSelect(option.value);\n }}\n ref={\n cycle === WHEEL_CENTER_CYCLE && option.value === selected ? selectedRef : undefined\n }\n role=\"option\"\n tabIndex={-1}\n type=\"button\"\n >\n {option.label}\n </button>\n )),\n )}\n </div>\n );\n}\n\nObject.assign(Wheel, { displayName: 'DateTimePicker.Wheel' });\nexport default Wheel;\n"],"mappings":"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"}
|