@stll/ui 0.25.2 → 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.
- package/dist/calendar/resource-calendar.logic.js +11 -12
- package/dist/components/button-variants.d.ts +1 -1
- package/dist/components/color-picker.d.ts +15 -5
- package/dist/components/color-picker.js +114 -47
- package/dist/components/date-picker-popover.js +64 -64
- package/dist/components/date-picker-popover.logic.d.ts +5 -1
- package/dist/components/date-picker-popover.logic.js +16 -11
- package/dist/components/outline-rail.js +3 -2
- package/dist/components/sidebar.d.ts +2 -2
- package/dist/inspector/tabs.d.ts +1 -1
- package/dist/lib/control-size.d.ts +1 -1
- package/dist/lib/week.d.ts +2 -2
- package/dist/lib/week.js +2 -2
- package/dist/review/review-comment-card.js +2 -1
- package/package.json +3 -2
|
@@ -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
|
|
4
|
-
const toUTCDate = (value) => {
|
|
5
|
+
const toPlainDate = (value) => {
|
|
5
6
|
if (!ISO_DATE_PATTERN.test(value)) return null;
|
|
6
|
-
|
|
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 =
|
|
11
|
-
const earlierDate =
|
|
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
|
|
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 ||
|
|
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 =
|
|
38
|
+
const date = toPlainDate(value);
|
|
39
39
|
if (date === null) throw new RangeError("Calendar dates must use normalized YYYY-MM-DD values");
|
|
40
|
-
date.
|
|
41
|
-
|
|
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" | "chip" | "icon" | "icon-lg" | "icon-sm" | "icon-xl" | "icon-xs" | "
|
|
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
|
|
@@ -31,17 +31,27 @@ type ColorPickerProps = {
|
|
|
31
31
|
align?: "start" | "center" | "end";
|
|
32
32
|
className?: string;
|
|
33
33
|
};
|
|
34
|
-
type
|
|
34
|
+
type ColorPickerContentBaseProps = {
|
|
35
35
|
value?: string | undefined;
|
|
36
36
|
onSelect?: ((value: string) => void) | undefined;
|
|
37
|
-
onClear?: (() => void) | undefined;
|
|
38
37
|
presets: ColorPreset[];
|
|
39
|
-
columns: number;
|
|
40
|
-
defaultExpanded: boolean;
|
|
41
38
|
moreLabel: string;
|
|
42
39
|
};
|
|
40
|
+
type ColorPickerContentProps = ColorPickerContentBaseProps & ({
|
|
41
|
+
columns: number;
|
|
42
|
+
defaultExpanded: boolean;
|
|
43
|
+
onClear?: (() => void) | undefined;
|
|
44
|
+
/** Popover content closes on preset selection. */
|
|
45
|
+
presentation?: "popover";
|
|
46
|
+
} | {
|
|
47
|
+
columns?: never;
|
|
48
|
+
defaultExpanded?: never;
|
|
49
|
+
onClear?: never;
|
|
50
|
+
/** Inline content stays mounted and reserves its popup for custom color. */
|
|
51
|
+
presentation: "inline";
|
|
52
|
+
});
|
|
43
53
|
declare const DEFAULT_PRESETS: ColorPreset[];
|
|
44
|
-
declare const ColorPickerContent: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel }: ColorPickerContentProps) => React$1.JSX.Element;
|
|
54
|
+
declare const ColorPickerContent: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, presentation }: ColorPickerContentProps) => React$1.JSX.Element;
|
|
45
55
|
declare const ColorPicker: ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, children, side, align, className }: ColorPickerProps) => React$1.JSX.Element;
|
|
46
56
|
//#endregion
|
|
47
57
|
export { ColorPicker, ColorPickerContent, type ColorPickerContentProps, type ColorPickerProps, type ColorPreset, DEFAULT_PRESETS };
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { cn } from "../lib/utils.js";
|
|
3
|
+
import { OVERLAY_LAYER_CLASS_NAMES } from "../lib/overlay-layer.js";
|
|
3
4
|
import { CheckIcon, ChevronDownIcon } from "lucide-react";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
5
6
|
import { Suspense, lazy, useState } from "react";
|
|
6
7
|
import { Popover } from "@base-ui/react/popover";
|
|
7
8
|
//#region src/components/color-picker.tsx
|
|
@@ -112,25 +113,97 @@ const isLightHex = (hex) => {
|
|
|
112
113
|
const b = Number.parseInt(hex.slice(4, 6), 16);
|
|
113
114
|
return (r * 299 + g * 587 + b * 114) / 1e3 > 220;
|
|
114
115
|
};
|
|
116
|
+
const checkIconColorClassNames = {
|
|
117
|
+
dark: "text-(--color-white)",
|
|
118
|
+
light: "text-(--color-black)"
|
|
119
|
+
};
|
|
115
120
|
/** Check if a value looks like a 6-char hex (no CSS vars, no named colors). */
|
|
116
121
|
const looksLikeHex = (v) => /^[0-9A-Fa-f]{6}$/u.test(v);
|
|
117
|
-
const ColorSwatch = ({ cssColor, selected, label, isLight, onClick }) =>
|
|
118
|
-
|
|
122
|
+
const ColorSwatch = ({ cssColor, selected, label, isLight, onClick, presentation }) => {
|
|
123
|
+
let selectionClassName = "border-border/40";
|
|
124
|
+
if (selected) selectionClassName = presentation === "inline" ? "border-transparent ring-2 ring-ring" : "border-foreground ring-ring/24 ring-1";
|
|
125
|
+
const swatch = /* @__PURE__ */ jsx("button", {
|
|
119
126
|
"aria-label": label,
|
|
120
|
-
|
|
127
|
+
"aria-pressed": selected,
|
|
128
|
+
className: cn(presentation === "inline" ? "ring-offset-popover relative grid size-11 shrink-0 place-items-center rounded-full border ring-offset-2 transition-transform outline-none hover:scale-105 focus-visible:ring-2" : "hover:border-foreground relative flex size-6 items-center justify-center rounded-md border transition-[transform,border-color] hover:scale-115 sm:size-5", selectionClassName, isLight && !selected && "border-border"),
|
|
121
129
|
onClick,
|
|
122
130
|
style: { backgroundColor: cssColor },
|
|
123
|
-
type: "button"
|
|
131
|
+
type: "button",
|
|
132
|
+
children: selected && /* @__PURE__ */ jsx(CheckIcon, { className: cn("pointer-events-none", presentation === "inline" ? "bg-background/88 text-foreground size-5 rounded-full p-0.5 shadow-sm" : "size-3 sm:size-2.5", presentation === "popover" && checkIconColorClassNames[isLight ? "light" : "dark"]) })
|
|
133
|
+
});
|
|
134
|
+
return presentation === "inline" ? swatch : /* @__PURE__ */ jsx(Popover.Close, { render: swatch });
|
|
135
|
+
};
|
|
136
|
+
const CustomColorControls = ({ handleInputChange, handlePickerChange, inputHex, pickerHex }) => /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(Suspense, {
|
|
137
|
+
fallback: /* @__PURE__ */ jsx("div", {
|
|
138
|
+
"aria-hidden": true,
|
|
139
|
+
className: "ring-border/30 h-[140px] w-full rounded-lg ring-1"
|
|
124
140
|
}),
|
|
125
|
-
children:
|
|
126
|
-
className: "
|
|
127
|
-
|
|
141
|
+
children: /* @__PURE__ */ jsx(HexColorPicker, {
|
|
142
|
+
className: "ring-border/30 !h-[140px] !w-full overflow-hidden rounded-lg ring-1",
|
|
143
|
+
color: pickerHex,
|
|
144
|
+
onChange: (hex) => handlePickerChange(hex.replace("#", ""))
|
|
128
145
|
})
|
|
129
|
-
})
|
|
130
|
-
|
|
146
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
147
|
+
className: "flex items-center gap-1.5",
|
|
148
|
+
children: [
|
|
149
|
+
/* @__PURE__ */ jsx("span", {
|
|
150
|
+
className: "text-muted-foreground text-[11px]",
|
|
151
|
+
children: "#"
|
|
152
|
+
}),
|
|
153
|
+
/* @__PURE__ */ jsx("input", {
|
|
154
|
+
"aria-label": "Custom hex color",
|
|
155
|
+
className: "border-input bg-background text-foreground h-6 flex-1 rounded border px-1.5 font-mono text-[11px] outline-none",
|
|
156
|
+
dir: "ltr",
|
|
157
|
+
maxLength: 6,
|
|
158
|
+
onChange: (event) => handleInputChange(event.target.value),
|
|
159
|
+
onKeyDown: (event) => {
|
|
160
|
+
if (event.key !== "Escape") event.stopPropagation();
|
|
161
|
+
},
|
|
162
|
+
onMouseDown: (event) => event.stopPropagation(),
|
|
163
|
+
onPointerDown: (event) => event.stopPropagation(),
|
|
164
|
+
placeholder: "FF0000",
|
|
165
|
+
value: inputHex
|
|
166
|
+
}),
|
|
167
|
+
isValidHex(inputHex) && /* @__PURE__ */ jsx("span", {
|
|
168
|
+
className: "border-border size-6 shrink-0 rounded border",
|
|
169
|
+
style: { backgroundColor: `#${inputHex}` }
|
|
170
|
+
})
|
|
171
|
+
]
|
|
172
|
+
})] });
|
|
173
|
+
const InlineCustomColor = ({ customSelected, handleInputChange, handlePickerChange, inputHex, label, pickerHex, presets, value }) => {
|
|
174
|
+
const customColor = customSelected ? `#${value}` : void 0;
|
|
175
|
+
const customGradient = `conic-gradient(${presets.map((preset) => swatchColor(preset)).join(", ")})`;
|
|
176
|
+
return /* @__PURE__ */ jsxs(Popover.Root, { children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
177
|
+
render: /* @__PURE__ */ jsx("button", {
|
|
178
|
+
"aria-label": label,
|
|
179
|
+
"aria-pressed": customSelected,
|
|
180
|
+
className: cn("ring-offset-popover relative grid size-11 shrink-0 place-items-center rounded-full border border-transparent ring-offset-2 transition-transform outline-none hover:scale-105 focus-visible:ring-2", customSelected && "ring-ring ring-2"),
|
|
181
|
+
style: customColor ? { backgroundColor: customColor } : { backgroundImage: customGradient },
|
|
182
|
+
type: "button"
|
|
183
|
+
}),
|
|
184
|
+
children: customSelected ? /* @__PURE__ */ jsx(CheckIcon, { className: "bg-background/88 text-foreground pointer-events-none size-5 rounded-full p-0.5 shadow-sm" }) : null
|
|
185
|
+
}), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
186
|
+
align: "end",
|
|
187
|
+
className: OVERLAY_LAYER_CLASS_NAMES.popup,
|
|
188
|
+
side: "bottom",
|
|
189
|
+
sideOffset: 4,
|
|
190
|
+
children: /* @__PURE__ */ jsx(Popover.Popup, {
|
|
191
|
+
className: "bg-popover text-popover-foreground flex w-56 flex-col gap-2 rounded-lg border p-2 shadow-lg/5",
|
|
192
|
+
"data-slot": "color-picker-custom-popup",
|
|
193
|
+
children: /* @__PURE__ */ jsx(CustomColorControls, {
|
|
194
|
+
handleInputChange,
|
|
195
|
+
handlePickerChange,
|
|
196
|
+
inputHex,
|
|
197
|
+
pickerHex
|
|
198
|
+
})
|
|
199
|
+
})
|
|
200
|
+
}) })] });
|
|
201
|
+
};
|
|
202
|
+
const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaultExpanded, moreLabel, presentation = "popover" }) => {
|
|
131
203
|
const [expanded, setExpanded] = useState(defaultExpanded);
|
|
132
204
|
const [pickerHex, setPickerHex] = useState(() => (looksLikeHex(value ?? "") ? value : "000000") ?? "000000");
|
|
133
205
|
const [inputHex, setInputHex] = useState("");
|
|
206
|
+
const customSelected = !presets.some((preset) => preset.value === value) && looksLikeHex(value ?? "");
|
|
134
207
|
/** Called when the visual picker (SB square / hue strip) emits a color. */
|
|
135
208
|
const handlePickerChange = (hex) => {
|
|
136
209
|
const normalized = normalizeHex(hex);
|
|
@@ -147,6 +220,27 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
147
220
|
onSelect?.(cleaned);
|
|
148
221
|
}
|
|
149
222
|
};
|
|
223
|
+
if (presentation === "inline") return /* @__PURE__ */ jsxs("div", {
|
|
224
|
+
className: "flex items-center gap-1",
|
|
225
|
+
"data-slot": "color-picker",
|
|
226
|
+
children: [presets.map((preset) => /* @__PURE__ */ jsx(ColorSwatch, {
|
|
227
|
+
cssColor: swatchColor(preset),
|
|
228
|
+
isLight: looksLikeHex(preset.value) && isLightHex(preset.value),
|
|
229
|
+
label: preset.label,
|
|
230
|
+
onClick: () => onSelect?.(preset.value),
|
|
231
|
+
presentation: "inline",
|
|
232
|
+
selected: value === preset.value
|
|
233
|
+
}, preset.value)), /* @__PURE__ */ jsx(InlineCustomColor, {
|
|
234
|
+
customSelected,
|
|
235
|
+
handleInputChange,
|
|
236
|
+
handlePickerChange,
|
|
237
|
+
inputHex,
|
|
238
|
+
label: moreLabel,
|
|
239
|
+
pickerHex,
|
|
240
|
+
presets,
|
|
241
|
+
value
|
|
242
|
+
})]
|
|
243
|
+
});
|
|
150
244
|
return /* @__PURE__ */ jsxs("div", {
|
|
151
245
|
className: "flex flex-col gap-1.5",
|
|
152
246
|
"data-slot": "color-picker",
|
|
@@ -172,6 +266,7 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
172
266
|
isLight: looksLikeHex(preset.value) && isLightHex(preset.value),
|
|
173
267
|
label: preset.label,
|
|
174
268
|
onClick: () => onSelect?.(preset.value),
|
|
269
|
+
presentation: "popover",
|
|
175
270
|
selected: value === preset.value
|
|
176
271
|
}, preset.value))
|
|
177
272
|
}),
|
|
@@ -180,43 +275,14 @@ const ColorPickerContent = ({ value, onSelect, onClear, presets, columns, defaul
|
|
|
180
275
|
onClick: () => setExpanded(true),
|
|
181
276
|
type: "button",
|
|
182
277
|
children: [moreLabel, /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3" })]
|
|
183
|
-
}) : /* @__PURE__ */
|
|
278
|
+
}) : /* @__PURE__ */ jsx("div", {
|
|
184
279
|
className: "border-border flex flex-col gap-2 border-t pt-2",
|
|
185
|
-
children:
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
className: "ring-border/30 !h-[140px] !w-full overflow-hidden rounded-lg ring-1",
|
|
192
|
-
color: pickerHex,
|
|
193
|
-
onChange: (hex) => handlePickerChange(hex.replace("#", ""))
|
|
194
|
-
})
|
|
195
|
-
}), /* @__PURE__ */ jsxs("div", {
|
|
196
|
-
className: "flex items-center gap-1.5",
|
|
197
|
-
children: [
|
|
198
|
-
/* @__PURE__ */ jsx("span", {
|
|
199
|
-
className: "text-muted-foreground text-[11px]",
|
|
200
|
-
children: "#"
|
|
201
|
-
}),
|
|
202
|
-
/* @__PURE__ */ jsx("input", {
|
|
203
|
-
"aria-label": "Custom hex color",
|
|
204
|
-
className: "border-input bg-background text-foreground h-6 flex-1 rounded border px-1.5 font-mono text-[11px] outline-none",
|
|
205
|
-
dir: "ltr",
|
|
206
|
-
maxLength: 6,
|
|
207
|
-
onChange: (e) => handleInputChange(e.target.value),
|
|
208
|
-
onKeyDown: (e) => e.stopPropagation(),
|
|
209
|
-
onMouseDown: (e) => e.stopPropagation(),
|
|
210
|
-
onPointerDown: (e) => e.stopPropagation(),
|
|
211
|
-
placeholder: "FF0000",
|
|
212
|
-
value: inputHex
|
|
213
|
-
}),
|
|
214
|
-
isValidHex(inputHex) && /* @__PURE__ */ jsx("span", {
|
|
215
|
-
className: "border-border size-6 shrink-0 rounded border",
|
|
216
|
-
style: { backgroundColor: `#${inputHex}` }
|
|
217
|
-
})
|
|
218
|
-
]
|
|
219
|
-
})]
|
|
280
|
+
children: /* @__PURE__ */ jsx(CustomColorControls, {
|
|
281
|
+
handleInputChange,
|
|
282
|
+
handlePickerChange,
|
|
283
|
+
inputHex,
|
|
284
|
+
pickerHex
|
|
285
|
+
})
|
|
220
286
|
})
|
|
221
287
|
]
|
|
222
288
|
});
|
|
@@ -228,7 +294,7 @@ const ColorPicker = ({ value, onSelect, onClear, presets = DEFAULT_PRESETS, colu
|
|
|
228
294
|
children
|
|
229
295
|
}), /* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, {
|
|
230
296
|
align,
|
|
231
|
-
className:
|
|
297
|
+
className: OVERLAY_LAYER_CLASS_NAMES.popup,
|
|
232
298
|
side,
|
|
233
299
|
sideOffset: 4,
|
|
234
300
|
children: /* @__PURE__ */ jsx(Popover.Popup, {
|
|
@@ -240,6 +306,7 @@ const ColorPicker = ({ value, onSelect, onClear, presets = DEFAULT_PRESETS, colu
|
|
|
240
306
|
moreLabel,
|
|
241
307
|
onClear,
|
|
242
308
|
onSelect,
|
|
309
|
+
presentation: "popover",
|
|
243
310
|
presets,
|
|
244
311
|
value
|
|
245
312
|
})
|
|
@@ -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.
|
|
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(
|
|
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(
|
|
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 =
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
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 =
|
|
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.
|
|
78
|
+
isCurrentMonth: d.month === month + 1,
|
|
72
79
|
isToday: iso === today,
|
|
73
|
-
isWeekend: weekendDays.has(d.
|
|
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 =
|
|
97
|
+
const d = Temporal.PlainDate.from("2024-01-01").add({ days: (i + firstDow) % 7 });
|
|
91
98
|
return {
|
|
92
|
-
isWeekend: weekendDays.has(d.
|
|
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(
|
|
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(
|
|
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.
|
|
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 ? (
|
|
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) => (
|
|
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 =
|
|
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 = ((
|
|
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 = ((
|
|
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
|
-
|
|
222
|
-
|
|
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 =
|
|
241
|
-
const nextMonth = nextDate.
|
|
242
|
-
const nextYear = nextDate.
|
|
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 ? (
|
|
320
|
-
const selectedMonth = value ? (
|
|
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 =
|
|
454
|
+
const todayDate = Temporal.PlainDate.from(today);
|
|
455
455
|
setViewMonthOverride({
|
|
456
|
-
month: todayDate.
|
|
457
|
-
year: todayDate.
|
|
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 =
|
|
491
|
-
const todayMonth = now.
|
|
492
|
-
const todayYear = now.
|
|
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 = (
|
|
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 =
|
|
6
|
+
const current = Temporal.Instant.fromEpochMilliseconds(timestamp).toZonedDateTimeISO(Temporal.Now.timeZoneId());
|
|
6
7
|
return [
|
|
7
|
-
current.
|
|
8
|
-
padDatePart(current.
|
|
9
|
-
padDatePart(current.
|
|
8
|
+
current.year,
|
|
9
|
+
padDatePart(current.month),
|
|
10
|
+
padDatePart(current.day)
|
|
10
11
|
].join("-");
|
|
11
12
|
};
|
|
12
13
|
const calendarMonthFromDate = (date) => {
|
|
13
|
-
const current =
|
|
14
|
+
const current = Temporal.PlainDate.from(date);
|
|
14
15
|
return {
|
|
15
|
-
month: current.
|
|
16
|
-
year: current.
|
|
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 =
|
|
22
|
-
const nextLocalDate =
|
|
23
|
-
|
|
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 };
|
|
@@ -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 (
|
|
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 =
|
|
201
|
+
manualLockUntil.current = Temporal.Now.instant().epochMilliseconds + 900;
|
|
201
202
|
}
|
|
202
203
|
onJumpRef.current(id, container);
|
|
203
204
|
}, [activeId, scrollContainerRef]);
|
|
@@ -30,7 +30,7 @@ declare function useSidebar(): SidebarContextProps;
|
|
|
30
30
|
* left for the content column. Mobile reports 0: there the sidebar is an
|
|
31
31
|
* overlay sheet and occupies no layout width.
|
|
32
32
|
*/
|
|
33
|
-
declare function useSidebarInlineSize(): 0 |
|
|
33
|
+
declare function useSidebarInlineSize(): 0 | 48 | 256;
|
|
34
34
|
declare const SidebarProvider: ({ defaultOpen, forceCollapsed, open: openProp, onOpenChange: setOpenProp, className, style, children, ...props }: React.ComponentProps<"div"> & {
|
|
35
35
|
defaultOpen?: boolean;
|
|
36
36
|
forceCollapsed?: boolean;
|
|
@@ -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?: "
|
|
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;
|
package/dist/inspector/tabs.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ import { Tabs } from "@base-ui/react/tabs";
|
|
|
8
8
|
*/
|
|
9
9
|
declare const InspectorTabs: ({ className, ...props }: Omit<Tabs.Root.Props, "orientation">) => React$1.JSX.Element;
|
|
10
10
|
declare const INSPECTOR_RAIL_MEDIA_QUERY: "(min-width: 48rem)";
|
|
11
|
-
declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "
|
|
11
|
+
declare const resolveInspectorTabOrientation: (isRailLayout: boolean) => "horizontal" | "vertical";
|
|
12
12
|
declare const InspectorTabList: ({ className, ...props }: Tabs.List.Props) => React$1.JSX.Element;
|
|
13
13
|
declare const InspectorTab: ({ className, ...props }: Tabs.Tab.Props) => React$1.JSX.Element;
|
|
14
14
|
declare const InspectorTabPanel: ({ className, ...props }: Tabs.Panel.Props) => React$1.JSX.Element;
|
|
@@ -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 ("
|
|
8
|
+
declare const CONTROL_SIZES: readonly ("sm" | "default" | "lg")[];
|
|
9
9
|
//#endregion
|
|
10
10
|
export { CONTROL_SIZE, CONTROL_SIZES, type ControlSize };
|
package/dist/lib/week.d.ts
CHANGED
|
@@ -10,13 +10,13 @@
|
|
|
10
10
|
*/
|
|
11
11
|
declare const getLocaleWeekInfo: (locale: string) => Intl.WeekInfo | undefined;
|
|
12
12
|
/**
|
|
13
|
-
* First weekday as a
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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",
|