@boxcc/maildeno-editor 0.0.0-stage → 0.4.14

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 (57) hide show
  1. package/CHANGELOG.md +479 -0
  2. package/README.md +442 -2
  3. package/dist/DatePicker-AdfGW0Tw.js +5347 -0
  4. package/dist/DatePicker-aNFlsoOb.js +5347 -0
  5. package/dist/Dialog-By0JLN8s.js +6294 -0
  6. package/dist/HealthIndicator-BLID6Ty0.js +1216 -0
  7. package/dist/HealthIndicator-DfzqzPNw.js +1217 -0
  8. package/dist/PopperContent-N2nAEFeH.js +2538 -0
  9. package/dist/PopperContent-eLmz1Gjd.js +2578 -0
  10. package/dist/PreviewCanvas-D3SpILsV.js +534 -0
  11. package/dist/PreviewCanvas-PtW1UL1J.js +534 -0
  12. package/dist/RichTextEditor-D6DQqbJg.js +12218 -0
  13. package/dist/RichTextEditor-DDEfKPZm.js +12217 -0
  14. package/dist/RowPreviewChildren-BGnilx-K.js +4 -0
  15. package/dist/RowPreviewChildren-CalQWx1C.js +4 -0
  16. package/dist/RowPreviewLegacyComponent-Df_1HTly.js +403 -0
  17. package/dist/RowPreviewLegacyComponent-NECG3wpn.js +403 -0
  18. package/dist/RowPreviewRow-C2XAe5Xs.js +81 -0
  19. package/dist/RowPreviewRow-DG4AdMrv.js +81 -0
  20. package/dist/SavedRowsPanel-2JBfYdxN.js +492 -0
  21. package/dist/SavedRowsPanel-B6_VHQZm.js +493 -0
  22. package/dist/_plugin-vue_export-helper-Dj7HTbfw.js +8 -0
  23. package/dist/adapters/errors.d.ts +59 -0
  24. package/dist/adapters/localStorageAdapter.d.ts +6 -0
  25. package/dist/adapters/types.d.ts +151 -0
  26. package/dist/babel-DV7WPQI0.js +10043 -0
  27. package/dist/blocks/registry.d.ts +23 -0
  28. package/dist/blocks/types.d.ts +73 -0
  29. package/dist/borderRadius-CkSa1lQ9.js +75 -0
  30. package/dist/components/features/emailBuilder/EmailEditor.vue.d.ts +183 -0
  31. package/dist/composables/emailBuilder/export/logic/espLogicWrapper.d.ts +76 -0
  32. package/dist/composables/emailBuilder/persistence/useEmailBuilderPersistence.d.ts +38 -0
  33. package/dist/composables/emailBuilder/transform/pipeline/optimize.d.ts +100 -0
  34. package/dist/composables/system/useColorScheme.d.ts +16 -0
  35. package/dist/element-DQw3HLit.js +21540 -0
  36. package/dist/element.d.ts +6 -0
  37. package/dist/element.js +5 -0
  38. package/dist/esp/registry.d.ts +33 -0
  39. package/dist/estree-DY9POgc0.js +8195 -0
  40. package/dist/html-wb0gSX1o.js +7273 -0
  41. package/dist/index.d.ts +17 -0
  42. package/dist/index.js +15032 -0
  43. package/dist/init.d.ts +180 -0
  44. package/dist/init.js +143 -0
  45. package/dist/maildeno-editor.css +2 -0
  46. package/dist/merge-tags/registry.d.ts +33 -0
  47. package/dist/mergeTagDefinitions-Cler19nv.js +27 -0
  48. package/dist/standalone-DHvJ30Td.js +3554 -0
  49. package/dist/theme.d.ts +206 -0
  50. package/dist/types/assistant.d.ts +56 -0
  51. package/dist/useEmailBuilder-2yCUzRx2.js +4934 -0
  52. package/dist/useEmailBuilder-D3uV7dwL.js +4934 -0
  53. package/dist/useToast-D1GgDMqQ.js +194 -0
  54. package/dist/utils/border.d.ts +15 -0
  55. package/dist/utils/borderRadius.d.ts +10 -0
  56. package/dist/vue.runtime.esm-bundler-D2AjRP90.js +6117 -0
  57. package/package.json +100 -4
package/CHANGELOG.md ADDED
@@ -0,0 +1,479 @@
1
+ # Changelog
2
+
3
+ ## 0.4.12
4
+
5
+ API change.
6
+
7
+ ### Fixed
8
+ - The **Image component** no longer shows extra space below the image, and linked images now size the same as unlinked ones. Alignment (left, center, right) still works.
9
+
10
+ ## 0.4.11
11
+
12
+ API changes.
13
+
14
+ ### Changed
15
+ + Moved Button and Anchor padding from the container `<div>` to the clickable `<a>` / `<Link>` element.
16
+ + Updated HTML, MJML, and React Email renderers to consistently apply padding to the link element.
17
+ + Updated generated styles so Button and Anchor padding targets the .{uid}-link selector.
18
+
19
+ ## 0.4.10
20
+
21
+ API change.
22
+
23
+ ### Changed
24
+ - Reduced the **Image** panel minimum width from `8px` to `1px`.
25
+
26
+ ## 0.4.9
27
+
28
+ API change.
29
+
30
+ ### Changed
31
+ - The **Content** tab is now the default tab in the left-hand panel.
32
+
33
+ ## 0.4.8
34
+
35
+ API changes.
36
+
37
+ ### Changed
38
+ - The **Layout** tab is now the default tab in the left-hand panel.
39
+
40
+ ### Removed
41
+ - Unused code in `CanvasRowDropZone`.
42
+
43
+ ## 0.4.7
44
+
45
+ Public API surface. No runtime change.
46
+
47
+ ### Added
48
+
49
+ **The document model and editor state types are exported.** `Canvas`,
50
+ `NestedRow`, `RowSpacer`, `Column`, `VisibilityConfig`, `BorderConfig`,
51
+ `GradientConfig`, `AutoSaveStatus` and `ColorMode` now come from the
52
+ package root.
53
+
54
+ Five of these already appeared in `EmailEditor`'s props and slot props,
55
+ so they were public whether or not they were exported — just unnameable.
56
+ A consumer destructuring the default slot got a `rows` array it could
57
+ read but could not write a signature for, and `tsc --declaration` failed
58
+ with TS2883 on anything that touched one.
59
+
60
+ `Column`, `VisibilityConfig`, `BorderConfig` and `GradientConfig` were
61
+ not leaked themselves, but `NestedRow` and `RowSpacer` are not usable
62
+ without them: being able to name a row but not the type of its `columns`
63
+ is only half a fix. They were module-private in `optimize.ts` and are now
64
+ exported.
65
+
66
+ `Canvas` is the email body's own settings — width, padding, background,
67
+ preheader — not an HTML canvas. Alias it on import if that reads badly.
68
+
69
+ ### Fixed
70
+
71
+ **`index.ts` pointed at the wrong entry for `init()`.** The comment said
72
+ custom-element usage "including init()" lives at
73
+ `@maildeno/editor/element`. `init()` is at `@maildeno/editor/init`;
74
+ `/element` has `registerMaildenoEditorElement` and
75
+ `MaildenoEditorElement`.
76
+
77
+ **Added `main` and `module` fallbacks.** With only an `exports` map, any
78
+ tool predating it failed to resolve the package at all rather than
79
+ falling back. Both point at `dist/index.js`, same as `exports["."]`.
80
+
81
+ Verified with `tsc --strict`, `declaration: true` and
82
+ `skipLibCheck: false` against every value export of all three entries:
83
+ 0 errors, down from 5.
84
+
85
+ ## 0.4.6
86
+
87
+ ### Changed
88
+
89
+ **Rich text, the date picker and three panels now load on demand.** First
90
+ load drops from 440kB to 269kB gzipped, 38.8% smaller.
91
+
92
+ TipTap and ProseMirror are ~745kB — a quarter of the bundle — and
93
+ RichTextEditor is the only thing that pulls them. It is also how heading,
94
+ paragraph and list blocks render, not just how they are edited, so it
95
+ cannot simply be made async: the canvas would be blank until the chunk
96
+ landed. Those blocks now mount RichTextBlock, which paints the text
97
+ through RichTextStatic and swaps in the real editor when its chunk
98
+ resolves. Same root element and content classes, so the swap is
99
+ invisible. Merge tags render through a TipTap NodeView, so their markup
100
+ shows raw for that one frame.
101
+
102
+ This defers parsing, not downloading. The chunk is still fetched on
103
+ mount, so a session transfers the same bytes; what improves is time to
104
+ first paint and time to interactive.
105
+
106
+ DatePicker, HealthIndicator, SavedRowsPanel and PreviewCanvas are plain
107
+ async components — all four are already behind a v-if and none is visible
108
+ until the user opens something. DatePicker alone was worth 128kB: it is
109
+ used in exactly one place, an advanced ESP visibility rule, and pulled
110
+ all of @internationalized/date plus reka-ui's calendar tree into every
111
+ page load.
112
+
113
+ **Unreachable type declarations are no longer published.** 216 .d.ts
114
+ files down to 17, 200kB smaller. unplugin-dts emits a declaration for
115
+ every module under src/, but `exports` exposes only ".", "./element" and
116
+ "./init" and has no wildcard, so a consumer could never load the other
117
+ 201 — including three that still imported @tiptap/vue-3, which stopped
118
+ being a dependency in 0.4.5. `scripts/prune-types.mjs` walks the import
119
+ graph from each entry's `types` target and removes what it never visits.
120
+ It fails the build if an entry is missing rather than pruning against an
121
+ incomplete graph.
122
+
123
+ Verified with `tsc --strict` and `skipLibCheck: false` against the whole
124
+ public surface, before and after: identical results.
125
+
126
+ ## 0.4.5
127
+
128
+ Packaging only. No API change, no behaviour change.
129
+
130
+ ### Changed
131
+
132
+ **The 15 runtime dependencies moved to devDependencies.** TipTap,
133
+ ProseMirror, reka-ui, @vueuse/core, prettier and @internationalized/date
134
+ are all bundled into `dist` at build time, so declaring them as runtime
135
+ dependencies made npm install a second, unused copy of each into every
136
+ consumer's node_modules.
137
+
138
+ `dist` imports exactly one external module — `vue` — which is already the
139
+ sole peerDependency. Verified across every emitted chunk, and by
140
+ installing the package with nothing but Vue and building a consumer:
141
+ 32/32 scoped selectors present, no unresolved imports.
142
+
143
+ Installing the package now pulls **25 MB across 15 packages instead of
144
+ 71 MB across 45**.
145
+
146
+ If any of these is ever externalised rather than bundled, it has to move
147
+ back. `dist` importing anything other than `vue` is the signal.
148
+
149
+ ## 0.4.4
150
+
151
+ Packaging only. No API change, no behaviour change in the editor itself.
152
+ The published package drops from 8.13 MB unpacked to 5.48 MB, 32.6% smaller.
153
+
154
+ ### Changed
155
+
156
+ **React Email export formats with prettier's babel-ts parser** instead of
157
+ the typescript parser. `prettier/plugins/typescript` is 900kB of source
158
+ against babel's 318kB and was the largest single file in the package.
159
+ Output is byte-identical on the TSX this package generates, verified
160
+ across generics, JSX, inline style objects and mapped children. The
161
+ typescript parser is the stricter of the two, which matters for arbitrary
162
+ user code but not for TSX `react-email.ts` generated moments earlier.
163
+ Saves 600kB.
164
+
165
+ **Both build passes are minified.** They have to agree: the two passes
166
+ share chunks by content hash, so identical output collapses to one file
167
+ and differing output ships two. Minifying only the element pass made the
168
+ package *larger* — 8.68 MB — because every prettier chunk was then
169
+ carried twice, once minified and once not. Saves 1.92MB with both on.
170
+
171
+ **`element-scoped-styles.css` is no longer emitted.** Nothing referenced
172
+ it: not `src/`, not the framework guides, not the README, not the exports
173
+ map. The shadow root reads those rules from the substituted string inside
174
+ the chunk, and Vite only extracted the file because library mode always
175
+ does. `dist/editor.css` is unaffected and `./style.css` still resolves.
176
+ Saves 72kB.
177
+
178
+ ## 0.4.3
179
+
180
+ ### Fixed
181
+
182
+ **Every component `<style scoped>` block was missing when installing from
183
+ npm and using the `EmailEditor` Vue component.** The editor rendered
184
+ unstyled panels — `HealthIndicator`, `DesktopOnlyNotice`, the text panel,
185
+ and 29 other scoped blocks — while Tailwind, the fonts and the icons all
186
+ applied normally. `init()` and the custom element were unaffected, and
187
+ building against a local `dist/` folder never reproduced it.
188
+
189
+ 0.4.2 delivered those styles by prepending a self-executing snippet to the
190
+ entry chunk:
191
+
192
+ ```js
193
+ (function(){ /* … document.head.appendChild(style) … */ })();
194
+ import { a, c, g, … } from "./index-DhFg3uKs.js";
195
+ export { a as EmailEditor, … };
196
+ ```
197
+
198
+ `package.json` declares `sideEffects` as covering CSS files only, which
199
+ tells a consumer's bundler that every `.js` in the package is pure. Rollup
200
+ had emitted `dist/index.js` as a thin facade holding nothing but that
201
+ snippet and a set of re-exports — and a pure module whose exports can be
202
+ reached directly is one a bundler may delete outright. So consumer builds
203
+ dropped the file, the snippet went with it, and the CSS never ran.
204
+ Verified against the published 0.4.2 tarball: zero of 32 scoped selectors
205
+ survived a consumer build.
206
+
207
+ Whether Rollup emits that facade is a chunking decision, which is why the
208
+ same source built correctly in this repo and shipped broken. The styles
209
+ are now substituted into a value `baseStyles.ts` returns, so
210
+ `EmailEditor.vue` injects them on mount alongside Tailwind and the fonts.
211
+ Reachable from the component, they cannot be dropped without dropping the
212
+ component — the mechanism `shadowStyles.ts` has always used for the shadow
213
+ root. Confirmed surviving even under `sideEffects: false`.
214
+
215
+ Nothing changed in the public API, and no CSS import is needed.
216
+
217
+ ### Changed
218
+
219
+ **A missing style substitution now fails the build instead of warning.**
220
+ Both build passes error out if the placeholder cannot be found in any
221
+ chunk. A warning in a build log was not enough to catch this before
222
+ publishing.
223
+
224
+ ## 0.4.2
225
+
226
+ Docs only — no code changes. 0.4.1's `onSave` fix is confirmed working on the
227
+ `init()` path.
228
+
229
+ - **Save gating documented** in the Vanilla, React and Astro guides: `onSave`
230
+ is what reveals the Save button, and `handle.on("save", …)` only fires when
231
+ it was passed, because without it the editor never saves.
232
+ - **New "Reading the canvas" section** in the Nuxt and Vue guides, covering
233
+ `getHtml` / `getMjml` / `getReactEmail` / `getJson` via a template ref —
234
+ they are instance methods, not events or slot props, which was not written
235
+ down anywhere.
236
+
237
+ ## 0.4.1
238
+
239
+ ### Fixed
240
+
241
+ **`onSave` from `init()` never fired.** `save` was a `defineEmits` entry, and
242
+ `defineCustomElement` *replaces* `instance.emit` with a DOM-event dispatcher:
243
+
244
+ ```js
245
+ instance.emit = (event, ...args) => { dispatch(event, args); … }
246
+ ```
247
+
248
+ So `emit("save")` dispatched a CustomEvent and never called the handler the
249
+ host had passed. The Save button appeared (the prop was present) and the
250
+ callback was unreachable — while `handle.on("save", …)` worked, because that
251
+ listens for the DOM event.
252
+
253
+ `save` is no longer an emit. The handler is a prop the component calls
254
+ directly, and the component re-dispatches a `bubbles: true, composed: true`
255
+ CustomEvent alongside it so `handle.on("save", …)` keeps working.
256
+
257
+ `init()` sets it as **`saveHandler`**, not `onSave`: Vue's custom-element
258
+ wrapper routes `on*` keys to its event machinery, so `el.onSave = fn` never
259
+ reaches the component either. Vue hosts keep using `@save`.
260
+
261
+
262
+ ## 0.4.0
263
+
264
+ Gating corrections. All three came from running the editor as a guest, where
265
+ every "can the user do this?" question has a different answer.
266
+
267
+ ### Changed
268
+
269
+ **The Save button now follows an `onSave` handler**, matching how
270
+ `onSendTestEmail` reveals the Send-test button. Pass it and Save appears; omit
271
+ it and the button, the save-status indicator and the autosave timer all
272
+ disappear.
273
+
274
+ ```vue
275
+ <EmailEditor @save="onSave" /> <!-- Vue: @save IS the onSave prop -->
276
+ ```
277
+ ```ts
278
+ init({ onSave(payload) { … } })
279
+ ```
280
+
281
+ 0.3.0 gated this on the storage adapter having `saveTemplate`, which was
282
+ wrong: `mergeWithDefaults` fills every missing method from the localStorage
283
+ defaults, so `saveTemplate` is *always* present by the time anything reads it.
284
+ The check could never be false. Gating on an explicit handler is both correct
285
+ and more discoverable.
286
+
287
+ **The saved-templates panel button is hidden when the host omits
288
+ `listTemplates`.** Same before-merge reasoning. A guest would otherwise be
289
+ offered a template library backed by localStorage that they never saved to and
290
+ cannot reach anywhere else. `versions: true` forces the button on, since
291
+ version history comes from different adapter methods.
292
+
293
+ ### Guest editors
294
+
295
+ The two above make a genuine read-only editor a one-liner, and the shape
296
+ matters:
297
+
298
+ ```ts
299
+ // Right — everything unlisted falls back to localStorage
300
+ const adapter = { loadTemplate: api.loadTemplate };
301
+ ```
302
+ ```ts
303
+ // Wrong — every other method still points at authenticated endpoints,
304
+ // so saving a row 401s
305
+ const { saveTemplate, ...adapter } = api;
306
+ ```
307
+
308
+ With the first, saved rows, image uploads and drafts all keep working against
309
+ the visitor's own browser. Exports work fully. There is no Save button and no
310
+ template library.
311
+
312
+ ## 0.3.0
313
+
314
+ Four fixes from real integration, three of them things only a running app
315
+ could surface.
316
+
317
+ ### Fixed
318
+
319
+ **The editor's CSS no longer leaks into the host page.** The Vue-component
320
+ path injected ~183KB into `document.head` — bare `.grid`, `.flex`, `.hidden`,
321
+ `.block` utilities plus `html`, `body` and `h1`–`h6` element rules. In an app
322
+ that also uses Tailwind, the editor's copy was injected later and won on
323
+ source order, so the host's own layout classes started behaving like the
324
+ editor's.
325
+
326
+ Every rule is now prefixed with `:where(.md-editor-scope)` at build time by a
327
+ PostCSS pass, and the editor root carries that class. `:where()` adds no
328
+ specificity, so the cascade inside the editor is unchanged. `@font-face`,
329
+ `@property`, `@keyframes` and `@import` stay global — they are document-scoped
330
+ by nature, and `@property` in particular is what makes Tailwind's `--tw-*`
331
+ variables resolve at all. `:root`, `html` and `body` are retargeted to the
332
+ editor root rather than dropped, since some carry the editor's own background
333
+ and font stack.
334
+
335
+ Verified on a real mount: 1,121 rules scoped, zero unscoped utilities or
336
+ element rules remaining.
337
+
338
+ **Save is hidden when the host can't save.** Pass a `storageAdapter` without
339
+ `saveTemplate` and the Save button, the save-status indicator and the autosave
340
+ timer all disappear — a guest session no longer fires 401s in the background
341
+ or shows a button that always errors.
342
+
343
+ Gated on `useCanSave()` rather than checking the resolved adapter, because
344
+ `mergeWithDefaults` fills every missing method from the localStorage adapter,
345
+ so `typeof adapter.saveTemplate` is *always* a function by the time anything
346
+ reads it. The signal is computed from the host's partial before merging.
347
+ Passing no adapter at all still counts as "can save" — that is the zero-config
348
+ demo path.
349
+
350
+ ### Added
351
+
352
+ **`ready` event.** Fires once the canvas has actually painted its initial
353
+ content, not when the component mounts. Hosts showing a loading placeholder
354
+ were removing it on mount, which is before `loadTemplate` resolves and the rows
355
+ hydrate — so users watched blocks appear one at a time.
356
+
357
+ ```vue
358
+ <EmailEditor @ready="showSkeleton = false" />
359
+ ```
360
+
361
+ Emitted two ticks after the internal ready state flips, so the DOM for that
362
+ first paint exists by the time the handler runs. Fires once per mount.
363
+
364
+ ### Note on layout
365
+
366
+ The editor is built around **document scroll**: its shell is `min-h-screen`
367
+ with a `sticky top-0` header, so the canvas grows past the viewport and the
368
+ page scrolls under a pinned toolbar. Giving its container a fixed height with
369
+ `overflow: hidden` clips everything below the fold and leaves no scroll
370
+ container to reach it. Give the container a minimum height, not a maximum.
371
+
372
+ The docs previously said "the editor fills its parent; give it a real height",
373
+ which is easy to read as "one viewport tall, overflow hidden". Reworded.
374
+
375
+ ## 0.2.0
376
+
377
+ Adds the write half of the editor's API, version history, a shared row
378
+ library, and two host slots. Nothing in 0.1.x breaks.
379
+
380
+ ### Added
381
+
382
+ **Programmatic write API.** The read side (`getHtml`, `getMjml`,
383
+ `getReactEmail`, `getJson`) has always been public; these are its counterpart,
384
+ so a host can drive the canvas from its own UI without reaching into builder
385
+ internals.
386
+
387
+ ```ts
388
+ setJson(data, opts?) // opts.history: "undoable" (default) | "reset"
389
+ getSelection() // { id, type } | null — type is the block type
390
+ setSelection(id) // false if no block has that id
391
+ onChange(cb) // returns an unsubscribe function
392
+ ```
393
+
394
+ `setJson` accepts exactly what `getJson()` returns, so `setJson(getJson())`
395
+ round-trips, plus the `{ canvas, content: { rows } }` shape version APIs
396
+ typically return. It defaults to a single undoable step. Available on the Vue
397
+ component ref, on `EditorHandle` from `init()`, and on the custom element.
398
+
399
+ **Version history** — `versions` prop on the component and `init()`. Replaces
400
+ the saved-templates panel and its header button with restore / delete /
401
+ delete-all / keep. Backed by five adapter methods:
402
+
403
+ ```ts
404
+ listTemplateVersions(templateId)
405
+ getTemplateVersion(templateId, versionId)
406
+ deleteTemplateVersion(templateId, versionId)
407
+ deleteAllTemplateVersions(templateId) // kept versions survive
408
+ setTemplateVersionKept(templateId, versionId, kept)
409
+ ```
410
+
411
+ Each control appears only when its method exists, so an adapter that can list
412
+ and restore but not delete gets exactly that. `createLocalStorageAdapter`
413
+ implements all five, so this works with no backend.
414
+
415
+ **Shared saved rows** — `listSystemSavedRows()`. An optional read-only second
416
+ row library in its own tab beside the user's own. The tab appears only when
417
+ the call returns rows. Read-only by construction: there is no save/rename/delete
418
+ counterpart, because who may curate a shared library is a permissions question
419
+ the editor has no user model to answer.
420
+
421
+ **Assistant slot.** The editor supplies a drawer, its trigger, open/close
422
+ state, escape handling and focus return; the host supplies the contents.
423
+
424
+ ```vue
425
+ <EmailEditor><template #assistant="{ editor }">…</template></EmailEditor>
426
+ ```
427
+
428
+ ```ts
429
+ init({ assistant: { mount(el, editor) {…}, unmount(el) {} } })
430
+ ```
431
+
432
+ There is no AI in this package. Prompts, endpoints and diff strategy belong to
433
+ whoever is building the product. `mount` runs on first open rather than at
434
+ startup, so a drawer nobody opens costs nothing.
435
+
436
+ **`header-actions` slot.** Host controls beside Save, receiving
437
+ `{ templateId, isSaving, saveStatus }`. Renders nothing when unused.
438
+
439
+ **`brandName`** prop and `init()` option — the "Powered by" line in the
440
+ desktop-only notice. Pass `""` to hide the line entirely.
441
+
442
+ **New exports:** `EditorWriteApi`, `AssistantMount`, `TemplateSummary`,
443
+ `TemplateVersionSummary`.
444
+
445
+ ### Fixed
446
+
447
+ **Published types were broken.** `dist/index.d.ts` re-exported `EmailEditor`
448
+ from a path that was never emitted. Consumers with `skipLibCheck: true` (Nuxt's
449
+ default) got `any` — no prop typing, no autocomplete, no error on a misspelled
450
+ prop; with it off, a hard `TS2307`.
451
+
452
+ Two independent causes, both failing silently:
453
+
454
+ 1. `vite-plugin-dts` needs `processor: "vue"` to emit SFC declarations. Its own
455
+ warning only fires when the entry or an include glob contains `.vue`, and
456
+ neither did.
457
+ 2. `unplugin-dts` gets Vue support from an optional peer on
458
+ `@vue/language-core ^3.1.5`. The playground's `vue-tsc ^2.1.0` hoisted v2 to
459
+ the monorepo root, failing the range check.
460
+
461
+ Fixed by setting `processor: "vue"` and aligning the playground to
462
+ `vue-tsc ^3.3.11`. Declaration coverage went 0 → 122 files.
463
+
464
+ **The typecheck wasn't checking components.** 34 SFCs used `<script setup>`
465
+ without `lang="ts"`, so `vue-shims.d.ts` declared every `*.vue` import as
466
+ `DefineComponent<{}, {}, any>` — which untyped all 121 components as
467
+ collateral. Converted, shim removed, and the 82 latent type errors it was
468
+ hiding are fixed.
469
+
470
+ **`getSelection().type` returned `"component"`** for every block. The tree
471
+ stores the structural kind in `type` and the block kind in `componentType`;
472
+ this returns the latter, which is what the field exists for.
473
+
474
+ ### Removed
475
+
476
+ - `optimizeAI.ts` — AI-facing snapshot stripping, unreferenced and belonging to
477
+ a host rather than the editor.
478
+ - `PropertyNumber.vue` — superseded by `PropertyNumberSlider`, unreferenced.
479
+