@web-ppt/editor 0.5.0-beta.1 → 0.5.0-beta.7
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.
- package/CHANGELOG.md +188 -0
- package/README.md +97 -6
- package/dist/accessibility.js +60 -0
- package/dist/adjustments/index.d.ts +2 -0
- package/dist/adjustments/preset-adjustment-editor.d.ts +4 -0
- package/dist/adjustments/types.d.ts +22 -0
- package/dist/adjustments.js +300 -0
- package/dist/canvas-accessibility.d.ts +6 -0
- package/dist/chart/index.d.ts +2 -0
- package/dist/chart-shared/index.d.ts +2 -0
- package/dist/chart-shared.js +7 -0
- package/dist/chart.js +6 -0
- package/dist/common-object-slide-commands.d.ts +20 -0
- package/dist/design/index.d.ts +3 -0
- package/dist/design-editor-types.d.ts +15 -0
- package/dist/design-editor.d.ts +3 -0
- package/dist/design.js +108 -0
- package/dist/dom-identity.d.ts +4 -1
- package/dist/dom-patch.d.ts +1 -1
- package/dist/edit-context/geometry.d.ts +8 -0
- package/dist/edit-context/index.d.ts +8 -0
- package/dist/edit-context/native.d.ts +33 -0
- package/dist/edit-context.js +333 -0
- package/dist/editor-keyboard.d.ts +4 -1
- package/dist/editor.js +1 -6332
- package/dist/element-clipboard.d.ts +4 -2
- package/dist/framework-adapter-types.d.ts +17 -2
- package/dist/image-insertion.d.ts +4 -2
- package/dist/index.d.ts +6 -5
- package/dist/keyboard-context.d.ts +1 -0
- package/dist/keyboard-document.d.ts +8 -0
- package/dist/keyboard-group.d.ts +7 -0
- package/dist/media/index.d.ts +1 -0
- package/dist/media.js +1 -0
- package/dist/rotation-geometry.d.ts +4 -1
- package/dist/selection-all.d.ts +3 -0
- package/dist/selection-hit.d.ts +6 -0
- package/dist/selection-pane-types.d.ts +1 -0
- package/dist/session-state.d.ts +5 -1
- package/dist/session.d.ts +17 -1
- package/dist/slide-dom-renderer.d.ts +1 -0
- package/dist/slide-editor-commands.d.ts +14 -2
- package/dist/slide-editor-events.d.ts +1 -0
- package/dist/slide-editor-types.d.ts +37 -2
- package/dist/slide-pointer-controller.d.ts +3 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates.js +5 -0
- package/dist/text-edit-commit.d.ts +8 -0
- package/dist/text-editor-types.d.ts +2 -0
- package/dist/text-editor.d.ts +8 -3
- package/dist/text-font-step.d.ts +5 -0
- package/dist/text-keyboard.d.ts +28 -0
- package/dist/text-list-level.d.ts +4 -0
- package/dist/touch-gesture.d.ts +42 -0
- package/dist/transform-frame.d.ts +11 -6
- package/dist/vertex/index.d.ts +2 -0
- package/dist/vertex/types.d.ts +21 -0
- package/dist/vertex/vertex-editor.d.ts +4 -0
- package/dist/vertex.js +338 -0
- package/package.json +42 -6
|
@@ -0,0 +1,300 @@
|
|
|
1
|
+
import { resolvePresetAdjustmentHandles as m, dragPresetAdjustmentHandle as g } from "@web-ppt/core/geometry/handles";
|
|
2
|
+
import { queryElementPresetGeometry as p, slideOfElement as f, elementFrameToSlidePoint as v, screenToSlidePoint as w, slideToElementFramePoint as E } from "@web-ppt/edit-core";
|
|
3
|
+
const A = 3, d = (c) => c.pointerId ?? 0;
|
|
4
|
+
class b {
|
|
5
|
+
constructor(t) {
|
|
6
|
+
this.active = null, this.root = t;
|
|
7
|
+
}
|
|
8
|
+
get isActive() {
|
|
9
|
+
return this.active !== null;
|
|
10
|
+
}
|
|
11
|
+
begin(t, e) {
|
|
12
|
+
var s, n;
|
|
13
|
+
this.cancel();
|
|
14
|
+
const r = { x: t.clientX, y: t.clientY };
|
|
15
|
+
this.active = {
|
|
16
|
+
pointerId: d(t),
|
|
17
|
+
startScreen: r,
|
|
18
|
+
snapshot: {
|
|
19
|
+
screen: r,
|
|
20
|
+
altKey: t.altKey,
|
|
21
|
+
ctrlKey: t.ctrlKey,
|
|
22
|
+
metaKey: t.metaKey,
|
|
23
|
+
shiftKey: t.shiftKey
|
|
24
|
+
},
|
|
25
|
+
gesture: e,
|
|
26
|
+
started: !1,
|
|
27
|
+
frame: null,
|
|
28
|
+
cursor: this.root.style.cursor
|
|
29
|
+
};
|
|
30
|
+
try {
|
|
31
|
+
(n = (s = this.root).setPointerCapture) == null || n.call(s, d(t));
|
|
32
|
+
} catch {
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
move(t) {
|
|
36
|
+
var r, s;
|
|
37
|
+
const e = this.active;
|
|
38
|
+
if (!(!e || d(t) !== e.pointerId)) {
|
|
39
|
+
this.updateSnapshot(e, t);
|
|
40
|
+
try {
|
|
41
|
+
(s = (r = e.gesture).observePointer) == null || s.call(r, e.snapshot);
|
|
42
|
+
} catch (n) {
|
|
43
|
+
throw this.clear(e), n;
|
|
44
|
+
}
|
|
45
|
+
if (!e.started) {
|
|
46
|
+
if (Math.hypot(
|
|
47
|
+
e.snapshot.screen.x - e.startScreen.x,
|
|
48
|
+
e.snapshot.screen.y - e.startScreen.y
|
|
49
|
+
) < A) return;
|
|
50
|
+
e.started = !0;
|
|
51
|
+
try {
|
|
52
|
+
e.gesture.start();
|
|
53
|
+
} catch (i) {
|
|
54
|
+
throw this.clear(e), i;
|
|
55
|
+
}
|
|
56
|
+
this.root.style.cursor = e.gesture.cursor, this.root.dataset[e.gesture.dataset.name] = e.gesture.dataset.value;
|
|
57
|
+
}
|
|
58
|
+
t.preventDefault(), this.scheduleFrame(e);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
finish(t) {
|
|
62
|
+
var s, n;
|
|
63
|
+
const e = this.active;
|
|
64
|
+
if (!e || d(t) !== e.pointerId) return "ignored";
|
|
65
|
+
this.updateSnapshot(e, t);
|
|
66
|
+
let r;
|
|
67
|
+
try {
|
|
68
|
+
(n = (s = e.gesture).observePointer) == null || n.call(s, e.snapshot), r = e.started ? e.gesture.finish(e.snapshot) : null;
|
|
69
|
+
} catch (i) {
|
|
70
|
+
throw this.clear(e), i;
|
|
71
|
+
}
|
|
72
|
+
return this.clear(e), r == null || r(), r && t.preventDefault(), e.started ? "gesture" : "click";
|
|
73
|
+
}
|
|
74
|
+
/** 键盘确认使用最后一次指针快照;先清理 capture/rAF,再执行提交,避免订阅回调重入活动手势。 */
|
|
75
|
+
commit() {
|
|
76
|
+
const t = this.active;
|
|
77
|
+
if (!t) return !1;
|
|
78
|
+
let e = null;
|
|
79
|
+
try {
|
|
80
|
+
e = t.started ? t.gesture.finish(t.snapshot) : null;
|
|
81
|
+
} catch (r) {
|
|
82
|
+
throw this.clear(t), r;
|
|
83
|
+
}
|
|
84
|
+
return this.clear(t), e == null || e(), t.started;
|
|
85
|
+
}
|
|
86
|
+
modifier(t) {
|
|
87
|
+
const e = this.active;
|
|
88
|
+
return !e || !["Shift", "Alt", "Control", "Meta"].includes(t.key) ? !1 : (e.snapshot = {
|
|
89
|
+
...e.snapshot,
|
|
90
|
+
altKey: t.altKey,
|
|
91
|
+
ctrlKey: t.ctrlKey,
|
|
92
|
+
metaKey: t.metaKey,
|
|
93
|
+
shiftKey: t.shiftKey
|
|
94
|
+
}, e.started && this.scheduleFrame(e), !0);
|
|
95
|
+
}
|
|
96
|
+
cancel() {
|
|
97
|
+
this.active && this.clear(this.active);
|
|
98
|
+
}
|
|
99
|
+
cancelPointer(t) {
|
|
100
|
+
this.active && d(t) === this.active.pointerId && this.clear(this.active);
|
|
101
|
+
}
|
|
102
|
+
updateSnapshot(t, e) {
|
|
103
|
+
t.snapshot = {
|
|
104
|
+
screen: { x: e.clientX, y: e.clientY },
|
|
105
|
+
altKey: e.altKey,
|
|
106
|
+
ctrlKey: e.ctrlKey,
|
|
107
|
+
metaKey: e.metaKey,
|
|
108
|
+
shiftKey: e.shiftKey
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
scheduleFrame(t) {
|
|
112
|
+
if (t.frame !== null) return;
|
|
113
|
+
const e = this.root.ownerDocument.defaultView;
|
|
114
|
+
if (!(e != null && e.requestAnimationFrame)) {
|
|
115
|
+
try {
|
|
116
|
+
t.gesture.frame(t.snapshot);
|
|
117
|
+
} catch (r) {
|
|
118
|
+
throw this.clear(t), r;
|
|
119
|
+
}
|
|
120
|
+
return;
|
|
121
|
+
}
|
|
122
|
+
t.frame = e.requestAnimationFrame(() => {
|
|
123
|
+
if (t.frame = null, this.active === t)
|
|
124
|
+
try {
|
|
125
|
+
t.gesture.frame(t.snapshot);
|
|
126
|
+
} catch (r) {
|
|
127
|
+
throw this.clear(t), r;
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
clear(t) {
|
|
132
|
+
var r, s;
|
|
133
|
+
this.active = null;
|
|
134
|
+
const e = this.root.ownerDocument.defaultView;
|
|
135
|
+
t.frame !== null && (e != null && e.cancelAnimationFrame) && e.cancelAnimationFrame(t.frame);
|
|
136
|
+
try {
|
|
137
|
+
t.started && t.gesture.clear();
|
|
138
|
+
} finally {
|
|
139
|
+
this.root.style.cursor = t.cursor, delete this.root.dataset[t.gesture.dataset.name];
|
|
140
|
+
try {
|
|
141
|
+
(s = (r = this.root).hasPointerCapture) != null && s.call(r, t.pointerId) && this.root.releasePointerCapture(t.pointerId);
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const I = "http://www.w3.org/2000/svg";
|
|
148
|
+
function y(c, t) {
|
|
149
|
+
return c.createElementNS(I, t);
|
|
150
|
+
}
|
|
151
|
+
class P {
|
|
152
|
+
constructor(t, e, r) {
|
|
153
|
+
var a;
|
|
154
|
+
if (this.session = t, this.view = e, this.options = r, this.activeId = null, this.preview = null, this.isDestroyed = !1, this.pointerDown = (o) => {
|
|
155
|
+
const h = o.target instanceof Element ? o.target.closest("[data-ppt-preset-handle]") : null;
|
|
156
|
+
if (!(!h || o.button !== 0 || o.isPrimary === !1))
|
|
157
|
+
try {
|
|
158
|
+
const u = this.geometry;
|
|
159
|
+
if (!u) return;
|
|
160
|
+
this.lifecycle.begin(o, this.gesture(Number(h.dataset.pptPresetHandle), u)), this.stop(o);
|
|
161
|
+
} catch (u) {
|
|
162
|
+
this.report(u);
|
|
163
|
+
}
|
|
164
|
+
}, this.pointerMove = (o) => {
|
|
165
|
+
if (this.lifecycle.isActive)
|
|
166
|
+
try {
|
|
167
|
+
this.lifecycle.move(o), this.stop(o);
|
|
168
|
+
} catch (h) {
|
|
169
|
+
this.report(h);
|
|
170
|
+
}
|
|
171
|
+
}, this.pointerUp = (o) => {
|
|
172
|
+
if (this.lifecycle.isActive)
|
|
173
|
+
try {
|
|
174
|
+
this.lifecycle.finish(o), this.stop(o);
|
|
175
|
+
} catch (h) {
|
|
176
|
+
this.report(h);
|
|
177
|
+
}
|
|
178
|
+
}, this.pointerCancel = (o) => {
|
|
179
|
+
this.lifecycle.isActive && (this.lifecycle.cancelPointer(o), this.stop(o));
|
|
180
|
+
}, this.keyDown = (o) => {
|
|
181
|
+
o.key !== "Escape" || !this.lifecycle.isActive || (this.lifecycle.cancel(), this.stop(o));
|
|
182
|
+
}, t.disposed || e.destroyed) throw new Error("不能挂载到已释放的编辑视图");
|
|
183
|
+
this.root = e.element;
|
|
184
|
+
const s = this.root.querySelector("[data-ppt-stage]"), n = this.root.querySelector('[data-ppt-layer="interaction"]'), i = this.root.querySelector('[data-ppt-layer="static"]');
|
|
185
|
+
if (!s || !n || !i) throw new Error("编辑视图缺少三层 DOM");
|
|
186
|
+
this.stage = s, this.layer = n, this.lifecycle = new b(this.root), this.root.addEventListener("pointerdown", this.pointerDown, !0), this.root.addEventListener("pointermove", this.pointerMove, !0), this.root.addEventListener("pointerup", this.pointerUp, !0), this.root.addEventListener("pointercancel", this.pointerCancel, !0), this.root.addEventListener("keydown", this.keyDown, !0), this.unsubscribe = t.editor.subscribe(() => this.render());
|
|
187
|
+
const l = ((a = this.root.ownerDocument.defaultView) == null ? void 0 : a.MutationObserver) ?? MutationObserver;
|
|
188
|
+
this.observer = new l(() => this.render()), this.observer.observe(i, { childList: !0 });
|
|
189
|
+
}
|
|
190
|
+
get elementId() {
|
|
191
|
+
return this.activeId;
|
|
192
|
+
}
|
|
193
|
+
get geometry() {
|
|
194
|
+
return !this.activeId || !this.session.editor.doc.elements[this.activeId] ? null : p(this.session.editor.doc, [this.activeId]).value;
|
|
195
|
+
}
|
|
196
|
+
get handles() {
|
|
197
|
+
const t = this.activeId, e = this.preview ?? this.geometry;
|
|
198
|
+
if (!t || !e) return [];
|
|
199
|
+
const r = this.session.editor.effectiveElement(t);
|
|
200
|
+
return m(e, r.w, r.h);
|
|
201
|
+
}
|
|
202
|
+
get destroyed() {
|
|
203
|
+
return this.isDestroyed;
|
|
204
|
+
}
|
|
205
|
+
start(t) {
|
|
206
|
+
this.assertAlive();
|
|
207
|
+
const e = this.session.editor.selection, r = t ?? (e.kind === "elements" && e.ids.length === 1 ? e.ids[0] : null);
|
|
208
|
+
return !r || this.view.mode !== "edit" || f(this.session.editor.doc, r) !== this.view.slideId || !p(this.session.editor.doc, [r]).value ? !1 : (this.activeId = r, this.preview = null, this.render(), !0);
|
|
209
|
+
}
|
|
210
|
+
end() {
|
|
211
|
+
var t;
|
|
212
|
+
this.lifecycle.cancel(), this.activeId = null, this.preview = null, (t = this.group()) == null || t.remove();
|
|
213
|
+
}
|
|
214
|
+
setPreset(t) {
|
|
215
|
+
this.assertAlive();
|
|
216
|
+
const e = this.session.editor.selection, r = this.activeId ?? (e.kind === "elements" && e.ids.length === 1 ? e.ids[0] : null);
|
|
217
|
+
if (!r || this.view.mode !== "edit") return !1;
|
|
218
|
+
try {
|
|
219
|
+
return this.session.editor.exec({ type: "SetPreset", id: r, preset: t }), this.activeId = r, this.preview = null, this.render(), !0;
|
|
220
|
+
} catch (s) {
|
|
221
|
+
return this.report(s), !1;
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
refresh() {
|
|
225
|
+
this.assertAlive(), this.render();
|
|
226
|
+
}
|
|
227
|
+
destroy() {
|
|
228
|
+
var t;
|
|
229
|
+
this.isDestroyed || (this.isDestroyed = !0, this.lifecycle.cancel(), this.unsubscribe(), this.observer.disconnect(), this.root.removeEventListener("pointerdown", this.pointerDown, !0), this.root.removeEventListener("pointermove", this.pointerMove, !0), this.root.removeEventListener("pointerup", this.pointerUp, !0), this.root.removeEventListener("pointercancel", this.pointerCancel, !0), this.root.removeEventListener("keydown", this.keyDown, !0), (t = this.group()) == null || t.remove(), this.activeId = null, this.preview = null);
|
|
230
|
+
}
|
|
231
|
+
assertAlive() {
|
|
232
|
+
if (this.isDestroyed || this.session.disposed || this.view.destroyed)
|
|
233
|
+
throw new Error("预设调节柄扩展已经释放");
|
|
234
|
+
}
|
|
235
|
+
group() {
|
|
236
|
+
return this.layer.querySelector("[data-ppt-preset-adjustments]");
|
|
237
|
+
}
|
|
238
|
+
render() {
|
|
239
|
+
var r;
|
|
240
|
+
(r = this.group()) == null || r.remove();
|
|
241
|
+
const t = this.activeId;
|
|
242
|
+
if (!t || this.isDestroyed || this.view.destroyed || this.view.mode !== "edit" || !this.session.editor.doc.elements[t] || f(this.session.editor.doc, t) !== this.view.slideId) return;
|
|
243
|
+
const e = y(this.layer.ownerDocument, "g");
|
|
244
|
+
e.dataset.pptPresetAdjustments = "", e.dataset.pptPresetElement = t;
|
|
245
|
+
for (const s of this.handles) {
|
|
246
|
+
const n = v(this.session.editor.doc, t, s), i = y(this.layer.ownerDocument, "circle");
|
|
247
|
+
i.dataset.pptPresetHandle = String(s.index), i.dataset.pptPresetKind = s.kind, i.setAttribute("cx", String(n.x)), i.setAttribute("cy", String(n.y)), i.setAttribute("r", String(6 / this.view.zoom)), i.setAttribute("fill", "#f59e0b"), i.setAttribute("stroke", "#fff"), i.setAttribute("stroke-width", String(2 / this.view.zoom)), i.style.pointerEvents = "all", i.style.cursor = "crosshair", e.append(i);
|
|
248
|
+
}
|
|
249
|
+
this.layer.append(e);
|
|
250
|
+
}
|
|
251
|
+
geometryAt(t, e, r) {
|
|
252
|
+
const s = this.activeId, n = this.stage.getBoundingClientRect(), i = w(t.screen, {
|
|
253
|
+
left: n.left,
|
|
254
|
+
top: n.top,
|
|
255
|
+
zoom: this.view.zoom
|
|
256
|
+
}), l = E(this.session.editor.doc, s, i), a = this.session.editor.effectiveElement(s);
|
|
257
|
+
return g(r, a.w, a.h, e, l);
|
|
258
|
+
}
|
|
259
|
+
gesture(t, e) {
|
|
260
|
+
let r = e;
|
|
261
|
+
const s = (n) => {
|
|
262
|
+
r = this.geometryAt(n, t, e), this.preview = r, this.render();
|
|
263
|
+
};
|
|
264
|
+
return {
|
|
265
|
+
cursor: "crosshair",
|
|
266
|
+
dataset: { name: "pptPresetDragging", value: String(t) },
|
|
267
|
+
start: () => {
|
|
268
|
+
},
|
|
269
|
+
frame: s,
|
|
270
|
+
finish: (n) => {
|
|
271
|
+
s(n);
|
|
272
|
+
const i = this.activeId, l = Object.entries(r.adj).filter(([a, o]) => e.adj[a] !== o);
|
|
273
|
+
return l.length ? () => {
|
|
274
|
+
this.preview = null, this.session.editor.transaction((a) => {
|
|
275
|
+
for (const [o, h] of l)
|
|
276
|
+
a.exec({ type: "SetAdj", id: i, name: o, value: h });
|
|
277
|
+
}, "拖动预设调节柄");
|
|
278
|
+
} : null;
|
|
279
|
+
},
|
|
280
|
+
clear: () => {
|
|
281
|
+
this.preview = null, this.render();
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
}
|
|
285
|
+
stop(t) {
|
|
286
|
+
t.preventDefault(), t.stopImmediatePropagation();
|
|
287
|
+
}
|
|
288
|
+
report(t) {
|
|
289
|
+
var e, r;
|
|
290
|
+
this.lifecycle.cancel(), (r = (e = this.options).onError) == null || r.call(e, t), this.options.onError || queueMicrotask(() => {
|
|
291
|
+
throw t;
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
function D(c, t, e = {}) {
|
|
296
|
+
return new P(c, t, e);
|
|
297
|
+
}
|
|
298
|
+
export {
|
|
299
|
+
D as createPresetAdjustmentEditor
|
|
300
|
+
};
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { EditorSession } from './session';
|
|
2
|
+
import type { SlideEditor } from './slide-editor-types';
|
|
3
|
+
/** 产品可在挂载后启用;不使用辅助对象目录的宿主不承担其模型遍历与 DOM 成本。 */
|
|
4
|
+
export declare function createCanvasAccessibility(session: EditorSession, view: SlideEditor): {
|
|
5
|
+
dispose(): void;
|
|
6
|
+
};
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { createChartDataEditor, listEditableCharts, queryChartData, } from '@web-ppt/edit-core/chart';
|
|
2
|
+
export type { ChartCategory, ChartDataBinding, ChartDataEditor, ChartDataset, ChartFormulaBinding, ChartPlotKind, ChartPoint, ChartPointId, ChartSeries, ChartSeriesId, EditableChart, } from '@web-ppt/edit-core/chart';
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
export { registerSharedChartEditing, createChartDataEditor, listEditableCharts, queryChartData, } from '@web-ppt/edit-core/chart-shared';
|
|
2
|
+
export type { ChartCategory, ChartDataBinding, ChartDataEditor, ChartDataset, ChartFormulaBinding, ChartPlotKind, ChartPoint, ChartPointId, ChartSeries, ChartSeriesId, EditableChart, } from '@web-ppt/edit-core/chart-shared';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createChartDataEditor as a, listEditableCharts as e, queryChartData as i, registerSharedChartEditing as h } from "@web-ppt/edit-core/chart-shared";
|
|
2
|
+
export {
|
|
3
|
+
a as createChartDataEditor,
|
|
4
|
+
e as listEditableCharts,
|
|
5
|
+
i as queryChartData,
|
|
6
|
+
h as registerSharedChartEditing
|
|
7
|
+
};
|
package/dist/chart.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AddSectionCommand, DistributeElementsCommand, Editor, ElementAltTextState, ElementId, SectionId, SectionRecord, SetAltTextCommand, SetSlideSizeCommand, SlideSizeState } from '@web-ppt/edit-core';
|
|
2
|
+
/** 挂载视图与 headless adapter 共享同一套公共命令语义。 */
|
|
3
|
+
export declare class CommonObjectSlideCommands {
|
|
4
|
+
private readonly editor;
|
|
5
|
+
constructor(editor: Editor);
|
|
6
|
+
distribute(enabled: boolean, axis: DistributeElementsCommand['axis'], ids?: readonly ElementId[]): boolean;
|
|
7
|
+
queryAltText(id?: ElementId): ElementAltTextState | null;
|
|
8
|
+
setAltText(enabled: boolean, value: Pick<SetAltTextCommand, 'title' | 'descr'>, id?: ElementId): boolean;
|
|
9
|
+
listSections(): SectionRecord[];
|
|
10
|
+
addSection(enabled: boolean, value: Omit<AddSectionCommand, 'type'>): SectionRecord | null;
|
|
11
|
+
renameSection(enabled: boolean, id: SectionId, name: string): boolean;
|
|
12
|
+
moveSection(enabled: boolean, id: SectionId, after: SectionId | null): boolean;
|
|
13
|
+
removeSection(enabled: boolean, id: SectionId): boolean;
|
|
14
|
+
querySlideSize(): SlideSizeState;
|
|
15
|
+
setSlideSize(enabled: boolean, value: Pick<SetSlideSizeCommand, 'w' | 'h' | 'fit'>): boolean;
|
|
16
|
+
private writable;
|
|
17
|
+
private exec;
|
|
18
|
+
private selectedElementId;
|
|
19
|
+
}
|
|
20
|
+
export declare function commonObjectSlideCommands(editor: Editor): CommonObjectSlideCommands;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { DesignCommand, DesignTarget, TransactionResult } from '@web-ppt/edit-core';
|
|
2
|
+
export interface DesignEditorOptions {
|
|
3
|
+
readonly target: DesignTarget;
|
|
4
|
+
readonly textMode?: 'auto' | 'html' | 'svg';
|
|
5
|
+
}
|
|
6
|
+
/** 版式 DOM 适配器只暴露设计目标命令,不混入页序、备注或动画入口。 */
|
|
7
|
+
export interface DesignEditor {
|
|
8
|
+
readonly element: HTMLDivElement;
|
|
9
|
+
readonly target: DesignTarget;
|
|
10
|
+
readonly destroyed: boolean;
|
|
11
|
+
setTarget(target: DesignTarget): void;
|
|
12
|
+
exec(...commands: DesignCommand[]): TransactionResult;
|
|
13
|
+
render(): void;
|
|
14
|
+
destroy(): void;
|
|
15
|
+
}
|
package/dist/design.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { renderSlideToSvg as u } from "@web-ppt/core";
|
|
2
|
+
import { foreignObjectScalesCorrectly as f } from "@web-ppt/viewer-core";
|
|
3
|
+
import { listLayouts as x, listMasters as T, queryLayout as M, queryMaster as b, toDesignCanvas as $ } from "@web-ppt/edit-core";
|
|
4
|
+
function h(s, e) {
|
|
5
|
+
const t = [], r = (d) => {
|
|
6
|
+
for (const i of d) {
|
|
7
|
+
t.push(i);
|
|
8
|
+
const n = s.elements[i];
|
|
9
|
+
n && n.meta.editable !== "frame" && n.children && r(n.children);
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
return r(e), t;
|
|
13
|
+
}
|
|
14
|
+
function c(s, e) {
|
|
15
|
+
return [...s.nodeType === 1 && s.matches(e) ? [s] : [], ...s.querySelectorAll(e)];
|
|
16
|
+
}
|
|
17
|
+
function m(s, e, t) {
|
|
18
|
+
return c(s, "[data-edit-id]").find((r) => r.dataset[e] === t) ?? null;
|
|
19
|
+
}
|
|
20
|
+
function l(s, e, t) {
|
|
21
|
+
var d;
|
|
22
|
+
const r = c(s, "[data-el]");
|
|
23
|
+
if (r.length !== t.length) throw new Error("渲染节点与编辑投影的元素数量不一致");
|
|
24
|
+
r.forEach((i, n) => {
|
|
25
|
+
const o = t[n];
|
|
26
|
+
if (o === null) return;
|
|
27
|
+
const a = e.elements[o].src.id;
|
|
28
|
+
if ((a === void 0 ? "" : String(a)) !== i.dataset.el)
|
|
29
|
+
throw new Error(`渲染节点与编辑投影的顺序不一致:${o}`);
|
|
30
|
+
i.dataset.editId = o;
|
|
31
|
+
});
|
|
32
|
+
for (const i of t) {
|
|
33
|
+
if (i === null) continue;
|
|
34
|
+
const n = m(s, "editId", i);
|
|
35
|
+
if (!n) throw new Error(`渲染结果缺少编辑元素:${i}`);
|
|
36
|
+
const o = ((d = n.parentElement) == null ? void 0 : d.localName) === "a" ? n.parentElement : n;
|
|
37
|
+
o.dataset.editRoot = i;
|
|
38
|
+
}
|
|
39
|
+
for (const i of s.querySelectorAll("[data-r]"))
|
|
40
|
+
i.dataset.pptSearchR = i.dataset.r, delete i.dataset.r, i.dataset.from !== void 0 && (i.dataset.pptSearchFrom = i.dataset.from, delete i.dataset.from), i.dataset.to !== void 0 && (i.dataset.pptSearchTo = i.dataset.to, delete i.dataset.to);
|
|
41
|
+
}
|
|
42
|
+
function p(s, e, t) {
|
|
43
|
+
if (t.kind === "master") {
|
|
44
|
+
const i = e.masters[t.id];
|
|
45
|
+
if (!i) throw new Error(`找不到母版设计目标:${t.id}`);
|
|
46
|
+
l(s, e, h(e, i.children));
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
const r = e.layouts[t.id];
|
|
50
|
+
if (!r) throw new Error(`找不到版式设计目标:${t.id}`);
|
|
51
|
+
const d = r.showMasterShapes === !1 ? void 0 : e.masters[r.origin.masterPart];
|
|
52
|
+
l(s, e, h(e, [
|
|
53
|
+
...(d == null ? void 0 : d.children) ?? [],
|
|
54
|
+
...r.children
|
|
55
|
+
]));
|
|
56
|
+
}
|
|
57
|
+
let g = 0;
|
|
58
|
+
class w {
|
|
59
|
+
constructor(e, t, r) {
|
|
60
|
+
if (this.session = t, this.isDestroyed = !1, t.disposed) throw new Error("不能挂载已经释放的编辑会话");
|
|
61
|
+
this.currentTarget = structuredClone(r.target), t.editor.toDesignCanvas(this.currentTarget), this.idPrefix = `${t.editor.doc.identity.prefix}design-view-${++g}-`, this.presentation = t.toPresentation(), this.textMode = r.textMode === "svg" || r.textMode === "html" ? r.textMode : f(e.ownerDocument) ? "html" : "svg", this.element = e.ownerDocument.createElement("div"), this.element.dataset.pptDesignEditor = this.currentTarget.kind, this.element.style.position = "relative", this.element.style.width = "100%", this.element.style.height = "100%", e.append(this.element), this.unsubscribe = t.editor.subscribe((d) => this.update(d)), this.render();
|
|
62
|
+
}
|
|
63
|
+
get target() {
|
|
64
|
+
return structuredClone(this.currentTarget);
|
|
65
|
+
}
|
|
66
|
+
get destroyed() {
|
|
67
|
+
return this.isDestroyed;
|
|
68
|
+
}
|
|
69
|
+
setTarget(e) {
|
|
70
|
+
this.assertAlive(), this.session.editor.toDesignCanvas(e), this.currentTarget = structuredClone(e), this.element.dataset.pptDesignEditor = e.kind, this.render();
|
|
71
|
+
}
|
|
72
|
+
exec(...e) {
|
|
73
|
+
return this.assertAlive(), this.session.editor.execDesign(this.currentTarget, ...e);
|
|
74
|
+
}
|
|
75
|
+
render() {
|
|
76
|
+
this.assertAlive(), this.element.innerHTML = u(
|
|
77
|
+
this.presentation,
|
|
78
|
+
this.session.editor.toDesignCanvas(this.currentTarget),
|
|
79
|
+
{
|
|
80
|
+
textMode: this.textMode,
|
|
81
|
+
idPrefix: `${this.idPrefix}${this.currentTarget.id}-`,
|
|
82
|
+
includeEditMarkers: !0
|
|
83
|
+
}
|
|
84
|
+
), p(this.element, this.session.editor.doc, this.currentTarget);
|
|
85
|
+
}
|
|
86
|
+
destroy() {
|
|
87
|
+
this.isDestroyed || (this.isDestroyed = !0, this.unsubscribe(), this.element.remove());
|
|
88
|
+
}
|
|
89
|
+
assertAlive() {
|
|
90
|
+
if (this.isDestroyed || this.session.disposed) throw new Error("设计视图已经销毁");
|
|
91
|
+
}
|
|
92
|
+
update(e) {
|
|
93
|
+
if (e.source === "selection") return;
|
|
94
|
+
const t = this.session.editor.doc;
|
|
95
|
+
this.presentation.width = t.meta.width, this.presentation.height = t.meta.height, (e.createdSlides.size || e.removedSlides.size || e.movedSlides.size) && (this.presentation.slides = t.slideOrder.map((r) => this.session.editor.toSlide(r))), this.render();
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
function D(s, e, t) {
|
|
99
|
+
return new w(s, e, t);
|
|
100
|
+
}
|
|
101
|
+
export {
|
|
102
|
+
D as createDesignEditor,
|
|
103
|
+
x as listLayouts,
|
|
104
|
+
T as listMasters,
|
|
105
|
+
M as queryLayout,
|
|
106
|
+
b as queryMaster,
|
|
107
|
+
$ as toDesignCanvas
|
|
108
|
+
};
|
package/dist/dom-identity.d.ts
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
-
import type { EditDoc, ElementId, SlideId } from '@web-ppt/edit-core';
|
|
1
|
+
import type { DesignTarget, EditDoc, ElementId, SlideId } from '@web-ppt/edit-core';
|
|
2
2
|
export declare function elementIds(doc: EditDoc, roots: readonly ElementId[]): ElementId[];
|
|
3
3
|
export declare function bindElementIdentities(root: ParentNode, doc: EditDoc, roots: readonly ElementId[]): void;
|
|
4
|
+
/** 结构壳尚未挂孩子时只绑定容器本身,孩子沿用原分区身份。 */
|
|
5
|
+
export declare function bindSingleElementIdentity(root: ParentNode, doc: EditDoc, id: ElementId): void;
|
|
4
6
|
export declare function bindSlideIdentities(root: ParentNode, doc: EditDoc, slideId: SlideId): void;
|
|
7
|
+
export declare function bindDesignIdentities(root: ParentNode, doc: EditDoc, target: DesignTarget): void;
|
|
5
8
|
export declare function findElementPartition(root: ParentNode, id: ElementId): SVGElement | null;
|
|
6
9
|
/**
|
|
7
10
|
* visibility 会被后代的 visible 覆盖;显示元素时必须删除声明,让祖先隐藏继续继承。
|
package/dist/dom-patch.d.ts
CHANGED
|
@@ -4,6 +4,6 @@ export declare function patchElement(staticLayer: HTMLElement, editor: Editor, i
|
|
|
4
4
|
/** 删除结构节点时只移除其 markup/defs 分区,未触碰兄弟必须保留 DOM 身份。 */
|
|
5
5
|
export declare function removeElementPartition(staticLayer: HTMLElement, id: ElementId): boolean;
|
|
6
6
|
/** 撤销删除时以模型兄弟 z 序寻找稳定锚点;空父容器交给整页回退。 */
|
|
7
|
-
export declare function insertElementPartition(staticLayer: HTMLElement, editor: Editor, id: ElementId, idPrefix: string, textMode: 'html' | 'svg'): boolean;
|
|
7
|
+
export declare function insertElementPartition(staticLayer: HTMLElement, editor: Editor, id: ElementId, idPrefix: string, textMode: 'html' | 'svg', fallbackParent?: Node | null, knownChildren?: readonly SVGElement[]): boolean;
|
|
8
8
|
/** 按模型目标序倒序移动受影响分区;锚点标记保证末元素不会越过非元素装饰节点。 */
|
|
9
9
|
export declare function reorderElementPartitions(staticLayer: HTMLElement, editor: Editor, ids: ReadonlySet<ElementId>): boolean;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { TextBody } from '@web-ppt/core';
|
|
2
|
+
import type { NativeTextFormat } from './native';
|
|
3
|
+
export declare function textRange(root: HTMLElement, text: TextBody, from: number, to: number): Range | null;
|
|
4
|
+
export declare function textBounds(root: HTMLElement, text: TextBody, from: number, to: number): DOMRect;
|
|
5
|
+
export declare function compositionDecoration(root: HTMLElement): {
|
|
6
|
+
update(text: TextBody, formats: readonly NativeTextFormat[]): void;
|
|
7
|
+
dispose(): void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { EditorSession } from '../session';
|
|
2
|
+
import type { SlideEditor } from '../slide-editor-types';
|
|
3
|
+
export interface EditContextEnhancement {
|
|
4
|
+
readonly supported: boolean;
|
|
5
|
+
dispose(): void;
|
|
6
|
+
}
|
|
7
|
+
/** 仅替换浏览器输入适配;格式、历史、IME 合并与协同重基仍经过既有文字控制器。 */
|
|
8
|
+
export declare function enableEditContext(session: EditorSession, view: SlideEditor): EditContextEnhancement;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export interface NativeEditContext extends EventTarget {
|
|
2
|
+
readonly text: string;
|
|
3
|
+
readonly selectionStart: number;
|
|
4
|
+
readonly selectionEnd: number;
|
|
5
|
+
updateText(start: number, end: number, text: string): void;
|
|
6
|
+
updateSelection(start: number, end: number): void;
|
|
7
|
+
updateControlBounds(bounds: DOMRect): void;
|
|
8
|
+
updateSelectionBounds(bounds: DOMRect): void;
|
|
9
|
+
updateCharacterBounds(start: number, bounds: DOMRect[]): void;
|
|
10
|
+
}
|
|
11
|
+
export interface NativeTextUpdate extends Event {
|
|
12
|
+
readonly updateRangeStart: number;
|
|
13
|
+
readonly updateRangeEnd: number;
|
|
14
|
+
readonly text: string;
|
|
15
|
+
readonly selectionStart: number;
|
|
16
|
+
readonly selectionEnd: number;
|
|
17
|
+
}
|
|
18
|
+
export interface NativeTextFormat {
|
|
19
|
+
readonly rangeStart: number;
|
|
20
|
+
readonly rangeEnd: number;
|
|
21
|
+
readonly underlineStyle: string;
|
|
22
|
+
readonly underlineThickness: string;
|
|
23
|
+
}
|
|
24
|
+
export type EditContextWindow = Window & typeof globalThis & {
|
|
25
|
+
EditContext?: new (options: {
|
|
26
|
+
text: string;
|
|
27
|
+
selectionStart: number;
|
|
28
|
+
selectionEnd: number;
|
|
29
|
+
}) => NativeEditContext;
|
|
30
|
+
};
|
|
31
|
+
export type EditingHost = HTMLDivElement & {
|
|
32
|
+
editContext: NativeEditContext | null;
|
|
33
|
+
};
|