@jxsuite/studio 0.11.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/studio.js +6517 -5870
- package/dist/studio.js.map +57 -51
- package/package.json +5 -3
- package/src/canvas/canvas-diff.js +184 -0
- package/src/canvas/canvas-helpers.js +10 -14
- package/src/canvas/canvas-live-render.js +28 -2
- package/src/canvas/canvas-render.js +170 -20
- package/src/canvas/canvas-utils.js +22 -25
- package/src/editor/component-inline-edit.js +55 -44
- package/src/editor/content-inline-edit.js +47 -50
- package/src/editor/context-menu.js +78 -53
- package/src/editor/convert-to-component.js +11 -14
- package/src/editor/insertion-helper.js +8 -11
- package/src/editor/shortcuts.js +88 -64
- package/src/files/components.js +15 -4
- package/src/files/file-ops.js +57 -108
- package/src/files/files.js +81 -28
- package/src/panels/activity-bar.js +31 -7
- package/src/panels/block-action-bar.js +104 -80
- package/src/panels/canvas-dnd.js +4 -10
- package/src/panels/dnd.js +77 -35
- package/src/panels/editors.js +17 -26
- package/src/panels/elements-panel.js +17 -11
- package/src/panels/events-panel.js +44 -39
- package/src/panels/git-panel.js +47 -4
- package/src/panels/layers-panel.js +25 -21
- package/src/panels/left-panel.js +109 -44
- package/src/panels/overlays.js +91 -41
- package/src/panels/panel-events.js +28 -37
- package/src/panels/preview-render.js +7 -3
- package/src/panels/properties-panel.js +179 -104
- package/src/panels/pseudo-preview.js +9 -8
- package/src/panels/right-panel.js +85 -37
- package/src/panels/shared.js +0 -22
- package/src/panels/signals-panel.js +125 -54
- package/src/panels/statusbar.js +26 -19
- package/src/panels/style-inputs.js +5 -4
- package/src/panels/style-panel.js +128 -105
- package/src/panels/style-utils.js +8 -6
- package/src/panels/stylebook-layers-panel.js +5 -5
- package/src/panels/stylebook-panel.js +27 -31
- package/src/panels/tab-strip.js +124 -0
- package/src/panels/toolbar.js +40 -10
- package/src/reactivity.js +28 -0
- package/src/settings/content-types-editor.js +56 -7
- package/src/settings/defs-editor.js +56 -7
- package/src/settings/schema-field-ui.js +60 -25
- package/src/state.js +2 -459
- package/src/store.js +61 -219
- package/src/studio.js +163 -300
- package/src/tabs/tab.js +168 -0
- package/src/tabs/transact.js +406 -0
- package/src/ui/color-selector.js +4 -5
- package/src/view.js +3 -0
- package/src/workspace/workspace.js +90 -0
|
@@ -8,8 +8,8 @@ import { ref } from "lit-html/directives/ref.js";
|
|
|
8
8
|
import { styleMap } from "lit-html/directives/style-map.js";
|
|
9
9
|
import { ifDefined } from "lit-html/directives/if-defined.js";
|
|
10
10
|
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
11
|
+
import { renderOnly, updateUi, canvasWrap, canvasPanels } from "../store.js";
|
|
12
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
13
13
|
import { view } from "../view.js";
|
|
14
14
|
|
|
15
15
|
/** @type {any} */
|
|
@@ -44,14 +44,14 @@ export function initCanvasUtils(ctx) {
|
|
|
44
44
|
export function canvasPanelTemplate(mediaName, label, fullWidth, width = null) {
|
|
45
45
|
/**
|
|
46
46
|
* @type {{
|
|
47
|
-
* mediaName:
|
|
48
|
-
* element:
|
|
49
|
-
* canvas:
|
|
50
|
-
* overlay:
|
|
51
|
-
* overlayClk:
|
|
52
|
-
* viewport:
|
|
53
|
-
* dropLine:
|
|
54
|
-
* _width:
|
|
47
|
+
* mediaName: string;
|
|
48
|
+
* element: HTMLElement | null;
|
|
49
|
+
* canvas: HTMLElement | null;
|
|
50
|
+
* overlay: HTMLElement | null;
|
|
51
|
+
* overlayClk: HTMLElement | null;
|
|
52
|
+
* viewport: HTMLElement | null;
|
|
53
|
+
* dropLine: HTMLElement | null;
|
|
54
|
+
* _width: number | null;
|
|
55
55
|
* }}
|
|
56
56
|
*/
|
|
57
57
|
const panel = {
|
|
@@ -69,7 +69,7 @@ export function canvasPanelTemplate(mediaName, label, fullWidth, width = null) {
|
|
|
69
69
|
class=${`canvas-panel${fullWidth ? " full-width" : ""}`}
|
|
70
70
|
data-media=${ifDefined(mediaName !== null ? mediaName : undefined)}
|
|
71
71
|
${ref((el) => {
|
|
72
|
-
if (el) panel.element = el;
|
|
72
|
+
if (el) panel.element = /** @type {HTMLElement} */ (el);
|
|
73
73
|
})}
|
|
74
74
|
>
|
|
75
75
|
${label
|
|
@@ -88,34 +88,34 @@ export function canvasPanelTemplate(mediaName, label, fullWidth, width = null) {
|
|
|
88
88
|
class="canvas-panel-viewport"
|
|
89
89
|
style=${styleMap({ width: width && !fullWidth ? `${width}px` : "" })}
|
|
90
90
|
${ref((el) => {
|
|
91
|
-
if (el) panel.viewport = el;
|
|
91
|
+
if (el) panel.viewport = /** @type {HTMLElement} */ (el);
|
|
92
92
|
})}
|
|
93
93
|
>
|
|
94
94
|
<div
|
|
95
95
|
class="canvas-panel-canvas"
|
|
96
96
|
style=${styleMap({ width: width ? `${width}px` : "" })}
|
|
97
97
|
${ref((el) => {
|
|
98
|
-
if (el) panel.canvas = el;
|
|
98
|
+
if (el) panel.canvas = /** @type {HTMLElement} */ (el);
|
|
99
99
|
})}
|
|
100
100
|
></div>
|
|
101
101
|
<div
|
|
102
102
|
class="canvas-panel-overlay"
|
|
103
103
|
${ref((el) => {
|
|
104
|
-
if (el) panel.overlay = el;
|
|
104
|
+
if (el) panel.overlay = /** @type {HTMLElement} */ (el);
|
|
105
105
|
})}
|
|
106
106
|
>
|
|
107
107
|
<div
|
|
108
108
|
class="canvas-drop-indicator"
|
|
109
109
|
style="display:none"
|
|
110
110
|
${ref((el) => {
|
|
111
|
-
if (el) panel.dropLine = el;
|
|
111
|
+
if (el) panel.dropLine = /** @type {HTMLElement} */ (el);
|
|
112
112
|
})}
|
|
113
113
|
></div>
|
|
114
114
|
</div>
|
|
115
115
|
<div
|
|
116
116
|
class="canvas-panel-click"
|
|
117
117
|
${ref((el) => {
|
|
118
|
-
if (el) panel.overlayClk = el;
|
|
118
|
+
if (el) panel.overlayClk = /** @type {HTMLElement} */ (el);
|
|
119
119
|
})}
|
|
120
120
|
></div>
|
|
121
121
|
</div>
|
|
@@ -168,8 +168,7 @@ export function applyTransform() {
|
|
|
168
168
|
if (!view.panzoomWrap) return;
|
|
169
169
|
const zoom = _ctx.getZoom();
|
|
170
170
|
view.panzoomWrap.style.transform = `translate(${view.panX}px, ${view.panY}px) scale(${zoom})`;
|
|
171
|
-
|
|
172
|
-
if (label) label.textContent = `${Math.round(zoom * 100)}%`;
|
|
171
|
+
renderZoomIndicator();
|
|
173
172
|
renderOnly("overlays");
|
|
174
173
|
if (_ctx.getCanvasMode() === "settings") _ctx.renderStylebookOverlays();
|
|
175
174
|
}
|
|
@@ -207,7 +206,6 @@ export function fitToScreen() {
|
|
|
207
206
|
|
|
208
207
|
/** Reset the zoom indicator (clear its content). Called when switching to non-panzoom modes. */
|
|
209
208
|
export function resetZoomIndicator() {
|
|
210
|
-
ensureLitState(zoomIndicatorHost);
|
|
211
209
|
litRender(nothing, zoomIndicatorHost);
|
|
212
210
|
}
|
|
213
211
|
|
|
@@ -220,7 +218,6 @@ export function renderZoomIndicator() {
|
|
|
220
218
|
if (!zoomIndicatorHost.isConnected) {
|
|
221
219
|
document.body.appendChild(zoomIndicatorHost);
|
|
222
220
|
}
|
|
223
|
-
ensureLitState(zoomIndicatorHost);
|
|
224
221
|
litRender(
|
|
225
222
|
html`
|
|
226
223
|
<div class="zoom-indicator">
|
|
@@ -263,14 +260,14 @@ export function positionZoomIndicator() {
|
|
|
263
260
|
|
|
264
261
|
/** Toggle "active" class on canvas panel headers based on activeMedia. */
|
|
265
262
|
export function updateActivePanelHeaders() {
|
|
266
|
-
const
|
|
263
|
+
const activeMedia = activeTab.value?.session.ui.activeMedia ?? null;
|
|
267
264
|
for (const p of canvasPanels) {
|
|
268
|
-
const header = p.element
|
|
265
|
+
const header = p.element?.querySelector(".canvas-panel-header");
|
|
269
266
|
if (header) {
|
|
270
267
|
const isActive =
|
|
271
|
-
(
|
|
272
|
-
(
|
|
273
|
-
|
|
268
|
+
(activeMedia === null && p.mediaName === "base") ||
|
|
269
|
+
(activeMedia === null && p.mediaName === null) ||
|
|
270
|
+
activeMedia === p.mediaName;
|
|
274
271
|
header.classList.toggle("active", isActive);
|
|
275
272
|
}
|
|
276
273
|
}
|
|
@@ -4,20 +4,21 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
getState,
|
|
8
|
-
update,
|
|
9
7
|
updateUi,
|
|
10
8
|
renderOnly,
|
|
11
9
|
getNodeAtPath,
|
|
12
|
-
selectNode,
|
|
13
|
-
removeNode,
|
|
14
|
-
insertNode,
|
|
15
|
-
updateProperty,
|
|
16
10
|
parentElementPath,
|
|
17
11
|
childIndex,
|
|
18
12
|
canvasPanels,
|
|
19
13
|
elToPath,
|
|
20
14
|
} from "../store.js";
|
|
15
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
16
|
+
import {
|
|
17
|
+
transactDoc,
|
|
18
|
+
mutateRemoveNode,
|
|
19
|
+
mutateInsertNode,
|
|
20
|
+
mutateUpdateProperty,
|
|
21
|
+
} from "../tabs/transact.js";
|
|
21
22
|
import { view } from "../view.js";
|
|
22
23
|
import { isSlashMenuOpen, showSlashMenu, dismissSlashMenu } from "./slash-menu.js";
|
|
23
24
|
import { renderBlockActionBar } from "../panels/block-action-bar.js";
|
|
@@ -46,8 +47,7 @@ export function enterComponentInlineEdit(el, path) {
|
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
|
|
49
|
-
const
|
|
50
|
-
const node = getNodeAtPath(S.document, path);
|
|
50
|
+
const node = getNodeAtPath(activeTab.value?.doc.document, path);
|
|
51
51
|
if (!node) return;
|
|
52
52
|
|
|
53
53
|
const tc = node.textContent;
|
|
@@ -59,7 +59,9 @@ export function enterComponentInlineEdit(el, path) {
|
|
|
59
59
|
if (voids.has(node.tagName)) return;
|
|
60
60
|
|
|
61
61
|
for (const p of canvasPanels) {
|
|
62
|
-
const boxes =
|
|
62
|
+
const boxes = /** @type {NodeListOf<HTMLElement>} */ (
|
|
63
|
+
p.overlay.querySelectorAll(".overlay-box")
|
|
64
|
+
);
|
|
63
65
|
for (const box of boxes) {
|
|
64
66
|
box.style.border = "none";
|
|
65
67
|
}
|
|
@@ -104,10 +106,11 @@ export function enterComponentInlineEdit(el, path) {
|
|
|
104
106
|
if (view.blockActionBarEl && view.blockActionBarEl.contains(evt.target)) return;
|
|
105
107
|
document.removeEventListener("mousedown", outsideHandler, true);
|
|
106
108
|
|
|
109
|
+
/** @type {(string | number)[] | null} */
|
|
107
110
|
let hitPath = null,
|
|
108
111
|
hitMedia = null;
|
|
109
112
|
for (const p of canvasPanels) {
|
|
110
|
-
const els = p.canvas.querySelectorAll("*");
|
|
113
|
+
const els = /** @type {NodeListOf<HTMLElement>} */ (p.canvas.querySelectorAll("*"));
|
|
111
114
|
for (const el of els) el.style.pointerEvents = "auto";
|
|
112
115
|
p.overlayClk.style.display = "none";
|
|
113
116
|
const found = document.elementsFromPoint(evt.clientX, evt.clientY);
|
|
@@ -132,37 +135,44 @@ export function enterComponentInlineEdit(el, path) {
|
|
|
132
135
|
|
|
133
136
|
const isEmpty = !newText;
|
|
134
137
|
const pPath = parentElementPath(editPath);
|
|
135
|
-
const S = getState();
|
|
136
138
|
|
|
137
139
|
if (hitPath) {
|
|
140
|
+
let hp = hitPath;
|
|
138
141
|
const media = hitMedia === "base" ? null : (hitMedia ?? null);
|
|
139
|
-
updateUi("pendingInlineEdit", { path:
|
|
140
|
-
|
|
142
|
+
updateUi("pendingInlineEdit", { path: hp, mediaName: hitMedia });
|
|
143
|
+
activeTab.value.session.ui.activeMedia = media;
|
|
141
144
|
if (isEmpty && pPath) {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
145
|
+
transactDoc(activeTab.value, (t) => {
|
|
146
|
+
mutateRemoveNode(t, editPath);
|
|
147
|
+
const removedIdx = /** @type {number} */ (childIndex(editPath));
|
|
148
|
+
const hitIdx = /** @type {number} */ (childIndex(hp));
|
|
149
|
+
const hitParent = parentElementPath(hp);
|
|
150
|
+
if (
|
|
151
|
+
hitParent &&
|
|
152
|
+
pPath &&
|
|
153
|
+
hitParent.join("/") === pPath.join("/") &&
|
|
154
|
+
hitIdx > removedIdx
|
|
155
|
+
) {
|
|
156
|
+
hp = [...pPath, "children", hitIdx - 1];
|
|
157
|
+
updateUi("pendingInlineEdit", { path: hp, mediaName: hitMedia });
|
|
158
|
+
}
|
|
159
|
+
t.session.selection = hp;
|
|
160
|
+
});
|
|
151
161
|
} else if (newText !== originalText) {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
),
|
|
157
|
-
);
|
|
162
|
+
transactDoc(activeTab.value, (t) => {
|
|
163
|
+
mutateUpdateProperty(t, editPath, "textContent", newText || undefined);
|
|
164
|
+
t.session.selection = hp;
|
|
165
|
+
});
|
|
158
166
|
} else {
|
|
159
|
-
|
|
167
|
+
activeTab.value.session.selection = hp;
|
|
160
168
|
}
|
|
161
169
|
} else {
|
|
162
170
|
if (isEmpty && pPath) {
|
|
163
|
-
|
|
171
|
+
transactDoc(activeTab.value, (t) => mutateRemoveNode(t, editPath));
|
|
164
172
|
} else if (newText !== originalText) {
|
|
165
|
-
|
|
173
|
+
transactDoc(activeTab.value, (t) =>
|
|
174
|
+
mutateUpdateProperty(t, editPath, "textContent", newText || undefined),
|
|
175
|
+
);
|
|
166
176
|
} else {
|
|
167
177
|
renderOnly("canvas");
|
|
168
178
|
renderOnly("overlays");
|
|
@@ -219,13 +229,13 @@ function splitParagraph() {
|
|
|
219
229
|
|
|
220
230
|
cleanupComponentInlineEdit(el);
|
|
221
231
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
232
|
+
transactDoc(activeTab.value, (t) => {
|
|
233
|
+
mutateUpdateProperty(t, path, "textContent", textBefore || undefined);
|
|
234
|
+
mutateInsertNode(t, pPath, idx + 1, newDef);
|
|
235
|
+
t.session.selection = newPath;
|
|
236
|
+
});
|
|
226
237
|
|
|
227
238
|
updateUi("pendingInlineEdit", { path: newPath, mediaName });
|
|
228
|
-
update(s);
|
|
229
239
|
}
|
|
230
240
|
|
|
231
241
|
function _commitComponentInlineEdit() {
|
|
@@ -235,12 +245,13 @@ function _commitComponentInlineEdit() {
|
|
|
235
245
|
|
|
236
246
|
cleanupComponentInlineEdit(el);
|
|
237
247
|
|
|
238
|
-
const S = getState();
|
|
239
248
|
const pPath = parentElementPath(path);
|
|
240
249
|
if (!newText && pPath) {
|
|
241
|
-
|
|
250
|
+
transactDoc(activeTab.value, (t) => mutateRemoveNode(t, path));
|
|
242
251
|
} else if (newText !== originalText) {
|
|
243
|
-
|
|
252
|
+
transactDoc(activeTab.value, (t) =>
|
|
253
|
+
mutateUpdateProperty(t, path, "textContent", newText || undefined),
|
|
254
|
+
);
|
|
244
255
|
} else {
|
|
245
256
|
renderOnly("canvas");
|
|
246
257
|
renderOnly("overlays");
|
|
@@ -303,15 +314,15 @@ function handleComponentSlashSelect(cmd) {
|
|
|
303
314
|
|
|
304
315
|
cleanupComponentInlineEdit(el);
|
|
305
316
|
|
|
306
|
-
const S = getState();
|
|
307
317
|
const newDef = defaultDef(cmd.tag);
|
|
308
318
|
const newPath = [...pPath, "children", idx];
|
|
309
319
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
320
|
+
transactDoc(activeTab.value, (t) => {
|
|
321
|
+
mutateRemoveNode(t, path);
|
|
322
|
+
mutateInsertNode(t, pPath, idx, newDef);
|
|
323
|
+
t.session.selection = newPath;
|
|
324
|
+
});
|
|
313
325
|
|
|
314
326
|
const hasText = newDef.textContent != null;
|
|
315
327
|
if (hasText) updateUi("pendingInlineEdit", { path: newPath, mediaName });
|
|
316
|
-
update(s);
|
|
317
328
|
}
|
|
@@ -4,17 +4,14 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import {
|
|
7
|
-
getState,
|
|
8
|
-
update,
|
|
9
7
|
renderOnly,
|
|
10
|
-
selectNode,
|
|
11
|
-
insertNode,
|
|
12
|
-
updateProperty,
|
|
13
8
|
getNodeAtPath,
|
|
14
9
|
parentElementPath,
|
|
15
10
|
childIndex,
|
|
16
11
|
canvasPanels,
|
|
17
12
|
} from "../store.js";
|
|
13
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
14
|
+
import { transactDoc, mutateInsertNode, mutateUpdateProperty } from "../tabs/transact.js";
|
|
18
15
|
import { view } from "../view.js";
|
|
19
16
|
import { startEditing, isEditableBlock } from "./inline-edit.js";
|
|
20
17
|
import { restoreTemplateExpressions } from "../utils/edit-display.js";
|
|
@@ -46,32 +43,24 @@ export function enterInlineEdit(el, path) {
|
|
|
46
43
|
/** @type {any} */ children,
|
|
47
44
|
/** @type {any} */ textContent,
|
|
48
45
|
) {
|
|
49
|
-
const
|
|
50
|
-
const node = getNodeAtPath(S.document, commitPath);
|
|
46
|
+
const node = getNodeAtPath(activeTab.value?.doc.document, commitPath);
|
|
51
47
|
if (children) {
|
|
52
48
|
if (node && JSON.stringify(node.children) === JSON.stringify(children)) return;
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
49
|
+
transactDoc(activeTab.value, (t) => {
|
|
50
|
+
mutateUpdateProperty(t, commitPath, "textContent", undefined);
|
|
51
|
+
mutateUpdateProperty(t, commitPath, "children", children);
|
|
52
|
+
});
|
|
56
53
|
} else if (textContent != null) {
|
|
57
54
|
if (node && node.textContent === textContent && !node.children) return;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
55
|
+
transactDoc(activeTab.value, (t) => {
|
|
56
|
+
mutateUpdateProperty(t, commitPath, "children", undefined);
|
|
57
|
+
mutateUpdateProperty(t, commitPath, "textContent", textContent);
|
|
58
|
+
});
|
|
61
59
|
}
|
|
62
60
|
},
|
|
63
61
|
|
|
64
62
|
onSplit(/** @type {any} */ splitPath, /** @type {any} */ before, /** @type {any} */ after) {
|
|
65
63
|
const tag = "p";
|
|
66
|
-
let s = getState();
|
|
67
|
-
|
|
68
|
-
if (before.textContent != null) {
|
|
69
|
-
s = updateProperty(s, splitPath, "children", undefined);
|
|
70
|
-
s = updateProperty(s, splitPath, "textContent", before.textContent);
|
|
71
|
-
} else if (before.children) {
|
|
72
|
-
s = updateProperty(s, splitPath, "textContent", undefined);
|
|
73
|
-
s = updateProperty(s, splitPath, "children", before.children);
|
|
74
|
-
}
|
|
75
64
|
|
|
76
65
|
// Insert new element after with "after" content
|
|
77
66
|
const parentPath = /** @type {any} */ (parentElementPath(splitPath));
|
|
@@ -86,10 +75,19 @@ export function enterInlineEdit(el, path) {
|
|
|
86
75
|
newNode.textContent = "";
|
|
87
76
|
}
|
|
88
77
|
|
|
89
|
-
s = insertNode(s, parentPath, idx + 1, newNode);
|
|
90
78
|
const newPath = [...parentPath, "children", idx + 1];
|
|
91
|
-
|
|
92
|
-
|
|
79
|
+
|
|
80
|
+
transactDoc(activeTab.value, (t) => {
|
|
81
|
+
if (before.textContent != null) {
|
|
82
|
+
mutateUpdateProperty(t, splitPath, "children", undefined);
|
|
83
|
+
mutateUpdateProperty(t, splitPath, "textContent", before.textContent);
|
|
84
|
+
} else if (before.children) {
|
|
85
|
+
mutateUpdateProperty(t, splitPath, "textContent", undefined);
|
|
86
|
+
mutateUpdateProperty(t, splitPath, "children", before.children);
|
|
87
|
+
}
|
|
88
|
+
mutateInsertNode(t, parentPath, idx + 1, newNode);
|
|
89
|
+
t.session.selection = newPath;
|
|
90
|
+
});
|
|
93
91
|
|
|
94
92
|
// Re-enter editing on the new element after render
|
|
95
93
|
requestAnimationFrame(() => {
|
|
@@ -125,17 +123,17 @@ export function enterInlineEdit(el, path) {
|
|
|
125
123
|
|
|
126
124
|
// If the element is empty, swap its tagName instead of inserting after
|
|
127
125
|
if (isEmpty) {
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
126
|
+
transactDoc(activeTab.value, (t) => {
|
|
127
|
+
mutateUpdateProperty(t, afterPath, "tagName", cmd.tag);
|
|
128
|
+
mutateUpdateProperty(t, afterPath, "children", undefined);
|
|
129
|
+
const def = defaultDef(cmd.tag);
|
|
130
|
+
if (def.textContent && def.textContent !== "Paragraph text") {
|
|
131
|
+
mutateUpdateProperty(t, afterPath, "textContent", def.textContent);
|
|
132
|
+
} else {
|
|
133
|
+
mutateUpdateProperty(t, afterPath, "textContent", undefined);
|
|
134
|
+
}
|
|
135
|
+
t.session.selection = afterPath;
|
|
136
|
+
});
|
|
139
137
|
|
|
140
138
|
requestAnimationFrame(() => {
|
|
141
139
|
const activePanel = getActivePanel();
|
|
@@ -152,23 +150,22 @@ export function enterInlineEdit(el, path) {
|
|
|
152
150
|
const elementDef = defaultDef(cmd.tag);
|
|
153
151
|
const parentPath = /** @type {any} */ (parentElementPath(afterPath));
|
|
154
152
|
const idx = /** @type {number} */ (childIndex(afterPath));
|
|
153
|
+
const newPath = [...parentPath, "children", idx + 1];
|
|
155
154
|
|
|
156
155
|
// Apply pending commit from inline edit first (batched to avoid double render)
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
156
|
+
transactDoc(activeTab.value, (t) => {
|
|
157
|
+
if (commitData) {
|
|
158
|
+
if (commitData.children) {
|
|
159
|
+
mutateUpdateProperty(t, afterPath, "textContent", undefined);
|
|
160
|
+
mutateUpdateProperty(t, afterPath, "children", commitData.children);
|
|
161
|
+
} else if (commitData.textContent != null) {
|
|
162
|
+
mutateUpdateProperty(t, afterPath, "children", undefined);
|
|
163
|
+
mutateUpdateProperty(t, afterPath, "textContent", commitData.textContent);
|
|
164
|
+
}
|
|
165
165
|
}
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const newPath = [...parentPath, "children", idx + 1];
|
|
170
|
-
s = selectNode(s, newPath);
|
|
171
|
-
update(s);
|
|
166
|
+
mutateInsertNode(t, parentPath, idx + 1, structuredClone(elementDef));
|
|
167
|
+
t.session.selection = newPath;
|
|
168
|
+
});
|
|
172
169
|
|
|
173
170
|
// If the inserted element is editable, enter editing
|
|
174
171
|
requestAnimationFrame(() => {
|