gridsmith-ui 0.29.1 → 0.30.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/CHANGELOG.md +94 -0
- package/README.md +5 -1
- package/dist/DropdownMenu-DqT7ZQ0D.d.ts +39 -0
- package/dist/charts.js +24 -9
- package/dist/charts.js.map +1 -1
- package/dist/chat.js +7 -7
- package/dist/{chunk-MFAWJSMJ.js → chunk-6C2IUMY7.js} +4 -23
- package/dist/chunk-6C2IUMY7.js.map +1 -0
- package/dist/{chunk-OYNUU346.js → chunk-7QLXYRPD.js} +3 -12
- package/dist/chunk-7QLXYRPD.js.map +1 -0
- package/dist/{chunk-FD4YED7O.js → chunk-DBHVJ7Z3.js} +5 -49
- package/dist/chunk-DBHVJ7Z3.js.map +1 -0
- package/dist/chunk-IELIF4PJ.js +110 -0
- package/dist/chunk-IELIF4PJ.js.map +1 -0
- package/dist/chunk-ISONVOA7.js +316 -0
- package/dist/chunk-ISONVOA7.js.map +1 -0
- package/dist/{chunk-4TUJXDRU.js → chunk-KMKBOTFR.js} +93 -32
- package/dist/chunk-KMKBOTFR.js.map +1 -0
- package/dist/{chunk-MKFWHWBK.js → chunk-L6HWACK7.js} +7 -7
- package/dist/chunk-L6HWACK7.js.map +1 -0
- package/dist/chunk-LJYSVZMI.js +25 -0
- package/dist/chunk-LJYSVZMI.js.map +1 -0
- package/dist/{chunk-6A5RHW2W.js → chunk-NEUWZUK6.js} +4 -5
- package/dist/chunk-NEUWZUK6.js.map +1 -0
- package/dist/chunk-NKUCS67T.js +13 -0
- package/dist/chunk-NKUCS67T.js.map +1 -0
- package/dist/{chunk-RECCCA7Z.js → chunk-OVHBQT3Z.js} +6 -5
- package/dist/chunk-OVHBQT3Z.js.map +1 -0
- package/dist/{chunk-I3MTQ3CS.js → chunk-OX3NNMWG.js} +6 -6
- package/dist/{chunk-I3MTQ3CS.js.map → chunk-OX3NNMWG.js.map} +1 -1
- package/dist/{chunk-ZI3OQDET.js → chunk-R5QXMNW7.js} +297 -15
- package/dist/chunk-R5QXMNW7.js.map +1 -0
- package/dist/chunk-SJZWEBHL.js +58 -0
- package/dist/chunk-SJZWEBHL.js.map +1 -0
- package/dist/{chunk-FUKSLQ77.js → chunk-SLRTSBCJ.js} +91 -51
- package/dist/chunk-SLRTSBCJ.js.map +1 -0
- package/dist/chunk-T52LAFKG.js +1350 -0
- package/dist/chunk-T52LAFKG.js.map +1 -0
- package/dist/chunk-TYNDXMBV.js +105 -0
- package/dist/chunk-TYNDXMBV.js.map +1 -0
- package/dist/{chunk-37WOC7F7.js → chunk-UDJOIVKQ.js} +31 -113
- package/dist/chunk-UDJOIVKQ.js.map +1 -0
- package/dist/{chunk-RJEUQ7RL.js → chunk-ULCACQSA.js} +47 -90
- package/dist/chunk-ULCACQSA.js.map +1 -0
- package/dist/{chunk-HP7WUZPK.js → chunk-WIUGPZOH.js} +10 -3
- package/dist/chunk-WIUGPZOH.js.map +1 -0
- package/dist/{chunk-JTU7OBYJ.js → chunk-YL5KD5RC.js} +4 -3
- package/dist/chunk-YL5KD5RC.js.map +1 -0
- package/dist/data-grid.d.ts +25 -6
- package/dist/data-grid.js +180 -58
- package/dist/data-grid.js.map +1 -1
- package/dist/editor-mentions.js +4 -5
- package/dist/editor-mentions.js.map +1 -1
- package/dist/editor.js +11 -8
- package/dist/editor.js.map +1 -1
- package/dist/{feather-FNBQ74RR.js → feather-XFFEFLTV.js} +5 -3
- package/dist/feather-XFFEFLTV.js.map +1 -0
- package/dist/{heroicons-DODCSYWD.js → heroicons-L6DOHBEA.js} +5 -3
- package/dist/heroicons-L6DOHBEA.js.map +1 -0
- package/dist/icons.d.ts +1 -1
- package/dist/icons.js +1 -1
- package/dist/index.d.ts +138 -39
- package/dist/index.js +846 -1667
- package/dist/index.js.map +1 -1
- package/dist/kanban.d.ts +26 -8
- package/dist/kanban.js +204 -79
- package/dist/kanban.js.map +1 -1
- package/dist/{lucide-ZWE3EPGP.js → lucide-JOORDTO6.js} +5 -3
- package/dist/lucide-JOORDTO6.js.map +1 -0
- package/dist/{phosphor-DIHPA4AJ.js → phosphor-TKGDYNGR.js} +5 -3
- package/dist/phosphor-TKGDYNGR.js.map +1 -0
- package/dist/resizable.js +47 -16
- package/dist/resizable.js.map +1 -1
- package/dist/roots.css +12 -8
- package/dist/{table-utils-CxnpFHRF.d.ts → table-utils-BXkP-2Hx.d.ts} +3 -1
- package/dist/{tabler-D3VYTSGI.js → tabler-YGETLYRU.js} +5 -3
- package/dist/tabler-YGETLYRU.js.map +1 -0
- package/dist/tokens.css +14 -0
- package/dist/utils.js.map +1 -1
- package/dist/virtualized.d.ts +6 -1
- package/dist/virtualized.js +17 -13
- package/dist/virtualized.js.map +1 -1
- package/dist-static/tokens.css +14 -0
- package/package.json +1 -1
- package/dist/chunk-37WOC7F7.js.map +0 -1
- package/dist/chunk-4TUJXDRU.js.map +0 -1
- package/dist/chunk-6A5RHW2W.js.map +0 -1
- package/dist/chunk-FD4YED7O.js.map +0 -1
- package/dist/chunk-FUKSLQ77.js.map +0 -1
- package/dist/chunk-HP7WUZPK.js.map +0 -1
- package/dist/chunk-JTU7OBYJ.js.map +0 -1
- package/dist/chunk-MFAWJSMJ.js.map +0 -1
- package/dist/chunk-MKFWHWBK.js.map +0 -1
- package/dist/chunk-OYNUU346.js.map +0 -1
- package/dist/chunk-QM4SJKWV.js +0 -51
- package/dist/chunk-QM4SJKWV.js.map +0 -1
- package/dist/chunk-QNHVPE2B.js +0 -117
- package/dist/chunk-QNHVPE2B.js.map +0 -1
- package/dist/chunk-RECCCA7Z.js.map +0 -1
- package/dist/chunk-RJEUQ7RL.js.map +0 -1
- package/dist/chunk-WH2FUFAC.js +0 -15
- package/dist/chunk-WH2FUFAC.js.map +0 -1
- package/dist/chunk-ZI3OQDET.js.map +0 -1
- package/dist/feather-FNBQ74RR.js.map +0 -1
- package/dist/heroicons-DODCSYWD.js.map +0 -1
- package/dist/lucide-ZWE3EPGP.js.map +0 -1
- package/dist/phosphor-DIHPA4AJ.js.map +0 -1
- package/dist/tabler-D3VYTSGI.js.map +0 -1
|
@@ -0,0 +1,1350 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useFieldControl, CHECK_FILL } from './chunk-SLRTSBCJ.js';
|
|
3
|
+
import { useHydrated, LocaleContext, useFormatLocale, useToday } from './chunk-LJYSVZMI.js';
|
|
4
|
+
import { formatLocale } from './chunk-7QLXYRPD.js';
|
|
5
|
+
import { useInputModality } from './chunk-7RKC5C7G.js';
|
|
6
|
+
import { useReportedChange } from './chunk-72SDAX54.js';
|
|
7
|
+
import { RowsCtx, ControlSizeContext, Button } from './chunk-ULCACQSA.js';
|
|
8
|
+
import { CONTROL_ANCESTOR, useGridKeyboard, usePopupFocus } from './chunk-R5QXMNW7.js';
|
|
9
|
+
import { useTextOverflow } from './chunk-IELIF4PJ.js';
|
|
10
|
+
import { RevealTooltip, AutoTooltip, Tooltip } from './chunk-UDJOIVKQ.js';
|
|
11
|
+
import { Icon } from './chunk-L6HWACK7.js';
|
|
12
|
+
import { mergeRefs, Slot } from './chunk-7Q46JXSK.js';
|
|
13
|
+
import { usePosition, useLatest } from './chunk-WIUGPZOH.js';
|
|
14
|
+
import { cn, FOCUS_RING, GLASS_DROPDOWN, PEER_FOCUS_RING, ERROR_ACTIVE_RING, ACTIVE_RING, ERROR_FOCUS_WITHIN_RING, FIELD_FOCUS_WITHIN_RING } from './chunk-YL5KD5RC.js';
|
|
15
|
+
import { createContext, forwardRef, useState, useCallback, cloneElement, useRef, useEffect, useContext, useId, useMemo, useLayoutEffect, Fragment as Fragment$1 } from 'react';
|
|
16
|
+
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
17
|
+
import { createPortal } from 'react-dom';
|
|
18
|
+
|
|
19
|
+
var CHECKBOX_SIZES = {
|
|
20
|
+
sm: { box: "h-[16px] w-[16px]", glyph: 10, label: "text-xs" },
|
|
21
|
+
md: { box: "h-[18px] w-[18px]", glyph: 12, label: "text-sm" }
|
|
22
|
+
};
|
|
23
|
+
function Checkbox({ checked, onChange: onChangeProp, label, size = "md", disabled = false, indeterminate = false, className, ref, ...wiring }) {
|
|
24
|
+
const onChange = useReportedChange(onChangeProp, checked);
|
|
25
|
+
const internalRef = useRef(null);
|
|
26
|
+
const spaceWithShift = useRef(false);
|
|
27
|
+
const dims = CHECKBOX_SIZES[size];
|
|
28
|
+
const control = useFieldControl(wiring);
|
|
29
|
+
const mergedRef = useCallback(
|
|
30
|
+
(node) => {
|
|
31
|
+
internalRef.current = node;
|
|
32
|
+
if (typeof ref === "function") ref(node);
|
|
33
|
+
else if (ref) ref.current = node;
|
|
34
|
+
},
|
|
35
|
+
[ref]
|
|
36
|
+
);
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (internalRef.current) internalRef.current.indeterminate = indeterminate;
|
|
39
|
+
}, [indeterminate]);
|
|
40
|
+
const showDash = indeterminate;
|
|
41
|
+
const filled = checked || indeterminate;
|
|
42
|
+
return /* @__PURE__ */ jsxs(
|
|
43
|
+
"label",
|
|
44
|
+
{
|
|
45
|
+
className: cn(
|
|
46
|
+
"flex items-center gap-ds-2.5 cursor-pointer select-none",
|
|
47
|
+
// a label's row is padded; a box alone isn't, its target drawn round it instead, 24 px square however small the
|
|
48
|
+
// box (WCAG 2.5.8), so it sits level with what's beside it (Sprint 25.8.7 item 22: a page's py-0 couldn't undo it)
|
|
49
|
+
label ? "py-ds-1" : "relative before:absolute before:left-1/2 before:top-1/2 before:h-6 before:w-6 before:-translate-x-1/2 before:-translate-y-1/2 before:content-['']",
|
|
50
|
+
disabled && "opacity-disabled cursor-not-allowed",
|
|
51
|
+
className
|
|
52
|
+
),
|
|
53
|
+
children: [
|
|
54
|
+
/* @__PURE__ */ jsxs("span", { className: "relative inline-flex shrink-0", children: [
|
|
55
|
+
/* @__PURE__ */ jsx(
|
|
56
|
+
"input",
|
|
57
|
+
{
|
|
58
|
+
ref: mergedRef,
|
|
59
|
+
type: "checkbox",
|
|
60
|
+
id: control.id,
|
|
61
|
+
"aria-label": control.label,
|
|
62
|
+
"aria-labelledby": wiring["aria-labelledby"],
|
|
63
|
+
"aria-describedby": control.describedBy,
|
|
64
|
+
"aria-invalid": control.invalid || void 0,
|
|
65
|
+
required: control.required || void 0,
|
|
66
|
+
checked,
|
|
67
|
+
disabled,
|
|
68
|
+
onKeyDown: (e) => {
|
|
69
|
+
if (e.key === " ") spaceWithShift.current = e.shiftKey;
|
|
70
|
+
},
|
|
71
|
+
onKeyUp: (e) => {
|
|
72
|
+
if (e.key === " ") setTimeout(() => {
|
|
73
|
+
spaceWithShift.current = false;
|
|
74
|
+
}, 0);
|
|
75
|
+
},
|
|
76
|
+
onBlur: () => {
|
|
77
|
+
spaceWithShift.current = false;
|
|
78
|
+
},
|
|
79
|
+
onChange: (e) => onChange(e.target.checked, { shiftKey: e.nativeEvent.shiftKey === true || spaceWithShift.current }),
|
|
80
|
+
className: "peer absolute inset-0 m-0 h-full w-full cursor-[inherit] opacity-0"
|
|
81
|
+
}
|
|
82
|
+
),
|
|
83
|
+
/* @__PURE__ */ jsx(
|
|
84
|
+
"span",
|
|
85
|
+
{
|
|
86
|
+
className: cn(
|
|
87
|
+
"flex items-center justify-center",
|
|
88
|
+
dims.box,
|
|
89
|
+
"shrink-0",
|
|
90
|
+
"rounded-[calc(var(--ds-radius-sm)*0.6)]",
|
|
91
|
+
"border-[2px]",
|
|
92
|
+
"transition-all",
|
|
93
|
+
PEER_FOCUS_RING,
|
|
94
|
+
filled ? cn(CHECK_FILL, "border-[var(--ds-check-border)]") : "bg-[var(--ds-input-bg)] border-[var(--ds-input-border)]",
|
|
95
|
+
disabled && "pointer-events-none"
|
|
96
|
+
),
|
|
97
|
+
children: /* @__PURE__ */ jsx(
|
|
98
|
+
"svg",
|
|
99
|
+
{
|
|
100
|
+
width: dims.glyph,
|
|
101
|
+
height: dims.glyph,
|
|
102
|
+
viewBox: "0 0 12 12",
|
|
103
|
+
fill: "none",
|
|
104
|
+
className: cn(
|
|
105
|
+
"text-[var(--ds-check-fg)] transition-opacity",
|
|
106
|
+
filled ? "opacity-100" : "opacity-0"
|
|
107
|
+
),
|
|
108
|
+
children: showDash ? /* @__PURE__ */ jsx("path", { d: "M3 6H9", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round" }) : /* @__PURE__ */ jsx("path", { d: "M2.5 6L5 8.5L9.5 3.5", stroke: "currentColor", strokeWidth: "1.75", strokeLinecap: "round", strokeLinejoin: "round" })
|
|
109
|
+
}
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
)
|
|
113
|
+
] }),
|
|
114
|
+
label && /* @__PURE__ */ jsx("span", { className: cn(dims.label, "text-[var(--ds-text-primary)]"), children: label })
|
|
115
|
+
]
|
|
116
|
+
}
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
var CheckboxGroupContext = createContext(null);
|
|
120
|
+
function CheckboxGroup({ value, onChange, children, className }) {
|
|
121
|
+
return /* @__PURE__ */ jsx(CheckboxGroupContext, { value: { value, onChange }, children: /* @__PURE__ */ jsx("div", { role: "group", className: cn("flex flex-col gap-ds-2", className), children }) });
|
|
122
|
+
}
|
|
123
|
+
function CheckboxGroupItem({ value, label, disabled }) {
|
|
124
|
+
const ctx = useContext(CheckboxGroupContext);
|
|
125
|
+
const resolvedValue = ctx?.value ?? [];
|
|
126
|
+
const resolvedOnChange = ctx?.onChange;
|
|
127
|
+
const checked = resolvedValue.includes(value);
|
|
128
|
+
return /* @__PURE__ */ jsx(
|
|
129
|
+
Checkbox,
|
|
130
|
+
{
|
|
131
|
+
checked,
|
|
132
|
+
disabled,
|
|
133
|
+
label,
|
|
134
|
+
onChange: (c) => {
|
|
135
|
+
resolvedOnChange?.(c ? [...resolvedValue, value] : resolvedValue.filter((v) => v !== value));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// ../../showcase/src/lib/date-grid.ts
|
|
142
|
+
function addDays(d, n) {
|
|
143
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
|
|
144
|
+
}
|
|
145
|
+
function addMonthsClamped(d, n) {
|
|
146
|
+
const first = new Date(d.getFullYear(), d.getMonth() + n, 1);
|
|
147
|
+
const last2 = new Date(first.getFullYear(), first.getMonth() + 1, 0).getDate();
|
|
148
|
+
return new Date(first.getFullYear(), first.getMonth(), Math.min(d.getDate(), last2));
|
|
149
|
+
}
|
|
150
|
+
function dayKey(d) {
|
|
151
|
+
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, "0")}-${String(d.getDate()).padStart(2, "0")}`;
|
|
152
|
+
}
|
|
153
|
+
function isExcludedDay(rule, day) {
|
|
154
|
+
if (!rule) return false;
|
|
155
|
+
return typeof rule === "function" ? rule(day) : rule.includes(day.getDay());
|
|
156
|
+
}
|
|
157
|
+
function moveDay(from, key, shift, weekStartsOn = 0) {
|
|
158
|
+
const intoWeek = (from.getDay() - weekStartsOn + 7) % 7;
|
|
159
|
+
switch (key) {
|
|
160
|
+
case "ArrowLeft":
|
|
161
|
+
return addDays(from, -1);
|
|
162
|
+
case "ArrowRight":
|
|
163
|
+
return addDays(from, 1);
|
|
164
|
+
case "ArrowUp":
|
|
165
|
+
return addDays(from, -7);
|
|
166
|
+
case "ArrowDown":
|
|
167
|
+
return addDays(from, 7);
|
|
168
|
+
case "Home":
|
|
169
|
+
return addDays(from, -intoWeek);
|
|
170
|
+
case "End":
|
|
171
|
+
return addDays(from, 6 - intoWeek);
|
|
172
|
+
case "PageUp":
|
|
173
|
+
return addMonthsClamped(from, shift ? -12 : -1);
|
|
174
|
+
case "PageDown":
|
|
175
|
+
return addMonthsClamped(from, shift ? 12 : 1);
|
|
176
|
+
default:
|
|
177
|
+
return null;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// ../../showcase/src/lib/segments.ts
|
|
182
|
+
function stepValue(spec, current, delta) {
|
|
183
|
+
if (current === null) return delta > 0 ? spec.min : spec.max;
|
|
184
|
+
const span = spec.max - spec.min + 1;
|
|
185
|
+
return spec.min + ((current - spec.min + delta) % span + span) % span;
|
|
186
|
+
}
|
|
187
|
+
function typeDigit(spec, buffer, digit) {
|
|
188
|
+
if (!/^\d$/.test(digit)) return { kind: "here", buffer, value: valueOf(spec, buffer) };
|
|
189
|
+
const next = buffer + digit;
|
|
190
|
+
if (buffer && (next.length > spec.maxDigits || Number(next) > spec.max)) return { kind: "next" };
|
|
191
|
+
return { kind: "here", buffer: next, value: valueOf(spec, next) };
|
|
192
|
+
}
|
|
193
|
+
function valueOf(spec, digits) {
|
|
194
|
+
if (!digits) return null;
|
|
195
|
+
const n = Number(digits);
|
|
196
|
+
return n >= spec.min && n <= spec.max ? n : null;
|
|
197
|
+
}
|
|
198
|
+
var DATE_SEPARATORS = ["/", "-", ".", " "];
|
|
199
|
+
var TIME_SEPARATORS = [":", ".", " "];
|
|
200
|
+
function separatorMovesOn(separators, key, holds) {
|
|
201
|
+
return holds && separators.includes(key);
|
|
202
|
+
}
|
|
203
|
+
var pad2 = (n) => String(n).padStart(2, "0");
|
|
204
|
+
function timeSegments(use24Hour) {
|
|
205
|
+
return [
|
|
206
|
+
{ key: "hour", label: "Hours", min: use24Hour ? 0 : 1, max: use24Hour ? 23 : 12, maxDigits: 2, placeholder: "--" },
|
|
207
|
+
{ key: "minute", label: "Minutes", min: 0, max: 59, maxDigits: 2, placeholder: "--" }
|
|
208
|
+
];
|
|
209
|
+
}
|
|
210
|
+
function dateSegments(dayFirst, daysInMonth = 31) {
|
|
211
|
+
const day = { key: "day", label: "Day", min: 1, max: daysInMonth, maxDigits: 2, placeholder: "dd" };
|
|
212
|
+
const month = { key: "month", label: "Month", min: 1, max: 12, maxDigits: 2, placeholder: "mm" };
|
|
213
|
+
const year = { key: "year", label: "Year", min: 1, max: 9999, maxDigits: 4, placeholder: "yyyy" };
|
|
214
|
+
return dayFirst ? [day, month, year] : [month, day, year];
|
|
215
|
+
}
|
|
216
|
+
function localeDayFirst(locale = formatLocale()) {
|
|
217
|
+
try {
|
|
218
|
+
const parts = new Intl.DateTimeFormat(locale).formatToParts(new Date(2e3, 11, 25));
|
|
219
|
+
return parts.findIndex((p) => p.type === "day") < parts.findIndex((p) => p.type === "month");
|
|
220
|
+
} catch {
|
|
221
|
+
return true;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
var NONE = { day: null, month: null, year: null };
|
|
225
|
+
var partsOf = (d) => d ? { day: d.getDate(), month: d.getMonth() + 1, year: d.getFullYear() } : NONE;
|
|
226
|
+
var daysIn = (year, monthIndex2) => new Date(year, monthIndex2 + 1, 0).getDate();
|
|
227
|
+
function dateOfParts(p) {
|
|
228
|
+
if (p.day === null || p.month === null || p.year === null) return null;
|
|
229
|
+
const d = new Date(p.year, p.month - 1, p.day);
|
|
230
|
+
return d.getFullYear() === p.year && d.getMonth() === p.month - 1 && d.getDate() === p.day ? d : null;
|
|
231
|
+
}
|
|
232
|
+
var sameDay = (a, b) => a === null || b === null ? a === b : a.getTime() === b.getTime();
|
|
233
|
+
function DateSegmentFields({ values, names, dayFirst, hydrated, disabled, onChange, between = "\u2013", focusRef }) {
|
|
234
|
+
const [parts, setParts] = useState(() => values.map(partsOf));
|
|
235
|
+
const [buffers, setBuffers] = useState({});
|
|
236
|
+
const reported = useRef(values.map(() => null));
|
|
237
|
+
const valuesKey = values.map((v) => v ? v.getTime() : "").join("|");
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
setParts((cur) => values.map((v, i) => sameDay(v, reported.current[i] ?? null) && cur[i] ? cur[i] : partsOf(v)));
|
|
240
|
+
setBuffers((b) => values.every((v, i) => sameDay(v, reported.current[i] ?? null)) ? b : {});
|
|
241
|
+
}, [valuesKey]);
|
|
242
|
+
const specsOf = (p) => dateSegments(dayFirst, hydrated && p.month && p.year ? daysIn(p.year, p.month - 1) : 31);
|
|
243
|
+
const all = parts.flatMap((p, d) => specsOf(p).map((spec) => ({ date: d, spec, k: spec.key })));
|
|
244
|
+
const bufferKey = (date, k) => `${date}:${k}`;
|
|
245
|
+
const refs = useRef([]);
|
|
246
|
+
const focusAt = (i) => {
|
|
247
|
+
refs.current[Math.max(0, Math.min(all.length - 1, i))]?.focus();
|
|
248
|
+
};
|
|
249
|
+
useEffect(() => {
|
|
250
|
+
focusRef?.(focusAt);
|
|
251
|
+
});
|
|
252
|
+
const report = (next) => {
|
|
253
|
+
const dates = next.map(dateOfParts);
|
|
254
|
+
reported.current = dates;
|
|
255
|
+
onChange(dates, next.map((p) => p.day !== null && p.month !== null && p.year !== null));
|
|
256
|
+
};
|
|
257
|
+
const setPart = (date, k, v) => {
|
|
258
|
+
const next = parts.map((p, i) => i === date ? { ...p, [k]: v } : p);
|
|
259
|
+
setParts(next);
|
|
260
|
+
report(next);
|
|
261
|
+
};
|
|
262
|
+
const fresh = (date, k) => setBuffers((b) => b[bufferKey(date, k)] ? { ...b, [bufferKey(date, k)]: "" } : b);
|
|
263
|
+
const typeInto = (i, digit) => {
|
|
264
|
+
const { date, spec, k } = all[i];
|
|
265
|
+
const r = typeDigit(spec, buffers[bufferKey(date, k)] ?? "", digit);
|
|
266
|
+
if (r.kind === "here") {
|
|
267
|
+
setBuffers((b) => ({ ...b, [bufferKey(date, k)]: r.buffer }));
|
|
268
|
+
setPart(date, k, r.value);
|
|
269
|
+
return;
|
|
270
|
+
}
|
|
271
|
+
const next = all[i + 1];
|
|
272
|
+
if (!next) return;
|
|
273
|
+
focusAt(i + 1);
|
|
274
|
+
const carried = typeDigit(next.spec, "", digit);
|
|
275
|
+
if (carried.kind !== "here") return;
|
|
276
|
+
setBuffers((b) => ({ ...b, [bufferKey(next.date, next.k)]: carried.buffer }));
|
|
277
|
+
setPart(next.date, next.k, carried.value);
|
|
278
|
+
};
|
|
279
|
+
const onKeyDown = (e, i, spec) => {
|
|
280
|
+
const key = e.key;
|
|
281
|
+
if (key === "Tab" || key === "Shift" || key === "Escape" || key.startsWith("F")) return;
|
|
282
|
+
e.preventDefault();
|
|
283
|
+
const { date, k } = all[i];
|
|
284
|
+
const held = parts[date][k];
|
|
285
|
+
const buffer = buffers[bufferKey(date, k)];
|
|
286
|
+
const clearBuffer = () => setBuffers((b) => ({ ...b, [bufferKey(date, k)]: "" }));
|
|
287
|
+
if (key === "ArrowLeft") {
|
|
288
|
+
focusAt(i - 1);
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
if (key === "ArrowRight") {
|
|
292
|
+
focusAt(i + 1);
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (key === "ArrowUp" || key === "ArrowDown") {
|
|
296
|
+
clearBuffer();
|
|
297
|
+
setPart(date, k, stepValue(spec, held, key === "ArrowUp" ? 1 : -1));
|
|
298
|
+
return;
|
|
299
|
+
}
|
|
300
|
+
if (key === "Home") {
|
|
301
|
+
clearBuffer();
|
|
302
|
+
setPart(date, k, spec.min);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
if (key === "End") {
|
|
306
|
+
clearBuffer();
|
|
307
|
+
setPart(date, k, spec.max);
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (key === "Backspace" || key === "Delete") {
|
|
311
|
+
if (held === null && !buffer) {
|
|
312
|
+
focusAt(i - 1);
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
clearBuffer();
|
|
316
|
+
setPart(date, k, null);
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (/^\d$/.test(key)) {
|
|
320
|
+
typeInto(i, key);
|
|
321
|
+
return;
|
|
322
|
+
}
|
|
323
|
+
if (separatorMovesOn(DATE_SEPARATORS, key, !!buffer || held !== null)) focusAt(i + 1);
|
|
324
|
+
};
|
|
325
|
+
const drawn = hydrated ? parts : parts.map(() => NONE);
|
|
326
|
+
const shown = (date, spec) => {
|
|
327
|
+
const k = spec.key;
|
|
328
|
+
const b = buffers[bufferKey(date, k)];
|
|
329
|
+
const v = drawn[date][k];
|
|
330
|
+
if (b && v === null) return b;
|
|
331
|
+
if (v === null) return spec.placeholder;
|
|
332
|
+
return k === "year" ? String(v) : pad2(v);
|
|
333
|
+
};
|
|
334
|
+
return /* @__PURE__ */ jsx(Fragment, { children: all.map(({ date, spec, k }, i) => {
|
|
335
|
+
const firstOfDate = i === 0 || all[i - 1].date !== date;
|
|
336
|
+
const name = names?.[date];
|
|
337
|
+
const v = drawn[date][k];
|
|
338
|
+
return /* @__PURE__ */ jsxs("span", { className: "contents", children: [
|
|
339
|
+
firstOfDate && date > 0 && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-ds-1 text-[var(--ds-text-muted)]", children: between }),
|
|
340
|
+
!firstOfDate && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "px-[1px] text-[var(--ds-text-muted)]", children: "/" }),
|
|
341
|
+
/* @__PURE__ */ jsx(
|
|
342
|
+
"span",
|
|
343
|
+
{
|
|
344
|
+
ref: (el) => {
|
|
345
|
+
refs.current[i] = el;
|
|
346
|
+
},
|
|
347
|
+
role: "spinbutton",
|
|
348
|
+
tabIndex: disabled ? -1 : 0,
|
|
349
|
+
"data-segment": spec.key,
|
|
350
|
+
"data-segment-of": names ? String(date) : void 0,
|
|
351
|
+
"aria-label": name ? `${name} ${spec.label.toLowerCase()}` : spec.label,
|
|
352
|
+
"aria-valuemin": spec.min,
|
|
353
|
+
"aria-valuemax": spec.max,
|
|
354
|
+
"aria-valuenow": v ?? void 0,
|
|
355
|
+
"aria-valuetext": v === null ? "empty" : String(v),
|
|
356
|
+
onKeyDown: (e) => onKeyDown(e, i, spec),
|
|
357
|
+
onFocus: () => fresh(date, k),
|
|
358
|
+
onMouseDown: () => fresh(date, k),
|
|
359
|
+
onClick: (e) => e.stopPropagation(),
|
|
360
|
+
className: cn("rounded-[var(--ds-radius-sm)] px-[2px] outline-none focus:bg-[var(--ds-accent-subtle)] focus:text-[var(--ds-accent-ink)] cursor-text", v === null && !buffers[bufferKey(date, k)] && "text-[var(--ds-text-muted)]"),
|
|
361
|
+
children: shown(date, spec)
|
|
362
|
+
}
|
|
363
|
+
)
|
|
364
|
+
] }, `${date}:${spec.key}`);
|
|
365
|
+
}) });
|
|
366
|
+
}
|
|
367
|
+
var FIRST_DAY_BY_REGION = Object.fromEntries([
|
|
368
|
+
...["AG", "AS", "BD", "BR", "BS", "BT", "BW", "BZ", "CA", "CO", "DM", "DO", "ET", "GT", "GU", "HK", "HN", "ID", "IL", "IN", "JM", "JP", "KE", "KH", "KR", "LA", "MH", "MM", "MO", "MT", "MX", "MZ", "NI", "NP", "PA", "PE", "PH", "PK", "PR", "PT", "PY", "SA", "SG", "SV", "TH", "TT", "TW", "UM", "US", "VE", "VI", "WS", "YE", "ZA", "ZW"].map((r) => [r, 0]),
|
|
369
|
+
...["AF", "BH", "DJ", "DZ", "EG", "IQ", "IR", "JO", "KW", "LY", "OM", "QA", "SD", "SY"].map((r) => [r, 6]),
|
|
370
|
+
["MV", 5]
|
|
371
|
+
]);
|
|
372
|
+
function weekStartOf(tag) {
|
|
373
|
+
if (!tag) return void 0;
|
|
374
|
+
try {
|
|
375
|
+
const locale = new Intl.Locale(tag);
|
|
376
|
+
const info = typeof locale.getWeekInfo === "function" ? locale.getWeekInfo() : locale.weekInfo;
|
|
377
|
+
if (info && typeof info.firstDay === "number" && info.firstDay >= 1 && info.firstDay <= 7) return info.firstDay % 7;
|
|
378
|
+
const region = locale.region ?? locale.maximize().region;
|
|
379
|
+
if (!region) return void 0;
|
|
380
|
+
return FIRST_DAY_BY_REGION[region] ?? 1;
|
|
381
|
+
} catch {
|
|
382
|
+
return void 0;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
var last = null;
|
|
386
|
+
function firstDayFor(spoken, page) {
|
|
387
|
+
for (const tag of [...spoken, page]) {
|
|
388
|
+
const found = weekStartOf(tag);
|
|
389
|
+
if (found !== void 0) return found;
|
|
390
|
+
}
|
|
391
|
+
return 1;
|
|
392
|
+
}
|
|
393
|
+
function regionWeekStart() {
|
|
394
|
+
if (typeof document === "undefined") return 1;
|
|
395
|
+
const spoken = typeof navigator === "undefined" ? [] : navigator.languages?.length ? navigator.languages : navigator.language ? [navigator.language] : [];
|
|
396
|
+
const page = formatLocale();
|
|
397
|
+
const key = `${spoken.join(",")}|${page ?? ""}`;
|
|
398
|
+
if (last?.key === key) return last.day;
|
|
399
|
+
const day = firstDayFor(spoken, page);
|
|
400
|
+
last = { key, day };
|
|
401
|
+
return day;
|
|
402
|
+
}
|
|
403
|
+
function useWeekStart(own, locale) {
|
|
404
|
+
const readable = useHydrated();
|
|
405
|
+
const choice = useContext(LocaleContext);
|
|
406
|
+
if (own !== void 0) return own;
|
|
407
|
+
if (locale !== void 0) return weekStartOf(locale) ?? 1;
|
|
408
|
+
if (readable) return regionWeekStart();
|
|
409
|
+
return choice?.hasHeader ? firstDayFor(choice.spoken, choice.server) : 1;
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// ../../showcase/src/lib/locale-cache.ts
|
|
413
|
+
var caches = /* @__PURE__ */ new Set();
|
|
414
|
+
function localeCache(limit) {
|
|
415
|
+
const map = /* @__PURE__ */ new Map();
|
|
416
|
+
caches.add(map);
|
|
417
|
+
return (key, make) => {
|
|
418
|
+
const hit = map.get(key);
|
|
419
|
+
if (hit !== void 0) {
|
|
420
|
+
map.delete(key);
|
|
421
|
+
map.set(key, hit);
|
|
422
|
+
return hit;
|
|
423
|
+
}
|
|
424
|
+
const made = make();
|
|
425
|
+
map.set(key, made);
|
|
426
|
+
if (map.size > limit) map.delete(map.keys().next().value);
|
|
427
|
+
return made;
|
|
428
|
+
};
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
// ../../showcase/src/components/Calendar/calendar-utils.ts
|
|
432
|
+
var formatters = localeCache(512);
|
|
433
|
+
function dtfFor(locale, options) {
|
|
434
|
+
return formatters(`${locale ?? ""}|${JSON.stringify(options)}`, () => new Intl.DateTimeFormat(locale, options));
|
|
435
|
+
}
|
|
436
|
+
function isSameDay(a, b) {
|
|
437
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
438
|
+
}
|
|
439
|
+
function isSameMonth(a, b) {
|
|
440
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth();
|
|
441
|
+
}
|
|
442
|
+
function isWeekend(d) {
|
|
443
|
+
const day = d.getDay();
|
|
444
|
+
return day === 0 || day === 6;
|
|
445
|
+
}
|
|
446
|
+
function startOfDay(d) {
|
|
447
|
+
return new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
448
|
+
}
|
|
449
|
+
function startOfWeek(d, weekStartsOn = 0) {
|
|
450
|
+
const date = new Date(d);
|
|
451
|
+
const day = date.getDay();
|
|
452
|
+
const diff = (day - weekStartsOn + 7) % 7;
|
|
453
|
+
date.setDate(date.getDate() - diff);
|
|
454
|
+
return startOfDay(date);
|
|
455
|
+
}
|
|
456
|
+
function endOfWeek(d, weekStartsOn = 0) {
|
|
457
|
+
const start = startOfWeek(d, weekStartsOn);
|
|
458
|
+
const end = new Date(start);
|
|
459
|
+
end.setDate(end.getDate() + 6);
|
|
460
|
+
end.setHours(23, 59, 59, 999);
|
|
461
|
+
return end;
|
|
462
|
+
}
|
|
463
|
+
function addDays2(d, n) {
|
|
464
|
+
const result = new Date(d);
|
|
465
|
+
result.setDate(result.getDate() + n);
|
|
466
|
+
return result;
|
|
467
|
+
}
|
|
468
|
+
function addMonths(d, n) {
|
|
469
|
+
const result = new Date(d);
|
|
470
|
+
const day = result.getDate();
|
|
471
|
+
result.setDate(1);
|
|
472
|
+
result.setMonth(result.getMonth() + n);
|
|
473
|
+
result.setDate(Math.min(day, new Date(result.getFullYear(), result.getMonth() + 1, 0).getDate()));
|
|
474
|
+
return result;
|
|
475
|
+
}
|
|
476
|
+
function getMonthGrid(year, month, weekStartsOn = 0) {
|
|
477
|
+
const firstOfMonth = new Date(year, month, 1);
|
|
478
|
+
const gridStart = startOfWeek(firstOfMonth, weekStartsOn);
|
|
479
|
+
const weeks = [];
|
|
480
|
+
const current = new Date(gridStart);
|
|
481
|
+
for (let w = 0; w < 6; w++) {
|
|
482
|
+
const week = [];
|
|
483
|
+
for (let d = 0; d < 7; d++) {
|
|
484
|
+
week.push(new Date(current));
|
|
485
|
+
current.setDate(current.getDate() + 1);
|
|
486
|
+
}
|
|
487
|
+
weeks.push(week);
|
|
488
|
+
}
|
|
489
|
+
return weeks;
|
|
490
|
+
}
|
|
491
|
+
function getWeekDays(date, weekStartsOn = 0) {
|
|
492
|
+
const start = startOfWeek(date, weekStartsOn);
|
|
493
|
+
const days = [];
|
|
494
|
+
for (let i = 0; i < 7; i++) {
|
|
495
|
+
days.push(addDays2(start, i));
|
|
496
|
+
}
|
|
497
|
+
return days;
|
|
498
|
+
}
|
|
499
|
+
var DAY_MS = 864e5;
|
|
500
|
+
function daysBetween(a, b) {
|
|
501
|
+
return Math.round((startOfDay(b).getTime() - startOfDay(a).getTime()) / DAY_MS);
|
|
502
|
+
}
|
|
503
|
+
function eventSpan(e) {
|
|
504
|
+
const first = startOfDay(e.start);
|
|
505
|
+
if (!e.end) return { first, last: first };
|
|
506
|
+
const lastInstant = e.allDay ? e.end : new Date(e.end.getTime() - 1);
|
|
507
|
+
const last2 = startOfDay(lastInstant);
|
|
508
|
+
return { first, last: last2 < first ? first : last2 };
|
|
509
|
+
}
|
|
510
|
+
function isBarEvent(e) {
|
|
511
|
+
if (e.allDay) return true;
|
|
512
|
+
if (!e.end) return false;
|
|
513
|
+
const dayLater = new Date(e.start);
|
|
514
|
+
dayLater.setDate(dayLater.getDate() + 1);
|
|
515
|
+
return e.end.getTime() >= dayLater.getTime();
|
|
516
|
+
}
|
|
517
|
+
function getEventsForDay(events, date) {
|
|
518
|
+
const day = startOfDay(date).getTime();
|
|
519
|
+
return events.filter((e) => {
|
|
520
|
+
const { first, last: last2 } = eventSpan(e);
|
|
521
|
+
return first.getTime() <= day && day <= last2.getTime();
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
function groupEventsByDay(events, from, to) {
|
|
525
|
+
const out = /* @__PURE__ */ new Map();
|
|
526
|
+
const lo = startOfDay(from), hi = startOfDay(to);
|
|
527
|
+
for (const e of events) {
|
|
528
|
+
const { first, last: last2 } = eventSpan(e);
|
|
529
|
+
for (let day = first < lo ? lo : first; day <= last2 && day < hi; day = new Date(day.getFullYear(), day.getMonth(), day.getDate() + 1)) {
|
|
530
|
+
const key = dayKey(day);
|
|
531
|
+
const list = out.get(key);
|
|
532
|
+
if (list) list.push(e);
|
|
533
|
+
else out.set(key, [e]);
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return out;
|
|
537
|
+
}
|
|
538
|
+
function dayPieces(events, date) {
|
|
539
|
+
const dayStart = startOfDay(date);
|
|
540
|
+
const next = new Date(dayStart.getFullYear(), dayStart.getMonth(), dayStart.getDate() + 1);
|
|
541
|
+
const pieces = [];
|
|
542
|
+
for (const event of events) {
|
|
543
|
+
if (isBarEvent(event)) continue;
|
|
544
|
+
const ownDayEnd = new Date(event.start.getFullYear(), event.start.getMonth(), event.start.getDate() + 1);
|
|
545
|
+
const end = event.end && event.end > event.start ? event.end : new Date(Math.min(event.start.getTime() + 36e5, ownDayEnd.getTime()));
|
|
546
|
+
const start = event.start < dayStart ? dayStart : event.start;
|
|
547
|
+
const stop = end > next ? next : end;
|
|
548
|
+
if (stop > start) pieces.push({ event, start, end: stop });
|
|
549
|
+
}
|
|
550
|
+
return pieces.sort((a, b) => a.start.getTime() - b.start.getTime() || b.end.getTime() - a.end.getTime());
|
|
551
|
+
}
|
|
552
|
+
function endDays(start, end) {
|
|
553
|
+
return end > start ? daysBetween(start, new Date(end.getTime() - 1)) : daysBetween(start, end);
|
|
554
|
+
}
|
|
555
|
+
function makeDateWords(locale) {
|
|
556
|
+
const dtf = (options) => dtfFor(locale, options);
|
|
557
|
+
const twelveHour = () => /^h1[12]$/.test(dtf({ hour: "numeric" }).resolvedOptions().hourCycle ?? "");
|
|
558
|
+
const timeOptions = () => ({ hour: twelveHour() ? "numeric" : "2-digit", minute: "2-digit" });
|
|
559
|
+
const dayOffset = (days) => new Intl.NumberFormat(locale, { signDisplay: "always" }).format(days);
|
|
560
|
+
function monthName(month, width = "long") {
|
|
561
|
+
return dtf({ month: width }).format(new Date(2026, month, 1));
|
|
562
|
+
}
|
|
563
|
+
function weekdayNames(weekStartsOn, width = "short") {
|
|
564
|
+
const f = dtf({ weekday: width });
|
|
565
|
+
return Array.from({ length: 7 }, (_, i) => f.format(new Date(2026, 0, 4 + weekStartsOn + i)));
|
|
566
|
+
}
|
|
567
|
+
function formatTime(d) {
|
|
568
|
+
return dtf(timeOptions()).format(d);
|
|
569
|
+
}
|
|
570
|
+
function formatHourLabel(hour) {
|
|
571
|
+
const at = new Date(2026, 0, 5, hour);
|
|
572
|
+
return twelveHour() ? dtf({ hour: "numeric" }).format(at) : dtf({ hour: "2-digit", minute: "2-digit" }).format(at);
|
|
573
|
+
}
|
|
574
|
+
function formatTimeRange(start, end) {
|
|
575
|
+
if (!end) return formatTime(start);
|
|
576
|
+
const f = dtf(timeOptions());
|
|
577
|
+
if (daysBetween(start, end) === 0) return f.formatRange(start, end);
|
|
578
|
+
const sep = f.formatRangeToParts(start, end).find((p) => p.source === "shared" && p.type === "literal")?.value ?? " \u2013 ";
|
|
579
|
+
const days = endDays(start, end);
|
|
580
|
+
return days === 0 ? `${f.format(start)}${sep}${f.format(end)}` : `${f.format(start)}${sep}${f.format(end)} (${dayOffset(days)})`;
|
|
581
|
+
}
|
|
582
|
+
function speakTimeRange(start, end) {
|
|
583
|
+
if (!end) return formatTime(start);
|
|
584
|
+
const days = endDays(start, end);
|
|
585
|
+
const to = `${formatTime(start)} to ${formatTime(end)}`;
|
|
586
|
+
return days === 0 ? to : days === 1 ? `${to} the next day` : `${to}, ${days} days later`;
|
|
587
|
+
}
|
|
588
|
+
function formatMonthYear(d) {
|
|
589
|
+
return dtf({ month: "long", year: "numeric" }).format(d);
|
|
590
|
+
}
|
|
591
|
+
function formatDayLong(d) {
|
|
592
|
+
return dtf({ weekday: "long", day: "numeric", month: "long", year: "numeric" }).format(d);
|
|
593
|
+
}
|
|
594
|
+
function formatDayShort(d) {
|
|
595
|
+
return dtf({ weekday: "short", day: "numeric", month: "short" }).format(d);
|
|
596
|
+
}
|
|
597
|
+
function formatDayMedium(d) {
|
|
598
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).format(d);
|
|
599
|
+
}
|
|
600
|
+
function formatDayRange(start, end) {
|
|
601
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfDay(start), startOfDay(end));
|
|
602
|
+
}
|
|
603
|
+
function formatMonthRange(start, end) {
|
|
604
|
+
return dtf({ month: "long", year: "numeric" }).formatRange(new Date(start.getFullYear(), start.getMonth(), 1), new Date(end.getFullYear(), end.getMonth(), 1));
|
|
605
|
+
}
|
|
606
|
+
function formatWeekRange(d, weekStartsOn = 0) {
|
|
607
|
+
return dtf({ day: "numeric", month: "short", year: "numeric" }).formatRange(startOfWeek(d, weekStartsOn), startOfDay(endOfWeek(d, weekStartsOn)));
|
|
608
|
+
}
|
|
609
|
+
function formatEventWhen(e, spoken = false) {
|
|
610
|
+
const { first, last: last2 } = eventSpan(e);
|
|
611
|
+
const multiDay = last2 > first;
|
|
612
|
+
if (e.allDay) {
|
|
613
|
+
if (!multiDay) return spoken ? formatDayLong(first) : formatDayShort(first);
|
|
614
|
+
return dtf(spoken ? { weekday: "long", day: "numeric", month: "long" } : { day: "numeric", month: "short" }).formatRange(first, last2);
|
|
615
|
+
}
|
|
616
|
+
if (!e.end || !isBarEvent(e)) {
|
|
617
|
+
const day = spoken ? formatDayLong(e.start) : formatDayShort(e.start);
|
|
618
|
+
const end = e.end && e.end > e.start ? e.end : void 0;
|
|
619
|
+
return `${day}, ${spoken ? speakTimeRange(e.start, end) : formatTimeRange(e.start, end)}`;
|
|
620
|
+
}
|
|
621
|
+
return dtf({ weekday: "short", day: "numeric", month: "short", hour: "numeric", minute: "2-digit" }).formatRange(e.start, e.end);
|
|
622
|
+
}
|
|
623
|
+
return { monthName, weekdayNames, formatTime, formatHourLabel, formatTimeRange, speakTimeRange, formatMonthYear, formatDayLong, formatDayShort, formatDayMedium, formatDayRange, formatMonthRange, formatWeekRange, formatEventWhen };
|
|
624
|
+
}
|
|
625
|
+
var wordsByLocale = localeCache(32);
|
|
626
|
+
function dateWords(locale) {
|
|
627
|
+
return wordsByLocale(locale ?? "", () => makeDateWords(locale));
|
|
628
|
+
}
|
|
629
|
+
function useDateWords() {
|
|
630
|
+
return dateWords(useFormatLocale());
|
|
631
|
+
}
|
|
632
|
+
function layoutWeek(events, days, capacity) {
|
|
633
|
+
const weekStart = startOfDay(days[0]);
|
|
634
|
+
const weekEnd = startOfDay(days[days.length - 1]);
|
|
635
|
+
const items = [];
|
|
636
|
+
for (const event of events) {
|
|
637
|
+
const { first, last: last2 } = eventSpan(event);
|
|
638
|
+
if (last2 < weekStart || first > weekEnd) continue;
|
|
639
|
+
items.push({
|
|
640
|
+
event,
|
|
641
|
+
startCol: Math.max(0, daysBetween(weekStart, first)),
|
|
642
|
+
endCol: Math.min(days.length - 1, daysBetween(weekStart, last2)),
|
|
643
|
+
before: first < weekStart,
|
|
644
|
+
after: last2 > weekEnd,
|
|
645
|
+
length: daysBetween(first, last2) + 1
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
items.sort((a, b) => {
|
|
649
|
+
const barA = isBarEvent(a.event) || a.length > 1, barB = isBarEvent(b.event) || b.length > 1;
|
|
650
|
+
if (barA !== barB) return barA ? -1 : 1;
|
|
651
|
+
if (barA && a.length !== b.length) return b.length - a.length;
|
|
652
|
+
return a.event.start.getTime() - b.event.start.getTime() || a.event.title.localeCompare(b.event.title);
|
|
653
|
+
});
|
|
654
|
+
const taken = [];
|
|
655
|
+
const laneOf = /* @__PURE__ */ new Map();
|
|
656
|
+
for (const item of items) {
|
|
657
|
+
let lane = 0;
|
|
658
|
+
while (Array.from({ length: item.endCol - item.startCol + 1 }, (_, k) => taken[lane]?.[item.startCol + k]).some(Boolean)) lane++;
|
|
659
|
+
taken[lane] ??= [];
|
|
660
|
+
for (let c = item.startCol; c <= item.endCol; c++) taken[lane][c] = true;
|
|
661
|
+
laneOf.set(item, lane);
|
|
662
|
+
}
|
|
663
|
+
const cap = Math.max(1, capacity);
|
|
664
|
+
const overflow = days.map((_, c) => items.some((it) => laneOf.get(it) >= cap && it.startCol <= c && c <= it.endCol));
|
|
665
|
+
const more = days.map((_, c) => overflow[c] ? items.filter((it) => laneOf.get(it) >= cap - 1 && it.startCol <= c && c <= it.endCol).map((it) => it.event) : []);
|
|
666
|
+
const segments = [];
|
|
667
|
+
for (const item of items) {
|
|
668
|
+
const lane = laneOf.get(item);
|
|
669
|
+
if (lane >= cap) continue;
|
|
670
|
+
if (lane < cap - 1) {
|
|
671
|
+
segments.push({ event: item.event, startCol: item.startCol, span: item.endCol - item.startCol + 1, lane, continuesBefore: item.before, continuesAfter: item.after });
|
|
672
|
+
continue;
|
|
673
|
+
}
|
|
674
|
+
let runStart = -1;
|
|
675
|
+
for (let c = item.startCol; c <= item.endCol + 1; c++) {
|
|
676
|
+
const free = c <= item.endCol && !overflow[c];
|
|
677
|
+
if (free && runStart < 0) runStart = c;
|
|
678
|
+
if (!free && runStart >= 0) {
|
|
679
|
+
segments.push({ event: item.event, startCol: runStart, span: c - runStart, lane, continuesBefore: runStart > item.startCol || item.before, continuesAfter: c - 1 < item.endCol || item.after });
|
|
680
|
+
runStart = -1;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
const lanes = Math.min(cap, taken.length);
|
|
685
|
+
return { segments, more, lanes };
|
|
686
|
+
}
|
|
687
|
+
function layoutPieces(pieces, minMinutes = 0) {
|
|
688
|
+
const out = [];
|
|
689
|
+
let group = [];
|
|
690
|
+
let columnEnds = [];
|
|
691
|
+
let groupEnd = -Infinity;
|
|
692
|
+
const close = () => {
|
|
693
|
+
for (const placed of group) placed.columns = columnEnds.length;
|
|
694
|
+
out.push(...group);
|
|
695
|
+
group = [];
|
|
696
|
+
columnEnds = [];
|
|
697
|
+
};
|
|
698
|
+
for (const piece of pieces) {
|
|
699
|
+
const at = piece.start.getTime();
|
|
700
|
+
const end = Math.max(piece.end.getTime(), at + minMinutes * 6e4);
|
|
701
|
+
if (group.length && at >= groupEnd) close();
|
|
702
|
+
let column = columnEnds.findIndex((e) => e <= at);
|
|
703
|
+
if (column < 0) column = columnEnds.push(0) - 1;
|
|
704
|
+
columnEnds[column] = end;
|
|
705
|
+
groupEnd = Math.max(group.length ? groupEnd : -Infinity, end);
|
|
706
|
+
group.push({ piece, column, columns: 0 });
|
|
707
|
+
}
|
|
708
|
+
if (group.length) close();
|
|
709
|
+
return out;
|
|
710
|
+
}
|
|
711
|
+
function timeToFraction(d) {
|
|
712
|
+
return (d.getHours() * 60 + d.getMinutes()) / (24 * 60);
|
|
713
|
+
}
|
|
714
|
+
var CONTROL_HEIGHT = {
|
|
715
|
+
sm: "h-[var(--ds-control-height-sm)]",
|
|
716
|
+
md: "h-[var(--ds-control-height-md)]",
|
|
717
|
+
lg: "h-[var(--ds-control-height-lg)]"
|
|
718
|
+
};
|
|
719
|
+
var TEXT_SIZE = {
|
|
720
|
+
sm: "text-xs",
|
|
721
|
+
md: "text-sm",
|
|
722
|
+
lg: "text-base"
|
|
723
|
+
};
|
|
724
|
+
var ENGLISH_MONTHS = [
|
|
725
|
+
"january",
|
|
726
|
+
"february",
|
|
727
|
+
"march",
|
|
728
|
+
"april",
|
|
729
|
+
"may",
|
|
730
|
+
"june",
|
|
731
|
+
"july",
|
|
732
|
+
"august",
|
|
733
|
+
"september",
|
|
734
|
+
"october",
|
|
735
|
+
"november",
|
|
736
|
+
"december"
|
|
737
|
+
];
|
|
738
|
+
function getDaysInMonth(year, month) {
|
|
739
|
+
return new Date(year, month + 1, 0).getDate();
|
|
740
|
+
}
|
|
741
|
+
function getFirstDayOfWeek(year, month, weekStartsOn) {
|
|
742
|
+
return (new Date(year, month, 1).getDay() - weekStartsOn + 7) % 7;
|
|
743
|
+
}
|
|
744
|
+
function isSameDay2(a, b) {
|
|
745
|
+
return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
746
|
+
}
|
|
747
|
+
function validDate(year, monthIndex2, day) {
|
|
748
|
+
if (monthIndex2 < 0 || monthIndex2 > 11 || day < 1) return null;
|
|
749
|
+
const d = new Date(year, monthIndex2, day);
|
|
750
|
+
return d.getFullYear() === year && d.getMonth() === monthIndex2 && d.getDate() === day ? d : null;
|
|
751
|
+
}
|
|
752
|
+
function monthIndex(name, locale) {
|
|
753
|
+
const typed = name.toLocaleLowerCase().replace(/\.$/, "");
|
|
754
|
+
const fold = (m) => m.toLocaleLowerCase().replace(/\.$/, "");
|
|
755
|
+
const { monthName } = dateWords(locale);
|
|
756
|
+
const lists = [ENGLISH_MONTHS, Array.from({ length: 12 }, (_, i) => fold(monthName(i, "long"))), Array.from({ length: 12 }, (_, i) => fold(monthName(i, "short")))];
|
|
757
|
+
for (const list of lists) {
|
|
758
|
+
const i = list.findIndex((m) => m.startsWith(typed) || typed.length >= 3 && typed.startsWith(m));
|
|
759
|
+
if (i >= 0) return i;
|
|
760
|
+
}
|
|
761
|
+
return -1;
|
|
762
|
+
}
|
|
763
|
+
function parseTypedDate(text, dayFirst = localeDayFirst(), locale = formatLocale()) {
|
|
764
|
+
const t = text.trim().replace(/\s+/g, " ");
|
|
765
|
+
if (!t) return null;
|
|
766
|
+
let m = /^(\d{4})-(\d{1,2})-(\d{1,2})$/.exec(t);
|
|
767
|
+
if (m) return validDate(Number(m[1]), Number(m[2]) - 1, Number(m[3]));
|
|
768
|
+
m = /^(\p{L}{3,})\.?\s+(\d{1,2}),?\s+(\d{4})$/u.exec(t);
|
|
769
|
+
if (m) {
|
|
770
|
+
const mi = monthIndex(m[1], locale);
|
|
771
|
+
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[2]));
|
|
772
|
+
}
|
|
773
|
+
m = /^(\d{1,2})\.?\s+(\p{L}{3,})\.?,?\s+(\d{4})$/u.exec(t);
|
|
774
|
+
if (m) {
|
|
775
|
+
const mi = monthIndex(m[2], locale);
|
|
776
|
+
return mi < 0 ? null : validDate(Number(m[3]), mi, Number(m[1]));
|
|
777
|
+
}
|
|
778
|
+
m = /^(\d{1,2})[/.-](\d{1,2})[/.-](\d{2,4})$/.exec(t);
|
|
779
|
+
if (m) {
|
|
780
|
+
const a = Number(m[1]), b = Number(m[2]);
|
|
781
|
+
const year = m[3].length === 2 ? 2e3 + Number(m[3]) : Number(m[3]);
|
|
782
|
+
const [day, month] = a > 12 ? [a, b] : b > 12 ? [b, a] : dayFirst ? [a, b] : [b, a];
|
|
783
|
+
return validDate(year, month - 1, day);
|
|
784
|
+
}
|
|
785
|
+
return null;
|
|
786
|
+
}
|
|
787
|
+
function DatePicker({ value, onChange: onChangeProp, placeholder = "Pick a date", disabled, className, ref, container, error = false, label, id, size: sizeProp, min, max, disabledDates, range, weekStartsOn: weekStartsOnProp, ...wiring }) {
|
|
788
|
+
const weekStartsOn = useWeekStart(weekStartsOnProp);
|
|
789
|
+
const locale = useFormatLocale();
|
|
790
|
+
const { formatDayLong, formatMonthYear, weekdayNames } = useDateWords();
|
|
791
|
+
const hydrated = useHydrated();
|
|
792
|
+
const today = useToday();
|
|
793
|
+
const onChange = useReportedChange(onChangeProp, value);
|
|
794
|
+
const contextSize = useContext(ControlSizeContext);
|
|
795
|
+
const size = sizeProp ?? contextSize ?? "md";
|
|
796
|
+
const [open, setOpen] = useState(false);
|
|
797
|
+
const [hover, setHover] = useState(null);
|
|
798
|
+
const [viewDate, setViewDate] = useState(() => value ?? range?.start ?? range?.end ?? /* @__PURE__ */ new Date());
|
|
799
|
+
const triggerRef = useRef(null);
|
|
800
|
+
const buttonRef = useRef(null);
|
|
801
|
+
const panelRef = useRef(null);
|
|
802
|
+
const gridRef = useRef(null);
|
|
803
|
+
const generatedId = useId();
|
|
804
|
+
const control = useFieldControl({ ...wiring, id, error: error || void 0 }, { requiredInDescription: true });
|
|
805
|
+
useInputModality();
|
|
806
|
+
const inputId = control.id ?? generatedId;
|
|
807
|
+
const pos = usePosition(triggerRef, panelRef, open, { side: "bottom", align: "start", offset: 4, flip: true });
|
|
808
|
+
const year = viewDate.getFullYear();
|
|
809
|
+
const month = viewDate.getMonth();
|
|
810
|
+
const daysInMonth = getDaysInMonth(year, month);
|
|
811
|
+
const firstDay = getFirstDayOfWeek(year, month, weekStartsOn);
|
|
812
|
+
const startOf = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
|
|
813
|
+
const isDisabledDay = (d) => !!min && d < startOf(min) || !!max && d > startOf(max) || isExcludedDay(disabledDates, d);
|
|
814
|
+
const [focusDate, setFocusDate] = useState(() => startOf(value ?? range?.start ?? range?.end ?? /* @__PURE__ */ new Date()));
|
|
815
|
+
const [prevOpen, setPrevOpen] = useState(open);
|
|
816
|
+
if (open !== prevOpen) {
|
|
817
|
+
setPrevOpen(open);
|
|
818
|
+
if (open) {
|
|
819
|
+
const start = startOf(value ?? range?.start ?? range?.end ?? today ?? /* @__PURE__ */ new Date());
|
|
820
|
+
setFocusDate(start);
|
|
821
|
+
setViewDate(new Date(start.getFullYear(), start.getMonth(), 1));
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
const showDay = (d) => {
|
|
825
|
+
setFocusDate(d);
|
|
826
|
+
if (d.getFullYear() !== year || d.getMonth() !== month) setViewDate(new Date(d.getFullYear(), d.getMonth(), 1));
|
|
827
|
+
};
|
|
828
|
+
const grid = useGridKeyboard({
|
|
829
|
+
container: gridRef,
|
|
830
|
+
active: focusDate,
|
|
831
|
+
setActive: showDay,
|
|
832
|
+
keyOf: dayKey,
|
|
833
|
+
move: (from, e) => moveDay(from, e.key, e.shiftKey, weekStartsOn)
|
|
834
|
+
});
|
|
835
|
+
const prevMonth = () => {
|
|
836
|
+
setViewDate(new Date(year, month - 1, 1));
|
|
837
|
+
setFocusDate(addMonthsClamped(focusDate, -1));
|
|
838
|
+
};
|
|
839
|
+
const nextMonth = () => {
|
|
840
|
+
setViewDate(new Date(year, month + 1, 1));
|
|
841
|
+
setFocusDate(addMonthsClamped(focusDate, 1));
|
|
842
|
+
};
|
|
843
|
+
const { isTop: isTopLayer, returnFocus } = usePopupFocus(open, { trigger: buttonRef, panel: panelRef, close: () => setOpen(false), tabExits: "edges" });
|
|
844
|
+
const focusActiveDay = useLatest(grid.focusActive);
|
|
845
|
+
useEffect(() => {
|
|
846
|
+
if (!open) return;
|
|
847
|
+
const raf = requestAnimationFrame(() => focusActiveDay.current());
|
|
848
|
+
return () => cancelAnimationFrame(raf);
|
|
849
|
+
}, [open, focusActiveDay]);
|
|
850
|
+
const choose = (d) => {
|
|
851
|
+
returnFocus();
|
|
852
|
+
onChange(d);
|
|
853
|
+
setOpen(false);
|
|
854
|
+
};
|
|
855
|
+
const dayFirst = useMemo(() => localeDayFirst(locale), [locale]);
|
|
856
|
+
const focusPart = useRef(() => {
|
|
857
|
+
});
|
|
858
|
+
useEffect(() => {
|
|
859
|
+
if (!open) return;
|
|
860
|
+
const handler = (e) => {
|
|
861
|
+
const t = e.target;
|
|
862
|
+
if (triggerRef.current?.contains(t) || panelRef.current?.contains(t)) return;
|
|
863
|
+
setOpen(false);
|
|
864
|
+
};
|
|
865
|
+
const keyHandler = (e) => {
|
|
866
|
+
if (e.key !== "Escape" || e.defaultPrevented || !isTopLayer()) return;
|
|
867
|
+
e.preventDefault();
|
|
868
|
+
returnFocus();
|
|
869
|
+
setOpen(false);
|
|
870
|
+
};
|
|
871
|
+
document.addEventListener("mousedown", handler);
|
|
872
|
+
document.addEventListener("keydown", keyHandler);
|
|
873
|
+
return () => {
|
|
874
|
+
document.removeEventListener("mousedown", handler);
|
|
875
|
+
document.removeEventListener("keydown", keyHandler);
|
|
876
|
+
};
|
|
877
|
+
}, [open, isTopLayer, returnFocus]);
|
|
878
|
+
const [typedInvalid, setTypedInvalid] = useState(false);
|
|
879
|
+
const takeTyped = (d, filled) => {
|
|
880
|
+
if (!filled) {
|
|
881
|
+
setTypedInvalid(false);
|
|
882
|
+
return;
|
|
883
|
+
}
|
|
884
|
+
const ok = !!d && !isDisabledDay(d);
|
|
885
|
+
setTypedInvalid(!ok);
|
|
886
|
+
if (d && ok && !(value && isSameDay2(value, d))) {
|
|
887
|
+
onChange(d);
|
|
888
|
+
setViewDate(d);
|
|
889
|
+
}
|
|
890
|
+
};
|
|
891
|
+
const applyTyped = (text) => {
|
|
892
|
+
const d = parseTypedDate(text, dayFirst, locale);
|
|
893
|
+
if (d) takeTyped(d, true);
|
|
894
|
+
};
|
|
895
|
+
const selectDay = (day) => {
|
|
896
|
+
const d = new Date(year, month, day);
|
|
897
|
+
if (isDisabledDay(d)) return;
|
|
898
|
+
choose(d);
|
|
899
|
+
};
|
|
900
|
+
const rangeA = range?.start ?? null;
|
|
901
|
+
const rangeB = range?.end ?? null;
|
|
902
|
+
const otherEnd = value ? rangeA && !isSameDay2(rangeA, value) ? rangeA : rangeB : rangeA ?? rangeB;
|
|
903
|
+
const thisEnd = value ?? (otherEnd && hover ? hover : null);
|
|
904
|
+
const [bandStart, bandEnd] = otherEnd && thisEnd ? otherEnd <= thisEnd ? [otherEnd, thisEnd] : [thisEnd, otherEnd] : [null, null];
|
|
905
|
+
const inBand = (d) => !!(bandStart && bandEnd && d > bandStart && d < bandEnd);
|
|
906
|
+
const cells = [];
|
|
907
|
+
for (let i = 0; i < firstDay; i++) cells.push(null);
|
|
908
|
+
for (let d = 1; d <= daysInMonth; d++) cells.push(d);
|
|
909
|
+
while (cells.length % 7) cells.push(null);
|
|
910
|
+
const weeks = [];
|
|
911
|
+
for (let i = 0; i < cells.length; i += 7) weeks.push(cells.slice(i, i + 7));
|
|
912
|
+
return /* @__PURE__ */ jsxs("div", { ref, className: cn(className), children: [
|
|
913
|
+
label && /* @__PURE__ */ jsx("label", { htmlFor: inputId, className: "block text-sm font-medium text-[var(--ds-text-primary)] mb-ds-1", children: label }),
|
|
914
|
+
control.requiredNote,
|
|
915
|
+
/* @__PURE__ */ jsxs(
|
|
916
|
+
"div",
|
|
917
|
+
{
|
|
918
|
+
ref: triggerRef,
|
|
919
|
+
"data-date-field": "",
|
|
920
|
+
role: "group",
|
|
921
|
+
id: inputId,
|
|
922
|
+
"aria-label": control.labelId ? void 0 : label ?? control.label ?? "Date",
|
|
923
|
+
"aria-labelledby": control.labelId,
|
|
924
|
+
"aria-describedby": control.describedBy,
|
|
925
|
+
"aria-description": !value ? placeholder : void 0,
|
|
926
|
+
"aria-invalid": control.invalid || typedInvalid || void 0,
|
|
927
|
+
onPaste: (e) => {
|
|
928
|
+
const text = e.clipboardData.getData("text");
|
|
929
|
+
if (text) {
|
|
930
|
+
e.preventDefault();
|
|
931
|
+
applyTyped(text);
|
|
932
|
+
}
|
|
933
|
+
},
|
|
934
|
+
className: cn(
|
|
935
|
+
"flex items-center gap-ds-2 w-full",
|
|
936
|
+
CONTROL_HEIGHT[size],
|
|
937
|
+
TEXT_SIZE[size],
|
|
938
|
+
"border-[length:var(--ds-border-width)]",
|
|
939
|
+
control.invalid || typedInvalid ? "border-[var(--ds-status-error)]" : "border-[var(--ds-input-border)]",
|
|
940
|
+
"bg-[var(--ds-input-bg)] rounded-[var(--ds-radius-md)]",
|
|
941
|
+
"shadow-[var(--ds-input-shadow)]",
|
|
942
|
+
"transition-colors",
|
|
943
|
+
"px-ds-3 py-ds-2",
|
|
944
|
+
!control.invalid && !disabled && !open && "hover:border-[var(--ds-input-border-hover)]",
|
|
945
|
+
open && (control.invalid || typedInvalid ? ERROR_ACTIVE_RING : ACTIVE_RING),
|
|
946
|
+
// the segments mark which part has focus (their tint); the field draws the focus (a hover keeps its border)
|
|
947
|
+
control.invalid || typedInvalid ? ERROR_FOCUS_WITHIN_RING : FIELD_FOCUS_WITHIN_RING,
|
|
948
|
+
disabled && "opacity-disabled cursor-not-allowed",
|
|
949
|
+
"text-[var(--ds-text-primary)]"
|
|
950
|
+
),
|
|
951
|
+
children: [
|
|
952
|
+
/* @__PURE__ */ jsx(Icon, { name: "calendar", size: 14, className: "text-[var(--ds-text-muted)] shrink-0" }),
|
|
953
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center min-w-0 flex-1 tabular-nums", onClick: () => focusPart.current(0), children: /* @__PURE__ */ jsx(
|
|
954
|
+
DateSegmentFields,
|
|
955
|
+
{
|
|
956
|
+
values: [value],
|
|
957
|
+
dayFirst,
|
|
958
|
+
hydrated,
|
|
959
|
+
disabled,
|
|
960
|
+
focusRef: (focus) => {
|
|
961
|
+
focusPart.current = focus;
|
|
962
|
+
},
|
|
963
|
+
onChange: ([d], [filled]) => takeTyped(d, filled)
|
|
964
|
+
}
|
|
965
|
+
) }),
|
|
966
|
+
/* @__PURE__ */ jsx(AutoTooltip, { content: "Choose a date", children: /* @__PURE__ */ jsx(
|
|
967
|
+
"button",
|
|
968
|
+
{
|
|
969
|
+
ref: buttonRef,
|
|
970
|
+
type: "button",
|
|
971
|
+
"aria-label": "Choose a date",
|
|
972
|
+
"aria-haspopup": "dialog",
|
|
973
|
+
"aria-expanded": open,
|
|
974
|
+
onClick: () => !disabled && setOpen(!open),
|
|
975
|
+
disabled,
|
|
976
|
+
className: cn("shrink-0 -mr-ds-1 rounded-[var(--ds-radius-sm)] text-[var(--ds-text-muted)] hover:text-[var(--ds-text-primary)] disabled:cursor-not-allowed", FOCUS_RING),
|
|
977
|
+
children: /* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 14 })
|
|
978
|
+
}
|
|
979
|
+
) })
|
|
980
|
+
]
|
|
981
|
+
}
|
|
982
|
+
),
|
|
983
|
+
open && createPortal(
|
|
984
|
+
/* @__PURE__ */ jsxs(
|
|
985
|
+
"div",
|
|
986
|
+
{
|
|
987
|
+
ref: panelRef,
|
|
988
|
+
role: "dialog",
|
|
989
|
+
"aria-label": "Choose a date",
|
|
990
|
+
tabIndex: -1,
|
|
991
|
+
className: cn(
|
|
992
|
+
"fixed z-[var(--ds-z-popover)] w-[280px] outline-none",
|
|
993
|
+
"bg-[var(--ds-bg-surface-elevated)]",
|
|
994
|
+
"[backdrop-filter:var(--ds-glass-filter)] [-webkit-backdrop-filter:var(--ds-glass-filter)]",
|
|
995
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
996
|
+
"rounded-[var(--ds-radius-md)]",
|
|
997
|
+
"shadow-[var(--ds-shadow-dropdown),var(--ds-glass-inset)]"
|
|
998
|
+
),
|
|
999
|
+
style: { top: pos.top, left: pos.left },
|
|
1000
|
+
children: [
|
|
1001
|
+
/* @__PURE__ */ jsxs(
|
|
1002
|
+
"div",
|
|
1003
|
+
{
|
|
1004
|
+
className: "flex items-center justify-between bg-[var(--ds-bg-muted)] rounded-t-[var(--ds-radius-md)]",
|
|
1005
|
+
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1006
|
+
children: [
|
|
1007
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: prevMonth, "aria-label": "Previous month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14, className: "rotate-180" }) }),
|
|
1008
|
+
/* @__PURE__ */ jsx("span", { className: "text-sm font-medium text-[var(--ds-text-primary)]", children: formatMonthYear(viewDate) }),
|
|
1009
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", size: "icon-sm", onClick: nextMonth, "aria-label": "Next month", children: /* @__PURE__ */ jsx(Icon, { name: "chevron-right", size: 14 }) })
|
|
1010
|
+
]
|
|
1011
|
+
}
|
|
1012
|
+
),
|
|
1013
|
+
/* @__PURE__ */ jsxs(
|
|
1014
|
+
"div",
|
|
1015
|
+
{
|
|
1016
|
+
ref: gridRef,
|
|
1017
|
+
role: "grid",
|
|
1018
|
+
"aria-label": formatMonthYear(viewDate),
|
|
1019
|
+
onKeyDown: grid.onKeyDown,
|
|
1020
|
+
className: "flex flex-col gap-[4px] tabular-nums",
|
|
1021
|
+
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1022
|
+
children: [
|
|
1023
|
+
/* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px] mb-ds-0.5", children: weekdayNames(weekStartsOn, "narrow").map((d, i) => /* @__PURE__ */ jsx("div", { role: "columnheader", "aria-label": weekdayNames(weekStartsOn, "long")[i], className: "text-center text-2xs font-medium text-[var(--ds-text-muted)] py-ds-1", children: d }, i)) }),
|
|
1024
|
+
weeks.map((week, w) => /* @__PURE__ */ jsx("div", { role: "row", className: "grid grid-cols-7 gap-[4px]", onMouseLeave: () => setHover(null), children: week.map((day, i) => {
|
|
1025
|
+
if (day === null) return /* @__PURE__ */ jsx("div", { role: "gridcell" }, `empty-${i}`);
|
|
1026
|
+
const dateObj = new Date(year, month, day);
|
|
1027
|
+
const isSelected = !!value && isSameDay2(dateObj, value);
|
|
1028
|
+
const isOtherEnd = !!otherEnd && isSameDay2(dateObj, otherEnd);
|
|
1029
|
+
const isToday = today !== null && isSameDay2(dateObj, today);
|
|
1030
|
+
const between = inBand(dateObj);
|
|
1031
|
+
const dis = isDisabledDay(dateObj);
|
|
1032
|
+
return /* @__PURE__ */ jsx(
|
|
1033
|
+
"button",
|
|
1034
|
+
{
|
|
1035
|
+
type: "button",
|
|
1036
|
+
role: "gridcell",
|
|
1037
|
+
"data-grid-key": dayKey(dateObj),
|
|
1038
|
+
tabIndex: grid.tabIndexOf(dateObj),
|
|
1039
|
+
"aria-disabled": dis || void 0,
|
|
1040
|
+
onClick: () => selectDay(day),
|
|
1041
|
+
onFocus: () => {
|
|
1042
|
+
if (!isSameDay2(dateObj, focusDate)) setFocusDate(dateObj);
|
|
1043
|
+
},
|
|
1044
|
+
onMouseEnter: () => setHover(dateObj),
|
|
1045
|
+
"aria-selected": isSelected,
|
|
1046
|
+
"aria-current": isToday ? "date" : void 0,
|
|
1047
|
+
"aria-label": formatDayLong(dateObj),
|
|
1048
|
+
className: cn(
|
|
1049
|
+
"w-full aspect-square flex items-center justify-center text-xs",
|
|
1050
|
+
"transition-colors cursor-pointer",
|
|
1051
|
+
FOCUS_RING,
|
|
1052
|
+
isSelected ? "bg-[var(--ds-accent-primary)] text-[var(--ds-text-on-primary)] font-bold rounded-[var(--ds-radius-sm)]" : isOtherEnd ? "bg-[var(--ds-accent-muted)] text-[var(--ds-accent-subtle-text)] font-semibold rounded-[var(--ds-radius-sm)]" : between ? "bg-[var(--ds-accent-subtle)] text-[var(--ds-accent-subtle-text)] rounded-none" : isToday ? "border-[length:var(--ds-border-width)] border-[var(--ds-accent-ink)] text-[var(--ds-accent-ink)] font-medium rounded-[var(--ds-radius-sm)]" : "text-[var(--ds-text-secondary)] hover:bg-[var(--ds-bg-emphasis)] rounded-[var(--ds-radius-sm)]",
|
|
1053
|
+
dis && "opacity-disabled cursor-not-allowed hover:bg-transparent"
|
|
1054
|
+
),
|
|
1055
|
+
children: day
|
|
1056
|
+
},
|
|
1057
|
+
day
|
|
1058
|
+
);
|
|
1059
|
+
}) }, w))
|
|
1060
|
+
]
|
|
1061
|
+
}
|
|
1062
|
+
),
|
|
1063
|
+
/* @__PURE__ */ jsxs(
|
|
1064
|
+
"div",
|
|
1065
|
+
{
|
|
1066
|
+
className: "flex justify-between items-center bg-[var(--ds-bg-muted)] border-t-[length:var(--ds-border-width)] border-[var(--ds-border-subtle)] rounded-b-[var(--ds-radius-md)]",
|
|
1067
|
+
style: { padding: "var(--ds-space-2) var(--ds-space-3)" },
|
|
1068
|
+
children: [
|
|
1069
|
+
/* @__PURE__ */ jsx(
|
|
1070
|
+
Button,
|
|
1071
|
+
{
|
|
1072
|
+
type: "button",
|
|
1073
|
+
variant: "ghost",
|
|
1074
|
+
size: "sm",
|
|
1075
|
+
disabled: today !== null && isDisabledDay(startOf(today)),
|
|
1076
|
+
onClick: () => {
|
|
1077
|
+
const now = /* @__PURE__ */ new Date();
|
|
1078
|
+
setViewDate(now);
|
|
1079
|
+
choose(now);
|
|
1080
|
+
},
|
|
1081
|
+
children: "Today"
|
|
1082
|
+
}
|
|
1083
|
+
),
|
|
1084
|
+
value && /* @__PURE__ */ jsx(
|
|
1085
|
+
Button,
|
|
1086
|
+
{
|
|
1087
|
+
type: "button",
|
|
1088
|
+
variant: "ghost",
|
|
1089
|
+
size: "sm",
|
|
1090
|
+
onClick: () => choose(null),
|
|
1091
|
+
children: "Clear"
|
|
1092
|
+
}
|
|
1093
|
+
)
|
|
1094
|
+
]
|
|
1095
|
+
}
|
|
1096
|
+
)
|
|
1097
|
+
]
|
|
1098
|
+
}
|
|
1099
|
+
),
|
|
1100
|
+
container ?? document.body
|
|
1101
|
+
)
|
|
1102
|
+
] });
|
|
1103
|
+
}
|
|
1104
|
+
function HoverCard({
|
|
1105
|
+
content,
|
|
1106
|
+
children,
|
|
1107
|
+
side = "bottom",
|
|
1108
|
+
delay = 300,
|
|
1109
|
+
closeDelay = 200,
|
|
1110
|
+
className,
|
|
1111
|
+
container
|
|
1112
|
+
}) {
|
|
1113
|
+
const [open, setOpen] = useState(false);
|
|
1114
|
+
const triggerRef = useRef(null);
|
|
1115
|
+
const floatingRef = useRef(null);
|
|
1116
|
+
const openTimeout = useRef(void 0);
|
|
1117
|
+
const closeTimeout = useRef(void 0);
|
|
1118
|
+
const pos = usePosition(triggerRef, floatingRef, open, { side, offset: 8, flip: true });
|
|
1119
|
+
const show = useCallback(() => {
|
|
1120
|
+
clearTimeout(closeTimeout.current);
|
|
1121
|
+
openTimeout.current = setTimeout(() => setOpen(true), delay);
|
|
1122
|
+
}, [delay]);
|
|
1123
|
+
const hide = useCallback(() => {
|
|
1124
|
+
clearTimeout(openTimeout.current);
|
|
1125
|
+
closeTimeout.current = setTimeout(() => setOpen(false), closeDelay);
|
|
1126
|
+
}, [closeDelay]);
|
|
1127
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1128
|
+
/* @__PURE__ */ jsx(
|
|
1129
|
+
Slot,
|
|
1130
|
+
{
|
|
1131
|
+
ref: triggerRef,
|
|
1132
|
+
onMouseEnter: show,
|
|
1133
|
+
onMouseLeave: hide,
|
|
1134
|
+
onFocus: show,
|
|
1135
|
+
onBlur: hide,
|
|
1136
|
+
children
|
|
1137
|
+
}
|
|
1138
|
+
),
|
|
1139
|
+
open && createPortal(
|
|
1140
|
+
/* @__PURE__ */ jsx(
|
|
1141
|
+
"div",
|
|
1142
|
+
{
|
|
1143
|
+
ref: floatingRef,
|
|
1144
|
+
onMouseEnter: () => {
|
|
1145
|
+
clearTimeout(closeTimeout.current);
|
|
1146
|
+
},
|
|
1147
|
+
onMouseLeave: hide,
|
|
1148
|
+
className: cn(
|
|
1149
|
+
"fixed z-[var(--ds-z-popover)]",
|
|
1150
|
+
"w-72 p-ds-4",
|
|
1151
|
+
"bg-[var(--ds-bg-surface-elevated)] text-[var(--ds-text-primary)]",
|
|
1152
|
+
GLASS_DROPDOWN,
|
|
1153
|
+
"border-[length:var(--ds-border-width)] border-[var(--ds-border-default)]",
|
|
1154
|
+
"rounded-[var(--ds-radius-md)]",
|
|
1155
|
+
"animate-in fade-in-0 zoom-in-95",
|
|
1156
|
+
className
|
|
1157
|
+
),
|
|
1158
|
+
style: { top: pos.top, left: pos.left },
|
|
1159
|
+
children: /* @__PURE__ */ jsx(RowsCtx, { value: false, children: content })
|
|
1160
|
+
}
|
|
1161
|
+
),
|
|
1162
|
+
container ?? document.body
|
|
1163
|
+
)
|
|
1164
|
+
] });
|
|
1165
|
+
}
|
|
1166
|
+
var TEXT_HOLDER = `${CONTROL_ANCESTOR}, tr[tabindex]`;
|
|
1167
|
+
function CutText({ cut, content, card = false, children }) {
|
|
1168
|
+
const [inControl, setInControl] = useState(false);
|
|
1169
|
+
const placed = useCallback((el) => {
|
|
1170
|
+
if (!el) return;
|
|
1171
|
+
const inside = !!el.parentElement?.closest(TEXT_HOLDER);
|
|
1172
|
+
if (inside) el.removeAttribute("tabindex");
|
|
1173
|
+
setInControl(inside);
|
|
1174
|
+
}, []);
|
|
1175
|
+
if (!cut) return children;
|
|
1176
|
+
const stop = cloneElement(children, {
|
|
1177
|
+
ref: mergeRefs(children.props.ref, placed),
|
|
1178
|
+
...inControl ? {} : { tabIndex: 0, className: cn(children.props.className, "rounded-[var(--ds-radius-sm)]", FOCUS_RING) }
|
|
1179
|
+
});
|
|
1180
|
+
if (card) {
|
|
1181
|
+
return /* @__PURE__ */ jsx(HoverCard, { content: /* @__PURE__ */ jsx("div", { className: "max-w-[320px] text-sm text-[var(--ds-text-primary)]", children: content }), children: stop });
|
|
1182
|
+
}
|
|
1183
|
+
return /* @__PURE__ */ jsx(RevealTooltip, { content, children: stop });
|
|
1184
|
+
}
|
|
1185
|
+
function CutCell({ children, lines }) {
|
|
1186
|
+
const { ref, isTruncated } = useTextOverflow({ lines });
|
|
1187
|
+
const clampClass = lines === 1 ? "truncate" : `line-clamp-${lines}`;
|
|
1188
|
+
return /* @__PURE__ */ jsx(CutText, { cut: isTruncated, content: children, children: /* @__PURE__ */ jsx("span", { ref, className: cn(clampClass, "block"), children }) });
|
|
1189
|
+
}
|
|
1190
|
+
function CutEmail({ children }) {
|
|
1191
|
+
const { ref, isTruncated } = useTextOverflow({ lines: 1 });
|
|
1192
|
+
return /* @__PURE__ */ jsx(CutText, { cut: isTruncated, content: children, children: /* @__PURE__ */ jsx("span", { ref, className: "max-w-[40ch] truncate inline-block align-bottom", children }) });
|
|
1193
|
+
}
|
|
1194
|
+
var lineClampClasses = {
|
|
1195
|
+
1: "truncate",
|
|
1196
|
+
2: "line-clamp-2",
|
|
1197
|
+
3: "line-clamp-3",
|
|
1198
|
+
4: "line-clamp-4",
|
|
1199
|
+
5: "line-clamp-5",
|
|
1200
|
+
6: "line-clamp-6"
|
|
1201
|
+
};
|
|
1202
|
+
function getTruncationClass(lines) {
|
|
1203
|
+
return lineClampClasses[lines] || `line-clamp-[${lines}]`;
|
|
1204
|
+
}
|
|
1205
|
+
var TextOverflow = forwardRef(function TextOverflow2({
|
|
1206
|
+
lines = 1,
|
|
1207
|
+
tooltip = true,
|
|
1208
|
+
tooltipContent,
|
|
1209
|
+
expandMode = "tooltip",
|
|
1210
|
+
as = "div",
|
|
1211
|
+
children,
|
|
1212
|
+
className
|
|
1213
|
+
}, forwardedRef) {
|
|
1214
|
+
const { ref: overflowRef, isTruncated } = useTextOverflow({ lines });
|
|
1215
|
+
const truncClass = getTruncationClass(lines);
|
|
1216
|
+
const Tag = as;
|
|
1217
|
+
const content = /* @__PURE__ */ jsx(
|
|
1218
|
+
Tag,
|
|
1219
|
+
{
|
|
1220
|
+
ref: (node) => {
|
|
1221
|
+
overflowRef(node);
|
|
1222
|
+
if (typeof forwardedRef === "function") forwardedRef(node);
|
|
1223
|
+
else if (forwardedRef) forwardedRef.current = node;
|
|
1224
|
+
},
|
|
1225
|
+
className: cn(truncClass, "min-w-0", className),
|
|
1226
|
+
children
|
|
1227
|
+
}
|
|
1228
|
+
);
|
|
1229
|
+
if (!tooltip) return content;
|
|
1230
|
+
return /* @__PURE__ */ jsx(CutText, { cut: isTruncated, content: tooltipContent ?? children, card: expandMode === "hovercard", children: content });
|
|
1231
|
+
});
|
|
1232
|
+
function SortIndicator({ sorted }) {
|
|
1233
|
+
return /* @__PURE__ */ jsx("span", { "aria-hidden": "true", "data-sort": sorted || "none", className: "relative inline-block h-[18px] w-3 shrink-0", children: sorted ? /* @__PURE__ */ jsx(Icon, { name: sorted === "asc" ? "chevron-up" : "chevron-down", size: 12, className: "absolute left-0 top-[3px] text-[var(--ds-accent-ink)]" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1234
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-up", size: 12, className: "absolute left-0 top-0 text-[var(--ds-text-muted)]" }),
|
|
1235
|
+
/* @__PURE__ */ jsx(Icon, { name: "chevron-down", size: 12, className: "absolute left-0 bottom-0 text-[var(--ds-text-muted)]" })
|
|
1236
|
+
] }) });
|
|
1237
|
+
}
|
|
1238
|
+
|
|
1239
|
+
// ../../showcase/src/lib/table-utils.ts
|
|
1240
|
+
var DATE_ISO = /^\d{4}-\d{2}-\d{2}$/;
|
|
1241
|
+
var DATE_US = /^\d{1,2}\/\d{1,2}\/\d{4}$/;
|
|
1242
|
+
var MONTH = "[A-Z][a-z]{2,8}\\.?";
|
|
1243
|
+
var DATE_TEXT_MDY = new RegExp(`^${MONTH}\\s+\\d{1,2},?\\s+\\d{4}$`);
|
|
1244
|
+
var DATE_TEXT_DMY = new RegExp(`^\\d{1,2}\\s+${MONTH}\\s+\\d{4}$`);
|
|
1245
|
+
var MONTH_NAME = "(?:Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|June?|July?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\\.?";
|
|
1246
|
+
var DATE_TEXT_MD = new RegExp(`^${MONTH_NAME}\\s+\\d{1,2}$`);
|
|
1247
|
+
var DATE_TEXT_DM = new RegExp(`^\\d{1,2}\\s+${MONTH_NAME}$`);
|
|
1248
|
+
var NUMBER_RE = /^[$€£¥]?\s?[\d,]+\.?\d*\s?(?:%|[KMGTP]i?B|B|bytes?|ms|s|sec|min|h|hrs?|kg|g|km|m|°[CF])?$/i;
|
|
1249
|
+
var IDENTIFIER_RE = /^\d{13,}$/;
|
|
1250
|
+
var EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
1251
|
+
function isDate(v) {
|
|
1252
|
+
return DATE_ISO.test(v) || DATE_US.test(v) || DATE_TEXT_MDY.test(v) || DATE_TEXT_DMY.test(v) || DATE_TEXT_MD.test(v) || DATE_TEXT_DM.test(v);
|
|
1253
|
+
}
|
|
1254
|
+
function isJsx(v) {
|
|
1255
|
+
return typeof v === "object" && v !== null;
|
|
1256
|
+
}
|
|
1257
|
+
function detectKind(values) {
|
|
1258
|
+
const present = values.filter((v) => v != null);
|
|
1259
|
+
if (present.length === 0) return void 0;
|
|
1260
|
+
if (present.some(isJsx)) return void 0;
|
|
1261
|
+
if (present.every((v) => typeof v === "boolean")) return "boolean";
|
|
1262
|
+
if (present.every((v) => typeof v === "string" && isDate(v))) return "date";
|
|
1263
|
+
if (present.every((v) => typeof v === "string" && IDENTIFIER_RE.test(v) || typeof v === "number" && Math.abs(v) >= 1e13 && Number.isInteger(v))) return "identifier";
|
|
1264
|
+
if (present.every((v) => typeof v === "number")) return "number";
|
|
1265
|
+
if (present.every((v) => typeof v === "string" && NUMBER_RE.test(v))) return "number";
|
|
1266
|
+
if (present.every((v) => typeof v === "string" && EMAIL_RE.test(v))) return "email";
|
|
1267
|
+
if (present.every((v) => typeof v === "string" && v.length <= 20 && !/[\n\r]/.test(v))) return "label";
|
|
1268
|
+
return "text";
|
|
1269
|
+
}
|
|
1270
|
+
function kindOfRenderedText(texts) {
|
|
1271
|
+
const kind = detectKind(texts.map((t) => t.trim()).filter(Boolean));
|
|
1272
|
+
return kind === "date" || kind === "number" ? kind : void 0;
|
|
1273
|
+
}
|
|
1274
|
+
function inferColumnKinds(data, columnKeys, maxSample = 50) {
|
|
1275
|
+
const sample = data.length > maxSample ? data.slice(0, maxSample) : data;
|
|
1276
|
+
const result = /* @__PURE__ */ new Map();
|
|
1277
|
+
for (const key of columnKeys) {
|
|
1278
|
+
const values = sample.map((row) => row[key]);
|
|
1279
|
+
const kind = detectKind(values);
|
|
1280
|
+
if (kind) result.set(key, kind);
|
|
1281
|
+
}
|
|
1282
|
+
return result;
|
|
1283
|
+
}
|
|
1284
|
+
var CARD_VALUE_CLASS = cn(
|
|
1285
|
+
"min-w-0 text-right text-[var(--ds-text-primary)]",
|
|
1286
|
+
"[overflow-wrap:break-word] [&_*]:min-w-0 [&_*]:[overflow-wrap:break-word]",
|
|
1287
|
+
// A hand-rolled avatar cell (div > Avatar + text) keeps its row and sits against the value column's right edge,
|
|
1288
|
+
// like EntityCell (round 7: the stacked cell was replaced).
|
|
1289
|
+
"[&:has([data-avatar])>*]:flex [&:has([data-avatar])>*]:items-center [&:has([data-avatar])>*]:justify-end [&:has([data-avatar])>*]:text-right"
|
|
1290
|
+
);
|
|
1291
|
+
var BREAK_AFTER = /([@./-])/g;
|
|
1292
|
+
function breakable(text) {
|
|
1293
|
+
const parts = text.split(BREAK_AFTER);
|
|
1294
|
+
if (parts.length === 1) return text;
|
|
1295
|
+
return parts.map((part, i) => /* @__PURE__ */ jsxs(Fragment$1, { children: [
|
|
1296
|
+
part,
|
|
1297
|
+
i % 2 === 1 && /* @__PURE__ */ jsx("wbr", {})
|
|
1298
|
+
] }, i));
|
|
1299
|
+
}
|
|
1300
|
+
function CardStringValue({ text }) {
|
|
1301
|
+
const { ref, isTruncated } = useTextOverflow({ lines: 2, content: text });
|
|
1302
|
+
const el = /* @__PURE__ */ jsx("span", { ref, className: "block line-clamp-2", children: breakable(text) });
|
|
1303
|
+
return isTruncated ? /* @__PURE__ */ jsx(Tooltip, { content: text, children: el }) : el;
|
|
1304
|
+
}
|
|
1305
|
+
function CardValue({ value, id }) {
|
|
1306
|
+
return /* @__PURE__ */ jsx("span", { id, className: CARD_VALUE_CLASS, children: typeof value === "string" ? /* @__PURE__ */ jsx(CardStringValue, { text: value }) : value });
|
|
1307
|
+
}
|
|
1308
|
+
var CARDS_BELOW = 440;
|
|
1309
|
+
var CARDS_HYSTERESIS = 40;
|
|
1310
|
+
function useCardsSwitch(narrowScreen, cardsBelow = CARDS_BELOW, remeasure) {
|
|
1311
|
+
const rootRef = useRef(null);
|
|
1312
|
+
const [narrowBox, setNarrowBox] = useState(false);
|
|
1313
|
+
const needed = useRef(0);
|
|
1314
|
+
const cards = narrowScreen || narrowBox;
|
|
1315
|
+
useLayoutEffect(() => {
|
|
1316
|
+
const root = rootRef.current;
|
|
1317
|
+
if (!root || cardsBelow <= 0) {
|
|
1318
|
+
setNarrowBox(false);
|
|
1319
|
+
return;
|
|
1320
|
+
}
|
|
1321
|
+
const measure = () => {
|
|
1322
|
+
const style = getComputedStyle(root);
|
|
1323
|
+
const width = root.getBoundingClientRect().width + (parseFloat(style.marginLeft) || 0) + (parseFloat(style.marginRight) || 0);
|
|
1324
|
+
if (width <= 0) return;
|
|
1325
|
+
if (narrowBox) {
|
|
1326
|
+
if (width >= Math.min(needed.current, cardsBelow + CARDS_HYSTERESIS)) setNarrowBox(false);
|
|
1327
|
+
return;
|
|
1328
|
+
}
|
|
1329
|
+
if (cards) return;
|
|
1330
|
+
const frame = root.querySelector("[data-table-scroll]") ?? root;
|
|
1331
|
+
const over = frame.scrollWidth - frame.clientWidth;
|
|
1332
|
+
if (width < cardsBelow && over > 1) {
|
|
1333
|
+
needed.current = width + over;
|
|
1334
|
+
setNarrowBox(true);
|
|
1335
|
+
}
|
|
1336
|
+
};
|
|
1337
|
+
measure();
|
|
1338
|
+
if (typeof ResizeObserver === "undefined") return;
|
|
1339
|
+
const observer = new ResizeObserver(measure);
|
|
1340
|
+
observer.observe(root);
|
|
1341
|
+
const table = root.querySelector("[data-table-scroll] > *");
|
|
1342
|
+
if (table) observer.observe(table);
|
|
1343
|
+
return () => observer.disconnect();
|
|
1344
|
+
}, [cardsBelow, cards, narrowBox, remeasure]);
|
|
1345
|
+
return { cards, rootRef };
|
|
1346
|
+
}
|
|
1347
|
+
|
|
1348
|
+
export { CARDS_BELOW, CardValue, Checkbox, CheckboxGroup, CheckboxGroupItem, CutCell, CutEmail, DatePicker, DateSegmentFields, HoverCard, SortIndicator, TIME_SEPARATORS, TextOverflow, addDays2 as addDays, addMonths, addMonthsClamped, dayKey, dayPieces, endOfWeek, getEventsForDay, getMonthGrid, getWeekDays, groupEventsByDay, inferColumnKinds, isBarEvent, isExcludedDay, isSameDay, isSameMonth, isWeekend, kindOfRenderedText, layoutPieces, layoutWeek, localeCache, localeDayFirst, moveDay, pad2, separatorMovesOn, startOfDay, startOfWeek, stepValue, timeSegments, timeToFraction, typeDigit, useCardsSwitch, useDateWords, useWeekStart };
|
|
1349
|
+
//# sourceMappingURL=chunk-T52LAFKG.js.map
|
|
1350
|
+
//# sourceMappingURL=chunk-T52LAFKG.js.map
|