@assistant-ui/react-generative-ui 0.0.7 → 0.0.9

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 (181) hide show
  1. package/dist/JSONGenerativeUI.client.d.ts +0 -1
  2. package/dist/JSONGenerativeUI.client.d.ts.map +1 -1
  3. package/dist/JSONGenerativeUI.server.d.ts +0 -1
  4. package/dist/JSONGenerativeUI.server.d.ts.map +1 -1
  5. package/dist/JSONGenerativeUI.shared.d.ts +0 -1
  6. package/dist/JSONGenerativeUI.shared.d.ts.map +1 -1
  7. package/dist/actionRegistry.d.ts +2 -11
  8. package/dist/actionRegistry.d.ts.map +1 -1
  9. package/dist/actionRegistry.js.map +1 -1
  10. package/dist/buildPresentParameters.d.ts +5 -5
  11. package/dist/buildPresentParameters.d.ts.map +1 -1
  12. package/dist/buildPresentParameters.js +10 -5
  13. package/dist/buildPresentParameters.js.map +1 -1
  14. package/dist/constants.d.ts.map +1 -1
  15. package/dist/defineGenerativeComponents.d.ts +0 -1
  16. package/dist/defineGenerativeComponents.d.ts.map +1 -1
  17. package/dist/generativeUIToJSX.d.ts +15 -10
  18. package/dist/generativeUIToJSX.d.ts.map +1 -1
  19. package/dist/generativeUIToJSX.js +47 -17
  20. package/dist/generativeUIToJSX.js.map +1 -1
  21. package/dist/index.d.ts +4 -3
  22. package/dist/index.js +2 -2
  23. package/dist/index.server.d.ts +4 -3
  24. package/dist/index.server.js +2 -2
  25. package/dist/index.shared.d.ts +3 -3
  26. package/dist/index.shared.js +2 -2
  27. package/dist/ir.d.ts +6 -6
  28. package/dist/ir.d.ts.map +1 -1
  29. package/dist/ir.js +27 -1
  30. package/dist/ir.js.map +1 -1
  31. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts +3 -3
  32. package/dist/node_modules/.pnpm/@types_json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts.map +1 -1
  33. package/dist/renderGenerativeUI.d.ts +0 -1
  34. package/dist/renderGenerativeUI.d.ts.map +1 -1
  35. package/dist/slack/constants.d.ts +111 -0
  36. package/dist/slack/constants.d.ts.map +1 -0
  37. package/dist/slack/constants.js +162 -0
  38. package/dist/slack/constants.js.map +1 -0
  39. package/dist/slack/decodeBlockAction.d.ts +11 -0
  40. package/dist/slack/decodeBlockAction.d.ts.map +1 -0
  41. package/dist/slack/decodeBlockAction.js +40 -0
  42. package/dist/slack/decodeBlockAction.js.map +1 -0
  43. package/dist/slack/fromSlackBlocks.d.ts +30 -0
  44. package/dist/slack/fromSlackBlocks.d.ts.map +1 -0
  45. package/dist/slack/fromSlackBlocks.js +447 -0
  46. package/dist/slack/fromSlackBlocks.js.map +1 -0
  47. package/dist/slack/toSlackBlocks.d.ts +7 -0
  48. package/dist/slack/toSlackBlocks.d.ts.map +1 -0
  49. package/dist/slack/toSlackBlocks.js +649 -0
  50. package/dist/slack/toSlackBlocks.js.map +1 -0
  51. package/dist/slack/types.d.ts +178 -0
  52. package/dist/slack/types.d.ts.map +1 -0
  53. package/dist/slack/types.js +0 -0
  54. package/dist/slack.d.ts +5 -0
  55. package/dist/slack.js +4 -0
  56. package/dist/teams/boundSpec.d.ts +20 -0
  57. package/dist/teams/boundSpec.d.ts.map +1 -0
  58. package/dist/teams/boundSpec.js +67 -0
  59. package/dist/teams/boundSpec.js.map +1 -0
  60. package/dist/teams/constants.d.ts +57 -0
  61. package/dist/teams/constants.d.ts.map +1 -0
  62. package/dist/teams/constants.js +92 -0
  63. package/dist/teams/constants.js.map +1 -0
  64. package/dist/teams/decodeSubmitData.d.ts +25 -0
  65. package/dist/teams/decodeSubmitData.d.ts.map +1 -0
  66. package/dist/teams/decodeSubmitData.js +44 -0
  67. package/dist/teams/decodeSubmitData.js.map +1 -0
  68. package/dist/teams/toAdaptiveCard.d.ts +39 -0
  69. package/dist/teams/toAdaptiveCard.d.ts.map +1 -0
  70. package/dist/teams/toAdaptiveCard.js +496 -0
  71. package/dist/teams/toAdaptiveCard.js.map +1 -0
  72. package/dist/teams/toTeamsAttachments.d.ts +13 -0
  73. package/dist/teams/toTeamsAttachments.d.ts.map +1 -0
  74. package/dist/teams/toTeamsAttachments.js +95 -0
  75. package/dist/teams/toTeamsAttachments.js.map +1 -0
  76. package/dist/teams/types.d.ts +196 -0
  77. package/dist/teams/types.d.ts.map +1 -0
  78. package/dist/teams/types.js +0 -0
  79. package/dist/teams.d.ts +5 -0
  80. package/dist/teams.js +4 -0
  81. package/dist/types.d.ts +7 -4
  82. package/dist/types.d.ts.map +1 -1
  83. package/dist/vocabulary/alert.d.ts +6 -12
  84. package/dist/vocabulary/alert.d.ts.map +1 -1
  85. package/dist/vocabulary/alert.js +13 -4
  86. package/dist/vocabulary/alert.js.map +1 -1
  87. package/dist/vocabulary/collectFormValues.d.ts +23 -0
  88. package/dist/vocabulary/collectFormValues.d.ts.map +1 -0
  89. package/dist/vocabulary/collectFormValues.js +32 -0
  90. package/dist/vocabulary/collectFormValues.js.map +1 -0
  91. package/dist/vocabulary/data.d.ts +16 -17
  92. package/dist/vocabulary/data.d.ts.map +1 -1
  93. package/dist/vocabulary/data.js +244 -13
  94. package/dist/vocabulary/data.js.map +1 -1
  95. package/dist/vocabulary/dispatch.d.ts +11 -0
  96. package/dist/vocabulary/dispatch.d.ts.map +1 -0
  97. package/dist/vocabulary/dispatch.js +21 -0
  98. package/dist/vocabulary/dispatch.js.map +1 -0
  99. package/dist/vocabulary/fact.d.ts +1 -6
  100. package/dist/vocabulary/fact.d.ts.map +1 -1
  101. package/dist/vocabulary/fact.js.map +1 -1
  102. package/dist/vocabulary/form.d.ts +14 -0
  103. package/dist/vocabulary/form.d.ts.map +1 -0
  104. package/dist/vocabulary/form.js +23 -0
  105. package/dist/vocabulary/form.js.map +1 -0
  106. package/dist/vocabulary/icon.d.ts +44 -0
  107. package/dist/vocabulary/icon.d.ts.map +1 -0
  108. package/dist/vocabulary/icon.js +272 -0
  109. package/dist/vocabulary/icon.js.map +1 -0
  110. package/dist/vocabulary/index.d.ts +0 -1
  111. package/dist/vocabulary/index.d.ts.map +1 -1
  112. package/dist/vocabulary/index.js +7 -1
  113. package/dist/vocabulary/index.js.map +1 -1
  114. package/dist/vocabulary/interactive.d.ts +45 -33
  115. package/dist/vocabulary/interactive.d.ts.map +1 -1
  116. package/dist/vocabulary/interactive.js +78 -29
  117. package/dist/vocabulary/interactive.js.map +1 -1
  118. package/dist/vocabulary/layout.d.ts +27 -23
  119. package/dist/vocabulary/layout.d.ts.map +1 -1
  120. package/dist/vocabulary/layout.js +78 -14
  121. package/dist/vocabulary/layout.js.map +1 -1
  122. package/dist/vocabulary/list.d.ts +17 -0
  123. package/dist/vocabulary/list.d.ts.map +1 -0
  124. package/dist/vocabulary/list.js +48 -0
  125. package/dist/vocabulary/list.js.map +1 -0
  126. package/dist/vocabulary/media.d.ts +3 -9
  127. package/dist/vocabulary/media.d.ts.map +1 -1
  128. package/dist/vocabulary/media.js +17 -7
  129. package/dist/vocabulary/media.js.map +1 -1
  130. package/dist/vocabulary/text.d.ts +3 -17
  131. package/dist/vocabulary/text.d.ts.map +1 -1
  132. package/dist/vocabulary/text.js.map +1 -1
  133. package/package.json +15 -7
  134. package/src/actionRegistry.ts +2 -10
  135. package/src/buildPresentParameters.ts +15 -9
  136. package/src/generativeUIToJSX.test.ts +186 -0
  137. package/src/generativeUIToJSX.ts +112 -21
  138. package/src/index.shared.ts +3 -0
  139. package/src/ir.ts +31 -5
  140. package/src/renderGenerativeUI.test.tsx +16 -2
  141. package/src/slack/constants.ts +212 -0
  142. package/src/slack/decodeBlockAction.test.ts +135 -0
  143. package/src/slack/decodeBlockAction.ts +66 -0
  144. package/src/slack/fromSlackBlocks.test.ts +1145 -0
  145. package/src/slack/fromSlackBlocks.ts +709 -0
  146. package/src/slack/toSlackBlocks.test.ts +1936 -0
  147. package/src/slack/toSlackBlocks.ts +1319 -0
  148. package/src/slack/types.ts +230 -0
  149. package/src/slack.ts +37 -0
  150. package/src/teams/boundSpec.ts +102 -0
  151. package/src/teams/constants.ts +127 -0
  152. package/src/teams/decodeSubmitData.test.ts +148 -0
  153. package/src/teams/decodeSubmitData.ts +57 -0
  154. package/src/teams/toAdaptiveCard.test.ts +1410 -0
  155. package/src/teams/toAdaptiveCard.ts +762 -0
  156. package/src/teams/toTeamsAttachments.test.ts +29 -0
  157. package/src/teams/toTeamsAttachments.ts +137 -0
  158. package/src/teams/types.ts +237 -0
  159. package/src/teams.ts +34 -0
  160. package/src/vocabulary/alert.test.tsx +72 -2
  161. package/src/vocabulary/alert.tsx +24 -5
  162. package/src/vocabulary/collectFormValues.test.ts +127 -0
  163. package/src/vocabulary/collectFormValues.ts +58 -0
  164. package/src/vocabulary/data.test.tsx +503 -3
  165. package/src/vocabulary/data.tsx +426 -18
  166. package/src/vocabulary/dispatch.ts +22 -0
  167. package/src/vocabulary/form.test.tsx +112 -0
  168. package/src/vocabulary/form.tsx +34 -0
  169. package/src/vocabulary/icon.test.tsx +64 -0
  170. package/src/vocabulary/icon.tsx +174 -0
  171. package/src/vocabulary/index.test.ts +7 -0
  172. package/src/vocabulary/index.ts +6 -0
  173. package/src/vocabulary/interactive.dispatch.test.tsx +243 -1
  174. package/src/vocabulary/interactive.test.tsx +143 -3
  175. package/src/vocabulary/interactive.tsx +134 -30
  176. package/src/vocabulary/layout.test.tsx +231 -3
  177. package/src/vocabulary/layout.tsx +168 -15
  178. package/src/vocabulary/list.test.tsx +195 -0
  179. package/src/vocabulary/list.tsx +48 -0
  180. package/src/vocabulary/media.test.tsx +36 -4
  181. package/src/vocabulary/media.tsx +27 -8
package/dist/ir.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ir.js","names":[],"sources":["../src/ir.ts"],"sourcesContent":["/**\n * The generative-ui intermediate representation: a model-emitted, cross-platform\n * UI tree. React-free, so converters and non-web runtimes consume it without\n * pulling React. The flat `$type` shape is the canonical form; the legacy\n * `component` shape is accepted as a backward-compatible alias.\n *\n * Reserved keys are partitioned off from component props so the component prop\n * namespace stays fully free:\n *\n * - `$`-prefixed keys are framework-reserved (`$type`, `$key`, `$action`,\n * `$status`). Components never declare `$`-prefixed props, so a component\n * can use `type`, `status`, `variant`, etc. as ordinary props without\n * colliding with the framework.\n * - `children` is additionally reserved (the JSX convention).\n * - every other key is an inline prop passed straight to the component.\n */\n\nimport { TYPE_KEY } from \"./constants\";\n\nexport const TEXT_SIZES = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\"] as const;\nexport type TextSize = (typeof TEXT_SIZES)[number];\n\nexport const IMAGE_SIZE_TOKENS = [\"sm\", \"md\", \"lg\"] as const;\nexport type ImageSize = (typeof IMAGE_SIZE_TOKENS)[number] | number;\n\nexport const WEIGHTS = [\"normal\", \"medium\", \"semibold\", \"bold\"] as const;\nexport type Weight = (typeof WEIGHTS)[number];\n\nexport const COLORS = [\n \"emphasis\",\n \"secondary\",\n \"alpha-70\",\n \"white\",\n \"white-70\",\n \"white-50\",\n] as const;\nexport type Color = (typeof COLORS)[number];\n\nexport const ALIGNS = [\"start\", \"center\", \"end\"] as const;\nexport type Align = (typeof ALIGNS)[number];\n\nexport const JUSTIFIES = [\"start\", \"center\", \"end\", \"between\"] as const;\nexport type Justify = (typeof JUSTIFIES)[number];\n\nexport const BUTTON_STYLES = [\n \"primary\",\n \"secondary\",\n \"outline\",\n \"ghost\",\n \"danger\",\n] as const;\nexport type ButtonStyle = (typeof BUTTON_STYLES)[number];\n\nexport const ALERT_TONES = [\"info\", \"success\", \"warning\", \"danger\"] as const;\n/** Maps to ChatKit `alert` severity levels. */\nexport type AlertTone = (typeof ALERT_TONES)[number];\n\n/**\n * Behavior payload carried by an interactive node. `type` is resolved by the\n * host's action registry, not the renderer; keeping behavior as data keeps the\n * tree serializable so the same node renders on web and converts to a native\n * action id on Slack.\n */\nexport interface Action {\n readonly type: string;\n readonly [payload: string]: unknown;\n}\n\n/**\n * Anything renderable as generative UI, as the model emits it. The renderer\n * also accepts `number`, `boolean`, `null`, `undefined`, and arrays at the\n * input boundary (numbers render as text, falsy/boolean as nothing, arrays as\n * lists); {@link normalizeUINode} accepts that full range.\n */\nexport type UINode = string | number | UIElement | LegacyComponentNode;\n\nexport type UIChildren = UINode | readonly UINode[];\n\n/** The flat node shape: inline props keep the tree compact and natural for a\n * model to emit, instead of a nested `{ type, props }` bag. Reserved keys are\n * stripped before props reach the component (see the module header). */\nexport interface UIElement {\n readonly $type: string;\n readonly $key?: string | number;\n readonly children?: UIChildren;\n readonly $action?: Action;\n readonly [prop: string]: unknown;\n}\n\n/**\n * The legacy node shape: a `component` name plus a nested `props` bag. Kept\n * for backward compatibility. New code authors the flat {@link UIElement}\n * shape instead.\n */\nexport interface LegacyComponentNode {\n readonly component: string;\n readonly props?: Record<string, unknown>;\n readonly children?: UIChildren;\n readonly key?: string;\n}\n\nexport type UISpec = UINode | readonly UINode[];\n\n/**\n * A node normalized to a single canonical shape: a `type` string, an inline\n * `props` bag, recursive `children`, an optional `key`, and an optional\n * `action`. Renderers and platform converters consume this form, so they never\n * branch on whether the model emitted the flat `$type` shape or the legacy\n * `component` shape, and they never see the reserved `$`-prefixed keys leak\n * into component props.\n */\nexport interface NormalizedUIElement {\n readonly type: string;\n readonly props: Readonly<Record<string, unknown>>;\n readonly children?: NormalizedUINode | undefined;\n readonly key?: string | number | undefined;\n readonly action?: Action | undefined;\n}\n\nexport type NormalizedUINode =\n | string\n | number\n | readonly NormalizedUINode[]\n | NormalizedUIElement\n | null;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\ntype LegacyNodeRecord = { component: string } & Record<string, unknown>;\n\nconst isLegacyNode = (\n node: Record<string, unknown>,\n): node is LegacyNodeRecord => typeof node[\"component\"] === \"string\";\n\nconst isTypeNode = (node: Record<string, unknown>): node is UIElement =>\n typeof node[TYPE_KEY] === \"string\";\n\n/** Bounds recursion so a runaway or adversarial model response cannot overflow\n * the stack; past this depth (far beyond any real UI) we stop. */\nconst MAX_DEPTH = 64;\n\n/**\n * Steps a streaming partial path down into `key`. `partialPath` is the remaining\n * segment of the parse meta's partial path relative to `node` (`undefined` once\n * the walk leaves the partial frontier, i.e. everything below is complete).\n */\nfunction descend(\n partialPath: readonly string[] | undefined,\n key: string,\n): readonly string[] | undefined {\n return partialPath?.[0] === key ? partialPath.slice(1) : undefined;\n}\n\n/**\n * Normalizes a generative-ui input to {@link NormalizedUINode}. The flat\n * `$type` shape and the legacy `component` shape both map to the same canonical\n * element, with reserved keys (`$type`, `$key`, `$action`, `children`) stripped\n * from the prop bag. A node that carries neither a `$type` nor a `component`\n * string is not renderable and resolves to `null` rather than throwing, so a\n * partially-streamed or malformed node degrades to \"render nothing\".\n *\n * `partialPath` carries streaming state from the tool-args parse meta: a node\n * whose `$type` is still mid-arrival is held back (resolves to `null`) until it\n * completes, and the path is threaded into `children` so a nested streaming\n * node is held back while completed siblings render. Omit it for a\n * non-streaming (converter) normalize.\n */\nexport function normalizeUINode(\n node: unknown,\n partialPath?: readonly string[] | undefined,\n depth = 0,\n): NormalizedUINode {\n if (depth > MAX_DEPTH) return null;\n if (node == null || typeof node === \"boolean\") return null;\n if (typeof node === \"string\" || typeof node === \"number\") return node;\n if (Array.isArray(node))\n return node.map((child, index) =>\n normalizeUINode(child, descend(partialPath, String(index)), depth + 1),\n );\n if (!isRecord(node)) return null;\n\n // The flat `$type` shape is the canonical form; detect it first so a flat\n // node that happens to use `component` as an ordinary prop is not swallowed\n // by the legacy `component`-shape branch.\n if (isTypeNode(node)) {\n if (partialPath?.length === 1 && partialPath[0] === TYPE_KEY) return null;\n const { [TYPE_KEY]: type, $key, $action, children, ...rest } = node;\n // The `$`-prefixed namespace is framework-reserved (see the module header),\n // so any model-supplied `$`-prefixed key is stripped from the prop bag the\n // component sees. `$type`/`$key`/`$action` are pulled above; sweep the rest\n // (e.g. a stray `$status`) so it never leaks to converters or components.\n const props = stripReservedProps(rest);\n return {\n type,\n props,\n children: normalizeChildren(children, partialPath, depth),\n key: $key,\n action: $action,\n };\n }\n\n if (isLegacyNode(node)) {\n const props = stripReservedProps(\n (node.props ?? {}) as Record<string, unknown>,\n );\n return {\n type: node.component,\n props,\n children: normalizeChildren(node.children, partialPath, depth),\n key: node.key as string | undefined,\n };\n }\n\n return null;\n}\n\nfunction stripReservedProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n let out: Record<string, unknown> | undefined;\n for (const key of Object.keys(props)) {\n if (key.startsWith(\"$\")) {\n out ??= { ...props };\n delete out[key];\n }\n }\n return out ?? props;\n}\n\nfunction normalizeChildren(\n children: unknown,\n partialPath: readonly string[] | undefined,\n depth: number,\n): NormalizedUINode | undefined {\n if (children === undefined) return undefined;\n return normalizeUINode(children, descend(partialPath, \"children\"), depth + 1);\n}\n\n/**\n * Normalizes the root of a {@link UISpec}, preserving whether the root was a\n * single node or a list.\n */\nexport function normalizeSpec(spec: UISpec): {\n readonly root: NormalizedUINode | readonly NormalizedUINode[];\n} {\n if (Array.isArray(spec)) {\n return {\n root: (spec as readonly UINode[]).map((node) => normalizeUINode(node)),\n };\n }\n return { root: normalizeUINode(spec) };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAa,aAAa;CAAC;CAAM;CAAM;CAAM;CAAM;CAAO;AAAK;AAG/D,MAAa,oBAAoB;CAAC;CAAM;CAAM;AAAI;AAGlD,MAAa,UAAU;CAAC;CAAU;CAAU;CAAY;AAAM;AAG9D,MAAa,SAAS;CACpB;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,SAAS;CAAC;CAAS;CAAU;AAAK;AAG/C,MAAa,YAAY;CAAC;CAAS;CAAU;CAAO;AAAS;AAG7D,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,cAAc;CAAC;CAAQ;CAAW;CAAW;AAAQ;AAyElE,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAIrE,MAAM,gBACJ,SAC6B,OAAO,KAAK,iBAAiB;AAE5D,MAAM,cAAc,SAClB,OAAO,KAAK,cAAc;;;AAI5B,MAAM,YAAY;;;;;;AAOlB,SAAS,QACP,aACA,KAC+B;CAC/B,OAAO,cAAc,OAAO,MAAM,YAAY,MAAM,CAAC,IAAI,KAAA;AAC3D;;;;;;;;;;;;;;;AAgBA,SAAgB,gBACd,MACA,aACA,QAAQ,GACU;CAClB,IAAI,QAAQ,WAAW,OAAO;CAC9B,IAAI,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;CACtD,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU,OAAO;CACjE,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,KAAK,KAAK,OAAO,UACtB,gBAAgB,OAAO,QAAQ,aAAa,OAAO,KAAK,CAAC,GAAG,QAAQ,CAAC,CACvE;CACF,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO;CAK5B,IAAI,WAAW,IAAI,GAAG;EACpB,IAAI,aAAa,WAAW,KAAK,YAAY,OAAA,SAAiB,OAAO;EACrE,MAAM,GAAG,WAAW,MAAM,MAAM,SAAS,UAAU,GAAG,SAAS;EAM/D,OAAO;GACL;GACA,OAHY,mBAAmB,IAG3B;GACJ,UAAU,kBAAkB,UAAU,aAAa,KAAK;GACxD,KAAK;GACL,QAAQ;EACV;CACF;CAEA,IAAI,aAAa,IAAI,GAAG;EACtB,MAAM,QAAQ,mBACX,KAAK,SAAS,CAAC,CAClB;EACA,OAAO;GACL,MAAM,KAAK;GACX;GACA,UAAU,kBAAkB,KAAK,UAAU,aAAa,KAAK;GAC7D,KAAK,KAAK;EACZ;CACF;CAEA,OAAO;AACT;AAEA,SAAS,mBACP,OACyB;CACzB,IAAI;CACJ,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GACjC,IAAI,IAAI,WAAW,GAAG,GAAG;EACvB,QAAQ,EAAE,GAAG,MAAM;EACnB,OAAO,IAAI;CACb;CAEF,OAAO,OAAO;AAChB;AAEA,SAAS,kBACP,UACA,aACA,OAC8B;CAC9B,IAAI,aAAa,KAAA,GAAW,OAAO,KAAA;CACnC,OAAO,gBAAgB,UAAU,QAAQ,aAAa,UAAU,GAAG,QAAQ,CAAC;AAC9E;;;;;AAMA,SAAgB,cAAc,MAE5B;CACA,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,EACL,MAAO,KAA2B,KAAK,SAAS,gBAAgB,IAAI,CAAC,EACvE;CAEF,OAAO,EAAE,MAAM,gBAAgB,IAAI,EAAE;AACvC"}
1
+ {"version":3,"file":"ir.js","names":[],"sources":["../src/ir.ts"],"sourcesContent":["/**\n * The generative-ui intermediate representation: a model-emitted, cross-platform\n * UI tree. React-free, so converters and non-web runtimes consume it without\n * pulling React. The flat `$type` shape is the canonical form; the legacy\n * `component` shape is accepted as a backward-compatible alias.\n *\n * Reserved keys are partitioned off from component props so the component prop\n * namespace stays fully free:\n *\n * - `$`-prefixed keys are framework-reserved (`$type`, `$key`, `$action`,\n * `$status`). Components never declare `$`-prefixed props, so a component\n * can use `type`, `status`, `variant`, etc. as ordinary props without\n * colliding with the framework.\n * - `children` is additionally reserved (the JSX convention).\n * - every other key is an inline prop passed straight to the component.\n */\n\nimport { TYPE_KEY } from \"./constants\";\n\nexport const TEXT_SIZES = [\"sm\", \"md\", \"lg\", \"xl\", \"2xl\", \"3xl\"] as const;\nexport type TextSize = (typeof TEXT_SIZES)[number];\n\nexport const IMAGE_SIZE_TOKENS = [\"sm\", \"md\", \"lg\"] as const;\nexport type ImageSize = (typeof IMAGE_SIZE_TOKENS)[number] | number;\n\nexport const WEIGHTS = [\"normal\", \"medium\", \"semibold\", \"bold\"] as const;\nexport type Weight = (typeof WEIGHTS)[number];\n\nexport const COLORS = [\n \"emphasis\",\n \"secondary\",\n \"alpha-70\",\n \"white\",\n \"white-70\",\n \"white-50\",\n] as const;\nexport type Color = (typeof COLORS)[number];\n\nexport const ALIGNS = [\"start\", \"center\", \"end\"] as const;\nexport type Align = (typeof ALIGNS)[number];\n\nexport const JUSTIFIES = [\"start\", \"center\", \"end\", \"between\"] as const;\nexport type Justify = (typeof JUSTIFIES)[number];\n\nexport const BUTTON_STYLES = [\n \"primary\",\n \"secondary\",\n \"outline\",\n \"ghost\",\n \"danger\",\n] as const;\nexport type ButtonStyle = (typeof BUTTON_STYLES)[number];\n\nexport const ALERT_TONES = [\"info\", \"success\", \"warning\", \"danger\"] as const;\n/** A severity level, from informational to destructive. */\nexport type AlertTone = (typeof ALERT_TONES)[number];\n\nexport const ICON_NAMES = [\n \"sun\",\n \"moon\",\n \"cloud\",\n \"rain\",\n \"snow\",\n \"wind\",\n \"play\",\n \"pause\",\n \"check\",\n \"x\",\n \"star\",\n \"heart\",\n \"arrow-right\",\n \"arrow-up-right\",\n \"chevron-right\",\n \"calendar\",\n \"clock\",\n \"map-pin\",\n \"plane\",\n \"truck\",\n \"credit-card\",\n \"user\",\n \"search\",\n \"bell\",\n] as const;\n/** A name from the built-in icon set; the closed enum lets the model see exactly which icons exist. */\nexport type IconName = (typeof ICON_NAMES)[number];\n\n/**\n * Behavior payload carried by an interactive node. `type` is resolved by the host's action registry, not the renderer; keeping behavior as data keeps the tree serializable, so the same node renders on web while converters may bind the type to a native action id on other platforms.\n */\nexport interface Action {\n readonly type: string;\n readonly [payload: string]: unknown;\n}\n\n/**\n * Anything renderable as generative UI, as the model emits it. The renderer\n * also accepts `number`, `boolean`, `null`, `undefined`, and arrays at the\n * input boundary (numbers render as text, falsy/boolean as nothing, arrays as\n * lists); {@link normalizeUINode} accepts that full range.\n */\nexport type UINode = string | number | UIElement | LegacyComponentNode;\n\nexport type UIChildren = UINode | readonly UINode[];\n\n/** The flat node shape: inline props keep the tree compact and natural for a\n * model to emit, instead of a nested `{ type, props }` bag. Reserved keys are\n * stripped before props reach the component (see the module header). */\nexport interface UIElement {\n readonly $type: string;\n readonly $key?: string | number;\n readonly children?: UIChildren;\n readonly $action?: Action;\n readonly [prop: string]: unknown;\n}\n\n/**\n * The legacy node shape: a `component` name plus a nested `props` bag. Kept\n * for backward compatibility. New code authors the flat {@link UIElement}\n * shape instead.\n */\nexport interface LegacyComponentNode {\n readonly component: string;\n readonly props?: Record<string, unknown>;\n readonly children?: UIChildren;\n readonly key?: string;\n}\n\nexport type UISpec = UINode | readonly UINode[];\n\n/**\n * A node normalized to a single canonical shape: a `type` string, an inline\n * `props` bag, recursive `children`, an optional `key`, and an optional\n * `action`. Renderers and platform converters consume this form, so they never\n * branch on whether the model emitted the flat `$type` shape or the legacy\n * `component` shape, and they never see the reserved `$`-prefixed keys leak\n * into component props.\n */\nexport interface NormalizedUIElement {\n readonly type: string;\n readonly props: Readonly<Record<string, unknown>>;\n readonly children?: NormalizedUINode | undefined;\n readonly key?: string | number | undefined;\n readonly action?: Action | undefined;\n}\n\nexport type NormalizedUINode =\n | string\n | number\n | readonly NormalizedUINode[]\n | NormalizedUIElement\n | null;\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\ntype LegacyNodeRecord = { component: string } & Record<string, unknown>;\n\nconst isLegacyNode = (\n node: Record<string, unknown>,\n): node is LegacyNodeRecord => typeof node[\"component\"] === \"string\";\n\nconst isTypeNode = (node: Record<string, unknown>): node is UIElement =>\n typeof node[TYPE_KEY] === \"string\";\n\n/** Bounds recursion so a runaway or adversarial model response cannot overflow\n * the stack; past this depth (far beyond any real UI) we stop. */\nconst MAX_DEPTH = 64;\n\n/**\n * Steps a streaming partial path down into `key`. `partialPath` is the remaining\n * segment of the parse meta's partial path relative to `node` (`undefined` once\n * the walk leaves the partial frontier, i.e. everything below is complete).\n */\nfunction descend(\n partialPath: readonly string[] | undefined,\n key: string,\n): readonly string[] | undefined {\n return partialPath?.[0] === key ? partialPath.slice(1) : undefined;\n}\n\n/**\n * Normalizes a generative-ui input to {@link NormalizedUINode}. The flat\n * `$type` shape and the legacy `component` shape both map to the same canonical\n * element, with reserved keys (`$type`, `$key`, `$action`, `children`) stripped\n * from the prop bag. A node that carries neither a `$type` nor a `component`\n * string is not renderable and resolves to `null` rather than throwing, so a\n * partially-streamed or malformed node degrades to \"render nothing\".\n *\n * `partialPath` carries streaming state from the tool-args parse meta: a node\n * whose `$type` is still mid-arrival is held back (resolves to `null`) until it\n * completes, and the path is threaded into `children` so a nested streaming\n * node is held back while completed siblings render. Omit it for a\n * non-streaming (converter) normalize.\n */\nexport function normalizeUINode(\n node: unknown,\n partialPath?: readonly string[] | undefined,\n depth = 0,\n): NormalizedUINode {\n if (depth > MAX_DEPTH) return null;\n if (node == null || typeof node === \"boolean\") return null;\n if (typeof node === \"string\" || typeof node === \"number\") return node;\n if (Array.isArray(node))\n return node.map((child, index) =>\n normalizeUINode(child, descend(partialPath, String(index)), depth + 1),\n );\n if (!isRecord(node)) return null;\n\n // The flat `$type` shape is the canonical form; detect it first so a flat\n // node that happens to use `component` as an ordinary prop is not swallowed\n // by the legacy `component`-shape branch.\n if (isTypeNode(node)) {\n if (partialPath?.length === 1 && partialPath[0] === TYPE_KEY) return null;\n const { [TYPE_KEY]: type, $key, $action, children, ...rest } = node;\n // The `$`-prefixed namespace is framework-reserved (see the module header),\n // so any model-supplied `$`-prefixed key is stripped from the prop bag the\n // component sees. `$type`/`$key`/`$action` are pulled above; sweep the rest\n // (e.g. a stray `$status`) so it never leaks to converters or components.\n const props = stripReservedProps(rest);\n return {\n type,\n props,\n children: normalizeChildren(children, partialPath, depth),\n key: $key,\n action: $action,\n };\n }\n\n if (isLegacyNode(node)) {\n const props = stripReservedProps(\n (node.props ?? {}) as Record<string, unknown>,\n );\n return {\n type: node.component,\n props,\n children: normalizeChildren(node.children, partialPath, depth),\n key: node.key as string | undefined,\n };\n }\n\n return null;\n}\n\nfunction stripReservedProps(\n props: Record<string, unknown>,\n): Record<string, unknown> {\n let out: Record<string, unknown> | undefined;\n for (const key of Object.keys(props)) {\n if (key.startsWith(\"$\")) {\n out ??= { ...props };\n delete out[key];\n }\n }\n return out ?? props;\n}\n\nfunction normalizeChildren(\n children: unknown,\n partialPath: readonly string[] | undefined,\n depth: number,\n): NormalizedUINode | undefined {\n if (children === undefined) return undefined;\n return normalizeUINode(children, descend(partialPath, \"children\"), depth + 1);\n}\n\n/**\n * Normalizes the root of a {@link UISpec}, preserving whether the root was a\n * single node or a list.\n */\nexport function normalizeSpec(spec: UISpec): {\n readonly root: NormalizedUINode | readonly NormalizedUINode[];\n} {\n if (Array.isArray(spec)) {\n return {\n root: (spec as readonly UINode[]).map((node) => normalizeUINode(node)),\n };\n }\n return { root: normalizeUINode(spec) };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAmBA,MAAa,aAAa;CAAC;CAAM;CAAM;CAAM;CAAM;CAAO;AAAK;AAG/D,MAAa,oBAAoB;CAAC;CAAM;CAAM;AAAI;AAGlD,MAAa,UAAU;CAAC;CAAU;CAAU;CAAY;AAAM;AAG9D,MAAa,SAAS;CACpB;CACA;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,SAAS;CAAC;CAAS;CAAU;AAAK;AAG/C,MAAa,YAAY;CAAC;CAAS;CAAU;CAAO;AAAS;AAG7D,MAAa,gBAAgB;CAC3B;CACA;CACA;CACA;CACA;AACF;AAGA,MAAa,cAAc;CAAC;CAAQ;CAAW;CAAW;AAAQ;AAIlE,MAAa,aAAa;CACxB;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;AACF;AAsEA,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAIrE,MAAM,gBACJ,SAC6B,OAAO,KAAK,iBAAiB;AAE5D,MAAM,cAAc,SAClB,OAAO,KAAK,cAAc;;;AAI5B,MAAM,YAAY;;;;;;AAOlB,SAAS,QACP,aACA,KAC+B;CAC/B,OAAO,cAAc,OAAO,MAAM,YAAY,MAAM,CAAC,IAAI,KAAA;AAC3D;;;;;;;;;;;;;;;AAgBA,SAAgB,gBACd,MACA,aACA,QAAQ,GACU;CAClB,IAAI,QAAQ,WAAW,OAAO;CAC9B,IAAI,QAAQ,QAAQ,OAAO,SAAS,WAAW,OAAO;CACtD,IAAI,OAAO,SAAS,YAAY,OAAO,SAAS,UAAU,OAAO;CACjE,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,KAAK,KAAK,OAAO,UACtB,gBAAgB,OAAO,QAAQ,aAAa,OAAO,KAAK,CAAC,GAAG,QAAQ,CAAC,CACvE;CACF,IAAI,CAAC,SAAS,IAAI,GAAG,OAAO;CAK5B,IAAI,WAAW,IAAI,GAAG;EACpB,IAAI,aAAa,WAAW,KAAK,YAAY,OAAA,SAAiB,OAAO;EACrE,MAAM,GAAG,WAAW,MAAM,MAAM,SAAS,UAAU,GAAG,SAAS;EAM/D,OAAO;GACL;GACA,OAHY,mBAAmB,IAG3B;GACJ,UAAU,kBAAkB,UAAU,aAAa,KAAK;GACxD,KAAK;GACL,QAAQ;EACV;CACF;CAEA,IAAI,aAAa,IAAI,GAAG;EACtB,MAAM,QAAQ,mBACX,KAAK,SAAS,CAAC,CAClB;EACA,OAAO;GACL,MAAM,KAAK;GACX;GACA,UAAU,kBAAkB,KAAK,UAAU,aAAa,KAAK;GAC7D,KAAK,KAAK;EACZ;CACF;CAEA,OAAO;AACT;AAEA,SAAS,mBACP,OACyB;CACzB,IAAI;CACJ,KAAK,MAAM,OAAO,OAAO,KAAK,KAAK,GACjC,IAAI,IAAI,WAAW,GAAG,GAAG;EACvB,QAAQ,EAAE,GAAG,MAAM;EACnB,OAAO,IAAI;CACb;CAEF,OAAO,OAAO;AAChB;AAEA,SAAS,kBACP,UACA,aACA,OAC8B;CAC9B,IAAI,aAAa,KAAA,GAAW,OAAO,KAAA;CACnC,OAAO,gBAAgB,UAAU,QAAQ,aAAa,UAAU,GAAG,QAAQ,CAAC;AAC9E;;;;;AAMA,SAAgB,cAAc,MAE5B;CACA,IAAI,MAAM,QAAQ,IAAI,GACpB,OAAO,EACL,MAAO,KAA2B,KAAK,SAAS,gBAAgB,IAAI,CAAC,EACvE;CAEF,OAAO,EAAE,MAAM,gBAAgB,IAAI,EAAE;AACvC"}
@@ -9,13 +9,13 @@
9
9
  * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
10
10
  */
11
11
  type JSONSchema7TypeName = "string" //
12
- | "number" | "integer" | "boolean" | "object" | "array" | "null";
12
+ | "number" | "integer" | "boolean" | "object" | "array" | "null";
13
13
  /**
14
14
  * Primitive type
15
15
  * @see https://tools.ietf.org/html/draft-handrews-json-schema-validation-01#section-6.1.1
16
16
  */
17
17
  type JSONSchema7Type = string //
18
- | number | boolean | JSONSchema7Object | JSONSchema7Array | null;
18
+ | number | boolean | JSONSchema7Object | JSONSchema7Array | null;
19
19
  // Workaround for infinite type recursion
20
20
  interface JSONSchema7Object {
21
21
  [key: string]: JSONSchema7Type;
@@ -137,5 +137,5 @@ interface JSONSchema7 {
137
137
  examples?: JSONSchema7Type | undefined;
138
138
  }
139
139
  //#endregion
140
- export { JSONSchema7 };
140
+ export { JSONSchema7, JSONSchema7Array, JSONSchema7Definition, JSONSchema7Object, JSONSchema7Type, JSONSchema7TypeName, JSONSchema7Version };
141
141
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","names":["JSONSchema4Object","JSONSchema4Array","key","JSONSchema4Type","Array","id","$ref","$schema","JSONSchema4Version","title","description","default","multipleOf","maximum","exclusiveMaximum","minimum","exclusiveMinimum","maxLength","minLength","pattern","additionalItems","JSONSchema4","items","maxItems","minItems","uniqueItems","maxProperties","minProperties","required","additionalProperties","definitions","k","properties","patternProperties","dependencies","enum","type","JSONSchema4TypeName","allOf","anyOf","oneOf","not","extends","format","JSONSchema6Object","JSONSchema6Array","JSONSchema6Type","JSONSchema6","$id","JSONSchema6Version","JSONSchema6Definition","contains","propertyNames","const","JSONSchema6TypeName","examples","JSONSchema7Object","JSONSchema7Array","JSONSchema7Type","JSONSchema7","JSONSchema7Version","$comment","$defs","JSONSchema7Definition","JSONSchema7TypeName","if","then","else","contentMediaType","contentEncoding","readOnly","writeOnly","valid","errors","ValidationError","property","message","instance","schema","ValidationResult","value","result"],"sources":["../../../../../../../../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;KA+iBY,mBAAA;AAAA;;;;;KAaA,eAAA;AAAA,qBAIN,iBAAA,GACA,gBAAgB;AAAA;AAAA,UAIL,iBAAA;EAAA,CACZE,GAAAA,WAAc,eAAe;AAAA;AAAA;AAAA;AAAA,UAKjB,gBAAA,SAAyB,KAAK,CAAC,eAAA;;;;;;;;;;;;KAapC,kBAAA;;;;;KAMA,qBAAA,GAAwB,WAAW;AAAA,UAC9B,WAAA;EACb8C,GAAAA;EACA1C,IAAAA;EACAC,OAAAA,GAAU,kBAAA;EACVsD,QAAAA;;;;;EAMAC,KAAAA;IAAAA,CACK5D,GAAAA,WAAc,qBAAA;EAAA;;;;EAMnBkC,IAAAA,GAAO,mBAAA,GAAsB,mBAAA;EAC7BD,IAAAA,GAAO,eAAA;EACPkB,KAAAA,GAAQ,eAAA;;;;EAKRzC,UAAAA;EACAC,OAAAA;EACAC,gBAAAA;EACAC,OAAAA;EACAC,gBAAAA;;;;EAKAC,SAAAA;EACAC,SAAAA;EACAC,OAAAA;;;;EAKAG,KAAAA,GAAQ,qBAAA,GAAwB,qBAAA;EAChCF,eAAAA,GAAkB,qBAAA;EAClBG,QAAAA;EACAC,QAAAA;EACAC,WAAAA;EACA0B,QAAAA,GAAW,qBAAA;;;;EAKXzB,aAAAA;EACAC,aAAAA;EACAC,QAAAA;EACAI,UAAAA;IAAAA,CACK9B,GAAAA,WAAc,qBAAA;EAAA;EAEnB+B,iBAAAA;IAAAA,CACK/B,GAAAA,WAAc,qBAAA;EAAA;EAEnB2B,oBAAAA,GAAuB,qBAAA;EACvBK,YAAAA;IAAAA,CACKhC,GAAAA,WAAc,qBAAA;EAAA;EAEnBkD,aAAAA,GAAgB,qBAAA;;;;EAKhBa,EAAAA,GAAK,qBAAA;EACLC,IAAAA,GAAO,qBAAA;EACPC,IAAAA,GAAO,qBAAA;;;;EAKP7B,KAAAA,GAAQ,qBAAA;EACRC,KAAAA,GAAQ,qBAAA;EACRC,KAAAA,GAAQ,qBAAA;EACRC,GAAAA,GAAM,qBAAA;;;;EAKNE,MAAAA;;;;EAKAyB,gBAAAA;EACAC,eAAAA;;;;EAKAvC,WAAAA;IAAAA,CACK5B,GAAAA,WAAc,qBAAA;EAAA;;;;EAMnBO,KAAAA;EACAC,WAAAA;EACAC,OAAAA,GAAU,eAAA;EACV2D,QAAAA;EACAC,SAAAA;EACAhB,QAAAA,GAAW,eAAA;AAAA"}
1
+ {"version":3,"file":"index.d.ts","names":[],"sources":["../../../../../../../../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts"],"x_google_ignoreList":[0],"mappings":";;;;;;;;;;KA+iBY;;;;;;KAaA;sBAIN,oBACA;;UAIW;GACZ,cAAc;;;;UAKF,yBAAyB,MAAM;;;;;;;;;;;;KAapC;;;;;KAMA,wBAAwB;UACnB;EACb;EACA;EACA,UAAU;EACV;;;;;EAMA;KACK,cAAc;;;;;EAMnB,OAAO,sBAAsB;EAC7B,OAAO;EACP,QAAQ;;;;EAKR;EACA;EACA;EACA;EACA;;;;EAKA;EACA;EACA;;;;EAKA,QAAQ,wBAAwB;EAChC,kBAAkB;EAClB;EACA;EACA;EACA,WAAW;;;;EAKX;EACA;EACA;EACA;KACK,cAAc;;EAEnB;KACK,cAAc;;EAEnB,uBAAuB;EACvB;KACK,cAAc;;EAEnB,gBAAgB;;;;EAKhB,KAAK;EACL,OAAO;EACP,OAAO;;;;EAKP,QAAQ;EACR,QAAQ;EACR,QAAQ;EACR,MAAM;;;;EAKN;;;;EAKA;EACA;;;;EAKA;KACK,cAAc;;;;;EAMnB;EACA;EACA,UAAU;EACV;EACA;EACA,WAAW"}
@@ -1,6 +1,5 @@
1
1
  import { GenerativeUILibrary, GenerativeUIRenderContext } from "./types.js";
2
2
  import { ReactNode } from "react";
3
-
4
3
  //#region src/renderGenerativeUI.d.ts
5
4
  /**
6
5
  * Renders a generative-ui tree against a {@link GenerativeUILibrary}.
@@ -1 +1 @@
1
- {"version":3,"file":"renderGenerativeUI.d.ts","names":[],"sources":["../src/renderGenerativeUI.tsx"],"mappings":";;;;;;AAwBA;;;;;;;;iBAAgB,kBAAA,CACd,IAAA,WACA,OAAA,EAAS,mBAAA,EACT,OAAA,GAAS,yBAAA,GACR,SAAA"}
1
+ {"version":3,"file":"renderGenerativeUI.d.ts","names":[],"sources":["../src/renderGenerativeUI.tsx"],"mappings":";;;;;;;;;;;;;iBAwBgB,mBACd,eACA,SAAS,qBACT,UAAS,4BACR"}
@@ -0,0 +1,111 @@
1
+ import { SlackAlertBlock, SlackButtonElement, SlackCardBlock, SlackCarouselBlock, SlackContextBlock, SlackDataTableBlock, SlackDataTableCell, SlackImageBlock, SlackSectionBlock, SlackTextObject } from "./types.js";
2
+ //#region src/slack/constants.d.ts
3
+ /** The maximum normalized traversal depth. */
4
+ declare const MAX_TRAVERSAL_DEPTH = 64;
5
+ /**
6
+ * The maximum number of entries kept at any single level (root, or a
7
+ * `children` array at any depth) of the raw spec, before it ever reaches
8
+ * `normalizeSpec`. Bounds a hostile array's reported `length` so the pre-pass
9
+ * can never be made to walk further than this regardless of what the array
10
+ * claims about itself.
11
+ */
12
+ declare const CHILDREN_CAP = 200;
13
+ /**
14
+ * The total number of nodes the pre-normalization bounding walk will visit
15
+ * across one call, regardless of how many times a shared reference recurs.
16
+ * Bounds the combinatorial work a DAG of shared or self-referential nodes
17
+ * would otherwise force even though each individual array stays within
18
+ * {@link CHILDREN_CAP}.
19
+ */
20
+ declare const NODE_BUDGET = 5000;
21
+ /** The block limit for a Slack message. */
22
+ declare const MESSAGE_BLOCK_CAP = 50;
23
+ /** The block limit for a Slack modal. */
24
+ declare const MODAL_BLOCK_CAP = 100;
25
+ /**
26
+ * The maximum number of top-level blocks accepted when parsing Slack Block
27
+ * Kit JSON back into generative UI, guarding against a hostile or malformed
28
+ * payload.
29
+ */
30
+ declare const INBOUND_BLOCK_CAP = 200;
31
+ /** The character limit for header text. */
32
+ declare const HEADER_TEXT_CAP = 150;
33
+ /** The character limit for section text. */
34
+ declare const SECTION_TEXT_CAP = 3000;
35
+ /** The maximum number of fields in one section. */
36
+ declare const FACT_FIELD_CAP = 10;
37
+ /** The character limit for one section field. */
38
+ declare const FACT_FIELD_TEXT_CAP = 2000;
39
+ /** The character limit for button labels and option labels. */
40
+ declare const INTERACTIVE_TEXT_CAP = 75;
41
+ /** The character limit for an action_id. */
42
+ declare const ACTION_ID_CAP = 255;
43
+ /** The character limit for a button's serialized value payload. */
44
+ declare const BUTTON_VALUE_CAP = 2000;
45
+ /** The maximum number of elements in one actions block. */
46
+ declare const ACTIONS_ELEMENT_CAP = 25;
47
+ /** The maximum number of options in a static select. */
48
+ declare const SELECT_OPTION_CAP = 100;
49
+ /** The maximum number of options in a radio-button group. */
50
+ declare const RADIO_OPTION_CAP = 10;
51
+ /** The character limit for a select or input placeholder. */
52
+ declare const PLACEHOLDER_TEXT_CAP = 150;
53
+ /** The character limit for an input's label. */
54
+ declare const INPUT_LABEL_CAP = 2000;
55
+ /** The maximum number of elements in one context block. */
56
+ declare const CONTEXT_ELEMENT_CAP = 10;
57
+ /** The character limit for one context element's text. */
58
+ declare const CONTEXT_TEXT_CAP = 3000;
59
+ /** The character limit for card titles and subtitles. */
60
+ declare const CARD_TITLE_CAP = 150;
61
+ /** The character limit for a card's body text. */
62
+ declare const CARD_BODY_CAP = 200;
63
+ /** The character limit for a card's subtext. */
64
+ declare const CARD_SUBTEXT_CAP = 200;
65
+ /** The maximum number of buttons in a card's actions. */
66
+ declare const CARD_ACTIONS_CAP = 3;
67
+ /** The minimum number of elements in a renderable carousel. */
68
+ declare const CAROUSEL_CARD_MIN = 1;
69
+ /** The maximum number of elements in a carousel. */
70
+ declare const CAROUSEL_CARD_CAP = 10;
71
+ /** The character limit for an alert's text. */
72
+ declare const ALERT_TEXT_CAP = 200;
73
+ /**
74
+ * The maximum number of data rows in a data-table block; the emitted `rows`
75
+ * array additionally carries one header row.
76
+ */
77
+ declare const DATA_TABLE_ROW_CAP = 100;
78
+ /** The maximum number of columns in a data-table block. */
79
+ declare const DATA_TABLE_COLUMN_CAP = 20;
80
+ /**
81
+ * The cumulative character limit (summed across every cell's text) shared by
82
+ * every data-table block in one payload.
83
+ */
84
+ declare const DATA_TABLE_CHAR_BUDGET = 10000;
85
+ /** The caption emitted on every native data-table block. */
86
+ declare const TABLE_CAPTION = "Table";
87
+ /** The cumulative character limit for native markdown blocks. */
88
+ declare const MARKDOWN_TEXT_BUDGET = 12000;
89
+ /** Builds the message-surface fallback for an alert. */
90
+ declare function buildAlertFallback(title: string, description: string, tone: "info" | "success" | "warning" | "danger"): readonly [SlackContextBlock, SlackSectionBlock];
91
+ /** Builds a 2026 Slack modal-only alert block, mapping `tone` to its `level`. */
92
+ declare function buildAlertBlock(text: string, tone: "info" | "success" | "warning" | "danger"): SlackAlertBlock;
93
+ type CardBlockFields = {
94
+ readonly heroImage?: SlackImageBlock;
95
+ readonly title?: SlackTextObject;
96
+ readonly subtitle?: SlackTextObject;
97
+ readonly body?: SlackTextObject;
98
+ readonly subtext?: SlackTextObject;
99
+ readonly actions?: readonly SlackButtonElement[];
100
+ };
101
+ /** Builds a 2026 Slack card block from its already-clamped fields. */
102
+ declare function buildCardBlock(fields: CardBlockFields): SlackCardBlock;
103
+ /** Builds a 2026 Slack carousel block. */
104
+ declare function buildCarouselBlock(elements: readonly SlackCardBlock[]): SlackCarouselBlock;
105
+ /** Builds a 2026 Slack data-table block; `rows[0]` must be the header row. */
106
+ declare function buildDataTableBlock(rows: readonly (readonly SlackDataTableCell[])[]): SlackDataTableBlock;
107
+ /** Builds the final note used when a surface block budget is exceeded. */
108
+ declare function buildBlockBudgetNote(omitted: number): SlackContextBlock;
109
+ //#endregion
110
+ export { ACTIONS_ELEMENT_CAP, ACTION_ID_CAP, ALERT_TEXT_CAP, BUTTON_VALUE_CAP, CARD_ACTIONS_CAP, CARD_BODY_CAP, CARD_SUBTEXT_CAP, CARD_TITLE_CAP, CAROUSEL_CARD_CAP, CAROUSEL_CARD_MIN, CHILDREN_CAP, CONTEXT_ELEMENT_CAP, CONTEXT_TEXT_CAP, DATA_TABLE_CHAR_BUDGET, DATA_TABLE_COLUMN_CAP, DATA_TABLE_ROW_CAP, FACT_FIELD_CAP, FACT_FIELD_TEXT_CAP, HEADER_TEXT_CAP, INBOUND_BLOCK_CAP, INPUT_LABEL_CAP, INTERACTIVE_TEXT_CAP, MARKDOWN_TEXT_BUDGET, MAX_TRAVERSAL_DEPTH, MESSAGE_BLOCK_CAP, MODAL_BLOCK_CAP, NODE_BUDGET, PLACEHOLDER_TEXT_CAP, RADIO_OPTION_CAP, SECTION_TEXT_CAP, SELECT_OPTION_CAP, TABLE_CAPTION, buildAlertBlock, buildAlertFallback, buildBlockBudgetNote, buildCardBlock, buildCarouselBlock, buildDataTableBlock };
111
+ //# sourceMappingURL=constants.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.d.ts","names":[],"sources":["../../src/slack/constants.ts"],"mappings":";;;cAca;;;;;;;;cASA;;;;;;;;cASA;;cAGA;;cAGA;;;;;;cAOA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;cAGA;;;;;cAMA;;cAGA;;;;;cAMA;;cAGA;;cAGA;;iBAGG,mBACd,eACA,qBACA,4DACW,mBAAmB;;iBAmBhB,gBACd,cACA,kDACC;KAKE;WACM,YAAY;WACZ,QAAQ;WACR,WAAW;WACX,OAAO;WACP,UAAU;WACV,mBAAmB;;;iBAId,eAAe,QAAQ,kBAAkB;;iBAczC,mBACd,mBAAmB,mBAClB;;iBAKa,oBACd,yBAAyB,0BACxB;;iBAKa,qBAAqB,kBAAkB"}
@@ -0,0 +1,162 @@
1
+ //#region src/slack/constants.ts
2
+ /** The maximum normalized traversal depth. */
3
+ const MAX_TRAVERSAL_DEPTH = 64;
4
+ /**
5
+ * The maximum number of entries kept at any single level (root, or a
6
+ * `children` array at any depth) of the raw spec, before it ever reaches
7
+ * `normalizeSpec`. Bounds a hostile array's reported `length` so the pre-pass
8
+ * can never be made to walk further than this regardless of what the array
9
+ * claims about itself.
10
+ */
11
+ const CHILDREN_CAP = 200;
12
+ /**
13
+ * The total number of nodes the pre-normalization bounding walk will visit
14
+ * across one call, regardless of how many times a shared reference recurs.
15
+ * Bounds the combinatorial work a DAG of shared or self-referential nodes
16
+ * would otherwise force even though each individual array stays within
17
+ * {@link CHILDREN_CAP}.
18
+ */
19
+ const NODE_BUDGET = 5e3;
20
+ /** The block limit for a Slack message. */
21
+ const MESSAGE_BLOCK_CAP = 50;
22
+ /** The block limit for a Slack modal. */
23
+ const MODAL_BLOCK_CAP = 100;
24
+ /**
25
+ * The maximum number of top-level blocks accepted when parsing Slack Block
26
+ * Kit JSON back into generative UI, guarding against a hostile or malformed
27
+ * payload.
28
+ */
29
+ const INBOUND_BLOCK_CAP = 200;
30
+ /** The character limit for header text. */
31
+ const HEADER_TEXT_CAP = 150;
32
+ /** The character limit for section text. */
33
+ const SECTION_TEXT_CAP = 3e3;
34
+ /** The maximum number of fields in one section. */
35
+ const FACT_FIELD_CAP = 10;
36
+ /** The character limit for one section field. */
37
+ const FACT_FIELD_TEXT_CAP = 2e3;
38
+ /** The character limit for button labels and option labels. */
39
+ const INTERACTIVE_TEXT_CAP = 75;
40
+ /** The character limit for an action_id. */
41
+ const ACTION_ID_CAP = 255;
42
+ /** The character limit for a button's serialized value payload. */
43
+ const BUTTON_VALUE_CAP = 2e3;
44
+ /** The maximum number of elements in one actions block. */
45
+ const ACTIONS_ELEMENT_CAP = 25;
46
+ /** The maximum number of options in a static select. */
47
+ const SELECT_OPTION_CAP = 100;
48
+ /** The maximum number of options in a radio-button group. */
49
+ const RADIO_OPTION_CAP = 10;
50
+ /** The character limit for a select or input placeholder. */
51
+ const PLACEHOLDER_TEXT_CAP = 150;
52
+ /** The character limit for an input's label. */
53
+ const INPUT_LABEL_CAP = 2e3;
54
+ /** The maximum number of elements in one context block. */
55
+ const CONTEXT_ELEMENT_CAP = 10;
56
+ /** The character limit for one context element's text. */
57
+ const CONTEXT_TEXT_CAP = 3e3;
58
+ /** The character limit for card titles and subtitles. */
59
+ const CARD_TITLE_CAP = 150;
60
+ /** The character limit for a card's body text. */
61
+ const CARD_BODY_CAP = 200;
62
+ /** The character limit for a card's subtext. */
63
+ const CARD_SUBTEXT_CAP = 200;
64
+ /** The maximum number of buttons in a card's actions. */
65
+ const CARD_ACTIONS_CAP = 3;
66
+ /** The minimum number of elements in a renderable carousel. */
67
+ const CAROUSEL_CARD_MIN = 1;
68
+ /** The maximum number of elements in a carousel. */
69
+ const CAROUSEL_CARD_CAP = 10;
70
+ /** The character limit for an alert's text. */
71
+ const ALERT_TEXT_CAP = 200;
72
+ /**
73
+ * The maximum number of data rows in a data-table block; the emitted `rows`
74
+ * array additionally carries one header row.
75
+ */
76
+ const DATA_TABLE_ROW_CAP = 100;
77
+ /** The maximum number of columns in a data-table block. */
78
+ const DATA_TABLE_COLUMN_CAP = 20;
79
+ /**
80
+ * The cumulative character limit (summed across every cell's text) shared by
81
+ * every data-table block in one payload.
82
+ */
83
+ const DATA_TABLE_CHAR_BUDGET = 1e4;
84
+ /** The caption emitted on every native data-table block. */
85
+ const TABLE_CAPTION = "Table";
86
+ /** The cumulative character limit for native markdown blocks. */
87
+ const MARKDOWN_TEXT_BUDGET = 12e3;
88
+ /** Builds the message-surface fallback for an alert. */
89
+ function buildAlertFallback(title, description, tone) {
90
+ const emoji = {
91
+ info: "ℹ️",
92
+ success: "✅",
93
+ warning: "⚠️",
94
+ danger: "🛑"
95
+ }[tone];
96
+ return [{
97
+ type: "context",
98
+ elements: [{
99
+ type: "mrkdwn",
100
+ text: title ? `${emoji} *${title}*` : emoji
101
+ }]
102
+ }, {
103
+ type: "section",
104
+ text: {
105
+ type: "mrkdwn",
106
+ text: description
107
+ }
108
+ }];
109
+ }
110
+ /** Builds a 2026 Slack modal-only alert block, mapping `tone` to its `level`. */
111
+ function buildAlertBlock(text, tone) {
112
+ return {
113
+ type: "alert",
114
+ text: {
115
+ type: "mrkdwn",
116
+ text
117
+ },
118
+ level: tone === "danger" ? "error" : tone
119
+ };
120
+ }
121
+ /** Builds a 2026 Slack card block from its already-clamped fields. */
122
+ function buildCardBlock(fields) {
123
+ const { heroImage, title, subtitle, body, subtext, actions } = fields;
124
+ return {
125
+ type: "card",
126
+ ...heroImage !== void 0 ? { hero_image: heroImage } : {},
127
+ ...title !== void 0 ? { title } : {},
128
+ ...subtitle !== void 0 ? { subtitle } : {},
129
+ ...body !== void 0 ? { body } : {},
130
+ ...subtext !== void 0 ? { subtext } : {},
131
+ ...actions !== void 0 ? { actions } : {}
132
+ };
133
+ }
134
+ /** Builds a 2026 Slack carousel block. */
135
+ function buildCarouselBlock(elements) {
136
+ return {
137
+ type: "carousel",
138
+ elements
139
+ };
140
+ }
141
+ /** Builds a 2026 Slack data-table block; `rows[0]` must be the header row. */
142
+ function buildDataTableBlock(rows) {
143
+ return {
144
+ type: "data_table",
145
+ caption: TABLE_CAPTION,
146
+ rows
147
+ };
148
+ }
149
+ /** Builds the final note used when a surface block budget is exceeded. */
150
+ function buildBlockBudgetNote(omitted) {
151
+ return {
152
+ type: "context",
153
+ elements: [{
154
+ type: "mrkdwn",
155
+ text: `${omitted} ${omitted === 1 ? "block was" : "blocks were"} omitted.`
156
+ }]
157
+ };
158
+ }
159
+ //#endregion
160
+ export { ACTIONS_ELEMENT_CAP, ACTION_ID_CAP, ALERT_TEXT_CAP, BUTTON_VALUE_CAP, CARD_ACTIONS_CAP, CARD_BODY_CAP, CARD_SUBTEXT_CAP, CARD_TITLE_CAP, CAROUSEL_CARD_CAP, CAROUSEL_CARD_MIN, CHILDREN_CAP, CONTEXT_ELEMENT_CAP, CONTEXT_TEXT_CAP, DATA_TABLE_CHAR_BUDGET, DATA_TABLE_COLUMN_CAP, DATA_TABLE_ROW_CAP, FACT_FIELD_CAP, FACT_FIELD_TEXT_CAP, HEADER_TEXT_CAP, INBOUND_BLOCK_CAP, INPUT_LABEL_CAP, INTERACTIVE_TEXT_CAP, MARKDOWN_TEXT_BUDGET, MAX_TRAVERSAL_DEPTH, MESSAGE_BLOCK_CAP, MODAL_BLOCK_CAP, NODE_BUDGET, PLACEHOLDER_TEXT_CAP, RADIO_OPTION_CAP, SECTION_TEXT_CAP, SELECT_OPTION_CAP, TABLE_CAPTION, buildAlertBlock, buildAlertFallback, buildBlockBudgetNote, buildCardBlock, buildCarouselBlock, buildDataTableBlock };
161
+
162
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"constants.js","names":[],"sources":["../../src/slack/constants.ts"],"sourcesContent":["import type {\n SlackAlertBlock,\n SlackButtonElement,\n SlackCardBlock,\n SlackCarouselBlock,\n SlackContextBlock,\n SlackDataTableBlock,\n SlackDataTableCell,\n SlackImageBlock,\n SlackSectionBlock,\n SlackTextObject,\n} from \"./types\";\n\n/** The maximum normalized traversal depth. */\nexport const MAX_TRAVERSAL_DEPTH = 64;\n\n/**\n * The maximum number of entries kept at any single level (root, or a\n * `children` array at any depth) of the raw spec, before it ever reaches\n * `normalizeSpec`. Bounds a hostile array's reported `length` so the pre-pass\n * can never be made to walk further than this regardless of what the array\n * claims about itself.\n */\nexport const CHILDREN_CAP = 200;\n\n/**\n * The total number of nodes the pre-normalization bounding walk will visit\n * across one call, regardless of how many times a shared reference recurs.\n * Bounds the combinatorial work a DAG of shared or self-referential nodes\n * would otherwise force even though each individual array stays within\n * {@link CHILDREN_CAP}.\n */\nexport const NODE_BUDGET = 5000;\n\n/** The block limit for a Slack message. */\nexport const MESSAGE_BLOCK_CAP = 50;\n\n/** The block limit for a Slack modal. */\nexport const MODAL_BLOCK_CAP = 100;\n\n/**\n * The maximum number of top-level blocks accepted when parsing Slack Block\n * Kit JSON back into generative UI, guarding against a hostile or malformed\n * payload.\n */\nexport const INBOUND_BLOCK_CAP = 200;\n\n/** The character limit for header text. */\nexport const HEADER_TEXT_CAP = 150;\n\n/** The character limit for section text. */\nexport const SECTION_TEXT_CAP = 3000;\n\n/** The maximum number of fields in one section. */\nexport const FACT_FIELD_CAP = 10;\n\n/** The character limit for one section field. */\nexport const FACT_FIELD_TEXT_CAP = 2000;\n\n/** The character limit for button labels and option labels. */\nexport const INTERACTIVE_TEXT_CAP = 75;\n\n/** The character limit for an action_id. */\nexport const ACTION_ID_CAP = 255;\n\n/** The character limit for a button's serialized value payload. */\nexport const BUTTON_VALUE_CAP = 2000;\n\n/** The maximum number of elements in one actions block. */\nexport const ACTIONS_ELEMENT_CAP = 25;\n\n/** The maximum number of options in a static select. */\nexport const SELECT_OPTION_CAP = 100;\n\n/** The maximum number of options in a radio-button group. */\nexport const RADIO_OPTION_CAP = 10;\n\n/** The character limit for a select or input placeholder. */\nexport const PLACEHOLDER_TEXT_CAP = 150;\n\n/** The character limit for an input's label. */\nexport const INPUT_LABEL_CAP = 2000;\n\n/** The maximum number of elements in one context block. */\nexport const CONTEXT_ELEMENT_CAP = 10;\n\n/** The character limit for one context element's text. */\nexport const CONTEXT_TEXT_CAP = 3000;\n\n/** The character limit for card titles and subtitles. */\nexport const CARD_TITLE_CAP = 150;\n\n/** The character limit for a card's body text. */\nexport const CARD_BODY_CAP = 200;\n\n/** The character limit for a card's subtext. */\nexport const CARD_SUBTEXT_CAP = 200;\n\n/** The maximum number of buttons in a card's actions. */\nexport const CARD_ACTIONS_CAP = 3;\n\n/** The minimum number of elements in a renderable carousel. */\nexport const CAROUSEL_CARD_MIN = 1;\n\n/** The maximum number of elements in a carousel. */\nexport const CAROUSEL_CARD_CAP = 10;\n\n/** The character limit for an alert's text. */\nexport const ALERT_TEXT_CAP = 200;\n\n/**\n * The maximum number of data rows in a data-table block; the emitted `rows`\n * array additionally carries one header row.\n */\nexport const DATA_TABLE_ROW_CAP = 100;\n\n/** The maximum number of columns in a data-table block. */\nexport const DATA_TABLE_COLUMN_CAP = 20;\n\n/**\n * The cumulative character limit (summed across every cell's text) shared by\n * every data-table block in one payload.\n */\nexport const DATA_TABLE_CHAR_BUDGET = 10000;\n\n/** The caption emitted on every native data-table block. */\nexport const TABLE_CAPTION = \"Table\";\n\n/** The cumulative character limit for native markdown blocks. */\nexport const MARKDOWN_TEXT_BUDGET = 12000;\n\n/** Builds the message-surface fallback for an alert. */\nexport function buildAlertFallback(\n title: string,\n description: string,\n tone: \"info\" | \"success\" | \"warning\" | \"danger\",\n): readonly [SlackContextBlock, SlackSectionBlock] {\n const emoji = {\n info: \"ℹ️\",\n success: \"✅\",\n warning: \"⚠️\",\n danger: \"🛑\",\n }[tone];\n return [\n {\n type: \"context\",\n elements: [\n { type: \"mrkdwn\", text: title ? `${emoji} *${title}*` : emoji },\n ],\n },\n { type: \"section\", text: { type: \"mrkdwn\", text: description } },\n ];\n}\n\n/** Builds a 2026 Slack modal-only alert block, mapping `tone` to its `level`. */\nexport function buildAlertBlock(\n text: string,\n tone: \"info\" | \"success\" | \"warning\" | \"danger\",\n): SlackAlertBlock {\n const level = tone === \"danger\" ? \"error\" : tone;\n return { type: \"alert\", text: { type: \"mrkdwn\", text }, level };\n}\n\ntype CardBlockFields = {\n readonly heroImage?: SlackImageBlock;\n readonly title?: SlackTextObject;\n readonly subtitle?: SlackTextObject;\n readonly body?: SlackTextObject;\n readonly subtext?: SlackTextObject;\n readonly actions?: readonly SlackButtonElement[];\n};\n\n/** Builds a 2026 Slack card block from its already-clamped fields. */\nexport function buildCardBlock(fields: CardBlockFields): SlackCardBlock {\n const { heroImage, title, subtitle, body, subtext, actions } = fields;\n return {\n type: \"card\",\n ...(heroImage !== undefined ? { hero_image: heroImage } : {}),\n ...(title !== undefined ? { title } : {}),\n ...(subtitle !== undefined ? { subtitle } : {}),\n ...(body !== undefined ? { body } : {}),\n ...(subtext !== undefined ? { subtext } : {}),\n ...(actions !== undefined ? { actions } : {}),\n };\n}\n\n/** Builds a 2026 Slack carousel block. */\nexport function buildCarouselBlock(\n elements: readonly SlackCardBlock[],\n): SlackCarouselBlock {\n return { type: \"carousel\", elements };\n}\n\n/** Builds a 2026 Slack data-table block; `rows[0]` must be the header row. */\nexport function buildDataTableBlock(\n rows: readonly (readonly SlackDataTableCell[])[],\n): SlackDataTableBlock {\n return { type: \"data_table\", caption: TABLE_CAPTION, rows };\n}\n\n/** Builds the final note used when a surface block budget is exceeded. */\nexport function buildBlockBudgetNote(omitted: number): SlackContextBlock {\n return {\n type: \"context\",\n elements: [\n {\n type: \"mrkdwn\",\n text: `${omitted} ${omitted === 1 ? \"block was\" : \"blocks were\"} omitted.`,\n },\n ],\n };\n}\n"],"mappings":";;AAcA,MAAa,sBAAsB;;;;;;;;AASnC,MAAa,eAAe;;;;;;;;AAS5B,MAAa,cAAc;;AAG3B,MAAa,oBAAoB;;AAGjC,MAAa,kBAAkB;;;;;;AAO/B,MAAa,oBAAoB;;AAGjC,MAAa,kBAAkB;;AAG/B,MAAa,mBAAmB;;AAGhC,MAAa,iBAAiB;;AAG9B,MAAa,sBAAsB;;AAGnC,MAAa,uBAAuB;;AAGpC,MAAa,gBAAgB;;AAG7B,MAAa,mBAAmB;;AAGhC,MAAa,sBAAsB;;AAGnC,MAAa,oBAAoB;;AAGjC,MAAa,mBAAmB;;AAGhC,MAAa,uBAAuB;;AAGpC,MAAa,kBAAkB;;AAG/B,MAAa,sBAAsB;;AAGnC,MAAa,mBAAmB;;AAGhC,MAAa,iBAAiB;;AAG9B,MAAa,gBAAgB;;AAG7B,MAAa,mBAAmB;;AAGhC,MAAa,mBAAmB;;AAGhC,MAAa,oBAAoB;;AAGjC,MAAa,oBAAoB;;AAGjC,MAAa,iBAAiB;;;;;AAM9B,MAAa,qBAAqB;;AAGlC,MAAa,wBAAwB;;;;;AAMrC,MAAa,yBAAyB;;AAGtC,MAAa,gBAAgB;;AAG7B,MAAa,uBAAuB;;AAGpC,SAAgB,mBACd,OACA,aACA,MACiD;CACjD,MAAM,QAAQ;EACZ,MAAM;EACN,SAAS;EACT,SAAS;EACT,QAAQ;CACV,EAAE;CACF,OAAO,CACL;EACE,MAAM;EACN,UAAU,CACR;GAAE,MAAM;GAAU,MAAM,QAAQ,GAAG,MAAM,IAAI,MAAM,KAAK;EAAM,CAChE;CACF,GACA;EAAE,MAAM;EAAW,MAAM;GAAE,MAAM;GAAU,MAAM;EAAY;CAAE,CACjE;AACF;;AAGA,SAAgB,gBACd,MACA,MACiB;CAEjB,OAAO;EAAE,MAAM;EAAS,MAAM;GAAE,MAAM;GAAU;EAAK;EAAG,OAD1C,SAAS,WAAW,UAAU;CACkB;AAChE;;AAYA,SAAgB,eAAe,QAAyC;CACtE,MAAM,EAAE,WAAW,OAAO,UAAU,MAAM,SAAS,YAAY;CAC/D,OAAO;EACL,MAAM;EACN,GAAI,cAAc,KAAA,IAAY,EAAE,YAAY,UAAU,IAAI,CAAC;EAC3D,GAAI,UAAU,KAAA,IAAY,EAAE,MAAM,IAAI,CAAC;EACvC,GAAI,aAAa,KAAA,IAAY,EAAE,SAAS,IAAI,CAAC;EAC7C,GAAI,SAAS,KAAA,IAAY,EAAE,KAAK,IAAI,CAAC;EACrC,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;EAC3C,GAAI,YAAY,KAAA,IAAY,EAAE,QAAQ,IAAI,CAAC;CAC7C;AACF;;AAGA,SAAgB,mBACd,UACoB;CACpB,OAAO;EAAE,MAAM;EAAY;CAAS;AACtC;;AAGA,SAAgB,oBACd,MACqB;CACrB,OAAO;EAAE,MAAM;EAAc,SAAS;EAAe;CAAK;AAC5D;;AAGA,SAAgB,qBAAqB,SAAoC;CACvE,OAAO;EACL,MAAM;EACN,UAAU,CACR;GACE,MAAM;GACN,MAAM,GAAG,QAAQ,GAAG,YAAY,IAAI,cAAc,cAAc;EAClE,CACF;CACF;AACF"}
@@ -0,0 +1,11 @@
1
+ import { Action } from "../ir.js";
2
+ //#region src/slack/decodeBlockAction.d.ts
3
+ /**
4
+ * Decodes one structural entry from a Slack `block_actions` payload.
5
+ * `$input` is reserved for the runtime selection: a `$input` key inside the
6
+ * button's JSON `value` payload is dropped rather than spread into the result.
7
+ */
8
+ declare function decodeBlockAction(action: unknown): Action | undefined;
9
+ //#endregion
10
+ export { decodeBlockAction };
11
+ //# sourceMappingURL=decodeBlockAction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decodeBlockAction.d.ts","names":[],"sources":["../../src/slack/decodeBlockAction.ts"],"mappings":";;;;;;;iBAegB,kBAAkB,kBAAkB"}
@@ -0,0 +1,40 @@
1
+ //#region src/slack/decodeBlockAction.ts
2
+ const isRecord = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
3
+ const optionValue = (value) => isRecord(value) && typeof value["value"] === "string" ? value["value"] : void 0;
4
+ /**
5
+ * Decodes one structural entry from a Slack `block_actions` payload.
6
+ * `$input` is reserved for the runtime selection: a `$input` key inside the
7
+ * button's JSON `value` payload is dropped rather than spread into the result.
8
+ */
9
+ function decodeBlockAction(action) {
10
+ try {
11
+ if (!isRecord(action) || typeof action["action_id"] !== "string") return;
12
+ const actionId = action["action_id"];
13
+ if (!actionId) return void 0;
14
+ const rawValue = action["value"];
15
+ let payload = {};
16
+ let plainValue;
17
+ if (typeof rawValue === "string") try {
18
+ const parsed = JSON.parse(rawValue);
19
+ if (isRecord(parsed)) payload = parsed;
20
+ else plainValue = rawValue;
21
+ } catch {
22
+ plainValue = rawValue;
23
+ }
24
+ const selectedOption = optionValue(action["selected_option"]);
25
+ const selectedDate = typeof action["selected_date"] === "string" ? action["selected_date"] : void 0;
26
+ const selectedOptions = Array.isArray(action["selected_options"]) ? action["selected_options"].map(optionValue).filter((value) => value !== void 0) : void 0;
27
+ const input = selectedOption ?? selectedDate ?? (selectedOptions !== void 0 ? selectedOptions : plainValue);
28
+ return {
29
+ ...Object.fromEntries(Object.entries(payload).filter(([key]) => key !== "$input")),
30
+ type: actionId,
31
+ ...input !== void 0 ? { $input: input } : {}
32
+ };
33
+ } catch {
34
+ return;
35
+ }
36
+ }
37
+ //#endregion
38
+ export { decodeBlockAction };
39
+
40
+ //# sourceMappingURL=decodeBlockAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decodeBlockAction.js","names":[],"sources":["../../src/slack/decodeBlockAction.ts"],"sourcesContent":["import type { Action } from \"../ir\";\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst optionValue = (value: unknown): string | undefined =>\n isRecord(value) && typeof value[\"value\"] === \"string\"\n ? value[\"value\"]\n : undefined;\n\n/**\n * Decodes one structural entry from a Slack `block_actions` payload.\n * `$input` is reserved for the runtime selection: a `$input` key inside the\n * button's JSON `value` payload is dropped rather than spread into the result.\n */\nexport function decodeBlockAction(action: unknown): Action | undefined {\n try {\n if (!isRecord(action) || typeof action[\"action_id\"] !== \"string\") {\n return undefined;\n }\n\n const actionId = action[\"action_id\"];\n if (!actionId) return undefined;\n\n const rawValue = action[\"value\"];\n let payload: Record<string, unknown> = {};\n let plainValue: string | undefined;\n if (typeof rawValue === \"string\") {\n try {\n const parsed: unknown = JSON.parse(rawValue);\n if (isRecord(parsed)) {\n payload = parsed;\n } else {\n plainValue = rawValue;\n }\n } catch {\n plainValue = rawValue;\n }\n }\n\n const selectedOption = optionValue(action[\"selected_option\"]);\n const selectedDate =\n typeof action[\"selected_date\"] === \"string\"\n ? action[\"selected_date\"]\n : undefined;\n const selectedOptions = Array.isArray(action[\"selected_options\"])\n ? action[\"selected_options\"]\n .map(optionValue)\n .filter((value): value is string => value !== undefined)\n : undefined;\n const input =\n selectedOption ??\n selectedDate ??\n (selectedOptions !== undefined ? selectedOptions : plainValue);\n\n return {\n ...Object.fromEntries(\n Object.entries(payload).filter(([key]) => key !== \"$input\"),\n ),\n type: actionId,\n ...(input !== undefined ? { $input: input } : {}),\n };\n } catch {\n return undefined;\n }\n}\n"],"mappings":";AAEA,MAAM,YAAY,UAChB,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,KAAK;AAErE,MAAM,eAAe,UACnB,SAAS,KAAK,KAAK,OAAO,MAAM,aAAa,WACzC,MAAM,WACN,KAAA;;;;;;AAON,SAAgB,kBAAkB,QAAqC;CACrE,IAAI;EACF,IAAI,CAAC,SAAS,MAAM,KAAK,OAAO,OAAO,iBAAiB,UACtD;EAGF,MAAM,WAAW,OAAO;EACxB,IAAI,CAAC,UAAU,OAAO,KAAA;EAEtB,MAAM,WAAW,OAAO;EACxB,IAAI,UAAmC,CAAC;EACxC,IAAI;EACJ,IAAI,OAAO,aAAa,UACtB,IAAI;GACF,MAAM,SAAkB,KAAK,MAAM,QAAQ;GAC3C,IAAI,SAAS,MAAM,GACjB,UAAU;QAEV,aAAa;EAEjB,QAAQ;GACN,aAAa;EACf;EAGF,MAAM,iBAAiB,YAAY,OAAO,kBAAkB;EAC5D,MAAM,eACJ,OAAO,OAAO,qBAAqB,WAC/B,OAAO,mBACP,KAAA;EACN,MAAM,kBAAkB,MAAM,QAAQ,OAAO,mBAAmB,IAC5D,OAAO,mBAAmB,CACvB,IAAI,WAAW,CAAC,CAChB,QAAQ,UAA2B,UAAU,KAAA,CAAS,IACzD,KAAA;EACJ,MAAM,QACJ,kBACA,iBACC,oBAAoB,KAAA,IAAY,kBAAkB;EAErD,OAAO;GACL,GAAG,OAAO,YACR,OAAO,QAAQ,OAAO,CAAC,CAAC,QAAQ,CAAC,SAAS,QAAQ,QAAQ,CAC5D;GACA,MAAM;GACN,GAAI,UAAU,KAAA,IAAY,EAAE,QAAQ,MAAM,IAAI,CAAC;EACjD;CACF,QAAQ;EACN;CACF;AACF"}
@@ -0,0 +1,30 @@
1
+ import { FromSlackBlocksResult } from "./types.js";
2
+ //#region src/slack/fromSlackBlocks.d.ts
3
+ /**
4
+ * Converts Slack Block Kit JSON back into a generative-ui IR tree, inverting
5
+ * {@link toSlackBlocks}. Accepts a blocks array or a `{ blocks }` wrapper;
6
+ * malformed input resolves to an empty node list plus a warning, and an
7
+ * unrecognized block or action element is skipped with a "dropped" warning.
8
+ * Every array read along the way (blocks, fields, options, elements, cards,
9
+ * rows, cells) is bounded to its site's cap before it is mapped over, so a
10
+ * hostile array (sparse or proxied with a fabricated `length`) is clamped
11
+ * with a "clamped" warning instead of stalling the event loop. Never throws.
12
+ *
13
+ * The Slack shape is lossier than the IR, so some information cannot be
14
+ * recovered: a context block's elements always decode as `Caption` (the
15
+ * original `Badge` vs `Caption` distinction does not survive the round trip),
16
+ * a button's `buttonStyle` is only recovered for the `primary`/`danger` Slack
17
+ * styles, a native alert block's `title` and `description` merge into a
18
+ * single `description` string, and a card's layout collapses to its `title`,
19
+ * a flat `children` list (image, then text, then caption, in that order),
20
+ * and `confirm`/`cancel` footer buttons. A section field's label and value
21
+ * are split on the first `*`+newline delimiter, so a label or value that
22
+ * itself contains that exact delimiter cannot be split back unambiguously.
23
+ * A data-table cell that Slack carries as `raw_text` always decodes as a
24
+ * string, even when its text is the stringified form of a boolean, since the
25
+ * Slack shape does not distinguish a boolean from ordinary text.
26
+ */
27
+ declare function fromSlackBlocks(blocks: unknown): FromSlackBlocksResult;
28
+ //#endregion
29
+ export { fromSlackBlocks };
30
+ //# sourceMappingURL=fromSlackBlocks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fromSlackBlocks.d.ts","names":[],"sources":["../../src/slack/fromSlackBlocks.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;iBA+pBgB,gBAAgB,kBAAkB"}