@iyulab/chat-components 0.12.3 → 0.14.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 (73) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/README.md +1 -0
  3. package/dist/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.151.0}/helpers/esm/decorate.js +1 -1
  4. package/dist/_virtual/{_@oxc-project_runtime@0.150.0 → _@oxc-project_runtime@0.151.0}/helpers/esm/decorateMetadata.js +1 -1
  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/external-link.svg.a9f7f02d.js +4 -0
  10. package/dist/_virtual/_glob-assets_raw/file-code.svg.0e706f93.js +4 -0
  11. package/dist/_virtual/_glob-assets_raw/file-music.svg.b9970203.js +4 -0
  12. package/dist/_virtual/_glob-assets_raw/file-spreadsheet.svg.8c03bdfa.js +4 -0
  13. package/dist/_virtual/_glob-assets_raw/file-text.svg.85bdd923.js +4 -0
  14. package/dist/_virtual/_glob-assets_raw/file-type-pdf.svg.bc12db6d.js +4 -0
  15. package/dist/_virtual/_glob-assets_raw/file-zip.svg.76dde660.js +4 -0
  16. package/dist/_virtual/_glob-assets_raw/file.svg.28f5d6f1.js +4 -0
  17. package/dist/_virtual/_glob-assets_raw/photo.svg.cc273cc1.js +4 -0
  18. package/dist/_virtual/_glob-assets_raw/player-stop-fill.svg.5378b752.js +4 -0
  19. package/dist/_virtual/_glob-assets_raw/send.svg.02326253.js +4 -0
  20. package/dist/_virtual/_glob-assets_raw/sort-ascending-letters.svg.14a3df67.js +4 -0
  21. package/dist/_virtual/_glob-assets_raw/sort-descending-letters.svg.3e03647c.js +4 -0
  22. package/dist/_virtual/_glob-assets_raw/video.svg.c183f03c.js +4 -0
  23. package/dist/_virtual/_glob-assets_raw/world.svg.cd9903c8.js +4 -0
  24. package/dist/components/UDataElement.d.ts +2 -0
  25. package/dist/components/UDataElement.js +9 -1
  26. package/dist/components/blocks/UCodeBlock.js +3 -2
  27. package/dist/components/blocks/UElementBlock.d.ts +12 -16
  28. package/dist/components/blocks/UElementBlock.js +25 -33
  29. package/dist/components/blocks/UFileBlock.d.ts +3 -2
  30. package/dist/components/blocks/UFileBlock.js +12 -10
  31. package/dist/components/blocks/UFileBlock.styles.js +1 -1
  32. package/dist/components/blocks/UMarkedBlock.d.ts +8 -1
  33. package/dist/components/blocks/UMarkedBlock.js +25 -7
  34. package/dist/components/blocks/UMarkedBlock.styles.js +10 -0
  35. package/dist/components/blocks/URefBlock.js +2 -2
  36. package/dist/components/blocks/UTableBlock.js +3 -2
  37. package/dist/components/blocks/UTextBlock.js +2 -2
  38. package/dist/components/message/UMessage.js +2 -2
  39. package/dist/components/prompt/UPrompt.js +5 -3
  40. package/dist/components/references/URefCard.d.ts +21 -2
  41. package/dist/components/references/URefCard.js +33 -19
  42. package/dist/components/references/URefCardGroup.js +2 -2
  43. package/dist/components/references/URefTag.js +5 -3
  44. package/dist/components-extra/UChartBlock.js +6 -2
  45. package/dist/components-extra/UImagesBlock.d.ts +6 -1
  46. package/dist/components-extra/UImagesBlock.js +30 -7
  47. package/dist/components-extra/UImagesBlock.styles.js +20 -1
  48. package/dist/components-extra/UMapBlock.js +5 -2
  49. package/dist/components-extra/UVideoBlock.js +5 -2
  50. package/dist/extra.d.ts +7 -1
  51. package/dist/extra.js +12 -6
  52. package/dist/index.d.ts +2 -0
  53. package/dist/index.js +6 -3
  54. package/dist/node_modules/katex/dist/katex.js +2 -2
  55. package/dist/utilities/ElementRegistry.d.ts +13 -0
  56. package/dist/utilities/ElementRegistry.js +33 -0
  57. package/dist/utilities/PromptBuilder.d.ts +3 -0
  58. package/dist/utilities/PromptBuilder.js +5 -0
  59. package/dist/utilities/icons.js +52 -0
  60. package/dist/utilities/imageSources.d.ts +25 -0
  61. package/dist/utilities/imageSources.js +61 -0
  62. package/dist/utilities/messages.d.ts +1 -1
  63. package/dist/utilities/messages.js +6 -2
  64. package/dist/utilities/sanitizers.d.ts +10 -1
  65. package/dist/utilities/sanitizers.js +16 -5
  66. package/package.json +4 -2
  67. package/skills/iyulab-chat-components/SKILL.md +1 -0
  68. package/skills/iyulab-chat-components/references/components/element-block.md +5 -6
  69. package/skills/iyulab-chat-components/references/components/images-block.md +1 -0
  70. package/skills/iyulab-chat-components/references/components/marked-block.md +12 -0
  71. package/skills/iyulab-chat-components/references/components/ref-card.md +20 -1
  72. package/skills/iyulab-chat-components/references/extra-system.md +4 -4
  73. package/skills/iyulab-chat-components/references/security.md +23 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,91 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.14.0] - 2026-09-30
4
+
5
+ ### Security
6
+
7
+ - 🔴 **Breaking — `block-json` renders only registered blocks and assigns only their schema's
8
+ properties.** `u-element-block` used to create any element defined on the page and assign every
9
+ property except six names (`innerHTML`, `outerHTML`, …). `block-json` is model output, so a
10
+ prompt-injected document could create an element that renders a property as HTML (for example
11
+ `u-table-block`'s cell text) and run script. Now a tag must be registered as a block, and only the
12
+ names in that block's schema `properties` are assigned; other keys (including `style`) are dropped
13
+ and logged to the console.
14
+ - The four built-in extras register themselves when their module is imported, and
15
+ `ElementPromptBuilder.add()` registers the schema it is given — extras set up as documented keep
16
+ working.
17
+ - New `registerElementBlock(schema)` for blocks you describe in your own prompt, and
18
+ `getElementBlockProperties(tag)`.
19
+ - The `blacklist` property of `u-element-block` is removed.
20
+ - **New `setAllowedImagePrefixes(prefixes)` — an origin policy for images in model output.** Markdown
21
+ images in `u-marked-block` (table cells included) and the items of `u-images-block` load the URL the
22
+ model wrote as soon as they render, so a prompt-injected response can send data to a third party in
23
+ an image URL's query string. With a list set, only images whose resolved absolute URL starts with one
24
+ of the prefixes are requested; any other image is drawn as its alt text (`Image blocked: …`,
25
+ localized) and no request is made. The default (`undefined`) keeps loading every image; `[]` blocks
26
+ all, `['*']` allows all. `getAllowedImagePrefixes()` and `resolveImageSource(src)` are exported too.
27
+ - `data:image/…` URLs make no request and are shown under any policy — markdown images with such a
28
+ URL used to be replaced by `#`.
29
+ - A markdown image with a blocked protocol (`javascript:` and the like) is drawn as its alt text
30
+ instead of `<img src="#">`, which requested the page itself as an image.
31
+ - `u-images-block` now applies the same protocol check to `src` as markdown images do.
32
+ - New `docs/security.md` (and a skill reference) — what each input is trusted to contain, the requests
33
+ the components make, and what is left to the application.
34
+ - New `sanitizeHref(url)` — the protocol check without HTML escaping, for property bindings.
35
+ - Migration: a custom element that `block-json` should render needs its schema registered with
36
+ `ElementPromptBuilder.add()` or `registerElementBlock()`, and every property the model may set
37
+ must be listed in that schema's `properties`.
38
+
39
+ ### Fixed
40
+
41
+ - **`u-ref-card` checks the protocol of its `url`, like `u-ref-tag` already did.** A citation source URL
42
+ such as `javascript:…` became `#` in the inline citation but stayed as written in the card inside its
43
+ tooltip. Both now use the same check.
44
+ - **`u-prompt` no longer sends on the Enter that finishes an IME composition.** Typing Korean (or
45
+ another composed language) and pressing Enter sent the message and then left the last syllable in
46
+ the box, so it was sent again. Requires `@iyulab/components` 1.51.0 or later.
47
+ - **Icons of `u-prompt`, `u-table-block`, `u-code-block` and the other components that use the
48
+ bundled `internal-chat` set are drawn again.** The module that registers that set had no exports
49
+ and was not declared in `sideEffects`, so the package build dropped it and those icons rendered at
50
+ 0×0 (0.11.1 – 0.13.0).
51
+ - **A table whose cell carries a citation keeps its rows.** The citation markup was inserted into the
52
+ table's JSON payload after it had been serialized, which broke the JSON, and the table rendered
53
+ empty. Citations inside `block-json` payloads are removed for the same reason.
54
+ - **`u-marked-block` keeps updating after it is detached and re-attached while a render or the
55
+ streaming indicator is pending.** It used to stop updating for good, showing an intermediate
56
+ frame, or leave a `block-json` block on its loading skeleton.
57
+ - Blocks that read their data from a `<script type="application/json">` child no longer log a
58
+ "Missing script" error when they are moved in the DOM after loading.
59
+ - `@iyulab/chat-components/extra` registers the built-in extras on `ElementPromptBuilder.instance`,
60
+ as documented. Adding your own extras there and calling `build()` again now returns the built-ins
61
+ too; it used to return only yours.
62
+
63
+ ## [0.13.0] - 2026-09-28
64
+
65
+ ### Fixed
66
+
67
+ - **Escape in a file preview or an image lightbox opened inside a dialog closes only the viewer.**
68
+ Both listened for Escape on the document themselves, so one press closed the viewer and the
69
+ dialog under it. They now join `@iyulab/components`' layer stack, where one Escape closes the
70
+ most recently opened layer. Arrow keys still page the lightbox. Requires `@iyulab/components`
71
+ 1.49.0 or later.
72
+
73
+ ### Changed
74
+
75
+ - 🔴 **Breaking — `u-ref-card` no longer requests a favicon unless you choose where from.** A web
76
+ card used to load `https://www.google.com/s2/favicons?domain=<host>` for every card, with no way to
77
+ point it elsewhere or turn it off — each card sent the site's host name to a third party, and on a
78
+ closed network every card made a request that failed. Cards now show no favicon by default. Set
79
+ `URefCard.defaultFaviconUrl` (every card, including those inside `u-ref-block` and
80
+ `u-ref-card-group`) or a card's `faviconUrl` property to a `(url) => string | undefined` resolver.
81
+ A card without a `url` no longer falls back to the app's own `/favicon.ico`.
82
+ Migration, to keep the previous look: `URefCard.defaultFaviconUrl = googleFaviconUrl;` (both
83
+ exported from `@iyulab/chat-components`).
84
+
85
+ - The file preview and the image lightbox read `--u-layer-overlay` (9999, as before) — the shared
86
+ stacking token from `@iyulab/components` — instead of their own number, so they stack in the
87
+ same order as dialogs and drawers.
88
+
3
89
  ## [0.12.3] - 2026-09-21
4
90
 
5
91
  ### Documentation
package/README.md CHANGED
@@ -137,6 +137,7 @@ package's Accessibility section.
137
137
  | [docs/block-system.md](./docs/block-system.md) | Block components and `BlockItem` types in depth |
138
138
  | [docs/extras-system.md](./docs/extras-system.md) | Extras system setup and custom extras |
139
139
  | [docs/events.md](./docs/events.md) | Full event reference |
140
+ | [docs/security.md](./docs/security.md) | What each input is trusted to contain, requests the components make, and your application's part |
140
141
 
141
142
  ---
142
143
 
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorate.js
1
+ //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorate.js
2
2
  function __decorate(decorators, target, key, desc) {
3
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -1,4 +1,4 @@
1
- //#region \0@oxc-project+runtime@0.150.0/helpers/esm/decorateMetadata.js
1
+ //#region \0@oxc-project+runtime@0.151.0/helpers/esm/decorateMetadata.js
2
2
  function __decorateMetadata(k, v) {
3
3
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
4
4
  }
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/alert-triangle-fill.svg.4cfc4305
2
+ var alert_triangle_fill_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M12 1.67c.955 0 1.845 .467 2.39 1.247l.105 .16l8.114 13.548a2.914 2.914 0 0 1 -2.307 4.363l-.195 .008h-16.225a2.914 2.914 0 0 1 -2.582 -4.2l.099 -.185l8.11 -13.538a2.914 2.914 0 0 1 2.491 -1.403zm.01 13.33l-.127 .007a1 1 0 0 0 0 1.986l.117 .007l.127 -.007a1 1 0 0 0 0 -1.986l-.117 -.007zm-.01 -7a1 1 0 0 0 -.993 .883l-.007 .117v4l.007 .117a1 1 0 0 0 1.986 0l.007 -.117v-4l-.007 -.117a1 1 0 0 0 -.993 -.883z\" />\n</svg>\n";
3
+ //#endregion
4
+ export { alert_triangle_fill_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/arrows-sort.svg.dda43a85
2
+ var arrows_sort_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M3 9l4 -4l4 4m-4 -4v14\" />\n <path d=\"M21 15l-4 4l-4 -4m4 4v-14\" />\n</svg>\n";
3
+ //#endregion
4
+ export { arrows_sort_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/code.svg.c69bc144
2
+ var code_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M7 8l-4 4l4 4\" />\n <path d=\"M17 8l4 4l-4 4\" />\n <path d=\"M14 4l-4 16\" />\n</svg>\n";
3
+ //#endregion
4
+ export { code_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/download.svg.bce82177
2
+ var download_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M4 17v2a2 2 0 0 0 2 2h12a2 2 0 0 0 2 -2v-2\" />\n <path d=\"M7 11l5 5l5 -5\" />\n <path d=\"M12 4l0 12\" />\n</svg>\n";
3
+ //#endregion
4
+ export { download_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/external-link.svg.a9f7f02d
2
+ var external_link_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M12 6h-6a2 2 0 0 0 -2 2v10a2 2 0 0 0 2 2h10a2 2 0 0 0 2 -2v-6\" />\n <path d=\"M11 13l9 -9\" />\n <path d=\"M15 4h5v5\" />\n</svg>\n";
3
+ //#endregion
4
+ export { external_link_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-code.svg.0e706f93
2
+ var file_code_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2\" />\n <path d=\"M10 13l-1 2l1 2\" />\n <path d=\"M14 13l1 2l-1 2\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_code_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-music.svg.b9970203
2
+ var file_music_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2\" />\n <path d=\"M10 16a1 1 0 1 0 2 0a1 1 0 1 0 -2 0\" />\n <path d=\"M12 16l0 -5l2 1\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_music_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-spreadsheet.svg.8c03bdfa
2
+ var file_spreadsheet_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2\" />\n <path d=\"M8 11h8v7h-8l0 -7\" />\n <path d=\"M8 15h8\" />\n <path d=\"M11 11v7\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_spreadsheet_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-text.svg.85bdd923
2
+ var file_text_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2\" />\n <path d=\"M9 9l1 0\" />\n <path d=\"M9 13l6 0\" />\n <path d=\"M9 17l6 0\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_text_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-type-pdf.svg.bc12db6d
2
+ var file_type_pdf_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M5 12v-7a2 2 0 0 1 2 -2h7l5 5v4\" />\n <path d=\"M5 18h1.5a1.5 1.5 0 0 0 0 -3h-1.5v6\" />\n <path d=\"M17 18h2\" />\n <path d=\"M20 15h-3v6\" />\n <path d=\"M11 15v6h1a2 2 0 0 0 2 -2v-2a2 2 0 0 0 -2 -2h-1\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_type_pdf_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file-zip.svg.76dde660
2
+ var file_zip_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M6 20.735a2 2 0 0 1 -1 -1.735v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2h-1\" />\n <path d=\"M11 17a2 2 0 0 1 2 2v2a1 1 0 0 1 -1 1h-2a1 1 0 0 1 -1 -1v-2a2 2 0 0 1 2 -2\" />\n <path d=\"M11 5l-1 0\" />\n <path d=\"M13 7l-1 0\" />\n <path d=\"M11 9l-1 0\" />\n <path d=\"M13 11l-1 0\" />\n <path d=\"M11 13l-1 0\" />\n <path d=\"M13 15l-1 0\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_zip_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/file.svg.28f5d6f1
2
+ var file_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M14 3v4a1 1 0 0 0 1 1h4\" />\n <path d=\"M17 21h-10a2 2 0 0 1 -2 -2v-14a2 2 0 0 1 2 -2h7l5 5v11a2 2 0 0 1 -2 2\" />\n</svg>\n";
3
+ //#endregion
4
+ export { file_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/photo.svg.cc273cc1
2
+ var photo_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M15 8h.01\" />\n <path d=\"M3 6a3 3 0 0 1 3 -3h12a3 3 0 0 1 3 3v12a3 3 0 0 1 -3 3h-12a3 3 0 0 1 -3 -3v-12\" />\n <path d=\"M3 16l5 -5c.928 -.893 2.072 -.893 3 0l5 5\" />\n <path d=\"M14 14l1 -1c.928 -.893 2.072 -.893 3 0l3 3\" />\n</svg>\n";
3
+ //#endregion
4
+ export { photo_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/player-stop-fill.svg.5378b752
2
+ var player_stop_fill_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"currentColor\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M17 4h-10a3 3 0 0 0 -3 3v10a3 3 0 0 0 3 3h10a3 3 0 0 0 3 -3v-10a3 3 0 0 0 -3 -3z\" />\n</svg>\n";
3
+ //#endregion
4
+ export { player_stop_fill_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/send.svg.02326253
2
+ var send_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M10 14l11 -11\" />\n <path d=\"M21 3l-6.5 18a.55 .55 0 0 1 -1 0l-3.5 -7l-7 -3.5a.55 .55 0 0 1 0 -1l18 -6.5\" />\n</svg>\n";
3
+ //#endregion
4
+ export { send_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/sort-ascending-letters.svg.14a3df67
2
+ var sort_ascending_letters_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M15 10v-5c0 -1.38 .62 -2 2 -2s2 .62 2 2v5m0 -3h-4\" />\n <path d=\"M19 21h-4l4 -7h-4\" />\n <path d=\"M4 15l3 3l3 -3\" />\n <path d=\"M7 6v12\" />\n</svg>\n";
3
+ //#endregion
4
+ export { sort_ascending_letters_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/sort-descending-letters.svg.3e03647c
2
+ var sort_descending_letters_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M15 21v-5c0 -1.38 .62 -2 2 -2s2 .62 2 2v5m0 -3h-4\" />\n <path d=\"M19 10h-4l4 -7h-4\" />\n <path d=\"M4 15l3 3l3 -3\" />\n <path d=\"M7 6v12\" />\n</svg>\n";
3
+ //#endregion
4
+ export { sort_descending_letters_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/video.svg.c183f03c
2
+ var video_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M15 10l4.553 -2.276a1 1 0 0 1 1.447 .894v6.764a1 1 0 0 1 -1.447 .894l-4.553 -2.276v-4\" />\n <path d=\"M3 8a2 2 0 0 1 2 -2h8a2 2 0 0 1 2 2v8a2 2 0 0 1 -2 2h-8a2 2 0 0 1 -2 -2l0 -8\" />\n</svg>\n";
3
+ //#endregion
4
+ export { video_svg_default as default };
@@ -0,0 +1,4 @@
1
+ //#region \0glob-assets_raw/world.svg.cd9903c8
2
+ var world_svg_default = "<svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n>\n <path stroke=\"none\" d=\"M0 0h24v24H0z\" fill=\"none\"/>\n <path d=\"M3 12a9 9 0 1 0 18 0a9 9 0 0 0 -18 0\" />\n <path d=\"M3.6 9h16.8\" />\n <path d=\"M3.6 15h16.8\" />\n <path d=\"M11.5 3a17 17 0 0 0 0 18\" />\n <path d=\"M12.5 3a17 17 0 0 1 0 18\" />\n</svg>\n";
3
+ //#endregion
4
+ export { world_svg_default as default };
@@ -18,6 +18,8 @@ import { UElement } from '@iyulab/components/dist/components/UElement.js';
18
18
  */
19
19
  export declare class UDataElement extends UElement {
20
20
  static styles: import('lit').CSSResultGroup;
21
+ /** 데이터를 한 번이라도 읽었는가 — 재연결 때 «스크립트 없음» 을 오류로 보지 않기 위해. */
22
+ private loaded;
21
23
  connectedCallback(): void;
22
24
  /**
23
25
  * 지정한 태그와 데이터로 커스텀 엘리먼트 HTML 문자열을 생성합니다.
@@ -19,6 +19,10 @@ import { UElement } from "@iyulab/components/dist/components/UElement.js";
19
19
  * (예: `URefCard` — URefBlock의 property 구동과 UMarkedBlock의 script 주입을 모두 지원)
20
20
  */
21
21
  var UDataElement = class extends UElement {
22
+ constructor(..._args) {
23
+ super(..._args);
24
+ this.loaded = false;
25
+ }
22
26
  static {
23
27
  this.styles = super.styles;
24
28
  }
@@ -55,12 +59,16 @@ var UDataElement = class extends UElement {
55
59
  try {
56
60
  if (!data) {
57
61
  const script = this.querySelector("script[type=\"application/json\"]");
58
- if (!script) throw new Error("Missing <script type=\"application/json\">");
62
+ if (!script) {
63
+ if (this.loaded) return;
64
+ throw new Error("Missing <script type=\"application/json\">");
65
+ }
59
66
  data = JSON.parse(script.textContent ?? "{}");
60
67
  script.remove();
61
68
  }
62
69
  if (typeof data !== "object" || data === null || Array.isArray(data)) throw new Error("Invalid JSON data: expected an object at the top level");
63
70
  Object.assign(this, data);
71
+ this.loaded = true;
64
72
  } catch (error) {
65
73
  await this.error(error);
66
74
  }
@@ -1,6 +1,7 @@
1
+ import "../../utilities/icons.js";
1
2
  import { styles } from "./UCodeBlock.styles.js";
2
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
3
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
3
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
4
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
4
5
  import { html } from "lit";
5
6
  import { customElement, property } from "lit/decorators.js";
6
7
  import { unsafeHTML } from "lit/directives/unsafe-html.js";
@@ -1,19 +1,22 @@
1
1
  import { nothing, PropertyValues } from 'lit';
2
2
  import { UDataElement } from '../UDataElement.js';
3
3
  /**
4
- * `block-json` 코드펜스에서 지정한 커스텀 엘리먼트를 동적으로 렌더링하는 컴포넌트입니다.
4
+ * `block-json` 코드펜스에서 지정한 블록을 동적으로 렌더링하는 컴포넌트입니다.
5
+ *
6
+ * 만들 수 있는 것은 **블록으로 등록된 태그뿐**이고(`registerElementBlock` ·
7
+ * `ElementPromptBuilder.add`), 대입하는 것은 **그 스키마의 `properties` 에 적힌 이름뿐**입니다.
8
+ * `tag`·`properties` 는 LLM 출력에서 오므로 신뢰할 수 없는 입력으로 다룹니다 — 스키마 밖의
9
+ * 이름은 대입하지 않고 콘솔에 기록합니다.
5
10
  * 대상 태그가 등록되어 있지 않거나 데이터가 유효하지 않은 경우, 에러 카드 없이 콘솔에만 기록하고 아무것도 렌더링하지 않습니다.
6
11
  */
7
12
  export declare class UElementBlock extends UDataElement {
8
13
  static styles: import('lit').CSSResultGroup[];
9
14
  /** 로딩 상태입니다. `true`인 경우, 위젯이 로딩 중임을 나타냅니다. */
10
15
  loading: boolean;
11
- /** `tag` 프로퍼티에 등록된 커스텀 엘리먼트를 렌더링하는 컴포넌트입니다. */
16
+ /** 렌더링할 블록의 태그입니다. 블록으로 등록된 태그만 렌더링됩니다. */
12
17
  tag?: string;
13
- /** `properties` 객체의 키가 렌더링된 엘리먼트의 프로퍼티 이름과 일치하면 자동으로 할당됩니다. */
18
+ /** 블록에 대입할 값입니다. 블록 스키마의 `properties` 에 적힌 이름만 대입됩니다. */
14
19
  properties?: Record<string, unknown>;
15
- /** `properties` 객체에서 위험한 프로퍼티 이름을 지정하여 차단할 수 있습니다. */
16
- blacklist: string[];
17
20
  /** 실제 렌더링된 엘리먼트입니다. `tag` 프로퍼티가 변경될 때마다 업데이트됩니다. */
18
21
  private element;
19
22
  protected willUpdate(changedProperties: PropertyValues): void;
@@ -24,24 +27,17 @@ export declare class UElementBlock extends UDataElement {
24
27
  */
25
28
  protected error(error: unknown): Promise<void>;
26
29
  /**
27
- * `tag` 프로퍼티에 등록된 커스텀 엘리먼트를 렌더링하는 컴포넌트입니다.
28
- * `tag`가 변경될 때마다 등록된 커스텀 엘리먼트를 새로 생성하여 렌더링합니다.
29
- * `tag`가 유효하지 않거나 등록된 커스텀 엘리먼트가 아닌 경우, 에러 처리합니다.
30
+ * `tag`가 변경될 때마다 블록 엘리먼트를 새로 생성합니다.
31
+ * 블록으로 등록되지 않은 태그나 아직 정의되지 않은 커스텀 엘리먼트는 만들지 않고 기록만 합니다.
30
32
  * JSON 자체는 이미 파싱에 성공한 상태이므로(스트리밍 중 파싱 실패와는 다른 케이스),
31
33
  * `loading` 여부와 무관하게 항상 기록합니다.
32
34
  */
33
35
  private updateElement;
34
36
  /**
35
- * `properties` 객체의 키가 렌더링된 엘리먼트의 프로퍼티 이름과 일치하면 자동으로 할당됩니다.
36
- * `properties` 객체에 위험한 프로퍼티가 포함되어 있는지 검증하여, 유효한 경우에만 할당합니다.
37
- * 할당 중 오류가 발생한 경우, 에러 처리합니다.
37
+ * 블록 스키마에 적힌 이름만 대입합니다. 스키마 밖의 이름은 대입하지 않고 기록합니다 —
38
+ * 블록 하나를 통째로 버리지 않는 것은 LLM 이 무해한 여분 키를 붙이는 일이 흔하기 때문입니다.
38
39
  */
39
40
  private updateProperties;
40
- /**
41
- * `properties` 객체에 위험한 프로퍼티가 포함되어 있는지 검증합니다.
42
- * DOM 조작이나 이벤트 핸들러로 악용될 수 있는 프로퍼티를 최소한으로 차단합니다.
43
- */
44
- private validateProperties;
45
41
  /**
46
42
  * 에러 카드 없이 콘솔에만 기록합니다. 채팅 UI에 갑작스러운 에러 카드가 뜨는 것을 피하기 위함입니다 —
47
43
  * addon 모듈을 import하지 않아 아직 등록되지 않은 태그일 수도 있으므로, 실제 에러라기보다
@@ -1,24 +1,16 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
1
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
2
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
3
  import { UDataElement } from "../UDataElement.js";
4
+ import { getElementBlockProperties } from "../../utilities/ElementRegistry.js";
4
5
  import { styles } from "./UElementBlock.styles.js";
5
6
  import { html, nothing } from "lit";
6
7
  import { customElement, property, state } from "lit/decorators.js";
7
8
  import "@iyulab/components/dist/components/skeleton/USkeleton.js";
8
9
  //#region src/components/blocks/UElementBlock.ts
9
- var DEFAULT_BLACKLIST = [
10
- "innerHTML",
11
- "outerHTML",
12
- "textContent",
13
- "innerText",
14
- "outerText",
15
- "srcdoc"
16
- ];
17
10
  var UElementBlock = class UElementBlock extends UDataElement {
18
11
  constructor(..._args) {
19
12
  super(..._args);
20
13
  this.loading = false;
21
- this.blacklist = DEFAULT_BLACKLIST;
22
14
  this.element = null;
23
15
  }
24
16
  static {
@@ -27,8 +19,7 @@ var UElementBlock = class UElementBlock extends UDataElement {
27
19
  willUpdate(changedProperties) {
28
20
  super.willUpdate(changedProperties);
29
21
  if (changedProperties.has("tag")) this.updateElement(this.tag);
30
- if (changedProperties.has("properties") && this.element) this.updateProperties(this.element, this.properties);
31
- if (changedProperties.has("blacklist") && this.element && this.properties) this.updateProperties(this.element, this.properties);
22
+ if ((changedProperties.has("properties") || changedProperties.has("tag")) && this.element && this.properties) this.updateProperties(this.element, this.properties);
32
23
  }
33
24
  render() {
34
25
  if (this.loading === true) return html`
@@ -54,9 +45,8 @@ var UElementBlock = class UElementBlock extends UDataElement {
54
45
  this.reportError(error);
55
46
  }
56
47
  /**
57
- * `tag` 프로퍼티에 등록된 커스텀 엘리먼트를 렌더링하는 컴포넌트입니다.
58
- * `tag`가 변경될 때마다 등록된 커스텀 엘리먼트를 새로 생성하여 렌더링합니다.
59
- * `tag`가 유효하지 않거나 등록된 커스텀 엘리먼트가 아닌 경우, 에러 처리합니다.
48
+ * `tag`가 변경될 때마다 블록 엘리먼트를 새로 생성합니다.
49
+ * 블록으로 등록되지 않은 태그나 아직 정의되지 않은 커스텀 엘리먼트는 만들지 않고 기록만 합니다.
60
50
  * JSON 자체는 이미 파싱에 성공한 상태이므로(스트리밍 중 파싱 실패와는 다른 케이스),
61
51
  * `loading` 여부와 무관하게 항상 기록합니다.
62
52
  */
@@ -67,6 +57,11 @@ var UElementBlock = class UElementBlock extends UDataElement {
67
57
  this.reportError(/* @__PURE__ */ new Error("Tag is required"));
68
58
  return;
69
59
  }
60
+ if (!getElementBlockProperties(tag)) {
61
+ this.element = null;
62
+ this.reportError(/* @__PURE__ */ new Error(`"${tag}" is not a registered element block — register its schema with registerElementBlock() or ElementPromptBuilder.add()`));
63
+ return;
64
+ }
70
65
  if (!customElements.get(tag)) {
71
66
  this.element = null;
72
67
  this.reportError(/* @__PURE__ */ new Error(`Unknown tag: ${tag}`));
@@ -75,27 +70,25 @@ var UElementBlock = class UElementBlock extends UDataElement {
75
70
  this.element = document.createElement(tag);
76
71
  }
77
72
  /**
78
- * `properties` 객체의 키가 렌더링된 엘리먼트의 프로퍼티 이름과 일치하면 자동으로 할당됩니다.
79
- * `properties` 객체에 위험한 프로퍼티가 포함되어 있는지 검증하여, 유효한 경우에만 할당합니다.
80
- * 할당 중 오류가 발생한 경우, 에러 처리합니다.
73
+ * 블록 스키마에 적힌 이름만 대입합니다. 스키마 밖의 이름은 대입하지 않고 기록합니다 —
74
+ * 블록 하나를 통째로 버리지 않는 것은 LLM 이 무해한 여분 키를 붙이는 일이 흔하기 때문입니다.
81
75
  */
82
76
  updateProperties(element, props) {
83
- if (this.validateProperties(props)) try {
84
- Object.assign(element, props);
77
+ if (typeof props !== "object" || props === null || Array.isArray(props)) {
78
+ this.reportError(/* @__PURE__ */ new Error(`Properties must be an object: ${JSON.stringify(props)}`));
79
+ return;
80
+ }
81
+ const allowed = getElementBlockProperties(element.localName) ?? /* @__PURE__ */ new Set();
82
+ const accepted = {};
83
+ const rejected = [];
84
+ for (const [key, value] of Object.entries(props)) if (allowed.has(key)) accepted[key] = value;
85
+ else rejected.push(key);
86
+ if (rejected.length > 0) this.reportError(/* @__PURE__ */ new Error(`Not in the "${element.localName}" schema, not assigned: ${rejected.join(", ")}`));
87
+ try {
88
+ Object.assign(element, accepted);
85
89
  } catch (error) {
86
90
  this.reportError(error);
87
91
  }
88
- else this.reportError(/* @__PURE__ */ new Error(`Not allowed properties: ${JSON.stringify(props)}`));
89
- }
90
- /**
91
- * `properties` 객체에 위험한 프로퍼티가 포함되어 있는지 검증합니다.
92
- * DOM 조작이나 이벤트 핸들러로 악용될 수 있는 프로퍼티를 최소한으로 차단합니다.
93
- */
94
- validateProperties(props) {
95
- if (typeof props !== "object" || props === null || Array.isArray(props)) return false;
96
- const obj = props;
97
- for (const key of Object.keys(obj)) if (this.blacklist.includes(key)) return false;
98
- return true;
99
92
  }
100
93
  /**
101
94
  * 에러 카드 없이 콘솔에만 기록합니다. 채팅 UI에 갑작스러운 에러 카드가 뜨는 것을 피하기 위함입니다 —
@@ -112,7 +105,6 @@ __decorate([property({
112
105
  }), __decorateMetadata("design:type", Object)], UElementBlock.prototype, "loading", void 0);
113
106
  __decorate([property({ type: String }), __decorateMetadata("design:type", String)], UElementBlock.prototype, "tag", void 0);
114
107
  __decorate([property({ type: Object }), __decorateMetadata("design:type", typeof Record === "undefined" ? Object : Record)], UElementBlock.prototype, "properties", void 0);
115
- __decorate([property({ type: Array }), __decorateMetadata("design:type", Array)], UElementBlock.prototype, "blacklist", void 0);
116
108
  __decorate([state(), __decorateMetadata("design:type", Object)], UElementBlock.prototype, "element", void 0);
117
109
  UElementBlock = __decorate([customElement("u-element-block")], UElementBlock);
118
110
  //#endregion
@@ -1,3 +1,4 @@
1
+ import { PropertyValues } from 'lit';
1
2
  import { UElement } from '@iyulab/components/dist/components/UElement.js';
2
3
  /**
3
4
  * 단일 파일을 표시하는 블록 컴포넌트입니다.
@@ -18,8 +19,9 @@ export declare class UFileBlock extends UElement {
18
19
  url?: string;
19
20
  /** 미리보기 오버레이가 열려있는지 여부 */
20
21
  private previewOpen;
21
- connectedCallback(): void;
22
22
  disconnectedCallback(): void;
23
+ /** 열린 미리보기는 층이다 — Escape 는 components 의 층 스택이 «가장 나중에 연 층 하나» 에만 준다. */
24
+ protected updated(changed: PropertyValues): void;
23
25
  private get isImage();
24
26
  private get isVideo();
25
27
  /** 클릭 시 오버레이로 미리볼 수 있는 타입인지 여부 */
@@ -29,7 +31,6 @@ export declare class UFileBlock extends UElement {
29
31
  private renderCardMain;
30
32
  private handleCardClick;
31
33
  private closePreview;
32
- private handleKeyDown;
33
34
  private handleRemoveClick;
34
35
  /** MIME 타입 → Tabler Icon 이름 */
35
36
  private resolveIcon;
@@ -1,5 +1,6 @@
1
- import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorateMetadata.js";
2
- import __decorate from "../../_virtual/_@oxc-project_runtime@0.150.0/helpers/esm/decorate.js";
1
+ import "../../utilities/icons.js";
2
+ import __decorateMetadata from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorateMetadata.js";
3
+ import __decorate from "../../_virtual/_@oxc-project_runtime@0.151.0/helpers/esm/decorate.js";
3
4
  import { messages } from "../../utilities/messages.js";
4
5
  import { styles } from "./UFileBlock.styles.js";
5
6
  import { html, nothing } from "lit";
@@ -7,6 +8,7 @@ import { customElement, property, state } from "lit/decorators.js";
7
8
  import "@iyulab/components/dist/components/icon/UIcon.js";
8
9
  import { UElement } from "@iyulab/components/dist/components/UElement.js";
9
10
  import "@iyulab/components/dist/components/button/UButton.js";
11
+ import { OverlayManager } from "@iyulab/components/dist/utilities/OverlayManager.js";
10
12
  //#region src/components/blocks/UFileBlock.ts
11
13
  var UFileBlock = class UFileBlock extends UElement {
12
14
  constructor(..._args) {
@@ -21,9 +23,6 @@ var UFileBlock = class UFileBlock extends UElement {
21
23
  e?.stopPropagation();
22
24
  this.previewOpen = false;
23
25
  };
24
- this.handleKeyDown = (e) => {
25
- if (this.previewOpen && e.key === "Escape") this.closePreview();
26
- };
27
26
  this.handleRemoveClick = (e) => {
28
27
  e.stopPropagation();
29
28
  if (this.fire("remove")) this.remove();
@@ -32,14 +31,17 @@ var UFileBlock = class UFileBlock extends UElement {
32
31
  static {
33
32
  this.styles = [super.styles, styles];
34
33
  }
35
- connectedCallback() {
36
- super.connectedCallback();
37
- document.addEventListener("keydown", this.handleKeyDown);
38
- }
39
34
  disconnectedCallback() {
40
- document.removeEventListener("keydown", this.handleKeyDown);
35
+ OverlayManager.closeLayer(this);
41
36
  super.disconnectedCallback();
42
37
  }
38
+ /** 열린 미리보기는 층이다 — Escape 는 components 의 층 스택이 «가장 나중에 연 층 하나» 에만 준다. */
39
+ updated(changed) {
40
+ super.updated(changed);
41
+ if (!changed.has("previewOpen")) return;
42
+ if (this.previewOpen) OverlayManager.openLayer(this, () => this.closePreview());
43
+ else OverlayManager.closeLayer(this);
44
+ }
43
45
  get isImage() {
44
46
  return !!this.url && !!this.type?.startsWith("image/");
45
47
  }
@@ -138,7 +138,7 @@ var styles = css`
138
138
  .preview-overlay {
139
139
  position: fixed;
140
140
  inset: 0;
141
- z-index: 9999;
141
+ z-index: var(--u-layer-overlay, 9999);
142
142
  display: flex;
143
143
  flex-direction: column;
144
144
  background: rgba(0, 0, 0, 0.92);
@@ -13,6 +13,8 @@ import { ReferenceCitation } from '../../types/References.js';
13
13
  * - 마크다운 링크/이미지(`[..](href)`, `![..](src)`, autolink)의 href/src는
14
14
  * `escapeHtmlHref`로 protocol을 검사합니다(javascript:/data:/vbscript: 차단) —
15
15
  * marked 자신은 URL을 encodeURI할 뿐 protocol을 걸러내지 않습니다.
16
+ * - 이미지 src는 그 위에 출처 정책(`setAllowedImagePrefixes`)을 거칩니다 — 막힌 이미지는
17
+ * 요청하지 않고 대체 텍스트로 그립니다(이미지 URL은 데이터 반출 경로다).
16
18
  * - 테이블 셀 인라인 콘텐츠(renderTable)도 위 두 규칙과 같은 렌더러 설정을 공유합니다
17
19
  * — `Parser.parseInline`을 옵션 없이 호출하면 기본(비-sanitize) 렌더러로 되돌아가므로
18
20
  * 반드시 `this.parser.defaults`를 함께 넘겨야 합니다.
@@ -30,6 +32,7 @@ export declare class UMarkedBlock extends UElement {
30
32
  private queuedTimer?;
31
33
  private streaming;
32
34
  private streamingTimer?;
35
+ connectedCallback(): void;
33
36
  disconnectedCallback(): void;
34
37
  protected shouldUpdate(_changedProperties: PropertyValues): boolean;
35
38
  protected willUpdate(changedProperties: PropertyValues): void;
@@ -60,7 +63,11 @@ export declare class UMarkedBlock extends UElement {
60
63
  * URL을 encodeURI할 뿐 protocol을 걸러내지 않는다.
61
64
  */
62
65
  private renderLink;
63
- /** 마크다운 이미지의 src도 `renderLink`와 동일하게 protocol을 검사합니다. */
66
+ /**
67
+ * 마크다운 이미지의 src도 `renderLink`와 동일하게 protocol을 검사하고, 이미지 출처 정책
68
+ * (`setAllowedImagePrefixes`)에 대어 봅니다. 막힌 이미지는 `<img>` 를 만들지 않는다 —
69
+ * 요청 자체가 반출 경로이므로 대체 텍스트만 그린다.
70
+ */
64
71
  private renderImage;
65
72
  /**
66
73
  * 인용/출처 참조객체가 있을때 ref 태그 HTML을 this.placeholder에 보관하고