@stll/ui 0.26.0 → 0.26.1

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.
@@ -1,16 +1,16 @@
1
+ import { Result } from "better-result";
2
+ import { Temporal } from "temporal-polyfill/full";
1
3
  //#region src/calendar/resource-calendar.logic.ts
2
4
  const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/u;
3
- const DAY_IN_MS = 864e5;
4
- const toUTCDate = (value) => {
5
+ const toPlainDate = (value) => {
5
6
  if (!ISO_DATE_PATTERN.test(value)) return null;
6
- const date = /* @__PURE__ */ new Date(`${value}T00:00:00.000Z`);
7
- return date.toISOString().slice(0, 10) === value ? date : null;
7
+ return Result.try(() => Temporal.PlainDate.from(value)).unwrapOr(null);
8
8
  };
9
9
  const differenceInCalendarDays = (later, earlier) => {
10
- const laterDate = toUTCDate(later);
11
- const earlierDate = toUTCDate(earlier);
10
+ const laterDate = toPlainDate(later);
11
+ const earlierDate = toPlainDate(earlier);
12
12
  if (laterDate === null || earlierDate === null) throw new RangeError("Calendar dates must use normalized YYYY-MM-DD values");
13
- return (laterDate.getTime() - earlierDate.getTime()) / DAY_IN_MS;
13
+ return laterDate.since(earlierDate, { largestUnit: "days" }).days;
14
14
  };
15
15
  const getResourceCalendarPlacement = ({ entry, visibleRange }) => {
16
16
  const visibleDayCount = differenceInCalendarDays(visibleRange.endDateExclusive, visibleRange.startDate);
@@ -27,7 +27,7 @@ const getResourceCalendarPlacement = ({ entry, visibleRange }) => {
27
27
  const assertConsecutiveCalendarDates = (dates) => {
28
28
  if (dates.length === 0) throw new RangeError("A resource calendar needs at least one date column");
29
29
  const first = dates.at(0);
30
- if (first === void 0 || toUTCDate(first) === null) throw new RangeError("Resource calendar date columns must be consecutive normalized dates");
30
+ if (first === void 0 || toPlainDate(first) === null) throw new RangeError("Resource calendar date columns must be consecutive normalized dates");
31
31
  for (let index = 1; index < dates.length; index += 1) {
32
32
  const previous = dates.at(index - 1);
33
33
  const current = dates.at(index);
@@ -35,11 +35,10 @@ const assertConsecutiveCalendarDates = (dates) => {
35
35
  }
36
36
  };
37
37
  const nextCalendarDate = (value) => {
38
- const date = toUTCDate(value);
38
+ const date = toPlainDate(value);
39
39
  if (date === null) throw new RangeError("Calendar dates must use normalized YYYY-MM-DD values");
40
- date.setUTCDate(date.getUTCDate() + 1);
41
- const nextDate = date.toISOString().slice(0, 10);
42
- if (toUTCDate(nextDate) === null) throw new RangeError("Calendar dates must have a following normalized YYYY-MM-DD value");
40
+ const nextDate = date.add({ days: 1 }).toString();
41
+ if (toPlainDate(nextDate) === null) throw new RangeError("Calendar dates must have a following normalized YYYY-MM-DD value");
43
42
  return nextDate;
44
43
  };
45
44
  const layoutResourceCalendarEntries = (entries, visibleRange) => {
@@ -10,7 +10,7 @@
10
10
  */
11
11
  declare const buttonAccessibleDisabledClass = "cursor-not-allowed opacity-64";
12
12
  declare const buttonVariants: (props?: ({
13
- size?: "default" | "sm" | "lg" | "chip" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "xl" | "xs" | null | undefined;
13
+ size?: "sm" | "default" | "lg" | "chip" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "xl" | "xs" | null | undefined;
14
14
  variant?: "link" | "default" | "destructive" | "destructive-outline" | "ghost" | "outline" | "secondary" | null | undefined;
15
15
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
16
16
  //#endregion
@@ -3,17 +3,22 @@ import { cn } from "../lib/utils.js";
3
3
  import { Button } from "./button.js";
4
4
  import { DirectionalIcon } from "./directional-icon.js";
5
5
  import { getLocaleWeekInfo, getWeekendDays } from "../lib/week.js";
6
- import { localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth } from "./date-picker-popover.logic.js";
6
+ import { localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth, shiftCalendarDate } from "./date-picker-popover.logic.js";
7
7
  import { Popover, PopoverContent as PopoverPopup, PopoverTrigger } from "./popover.js";
8
8
  import { CalendarIcon, ChevronLeftIcon, ChevronRightIcon } from "lucide-react";
9
9
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
10
10
  import { useCallback, useId, useMemo, useRef, useState, useSyncExternalStore } from "react";
11
+ import { Temporal } from "temporal-polyfill/full";
11
12
  //#region src/components/date-picker-popover.tsx
12
- const toISODate = (date) => date.toISOString().slice(0, 10);
13
+ const toISODate = (date) => date.toString();
14
+ const toUTCDateTime = (date) => date.toZonedDateTime({
15
+ plainTime: Temporal.PlainTime.from("00:00"),
16
+ timeZone: "UTC"
17
+ }).epochMilliseconds;
13
18
  const HYDRATION_DATE = "1970-01-01";
14
19
  const HYDRATION_LOCALE = "en";
15
20
  const noopSubscribe = (_onStoreChange) => () => void 0;
16
- const getLocalToday = () => localDateFromTimestamp(Date.now());
21
+ const getLocalToday = () => localDateFromTimestamp(Temporal.Now.instant().epochMilliseconds);
17
22
  const localDateListeners = /* @__PURE__ */ new Set();
18
23
  let localDateTimeoutId;
19
24
  const notifyLocalDateListeners = () => {
@@ -24,7 +29,7 @@ const scheduleNextLocalDate = () => {
24
29
  localDateTimeoutId = setTimeout(() => {
25
30
  notifyLocalDateListeners();
26
31
  if (localDateListeners.size > 0) scheduleNextLocalDate();
27
- }, millisecondsUntilNextLocalDate(Date.now()));
32
+ }, millisecondsUntilNextLocalDate(Temporal.Now.instant().epochMilliseconds));
28
33
  };
29
34
  const refreshLocalDateEnvironment = () => {
30
35
  notifyLocalDateListeners();
@@ -58,19 +63,21 @@ const getFirstDayOfWeek = (locale) => {
58
63
  };
59
64
  const getMonthDays = (year, month, firstDow, weekendDays, today) => {
60
65
  const days = [];
61
- const first = new Date(Date.UTC(year, month, 1));
62
- const startOffset = ((first.getUTCDay() + 6) % 7 - firstDow + 7) % 7;
63
- const start = new Date(first);
64
- start.setUTCDate(start.getUTCDate() - startOffset);
66
+ const first = Temporal.PlainDate.from({
67
+ year,
68
+ month: month + 1,
69
+ day: 1
70
+ });
71
+ const startOffset = (first.dayOfWeek - 1 - firstDow + 7) % 7;
72
+ const start = first.subtract({ days: startOffset });
65
73
  for (let i = 0; i < 42; i++) {
66
- const d = new Date(start);
67
- d.setUTCDate(d.getUTCDate() + i);
74
+ const d = start.add({ days: i });
68
75
  const iso = toISODate(d);
69
76
  days.push({
70
77
  date: iso,
71
- isCurrentMonth: d.getUTCMonth() === month,
78
+ isCurrentMonth: d.month === month + 1,
72
79
  isToday: iso === today,
73
- isWeekend: weekendDays.has(d.getUTCDay())
80
+ isWeekend: weekendDays.has(d.dayOfWeek % 7)
74
81
  });
75
82
  }
76
83
  return days;
@@ -87,14 +94,21 @@ const getWeekdayFormatter = (locale) => {
87
94
  const getWeekdayLabels = (locale, firstDow, weekendDays) => {
88
95
  const fmt = getWeekdayFormatter(locale);
89
96
  return Array.from({ length: 7 }, (_, i) => {
90
- const d = new Date(Date.UTC(2024, 0, 1 + (i + firstDow) % 7));
97
+ const d = Temporal.PlainDate.from("2024-01-01").add({ days: (i + firstDow) % 7 });
91
98
  return {
92
- isWeekend: weekendDays.has(d.getUTCDay()),
93
- label: fmt.format(d)
99
+ isWeekend: weekendDays.has(d.dayOfWeek % 7),
100
+ label: fmt.format(toUTCDateTime(d))
94
101
  };
95
102
  });
96
103
  };
97
104
  const monthFormatters = /* @__PURE__ */ new Map();
105
+ const dateFormatters = /* @__PURE__ */ new Map();
106
+ const getDateFormatter = (locale, options) => {
107
+ const key = `${locale}:${JSON.stringify(options)}`;
108
+ const formatter = dateFormatters.get(key) ?? new Intl.DateTimeFormat(locale, options);
109
+ dateFormatters.set(key, formatter);
110
+ return formatter;
111
+ };
98
112
  const getMonthFormatter = (locale, format) => {
99
113
  const key = `${locale}:${format}`;
100
114
  const fmt = monthFormatters.get(key) ?? new Intl.DateTimeFormat(locale, {
@@ -107,7 +121,11 @@ const getMonthFormatter = (locale, format) => {
107
121
  };
108
122
  const getMonthLabels = (locale, format = "long") => {
109
123
  const fmt = getMonthFormatter(locale, format);
110
- return Array.from({ length: 12 }, (_, i) => fmt.format(new Date(Date.UTC(2024, i, 1))));
124
+ return Array.from({ length: 12 }, (_, i) => fmt.format(toUTCDateTime(Temporal.PlainDate.from({
125
+ year: 2024,
126
+ month: i + 1,
127
+ day: 1
128
+ }))));
111
129
  };
112
130
  const monthYearFormatters = /* @__PURE__ */ new Map();
113
131
  const getMonthYearFormatter = (locale) => {
@@ -120,7 +138,11 @@ const getMonthYearFormatter = (locale) => {
120
138
  monthYearFormatters.set(locale, fmt);
121
139
  return fmt;
122
140
  };
123
- const formatMonthYear = (locale, year, month) => getMonthYearFormatter(locale).format(new Date(Date.UTC(year, month, 1)));
141
+ const formatMonthYear = (locale, year, month) => getMonthYearFormatter(locale).format(toUTCDateTime(Temporal.PlainDate.from({
142
+ year,
143
+ month: month + 1,
144
+ day: 1
145
+ })));
124
146
  const relativeTimeFormatters = /* @__PURE__ */ new Map();
125
147
  const getRelativeTimeFormatter = (locale) => {
126
148
  const fmt = relativeTimeFormatters.get(locale) ?? new Intl.RelativeTimeFormat(locale, { numeric: "auto" });
@@ -134,14 +156,10 @@ const deriveTodayLabel = (locale) => {
134
156
  };
135
157
  const normalizeDate = (v) => {
136
158
  if (v === null || v === void 0) return "";
137
- if (v instanceof Date) return v.toISOString().slice(0, 10);
159
+ if (v instanceof Date) return Temporal.Instant.fromEpochMilliseconds(v.getTime()).toZonedDateTimeISO("UTC").toPlainDate().toString();
138
160
  return v.length >= 10 ? v.slice(0, 10) : v;
139
161
  };
140
- const addDays = (iso, n) => {
141
- const d = /* @__PURE__ */ new Date(`${iso}T00:00:00Z`);
142
- d.setUTCDate(d.getUTCDate() + n);
143
- return toISODate(d);
144
- };
162
+ const addDays = (iso, n) => Temporal.PlainDate.from(iso).add({ days: n }).toString();
145
163
  const isBefore = (a, b) => a < b;
146
164
  const isAfter = (a, b) => a > b;
147
165
  /** Round down to the start of a decade (e.g. 2026 → 2020). */
@@ -186,22 +204,22 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
186
204
  maxDate,
187
205
  isDateDisabled
188
206
  ]);
189
- const displayLabel = value ? (/* @__PURE__ */ new Date(`${value}T00:00:00Z`)).toLocaleDateString(locale, {
207
+ const displayLabel = value ? getDateFormatter(locale, {
190
208
  month: "short",
191
209
  day: "numeric",
192
210
  year: "numeric",
193
211
  calendar: "gregory",
194
212
  timeZone: "UTC"
195
- }) : placeholderLabel ?? "—";
196
- const formatDayLabel = useCallback((iso) => (/* @__PURE__ */ new Date(`${iso}T00:00:00Z`)).toLocaleDateString(locale, {
213
+ }).format(toUTCDateTime(Temporal.PlainDate.from(value))) : placeholderLabel ?? "—";
214
+ const formatDayLabel = useCallback((iso) => getDateFormatter(locale, {
197
215
  weekday: "long",
198
216
  month: "long",
199
217
  day: "numeric",
200
218
  year: "numeric",
201
219
  calendar: "gregory",
202
220
  timeZone: "UTC"
203
- }), [locale]);
204
- const handleGridKeyDown = useCallback((e) => {
221
+ }).format(toUTCDateTime(Temporal.PlainDate.from(iso))), [locale]);
222
+ const handleGridKeyDown = (e) => {
205
223
  const firstDay = days.at(0);
206
224
  if (!firstDay) return;
207
225
  const current = focusedDate || value || firstDay.date;
@@ -212,22 +230,14 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
212
230
  else if (e.key === "ArrowDown") next = addDays(current, 7);
213
231
  else if (e.key === "ArrowUp") next = addDays(current, -7);
214
232
  else if (e.key === "Home") {
215
- const offset = (((/* @__PURE__ */ new Date(`${current}T00:00:00Z`)).getUTCDay() + 6) % 7 - firstDow + 7) % 7;
233
+ const offset = (Temporal.PlainDate.from(current).dayOfWeek - 1 - firstDow + 7) % 7;
216
234
  next = addDays(current, -offset);
217
235
  } else if (e.key === "End") {
218
- const offset = (((/* @__PURE__ */ new Date(`${current}T00:00:00Z`)).getUTCDay() + 6) % 7 - firstDow + 7) % 7;
236
+ const offset = (Temporal.PlainDate.from(current).dayOfWeek - 1 - firstDow + 7) % 7;
219
237
  next = addDays(current, 6 - offset);
220
- } else if (e.key === "PageUp") {
221
- const d = /* @__PURE__ */ new Date(`${current}T00:00:00Z`);
222
- if (e.shiftKey) d.setUTCFullYear(d.getUTCFullYear() - 1);
223
- else d.setUTCMonth(d.getUTCMonth() - 1);
224
- next = toISODate(d);
225
- } else if (e.key === "PageDown") {
226
- const d = /* @__PURE__ */ new Date(`${current}T00:00:00Z`);
227
- if (e.shiftKey) d.setUTCFullYear(d.getUTCFullYear() + 1);
228
- else d.setUTCMonth(d.getUTCMonth() + 1);
229
- next = toISODate(d);
230
- } else {
238
+ } else if (e.key === "PageUp") next = shiftCalendarDate(current, e.shiftKey ? { years: -1 } : { months: -1 });
239
+ else if (e.key === "PageDown") next = shiftCalendarDate(current, e.shiftKey ? { years: 1 } : { months: 1 });
240
+ else {
231
241
  if (e.key === "Enter" || e.key === " ") {
232
242
  e.preventDefault();
233
243
  if (!isDayDisabled(current)) onChange(current);
@@ -237,9 +247,9 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
237
247
  e.preventDefault();
238
248
  if (next) {
239
249
  setFocusedDate(next);
240
- const nextDate = /* @__PURE__ */ new Date(`${next}T00:00:00Z`);
241
- const nextMonth = nextDate.getUTCMonth();
242
- const nextYear = nextDate.getUTCFullYear();
250
+ const nextDate = Temporal.PlainDate.from(next);
251
+ const nextMonth = nextDate.month - 1;
252
+ const nextYear = nextDate.year;
243
253
  if (nextMonth !== viewMonth || nextYear !== viewYear) setViewMonthOverride({
244
254
  month: nextMonth,
245
255
  year: nextYear
@@ -248,17 +258,7 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
248
258
  (gridRef.current?.querySelector(`[data-date="${next}"]`))?.focus();
249
259
  });
250
260
  }
251
- }, [
252
- focusedDate,
253
- value,
254
- days,
255
- firstDow,
256
- viewMonth,
257
- viewYear,
258
- isDayDisabled,
259
- onChange,
260
- setViewMonthOverride
261
- ]);
261
+ };
262
262
  const handlePrev = () => {
263
263
  if (view === "days") if (viewMonth === 0) setViewMonthOverride({
264
264
  month: 11,
@@ -316,8 +316,8 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
316
316
  setDecadeBaseOverride(decadeStart(year));
317
317
  setView("months");
318
318
  };
319
- const selectedYear = value ? (/* @__PURE__ */ new Date(`${value}T00:00:00Z`)).getUTCFullYear() : null;
320
- const selectedMonth = value ? (/* @__PURE__ */ new Date(`${value}T00:00:00Z`)).getUTCMonth() : null;
319
+ const selectedYear = value ? Temporal.PlainDate.from(value).year : null;
320
+ const selectedMonth = value ? Temporal.PlainDate.from(value).month - 1 : null;
321
321
  const handleOpenChange = (open) => {
322
322
  onOpenChange?.(open);
323
323
  if (!open) {
@@ -451,10 +451,10 @@ const DatePickerPopoverContent = ({ id, labelledBy, value: rawValue, onChange, l
451
451
  children: [/* @__PURE__ */ jsx(Button, {
452
452
  className: "flex-1",
453
453
  onClick: () => {
454
- const todayDate = /* @__PURE__ */ new Date(`${today}T00:00:00Z`);
454
+ const todayDate = Temporal.PlainDate.from(today);
455
455
  setViewMonthOverride({
456
- month: todayDate.getUTCMonth(),
457
- year: todayDate.getUTCFullYear()
456
+ month: todayDate.month - 1,
457
+ year: todayDate.year
458
458
  });
459
459
  setView("days");
460
460
  },
@@ -487,9 +487,9 @@ const DatePickerPopover = (props) => {
487
487
  const MONTHS_PER_ROW = 3;
488
488
  const MonthGrid = ({ locale, viewYear, currentMonth, currentYear, onSelect, today }) => {
489
489
  const labels = useMemo(() => getMonthLabels(locale, "short"), [locale]);
490
- const now = /* @__PURE__ */ new Date(`${today}T00:00:00Z`);
491
- const todayMonth = now.getUTCMonth();
492
- const todayYear = now.getUTCFullYear();
490
+ const now = Temporal.PlainDate.from(today);
491
+ const todayMonth = now.month - 1;
492
+ const todayYear = now.year;
493
493
  const rows = [];
494
494
  for (let r = 0; r < 12; r += MONTHS_PER_ROW) rows.push(Array.from({ length: MONTHS_PER_ROW }, (_, c) => r + c));
495
495
  return /* @__PURE__ */ jsx("div", {
@@ -518,7 +518,7 @@ const MonthGrid = ({ locale, viewYear, currentMonth, currentYear, onSelect, toda
518
518
  };
519
519
  const YEARS_PER_ROW = 3;
520
520
  const YearGrid = ({ decadeBase, currentYear, onSelect, today }) => {
521
- const todayYear = (/* @__PURE__ */ new Date(`${today}T00:00:00Z`)).getUTCFullYear();
521
+ const todayYear = Temporal.PlainDate.from(today).year;
522
522
  const startYear = decadeBase - 1;
523
523
  const rows = [];
524
524
  for (let r = 0; r < DECADE_SIZE; r += YEARS_PER_ROW) rows.push(Array.from({ length: Math.min(YEARS_PER_ROW, DECADE_SIZE - r) }, (_, c) => r + c));
@@ -9,6 +9,10 @@ declare const resolveCalendarViewMonth: ({ override, today, value }: {
9
9
  today: string;
10
10
  value: string;
11
11
  }) => CalendarMonth;
12
+ declare const shiftCalendarDate: (date: string, options: {
13
+ months?: number;
14
+ years?: number;
15
+ }) => string;
12
16
  declare const millisecondsUntilNextLocalDate: (timestamp: number) => number;
13
17
  //#endregion
14
- export { CalendarMonth, localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth };
18
+ export { CalendarMonth, localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth, shiftCalendarDate };
@@ -1,26 +1,31 @@
1
+ import { Temporal } from "temporal-polyfill/full";
1
2
  //#region src/components/date-picker-popover.logic.ts
2
3
  const DATE_ROLLOVER_EPSILON_MS = 50;
3
4
  const padDatePart = (value) => value.toString().padStart(2, "0");
4
5
  const localDateFromTimestamp = (timestamp) => {
5
- const current = new Date(timestamp);
6
+ const current = Temporal.Instant.fromEpochMilliseconds(timestamp).toZonedDateTimeISO(Temporal.Now.timeZoneId());
6
7
  return [
7
- current.getFullYear(),
8
- padDatePart(current.getMonth() + 1),
9
- padDatePart(current.getDate())
8
+ current.year,
9
+ padDatePart(current.month),
10
+ padDatePart(current.day)
10
11
  ].join("-");
11
12
  };
12
13
  const calendarMonthFromDate = (date) => {
13
- const current = /* @__PURE__ */ new Date(`${date}T00:00:00Z`);
14
+ const current = Temporal.PlainDate.from(date);
14
15
  return {
15
- month: current.getUTCMonth(),
16
- year: current.getUTCFullYear()
16
+ month: current.month - 1,
17
+ year: current.year
17
18
  };
18
19
  };
19
20
  const resolveCalendarViewMonth = ({ override, today, value }) => override ?? calendarMonthFromDate(value || today);
21
+ const shiftCalendarDate = (date, options) => Temporal.PlainDate.from(date).add(options).toString();
20
22
  const millisecondsUntilNextLocalDate = (timestamp) => {
21
- const current = new Date(timestamp);
22
- const nextLocalDate = new Date(current.getFullYear(), current.getMonth(), current.getDate() + 1);
23
- return Math.max(0, nextLocalDate.getTime() - timestamp) + DATE_ROLLOVER_EPSILON_MS;
23
+ const current = Temporal.Instant.fromEpochMilliseconds(timestamp).toZonedDateTimeISO(Temporal.Now.timeZoneId());
24
+ const nextLocalDate = current.toPlainDate().add({ days: 1 }).toZonedDateTime({
25
+ plainTime: Temporal.PlainTime.from("00:00"),
26
+ timeZone: current.timeZoneId
27
+ });
28
+ return Math.max(0, nextLocalDate.epochMilliseconds - timestamp) + DATE_ROLLOVER_EPSILON_MS;
24
29
  };
25
30
  //#endregion
26
- export { localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth };
31
+ export { localDateFromTimestamp, millisecondsUntilNextLocalDate, resolveCalendarViewMonth, shiftCalendarDate };
@@ -5,7 +5,7 @@ import { VariantProps } from "class-variance-authority";
5
5
  //#region src/components/input-group.d.ts
6
6
  declare const InputGroup: ({ className, ...props }: React$1.ComponentProps<"div">) => React$1.JSX.Element;
7
7
  declare const inputGroupAddonVariants: (props?: ({
8
- align?: "inline-end" | "inline-start" | "block-start" | "block-end" | null | undefined;
8
+ align?: "inline-end" | "inline-start" | "block-end" | "block-start" | null | undefined;
9
9
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
10
10
  declare const InputGroupAddon: ({ className, align, ...props }: React$1.ComponentProps<"div"> & VariantProps<typeof inputGroupAddonVariants>) => React$1.JSX.Element;
11
11
  declare const InputGroupText: ({ className, ...props }: React$1.ComponentProps<"span">) => React$1.JSX.Element;
@@ -3,6 +3,7 @@ import { cn } from "../lib/utils.js";
3
3
  import { Tooltip, TooltipContent as TooltipPopup, TooltipTrigger } from "./tooltip.js";
4
4
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
5
5
  import { useCallback, useEffect, useId, useLayoutEffect, useMemo, useRef, useState } from "react";
6
+ import { Temporal } from "temporal-polyfill/full";
6
7
  //#region src/components/outline-rail.tsx
7
8
  /**
8
9
  * Outline rail — the shared right-edge navigation rail.
@@ -153,7 +154,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
153
154
  if (!container || items.length === 0) return;
154
155
  let raf = 0;
155
156
  const compute = () => {
156
- if (Date.now() < manualLockUntil.current || container.scrollHeight <= 0) return;
157
+ if (Temporal.Now.instant().epochMilliseconds < manualLockUntil.current || container.scrollHeight <= 0) return;
157
158
  const centrePct = (container.scrollTop + container.clientHeight / 2) / container.scrollHeight * 100;
158
159
  let next = null;
159
160
  for (const item of items) {
@@ -197,7 +198,7 @@ const OutlineRail = ({ items, scrollContainerRef, resolvePct, onJump, activeId,
197
198
  if (!container) return;
198
199
  if (activeId === void 0) {
199
200
  setDerivedActive(id);
200
- manualLockUntil.current = Date.now() + 900;
201
+ manualLockUntil.current = Temporal.Now.instant().epochMilliseconds + 900;
201
202
  }
202
203
  onJumpRef.current(id, container);
203
204
  }, [activeId, scrollContainerRef]);
@@ -83,7 +83,7 @@ declare const SidebarMenu: ({ className, ...props }: React.ComponentProps<"ul">)
83
83
  declare const SidebarMenuItem: ({ className, ...props }: React.ComponentProps<"li">) => import("react").JSX.Element;
84
84
  declare const sidebarMenuButtonVariants: (props?: ({
85
85
  variant?: "default" | "outline" | null | undefined;
86
- size?: "default" | "sm" | "lg" | "rail" | null | undefined;
86
+ size?: "sm" | "default" | "lg" | "rail" | null | undefined;
87
87
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
88
88
  declare const SidebarMenuButton: ({ asChild, isActive, variant, size, tooltip, className, ...props }: React.ComponentProps<"button"> & {
89
89
  asChild?: boolean;
@@ -5,6 +5,6 @@ declare const CONTROL_SIZE: Readonly<{
5
5
  readonly lg: "lg";
6
6
  }>;
7
7
  type ControlSize = (typeof CONTROL_SIZE)[keyof typeof CONTROL_SIZE];
8
- declare const CONTROL_SIZES: readonly ("default" | "sm" | "lg")[];
8
+ declare const CONTROL_SIZES: readonly ("sm" | "default" | "lg")[];
9
9
  //#endregion
10
10
  export { CONTROL_SIZE, CONTROL_SIZES, type ControlSize };
@@ -10,13 +10,13 @@
10
10
  */
11
11
  declare const getLocaleWeekInfo: (locale: string) => Intl.WeekInfo | undefined;
12
12
  /**
13
- * First weekday as a `Date.getDay()` value (0 = Sunday … 6 = Saturday): Monday
13
+ * First weekday as a day-of-week value (0 = Sunday … 6 = Saturday): Monday
14
14
  * across most of Europe, Sunday in the US, Saturday across much of the Gulf.
15
15
  * Falls back to Monday when the runtime lacks week info.
16
16
  */
17
17
  declare const getFirstWeekday: (locale: string) => number;
18
18
  /**
19
- * Weekend weekdays as `Date.getDay()` values (0 = Sunday … 6 = Saturday):
19
+ * Weekend weekdays as day-of-week values (0 = Sunday … 6 = Saturday):
20
20
  * Saturday/Sunday across the West, Friday/Saturday across much of the Gulf.
21
21
  * Falls back to Saturday/Sunday when the runtime lacks week info.
22
22
  */
package/dist/lib/week.js CHANGED
@@ -18,7 +18,7 @@ const getLocaleWeekInfo = (locale) => {
18
18
  }
19
19
  };
20
20
  /**
21
- * First weekday as a `Date.getDay()` value (0 = Sunday … 6 = Saturday): Monday
21
+ * First weekday as a day-of-week value (0 = Sunday … 6 = Saturday): Monday
22
22
  * across most of Europe, Sunday in the US, Saturday across much of the Gulf.
23
23
  * Falls back to Monday when the runtime lacks week info.
24
24
  */
@@ -27,7 +27,7 @@ const getFirstWeekday = (locale) => {
27
27
  return typeof firstDay === "number" ? firstDay % 7 : 1;
28
28
  };
29
29
  /**
30
- * Weekend weekdays as `Date.getDay()` values (0 = Sunday … 6 = Saturday):
30
+ * Weekend weekdays as day-of-week values (0 = Sunday … 6 = Saturday):
31
31
  * Saturday/Sunday across the West, Friday/Saturday across much of the Gulf.
32
32
  * Falls back to Saturday/Sunday when the runtime lacks week info.
33
33
  */
@@ -4,6 +4,7 @@ import { BidiText } from "../components/bidi-text.js";
4
4
  import { ReviewAuthorAvatar } from "./review-author-avatar.js";
5
5
  import { CheckIcon, RotateCcwIcon, Trash2Icon } from "lucide-react";
6
6
  import { jsx, jsxs } from "react/jsx-runtime";
7
+ import { Temporal } from "temporal-polyfill/full";
7
8
  //#region src/review/review-comment-card.tsx
8
9
  /** One comment on a reviewed surface: who wrote it, when, what it says, what
9
10
  * it points at, and the two things a reader can do to it. */
@@ -70,7 +71,7 @@ const ReviewCommentCard = ({ author, timestamp, formattedTime, body, anchorText,
70
71
  * yields no attribute rather than throwing on `toISOString`. */
71
72
  const toIsoInstant = (timestamp) => {
72
73
  if (typeof timestamp === "string") return timestamp;
73
- return Number.isNaN(timestamp.getTime()) ? void 0 : timestamp.toISOString();
74
+ return Number.isNaN(timestamp.getTime()) ? void 0 : Temporal.Instant.fromEpochMilliseconds(timestamp.getTime()).toString({ fractionalSecondDigits: 3 });
74
75
  };
75
76
  //#endregion
76
77
  export { ReviewCommentCard };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stll/ui",
3
- "version": "0.26.0",
3
+ "version": "0.26.1",
4
4
  "description": "Stella's design system: bidi-aware React primitives built on Base UI, the dockable inspector pane, and the Tailwind v4 theme they are styled with.",
5
5
  "keywords": [
6
6
  "base-ui",
@@ -594,7 +594,8 @@
594
594
  "clsx": "^2.1.1",
595
595
  "input-otp": "^1.5.0",
596
596
  "lucide-react": "1.39.0",
597
- "tailwind-merge": "^3.6.0"
597
+ "tailwind-merge": "^3.6.0",
598
+ "temporal-polyfill": "1.0.4"
598
599
  },
599
600
  "devDependencies": {
600
601
  "@atlaskit/pragmatic-drag-and-drop": "^3.1.0",