@kitn.ai/ui 0.15.0 → 0.16.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 (366) hide show
  1. package/README.md +9 -0
  2. package/bin/mcp.js +22 -0
  3. package/dist/bash-InADTalH.js +6 -1
  4. package/dist/components/artifact.d.ts +58 -0
  5. package/dist/components/attachments.d.ts +67 -0
  6. package/dist/components/card-fallback.d.ts +10 -0
  7. package/dist/components/card-renderer.d.ts +13 -0
  8. package/dist/components/card.d.ts +28 -0
  9. package/dist/components/chain-of-thought.d.ts +29 -0
  10. package/dist/components/chat-container.d.ts +19 -0
  11. package/dist/components/chat-scope-picker.d.ts +9 -0
  12. package/dist/components/chat-thread.d.ts +93 -0
  13. package/dist/components/checkpoint.d.ts +20 -0
  14. package/dist/components/choice-card.d.ts +77 -0
  15. package/dist/components/code-block.d.ts +16 -0
  16. package/dist/components/confirm-card.d.ts +57 -0
  17. package/dist/components/context.d.ts +65 -0
  18. package/dist/components/conversation-item.d.ts +8 -0
  19. package/dist/components/conversation-list.d.ts +11 -0
  20. package/dist/components/embed.d.ts +21 -0
  21. package/dist/components/empty.d.ts +43 -0
  22. package/dist/components/feedback-bar.d.ts +45 -0
  23. package/dist/components/file-tree.d.ts +57 -0
  24. package/dist/components/file-upload.d.ts +16 -0
  25. package/dist/components/form-widgets.d.ts +31 -0
  26. package/dist/components/form.d.ts +103 -0
  27. package/dist/components/image.d.ts +12 -0
  28. package/dist/components/link-preview.d.ts +23 -0
  29. package/dist/components/loader.d.ts +60 -0
  30. package/dist/components/markdown.d.ts +8 -0
  31. package/dist/components/message-skills.d.ts +15 -0
  32. package/dist/components/message.d.ts +54 -0
  33. package/dist/components/model-switcher.d.ts +8 -0
  34. package/dist/components/prompt-input.d.ts +38 -0
  35. package/dist/components/prompt-suggestion.d.ts +13 -0
  36. package/dist/components/reasoning.d.ts +20 -0
  37. package/dist/components/response-stream.d.ts +14 -0
  38. package/dist/components/scroll-button.d.ts +7 -0
  39. package/dist/components/slash-command.d.ts +15 -0
  40. package/dist/components/source.d.ts +23 -0
  41. package/dist/components/tasks-card.d.ts +71 -0
  42. package/dist/components/text-shimmer.d.ts +9 -0
  43. package/dist/components/thinking-bar.d.ts +10 -0
  44. package/dist/components/tool.d.ts +16 -0
  45. package/dist/components/use-card-resolution.d.ts +12 -0
  46. package/dist/components/voice-input.d.ts +7 -0
  47. package/dist/core-AYMC6_lb.js +5874 -12
  48. package/dist/css-M7EaDHN_.js +6 -1
  49. package/dist/elements/artifact.d.ts +1 -0
  50. package/dist/elements/attachments.d.ts +1 -0
  51. package/dist/elements/card.d.ts +1 -0
  52. package/dist/elements/cards.d.ts +0 -0
  53. package/dist/elements/chain-of-thought.d.ts +13 -0
  54. package/dist/elements/chat-scope-picker.d.ts +1 -0
  55. package/dist/elements/chat-types.d.ts +41 -0
  56. package/dist/elements/chat-workspace.d.ts +1 -0
  57. package/dist/elements/chat.d.ts +1 -0
  58. package/dist/elements/checkpoint.d.ts +1 -0
  59. package/dist/elements/choice.d.ts +1 -0
  60. package/dist/elements/code-block.d.ts +1 -0
  61. package/dist/elements/confirm-card.d.ts +1 -0
  62. package/dist/elements/context-meter.d.ts +1 -0
  63. package/dist/elements/conversation-list.d.ts +11 -0
  64. package/dist/elements/css.d.ts +1 -0
  65. package/dist/elements/default-input.d.ts +40 -0
  66. package/dist/elements/define.d.ts +42 -0
  67. package/dist/elements/embed.d.ts +1 -0
  68. package/dist/elements/empty.d.ts +1 -0
  69. package/dist/elements/feedback-bar.d.ts +1 -0
  70. package/dist/elements/file-tree.d.ts +1 -0
  71. package/dist/elements/file-upload.d.ts +1 -0
  72. package/dist/elements/form.d.ts +1 -0
  73. package/dist/elements/image.d.ts +1 -0
  74. package/dist/elements/link-preview.d.ts +1 -0
  75. package/dist/elements/loader.d.ts +1 -0
  76. package/dist/elements/markdown.d.ts +1 -0
  77. package/dist/elements/message-skills.d.ts +17 -0
  78. package/dist/elements/message.d.ts +1 -0
  79. package/dist/elements/model-switcher.d.ts +11 -0
  80. package/dist/elements/popover.d.ts +1 -0
  81. package/dist/elements/prompt-input.d.ts +9 -0
  82. package/dist/elements/prompt-suggestions.d.ts +7 -0
  83. package/dist/elements/reasoning.d.ts +1 -0
  84. package/dist/elements/register-impl.d.ts +0 -0
  85. package/dist/elements/register.d.ts +3 -0
  86. package/dist/elements/remote.d.ts +1 -0
  87. package/dist/elements/resizable.d.ts +17 -0
  88. package/dist/elements/response-stream.d.ts +1 -0
  89. package/dist/elements/scroll-button.d.ts +1 -0
  90. package/dist/elements/source.d.ts +18 -0
  91. package/dist/elements/switch.d.ts +1 -0
  92. package/dist/elements/tasks.d.ts +1 -0
  93. package/dist/elements/text-shimmer.d.ts +1 -0
  94. package/dist/elements/thinking-bar.d.ts +1 -0
  95. package/dist/elements/tool.d.ts +1 -0
  96. package/dist/elements/voice-input.d.ts +1 -0
  97. package/dist/elements.d.ts +732 -0
  98. package/dist/engine-javascript-vq0WuIJl.js +2516 -14
  99. package/dist/github-dark-dimmed-DUshB20C.js +4 -1
  100. package/dist/github-light-JYsPkUQd.js +4 -1
  101. package/dist/html-CPZ3oZQ7.js +10 -1
  102. package/dist/index.d.ts +112 -2
  103. package/dist/index.js +13551 -0
  104. package/dist/javascript-C25yR2R2.js +6 -1
  105. package/dist/json-DxJze_jm.js +6 -1
  106. package/dist/kitn-chat.es.js +1 -77
  107. package/dist/llms/llms-full.txt +1 -1
  108. package/dist/llms/llms.txt +1 -1
  109. package/dist/mcp.es.js +2140 -0
  110. package/dist/primitives/card-contract.d.ts +103 -0
  111. package/dist/primitives/card-host.d.ts +12 -0
  112. package/dist/primitives/card-registry.d.ts +17 -0
  113. package/dist/primitives/card-resolution.d.ts +8 -0
  114. package/dist/primitives/card-routing.d.ts +12 -0
  115. package/dist/primitives/card-validate.d.ts +25 -0
  116. package/dist/primitives/chat-config.d.ts +31 -0
  117. package/dist/primitives/controllable.d.ts +13 -0
  118. package/dist/primitives/embed-providers.d.ts +65 -0
  119. package/dist/primitives/highlighter.d.ts +23 -0
  120. package/dist/primitives/link-preview.d.ts +47 -0
  121. package/dist/primitives/pdf-preview.d.ts +50 -0
  122. package/dist/primitives/use-auto-resize.d.ts +8 -0
  123. package/dist/primitives/use-resize-observer.d.ts +1 -0
  124. package/dist/primitives/use-stick-to-bottom.d.ts +5 -0
  125. package/dist/primitives/use-text-stream.d.ts +19 -0
  126. package/dist/primitives/use-voice-recorder.d.ts +9 -0
  127. package/dist/react/index.d.ts +1118 -0
  128. package/dist/react/runtime.d.ts +15 -0
  129. package/dist/react.js +265 -0
  130. package/dist/register-impl-wCsFPoh9.js +77 -0
  131. package/dist/register-ujhr1nBS.js +1 -0
  132. package/dist/remote/host-embed.d.ts +33 -0
  133. package/dist/remote/index.d.ts +2 -0
  134. package/dist/remote/origin.d.ts +5 -0
  135. package/dist/remote/provider-runtime.d.ts +27 -0
  136. package/dist/remote/provider.d.ts +2 -0
  137. package/dist/remote/validate.d.ts +4 -0
  138. package/dist/remote/version.d.ts +4 -0
  139. package/dist/remote/wire.d.ts +53 -0
  140. package/dist/svelte--5p79yCD.js +15 -1
  141. package/dist/tsx-B8rCNbgL.js +6 -1
  142. package/dist/types.d.ts +42 -0
  143. package/dist/typescript-RycA9KXf.js +6 -1
  144. package/dist/ui/action-icons.d.ts +11 -0
  145. package/dist/ui/avatar.d.ts +8 -0
  146. package/dist/ui/badge.d.ts +9 -0
  147. package/dist/ui/button.d.ts +10 -0
  148. package/dist/ui/collapsible.d.ts +27 -0
  149. package/dist/ui/dropdown.d.ts +20 -0
  150. package/dist/ui/hover-card.d.ts +28 -0
  151. package/dist/ui/overlay.d.ts +67 -0
  152. package/dist/ui/popover.d.ts +32 -0
  153. package/dist/ui/resizable.d.ts +76 -0
  154. package/dist/ui/scroll-area.d.ts +5 -0
  155. package/dist/ui/separator.d.ts +5 -0
  156. package/dist/ui/skeleton.d.ts +5 -0
  157. package/dist/ui/switch.d.ts +19 -0
  158. package/dist/ui/textarea.d.ts +6 -0
  159. package/dist/ui/tooltip.d.ts +8 -0
  160. package/dist/utils/cn.d.ts +2 -0
  161. package/dist/vue-BmIZj4XD.js +33 -1
  162. package/frameworks/react/index.tsx +4 -0
  163. package/frameworks/react/runtime.tsx +16 -2
  164. package/llms-full.txt +1 -1
  165. package/llms.txt +1 -1
  166. package/package.json +29 -11
  167. package/src/agent-tooling/archetypes.ts +46 -0
  168. package/src/agent-tooling/integrations/cloudflare.ts +88 -0
  169. package/src/agent-tooling/integrations/langgraph.ts +60 -0
  170. package/src/agent-tooling/integrations/mastra.ts +27 -0
  171. package/src/agent-tooling/integrations/mock.ts +34 -0
  172. package/src/agent-tooling/integrations/ollama.ts +47 -0
  173. package/src/agent-tooling/integrations/openrouter.ts +26 -0
  174. package/src/agent-tooling/integrations/pi.ts +40 -0
  175. package/src/agent-tooling/integrations/pydantic-ai.ts +52 -0
  176. package/src/agent-tooling/integrations/vercel-ai-sdk.ts +44 -0
  177. package/src/agent-tooling/mcp/manifest.ts +128 -0
  178. package/src/agent-tooling/mcp/server.ts +59 -0
  179. package/src/agent-tooling/mcp/stdio.ts +18 -0
  180. package/src/agent-tooling/mcp/tools/debug.ts +305 -0
  181. package/src/agent-tooling/mcp/tools/reference.ts +132 -0
  182. package/src/agent-tooling/mcp/tools/scaffold.ts +1627 -0
  183. package/src/agent-tooling/mcp/tools/theme.ts +340 -0
  184. package/src/agent-tooling/mcp/tools/types.ts +14 -0
  185. package/src/agent-tooling/registry.ts +41 -0
  186. package/src/agent-tooling/types.ts +30 -0
  187. package/src/elements/compiled.css +1 -1
  188. package/src/elements/define.tsx +7 -1
  189. package/src/elements/element-types.d.ts +2 -1
  190. package/src/elements/register-impl.ts +55 -0
  191. package/src/elements/register.ts +17 -51
  192. package/theme.css +4 -2
  193. package/src/components/artifact.stories.tsx +0 -138
  194. package/src/components/attachments.stories.tsx +0 -303
  195. package/src/components/attachments.test.tsx +0 -64
  196. package/src/components/chain-of-thought.stories.tsx +0 -211
  197. package/src/components/chat-container.stories.tsx +0 -187
  198. package/src/components/chat-thread.test.tsx +0 -58
  199. package/src/components/checkpoint.stories.tsx +0 -102
  200. package/src/components/code-block.stories.tsx +0 -150
  201. package/src/components/confirm-card.stories.tsx +0 -74
  202. package/src/components/context.stories.tsx +0 -229
  203. package/src/components/context.test.tsx +0 -133
  204. package/src/components/conversation-item.stories.tsx +0 -125
  205. package/src/components/conversation-list.stories.tsx +0 -133
  206. package/src/components/default-input.test.tsx +0 -111
  207. package/src/components/empty.stories.tsx +0 -434
  208. package/src/components/feedback-bar.stories.tsx +0 -138
  209. package/src/components/feedback-bar.test.tsx +0 -103
  210. package/src/components/file-tree.stories.tsx +0 -73
  211. package/src/components/file-upload.stories.tsx +0 -156
  212. package/src/components/image.stories.tsx +0 -89
  213. package/src/components/loader.stories.tsx +0 -181
  214. package/src/components/markdown.stories.tsx +0 -180
  215. package/src/components/message-action-bar.test.tsx +0 -128
  216. package/src/components/message-narrow.stories.tsx +0 -329
  217. package/src/components/message-skills.stories.tsx +0 -211
  218. package/src/components/message.stories.tsx +0 -281
  219. package/src/components/model-switcher.stories.tsx +0 -123
  220. package/src/components/model-switcher.test.tsx +0 -65
  221. package/src/components/prompt-input.stories.tsx +0 -222
  222. package/src/components/prompt-suggestion.stories.tsx +0 -142
  223. package/src/components/reasoning.stories.tsx +0 -140
  224. package/src/components/resizable.test.tsx +0 -226
  225. package/src/components/scroll-button.stories.tsx +0 -100
  226. package/src/components/slash-command.stories.tsx +0 -163
  227. package/src/components/source-list.test.tsx +0 -152
  228. package/src/components/source.stories.tsx +0 -124
  229. package/src/components/tasks-card.stories.tsx +0 -78
  230. package/src/components/text-shimmer.stories.tsx +0 -87
  231. package/src/components/thinking-bar.stories.tsx +0 -87
  232. package/src/components/tool.stories.tsx +0 -153
  233. package/src/components/voice-input.stories.tsx +0 -83
  234. package/src/elements/artifact.stories.tsx +0 -506
  235. package/src/elements/attachments.stories.tsx +0 -190
  236. package/src/elements/card.stories.tsx +0 -113
  237. package/src/elements/cards.stories.tsx +0 -59
  238. package/src/elements/catalog.stories.tsx +0 -491
  239. package/src/elements/chain-of-thought.declarative.test.tsx +0 -153
  240. package/src/elements/chain-of-thought.stories.tsx +0 -113
  241. package/src/elements/chat-scope-picker.stories.tsx +0 -73
  242. package/src/elements/chat-workspace.stories.tsx +0 -288
  243. package/src/elements/chat.stories.tsx +0 -151
  244. package/src/elements/checkpoint.stories.tsx +0 -72
  245. package/src/elements/choice.stories.tsx +0 -240
  246. package/src/elements/code-block.stories.tsx +0 -83
  247. package/src/elements/composed-shell.stories.tsx +0 -316
  248. package/src/elements/confirm-card.stories.tsx +0 -227
  249. package/src/elements/context-meter.stories.tsx +0 -151
  250. package/src/elements/conversation-list.declarative.test.tsx +0 -137
  251. package/src/elements/conversation-list.stories.tsx +0 -243
  252. package/src/elements/embed.stories.tsx +0 -213
  253. package/src/elements/empty.stories.tsx +0 -111
  254. package/src/elements/feedback-bar.stories.tsx +0 -114
  255. package/src/elements/file-tree.stories.tsx +0 -134
  256. package/src/elements/file-upload.stories.tsx +0 -82
  257. package/src/elements/form.stories.tsx +0 -248
  258. package/src/elements/image.stories.tsx +0 -71
  259. package/src/elements/link-preview.stories.tsx +0 -209
  260. package/src/elements/loader.stories.tsx +0 -88
  261. package/src/elements/markdown.stories.tsx +0 -76
  262. package/src/elements/message-skills.declarative.test.tsx +0 -104
  263. package/src/elements/message-skills.stories.tsx +0 -114
  264. package/src/elements/message.stories.tsx +0 -218
  265. package/src/elements/model-switcher.declarative.test.tsx +0 -130
  266. package/src/elements/model-switcher.stories.tsx +0 -198
  267. package/src/elements/popover.stories.tsx +0 -80
  268. package/src/elements/prompt-input-slash-command.test.tsx +0 -128
  269. package/src/elements/prompt-input-stoppable.test.tsx +0 -88
  270. package/src/elements/prompt-input-toolbar-actions.test.tsx +0 -120
  271. package/src/elements/prompt-input.stories.tsx +0 -331
  272. package/src/elements/prompt-suggestions.declarative.test.tsx +0 -164
  273. package/src/elements/prompt-suggestions.stories.tsx +0 -213
  274. package/src/elements/reasoning.stories.tsx +0 -77
  275. package/src/elements/remote.stories.tsx +0 -314
  276. package/src/elements/resizable.stories.tsx +0 -426
  277. package/src/elements/response-stream.stories.tsx +0 -79
  278. package/src/elements/scroll-button.stories.tsx +0 -202
  279. package/src/elements/scroll-button.test.tsx +0 -148
  280. package/src/elements/source-list.stories.tsx +0 -143
  281. package/src/elements/source.stories.tsx +0 -88
  282. package/src/elements/switch.stories.tsx +0 -56
  283. package/src/elements/tasks.stories.tsx +0 -237
  284. package/src/elements/text-shimmer.stories.tsx +0 -64
  285. package/src/elements/thinking-bar.stories.tsx +0 -72
  286. package/src/elements/tool.stories.tsx +0 -89
  287. package/src/elements/voice-input.stories.tsx +0 -88
  288. package/src/primitives/controllable.test.ts +0 -47
  289. package/src/stories/chat-panel-layout.stories.tsx +0 -145
  290. package/src/stories/chat-scene.tsx +0 -571
  291. package/src/stories/checkpoint-restore.stories.tsx +0 -256
  292. package/src/stories/context-usage.stories.tsx +0 -212
  293. package/src/stories/conversation-with-reasoning.stories.tsx +0 -182
  294. package/src/stories/conversation-with-sources.stories.tsx +0 -471
  295. package/src/stories/docs/Accessibility.mdx +0 -119
  296. package/src/stories/docs/ChildElements.mdx +0 -269
  297. package/src/stories/docs/ForAIAgents.mdx +0 -162
  298. package/src/stories/docs/GettingStarted.mdx +0 -65
  299. package/src/stories/docs/Installation.mdx +0 -83
  300. package/src/stories/docs/Introduction.mdx +0 -50
  301. package/src/stories/docs/SolidJsAdvanced.mdx +0 -17
  302. package/src/stories/docs/Theming.mdx +0 -85
  303. package/src/stories/docs/element-controls.ts +0 -121
  304. package/src/stories/docs/frameworks/Angular.mdx +0 -245
  305. package/src/stories/docs/frameworks/Html.mdx +0 -227
  306. package/src/stories/docs/frameworks/Overview.mdx +0 -47
  307. package/src/stories/docs/frameworks/React.mdx +0 -227
  308. package/src/stories/docs/frameworks/Solid.mdx +0 -173
  309. package/src/stories/docs/frameworks/Svelte.mdx +0 -194
  310. package/src/stories/docs/frameworks/Vue.mdx +0 -238
  311. package/src/stories/docs/generative-ui-overview.mdx +0 -186
  312. package/src/stories/docs/recipes/SpeechToText.mdx +0 -7
  313. package/src/stories/docs/recipes/Streaming.mdx +0 -68
  314. package/src/stories/docs/recipes/TextToSpeech.mdx +0 -35
  315. package/src/stories/docs/theme-editor/canvas.tsx +0 -32
  316. package/src/stories/docs/theme-editor/inspector.tsx +0 -66
  317. package/src/stories/docs/theme-editor/presets.test.ts +0 -32
  318. package/src/stories/docs/theme-editor/presets.ts +0 -64
  319. package/src/stories/docs/theme-editor/theme-css.test.ts +0 -19
  320. package/src/stories/docs/theme-editor/theme-css.ts +0 -15
  321. package/src/stories/docs/theme-editor/theme-editor.tsx +0 -146
  322. package/src/stories/docs/theme-tokens.tsx +0 -174
  323. package/src/stories/examples/ChoosingComponents.mdx +0 -106
  324. package/src/stories/examples/sample-data.ts +0 -79
  325. package/src/stories/examples/usage/checkpoint-restore.ts +0 -156
  326. package/src/stories/examples/usage/context-usage.ts +0 -591
  327. package/src/stories/examples/usage/conversation-with-reasoning.ts +0 -224
  328. package/src/stories/examples/usage/conversation-with-sources.ts +0 -589
  329. package/src/stories/examples/usage/empty-state.ts +0 -144
  330. package/src/stories/examples/usage/full-chat-app.ts +0 -277
  331. package/src/stories/examples/usage/index.ts +0 -63
  332. package/src/stories/examples/usage/message-actions.ts +0 -704
  333. package/src/stories/examples/usage/pattern-centered-conversation.ts +0 -446
  334. package/src/stories/examples/usage/pattern-chat-panel-layout.ts +0 -442
  335. package/src/stories/examples/usage/pattern-docked-widget.ts +0 -479
  336. package/src/stories/examples/usage/prompt-input-variants.ts +0 -1356
  337. package/src/stories/examples/usage/streaming-response.ts +0 -687
  338. package/src/stories/examples/usage/types.ts +0 -33
  339. package/src/stories/full-chat.stories.tsx +0 -18
  340. package/src/stories/message-actions.stories.tsx +0 -230
  341. package/src/stories/pattern-centered-conversation.stories.tsx +0 -93
  342. package/src/stories/pattern-docked-widget.stories.tsx +0 -93
  343. package/src/stories/pattern-empty-state.stories.tsx +0 -76
  344. package/src/stories/prompt-input-variants.stories.tsx +0 -456
  345. package/src/stories/streaming-response.stories.tsx +0 -438
  346. package/src/stories/theme-editor.stories.tsx +0 -16
  347. package/src/stories/token-reference.stories.tsx +0 -18
  348. package/src/stories/typography.stories.tsx +0 -78
  349. package/src/ui/avatar.stories.tsx +0 -103
  350. package/src/ui/badge.stories.tsx +0 -86
  351. package/src/ui/button.stories.tsx +0 -145
  352. package/src/ui/collapsible.stories.tsx +0 -69
  353. package/src/ui/dropdown.stories.tsx +0 -59
  354. package/src/ui/hover-card.stories.tsx +0 -77
  355. package/src/ui/hover-card.test.tsx +0 -30
  356. package/src/ui/overlay.stories.tsx +0 -115
  357. package/src/ui/popover.stories.tsx +0 -81
  358. package/src/ui/popover.test.tsx +0 -99
  359. package/src/ui/resizable.stories.tsx +0 -236
  360. package/src/ui/scroll-area.stories.tsx +0 -50
  361. package/src/ui/separator.stories.tsx +0 -81
  362. package/src/ui/skeleton.stories.tsx +0 -337
  363. package/src/ui/switch.stories.tsx +0 -51
  364. package/src/ui/switch.test.tsx +0 -59
  365. package/src/ui/textarea.stories.tsx +0 -76
  366. package/src/ui/tooltip.stories.tsx +0 -74
@@ -1,151 +0,0 @@
1
- import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
- import { onMount } from 'solid-js';
3
- import './register'; // side effect: registers <kai-chat>, <kai-conversations>, <kai-prompt-input>
4
- import type { ChatMessage } from './chat-types';
5
- import { argTypesFor, specDescription } from '../stories/docs/element-controls';
6
-
7
- // The web components are custom DOM elements, so declare the tags for JSX.
8
- declare module 'solid-js' {
9
- // eslint-disable-next-line @typescript-eslint/no-namespace
10
- namespace JSX {
11
- interface IntrinsicElements {
12
- 'kai-chat': JSX.HTMLAttributes<HTMLElement>;
13
- }
14
- }
15
- }
16
-
17
- const sampleMessages: ChatMessage[] = [
18
- { id: '1', role: 'user', content: 'How do I center a div?' },
19
- {
20
- id: '2',
21
- role: 'assistant',
22
- content:
23
- 'The modern way is a grid:\n\n```css\n.box {\n display: grid;\n place-items: center;\n}\n```\n\nThat centers the child on both axes.',
24
- actions: ['copy', 'like', 'dislike'],
25
- },
26
- ];
27
-
28
- type ChatEl = HTMLElement & {
29
- messages?: ChatMessage[];
30
- value?: string;
31
- placeholder?: string;
32
- loading?: boolean;
33
- suggestionMode?: string;
34
- proseSize?: string;
35
- codeTheme?: string;
36
- codeHighlight?: boolean;
37
- chatTitle?: string;
38
- currentModel?: string;
39
- scrollButton?: boolean;
40
- search?: boolean;
41
- voice?: boolean;
42
- slashCompact?: boolean;
43
- };
44
-
45
- /** Live demo of the actual `<kai-chat>` custom element (Shadow DOM and all). */
46
- function ChatElement(props: { args?: Record<string, unknown> }) {
47
- let el: ChatEl | undefined;
48
- onMount(() => {
49
- if (el) {
50
- // Fixed array data
51
- el.messages = sampleMessages;
52
- // Scalar args from Controls
53
- const args = props.args;
54
- if (args) {
55
- const scalarNames = [
56
- 'value', 'placeholder', 'loading', 'suggestionMode', 'proseSize',
57
- 'codeTheme', 'codeHighlight', 'chatTitle', 'currentModel',
58
- 'scrollButton', 'search', 'voice', 'slashCompact',
59
- ];
60
- for (const name of scalarNames) {
61
- if (name in args) (el as unknown as Record<string, unknown>)[name] = args[name];
62
- }
63
- }
64
- }
65
- });
66
- return <kai-chat ref={(e) => (el = e as ChatEl)} style={{ display: 'block', height: '560px' }} />;
67
- }
68
-
69
- const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
70
- <kai-chat id="chat" style="display:block; height:100vh;"></kai-chat>
71
-
72
- <script type="module">
73
- import '@kitn.ai/ui/elements'; // registers the custom elements
74
-
75
- const chat = document.getElementById('chat');
76
- chat.messages = [
77
- { id: '1', role: 'user', content: 'How do I center a div?' },
78
- { id: '2', role: 'assistant', content: 'Use \`display: grid; place-items: center;\`' },
79
- ];
80
-
81
- // events are CustomEvents on the element (they do not bubble)
82
- chat.addEventListener('kai-submit', (e) => console.log('user sent:', e.detail.value));
83
- </script>`;
84
-
85
- const SOLID_SNIPPET = `import '@kitn.ai/ui/elements'; // registers the custom elements
86
- import { onMount } from 'solid-js';
87
- import type { ChatMessage } from '@kitn.ai/ui/elements';
88
-
89
- function Chat() {
90
- let el: HTMLElement & { messages?: ChatMessage[] };
91
- const messages: ChatMessage[] = [
92
- { id: '1', role: 'user', content: 'How do I center a div?' },
93
- { id: '2', role: 'assistant', content: 'Use \`display: grid; place-items: center;\`' },
94
- ];
95
- onMount(() => { el.messages = messages; });
96
- return (
97
- <kai-chat
98
- ref={el}
99
- style={{ display: 'block', height: '100vh' }}
100
- on:kai-submit={(e) => console.log('user sent:', e.detail.value)}
101
- />
102
- );
103
- }`;
104
-
105
- const meta = {
106
- title: 'Components/Chat',
107
- tags: ['autodocs'],
108
- argTypes: argTypesFor('kai-chat'),
109
- parameters: {
110
- layout: 'fullscreen',
111
- docs: {
112
- description: specDescription('kai-chat', [
113
- '`<kai-chat>` is the framework-agnostic **web component** version of the chat UI — a complete message thread plus prompt input, isolated in **Shadow DOM** so the host page\'s CSS can\'t leak in and the kit\'s styles can\'t leak out. SolidJS is bundled in, so the host needs nothing.',
114
- '**When to use:** dropping a full chat into a non-Solid app (React, Vue, Svelte, plain HTML), or anywhere you want zero style conflicts. If you *are* in SolidJS and want fine-grained control, compose the primitives (`ChatContainer`, `Message`, `PromptInput`) instead.',
115
- '**How to use:** register once with `import \'@kitn.ai/ui/elements\'`, set rich data as JS **properties** (`el.messages = [...]`), and listen for **CustomEvents** (`kai-submit`, `kai-message-action`, `kai-value-change`) directly on the element.',
116
- '**Anatomy:** **header** (model switcher + context-meter, shown when `models`/`context` props are set) → **message list** (scrollable thread of `<Message>` rows, each rendered per `role`; a scroll-to-bottom button appears when scrolled up) → **prompt composer** (`<PromptInput>`: textarea + toolbar with suggestions, slash-command palette, voice/search buttons, and optional attachment area).',
117
- '**Placement:** as a top-level panel or full-page surface. Give it an explicit height (e.g. `height: 100vh`).',
118
- 'See the **Code** tab below for the HTML usage; the *SolidJS* story shows the same element inside a Solid component.',
119
- ]),
120
- },
121
- },
122
- } satisfies Meta;
123
-
124
- export default meta;
125
- type Story = StoryObj;
126
-
127
- /** The element used the plain-HTML / any-framework way. */
128
- export const Default: Story = {
129
- args: {
130
- placeholder: 'Send a message...',
131
- loading: false,
132
- suggestionMode: 'submit',
133
- proseSize: 'sm',
134
- codeTheme: 'github-dark-dimmed',
135
- codeHighlight: true,
136
- scrollButton: true,
137
- search: false,
138
- voice: false,
139
- slashCompact: false,
140
- },
141
- render: (args: Record<string, unknown>) => <ChatElement args={args} />,
142
- parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
143
- };
144
-
145
- /** The same element used inside a SolidJS component (properties via `ref`, events via `on:`). */
146
- export const InSolidJS: Story = {
147
- name: 'In SolidJS',
148
- render: () => <ChatElement />,
149
- parameters: { docs: { source: { code: SOLID_SNIPPET, language: 'tsx' } } },
150
- };
151
-
@@ -1,72 +0,0 @@
1
- import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
- import { onMount } from 'solid-js';
3
- import './register'; // side effect: registers the custom elements
4
- import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
-
6
- // The web components are custom DOM elements, so declare the tags for JSX.
7
- declare module 'solid-js' {
8
- // eslint-disable-next-line @typescript-eslint/no-namespace
9
- namespace JSX {
10
- interface IntrinsicElements {
11
- 'kai-checkpoint': JSX.HTMLAttributes<HTMLElement>;
12
- }
13
- }
14
- }
15
-
16
- /** Render the actual `<kai-checkpoint>` custom element configured by attributes. */
17
- function CheckpointElement(props: { label?: string; tooltip?: string; variant?: string; size?: string }) {
18
- let el: HTMLElement | undefined;
19
- onMount(() => {
20
- if (!el) return;
21
- if (props.label) el.setAttribute('label', props.label);
22
- if (props.tooltip) el.setAttribute('tooltip', props.tooltip);
23
- if (props.variant) el.setAttribute('variant', props.variant);
24
- if (props.size) el.setAttribute('size', props.size);
25
- el.addEventListener('kai-select', () => console.log('checkpoint selected'));
26
- });
27
- return <kai-checkpoint ref={(e) => (el = e as HTMLElement)} style={{ display: 'inline-block', padding: '16px' }} />;
28
- }
29
-
30
- const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
31
- <kai-checkpoint label="Restore" tooltip="Restore this checkpoint" variant="outline" size="sm"></kai-checkpoint>
32
-
33
- <script type="module">
34
- import '@kitn.ai/ui/elements'; // registers the custom elements
35
-
36
- const cp = document.querySelector('kai-checkpoint');
37
- // events are CustomEvents on the element (they do not bubble)
38
- cp.addEventListener('kai-select', () => console.log('restore checkpoint'));
39
- </script>`;
40
-
41
- const meta = {
42
- title: 'Components/Checkpoint',
43
- tags: ['autodocs'],
44
- argTypes: argTypesFor('kai-checkpoint'),
45
- parameters: {
46
- layout: 'fullscreen',
47
- docs: {
48
- description: specDescription('kai-checkpoint', [
49
- '`<kai-checkpoint>` is the framework-agnostic **web component** for a bookmark/checkpoint button (with an optional tooltip and label), isolated in **Shadow DOM**.',
50
- '**When to use:** marking a restore point in a conversation in a non-Solid app. In SolidJS, compose the `Checkpoint` primitives.',
51
- '**Placement:** inline inside a message row (e.g. in the action bar) or in a chat toolbar; it is a compact `inline-block` button and does not need a dedicated row.',
52
- "**How to use:** register once with `import '@kitn.ai/ui/elements'`, set `label`, `tooltip`, `variant` (`ghost` | `default` | `outline`), and `size` via attributes, and listen for the `kai-select` **CustomEvent** on click.",
53
- 'See the **Code** tab for HTML usage.',
54
- ]),
55
- },
56
- },
57
- } satisfies Meta;
58
-
59
- export default meta;
60
- type Story = StoryObj;
61
-
62
- /** A labeled checkpoint button. (Add a `tooltip` attribute for a hover hint — see the Code tab.) */
63
- export const Labeled: Story = {
64
- render: () => <CheckpointElement label="Restore" variant="outline" />,
65
- parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
66
- };
67
-
68
- /** Icon-only (no label), using an `icon` size. */
69
- export const IconOnly: Story = {
70
- name: 'Icon Only',
71
- render: () => <CheckpointElement size="icon-sm" />,
72
- };
@@ -1,240 +0,0 @@
1
- import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
- import { createSignal, onMount, type JSX } from 'solid-js';
3
- import './choice';
4
- import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
- import type { ChoiceCardData } from '../components/choice-card';
6
- import type { CardEvent } from '../primitives/card-contract';
7
-
8
- declare module 'solid-js' {
9
- // eslint-disable-next-line @typescript-eslint/no-namespace
10
- namespace JSX {
11
- interface IntrinsicElements {
12
- 'kai-choice': JSX.HTMLAttributes<HTMLElement> & {
13
- heading?: string;
14
- 'card-id'?: string;
15
- ref?: (el: HTMLElement) => void;
16
- };
17
- }
18
- }
19
- }
20
-
21
- type ChoiceEl = HTMLElement & { data?: ChoiceCardData; resolution?: Record<string, unknown> };
22
-
23
- function Frame(props: { children: JSX.Element }) {
24
- return <div style={{ 'max-width': '460px' }}>{props.children}</div>;
25
- }
26
-
27
- /** Mounts a <kai-choice>, sets `.data`, logs the emitted CardEvent under the render. */
28
- function ChoiceDemo(props: { def: ChoiceCardData; cardId: string; heading?: string }) {
29
- const [log, setLog] = createSignal<CardEvent[]>([]);
30
- let el: ChoiceEl | undefined;
31
- onMount(() => {
32
- if (!el) return;
33
- el.data = props.def;
34
- el.addEventListener('kai-card', (e) => {
35
- const detail = (e as CustomEvent<CardEvent>).detail;
36
- setLog((prev) => [...prev, detail]);
37
- });
38
- });
39
- return (
40
- <Frame>
41
- <div style={{ display: 'flex', 'flex-direction': 'column', gap: '12px' }}>
42
- <kai-choice ref={(e) => (el = e as ChoiceEl)} card-id={props.cardId} heading={props.heading} />
43
- <pre
44
- style={{
45
- margin: 0,
46
- 'max-height': '180px',
47
- overflow: 'auto',
48
- background: 'var(--color-muted, #f4f4f5)',
49
- 'border-radius': '8px',
50
- padding: '8px',
51
- 'font-size': '12px',
52
- }}
53
- >
54
- {log().length === 0 ? '// emitted CardEvents appear here' : JSON.stringify(log(), null, 2)}
55
- </pre>
56
- </div>
57
- </Frame>
58
- );
59
- }
60
-
61
- const PLANS: ChoiceCardData = {
62
- prompt: 'Which plan fits your team?',
63
- options: [
64
- { id: 'free', label: 'Free', description: 'For trying things out', meta: '$0' },
65
- {
66
- id: 'pro',
67
- label: 'Pro',
68
- description: 'For growing teams',
69
- meta: '$12/seat',
70
- recommended: true,
71
- payload: { plan: 'pro' },
72
- },
73
- { id: 'enterprise', label: 'Enterprise', description: 'SSO, audit log, SLA', meta: 'Contact us' },
74
- { id: 'legacy', label: 'Legacy', description: 'No longer available', disabled: true },
75
- ],
76
- };
77
-
78
- const TEMPLATES: ChoiceCardData = {
79
- prompt: 'Pick a workspace template.',
80
- submitLabel: 'Create workspace',
81
- options: [
82
- {
83
- id: 'blank',
84
- label: 'Blank',
85
- description: 'Start from scratch',
86
- media: { image: 'https://placehold.co/80x80/png?text=Blank', imageAlt: 'A blank canvas' },
87
- },
88
- {
89
- id: 'kanban',
90
- label: 'Kanban',
91
- description: 'Board with columns',
92
- recommended: true,
93
- media: { image: 'https://placehold.co/80x80/png?text=Kanban', imageAlt: 'A kanban board' },
94
- payload: { template: 'kanban' },
95
- },
96
- {
97
- id: 'docs',
98
- label: 'Docs',
99
- description: 'Wiki-style pages',
100
- media: { image: 'https://placehold.co/80x80/png?text=Docs', imageAlt: 'A document page' },
101
- },
102
- ],
103
- };
104
-
105
- const QUICK_REPLIES: ChoiceCardData = {
106
- prompt: 'How did this answer land?',
107
- options: [
108
- { id: 'great', label: 'That solved it', payload: { sentiment: 'positive' } },
109
- { id: 'partly', label: 'Partly — needs more', payload: { sentiment: 'neutral' } },
110
- { id: 'no', label: 'Not what I meant', payload: { sentiment: 'negative' } },
111
- ],
112
- allowOther: { label: 'Something else…', placeholder: 'Tell me what you expected' },
113
- };
114
-
115
- const HEADING_MAP: Record<string, string | undefined> = {
116
- 'card-plans': 'Choose a plan',
117
- 'card-templates': 'New workspace',
118
- 'card-replies': undefined,
119
- };
120
-
121
- const HTML_SNIPPET = (def: ChoiceCardData, cardId: string) => {
122
- const heading = HEADING_MAP[cardId];
123
- return `<kai-choice${heading ? ` heading="${heading}"` : ''}></kai-choice>
124
- <script type="module">
125
- import '@kitn.ai/ui/elements'; // registers the custom elements
126
-
127
- const el = document.querySelector('kai-choice');
128
- // \`data\` is the CardEnvelope.data (set as a property).
129
- el.data = ${JSON.stringify(def, null, 2)};
130
-
131
- // Cards bubble ONE \`kai-card\` CustomEvent carrying a typed CardEvent.
132
- el.addEventListener('kai-card', (e) => {
133
- const ev = e.detail; // { kind:'action', cardId, action, payload? } | { kind:'ready', ... } | ...
134
- if (ev.kind === 'action') console.log('chose', ev.action, ev.payload);
135
- });
136
- </script>`;
137
- };
138
-
139
- const meta = {
140
- title: 'Generative UI/Cards/kai-choice',
141
- tags: ['autodocs'],
142
- argTypes: argTypesFor('kai-choice'),
143
- parameters: {
144
- layout: 'padded',
145
- docs: {
146
- description: specDescription('kai-choice', [
147
- "`<kai-choice>` is a **single-select** 'pick one of N rich options' card (set via the `data` **property**): an optional prompt + a radiogroup of list rows + a **Submit** button. Clicking a row (or Space/Enter on the focused row) **selects** it locally — nothing is emitted. Submit then emits the Card contract's **`action`** verb up a bubbling **`kai-card`** CustomEvent of `{ kind:'action', cardId, action: option.id, payload? }`, then **resolves** the card (the chosen option shown read-only) so the same pick can't double-fire. The Submit label is `submitLabel` (default 'Submit').",
148
- '**Rich-but-bounded options:** every field except `id`/`label` is optional — `description`, `media` (image + `imageAlt`, or a named `icon`), `meta` (trailing price/badge), `recommended` (a pill), `disabled` (inert + skipped in keyboard nav), and an opaque `payload` echoed back. A weaker model can just omit them.',
149
- "**`allowOther`** (opt-in) appends a final 'Other…' row: selecting it reveals an inline text input. The single shared **Submit** stays disabled until the text is non-empty; submitting emits `{ kind:'action', action:'__other__', payload:{ text } }`.",
150
- '**Accessibility:** the options are a WAI-ARIA `radiogroup` (`role="radio"` + `aria-checked`) with **roving tabindex** — one tab stop in, Arrow keys move focus (skipping disabled), Enter/Space select the focused row. Disabled options are `aria-disabled` and not focusable; option images carry alt text; the Other input has a label. **0 axe violations** (light + dark).',
151
- '**Events** (all frozen Card-contract verbs): `ready` on mount, `action` on Submit, `error` for a malformed definition (renders the inline `kai-card` error). It **never invents events**, and — because it carries a registry entry — `<kai-cards>` / `renderCard` dispatch it automatically.',
152
- ]),
153
- },
154
- },
155
- } satisfies Meta;
156
-
157
- export default meta;
158
- type Story = StoryObj;
159
-
160
- /** A list of plans with a `recommended` pill, `meta` prices, and a disabled legacy row.
161
- * Select a row, then click Submit to emit the `action`. */
162
- export const Plans: Story = {
163
- render: () => <ChoiceDemo def={PLANS} cardId="card-plans" heading="Choose a plan" />,
164
- parameters: { docs: { source: { code: HTML_SNIPPET(PLANS, 'card-plans'), language: 'html' } } },
165
- };
166
-
167
- /** Rows with leading images (each `media.image` carries `imageAlt`) and a custom `submitLabel`. */
168
- export const WithMedia: Story = {
169
- render: () => <ChoiceDemo def={TEMPLATES} cardId="card-templates" heading="New workspace" />,
170
- parameters: { docs: { source: { code: HTML_SNIPPET(TEMPLATES, 'card-templates'), language: 'html' } } },
171
- };
172
-
173
- /** Quick replies with the `allowOther` free-text escape: select Other, type, then Submit. */
174
- export const AllowOther: Story = {
175
- render: () => <ChoiceDemo def={QUICK_REPLIES} cardId="card-replies" />,
176
- parameters: { docs: { source: { code: HTML_SNIPPET(QUICK_REPLIES, 'card-replies'), language: 'html' } } },
177
- };
178
-
179
- const RESOLVED_CHOICE: ChoiceCardData = {
180
- prompt: 'Which plan?',
181
- options: [
182
- { id: 'free', label: 'Free', meta: '$0' },
183
- { id: 'pro', label: 'Pro', meta: '$20/mo' },
184
- ],
185
- };
186
-
187
- /** The card after the user chose **Pro** — only the chosen option shown, no radiogroup or Submit. */
188
- export const Resolved: Story = {
189
- name: 'Resolved (read-only)',
190
- render: () => {
191
- let el: ChoiceEl | undefined;
192
- onMount(() => {
193
- if (!el) return;
194
- el.data = RESOLVED_CHOICE;
195
- el.resolution = { kind: 'action', action: 'pro' };
196
- });
197
- return (
198
- <Frame>
199
- <kai-choice ref={(e) => (el = e as ChoiceEl)} card-id="card-resolved-choice" heading="Choose a plan" />
200
- </Frame>
201
- );
202
- },
203
- parameters: {
204
- docs: {
205
- source: {
206
- code: `<kai-choice heading="Choose a plan"></kai-choice>
207
- <script type="module">
208
- import '@kitn.ai/ui/elements';
209
- const el = document.querySelector('kai-choice');
210
- el.data = ${JSON.stringify(RESOLVED_CHOICE, null, 2)};
211
- // Setting .resolution renders the chromed read-only view — no radiogroup or Submit.
212
- el.resolution = { kind: 'action', action: 'pro' };
213
- </script>`,
214
- language: 'html',
215
- },
216
- },
217
- },
218
- };
219
-
220
- /** A malformed `data` (empty `options`) → the inline error state + an `error` event. */
221
- export const ErrorState: Story = {
222
- render: () => <ChoiceDemo def={{ options: [] } as unknown as ChoiceCardData} cardId="card-bad" />,
223
- parameters: {
224
- docs: {
225
- source: {
226
- code: `<kai-choice></kai-choice>
227
- <script type="module">
228
- import '@kitn.ai/ui/elements';
229
- const el = document.querySelector('kai-choice');
230
- // No options → inline error state + an \`error\` event.
231
- el.data = { options: [] };
232
- el.addEventListener('kai-card', (e) => {
233
- if (e.detail.kind === 'error') console.warn('choice error:', e.detail.message);
234
- });
235
- </script>`,
236
- language: 'html',
237
- },
238
- },
239
- },
240
- };
@@ -1,83 +0,0 @@
1
- import type { Meta, StoryObj } from 'storybook-solidjs-vite';
2
- import { onMount } from 'solid-js';
3
- import './register'; // side effect: registers the custom elements
4
- import { argTypesFor, specDescription } from '../stories/docs/element-controls';
5
-
6
- // The web components are custom DOM elements, so declare the tags for JSX.
7
- declare module 'solid-js' {
8
- // eslint-disable-next-line @typescript-eslint/no-namespace
9
- namespace JSX {
10
- interface IntrinsicElements {
11
- 'kai-code-block': JSX.HTMLAttributes<HTMLElement>;
12
- }
13
- }
14
- }
15
-
16
- const sampleCode = `export function add(a: number, b: number): number {
17
- return a + b;
18
- }`;
19
-
20
- const pythonCode = `def fib(n):
21
- a, b = 0, 1
22
- for _ in range(n):
23
- a, b = b, a + b
24
- return a`;
25
-
26
- /** Render the actual `<kai-code-block>` custom element with a `code` property. */
27
- function CodeBlockElement(props: { code: string; language?: string }) {
28
- let el: (HTMLElement & { code?: string }) | undefined;
29
- onMount(() => {
30
- if (el) {
31
- el.code = props.code;
32
- if (props.language) el.setAttribute('language', props.language);
33
- }
34
- });
35
- return (
36
- <kai-code-block
37
- ref={(e) => (el = e as HTMLElement)}
38
- style={{ display: 'block', padding: '16px', 'max-width': '720px' }}
39
- />
40
- );
41
- }
42
-
43
- const HTML_SNIPPET = `<!-- Works in any framework or plain HTML -->
44
- <kai-code-block id="code" language="ts" code-theme="github-dark-dimmed"></kai-code-block>
45
-
46
- <script type="module">
47
- import '@kitn.ai/ui/elements'; // registers the custom elements
48
-
49
- const code = document.getElementById('code');
50
- code.code = 'export function add(a, b) {\\n return a + b;\\n}';
51
- </script>`;
52
-
53
- const meta = {
54
- title: 'Components/CodeBlock',
55
- tags: ['autodocs'],
56
- argTypes: argTypesFor('kai-code-block'),
57
- parameters: {
58
- layout: 'fullscreen',
59
- docs: {
60
- description: specDescription('kai-code-block', [
61
- '`<kai-code-block>` is the framework-agnostic **web component** for a single syntax-highlighted code block, complete with a copy button, isolated in **Shadow DOM**.',
62
- '**When to use:** dropping a highlighted snippet into a non-Solid app. In SolidJS, compose `CodeBlock` + `CodeBlockCode` directly.',
63
- '**Placement:** as a block inside a message row, tutorial card, or documentation pane; it is `display: block` and fills container width, so set `max-width` on the parent or the element to control line lengths.',
64
- "**How to use:** register once with `import '@kitn.ai/ui/elements'`, set the source via the `code` **property** (`el.code = '...'`), and pick a grammar with the `language` attribute (defaults to `tsx`). Tune highlighting with `code-theme` / `code-highlight`.",
65
- 'See the **Code** tab for HTML usage.',
66
- ]),
67
- },
68
- },
69
- } satisfies Meta;
70
-
71
- export default meta;
72
- type Story = StoryObj;
73
-
74
- /** A TypeScript snippet (the default `tsx` grammar). */
75
- export const TypeScript: Story = {
76
- render: () => <CodeBlockElement code={sampleCode} language="ts" />,
77
- parameters: { docs: { source: { code: HTML_SNIPPET, language: 'html' } } },
78
- };
79
-
80
- /** A different grammar via the `language` attribute. */
81
- export const Python: Story = {
82
- render: () => <CodeBlockElement code={pythonCode} language="python" />,
83
- };