@xoroh/axis 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +134 -2
- package/dist/chunk-QDT5F2VT.js +1823 -0
- package/dist/index.cjs +13872 -0
- package/dist/index.d.cts +5718 -0
- package/dist/index.d.ts +5718 -0
- package/dist/index.js +12200 -0
- package/dist/models-DM_HxYGZ.d.cts +1890 -0
- package/dist/models-DM_HxYGZ.d.ts +1890 -0
- package/dist/models.cjs +1952 -0
- package/dist/models.d.cts +2 -0
- package/dist/models.d.ts +2 -0
- package/dist/models.js +212 -0
- package/package.json +97 -4
package/dist/models.cjs
ADDED
|
@@ -0,0 +1,1952 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/models.ts
|
|
21
|
+
var models_exports = {};
|
|
22
|
+
__export(models_exports, {
|
|
23
|
+
addTimeMinutes: () => addTimeMinutes,
|
|
24
|
+
appendTypeaheadQuery: () => appendTypeaheadQuery,
|
|
25
|
+
buildCalendarGrid: () => buildCalendarGrid,
|
|
26
|
+
clampNumberValue: () => clampNumberValue,
|
|
27
|
+
clampSliderValue: () => clampSliderValue,
|
|
28
|
+
composeEventHandlers: () => composeEventHandlers,
|
|
29
|
+
createDismissPolicy: () => createDismissPolicy,
|
|
30
|
+
createIdScope: () => createIdScope,
|
|
31
|
+
createOverlayModality: () => createOverlayModality,
|
|
32
|
+
createPortalRegistry: () => createPortalRegistry,
|
|
33
|
+
createPresenceModel: () => createPresenceModel,
|
|
34
|
+
createToastQueue: () => createToastQueue,
|
|
35
|
+
daysInCalendarMonth: () => daysInCalendarMonth,
|
|
36
|
+
defaultCollectionMatch: () => defaultCollectionMatch,
|
|
37
|
+
dismissBranchesFor: () => dismissBranchesFor,
|
|
38
|
+
dismissTriggersFor: () => dismissTriggersFor,
|
|
39
|
+
filterCollectionKeys: () => filterCollectionKeys,
|
|
40
|
+
findCollectionText: () => findCollectionText,
|
|
41
|
+
formatNumberValue: () => formatNumberValue,
|
|
42
|
+
formatTimeParts: () => formatTimeParts,
|
|
43
|
+
formatTimeValue: () => formatTimeValue,
|
|
44
|
+
getSharedOverlayModality: () => getSharedOverlayModality,
|
|
45
|
+
isAtBottom: () => isAtBottom,
|
|
46
|
+
isCalendarDateDisabled: () => isCalendarDateDisabled,
|
|
47
|
+
isChatBusy: () => isChatBusy,
|
|
48
|
+
isChatError: () => isChatError,
|
|
49
|
+
isChatStreaming: () => isChatStreaming,
|
|
50
|
+
isEmptyValue: () => isEmptyValue,
|
|
51
|
+
isSelected: () => isSelected,
|
|
52
|
+
isToolCallApproval: () => isToolCallApproval,
|
|
53
|
+
isToolCallComplete: () => isToolCallComplete,
|
|
54
|
+
isToolCallError: () => isToolCallError,
|
|
55
|
+
isToolCallRunning: () => isToolCallRunning,
|
|
56
|
+
isTypeaheadExpired: () => isTypeaheadExpired,
|
|
57
|
+
isUserMessage: () => isUserMessage,
|
|
58
|
+
leadingBlankCount: () => leadingBlankCount,
|
|
59
|
+
matchTypeaheadKey: () => matchTypeaheadKey,
|
|
60
|
+
mergeFormErrors: () => mergeFormErrors,
|
|
61
|
+
mergeSlotProps: () => mergeSlotProps,
|
|
62
|
+
minutesForStep: () => minutesForStep,
|
|
63
|
+
nearestSliderThumbIndex: () => nearestSliderThumbIndex,
|
|
64
|
+
nextBranchIndex: () => nextBranchIndex,
|
|
65
|
+
nextPresenceState: () => nextPresenceState,
|
|
66
|
+
nextTrapIndex: () => nextTrapIndex,
|
|
67
|
+
normalizeBranchIndex: () => normalizeBranchIndex,
|
|
68
|
+
normalizeChatSources: () => normalizeChatSources,
|
|
69
|
+
normalizeFieldErrors: () => normalizeFieldErrors,
|
|
70
|
+
normalizeSelection: () => normalizeSelection,
|
|
71
|
+
normalizeSliderValues: () => normalizeSliderValues,
|
|
72
|
+
normalizeTimeValue: () => normalizeTimeValue,
|
|
73
|
+
parseCalendarDate: () => parseCalendarDate,
|
|
74
|
+
parseCalendarMonth: () => parseCalendarMonth,
|
|
75
|
+
parseNumberValue: () => parseNumberValue,
|
|
76
|
+
previousBranchIndex: () => previousBranchIndex,
|
|
77
|
+
resolveAutofocus: () => resolveAutofocus,
|
|
78
|
+
resolveCalendarFocus: () => resolveCalendarFocus,
|
|
79
|
+
resolveCalendarMonthNames: () => resolveCalendarMonthNames,
|
|
80
|
+
resolveCalendarSelection: () => resolveCalendarSelection,
|
|
81
|
+
resolveCalendarWeekdayNames: () => resolveCalendarWeekdayNames,
|
|
82
|
+
resolveCanSend: () => resolveCanSend,
|
|
83
|
+
resolveChatMessageLabel: () => resolveChatMessageLabel,
|
|
84
|
+
resolveChatMessageSpeaker: () => resolveChatMessageSpeaker,
|
|
85
|
+
resolveChatSourceLabel: () => resolveChatSourceLabel,
|
|
86
|
+
resolveComposerHeight: () => resolveComposerHeight,
|
|
87
|
+
resolveDir: () => resolveDir,
|
|
88
|
+
resolveFloatingRect: () => resolveFloatingRect,
|
|
89
|
+
resolveFloatingSide: () => resolveFloatingSide,
|
|
90
|
+
resolveLocaleFirstDay: () => resolveLocaleFirstDay,
|
|
91
|
+
resolvePortalTarget: () => resolvePortalTarget,
|
|
92
|
+
resolveReasoningOpen: () => resolveReasoningOpen,
|
|
93
|
+
resolveRender: () => resolveRender,
|
|
94
|
+
resolveScrollButtonVisible: () => resolveScrollButtonVisible,
|
|
95
|
+
resolveSliderCommit: () => resolveSliderCommit,
|
|
96
|
+
resolveStyle: () => resolveStyle,
|
|
97
|
+
resolveToolCallLabel: () => resolveToolCallLabel,
|
|
98
|
+
shiftCalendarMonth: () => shiftCalendarMonth,
|
|
99
|
+
shouldCancelOnEscapeKey: () => shouldCancelOnEscapeKey,
|
|
100
|
+
shouldDismissOn: () => shouldDismissOn,
|
|
101
|
+
shouldHideBranchPicker: () => shouldHideBranchPicker,
|
|
102
|
+
shouldSubmitOnKey: () => shouldSubmitOnKey,
|
|
103
|
+
sliderRatioFromLocation: () => sliderRatioFromLocation,
|
|
104
|
+
sliderValueFromRatio: () => sliderValueFromRatio,
|
|
105
|
+
sliderValuePercent: () => sliderValuePercent,
|
|
106
|
+
snapSliderValue: () => snapSliderValue,
|
|
107
|
+
stepNumberValue: () => stepNumberValue,
|
|
108
|
+
toCalendarDate: () => toCalendarDate,
|
|
109
|
+
toCalendarMonth: () => toCalendarMonth,
|
|
110
|
+
toTwentyFourHour: () => toTwentyFourHour,
|
|
111
|
+
toggleSelection: () => toggleSelection,
|
|
112
|
+
updateAttachment: () => updateAttachment,
|
|
113
|
+
useAttachments: () => useAttachments,
|
|
114
|
+
useBranch: () => useBranch,
|
|
115
|
+
useCollectionRegistry: () => useCollectionRegistry,
|
|
116
|
+
useControllableState: () => useControllableState,
|
|
117
|
+
useOverlayModality: () => useOverlayModality,
|
|
118
|
+
useOverlayRegistration: () => useOverlayRegistration,
|
|
119
|
+
usePresence: () => usePresence,
|
|
120
|
+
usePress: () => usePress,
|
|
121
|
+
usePromptInput: () => usePromptInput,
|
|
122
|
+
useRovingModel: () => useRovingModel,
|
|
123
|
+
useSelection: () => useSelection,
|
|
124
|
+
useStickToBottom: () => useStickToBottom,
|
|
125
|
+
useToolCall: () => useToolCall,
|
|
126
|
+
validateAttachment: () => validateAttachment
|
|
127
|
+
});
|
|
128
|
+
module.exports = __toCommonJS(models_exports);
|
|
129
|
+
|
|
130
|
+
// src/a11y.ts
|
|
131
|
+
function createIdScope(prefix) {
|
|
132
|
+
let counter = 0;
|
|
133
|
+
return {
|
|
134
|
+
prefix,
|
|
135
|
+
nextId: () => {
|
|
136
|
+
counter += 1;
|
|
137
|
+
return `${prefix}-${counter}`;
|
|
138
|
+
}
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
function resolveDir(options) {
|
|
142
|
+
return options?.dir ?? options?.defaultDir ?? "ltr";
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/attachments.ts
|
|
146
|
+
var import_react2 = require("react");
|
|
147
|
+
|
|
148
|
+
// src/useControllableState.ts
|
|
149
|
+
var import_react = require("react");
|
|
150
|
+
function useControllableState(value, defaultValue, onChange) {
|
|
151
|
+
const [internal, setInternal] = (0, import_react.useState)(defaultValue);
|
|
152
|
+
const controlled = value !== void 0;
|
|
153
|
+
const current = controlled ? value : internal;
|
|
154
|
+
const currentRef = (0, import_react.useRef)(current);
|
|
155
|
+
const wasControlled = (0, import_react.useRef)(controlled);
|
|
156
|
+
currentRef.current = current;
|
|
157
|
+
(0, import_react.useEffect)(() => {
|
|
158
|
+
if (wasControlled.current !== controlled) {
|
|
159
|
+
console.warn(
|
|
160
|
+
"Axis: a component changed from controlled to uncontrolled (or vice versa). Keep the value prop defined for its lifetime."
|
|
161
|
+
);
|
|
162
|
+
wasControlled.current = controlled;
|
|
163
|
+
}
|
|
164
|
+
}, [controlled]);
|
|
165
|
+
const setValue = (0, import_react.useCallback)(
|
|
166
|
+
(action, details) => {
|
|
167
|
+
const previous = currentRef.current;
|
|
168
|
+
const next = typeof action === "function" ? action(previous) : action;
|
|
169
|
+
currentRef.current = next;
|
|
170
|
+
if (!controlled) setInternal(next);
|
|
171
|
+
if (!Object.is(previous, next)) {
|
|
172
|
+
if (details === void 0) onChange?.(next);
|
|
173
|
+
else onChange?.(next, details);
|
|
174
|
+
}
|
|
175
|
+
},
|
|
176
|
+
[controlled, onChange]
|
|
177
|
+
);
|
|
178
|
+
return [current, setValue];
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// src/attachments.ts
|
|
182
|
+
function validateAttachment(current, candidate, limits) {
|
|
183
|
+
if (current.some((entry) => entry.id === candidate.id)) return "duplicate";
|
|
184
|
+
if (limits?.maxFileSize !== void 0 && candidate.size !== void 0 && candidate.size > limits.maxFileSize) {
|
|
185
|
+
return "too-large";
|
|
186
|
+
}
|
|
187
|
+
if (limits?.maxFiles !== void 0 && current.length >= limits.maxFiles) {
|
|
188
|
+
return "too-many";
|
|
189
|
+
}
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
function updateAttachment(current, id, patch) {
|
|
193
|
+
return current.map(
|
|
194
|
+
(entry) => entry.id === id ? { ...entry, ...patch } : entry
|
|
195
|
+
);
|
|
196
|
+
}
|
|
197
|
+
function useAttachments(options) {
|
|
198
|
+
const [raw, setRaw] = useControllableState(
|
|
199
|
+
options?.value,
|
|
200
|
+
options?.defaultValue ?? [],
|
|
201
|
+
options?.onChange
|
|
202
|
+
);
|
|
203
|
+
const attachments = raw ?? [];
|
|
204
|
+
const { maxFiles, maxFileSize, onError } = options ?? {};
|
|
205
|
+
const addMany = (0, import_react2.useCallback)(
|
|
206
|
+
(candidates) => {
|
|
207
|
+
const working = [...attachments];
|
|
208
|
+
let accepted = false;
|
|
209
|
+
for (const candidate of candidates) {
|
|
210
|
+
const error = validateAttachment(working, candidate, {
|
|
211
|
+
maxFiles,
|
|
212
|
+
maxFileSize
|
|
213
|
+
});
|
|
214
|
+
if (error) {
|
|
215
|
+
onError?.(error, candidate);
|
|
216
|
+
continue;
|
|
217
|
+
}
|
|
218
|
+
working.push(candidate);
|
|
219
|
+
accepted = true;
|
|
220
|
+
}
|
|
221
|
+
if (accepted) setRaw(working);
|
|
222
|
+
},
|
|
223
|
+
[attachments, maxFiles, maxFileSize, onError, setRaw]
|
|
224
|
+
);
|
|
225
|
+
const add = (0, import_react2.useCallback)(
|
|
226
|
+
(candidate) => {
|
|
227
|
+
addMany([candidate]);
|
|
228
|
+
},
|
|
229
|
+
[addMany]
|
|
230
|
+
);
|
|
231
|
+
const update = (0, import_react2.useCallback)(
|
|
232
|
+
(id, patch) => {
|
|
233
|
+
setRaw((previous) => updateAttachment(previous ?? [], id, patch));
|
|
234
|
+
},
|
|
235
|
+
[setRaw]
|
|
236
|
+
);
|
|
237
|
+
const remove = (0, import_react2.useCallback)(
|
|
238
|
+
(id) => {
|
|
239
|
+
setRaw((previous) => (previous ?? []).filter((entry) => entry.id !== id));
|
|
240
|
+
},
|
|
241
|
+
[setRaw]
|
|
242
|
+
);
|
|
243
|
+
const clear = (0, import_react2.useCallback)(() => {
|
|
244
|
+
setRaw([]);
|
|
245
|
+
}, [setRaw]);
|
|
246
|
+
return { attachments, add, addMany, update, remove, clear };
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
// src/calendar.ts
|
|
250
|
+
var ISO_DATE_PATTERN = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
251
|
+
var MONTH_PATTERN = /^(\d{4})-(\d{2})$/;
|
|
252
|
+
var FALLBACK_WEEKDAY_NAMES = ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"];
|
|
253
|
+
function parseCalendarDate(value) {
|
|
254
|
+
if (typeof value !== "string") return null;
|
|
255
|
+
const match = ISO_DATE_PATTERN.exec(value);
|
|
256
|
+
if (match === null) return null;
|
|
257
|
+
const year = Number(match[1]);
|
|
258
|
+
const month = Number(match[2]);
|
|
259
|
+
const day = Number(match[3]);
|
|
260
|
+
if (month < 1 || month > 12 || day < 1 || day > 31) return null;
|
|
261
|
+
const check = new Date(Date.UTC(year, month - 1, day));
|
|
262
|
+
if (check.getUTCFullYear() !== year || check.getUTCMonth() !== month - 1 || check.getUTCDate() !== day) {
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
return { year, monthIndex: month - 1, day };
|
|
266
|
+
}
|
|
267
|
+
function parseCalendarMonth(value) {
|
|
268
|
+
if (typeof value !== "string") return null;
|
|
269
|
+
const match = MONTH_PATTERN.exec(value);
|
|
270
|
+
if (match === null) return null;
|
|
271
|
+
const year = Number(match[1]);
|
|
272
|
+
const month = Number(match[2]);
|
|
273
|
+
if (month < 1 || month > 12) return null;
|
|
274
|
+
return { year, monthIndex: month - 1 };
|
|
275
|
+
}
|
|
276
|
+
function toCalendarDate(year, monthIndex, day) {
|
|
277
|
+
return `${String(year).padStart(4, "0")}-${String(monthIndex + 1).padStart(2, "0")}-${String(day).padStart(2, "0")}`;
|
|
278
|
+
}
|
|
279
|
+
function toCalendarMonth(year, monthIndex) {
|
|
280
|
+
return `${String(year).padStart(4, "0")}-${String(monthIndex + 1).padStart(2, "0")}`;
|
|
281
|
+
}
|
|
282
|
+
function daysInCalendarMonth(year, monthIndex) {
|
|
283
|
+
return new Date(Date.UTC(year, monthIndex + 1, 0)).getUTCDate();
|
|
284
|
+
}
|
|
285
|
+
function shiftCalendarMonth(year, monthIndex, delta) {
|
|
286
|
+
const total = year * 12 + monthIndex + delta;
|
|
287
|
+
const nextYear = Math.floor(total / 12);
|
|
288
|
+
return { year: nextYear, monthIndex: total - nextYear * 12 };
|
|
289
|
+
}
|
|
290
|
+
function leadingBlankCount(year, monthIndex, firstDayOfWeek = 0) {
|
|
291
|
+
const sundayFirst = new Date(Date.UTC(year, monthIndex, 1)).getUTCDay();
|
|
292
|
+
return (sundayFirst - firstDayOfWeek + 7) % 7;
|
|
293
|
+
}
|
|
294
|
+
function resolveCalendarWeekdayNames(locale = "en-US", firstDayOfWeek = 0) {
|
|
295
|
+
let names = FALLBACK_WEEKDAY_NAMES;
|
|
296
|
+
try {
|
|
297
|
+
const format = new Intl.DateTimeFormat(locale, {
|
|
298
|
+
weekday: "short",
|
|
299
|
+
timeZone: "UTC"
|
|
300
|
+
});
|
|
301
|
+
names = Array.from(
|
|
302
|
+
{ length: 7 },
|
|
303
|
+
(_, i) => format.format(new Date(Date.UTC(2026, 5, 7 + i)))
|
|
304
|
+
);
|
|
305
|
+
} catch {
|
|
306
|
+
names = FALLBACK_WEEKDAY_NAMES;
|
|
307
|
+
}
|
|
308
|
+
return [...names.slice(firstDayOfWeek), ...names.slice(0, firstDayOfWeek)];
|
|
309
|
+
}
|
|
310
|
+
function validBound(value) {
|
|
311
|
+
return parseCalendarDate(value) !== null && typeof value === "string" ? value : null;
|
|
312
|
+
}
|
|
313
|
+
function resolveCalendarMonthNames(locale = "en-US", style = "long") {
|
|
314
|
+
const fallback = [
|
|
315
|
+
"January",
|
|
316
|
+
"February",
|
|
317
|
+
"March",
|
|
318
|
+
"April",
|
|
319
|
+
"May",
|
|
320
|
+
"June",
|
|
321
|
+
"July",
|
|
322
|
+
"August",
|
|
323
|
+
"September",
|
|
324
|
+
"October",
|
|
325
|
+
"November",
|
|
326
|
+
"December"
|
|
327
|
+
];
|
|
328
|
+
try {
|
|
329
|
+
const format = new Intl.DateTimeFormat(locale, {
|
|
330
|
+
month: style,
|
|
331
|
+
timeZone: "UTC"
|
|
332
|
+
});
|
|
333
|
+
return Array.from(
|
|
334
|
+
{ length: 12 },
|
|
335
|
+
(_, monthIndex) => format.format(new Date(Date.UTC(2026, monthIndex, 15, 12)))
|
|
336
|
+
);
|
|
337
|
+
} catch {
|
|
338
|
+
return fallback;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
function resolveLocaleFirstDay(locale = "en-US") {
|
|
342
|
+
const override = fwExtensionFirstDay(locale);
|
|
343
|
+
if (override !== void 0) return override;
|
|
344
|
+
const live = liveWeekInfoFirstDay(locale);
|
|
345
|
+
if (live !== void 0) return live;
|
|
346
|
+
return tableFirstDay(regionOfLocale(locale));
|
|
347
|
+
}
|
|
348
|
+
function fwExtensionFirstDay(locale) {
|
|
349
|
+
const subtags = String(locale).toLowerCase().replace(/_/g, "-").split("-");
|
|
350
|
+
const uIndex = subtags.indexOf("u");
|
|
351
|
+
if (uIndex === -1) return void 0;
|
|
352
|
+
const section = [];
|
|
353
|
+
for (let i = uIndex + 1; i < subtags.length; i++) {
|
|
354
|
+
const sub = subtags[i];
|
|
355
|
+
if (sub === void 0 || sub.length < 2) break;
|
|
356
|
+
section.push(sub);
|
|
357
|
+
}
|
|
358
|
+
const keyIndex = section.indexOf("fw");
|
|
359
|
+
const value = keyIndex === -1 ? void 0 : section[keyIndex + 1];
|
|
360
|
+
switch (value) {
|
|
361
|
+
case "mon":
|
|
362
|
+
return 1;
|
|
363
|
+
case "tue":
|
|
364
|
+
return 2;
|
|
365
|
+
case "wed":
|
|
366
|
+
return 3;
|
|
367
|
+
case "thu":
|
|
368
|
+
return 4;
|
|
369
|
+
case "fri":
|
|
370
|
+
return 5;
|
|
371
|
+
case "sat":
|
|
372
|
+
return 6;
|
|
373
|
+
case "sun":
|
|
374
|
+
return 0;
|
|
375
|
+
default:
|
|
376
|
+
return void 0;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
function liveWeekInfoFirstDay(locale) {
|
|
380
|
+
try {
|
|
381
|
+
const Ctor = Intl.Locale;
|
|
382
|
+
if (typeof Ctor !== "function") return void 0;
|
|
383
|
+
const loc = new Ctor(locale);
|
|
384
|
+
const fromMethod = typeof loc.getWeekInfo === "function" ? loc.getWeekInfo() : void 0;
|
|
385
|
+
const info = fromMethod ?? loc.weekInfo;
|
|
386
|
+
const firstDay = info !== null && typeof info === "object" ? info.firstDay : void 0;
|
|
387
|
+
if (typeof firstDay === "number" && Number.isInteger(firstDay) && firstDay >= 1 && firstDay <= 7) {
|
|
388
|
+
return (firstDay % 7 + 7) % 7;
|
|
389
|
+
}
|
|
390
|
+
return void 0;
|
|
391
|
+
} catch {
|
|
392
|
+
return void 0;
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
var SATURDAY_START = /* @__PURE__ */ new Set([
|
|
396
|
+
"AF",
|
|
397
|
+
"BH",
|
|
398
|
+
"DJ",
|
|
399
|
+
"DZ",
|
|
400
|
+
"EG",
|
|
401
|
+
"IQ",
|
|
402
|
+
"IR",
|
|
403
|
+
"JO",
|
|
404
|
+
"KW",
|
|
405
|
+
"LY",
|
|
406
|
+
"OM",
|
|
407
|
+
"QA",
|
|
408
|
+
"SD",
|
|
409
|
+
"SY"
|
|
410
|
+
]);
|
|
411
|
+
var FRIDAY_START = /* @__PURE__ */ new Set(["MV"]);
|
|
412
|
+
var SUNDAY_START = /* @__PURE__ */ new Set([
|
|
413
|
+
"AG",
|
|
414
|
+
"AS",
|
|
415
|
+
"BD",
|
|
416
|
+
"BR",
|
|
417
|
+
"BS",
|
|
418
|
+
"BT",
|
|
419
|
+
"BW",
|
|
420
|
+
"BZ",
|
|
421
|
+
"CA",
|
|
422
|
+
"CO",
|
|
423
|
+
"DM",
|
|
424
|
+
"DO",
|
|
425
|
+
"ET",
|
|
426
|
+
"GT",
|
|
427
|
+
"GU",
|
|
428
|
+
"HK",
|
|
429
|
+
"HN",
|
|
430
|
+
"ID",
|
|
431
|
+
"IL",
|
|
432
|
+
"IN",
|
|
433
|
+
"IS",
|
|
434
|
+
"JM",
|
|
435
|
+
"JP",
|
|
436
|
+
"KE",
|
|
437
|
+
"KH",
|
|
438
|
+
"KR",
|
|
439
|
+
"LA",
|
|
440
|
+
"MH",
|
|
441
|
+
"MM",
|
|
442
|
+
"MO",
|
|
443
|
+
"MT",
|
|
444
|
+
"MX",
|
|
445
|
+
"MZ",
|
|
446
|
+
"NI",
|
|
447
|
+
"NP",
|
|
448
|
+
"PA",
|
|
449
|
+
"PE",
|
|
450
|
+
"PH",
|
|
451
|
+
"PK",
|
|
452
|
+
"PR",
|
|
453
|
+
"PT",
|
|
454
|
+
"PY",
|
|
455
|
+
"SA",
|
|
456
|
+
"SG",
|
|
457
|
+
"SV",
|
|
458
|
+
"TH",
|
|
459
|
+
"TT",
|
|
460
|
+
"TW",
|
|
461
|
+
"UM",
|
|
462
|
+
"US",
|
|
463
|
+
"VE",
|
|
464
|
+
"VI",
|
|
465
|
+
"WS",
|
|
466
|
+
"YE",
|
|
467
|
+
"ZA",
|
|
468
|
+
"ZW"
|
|
469
|
+
]);
|
|
470
|
+
function tableFirstDay(region) {
|
|
471
|
+
if (region !== void 0) {
|
|
472
|
+
if (SATURDAY_START.has(region)) return 6;
|
|
473
|
+
if (FRIDAY_START.has(region)) return 5;
|
|
474
|
+
if (SUNDAY_START.has(region)) return 0;
|
|
475
|
+
}
|
|
476
|
+
return 1;
|
|
477
|
+
}
|
|
478
|
+
var LIKELY_REGION = {
|
|
479
|
+
ar: "EG",
|
|
480
|
+
en: "US",
|
|
481
|
+
es: "ES",
|
|
482
|
+
fa: "IR",
|
|
483
|
+
he: "IL",
|
|
484
|
+
hi: "IN",
|
|
485
|
+
id: "ID",
|
|
486
|
+
ja: "JP",
|
|
487
|
+
ko: "KR",
|
|
488
|
+
pt: "BR",
|
|
489
|
+
th: "TH",
|
|
490
|
+
zh: "CN"
|
|
491
|
+
};
|
|
492
|
+
function regionOfLocale(locale) {
|
|
493
|
+
try {
|
|
494
|
+
const Ctor = Intl.Locale;
|
|
495
|
+
if (typeof Ctor === "function") {
|
|
496
|
+
const region = new Ctor(locale).maximize?.().region;
|
|
497
|
+
if (typeof region === "string" && region !== "") {
|
|
498
|
+
return region.toUpperCase();
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
} catch {
|
|
502
|
+
}
|
|
503
|
+
const parts = String(locale).replace(/_/g, "-").split("-");
|
|
504
|
+
const language = parts[0]?.toLowerCase();
|
|
505
|
+
if (parts.length === 1 && language !== void 0) {
|
|
506
|
+
const likely = LIKELY_REGION[language];
|
|
507
|
+
if (likely !== void 0) return likely;
|
|
508
|
+
}
|
|
509
|
+
for (let i = 1; i < parts.length; i++) {
|
|
510
|
+
const part = parts[i];
|
|
511
|
+
if (part !== void 0 && (/^[A-Za-z]{2}$/.test(part) || /^[0-9]{3}$/.test(part))) {
|
|
512
|
+
return part.toUpperCase();
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
return void 0;
|
|
516
|
+
}
|
|
517
|
+
function isCalendarDateDisabled(iso, options = {}) {
|
|
518
|
+
const { minDate, maxDate, isDateDisabled, disabled = false } = options;
|
|
519
|
+
if (disabled) return true;
|
|
520
|
+
const min = validBound(minDate);
|
|
521
|
+
const max = validBound(maxDate);
|
|
522
|
+
if (min !== null && iso < min) return true;
|
|
523
|
+
if (max !== null && iso > max) return true;
|
|
524
|
+
return isDateDisabled?.(iso) === true;
|
|
525
|
+
}
|
|
526
|
+
function buildCalendarGrid(monthKey, options = {}) {
|
|
527
|
+
const {
|
|
528
|
+
firstDayOfWeek = 0,
|
|
529
|
+
locale = "en-US",
|
|
530
|
+
selected = null,
|
|
531
|
+
range = null
|
|
532
|
+
} = options;
|
|
533
|
+
const weekdayNames = resolveCalendarWeekdayNames(locale, firstDayOfWeek);
|
|
534
|
+
const parts = parseCalendarMonth(monthKey);
|
|
535
|
+
if (parts === null) return { weeks: [], weekdayNames };
|
|
536
|
+
const dayCount = daysInCalendarMonth(parts.year, parts.monthIndex);
|
|
537
|
+
const blanks = leadingBlankCount(
|
|
538
|
+
parts.year,
|
|
539
|
+
parts.monthIndex,
|
|
540
|
+
firstDayOfWeek
|
|
541
|
+
);
|
|
542
|
+
const cells = [];
|
|
543
|
+
for (let i = 0; i < blanks; i += 1) cells.push(null);
|
|
544
|
+
for (let day = 1; day <= dayCount; day += 1) {
|
|
545
|
+
const iso = toCalendarDate(parts.year, parts.monthIndex, day);
|
|
546
|
+
const disabled = isCalendarDateDisabled(iso, options);
|
|
547
|
+
const inRange = range !== null && iso >= range.start && iso <= range.end;
|
|
548
|
+
cells.push({
|
|
549
|
+
iso,
|
|
550
|
+
day,
|
|
551
|
+
disabled,
|
|
552
|
+
selected: selected !== null && iso === selected,
|
|
553
|
+
range: range === null || !inRange ? null : iso === range.start && iso === range.end ? "start" : iso === range.start ? "start" : iso === range.end ? "end" : "inside"
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
while (cells.length % 7 !== 0) cells.push(null);
|
|
557
|
+
const weeks = [];
|
|
558
|
+
for (let i = 0; i < cells.length; i += 7) {
|
|
559
|
+
weeks.push(cells.slice(i, i + 7));
|
|
560
|
+
}
|
|
561
|
+
return { weeks, weekdayNames };
|
|
562
|
+
}
|
|
563
|
+
function clampDay(year, monthIndex, day) {
|
|
564
|
+
return Math.min(Math.max(1, day), daysInCalendarMonth(year, monthIndex));
|
|
565
|
+
}
|
|
566
|
+
function shiftCalendarDay(year, monthIndex, day, deltaDays) {
|
|
567
|
+
const shifted = new Date(Date.UTC(year, monthIndex, day + deltaDays));
|
|
568
|
+
return {
|
|
569
|
+
year: shifted.getUTCFullYear(),
|
|
570
|
+
monthIndex: shifted.getUTCMonth(),
|
|
571
|
+
day: shifted.getUTCDate()
|
|
572
|
+
};
|
|
573
|
+
}
|
|
574
|
+
function resolveCalendarFocus(currentISO, key, options = {}) {
|
|
575
|
+
const { firstDayOfWeek = 0, dir = "ltr" } = options;
|
|
576
|
+
const parts = parseCalendarDate(currentISO);
|
|
577
|
+
if (parts === null) return null;
|
|
578
|
+
const { year, monthIndex, day } = parts;
|
|
579
|
+
switch (key) {
|
|
580
|
+
case "ArrowLeft":
|
|
581
|
+
case "ArrowRight": {
|
|
582
|
+
const step = key === "ArrowLeft" ? -1 : 1;
|
|
583
|
+
const next = shiftCalendarDay(
|
|
584
|
+
year,
|
|
585
|
+
monthIndex,
|
|
586
|
+
day,
|
|
587
|
+
dir === "rtl" ? -step : step
|
|
588
|
+
);
|
|
589
|
+
return toCalendarDate(next.year, next.monthIndex, next.day);
|
|
590
|
+
}
|
|
591
|
+
case "ArrowUp":
|
|
592
|
+
case "ArrowDown": {
|
|
593
|
+
const next = shiftCalendarDay(
|
|
594
|
+
year,
|
|
595
|
+
monthIndex,
|
|
596
|
+
day,
|
|
597
|
+
key === "ArrowUp" ? -7 : 7
|
|
598
|
+
);
|
|
599
|
+
return toCalendarDate(next.year, next.monthIndex, next.day);
|
|
600
|
+
}
|
|
601
|
+
case "Home":
|
|
602
|
+
case "End": {
|
|
603
|
+
const blanks = leadingBlankCount(year, monthIndex, firstDayOfWeek);
|
|
604
|
+
const rowStart = day - (day - 1 + blanks) % 7;
|
|
605
|
+
const rowEnd = Math.min(
|
|
606
|
+
rowStart + 6,
|
|
607
|
+
daysInCalendarMonth(year, monthIndex)
|
|
608
|
+
);
|
|
609
|
+
const target = key === "Home" ? rowStart : rowEnd;
|
|
610
|
+
return toCalendarDate(
|
|
611
|
+
year,
|
|
612
|
+
monthIndex,
|
|
613
|
+
clampDay(year, monthIndex, target)
|
|
614
|
+
);
|
|
615
|
+
}
|
|
616
|
+
case "PageUp":
|
|
617
|
+
case "PageDown": {
|
|
618
|
+
const next = shiftCalendarMonth(
|
|
619
|
+
year,
|
|
620
|
+
monthIndex,
|
|
621
|
+
key === "PageUp" ? -1 : 1
|
|
622
|
+
);
|
|
623
|
+
return toCalendarDate(
|
|
624
|
+
next.year,
|
|
625
|
+
next.monthIndex,
|
|
626
|
+
clampDay(next.year, next.monthIndex, day)
|
|
627
|
+
);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
function resolveCalendarSelection(iso, options = {}) {
|
|
632
|
+
const { mode = "single", range = null } = options;
|
|
633
|
+
if (parseCalendarDate(iso) === null) return null;
|
|
634
|
+
if (isCalendarDateDisabled(iso, options)) return null;
|
|
635
|
+
if (mode === "single") return { value: iso, range };
|
|
636
|
+
if (range === null || range.start !== range.end) {
|
|
637
|
+
return { value: iso, range: { start: iso, end: iso } };
|
|
638
|
+
}
|
|
639
|
+
const start = range.start <= iso ? range.start : iso;
|
|
640
|
+
const end = range.start <= iso ? iso : range.start;
|
|
641
|
+
return { value: iso, range: { start, end } };
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
// src/chatBranch.ts
|
|
645
|
+
var import_react3 = require("react");
|
|
646
|
+
function normalizeBranchIndex(index, count) {
|
|
647
|
+
if (count <= 0) return 0;
|
|
648
|
+
if (!Number.isFinite(index)) return 0;
|
|
649
|
+
return Math.min(Math.max(Math.floor(index), 0), count - 1);
|
|
650
|
+
}
|
|
651
|
+
function nextBranchIndex(index, count) {
|
|
652
|
+
if (count <= 0) return 0;
|
|
653
|
+
return Math.min(normalizeBranchIndex(index, count) + 1, count - 1);
|
|
654
|
+
}
|
|
655
|
+
function previousBranchIndex(index, count) {
|
|
656
|
+
if (count <= 0) return 0;
|
|
657
|
+
return Math.max(normalizeBranchIndex(index, count) - 1, 0);
|
|
658
|
+
}
|
|
659
|
+
function shouldHideBranchPicker(count, hideWhenSingleBranch = true) {
|
|
660
|
+
return hideWhenSingleBranch && count <= 1;
|
|
661
|
+
}
|
|
662
|
+
function useBranch(options) {
|
|
663
|
+
const count = Math.max(0, Math.floor(options.count));
|
|
664
|
+
const [raw, setRaw] = useControllableState(
|
|
665
|
+
options.value,
|
|
666
|
+
options.defaultValue ?? 0,
|
|
667
|
+
options.onChange
|
|
668
|
+
);
|
|
669
|
+
const index = normalizeBranchIndex(raw ?? 0, count);
|
|
670
|
+
const goTo = (0, import_react3.useCallback)(
|
|
671
|
+
(next2) => {
|
|
672
|
+
setRaw(normalizeBranchIndex(next2, count));
|
|
673
|
+
},
|
|
674
|
+
[count, setRaw]
|
|
675
|
+
);
|
|
676
|
+
const next = (0, import_react3.useCallback)(() => {
|
|
677
|
+
setRaw((previous2) => nextBranchIndex(previous2 ?? 0, count));
|
|
678
|
+
}, [count, setRaw]);
|
|
679
|
+
const previous = (0, import_react3.useCallback)(() => {
|
|
680
|
+
setRaw((previous2) => previousBranchIndex(previous2 ?? 0, count));
|
|
681
|
+
}, [count, setRaw]);
|
|
682
|
+
return { index, count, previous, next, goTo };
|
|
683
|
+
}
|
|
684
|
+
|
|
685
|
+
// src/chatMessage.ts
|
|
686
|
+
function resolveChatMessageSpeaker(options) {
|
|
687
|
+
if (options.authorName?.trim()) return options.authorName.trim();
|
|
688
|
+
switch (options.role) {
|
|
689
|
+
case "user":
|
|
690
|
+
return "You";
|
|
691
|
+
case "assistant":
|
|
692
|
+
return "Assistant";
|
|
693
|
+
case "system":
|
|
694
|
+
return "System";
|
|
695
|
+
case "tool":
|
|
696
|
+
return "Tool";
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
function resolveChatMessageLabel(options) {
|
|
700
|
+
const speaker = resolveChatMessageSpeaker(options);
|
|
701
|
+
const text = options.text?.trim();
|
|
702
|
+
return text ? `${speaker}: ${text}` : speaker;
|
|
703
|
+
}
|
|
704
|
+
function isUserMessage(message) {
|
|
705
|
+
return message.role === "user";
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
// src/chatSource.ts
|
|
709
|
+
function normalizeChatSources(sources) {
|
|
710
|
+
if (!sources) return [];
|
|
711
|
+
const seen = /* @__PURE__ */ new Set();
|
|
712
|
+
const out = [];
|
|
713
|
+
for (const source of sources) {
|
|
714
|
+
const href = source.href.trim();
|
|
715
|
+
if (!href || seen.has(href)) continue;
|
|
716
|
+
seen.add(href);
|
|
717
|
+
out.push({ ...source, href });
|
|
718
|
+
}
|
|
719
|
+
return out;
|
|
720
|
+
}
|
|
721
|
+
function resolveChatSourceLabel(source) {
|
|
722
|
+
const title = source.title?.trim();
|
|
723
|
+
return title ? title : source.href.trim();
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
// src/chatStatus.ts
|
|
727
|
+
function isChatBusy(status) {
|
|
728
|
+
return status === "submitted" || status === "streaming";
|
|
729
|
+
}
|
|
730
|
+
function isChatStreaming(status) {
|
|
731
|
+
return status === "streaming";
|
|
732
|
+
}
|
|
733
|
+
function isChatError(status) {
|
|
734
|
+
return status === "error";
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// src/collection.ts
|
|
738
|
+
var import_react4 = require("react");
|
|
739
|
+
function defaultCollectionMatch(query, text) {
|
|
740
|
+
const needle = query.trim().toLowerCase();
|
|
741
|
+
if (needle === "") return true;
|
|
742
|
+
return text.toLowerCase().includes(needle);
|
|
743
|
+
}
|
|
744
|
+
function filterCollectionKeys(items, query, match = defaultCollectionMatch) {
|
|
745
|
+
return items.filter((item) => match(query, item.text)).map((item) => item.key);
|
|
746
|
+
}
|
|
747
|
+
function findCollectionText(items, key) {
|
|
748
|
+
return items.find((item) => item.key === key)?.text;
|
|
749
|
+
}
|
|
750
|
+
function useCollectionRegistry() {
|
|
751
|
+
const [items, setItems] = (0, import_react4.useState)([]);
|
|
752
|
+
const register = (0, import_react4.useCallback)((item) => {
|
|
753
|
+
setItems((previous) => {
|
|
754
|
+
const at = previous.findIndex((entry) => entry.key === item.key);
|
|
755
|
+
if (at === -1) return [...previous, item];
|
|
756
|
+
if (previous[at]?.text === item.text) return previous;
|
|
757
|
+
const next = [...previous];
|
|
758
|
+
next[at] = item;
|
|
759
|
+
return next;
|
|
760
|
+
});
|
|
761
|
+
}, []);
|
|
762
|
+
const unregister = (0, import_react4.useCallback)((key) => {
|
|
763
|
+
setItems(
|
|
764
|
+
(previous) => previous.some((entry) => entry.key === key) ? previous.filter((entry) => entry.key !== key) : previous
|
|
765
|
+
);
|
|
766
|
+
}, []);
|
|
767
|
+
return (0, import_react4.useMemo)(
|
|
768
|
+
() => ({ items, register, unregister }),
|
|
769
|
+
[items, register, unregister]
|
|
770
|
+
);
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
// src/dismissPolicy.ts
|
|
774
|
+
function createDismissPolicy(options) {
|
|
775
|
+
const dismissible = options.dismissible ?? options.hasDismissHandler;
|
|
776
|
+
return {
|
|
777
|
+
canDismiss: dismissible,
|
|
778
|
+
// A close control is derived from the SAME value the triggers read, so the
|
|
779
|
+
// two can never disagree.
|
|
780
|
+
showClose: dismissible,
|
|
781
|
+
shouldDismiss: (trigger, enabled, triggers) => enabled && dismissible && triggers[trigger] === true
|
|
782
|
+
};
|
|
783
|
+
}
|
|
784
|
+
function dismissTriggersFor(surface) {
|
|
785
|
+
return {
|
|
786
|
+
scrim: surface.modal,
|
|
787
|
+
escape: surface.modal,
|
|
788
|
+
closeButton: surface.hasVisibleClose
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
// src/dismissWiring.ts
|
|
793
|
+
function dismissBranchesFor(options) {
|
|
794
|
+
const armed = options.modal && options.dismissible;
|
|
795
|
+
return {
|
|
796
|
+
"outside-pointer": armed,
|
|
797
|
+
"focus-out": armed,
|
|
798
|
+
escape: armed,
|
|
799
|
+
// The system back button exists on native only, but the DECLARATION is
|
|
800
|
+
// platform-free: web simply never binds this branch, the same shape as the
|
|
801
|
+
// parity contract's `dismissalOnlyNative`. Declaring it here keeps the set
|
|
802
|
+
// identical on both sides instead of letting each renderer invent one.
|
|
803
|
+
"system-back": armed,
|
|
804
|
+
close: options.dismissible && options.hasVisibleClose
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
function shouldDismissOn(source, enabled, branches) {
|
|
808
|
+
return enabled && branches[source] === true;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
// src/focusTrap.ts
|
|
812
|
+
function nextTrapIndex(current, count, move, loop) {
|
|
813
|
+
if (count <= 0) return -1;
|
|
814
|
+
const at = Math.min(Math.max(current, 0), count - 1);
|
|
815
|
+
switch (move) {
|
|
816
|
+
case "first":
|
|
817
|
+
return 0;
|
|
818
|
+
case "last":
|
|
819
|
+
return count - 1;
|
|
820
|
+
case "next":
|
|
821
|
+
return at + 1 < count ? at + 1 : loop ? 0 : at;
|
|
822
|
+
case "previous":
|
|
823
|
+
return at - 1 >= 0 ? at - 1 : loop ? count - 1 : at;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
function resolveAutofocus(count, autoFocusIndex) {
|
|
827
|
+
if (count <= 0) return { type: "none" };
|
|
828
|
+
if (autoFocusIndex !== void 0 && autoFocusIndex >= 0 && autoFocusIndex < count) {
|
|
829
|
+
return { type: "focus-stop", index: autoFocusIndex };
|
|
830
|
+
}
|
|
831
|
+
return { type: "focus-stop", index: 0 };
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
// src/form.ts
|
|
835
|
+
function normalizeFieldErrors(error) {
|
|
836
|
+
if (error === void 0) return [];
|
|
837
|
+
return Array.isArray(error) ? [...error] : [error];
|
|
838
|
+
}
|
|
839
|
+
function mergeFormErrors(internal, server) {
|
|
840
|
+
const merged = {};
|
|
841
|
+
const names = /* @__PURE__ */ new Set([...Object.keys(internal), ...Object.keys(server)]);
|
|
842
|
+
for (const name of names) {
|
|
843
|
+
const fromServer = server[name];
|
|
844
|
+
if (fromServer !== void 0) {
|
|
845
|
+
merged[name] = fromServer;
|
|
846
|
+
continue;
|
|
847
|
+
}
|
|
848
|
+
const fromInternal = internal[name];
|
|
849
|
+
if (fromInternal !== void 0) merged[name] = fromInternal;
|
|
850
|
+
}
|
|
851
|
+
return merged;
|
|
852
|
+
}
|
|
853
|
+
function isEmptyValue(value) {
|
|
854
|
+
return value === void 0 || value === null || value === "";
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
// src/number.ts
|
|
858
|
+
function formatNumberValue(value, spec = {}) {
|
|
859
|
+
if (value === null || !Number.isFinite(value)) return "";
|
|
860
|
+
const { locale, format } = spec;
|
|
861
|
+
try {
|
|
862
|
+
return new Intl.NumberFormat(locale, format).format(value);
|
|
863
|
+
} catch {
|
|
864
|
+
return String(value);
|
|
865
|
+
}
|
|
866
|
+
}
|
|
867
|
+
function parseNumberValue(text, spec = {}) {
|
|
868
|
+
if (typeof text !== "string") return null;
|
|
869
|
+
const trimmed = text.trim();
|
|
870
|
+
if (trimmed === "") return null;
|
|
871
|
+
let decimal = ".";
|
|
872
|
+
let grouping = ",";
|
|
873
|
+
try {
|
|
874
|
+
const parts = new Intl.NumberFormat(
|
|
875
|
+
spec.locale,
|
|
876
|
+
spec.format !== void 0 ? { ...spec.format, useGrouping: true } : void 0
|
|
877
|
+
).formatToParts(12345.6);
|
|
878
|
+
for (const part of parts) {
|
|
879
|
+
if (part.type === "decimal") decimal = part.value;
|
|
880
|
+
if (part.type === "group") grouping = part.value;
|
|
881
|
+
}
|
|
882
|
+
} catch {
|
|
883
|
+
}
|
|
884
|
+
const compact = trimmed.split(" ").join("").split("\xA0").join("");
|
|
885
|
+
const noGrouping = grouping === "" ? compact : compact.split(grouping).join("");
|
|
886
|
+
const normalized = decimal === "." ? noGrouping : noGrouping.split(decimal).join(".");
|
|
887
|
+
if (!/^[+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?$/.test(normalized)) {
|
|
888
|
+
return null;
|
|
889
|
+
}
|
|
890
|
+
const parsed = Number.parseFloat(normalized);
|
|
891
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
892
|
+
}
|
|
893
|
+
function clampNumberValue(value, min, max) {
|
|
894
|
+
if (min !== void 0 && value < min) return min;
|
|
895
|
+
if (max !== void 0 && value > max) return max;
|
|
896
|
+
return value;
|
|
897
|
+
}
|
|
898
|
+
function stepNumberValue(value, direction, options = {}) {
|
|
899
|
+
const { step = 1, snapOnStep = false, min, max } = options;
|
|
900
|
+
const effective = step > 0 && Number.isFinite(step) ? step : 1;
|
|
901
|
+
const raw = value + direction * effective;
|
|
902
|
+
const snapped = snapOnStep && effective > 0 ? Math.round(raw / effective) * effective : raw;
|
|
903
|
+
const clean = snapOnStep && effective > 0 ? Number(snapped.toPrecision(12)) : snapped;
|
|
904
|
+
return clampNumberValue(clean, min, max);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
// src/overlayModality.ts
|
|
908
|
+
var import_react5 = require("react");
|
|
909
|
+
function createOverlayModality() {
|
|
910
|
+
const stack = [];
|
|
911
|
+
const modalById = /* @__PURE__ */ new Map();
|
|
912
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
913
|
+
const emit = () => {
|
|
914
|
+
for (const l of listeners) l();
|
|
915
|
+
};
|
|
916
|
+
return {
|
|
917
|
+
register(id, options) {
|
|
918
|
+
if (!stack.includes(id)) {
|
|
919
|
+
stack.push(id);
|
|
920
|
+
modalById.set(id, options?.modal ?? false);
|
|
921
|
+
emit();
|
|
922
|
+
}
|
|
923
|
+
let released = false;
|
|
924
|
+
return () => {
|
|
925
|
+
if (released) return;
|
|
926
|
+
released = true;
|
|
927
|
+
const i = stack.indexOf(id);
|
|
928
|
+
if (i !== -1) {
|
|
929
|
+
stack.splice(i, 1);
|
|
930
|
+
modalById.delete(id);
|
|
931
|
+
emit();
|
|
932
|
+
}
|
|
933
|
+
};
|
|
934
|
+
},
|
|
935
|
+
subscribe(listener) {
|
|
936
|
+
listeners.add(listener);
|
|
937
|
+
return () => {
|
|
938
|
+
listeners.delete(listener);
|
|
939
|
+
};
|
|
940
|
+
},
|
|
941
|
+
getState() {
|
|
942
|
+
const snapshot = stack.slice();
|
|
943
|
+
const modalTop = [...snapshot].reverse().find((id) => modalById.get(id) === true) ?? null;
|
|
944
|
+
return {
|
|
945
|
+
top: snapshot.length ? snapshot[snapshot.length - 1] : null,
|
|
946
|
+
stack: snapshot,
|
|
947
|
+
modalTop,
|
|
948
|
+
isModalActive: modalTop !== null,
|
|
949
|
+
isTop: (id) => snapshot[snapshot.length - 1] === id,
|
|
950
|
+
isInertOutside: (id) => snapshot.length > 0 && snapshot[snapshot.length - 1] !== id
|
|
951
|
+
};
|
|
952
|
+
}
|
|
953
|
+
};
|
|
954
|
+
}
|
|
955
|
+
function useOverlayRegistration(registry, id, active = true, modal = false) {
|
|
956
|
+
const latest = (0, import_react5.useRef)({ registry, id, active, modal });
|
|
957
|
+
latest.current = { registry, id, active, modal };
|
|
958
|
+
(0, import_react5.useEffect)(() => {
|
|
959
|
+
if (!latest.current.active) return;
|
|
960
|
+
return latest.current.registry.register(latest.current.id, {
|
|
961
|
+
modal: latest.current.modal
|
|
962
|
+
});
|
|
963
|
+
}, [registry, id, active, modal]);
|
|
964
|
+
}
|
|
965
|
+
function useOverlayModality(registry) {
|
|
966
|
+
const [state, setState] = (0, import_react5.useState)(
|
|
967
|
+
() => registry.getState()
|
|
968
|
+
);
|
|
969
|
+
const read = (0, import_react5.useCallback)(() => setState(registry.getState()), [registry]);
|
|
970
|
+
(0, import_react5.useEffect)(() => {
|
|
971
|
+
read();
|
|
972
|
+
return registry.subscribe(read);
|
|
973
|
+
}, [registry, read]);
|
|
974
|
+
return state;
|
|
975
|
+
}
|
|
976
|
+
var sharedOverlayModality = null;
|
|
977
|
+
function getSharedOverlayModality() {
|
|
978
|
+
if (!sharedOverlayModality) {
|
|
979
|
+
sharedOverlayModality = createOverlayModality();
|
|
980
|
+
}
|
|
981
|
+
return sharedOverlayModality;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
// src/portal.ts
|
|
985
|
+
function createPortalRegistry() {
|
|
986
|
+
const mounted = /* @__PURE__ */ new Map();
|
|
987
|
+
let sequence = 0;
|
|
988
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
989
|
+
const emit = () => {
|
|
990
|
+
for (const l of listeners) l();
|
|
991
|
+
};
|
|
992
|
+
return {
|
|
993
|
+
subscribe(listener) {
|
|
994
|
+
listeners.add(listener);
|
|
995
|
+
return () => {
|
|
996
|
+
listeners.delete(listener);
|
|
997
|
+
};
|
|
998
|
+
},
|
|
999
|
+
mount(id) {
|
|
1000
|
+
if (mounted.has(id)) return;
|
|
1001
|
+
mounted.set(id, sequence++);
|
|
1002
|
+
emit();
|
|
1003
|
+
},
|
|
1004
|
+
unmount(id) {
|
|
1005
|
+
if (!mounted.has(id)) return;
|
|
1006
|
+
mounted.delete(id);
|
|
1007
|
+
emit();
|
|
1008
|
+
},
|
|
1009
|
+
order() {
|
|
1010
|
+
return [...mounted.entries()].sort((a, b) => a[1] - b[1]).map(([id]) => id);
|
|
1011
|
+
},
|
|
1012
|
+
isMounted: (id) => mounted.has(id)
|
|
1013
|
+
};
|
|
1014
|
+
}
|
|
1015
|
+
function resolvePortalTarget(options) {
|
|
1016
|
+
return options.ownerProvided ?? options.defaultTarget ?? "kern-portal-root";
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
// src/positioning.ts
|
|
1020
|
+
function resolveFloatingOrigin(anchor, size, options) {
|
|
1021
|
+
const placement = options?.placement ?? "bottom";
|
|
1022
|
+
const offset = options?.offset ?? 0;
|
|
1023
|
+
const align = options?.align ?? "center";
|
|
1024
|
+
const alignOffset = options?.alignOffset ?? 0;
|
|
1025
|
+
const cross = (anchorStart, anchorSpan, surfaceSpan) => {
|
|
1026
|
+
if (align === "start") return anchorStart + alignOffset;
|
|
1027
|
+
if (align === "end")
|
|
1028
|
+
return anchorStart + anchorSpan - surfaceSpan + alignOffset;
|
|
1029
|
+
return anchorStart + (anchorSpan - surfaceSpan) / 2 + alignOffset;
|
|
1030
|
+
};
|
|
1031
|
+
switch (placement) {
|
|
1032
|
+
case "top":
|
|
1033
|
+
return {
|
|
1034
|
+
x: cross(anchor.x, anchor.width, size.width),
|
|
1035
|
+
y: anchor.y - size.height - offset
|
|
1036
|
+
};
|
|
1037
|
+
case "left":
|
|
1038
|
+
return {
|
|
1039
|
+
x: anchor.x - size.width - offset,
|
|
1040
|
+
y: cross(anchor.y, anchor.height, size.height)
|
|
1041
|
+
};
|
|
1042
|
+
case "right":
|
|
1043
|
+
return {
|
|
1044
|
+
x: anchor.x + anchor.width + offset,
|
|
1045
|
+
y: cross(anchor.y, anchor.height, size.height)
|
|
1046
|
+
};
|
|
1047
|
+
case "bottom":
|
|
1048
|
+
return {
|
|
1049
|
+
x: cross(anchor.x, anchor.width, size.width),
|
|
1050
|
+
y: anchor.y + anchor.height + offset
|
|
1051
|
+
};
|
|
1052
|
+
}
|
|
1053
|
+
}
|
|
1054
|
+
function clampRectToViewport(origin, size, viewport, padding) {
|
|
1055
|
+
const pad = padding ?? 0;
|
|
1056
|
+
const maxX = Math.max(pad, viewport.width - size.width - pad);
|
|
1057
|
+
const maxY = Math.max(pad, viewport.height - size.height - pad);
|
|
1058
|
+
return {
|
|
1059
|
+
x: Math.min(Math.max(origin.x, pad), maxX),
|
|
1060
|
+
y: Math.min(Math.max(origin.y, pad), maxY)
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
1063
|
+
function resolveFloatingSide(anchor, size, options) {
|
|
1064
|
+
const placement = options?.placement ?? "bottom";
|
|
1065
|
+
if (!options?.viewport) return placement;
|
|
1066
|
+
const pad = options.viewportPadding ?? 0;
|
|
1067
|
+
const offset = options.offset ?? 0;
|
|
1068
|
+
const viewport = options.viewport;
|
|
1069
|
+
if (placement === "bottom") {
|
|
1070
|
+
const bottomOverflow = anchor.y + anchor.height + offset + size.height - (viewport.height - pad);
|
|
1071
|
+
const topFits = anchor.y - offset - size.height >= pad;
|
|
1072
|
+
if (bottomOverflow > 0 && topFits) return "top";
|
|
1073
|
+
} else if (placement === "top") {
|
|
1074
|
+
const topOverflow = pad - (anchor.y - offset - size.height);
|
|
1075
|
+
const bottomFits = anchor.y + anchor.height + offset + size.height <= viewport.height - pad;
|
|
1076
|
+
if (topOverflow > 0 && bottomFits) return "bottom";
|
|
1077
|
+
} else if (placement === "right") {
|
|
1078
|
+
const rightOverflow = anchor.x + anchor.width + offset + size.width - (viewport.width - pad);
|
|
1079
|
+
const leftFits = anchor.x - offset - size.width >= pad;
|
|
1080
|
+
if (rightOverflow > 0 && leftFits) return "left";
|
|
1081
|
+
} else if (placement === "left") {
|
|
1082
|
+
const leftOverflow = pad - (anchor.x - offset - size.width);
|
|
1083
|
+
const rightFits = anchor.x + anchor.width + offset + size.width <= viewport.width - pad;
|
|
1084
|
+
if (leftOverflow > 0 && rightFits) return "right";
|
|
1085
|
+
}
|
|
1086
|
+
return placement;
|
|
1087
|
+
}
|
|
1088
|
+
function resolveFloatingRect(anchor, size, options) {
|
|
1089
|
+
const placement = options?.flip ? resolveFloatingSide(anchor, size, options) : options?.placement;
|
|
1090
|
+
const origin = resolveFloatingOrigin(anchor, size, { ...options, placement });
|
|
1091
|
+
if (!options?.viewport) return origin;
|
|
1092
|
+
return clampRectToViewport(
|
|
1093
|
+
origin,
|
|
1094
|
+
size,
|
|
1095
|
+
options.viewport,
|
|
1096
|
+
options.viewportPadding
|
|
1097
|
+
);
|
|
1098
|
+
}
|
|
1099
|
+
|
|
1100
|
+
// src/presence.ts
|
|
1101
|
+
var import_react6 = require("react");
|
|
1102
|
+
function nextPresenceState(current, open) {
|
|
1103
|
+
if (open) return "mounted";
|
|
1104
|
+
return current === "unmounted" ? "unmounted" : "exiting";
|
|
1105
|
+
}
|
|
1106
|
+
function createPresenceModel(initialOpen) {
|
|
1107
|
+
let state = initialOpen ? "mounted" : "unmounted";
|
|
1108
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1109
|
+
const emit = () => {
|
|
1110
|
+
for (const l of listeners) l();
|
|
1111
|
+
};
|
|
1112
|
+
const setState = (next) => {
|
|
1113
|
+
if (next === state) return;
|
|
1114
|
+
state = next;
|
|
1115
|
+
emit();
|
|
1116
|
+
};
|
|
1117
|
+
return {
|
|
1118
|
+
subscribe(listener) {
|
|
1119
|
+
listeners.add(listener);
|
|
1120
|
+
return () => {
|
|
1121
|
+
listeners.delete(listener);
|
|
1122
|
+
};
|
|
1123
|
+
},
|
|
1124
|
+
getState: () => state,
|
|
1125
|
+
setOpen: (open) => setState(nextPresenceState(state, open)),
|
|
1126
|
+
finishExit: () => {
|
|
1127
|
+
if (state === "exiting") setState("unmounted");
|
|
1128
|
+
},
|
|
1129
|
+
isPresent: () => state !== "unmounted"
|
|
1130
|
+
};
|
|
1131
|
+
}
|
|
1132
|
+
function usePresence(open) {
|
|
1133
|
+
const [model] = (0, import_react6.useState)(() => createPresenceModel(open));
|
|
1134
|
+
const state = (0, import_react6.useSyncExternalStore)(
|
|
1135
|
+
(listener) => model.subscribe(listener),
|
|
1136
|
+
() => model.getState()
|
|
1137
|
+
);
|
|
1138
|
+
(0, import_react6.useEffect)(() => {
|
|
1139
|
+
model.setOpen(open);
|
|
1140
|
+
}, [model, open]);
|
|
1141
|
+
return {
|
|
1142
|
+
present: state !== "unmounted",
|
|
1143
|
+
state,
|
|
1144
|
+
finishExit: model.finishExit
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
|
|
1148
|
+
// src/press.ts
|
|
1149
|
+
var import_react7 = require("react");
|
|
1150
|
+
function createPressModel(options) {
|
|
1151
|
+
const disabled = options?.disabled ?? false;
|
|
1152
|
+
const onPress = options?.onPress;
|
|
1153
|
+
let phase = "idle";
|
|
1154
|
+
return {
|
|
1155
|
+
getPhase: () => phase,
|
|
1156
|
+
isPressed: () => phase === "pressed",
|
|
1157
|
+
isDisabled: () => disabled,
|
|
1158
|
+
begin: () => {
|
|
1159
|
+
if (disabled || phase === "pressed") return;
|
|
1160
|
+
phase = "pressed";
|
|
1161
|
+
},
|
|
1162
|
+
end: () => {
|
|
1163
|
+
if (disabled || phase !== "pressed") return;
|
|
1164
|
+
phase = "idle";
|
|
1165
|
+
onPress?.();
|
|
1166
|
+
},
|
|
1167
|
+
cancel: () => {
|
|
1168
|
+
phase = "idle";
|
|
1169
|
+
}
|
|
1170
|
+
};
|
|
1171
|
+
}
|
|
1172
|
+
function usePress(options) {
|
|
1173
|
+
const [model] = (0, import_react7.useState)(() => createPressModel(options));
|
|
1174
|
+
const [pressed, setPressed] = (0, import_react7.useState)(false);
|
|
1175
|
+
const sync = (0, import_react7.useCallback)(() => setPressed(model.isPressed()), [model]);
|
|
1176
|
+
const begin = (0, import_react7.useCallback)(() => {
|
|
1177
|
+
model.begin();
|
|
1178
|
+
sync();
|
|
1179
|
+
}, [model, sync]);
|
|
1180
|
+
const end = (0, import_react7.useCallback)(() => {
|
|
1181
|
+
model.end();
|
|
1182
|
+
sync();
|
|
1183
|
+
}, [model, sync]);
|
|
1184
|
+
const cancel = (0, import_react7.useCallback)(() => {
|
|
1185
|
+
model.cancel();
|
|
1186
|
+
sync();
|
|
1187
|
+
}, [model, sync]);
|
|
1188
|
+
return { pressed, begin, end, cancel };
|
|
1189
|
+
}
|
|
1190
|
+
|
|
1191
|
+
// src/promptInput.ts
|
|
1192
|
+
var import_react8 = require("react");
|
|
1193
|
+
function resolveCanSend(options) {
|
|
1194
|
+
if (!options.text.trim()) return false;
|
|
1195
|
+
if (isChatBusy(options.status)) return false;
|
|
1196
|
+
if (options.maxLength !== void 0 && options.text.length > options.maxLength) {
|
|
1197
|
+
return false;
|
|
1198
|
+
}
|
|
1199
|
+
return true;
|
|
1200
|
+
}
|
|
1201
|
+
function shouldSubmitOnKey(options) {
|
|
1202
|
+
if (options.key !== "Enter") return false;
|
|
1203
|
+
switch (options.submitMode) {
|
|
1204
|
+
case "enter":
|
|
1205
|
+
return !options.shiftKey;
|
|
1206
|
+
case "ctrlEnter":
|
|
1207
|
+
return Boolean(options.ctrlKey || options.metaKey);
|
|
1208
|
+
case "none":
|
|
1209
|
+
return false;
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
function shouldCancelOnEscapeKey(key, cancelOnEscape) {
|
|
1213
|
+
return cancelOnEscape && key === "Escape";
|
|
1214
|
+
}
|
|
1215
|
+
function resolveComposerHeight(options) {
|
|
1216
|
+
const minLines = Math.max(1, options.minLines ?? 1);
|
|
1217
|
+
const maxLines = Math.max(minLines, options.maxLines ?? 5);
|
|
1218
|
+
const lines = Math.min(Math.max(options.lineCount, minLines), maxLines);
|
|
1219
|
+
return lines * options.lineHeight;
|
|
1220
|
+
}
|
|
1221
|
+
function usePromptInput(options) {
|
|
1222
|
+
const [raw, setRaw] = useControllableState(
|
|
1223
|
+
options?.value,
|
|
1224
|
+
options?.defaultValue ?? "",
|
|
1225
|
+
options?.onChange
|
|
1226
|
+
);
|
|
1227
|
+
const value = raw ?? "";
|
|
1228
|
+
const {
|
|
1229
|
+
status = "idle",
|
|
1230
|
+
submitMode = "enter",
|
|
1231
|
+
cancelOnEscape = false,
|
|
1232
|
+
maxLength,
|
|
1233
|
+
onSubmit
|
|
1234
|
+
} = options ?? {};
|
|
1235
|
+
const canSend = resolveCanSend({ text: value, status, maxLength });
|
|
1236
|
+
const setValue = (0, import_react8.useCallback)(
|
|
1237
|
+
(next) => {
|
|
1238
|
+
setRaw(next);
|
|
1239
|
+
},
|
|
1240
|
+
[setRaw]
|
|
1241
|
+
);
|
|
1242
|
+
const clear = (0, import_react8.useCallback)(() => {
|
|
1243
|
+
setRaw("");
|
|
1244
|
+
}, [setRaw]);
|
|
1245
|
+
const submit = (0, import_react8.useCallback)(() => {
|
|
1246
|
+
if (!resolveCanSend({ text: value, status, maxLength })) return;
|
|
1247
|
+
onSubmit?.(value);
|
|
1248
|
+
}, [value, status, maxLength, onSubmit]);
|
|
1249
|
+
const handleKey = (0, import_react8.useCallback)(
|
|
1250
|
+
(event) => {
|
|
1251
|
+
if (shouldSubmitOnKey({ ...event, submitMode }) && resolveCanSend({ text: value, status, maxLength })) {
|
|
1252
|
+
onSubmit?.(value);
|
|
1253
|
+
return true;
|
|
1254
|
+
}
|
|
1255
|
+
if (shouldCancelOnEscapeKey(event.key, cancelOnEscape)) {
|
|
1256
|
+
setRaw("");
|
|
1257
|
+
return true;
|
|
1258
|
+
}
|
|
1259
|
+
return false;
|
|
1260
|
+
},
|
|
1261
|
+
[value, status, maxLength, submitMode, cancelOnEscape, onSubmit, setRaw]
|
|
1262
|
+
);
|
|
1263
|
+
return { value, setValue, canSend, submit, clear, handleKey };
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
// src/reasoning.ts
|
|
1267
|
+
function resolveReasoningOpen(open, status) {
|
|
1268
|
+
if (status === "streaming") return true;
|
|
1269
|
+
return open ?? false;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
// src/render.ts
|
|
1273
|
+
var import_react9 = require("react");
|
|
1274
|
+
|
|
1275
|
+
// src/slot.ts
|
|
1276
|
+
function isHandler(value) {
|
|
1277
|
+
return typeof value === "function";
|
|
1278
|
+
}
|
|
1279
|
+
function composeEventHandlers(partHandler, consumerHandler) {
|
|
1280
|
+
if (!partHandler) return consumerHandler;
|
|
1281
|
+
if (!consumerHandler) return partHandler;
|
|
1282
|
+
return (event) => {
|
|
1283
|
+
partHandler(event);
|
|
1284
|
+
consumerHandler(event);
|
|
1285
|
+
};
|
|
1286
|
+
}
|
|
1287
|
+
function flattenStyleProp(style) {
|
|
1288
|
+
if (Array.isArray(style)) {
|
|
1289
|
+
const out = {};
|
|
1290
|
+
for (const entry of style) {
|
|
1291
|
+
Object.assign(out, flattenStyleProp(entry));
|
|
1292
|
+
}
|
|
1293
|
+
return out;
|
|
1294
|
+
}
|
|
1295
|
+
if (typeof style === "object" && style !== null) {
|
|
1296
|
+
return { ...style };
|
|
1297
|
+
}
|
|
1298
|
+
return {};
|
|
1299
|
+
}
|
|
1300
|
+
function mergeSlotProps(partProps, ...consumerSets) {
|
|
1301
|
+
const merged = { ...partProps };
|
|
1302
|
+
for (const set of consumerSets) {
|
|
1303
|
+
if (!set) continue;
|
|
1304
|
+
for (const key of Object.keys(set)) {
|
|
1305
|
+
const incoming = set[key];
|
|
1306
|
+
if (incoming === void 0) continue;
|
|
1307
|
+
const current = merged[key];
|
|
1308
|
+
if (key.startsWith("on") && isHandler(current) && isHandler(incoming)) {
|
|
1309
|
+
merged[key] = composeEventHandlers(
|
|
1310
|
+
current,
|
|
1311
|
+
incoming
|
|
1312
|
+
);
|
|
1313
|
+
continue;
|
|
1314
|
+
}
|
|
1315
|
+
if (key === "className" && typeof current === "string" && typeof incoming === "string") {
|
|
1316
|
+
merged[key] = `${current} ${incoming}`;
|
|
1317
|
+
continue;
|
|
1318
|
+
}
|
|
1319
|
+
if (key === "style" && (typeof current === "object" || Array.isArray(current)) && current !== null && (typeof incoming === "object" || Array.isArray(incoming)) && incoming !== null) {
|
|
1320
|
+
merged[key] = {
|
|
1321
|
+
...flattenStyleProp(current),
|
|
1322
|
+
...flattenStyleProp(incoming)
|
|
1323
|
+
};
|
|
1324
|
+
continue;
|
|
1325
|
+
}
|
|
1326
|
+
merged[key] = incoming;
|
|
1327
|
+
}
|
|
1328
|
+
}
|
|
1329
|
+
return merged;
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// src/render.ts
|
|
1333
|
+
function resolveStyle(style, state) {
|
|
1334
|
+
if (typeof style === "function") {
|
|
1335
|
+
return style(state);
|
|
1336
|
+
}
|
|
1337
|
+
return style;
|
|
1338
|
+
}
|
|
1339
|
+
function resolveRender(render, partProps, state) {
|
|
1340
|
+
if (render === void 0 || render === null) return null;
|
|
1341
|
+
if (typeof render === "function") {
|
|
1342
|
+
return render(partProps, state);
|
|
1343
|
+
}
|
|
1344
|
+
if ((0, import_react9.isValidElement)(render)) {
|
|
1345
|
+
const merged = mergeSlotProps(
|
|
1346
|
+
partProps,
|
|
1347
|
+
render.props ?? {}
|
|
1348
|
+
);
|
|
1349
|
+
const element = render;
|
|
1350
|
+
return (0, import_react9.cloneElement)(element, {
|
|
1351
|
+
...merged,
|
|
1352
|
+
className: void 0
|
|
1353
|
+
});
|
|
1354
|
+
}
|
|
1355
|
+
return null;
|
|
1356
|
+
}
|
|
1357
|
+
|
|
1358
|
+
// src/roving.ts
|
|
1359
|
+
var import_react10 = require("react");
|
|
1360
|
+
function clamp(index, count) {
|
|
1361
|
+
if (count <= 0) return 0;
|
|
1362
|
+
return Math.min(Math.max(index, 0), count - 1);
|
|
1363
|
+
}
|
|
1364
|
+
function createRovingModel(options) {
|
|
1365
|
+
const {
|
|
1366
|
+
count,
|
|
1367
|
+
orientation = "horizontal",
|
|
1368
|
+
loop = false,
|
|
1369
|
+
isDisabled = () => false
|
|
1370
|
+
} = options;
|
|
1371
|
+
const controlled = options.activeIndex !== void 0;
|
|
1372
|
+
let current = clamp(
|
|
1373
|
+
options.activeIndex ?? options.defaultActiveIndex ?? 0,
|
|
1374
|
+
count
|
|
1375
|
+
);
|
|
1376
|
+
const listeners = [];
|
|
1377
|
+
const notify = (next) => {
|
|
1378
|
+
for (const fn of listeners) fn(next);
|
|
1379
|
+
};
|
|
1380
|
+
const commit = (raw) => {
|
|
1381
|
+
const next = clamp(raw, count);
|
|
1382
|
+
if (next === current) return;
|
|
1383
|
+
if (controlled) {
|
|
1384
|
+
options.onActiveIndexChange?.(next);
|
|
1385
|
+
return;
|
|
1386
|
+
}
|
|
1387
|
+
current = next;
|
|
1388
|
+
notify(next);
|
|
1389
|
+
};
|
|
1390
|
+
const step = (delta) => {
|
|
1391
|
+
if (count <= 0) return current;
|
|
1392
|
+
const span = count;
|
|
1393
|
+
let index = current;
|
|
1394
|
+
for (let probe = 0; probe < span; probe += 1) {
|
|
1395
|
+
index += delta;
|
|
1396
|
+
if (index < 0 || index > span - 1) {
|
|
1397
|
+
if (!loop) return current;
|
|
1398
|
+
index = (index + span) % span;
|
|
1399
|
+
}
|
|
1400
|
+
if (!isDisabled(index)) break;
|
|
1401
|
+
}
|
|
1402
|
+
if (isDisabled(index)) return current;
|
|
1403
|
+
commit(index);
|
|
1404
|
+
return current;
|
|
1405
|
+
};
|
|
1406
|
+
return {
|
|
1407
|
+
get activeIndex() {
|
|
1408
|
+
return current;
|
|
1409
|
+
},
|
|
1410
|
+
set activeIndex(value) {
|
|
1411
|
+
commit(value);
|
|
1412
|
+
},
|
|
1413
|
+
setActive: commit,
|
|
1414
|
+
next: () => step(1),
|
|
1415
|
+
previous: () => step(-1),
|
|
1416
|
+
// `commit` reports rather than returns, so these read `current` back rather
|
|
1417
|
+
// than returning its void.
|
|
1418
|
+
first: () => {
|
|
1419
|
+
commit(0);
|
|
1420
|
+
return current;
|
|
1421
|
+
},
|
|
1422
|
+
last: () => {
|
|
1423
|
+
commit(count - 1);
|
|
1424
|
+
return current;
|
|
1425
|
+
},
|
|
1426
|
+
describe: (index) => {
|
|
1427
|
+
const disabled = count > 0 && isDisabled(index);
|
|
1428
|
+
const isActive = count > 0 && !disabled && clamp(index, count) === current;
|
|
1429
|
+
return {
|
|
1430
|
+
index,
|
|
1431
|
+
isActive,
|
|
1432
|
+
// EXACTLY ONE tabbable item per group — the whole point of the model.
|
|
1433
|
+
// When the active item is disabled there is none, which is correct: a
|
|
1434
|
+
// group whose only stop is disabled contributes no tab stop.
|
|
1435
|
+
isTabbable: isActive,
|
|
1436
|
+
disabled
|
|
1437
|
+
};
|
|
1438
|
+
},
|
|
1439
|
+
orientation,
|
|
1440
|
+
loop
|
|
1441
|
+
};
|
|
1442
|
+
}
|
|
1443
|
+
function useRovingModel(options) {
|
|
1444
|
+
const controlled = options.activeIndex !== void 0;
|
|
1445
|
+
const [internal, setInternal] = (0, import_react10.useState)(
|
|
1446
|
+
() => clamp(options.defaultActiveIndex ?? 0, options.count)
|
|
1447
|
+
);
|
|
1448
|
+
const model = createRovingModel({
|
|
1449
|
+
...options,
|
|
1450
|
+
// Always pass the resolved value, so the model behaves as controlled and
|
|
1451
|
+
// reports changes rather than mutating its own copy.
|
|
1452
|
+
activeIndex: controlled ? options.activeIndex ?? 0 : internal,
|
|
1453
|
+
onActiveIndexChange: (next) => {
|
|
1454
|
+
if (!controlled) setInternal(next);
|
|
1455
|
+
options.onActiveIndexChange?.(next);
|
|
1456
|
+
}
|
|
1457
|
+
});
|
|
1458
|
+
return model;
|
|
1459
|
+
}
|
|
1460
|
+
|
|
1461
|
+
// src/selection.ts
|
|
1462
|
+
var import_react11 = require("react");
|
|
1463
|
+
function normalizeSelection(value, mode) {
|
|
1464
|
+
if (value === void 0) return [];
|
|
1465
|
+
const list = typeof value === "string" || typeof value === "number" ? [value] : value;
|
|
1466
|
+
if (mode !== "multiple") return list.slice(0, 1);
|
|
1467
|
+
return [...new Set(list)];
|
|
1468
|
+
}
|
|
1469
|
+
function isSelected(selected, key) {
|
|
1470
|
+
return selected.includes(key);
|
|
1471
|
+
}
|
|
1472
|
+
function toggleSelection(selected, key, mode) {
|
|
1473
|
+
if (mode === "single-toggle") {
|
|
1474
|
+
return selected[0] === key ? [] : [key];
|
|
1475
|
+
}
|
|
1476
|
+
if (mode === "single") return [key];
|
|
1477
|
+
return selected.includes(key) ? selected.filter((entry) => entry !== key) : [...selected, key];
|
|
1478
|
+
}
|
|
1479
|
+
function sameSelection(a, b) {
|
|
1480
|
+
if (a.length !== b.length) return false;
|
|
1481
|
+
const setA = new Set(a);
|
|
1482
|
+
return b.every((entry) => setA.has(entry));
|
|
1483
|
+
}
|
|
1484
|
+
function useSelection({
|
|
1485
|
+
value,
|
|
1486
|
+
defaultValue,
|
|
1487
|
+
onChange,
|
|
1488
|
+
mode
|
|
1489
|
+
}) {
|
|
1490
|
+
const notify = (0, import_react11.useCallback)(
|
|
1491
|
+
(next) => {
|
|
1492
|
+
onChange?.(normalizeSelection(next, mode));
|
|
1493
|
+
},
|
|
1494
|
+
[onChange, mode]
|
|
1495
|
+
);
|
|
1496
|
+
const [raw, setRaw] = useControllableState(
|
|
1497
|
+
value,
|
|
1498
|
+
defaultValue,
|
|
1499
|
+
notify
|
|
1500
|
+
);
|
|
1501
|
+
const selected = (0, import_react11.useMemo)(() => normalizeSelection(raw, mode), [raw, mode]);
|
|
1502
|
+
const select = (0, import_react11.useCallback)(
|
|
1503
|
+
(key) => {
|
|
1504
|
+
setRaw((previous) => {
|
|
1505
|
+
const current = normalizeSelection(previous, mode);
|
|
1506
|
+
const updated = toggleSelection(current, key, mode);
|
|
1507
|
+
if (sameSelection(current, updated)) return previous;
|
|
1508
|
+
return updated;
|
|
1509
|
+
});
|
|
1510
|
+
},
|
|
1511
|
+
[mode, setRaw]
|
|
1512
|
+
);
|
|
1513
|
+
return [selected, select];
|
|
1514
|
+
}
|
|
1515
|
+
|
|
1516
|
+
// src/slider.ts
|
|
1517
|
+
function clampSliderValue(value, min, max) {
|
|
1518
|
+
const hi = max > min ? max : min;
|
|
1519
|
+
if (!Number.isFinite(value)) return min;
|
|
1520
|
+
return Math.min(Math.max(value, min), hi);
|
|
1521
|
+
}
|
|
1522
|
+
function snapSliderValue(value, min, step) {
|
|
1523
|
+
if (!Number.isFinite(step) || step <= 0) return value;
|
|
1524
|
+
return min + Math.round((value - min) / step) * step;
|
|
1525
|
+
}
|
|
1526
|
+
function sliderValuePercent(value, min, max) {
|
|
1527
|
+
const hi = max > min ? max : min;
|
|
1528
|
+
const range = hi - min;
|
|
1529
|
+
if (range <= 0) return 0;
|
|
1530
|
+
return (clampSliderValue(value, min, max) - min) / range * 100;
|
|
1531
|
+
}
|
|
1532
|
+
function normalizeSliderValues(value, min, max) {
|
|
1533
|
+
const list = Array.isArray(value) ? [...value] : [value];
|
|
1534
|
+
if (list.length === 0) return [min];
|
|
1535
|
+
return list.map(
|
|
1536
|
+
(v) => clampSliderValue(
|
|
1537
|
+
typeof v === "number" && Number.isFinite(v) ? v : min,
|
|
1538
|
+
min,
|
|
1539
|
+
max
|
|
1540
|
+
)
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
function sliderRatioFromLocation(location, extent, orientation) {
|
|
1544
|
+
if (!(extent > 0)) return 0;
|
|
1545
|
+
const ratio = location / extent;
|
|
1546
|
+
const clamped = Math.min(Math.max(ratio, 0), 1);
|
|
1547
|
+
return orientation === "vertical" ? 1 - clamped : clamped;
|
|
1548
|
+
}
|
|
1549
|
+
function sliderValueFromRatio(ratio, min, max) {
|
|
1550
|
+
const hi = max > min ? max : min;
|
|
1551
|
+
return min + Math.min(Math.max(ratio, 0), 1) * (hi - min);
|
|
1552
|
+
}
|
|
1553
|
+
function nearestSliderThumbIndex(values, target) {
|
|
1554
|
+
let best = 0;
|
|
1555
|
+
let bestDistance = Infinity;
|
|
1556
|
+
for (let i = 0; i < values.length; i++) {
|
|
1557
|
+
const distance = Math.abs((values[i] ?? 0) - target);
|
|
1558
|
+
if (distance < bestDistance) {
|
|
1559
|
+
bestDistance = distance;
|
|
1560
|
+
best = i;
|
|
1561
|
+
}
|
|
1562
|
+
}
|
|
1563
|
+
return best;
|
|
1564
|
+
}
|
|
1565
|
+
function resolveSliderCommit(values, index, next, options) {
|
|
1566
|
+
const { min, max, step, minStepsBetweenValues } = options;
|
|
1567
|
+
const clamped = clampSliderValue(next, min, max);
|
|
1568
|
+
const snapped = clampSliderValue(
|
|
1569
|
+
snapSliderValue(clamped, min, step),
|
|
1570
|
+
min,
|
|
1571
|
+
max
|
|
1572
|
+
);
|
|
1573
|
+
if (values.length < 2) return [snapped];
|
|
1574
|
+
const gapSteps = Math.max(0, minStepsBetweenValues);
|
|
1575
|
+
const gap = step > 0 && Number.isFinite(step) ? gapSteps * step : gapSteps;
|
|
1576
|
+
const updated = [...values];
|
|
1577
|
+
const at = Math.min(Math.max(index, 0), updated.length - 1);
|
|
1578
|
+
updated[at] = snapped;
|
|
1579
|
+
const lower = at > 0 ? (updated[at - 1] ?? min) + gap : min;
|
|
1580
|
+
const upper = at < updated.length - 1 ? (updated[at + 1] ?? max) - gap : max;
|
|
1581
|
+
const lo = Math.min(lower, upper);
|
|
1582
|
+
const hi = Math.max(lower, upper);
|
|
1583
|
+
updated[at] = Math.min(Math.max(snapped, lo), hi);
|
|
1584
|
+
return updated;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
// src/stickToBottom.ts
|
|
1588
|
+
var import_react12 = require("react");
|
|
1589
|
+
function distanceToBottom(metrics) {
|
|
1590
|
+
return metrics.contentHeight - metrics.viewportHeight - metrics.scrollOffset;
|
|
1591
|
+
}
|
|
1592
|
+
function isAtBottom(metrics, threshold = 24) {
|
|
1593
|
+
return distanceToBottom(metrics) <= threshold;
|
|
1594
|
+
}
|
|
1595
|
+
function resolveScrollButtonVisible(options) {
|
|
1596
|
+
return !options.stuck && options.contentHeight > options.viewportHeight;
|
|
1597
|
+
}
|
|
1598
|
+
function useStickToBottom(options) {
|
|
1599
|
+
const threshold = options?.threshold ?? 24;
|
|
1600
|
+
const [stuck, setStuck] = useControllableState(
|
|
1601
|
+
options?.stuck,
|
|
1602
|
+
options?.defaultStuck ?? true,
|
|
1603
|
+
options?.onStuckChange
|
|
1604
|
+
);
|
|
1605
|
+
const pinned = stuck ?? true;
|
|
1606
|
+
const handleScroll = (0, import_react12.useCallback)(
|
|
1607
|
+
(metrics) => {
|
|
1608
|
+
setStuck(isAtBottom(metrics, threshold));
|
|
1609
|
+
},
|
|
1610
|
+
[setStuck, threshold]
|
|
1611
|
+
);
|
|
1612
|
+
const handleContentChange = (0, import_react12.useCallback)(
|
|
1613
|
+
(metrics) => {
|
|
1614
|
+
const atBottom = isAtBottom(metrics, threshold);
|
|
1615
|
+
if (!pinned) return false;
|
|
1616
|
+
if (!atBottom) setStuck(false);
|
|
1617
|
+
return atBottom;
|
|
1618
|
+
},
|
|
1619
|
+
[pinned, setStuck, threshold]
|
|
1620
|
+
);
|
|
1621
|
+
const scrollToBottom = (0, import_react12.useCallback)(() => {
|
|
1622
|
+
setStuck(true);
|
|
1623
|
+
}, [setStuck]);
|
|
1624
|
+
const showScrollButton = (0, import_react12.useCallback)(
|
|
1625
|
+
(metrics) => resolveScrollButtonVisible({
|
|
1626
|
+
stuck: pinned,
|
|
1627
|
+
contentHeight: metrics.contentHeight,
|
|
1628
|
+
viewportHeight: metrics.viewportHeight
|
|
1629
|
+
}),
|
|
1630
|
+
[pinned]
|
|
1631
|
+
);
|
|
1632
|
+
return {
|
|
1633
|
+
stuck: pinned,
|
|
1634
|
+
showScrollButton,
|
|
1635
|
+
handleScroll,
|
|
1636
|
+
handleContentChange,
|
|
1637
|
+
scrollToBottom
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1641
|
+
// src/time.ts
|
|
1642
|
+
function minutesForStep(step) {
|
|
1643
|
+
const valid = Number.isInteger(step) && step > 0 && Number.isInteger(60 / step);
|
|
1644
|
+
if (!valid) {
|
|
1645
|
+
return Array.from({ length: 60 }, (_, i) => i);
|
|
1646
|
+
}
|
|
1647
|
+
return Array.from({ length: 60 / step }, (_, i) => i * step);
|
|
1648
|
+
}
|
|
1649
|
+
function normalizeTimeValue(value, step = 1) {
|
|
1650
|
+
const options = minutesForStep(step);
|
|
1651
|
+
const hours = Number.isFinite(value?.hours) ? Math.min(Math.max(Math.trunc(value?.hours ?? 0), 0), 23) : 0;
|
|
1652
|
+
const rawMinutes = Number.isFinite(value?.minutes) ? Math.trunc(value?.minutes ?? 0) : 0;
|
|
1653
|
+
let minutes = 0;
|
|
1654
|
+
for (const option of options) {
|
|
1655
|
+
if (option <= rawMinutes) minutes = option;
|
|
1656
|
+
}
|
|
1657
|
+
return { hours, minutes };
|
|
1658
|
+
}
|
|
1659
|
+
function formatTimeValue(value, format) {
|
|
1660
|
+
const normalised = normalizeTimeValue(value);
|
|
1661
|
+
if (format === "24h") {
|
|
1662
|
+
return {
|
|
1663
|
+
hours: normalised.hours,
|
|
1664
|
+
period: normalised.hours < 12 ? "AM" : "PM"
|
|
1665
|
+
};
|
|
1666
|
+
}
|
|
1667
|
+
const twelve = normalised.hours % 12 === 0 ? 12 : normalised.hours % 12;
|
|
1668
|
+
return { hours: twelve, period: normalised.hours < 12 ? "AM" : "PM" };
|
|
1669
|
+
}
|
|
1670
|
+
function toTwentyFourHour(twelveHour, period) {
|
|
1671
|
+
const base = twelveHour % 12;
|
|
1672
|
+
return period === "PM" ? base + 12 : base;
|
|
1673
|
+
}
|
|
1674
|
+
function formatDigits(value, digits, locale) {
|
|
1675
|
+
try {
|
|
1676
|
+
return new Intl.NumberFormat(locale, {
|
|
1677
|
+
minimumIntegerDigits: digits,
|
|
1678
|
+
useGrouping: false
|
|
1679
|
+
}).format(value);
|
|
1680
|
+
} catch {
|
|
1681
|
+
return String(value).padStart(digits, "0");
|
|
1682
|
+
}
|
|
1683
|
+
}
|
|
1684
|
+
function resolveDayPeriod(locale, hours24) {
|
|
1685
|
+
try {
|
|
1686
|
+
const format = new Intl.DateTimeFormat(locale, {
|
|
1687
|
+
hour: "numeric",
|
|
1688
|
+
hour12: true
|
|
1689
|
+
});
|
|
1690
|
+
const found = format.formatToParts(new Date(Date.UTC(2026, 0, 1, hours24))).find((part) => part.type === "dayPeriod")?.value;
|
|
1691
|
+
if (found !== void 0) return found;
|
|
1692
|
+
} catch {
|
|
1693
|
+
}
|
|
1694
|
+
return hours24 < 12 ? "AM" : "PM";
|
|
1695
|
+
}
|
|
1696
|
+
function formatTimeParts(value, format = "24h", locale) {
|
|
1697
|
+
const normalised = normalizeTimeValue(value);
|
|
1698
|
+
if (format === "24h") {
|
|
1699
|
+
return {
|
|
1700
|
+
hours: formatDigits(normalised.hours, 2, locale),
|
|
1701
|
+
minutes: formatDigits(normalised.minutes, 2, locale),
|
|
1702
|
+
period: null
|
|
1703
|
+
};
|
|
1704
|
+
}
|
|
1705
|
+
const twelve = normalised.hours % 12 === 0 ? 12 : normalised.hours % 12;
|
|
1706
|
+
return {
|
|
1707
|
+
hours: formatDigits(twelve, 1, locale),
|
|
1708
|
+
minutes: formatDigits(normalised.minutes, 2, locale),
|
|
1709
|
+
period: resolveDayPeriod(locale, normalised.hours)
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
function addTimeMinutes(value, deltaMinutes, step = 1) {
|
|
1713
|
+
const base = normalizeTimeValue(value, step);
|
|
1714
|
+
const delta = Number.isFinite(deltaMinutes) ? Math.trunc(deltaMinutes) : 0;
|
|
1715
|
+
const total = base.hours * 60 + base.minutes + delta;
|
|
1716
|
+
const wrapped = (total % 1440 + 1440) % 1440;
|
|
1717
|
+
return normalizeTimeValue(
|
|
1718
|
+
{ hours: Math.floor(wrapped / 60), minutes: wrapped % 60 },
|
|
1719
|
+
step
|
|
1720
|
+
);
|
|
1721
|
+
}
|
|
1722
|
+
|
|
1723
|
+
// src/toastQueue.ts
|
|
1724
|
+
function createToastQueue() {
|
|
1725
|
+
const queued = /* @__PURE__ */ new Map();
|
|
1726
|
+
let sequence = 0;
|
|
1727
|
+
let version = 0;
|
|
1728
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
1729
|
+
const emit = () => {
|
|
1730
|
+
version += 1;
|
|
1731
|
+
for (const l of listeners) l();
|
|
1732
|
+
};
|
|
1733
|
+
return {
|
|
1734
|
+
subscribe(listener) {
|
|
1735
|
+
listeners.add(listener);
|
|
1736
|
+
return () => {
|
|
1737
|
+
listeners.delete(listener);
|
|
1738
|
+
};
|
|
1739
|
+
},
|
|
1740
|
+
add(id) {
|
|
1741
|
+
if (queued.has(id)) return;
|
|
1742
|
+
queued.set(id, sequence++);
|
|
1743
|
+
emit();
|
|
1744
|
+
},
|
|
1745
|
+
dismiss(id) {
|
|
1746
|
+
if (!queued.has(id)) return;
|
|
1747
|
+
queued.delete(id);
|
|
1748
|
+
emit();
|
|
1749
|
+
},
|
|
1750
|
+
clear() {
|
|
1751
|
+
if (queued.size === 0) return;
|
|
1752
|
+
queued.clear();
|
|
1753
|
+
emit();
|
|
1754
|
+
},
|
|
1755
|
+
order() {
|
|
1756
|
+
return [...queued.entries()].sort((a, b) => a[1] - b[1]).map(([id]) => id);
|
|
1757
|
+
},
|
|
1758
|
+
isOpen: (id) => queued.has(id),
|
|
1759
|
+
count: () => queued.size,
|
|
1760
|
+
version: () => version
|
|
1761
|
+
};
|
|
1762
|
+
}
|
|
1763
|
+
|
|
1764
|
+
// src/toolCall.ts
|
|
1765
|
+
var import_react13 = require("react");
|
|
1766
|
+
function isToolCallRunning(state) {
|
|
1767
|
+
return state === "input-streaming" || state === "input-available";
|
|
1768
|
+
}
|
|
1769
|
+
function isToolCallComplete(state) {
|
|
1770
|
+
return state === "output-available" || state === "output-denied";
|
|
1771
|
+
}
|
|
1772
|
+
function isToolCallError(state) {
|
|
1773
|
+
return state === "output-error";
|
|
1774
|
+
}
|
|
1775
|
+
function isToolCallApproval(state) {
|
|
1776
|
+
return state === "approval-requested";
|
|
1777
|
+
}
|
|
1778
|
+
function resolveToolCallLabel(options) {
|
|
1779
|
+
const { name, state } = options;
|
|
1780
|
+
switch (state) {
|
|
1781
|
+
case "input-streaming":
|
|
1782
|
+
return `Tool ${name} running`;
|
|
1783
|
+
case "input-available":
|
|
1784
|
+
return `Tool ${name} queued`;
|
|
1785
|
+
case "output-available":
|
|
1786
|
+
return `Tool ${name} completed`;
|
|
1787
|
+
case "output-denied":
|
|
1788
|
+
return `Tool ${name} denied`;
|
|
1789
|
+
case "approval-requested":
|
|
1790
|
+
return `Tool ${name} needs approval`;
|
|
1791
|
+
case "output-error": {
|
|
1792
|
+
const detail = options.errorText?.trim();
|
|
1793
|
+
return detail ? `Tool ${name} failed: ${detail}` : `Tool ${name} failed`;
|
|
1794
|
+
}
|
|
1795
|
+
}
|
|
1796
|
+
}
|
|
1797
|
+
function useToolCall(options) {
|
|
1798
|
+
const [state, setState] = useControllableState(
|
|
1799
|
+
options?.state,
|
|
1800
|
+
options?.defaultState ?? "input-streaming",
|
|
1801
|
+
options?.onStateChange
|
|
1802
|
+
);
|
|
1803
|
+
const current = state ?? "input-streaming";
|
|
1804
|
+
const { onApprove, onDeny } = options ?? {};
|
|
1805
|
+
const approve = (0, import_react13.useCallback)(() => {
|
|
1806
|
+
if (current !== "approval-requested") return;
|
|
1807
|
+
setState("input-available");
|
|
1808
|
+
onApprove?.();
|
|
1809
|
+
}, [current, setState, onApprove]);
|
|
1810
|
+
const deny = (0, import_react13.useCallback)(() => {
|
|
1811
|
+
if (current !== "approval-requested") return;
|
|
1812
|
+
setState("output-denied");
|
|
1813
|
+
onDeny?.();
|
|
1814
|
+
}, [current, setState, onDeny]);
|
|
1815
|
+
return { state: current, approve, deny };
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
// src/typeahead.ts
|
|
1819
|
+
function appendTypeaheadQuery(previous, char, now, timeout = 500) {
|
|
1820
|
+
if (char.length !== 1) return previous ?? { text: "", at: now };
|
|
1821
|
+
if (!previous || now - previous.at > timeout) return { text: char, at: now };
|
|
1822
|
+
return { text: previous.text + char, at: now };
|
|
1823
|
+
}
|
|
1824
|
+
function isTypeaheadExpired(buffer, now, timeout = 500) {
|
|
1825
|
+
if (!buffer || buffer.text === "") return true;
|
|
1826
|
+
return now - buffer.at > timeout;
|
|
1827
|
+
}
|
|
1828
|
+
function matchTypeaheadKey(items, query, fromKey) {
|
|
1829
|
+
const buffer = query.toLowerCase();
|
|
1830
|
+
if (buffer === "" || items.length === 0) return void 0;
|
|
1831
|
+
const first = buffer.charAt(0);
|
|
1832
|
+
const repeating = buffer.length > 1 && buffer.split("").every((char) => char === first);
|
|
1833
|
+
const needle = repeating ? first : buffer;
|
|
1834
|
+
const matches = (text) => text.toLowerCase().startsWith(needle);
|
|
1835
|
+
if (!repeating) {
|
|
1836
|
+
return items.find((item) => matches(item.text))?.key;
|
|
1837
|
+
}
|
|
1838
|
+
const from = fromKey === void 0 || fromKey === null ? -1 : items.findIndex((item) => item.key === fromKey);
|
|
1839
|
+
for (let step = 1; step <= items.length; step += 1) {
|
|
1840
|
+
const index = (from + step + items.length * 2) % items.length;
|
|
1841
|
+
const item = items[index];
|
|
1842
|
+
if (item && matches(item.text)) return item.key;
|
|
1843
|
+
}
|
|
1844
|
+
return void 0;
|
|
1845
|
+
}
|
|
1846
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
1847
|
+
0 && (module.exports = {
|
|
1848
|
+
addTimeMinutes,
|
|
1849
|
+
appendTypeaheadQuery,
|
|
1850
|
+
buildCalendarGrid,
|
|
1851
|
+
clampNumberValue,
|
|
1852
|
+
clampSliderValue,
|
|
1853
|
+
composeEventHandlers,
|
|
1854
|
+
createDismissPolicy,
|
|
1855
|
+
createIdScope,
|
|
1856
|
+
createOverlayModality,
|
|
1857
|
+
createPortalRegistry,
|
|
1858
|
+
createPresenceModel,
|
|
1859
|
+
createToastQueue,
|
|
1860
|
+
daysInCalendarMonth,
|
|
1861
|
+
defaultCollectionMatch,
|
|
1862
|
+
dismissBranchesFor,
|
|
1863
|
+
dismissTriggersFor,
|
|
1864
|
+
filterCollectionKeys,
|
|
1865
|
+
findCollectionText,
|
|
1866
|
+
formatNumberValue,
|
|
1867
|
+
formatTimeParts,
|
|
1868
|
+
formatTimeValue,
|
|
1869
|
+
getSharedOverlayModality,
|
|
1870
|
+
isAtBottom,
|
|
1871
|
+
isCalendarDateDisabled,
|
|
1872
|
+
isChatBusy,
|
|
1873
|
+
isChatError,
|
|
1874
|
+
isChatStreaming,
|
|
1875
|
+
isEmptyValue,
|
|
1876
|
+
isSelected,
|
|
1877
|
+
isToolCallApproval,
|
|
1878
|
+
isToolCallComplete,
|
|
1879
|
+
isToolCallError,
|
|
1880
|
+
isToolCallRunning,
|
|
1881
|
+
isTypeaheadExpired,
|
|
1882
|
+
isUserMessage,
|
|
1883
|
+
leadingBlankCount,
|
|
1884
|
+
matchTypeaheadKey,
|
|
1885
|
+
mergeFormErrors,
|
|
1886
|
+
mergeSlotProps,
|
|
1887
|
+
minutesForStep,
|
|
1888
|
+
nearestSliderThumbIndex,
|
|
1889
|
+
nextBranchIndex,
|
|
1890
|
+
nextPresenceState,
|
|
1891
|
+
nextTrapIndex,
|
|
1892
|
+
normalizeBranchIndex,
|
|
1893
|
+
normalizeChatSources,
|
|
1894
|
+
normalizeFieldErrors,
|
|
1895
|
+
normalizeSelection,
|
|
1896
|
+
normalizeSliderValues,
|
|
1897
|
+
normalizeTimeValue,
|
|
1898
|
+
parseCalendarDate,
|
|
1899
|
+
parseCalendarMonth,
|
|
1900
|
+
parseNumberValue,
|
|
1901
|
+
previousBranchIndex,
|
|
1902
|
+
resolveAutofocus,
|
|
1903
|
+
resolveCalendarFocus,
|
|
1904
|
+
resolveCalendarMonthNames,
|
|
1905
|
+
resolveCalendarSelection,
|
|
1906
|
+
resolveCalendarWeekdayNames,
|
|
1907
|
+
resolveCanSend,
|
|
1908
|
+
resolveChatMessageLabel,
|
|
1909
|
+
resolveChatMessageSpeaker,
|
|
1910
|
+
resolveChatSourceLabel,
|
|
1911
|
+
resolveComposerHeight,
|
|
1912
|
+
resolveDir,
|
|
1913
|
+
resolveFloatingRect,
|
|
1914
|
+
resolveFloatingSide,
|
|
1915
|
+
resolveLocaleFirstDay,
|
|
1916
|
+
resolvePortalTarget,
|
|
1917
|
+
resolveReasoningOpen,
|
|
1918
|
+
resolveRender,
|
|
1919
|
+
resolveScrollButtonVisible,
|
|
1920
|
+
resolveSliderCommit,
|
|
1921
|
+
resolveStyle,
|
|
1922
|
+
resolveToolCallLabel,
|
|
1923
|
+
shiftCalendarMonth,
|
|
1924
|
+
shouldCancelOnEscapeKey,
|
|
1925
|
+
shouldDismissOn,
|
|
1926
|
+
shouldHideBranchPicker,
|
|
1927
|
+
shouldSubmitOnKey,
|
|
1928
|
+
sliderRatioFromLocation,
|
|
1929
|
+
sliderValueFromRatio,
|
|
1930
|
+
sliderValuePercent,
|
|
1931
|
+
snapSliderValue,
|
|
1932
|
+
stepNumberValue,
|
|
1933
|
+
toCalendarDate,
|
|
1934
|
+
toCalendarMonth,
|
|
1935
|
+
toTwentyFourHour,
|
|
1936
|
+
toggleSelection,
|
|
1937
|
+
updateAttachment,
|
|
1938
|
+
useAttachments,
|
|
1939
|
+
useBranch,
|
|
1940
|
+
useCollectionRegistry,
|
|
1941
|
+
useControllableState,
|
|
1942
|
+
useOverlayModality,
|
|
1943
|
+
useOverlayRegistration,
|
|
1944
|
+
usePresence,
|
|
1945
|
+
usePress,
|
|
1946
|
+
usePromptInput,
|
|
1947
|
+
useRovingModel,
|
|
1948
|
+
useSelection,
|
|
1949
|
+
useStickToBottom,
|
|
1950
|
+
useToolCall,
|
|
1951
|
+
validateAttachment
|
|
1952
|
+
});
|