@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.
Files changed (338) hide show
  1. package/README.md +2 -0
  2. package/dist/a2ui.d.ts +1 -4
  3. package/dist/a2ui.d.ts.map +1 -1
  4. package/dist/a2ui.js +1 -4
  5. package/dist/index.d.ts +1 -2
  6. package/dist/index.d.ts.map +1 -1
  7. package/dist/index.js +1 -10
  8. package/dist/index.server.d.ts +1 -2
  9. package/dist/index.server.d.ts.map +1 -1
  10. package/dist/index.server.js +1 -10
  11. package/dist/ir.d.ts +1 -111
  12. package/dist/ir.d.ts.map +1 -1
  13. package/dist/ir.js +1 -175
  14. package/dist/slack.d.ts +1 -4
  15. package/dist/slack.d.ts.map +1 -1
  16. package/dist/slack.js +1 -4
  17. package/dist/teams.d.ts +1 -4
  18. package/dist/teams.d.ts.map +1 -1
  19. package/dist/teams.js +1 -4
  20. package/package.json +4 -5
  21. package/src/a2ui.ts +1 -22
  22. package/src/index.server.ts +1 -2
  23. package/src/index.test.ts +75 -0
  24. package/src/index.ts +1 -2
  25. package/src/ir.ts +1 -279
  26. package/src/slack.ts +1 -39
  27. package/src/teams.ts +1 -35
  28. package/dist/JSONGenerativeUI.client.d.ts +0 -28
  29. package/dist/JSONGenerativeUI.client.d.ts.map +0 -1
  30. package/dist/JSONGenerativeUI.client.js +0 -101
  31. package/dist/JSONGenerativeUI.client.js.map +0 -1
  32. package/dist/JSONGenerativeUI.server.d.ts +0 -21
  33. package/dist/JSONGenerativeUI.server.d.ts.map +0 -1
  34. package/dist/JSONGenerativeUI.server.js +0 -32
  35. package/dist/JSONGenerativeUI.server.js.map +0 -1
  36. package/dist/JSONGenerativeUI.shared.d.ts +0 -63
  37. package/dist/JSONGenerativeUI.shared.d.ts.map +0 -1
  38. package/dist/JSONGenerativeUI.shared.js +0 -31
  39. package/dist/JSONGenerativeUI.shared.js.map +0 -1
  40. package/dist/RadioGroupScope.d.ts +0 -6
  41. package/dist/RadioGroupScope.d.ts.map +0 -1
  42. package/dist/RadioGroupScope.js +0 -25
  43. package/dist/RadioGroupScope.js.map +0 -1
  44. package/dist/a2ui/BindingContext.d.ts +0 -11
  45. package/dist/a2ui/BindingContext.d.ts.map +0 -1
  46. package/dist/a2ui/BindingContext.js +0 -12
  47. package/dist/a2ui/BindingContext.js.map +0 -1
  48. package/dist/a2ui/PresentRenderer.d.ts +0 -11
  49. package/dist/a2ui/PresentRenderer.d.ts.map +0 -1
  50. package/dist/a2ui/PresentRenderer.js +0 -39
  51. package/dist/a2ui/PresentRenderer.js.map +0 -1
  52. package/dist/a2ui/convert.d.ts +0 -15
  53. package/dist/a2ui/convert.d.ts.map +0 -1
  54. package/dist/a2ui/convert.js +0 -728
  55. package/dist/a2ui/convert.js.map +0 -1
  56. package/dist/a2ui/dataModel.d.ts +0 -9
  57. package/dist/a2ui/dataModel.d.ts.map +0 -1
  58. package/dist/a2ui/dataModel.js +0 -44
  59. package/dist/a2ui/dataModel.js.map +0 -1
  60. package/dist/a2ui/reducer.d.ts +0 -8
  61. package/dist/a2ui/reducer.d.ts.map +0 -1
  62. package/dist/a2ui/reducer.js +0 -242
  63. package/dist/a2ui/reducer.js.map +0 -1
  64. package/dist/a2ui/snapshot.d.ts +0 -3
  65. package/dist/a2ui/snapshot.d.ts.map +0 -1
  66. package/dist/a2ui/snapshot.js +0 -33
  67. package/dist/a2ui/snapshot.js.map +0 -1
  68. package/dist/a2ui/types.d.ts +0 -88
  69. package/dist/a2ui/types.d.ts.map +0 -1
  70. package/dist/a2ui/types.js +0 -6
  71. package/dist/a2ui/types.js.map +0 -1
  72. package/dist/a2ui/valueFunctions.d.ts +0 -16
  73. package/dist/a2ui/valueFunctions.d.ts.map +0 -1
  74. package/dist/a2ui/valueFunctions.js +0 -332
  75. package/dist/a2ui/valueFunctions.js.map +0 -1
  76. package/dist/actionRegistry.d.ts +0 -29
  77. package/dist/actionRegistry.d.ts.map +0 -1
  78. package/dist/actionRegistry.js +0 -41
  79. package/dist/actionRegistry.js.map +0 -1
  80. package/dist/answeredValues.d.ts +0 -16
  81. package/dist/answeredValues.d.ts.map +0 -1
  82. package/dist/answeredValues.js +0 -37
  83. package/dist/answeredValues.js.map +0 -1
  84. package/dist/buildPresentParameters.d.ts +0 -21
  85. package/dist/buildPresentParameters.d.ts.map +0 -1
  86. package/dist/buildPresentParameters.js +0 -95
  87. package/dist/buildPresentParameters.js.map +0 -1
  88. package/dist/constants.d.ts +0 -15
  89. package/dist/constants.d.ts.map +0 -1
  90. package/dist/constants.js +0 -19
  91. package/dist/constants.js.map +0 -1
  92. package/dist/convert/boundSpec.d.ts +0 -48
  93. package/dist/convert/boundSpec.d.ts.map +0 -1
  94. package/dist/convert/boundSpec.js +0 -108
  95. package/dist/convert/boundSpec.js.map +0 -1
  96. package/dist/convert/copyBounded.d.ts +0 -25
  97. package/dist/convert/copyBounded.d.ts.map +0 -1
  98. package/dist/convert/copyBounded.js +0 -38
  99. package/dist/convert/copyBounded.js.map +0 -1
  100. package/dist/convert/isElement.d.ts +0 -3
  101. package/dist/convert/isElement.d.ts.map +0 -1
  102. package/dist/convert/isElement.js +0 -6
  103. package/dist/convert/isElement.js.map +0 -1
  104. package/dist/convert/takeRun.d.ts +0 -6
  105. package/dist/convert/takeRun.d.ts.map +0 -1
  106. package/dist/convert/takeRun.js +0 -20
  107. package/dist/convert/takeRun.js.map +0 -1
  108. package/dist/defineGenerativeComponents.d.ts +0 -29
  109. package/dist/defineGenerativeComponents.d.ts.map +0 -1
  110. package/dist/defineGenerativeComponents.js +0 -34
  111. package/dist/defineGenerativeComponents.js.map +0 -1
  112. package/dist/fieldReferences.d.ts +0 -9
  113. package/dist/fieldReferences.d.ts.map +0 -1
  114. package/dist/fieldReferences.js +0 -53
  115. package/dist/fieldReferences.js.map +0 -1
  116. package/dist/generativeUIToJSX.d.ts +0 -18
  117. package/dist/generativeUIToJSX.d.ts.map +0 -1
  118. package/dist/generativeUIToJSX.js +0 -76
  119. package/dist/generativeUIToJSX.js.map +0 -1
  120. package/dist/index.shared.d.ts +0 -15
  121. package/dist/index.shared.d.ts.map +0 -1
  122. package/dist/index.shared.js +0 -9
  123. package/dist/ir.js.map +0 -1
  124. package/dist/renderGenerativeUI.d.ts +0 -14
  125. package/dist/renderGenerativeUI.d.ts.map +0 -1
  126. package/dist/renderGenerativeUI.js +0 -83
  127. package/dist/renderGenerativeUI.js.map +0 -1
  128. package/dist/scopeSchema.d.ts +0 -6
  129. package/dist/scopeSchema.d.ts.map +0 -1
  130. package/dist/scopeSchema.js +0 -56
  131. package/dist/scopeSchema.js.map +0 -1
  132. package/dist/slack/constants.d.ts +0 -93
  133. package/dist/slack/constants.d.ts.map +0 -1
  134. package/dist/slack/constants.js +0 -146
  135. package/dist/slack/constants.js.map +0 -1
  136. package/dist/slack/decodeBlockAction.d.ts +0 -10
  137. package/dist/slack/decodeBlockAction.d.ts.map +0 -1
  138. package/dist/slack/decodeBlockAction.js +0 -129
  139. package/dist/slack/decodeBlockAction.js.map +0 -1
  140. package/dist/slack/fromSlackBlocks.d.ts +0 -27
  141. package/dist/slack/fromSlackBlocks.d.ts.map +0 -1
  142. package/dist/slack/fromSlackBlocks.js +0 -483
  143. package/dist/slack/fromSlackBlocks.js.map +0 -1
  144. package/dist/slack/toSlackBlocks.d.ts +0 -4
  145. package/dist/slack/toSlackBlocks.d.ts.map +0 -1
  146. package/dist/slack/toSlackBlocks.js +0 -901
  147. package/dist/slack/toSlackBlocks.js.map +0 -1
  148. package/dist/slack/types.d.ts +0 -204
  149. package/dist/slack/types.d.ts.map +0 -1
  150. package/dist/slack/types.js +0 -0
  151. package/dist/teams/constants.d.ts +0 -34
  152. package/dist/teams/constants.d.ts.map +0 -1
  153. package/dist/teams/constants.js +0 -68
  154. package/dist/teams/constants.js.map +0 -1
  155. package/dist/teams/decodeSubmitData.d.ts +0 -26
  156. package/dist/teams/decodeSubmitData.d.ts.map +0 -1
  157. package/dist/teams/decodeSubmitData.js +0 -70
  158. package/dist/teams/decodeSubmitData.js.map +0 -1
  159. package/dist/teams/temporalId.d.ts +0 -5
  160. package/dist/teams/temporalId.d.ts.map +0 -1
  161. package/dist/teams/temporalId.js +0 -28
  162. package/dist/teams/temporalId.js.map +0 -1
  163. package/dist/teams/toAdaptiveCard.d.ts +0 -45
  164. package/dist/teams/toAdaptiveCard.d.ts.map +0 -1
  165. package/dist/teams/toAdaptiveCard.js +0 -642
  166. package/dist/teams/toAdaptiveCard.js.map +0 -1
  167. package/dist/teams/toTeamsAttachments.d.ts +0 -10
  168. package/dist/teams/toTeamsAttachments.d.ts.map +0 -1
  169. package/dist/teams/toTeamsAttachments.js +0 -99
  170. package/dist/teams/toTeamsAttachments.js.map +0 -1
  171. package/dist/teams/types.d.ts +0 -224
  172. package/dist/teams/types.d.ts.map +0 -1
  173. package/dist/teams/types.js +0 -0
  174. package/dist/temporal.d.ts +0 -33
  175. package/dist/temporal.d.ts.map +0 -1
  176. package/dist/temporal.js +0 -153
  177. package/dist/temporal.js.map +0 -1
  178. package/dist/types.d.ts +0 -99
  179. package/dist/types.d.ts.map +0 -1
  180. package/dist/types.js +0 -0
  181. package/dist/vocabulary/alert.d.ts +0 -32
  182. package/dist/vocabulary/alert.d.ts.map +0 -1
  183. package/dist/vocabulary/alert.js +0 -160
  184. package/dist/vocabulary/alert.js.map +0 -1
  185. package/dist/vocabulary/collectFormValues.d.ts +0 -23
  186. package/dist/vocabulary/collectFormValues.d.ts.map +0 -1
  187. package/dist/vocabulary/collectFormValues.js +0 -44
  188. package/dist/vocabulary/collectFormValues.js.map +0 -1
  189. package/dist/vocabulary/data.d.ts +0 -66
  190. package/dist/vocabulary/data.d.ts.map +0 -1
  191. package/dist/vocabulary/data.js +0 -503
  192. package/dist/vocabulary/data.js.map +0 -1
  193. package/dist/vocabulary/dispatch.d.ts +0 -9
  194. package/dist/vocabulary/dispatch.d.ts.map +0 -1
  195. package/dist/vocabulary/dispatch.js +0 -50
  196. package/dist/vocabulary/dispatch.js.map +0 -1
  197. package/dist/vocabulary/fact.d.ts +0 -19
  198. package/dist/vocabulary/fact.d.ts.map +0 -1
  199. package/dist/vocabulary/fact.js +0 -51
  200. package/dist/vocabulary/fact.js.map +0 -1
  201. package/dist/vocabulary/form.d.ts +0 -11
  202. package/dist/vocabulary/form.d.ts.map +0 -1
  203. package/dist/vocabulary/form.js +0 -23
  204. package/dist/vocabulary/form.js.map +0 -1
  205. package/dist/vocabulary/formatValue.d.ts +0 -7
  206. package/dist/vocabulary/formatValue.d.ts.map +0 -1
  207. package/dist/vocabulary/formatValue.js +0 -76
  208. package/dist/vocabulary/formatValue.js.map +0 -1
  209. package/dist/vocabulary/icon.d.ts +0 -41
  210. package/dist/vocabulary/icon.d.ts.map +0 -1
  211. package/dist/vocabulary/icon.js +0 -272
  212. package/dist/vocabulary/icon.js.map +0 -1
  213. package/dist/vocabulary/index.d.ts +0 -12
  214. package/dist/vocabulary/index.d.ts.map +0 -1
  215. package/dist/vocabulary/index.js +0 -36
  216. package/dist/vocabulary/index.js.map +0 -1
  217. package/dist/vocabulary/interactive.d.ts +0 -230
  218. package/dist/vocabulary/interactive.d.ts.map +0 -1
  219. package/dist/vocabulary/interactive.js +0 -584
  220. package/dist/vocabulary/interactive.js.map +0 -1
  221. package/dist/vocabulary/layout.d.ts +0 -79
  222. package/dist/vocabulary/layout.d.ts.map +0 -1
  223. package/dist/vocabulary/layout.js +0 -139
  224. package/dist/vocabulary/layout.js.map +0 -1
  225. package/dist/vocabulary/list.d.ts +0 -14
  226. package/dist/vocabulary/list.d.ts.map +0 -1
  227. package/dist/vocabulary/list.js +0 -50
  228. package/dist/vocabulary/list.js.map +0 -1
  229. package/dist/vocabulary/media.d.ts +0 -25
  230. package/dist/vocabulary/media.d.ts.map +0 -1
  231. package/dist/vocabulary/media.js +0 -42
  232. package/dist/vocabulary/media.js.map +0 -1
  233. package/dist/vocabulary/text.d.ts +0 -57
  234. package/dist/vocabulary/text.d.ts.map +0 -1
  235. package/dist/vocabulary/text.js +0 -49
  236. package/dist/vocabulary/text.js.map +0 -1
  237. package/dist/vocabulary/toTextContent.d.ts +0 -2
  238. package/dist/vocabulary/toTextContent.d.ts.map +0 -1
  239. package/dist/vocabulary/toTextContent.js +0 -6
  240. package/dist/vocabulary/toTextContent.js.map +0 -1
  241. package/src/JSONGenerativeUI.client.tsx +0 -168
  242. package/src/JSONGenerativeUI.server.tsx +0 -39
  243. package/src/JSONGenerativeUI.shared.ts +0 -90
  244. package/src/JSONGenerativeUI.test.tsx +0 -1298
  245. package/src/RadioGroupScope.server.test.tsx +0 -24
  246. package/src/RadioGroupScope.tsx +0 -34
  247. package/src/a2ui/BindingContext.ts +0 -26
  248. package/src/a2ui/PresentRenderer.tsx +0 -83
  249. package/src/a2ui/convert.test.ts +0 -2923
  250. package/src/a2ui/convert.ts +0 -1207
  251. package/src/a2ui/dataModel.ts +0 -69
  252. package/src/a2ui/reducer.test.ts +0 -422
  253. package/src/a2ui/reducer.ts +0 -363
  254. package/src/a2ui/snapshot.test.ts +0 -52
  255. package/src/a2ui/snapshot.ts +0 -52
  256. package/src/a2ui/types.ts +0 -114
  257. package/src/a2ui/valueFunctions.test.ts +0 -271
  258. package/src/a2ui/valueFunctions.ts +0 -523
  259. package/src/actionRegistry.test.ts +0 -90
  260. package/src/actionRegistry.ts +0 -88
  261. package/src/answeredValues.test.ts +0 -33
  262. package/src/answeredValues.tsx +0 -70
  263. package/src/buildPresentParameters.test.ts +0 -246
  264. package/src/buildPresentParameters.ts +0 -130
  265. package/src/constants.ts +0 -17
  266. package/src/convert/boundSpec.test.ts +0 -192
  267. package/src/convert/boundSpec.ts +0 -134
  268. package/src/convert/copyBounded.test.ts +0 -131
  269. package/src/convert/copyBounded.ts +0 -38
  270. package/src/convert/isElement.ts +0 -6
  271. package/src/convert/takeRun.test.ts +0 -64
  272. package/src/convert/takeRun.ts +0 -19
  273. package/src/defineGenerativeComponents.ts +0 -38
  274. package/src/fieldReferences.test.ts +0 -66
  275. package/src/fieldReferences.ts +0 -83
  276. package/src/generativeUIToJSX.test.ts +0 -268
  277. package/src/generativeUIToJSX.ts +0 -152
  278. package/src/index.server.test.ts +0 -106
  279. package/src/index.shared.ts +0 -61
  280. package/src/ir.test.ts +0 -203
  281. package/src/renderGenerativeUI.test.tsx +0 -373
  282. package/src/renderGenerativeUI.tsx +0 -165
  283. package/src/scopeSchema.test.ts +0 -72
  284. package/src/scopeSchema.ts +0 -71
  285. package/src/slack/a2uiSlack.test.ts +0 -198
  286. package/src/slack/constants.ts +0 -194
  287. package/src/slack/datePicker.test.ts +0 -612
  288. package/src/slack/decodeBlockAction.test.ts +0 -233
  289. package/src/slack/decodeBlockAction.ts +0 -232
  290. package/src/slack/fromSlackBlocks.test.ts +0 -1465
  291. package/src/slack/fromSlackBlocks.ts +0 -789
  292. package/src/slack/toSlackBlocks.test.ts +0 -3065
  293. package/src/slack/toSlackBlocks.ts +0 -1818
  294. package/src/slack/types.ts +0 -264
  295. package/src/teams/constants.ts +0 -93
  296. package/src/teams/decodeSubmitData.test.ts +0 -397
  297. package/src/teams/decodeSubmitData.ts +0 -110
  298. package/src/teams/temporal.test.ts +0 -766
  299. package/src/teams/temporalId.ts +0 -56
  300. package/src/teams/toAdaptiveCard.test.ts +0 -1897
  301. package/src/teams/toAdaptiveCard.ts +0 -1057
  302. package/src/teams/toTeamsAttachments.test.ts +0 -74
  303. package/src/teams/toTeamsAttachments.ts +0 -133
  304. package/src/teams/types.ts +0 -266
  305. package/src/temporal.test.ts +0 -337
  306. package/src/temporal.ts +0 -263
  307. package/src/types.ts +0 -119
  308. package/src/vocabulary/alert.test.tsx +0 -427
  309. package/src/vocabulary/alert.tsx +0 -217
  310. package/src/vocabulary/collectFormValues.test.ts +0 -389
  311. package/src/vocabulary/collectFormValues.ts +0 -116
  312. package/src/vocabulary/data.test.tsx +0 -858
  313. package/src/vocabulary/data.tsx +0 -819
  314. package/src/vocabulary/datepicker.dom.test.tsx +0 -1457
  315. package/src/vocabulary/dispatch.ts +0 -83
  316. package/src/vocabulary/fact.test.tsx +0 -94
  317. package/src/vocabulary/fact.tsx +0 -54
  318. package/src/vocabulary/form.test.tsx +0 -113
  319. package/src/vocabulary/form.tsx +0 -39
  320. package/src/vocabulary/formatValue.test.ts +0 -72
  321. package/src/vocabulary/formatValue.ts +0 -127
  322. package/src/vocabulary/icon.test.tsx +0 -64
  323. package/src/vocabulary/icon.tsx +0 -174
  324. package/src/vocabulary/index.test.ts +0 -65
  325. package/src/vocabulary/index.ts +0 -33
  326. package/src/vocabulary/interactive.dispatch.test.tsx +0 -454
  327. package/src/vocabulary/interactive.dom.test.tsx +0 -1747
  328. package/src/vocabulary/interactive.test.tsx +0 -377
  329. package/src/vocabulary/interactive.tsx +0 -1109
  330. package/src/vocabulary/layout.test.tsx +0 -323
  331. package/src/vocabulary/layout.tsx +0 -247
  332. package/src/vocabulary/list.test.tsx +0 -222
  333. package/src/vocabulary/list.tsx +0 -50
  334. package/src/vocabulary/media.test.tsx +0 -85
  335. package/src/vocabulary/media.tsx +0 -56
  336. package/src/vocabulary/text.test.tsx +0 -102
  337. package/src/vocabulary/text.tsx +0 -60
  338. 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
- }
@@ -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
- }