@iyulab/chat-components 0.6.0 → 0.7.1

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 (211) hide show
  1. package/CHANGELOG.md +51 -0
  2. package/README.md +15 -39
  3. package/dist/_virtual/{_@oxc-project_runtime@0.130.0/helpers → _@oxc-project_runtime@0.139.0/helpers/esm}/decorate.js +2 -2
  4. package/dist/_virtual/{_@oxc-project_runtime@0.130.0/helpers → _@oxc-project_runtime@0.139.0/helpers/esm}/decorateMetadata.js +2 -2
  5. package/dist/_virtual/_glob-assets_raw/alert-triangle-fill.svg.4cfc4305.js +4 -0
  6. package/dist/_virtual/_glob-assets_raw/arrows-sort.svg.dda43a85.js +4 -0
  7. package/dist/_virtual/_glob-assets_raw/code.svg.c69bc144.js +4 -0
  8. package/dist/_virtual/_glob-assets_raw/download.svg.bce82177.js +4 -0
  9. package/dist/_virtual/_glob-assets_raw/element-prompt.md.7047ffcc.js +4 -0
  10. package/dist/_virtual/_glob-assets_raw/external-link.svg.a9f7f02d.js +4 -0
  11. package/dist/_virtual/_glob-assets_raw/file-code.svg.0e706f93.js +4 -0
  12. package/dist/_virtual/_glob-assets_raw/file-music.svg.b9970203.js +4 -0
  13. package/dist/_virtual/_glob-assets_raw/file-spreadsheet.svg.8c03bdfa.js +4 -0
  14. package/dist/_virtual/_glob-assets_raw/file-text.svg.85bdd923.js +4 -0
  15. package/dist/_virtual/_glob-assets_raw/file-type-pdf.svg.bc12db6d.js +4 -0
  16. package/dist/_virtual/_glob-assets_raw/file-zip.svg.76dde660.js +4 -0
  17. package/dist/_virtual/_glob-assets_raw/file.svg.28f5d6f1.js +4 -0
  18. package/dist/_virtual/_glob-assets_raw/photo.svg.cc273cc1.js +4 -0
  19. package/dist/_virtual/_glob-assets_raw/player-stop-fill.svg.5378b752.js +4 -0
  20. package/dist/_virtual/_glob-assets_raw/send.svg.02326253.js +4 -0
  21. package/dist/_virtual/_glob-assets_raw/sort-ascending-letters.svg.14a3df67.js +4 -0
  22. package/dist/_virtual/_glob-assets_raw/sort-descending-letters.svg.3e03647c.js +4 -0
  23. package/dist/_virtual/_glob-assets_raw/video.svg.c183f03c.js +4 -0
  24. package/dist/_virtual/_glob-assets_raw/world.svg.cd9903c8.js +4 -0
  25. package/dist/components/UDataElement.d.ts +48 -0
  26. package/dist/components/UDataElement.js +80 -0
  27. package/dist/components/blocks/UCodeBlock.d.ts +0 -4
  28. package/dist/components/blocks/UCodeBlock.js +6 -12
  29. package/dist/components/{views/UView.d.ts → blocks/UElementBlock.d.ts} +18 -8
  30. package/dist/components/{views/UView.js → blocks/UElementBlock.js} +31 -21
  31. package/dist/components/{views/UView.styles.js → blocks/UElementBlock.styles.js} +1 -1
  32. package/dist/components/blocks/UFileBlock.d.ts +15 -5
  33. package/dist/components/blocks/UFileBlock.js +81 -68
  34. package/dist/components/blocks/UFileBlock.styles.js +86 -29
  35. package/dist/components/blocks/UMarkedBlock.d.ts +3 -1
  36. package/dist/components/blocks/UMarkedBlock.js +23 -18
  37. package/dist/components/blocks/URefBlock.js +2 -2
  38. package/dist/components/blocks/UTableBlock.d.ts +2 -2
  39. package/dist/components/blocks/UTableBlock.js +9 -8
  40. package/dist/components/blocks/UTableBlock.styles.js +1 -1
  41. package/dist/components/blocks/UTextBlock.d.ts +2 -0
  42. package/dist/components/blocks/UTextBlock.js +4 -5
  43. package/dist/components/message/UMessage.js +2 -2
  44. package/dist/components/prompt/UPrompt.d.ts +0 -5
  45. package/dist/components/prompt/UPrompt.js +18 -27
  46. package/dist/components/prompt/UPrompt.styles.js +9 -10
  47. package/dist/components/references/URefCard.d.ts +6 -5
  48. package/dist/components/references/URefCard.js +14 -11
  49. package/dist/components/references/URefCardGroup.js +2 -2
  50. package/dist/components/references/URefTag.js +5 -4
  51. package/dist/{components/views/UChartView.d.ts → components-extra/UChartBlock.d.ts} +4 -4
  52. package/dist/{components/views/UChartView.js → components-extra/UChartBlock.js} +22 -34
  53. package/dist/components-extra/UChartBlock.schema.d.ts +3 -0
  54. package/dist/components-extra/UChartBlock.schema.js +34 -0
  55. package/dist/{components/views/UChartView.styles.js → components-extra/UChartBlock.styles.js} +1 -1
  56. package/dist/{components/views/UImagesView.d.ts → components-extra/UImagesBlock.d.ts} +4 -4
  57. package/dist/{components/views/UImagesView.js → components-extra/UImagesBlock.js} +15 -15
  58. package/dist/components-extra/UImagesBlock.schema.d.ts +3 -0
  59. package/dist/components-extra/UImagesBlock.schema.js +31 -0
  60. package/dist/{components/views/UImagesView.styles.js → components-extra/UImagesBlock.styles.js} +5 -5
  61. package/dist/{components/views/UMapView.d.ts → components-extra/UMapBlock.d.ts} +4 -4
  62. package/dist/{components/views/UMapView.js → components-extra/UMapBlock.js} +18 -18
  63. package/dist/components-extra/UMapBlock.schema.d.ts +3 -0
  64. package/dist/components-extra/UMapBlock.schema.js +33 -0
  65. package/dist/{components/views/UMapView.styles.js → components-extra/UMapBlock.styles.js} +1 -1
  66. package/dist/{components/views/UVideoView.d.ts → components-extra/UVideoBlock.d.ts} +4 -4
  67. package/dist/{components/views/UVideoView.js → components-extra/UVideoBlock.js} +10 -10
  68. package/dist/components-extra/UVideoBlock.schema.d.ts +3 -0
  69. package/dist/components-extra/UVideoBlock.schema.js +28 -0
  70. package/dist/{components/views/UVideoView.styles.js → components-extra/UVideoBlock.styles.js} +1 -1
  71. package/dist/events/SendEvent.d.ts +0 -5
  72. package/dist/events/StopEvent.d.ts +0 -5
  73. package/dist/extra.d.ts +6 -0
  74. package/dist/extra.js +14 -0
  75. package/dist/index.d.ts +5 -17
  76. package/dist/index.js +6 -16
  77. package/dist/react/UCodeBlock.js +2 -2
  78. package/dist/react/UElementBlock.d.ts +9 -0
  79. package/dist/react/UElementBlock.js +10 -0
  80. package/dist/react/UFileBlock.js +2 -2
  81. package/dist/react/UImagesBlock.d.ts +9 -0
  82. package/dist/react/UImagesBlock.js +10 -0
  83. package/dist/react/UMapBlock.d.ts +9 -0
  84. package/dist/react/UMapBlock.js +10 -0
  85. package/dist/react/UMarkedBlock.js +2 -2
  86. package/dist/react/UMessage.js +2 -2
  87. package/dist/react/UPrompt.js +2 -2
  88. package/dist/react/URefBlock.js +2 -2
  89. package/dist/react/URefCard.js +2 -2
  90. package/dist/react/URefCardGroup.js +2 -2
  91. package/dist/react/URefTag.js +2 -2
  92. package/dist/react/UTableBlock.js +2 -2
  93. package/dist/react/UTextBlock.d.ts +1 -0
  94. package/dist/react/UTextBlock.js +5 -3
  95. package/dist/react/UVideoBlock.d.ts +9 -0
  96. package/dist/react/UVideoBlock.js +10 -0
  97. package/dist/react/index.d.ts +4 -11
  98. package/dist/react/index.js +4 -11
  99. package/dist/types/BlockItem.d.ts +1 -24
  100. package/dist/types/{JsonSchema.d.ts → Schema.d.ts} +13 -0
  101. package/dist/utilities/HtmlBuilder.d.ts +28 -0
  102. package/dist/utilities/HtmlBuilder.js +41 -0
  103. package/dist/utilities/PromptBuilder.d.ts +21 -0
  104. package/dist/utilities/PromptBuilder.js +60 -0
  105. package/dist/utilities/icons.d.ts +1 -0
  106. package/dist/utilities/icons.js +52 -0
  107. package/dist/utilities/sanitizers.d.ts +35 -0
  108. package/dist/utilities/sanitizers.js +75 -0
  109. package/package.json +18 -19
  110. package/skills/iyulab-chat-components/SKILL.md +18 -33
  111. package/skills/iyulab-chat-components/references/components/{chart-view.md → chart-block.md} +16 -12
  112. package/skills/iyulab-chat-components/references/components/code-block.md +1 -5
  113. package/skills/iyulab-chat-components/references/components/element-block.md +57 -0
  114. package/skills/iyulab-chat-components/references/components/file-block.md +22 -25
  115. package/skills/iyulab-chat-components/references/components/{images-view.md → images-block.md} +10 -10
  116. package/skills/iyulab-chat-components/references/components/{map-view.md → map-block.md} +9 -9
  117. package/skills/iyulab-chat-components/references/components/marked-block.md +5 -4
  118. package/skills/iyulab-chat-components/references/components/message.md +1 -2
  119. package/skills/iyulab-chat-components/references/components/prompt.md +12 -21
  120. package/skills/iyulab-chat-components/references/components/{video-view.md → video-block.md} +10 -10
  121. package/skills/iyulab-chat-components/references/extra-system.md +95 -0
  122. package/skills/iyulab-chat-components/references/types.md +17 -31
  123. package/skills/iyulab-chat-components/references/usage.md +13 -81
  124. package/skills/iyulab-chat-components/references/utilities/html-builder.md +35 -0
  125. package/skills/iyulab-chat-components/references/utilities/prompt-builder.md +73 -0
  126. package/dist/_virtual/_glob-assets_raw/intent-prompt.md.1907474e.js +0 -4
  127. package/dist/_virtual/_glob-assets_raw/view-prompt.md.e0dbcffe.js +0 -4
  128. package/dist/chart.d.ts +0 -1
  129. package/dist/chart.js +0 -2
  130. package/dist/components/blocks/UJsonBlock.d.ts +0 -49
  131. package/dist/components/blocks/UJsonBlock.js +0 -130
  132. package/dist/components/blocks/UJsonBlock.styles.js +0 -115
  133. package/dist/components/blocks/UThinkBlock.d.ts +0 -35
  134. package/dist/components/blocks/UThinkBlock.js +0 -87
  135. package/dist/components/blocks/UThinkBlock.styles.js +0 -74
  136. package/dist/components/blocks/UToolBlock.d.ts +0 -24
  137. package/dist/components/blocks/UToolBlock.js +0 -70
  138. package/dist/components/blocks/UToolBlock.styles.js +0 -66
  139. package/dist/components/buttons/UAttachButton.d.ts +0 -26
  140. package/dist/components/buttons/UAttachButton.js +0 -63
  141. package/dist/components/buttons/UAttachButton.styles.js +0 -14
  142. package/dist/components/buttons/UCopyButton.d.ts +0 -24
  143. package/dist/components/buttons/UCopyButton.js +0 -59
  144. package/dist/components/buttons/UCopyButton.styles.js +0 -18
  145. package/dist/components/buttons/UVoteButton.d.ts +0 -19
  146. package/dist/components/buttons/UVoteButton.js +0 -64
  147. package/dist/components/buttons/UVoteButton.styles.d.ts +0 -1
  148. package/dist/components/buttons/UVoteButton.styles.js +0 -19
  149. package/dist/components/intents/UQuestionIntent.d.ts +0 -22
  150. package/dist/components/intents/UQuestionIntent.js +0 -41
  151. package/dist/components/intents/UQuestionIntent.styles.d.ts +0 -1
  152. package/dist/components/intents/UQuestionIntent.styles.js +0 -43
  153. package/dist/components/views/UChartView.styles.d.ts +0 -1
  154. package/dist/components/views/UImagesView.styles.d.ts +0 -1
  155. package/dist/components/views/UMapView.styles.d.ts +0 -1
  156. package/dist/components/views/UVideoView.styles.d.ts +0 -1
  157. package/dist/components/views/UView.styles.d.ts +0 -1
  158. package/dist/events/AttachEvent.d.ts +0 -9
  159. package/dist/events/ChoiceEvent.d.ts +0 -9
  160. package/dist/react/UAttachButton.d.ts +0 -11
  161. package/dist/react/UAttachButton.js +0 -12
  162. package/dist/react/UCopyButton.d.ts +0 -9
  163. package/dist/react/UCopyButton.js +0 -10
  164. package/dist/react/UImagesView.d.ts +0 -9
  165. package/dist/react/UImagesView.js +0 -10
  166. package/dist/react/UJsonBlock.d.ts +0 -9
  167. package/dist/react/UJsonBlock.js +0 -10
  168. package/dist/react/UMapView.d.ts +0 -9
  169. package/dist/react/UMapView.js +0 -10
  170. package/dist/react/UQuestionIntent.d.ts +0 -11
  171. package/dist/react/UQuestionIntent.js +0 -12
  172. package/dist/react/UThinkBlock.d.ts +0 -9
  173. package/dist/react/UThinkBlock.js +0 -10
  174. package/dist/react/UToolBlock.d.ts +0 -9
  175. package/dist/react/UToolBlock.js +0 -10
  176. package/dist/react/UVideoView.d.ts +0 -9
  177. package/dist/react/UVideoView.js +0 -10
  178. package/dist/react/UView.d.ts +0 -9
  179. package/dist/react/UView.js +0 -10
  180. package/dist/react/UVoteButton.d.ts +0 -9
  181. package/dist/react/UVoteButton.js +0 -10
  182. package/dist/types/Intents.d.ts +0 -26
  183. package/dist/types/Intents.js +0 -30
  184. package/dist/types/JsonNode.d.ts +0 -20
  185. package/dist/types/Views.d.ts +0 -34
  186. package/dist/types/Views.js +0 -148
  187. package/dist/utilities/IntentPromptBuilder.d.ts +0 -40
  188. package/dist/utilities/IntentPromptBuilder.js +0 -95
  189. package/dist/utilities/ViewPromptBuilder.d.ts +0 -28
  190. package/dist/utilities/ViewPromptBuilder.js +0 -78
  191. package/dist/utilities/dom-agent/DOMAgent.d.ts +0 -74
  192. package/dist/utilities/dom-agent/DOMController.d.ts +0 -78
  193. package/dist/utilities/dom-agent/DOMPromptBuilder.d.ts +0 -54
  194. package/dist/utilities/dom-agent/DOMScanner.d.ts +0 -83
  195. package/dist/utilities/dom-agent/index.d.ts +0 -9
  196. package/dist/utilities/dom-agent/types.d.ts +0 -209
  197. package/skills/iyulab-chat-components/references/components/attach-button.md +0 -69
  198. package/skills/iyulab-chat-components/references/components/copy-button.md +0 -46
  199. package/skills/iyulab-chat-components/references/components/json-block.md +0 -41
  200. package/skills/iyulab-chat-components/references/components/question-intent.md +0 -75
  201. package/skills/iyulab-chat-components/references/components/think-block.md +0 -48
  202. package/skills/iyulab-chat-components/references/components/tool-block.md +0 -57
  203. package/skills/iyulab-chat-components/references/components/view.md +0 -51
  204. package/skills/iyulab-chat-components/references/components/vote-button.md +0 -60
  205. package/skills/iyulab-chat-components/references/utilities/intent-prompt-builder.md +0 -123
  206. package/skills/iyulab-chat-components/references/utilities/view-prompt-builder.md +0 -112
  207. /package/dist/components/{buttons/UCopyButton.styles.d.ts → blocks/UElementBlock.styles.d.ts} +0 -0
  208. /package/dist/{components/blocks/UJsonBlock.styles.d.ts → components-extra/UChartBlock.styles.d.ts} +0 -0
  209. /package/dist/{components/blocks/UThinkBlock.styles.d.ts → components-extra/UImagesBlock.styles.d.ts} +0 -0
  210. /package/dist/{components/blocks/UToolBlock.styles.d.ts → components-extra/UMapBlock.styles.d.ts} +0 -0
  211. /package/dist/{components/buttons/UAttachButton.styles.d.ts → components-extra/UVideoBlock.styles.d.ts} +0 -0
@@ -1,10 +1,10 @@
1
1
  ---
2
2
  name: iyulab-chat-components
3
- description: LLM chat UI component library. Covers all u-* custom elements for building chat interfaces — message rendering, chat input, markdown/code blocks, file attachments, reference citations, and the Intent/View system. Use when working with @iyulab/chat-components package.
3
+ description: LLM chat UI component library. Covers all u-* custom elements for building chat interfaces — message rendering, chat input, markdown/code/table/file blocks, reference citations, and the block-json Extra system (chart/images/map/video). Use when working with @iyulab/chat-components package.
4
4
  license: MIT
5
5
  metadata:
6
6
  author: iyulab
7
- version: "0.5.2"
7
+ version: "0.7.0"
8
8
  ---
9
9
 
10
10
  # @iyulab/chat-components
@@ -43,21 +43,13 @@ import '@iyulab/chat-components/dist/components/prompt/UPrompt.js';
43
43
 
44
44
  ### Content Blocks
45
45
 
46
- - [`u-marked-block`](./references/components/marked-block.md) — Renders markdown to HTML. KaTeX math, code highlighting, citation insertion, view-json/intent-json handling
46
+ - [`u-marked-block`](./references/components/marked-block.md) — Renders markdown to HTML. KaTeX math, code highlighting, citation insertion, `block-json` extra handling
47
47
  - [`u-code-block`](./references/components/code-block.md) — Highlight.js code block with language label and clipboard copy
48
48
  - [`u-text-block`](./references/components/text-block.md) — Plain text display or editable textarea
49
- - [`u-think-block`](./references/components/think-block.md) — LLM reasoning (thinking) block. Collapse/expand, auto-scroll
50
- - [`u-tool-block`](./references/components/tool-block.md) — Tool call input/output display. Collapse/expand
51
- - [`u-file-block`](./references/components/file-block.md) — File attachment card. Type icon, upload status, download, remove
49
+ - [`u-file-block`](./references/components/file-block.md) — File attachment card. Type icon or image/video thumbnail, click-to-preview, remove
52
50
  - [`u-ref-block`](./references/components/ref-block.md) — Reference source group block. Collapse/expand, grid of ref cards
53
- - [`u-json-block`](./references/components/json-block.md) — Visualizes JSON data as a collapsible tree
54
51
  - [`u-table-block`](./references/components/table-block.md) — Markdown table renderer. Column sort, search filter, CSV/XLS download
55
-
56
- ### Action Buttons
57
-
58
- - [`u-copy-button`](./references/components/copy-button.md) — Clipboard copy button; icon changes after copy
59
- - [`u-vote-button`](./references/components/vote-button.md) — Thumbs-up / thumbs-down vote button pair
60
- - [`u-attach-button`](./references/components/attach-button.md) — File picker button; fires `attach` event with selected files
52
+ - [`u-element-block`](./references/components/element-block.md) — Generic dynamic custom-element renderer, used internally to render `block-json` extras
61
53
 
62
54
  ### Reference Components
63
55
 
@@ -65,43 +57,36 @@ import '@iyulab/chat-components/dist/components/prompt/UPrompt.js';
65
57
  - [`u-ref-card`](./references/components/ref-card.md) — Reference source card. web/document type, favicon, tags
66
58
  - [`u-ref-card-group`](./references/components/ref-card-group.md) — Paginated group of reference cards
67
59
 
68
- ### Intent Components
69
-
70
- - [`u-question-intent`](./references/components/question-intent.md) — LLM-generated question with clickable choice buttons
60
+ ### Extra Components (optional, `@iyulab/chat-components/extra`)
71
61
 
72
- ### View Components
62
+ Not part of the core entrypoint — see [./references/extra-system.md](./references/extra-system.md) for setup.
73
63
 
74
- - [`u-images-view`](./references/components/images-view.md) — Image gallery (carousel + lightbox)
75
- - [`u-video-view`](./references/components/video-view.md) — YouTube / Vimeo / direct video file player
76
- - [`u-chart-view`](./references/components/chart-view.md) — Chart.js charts (bar, line, pie, etc.)
77
- - [`u-map-view`](./references/components/map-view.md) — OpenStreetMap embed
78
- - [`u-view`](./references/components/view.md) — Dynamic custom element renderer (runtime for view-json blocks)
64
+ - [`u-images-block`](./references/components/images-block.md) — Image gallery (carousel + lightbox)
65
+ - [`u-video-block`](./references/components/video-block.md) — YouTube / Vimeo / direct video file player
66
+ - [`u-chart-block`](./references/components/chart-block.md) — Chart.js charts (bar, line, pie, etc.)
67
+ - [`u-map-block`](./references/components/map-block.md) — OpenStreetMap embed
79
68
 
80
69
  ---
81
70
 
82
71
  ## Utilities
83
72
 
84
- - [`IntentPromptBuilder`](./references/utilities/intent-prompt-builder.md) — Build LLM system prompt instructions for intents and parse intent-json responses
85
- - [`ViewPromptBuilder`](./references/utilities/view-prompt-builder.md) — Build LLM system prompt instructions for views
73
+ - [`ElementPromptBuilder`](./references/utilities/prompt-builder.md) — Build LLM system prompt instructions for `block-json` extras/elements
74
+ - [`HtmlBuilder`](./references/utilities/html-builder.md) — Build custom-element HTML strings (used internally by `u-marked-block`)
86
75
 
87
76
  ---
88
77
 
89
78
  ## Types
90
79
 
91
- - [`BlockItem`](./references/types.md) — Union type for message content blocks (text, markdown, file, tool, reference, thinking)
80
+ - [`BlockItem`](./references/types.md) — Union type for message content blocks (text, markdown, file, reference)
92
81
  - `ReferenceSource` / `ReferenceCitation` — Citation source and inline citation position types
93
- - `IntentDefinition` / `PresetIntent` — Intent definition and preset bit flags
94
- - `ViewDefinition` / `PresetView` — View definition and preset bit flags
82
+ - `ElementSchema` / `JsonSchema` — Schema types for registering `block-json` extras/elements with `ElementPromptBuilder`
95
83
 
96
84
  ---
97
85
 
98
86
  ## Events
99
87
 
100
88
  | Event | Source | Detail Type | Description |
101
- |-------|--------|-------------|-------------|
102
- | `send` | `u-prompt` | `unknown` | Send button clicked or Enter pressed |
103
- | `stop` | `u-prompt` | `unknown` | Stop button clicked while loading |
104
- | `attach` | `u-attach-button` | `{ files: File[] }` | File selection completed |
105
- | `choice` | `u-question-intent` | `{ value: string }` | Choice button clicked |
106
- | `change` | `u-vote-button` | `Event` | Vote state changed |
89
+ |-------|--------|-------------|--------------|
90
+ | `send` | `u-prompt` | `SendEventDetail` (`{ value, files? }`) | Send button clicked or Enter pressed. Non-bubbling |
91
+ | `stop` | `u-prompt` | `StopEventDetail` (`{}`) | Stop button clicked while loading. Non-bubbling |
107
92
  | `remove` | `u-file-block` | `RemoveEventDetail` | Remove button clicked |
@@ -1,40 +1,40 @@
1
- # u-chart-view
1
+ # u-chart-block
2
2
 
3
3
  ```ts
4
- import '@iyulab/chat-components/dist/components/views/UChartView.js';
4
+ import '@iyulab/chat-components/dist/components-extra/UChartBlock.js';
5
5
  ```
6
6
 
7
- **Tag:** `u-chart-view`
7
+ **Tag:** `u-chart-block` — one of the 4 built-in **extra** blocks. Not part of the core entrypoint; import it (or the whole `/extra` subpath) explicitly. See [../extra-system.md](../extra-system.md).
8
8
 
9
- Renders charts using Chart.js (lazy-loaded). Supports PNG and JSON download. Automatically re-renders when the page theme changes.
9
+ Renders charts using Chart.js (statically imported). Supports PNG and JSON download, and a full-screen toggle. Automatically re-renders when the page theme changes.
10
10
 
11
11
  ```html
12
12
  <!-- Bar chart -->
13
- <u-chart-view
13
+ <u-chart-block
14
14
  type="bar"
15
15
  .data=${{
16
16
  labels: ['Jan', 'Feb', 'Mar'],
17
17
  datasets: [{ label: 'Revenue', data: [100, 200, 150] }]
18
18
  }}
19
- ></u-chart-view>
19
+ ></u-chart-block>
20
20
 
21
21
  <!-- Line chart with options -->
22
- <u-chart-view
22
+ <u-chart-block
23
23
  type="line"
24
24
  .data=${{
25
25
  labels: ['A', 'B', 'C', 'D'],
26
26
  datasets: [{ label: 'Trend', data: [10, 40, 30, 60], fill: true }]
27
27
  }}
28
28
  .options=${{ plugins: { legend: { position: 'bottom' } } }}
29
- ></u-chart-view>
29
+ ></u-chart-block>
30
30
  ```
31
31
 
32
- LLM output example (`view-json` code block):
32
+ LLM output example (`block-json` code fence, rendered via `u-element-block`):
33
33
 
34
34
  ````
35
- ```view-json
35
+ ```block-json
36
36
  {
37
- "tag": "u-chart-view",
37
+ "tag": "u-chart-block",
38
38
  "properties": {
39
39
  "type": "bar",
40
40
  "data": {
@@ -60,6 +60,10 @@ LLM output example (`view-json` code block):
60
60
 
61
61
  | Feature | Description |
62
62
  |---------|-------------|
63
- | Lazy load | Chart.js is dynamically imported on first render |
64
63
  | Download | Export chart as PNG or raw JSON data |
64
+ | Full screen | Toggle the chart viewport into full-screen mode |
65
65
  | Theme sync | Watches `document.documentElement[theme]` and re-renders on change |
66
+
67
+ ## Requires
68
+
69
+ `chart.js` (optional peer dependency) must be installed to use this component. It's imported statically at module load, not lazily.
@@ -6,7 +6,7 @@ import '@iyulab/chat-components/dist/components/blocks/UCodeBlock.js';
6
6
 
7
7
  **Tag:** `u-code-block`
8
8
 
9
- Syntax-highlighted code block powered by Highlight.js. Shows a language label, clipboard copy button, and loading spinner. Automatically rendered inside `u-marked-block` for fenced code blocks.
9
+ Syntax-highlighted code block powered by Highlight.js. Shows a language label and a clipboard copy button (from `@iyulab/components`). Automatically rendered inside `u-marked-block` for fenced code blocks.
10
10
 
11
11
  ```html
12
12
  <!-- Direct usage -->
@@ -15,9 +15,6 @@ Syntax-highlighted code block powered by Highlight.js. Shows a language label, c
15
15
  <!-- Without header -->
16
16
  <u-code-block lang="json" headless .value=${JSON.stringify({key: 'value'}, null, 2)}></u-code-block>
17
17
 
18
- <!-- Loading state (streaming) -->
19
- <u-code-block lang="python" loading .value=${"def hello():"}></u-code-block>
20
-
21
18
  <!-- Inject code via slot -->
22
19
  <u-code-block lang="javascript">
23
20
  console.log("Hello from slot");
@@ -32,7 +29,6 @@ Syntax-highlighted code block powered by Highlight.js. Shows a language label, c
32
29
  |----------|------|---------|---------|-------------|
33
30
  | `lang` | `string` | `'plaintext'` | ✓ | Code language. Falls back to `plaintext` if not supported by Highlight.js |
34
31
  | `value` | `string` | `undefined` | — | Code content. Can also be set via slot `textContent` |
35
- | `loading` | `boolean` | `false` | ✓ | Loading state. Replaces the code icon with a spinner in the header |
36
32
  | `headless` | `boolean` | `false` | ✓ | Hides the header (language label + copy button) |
37
33
 
38
34
  ## Slots
@@ -0,0 +1,57 @@
1
+ # u-element-block
2
+
3
+ ```ts
4
+ import '@iyulab/chat-components/dist/components/blocks/UElementBlock.js';
5
+ ```
6
+
7
+ **Tag:** `u-element-block`
8
+
9
+ Dynamic custom element renderer. Creates the element specified by `tag`, binds `properties` to it, and shows a skeleton placeholder while `loading`. Used internally by `u-marked-block` to render `block-json` code fences (see [../extra-system.md](../extra-system.md)) — you generally don't create it directly.
10
+
11
+ Extends `UDataElement`, so `tag`/`properties` can also be injected via a `<script type="application/json">` slot.
12
+
13
+ ```html
14
+ <!-- Render u-chart-block dynamically -->
15
+ <u-element-block
16
+ tag="u-chart-block"
17
+ .properties=${{
18
+ type: 'bar',
19
+ data: { labels: ['A', 'B'], datasets: [{ data: [10, 20] }] }
20
+ }}
21
+ ></u-element-block>
22
+
23
+ <!-- Loading state (skeleton placeholder) -->
24
+ <u-element-block tag="u-chart-block" loading></u-element-block>
25
+ ```
26
+
27
+ How `u-marked-block` processes a `block-json` fence:
28
+
29
+ ````
30
+ ```block-json
31
+ {
32
+ "tag": "u-images-block",
33
+ "properties": { "items": [{ "src": "https://..." }] }
34
+ }
35
+ ```
36
+ ````
37
+
38
+ This is converted to `<u-element-block tag="u-images-block" ...>` via `UElementBlock.buildHTML()`.
39
+
40
+ ---
41
+
42
+ ## Properties
43
+
44
+ | Property | Type | Default | Reflect | Description |
45
+ |----------|------|---------|---------|-------------|
46
+ | `tag` | `string` | `undefined` | — | Custom element tag to render. Must already be registered |
47
+ | `properties` | `Record<string, unknown>` | `undefined` | — | Properties to bind to the rendered element |
48
+ | `loading` | `boolean` | `false` | ✓ | Shows a skeleton placeholder instead of the element |
49
+ | `blacklist` | `string[]` | `['innerHTML', 'outerHTML', 'textContent', 'innerText', 'outerText', 'srcdoc']` | — | Property names blocked from binding for XSS prevention |
50
+
51
+ ## Error Handling
52
+
53
+ If `tag` is missing, unregistered, or `properties` fails validation/assignment, `u-element-block` does **not** show an error card — it renders nothing and logs to the console (`[u-element-block] ...`). While `loading` is `true`, JSON parse failures from the underlying `UDataElement` are silently ignored too, since incomplete streamed JSON is expected mid-stream.
54
+
55
+ ## Security
56
+
57
+ The following property names are blocked by default to prevent XSS: `innerHTML`, `outerHTML`, `textContent`, `innerText`, `outerText`, `srcdoc`. Extend `blacklist` to add more restrictions.
@@ -6,22 +6,16 @@ import '@iyulab/chat-components/dist/components/blocks/UFileBlock.js';
6
6
 
7
7
  **Tag:** `u-file-block`
8
8
 
9
- Displays a single file as a card. Shows a type-appropriate icon, upload status, download link, and an optional remove button.
9
+ Displays a single file as a card. Shows a type-appropriate icon (or an actual thumbnail for image/video files with a `url`), and an optional remove button. There is no download affordance — wire up your own using the `url` property if needed.
10
+
11
+ Clicking anywhere on the card opens a full-size preview overlay, but only for image/video files that have a `url` set; other file types are not clickable.
10
12
 
11
13
  ```html
12
- <!-- Image file -->
13
- <u-file-block name="photo.png" type="image/png" size=${102400}></u-file-block>
14
+ <!-- Generic file (icon by MIME type) -->
15
+ <u-file-block name="report.xlsx" type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" size=${512000}></u-file-block>
14
16
 
15
- <!-- Uploading state -->
16
- <u-file-block name="document.pdf" type="application/pdf" status="uploading"></u-file-block>
17
-
18
- <!-- With download link -->
19
- <u-file-block
20
- name="report.xlsx"
21
- type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
22
- size=${512000}
23
- url="https://example.com/report.xlsx"
24
- ></u-file-block>
17
+ <!-- Image file — renders a thumbnail, click opens full-size preview -->
18
+ <u-file-block name="photo.png" type="image/png" size=${102400} url="https://example.com/photo.png"></u-file-block>
25
19
 
26
20
  <!-- Removable (e.g. prompt attachment) -->
27
21
  <u-file-block
@@ -39,26 +33,29 @@ Displays a single file as a card. Shows a type-appropriate icon, upload status,
39
33
  | Property | Type | Default | Reflect | Description |
40
34
  |----------|------|---------|---------|-------------|
41
35
  | `removable` | `boolean` | `false` | ✓ | Shows the remove button |
42
- | `status` | `'idle'\|'uploading'\|'error'` | `undefined` | ✓ | File state. `uploading` shows spinner; `error` shows error icon |
43
36
  | `name` | `string` | `undefined` | — | File name |
44
- | `type` | `string` | `undefined` | — | MIME type (determines icon) |
45
- | `size` | `number` | `undefined` | — | File size in bytes; auto-formatted to KB/MB |
46
- | `url` | `string` | `undefined` | — | Download URL. Shows download button when set |
37
+ | `type` | `string` | `undefined` | — | MIME type (determines icon / thumbnail) |
38
+ | `size` | `number` | `undefined` | — | File size in bytes; auto-formatted to KB/MB/GB |
39
+ | `url` | `string` | `undefined` | — | File URL, used for the image/video thumbnail and preview overlay |
47
40
 
48
41
  ## Events
49
42
 
50
43
  | Event | Detail | Description |
51
- |-------|--------|-------------|
44
+ |-------|--------|--------------|
52
45
  | `remove` | `RemoveEventDetail` | Fired when the remove button is clicked. If not cancelled, the element removes itself from the DOM |
53
46
 
54
47
  ## Icon Resolution by MIME Type
55
48
 
49
+ Only used when `type` doesn't start with `image/` or `video/` (or `url` is unset) — otherwise an actual `<img>`/`<video>` thumbnail is rendered instead.
50
+
56
51
  | MIME | Icon |
57
52
  |------|------|
58
- | `image/*` | `file-earmark-image` |
59
- | `video/*` | `file-earmark-play` |
60
- | `audio/*` | `file-earmark-music` |
61
- | `application/pdf` | `file-earmark-pdf` |
62
- | `application/zip` | `file-earmark-zip` |
63
- | `text/*` | `file-earmark-text` |
64
- | other | `file-earmark` |
53
+ | `image/*` | photo |
54
+ | `video/*` | video |
55
+ | `audio/*` | file-music |
56
+ | `application/pdf` | file-type-pdf |
57
+ | code types (`application/json`, `text/html`, `text/x-*`, etc.) | file-code |
58
+ | spreadsheet types (`.xls`, `.xlsx`, `text/csv`) | file-spreadsheet |
59
+ | archive types (`.zip`, `.tar`, `.rar`, `.gz`, `.7z`) | file-zip |
60
+ | `text/*` | file-text |
61
+ | other | file |
@@ -1,32 +1,32 @@
1
- # u-images-view
1
+ # u-images-block
2
2
 
3
3
  ```ts
4
- import '@iyulab/chat-components/dist/components/views/UImagesView.js';
4
+ import '@iyulab/chat-components/dist/components-extra/UImagesBlock.js';
5
5
  ```
6
6
 
7
- **Tag:** `u-images-view`
7
+ **Tag:** `u-images-block` — one of the 4 built-in **extra** blocks. Not part of the core entrypoint; import it (or the whole `/extra` subpath) explicitly. See [../extra-system.md](../extra-system.md).
8
8
 
9
- Image gallery view. Uses `u-carousel` for a horizontal slide layout, with a click-to-open lightbox. Shows up to 3 slides at once. Keyboard arrow keys navigate the lightbox.
9
+ Image gallery. Uses `u-carousel` for a horizontal slide layout, with a click-to-open lightbox. Shows up to 3 slides at once. Keyboard arrow keys navigate the lightbox.
10
10
 
11
- Automatically rendered by `u-marked-block` from a `view-json` code block.
11
+ Automatically rendered by `u-marked-block` from a `block-json` code fence via `u-element-block`.
12
12
 
13
13
  ```html
14
14
  <!-- Direct usage -->
15
- <u-images-view
15
+ <u-images-block
16
16
  .items=${[
17
17
  { src: 'https://example.com/photo1.jpg', alt: 'First photo', caption: 'Seoul at night' },
18
18
  { src: 'https://example.com/photo2.jpg', caption: 'Busan beach' },
19
19
  { src: 'https://example.com/photo3.jpg' }
20
20
  ]}
21
- ></u-images-view>
21
+ ></u-images-block>
22
22
  ```
23
23
 
24
- LLM output example (`view-json` code block):
24
+ LLM output example (`block-json` code fence):
25
25
 
26
26
  ````
27
- ```view-json
27
+ ```block-json
28
28
  {
29
- "tag": "u-images-view",
29
+ "tag": "u-images-block",
30
30
  "properties": {
31
31
  "items": [
32
32
  { "src": "https://example.com/photo.jpg", "alt": "Description", "caption": "Caption" }
@@ -1,33 +1,33 @@
1
- # u-map-view
1
+ # u-map-block
2
2
 
3
3
  ```ts
4
- import '@iyulab/chat-components/dist/components/views/UMapView.js';
4
+ import '@iyulab/chat-components/dist/components-extra/UMapBlock.js';
5
5
  ```
6
6
 
7
- **Tag:** `u-map-view`
7
+ **Tag:** `u-map-block` — one of the 4 built-in **extra** blocks. Not part of the core entrypoint; import it (or the whole `/extra` subpath) explicitly. See [../extra-system.md](../extra-system.md).
8
8
 
9
9
  Embeds an OpenStreetMap iframe centered on a given coordinate. A marker is placed at the specified `lat`/`lng` position.
10
10
 
11
11
  ```html
12
12
  <!-- Basic map -->
13
- <u-map-view lat="37.5665" lng="126.9780"></u-map-view>
13
+ <u-map-block lat="37.5665" lng="126.9780"></u-map-block>
14
14
 
15
15
  <!-- With label, description, and zoom -->
16
- <u-map-view
16
+ <u-map-block
17
17
  lat="37.5665"
18
18
  lng="126.9780"
19
19
  zoom="13"
20
20
  label="Seoul City Hall"
21
21
  description="110 Sejong-daero, Jung-gu, Seoul"
22
- ></u-map-view>
22
+ ></u-map-block>
23
23
  ```
24
24
 
25
- LLM output example (`view-json` code block):
25
+ LLM output example (`block-json` code fence, rendered via `u-element-block`):
26
26
 
27
27
  ````
28
- ```view-json
28
+ ```block-json
29
29
  {
30
- "tag": "u-map-view",
30
+ "tag": "u-map-block",
31
31
  "properties": {
32
32
  "lat": 37.5665,
33
33
  "lng": 126.9780,
@@ -6,13 +6,14 @@ import '@iyulab/chat-components/dist/components/blocks/UMarkedBlock.js';
6
6
 
7
7
  **Tag:** `u-marked-block`
8
8
 
9
- Renders markdown text to HTML. Supports KaTeX math equations, code syntax highlighting, inline citation tag injection, and special handling for `view-json` and `intent-json` code blocks. Applying an 80ms debounce makes it suitable for LLM streaming.
9
+ Renders markdown text to HTML. Supports KaTeX math equations, code syntax highlighting, inline citation tag injection, and special handling for `block-json` code fences (the [extra system](../extra-system.md)). Applying an 80ms debounce makes it suitable for LLM streaming.
10
10
 
11
- **Special code fences:**
12
- - `` ```view-json `` → automatically rendered as a `u-view` component
13
- - `` ```intent-json `` → stripped from output (must be parsed separately via `IntentPromptBuilder`)
11
+ **Special code fence:**
12
+ - `` ```block-json `` → automatically rendered via [`u-element-block`](./element-block.md)
14
13
  - All other HTML inside markdown is escaped to prevent XSS
15
14
 
15
+ Tracks a `streaming` state internally (resets a 1500ms idle timer on every `value` update). A `block-json` extra's `loading` stays `true` until both its own fence is closed and the message has been idle for 1500ms.
16
+
16
17
  ```html
17
18
  <!-- Basic markdown -->
18
19
  <u-marked-block value="# Hello\n\nThis is **bold** and `code`."></u-marked-block>
@@ -29,8 +29,7 @@ Chat message wrapper component. Arranges content blocks via slots, shows a loadi
29
29
  <div slot="header">AI Assistant</div>
30
30
  <u-marked-block .value=${content}></u-marked-block>
31
31
  <div slot="footer">
32
- <u-copy-button .value=${content}></u-copy-button>
33
- <u-vote-button></u-vote-button>
32
+ <!-- Add your own action buttons here (e.g. @iyulab/components's copy-button) -->
34
33
  </div>
35
34
  </u-message>
36
35
  ```
@@ -15,11 +15,9 @@ Chat input component. Combines a text input area, file attachment previews, and
15
15
  <!-- Loading (streaming) state -->
16
16
  <u-prompt loading></u-prompt>
17
17
 
18
- <!-- With file attach button -->
18
+ <!-- Custom actions via slots (there is no built-in attach button) -->
19
19
  <u-prompt>
20
- <u-attach-button slot="left-actions" multiple accept="image/*,application/pdf">
21
- Attach
22
- </u-attach-button>
20
+ <button slot="left-actions" @click=${openFilePicker}>Attach</button>
23
21
  </u-prompt>
24
22
  ```
25
23
 
@@ -37,20 +35,11 @@ prompt.addEventListener('stop', () => {
37
35
  console.log('stopped');
38
36
  });
39
37
 
40
- // Wire up file attach button
41
- prompt.addEventListener('attach', (e) => {
42
- const { files } = e.detail;
43
- prompt.files = [
44
- ...(prompt.files ?? []),
45
- ...files.map(f => ({
46
- type: 'file' as const,
47
- name: f.name,
48
- size: f.size,
49
- mimeType: f.type,
50
- status: 'idle' as const,
51
- }))
52
- ];
53
- });
38
+ // Attaching files (no built-in picker — wire up your own <input type="file">)
39
+ prompt.files = [
40
+ ...(prompt.files ?? []),
41
+ { type: 'file' as const, name: 'photo.png', size: 12345, mimeType: 'image/png' }
42
+ ];
54
43
 
55
44
  // Programmatic submit
56
45
  prompt.submit();
@@ -63,7 +52,7 @@ prompt.submit();
63
52
  | Name | Description |
64
53
  |------|-------------|
65
54
  | `header` | Area above the input |
66
- | `left-actions` | Left side of the control bar (e.g. attach button) |
55
+ | `left-actions` | Left side of the control bar (e.g. a custom attach button) |
67
56
  | `right-actions` | Right side of the control bar |
68
57
  | `footer` | Area below the input |
69
58
 
@@ -86,10 +75,12 @@ prompt.submit();
86
75
 
87
76
  ## Events
88
77
 
78
+ Both `send` and `stop` are dispatched with `bubbles: false, composed: false` — listen directly on the `u-prompt` element, they won't bubble past it.
79
+
89
80
  | Event | Detail | Description |
90
81
  |-------|--------|-------------|
91
- | `send` | `unknown` | Fired on Enter or send button click |
92
- | `stop` | `unknown` | Fired on send button click while loading |
82
+ | `send` | `SendEventDetail` (`{ value, files? }`) | Fired on Enter or send button click (only when there's a value or files) |
83
+ | `stop` | `StopEventDetail` (`{}`) | Fired on send button click while loading |
93
84
  | `remove` | `RemoveEventDetail` | Fired when an attached file's remove button is clicked |
94
85
 
95
86
  ## CSS Parts
@@ -1,34 +1,34 @@
1
- # u-video-view
1
+ # u-video-block
2
2
 
3
3
  ```ts
4
- import '@iyulab/chat-components/dist/components/views/UVideoView.js';
4
+ import '@iyulab/chat-components/dist/components-extra/UVideoBlock.js';
5
5
  ```
6
6
 
7
- **Tag:** `u-video-view`
7
+ **Tag:** `u-video-block` — one of the 4 built-in **extra** blocks. Not part of the core entrypoint; import it (or the whole `/extra` subpath) explicitly. See [../extra-system.md](../extra-system.md).
8
8
 
9
9
  Embeds a video from YouTube, Vimeo, or a direct file URL. Automatically detects the platform from the URL and selects the appropriate player.
10
10
 
11
11
  ```html
12
12
  <!-- YouTube -->
13
- <u-video-view src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"></u-video-view>
13
+ <u-video-block src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"></u-video-block>
14
14
 
15
15
  <!-- Vimeo -->
16
- <u-video-view src="https://vimeo.com/123456789"></u-video-view>
16
+ <u-video-block src="https://vimeo.com/123456789"></u-video-block>
17
17
 
18
18
  <!-- Direct video file -->
19
- <u-video-view
19
+ <u-video-block
20
20
  src="https://example.com/video.mp4"
21
21
  poster="https://example.com/thumbnail.jpg"
22
22
  ratio="4:3"
23
- ></u-video-view>
23
+ ></u-video-block>
24
24
  ```
25
25
 
26
- LLM output example (`view-json` code block):
26
+ LLM output example (`block-json` code fence, rendered via `u-element-block`):
27
27
 
28
28
  ````
29
- ```view-json
29
+ ```block-json
30
30
  {
31
- "tag": "u-video-view",
31
+ "tag": "u-video-block",
32
32
  "properties": {
33
33
  "src": "https://www.youtube.com/watch?v=VIDEO_ID"
34
34
  }
@@ -0,0 +1,95 @@
1
+ # Extra System
2
+
3
+ Extras let the LLM render rich media content — charts, maps, image galleries, videos — directly inside a chat message by outputting a `block-json` fenced code block. **Extras are rendered automatically** by `u-marked-block`; no manual parsing is required.
4
+
5
+ ## How It Works
6
+
7
+ 1. **Register** extra schemas with `ElementPromptBuilder` (or just import the built-in `prompt`)
8
+ 2. **Inject** the resulting instruction string into your LLM system prompt
9
+ 3. **Automatic rendering**: `u-marked-block` detects `block-json` fences and passes them to [`u-element-block`](./components/element-block.md), which creates the appropriate custom element with the specified properties
10
+
11
+ ````
12
+ ```block-json
13
+ {
14
+ "tag": "u-chart-block",
15
+ "properties": {
16
+ "type": "bar",
17
+ "data": { "labels": ["Jan", "Feb", "Mar"], "datasets": [{ "label": "Revenue ($k)", "data": [120, 98, 145] }] }
18
+ }
19
+ }
20
+ ```
21
+ ````
22
+
23
+ ## Setup
24
+
25
+ The 4 built-in extras (chart/images/map/video) are not part of the core package — import `@iyulab/chat-components/extra` to register all of them at once and get a ready-built prompt fragment:
26
+
27
+ ```ts
28
+ import '@iyulab/chat-components';
29
+ import { prompt } from '@iyulab/chat-components/extra';
30
+
31
+ const systemPrompt = `You are a helpful assistant.\n\n${prompt}`;
32
+ ```
33
+
34
+ `prompt` is built once at import time from the 4 built-in schemas. Registering additional custom extras via `ElementPromptBuilder.instance.add(...)`? Call `ElementPromptBuilder.instance.build()` again to get a fragment that includes both the built-ins and your custom extras.
35
+
36
+ Need only one or two of the built-ins (e.g. to skip bundling `chart.js`)? Import the specific component directly instead of the bulk `/extra` entry:
37
+
38
+ ```ts
39
+ import '@iyulab/chat-components/dist/components-extra/UImagesBlock.js';
40
+ ```
41
+
42
+ ## Built-in Extras
43
+
44
+ | Tag | Doc |
45
+ |-----|-----|
46
+ | `u-images-block` | [components/images-block.md](./components/images-block.md) |
47
+ | `u-video-block` | [components/video-block.md](./components/video-block.md) |
48
+ | `u-chart-block` | [components/chart-block.md](./components/chart-block.md) |
49
+ | `u-map-block` | [components/map-block.md](./components/map-block.md) |
50
+
51
+ ## Registering Custom Extras
52
+
53
+ ```ts
54
+ import { ElementPromptBuilder } from '@iyulab/chat-components';
55
+ import type { ElementSchema } from '@iyulab/chat-components';
56
+
57
+ class MyTimelineBlock extends HTMLElement { /* ... */ }
58
+ customElements.define('my-timeline-block', MyTimelineBlock);
59
+
60
+ const def: ElementSchema = {
61
+ tag: 'my-timeline-block',
62
+ description: 'Display a sequence of events on a timeline',
63
+ properties: {
64
+ events: {
65
+ type: 'array',
66
+ items: { type: 'object', properties: {
67
+ date: { type: 'string', description: 'ISO date string' },
68
+ title: { type: 'string', description: 'Event title' },
69
+ }, required: ['date', 'title'] },
70
+ description: 'Array of timeline events',
71
+ }
72
+ },
73
+ required: ['events'],
74
+ };
75
+
76
+ ElementPromptBuilder.instance.add(def);
77
+ ```
78
+
79
+ The element just needs to accept standard property assignments — `u-element-block` binds `properties` keys directly to element properties.
80
+
81
+ ## Error Handling
82
+
83
+ If the LLM outputs a `tag` that isn't registered (e.g. missing `@iyulab/chat-components/extra` import, or a custom extra's element isn't defined yet), `u-element-block` does **not** show an error card — it renders nothing and logs to the console instead. Genuine data errors (invalid `properties`, assignment failures) are also console-only.
84
+
85
+ ## Security
86
+
87
+ `u-element-block` maintains a `blacklist` of dangerous property names that are never bound: `innerHTML`, `outerHTML`, `textContent`, `innerText`, `outerText`, `srcdoc`. Custom elements registered as extras should only accept well-typed, data-only properties.
88
+
89
+ ## `ElementPromptBuilder` API
90
+
91
+ | Method | Description |
92
+ |--------|-------------|
93
+ | `ElementPromptBuilder.instance` | Singleton accessor |
94
+ | `.add(definition: ElementSchema)` | Register a custom extra (throws on tag conflict) |
95
+ | `.build(): string` | Generate system prompt instruction string |