@assistant-ui/react-generative-ui 0.0.24 → 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/README.md +2 -0
- package/dist/a2ui.d.ts +1 -4
- package/dist/a2ui.d.ts.map +1 -1
- package/dist/a2ui.js +1 -4
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -10
- package/dist/index.server.d.ts +1 -2
- package/dist/index.server.d.ts.map +1 -1
- package/dist/index.server.js +1 -10
- package/dist/ir.d.ts +1 -111
- package/dist/ir.d.ts.map +1 -1
- package/dist/ir.js +1 -175
- package/dist/slack.d.ts +1 -4
- package/dist/slack.d.ts.map +1 -1
- package/dist/slack.js +1 -4
- package/dist/teams.d.ts +1 -4
- package/dist/teams.d.ts.map +1 -1
- package/dist/teams.js +1 -4
- package/package.json +4 -5
- package/src/a2ui.ts +1 -22
- package/src/index.server.ts +1 -2
- package/src/index.test.ts +75 -0
- package/src/index.ts +1 -2
- package/src/ir.ts +1 -279
- package/src/slack.ts +1 -39
- package/src/teams.ts +1 -35
- package/dist/JSONGenerativeUI.client.d.ts +0 -28
- package/dist/JSONGenerativeUI.client.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.client.js +0 -101
- package/dist/JSONGenerativeUI.client.js.map +0 -1
- package/dist/JSONGenerativeUI.server.d.ts +0 -21
- package/dist/JSONGenerativeUI.server.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.server.js +0 -32
- package/dist/JSONGenerativeUI.server.js.map +0 -1
- package/dist/JSONGenerativeUI.shared.d.ts +0 -63
- package/dist/JSONGenerativeUI.shared.d.ts.map +0 -1
- package/dist/JSONGenerativeUI.shared.js +0 -31
- package/dist/JSONGenerativeUI.shared.js.map +0 -1
- package/dist/RadioGroupScope.d.ts +0 -6
- package/dist/RadioGroupScope.d.ts.map +0 -1
- package/dist/RadioGroupScope.js +0 -25
- package/dist/RadioGroupScope.js.map +0 -1
- package/dist/a2ui/BindingContext.d.ts +0 -11
- package/dist/a2ui/BindingContext.d.ts.map +0 -1
- package/dist/a2ui/BindingContext.js +0 -12
- package/dist/a2ui/BindingContext.js.map +0 -1
- package/dist/a2ui/PresentRenderer.d.ts +0 -11
- package/dist/a2ui/PresentRenderer.d.ts.map +0 -1
- package/dist/a2ui/PresentRenderer.js +0 -39
- package/dist/a2ui/PresentRenderer.js.map +0 -1
- package/dist/a2ui/convert.d.ts +0 -15
- package/dist/a2ui/convert.d.ts.map +0 -1
- package/dist/a2ui/convert.js +0 -728
- package/dist/a2ui/convert.js.map +0 -1
- package/dist/a2ui/dataModel.d.ts +0 -9
- package/dist/a2ui/dataModel.d.ts.map +0 -1
- package/dist/a2ui/dataModel.js +0 -44
- package/dist/a2ui/dataModel.js.map +0 -1
- package/dist/a2ui/reducer.d.ts +0 -8
- package/dist/a2ui/reducer.d.ts.map +0 -1
- package/dist/a2ui/reducer.js +0 -242
- package/dist/a2ui/reducer.js.map +0 -1
- package/dist/a2ui/snapshot.d.ts +0 -3
- package/dist/a2ui/snapshot.d.ts.map +0 -1
- package/dist/a2ui/snapshot.js +0 -33
- package/dist/a2ui/snapshot.js.map +0 -1
- package/dist/a2ui/types.d.ts +0 -88
- package/dist/a2ui/types.d.ts.map +0 -1
- package/dist/a2ui/types.js +0 -6
- package/dist/a2ui/types.js.map +0 -1
- package/dist/a2ui/valueFunctions.d.ts +0 -16
- package/dist/a2ui/valueFunctions.d.ts.map +0 -1
- package/dist/a2ui/valueFunctions.js +0 -332
- package/dist/a2ui/valueFunctions.js.map +0 -1
- package/dist/actionRegistry.d.ts +0 -29
- package/dist/actionRegistry.d.ts.map +0 -1
- package/dist/actionRegistry.js +0 -41
- package/dist/actionRegistry.js.map +0 -1
- package/dist/answeredValues.d.ts +0 -16
- package/dist/answeredValues.d.ts.map +0 -1
- package/dist/answeredValues.js +0 -37
- package/dist/answeredValues.js.map +0 -1
- package/dist/buildPresentParameters.d.ts +0 -21
- package/dist/buildPresentParameters.d.ts.map +0 -1
- package/dist/buildPresentParameters.js +0 -95
- package/dist/buildPresentParameters.js.map +0 -1
- package/dist/constants.d.ts +0 -15
- package/dist/constants.d.ts.map +0 -1
- package/dist/constants.js +0 -19
- package/dist/constants.js.map +0 -1
- package/dist/convert/boundSpec.d.ts +0 -48
- package/dist/convert/boundSpec.d.ts.map +0 -1
- package/dist/convert/boundSpec.js +0 -108
- package/dist/convert/boundSpec.js.map +0 -1
- package/dist/convert/copyBounded.d.ts +0 -25
- package/dist/convert/copyBounded.d.ts.map +0 -1
- package/dist/convert/copyBounded.js +0 -38
- package/dist/convert/copyBounded.js.map +0 -1
- package/dist/convert/isElement.d.ts +0 -3
- package/dist/convert/isElement.d.ts.map +0 -1
- package/dist/convert/isElement.js +0 -6
- package/dist/convert/isElement.js.map +0 -1
- package/dist/convert/takeRun.d.ts +0 -6
- package/dist/convert/takeRun.d.ts.map +0 -1
- package/dist/convert/takeRun.js +0 -20
- package/dist/convert/takeRun.js.map +0 -1
- package/dist/defineGenerativeComponents.d.ts +0 -29
- package/dist/defineGenerativeComponents.d.ts.map +0 -1
- package/dist/defineGenerativeComponents.js +0 -34
- package/dist/defineGenerativeComponents.js.map +0 -1
- package/dist/fieldReferences.d.ts +0 -9
- package/dist/fieldReferences.d.ts.map +0 -1
- package/dist/fieldReferences.js +0 -53
- package/dist/fieldReferences.js.map +0 -1
- package/dist/generativeUIToJSX.d.ts +0 -18
- package/dist/generativeUIToJSX.d.ts.map +0 -1
- package/dist/generativeUIToJSX.js +0 -76
- package/dist/generativeUIToJSX.js.map +0 -1
- package/dist/index.shared.d.ts +0 -15
- package/dist/index.shared.d.ts.map +0 -1
- package/dist/index.shared.js +0 -9
- package/dist/ir.js.map +0 -1
- package/dist/renderGenerativeUI.d.ts +0 -14
- package/dist/renderGenerativeUI.d.ts.map +0 -1
- package/dist/renderGenerativeUI.js +0 -83
- package/dist/renderGenerativeUI.js.map +0 -1
- package/dist/scopeSchema.d.ts +0 -6
- package/dist/scopeSchema.d.ts.map +0 -1
- package/dist/scopeSchema.js +0 -56
- package/dist/scopeSchema.js.map +0 -1
- package/dist/slack/constants.d.ts +0 -93
- package/dist/slack/constants.d.ts.map +0 -1
- package/dist/slack/constants.js +0 -146
- package/dist/slack/constants.js.map +0 -1
- package/dist/slack/decodeBlockAction.d.ts +0 -10
- package/dist/slack/decodeBlockAction.d.ts.map +0 -1
- package/dist/slack/decodeBlockAction.js +0 -129
- package/dist/slack/decodeBlockAction.js.map +0 -1
- package/dist/slack/fromSlackBlocks.d.ts +0 -27
- package/dist/slack/fromSlackBlocks.d.ts.map +0 -1
- package/dist/slack/fromSlackBlocks.js +0 -483
- package/dist/slack/fromSlackBlocks.js.map +0 -1
- package/dist/slack/toSlackBlocks.d.ts +0 -4
- package/dist/slack/toSlackBlocks.d.ts.map +0 -1
- package/dist/slack/toSlackBlocks.js +0 -901
- package/dist/slack/toSlackBlocks.js.map +0 -1
- package/dist/slack/types.d.ts +0 -204
- package/dist/slack/types.d.ts.map +0 -1
- package/dist/slack/types.js +0 -0
- package/dist/teams/constants.d.ts +0 -34
- package/dist/teams/constants.d.ts.map +0 -1
- package/dist/teams/constants.js +0 -68
- package/dist/teams/constants.js.map +0 -1
- package/dist/teams/decodeSubmitData.d.ts +0 -26
- package/dist/teams/decodeSubmitData.d.ts.map +0 -1
- package/dist/teams/decodeSubmitData.js +0 -70
- package/dist/teams/decodeSubmitData.js.map +0 -1
- package/dist/teams/temporalId.d.ts +0 -5
- package/dist/teams/temporalId.d.ts.map +0 -1
- package/dist/teams/temporalId.js +0 -28
- package/dist/teams/temporalId.js.map +0 -1
- package/dist/teams/toAdaptiveCard.d.ts +0 -45
- package/dist/teams/toAdaptiveCard.d.ts.map +0 -1
- package/dist/teams/toAdaptiveCard.js +0 -642
- package/dist/teams/toAdaptiveCard.js.map +0 -1
- package/dist/teams/toTeamsAttachments.d.ts +0 -10
- package/dist/teams/toTeamsAttachments.d.ts.map +0 -1
- package/dist/teams/toTeamsAttachments.js +0 -99
- package/dist/teams/toTeamsAttachments.js.map +0 -1
- package/dist/teams/types.d.ts +0 -224
- package/dist/teams/types.d.ts.map +0 -1
- package/dist/teams/types.js +0 -0
- package/dist/temporal.d.ts +0 -33
- package/dist/temporal.d.ts.map +0 -1
- package/dist/temporal.js +0 -153
- package/dist/temporal.js.map +0 -1
- package/dist/types.d.ts +0 -99
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -0
- package/dist/vocabulary/alert.d.ts +0 -32
- package/dist/vocabulary/alert.d.ts.map +0 -1
- package/dist/vocabulary/alert.js +0 -160
- package/dist/vocabulary/alert.js.map +0 -1
- package/dist/vocabulary/collectFormValues.d.ts +0 -23
- package/dist/vocabulary/collectFormValues.d.ts.map +0 -1
- package/dist/vocabulary/collectFormValues.js +0 -44
- package/dist/vocabulary/collectFormValues.js.map +0 -1
- package/dist/vocabulary/data.d.ts +0 -66
- package/dist/vocabulary/data.d.ts.map +0 -1
- package/dist/vocabulary/data.js +0 -503
- package/dist/vocabulary/data.js.map +0 -1
- package/dist/vocabulary/dispatch.d.ts +0 -9
- package/dist/vocabulary/dispatch.d.ts.map +0 -1
- package/dist/vocabulary/dispatch.js +0 -50
- package/dist/vocabulary/dispatch.js.map +0 -1
- package/dist/vocabulary/fact.d.ts +0 -19
- package/dist/vocabulary/fact.d.ts.map +0 -1
- package/dist/vocabulary/fact.js +0 -51
- package/dist/vocabulary/fact.js.map +0 -1
- package/dist/vocabulary/form.d.ts +0 -11
- package/dist/vocabulary/form.d.ts.map +0 -1
- package/dist/vocabulary/form.js +0 -23
- package/dist/vocabulary/form.js.map +0 -1
- package/dist/vocabulary/formatValue.d.ts +0 -7
- package/dist/vocabulary/formatValue.d.ts.map +0 -1
- package/dist/vocabulary/formatValue.js +0 -76
- package/dist/vocabulary/formatValue.js.map +0 -1
- package/dist/vocabulary/icon.d.ts +0 -41
- package/dist/vocabulary/icon.d.ts.map +0 -1
- package/dist/vocabulary/icon.js +0 -272
- package/dist/vocabulary/icon.js.map +0 -1
- package/dist/vocabulary/index.d.ts +0 -12
- package/dist/vocabulary/index.d.ts.map +0 -1
- package/dist/vocabulary/index.js +0 -36
- package/dist/vocabulary/index.js.map +0 -1
- package/dist/vocabulary/interactive.d.ts +0 -230
- package/dist/vocabulary/interactive.d.ts.map +0 -1
- package/dist/vocabulary/interactive.js +0 -584
- package/dist/vocabulary/interactive.js.map +0 -1
- package/dist/vocabulary/layout.d.ts +0 -79
- package/dist/vocabulary/layout.d.ts.map +0 -1
- package/dist/vocabulary/layout.js +0 -139
- package/dist/vocabulary/layout.js.map +0 -1
- package/dist/vocabulary/list.d.ts +0 -14
- package/dist/vocabulary/list.d.ts.map +0 -1
- package/dist/vocabulary/list.js +0 -50
- package/dist/vocabulary/list.js.map +0 -1
- package/dist/vocabulary/media.d.ts +0 -25
- package/dist/vocabulary/media.d.ts.map +0 -1
- package/dist/vocabulary/media.js +0 -42
- package/dist/vocabulary/media.js.map +0 -1
- package/dist/vocabulary/text.d.ts +0 -57
- package/dist/vocabulary/text.d.ts.map +0 -1
- package/dist/vocabulary/text.js +0 -49
- package/dist/vocabulary/text.js.map +0 -1
- package/dist/vocabulary/toTextContent.d.ts +0 -2
- package/dist/vocabulary/toTextContent.d.ts.map +0 -1
- package/dist/vocabulary/toTextContent.js +0 -6
- package/dist/vocabulary/toTextContent.js.map +0 -1
- package/src/JSONGenerativeUI.client.tsx +0 -168
- package/src/JSONGenerativeUI.server.tsx +0 -39
- package/src/JSONGenerativeUI.shared.ts +0 -90
- package/src/JSONGenerativeUI.test.tsx +0 -1298
- package/src/RadioGroupScope.server.test.tsx +0 -24
- package/src/RadioGroupScope.tsx +0 -34
- package/src/a2ui/BindingContext.ts +0 -26
- package/src/a2ui/PresentRenderer.tsx +0 -83
- package/src/a2ui/convert.test.ts +0 -2923
- package/src/a2ui/convert.ts +0 -1207
- package/src/a2ui/dataModel.ts +0 -69
- package/src/a2ui/reducer.test.ts +0 -422
- package/src/a2ui/reducer.ts +0 -363
- package/src/a2ui/snapshot.test.ts +0 -52
- package/src/a2ui/snapshot.ts +0 -52
- package/src/a2ui/types.ts +0 -114
- package/src/a2ui/valueFunctions.test.ts +0 -271
- package/src/a2ui/valueFunctions.ts +0 -523
- package/src/actionRegistry.test.ts +0 -90
- package/src/actionRegistry.ts +0 -88
- package/src/answeredValues.test.ts +0 -33
- package/src/answeredValues.tsx +0 -70
- package/src/buildPresentParameters.test.ts +0 -246
- package/src/buildPresentParameters.ts +0 -130
- package/src/constants.ts +0 -17
- package/src/convert/boundSpec.test.ts +0 -192
- package/src/convert/boundSpec.ts +0 -134
- package/src/convert/copyBounded.test.ts +0 -131
- package/src/convert/copyBounded.ts +0 -38
- package/src/convert/isElement.ts +0 -6
- package/src/convert/takeRun.test.ts +0 -64
- package/src/convert/takeRun.ts +0 -19
- package/src/defineGenerativeComponents.ts +0 -38
- package/src/fieldReferences.test.ts +0 -66
- package/src/fieldReferences.ts +0 -83
- package/src/generativeUIToJSX.test.ts +0 -268
- package/src/generativeUIToJSX.ts +0 -152
- package/src/index.server.test.ts +0 -106
- package/src/index.shared.ts +0 -61
- package/src/ir.test.ts +0 -203
- package/src/renderGenerativeUI.test.tsx +0 -373
- package/src/renderGenerativeUI.tsx +0 -165
- package/src/scopeSchema.test.ts +0 -72
- package/src/scopeSchema.ts +0 -71
- package/src/slack/a2uiSlack.test.ts +0 -198
- package/src/slack/constants.ts +0 -194
- package/src/slack/datePicker.test.ts +0 -612
- package/src/slack/decodeBlockAction.test.ts +0 -233
- package/src/slack/decodeBlockAction.ts +0 -232
- package/src/slack/fromSlackBlocks.test.ts +0 -1465
- package/src/slack/fromSlackBlocks.ts +0 -789
- package/src/slack/toSlackBlocks.test.ts +0 -3065
- package/src/slack/toSlackBlocks.ts +0 -1818
- package/src/slack/types.ts +0 -264
- package/src/teams/constants.ts +0 -93
- package/src/teams/decodeSubmitData.test.ts +0 -397
- package/src/teams/decodeSubmitData.ts +0 -110
- package/src/teams/temporal.test.ts +0 -766
- package/src/teams/temporalId.ts +0 -56
- package/src/teams/toAdaptiveCard.test.ts +0 -1897
- package/src/teams/toAdaptiveCard.ts +0 -1057
- package/src/teams/toTeamsAttachments.test.ts +0 -74
- package/src/teams/toTeamsAttachments.ts +0 -133
- package/src/teams/types.ts +0 -266
- package/src/temporal.test.ts +0 -337
- package/src/temporal.ts +0 -263
- package/src/types.ts +0 -119
- package/src/vocabulary/alert.test.tsx +0 -427
- package/src/vocabulary/alert.tsx +0 -217
- package/src/vocabulary/collectFormValues.test.ts +0 -389
- package/src/vocabulary/collectFormValues.ts +0 -116
- package/src/vocabulary/data.test.tsx +0 -858
- package/src/vocabulary/data.tsx +0 -819
- package/src/vocabulary/datepicker.dom.test.tsx +0 -1457
- package/src/vocabulary/dispatch.ts +0 -83
- package/src/vocabulary/fact.test.tsx +0 -94
- package/src/vocabulary/fact.tsx +0 -54
- package/src/vocabulary/form.test.tsx +0 -113
- package/src/vocabulary/form.tsx +0 -39
- package/src/vocabulary/formatValue.test.ts +0 -72
- package/src/vocabulary/formatValue.ts +0 -127
- package/src/vocabulary/icon.test.tsx +0 -64
- package/src/vocabulary/icon.tsx +0 -174
- package/src/vocabulary/index.test.ts +0 -65
- package/src/vocabulary/index.ts +0 -33
- package/src/vocabulary/interactive.dispatch.test.tsx +0 -454
- package/src/vocabulary/interactive.dom.test.tsx +0 -1747
- package/src/vocabulary/interactive.test.tsx +0 -377
- package/src/vocabulary/interactive.tsx +0 -1109
- package/src/vocabulary/layout.test.tsx +0 -323
- package/src/vocabulary/layout.tsx +0 -247
- package/src/vocabulary/list.test.tsx +0 -222
- package/src/vocabulary/list.tsx +0 -50
- package/src/vocabulary/media.test.tsx +0 -85
- package/src/vocabulary/media.tsx +0 -56
- package/src/vocabulary/text.test.tsx +0 -102
- package/src/vocabulary/text.tsx +0 -60
- package/src/vocabulary/toTextContent.ts +0 -2
package/dist/temporal.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
//#region src/temporal.ts
|
|
2
|
-
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
|
|
3
|
-
const TIME_PATTERN = /^([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d)(?:\.(\d{1,9}))?)?$/;
|
|
4
|
-
const DATETIME_PATTERN = /^(\d{4}-\d{2}-\d{2})T([01]\d|2[0-3]):([0-5]\d)(?::([0-5]\d)(?:\.(\d+))?)?(Z|[+-](?:[01]\d|2[0-3]):[0-5]\d)?$/;
|
|
5
|
-
const INPUT_PATTERN = /^((?:\d{4}-\d{2}-\d{2}T)?(?:[01]\d|2[0-3]):[0-5]\d)(?::([0-5]\d)(?:\.(\d{1,9}))?)?$/;
|
|
6
|
-
const normalizeTemporalInputValue = (value) => {
|
|
7
|
-
const match = INPUT_PATTERN.exec(value);
|
|
8
|
-
if (!match || match[2] === void 0) return value;
|
|
9
|
-
const digits = match[3]?.slice(0, 3) ?? "";
|
|
10
|
-
let end = digits.length;
|
|
11
|
-
while (end > 0 && digits[end - 1] === "0") end--;
|
|
12
|
-
const fraction = digits.slice(0, end);
|
|
13
|
-
if (match[2] === "00" && !fraction) return match[1];
|
|
14
|
-
return `${match[1]}:${match[2]}${fraction ? `.${fraction}` : ""}`;
|
|
15
|
-
};
|
|
16
|
-
const isCalendarDate = (value) => {
|
|
17
|
-
const date = /* @__PURE__ */ new Date(`${value}T00:00:00Z`);
|
|
18
|
-
return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value;
|
|
19
|
-
};
|
|
20
|
-
const classifyTemporal = (value) => {
|
|
21
|
-
if (DATE_PATTERN.test(value) && isCalendarDate(value)) return {
|
|
22
|
-
kind: "date",
|
|
23
|
-
value
|
|
24
|
-
};
|
|
25
|
-
const time = TIME_PATTERN.exec(value);
|
|
26
|
-
if (time) return {
|
|
27
|
-
kind: "time",
|
|
28
|
-
value,
|
|
29
|
-
precision: time[4]?.length ?? (time[3] === void 0 ? "minutes" : "seconds")
|
|
30
|
-
};
|
|
31
|
-
const datetime = DATETIME_PATTERN.exec(value);
|
|
32
|
-
if (!datetime || !isCalendarDate(datetime[1])) return {
|
|
33
|
-
kind: "unparseable",
|
|
34
|
-
value
|
|
35
|
-
};
|
|
36
|
-
const precision = datetime[5]?.length ?? (datetime[4] === void 0 ? "minutes" : "seconds");
|
|
37
|
-
const offset = datetime[6];
|
|
38
|
-
if (offset === void 0) return {
|
|
39
|
-
kind: "floating",
|
|
40
|
-
value,
|
|
41
|
-
precision
|
|
42
|
-
};
|
|
43
|
-
return {
|
|
44
|
-
kind: "instant",
|
|
45
|
-
epochMs: Date.parse(value),
|
|
46
|
-
offset,
|
|
47
|
-
precision,
|
|
48
|
-
...datetime[5] && datetime[5].length > 3 ? { subMillisecondDigits: datetime[5].slice(3) } : {}
|
|
49
|
-
};
|
|
50
|
-
};
|
|
51
|
-
const getTemporalInputStep = (...values) => {
|
|
52
|
-
let step;
|
|
53
|
-
for (const value of values) {
|
|
54
|
-
const temporal = classifyTemporal(value ?? "");
|
|
55
|
-
const precision = "precision" in temporal ? temporal.precision : INPUT_PATTERN.exec(value ?? "")?.[3]?.length;
|
|
56
|
-
if (typeof precision === "number") return "any";
|
|
57
|
-
if (precision === "seconds") step = 1;
|
|
58
|
-
}
|
|
59
|
-
return step;
|
|
60
|
-
};
|
|
61
|
-
const splitTemporalMinutes = (value, offset) => {
|
|
62
|
-
const temporal = classifyTemporal(value);
|
|
63
|
-
if (temporal.kind === "date" || temporal.kind === "unparseable") return void 0;
|
|
64
|
-
const wallTime = temporal.kind === "instant" ? formatTemporalInstant(temporal, offset).slice(0, -(offset ?? temporal.offset).length) : temporal.value;
|
|
65
|
-
const end = temporal.kind === "time" ? 5 : 16;
|
|
66
|
-
return {
|
|
67
|
-
...temporal.kind === "time" ? {} : { date: wallTime.slice(0, 10) },
|
|
68
|
-
time: wallTime.slice(end - 5, end),
|
|
69
|
-
droppedPrecision: /[1-9]/.test(wallTime.slice(end))
|
|
70
|
-
};
|
|
71
|
-
};
|
|
72
|
-
const mergeTemporalMinutes = (date, time) => {
|
|
73
|
-
if (classifyTemporal(date).kind !== "date" || classifyTemporal(time).kind !== "time") return "";
|
|
74
|
-
return `${date}T${time.slice(0, 5)}`;
|
|
75
|
-
};
|
|
76
|
-
const pad = (value, digits = 2) => String(value).padStart(digits, "0");
|
|
77
|
-
const offsetMinutes = (offset) => offset === "Z" ? 0 : (offset.startsWith("-") ? -1 : 1) * (Number(offset.slice(1, 3)) * 60 + Number(offset.slice(4, 6)));
|
|
78
|
-
const formatTemporalInstant = (instant, offset = instant.offset, precision = instant.precision) => {
|
|
79
|
-
const date = new Date(instant.epochMs + offsetMinutes(offset) * 6e4);
|
|
80
|
-
const iso = date.toISOString();
|
|
81
|
-
return `${precision === "minutes" ? iso.slice(0, 16) : precision === "seconds" ? iso.slice(0, 19) : `${iso.slice(0, 19)}.${(pad(date.getUTCMilliseconds(), 3) + (instant.subMillisecondDigits ?? "")).padEnd(precision, "0").slice(0, precision)}`}${offset}`;
|
|
82
|
-
};
|
|
83
|
-
const formatTemporalUnixSeconds = (seconds, offset = "Z") => {
|
|
84
|
-
if (!Number.isInteger(seconds)) return void 0;
|
|
85
|
-
try {
|
|
86
|
-
const value = formatTemporalInstant({
|
|
87
|
-
kind: "instant",
|
|
88
|
-
epochMs: seconds * 1e3,
|
|
89
|
-
offset,
|
|
90
|
-
precision: "seconds"
|
|
91
|
-
});
|
|
92
|
-
return classifyTemporal(value).kind === "instant" ? value : void 0;
|
|
93
|
-
} catch {
|
|
94
|
-
return;
|
|
95
|
-
}
|
|
96
|
-
};
|
|
97
|
-
const temporalOffsetLabel = (value) => {
|
|
98
|
-
const temporal = classifyTemporal(value);
|
|
99
|
-
if (temporal.kind !== "instant") return void 0;
|
|
100
|
-
return temporal.offset === "Z" ? "UTC" : `UTC${temporal.offset}`;
|
|
101
|
-
};
|
|
102
|
-
const fromOffsetDateTime = (value, previousValue) => {
|
|
103
|
-
if (value === "") return "";
|
|
104
|
-
if (classifyTemporal(value).kind !== "floating") return value;
|
|
105
|
-
const previous = classifyTemporal(previousValue ?? "");
|
|
106
|
-
if (previous.kind !== "instant") return value;
|
|
107
|
-
const epochMs = Date.parse(`${value}${previous.offset}`);
|
|
108
|
-
const minuteRemainder = previous.precision === "minutes" ? 0 : (previous.epochMs % 6e4 + 6e4) % 6e4;
|
|
109
|
-
return formatTemporalInstant({
|
|
110
|
-
...previous,
|
|
111
|
-
epochMs: epochMs + minuteRemainder
|
|
112
|
-
});
|
|
113
|
-
};
|
|
114
|
-
const toLocalDateTime = (value, precision) => {
|
|
115
|
-
const temporal = classifyTemporal(value);
|
|
116
|
-
if (temporal.kind !== "instant") return value;
|
|
117
|
-
const date = new Date(temporal.epochMs);
|
|
118
|
-
const wallTime = `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;
|
|
119
|
-
return (precision ?? temporal.precision) === "minutes" ? wallTime : `${wallTime}:${pad(date.getSeconds())}${typeof precision === "number" ? formatTemporalInstant(temporal, "Z", precision).slice(19, -1) : ""}`;
|
|
120
|
-
};
|
|
121
|
-
const toPickerLocalDateTime = (value) => {
|
|
122
|
-
const temporal = classifyTemporal(value);
|
|
123
|
-
if (temporal.kind !== "instant") return normalizeTemporalInputValue(value);
|
|
124
|
-
const local = toLocalDateTime(value, typeof temporal.precision === "number" ? 3 : temporal.precision);
|
|
125
|
-
return typeof temporal.precision !== "number" || local.endsWith(".000") ? normalizeTemporalInputValue(local) : local;
|
|
126
|
-
};
|
|
127
|
-
const fromLocalDateTime = (value, previousValue) => {
|
|
128
|
-
const temporal = classifyTemporal(value);
|
|
129
|
-
const previous = classifyTemporal(previousValue ?? "");
|
|
130
|
-
if (temporal.kind !== "floating" || previous.kind === "floating") return value;
|
|
131
|
-
const date = new Date(value.replace(/\.(\d{1,2})$/, (_, digits) => `.${digits.padEnd(3, "0")}`));
|
|
132
|
-
const minutes = -date.getTimezoneOffset();
|
|
133
|
-
const offset = `${minutes < 0 ? "-" : "+"}${pad(Math.floor(Math.abs(minutes) / 60))}:${pad(Math.abs(minutes) % 60)}`;
|
|
134
|
-
if (previous.kind !== "instant") return formatTemporalInstant({
|
|
135
|
-
kind: "instant",
|
|
136
|
-
epochMs: date.getTime(),
|
|
137
|
-
offset,
|
|
138
|
-
precision: "seconds"
|
|
139
|
-
});
|
|
140
|
-
return formatTemporalInstant({
|
|
141
|
-
...previous,
|
|
142
|
-
epochMs: date.getTime(),
|
|
143
|
-
...previous.precision === "minutes" && (temporal.precision === "seconds" || date.getUTCSeconds() !== 0) ? { precision: "seconds" } : {},
|
|
144
|
-
...date.getMilliseconds() === new Date(previous.epochMs).getUTCMilliseconds() ? {} : typeof temporal.precision === "number" ? {
|
|
145
|
-
precision: Math.max(temporal.precision, typeof previous.precision === "number" ? previous.precision : 0),
|
|
146
|
-
subMillisecondDigits: value.slice(value.indexOf(".") + 4)
|
|
147
|
-
} : { subMillisecondDigits: "" }
|
|
148
|
-
});
|
|
149
|
-
};
|
|
150
|
-
//#endregion
|
|
151
|
-
export { classifyTemporal, formatTemporalInstant, formatTemporalUnixSeconds, fromLocalDateTime, fromOffsetDateTime, getTemporalInputStep, mergeTemporalMinutes, normalizeTemporalInputValue, splitTemporalMinutes, temporalOffsetLabel, toLocalDateTime, toPickerLocalDateTime };
|
|
152
|
-
|
|
153
|
-
//# sourceMappingURL=temporal.js.map
|
package/dist/temporal.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"temporal.js","names":[],"sources":["../src/temporal.ts"],"sourcesContent":["export type TemporalPrecision = \"minutes\" | \"seconds\" | number;\n\nexport type TemporalInstant = {\n kind: \"instant\";\n epochMs: number;\n offset: string;\n precision: TemporalPrecision;\n subMillisecondDigits?: string;\n};\n\nexport type TemporalValue =\n | { kind: \"date\" | \"unparseable\"; value: string }\n | {\n kind: \"time\" | \"floating\";\n value: string;\n precision: TemporalPrecision;\n }\n | TemporalInstant;\n\nconst DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}$/;\nconst TIME_PATTERN =\n /^([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d)(?:\\.(\\d{1,9}))?)?$/;\nconst DATETIME_PATTERN =\n /^(\\d{4}-\\d{2}-\\d{2})T([01]\\d|2[0-3]):([0-5]\\d)(?::([0-5]\\d)(?:\\.(\\d+))?)?(Z|[+-](?:[01]\\d|2[0-3]):[0-5]\\d)?$/;\nconst INPUT_PATTERN =\n /^((?:\\d{4}-\\d{2}-\\d{2}T)?(?:[01]\\d|2[0-3]):[0-5]\\d)(?::([0-5]\\d)(?:\\.(\\d{1,9}))?)?$/;\n\nexport const normalizeTemporalInputValue = (value: string): string => {\n const match = INPUT_PATTERN.exec(value);\n if (!match || match[2] === undefined) return value;\n const digits = match[3]?.slice(0, 3) ?? \"\";\n let end = digits.length;\n while (end > 0 && digits[end - 1] === \"0\") end--;\n const fraction = digits.slice(0, end);\n if (match[2] === \"00\" && !fraction) return match[1]!;\n return `${match[1]}:${match[2]}${fraction ? `.${fraction}` : \"\"}`;\n};\n\nconst isCalendarDate = (value: string): boolean => {\n const date = new Date(`${value}T00:00:00Z`);\n return (\n Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value\n );\n};\n\nexport const classifyTemporal = (value: string): TemporalValue => {\n if (DATE_PATTERN.test(value) && isCalendarDate(value)) {\n return { kind: \"date\", value };\n }\n const time = TIME_PATTERN.exec(value);\n if (time) {\n return {\n kind: \"time\",\n value,\n precision:\n time[4]?.length ?? (time[3] === undefined ? \"minutes\" : \"seconds\"),\n };\n }\n const datetime = DATETIME_PATTERN.exec(value);\n if (!datetime || !isCalendarDate(datetime[1]!)) {\n return { kind: \"unparseable\", value };\n }\n const precision =\n datetime[5]?.length ?? (datetime[4] === undefined ? \"minutes\" : \"seconds\");\n const offset = datetime[6];\n if (offset === undefined) return { kind: \"floating\", value, precision };\n return {\n kind: \"instant\",\n epochMs: Date.parse(value),\n offset,\n precision,\n ...(datetime[5] && datetime[5].length > 3\n ? { subMillisecondDigits: datetime[5].slice(3) }\n : {}),\n };\n};\n\nexport const getTemporalInputStep = (\n ...values: (string | undefined)[]\n): \"any\" | 1 | undefined => {\n let step: 1 | undefined;\n for (const value of values) {\n const temporal = classifyTemporal(value ?? \"\");\n const precision =\n \"precision\" in temporal\n ? temporal.precision\n : INPUT_PATTERN.exec(value ?? \"\")?.[3]?.length;\n if (typeof precision === \"number\") return \"any\";\n if (precision === \"seconds\") step = 1;\n }\n return step;\n};\n\nexport const splitTemporalMinutes = (\n value: string,\n offset?: string,\n): { date?: string; time: string; droppedPrecision: boolean } | undefined => {\n const temporal = classifyTemporal(value);\n if (temporal.kind === \"date\" || temporal.kind === \"unparseable\")\n return undefined;\n const wallTime =\n temporal.kind === \"instant\"\n ? formatTemporalInstant(temporal, offset).slice(\n 0,\n -(offset ?? temporal.offset).length,\n )\n : temporal.value;\n const end = temporal.kind === \"time\" ? 5 : 16;\n return {\n ...(temporal.kind === \"time\" ? {} : { date: wallTime.slice(0, 10) }),\n time: wallTime.slice(end - 5, end),\n droppedPrecision: /[1-9]/.test(wallTime.slice(end)),\n };\n};\n\nexport const mergeTemporalMinutes = (date: string, time: string): string => {\n if (\n classifyTemporal(date).kind !== \"date\" ||\n classifyTemporal(time).kind !== \"time\"\n )\n return \"\";\n return `${date}T${time.slice(0, 5)}`;\n};\n\nconst pad = (value: number, digits = 2): string =>\n String(value).padStart(digits, \"0\");\n\nconst offsetMinutes = (offset: string): number =>\n offset === \"Z\"\n ? 0\n : (offset.startsWith(\"-\") ? -1 : 1) *\n (Number(offset.slice(1, 3)) * 60 + Number(offset.slice(4, 6)));\n\nexport const formatTemporalInstant = (\n instant: TemporalInstant,\n offset = instant.offset,\n precision = instant.precision,\n): string => {\n const date = new Date(instant.epochMs + offsetMinutes(offset) * 60_000);\n const iso = date.toISOString();\n const wallTime =\n precision === \"minutes\"\n ? iso.slice(0, 16)\n : precision === \"seconds\"\n ? iso.slice(0, 19)\n : `${iso.slice(0, 19)}.${(pad(date.getUTCMilliseconds(), 3) + (instant.subMillisecondDigits ?? \"\")).padEnd(precision, \"0\").slice(0, precision)}`;\n return `${wallTime}${offset}`;\n};\n\nexport const formatTemporalUnixSeconds = (\n seconds: number,\n offset = \"Z\",\n): string | undefined => {\n if (!Number.isInteger(seconds)) return undefined;\n try {\n const value = formatTemporalInstant({\n kind: \"instant\",\n epochMs: seconds * 1000,\n offset,\n precision: \"seconds\",\n });\n return classifyTemporal(value).kind === \"instant\" ? value : undefined;\n } catch {\n return undefined;\n }\n};\n\nexport const temporalOffsetLabel = (value: string): string | undefined => {\n const temporal = classifyTemporal(value);\n if (temporal.kind !== \"instant\") return undefined;\n return temporal.offset === \"Z\" ? \"UTC\" : `UTC${temporal.offset}`;\n};\n\nexport const fromOffsetDateTime = (\n value: string,\n previousValue?: string,\n): string => {\n if (value === \"\") return \"\";\n if (classifyTemporal(value).kind !== \"floating\") return value;\n const previous = classifyTemporal(previousValue ?? \"\");\n if (previous.kind !== \"instant\") return value;\n const epochMs = Date.parse(`${value}${previous.offset}`);\n const minuteRemainder =\n previous.precision === \"minutes\"\n ? 0\n : ((previous.epochMs % 60_000) + 60_000) % 60_000;\n return formatTemporalInstant({\n ...previous,\n epochMs: epochMs + minuteRemainder,\n });\n};\n\nexport const toLocalDateTime = (\n value: string,\n precision?: TemporalPrecision,\n): string => {\n const temporal = classifyTemporal(value);\n if (temporal.kind !== \"instant\") return value;\n const date = new Date(temporal.epochMs);\n const wallTime = `${pad(date.getFullYear(), 4)}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;\n return (precision ?? temporal.precision) === \"minutes\"\n ? wallTime\n : `${wallTime}:${pad(date.getSeconds())}${typeof precision === \"number\" ? formatTemporalInstant(temporal, \"Z\", precision).slice(19, -1) : \"\"}`;\n};\n\nexport const toPickerLocalDateTime = (value: string): string => {\n const temporal = classifyTemporal(value);\n if (temporal.kind !== \"instant\") return normalizeTemporalInputValue(value);\n const local = toLocalDateTime(\n value,\n typeof temporal.precision === \"number\" ? 3 : temporal.precision,\n );\n return typeof temporal.precision !== \"number\" || local.endsWith(\".000\")\n ? normalizeTemporalInputValue(local)\n : local;\n};\n\nexport const fromLocalDateTime = (\n value: string,\n previousValue?: string,\n): string => {\n const temporal = classifyTemporal(value);\n const previous = classifyTemporal(previousValue ?? \"\");\n if (temporal.kind !== \"floating\" || previous.kind === \"floating\") {\n return value;\n }\n const date = new Date(\n value.replace(\n /\\.(\\d{1,2})$/,\n (_, digits: string) => `.${digits.padEnd(3, \"0\")}`,\n ),\n );\n const minutes = -date.getTimezoneOffset();\n const offset = `${minutes < 0 ? \"-\" : \"+\"}${pad(Math.floor(Math.abs(minutes) / 60))}:${pad(Math.abs(minutes) % 60)}`;\n if (previous.kind !== \"instant\") {\n return formatTemporalInstant({\n kind: \"instant\",\n epochMs: date.getTime(),\n offset,\n precision: \"seconds\",\n });\n }\n return formatTemporalInstant({\n ...previous,\n epochMs: date.getTime(),\n ...(previous.precision === \"minutes\" &&\n (temporal.precision === \"seconds\" || date.getUTCSeconds() !== 0)\n ? { precision: \"seconds\" }\n : {}),\n ...(date.getMilliseconds() ===\n new Date(previous.epochMs).getUTCMilliseconds()\n ? {}\n : typeof temporal.precision === \"number\"\n ? {\n precision: Math.max(\n temporal.precision,\n typeof previous.precision === \"number\" ? previous.precision : 0,\n ),\n subMillisecondDigits: value.slice(value.indexOf(\".\") + 4),\n }\n : { subMillisecondDigits: \"\" }),\n });\n};\n"],"mappings":"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"}
|
package/dist/types.d.ts
DELETED
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
import type { ReactNode } from "react";
|
|
2
|
-
import type { ZodType } from "zod";
|
|
3
|
-
import type { Action, NormalizedUIElement } from "./ir.js";
|
|
4
|
-
/**
|
|
5
|
-
* The canonical generative-ui element, normalized from the flat `$type` shape
|
|
6
|
-
* or the legacy `component` shape (see {@link normalizeUINode}). `children` is
|
|
7
|
-
* a reserved top-level key, not a prop, so it lives here rather than inside
|
|
8
|
-
* `props`. Alias of {@link NormalizedUIElement}; kept under its old name so the
|
|
9
|
-
* package's public surface stays append-only.
|
|
10
|
-
*/
|
|
11
|
-
export type GenerativeUIElement = NormalizedUIElement;
|
|
12
|
-
export type GenerativeUIProps = NormalizedUIElement["props"];
|
|
13
|
-
/**
|
|
14
|
-
* Anything renderable as generative UI — mirrors React's `ReactNode`: an
|
|
15
|
-
* element, primitive text, a list of nodes, or nothing. Widened beyond the
|
|
16
|
-
* model payload (a {@link GenerativeUIElement}) with the renderer's
|
|
17
|
-
* null/boolean/undefined inputs.
|
|
18
|
-
*/
|
|
19
|
-
export type GenerativeUINode = GenerativeUIElement | string | number | boolean | null | undefined | GenerativeUINode[];
|
|
20
|
-
export type GenerativeUIAction = Action;
|
|
21
|
-
/** Whether a node's props are still streaming in or have fully arrived. */
|
|
22
|
-
export type GenerativeUIStatus = "streaming" | "done";
|
|
23
|
-
/** The dispatcher an interactive component calls to fire its `$action`. */
|
|
24
|
-
export type GenerativeUIDispatch = (action: Action) => unknown;
|
|
25
|
-
/** The render context threaded through {@link renderGenerativeUI}. */
|
|
26
|
-
export type GenerativeUIRenderContext = {
|
|
27
|
-
/** Whether the tool call's arguments are still streaming or are complete. */
|
|
28
|
-
status: GenerativeUIStatus;
|
|
29
|
-
dispatch?: GenerativeUIDispatch;
|
|
30
|
-
};
|
|
31
|
-
/**
|
|
32
|
-
* Props a component's `render` receives: its model props, rendered `children`,
|
|
33
|
-
* and the injected framework keys. `$status` is the discriminant — when it is
|
|
34
|
-
* `"done"`, `P` is complete; while `"streaming"`, `P` is partial. `$action` is
|
|
35
|
-
* the node's behavior payload, present only on interactive nodes. `$dispatch`
|
|
36
|
-
* fires that payload through the host's {@link ActionRegistry}; it is present
|
|
37
|
-
* only when a registry was wired. All three are `$`-prefixed so they never
|
|
38
|
-
* collide with a real `status`/`action`/`dispatch` prop.
|
|
39
|
-
*/
|
|
40
|
-
type StreamingRenderProps<P> = (Partial<P> & {
|
|
41
|
-
children?: ReactNode;
|
|
42
|
-
$status: "streaming";
|
|
43
|
-
$action?: Action;
|
|
44
|
-
$dispatch?: GenerativeUIDispatch;
|
|
45
|
-
}) | (P & {
|
|
46
|
-
children?: ReactNode;
|
|
47
|
-
$status: "done";
|
|
48
|
-
$action?: Action;
|
|
49
|
-
$dispatch?: GenerativeUIDispatch;
|
|
50
|
-
});
|
|
51
|
-
/** Props for a component that only renders once complete — `$status` is always `"done"`. */
|
|
52
|
-
type StaticRenderProps<P> = P & {
|
|
53
|
-
children?: ReactNode;
|
|
54
|
-
$status: "done";
|
|
55
|
-
$action?: Action;
|
|
56
|
-
$dispatch?: GenerativeUIDispatch;
|
|
57
|
-
};
|
|
58
|
-
/**
|
|
59
|
-
* A component the model is allowed to render, with the schema for its props.
|
|
60
|
-
*
|
|
61
|
-
* Components opt into prop streaming with `streamProperties`: they render as
|
|
62
|
-
* props arrive, so `render` sees `Partial<P>` while `$status` is `"streaming"`
|
|
63
|
-
* and the full `P` once it is `"done"`. By default a component opts out and is
|
|
64
|
-
* only rendered once its props are complete.
|
|
65
|
-
*
|
|
66
|
-
* `render` is a function of `props`, not a React component. Direct hook use is
|
|
67
|
-
* fine (each node is mounted on its own fiber), but a given node must keep its
|
|
68
|
-
* `type` across renders for hook identity to be stable.
|
|
69
|
-
*/
|
|
70
|
-
export type GenerativeUIComponent<P = any> = {
|
|
71
|
-
/** Natural-language description shown to the model when selecting the component. */
|
|
72
|
-
description: string;
|
|
73
|
-
/** Schema for the props the model must provide. Drives the tool parameters. */
|
|
74
|
-
properties: ZodType<P>;
|
|
75
|
-
/**
|
|
76
|
-
* Render from partially-streamed props. Widened to `boolean | undefined`
|
|
77
|
-
* so a non-literal value (e.g. a variable) still resolves to this branch
|
|
78
|
-
* cleanly rather than matching neither; the strict `false | undefined`
|
|
79
|
-
* branch below is the only one that promises complete props.
|
|
80
|
-
*/
|
|
81
|
-
streamProperties: boolean | undefined;
|
|
82
|
-
render: (props: StreamingRenderProps<P>) => ReactNode;
|
|
83
|
-
} | {
|
|
84
|
-
description: string;
|
|
85
|
-
properties: ZodType<P>;
|
|
86
|
-
/** Render only once props are complete (the default). */
|
|
87
|
-
streamProperties?: false | undefined;
|
|
88
|
-
render: (props: StaticRenderProps<P>) => ReactNode;
|
|
89
|
-
};
|
|
90
|
-
/**
|
|
91
|
-
* The consumer-provided allowlist of components the model is permitted to
|
|
92
|
-
* render. Keys are the `type` values referenced in the generative-ui tree
|
|
93
|
-
* (e.g. `"Card"`, `"Button"`); values describe each component.
|
|
94
|
-
*
|
|
95
|
-
* This registry is the security boundary — any `type` not present is rejected.
|
|
96
|
-
*/
|
|
97
|
-
export type GenerativeUILibrary = Record<string, GenerativeUIComponent>;
|
|
98
|
-
export {};
|
|
99
|
-
//# sourceMappingURL=types.d.ts.map
|
package/dist/types.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,KAAK,CAAC;AACnC,OAAO,KAAK,EAAE,MAAM,EAAE,mBAAmB,EAAE,gBAAa;AAExD;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD,MAAM,MAAM,iBAAiB,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAE7D;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GACxB,mBAAmB,GACnB,MAAM,GACN,MAAM,GACN,OAAO,GACP,IAAI,GACJ,SAAS,GACT,gBAAgB,EAAE,CAAC;AAEvB,MAAM,MAAM,kBAAkB,GAAG,MAAM,CAAC;AAExC,2EAA2E;AAC3E,MAAM,MAAM,kBAAkB,GAAG,WAAW,GAAG,MAAM,CAAC;AAEtD,2EAA2E;AAC3E,MAAM,MAAM,oBAAoB,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC;AAE/D,sEAAsE;AACtE,MAAM,MAAM,yBAAyB,GAAG;IACtC,6EAA6E;IAC7E,MAAM,EAAE,kBAAkB,CAAC;IAC3B,QAAQ,CAAC,EAAE,oBAAoB,CAAC;CACjC,CAAC;AAEF;;;;;;;;GAQG;AACH,KAAK,oBAAoB,CAAC,CAAC,IACvB,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;IACZ,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,WAAW,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC,CAAC,GACF,CAAC,CAAC,GAAG;IACH,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC,CAAC,CAAC;AAEP,4FAA4F;AAC5F,KAAK,iBAAiB,CAAC,CAAC,IAAI,CAAC,GAAG;IAC9B,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,oBAAoB,CAAC;CAClC,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,GAAG,GAAG,IACrC;IACE,oFAAoF;IACpF,WAAW,EAAE,MAAM,CAAC;IACpB,+EAA+E;IAC/E,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB;;;;;OAKG;IACH,gBAAgB,EAAE,OAAO,GAAG,SAAS,CAAC;IACtC,MAAM,EAAE,CAAC,KAAK,EAAE,oBAAoB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;CACvD,GACD;IACE,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IACvB,yDAAyD;IACzD,gBAAgB,CAAC,EAAE,KAAK,GAAG,SAAS,CAAC;IACrC,MAAM,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC;CACpD,CAAC;AAEN;;;;;;GAMG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,CAAC,MAAM,EAAE,qBAAqB,CAAC,CAAC"}
|
package/dist/types.js
DELETED
|
File without changes
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
import { z } from "zod";
|
|
3
|
-
type CarouselRenderProps = {
|
|
4
|
-
label?: string;
|
|
5
|
-
children?: React.ReactNode;
|
|
6
|
-
};
|
|
7
|
-
declare function CarouselRender({ label, children }: CarouselRenderProps): React.JSX.Element;
|
|
8
|
-
export declare const alertVocabulary: {
|
|
9
|
-
Alert: {
|
|
10
|
-
description: string;
|
|
11
|
-
properties: z.ZodObject<{
|
|
12
|
-
title: z.ZodOptional<z.ZodString>;
|
|
13
|
-
description: z.ZodOptional<z.ZodString>;
|
|
14
|
-
tone: z.ZodOptional<z.ZodEnum<{
|
|
15
|
-
danger: "danger";
|
|
16
|
-
info: "info";
|
|
17
|
-
success: "success";
|
|
18
|
-
warning: "warning";
|
|
19
|
-
}>>;
|
|
20
|
-
}, z.core.$strip>;
|
|
21
|
-
render: ({ title, description, tone, children }: any) => React.JSX.Element;
|
|
22
|
-
};
|
|
23
|
-
Carousel: {
|
|
24
|
-
description: string;
|
|
25
|
-
properties: z.ZodObject<{
|
|
26
|
-
label: z.ZodOptional<z.ZodString>;
|
|
27
|
-
}, z.core.$strip>;
|
|
28
|
-
render: typeof CarouselRender;
|
|
29
|
-
};
|
|
30
|
-
};
|
|
31
|
-
export {};
|
|
32
|
-
//# sourceMappingURL=alert.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"alert.d.ts","sourceRoot":"","sources":["../../src/vocabulary/alert.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAOxB,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC5B,CAAC;AAQF,iBAAS,cAAc,CAAC,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,mBAAmB,qBAyJ/D;AAED,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;CA0CG,CAAC"}
|
package/dist/vocabulary/alert.js
DELETED
|
@@ -1,160 +0,0 @@
|
|
|
1
|
-
import { ALERT_TONES } from "../ir.js";
|
|
2
|
-
import { toTextContent } from "./toTextContent.js";
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
-
import { z } from "zod";
|
|
6
|
-
//#region src/vocabulary/alert.tsx
|
|
7
|
-
const MAX_CARDS = 10;
|
|
8
|
-
function CarouselRender({ label, children }) {
|
|
9
|
-
const carouselId = React.useId();
|
|
10
|
-
const carouselRef = React.useRef(null);
|
|
11
|
-
const [measurement, setMeasurement] = React.useState(void 0);
|
|
12
|
-
const cards = React.Children.toArray(children).slice(0, MAX_CARDS);
|
|
13
|
-
const n = cards.length;
|
|
14
|
-
React.useEffect(() => {
|
|
15
|
-
const carousel = carouselRef.current;
|
|
16
|
-
if (!carousel) return;
|
|
17
|
-
const measure = () => {
|
|
18
|
-
const maxScrollLeft = Math.max(carousel.scrollWidth - carousel.clientWidth, 0);
|
|
19
|
-
const position = Math.abs(carousel.scrollLeft);
|
|
20
|
-
const next = {
|
|
21
|
-
overflows: maxScrollLeft > 0,
|
|
22
|
-
atStart: position <= 1,
|
|
23
|
-
atEnd: position >= maxScrollLeft - 1
|
|
24
|
-
};
|
|
25
|
-
setMeasurement((current) => current?.overflows === next.overflows && current.atStart === next.atStart && current.atEnd === next.atEnd ? current : next);
|
|
26
|
-
};
|
|
27
|
-
measure();
|
|
28
|
-
carousel.addEventListener("scroll", measure, { passive: true });
|
|
29
|
-
window.addEventListener("resize", measure);
|
|
30
|
-
const resizeObserver = typeof ResizeObserver === "undefined" ? void 0 : new ResizeObserver(measure);
|
|
31
|
-
resizeObserver?.observe(carousel);
|
|
32
|
-
carousel.querySelectorAll(":scope > [data-aui=\"carousel-slide\"]").forEach((slide) => resizeObserver?.observe(slide));
|
|
33
|
-
return () => {
|
|
34
|
-
carousel.removeEventListener("scroll", measure);
|
|
35
|
-
window.removeEventListener("resize", measure);
|
|
36
|
-
resizeObserver?.disconnect();
|
|
37
|
-
};
|
|
38
|
-
}, [n]);
|
|
39
|
-
const move = (direction) => {
|
|
40
|
-
const carousel = carouselRef.current;
|
|
41
|
-
if (!carousel) return;
|
|
42
|
-
const rtl = getComputedStyle(carousel).direction === "rtl";
|
|
43
|
-
const startOf = (element) => {
|
|
44
|
-
const rect = element.getBoundingClientRect();
|
|
45
|
-
return rtl ? -rect.right : rect.left;
|
|
46
|
-
};
|
|
47
|
-
const edge = startOf(carousel);
|
|
48
|
-
const starts = Array.from(carousel.querySelectorAll(":scope > [data-aui=\"carousel-slide\"]"), startOf);
|
|
49
|
-
let current = 0;
|
|
50
|
-
starts.forEach((start, index) => {
|
|
51
|
-
if (Math.abs(start - edge) < Math.abs((starts[current] ?? start) - edge)) current = index;
|
|
52
|
-
});
|
|
53
|
-
const origin = starts[current];
|
|
54
|
-
const target = starts[current + (direction === "next" ? 1 : -1)];
|
|
55
|
-
if (origin === void 0 || target === void 0) return;
|
|
56
|
-
carousel.scrollBy({ left: rtl ? origin - target : target - origin });
|
|
57
|
-
};
|
|
58
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
59
|
-
"data-aui": "carousel-frame",
|
|
60
|
-
children: [/* @__PURE__ */ jsx("div", {
|
|
61
|
-
ref: carouselRef,
|
|
62
|
-
id: carouselId,
|
|
63
|
-
"data-aui": "carousel",
|
|
64
|
-
role: label ? "region" : "group",
|
|
65
|
-
"aria-roledescription": "carousel",
|
|
66
|
-
"aria-label": label,
|
|
67
|
-
tabIndex: 0,
|
|
68
|
-
children: cards.map((card, i) => /* @__PURE__ */ jsx("div", {
|
|
69
|
-
"data-aui": "carousel-slide",
|
|
70
|
-
role: "group",
|
|
71
|
-
"aria-roledescription": "slide",
|
|
72
|
-
"aria-label": `${i + 1} of ${n}`,
|
|
73
|
-
children: card
|
|
74
|
-
}, i))
|
|
75
|
-
}), measurement?.overflows ? /* @__PURE__ */ jsxs("div", {
|
|
76
|
-
"data-aui": "carousel-controls",
|
|
77
|
-
children: [/* @__PURE__ */ jsx("button", {
|
|
78
|
-
type: "button",
|
|
79
|
-
"data-aui": "carousel-prev",
|
|
80
|
-
"aria-label": "Previous slide",
|
|
81
|
-
"aria-controls": carouselId,
|
|
82
|
-
disabled: measurement.atStart,
|
|
83
|
-
onClick: () => move("previous"),
|
|
84
|
-
children: /* @__PURE__ */ jsx("svg", {
|
|
85
|
-
"aria-hidden": "true",
|
|
86
|
-
viewBox: "0 0 24 24",
|
|
87
|
-
width: "16",
|
|
88
|
-
height: "16",
|
|
89
|
-
fill: "none",
|
|
90
|
-
stroke: "currentColor",
|
|
91
|
-
strokeWidth: "2",
|
|
92
|
-
strokeLinecap: "round",
|
|
93
|
-
strokeLinejoin: "round",
|
|
94
|
-
children: /* @__PURE__ */ jsx("path", {
|
|
95
|
-
d: "M9 5l7 7-7 7",
|
|
96
|
-
transform: "translate(24 0) scale(-1 1)"
|
|
97
|
-
})
|
|
98
|
-
})
|
|
99
|
-
}), /* @__PURE__ */ jsx("button", {
|
|
100
|
-
type: "button",
|
|
101
|
-
"data-aui": "carousel-next",
|
|
102
|
-
"aria-label": "Next slide",
|
|
103
|
-
"aria-controls": carouselId,
|
|
104
|
-
disabled: measurement.atEnd,
|
|
105
|
-
onClick: () => move("next"),
|
|
106
|
-
children: /* @__PURE__ */ jsx("svg", {
|
|
107
|
-
"aria-hidden": "true",
|
|
108
|
-
viewBox: "0 0 24 24",
|
|
109
|
-
width: "16",
|
|
110
|
-
height: "16",
|
|
111
|
-
fill: "none",
|
|
112
|
-
stroke: "currentColor",
|
|
113
|
-
strokeWidth: "2",
|
|
114
|
-
strokeLinecap: "round",
|
|
115
|
-
strokeLinejoin: "round",
|
|
116
|
-
children: /* @__PURE__ */ jsx("path", { d: "M9 5l7 7-7 7" })
|
|
117
|
-
})
|
|
118
|
-
})]
|
|
119
|
-
}) : null]
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
const alertVocabulary = {
|
|
123
|
-
Alert: {
|
|
124
|
-
description: "A highlighted message conveying urgency. `tone` drives the severity.",
|
|
125
|
-
properties: z.object({
|
|
126
|
-
title: z.string().optional().describe("Alert title."),
|
|
127
|
-
description: z.string().optional().describe("Supporting description text."),
|
|
128
|
-
tone: z.enum(ALERT_TONES).optional().describe("Severity tone; defaults to `info`.")
|
|
129
|
-
}),
|
|
130
|
-
render: ({ title, description, tone, children }) => {
|
|
131
|
-
const alertTitle = toTextContent(title);
|
|
132
|
-
const alertDescription = toTextContent(description);
|
|
133
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
134
|
-
"data-aui": "alert",
|
|
135
|
-
"data-aui-tone": tone ?? "info",
|
|
136
|
-
role: "alert",
|
|
137
|
-
children: [
|
|
138
|
-
alertTitle ? /* @__PURE__ */ jsx("header", {
|
|
139
|
-
"data-aui": "alert-title",
|
|
140
|
-
children: alertTitle
|
|
141
|
-
}) : null,
|
|
142
|
-
alertDescription ? /* @__PURE__ */ jsx("p", {
|
|
143
|
-
"data-aui": "alert-desc",
|
|
144
|
-
children: alertDescription
|
|
145
|
-
}) : null,
|
|
146
|
-
children
|
|
147
|
-
]
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
},
|
|
151
|
-
Carousel: {
|
|
152
|
-
description: "A horizontally scrollable group of `Card` children (max 10). Set `label` for an accessible name.",
|
|
153
|
-
properties: z.object({ label: z.string().optional().describe("Accessible label for the carousel.") }),
|
|
154
|
-
render: CarouselRender
|
|
155
|
-
}
|
|
156
|
-
};
|
|
157
|
-
//#endregion
|
|
158
|
-
export { alertVocabulary };
|
|
159
|
-
|
|
160
|
-
//# sourceMappingURL=alert.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"alert.js","names":[],"sources":["../../src/vocabulary/alert.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { z } from \"zod\";\nimport type { GenerativeUILibrary } from \"../types\";\nimport { ALERT_TONES } from \"../ir\";\nimport { toTextContent } from \"./toTextContent\";\n\nconst MAX_CARDS = 10;\n\ntype CarouselRenderProps = {\n label?: string;\n children?: React.ReactNode;\n};\n\ntype CarouselMeasurement = {\n overflows: boolean;\n atStart: boolean;\n atEnd: boolean;\n};\n\nfunction CarouselRender({ label, children }: CarouselRenderProps) {\n const carouselId = React.useId();\n const carouselRef = React.useRef<HTMLDivElement>(null);\n const [measurement, setMeasurement] = React.useState<\n CarouselMeasurement | undefined\n >(undefined);\n const cards = React.Children.toArray(children).slice(0, MAX_CARDS);\n const n = cards.length;\n\n React.useEffect(() => {\n const carousel = carouselRef.current;\n if (!carousel) return;\n\n const measure = () => {\n const maxScrollLeft = Math.max(\n carousel.scrollWidth - carousel.clientWidth,\n 0,\n );\n const position = Math.abs(carousel.scrollLeft);\n const next = {\n overflows: maxScrollLeft > 0,\n atStart: position <= 1,\n atEnd: position >= maxScrollLeft - 1,\n };\n setMeasurement((current) =>\n current?.overflows === next.overflows &&\n current.atStart === next.atStart &&\n current.atEnd === next.atEnd\n ? current\n : next,\n );\n };\n\n measure();\n carousel.addEventListener(\"scroll\", measure, { passive: true });\n window.addEventListener(\"resize\", measure);\n const resizeObserver =\n typeof ResizeObserver === \"undefined\"\n ? undefined\n : new ResizeObserver(measure);\n resizeObserver?.observe(carousel);\n carousel\n .querySelectorAll(':scope > [data-aui=\"carousel-slide\"]')\n .forEach((slide) => resizeObserver?.observe(slide));\n\n return () => {\n carousel.removeEventListener(\"scroll\", measure);\n window.removeEventListener(\"resize\", measure);\n resizeObserver?.disconnect();\n };\n }, [n]);\n\n const move = (direction: \"previous\" | \"next\") => {\n const carousel = carouselRef.current;\n if (!carousel) return;\n\n const rtl = getComputedStyle(carousel).direction === \"rtl\";\n const startOf = (element: Element) => {\n const rect = element.getBoundingClientRect();\n return rtl ? -rect.right : rect.left;\n };\n const edge = startOf(carousel);\n const starts = Array.from(\n carousel.querySelectorAll(':scope > [data-aui=\"carousel-slide\"]'),\n startOf,\n );\n let current = 0;\n starts.forEach((start, index) => {\n if (\n Math.abs(start - edge) < Math.abs((starts[current] ?? start) - edge)\n ) {\n current = index;\n }\n });\n const origin = starts[current];\n const target = starts[current + (direction === \"next\" ? 1 : -1)];\n if (origin === undefined || target === undefined) return;\n carousel.scrollBy({ left: rtl ? origin - target : target - origin });\n };\n\n return (\n <div data-aui=\"carousel-frame\">\n <div\n ref={carouselRef}\n id={carouselId}\n data-aui=\"carousel\"\n role={label ? \"region\" : \"group\"}\n aria-roledescription=\"carousel\"\n aria-label={label}\n tabIndex={0}\n >\n {cards.map((card, i) => (\n <div\n key={i}\n data-aui=\"carousel-slide\"\n role=\"group\"\n aria-roledescription=\"slide\"\n aria-label={`${i + 1} of ${n}`}\n >\n {card}\n </div>\n ))}\n </div>\n {measurement?.overflows ? (\n <div data-aui=\"carousel-controls\">\n <button\n type=\"button\"\n data-aui=\"carousel-prev\"\n aria-label=\"Previous slide\"\n aria-controls={carouselId}\n disabled={measurement.atStart}\n onClick={() => move(\"previous\")}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M9 5l7 7-7 7\" transform=\"translate(24 0) scale(-1 1)\" />\n </svg>\n </button>\n <button\n type=\"button\"\n data-aui=\"carousel-next\"\n aria-label=\"Next slide\"\n aria-controls={carouselId}\n disabled={measurement.atEnd}\n onClick={() => move(\"next\")}\n >\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n width=\"16\"\n height=\"16\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n >\n <path d=\"M9 5l7 7-7 7\" />\n </svg>\n </button>\n </div>\n ) : null}\n </div>\n );\n}\n\nexport const alertVocabulary = {\n Alert: {\n description:\n \"A highlighted message conveying urgency. `tone` drives the severity.\",\n properties: z.object({\n title: z.string().optional().describe(\"Alert title.\"),\n description: z\n .string()\n .optional()\n .describe(\"Supporting description text.\"),\n tone: z\n .enum(ALERT_TONES)\n .optional()\n .describe(\"Severity tone; defaults to `info`.\"),\n }),\n render: ({ title, description, tone, children }) => {\n const alertTitle = toTextContent(title);\n const alertDescription = toTextContent(description);\n return (\n <div data-aui=\"alert\" data-aui-tone={tone ?? \"info\"} role=\"alert\">\n {alertTitle ? (\n <header data-aui=\"alert-title\">{alertTitle}</header>\n ) : null}\n {alertDescription ? (\n <p data-aui=\"alert-desc\">{alertDescription}</p>\n ) : null}\n {children}\n </div>\n );\n },\n },\n Carousel: {\n description:\n \"A horizontally scrollable group of `Card` children (max 10). Set `label` for an accessible name.\",\n properties: z.object({\n label: z\n .string()\n .optional()\n .describe(\"Accessible label for the carousel.\"),\n }),\n render: CarouselRender,\n },\n} satisfies GenerativeUILibrary;\n"],"mappings":"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"}
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import type { FormEvent } from "react";
|
|
2
|
-
/**
|
|
3
|
-
* The subset of `HTMLInputElement`/`HTMLSelectElement`/`HTMLTextAreaElement` that {@link collectFormValues} reads. A structural type rather than the DOM interfaces themselves, so a plain object can stand in for a form control in tests.
|
|
4
|
-
*/
|
|
5
|
-
export type FormControlElementLike = {
|
|
6
|
-
readonly name: string;
|
|
7
|
-
readonly type: string;
|
|
8
|
-
readonly value: string;
|
|
9
|
-
readonly checked?: boolean;
|
|
10
|
-
readonly disabled: boolean;
|
|
11
|
-
readonly hasAttribute: (name: string) => boolean;
|
|
12
|
-
readonly getAttribute?: ((name: string) => string | null) | undefined;
|
|
13
|
-
readonly matches?: ((selector: string) => boolean) | undefined;
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* Collects a submitted form's named control values into a plain object, keyed by `name`, in document order. Reads each control's live DOM state rather than `FormData`, so a checkbox resolves to its `checked` boolean instead of an on/off string. A radio group resolves to its checked option's `value`, or `undefined` if none is checked. A checkbox group resolves to its checked options' values in document order, or an empty array if none is checked. Any other repeated `name` resolves to an array of its controls' values, in document order. A time or datetime-local control's `data-aui-field-value` preserves the canonical string when its local projection is unchanged; an edited instant retains its original offset and precision. Controls without a `name`, that carry `data-aui-generated-name`, or that are effectively disabled, including through an ancestor disabled fieldset outside its first legend, are skipped entirely.
|
|
17
|
-
*/
|
|
18
|
-
export declare function collectFormValues(elements: ArrayLike<FormControlElementLike>): Record<string, unknown>;
|
|
19
|
-
/**
|
|
20
|
-
* Convenience wrapper around {@link collectFormValues} for a native form submit event; the cast from `HTMLFormControlsCollection` to `ArrayLike<FormControlElementLike>` lives here once instead of at every call site.
|
|
21
|
-
*/
|
|
22
|
-
export declare function collectFormValuesFromEvent(event: FormEvent<HTMLFormElement>): Record<string, unknown>;
|
|
23
|
-
//# sourceMappingURL=collectFormValues.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collectFormValues.d.ts","sourceRoot":"","sources":["../../src/vocabulary/collectFormValues.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAavC;;GAEG;AACH,MAAM,MAAM,sBAAsB,GAAG;IACnC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;IACjD,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;IACtE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;CAChE,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,SAAS,CAAC,sBAAsB,CAAC,GAC1C,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAuEzB;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CACxC,KAAK,EAAE,SAAS,CAAC,eAAe,CAAC,GAChC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAKzB"}
|
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
import { FIELD_VALUE_ATTR } from "../constants.js";
|
|
2
|
-
import { fromLocalDateTime, normalizeTemporalInputValue, toPickerLocalDateTime } from "../temporal.js";
|
|
3
|
-
//#region src/vocabulary/collectFormValues.ts
|
|
4
|
-
/**
|
|
5
|
-
* Collects a submitted form's named control values into a plain object, keyed by `name`, in document order. Reads each control's live DOM state rather than `FormData`, so a checkbox resolves to its `checked` boolean instead of an on/off string. A radio group resolves to its checked option's `value`, or `undefined` if none is checked. A checkbox group resolves to its checked options' values in document order, or an empty array if none is checked. Any other repeated `name` resolves to an array of its controls' values, in document order. A time or datetime-local control's `data-aui-field-value` preserves the canonical string when its local projection is unchanged; an edited instant retains its original offset and precision. Controls without a `name`, that carry `data-aui-generated-name`, or that are effectively disabled, including through an ancestor disabled fieldset outside its first legend, are skipped entirely.
|
|
6
|
-
*/
|
|
7
|
-
function collectFormValues(elements) {
|
|
8
|
-
const values = Object.create(null);
|
|
9
|
-
for (const element of Array.from(elements)) {
|
|
10
|
-
const { disabled } = element;
|
|
11
|
-
const name = element.getAttribute?.("data-aui-field-name") ?? element.name;
|
|
12
|
-
if (!name || disabled || element.hasAttribute("data-aui-generated-name") || element.matches?.(":disabled")) continue;
|
|
13
|
-
if (element.type === "radio") {
|
|
14
|
-
if (element.checked) values[name] = element.value;
|
|
15
|
-
else if (!Object.hasOwn(values, name)) values[name] = void 0;
|
|
16
|
-
continue;
|
|
17
|
-
}
|
|
18
|
-
if (element.type === "checkbox" && element.hasAttribute("data-aui-checkbox-group")) {
|
|
19
|
-
const existing = values[name];
|
|
20
|
-
const checked = Array.isArray(existing) ? existing : [];
|
|
21
|
-
values[name] = element.checked ? [...checked, element.value] : checked;
|
|
22
|
-
continue;
|
|
23
|
-
}
|
|
24
|
-
const temporalType = element.type === "datetime-local" || element.type === "time" ? element.type : element.getAttribute?.("type");
|
|
25
|
-
const inputValue = temporalType === "datetime-local" || temporalType === "time" ? normalizeTemporalInputValue(element.value) : element.value;
|
|
26
|
-
const fieldValue = temporalType === "datetime-local" || temporalType === "time" ? element.getAttribute?.(FIELD_VALUE_ATTR) : void 0;
|
|
27
|
-
const value = element.type === "checkbox" ? element.checked ?? false : element.type === "range" ? Number(element.value) : fieldValue && inputValue !== "" ? normalizeTemporalInputValue(inputValue) === normalizeTemporalInputValue(temporalType === "time" ? fieldValue : toPickerLocalDateTime(fieldValue)) ? fieldValue : temporalType === "datetime-local" ? fromLocalDateTime(inputValue, fieldValue) : inputValue : inputValue;
|
|
28
|
-
if (Object.hasOwn(values, name)) {
|
|
29
|
-
const existing = values[name];
|
|
30
|
-
values[name] = Array.isArray(existing) ? [...existing, value] : [existing, value];
|
|
31
|
-
} else values[name] = value;
|
|
32
|
-
}
|
|
33
|
-
return values;
|
|
34
|
-
}
|
|
35
|
-
/**
|
|
36
|
-
* Convenience wrapper around {@link collectFormValues} for a native form submit event; the cast from `HTMLFormControlsCollection` to `ArrayLike<FormControlElementLike>` lives here once instead of at every call site.
|
|
37
|
-
*/
|
|
38
|
-
function collectFormValuesFromEvent(event) {
|
|
39
|
-
return collectFormValues(event.currentTarget.elements);
|
|
40
|
-
}
|
|
41
|
-
//#endregion
|
|
42
|
-
export { collectFormValues, collectFormValuesFromEvent };
|
|
43
|
-
|
|
44
|
-
//# sourceMappingURL=collectFormValues.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"collectFormValues.js","names":[],"sources":["../../src/vocabulary/collectFormValues.ts"],"sourcesContent":["import type { FormEvent } from \"react\";\nimport {\n CHECKBOX_GROUP_ATTR,\n FIELD_NAME_ATTR,\n FIELD_VALUE_ATTR,\n GENERATED_NAME_ATTR,\n} from \"../constants\";\nimport {\n fromLocalDateTime,\n normalizeTemporalInputValue,\n toPickerLocalDateTime,\n} from \"../temporal\";\n\n/**\n * The subset of `HTMLInputElement`/`HTMLSelectElement`/`HTMLTextAreaElement` that {@link collectFormValues} reads. A structural type rather than the DOM interfaces themselves, so a plain object can stand in for a form control in tests.\n */\nexport type FormControlElementLike = {\n readonly name: string;\n readonly type: string;\n readonly value: string;\n readonly checked?: boolean;\n readonly disabled: boolean;\n readonly hasAttribute: (name: string) => boolean;\n readonly getAttribute?: ((name: string) => string | null) | undefined;\n readonly matches?: ((selector: string) => boolean) | undefined;\n};\n\n/**\n * Collects a submitted form's named control values into a plain object, keyed by `name`, in document order. Reads each control's live DOM state rather than `FormData`, so a checkbox resolves to its `checked` boolean instead of an on/off string. A radio group resolves to its checked option's `value`, or `undefined` if none is checked. A checkbox group resolves to its checked options' values in document order, or an empty array if none is checked. Any other repeated `name` resolves to an array of its controls' values, in document order. A time or datetime-local control's `data-aui-field-value` preserves the canonical string when its local projection is unchanged; an edited instant retains its original offset and precision. Controls without a `name`, that carry `data-aui-generated-name`, or that are effectively disabled, including through an ancestor disabled fieldset outside its first legend, are skipped entirely.\n */\nexport function collectFormValues(\n elements: ArrayLike<FormControlElementLike>,\n): Record<string, unknown> {\n const values: Record<string, unknown> = Object.create(null);\n\n for (const element of Array.from(elements)) {\n const { disabled } = element;\n const name = element.getAttribute?.(FIELD_NAME_ATTR) ?? element.name;\n if (\n !name ||\n disabled ||\n element.hasAttribute(GENERATED_NAME_ATTR) ||\n element.matches?.(\":disabled\")\n )\n continue;\n\n if (element.type === \"radio\") {\n if (element.checked) values[name] = element.value;\n else if (!Object.hasOwn(values, name)) values[name] = undefined;\n continue;\n }\n\n if (\n element.type === \"checkbox\" &&\n element.hasAttribute(CHECKBOX_GROUP_ATTR)\n ) {\n const existing = values[name];\n const checked = Array.isArray(existing) ? existing : [];\n values[name] = element.checked ? [...checked, element.value] : checked;\n continue;\n }\n\n const temporalType =\n element.type === \"datetime-local\" || element.type === \"time\"\n ? element.type\n : element.getAttribute?.(\"type\");\n const inputValue =\n temporalType === \"datetime-local\" || temporalType === \"time\"\n ? normalizeTemporalInputValue(element.value)\n : element.value;\n const fieldValue =\n temporalType === \"datetime-local\" || temporalType === \"time\"\n ? element.getAttribute?.(FIELD_VALUE_ATTR)\n : undefined;\n const value: string | number | boolean =\n element.type === \"checkbox\"\n ? (element.checked ?? false)\n : element.type === \"range\"\n ? Number(element.value)\n : fieldValue && inputValue !== \"\"\n ? normalizeTemporalInputValue(inputValue) ===\n normalizeTemporalInputValue(\n temporalType === \"time\"\n ? fieldValue\n : toPickerLocalDateTime(fieldValue),\n )\n ? fieldValue\n : temporalType === \"datetime-local\"\n ? fromLocalDateTime(inputValue, fieldValue)\n : inputValue\n : inputValue;\n\n if (Object.hasOwn(values, name)) {\n const existing = values[name];\n values[name] = Array.isArray(existing)\n ? [...existing, value]\n : [existing, value];\n } else {\n values[name] = value;\n }\n }\n\n return values;\n}\n\n/**\n * Convenience wrapper around {@link collectFormValues} for a native form submit event; the cast from `HTMLFormControlsCollection` to `ArrayLike<FormControlElementLike>` lives here once instead of at every call site.\n */\nexport function collectFormValuesFromEvent(\n event: FormEvent<HTMLFormElement>,\n): Record<string, unknown> {\n return collectFormValues(\n event.currentTarget\n .elements as unknown as ArrayLike<FormControlElementLike>,\n );\n}\n"],"mappings":";;;;;;AA8BA,SAAgB,kBACd,UACyB;CACzB,MAAM,SAAkC,OAAO,OAAO,IAAI;CAE1D,KAAK,MAAM,WAAW,MAAM,KAAK,QAAQ,GAAG;EAC1C,MAAM,EAAE,aAAa;EACrB,MAAM,OAAO,QAAQ,eAAA,qBAA8B,KAAK,QAAQ;EAChE,IACE,CAAC,QACD,YACA,QAAQ,aAAA,yBAAgC,KACxC,QAAQ,UAAU,WAAW,GAE7B;EAEF,IAAI,QAAQ,SAAS,SAAS;GAC5B,IAAI,QAAQ,SAAS,OAAO,QAAQ,QAAQ;QACvC,IAAI,CAAC,OAAO,OAAO,QAAQ,IAAI,GAAG,OAAO,QAAQ,KAAA;GACtD;EACF;EAEA,IACE,QAAQ,SAAS,cACjB,QAAQ,aAAA,yBAAgC,GACxC;GACA,MAAM,WAAW,OAAO;GACxB,MAAM,UAAU,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC;GACtD,OAAO,QAAQ,QAAQ,UAAU,CAAC,GAAG,SAAS,QAAQ,KAAK,IAAI;GAC/D;EACF;EAEA,MAAM,eACJ,QAAQ,SAAS,oBAAoB,QAAQ,SAAS,SAClD,QAAQ,OACR,QAAQ,eAAe,MAAM;EACnC,MAAM,aACJ,iBAAiB,oBAAoB,iBAAiB,SAClD,4BAA4B,QAAQ,KAAK,IACzC,QAAQ;EACd,MAAM,aACJ,iBAAiB,oBAAoB,iBAAiB,SAClD,QAAQ,eAAe,gBAAgB,IACvC,KAAA;EACN,MAAM,QACJ,QAAQ,SAAS,aACZ,QAAQ,WAAW,QACpB,QAAQ,SAAS,UACf,OAAO,QAAQ,KAAK,IACpB,cAAc,eAAe,KAC3B,4BAA4B,UAAU,MACtC,4BACE,iBAAiB,SACb,aACA,sBAAsB,UAAU,CACtC,IACE,aACA,iBAAiB,mBACf,kBAAkB,YAAY,UAAU,IACxC,aACJ;EAEV,IAAI,OAAO,OAAO,QAAQ,IAAI,GAAG;GAC/B,MAAM,WAAW,OAAO;GACxB,OAAO,QAAQ,MAAM,QAAQ,QAAQ,IACjC,CAAC,GAAG,UAAU,KAAK,IACnB,CAAC,UAAU,KAAK;EACtB,OACE,OAAO,QAAQ;CAEnB;CAEA,OAAO;AACT;;;;AAKA,SAAgB,2BACd,OACyB;CACzB,OAAO,kBACL,MAAM,cACH,QACL;AACF"}
|