@sixthshift/design-system 0.2.1 → 0.4.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/README.md +242 -33
- package/dist/components/Badge/Badge.d.ts +65 -7
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +56 -46
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/Badge/index.d.ts +1 -1
- package/dist/components/Badge/index.d.ts.map +1 -1
- package/dist/components/Badge/index.js +1 -1
- package/dist/components/Badge/index.js.map +1 -1
- package/dist/components/BarChart/BarChart.d.ts +20 -2
- package/dist/components/BarChart/BarChart.d.ts.map +1 -1
- package/dist/components/BarChart/BarChart.js +17 -3
- package/dist/components/BarChart/BarChart.js.map +1 -1
- package/dist/components/Button/Button.d.ts +85 -6
- package/dist/components/Button/Button.d.ts.map +1 -1
- package/dist/components/Button/Button.js +97 -106
- package/dist/components/Button/Button.js.map +1 -1
- package/dist/components/Button/index.d.ts +1 -1
- package/dist/components/Button/index.d.ts.map +1 -1
- package/dist/components/Button/index.js +1 -1
- package/dist/components/Button/index.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +31 -1
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +94 -225
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/CalendarView.d.ts +15 -0
- package/dist/components/Calendar/CalendarView.d.ts.map +1 -0
- package/dist/components/Calendar/CalendarView.js +263 -0
- package/dist/components/Calendar/CalendarView.js.map +1 -0
- package/dist/components/Calendar/calendar.types.d.ts +87 -27
- package/dist/components/Calendar/calendar.types.d.ts.map +1 -1
- package/dist/components/Calendar/calendar.types.js +10 -3
- package/dist/components/Calendar/calendar.types.js.map +1 -1
- package/dist/components/Calendar/index.d.ts +16 -2
- package/dist/components/Calendar/index.d.ts.map +1 -1
- package/dist/components/Calendar/index.js +15 -1
- package/dist/components/Calendar/index.js.map +1 -1
- package/dist/components/Card/Card.d.ts +13 -0
- package/dist/components/Card/Card.d.ts.map +1 -1
- package/dist/components/Card/Card.js +15 -2
- package/dist/components/Card/Card.js.map +1 -1
- package/dist/components/Checkbox/Checkbox.d.ts +21 -0
- package/dist/components/Checkbox/Checkbox.d.ts.map +1 -1
- package/dist/components/Checkbox/Checkbox.js +22 -1
- package/dist/components/Checkbox/Checkbox.js.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts +22 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.d.ts.map +1 -1
- package/dist/components/CheckboxGroup/CheckboxGroup.js +22 -0
- package/dist/components/CheckboxGroup/CheckboxGroup.js.map +1 -1
- package/dist/components/Code/Editor/Editor.js +2 -2
- package/dist/components/Code/Editor/Editor.js.map +1 -1
- package/dist/components/Code/Editor/themes.d.ts +2 -2
- package/dist/components/Code/Editor/themes.d.ts.map +1 -1
- package/dist/components/Code/Editor/themes.js +50 -32
- package/dist/components/Code/Editor/themes.js.map +1 -1
- package/dist/components/Code/ValidationStatus/ValidationStatus.d.ts.map +1 -1
- package/dist/components/Code/ValidationStatus/ValidationStatus.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +45 -2
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +228 -11
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePicker/DateSegments.d.ts +60 -0
- package/dist/components/DatePicker/DateSegments.d.ts.map +1 -0
- package/dist/components/DatePicker/DateSegments.js +80 -0
- package/dist/components/DatePicker/DateSegments.js.map +1 -0
- package/dist/components/DatePicker/datepicker.types.d.ts +53 -37
- package/dist/components/DatePicker/datepicker.types.d.ts.map +1 -1
- package/dist/components/DatePicker/datepicker.types.js +5 -3
- package/dist/components/DatePicker/datepicker.types.js.map +1 -1
- package/dist/components/DatePicker/index.d.ts +10 -1
- package/dist/components/DatePicker/index.d.ts.map +1 -1
- package/dist/components/DatePicker/index.js +8 -0
- package/dist/components/DatePicker/index.js.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +22 -3
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +38 -24
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts +26 -21
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.js +6 -0
- package/dist/components/DateRangePicker/daterangepicker.types.js.map +1 -1
- package/dist/components/DateRangePicker/index.d.ts +8 -1
- package/dist/components/DateRangePicker/index.d.ts.map +1 -1
- package/dist/components/DateRangePicker/index.js +6 -0
- package/dist/components/DateRangePicker/index.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +32 -4
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +133 -42
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimePicker/DateTimeSegments.d.ts +41 -0
- package/dist/components/DateTimePicker/DateTimeSegments.d.ts.map +1 -0
- package/dist/components/DateTimePicker/DateTimeSegments.js +67 -0
- package/dist/components/DateTimePicker/DateTimeSegments.js.map +1 -0
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts +26 -18
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimePicker/datetimepicker.types.js +10 -0
- package/dist/components/DateTimePicker/datetimepicker.types.js.map +1 -1
- package/dist/components/DateTimePicker/index.d.ts +8 -1
- package/dist/components/DateTimePicker/index.d.ts.map +1 -1
- package/dist/components/DateTimePicker/index.js +6 -0
- package/dist/components/DateTimePicker/index.js.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts +30 -4
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +171 -72
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts +28 -19
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.js +8 -0
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.js.map +1 -1
- package/dist/components/DateTimeRangePicker/index.d.ts +8 -0
- package/dist/components/DateTimeRangePicker/index.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/index.js +7 -0
- package/dist/components/DateTimeRangePicker/index.js.map +1 -1
- package/dist/components/Field/Field.d.ts +18 -20
- package/dist/components/Field/Field.d.ts.map +1 -1
- package/dist/components/Field/Field.js +22 -5
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/FormField/FormField.d.ts +15 -0
- package/dist/components/FormField/FormField.d.ts.map +1 -1
- package/dist/components/FormField/FormField.js +15 -0
- package/dist/components/FormField/FormField.js.map +1 -1
- package/dist/components/HoverCard/HoverCard.d.ts +6 -0
- package/dist/components/HoverCard/HoverCard.d.ts.map +1 -1
- package/dist/components/HoverCard/HoverCard.js +6 -0
- package/dist/components/HoverCard/HoverCard.js.map +1 -1
- package/dist/components/Input/Input.d.ts +15 -0
- package/dist/components/Input/Input.d.ts.map +1 -1
- package/dist/components/Input/Input.js +18 -3
- package/dist/components/Input/Input.js.map +1 -1
- package/dist/components/LineChart/LineChart.d.ts +35 -2
- package/dist/components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/components/LineChart/LineChart.js +22 -3
- package/dist/components/LineChart/LineChart.js.map +1 -1
- package/dist/components/Markdown/Markdown.d.ts +19 -4
- package/dist/components/Markdown/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown/Markdown.js +20 -2
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Message/Message.d.ts +49 -4
- package/dist/components/Message/Message.d.ts.map +1 -1
- package/dist/components/Message/Message.js +62 -11
- package/dist/components/Message/Message.js.map +1 -1
- package/dist/components/Message/index.d.ts +1 -1
- package/dist/components/Message/index.d.ts.map +1 -1
- package/dist/components/Modal/Modal.d.ts +60 -5
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +52 -6
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/components/ModalContext.d.ts +14 -0
- package/dist/components/Modal/components/ModalContext.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalContext.js.map +1 -1
- package/dist/components/Modal/components/ModalHeader.d.ts.map +1 -1
- package/dist/components/Modal/components/ModalHeader.js +13 -2
- package/dist/components/Modal/components/ModalHeader.js.map +1 -1
- package/dist/components/Popover/Popover.d.ts +29 -0
- package/dist/components/Popover/Popover.d.ts.map +1 -1
- package/dist/components/Popover/Popover.js +36 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/Popover/components/PopoverBody.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverBody.js +5 -2
- package/dist/components/Popover/components/PopoverBody.js.map +1 -1
- package/dist/components/Popover/components/PopoverContext.d.ts +1 -0
- package/dist/components/Popover/components/PopoverContext.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverContext.js.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.d.ts.map +1 -1
- package/dist/components/Popover/components/PopoverTrigger.js +2 -2
- package/dist/components/Popover/components/PopoverTrigger.js.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts +16 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.js +19 -3
- package/dist/components/ProgressBar/ProgressBar.js.map +1 -1
- package/dist/components/RadioButton/RadioButton.d.ts +26 -0
- package/dist/components/RadioButton/RadioButton.d.ts.map +1 -1
- package/dist/components/RadioButton/RadioButton.js +35 -1
- package/dist/components/RadioButton/RadioButton.js.map +1 -1
- package/dist/components/RadioButtonGroup/RadioButtonGroup.d.ts +26 -0
- package/dist/components/RadioButtonGroup/RadioButtonGroup.d.ts.map +1 -1
- package/dist/components/RadioButtonGroup/RadioButtonGroup.js +33 -0
- package/dist/components/RadioButtonGroup/RadioButtonGroup.js.map +1 -1
- package/dist/components/SearchInput/SearchInput.d.ts +10 -0
- package/dist/components/SearchInput/SearchInput.d.ts.map +1 -1
- package/dist/components/SearchInput/SearchInput.js +12 -1
- package/dist/components/SearchInput/SearchInput.js.map +1 -1
- package/dist/components/Select/Select.d.ts +10 -2
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +63 -18
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectDropdown.d.ts +14 -2
- package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
- package/dist/components/Select/SelectDropdown.js +20 -4
- package/dist/components/Select/SelectDropdown.js.map +1 -1
- package/dist/components/Select/SelectTrigger.d.ts +10 -3
- package/dist/components/Select/SelectTrigger.d.ts.map +1 -1
- package/dist/components/Select/SelectTrigger.js +12 -3
- package/dist/components/Select/SelectTrigger.js.map +1 -1
- package/dist/components/Select/useSelectKeyboard.d.ts +15 -1
- package/dist/components/Select/useSelectKeyboard.d.ts.map +1 -1
- package/dist/components/Select/useSelectKeyboard.js +73 -65
- package/dist/components/Select/useSelectKeyboard.js.map +1 -1
- package/dist/components/Separator/Separator.d.ts +10 -0
- package/dist/components/Separator/Separator.d.ts.map +1 -1
- package/dist/components/Separator/Separator.js +10 -0
- package/dist/components/Separator/Separator.js.map +1 -1
- package/dist/components/Sheet/Sheet.d.ts +25 -5
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +24 -6
- package/dist/components/Sheet/Sheet.js.map +1 -1
- package/dist/components/Sheet/components/SheetContext.d.ts +10 -0
- package/dist/components/Sheet/components/SheetContext.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetContext.js.map +1 -1
- package/dist/components/Sheet/components/SheetFooter.js +1 -1
- package/dist/components/Sheet/components/SheetFooter.js.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.d.ts.map +1 -1
- package/dist/components/Sheet/components/SheetHeader.js +11 -2
- package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.d.ts +21 -2
- package/dist/components/Sparkline/Sparkline.d.ts.map +1 -1
- package/dist/components/Sparkline/Sparkline.js +16 -3
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/Spinner/Spinner.d.ts +27 -2
- package/dist/components/Spinner/Spinner.d.ts.map +1 -1
- package/dist/components/Spinner/Spinner.js +28 -3
- package/dist/components/Spinner/Spinner.js.map +1 -1
- package/dist/components/Switch/Switch.d.ts +18 -0
- package/dist/components/Switch/Switch.d.ts.map +1 -1
- package/dist/components/Switch/Switch.js +19 -1
- package/dist/components/Switch/Switch.js.map +1 -1
- package/dist/components/Tabs/Tabs.d.ts +8 -2
- package/dist/components/Tabs/Tabs.d.ts.map +1 -1
- package/dist/components/Tabs/Tabs.js +6 -0
- package/dist/components/Tabs/Tabs.js.map +1 -1
- package/dist/components/Tabs/components/TabsList.d.ts +1 -1
- package/dist/components/Tabs/components/TabsList.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsList.js +5 -4
- package/dist/components/Tabs/components/TabsList.js.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.d.ts +1 -1
- package/dist/components/Tabs/components/TabsPanels.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsPanels.js +5 -3
- package/dist/components/Tabs/components/TabsPanels.js.map +1 -1
- package/dist/components/Tabs/components/TabsTrigger.d.ts.map +1 -1
- package/dist/components/Tabs/components/TabsTrigger.js +22 -6
- package/dist/components/Tabs/components/TabsTrigger.js.map +1 -1
- package/dist/components/TagChip/TagChip.d.ts +16 -13
- package/dist/components/TagChip/TagChip.d.ts.map +1 -1
- package/dist/components/TagChip/TagChip.js +18 -3
- package/dist/components/TagChip/TagChip.js.map +1 -1
- package/dist/components/TagInput/TagInput.d.ts +12 -9
- package/dist/components/TagInput/TagInput.d.ts.map +1 -1
- package/dist/components/TagInput/TagInput.js +16 -4
- package/dist/components/TagInput/TagInput.js.map +1 -1
- package/dist/components/Text/Text.d.ts +9 -0
- package/dist/components/Text/Text.d.ts.map +1 -1
- package/dist/components/Text/Text.js +9 -0
- package/dist/components/Text/Text.js.map +1 -1
- package/dist/components/TextInline/TextInline.d.ts +15 -4
- package/dist/components/TextInline/TextInline.d.ts.map +1 -1
- package/dist/components/TextInline/TextInline.js +11 -0
- package/dist/components/TextInline/TextInline.js.map +1 -1
- package/dist/components/Textarea/Textarea.d.ts +12 -0
- package/dist/components/Textarea/Textarea.d.ts.map +1 -1
- package/dist/components/Textarea/Textarea.js +13 -1
- package/dist/components/Textarea/Textarea.js.map +1 -1
- package/dist/components/TimePicker/TimeColumn.d.ts +10 -1
- package/dist/components/TimePicker/TimeColumn.d.ts.map +1 -1
- package/dist/components/TimePicker/TimeColumn.js +8 -1
- package/dist/components/TimePicker/TimeColumn.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.d.ts +34 -2
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +118 -15
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/TimePicker/TimeSegments.d.ts +50 -0
- package/dist/components/TimePicker/TimeSegments.d.ts.map +1 -0
- package/dist/components/TimePicker/TimeSegments.js +93 -0
- package/dist/components/TimePicker/TimeSegments.js.map +1 -0
- package/dist/components/TimePicker/timepicker.hooks.d.ts +0 -4
- package/dist/components/TimePicker/timepicker.hooks.d.ts.map +1 -1
- package/dist/components/TimePicker/timepicker.hooks.js +1 -23
- package/dist/components/TimePicker/timepicker.hooks.js.map +1 -1
- package/dist/components/TimePicker/timepicker.types.d.ts +14 -15
- package/dist/components/TimePicker/timepicker.types.d.ts.map +1 -1
- package/dist/components/TimePicker/timepicker.types.js +4 -3
- package/dist/components/TimePicker/timepicker.types.js.map +1 -1
- package/dist/components/Toast/Toast.d.ts +27 -0
- package/dist/components/Toast/Toast.d.ts.map +1 -1
- package/dist/components/Toast/Toast.js +28 -1
- package/dist/components/Toast/Toast.js.map +1 -1
- package/dist/components/Toggle/Toggle.d.ts +31 -12
- package/dist/components/Toggle/Toggle.d.ts.map +1 -1
- package/dist/components/Toggle/Toggle.js +19 -31
- package/dist/components/Toggle/Toggle.js.map +1 -1
- package/dist/components/Toggle/index.d.ts +1 -1
- package/dist/components/Toggle/index.d.ts.map +1 -1
- package/dist/components/Toggle/index.js +1 -1
- package/dist/components/Toggle/index.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.d.ts +17 -0
- package/dist/components/ToggleGroup/ToggleGroup.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroup.js +17 -0
- package/dist/components/ToggleGroup/ToggleGroup.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.d.ts +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupItem.js +7 -6
- package/dist/components/ToggleGroup/ToggleGroupItem.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts +4 -3
- package/dist/components/ToggleGroup/ToggleGroupMultiple.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroupMultiple.js.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts +4 -3
- package/dist/components/ToggleGroup/ToggleGroupSingle.d.ts.map +1 -1
- package/dist/components/ToggleGroup/ToggleGroupSingle.js +2 -2
- package/dist/components/ToggleGroup/ToggleGroupSingle.js.map +1 -1
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts +12 -3
- package/dist/components/ToggleGroup/toggleGroup.types.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +6 -0
- package/dist/components/Tooltip/Tooltip.d.ts.map +1 -1
- package/dist/components/Tooltip/Tooltip.js +6 -0
- package/dist/components/Tooltip/Tooltip.js.map +1 -1
- package/dist/date-time/index.d.ts +2 -0
- package/dist/date-time/index.d.ts.map +1 -1
- package/dist/date-time/index.js +9 -1
- package/dist/date-time/index.js.map +1 -1
- package/dist/date-time/iso.d.ts +261 -0
- package/dist/date-time/iso.d.ts.map +1 -0
- package/dist/date-time/iso.js +358 -0
- package/dist/date-time/iso.js.map +1 -0
- package/dist/date-time/now.d.ts +7 -6
- package/dist/date-time/now.d.ts.map +1 -1
- package/dist/date-time/now.js +3 -3
- package/dist/date-time/now.js.map +1 -1
- package/dist/internal/PickerField.d.ts +45 -0
- package/dist/internal/PickerField.d.ts.map +1 -0
- package/dist/internal/PickerField.js +24 -0
- package/dist/internal/PickerField.js.map +1 -0
- package/dist/internal/SegmentedField.d.ts +98 -0
- package/dist/internal/SegmentedField.d.ts.map +1 -0
- package/dist/internal/SegmentedField.js +315 -0
- package/dist/internal/SegmentedField.js.map +1 -0
- package/dist/internal/index.d.ts +2 -0
- package/dist/internal/index.d.ts.map +1 -1
- package/dist/internal/index.js +2 -0
- package/dist/internal/index.js.map +1 -1
- package/dist/theme/index.d.ts +4 -3
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +3 -2
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/schema.d.ts +49 -33
- package/dist/theme/schema.d.ts.map +1 -1
- package/dist/theme/schema.js +30 -21
- package/dist/theme/schema.js.map +1 -1
- package/package.json +11 -59
- package/src/components/Badge/Badge.tsx +87 -49
- package/src/components/Badge/index.ts +10 -1
- package/src/components/BarChart/BarChart.tsx +37 -30
- package/src/components/Button/Button.tsx +129 -106
- package/src/components/Button/index.ts +10 -1
- package/src/components/Calendar/Calendar.tsx +104 -401
- package/src/components/Calendar/CalendarView.tsx +454 -0
- package/src/components/Calendar/calendar.types.ts +104 -29
- package/src/components/Calendar/index.ts +16 -17
- package/src/components/Card/Card.tsx +15 -2
- package/src/components/Checkbox/Checkbox.tsx +22 -2
- package/src/components/CheckboxGroup/CheckboxGroup.tsx +22 -0
- package/src/components/Code/Editor/Editor.tsx +2 -2
- package/src/components/Code/Editor/themes.ts +50 -32
- package/src/components/Code/ValidationStatus/ValidationStatus.tsx +6 -3
- package/src/components/DatePicker/DatePicker.tsx +369 -42
- package/src/components/DatePicker/DateSegments.tsx +125 -0
- package/src/components/DatePicker/datepicker.types.ts +58 -39
- package/src/components/DatePicker/index.ts +11 -3
- package/src/components/DateRangePicker/DateRangePicker.tsx +38 -24
- package/src/components/DateRangePicker/daterangepicker.types.ts +29 -23
- package/src/components/DateRangePicker/index.ts +9 -1
- package/src/components/DateTimePicker/DateTimePicker.tsx +189 -88
- package/src/components/DateTimePicker/DateTimeSegments.tsx +113 -0
- package/src/components/DateTimePicker/datetimepicker.types.ts +29 -19
- package/src/components/DateTimePicker/index.ts +9 -1
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +251 -126
- package/src/components/DateTimeRangePicker/datetimerangepicker.types.ts +31 -20
- package/src/components/DateTimeRangePicker/index.ts +9 -0
- package/src/components/Field/Field.tsx +25 -26
- package/src/components/FormField/FormField.tsx +15 -0
- package/src/components/HoverCard/HoverCard.tsx +6 -0
- package/src/components/Input/Input.tsx +19 -4
- package/src/components/LineChart/LineChart.tsx +164 -141
- package/src/components/Markdown/Markdown.tsx +21 -3
- package/src/components/Message/Message.tsx +83 -17
- package/src/components/Message/index.ts +1 -1
- package/src/components/Modal/Modal.tsx +157 -86
- package/src/components/Modal/components/ModalContext.tsx +14 -0
- package/src/components/Modal/components/ModalHeader.tsx +15 -3
- package/src/components/Popover/Popover.tsx +36 -0
- package/src/components/Popover/components/PopoverBody.tsx +6 -1
- package/src/components/Popover/components/PopoverContext.tsx +1 -0
- package/src/components/Popover/components/PopoverTrigger.tsx +2 -1
- package/src/components/ProgressBar/ProgressBar.tsx +46 -28
- package/src/components/RadioButton/RadioButton.tsx +34 -3
- package/src/components/RadioButtonGroup/RadioButtonGroup.tsx +32 -0
- package/src/components/SearchInput/SearchInput.tsx +13 -2
- package/src/components/Select/Select.tsx +75 -19
- package/src/components/Select/SelectDropdown.tsx +45 -12
- package/src/components/Select/SelectTrigger.tsx +31 -8
- package/src/components/Select/useSelectKeyboard.ts +20 -10
- package/src/components/Separator/Separator.tsx +10 -0
- package/src/components/Sheet/Sheet.tsx +114 -83
- package/src/components/Sheet/components/SheetContext.tsx +10 -0
- package/src/components/Sheet/components/SheetFooter.tsx +1 -1
- package/src/components/Sheet/components/SheetHeader.tsx +18 -3
- package/src/components/Sparkline/Sparkline.tsx +40 -36
- package/src/components/Spinner/Spinner.tsx +28 -3
- package/src/components/Switch/Switch.tsx +27 -4
- package/src/components/Tabs/Tabs.tsx +6 -0
- package/src/components/Tabs/components/TabsList.tsx +5 -3
- package/src/components/Tabs/components/TabsPanels.tsx +5 -3
- package/src/components/Tabs/components/TabsTrigger.tsx +22 -5
- package/src/components/TagChip/TagChip.tsx +27 -18
- package/src/components/TagInput/TagInput.tsx +16 -11
- package/src/components/Text/Text.tsx +9 -0
- package/src/components/TextInline/TextInline.tsx +11 -0
- package/src/components/Textarea/Textarea.tsx +13 -1
- package/src/components/TimePicker/TimeColumn.tsx +24 -1
- package/src/components/TimePicker/TimePicker.tsx +157 -51
- package/src/components/TimePicker/TimeSegments.tsx +131 -0
- package/src/components/TimePicker/timepicker.hooks.ts +1 -24
- package/src/components/TimePicker/timepicker.types.ts +14 -16
- package/src/components/Toast/Toast.tsx +28 -1
- package/src/components/Toggle/Toggle.tsx +34 -32
- package/src/components/Toggle/index.ts +1 -1
- package/src/components/ToggleGroup/ToggleGroup.tsx +17 -0
- package/src/components/ToggleGroup/ToggleGroupItem.tsx +13 -8
- package/src/components/ToggleGroup/ToggleGroupMultiple.tsx +3 -1
- package/src/components/ToggleGroup/ToggleGroupSingle.tsx +3 -1
- package/src/components/ToggleGroup/toggleGroup.types.ts +12 -3
- package/src/components/Tooltip/Tooltip.tsx +6 -0
- package/src/date-time/index.ts +61 -1
- package/src/date-time/iso.ts +511 -0
- package/src/date-time/now.ts +10 -9
- package/src/internal/PickerField.tsx +90 -0
- package/src/internal/SegmentedField.tsx +445 -0
- package/src/internal/index.ts +2 -0
- package/src/theme/index.ts +11 -9
- package/src/theme/recipes/badge.css +140 -0
- package/src/theme/recipes/button.css +167 -0
- package/src/theme/recipes/card.css +26 -0
- package/src/theme/recipes/checkbox.css +44 -0
- package/src/theme/recipes/field.css +14 -0
- package/src/theme/recipes/index.css +28 -0
- package/src/theme/recipes/input.css +29 -0
- package/src/theme/recipes/message.css +47 -0
- package/src/theme/recipes/modal.css +31 -0
- package/src/theme/recipes/radio-button.css +42 -0
- package/src/theme/recipes/search-input.css +16 -0
- package/src/theme/recipes/select.css +105 -0
- package/src/theme/recipes/sheet.css +34 -0
- package/src/theme/recipes/spinner.css +17 -0
- package/src/theme/recipes/switch.css +39 -0
- package/src/theme/recipes/tabs.css +41 -0
- package/src/theme/recipes/tag-chip.css +27 -0
- package/src/theme/recipes/textarea.css +20 -0
- package/src/theme/recipes/toggle.css +92 -0
- package/src/theme/schema.ts +59 -58
- package/src/theme/tokens.css +824 -0
- package/dist/components/Avatar/Avatar.d.ts +0 -6
- package/dist/components/Avatar/Avatar.d.ts.map +0 -1
- package/dist/components/Avatar/Avatar.js +0 -11
- package/dist/components/Avatar/Avatar.js.map +0 -1
- package/dist/components/Avatar/index.d.ts +0 -2
- package/dist/components/Avatar/index.d.ts.map +0 -1
- package/dist/components/Avatar/index.js +0 -2
- package/dist/components/Avatar/index.js.map +0 -1
- package/dist/components/Breadcrumb/Breadcrumb.d.ts +0 -12
- package/dist/components/Breadcrumb/Breadcrumb.d.ts.map +0 -1
- package/dist/components/Breadcrumb/Breadcrumb.js +0 -19
- package/dist/components/Breadcrumb/Breadcrumb.js.map +0 -1
- package/dist/components/Breadcrumb/index.d.ts +0 -2
- package/dist/components/Breadcrumb/index.d.ts.map +0 -1
- package/dist/components/Breadcrumb/index.js +0 -2
- package/dist/components/Breadcrumb/index.js.map +0 -1
- package/dist/components/ColorDot/ColorDot.d.ts +0 -13
- package/dist/components/ColorDot/ColorDot.d.ts.map +0 -1
- package/dist/components/ColorDot/ColorDot.js +0 -34
- package/dist/components/ColorDot/ColorDot.js.map +0 -1
- package/dist/components/ColorDot/index.d.ts +0 -2
- package/dist/components/ColorDot/index.d.ts.map +0 -1
- package/dist/components/ColorDot/index.js +0 -2
- package/dist/components/ColorDot/index.js.map +0 -1
- package/dist/components/EmptyState/EmptyState.d.ts +0 -15
- package/dist/components/EmptyState/EmptyState.d.ts.map +0 -1
- package/dist/components/EmptyState/EmptyState.js +0 -7
- package/dist/components/EmptyState/EmptyState.js.map +0 -1
- package/dist/components/EmptyState/index.d.ts +0 -2
- package/dist/components/EmptyState/index.d.ts.map +0 -1
- package/dist/components/EmptyState/index.js +0 -2
- package/dist/components/EmptyState/index.js.map +0 -1
- package/dist/components/HeatMap/HeatMapCalendar.d.ts +0 -11
- package/dist/components/HeatMap/HeatMapCalendar.d.ts.map +0 -1
- package/dist/components/HeatMap/HeatMapCalendar.js +0 -68
- package/dist/components/HeatMap/HeatMapCalendar.js.map +0 -1
- package/dist/components/HeatMap/HeatMapMatrix.d.ts +0 -12
- package/dist/components/HeatMap/HeatMapMatrix.d.ts.map +0 -1
- package/dist/components/HeatMap/HeatMapMatrix.js +0 -35
- package/dist/components/HeatMap/HeatMapMatrix.js.map +0 -1
- package/dist/components/HeatMap/heat-map.utils.d.ts +0 -10
- package/dist/components/HeatMap/heat-map.utils.d.ts.map +0 -1
- package/dist/components/HeatMap/heat-map.utils.js +0 -10
- package/dist/components/HeatMap/heat-map.utils.js.map +0 -1
- package/dist/components/HeatMap/index.d.ts +0 -4
- package/dist/components/HeatMap/index.d.ts.map +0 -1
- package/dist/components/HeatMap/index.js +0 -3
- package/dist/components/HeatMap/index.js.map +0 -1
- package/dist/components/MetricList/MetricList.d.ts +0 -9
- package/dist/components/MetricList/MetricList.d.ts.map +0 -1
- package/dist/components/MetricList/MetricList.js +0 -6
- package/dist/components/MetricList/MetricList.js.map +0 -1
- package/dist/components/MetricList/MetricRow.d.ts +0 -13
- package/dist/components/MetricList/MetricRow.d.ts.map +0 -1
- package/dist/components/MetricList/MetricRow.js +0 -13
- package/dist/components/MetricList/MetricRow.js.map +0 -1
- package/dist/components/MetricList/index.d.ts +0 -3
- package/dist/components/MetricList/index.d.ts.map +0 -1
- package/dist/components/MetricList/index.js +0 -3
- package/dist/components/MetricList/index.js.map +0 -1
- package/dist/components/NavBottom/NavBottom.d.ts +0 -15
- package/dist/components/NavBottom/NavBottom.d.ts.map +0 -1
- package/dist/components/NavBottom/NavBottom.js +0 -19
- package/dist/components/NavBottom/NavBottom.js.map +0 -1
- package/dist/components/NavBottom/index.d.ts +0 -3
- package/dist/components/NavBottom/index.d.ts.map +0 -1
- package/dist/components/NavBottom/index.js +0 -2
- package/dist/components/NavBottom/index.js.map +0 -1
- package/dist/components/NavSide/NavItem.d.ts +0 -9
- package/dist/components/NavSide/NavItem.d.ts.map +0 -1
- package/dist/components/NavSide/NavItem.js +0 -13
- package/dist/components/NavSide/NavItem.js.map +0 -1
- package/dist/components/NavSide/NavSide.d.ts +0 -15
- package/dist/components/NavSide/NavSide.d.ts.map +0 -1
- package/dist/components/NavSide/NavSide.js +0 -10
- package/dist/components/NavSide/NavSide.js.map +0 -1
- package/dist/components/NavSide/index.d.ts +0 -3
- package/dist/components/NavSide/index.d.ts.map +0 -1
- package/dist/components/NavSide/index.js +0 -2
- package/dist/components/NavSide/index.js.map +0 -1
- package/dist/components/NavSide/types.d.ts +0 -38
- package/dist/components/NavSide/types.d.ts.map +0 -1
- package/dist/components/NavSide/types.js +0 -2
- package/dist/components/NavSide/types.js.map +0 -1
- package/dist/components/Pagination/Pagination.d.ts +0 -35
- package/dist/components/Pagination/Pagination.d.ts.map +0 -1
- package/dist/components/Pagination/Pagination.js +0 -26
- package/dist/components/Pagination/Pagination.js.map +0 -1
- package/dist/components/Pagination/index.d.ts +0 -3
- package/dist/components/Pagination/index.d.ts.map +0 -1
- package/dist/components/Pagination/index.js +0 -2
- package/dist/components/Pagination/index.js.map +0 -1
- package/dist/components/Skeleton/Skeleton.d.ts +0 -3
- package/dist/components/Skeleton/Skeleton.d.ts.map +0 -1
- package/dist/components/Skeleton/Skeleton.js +0 -7
- package/dist/components/Skeleton/Skeleton.js.map +0 -1
- package/dist/components/Skeleton/index.d.ts +0 -2
- package/dist/components/Skeleton/index.d.ts.map +0 -1
- package/dist/components/Skeleton/index.js +0 -2
- package/dist/components/Skeleton/index.js.map +0 -1
- package/dist/components/StatsCard/StatsCard.d.ts +0 -17
- package/dist/components/StatsCard/StatsCard.d.ts.map +0 -1
- package/dist/components/StatsCard/StatsCard.js +0 -13
- package/dist/components/StatsCard/StatsCard.js.map +0 -1
- package/dist/components/StatsCard/index.d.ts +0 -2
- package/dist/components/StatsCard/index.d.ts.map +0 -1
- package/dist/components/StatsCard/index.js +0 -2
- package/dist/components/StatsCard/index.js.map +0 -1
- package/dist/styles.css +0 -2
- package/dist/theme.generated.css +0 -438
- package/src/components/Avatar/Avatar.tsx +0 -19
- package/src/components/Avatar/index.ts +0 -1
- package/src/components/Breadcrumb/Breadcrumb.tsx +0 -47
- package/src/components/Breadcrumb/index.ts +0 -5
- package/src/components/ColorDot/ColorDot.tsx +0 -50
- package/src/components/ColorDot/index.ts +0 -1
- package/src/components/EmptyState/EmptyState.tsx +0 -29
- package/src/components/EmptyState/index.ts +0 -1
- package/src/components/HeatMap/HeatMapCalendar.tsx +0 -127
- package/src/components/HeatMap/HeatMapMatrix.tsx +0 -75
- package/src/components/HeatMap/heat-map.utils.ts +0 -15
- package/src/components/HeatMap/index.ts +0 -3
- package/src/components/MetricList/MetricList.tsx +0 -13
- package/src/components/MetricList/MetricRow.tsx +0 -30
- package/src/components/MetricList/index.ts +0 -2
- package/src/components/NavBottom/NavBottom.tsx +0 -53
- package/src/components/NavBottom/index.ts +0 -3
- package/src/components/NavSide/NavItem.tsx +0 -39
- package/src/components/NavSide/NavSide.tsx +0 -40
- package/src/components/NavSide/index.ts +0 -2
- package/src/components/NavSide/types.ts +0 -36
- package/src/components/Pagination/Pagination.tsx +0 -86
- package/src/components/Pagination/index.ts +0 -2
- package/src/components/Skeleton/Skeleton.tsx +0 -7
- package/src/components/Skeleton/index.ts +0 -1
- package/src/components/StatsCard/StatsCard.tsx +0 -40
- package/src/components/StatsCard/index.ts +0 -1
- package/src/styles/base.css +0 -41
- package/src/theme/palette.json +0 -100
- package/src/theme/palette.schema.json +0 -40
- package/src/theme/theme.json +0 -349
- package/src/theme/theme.schema.json +0 -876
- package/src/theme/typography.json +0 -7
- package/src/theme/typography.schema.json +0 -36
- package/tailwind.config.ts +0 -261
|
@@ -2,16 +2,86 @@ import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss,
|
|
|
2
2
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
3
|
import { cn } from "@sixthshift/design-system/utils";
|
|
4
4
|
import { Calendar as CalendarIcon, X } from "lucide-react";
|
|
5
|
-
import
|
|
6
|
-
import { useCallback, useId, useState } from "react";
|
|
7
|
-
import {
|
|
8
|
-
|
|
5
|
+
import * as React from "react";
|
|
6
|
+
import { useCallback, useId, useMemo, useRef, useState } from "react";
|
|
7
|
+
import {
|
|
8
|
+
adaptDisabledDates,
|
|
9
|
+
fromISODate,
|
|
10
|
+
fromISODateOrUndefined,
|
|
11
|
+
fromISODateRange,
|
|
12
|
+
type ISODate,
|
|
13
|
+
type ISODateRange,
|
|
14
|
+
isPlainDate,
|
|
15
|
+
type Temporal,
|
|
16
|
+
today,
|
|
17
|
+
toISODate,
|
|
18
|
+
toISODateOrUndefined,
|
|
19
|
+
toISODateRange,
|
|
20
|
+
} from "../../date-time";
|
|
21
|
+
import { PickerField } from "../../internal";
|
|
22
|
+
import { CalendarView } from "../Calendar/CalendarView";
|
|
23
|
+
import { isDateDisabled } from "../Calendar/calendar.hooks";
|
|
24
|
+
import type { PresetOption } from "../Calendar/calendar.types";
|
|
25
|
+
import { DateSegments } from "./DateSegments";
|
|
9
26
|
import { defaultFormatDisplay, getDisplayValue, temporalToISO } from "./datepicker.hooks";
|
|
10
27
|
import type { DatePickerProps, DateRangeValue } from "./datepicker.types";
|
|
11
28
|
|
|
12
29
|
export type { DatePickerProps };
|
|
13
30
|
|
|
14
|
-
|
|
31
|
+
/** The Temporal-shaped value the picker holds internally, across all modes. */
|
|
32
|
+
type InternalValue = Temporal.PlainDate | DateRangeValue | Temporal.PlainDate[] | undefined;
|
|
33
|
+
|
|
34
|
+
/** Widen a public, mode-appropriate ISO value to {@link InternalValue}. */
|
|
35
|
+
function toTemporal(mode: DatePickerProps["mode"], value: ISODate | ISODateRange | ISODate[] | undefined): InternalValue {
|
|
36
|
+
if (mode === "multiple") return ((value as ISODate[] | undefined) ?? []).map(fromISODate);
|
|
37
|
+
if (mode === "range") return fromISODateRange(value as ISODateRange | undefined);
|
|
38
|
+
return fromISODateOrUndefined(value as ISODate | undefined);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* A typeable date field and a `Calendar` popover, as one control. `mode`
|
|
43
|
+
* (`"single" | "range" | "multiple"`, default `"single"`) decides the shape of
|
|
44
|
+
* `value`/`defaultValue`/`onChange`: an `ISODate` string, an `ISODateRange`
|
|
45
|
+
* (`{ from?, to? }`), or an `ISODate[]`.
|
|
46
|
+
*
|
|
47
|
+
* In `single` mode the field is three `role="spinbutton"` segments rather than a
|
|
48
|
+
* text box. It is built to be typed straight through: `152026` is January the
|
|
49
|
+
* 5th 2026, because a digit that cannot extend the segment being typed rolls
|
|
50
|
+
* into the next one instead of restarting it. Separators (`/`, `-`, `.`) say
|
|
51
|
+
* done-with-this-one, arrows step a segment, `Backspace` takes back one digit
|
|
52
|
+
* (then clears, then steps back), `Alt+ArrowDown` opens the grid and moves focus
|
|
53
|
+
* there, and a paste fills all three. Segments rather than free
|
|
54
|
+
* text because `08/09` cannot be read without knowing the order: `segmentOrder`
|
|
55
|
+
* (default `mdy`) says which, the labels say it to a screen reader, and no
|
|
56
|
+
* parser has to guess. `range` and `multiple` keep the read-only text trigger —
|
|
57
|
+
* a list of dates has no sensible typed form.
|
|
58
|
+
*
|
|
59
|
+
* Typing and picking move one value. The segments show the draft while the
|
|
60
|
+
* popover is open and the committed value while it is closed, so typing a date
|
|
61
|
+
* moves the grid to it and picking a day shows up in the segments. The commit
|
|
62
|
+
* contract stays single: while the popover is open its Apply/Cancel owns the
|
|
63
|
+
* value (`Enter` in a segment is Apply); while it is closed, a date commits as
|
|
64
|
+
* soon as all three segments describe one. A partial date is never reported —
|
|
65
|
+
* clearing a segment reports `undefined`.
|
|
66
|
+
*
|
|
67
|
+
* Supports both controlled (`value`/`onChange`) and uncontrolled
|
|
68
|
+
* (`defaultValue`) use. Opening the popover seeds a draft from the committed
|
|
69
|
+
* value; picking a date only updates the draft; the footer's Apply commits it
|
|
70
|
+
* and closes, Cancel discards it and reverts to the last committed value. The
|
|
71
|
+
* clear button (hidden when `clearable={false}`) bypasses the draft and
|
|
72
|
+
* commits immediately.
|
|
73
|
+
*
|
|
74
|
+
* `minDate`/`maxDate` bound selectable dates inclusively; `disabled` accepts a
|
|
75
|
+
* single date, a list, or a declarative matcher (before/after/range/weekday)
|
|
76
|
+
* or predicate — see `DisabledDates`. `presets` renders a sidebar of quick
|
|
77
|
+
* picks whose values must match `mode`. When `name` is set, the committed
|
|
78
|
+
* value is mirrored into hidden `<input>`s for native form submission
|
|
79
|
+
* (`name.from`/`name.to` in range mode, `name[]` per entry in multiple mode).
|
|
80
|
+
*
|
|
81
|
+
* Keyboard interaction — arrow keys/Home/End/PageUp/PageDown on the day
|
|
82
|
+
* grid — is inherited from `Calendar`.
|
|
83
|
+
*/
|
|
84
|
+
export const DatePicker = React.forwardRef<HTMLDivElement, DatePickerProps>((props, ref) => {
|
|
15
85
|
const {
|
|
16
86
|
mode = "single",
|
|
17
87
|
weekStartsOn = 0,
|
|
@@ -26,6 +96,7 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
26
96
|
className,
|
|
27
97
|
align = "end",
|
|
28
98
|
clearable = true,
|
|
99
|
+
segmentOrder = "mdy",
|
|
29
100
|
} = props;
|
|
30
101
|
|
|
31
102
|
// Get mode-specific props
|
|
@@ -36,12 +107,66 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
36
107
|
|
|
37
108
|
// Open state
|
|
38
109
|
const [open, setOpen] = useState(false);
|
|
110
|
+
// Whether the day grid should take focus when the popover mounts — true only
|
|
111
|
+
// when the popover was opened from the keyboard. See `openWithGridFocus`.
|
|
112
|
+
const [autoFocusDay, setAutoFocusDay] = useState(false);
|
|
113
|
+
|
|
114
|
+
// ---------------------------------------------------------------------------
|
|
115
|
+
// The ISO boundary.
|
|
116
|
+
//
|
|
117
|
+
// Props arrive as canonical ISO strings and callbacks emit them; everything
|
|
118
|
+
// below this block — state, the calendar grid, display formatting — works in
|
|
119
|
+
// Temporal, exactly as before.
|
|
120
|
+
//
|
|
121
|
+
// Each conversion is memoised on the string it derives from. Temporal values
|
|
122
|
+
// have no value identity, so converting unmemoised would hand CalendarView a
|
|
123
|
+
// fresh object every render and invalidate its grid memos. Strings compare by
|
|
124
|
+
// value, which makes this strictly more stable than passing Temporal in.
|
|
125
|
+
// ---------------------------------------------------------------------------
|
|
126
|
+
|
|
127
|
+
const temporalMinDate = useMemo(() => fromISODateOrUndefined(minDate), [minDate]);
|
|
128
|
+
const temporalMaxDate = useMemo(() => fromISODateOrUndefined(maxDate), [maxDate]);
|
|
129
|
+
const temporalDisabled = useMemo(() => adaptDisabledDates(disabled), [disabled]);
|
|
130
|
+
|
|
131
|
+
const temporalPresets = useMemo(() => {
|
|
132
|
+
if (!presets) return undefined;
|
|
133
|
+
if (mode === "single") {
|
|
134
|
+
return (presets as PresetOption<ISODate>[]).map((preset) => ({ label: preset.label, value: fromISODate(preset.value) }));
|
|
135
|
+
}
|
|
136
|
+
if (mode === "multiple") {
|
|
137
|
+
return (presets as PresetOption<ISODate[]>[]).map((preset) => ({ label: preset.label, value: preset.value.map(fromISODate) }));
|
|
138
|
+
}
|
|
139
|
+
return (presets as PresetOption<ISODateRange>[]).map((preset) => ({
|
|
140
|
+
label: preset.label,
|
|
141
|
+
value: fromISODateRange(preset.value) ?? { from: undefined, to: undefined },
|
|
142
|
+
}));
|
|
143
|
+
}, [mode, presets]);
|
|
144
|
+
|
|
145
|
+
const temporalValue = useMemo(() => toTemporal(mode, value), [mode, value]);
|
|
146
|
+
// Read once, on mount, by useControllableState's useState initialiser.
|
|
147
|
+
const temporalDefaultValue = useMemo(() => toTemporal(mode, defaultValue), [mode, defaultValue]);
|
|
148
|
+
|
|
149
|
+
const handleChange = useCallback(
|
|
150
|
+
(next: InternalValue) => {
|
|
151
|
+
if (!onChange) return;
|
|
152
|
+
if (mode === "single") {
|
|
153
|
+
(onChange as (date: ISODate | undefined) => void)(toISODateOrUndefined(next as Temporal.PlainDate | undefined));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
if (mode === "multiple") {
|
|
157
|
+
(onChange as (dates: ISODate[]) => void)(((next as Temporal.PlainDate[] | undefined) ?? []).map(toISODate));
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
(onChange as (range: ISODateRange | undefined) => void)(toISODateRange(next as DateRangeValue | undefined));
|
|
161
|
+
},
|
|
162
|
+
[mode, onChange]
|
|
163
|
+
);
|
|
39
164
|
|
|
40
165
|
// Controllable value state (external/committed value)
|
|
41
|
-
const [committedValue, setCommittedValue] = useControllableState({
|
|
42
|
-
value:
|
|
43
|
-
defaultValue:
|
|
44
|
-
onChange:
|
|
166
|
+
const [committedValue, setCommittedValue] = useControllableState<InternalValue>({
|
|
167
|
+
value: temporalValue,
|
|
168
|
+
defaultValue: temporalDefaultValue,
|
|
169
|
+
onChange: handleChange,
|
|
45
170
|
});
|
|
46
171
|
|
|
47
172
|
// Draft value (internal state while popup is open)
|
|
@@ -52,6 +177,8 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
52
177
|
(newOpen: boolean) => {
|
|
53
178
|
if (newOpen) {
|
|
54
179
|
setDraftValue(committedValue);
|
|
180
|
+
} else {
|
|
181
|
+
setAutoFocusDay(false);
|
|
55
182
|
}
|
|
56
183
|
setOpen(newOpen);
|
|
57
184
|
},
|
|
@@ -144,35 +271,233 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
144
271
|
|
|
145
272
|
const rangeFormValues = getRangeFormValues();
|
|
146
273
|
|
|
274
|
+
// ---------------------------------------------------------------------------
|
|
275
|
+
// The typeable field (single mode).
|
|
276
|
+
//
|
|
277
|
+
// One value, two ways to move it. The segments show the draft while the
|
|
278
|
+
// popover is open and the committed value while it is closed, which is what
|
|
279
|
+
// makes typing and clicking feel like one control: type a date and the grid
|
|
280
|
+
// follows it, click a day and the segments follow that. The commit contract
|
|
281
|
+
// stays single — open means the popover's Apply/Cancel owns it, closed means a
|
|
282
|
+
// complete date commits as soon as it is complete.
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
|
|
285
|
+
const segmentSource = open ? draftValue : committedValue;
|
|
286
|
+
const segmentValue = isPlainDate(segmentSource) ? segmentSource : undefined;
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* A typed date can be one the grid would refuse — nothing stops you typing
|
|
290
|
+
* past `maxDate`. Rather than silently clamping it (which loses what was
|
|
291
|
+
* typed) or refusing it (which strands the field mid-edit), the field says so:
|
|
292
|
+
* `aria-invalid` and the danger border, with the value still reported so the
|
|
293
|
+
* caller's own validation sees the attempt.
|
|
294
|
+
*/
|
|
295
|
+
const outOfBounds = useCallback(
|
|
296
|
+
(date: Temporal.PlainDate | undefined) => date !== undefined && isDateDisabled(date, temporalDisabled, temporalMinDate, temporalMaxDate),
|
|
297
|
+
[temporalDisabled, temporalMaxDate, temporalMinDate]
|
|
298
|
+
);
|
|
299
|
+
|
|
300
|
+
const handleSegmentsChange = useCallback(
|
|
301
|
+
(date: Temporal.PlainDate | undefined) => {
|
|
302
|
+
// Keep the grid on the month being typed, so opening it lands where the
|
|
303
|
+
// user already is rather than on today.
|
|
304
|
+
if (date) setMonth(date);
|
|
305
|
+
if (open) {
|
|
306
|
+
setDraftValue(date);
|
|
307
|
+
return;
|
|
308
|
+
}
|
|
309
|
+
setCommittedValue(date as Temporal.PlainDate | DateRangeValue | Temporal.PlainDate[]);
|
|
310
|
+
},
|
|
311
|
+
[open, setCommittedValue]
|
|
312
|
+
);
|
|
313
|
+
|
|
314
|
+
/** `Alt+ArrowDown` from a segment: open the grid *and* go there. */
|
|
315
|
+
const openWithGridFocus = useCallback(() => {
|
|
316
|
+
setAutoFocusDay(true);
|
|
317
|
+
handleOpenChange(true);
|
|
318
|
+
}, [handleOpenChange]);
|
|
319
|
+
|
|
320
|
+
/** `Enter` in a segment commits the draft, matching the popover's Apply. */
|
|
321
|
+
const handleFieldSubmit = useCallback(() => {
|
|
322
|
+
if (open) handleApply();
|
|
323
|
+
}, [handleApply, open]);
|
|
324
|
+
|
|
325
|
+
// ---------------------------------------------------------------------------
|
|
326
|
+
// Range mode: two fields, not one.
|
|
327
|
+
//
|
|
328
|
+
// A range is two dates, and typing one of them should not require knowing
|
|
329
|
+
// where the other ends. Each half is its own segmented field with its own
|
|
330
|
+
// clear button; they share the one popover, which anchors to whichever half
|
|
331
|
+
// you are in so it opens under the date you are editing.
|
|
332
|
+
// ---------------------------------------------------------------------------
|
|
333
|
+
|
|
334
|
+
const rangeSource = (open ? draftValue : committedValue) as DateRangeValue | undefined;
|
|
335
|
+
|
|
336
|
+
const setRangeEnd = useCallback(
|
|
337
|
+
(end: "from" | "to", date: Temporal.PlainDate | undefined) => {
|
|
338
|
+
if (date) setMonth(date);
|
|
339
|
+
const current = (open ? draftValue : committedValue) as DateRangeValue | undefined;
|
|
340
|
+
const next: DateRangeValue = { from: current?.from, to: current?.to, [end]: date };
|
|
341
|
+
if (open) {
|
|
342
|
+
setDraftValue(next);
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
setCommittedValue(next as Temporal.PlainDate | DateRangeValue | Temporal.PlainDate[]);
|
|
346
|
+
},
|
|
347
|
+
[committedValue, draftValue, open, setCommittedValue]
|
|
348
|
+
);
|
|
349
|
+
|
|
350
|
+
const clearRangeEnd = useCallback(
|
|
351
|
+
(end: "from" | "to") => (event: React.MouseEvent) => {
|
|
352
|
+
event.stopPropagation();
|
|
353
|
+
event.preventDefault();
|
|
354
|
+
const existing = committedValue as DateRangeValue | undefined;
|
|
355
|
+
const next: DateRangeValue = {
|
|
356
|
+
from: end === "from" ? undefined : existing?.from,
|
|
357
|
+
to: end === "to" ? undefined : existing?.to,
|
|
358
|
+
};
|
|
359
|
+
// Clearing the last remaining end clears the range itself, so a consumer
|
|
360
|
+
// gets `undefined` rather than a husk with two empty ends.
|
|
361
|
+
const cleared = !next.from && !next.to;
|
|
362
|
+
setCommittedValue((cleared ? undefined : next) as Temporal.PlainDate | DateRangeValue | Temporal.PlainDate[]);
|
|
363
|
+
},
|
|
364
|
+
[committedValue, setCommittedValue]
|
|
365
|
+
);
|
|
366
|
+
|
|
367
|
+
// The popover anchors to the half being edited, so it opens under the date in
|
|
368
|
+
// question rather than under the middle of a wide trigger.
|
|
369
|
+
const rangeHalves = useRef<Record<"from" | "to", HTMLDivElement | null>>({ from: null, to: null });
|
|
370
|
+
const anchorToHalf = useCallback(
|
|
371
|
+
(end: "from" | "to") => {
|
|
372
|
+
const node = rangeHalves.current[end];
|
|
373
|
+
if (node) refs.setPositionReference(node);
|
|
374
|
+
},
|
|
375
|
+
[refs]
|
|
376
|
+
);
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* One end of the range. A render function rather than a component so the
|
|
380
|
+
* fields are not remounted — and so focus is not dropped — on every keystroke.
|
|
381
|
+
*/
|
|
382
|
+
const renderRangeHalf = (end: "from" | "to", label: string) => {
|
|
383
|
+
const shown = end === "from" ? rangeSource?.from : rangeSource?.to;
|
|
384
|
+
const settled = end === "from" ? (committedValue as DateRangeValue | undefined)?.from : (committedValue as DateRangeValue | undefined)?.to;
|
|
385
|
+
|
|
386
|
+
return (
|
|
387
|
+
<PickerField
|
|
388
|
+
ref={(node) => {
|
|
389
|
+
rangeHalves.current[end] = node;
|
|
390
|
+
}}
|
|
391
|
+
onFocusCapture={() => anchorToHalf(end)}
|
|
392
|
+
className="min-w-45 flex-1"
|
|
393
|
+
icon={<CalendarIcon className="h-4 w-4" />}
|
|
394
|
+
toggleLabel={`Open calendar for ${label.toLowerCase()}`}
|
|
395
|
+
// Both handlers have to run: Floating UI's opens the popover, and ours
|
|
396
|
+
// points it at this half. Spreading after `onClick` would drop ours on
|
|
397
|
+
// the floor, which is how the popover ended up anchored to the whole
|
|
398
|
+
// trigger.
|
|
399
|
+
toggleProps={getReferenceProps({ onClick: () => anchorToHalf(end) })}
|
|
400
|
+
isOpen={open}
|
|
401
|
+
contentId={contentId}
|
|
402
|
+
isDisabled={isDisabled}
|
|
403
|
+
isInvalid={isInvalid || outOfBounds(shown)}
|
|
404
|
+
onClear={clearable && settled && !isDisabled ? clearRangeEnd(end) : undefined}
|
|
405
|
+
clearLabel={`Clear ${label.toLowerCase()}`}
|
|
406
|
+
>
|
|
407
|
+
<DateSegments
|
|
408
|
+
className="h-full flex-1"
|
|
409
|
+
label={label}
|
|
410
|
+
value={shown}
|
|
411
|
+
onChange={(date) => setRangeEnd(end, date)}
|
|
412
|
+
order={segmentOrder}
|
|
413
|
+
isDisabled={isDisabled}
|
|
414
|
+
isInvalid={isInvalid || outOfBounds(shown)}
|
|
415
|
+
onOpenRequest={() => {
|
|
416
|
+
anchorToHalf(end);
|
|
417
|
+
openWithGridFocus();
|
|
418
|
+
}}
|
|
419
|
+
onSubmit={handleFieldSubmit}
|
|
420
|
+
/>
|
|
421
|
+
</PickerField>
|
|
422
|
+
);
|
|
423
|
+
};
|
|
424
|
+
|
|
147
425
|
return (
|
|
148
426
|
<>
|
|
149
427
|
{/* Trigger Input */}
|
|
150
|
-
<div
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
className
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
428
|
+
<div
|
|
429
|
+
ref={(node) => {
|
|
430
|
+
// The container is the interaction reference, so a click in either
|
|
431
|
+
// range half counts as inside; range mode then re-points the
|
|
432
|
+
// *position* reference at the half being edited.
|
|
433
|
+
refs.setReference(node);
|
|
434
|
+
if (typeof ref === "function") ref(node);
|
|
435
|
+
else if (ref) (ref as React.MutableRefObject<HTMLDivElement | null>).current = node;
|
|
436
|
+
}}
|
|
437
|
+
className={cn("relative flex items-center gap-2", mode === "range" && "min-w-91.25", mode !== "range" && "min-w-65")}
|
|
438
|
+
>
|
|
439
|
+
{mode === "range" ? (
|
|
440
|
+
<>
|
|
441
|
+
{renderRangeHalf("from", "Start date")}
|
|
442
|
+
<span aria-hidden="true" className="text-fg-subtle">
|
|
443
|
+
–
|
|
444
|
+
</span>
|
|
445
|
+
{renderRangeHalf("to", "End date")}
|
|
446
|
+
</>
|
|
447
|
+
) : mode === "single" ? (
|
|
448
|
+
<PickerField
|
|
449
|
+
className={cn("w-full min-w-65", className)}
|
|
450
|
+
icon={<CalendarIcon className="h-4 w-4" />}
|
|
451
|
+
toggleLabel="Open calendar"
|
|
452
|
+
toggleProps={getReferenceProps()}
|
|
453
|
+
isOpen={open}
|
|
454
|
+
contentId={contentId}
|
|
455
|
+
isDisabled={isDisabled}
|
|
456
|
+
isInvalid={isInvalid || outOfBounds(segmentValue)}
|
|
457
|
+
onClear={clearable && hasValue && !isDisabled ? handleClear : undefined}
|
|
458
|
+
clearLabel="Clear date"
|
|
459
|
+
>
|
|
460
|
+
<DateSegments
|
|
461
|
+
className="h-full flex-1"
|
|
462
|
+
id={inputId}
|
|
463
|
+
value={segmentValue}
|
|
464
|
+
onChange={handleSegmentsChange}
|
|
465
|
+
order={segmentOrder}
|
|
466
|
+
isDisabled={isDisabled}
|
|
467
|
+
isInvalid={isInvalid || outOfBounds(segmentValue)}
|
|
468
|
+
onOpenRequest={openWithGridFocus}
|
|
469
|
+
onSubmit={handleFieldSubmit}
|
|
470
|
+
/>
|
|
471
|
+
</PickerField>
|
|
472
|
+
) : (
|
|
473
|
+
<>
|
|
474
|
+
<CalendarIcon className="pointer-events-none absolute left-3 h-4 w-4 text-fg-subtle" />
|
|
475
|
+
<input
|
|
476
|
+
id={inputId}
|
|
477
|
+
type="text"
|
|
478
|
+
readOnly
|
|
479
|
+
value={displayValue}
|
|
480
|
+
placeholder={placeholder}
|
|
481
|
+
disabled={isDisabled}
|
|
482
|
+
role="combobox"
|
|
483
|
+
aria-invalid={isInvalid}
|
|
484
|
+
aria-haspopup="dialog"
|
|
485
|
+
aria-expanded={open}
|
|
486
|
+
aria-controls={open ? contentId : undefined}
|
|
487
|
+
className={cn(
|
|
488
|
+
`flex h-9 w-full cursor-pointer rounded-md border border-border-normal bg-transparent py-1 pl-9 text-sm shadow-xs transition-colors placeholder:text-fg-subtle focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-focus-ring disabled:cursor-not-allowed disabled:opacity-50`,
|
|
489
|
+
"min-w-65",
|
|
490
|
+
clearable && hasValue ? "pr-9" : "pr-3",
|
|
491
|
+
isInvalid && "border-border-danger",
|
|
492
|
+
className
|
|
493
|
+
)}
|
|
494
|
+
{...getReferenceProps()}
|
|
495
|
+
/>
|
|
496
|
+
</>
|
|
497
|
+
)}
|
|
498
|
+
{/* `multiple` mode still uses the read-only input, so its clear button
|
|
499
|
+
stays here; the other two modes get theirs from `PickerField`. */}
|
|
500
|
+
{clearable && hasValue && !isDisabled && mode === "multiple" && (
|
|
176
501
|
<button
|
|
177
502
|
type="button"
|
|
178
503
|
onClick={handleClear}
|
|
@@ -205,27 +530,28 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
205
530
|
ref={refs.setFloating}
|
|
206
531
|
id={contentId}
|
|
207
532
|
role="dialog"
|
|
208
|
-
aria-
|
|
533
|
+
aria-label="Choose date"
|
|
209
534
|
style={floatingStyles}
|
|
210
535
|
className="z-popover rounded-xl border border-border-normal bg-bg-normal p-4 shadow-lg"
|
|
211
536
|
{...getFloatingProps()}
|
|
212
537
|
>
|
|
213
538
|
{/* @ts-expect-error - TypeScript can't properly narrow discriminated union props across component boundaries */}
|
|
214
|
-
<
|
|
539
|
+
<CalendarView
|
|
215
540
|
mode={mode}
|
|
216
541
|
value={draftValue}
|
|
217
542
|
onSelect={setDraftValue}
|
|
218
543
|
month={month}
|
|
219
544
|
onMonthChange={setMonth}
|
|
220
|
-
minDate={
|
|
221
|
-
maxDate={
|
|
222
|
-
disabled={
|
|
545
|
+
minDate={temporalMinDate}
|
|
546
|
+
maxDate={temporalMaxDate}
|
|
547
|
+
disabled={temporalDisabled}
|
|
223
548
|
weekStartsOn={weekStartsOn}
|
|
224
|
-
presets={
|
|
549
|
+
presets={temporalPresets}
|
|
225
550
|
showFooter
|
|
226
551
|
showToday={mode !== "range"}
|
|
227
552
|
onApply={handleApply}
|
|
228
553
|
onCancel={handleCancel}
|
|
554
|
+
autoFocusDay={autoFocusDay}
|
|
229
555
|
{...(mode === "multiple" && max ? { max } : {})}
|
|
230
556
|
/>
|
|
231
557
|
</div>
|
|
@@ -233,4 +559,5 @@ export const DatePicker = (props: DatePickerProps) => {
|
|
|
233
559
|
)}
|
|
234
560
|
</>
|
|
235
561
|
);
|
|
236
|
-
};
|
|
562
|
+
});
|
|
563
|
+
DatePicker.displayName = "DatePicker";
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import { type Temporal, today, toISODate } from "../../date-time";
|
|
2
|
+
import { SegmentedField, type SegmentSpec, type SegmentValues } from "../../internal";
|
|
3
|
+
import type { DateSegmentOrder } from "./datepicker.types";
|
|
4
|
+
|
|
5
|
+
type SegmentName = "day" | "month" | "year";
|
|
6
|
+
|
|
7
|
+
export type DateSegmentsProps = {
|
|
8
|
+
/** The date the segments display. `undefined` leaves them empty. */
|
|
9
|
+
value: Temporal.PlainDate | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* Fires with a complete date, or `undefined` the moment the segments stop
|
|
12
|
+
* describing one. Never fires a partial date.
|
|
13
|
+
*/
|
|
14
|
+
onChange: (date: Temporal.PlainDate | undefined) => void;
|
|
15
|
+
order?: DateSegmentOrder | undefined;
|
|
16
|
+
isDisabled?: boolean | undefined;
|
|
17
|
+
isInvalid?: boolean | undefined;
|
|
18
|
+
/** Accessible name for the segment group. */
|
|
19
|
+
label?: string | undefined;
|
|
20
|
+
/** `Alt+ArrowDown` — the combobox convention for "open the popup". */
|
|
21
|
+
onOpenRequest?: (() => void) | undefined;
|
|
22
|
+
/** `Enter` — the caller decides whether that means commit, submit or nothing. */
|
|
23
|
+
onSubmit?: (() => void) | undefined;
|
|
24
|
+
id?: string | undefined;
|
|
25
|
+
className?: string | undefined;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export const DATE_ORDERS: Record<DateSegmentOrder, SegmentName[]> = {
|
|
29
|
+
mdy: ["month", "day", "year"],
|
|
30
|
+
dmy: ["day", "month", "year"],
|
|
31
|
+
ymd: ["year", "month", "day"],
|
|
32
|
+
};
|
|
33
|
+
|
|
34
|
+
const BASE: Record<SegmentName, Omit<Extract<SegmentSpec, { kind?: "numeric" }>, "separatorBefore" | "stepFrom">> = {
|
|
35
|
+
day: { name: "day", label: "Day", placeholder: "dd", digits: 2, min: 1, max: 31 },
|
|
36
|
+
month: { name: "month", label: "Month", placeholder: "mm", digits: 2, min: 1, max: 12 },
|
|
37
|
+
year: { name: "year", label: "Year", placeholder: "yyyy", digits: 4, min: 1, max: 9999 },
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/** Days in a (year, month). `day: 1` keeps `with` from constraining a stale day. */
|
|
41
|
+
const daysInMonth = (year: number, month: number) => today().with({ year, month, day: 1 }).daysInMonth;
|
|
42
|
+
|
|
43
|
+
export const dateToSegments = (date: Temporal.PlainDate | undefined): SegmentValues =>
|
|
44
|
+
date ? { day: date.day, month: date.month, year: date.year } : { day: null, month: null, year: null };
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* The day is clamped rather than rejected: typing `31` and then moving the month
|
|
48
|
+
* to February is a normal editing path, and snapping to the 28th keeps the field
|
|
49
|
+
* describing a date the user can see and correct. Nothing else can be out of
|
|
50
|
+
* range — the segments cap themselves as they are typed.
|
|
51
|
+
*/
|
|
52
|
+
export const dateFromSegments = (values: Record<string, number>): Temporal.PlainDate => {
|
|
53
|
+
const year = values.year!;
|
|
54
|
+
const month = values.month!;
|
|
55
|
+
return today().with({ year, month, day: Math.min(values.day!, daysInMonth(year, month)) });
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* ISO is always accepted — it is unambiguous, and it is what the rest of the
|
|
60
|
+
* library speaks. Anything else is read in the field's own segment order, which
|
|
61
|
+
* is the only reading that cannot be wrong.
|
|
62
|
+
*/
|
|
63
|
+
export function parseDatePasteIn(order: DateSegmentOrder) {
|
|
64
|
+
return (text: string): SegmentValues | null => {
|
|
65
|
+
const iso = /^(\d{4})-(\d{2})-(\d{2})$/.exec(text);
|
|
66
|
+
const parts = iso ? [iso[1]!, iso[2]!, iso[3]!] : text.split(/[/\-.\s]+/);
|
|
67
|
+
const names = iso ? DATE_ORDERS.ymd : DATE_ORDERS[order];
|
|
68
|
+
if (parts.length !== 3 || parts.some((part) => !/^\d+$/.test(part))) return null;
|
|
69
|
+
|
|
70
|
+
const next: SegmentValues = { day: null, month: null, year: null };
|
|
71
|
+
names.forEach((name, index) => {
|
|
72
|
+
const numeric = Number(parts[index]);
|
|
73
|
+
next[name] = numeric >= BASE[name].min && numeric <= BASE[name].max ? numeric : null;
|
|
74
|
+
});
|
|
75
|
+
return next;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The typeable half of `DatePicker`: a date as three spinbutton segments.
|
|
81
|
+
*
|
|
82
|
+
* A thin spec over `SegmentedField`, which owns the keyboard model — digits
|
|
83
|
+
* rolling forward, separators, digit-aware `Backspace`, deferred `onChange`.
|
|
84
|
+
* What belongs to dates specifically lives here: the segment order (never
|
|
85
|
+
* inferred from the locale, because `08/09` is a different date under each),
|
|
86
|
+
* clamping the day to the month, and accepting a pasted ISO date.
|
|
87
|
+
*
|
|
88
|
+
* Internal to `DatePicker`; not exported from `./index.ts`.
|
|
89
|
+
*/
|
|
90
|
+
/**
|
|
91
|
+
* The three date segments in the given order.
|
|
92
|
+
*
|
|
93
|
+
* Exported because `DateTimePicker` builds one field out of these plus the time
|
|
94
|
+
* segments, rather than two fields glued together.
|
|
95
|
+
*/
|
|
96
|
+
export function dateSpec(order: DateSegmentOrder): SegmentSpec[] {
|
|
97
|
+
const separator = order === "ymd" ? "-" : "/";
|
|
98
|
+
const current = dateToSegments(today());
|
|
99
|
+
|
|
100
|
+
return DATE_ORDERS[order].map((name, index) => ({
|
|
101
|
+
...BASE[name],
|
|
102
|
+
// An arrow key on an empty segment starts from today, not from 1: the year
|
|
103
|
+
// is the segment most likely to already be right.
|
|
104
|
+
stepFrom: current[name] ?? BASE[name].min,
|
|
105
|
+
separatorBefore: index > 0 ? separator : undefined,
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function DateSegments({ value, onChange, order = "mdy", label = "Date", ...rest }: DateSegmentsProps) {
|
|
110
|
+
const spec = dateSpec(order);
|
|
111
|
+
|
|
112
|
+
return (
|
|
113
|
+
<SegmentedField<Temporal.PlainDate>
|
|
114
|
+
spec={spec}
|
|
115
|
+
value={value}
|
|
116
|
+
toSegments={dateToSegments}
|
|
117
|
+
fromSegments={dateFromSegments}
|
|
118
|
+
keyOf={toISODate}
|
|
119
|
+
onChange={onChange}
|
|
120
|
+
parsePaste={parseDatePasteIn(order)}
|
|
121
|
+
label={label}
|
|
122
|
+
{...rest}
|
|
123
|
+
/>
|
|
124
|
+
);
|
|
125
|
+
}
|