@sixthshift/design-system 0.3.0 → 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 +114 -12
- package/dist/components/Badge/Badge.d.ts +64 -9
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +54 -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 +12 -0
- package/dist/components/BarChart/BarChart.d.ts.map +1 -1
- package/dist/components/BarChart/BarChart.js +12 -0
- 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 +18 -4
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +19 -5
- package/dist/components/Calendar/Calendar.js.map +1 -1
- package/dist/components/Calendar/CalendarView.d.ts.map +1 -1
- package/dist/components/Calendar/CalendarView.js +10 -2
- package/dist/components/Calendar/CalendarView.js.map +1 -1
- package/dist/components/Calendar/calendar.types.d.ts +9 -0
- package/dist/components/Calendar/calendar.types.d.ts.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 +43 -0
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +166 -4
- 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 +19 -1
- package/dist/components/DatePicker/datepicker.types.d.ts.map +1 -1
- package/dist/components/DatePicker/index.d.ts +1 -1
- package/dist/components/DatePicker/index.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.d.ts +20 -2
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +22 -4
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts +6 -1
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.d.ts +30 -2
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +105 -32
- 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 +6 -1
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts +28 -2
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +136 -58
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts +6 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts.map +1 -1
- package/dist/components/Field/Field.d.ts +15 -17
- package/dist/components/Field/Field.d.ts.map +1 -1
- package/dist/components/Field/Field.js +18 -3
- 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 +17 -0
- package/dist/components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/components/LineChart/LineChart.js +17 -0
- package/dist/components/LineChart/LineChart.js.map +1 -1
- package/dist/components/Markdown/Markdown.d.ts +17 -0
- package/dist/components/Markdown/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown/Markdown.js +17 -0
- 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 +53 -17
- 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 +36 -0
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +37 -1
- package/dist/components/Modal/Modal.js.map +1 -1
- package/dist/components/Modal/components/ModalHeader.js +1 -1
- 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 +29 -0
- package/dist/components/Popover/Popover.js.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts +14 -0
- package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.js +14 -0
- 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 +4 -5
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +4 -5
- package/dist/components/Select/Select.js.map +1 -1
- package/dist/components/Select/SelectDropdown.d.ts.map +1 -1
- package/dist/components/Select/SelectDropdown.js +4 -3
- package/dist/components/Select/SelectDropdown.js.map +1 -1
- package/dist/components/Select/SelectTrigger.js +2 -2
- package/dist/components/Select/SelectTrigger.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 +6 -0
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +7 -1
- package/dist/components/Sheet/Sheet.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.js +1 -1
- package/dist/components/Sheet/components/SheetHeader.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.d.ts +11 -0
- package/dist/components/Sparkline/Sparkline.d.ts.map +1 -1
- package/dist/components/Sparkline/Sparkline.js +11 -0
- 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 +6 -0
- 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/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 +14 -12
- package/dist/components/TagChip/TagChip.d.ts.map +1 -1
- package/dist/components/TagChip/TagChip.js +14 -1
- package/dist/components/TagChip/TagChip.js.map +1 -1
- package/dist/components/TagInput/TagInput.d.ts +11 -8
- package/dist/components/TagInput/TagInput.d.ts.map +1 -1
- package/dist/components/TagInput/TagInput.js +11 -0
- 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 +32 -0
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +93 -6
- 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 +0 -2
- package/dist/components/TimePicker/timepicker.types.d.ts.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.map +1 -1
- package/dist/date-time/index.js +0 -1
- package/dist/date-time/index.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 +2 -2
- package/dist/theme/index.d.ts.map +1 -1
- package/dist/theme/index.js +1 -1
- package/dist/theme/index.js.map +1 -1
- package/dist/theme/schema.d.ts +0 -22
- package/dist/theme/schema.d.ts.map +1 -1
- package/dist/theme/schema.js +0 -9
- package/dist/theme/schema.js.map +1 -1
- package/package.json +3 -45
- package/src/components/Badge/Badge.tsx +85 -48
- package/src/components/Badge/index.ts +10 -1
- package/src/components/BarChart/BarChart.tsx +12 -0
- package/src/components/Button/Button.tsx +129 -106
- package/src/components/Button/index.ts +10 -1
- package/src/components/Calendar/Calendar.tsx +29 -16
- package/src/components/Calendar/CalendarView.tsx +10 -1
- package/src/components/Calendar/calendar.types.ts +10 -0
- 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 +279 -28
- package/src/components/DatePicker/DateSegments.tsx +125 -0
- package/src/components/DatePicker/datepicker.types.ts +21 -1
- package/src/components/DatePicker/index.ts +8 -1
- package/src/components/DateRangePicker/DateRangePicker.tsx +22 -4
- package/src/components/DateRangePicker/daterangepicker.types.ts +7 -1
- package/src/components/DateTimePicker/DateTimePicker.tsx +143 -70
- package/src/components/DateTimePicker/DateTimeSegments.tsx +113 -0
- package/src/components/DateTimePicker/datetimepicker.types.ts +7 -1
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +195 -104
- package/src/components/DateTimeRangePicker/datetimerangepicker.types.ts +7 -1
- package/src/components/Field/Field.tsx +20 -22
- 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 +17 -0
- package/src/components/Markdown/Markdown.tsx +17 -0
- package/src/components/Message/Message.tsx +73 -23
- package/src/components/Message/index.ts +1 -1
- package/src/components/Modal/Modal.tsx +42 -3
- package/src/components/Modal/components/ModalHeader.tsx +1 -1
- package/src/components/Popover/Popover.tsx +29 -0
- package/src/components/ProgressBar/ProgressBar.tsx +14 -0
- 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 +4 -5
- package/src/components/Select/SelectDropdown.tsx +13 -9
- package/src/components/Select/SelectTrigger.tsx +7 -7
- package/src/components/Separator/Separator.tsx +10 -0
- package/src/components/Sheet/Sheet.tsx +8 -2
- package/src/components/Sheet/components/SheetFooter.tsx +1 -1
- package/src/components/Sheet/components/SheetHeader.tsx +2 -2
- package/src/components/Sparkline/Sparkline.tsx +11 -0
- 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/TabsTrigger.tsx +22 -5
- package/src/components/TagChip/TagChip.tsx +18 -16
- package/src/components/TagInput/TagInput.tsx +11 -8
- 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 +127 -39
- package/src/components/TimePicker/TimeSegments.tsx +131 -0
- package/src/components/TimePicker/timepicker.hooks.ts +1 -24
- package/src/components/TimePicker/timepicker.types.ts +0 -3
- 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 +0 -1
- 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 +0 -6
- 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 +0 -27
- package/src/theme/tokens.css +26 -9
- 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 -19
- package/dist/components/ColorDot/ColorDot.d.ts.map +0 -1
- package/dist/components/ColorDot/ColorDot.js +0 -36
- 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 -26
- package/dist/components/EmptyState/EmptyState.d.ts.map +0 -1
- package/dist/components/EmptyState/EmptyState.js +0 -9
- 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 -8
- 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 -16
- package/dist/components/NavBottom/NavBottom.d.ts.map +0 -1
- package/dist/components/NavBottom/NavBottom.js +0 -21
- 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 -16
- package/dist/components/NavSide/NavSide.d.ts.map +0 -1
- package/dist/components/NavSide/NavSide.js +0 -12
- 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 -4
- package/dist/components/Skeleton/Skeleton.d.ts.map +0 -1
- package/dist/components/Skeleton/Skeleton.js +0 -9
- 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 -15
- 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/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 -52
- package/src/components/ColorDot/index.ts +0 -1
- package/src/components/EmptyState/EmptyState.tsx +0 -30
- 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 -18
- package/src/components/MetricList/MetricRow.tsx +0 -30
- package/src/components/MetricList/index.ts +0 -2
- package/src/components/NavBottom/NavBottom.tsx +0 -55
- package/src/components/NavBottom/index.ts +0 -3
- package/src/components/NavSide/NavItem.tsx +0 -39
- package/src/components/NavSide/NavSide.tsx +0 -42
- 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 -9
- package/src/components/Skeleton/index.ts +0 -1
- package/src/components/StatsCard/StatsCard.tsx +0 -41
- package/src/components/StatsCard/index.ts +0 -1
|
@@ -2,22 +2,47 @@ import { cn } from "@sixthshift/design-system/utils";
|
|
|
2
2
|
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
/**
|
|
6
|
+
* Geometry (size) plus the one `--spinner-fg` component token.
|
|
7
|
+
*
|
|
8
|
+
* The colour used to be `text-fg-subtle`, a semantic token named directly in
|
|
9
|
+
* the class string — the one thing a consumer could not do was recolour a
|
|
10
|
+
* spinner without fighting `className` against it. `--spinner-fg` in
|
|
11
|
+
* src/theme/recipes/spinner.css is now that seam: a consumer overrides the
|
|
12
|
+
* variable, scoped to whatever subtree they like, instead of overriding a
|
|
13
|
+
* class.
|
|
14
|
+
*/
|
|
15
|
+
const spinnerVariants = cva("spinner animate-spin text-(--spinner-fg)", {
|
|
6
16
|
variants: {
|
|
7
17
|
size: {
|
|
8
18
|
sm: "h-4 w-4",
|
|
9
|
-
|
|
19
|
+
md: "h-6 w-6",
|
|
10
20
|
lg: "h-8 w-8",
|
|
11
21
|
xl: "h-12 w-12",
|
|
12
22
|
},
|
|
13
23
|
},
|
|
14
24
|
defaultVariants: {
|
|
15
|
-
size: "
|
|
25
|
+
size: "md",
|
|
16
26
|
},
|
|
17
27
|
});
|
|
18
28
|
|
|
19
29
|
export type SpinnerProps = React.SVGAttributes<SVGElement> & VariantProps<typeof spinnerVariants>;
|
|
20
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Animated loading indicator — an inline `<svg>`, `size` scales it (`sm` |
|
|
33
|
+
* `md` | `lg` | `xl`). Use it for a fetching-more state at the bottom
|
|
34
|
+
* of an already-rendered list, and for an initial load inside a container that
|
|
35
|
+
* already reserves its final height, so resolving the load does not jump the
|
|
36
|
+
* layout (see docs/states.md).
|
|
37
|
+
*
|
|
38
|
+
* It is `aria-hidden="true"` unconditionally — it announces nothing to
|
|
39
|
+
* assistive tech on its own, so pair it with visible or `sr-only` text (or a
|
|
40
|
+
* live region) if the loading state needs to be announced.
|
|
41
|
+
*
|
|
42
|
+
* Colour reads the `--spinner-fg` component token
|
|
43
|
+
* (src/theme/recipes/spinner.css) rather than a class name, so a consumer
|
|
44
|
+
* can recolour a spinner scoped to a subtree without fighting `className`.
|
|
45
|
+
*/
|
|
21
46
|
const Spinner = React.forwardRef<SVGSVGElement, SpinnerProps>(({ className, size, ...props }, ref) => (
|
|
22
47
|
<svg
|
|
23
48
|
ref={ref}
|
|
@@ -22,6 +22,24 @@ export type SwitchProps = Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, "o
|
|
|
22
22
|
labelClassName?: string;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* A boolean on/off control rendered as a track with a sliding thumb.
|
|
27
|
+
*
|
|
28
|
+
* Controlled via `checked`/`defaultChecked`/`onCheckedChange`
|
|
29
|
+
* (`useControllableState`). Renders `role="switch"` with `aria-checked`, plus
|
|
30
|
+
* a `data-state="checked" | "unchecked"` attribute the theme recipe
|
|
31
|
+
* (`switch.css`) styles off of.
|
|
32
|
+
*
|
|
33
|
+
* `pending` shows a spinner in the thumb and blocks clicks without disabling
|
|
34
|
+
* the control — it sets `aria-busy` rather than `disabled`, so the switch
|
|
35
|
+
* stays perceivable and focusable while the change is in flight.
|
|
36
|
+
*
|
|
37
|
+
* Pass `label` to wrap the switch in a `<Label>` linked to it by `id`;
|
|
38
|
+
* without one, the caller is responsible for its own accessible name (e.g.
|
|
39
|
+
* `aria-label`). Pass `name` to also render a hidden, read-only checkbox
|
|
40
|
+
* input so the value participates in native form submission (`value`
|
|
41
|
+
* defaults to `"on"`).
|
|
42
|
+
*/
|
|
25
43
|
const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
|
|
26
44
|
(
|
|
27
45
|
{
|
|
@@ -63,8 +81,7 @@ const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
|
|
|
63
81
|
ref={ref}
|
|
64
82
|
onClick={() => !pending && setChecked(!checked)}
|
|
65
83
|
className={cn(
|
|
66
|
-
"peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-xs transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-
|
|
67
|
-
checked ? "bg-bg-brand" : "bg-bg-subtle",
|
|
84
|
+
"switch peer focus-visible:ring-(color:--switch-ring) inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent bg-(--switch-bg) shadow-xs transition-colors focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-offset-bg-normal disabled:cursor-not-allowed disabled:opacity-50",
|
|
68
85
|
pending && "cursor-default",
|
|
69
86
|
className
|
|
70
87
|
)}
|
|
@@ -72,12 +89,18 @@ const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(
|
|
|
72
89
|
>
|
|
73
90
|
<span
|
|
74
91
|
className={cn(
|
|
75
|
-
"pointer-events-none flex h-4 w-4 items-center justify-center rounded-full bg-bg
|
|
92
|
+
"switch-thumb pointer-events-none flex h-4 w-4 items-center justify-center rounded-full bg-(--switch-thumb-bg) shadow-lg ring-0 transition-transform",
|
|
76
93
|
checked ? "translate-x-4" : "translate-x-0"
|
|
77
94
|
)}
|
|
78
95
|
>
|
|
79
96
|
{pending && (
|
|
80
|
-
<svg
|
|
97
|
+
<svg
|
|
98
|
+
className="h-2.5 w-2.5 animate-spin text-(--switch-thumb-fg)"
|
|
99
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
100
|
+
fill="none"
|
|
101
|
+
viewBox="0 0 24 24"
|
|
102
|
+
aria-hidden="true"
|
|
103
|
+
>
|
|
81
104
|
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
|
|
82
105
|
<path
|
|
83
106
|
className="opacity-75"
|
|
@@ -41,6 +41,12 @@ const TabsRoot = ({ items, value: controlledValue, defaultValue, onValueChange,
|
|
|
41
41
|
return <TabsContext.Provider value={contextValue}>{children}</TabsContext.Provider>;
|
|
42
42
|
};
|
|
43
43
|
|
|
44
|
+
/**
|
|
45
|
+
* NOTE: Storybook shows the copy in Tabs.stories.tsx
|
|
46
|
+
* (`parameters.docs.description.component`), not this comment. react-docgen
|
|
47
|
+
* cannot extract a description from an `Object.assign` / cast export, so a
|
|
48
|
+
* second copy here would only drift. Edit the stories file.
|
|
49
|
+
*/
|
|
44
50
|
export const Tabs = Object.assign(TabsRoot, {
|
|
45
51
|
List: TabsList,
|
|
46
52
|
Panels: TabsPanels,
|
|
@@ -4,16 +4,32 @@ import { cva } from "class-variance-authority";
|
|
|
4
4
|
import { forwardRef } from "react";
|
|
5
5
|
import { type TabItem, useTabsContext } from "./TabsContext";
|
|
6
6
|
|
|
7
|
+
/**
|
|
8
|
+
* Geometry and behaviour only.
|
|
9
|
+
*
|
|
10
|
+
* Colour reads `--tabs-trigger-bg` / `--tabs-trigger-fg` component tokens
|
|
11
|
+
* (each with a `-hovered` state) whose values are decided by
|
|
12
|
+
* src/theme/recipes/tabs.css. That file is the mapping from `selected` to a
|
|
13
|
+
* semantic token — the layer that used to be the two branches of a `cva`
|
|
14
|
+
* `selected` variant here, compiled into class-name literals and unreachable
|
|
15
|
+
* from outside. Nothing in this file names a colour, which is the point: the
|
|
16
|
+
* semantics are now configurable without a release.
|
|
17
|
+
*/
|
|
7
18
|
const tabsTriggerVariants = cva(
|
|
8
|
-
`inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md
|
|
9
|
-
px-3 py-1.5 text-sm font-medium cursor-pointer transition-colors
|
|
10
|
-
|
|
19
|
+
`tabs-trigger inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md
|
|
20
|
+
px-3 py-1.5 text-sm font-medium cursor-pointer transition-colors bg-(--tabs-trigger-bg)
|
|
21
|
+
text-(--tabs-trigger-fg) hover:bg-(--tabs-trigger-bg-hovered) hover:text-(--tabs-trigger-fg-hovered)
|
|
22
|
+
focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-(color:--tabs-trigger-ring)
|
|
11
23
|
focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50`,
|
|
12
24
|
{
|
|
13
25
|
variants: {
|
|
26
|
+
// No longer carries colour — see the recipe file. Kept as a variant
|
|
27
|
+
// (rather than dropped) purely so `data-selected` and the exported
|
|
28
|
+
// `tabsTriggerVariants` shape stay symmetric with the `isSelected` prop
|
|
29
|
+
// callers already pass.
|
|
14
30
|
selected: {
|
|
15
|
-
true: "
|
|
16
|
-
false: "
|
|
31
|
+
true: "",
|
|
32
|
+
false: "",
|
|
17
33
|
},
|
|
18
34
|
},
|
|
19
35
|
defaultVariants: {
|
|
@@ -53,6 +69,7 @@ export const TabsTrigger = forwardRef<HTMLButtonElement, TabsTriggerProps>(({ it
|
|
|
53
69
|
tabIndex={isSelected ? 0 : -1}
|
|
54
70
|
disabled={item.disabled}
|
|
55
71
|
data-index={index}
|
|
72
|
+
data-selected={isSelected}
|
|
56
73
|
className={cn(tabsTriggerVariants({ selected: isSelected }))}
|
|
57
74
|
onClick={handleClick}
|
|
58
75
|
>
|
|
@@ -3,26 +3,28 @@ import { cn } from "@sixthshift/design-system/utils";
|
|
|
3
3
|
import { X } from "lucide-react";
|
|
4
4
|
import * as React from "react";
|
|
5
5
|
|
|
6
|
-
/**
|
|
7
|
-
* One tag, rendered prettily. A `namespace:value` tag (`project:website`)
|
|
8
|
-
* shows the namespace muted; a plain tag (`urgent`) renders as-is.
|
|
9
|
-
*
|
|
10
|
-
* Pure presentation. Entity-reference tags (`person:per_…`) are NOT rendered
|
|
11
|
-
* here — the web `TagRef` intercepts those and resolves them to a name chip
|
|
12
|
-
* (identity-rendering.md); TagChip never shows a raw id.
|
|
13
|
-
*
|
|
14
|
-
* Two disjoint modes: navigable (no `onRemove`; the caller wraps it in a link)
|
|
15
|
-
* or removable (`onRemove` renders an × — used by `TagInput` and edit surfaces).
|
|
16
|
-
*/
|
|
17
6
|
export type TagChipProps = {
|
|
18
7
|
tag: string;
|
|
19
8
|
/** When set, renders an × affordance. Omit for read-only / navigable chips. */
|
|
20
9
|
onRemove?: () => void;
|
|
21
|
-
/** `sm` (default) for rows; `
|
|
22
|
-
size?: "sm" | "
|
|
10
|
+
/** `sm` (default) for rows; `md` for detail pages. */
|
|
11
|
+
size?: "sm" | "md";
|
|
23
12
|
className?: string;
|
|
24
13
|
};
|
|
25
14
|
|
|
15
|
+
/**
|
|
16
|
+
* One tag, rendered prettily. A `namespace:value` tag (`project:website`)
|
|
17
|
+
* shows the namespace muted; a plain tag (`urgent`) renders as-is.
|
|
18
|
+
*
|
|
19
|
+
* Pure presentation. Entity-reference tags (`person:per_…`) are NOT rendered
|
|
20
|
+
* here — the consuming app is expected to intercept those and resolve them to
|
|
21
|
+
* a name chip; TagChip never shows a raw id.
|
|
22
|
+
*
|
|
23
|
+
* Two disjoint modes, chosen by whether `onRemove` is passed: navigable (no
|
|
24
|
+
* `onRemove`; the caller wraps it in a link) or removable (`onRemove` renders
|
|
25
|
+
* an × — used by `TagInput` and edit surfaces). Built on `Badge`
|
|
26
|
+
* (`variant="outline" intent="muted"`).
|
|
27
|
+
*/
|
|
26
28
|
export const TagChip = React.forwardRef<HTMLSpanElement, TagChipProps>(({ tag, onRemove, size = "sm", className }, ref) => {
|
|
27
29
|
const sep = tag.indexOf(":");
|
|
28
30
|
const namespace = sep > 0 ? tag.slice(0, sep) : null;
|
|
@@ -33,16 +35,16 @@ export const TagChip = React.forwardRef<HTMLSpanElement, TagChipProps>(({ tag, o
|
|
|
33
35
|
ref={ref}
|
|
34
36
|
variant="outline"
|
|
35
37
|
intent="muted"
|
|
36
|
-
className={cn("gap-1 font-normal", size === "sm" ? "px-1.5 py-0 text-[10px]" : "px-2 py-0.5 text-xs", className)}
|
|
38
|
+
className={cn("tag-chip gap-1 font-normal", size === "sm" ? "px-1.5 py-0 text-[10px]" : "px-2 py-0.5 text-xs", className)}
|
|
37
39
|
>
|
|
38
|
-
{namespace && <span className="text-fg
|
|
40
|
+
{namespace && <span className="text-(--tag-chip-namespace-fg)">{namespace}:</span>}
|
|
39
41
|
<span>{value}</span>
|
|
40
42
|
{onRemove && (
|
|
41
43
|
<button
|
|
42
44
|
type="button"
|
|
43
45
|
onClick={onRemove}
|
|
44
46
|
aria-label={`Remove ${tag}`}
|
|
45
|
-
className="-mr-0.5 ml-0.5 rounded-sm text-fg
|
|
47
|
+
className="focus-visible:ring-(color:--tag-chip-remove-ring) -mr-0.5 ml-0.5 rounded-sm text-(--tag-chip-remove-fg) hover:text-(--tag-chip-remove-fg-hovered) focus-visible:outline-none focus-visible:ring-2"
|
|
46
48
|
>
|
|
47
49
|
<X className="h-3 w-3" />
|
|
48
50
|
</button>
|
|
@@ -2,14 +2,6 @@ import { TagChip } from "@sixthshift/design-system/tag-chip";
|
|
|
2
2
|
import { cn } from "@sixthshift/design-system/utils";
|
|
3
3
|
import { forwardRef, type KeyboardEvent, useState } from "react";
|
|
4
4
|
|
|
5
|
-
/**
|
|
6
|
-
* Token input for tags: existing tags render as removable chips, typing plus
|
|
7
|
-
* Enter or comma commits a new one, Backspace on an empty field removes the
|
|
8
|
-
* last. Duplicates are ignored. Controlled — the parent owns `value`.
|
|
9
|
-
*
|
|
10
|
-
* The chrome matches `Input` (same border/focus tokens) so it sits naturally
|
|
11
|
-
* among other form fields.
|
|
12
|
-
*/
|
|
13
5
|
export type TagInputProps = {
|
|
14
6
|
value: string[];
|
|
15
7
|
onChange: (tags: string[]) => void;
|
|
@@ -18,6 +10,17 @@ export type TagInputProps = {
|
|
|
18
10
|
className?: string;
|
|
19
11
|
};
|
|
20
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Token input for tags: existing tags render as removable `TagChip`s, typing
|
|
15
|
+
* plus Enter or comma commits a new one, Backspace on an empty field removes
|
|
16
|
+
* the last. Duplicates are ignored. Controlled only — there is no
|
|
17
|
+
* `defaultValue`, the parent always owns `value`.
|
|
18
|
+
*
|
|
19
|
+
* The chrome matches `Input` (same border/focus tokens) so it sits naturally
|
|
20
|
+
* among other form fields; the field has no visible label of its own, so
|
|
21
|
+
* give it an accessible name via a `<label htmlFor={id}>` (pass `id`) or
|
|
22
|
+
* `aria-label`.
|
|
23
|
+
*/
|
|
21
24
|
export const TagInput = forwardRef<HTMLDivElement, TagInputProps>(({ value, onChange, placeholder = "Add a tag…", id, className }, ref) => {
|
|
22
25
|
const [draft, setDraft] = useState("");
|
|
23
26
|
|
|
@@ -22,6 +22,15 @@ export type TextProps = React.HTMLAttributes<HTMLElement> & {
|
|
|
22
22
|
as?: TextElement;
|
|
23
23
|
};
|
|
24
24
|
|
|
25
|
+
/**
|
|
26
|
+
* The polymorphic base every typography preset (`Heading`, `Body`,
|
|
27
|
+
* `Emphasis`, ...) is built on: renders as `as` (default `span`) and applies
|
|
28
|
+
* no styling of its own beyond `className`.
|
|
29
|
+
*
|
|
30
|
+
* Reach for a preset first — the typographic ramp (docs/visual-hierarchy.md)
|
|
31
|
+
* is what keeps text sizing and color consistent across the app. Use `Text`
|
|
32
|
+
* directly only for one-off text that doesn't fit an existing preset.
|
|
33
|
+
*/
|
|
25
34
|
const Text = React.forwardRef<HTMLElement, TextProps>(({ as: Comp = "span", className, ...props }, ref) => (
|
|
26
35
|
<Comp
|
|
27
36
|
// biome-ignore lint/suspicious/noExplicitAny: polymorphic ref requires any
|
|
@@ -27,6 +27,17 @@ const textInlineVariants = cva("inline-flex items-center", {
|
|
|
27
27
|
|
|
28
28
|
export type TextInlineProps = React.HTMLAttributes<HTMLSpanElement> & VariantProps<typeof textInlineVariants>;
|
|
29
29
|
|
|
30
|
+
/**
|
|
31
|
+
* Lays out several inline fragments — typically `Text` nodes, but any inline
|
|
32
|
+
* content works — in a single flex row with a consistent gap and cross-axis
|
|
33
|
+
* alignment, so a label/value pair or a value/badge pair doesn't need one-off
|
|
34
|
+
* spacing classes at every call site.
|
|
35
|
+
*
|
|
36
|
+
* Renders a single `<span>`. `gap` (default `sm`) and `align` (default
|
|
37
|
+
* `baseline`) are the only two axes; there's no `as` polymorphism, and this
|
|
38
|
+
* is not a variant of `Text` — `TextInline` is about spacing *between*
|
|
39
|
+
* inline children, not about styling the text itself.
|
|
40
|
+
*/
|
|
30
41
|
const TextInline = React.forwardRef<HTMLSpanElement, TextInlineProps>(({ className, gap, align, ...props }, ref) => (
|
|
31
42
|
<span ref={ref} className={cn(textInlineVariants({ gap, align }), className)} {...props} />
|
|
32
43
|
));
|
|
@@ -3,11 +3,23 @@ import * as React from "react";
|
|
|
3
3
|
|
|
4
4
|
export type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement>;
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Multi-line text input for longer free-form text.
|
|
8
|
+
*
|
|
9
|
+
* A thin styled wrapper around `<textarea>` — no custom props beyond
|
|
10
|
+
* `React.TextareaHTMLAttributes`, no auto-resize, and no maximum-length UI of
|
|
11
|
+
* its own. Height comes from a `min-h-[60px]` default plus whatever `rows`
|
|
12
|
+
* or `className` the caller passes; growing with content is the caller's
|
|
13
|
+
* responsibility. Controlled or uncontrolled exactly like a native textarea.
|
|
14
|
+
*
|
|
15
|
+
* Meant to be wrapped by `FormField` for label, description and validation
|
|
16
|
+
* wiring.
|
|
17
|
+
*/
|
|
6
18
|
const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(({ className, ...props }, ref) => {
|
|
7
19
|
return (
|
|
8
20
|
<textarea
|
|
9
21
|
className={cn(
|
|
10
|
-
"flex min-h-[60px] w-full rounded-md border
|
|
22
|
+
"textarea border-(color:--textarea-border) focus-visible:ring-(color:--textarea-ring) flex min-h-[60px] w-full rounded-md border bg-transparent px-3 py-2 text-sm shadow-xs placeholder:text-(--textarea-placeholder-fg) focus-visible:outline-hidden focus-visible:ring-2 disabled:cursor-not-allowed disabled:opacity-50",
|
|
11
23
|
className
|
|
12
24
|
)}
|
|
13
25
|
ref={ref}
|
|
@@ -7,9 +7,25 @@ export type TimeColumnProps = {
|
|
|
7
7
|
onSelect: (value: number) => void;
|
|
8
8
|
formatValue?: (value: number) => string;
|
|
9
9
|
disabled?: (value: number) => boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Move DOM focus to the selected option on mount.
|
|
12
|
+
*
|
|
13
|
+
* Off by default: a column that grabs focus when it appears is wrong for a
|
|
14
|
+
* pointer user who clicked a trigger. `TimePicker` turns it on only when the
|
|
15
|
+
* popover was opened from the keyboard (`Alt+ArrowDown`), where the whole
|
|
16
|
+
* point of opening it was to pick an hour.
|
|
17
|
+
*/
|
|
18
|
+
autoFocusSelected?: boolean;
|
|
10
19
|
};
|
|
11
20
|
|
|
12
|
-
export const TimeColumn = ({
|
|
21
|
+
export const TimeColumn = ({
|
|
22
|
+
values,
|
|
23
|
+
selected,
|
|
24
|
+
onSelect,
|
|
25
|
+
formatValue = (v) => String(v).padStart(2, "0"),
|
|
26
|
+
disabled,
|
|
27
|
+
autoFocusSelected = false,
|
|
28
|
+
}: TimeColumnProps) => {
|
|
13
29
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
14
30
|
const selectedRef = useRef<HTMLButtonElement>(null);
|
|
15
31
|
|
|
@@ -25,6 +41,13 @@ export const TimeColumn = ({ values, selected, onSelect, formatValue = (v) => St
|
|
|
25
41
|
}
|
|
26
42
|
}, []);
|
|
27
43
|
|
|
44
|
+
// Seed focus once, when the caller asked for it. Keyed on the flag alone:
|
|
45
|
+
// `selected` changes as the user picks, and re-running then would drag focus
|
|
46
|
+
// back to the option they started from.
|
|
47
|
+
useEffect(() => {
|
|
48
|
+
if (autoFocusSelected) selectedRef.current?.focus();
|
|
49
|
+
}, [autoFocusSelected]);
|
|
50
|
+
|
|
28
51
|
return (
|
|
29
52
|
<div ref={containerRef} role="listbox" className="h-48 w-14 overflow-y-auto overscroll-contain rounded-lg border border-border-subtle bg-bg-subtle/50">
|
|
30
53
|
{/* Top spacer for centering first items */}
|
|
@@ -1,16 +1,17 @@
|
|
|
1
1
|
import { autoUpdate, FloatingPortal, flip, offset, shift, useClick, useDismiss, useFloating, useInteractions } from "@floating-ui/react";
|
|
2
2
|
import { useControllableState } from "@sixthshift/design-system/hooks";
|
|
3
3
|
import { cn } from "@sixthshift/design-system/utils";
|
|
4
|
-
import { Clock
|
|
4
|
+
import { Clock } from "lucide-react";
|
|
5
5
|
import * as React from "react";
|
|
6
6
|
import { useCallback, useId, useMemo, useState } from "react";
|
|
7
7
|
import { fromISOTime, fromISOTimeOrUndefined, type Temporal, toISOTimeOrUndefined } from "../../date-time";
|
|
8
|
+
import { PickerField } from "../../internal";
|
|
8
9
|
import { Button } from "../Button";
|
|
9
10
|
import { Separator } from "../Separator";
|
|
10
11
|
import { PeriodSelector } from "./PeriodSelector";
|
|
11
12
|
import { TimeColumn } from "./TimeColumn";
|
|
13
|
+
import { TimeSegments } from "./TimeSegments";
|
|
12
14
|
import {
|
|
13
|
-
formatTimeDisplay,
|
|
14
15
|
generateHours,
|
|
15
16
|
generateMinutes,
|
|
16
17
|
generateSeconds,
|
|
@@ -26,6 +27,38 @@ import type { ParsedTime, TimePeriod, TimePickerProps, TimePresetOption } from "
|
|
|
26
27
|
|
|
27
28
|
export type { TimePickerProps };
|
|
28
29
|
|
|
30
|
+
/**
|
|
31
|
+
* A typeable time field and a popover of scrollable hour/minute(/second)
|
|
32
|
+
* columns, as one control. The value is an `ISOTime` string — `"09:30"` and
|
|
33
|
+
* `"09:30:00"` are both accepted as input, and `onChange` always emits the
|
|
34
|
+
* canonical `HH:MM:SS` form regardless of `format`. There is no timezone
|
|
35
|
+
* conversion: the value is a plain time, not an instant.
|
|
36
|
+
*
|
|
37
|
+
* The field is spinbutton segments rather than a text box, and is built to be
|
|
38
|
+
* typed straight through: `0230p` is half past two in the afternoon, `345` in a
|
|
39
|
+
* 24-hour field is 03:45 (there is no 30th hour, so the digit rolls into the
|
|
40
|
+
* minute). `a`/`p` set the meridiem, arrows step any segment, `Alt+ArrowDown`
|
|
41
|
+
* opens the columns and moves focus to the hour, and `Enter` is Apply. See
|
|
42
|
+
* `SegmentedField` for the full keyboard model. `minuteStep` sets the column's
|
|
43
|
+
* increment and deliberately does not constrain typing.
|
|
44
|
+
*
|
|
45
|
+
* Typing and picking move one value: the segments show the draft while the
|
|
46
|
+
* popover is open and the committed value while it is closed. A partial time is
|
|
47
|
+
* never reported — clearing a segment reports `undefined`.
|
|
48
|
+
*
|
|
49
|
+
* Supports both controlled (`value`/`onChange`) and uncontrolled
|
|
50
|
+
* (`defaultValue`) use. Opening the popover seeds the draft columns from the
|
|
51
|
+
* committed value (or the current time, if none); scrolling the columns only
|
|
52
|
+
* updates the draft, and the footer's Apply commits it and closes, Cancel
|
|
53
|
+
* discards it. A "Now" button resets the draft to the current time without
|
|
54
|
+
* closing the popover.
|
|
55
|
+
*
|
|
56
|
+
* `format` (`"HH:mm" | "HH:mm:ss"`) shows or hides the seconds column;
|
|
57
|
+
* `clockFormat` (`"12h" | "24h"`) shows or hides the AM/PM selector.
|
|
58
|
+
* `minTime`/`maxTime` bound the selectable time inclusively — Apply is a
|
|
59
|
+
* no-op while the draft falls outside them. `minuteStep` controls the minute
|
|
60
|
+
* column's increment. `presets` renders a sidebar of quick picks.
|
|
61
|
+
*/
|
|
29
62
|
export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((props, ref) => {
|
|
30
63
|
const {
|
|
31
64
|
value,
|
|
@@ -37,7 +70,6 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
37
70
|
minTime,
|
|
38
71
|
maxTime,
|
|
39
72
|
presets,
|
|
40
|
-
placeholder = "Select time",
|
|
41
73
|
name,
|
|
42
74
|
isDisabled = false,
|
|
43
75
|
isInvalid = false,
|
|
@@ -84,10 +116,20 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
84
116
|
return "AM";
|
|
85
117
|
});
|
|
86
118
|
|
|
119
|
+
// Whether the hour column should take focus when the popover mounts — true
|
|
120
|
+
// only when it was opened from the keyboard. See `openWithColumnFocus`.
|
|
121
|
+
const [autoFocusHour, setAutoFocusHour] = useState(false);
|
|
122
|
+
// The draft is three numbers, so it cannot represent "no time". This does:
|
|
123
|
+
// clearing a segment while the popover is open has to stick rather than being
|
|
124
|
+
// instantly resynced back from the draft.
|
|
125
|
+
const [draftCleared, setDraftCleared] = useState(false);
|
|
126
|
+
|
|
87
127
|
// Sync draft when popup opens
|
|
88
128
|
const handleOpenChange = useCallback(
|
|
89
129
|
(newOpen: boolean) => {
|
|
130
|
+
if (!newOpen) setAutoFocusHour(false);
|
|
90
131
|
if (newOpen) {
|
|
132
|
+
setDraftCleared(false);
|
|
91
133
|
if (committedValue) {
|
|
92
134
|
const parsed = temporalToParsed(committedValue);
|
|
93
135
|
setDraftHour(clockFormat === "12h" ? to12Hour(parsed.hour).hour12 : parsed.hour);
|
|
@@ -121,6 +163,11 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
121
163
|
|
|
122
164
|
// Apply changes
|
|
123
165
|
const handleApply = useCallback(() => {
|
|
166
|
+
if (draftCleared) {
|
|
167
|
+
setCommittedValue(undefined);
|
|
168
|
+
setOpen(false);
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
124
171
|
const parsed = getDraftTime();
|
|
125
172
|
const temporalTime = parsedToTemporal(parsed);
|
|
126
173
|
|
|
@@ -131,7 +178,7 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
131
178
|
|
|
132
179
|
setCommittedValue(temporalTime);
|
|
133
180
|
setOpen(false);
|
|
134
|
-
}, [getDraftTime, temporalMinTime, temporalMaxTime, setCommittedValue]);
|
|
181
|
+
}, [draftCleared, getDraftTime, temporalMinTime, temporalMaxTime, setCommittedValue]);
|
|
135
182
|
|
|
136
183
|
// Cancel changes
|
|
137
184
|
const handleCancel = useCallback(() => {
|
|
@@ -202,9 +249,55 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
202
249
|
const inputId = `timepicker-input-${id}`;
|
|
203
250
|
|
|
204
251
|
// Display value
|
|
205
|
-
const displayValue = committedValue ? formatTimeDisplay(committedValue, clockFormat, format) : "";
|
|
206
252
|
const hasValue = Boolean(committedValue);
|
|
207
253
|
|
|
254
|
+
// ---------------------------------------------------------------------------
|
|
255
|
+
// The typeable field.
|
|
256
|
+
//
|
|
257
|
+
// One value, two ways to move it: the segments show the draft while the
|
|
258
|
+
// popover is open and the committed value while it is closed, so typing a time
|
|
259
|
+
// moves the columns and scrolling a column shows up in the segments. The
|
|
260
|
+
// commit contract stays single — open means Apply/Cancel owns it, closed means
|
|
261
|
+
// a complete time commits as soon as it is complete.
|
|
262
|
+
// ---------------------------------------------------------------------------
|
|
263
|
+
|
|
264
|
+
const draftTime = parsedToTemporal(getDraftTime());
|
|
265
|
+
const segmentValue = open ? (draftCleared ? undefined : draftTime) : committedValue;
|
|
266
|
+
|
|
267
|
+
// A typed time can fall outside `minTime`/`maxTime`, which the columns would
|
|
268
|
+
// refuse. The field says so rather than silently clamping. See DatePicker.
|
|
269
|
+
const outOfBounds = segmentValue !== undefined && isTimeDisabled(segmentValue, temporalMinTime, temporalMaxTime);
|
|
270
|
+
|
|
271
|
+
const handleSegmentsChange = useCallback(
|
|
272
|
+
(time: Temporal.PlainTime | undefined) => {
|
|
273
|
+
if (!open) {
|
|
274
|
+
setCommittedValue(time);
|
|
275
|
+
return;
|
|
276
|
+
}
|
|
277
|
+
if (!time) {
|
|
278
|
+
setDraftCleared(true);
|
|
279
|
+
return;
|
|
280
|
+
}
|
|
281
|
+
setDraftCleared(false);
|
|
282
|
+
setDraftHour(clockFormat === "12h" ? to12Hour(time.hour).hour12 : time.hour);
|
|
283
|
+
setDraftMinute(time.minute);
|
|
284
|
+
setDraftSecond(time.second);
|
|
285
|
+
setDraftPeriod(to12Hour(time.hour).period);
|
|
286
|
+
},
|
|
287
|
+
[clockFormat, open, setCommittedValue]
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
/** `Alt+ArrowDown` from a segment: open the columns *and* go there. */
|
|
291
|
+
const openWithColumnFocus = useCallback(() => {
|
|
292
|
+
setAutoFocusHour(true);
|
|
293
|
+
handleOpenChange(true);
|
|
294
|
+
}, [handleOpenChange]);
|
|
295
|
+
|
|
296
|
+
/** `Enter` in a segment commits the draft, matching the popover's Apply. */
|
|
297
|
+
const handleFieldSubmit = useCallback(() => {
|
|
298
|
+
if (open) handleApply();
|
|
299
|
+
}, [handleApply, open]);
|
|
300
|
+
|
|
208
301
|
// Generate column values
|
|
209
302
|
const hours = generateHours(clockFormat);
|
|
210
303
|
const minutes = generateMinutes(minuteStep);
|
|
@@ -214,38 +307,32 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
214
307
|
<>
|
|
215
308
|
{/* Trigger Input */}
|
|
216
309
|
<div ref={ref} className="relative flex items-center">
|
|
217
|
-
<
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
className="absolute right-3 rounded-sm p-0.5 text-fg-subtle hover:bg-bg-subtle hover:text-fg-normal focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-focus-ring"
|
|
244
|
-
aria-label="Clear time"
|
|
245
|
-
>
|
|
246
|
-
<X className="h-3.5 w-3.5" />
|
|
247
|
-
</button>
|
|
248
|
-
)}
|
|
310
|
+
<PickerField
|
|
311
|
+
ref={refs.setReference as React.Ref<HTMLDivElement>}
|
|
312
|
+
className={cn("w-full min-w-45", className)}
|
|
313
|
+
icon={<Clock className="h-4 w-4" />}
|
|
314
|
+
toggleLabel="Open time picker"
|
|
315
|
+
toggleProps={getReferenceProps()}
|
|
316
|
+
isOpen={open}
|
|
317
|
+
contentId={contentId}
|
|
318
|
+
isDisabled={isDisabled}
|
|
319
|
+
isInvalid={isInvalid || outOfBounds}
|
|
320
|
+
onClear={hasValue && !isDisabled ? handleClear : undefined}
|
|
321
|
+
clearLabel="Clear time"
|
|
322
|
+
>
|
|
323
|
+
<TimeSegments
|
|
324
|
+
className="h-full flex-1"
|
|
325
|
+
id={inputId}
|
|
326
|
+
value={segmentValue}
|
|
327
|
+
onChange={handleSegmentsChange}
|
|
328
|
+
format={format}
|
|
329
|
+
clockFormat={clockFormat}
|
|
330
|
+
isDisabled={isDisabled}
|
|
331
|
+
isInvalid={isInvalid || outOfBounds}
|
|
332
|
+
onOpenRequest={openWithColumnFocus}
|
|
333
|
+
onSubmit={handleFieldSubmit}
|
|
334
|
+
/>
|
|
335
|
+
</PickerField>
|
|
249
336
|
|
|
250
337
|
{/* Hidden input for form submission */}
|
|
251
338
|
{name && committedValue && <input type="hidden" name={name} value={temporalTimeToISO(committedValue, format)} />}
|
|
@@ -258,7 +345,7 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
258
345
|
ref={refs.setFloating}
|
|
259
346
|
id={contentId}
|
|
260
347
|
role="dialog"
|
|
261
|
-
aria-
|
|
348
|
+
aria-label="Choose time"
|
|
262
349
|
style={floatingStyles}
|
|
263
350
|
className="z-popover rounded-xl border border-border-normal bg-bg-normal p-4 shadow-lg"
|
|
264
351
|
{...getFloatingProps()}
|
|
@@ -302,6 +389,7 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
302
389
|
selected={draftHour}
|
|
303
390
|
onSelect={setDraftHour}
|
|
304
391
|
formatValue={clockFormat === "12h" ? (v) => String(v) : (v) => String(v).padStart(2, "0")}
|
|
392
|
+
autoFocusSelected={autoFocusHour}
|
|
305
393
|
/>
|
|
306
394
|
|
|
307
395
|
{/* Minutes */}
|
|
@@ -325,7 +413,7 @@ export const TimePicker = React.forwardRef<HTMLDivElement, TimePickerProps>((pro
|
|
|
325
413
|
<Button type="button" variant="ghost" size="sm" onClick={handleCancel}>
|
|
326
414
|
Cancel
|
|
327
415
|
</Button>
|
|
328
|
-
<Button type="button" variant="solid" size="sm" onClick={handleApply}>
|
|
416
|
+
<Button type="button" variant="solid" intent="brand" size="sm" onClick={handleApply}>
|
|
329
417
|
Apply
|
|
330
418
|
</Button>
|
|
331
419
|
</div>
|