mce 0.24.4 → 0.25.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 (69) hide show
  1. package/README.md +302 -4
  2. package/dist/components/EditorPanels.vue.d.ts +6 -0
  3. package/dist/components/Interactions.vue.d.ts +3 -0
  4. package/dist/components/Selection.vue.d.ts +20 -20
  5. package/dist/components/shared/Cropper.vue.d.ts +5 -1
  6. package/dist/components/shared/Dialog.vue.d.ts +33 -38
  7. package/dist/components/shared/FloatPanel.vue.d.ts +4 -2
  8. package/dist/components/shared/LayoutItem.vue.d.ts +29 -0
  9. package/dist/components/shared/PanelContent.vue.d.ts +29 -0
  10. package/dist/components/shared/Transform.vue.d.ts +1 -1
  11. package/dist/components/timeline/EasingCurve.vue.d.ts +11 -0
  12. package/dist/components/timeline/KeyframePopover.vue.d.ts +3 -0
  13. package/dist/crdt/YDoc.d.ts +39 -2
  14. package/dist/crdt/YDoc.test.d.ts +1 -0
  15. package/dist/crdt/index.d.ts +3 -0
  16. package/dist/crdt/providers/indexeddb/IndexeddbProvider.d.ts +3 -1
  17. package/dist/crdt/reactivity.d.ts +27 -0
  18. package/dist/crdt/reactivity.test.d.ts +1 -0
  19. package/dist/crdt/vueReactivity.d.ts +8 -0
  20. package/dist/index.css +1 -1
  21. package/dist/index.d.ts +3 -0
  22. package/dist/index.js +10433 -9049
  23. package/dist/locale/en.d.ts +51 -9
  24. package/dist/locale/zh-Hans.d.ts +51 -9
  25. package/dist/mixins/0.context.d.ts +8 -0
  26. package/dist/mixins/extensions.d.ts +105 -0
  27. package/dist/mixins/panels.d.ts +46 -0
  28. package/dist/plugin.d.ts +14 -0
  29. package/dist/plugins/animate.d.ts +40 -0
  30. package/dist/plugins/components.d.ts +32 -0
  31. package/dist/plugins/flexLayout.d.ts +15 -0
  32. package/dist/plugins/history.d.ts +2 -0
  33. package/dist/plugins/interactions.d.ts +44 -0
  34. package/dist/plugins/shape.d.ts +0 -4
  35. package/dist/plugins/slice.d.ts +10 -0
  36. package/dist/plugins/smartGuides.d.ts +2 -2
  37. package/dist/plugins/timeline.d.ts +17 -0
  38. package/dist/plugins/toolbelt.d.ts +4 -0
  39. package/dist/plugins/variables.d.ts +27 -0
  40. package/dist/plugins/zoom.d.ts +2 -0
  41. package/dist/scene/Doc.d.ts +13 -1
  42. package/dist/typed-global.d.ts +6 -2
  43. package/dist/typed-plugins.d.ts +6 -3
  44. package/dist/utils/animationPresets.d.ts +27 -0
  45. package/dist/utils/components.d.ts +33 -0
  46. package/dist/utils/components.test.d.ts +1 -0
  47. package/dist/utils/create.d.ts +1 -15
  48. package/dist/utils/easing.d.ts +23 -0
  49. package/dist/utils/easing.test.d.ts +1 -0
  50. package/dist/utils/image.d.ts +6 -0
  51. package/dist/utils/index.d.ts +8 -1
  52. package/dist/utils/keyframes.d.ts +31 -0
  53. package/dist/utils/keyframes.test.d.ts +1 -0
  54. package/dist/utils/lottie.d.ts +27 -0
  55. package/dist/utils/lottie.test.d.ts +1 -0
  56. package/dist/utils/remapTextSelection.d.ts +23 -0
  57. package/dist/utils/remapTextSelection.test.d.ts +1 -0
  58. package/dist/utils/traverse.d.ts +9 -0
  59. package/dist/utils/variables.d.ts +58 -0
  60. package/dist/utils/variables.test.d.ts +1 -0
  61. package/package.json +4 -8
  62. package/dist/plugins/html.d.ts +0 -2
  63. package/dist/plugins/table.d.ts +0 -2
  64. package/dist/plugins/workflow.d.ts +0 -31
  65. package/dist/utils/table.d.ts +0 -93
  66. package/dist/utils/workflow.d.ts +0 -9
  67. /package/dist/components/{TableEditor.vue.d.ts → Components.vue.d.ts} +0 -0
  68. /package/dist/components/{Workflow.vue.d.ts → InteractionBadges.vue.d.ts} +0 -0
  69. /package/dist/utils/{smartGuides-geometry.d.ts → smartGuidesGeometry.d.ts} +0 -0
package/README.md CHANGED
@@ -18,7 +18,7 @@
18
18
  </a>
19
19
  </p>
20
20
 
21
- <p align="center">A headless infinite canvas editor framework built on WebGL rendering, supports exporting to image, video, and PPT. Only the ESM.</p>
21
+ <p align="center">An infinite canvas editor framework (Vue 3 + TypeScript) with real-time collaboration, a timeline, components and design tokens — built on WebGL rendering. Bring your own UI. ESM only.</p>
22
22
 
23
23
  <p align="center">
24
24
  <a href="https://qq15725.github.io/mce/">📚 Documentation</a>
@@ -26,6 +26,76 @@
26
26
  <a href="https://codesandbox.io/p/github/qq15725/mce/main">🎮 Try in CodeSandbox</a>
27
27
  </p>
28
28
 
29
+ ## ✨ Features
30
+
31
+ **Canvas & editing**
32
+ - Infinite canvas with pan / zoom, rulers, scrollbars, pixel grid and checkerboard
33
+ - Smart guides & snapping, alignment / distribution, z-order arrange, tidy-up
34
+ - Multi-select & marquee, transform (move / resize / rotate / flip), foreground crop
35
+ - Frames (artboards) with auto-nesting, and Flex auto-layout (drag-to-reorder)
36
+
37
+ **Content**
38
+ - Shapes, pen / freehand paths, lines & arrows
39
+ - Rich text (fragment styling, custom fonts, format painter, auto-fit strategies)
40
+ - Images (insert / upload / crop), video, tables (`@mce/table`) and charts (`@mce/chart`)
41
+
42
+ **Motion**
43
+ - Timeline with frame-based playback
44
+ - Keyframe animation with reusable easing (presets + custom cubic-bezier)
45
+ - Export to GIF, MP4 and Lottie
46
+
47
+ **Collaboration & history**
48
+ - CRDT document model ([Yjs](https://github.com/yjs/yjs)) in the core — undo / redo and offline persistence (IndexedDB) build on it
49
+ - Real-time multi-user editing + awareness (remote cursors / selection / avatars) via `@mce/collaboration` (WebSocket / pluggable transport)
50
+ - Comments anchored to elements (pins follow on move / scale / rotate, threads with replies & resolve) via `@mce/comments`
51
+
52
+ **Design systems**
53
+ - Components / symbols / instances with per-instance overrides and master propagation
54
+ - Design tokens / variables (collections + modes) for theming and responsive values
55
+
56
+ **AI** (`@mce/ai`)
57
+ - A typed AI canvas action schema — drive edits from an LLM over the existing command & undo stack (model wiring left to the consumer)
58
+
59
+ **Workflow** (`@mce/workflow`)
60
+ - A node-graph editing mode: connectable nodes with input / output ports and curved connections
61
+
62
+ **Extensible**
63
+ - ~40 built-in plugins; a plugin can contribute commands, tools, hotkeys, exporters, loaders, components and events
64
+ - Element types & modes are decoupled via extension points (selection redirect, resize override, enter handler, editing state, toolbelt item, icon, mode, statusbar item) — see `mixins/extensions.ts`
65
+ - Unified command system, hotkeys, and i18n
66
+
67
+ ## 📤 Import & export
68
+
69
+ - **Export**: `PNG` · `JPEG` · `WebP` · `SVG` · `PDF` · `GIF` · `MP4` · `Lottie` · `PPTX` / `XLSX` / `DOCX` · `JSON`
70
+ - **Import**: `PPTX` / `XLSX` / `DOCX` · `PSD` · `SVG` · `HTML` · images · `JSON`
71
+
72
+ These ship as optional plugins; their heavy encoders / parsers are lazy-loaded on first use:
73
+
74
+ | Package | Adds |
75
+ | --- | --- |
76
+ | `@mce/gif` | GIF export |
77
+ | `@mce/mp4` | MP4 export |
78
+ | `@mce/pdf` | PDF export |
79
+ | `@mce/svg` | SVG import & export |
80
+ | `@mce/openxml` | PPTX / XLSX / DOCX import & export |
81
+ | `@mce/psd` | PSD import (Photoshop layers → elements) |
82
+ | `@mce/html` | HTML import |
83
+
84
+ (`PNG` / `JPEG` / `WebP` / `JSON` / `Lottie` export are built in.)
85
+
86
+ ## 🔌 Feature plugins
87
+
88
+ Specialized features also ship as optional packages, registered the same way (`plugins: [...]`):
89
+
90
+ | Package | Adds |
91
+ | --- | --- |
92
+ | `@mce/table` | Table element + in-canvas table editor |
93
+ | `@mce/chart` | Chart elements (bar / line / pie / …) |
94
+ | `@mce/ai` | Typed AI canvas action schema (`applyAiActions`) |
95
+ | `@mce/workflow` | Node-graph editing mode |
96
+ | `@mce/collaboration` | Real-time collaboration: transport providers + presence (cursors / selection / avatars) |
97
+ | `@mce/comments` | Comments: comment tool + pins anchored to elements + threads (stored on `element.comments`) |
98
+
29
99
  ## 📦 Install
30
100
 
31
101
  ```shell
@@ -38,22 +108,38 @@ npm i mce
38
108
  <script setup lang="ts">
39
109
  import { Editor, EditorLayout, EditorLayoutItem } from 'mce'
40
110
  import 'mce/styles'
111
+ import ai from '@mce/ai'
112
+ import chart from '@mce/chart'
113
+ import collaboration from '@mce/collaboration'
114
+ import comments from '@mce/comments'
41
115
  import gif from '@mce/gif'
42
116
  import mp4 from '@mce/mp4'
43
117
  import openxml from '@mce/openxml'
44
118
  import pdf from '@mce/pdf'
45
119
  import svg from '@mce/svg'
46
- import gifWorkerUrl from 'modern-gif/worker?url'
120
+ import table from '@mce/table'
121
+ import workflow from '@mce/workflow'
47
122
 
48
123
  const editor = new Editor({
49
124
  plugins: [
125
+ // export / import formats
50
126
  gif(),
51
127
  mp4(),
52
128
  svg(),
53
129
  pdf(),
54
130
  openxml(),
131
+ // feature plugins (all optional)
132
+ table(),
133
+ chart(),
134
+ ai(),
135
+ workflow(),
136
+ collaboration(), // registers the collaboration + presence plugins
137
+ comments(),
55
138
  ],
56
- gifWorkerUrl,
139
+ // @mce/gif bundles its encoding worker by default. To self-host it
140
+ // (e.g. under a strict CSP), pass `gifWorkerUrl` explicitly:
141
+ // import gifWorkerUrl from 'modern-gif/worker?url'
142
+ // ...new Editor({ gifWorkerUrl })
57
143
  locale: { locale: 'en' },
58
144
  viewport: {
59
145
  camera: { enabled: true },
@@ -132,7 +218,7 @@ npm i mce
132
218
  </template>
133
219
  ```
134
220
 
135
- slot sub component
221
+ Slot sub component — read editor state via `useEditor()`:
136
222
 
137
223
  ```vue
138
224
  <script setup lang="ts">
@@ -147,3 +233,215 @@ slot sub component
147
233
  </template>
148
234
  ```
149
235
 
236
+ ## 🧩 Commands
237
+
238
+ Everything the editor does is a command — call `editor.exec(name, ...args)`. A few examples:
239
+
240
+ ```ts
241
+ // Arrange & layout
242
+ editor.exec('alignHorizontalCenter')
243
+ editor.exec('distributeHorizontalSpacing')
244
+ editor.exec('tidyUp')
245
+
246
+ // Design tokens / variables
247
+ const collection = editor.exec('createVariableCollection', 'Theme', 'Light')
248
+ const dark = editor.exec('addVariableMode', collection, 'Dark')
249
+ const brand = editor.exec('addVariable', collection, { name: 'brand', type: 'color', value: '#ff0000' })
250
+ editor.exec('setVariableValue', brand, dark, '#0000ff')
251
+ editor.exec('bindVariable', 'fill.color', brand) // bind selected element's fill
252
+ editor.exec('setActiveVariableMode', collection, dark) // theme switch → canvas recolors
253
+
254
+ // Components / instances
255
+ const component = editor.exec('createComponent') // from selection
256
+ editor.exec('createInstance', component, { position: { x: 200, y: 200 } })
257
+
258
+ // Keyframe animation → Lottie
259
+ editor.exec('addAnimationKeyframe', 0, { left: 0, opacity: 0 })
260
+ editor.exec('addAnimationKeyframe', 1, { left: 300, opacity: 1 })
261
+ const lottie = editor.exec('exportLottie')
262
+
263
+ // AI canvas actions (validated, applied in one undo step) — needs @mce/ai
264
+ editor.exec('applyAiActions', [
265
+ { type: 'createText', text: 'Hello', x: 40, y: 40 },
266
+ { type: 'align', direction: 'left' },
267
+ ])
268
+ ```
269
+
270
+ ## 🤖 AI
271
+
272
+ `@mce/ai` ships a **typed action layer**, not a model. It gives you a schema to
273
+ put in your prompt and a safe `applyAiActions` that validates / sanitizes a batch
274
+ of actions and applies them in a single undo step — wiring the LLM call is up to you.
275
+
276
+ **1. Register the plugin**
277
+
278
+ ```ts
279
+ import ai from '@mce/ai'
280
+ new Editor({ plugins: [ai()] })
281
+ ```
282
+
283
+ **2. Build the prompt — `getAiPrompt` assembles schema + node ids + request for you**
284
+
285
+ ```ts
286
+ const prompt = editor.exec('getAiPrompt', userInput)
287
+ // Already includes the action schema and every existing node id (so the model can
288
+ // reference current elements). Need the raw schema instead? editor.exec('getAiActionSchema').
289
+ ```
290
+
291
+ **3. Call your own model, then apply the returned actions**
292
+
293
+ ```ts
294
+ // ← your LLM / SDK; @mce/ai is model-agnostic
295
+ const text = await callYourLLM(prompt)
296
+ const actions = JSON.parse(text) // e.g. [{ type: 'createText', text: 'Hi', x: 40, y: 40 }]
297
+
298
+ const { created, errors } = editor.exec('applyAiActions', actions)
299
+ // created: ids of newly created elements
300
+ // errors: rejected actions + reasons (invalid fields / unknown node ids) — skipped, not applied
301
+ ```
302
+
303
+ - **Model-agnostic** — any LLM / SDK works as long as it emits schema-conforming JSON.
304
+ - **Safe** — invalid actions (bad fields, unknown ids) are rejected into `errors`, never written to the document.
305
+ - **One undo step** — the whole batch is a single undo entry.
306
+ - **Node ids included** — `getAiPrompt` embeds all current node ids, so actions referencing existing elements (`setStyle` / `move` / `delete` / `select` / `duplicate` / `align(ids)`) validate; building the prompt yourself means adding them manually.
307
+
308
+ ## 🤝 Collaboration
309
+
310
+ The CRDT document model (Yjs) lives in the **core** — undo / redo and offline
311
+ persistence (IndexedDB) build on it. The **network transport and presence**
312
+ (awareness) layer is the optional `@mce/collaboration` package.
313
+
314
+ **1. Register the plugin**
315
+
316
+ ```ts
317
+ import collaboration from '@mce/collaboration'
318
+
319
+ const editor = new Editor({
320
+ plugins: [
321
+ collaboration(), // registers the collaboration + presence plugins
322
+ ],
323
+ })
324
+ ```
325
+
326
+ **2. Identify the local user (presence)**
327
+
328
+ ```ts
329
+ editor.presence.setUser({
330
+ id: 'u-1', // optional, for dedupe / avatars
331
+ name: 'Alice',
332
+ color: '#E64980',
333
+ avatar: 'https://…', // optional
334
+ })
335
+ ```
336
+
337
+ **3. Connect to a room**
338
+
339
+ ```ts
340
+ // Built-in WebSocket transport (y-websocket compatible server)
341
+ editor.collaboration.connect({
342
+ url: 'wss://your-server',
343
+ room: 'doc-1', // defaults to the current document id
344
+ })
345
+
346
+ // …or a custom / pluggable transport (WebRTC, BroadcastChannel, …)
347
+ import { AbstractProvider } from '@mce/collaboration'
348
+ editor.collaboration.connect({
349
+ provider: doc => new MyProvider(doc), // doc is the document's YDoc
350
+ })
351
+
352
+ editor.collaboration.disconnect() // end the session
353
+ ```
354
+
355
+ You can also auto-connect on startup via the editor option:
356
+
357
+ ```ts
358
+ new Editor({ collaboration: { url: 'wss://your-server', room: 'doc-1' } })
359
+ ```
360
+
361
+ **4. Reactive status & remote peers**
362
+
363
+ ```ts
364
+ editor.collaboration.connected // Ref<boolean> — transport connected
365
+ editor.collaboration.synced // Ref<boolean> — first full sync done
366
+ editor.collaboration.active // Ref<boolean> — a session is active
367
+ editor.presence.peers // Ref<Peer[]> — remote users (cursor / selection / user)
368
+ editor.presence.localUser // Ref<PresenceUser>
369
+ ```
370
+
371
+ Remote cursors, selection boxes and a connection/avatars status-bar item render
372
+ automatically once a session is active. Document switching rebuilds the provider
373
+ on the new document's `YDoc`; the transport is bound per-document.
374
+
375
+ > Comments (`@mce/comments`) live on `element.comments` and are part of the
376
+ > document model, so they sync over the same session automatically.
377
+
378
+ ## 📚 Packages
379
+
380
+ Every package ships as ESM and registers the same way (`new Editor({ plugins: [pkg()] })`).
381
+ The default export of each `@mce/*` package is its plugin function; commands it adds are
382
+ called via `editor.exec(name, …)` rather than imported.
383
+
384
+ | Package | Description | Key exports |
385
+ | --- | --- | --- |
386
+ | `mce` | Headless infinite-canvas editor core (WebGL; export to image / video / PPT). | `Editor`, `EditorLayout`, `EditorLayoutItem`, `EditorLayers`, `createShapeElement` / `createTextElement` / … factories, `useEditor` |
387
+ | `@mce/ai` | LLM-driven, typed canvas actions (`createText` / `createShape` / `setStyle` / `move` / `select` / `delete` / `duplicate` / `align`) applied in one undo step with automatic validation. | `plugin` (default); `validateAiActions`, `AI_ACTION_SCHEMA` (commands: `applyAiActions`, `getAiActionSchema`, `getAiPrompt`) |
388
+ | `@mce/bigesj` | Bigesj design-doc integration: font preloading, clipboard paste detection, and PPTX / XLSX / DOCX loading. | `plugin(options)` (default); `useFonts`, `bigeLoader`, `bidTidLoader`, `clipboardLoader` |
389
+ | `@mce/chart` | Bar / line / pie chart elements with a built-in data editor and toolbelt entry. | `plugin` (default); `createChartElement(type, options)` |
390
+ | `@mce/collaboration` | Real-time multi-user editing (Yjs CRDT) over a pluggable provider (built-in WebSocket, y-websocket compatible; swap for WebRTC / BroadcastChannel) plus presence (remote cursors / selection / avatars). | `plugin` (default, registers collaboration + presence); `collaborationPlugin`, `presencePlugin`, `AbstractProvider`, `WebsocketProvider` |
391
+ | `@mce/comments` | Anchored comments: pins anchored to elements that follow on move / scale / rotate, with thread replies / resolve / reopen / delete. | `plugin` (default); `useComments`, `createCommentsStore` |
392
+ | `@mce/gaoding` | Gaoding design-doc clipboard-paste support. | `plugin` (default); `clipboardLoader` |
393
+ | `@mce/gif` | GIF export (frame-by-frame render from timeline keyframes; `modern-gif` lazy-loaded). | `plugin` (default) |
394
+ | `@mce/html` | HTML file / MIME import — DOM converted into canvas elements. | `plugin` (default) |
395
+ | `@mce/mp4` | MP4 export (adaptive bitrate, 720p–2160p, 30fps; `modern-mp4` lazy-loaded). | `plugin` (default) |
396
+ | `@mce/openxml` | PPTX / XLSX / DOCX two-way import & export with smart layer & font mapping (`modern-openxml`). | `plugin` (default) |
397
+ | `@mce/pdf` | PDF export with page metadata (size / margins; `modern-pdf` lazy-loaded). | `plugin` (default) |
398
+ | `@mce/psd` | PSD import — Photoshop layers expanded into elements, layer canvases auto-uploaded as image assets. | `plugin` (default); `psdToFrame` |
399
+ | `@mce/svg` | SVG import & export (Path2D path sets + viewBox, multi-MIME copy). | `plugin` (default) |
400
+ | `@mce/table` | Table element + in-canvas editor (add / remove rows & columns, merge / split cells, style editing, zoom-aware grid, toolbelt entry). | `plugin` (default); `createTableElement(rows, cols, options)` |
401
+ | `@mce/workflow` | Node-graph editing mode (connectable nodes, templated node types, preset text / image / video generation nodes). | `plugin` (default); `getWorkflowPorts`, `toConnectionPoints`, `INPUT_PORT`, `OUTPUT_PORT` (commands: `addWorkflowNode`, `addWorkflowConnection`) |
402
+
403
+ ## 🏗️ Architecture
404
+
405
+ ```
406
+ packages/
407
+ mce/ # core editor library (npm: mce)
408
+ gif/ # GIF export (@mce/gif)
409
+ mp4/ # MP4 export (@mce/mp4)
410
+ pdf/ # PDF export (@mce/pdf)
411
+ svg/ # SVG import & export (@mce/svg)
412
+ openxml/ # PPTX/XLSX/DOCX import & export (@mce/openxml)
413
+ psd/ # PSD import (@mce/psd)
414
+ html/ # HTML import (@mce/html)
415
+ table/ # table element + editor (@mce/table)
416
+ chart/ # chart elements (@mce/chart)
417
+ ai/ # AI canvas actions (@mce/ai)
418
+ workflow/ # node-graph mode (@mce/workflow)
419
+ collaboration/ # real-time collaboration (@mce/collaboration)
420
+ comments/ # comments (@mce/comments)
421
+ bigesj/ # Bigesj design-doc integration (@mce/bigesj)
422
+ gaoding/ # Gaoding clipboard paste (@mce/gaoding)
423
+ playground/ # demo & test app
424
+ ```
425
+
426
+ The `Editor` is composed from layered mixins and a plugin system. Rendering is powered by
427
+ [`modern-canvas`](https://www.npmjs.com/package/modern-canvas) (WebGL), with text / fonts /
428
+ document model from `modern-text`, `modern-font` and `modern-idoc`.
429
+
430
+ The core stays lean: element types and editing modes are decoupled through extension points
431
+ (`mixins/extensions.ts`), so feature packages register their behavior instead of the core
432
+ hard-coding it. The CRDT document model (`yjs` + `y-protocols`) lives in the core; the
433
+ real-time transport and presence layer is the optional `@mce/collaboration` package.
434
+
435
+ ## 🛠️ Development
436
+
437
+ ```shell
438
+ pnpm dev # start the playground
439
+ pnpm build # build core + all plugins
440
+ pnpm test # run tests
441
+ pnpm -F mce typecheck
442
+ pnpm lint
443
+ ```
444
+
445
+ ## 📄 License
446
+
447
+ [MIT](./LICENSE)
@@ -0,0 +1,6 @@
1
+ type __VLS_Props = {
2
+ slots: Record<string, any>;
3
+ };
4
+ declare const __VLS_export: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
5
+ declare const _default: typeof __VLS_export;
6
+ export default _default;
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -30,7 +30,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
30
30
  readonly lockAspectRatioStrategy?: "all" | "diagonal" | undefined;
31
31
  readonly handleStyle?: "8-points" | "4-points" | undefined;
32
32
  readonly handleShape?: "rect" | "circle" | undefined;
33
- readonly handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[] | undefined;
33
+ readonly handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[] | undefined;
34
34
  readonly scale?: [number, number] | undefined;
35
35
  readonly offset?: [number, number] | undefined;
36
36
  readonly initialSize?: boolean | undefined;
@@ -69,7 +69,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
69
69
  lockAspectRatioStrategy?: "all" | "diagonal";
70
70
  handleStyle?: "8-points" | "4-points";
71
71
  handleShape?: "rect" | "circle";
72
- handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
72
+ handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
73
73
  scale?: [number, number];
74
74
  offset?: [number, number];
75
75
  initialSize?: boolean;
@@ -85,7 +85,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
85
85
  "onUpdate:modelValue"?: ((value: Partial<Mce.TransformValue> | undefined) => any) | undefined;
86
86
  }>, {
87
87
  start: (event?: MouseEvent, index?: number) => boolean;
88
- activeHandle: import("vue").Ref<("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined, ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined>;
88
+ activeHandle: import("vue").Ref<("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined, ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined>;
89
89
  transforming: import("vue").Ref<boolean, boolean>;
90
90
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
91
91
  move: (context: Mce.TransformContext) => any;
@@ -97,14 +97,14 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
97
97
  scale: [number, number];
98
98
  threshold: number;
99
99
  ui: boolean;
100
+ resizeStrategy: "free" | "lockAspectRatio";
100
101
  movable: boolean;
101
102
  rotatable: boolean;
102
103
  resizable: boolean;
103
- resizeStrategy: "free" | "lockAspectRatio";
104
104
  tag: string | any;
105
105
  lockAspectRatioStrategy: "all" | "diagonal";
106
106
  handleShape: "rect" | "circle";
107
- handles: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
107
+ handles: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
108
108
  }, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & {
109
109
  beforeCreate?: (() => void) | (() => void)[];
110
110
  created?: (() => void) | (() => void)[];
@@ -130,14 +130,14 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
130
130
  scale: [number, number];
131
131
  threshold: number;
132
132
  ui: boolean;
133
+ resizeStrategy: "free" | "lockAspectRatio";
133
134
  movable: boolean;
134
135
  rotatable: boolean;
135
136
  resizable: boolean;
136
- resizeStrategy: "free" | "lockAspectRatio";
137
137
  tag: string | any;
138
138
  lockAspectRatioStrategy: "all" | "diagonal";
139
139
  handleShape: "rect" | "circle";
140
- handles: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
140
+ handles: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
141
141
  }> & Omit<Readonly<{
142
142
  ui?: boolean;
143
143
  tag?: string | any;
@@ -152,7 +152,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
152
152
  lockAspectRatioStrategy?: "all" | "diagonal";
153
153
  handleStyle?: "8-points" | "4-points";
154
154
  handleShape?: "rect" | "circle";
155
- handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
155
+ handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
156
156
  scale?: [number, number];
157
157
  offset?: [number, number];
158
158
  initialSize?: boolean;
@@ -166,9 +166,9 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
166
166
  onStart?: ((context: Mce.TransformContext) => any) | undefined;
167
167
  onEnd?: ((context: Mce.TransformContext) => any) | undefined;
168
168
  "onUpdate:modelValue"?: ((value: Partial<Mce.TransformValue> | undefined) => any) | undefined;
169
- }>, "transforming" | "start" | "activeHandle" | ("offset" | "scale" | "threshold" | "ui" | "movable" | "rotatable" | "resizable" | "resizeStrategy" | "tag" | "lockAspectRatioStrategy" | "handleShape" | "handles")> & {
169
+ }>, "transforming" | "start" | "activeHandle" | ("offset" | "scale" | "threshold" | "ui" | "resizeStrategy" | "movable" | "rotatable" | "resizable" | "tag" | "lockAspectRatioStrategy" | "handleShape" | "handles")> & {
170
170
  start: (event?: MouseEvent, index?: number) => boolean;
171
- activeHandle: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined;
171
+ activeHandle: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined;
172
172
  transforming: boolean;
173
173
  } & {} & import("vue").ComponentCustomProperties & {} & {
174
174
  $slots: {
@@ -215,7 +215,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
215
215
  readonly lockAspectRatioStrategy?: "all" | "diagonal" | undefined;
216
216
  readonly handleStyle?: "8-points" | "4-points" | undefined;
217
217
  readonly handleShape?: "rect" | "circle" | undefined;
218
- readonly handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[] | undefined;
218
+ readonly handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[] | undefined;
219
219
  readonly scale?: [number, number] | undefined;
220
220
  readonly offset?: [number, number] | undefined;
221
221
  readonly initialSize?: boolean | undefined;
@@ -254,7 +254,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
254
254
  lockAspectRatioStrategy?: "all" | "diagonal";
255
255
  handleStyle?: "8-points" | "4-points";
256
256
  handleShape?: "rect" | "circle";
257
- handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
257
+ handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
258
258
  scale?: [number, number];
259
259
  offset?: [number, number];
260
260
  initialSize?: boolean;
@@ -270,7 +270,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
270
270
  "onUpdate:modelValue"?: ((value: Partial<Mce.TransformValue> | undefined) => any) | undefined;
271
271
  }>, {
272
272
  start: (event?: MouseEvent, index?: number) => boolean;
273
- activeHandle: import("vue").Ref<("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined, ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined>;
273
+ activeHandle: import("vue").Ref<("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined, ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined>;
274
274
  transforming: import("vue").Ref<boolean, boolean>;
275
275
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
276
276
  move: (context: Mce.TransformContext) => any;
@@ -282,14 +282,14 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
282
282
  scale: [number, number];
283
283
  threshold: number;
284
284
  ui: boolean;
285
+ resizeStrategy: "free" | "lockAspectRatio";
285
286
  movable: boolean;
286
287
  rotatable: boolean;
287
288
  resizable: boolean;
288
- resizeStrategy: "free" | "lockAspectRatio";
289
289
  tag: string | any;
290
290
  lockAspectRatioStrategy: "all" | "diagonal";
291
291
  handleShape: "rect" | "circle";
292
- handles: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
292
+ handles: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
293
293
  }, {}, string, {}, import("vue").GlobalComponents, import("vue").GlobalDirectives, string, import("vue").ComponentProvideOptions> & {
294
294
  beforeCreate?: (() => void) | (() => void)[];
295
295
  created?: (() => void) | (() => void)[];
@@ -315,14 +315,14 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
315
315
  scale: [number, number];
316
316
  threshold: number;
317
317
  ui: boolean;
318
+ resizeStrategy: "free" | "lockAspectRatio";
318
319
  movable: boolean;
319
320
  rotatable: boolean;
320
321
  resizable: boolean;
321
- resizeStrategy: "free" | "lockAspectRatio";
322
322
  tag: string | any;
323
323
  lockAspectRatioStrategy: "all" | "diagonal";
324
324
  handleShape: "rect" | "circle";
325
- handles: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
325
+ handles: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
326
326
  }> & Omit<Readonly<{
327
327
  ui?: boolean;
328
328
  tag?: string | any;
@@ -337,7 +337,7 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
337
337
  lockAspectRatioStrategy?: "all" | "diagonal";
338
338
  handleStyle?: "8-points" | "4-points";
339
339
  handleShape?: "rect" | "circle";
340
- handles?: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
340
+ handles?: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl")[];
341
341
  scale?: [number, number];
342
342
  offset?: [number, number];
343
343
  initialSize?: boolean;
@@ -351,9 +351,9 @@ declare const __VLS_base: import("vue").DefineComponent<{}, {
351
351
  onStart?: ((context: Mce.TransformContext) => any) | undefined;
352
352
  onEnd?: ((context: Mce.TransformContext) => any) | undefined;
353
353
  "onUpdate:modelValue"?: ((value: Partial<Mce.TransformValue> | undefined) => any) | undefined;
354
- }>, "transforming" | "start" | "activeHandle" | ("offset" | "scale" | "threshold" | "ui" | "movable" | "rotatable" | "resizable" | "resizeStrategy" | "tag" | "lockAspectRatioStrategy" | "handleShape" | "handles")> & {
354
+ }>, "transforming" | "start" | "activeHandle" | ("offset" | "scale" | "threshold" | "ui" | "resizeStrategy" | "movable" | "rotatable" | "resizable" | "tag" | "lockAspectRatioStrategy" | "handleShape" | "handles")> & {
355
355
  start: (event?: MouseEvent, index?: number) => boolean;
356
- activeHandle: ("move" | "resize-b" | "resize-r" | "resize-l" | "resize-t" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined;
356
+ activeHandle: ("move" | "resize-b" | "resize-t" | "resize-r" | "resize-l" | "resize-br" | "resize-tr" | "resize-tl" | "resize-bl" | "rotate-br" | "rotate-tr" | "rotate-tl" | "rotate-bl" | "round-br" | "round-tr" | "round-tl" | "round-bl") | undefined;
357
357
  transforming: boolean;
358
358
  } & {} & import("vue").ComponentCustomProperties & {} & {
359
359
  $slots: {
@@ -1,6 +1,10 @@
1
1
  import type { ImageFillCropRect } from 'modern-idoc';
2
2
  /**
3
- * TODO 撤回无法重渲
3
+ * 撤回 / 重做修复说明:
4
+ * 下方 `viewEffect` watch 在 `view` 变化时反向补偿 `cropRect` 以保持 source 视觉不变。
5
+ * 但撤回/重做会由 UndoManager 同时回退 `view` 与 `cropRect`,此时不应再据旧 `view` 重算
6
+ * `cropRect`(会把已回退的 `cropRect` 覆盖掉)。因此 viewEffect 在 `editor.isUndoRedoing`
7
+ * 期间跳过补偿,仅对用户拖拽 / 改宽高比产生的 view 变化补偿。
4
8
  */
5
9
  type View = Record<'left' | 'top' | 'width' | 'height' | 'scaleX' | 'scaleY', number>;
6
10
  type __VLS_Props = {