@sixthshift/design-system 0.2.1 → 0.3.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 +135 -28
- package/dist/components/Badge/Badge.d.ts +5 -2
- package/dist/components/Badge/Badge.d.ts.map +1 -1
- package/dist/components/Badge/Badge.js +5 -3
- package/dist/components/Badge/Badge.js.map +1 -1
- package/dist/components/BarChart/BarChart.d.ts +8 -2
- package/dist/components/BarChart/BarChart.d.ts.map +1 -1
- package/dist/components/BarChart/BarChart.js +5 -3
- package/dist/components/BarChart/BarChart.js.map +1 -1
- package/dist/components/Calendar/Calendar.d.ts +17 -1
- package/dist/components/Calendar/Calendar.d.ts.map +1 -1
- package/dist/components/Calendar/Calendar.js +80 -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 +255 -0
- package/dist/components/Calendar/CalendarView.js.map +1 -0
- package/dist/components/Calendar/calendar.types.d.ts +78 -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/ColorDot/ColorDot.d.ts +9 -3
- package/dist/components/ColorDot/ColorDot.d.ts.map +1 -1
- package/dist/components/ColorDot/ColorDot.js +5 -3
- package/dist/components/ColorDot/ColorDot.js.map +1 -1
- package/dist/components/DatePicker/DatePicker.d.ts +2 -2
- package/dist/components/DatePicker/DatePicker.d.ts.map +1 -1
- package/dist/components/DatePicker/DatePicker.js +65 -10
- package/dist/components/DatePicker/DatePicker.js.map +1 -1
- package/dist/components/DatePicker/datepicker.types.d.ts +34 -36
- 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 +3 -2
- package/dist/components/DateRangePicker/DateRangePicker.d.ts.map +1 -1
- package/dist/components/DateRangePicker/DateRangePicker.js +17 -21
- package/dist/components/DateRangePicker/DateRangePicker.js.map +1 -1
- package/dist/components/DateRangePicker/daterangepicker.types.d.ts +20 -20
- 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 +3 -3
- package/dist/components/DateTimePicker/DateTimePicker.d.ts.map +1 -1
- package/dist/components/DateTimePicker/DateTimePicker.js +30 -12
- package/dist/components/DateTimePicker/DateTimePicker.js.map +1 -1
- package/dist/components/DateTimePicker/datetimepicker.types.d.ts +20 -17
- 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 +3 -3
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.d.ts.map +1 -1
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js +41 -20
- package/dist/components/DateTimeRangePicker/DateTimeRangePicker.js.map +1 -1
- package/dist/components/DateTimeRangePicker/datetimerangepicker.types.d.ts +22 -18
- 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/EmptyState/EmptyState.d.ts +16 -5
- package/dist/components/EmptyState/EmptyState.d.ts.map +1 -1
- package/dist/components/EmptyState/EmptyState.js +5 -3
- package/dist/components/EmptyState/EmptyState.js.map +1 -1
- package/dist/components/Field/Field.d.ts +3 -3
- package/dist/components/Field/Field.d.ts.map +1 -1
- package/dist/components/Field/Field.js +6 -4
- package/dist/components/Field/Field.js.map +1 -1
- package/dist/components/LineChart/LineChart.d.ts +18 -2
- package/dist/components/LineChart/LineChart.d.ts.map +1 -1
- package/dist/components/LineChart/LineChart.js +5 -3
- package/dist/components/LineChart/LineChart.js.map +1 -1
- package/dist/components/Markdown/Markdown.d.ts +2 -4
- package/dist/components/Markdown/Markdown.d.ts.map +1 -1
- package/dist/components/Markdown/Markdown.js +3 -2
- package/dist/components/Markdown/Markdown.js.map +1 -1
- package/dist/components/Message/Message.d.ts.map +1 -1
- package/dist/components/Message/Message.js +16 -1
- package/dist/components/Message/Message.js.map +1 -1
- package/dist/components/MetricList/MetricList.d.ts +3 -3
- package/dist/components/MetricList/MetricList.d.ts.map +1 -1
- package/dist/components/MetricList/MetricList.js +5 -3
- package/dist/components/MetricList/MetricList.js.map +1 -1
- package/dist/components/Modal/Modal.d.ts +24 -5
- package/dist/components/Modal/Modal.d.ts.map +1 -1
- package/dist/components/Modal/Modal.js +16 -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/NavBottom/NavBottom.d.ts +2 -1
- package/dist/components/NavBottom/NavBottom.d.ts.map +1 -1
- package/dist/components/NavBottom/NavBottom.js +6 -4
- package/dist/components/NavBottom/NavBottom.js.map +1 -1
- package/dist/components/NavSide/NavItem.js +1 -1
- package/dist/components/NavSide/NavItem.js.map +1 -1
- package/dist/components/NavSide/NavSide.d.ts +2 -1
- package/dist/components/NavSide/NavSide.d.ts.map +1 -1
- package/dist/components/NavSide/NavSide.js +5 -3
- package/dist/components/NavSide/NavSide.js.map +1 -1
- package/dist/components/Popover/Popover.d.ts.map +1 -1
- package/dist/components/Popover/Popover.js +7 -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 +2 -1
- package/dist/components/ProgressBar/ProgressBar.d.ts.map +1 -1
- package/dist/components/ProgressBar/ProgressBar.js +5 -3
- package/dist/components/ProgressBar/ProgressBar.js.map +1 -1
- package/dist/components/Select/Select.d.ts +11 -2
- package/dist/components/Select/Select.d.ts.map +1 -1
- package/dist/components/Select/Select.js +64 -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 +19 -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/Sheet/Sheet.d.ts +19 -5
- package/dist/components/Sheet/Sheet.d.ts.map +1 -1
- package/dist/components/Sheet/Sheet.js +18 -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/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/Skeleton/Skeleton.d.ts +2 -1
- package/dist/components/Skeleton/Skeleton.d.ts.map +1 -1
- package/dist/components/Skeleton/Skeleton.js +5 -3
- package/dist/components/Skeleton/Skeleton.js.map +1 -1
- package/dist/components/Sparkline/Sparkline.d.ts +10 -2
- package/dist/components/Sparkline/Sparkline.d.ts.map +1 -1
- package/dist/components/Sparkline/Sparkline.js +5 -3
- package/dist/components/Sparkline/Sparkline.js.map +1 -1
- package/dist/components/StatsCard/StatsCard.d.ts +4 -4
- package/dist/components/StatsCard/StatsCard.d.ts.map +1 -1
- package/dist/components/StatsCard/StatsCard.js +5 -3
- package/dist/components/StatsCard/StatsCard.js.map +1 -1
- package/dist/components/Tabs/Tabs.d.ts +2 -2
- 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/TagChip/TagChip.d.ts +2 -1
- package/dist/components/TagChip/TagChip.d.ts.map +1 -1
- package/dist/components/TagChip/TagChip.js +5 -3
- package/dist/components/TagChip/TagChip.js.map +1 -1
- package/dist/components/TagInput/TagInput.d.ts +1 -1
- package/dist/components/TagInput/TagInput.d.ts.map +1 -1
- package/dist/components/TagInput/TagInput.js +5 -4
- package/dist/components/TagInput/TagInput.js.map +1 -1
- package/dist/components/TimePicker/TimePicker.d.ts +2 -2
- package/dist/components/TimePicker/TimePicker.d.ts.map +1 -1
- package/dist/components/TimePicker/TimePicker.js +27 -11
- package/dist/components/TimePicker/TimePicker.js.map +1 -1
- package/dist/components/TimePicker/timepicker.types.d.ts +14 -13
- 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/date-time/index.d.ts +2 -0
- package/dist/date-time/index.d.ts.map +1 -1
- package/dist/date-time/index.js +9 -0
- 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/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 +70 -32
- package/dist/theme/schema.d.ts.map +1 -1
- package/dist/theme/schema.js +36 -18
- package/dist/theme/schema.js.map +1 -1
- package/package.json +9 -15
- package/src/components/Badge/Badge.tsx +5 -4
- package/src/components/BarChart/BarChart.tsx +25 -30
- package/src/components/Calendar/Calendar.tsx +91 -401
- package/src/components/Calendar/CalendarView.tsx +445 -0
- package/src/components/Calendar/calendar.types.ts +94 -29
- package/src/components/Calendar/index.ts +16 -17
- package/src/components/ColorDot/ColorDot.tsx +6 -4
- package/src/components/DatePicker/DatePicker.tsx +92 -16
- package/src/components/DatePicker/datepicker.types.ts +38 -39
- package/src/components/DatePicker/index.ts +11 -10
- package/src/components/DateRangePicker/DateRangePicker.tsx +17 -21
- package/src/components/DateRangePicker/daterangepicker.types.ts +22 -22
- package/src/components/DateRangePicker/index.ts +9 -1
- package/src/components/DateTimePicker/DateTimePicker.tsx +46 -18
- package/src/components/DateTimePicker/datetimepicker.types.ts +22 -18
- package/src/components/DateTimePicker/index.ts +9 -1
- package/src/components/DateTimeRangePicker/DateTimeRangePicker.tsx +62 -28
- package/src/components/DateTimeRangePicker/datetimerangepicker.types.ts +24 -19
- package/src/components/DateTimeRangePicker/index.ts +9 -0
- package/src/components/EmptyState/EmptyState.tsx +8 -7
- package/src/components/Field/Field.tsx +7 -6
- package/src/components/LineChart/LineChart.tsx +147 -141
- package/src/components/Markdown/Markdown.tsx +4 -3
- package/src/components/Message/Message.tsx +17 -1
- package/src/components/MetricList/MetricList.tsx +10 -5
- package/src/components/Modal/Modal.tsx +119 -87
- package/src/components/Modal/components/ModalContext.tsx +14 -0
- package/src/components/Modal/components/ModalHeader.tsx +14 -2
- package/src/components/NavBottom/NavBottom.tsx +6 -4
- package/src/components/NavSide/NavItem.tsx +1 -1
- package/src/components/NavSide/NavSide.tsx +5 -3
- package/src/components/Popover/Popover.tsx +7 -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 +32 -28
- package/src/components/Select/Select.tsx +76 -19
- package/src/components/Select/SelectDropdown.tsx +32 -3
- package/src/components/Select/SelectTrigger.tsx +26 -3
- package/src/components/Select/useSelectKeyboard.ts +20 -10
- package/src/components/Sheet/Sheet.tsx +108 -83
- package/src/components/Sheet/components/SheetContext.tsx +10 -0
- package/src/components/Sheet/components/SheetHeader.tsx +17 -2
- package/src/components/Skeleton/Skeleton.tsx +5 -3
- package/src/components/Sparkline/Sparkline.tsx +29 -36
- package/src/components/StatsCard/StatsCard.tsx +7 -6
- package/src/components/Tabs/components/TabsList.tsx +5 -3
- package/src/components/Tabs/components/TabsPanels.tsx +5 -3
- package/src/components/TagChip/TagChip.tsx +10 -3
- package/src/components/TagInput/TagInput.tsx +5 -3
- package/src/components/TimePicker/TimePicker.tsx +31 -13
- package/src/components/TimePicker/timepicker.types.ts +14 -13
- package/src/date-time/index.ts +61 -0
- package/src/date-time/iso.ts +511 -0
- package/src/date-time/now.ts +10 -9
- package/src/theme/index.ts +11 -3
- package/src/theme/schema.ts +82 -54
- package/src/theme/tokens.css +807 -0
- package/dist/styles.css +0 -2
- package/dist/theme.generated.css +0 -438
- 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
|
@@ -0,0 +1,511 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ISO 8601 string types — the public boundary of every date/time component.
|
|
3
|
+
*
|
|
4
|
+
* Components accept and emit canonical ISO strings, never Temporal objects. That
|
|
5
|
+
* keeps the engine (Temporal today, native Temporal or something else tomorrow)
|
|
6
|
+
* an implementation detail, and it means a consumer never has to adopt a date
|
|
7
|
+
* library to render a date picker.
|
|
8
|
+
*
|
|
9
|
+
* Two properties this module guarantees, which the components rely on:
|
|
10
|
+
*
|
|
11
|
+
* 1. **Canonical form.** Every value produced by `toISO*` is normalised via
|
|
12
|
+
* Temporal, so precision is fixed: dates are `YYYY-MM-DD`, times are
|
|
13
|
+
* `HH:MM:SS`, instants are `YYYY-MM-DDTHH:MM:SSZ`. Consumer input is *not*
|
|
14
|
+
* canonical — `"10:30"` and `"10:30:00"` are both valid input — so always
|
|
15
|
+
* normalise on entry rather than comparing raw props.
|
|
16
|
+
*
|
|
17
|
+
* 2. **Lexicographic order == chronological order**, but only once canonical.
|
|
18
|
+
* `"2026-08-26T00:30:00.250Z" < "2026-08-26T00:30Z"` sorts wrong as raw
|
|
19
|
+
* strings; both normalise to a form where `<` is correct. Compare with
|
|
20
|
+
* {@link compareISO}, never with `<` on a raw prop.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
import { Temporal } from "@js-temporal/polyfill";
|
|
24
|
+
import type { WeekStartsOn } from "./boundaries";
|
|
25
|
+
|
|
26
|
+
// =============================================================================
|
|
27
|
+
// Types
|
|
28
|
+
// =============================================================================
|
|
29
|
+
|
|
30
|
+
/** Any numeric segment of an ISO string. */
|
|
31
|
+
type N = `${number}`;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* An ISO 8601 calendar date: `YYYY-MM-DD`.
|
|
35
|
+
*
|
|
36
|
+
* The template literal rejects the obvious mistakes at compile time for literal
|
|
37
|
+
* values (a datetime passed where a date belongs, or outright garbage). It
|
|
38
|
+
* cannot check a value that arrives as a plain `string` — use
|
|
39
|
+
* {@link toISODate} for those.
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* const d: ISODate = "2026-08-26"; // ok
|
|
43
|
+
* const d: ISODate = "2026-08-26T10:00"; // Error
|
|
44
|
+
*/
|
|
45
|
+
export type ISODate = `${N}-${N}-${N}`;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* An ISO 8601 wall-clock time: `HH:MM` or `HH:MM:SS`.
|
|
49
|
+
*
|
|
50
|
+
* Both precisions are accepted as input; components always emit `HH:MM:SS`.
|
|
51
|
+
*/
|
|
52
|
+
export type ISOTime = `${N}:${N}` | `${N}:${N}:${N}`;
|
|
53
|
+
|
|
54
|
+
/** An ISO 8601 timezone-naive datetime: `YYYY-MM-DDTHH:MM:SS`. */
|
|
55
|
+
export type ISODateTime = `${ISODate}T${ISOTime}`;
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* An ISO 8601 absolute instant in UTC: `YYYY-MM-DDTHH:MM:SSZ`.
|
|
59
|
+
*
|
|
60
|
+
* The trailing `Z` is required. A numeric offset (`+10:00`) is a valid instant
|
|
61
|
+
* to Temporal but is rejected here, so that one instant has exactly one
|
|
62
|
+
* representation and string comparison stays meaningful.
|
|
63
|
+
*/
|
|
64
|
+
export type ISOInstant = `${ISODate}T${string}Z`;
|
|
65
|
+
|
|
66
|
+
/** A date range, either end of which may be unset. */
|
|
67
|
+
export type ISODateRange = {
|
|
68
|
+
from: ISODate | undefined;
|
|
69
|
+
to: ISODate | undefined;
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/** An instant range, either end of which may be unset. */
|
|
73
|
+
export type ISOInstantRange = {
|
|
74
|
+
from: ISOInstant | undefined;
|
|
75
|
+
to: ISOInstant | undefined;
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Day of week by name.
|
|
80
|
+
*
|
|
81
|
+
* Named rather than numbered on purpose: `weekStartsOn` counts from 0 = Sunday
|
|
82
|
+
* while ISO-8601 `dayOfWeek` counts from 1 = Monday, and two numeric day props
|
|
83
|
+
* with different origins in the same object is a bug waiting to be filed.
|
|
84
|
+
*/
|
|
85
|
+
export type Weekday = "mon" | "tue" | "wed" | "thu" | "fri" | "sat" | "sun";
|
|
86
|
+
|
|
87
|
+
/** ISO-8601 day numbers, indexed by {@link Weekday}. 1 = Monday. */
|
|
88
|
+
const WEEKDAY_NUMBER: Record<Weekday, number> = {
|
|
89
|
+
mon: 1,
|
|
90
|
+
tue: 2,
|
|
91
|
+
wed: 3,
|
|
92
|
+
thu: 4,
|
|
93
|
+
fri: 5,
|
|
94
|
+
sat: 6,
|
|
95
|
+
sun: 7,
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Which dates a calendar should refuse.
|
|
100
|
+
*
|
|
101
|
+
* The declarative forms cover the cases that would otherwise force a consumer
|
|
102
|
+
* to do date arithmetic; the predicate remains as an escape hatch.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* disabled="2026-08-26" // one date
|
|
106
|
+
* disabled={["2026-08-26", "2026-08-27"]} // several
|
|
107
|
+
* disabled={{ before: "2026-01-01" }} // everything earlier
|
|
108
|
+
* disabled={{ from: "2026-08-01", to: "2026-08-07" }} // an inclusive span
|
|
109
|
+
* disabled={{ dayOfWeek: ["sat", "sun"] }} // weekends
|
|
110
|
+
* disabled={(date) => date.endsWith("-01")} // anything else
|
|
111
|
+
*/
|
|
112
|
+
export type DisabledDates =
|
|
113
|
+
| ISODate
|
|
114
|
+
| readonly ISODate[]
|
|
115
|
+
| { before: ISODate }
|
|
116
|
+
| { after: ISODate }
|
|
117
|
+
| { from: ISODate; to: ISODate }
|
|
118
|
+
| { dayOfWeek: readonly Weekday[] }
|
|
119
|
+
| ((date: ISODate) => boolean);
|
|
120
|
+
|
|
121
|
+
// =============================================================================
|
|
122
|
+
// Narrowing: string | Temporal -> canonical branded ISO
|
|
123
|
+
// =============================================================================
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Normalise a date to canonical `YYYY-MM-DD`.
|
|
127
|
+
*
|
|
128
|
+
* Accepts an ISO date string or a `Temporal.PlainDate`. Throws on anything that
|
|
129
|
+
* is not a valid date, and on a datetime string — a value carrying a time is a
|
|
130
|
+
* caller mistake here, not something to silently truncate.
|
|
131
|
+
*/
|
|
132
|
+
export function toISODate(value: string | Temporal.PlainDate): ISODate {
|
|
133
|
+
if (value instanceof Temporal.PlainDate) return value.toString() as ISODate;
|
|
134
|
+
if (/[T ]/.test(value)) {
|
|
135
|
+
throw new RangeError(`Expected an ISO date (YYYY-MM-DD), got a datetime: ${value}`);
|
|
136
|
+
}
|
|
137
|
+
return Temporal.PlainDate.from(value).toString() as ISODate;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** {@link toISODate}, passing `undefined` through. */
|
|
141
|
+
export function toISODateOrUndefined(value: string | Temporal.PlainDate | null | undefined): ISODate | undefined {
|
|
142
|
+
return value === null || value === undefined ? undefined : toISODate(value);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Normalise a time to canonical `HH:MM:SS`.
|
|
147
|
+
*
|
|
148
|
+
* Accepts `HH:MM`, `HH:MM:SS`, or a `Temporal.PlainTime`. Rejects a datetime,
|
|
149
|
+
* which `Temporal.PlainTime.from` would otherwise happily accept.
|
|
150
|
+
*/
|
|
151
|
+
export function toISOTime(value: string | Temporal.PlainTime): ISOTime {
|
|
152
|
+
if (value instanceof Temporal.PlainTime) return value.toString() as ISOTime;
|
|
153
|
+
if (/[T ]/.test(value)) {
|
|
154
|
+
throw new RangeError(`Expected an ISO time (HH:MM or HH:MM:SS), got a datetime: ${value}`);
|
|
155
|
+
}
|
|
156
|
+
return Temporal.PlainTime.from(value).toString() as ISOTime;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/** {@link toISOTime}, passing `undefined` through. */
|
|
160
|
+
export function toISOTimeOrUndefined(value: string | Temporal.PlainTime | null | undefined): ISOTime | undefined {
|
|
161
|
+
return value === null || value === undefined ? undefined : toISOTime(value);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Normalise an instant to canonical `YYYY-MM-DDTHH:MM:SSZ` (UTC).
|
|
166
|
+
*
|
|
167
|
+
* Accepts any ISO instant — including one written with a numeric offset — and
|
|
168
|
+
* converts it to the `Z` form, so equal instants always compare equal as
|
|
169
|
+
* strings.
|
|
170
|
+
*/
|
|
171
|
+
export function toISOInstant(value: string | Temporal.Instant): ISOInstant {
|
|
172
|
+
const instant = value instanceof Temporal.Instant ? value : Temporal.Instant.from(value);
|
|
173
|
+
return instant.toString() as ISOInstant;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** {@link toISOInstant}, passing `undefined` through. */
|
|
177
|
+
export function toISOInstantOrUndefined(value: string | Temporal.Instant | null | undefined): ISOInstant | undefined {
|
|
178
|
+
return value === null || value === undefined ? undefined : toISOInstant(value);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/** Normalise a date range, dropping ends that are unset. */
|
|
182
|
+
export function toISODateRange(
|
|
183
|
+
range: { from?: string | Temporal.PlainDate | undefined; to?: string | Temporal.PlainDate | undefined } | null | undefined
|
|
184
|
+
): ISODateRange | undefined {
|
|
185
|
+
if (!range) return undefined;
|
|
186
|
+
return { from: toISODateOrUndefined(range.from), to: toISODateOrUndefined(range.to) };
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Normalise an instant range, dropping ends that are unset. */
|
|
190
|
+
export function toISOInstantRange(
|
|
191
|
+
range: { from?: string | Temporal.Instant | undefined; to?: string | Temporal.Instant | undefined } | null | undefined
|
|
192
|
+
): ISOInstantRange | undefined {
|
|
193
|
+
if (!range) return undefined;
|
|
194
|
+
return { from: toISOInstantOrUndefined(range.from), to: toISOInstantOrUndefined(range.to) };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// =============================================================================
|
|
198
|
+
// Widening: branded ISO -> Temporal (for component internals)
|
|
199
|
+
// =============================================================================
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Parse an {@link ISODate} to the `Temporal.PlainDate` the internals work in.
|
|
203
|
+
*
|
|
204
|
+
* Rejects a value carrying a time, exactly as {@link toISODate} does. The
|
|
205
|
+
* template literal type already catches that for a literal, but a value arriving
|
|
206
|
+
* as `string` from an API is unchecked — and `Temporal.PlainDate.from` would
|
|
207
|
+
* silently truncate `"2026-08-26T10:00:00"` to `2026-08-26`, which is the kind
|
|
208
|
+
* of quiet wrong answer this boundary exists to prevent.
|
|
209
|
+
*/
|
|
210
|
+
export function fromISODate(value: ISODate | string): Temporal.PlainDate {
|
|
211
|
+
if (/[T ]/.test(value)) {
|
|
212
|
+
throw new RangeError(`Expected an ISO date (YYYY-MM-DD), got a datetime: ${value}`);
|
|
213
|
+
}
|
|
214
|
+
return Temporal.PlainDate.from(value);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/** {@link fromISODate}, passing `undefined` through. */
|
|
218
|
+
export function fromISODateOrUndefined(value: ISODate | string | null | undefined): Temporal.PlainDate | undefined {
|
|
219
|
+
return value === null || value === undefined ? undefined : fromISODate(value);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/**
|
|
223
|
+
* Parse an {@link ISOTime} to `Temporal.PlainTime`.
|
|
224
|
+
*
|
|
225
|
+
* Rejects a datetime, which `Temporal.PlainTime.from` would otherwise accept by
|
|
226
|
+
* discarding the date half.
|
|
227
|
+
*/
|
|
228
|
+
export function fromISOTime(value: ISOTime | string): Temporal.PlainTime {
|
|
229
|
+
if (/[T ]/.test(value)) {
|
|
230
|
+
throw new RangeError(`Expected an ISO time (HH:MM or HH:MM:SS), got a datetime: ${value}`);
|
|
231
|
+
}
|
|
232
|
+
return Temporal.PlainTime.from(value);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/** {@link fromISOTime}, passing `undefined` through. */
|
|
236
|
+
export function fromISOTimeOrUndefined(value: ISOTime | string | null | undefined): Temporal.PlainTime | undefined {
|
|
237
|
+
return value === null || value === undefined ? undefined : fromISOTime(value);
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/** Parse an {@link ISOInstant} to `Temporal.Instant`. */
|
|
241
|
+
export function fromISOInstant(value: ISOInstant | string): Temporal.Instant {
|
|
242
|
+
return Temporal.Instant.from(value);
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/** {@link fromISOInstant}, passing `undefined` through. */
|
|
246
|
+
export function fromISOInstantOrUndefined(value: ISOInstant | string | null | undefined): Temporal.Instant | undefined {
|
|
247
|
+
return value === null || value === undefined ? undefined : Temporal.Instant.from(value);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* A date range in Temporal terms.
|
|
252
|
+
*
|
|
253
|
+
* Structurally identical to each picker's internal `DateRangeValue`. Declared
|
|
254
|
+
* here so the widening helpers below can live alongside their narrowing
|
|
255
|
+
* counterparts without `date-time` importing from `components`.
|
|
256
|
+
*/
|
|
257
|
+
export type TemporalDateRange = {
|
|
258
|
+
from: Temporal.PlainDate | undefined;
|
|
259
|
+
to: Temporal.PlainDate | undefined;
|
|
260
|
+
};
|
|
261
|
+
|
|
262
|
+
/** An instant range in Temporal terms. */
|
|
263
|
+
export type TemporalInstantRange = {
|
|
264
|
+
from: Temporal.Instant | undefined;
|
|
265
|
+
to: Temporal.Instant | undefined;
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
/** Widen an {@link ISODateRange} for the internals. Inverse of {@link toISODateRange}. */
|
|
269
|
+
export function fromISODateRange(range: ISODateRange | undefined): TemporalDateRange | undefined {
|
|
270
|
+
if (!range) return undefined;
|
|
271
|
+
return { from: fromISODateOrUndefined(range.from), to: fromISODateOrUndefined(range.to) };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** Widen an {@link ISOInstantRange} for the internals. Inverse of {@link toISOInstantRange}. */
|
|
275
|
+
export function fromISOInstantRange(range: ISOInstantRange | undefined): TemporalInstantRange | undefined {
|
|
276
|
+
if (!range) return undefined;
|
|
277
|
+
return { from: fromISOInstantOrUndefined(range.from), to: fromISOInstantOrUndefined(range.to) };
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
// =============================================================================
|
|
281
|
+
// Validation
|
|
282
|
+
// =============================================================================
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Whether `value` is a canonical-parseable ISO date, with no time component.
|
|
286
|
+
*
|
|
287
|
+
* Stricter than `isISODate` from `./validate`, which accepts a datetime because
|
|
288
|
+
* `Temporal.PlainDate.from` does. Use this one at a boundary.
|
|
289
|
+
*/
|
|
290
|
+
export function isDateString(value: unknown): value is ISODate {
|
|
291
|
+
if (typeof value !== "string" || /[T ]/.test(value)) return false;
|
|
292
|
+
try {
|
|
293
|
+
Temporal.PlainDate.from(value);
|
|
294
|
+
return true;
|
|
295
|
+
} catch {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/** Whether `value` is an ISO time, with no date component. */
|
|
301
|
+
export function isTimeString(value: unknown): value is ISOTime {
|
|
302
|
+
if (typeof value !== "string" || /[T ]/.test(value)) return false;
|
|
303
|
+
try {
|
|
304
|
+
Temporal.PlainTime.from(value);
|
|
305
|
+
return true;
|
|
306
|
+
} catch {
|
|
307
|
+
return false;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
/** Whether `value` is an ISO instant (any offset form; `Z` not required). */
|
|
312
|
+
export function isInstantString(value: unknown): value is ISOInstant {
|
|
313
|
+
if (typeof value !== "string") return false;
|
|
314
|
+
try {
|
|
315
|
+
Temporal.Instant.from(value);
|
|
316
|
+
return true;
|
|
317
|
+
} catch {
|
|
318
|
+
return false;
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// =============================================================================
|
|
323
|
+
// Comparison
|
|
324
|
+
// =============================================================================
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Compare two ISO strings of the same kind chronologically.
|
|
328
|
+
*
|
|
329
|
+
* Normalises first, so mixed input precision (`"10:30"` vs `"10:30:00"`) and
|
|
330
|
+
* mixed instant offsets compare correctly — which raw `<` does not.
|
|
331
|
+
*
|
|
332
|
+
* @returns negative if `a` is earlier, 0 if equal, positive if `a` is later.
|
|
333
|
+
*/
|
|
334
|
+
export function compareISO(a: string, b: string): number {
|
|
335
|
+
if (isDateString(a) && isDateString(b)) {
|
|
336
|
+
return Temporal.PlainDate.compare(fromISODate(a), fromISODate(b));
|
|
337
|
+
}
|
|
338
|
+
if (isTimeString(a) && isTimeString(b)) {
|
|
339
|
+
return Temporal.PlainTime.compare(fromISOTime(a), fromISOTime(b));
|
|
340
|
+
}
|
|
341
|
+
return Temporal.Instant.compare(fromISOInstant(a), fromISOInstant(b));
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// =============================================================================
|
|
345
|
+
// ISO-native arithmetic
|
|
346
|
+
// =============================================================================
|
|
347
|
+
//
|
|
348
|
+
// Enough to build the `presets` and `disabled` values a consumer actually needs
|
|
349
|
+
// without reaching for Temporal. Anything more involved is what
|
|
350
|
+
// `@sixthshift/design-system/date-time` is for.
|
|
351
|
+
//
|
|
352
|
+
// `todayISO()` and `nowISO()` live in ./now alongside their Temporal siblings.
|
|
353
|
+
|
|
354
|
+
/** Shift a date by whole days. Negative moves backwards. */
|
|
355
|
+
export function addDaysISO(date: ISODate, days: number): ISODate {
|
|
356
|
+
return fromISODate(date).add({ days }).toString() as ISODate;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
/** Shift a date by whole months, clamping the day to the target month's length. */
|
|
360
|
+
export function addMonthsISO(date: ISODate, months: number): ISODate {
|
|
361
|
+
return fromISODate(date).add({ months }).toString() as ISODate;
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
/** The first day of `date`'s month. */
|
|
365
|
+
export function startOfMonthISO(date: ISODate): ISODate {
|
|
366
|
+
return fromISODate(date).with({ day: 1 }).toString() as ISODate;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/** The last day of `date`'s month. */
|
|
370
|
+
export function endOfMonthISO(date: ISODate): ISODate {
|
|
371
|
+
const plain = fromISODate(date);
|
|
372
|
+
return plain.with({ day: plain.daysInMonth }).toString() as ISODate;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
/** The first day of `date`'s week. `weekStartsOn` counts from 0 = Sunday. */
|
|
376
|
+
export function startOfWeekISO(date: ISODate, weekStartsOn: WeekStartsOn = 0): ISODate {
|
|
377
|
+
const plain = fromISODate(date);
|
|
378
|
+
// Temporal's dayOfWeek is 1 = Monday..7 = Sunday; shift into 0 = Sunday..6.
|
|
379
|
+
const currentDay = plain.dayOfWeek % 7;
|
|
380
|
+
const diff = (currentDay - weekStartsOn + 7) % 7;
|
|
381
|
+
return plain.subtract({ days: diff }).toString() as ISODate;
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
/** The last day of `date`'s week. `weekStartsOn` counts from 0 = Sunday. */
|
|
385
|
+
export function endOfWeekISO(date: ISODate, weekStartsOn: WeekStartsOn = 0): ISODate {
|
|
386
|
+
return addDaysISO(startOfWeekISO(date, weekStartsOn), 6);
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* Shift an instant by whole minutes. Negative moves backwards.
|
|
391
|
+
*
|
|
392
|
+
* Instant arithmetic, unlike the date helpers above, is exact — there are no
|
|
393
|
+
* calendar boundaries to clamp against.
|
|
394
|
+
*/
|
|
395
|
+
export function addMinutesISO(instant: ISOInstant, minutes: number): ISOInstant {
|
|
396
|
+
return fromISOInstant(instant).add({ minutes }).toString() as ISOInstant;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
/** Shift an instant by whole hours. Negative moves backwards. */
|
|
400
|
+
export function addHoursISO(instant: ISOInstant, hours: number): ISOInstant {
|
|
401
|
+
return fromISOInstant(instant).add({ hours }).toString() as ISOInstant;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** The first day of `date`'s year. */
|
|
405
|
+
export function startOfYearISO(date: ISODate): ISODate {
|
|
406
|
+
return fromISODate(date).with({ month: 1, day: 1 }).toString() as ISODate;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
/** The last day of `date`'s year. */
|
|
410
|
+
export function endOfYearISO(date: ISODate): ISODate {
|
|
411
|
+
return fromISODate(date).with({ month: 12, day: 31 }).toString() as ISODate;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
/** ISO-8601 day numbers to {@link Weekday} names. Index 0 is unused; 1 = Monday. */
|
|
415
|
+
const WEEKDAY_NAME: readonly Weekday[] = ["mon", "tue", "wed", "thu", "fri", "sat", "sun"];
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Which day of the week a date falls on, by name.
|
|
419
|
+
*
|
|
420
|
+
* The reason a consumer can filter dates without reaching for Temporal — see
|
|
421
|
+
* {@link isWeekendISO} for the common case.
|
|
422
|
+
*
|
|
423
|
+
* @example
|
|
424
|
+
* presets.filter((date) => weekdayISO(date) !== "sun")
|
|
425
|
+
*/
|
|
426
|
+
export function weekdayISO(date: ISODate): Weekday {
|
|
427
|
+
// Temporal's dayOfWeek is 1 = Monday..7 = Sunday.
|
|
428
|
+
return WEEKDAY_NAME[fromISODate(date).dayOfWeek - 1] as Weekday;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/** Whether a date falls on a Saturday or Sunday. */
|
|
432
|
+
export function isWeekendISO(date: ISODate): boolean {
|
|
433
|
+
const day = weekdayISO(date);
|
|
434
|
+
return day === "sat" || day === "sun";
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
// =============================================================================
|
|
438
|
+
// Disabled-date adaptation
|
|
439
|
+
// =============================================================================
|
|
440
|
+
|
|
441
|
+
/**
|
|
442
|
+
* Convert one public {@link DisabledDates} matcher into the Temporal-shaped
|
|
443
|
+
* matcher the calendar internals evaluate.
|
|
444
|
+
*
|
|
445
|
+
* `dayOfWeek` has no declarative Temporal equivalent, so it becomes a predicate.
|
|
446
|
+
*/
|
|
447
|
+
/**
|
|
448
|
+
* Narrow the array form out of {@link DisabledDates}.
|
|
449
|
+
*
|
|
450
|
+
* `Array.isArray` narrows to `any[]`, which does not remove a `readonly T[]`
|
|
451
|
+
* member from a union — so the object branches below would still see it.
|
|
452
|
+
*/
|
|
453
|
+
function isDateList(matcher: DisabledDates): matcher is readonly ISODate[] {
|
|
454
|
+
return Array.isArray(matcher);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function adaptMatcher(matcher: DisabledDates): TemporalDisabledMatcher {
|
|
458
|
+
if (typeof matcher === "string") return fromISODate(matcher);
|
|
459
|
+
|
|
460
|
+
if (isDateList(matcher)) return matcher.map((date) => fromISODate(date));
|
|
461
|
+
|
|
462
|
+
if (typeof matcher === "function") {
|
|
463
|
+
return (date: Temporal.PlainDate) => matcher(date.toString() as ISODate);
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
if ("dayOfWeek" in matcher) {
|
|
467
|
+
const wanted = new Set(matcher.dayOfWeek.map((day) => WEEKDAY_NUMBER[day]));
|
|
468
|
+
return (date: Temporal.PlainDate) => wanted.has(date.dayOfWeek);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
if ("before" in matcher) return { before: fromISODate(matcher.before) };
|
|
472
|
+
if ("after" in matcher) return { after: fromISODate(matcher.after) };
|
|
473
|
+
return { from: fromISODate(matcher.from), to: fromISODate(matcher.to) };
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* The Temporal-shaped matcher union consumed by `calendar.hooks`.
|
|
478
|
+
*
|
|
479
|
+
* Declared here rather than imported to keep `date-time` free of component
|
|
480
|
+
* imports; `calendar.types` re-exports it under its historical name.
|
|
481
|
+
*/
|
|
482
|
+
export type TemporalDisabledMatcher =
|
|
483
|
+
| Temporal.PlainDate
|
|
484
|
+
| Temporal.PlainDate[]
|
|
485
|
+
| ((date: Temporal.PlainDate) => boolean)
|
|
486
|
+
| { before: Temporal.PlainDate }
|
|
487
|
+
| { after: Temporal.PlainDate }
|
|
488
|
+
| { from: Temporal.PlainDate; to: Temporal.PlainDate };
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Convert the public `disabled` prop into internal matchers.
|
|
492
|
+
*
|
|
493
|
+
* Call this once per render behind a `useMemo` keyed on the prop — the result
|
|
494
|
+
* holds Temporal objects, which have no value identity, so recomputing it every
|
|
495
|
+
* render would invalidate every downstream `useCallback`.
|
|
496
|
+
*/
|
|
497
|
+
export function adaptDisabledDates(disabled: DisabledDates | DisabledDates[] | undefined): TemporalDisabledMatcher | TemporalDisabledMatcher[] | undefined {
|
|
498
|
+
if (disabled === undefined) return undefined;
|
|
499
|
+
|
|
500
|
+
// A bare `ISODate[]` is itself one matcher, not a list of them. An array of
|
|
501
|
+
// anything else is a list. `["2026-08-26"]` is therefore adapted as a single
|
|
502
|
+
// array-matcher, which evaluates identically either way.
|
|
503
|
+
if (Array.isArray(disabled)) {
|
|
504
|
+
if (disabled.every((entry) => typeof entry === "string")) {
|
|
505
|
+
return adaptMatcher(disabled as ISODate[]);
|
|
506
|
+
}
|
|
507
|
+
return (disabled as DisabledDates[]).map(adaptMatcher);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return adaptMatcher(disabled);
|
|
511
|
+
}
|
package/src/date-time/now.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { Temporal } from "@js-temporal/polyfill";
|
|
8
|
+
import type { ISODate, ISODateTime, ISOInstant } from "./iso";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Get the current instant (point in time)
|
|
@@ -14,10 +15,10 @@ export function now(): Temporal.Instant {
|
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
/**
|
|
17
|
-
* Get the current instant as
|
|
18
|
+
* Get the current instant as a canonical ISO 8601 string (UTC, `...Z`)
|
|
18
19
|
*/
|
|
19
|
-
export function nowISO():
|
|
20
|
-
return Temporal.Now.instant().toString();
|
|
20
|
+
export function nowISO(): ISOInstant {
|
|
21
|
+
return Temporal.Now.instant().toString() as ISOInstant;
|
|
21
22
|
}
|
|
22
23
|
|
|
23
24
|
/**
|
|
@@ -28,10 +29,10 @@ export function today(): Temporal.PlainDate {
|
|
|
28
29
|
}
|
|
29
30
|
|
|
30
31
|
/**
|
|
31
|
-
* Get today's date as
|
|
32
|
+
* Get today's date as a canonical ISO 8601 string (`YYYY-MM-DD`)
|
|
32
33
|
*/
|
|
33
|
-
export function todayISO():
|
|
34
|
-
return Temporal.Now.plainDateISO().toString();
|
|
34
|
+
export function todayISO(): ISODate {
|
|
35
|
+
return Temporal.Now.plainDateISO().toString() as ISODate;
|
|
35
36
|
}
|
|
36
37
|
|
|
37
38
|
/**
|
|
@@ -49,10 +50,10 @@ export function nowDateTime(): Temporal.PlainDateTime {
|
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
/**
|
|
52
|
-
* Get the current date/time as
|
|
53
|
+
* Get the current date/time as a canonical ISO 8601 string (no timezone)
|
|
53
54
|
*/
|
|
54
|
-
export function nowDateTimeISO():
|
|
55
|
-
return Temporal.Now.plainDateTimeISO().toString();
|
|
55
|
+
export function nowDateTimeISO(): ISODateTime {
|
|
56
|
+
return Temporal.Now.plainDateTimeISO().toString() as ISODateTime;
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
/**
|
package/src/theme/index.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Theme Exports
|
|
3
3
|
*
|
|
4
|
-
*
|
|
4
|
+
* The token naming vocabulary and its types. Token *values* live in
|
|
5
|
+
* src/theme/tokens.css and are read from the stylesheet, not from here.
|
|
5
6
|
*/
|
|
6
7
|
|
|
7
8
|
export type {
|
|
@@ -20,18 +21,25 @@ export type {
|
|
|
20
21
|
HexValue,
|
|
21
22
|
Hierarchy,
|
|
22
23
|
HSLValue,
|
|
24
|
+
Intent,
|
|
23
25
|
Semantic,
|
|
26
|
+
StandaloneToken,
|
|
27
|
+
State,
|
|
24
28
|
ThemeSchema,
|
|
25
29
|
TokenKey,
|
|
30
|
+
TokenName,
|
|
31
|
+
Weight,
|
|
26
32
|
} from "./schema";
|
|
27
33
|
|
|
28
34
|
export {
|
|
29
35
|
contexts,
|
|
30
36
|
cssVar,
|
|
31
37
|
feedback,
|
|
32
|
-
getAllTokenNames,
|
|
33
|
-
getTokenNames,
|
|
34
38
|
hierarchy,
|
|
35
39
|
hsl,
|
|
40
|
+
intents,
|
|
36
41
|
semantics,
|
|
42
|
+
standaloneTokens,
|
|
43
|
+
states,
|
|
44
|
+
weights,
|
|
37
45
|
} from "./schema";
|