@assistant-ui/react-generative-ui 0.0.23 → 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 +5 -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 -152
- 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 -530
- 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 -319
- package/src/temporal.ts +0 -259
- 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 -1148
- 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 -1048
- 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
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from "vitest";
|
|
2
|
-
import { toTeamsAttachments } from "./toTeamsAttachments";
|
|
3
|
-
import { PAYLOAD_SOFT_CAP } from "./constants";
|
|
4
|
-
|
|
5
|
-
describe("toTeamsAttachments payload budget", () => {
|
|
6
|
-
it("warns on the aggregate carousel size even when no single card exceeds the soft cap", () => {
|
|
7
|
-
const value = "x".repeat(45000);
|
|
8
|
-
const { attachments, warnings } = toTeamsAttachments({
|
|
9
|
-
$type: "Carousel",
|
|
10
|
-
children: [
|
|
11
|
-
{ $type: "Card", title: "A", children: { $type: "Markdown", value } },
|
|
12
|
-
{ $type: "Card", title: "B", children: { $type: "Markdown", value } },
|
|
13
|
-
],
|
|
14
|
-
});
|
|
15
|
-
for (const attachment of attachments) {
|
|
16
|
-
expect(JSON.stringify(attachment.content).length).toBeLessThanOrEqual(
|
|
17
|
-
PAYLOAD_SOFT_CAP,
|
|
18
|
-
);
|
|
19
|
-
}
|
|
20
|
-
expect(
|
|
21
|
-
warnings.some(
|
|
22
|
-
(warning) =>
|
|
23
|
-
warning.code === "advisory" && warning.component === "Root",
|
|
24
|
-
),
|
|
25
|
-
).toBe(false);
|
|
26
|
-
expect(warnings).toContainEqual(
|
|
27
|
-
expect.objectContaining({
|
|
28
|
-
code: "advisory",
|
|
29
|
-
component: "Carousel",
|
|
30
|
-
detail: expect.stringContaining(
|
|
31
|
-
`over the ${PAYLOAD_SOFT_CAP}-byte soft budget`,
|
|
32
|
-
),
|
|
33
|
-
}),
|
|
34
|
-
);
|
|
35
|
-
});
|
|
36
|
-
});
|
|
37
|
-
|
|
38
|
-
describe("toTeamsAttachments root carousel children", () => {
|
|
39
|
-
it("reports a renderable non-card child instead of dropping it silently", () => {
|
|
40
|
-
const { attachments, warnings } = toTeamsAttachments({
|
|
41
|
-
$type: "Carousel",
|
|
42
|
-
children: [
|
|
43
|
-
{ $type: "Text", value: "lost" },
|
|
44
|
-
{ $type: "Card", title: "kept" },
|
|
45
|
-
],
|
|
46
|
-
});
|
|
47
|
-
expect(attachments).toHaveLength(1);
|
|
48
|
-
expect(warnings).toContainEqual({
|
|
49
|
-
code: "dropped",
|
|
50
|
-
component: "Carousel",
|
|
51
|
-
detail: "1 non-card child was dropped.",
|
|
52
|
-
});
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
it("forwards a discarded child's own dropped warning", () => {
|
|
56
|
-
const { warnings } = toTeamsAttachments({
|
|
57
|
-
$type: "Carousel",
|
|
58
|
-
children: [{ $type: "Mystery" }, { $type: "Card", title: "kept" }],
|
|
59
|
-
});
|
|
60
|
-
expect(warnings).toContainEqual({
|
|
61
|
-
code: "dropped",
|
|
62
|
-
component: "Mystery",
|
|
63
|
-
detail: "Unknown component type was dropped.",
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
it("stays silent for a child that renders nothing anyway", () => {
|
|
68
|
-
const { warnings } = toTeamsAttachments({
|
|
69
|
-
$type: "Carousel",
|
|
70
|
-
children: [{ $type: "Spacer" }, { $type: "Card", title: "kept" }],
|
|
71
|
-
});
|
|
72
|
-
expect(warnings).toEqual([]);
|
|
73
|
-
});
|
|
74
|
-
});
|
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
import { boundSpec, clampReasonDetail } from "../convert/boundSpec";
|
|
2
|
-
import { copyBounded } from "../convert/copyBounded";
|
|
3
|
-
import { isElement } from "../convert/isElement";
|
|
4
|
-
import {
|
|
5
|
-
normalizeSpec,
|
|
6
|
-
type NormalizedUIElement,
|
|
7
|
-
type NormalizedUINode,
|
|
8
|
-
} from "../ir";
|
|
9
|
-
import {
|
|
10
|
-
CAROUSEL_ATTACHMENT_CAP,
|
|
11
|
-
PAYLOAD_SOFT_CAP,
|
|
12
|
-
buildAttachment,
|
|
13
|
-
utf8ByteLength,
|
|
14
|
-
} from "./constants";
|
|
15
|
-
import {
|
|
16
|
-
convertRootToCard,
|
|
17
|
-
discardedChild,
|
|
18
|
-
type ConversionContext,
|
|
19
|
-
} from "./toAdaptiveCard";
|
|
20
|
-
import type {
|
|
21
|
-
TeamsAttachmentsResult,
|
|
22
|
-
TeamsCardAttachment,
|
|
23
|
-
TeamsConversionWarning,
|
|
24
|
-
ToAdaptiveCardOptions,
|
|
25
|
-
} from "./types";
|
|
26
|
-
|
|
27
|
-
const normalizedList = (
|
|
28
|
-
node: NormalizedUINode | undefined,
|
|
29
|
-
): NormalizedUINode[] => {
|
|
30
|
-
if (node === undefined || node === null) return [];
|
|
31
|
-
if (!Array.isArray(node)) return [node];
|
|
32
|
-
return node.flatMap((child) => normalizedList(child));
|
|
33
|
-
};
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Recognizes a root that is a single `Carousel` element, returning its `Card`
|
|
37
|
-
* children. A non-card child is routed through {@link discardedChild}, which
|
|
38
|
-
* reports it and forwards whatever it lost, rather than being filtered out
|
|
39
|
-
* silently. `undefined` means the root is not exclusively a
|
|
40
|
-
* root-level carousel, so the caller falls back to converting the whole tree
|
|
41
|
-
* as one card.
|
|
42
|
-
*/
|
|
43
|
-
function rootCarouselCards(
|
|
44
|
-
root: NormalizedUINode | readonly NormalizedUINode[],
|
|
45
|
-
context: ConversionContext,
|
|
46
|
-
): NormalizedUIElement[] | undefined {
|
|
47
|
-
const element = Array.isArray(root) && root.length === 1 ? root[0] : root;
|
|
48
|
-
if (!isElement(element) || element.type !== "Carousel") return undefined;
|
|
49
|
-
const cards: NormalizedUIElement[] = [];
|
|
50
|
-
let discarded = 0;
|
|
51
|
-
for (const child of normalizedList(element.children)) {
|
|
52
|
-
if (isElement(child) && child.type === "Card") {
|
|
53
|
-
cards.push(child);
|
|
54
|
-
continue;
|
|
55
|
-
}
|
|
56
|
-
if (discardedChild(child, context, 1)) discarded += 1;
|
|
57
|
-
}
|
|
58
|
-
if (discarded > 0) {
|
|
59
|
-
context.warnings.push({
|
|
60
|
-
code: "dropped",
|
|
61
|
-
component: "Carousel",
|
|
62
|
-
detail: `${discarded} non-card ${discarded === 1 ? "child was" : "children were"} dropped.`,
|
|
63
|
-
});
|
|
64
|
-
}
|
|
65
|
-
return cards;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* Converts a generative-ui tree into Teams bot-framework message attachments.
|
|
70
|
-
* A root-level `Carousel` becomes one attachment per `Card` child (clamped to
|
|
71
|
-
* {@link CAROUSEL_ATTACHMENT_CAP}) with `attachmentLayout: "carousel"`;
|
|
72
|
-
* anything else converts through {@link toAdaptiveCard}'s engine into a
|
|
73
|
-
* single attachment. Never throws.
|
|
74
|
-
*/
|
|
75
|
-
export function toTeamsAttachments(
|
|
76
|
-
node: unknown,
|
|
77
|
-
_options?: ToAdaptiveCardOptions,
|
|
78
|
-
): TeamsAttachmentsResult {
|
|
79
|
-
const warnings: TeamsConversionWarning[] = [];
|
|
80
|
-
const context: ConversionContext = {
|
|
81
|
-
warnings,
|
|
82
|
-
usedInputIds: new Set(),
|
|
83
|
-
};
|
|
84
|
-
try {
|
|
85
|
-
const bounded = boundSpec(node, (reason) =>
|
|
86
|
-
warnings.push({
|
|
87
|
-
code: "clamped",
|
|
88
|
-
component: "Root",
|
|
89
|
-
detail: clampReasonDetail(reason),
|
|
90
|
-
}),
|
|
91
|
-
);
|
|
92
|
-
const { root } = normalizeSpec(bounded as never);
|
|
93
|
-
const carouselCards = rootCarouselCards(root, context);
|
|
94
|
-
if (carouselCards !== undefined) {
|
|
95
|
-
const { items, truncated } = copyBounded(
|
|
96
|
-
carouselCards,
|
|
97
|
-
CAROUSEL_ATTACHMENT_CAP,
|
|
98
|
-
);
|
|
99
|
-
if (truncated) {
|
|
100
|
-
warnings.push({
|
|
101
|
-
code: "clamped",
|
|
102
|
-
component: "Carousel",
|
|
103
|
-
detail: `cards were clamped to ${CAROUSEL_ATTACHMENT_CAP} entries.`,
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
const attachments: TeamsCardAttachment[] = items.map((child) =>
|
|
107
|
-
buildAttachment(convertRootToCard(child, context)),
|
|
108
|
-
);
|
|
109
|
-
const size = utf8ByteLength(JSON.stringify(attachments));
|
|
110
|
-
if (size > PAYLOAD_SOFT_CAP) {
|
|
111
|
-
warnings.push({
|
|
112
|
-
code: "advisory",
|
|
113
|
-
component: "Carousel",
|
|
114
|
-
detail: `the carousel attachments total ${size} bytes, over the ${PAYLOAD_SOFT_CAP}-byte soft budget kept below Teams' 100 KB bot message limit.`,
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
return { attachments, attachmentLayout: "carousel", warnings };
|
|
118
|
-
}
|
|
119
|
-
const attachment = buildAttachment(convertRootToCard(root, context));
|
|
120
|
-
return { attachments: [attachment], warnings };
|
|
121
|
-
} catch {
|
|
122
|
-
return {
|
|
123
|
-
attachments: [],
|
|
124
|
-
warnings: [
|
|
125
|
-
{
|
|
126
|
-
code: "dropped",
|
|
127
|
-
component: "Root",
|
|
128
|
-
detail: "Input could not be converted.",
|
|
129
|
-
},
|
|
130
|
-
],
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
}
|
package/src/teams/types.ts
DELETED
|
@@ -1,266 +0,0 @@
|
|
|
1
|
-
/** A TextBlock size, from Adaptive Card's closed size enum. */
|
|
2
|
-
export type TeamsTextSize = "small" | "medium" | "large" | "extraLarge";
|
|
3
|
-
|
|
4
|
-
/** A Container's style, driving its accent color in Teams' renderer. */
|
|
5
|
-
export type TeamsContainerStyle =
|
|
6
|
-
| "default"
|
|
7
|
-
| "emphasis"
|
|
8
|
-
| "good"
|
|
9
|
-
| "attention"
|
|
10
|
-
| "warning"
|
|
11
|
-
| "accent";
|
|
12
|
-
|
|
13
|
-
/** A run of wrapped text. Every TextBlock we emit sets `wrap: true`. */
|
|
14
|
-
export interface TeamsTextBlock {
|
|
15
|
-
readonly type: "TextBlock";
|
|
16
|
-
readonly text: string;
|
|
17
|
-
readonly wrap: true;
|
|
18
|
-
readonly size?: TeamsTextSize;
|
|
19
|
-
readonly weight?: "bolder";
|
|
20
|
-
readonly style?: "heading";
|
|
21
|
-
readonly isSubtle?: true;
|
|
22
|
-
readonly separator?: true;
|
|
23
|
-
readonly spacing?: "large";
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** An image element. */
|
|
27
|
-
export interface TeamsImage {
|
|
28
|
-
readonly type: "Image";
|
|
29
|
-
readonly url: string;
|
|
30
|
-
readonly altText?: string;
|
|
31
|
-
readonly size?: "small" | "medium" | "large";
|
|
32
|
-
readonly separator?: true;
|
|
33
|
-
readonly spacing?: "large";
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/** One label/value entry inside a {@link TeamsFactSet}. */
|
|
37
|
-
export interface TeamsFact {
|
|
38
|
-
readonly title: string;
|
|
39
|
-
readonly value: string;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** A set of label/value facts, rendered as an aligned two-column list. */
|
|
43
|
-
export interface TeamsFactSet {
|
|
44
|
-
readonly type: "FactSet";
|
|
45
|
-
readonly facts: readonly TeamsFact[];
|
|
46
|
-
readonly separator?: true;
|
|
47
|
-
readonly spacing?: "large";
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/** The `aui` envelope nested inside every {@link TeamsSubmitAction}'s `data`. */
|
|
51
|
-
export interface TeamsSubmitData {
|
|
52
|
-
readonly aui: {
|
|
53
|
-
readonly type: string;
|
|
54
|
-
readonly payload?: Record<string, unknown>;
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
export type TeamsTemporalField = { readonly fieldId: string } & (
|
|
59
|
-
| { readonly role: "date" }
|
|
60
|
-
| { readonly role: "time"; readonly previousValue?: string }
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* A submit action. `data` carries the resume payload under an `aui` key so
|
|
65
|
-
* {@link decodeSubmitData} can invert it out of the merged `activity.value`
|
|
66
|
-
* a Teams bot receives, alongside whatever other named inputs shared the card.
|
|
67
|
-
*/
|
|
68
|
-
export interface TeamsSubmitAction {
|
|
69
|
-
readonly type: "Action.Submit";
|
|
70
|
-
readonly title: string;
|
|
71
|
-
readonly data: TeamsSubmitData;
|
|
72
|
-
readonly mode?: "secondary";
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/** The action shape accepted at the card's top-level `actions` field. */
|
|
76
|
-
export type TeamsCardAction = TeamsSubmitAction;
|
|
77
|
-
|
|
78
|
-
/** A bar of submit actions, rendered inline in the body flow. */
|
|
79
|
-
export interface TeamsActionSet {
|
|
80
|
-
readonly type: "ActionSet";
|
|
81
|
-
readonly actions: readonly TeamsSubmitAction[];
|
|
82
|
-
readonly separator?: true;
|
|
83
|
-
readonly spacing?: "large";
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
/** A bordered grouping container. */
|
|
87
|
-
export interface TeamsContainer {
|
|
88
|
-
readonly type: "Container";
|
|
89
|
-
readonly style?: TeamsContainerStyle;
|
|
90
|
-
readonly items: readonly TeamsCardElement[];
|
|
91
|
-
readonly selectAction?: TeamsSubmitAction;
|
|
92
|
-
readonly separator?: true;
|
|
93
|
-
readonly spacing?: "large";
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/** One column inside a {@link TeamsColumnSet}. */
|
|
97
|
-
export interface TeamsColumn {
|
|
98
|
-
readonly type: "Column";
|
|
99
|
-
readonly width: "auto";
|
|
100
|
-
readonly items: readonly TeamsCardElement[];
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** A horizontal row of columns. */
|
|
104
|
-
export interface TeamsColumnSet {
|
|
105
|
-
readonly type: "ColumnSet";
|
|
106
|
-
readonly columns: readonly TeamsColumn[];
|
|
107
|
-
readonly separator?: true;
|
|
108
|
-
readonly spacing?: "large";
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
/** One selectable choice inside a {@link TeamsInputChoiceSet}. */
|
|
112
|
-
export interface TeamsInputChoice {
|
|
113
|
-
readonly title: string;
|
|
114
|
-
readonly value: string;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** A dropdown (`compact`), radio group (`expanded`), or checkbox group (`expanded` with `isMultiSelect`) input. */
|
|
118
|
-
export interface TeamsInputChoiceSet {
|
|
119
|
-
readonly type: "Input.ChoiceSet";
|
|
120
|
-
readonly id: string;
|
|
121
|
-
readonly style: "compact" | "expanded";
|
|
122
|
-
readonly isMultiSelect?: true;
|
|
123
|
-
readonly choices: readonly TeamsInputChoice[];
|
|
124
|
-
readonly placeholder?: string;
|
|
125
|
-
readonly label?: string;
|
|
126
|
-
readonly value?: string;
|
|
127
|
-
readonly separator?: true;
|
|
128
|
-
readonly spacing?: "large";
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
/** A checkbox-shaped boolean input. */
|
|
132
|
-
export interface TeamsInputToggle {
|
|
133
|
-
readonly type: "Input.Toggle";
|
|
134
|
-
readonly id: string;
|
|
135
|
-
readonly title: string;
|
|
136
|
-
readonly value: "true" | "false";
|
|
137
|
-
readonly valueOn: "true";
|
|
138
|
-
readonly valueOff: "false";
|
|
139
|
-
readonly separator?: true;
|
|
140
|
-
readonly spacing?: "large";
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
/** A single or multi-line text input. */
|
|
144
|
-
export interface TeamsInputText {
|
|
145
|
-
readonly type: "Input.Text";
|
|
146
|
-
readonly id: string;
|
|
147
|
-
readonly style?: "password";
|
|
148
|
-
readonly label?: string;
|
|
149
|
-
readonly placeholder?: string;
|
|
150
|
-
readonly value?: string;
|
|
151
|
-
readonly isMultiline?: true;
|
|
152
|
-
readonly separator?: true;
|
|
153
|
-
readonly spacing?: "large";
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
/** A date input, restricted to `YYYY-MM-DD` values. */
|
|
157
|
-
export interface TeamsInputDate {
|
|
158
|
-
readonly type: "Input.Date";
|
|
159
|
-
readonly id: string;
|
|
160
|
-
readonly label?: string;
|
|
161
|
-
readonly value?: string;
|
|
162
|
-
readonly min?: string;
|
|
163
|
-
readonly max?: string;
|
|
164
|
-
readonly separator?: true;
|
|
165
|
-
readonly spacing?: "large";
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
export interface TeamsInputTime {
|
|
169
|
-
readonly type: "Input.Time";
|
|
170
|
-
readonly id: string;
|
|
171
|
-
readonly label?: string;
|
|
172
|
-
readonly value?: string;
|
|
173
|
-
readonly min?: string;
|
|
174
|
-
readonly max?: string;
|
|
175
|
-
readonly separator?: true;
|
|
176
|
-
readonly spacing?: "large";
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** One cell inside a {@link TeamsTableRow}. */
|
|
180
|
-
export interface TeamsTableCell {
|
|
181
|
-
readonly type: "TableCell";
|
|
182
|
-
readonly items: readonly TeamsTextBlock[];
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/** One row inside a {@link TeamsTable}. */
|
|
186
|
-
export interface TeamsTableRow {
|
|
187
|
-
readonly type: "TableRow";
|
|
188
|
-
readonly cells: readonly TeamsTableCell[];
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
/** A column width definition inside a {@link TeamsTable}. */
|
|
192
|
-
export interface TeamsTableColumnDefinition {
|
|
193
|
-
readonly width: 1;
|
|
194
|
-
}
|
|
195
|
-
|
|
196
|
-
/** A native table. `rows[0]` is the header row when `firstRowAsHeaders` is true. */
|
|
197
|
-
export interface TeamsTable {
|
|
198
|
-
readonly type: "Table";
|
|
199
|
-
readonly firstRowAsHeaders: boolean;
|
|
200
|
-
readonly columns: readonly TeamsTableColumnDefinition[];
|
|
201
|
-
readonly rows: readonly TeamsTableRow[];
|
|
202
|
-
readonly separator?: true;
|
|
203
|
-
readonly spacing?: "large";
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
/** A body element emitted by {@link toAdaptiveCard}. */
|
|
207
|
-
export type TeamsCardElement =
|
|
208
|
-
| TeamsTextBlock
|
|
209
|
-
| TeamsImage
|
|
210
|
-
| TeamsFactSet
|
|
211
|
-
| TeamsActionSet
|
|
212
|
-
| TeamsContainer
|
|
213
|
-
| TeamsColumnSet
|
|
214
|
-
| TeamsInputChoiceSet
|
|
215
|
-
| TeamsInputToggle
|
|
216
|
-
| TeamsInputText
|
|
217
|
-
| TeamsInputDate
|
|
218
|
-
| TeamsInputTime
|
|
219
|
-
| TeamsTable;
|
|
220
|
-
|
|
221
|
-
/** A Microsoft Teams Adaptive Card, pinned to schema version 1.5 (the Teams desktop/web cap; mobile clients cap at 1.2). */
|
|
222
|
-
export interface TeamsAdaptiveCard {
|
|
223
|
-
readonly $schema: "http://adaptivecards.io/schemas/adaptive-card.json";
|
|
224
|
-
readonly type: "AdaptiveCard";
|
|
225
|
-
readonly version: "1.5";
|
|
226
|
-
readonly body: readonly TeamsCardElement[];
|
|
227
|
-
readonly actions: readonly TeamsCardAction[];
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
/** An Adaptive Card wrapped as a bot-framework message attachment. */
|
|
231
|
-
export interface TeamsCardAttachment {
|
|
232
|
-
readonly contentType: "application/vnd.microsoft.card.adaptive";
|
|
233
|
-
readonly content: TeamsAdaptiveCard;
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
/**
|
|
237
|
-
* A non-fatal note reported during Teams conversion.
|
|
238
|
-
*
|
|
239
|
-
* `clamped` removed content to fit a limit, `dropped` discarded a node or one
|
|
240
|
-
* of its props and may leave a placeholder note behind, and `fallback`
|
|
241
|
-
* emitted the node in a different form than requested. `advisory` changed
|
|
242
|
-
* nothing at all and notes content Teams may still render poorly or refuse,
|
|
243
|
-
* such as a payload over the byte budget or a `Row` past the recommended
|
|
244
|
-
* column count.
|
|
245
|
-
*/
|
|
246
|
-
export interface TeamsConversionWarning {
|
|
247
|
-
readonly code: "clamped" | "dropped" | "fallback" | "advisory";
|
|
248
|
-
readonly component: string;
|
|
249
|
-
readonly detail: string;
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
/** Options accepted by {@link toAdaptiveCard} and {@link toTeamsAttachments}. Reserved for future extension; no options are currently defined. */
|
|
253
|
-
export interface ToAdaptiveCardOptions {}
|
|
254
|
-
|
|
255
|
-
/** The card and non-fatal warnings produced by {@link toAdaptiveCard}. */
|
|
256
|
-
export interface AdaptiveCardResult {
|
|
257
|
-
readonly card: TeamsAdaptiveCard;
|
|
258
|
-
readonly warnings: TeamsConversionWarning[];
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
/** The attachments and non-fatal warnings produced by {@link toTeamsAttachments}. */
|
|
262
|
-
export interface TeamsAttachmentsResult {
|
|
263
|
-
readonly attachments: TeamsCardAttachment[];
|
|
264
|
-
readonly attachmentLayout?: "carousel";
|
|
265
|
-
readonly warnings: TeamsConversionWarning[];
|
|
266
|
-
}
|