@jxsuite/studio 0.10.2 → 0.13.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/README.md +82 -0
- package/dist/studio.js +5114 -3424
- package/dist/studio.js.map +65 -49
- package/package.json +6 -3
- package/src/browse/browse.js +27 -3
- package/src/canvas/canvas-diff.js +184 -0
- package/src/canvas/canvas-helpers.js +10 -14
- package/src/canvas/canvas-live-render.js +136 -17
- package/src/canvas/canvas-render.js +154 -21
- package/src/canvas/canvas-utils.js +21 -23
- package/src/editor/component-inline-edit.js +54 -41
- package/src/editor/content-inline-edit.js +46 -47
- package/src/editor/context-menu.js +63 -39
- package/src/editor/convert-to-component.js +11 -14
- package/src/editor/insertion-helper.js +8 -10
- package/src/editor/shortcuts.js +69 -39
- package/src/files/components.js +15 -4
- package/src/files/files.js +72 -24
- package/src/panels/activity-bar.js +29 -7
- package/src/panels/block-action-bar.js +104 -80
- package/src/panels/canvas-dnd.js +132 -50
- package/src/panels/dnd.js +32 -28
- package/src/panels/editors.js +7 -14
- package/src/panels/elements-panel.js +9 -3
- package/src/panels/events-panel.js +44 -39
- package/src/panels/git-panel.js +45 -3
- package/src/panels/layers-panel.js +16 -11
- package/src/panels/left-panel.js +108 -43
- package/src/panels/overlays.js +97 -35
- package/src/panels/panel-events.js +18 -11
- package/src/panels/properties-panel.js +467 -98
- 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 +23 -8
- package/src/panels/style-inputs.js +4 -2
- package/src/panels/style-panel.js +128 -105
- package/src/panels/stylebook-panel.js +42 -17
- package/src/panels/tab-strip.js +124 -0
- package/src/panels/toolbar.js +39 -9
- package/src/reactivity.js +28 -0
- package/src/settings/content-types-editor.js +78 -8
- package/src/settings/defs-editor.js +56 -7
- package/src/settings/schema-field-ui.js +99 -11
- package/src/site-context.js +105 -0
- package/src/state.js +0 -456
- package/src/store.js +105 -124
- package/src/studio.js +112 -121
- package/src/tabs/tab.js +153 -0
- package/src/tabs/transact.js +406 -0
- package/src/ui/spectrum.js +2 -0
- package/src/view.js +3 -0
- package/src/workspace/workspace.js +89 -0
package/src/panels/dnd.js
CHANGED
|
@@ -16,16 +16,14 @@ import {
|
|
|
16
16
|
|
|
17
17
|
import {
|
|
18
18
|
getState,
|
|
19
|
-
update,
|
|
20
19
|
leftPanel,
|
|
21
|
-
moveNode,
|
|
22
|
-
insertNode,
|
|
23
|
-
applyMutation,
|
|
24
20
|
getNodeAtPath,
|
|
25
21
|
parentElementPath,
|
|
26
22
|
childIndex,
|
|
27
23
|
isAncestor,
|
|
28
24
|
} from "../store.js";
|
|
25
|
+
import { transact, transactDoc, mutateMoveNode, mutateInsertNode } from "../tabs/transact.js";
|
|
26
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
29
27
|
import { view } from "../view.js";
|
|
30
28
|
import { componentRegistry, computeRelativePath } from "../files/components.js";
|
|
31
29
|
import { renderComponentPreview } from "./stylebook-panel.js";
|
|
@@ -144,12 +142,14 @@ export function registerComponentsDnD() {
|
|
|
144
142
|
|
|
145
143
|
const instanceDef = {
|
|
146
144
|
tagName: comp.tagName,
|
|
147
|
-
$props:
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
145
|
+
$props: comp.props
|
|
146
|
+
? Object.fromEntries(
|
|
147
|
+
comp.props.map((/** @type {any} */ p) => [
|
|
148
|
+
p.name,
|
|
149
|
+
p.default !== undefined ? p.default : "",
|
|
150
|
+
]),
|
|
151
|
+
)
|
|
152
|
+
: {},
|
|
153
153
|
};
|
|
154
154
|
const cleanup = draggable({
|
|
155
155
|
element: row,
|
|
@@ -259,15 +259,17 @@ export function applyDropInstruction(instruction, srcData, targetPath) {
|
|
|
259
259
|
|
|
260
260
|
switch (instruction.type) {
|
|
261
261
|
case "reorder-above":
|
|
262
|
-
|
|
262
|
+
transactDoc(activeTab.value, (t) => mutateMoveNode(t, fromPath, targetParent, targetIdx));
|
|
263
263
|
break;
|
|
264
264
|
case "reorder-below":
|
|
265
|
-
|
|
265
|
+
transactDoc(activeTab.value, (t) =>
|
|
266
|
+
mutateMoveNode(t, fromPath, targetParent, targetIdx + 1),
|
|
267
|
+
);
|
|
266
268
|
break;
|
|
267
269
|
case "make-child": {
|
|
268
270
|
const target = getNodeAtPath(S.document, targetPath);
|
|
269
271
|
const len = target?.children?.length || 0;
|
|
270
|
-
|
|
272
|
+
transactDoc(activeTab.value, (t) => mutateMoveNode(t, fromPath, targetPath, len));
|
|
271
273
|
break;
|
|
272
274
|
}
|
|
273
275
|
}
|
|
@@ -277,15 +279,21 @@ export function applyDropInstruction(instruction, srcData, targetPath) {
|
|
|
277
279
|
|
|
278
280
|
switch (instruction.type) {
|
|
279
281
|
case "reorder-above":
|
|
280
|
-
|
|
282
|
+
transactDoc(activeTab.value, (t) =>
|
|
283
|
+
mutateInsertNode(t, targetParent, targetIdx, structuredClone(srcData.fragment)),
|
|
284
|
+
);
|
|
281
285
|
break;
|
|
282
286
|
case "reorder-below":
|
|
283
|
-
|
|
287
|
+
transactDoc(activeTab.value, (t) =>
|
|
288
|
+
mutateInsertNode(t, targetParent, targetIdx + 1, structuredClone(srcData.fragment)),
|
|
289
|
+
);
|
|
284
290
|
break;
|
|
285
291
|
case "make-child": {
|
|
286
292
|
const target = getNodeAtPath(S.document, targetPath);
|
|
287
293
|
const len = target?.children?.length || 0;
|
|
288
|
-
|
|
294
|
+
transactDoc(activeTab.value, (t) =>
|
|
295
|
+
mutateInsertNode(t, targetPath, len, structuredClone(srcData.fragment)),
|
|
296
|
+
);
|
|
289
297
|
break;
|
|
290
298
|
}
|
|
291
299
|
}
|
|
@@ -303,12 +311,10 @@ export function applyDropInstruction(instruction, srcData, targetPath) {
|
|
|
303
311
|
(/** @type {any} */ e) => e === specifier || e === comp.package,
|
|
304
312
|
);
|
|
305
313
|
if (!alreadyImported) {
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
}),
|
|
311
|
-
);
|
|
314
|
+
transact(activeTab.value, (/** @type {any} */ doc) => {
|
|
315
|
+
if (!doc.$elements) doc.$elements = [];
|
|
316
|
+
doc.$elements.push(specifier);
|
|
317
|
+
});
|
|
312
318
|
}
|
|
313
319
|
} else {
|
|
314
320
|
const alreadyImported = elements.some(
|
|
@@ -318,12 +324,10 @@ export function applyDropInstruction(instruction, srcData, targetPath) {
|
|
|
318
324
|
);
|
|
319
325
|
if (!alreadyImported) {
|
|
320
326
|
const relPath = computeRelativePath(currentS.documentPath, comp.path);
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
}),
|
|
326
|
-
);
|
|
327
|
+
transact(activeTab.value, (/** @type {any} */ doc) => {
|
|
328
|
+
if (!doc.$elements) doc.$elements = [];
|
|
329
|
+
doc.$elements.push({ $ref: relPath });
|
|
330
|
+
});
|
|
327
331
|
}
|
|
328
332
|
}
|
|
329
333
|
}
|
package/src/panels/editors.js
CHANGED
|
@@ -7,16 +7,9 @@ import * as monaco from "monaco-editor/esm/vs/editor/editor.api.js";
|
|
|
7
7
|
import { html, render as litRender, nothing } from "lit-html";
|
|
8
8
|
import { ref } from "lit-html/directives/ref.js";
|
|
9
9
|
|
|
10
|
-
import {
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
renderOnly,
|
|
14
|
-
canvasWrap,
|
|
15
|
-
canvasPanels,
|
|
16
|
-
updateDef,
|
|
17
|
-
updateProperty,
|
|
18
|
-
getNodeAtPath,
|
|
19
|
-
} from "../store.js";
|
|
10
|
+
import { getState, renderOnly, canvasWrap, canvasPanels, getNodeAtPath } from "../store.js";
|
|
11
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
12
|
+
import { transactDoc, mutateUpdateDef, mutateUpdateProperty } from "../tabs/transact.js";
|
|
20
13
|
import { view } from "../view.js";
|
|
21
14
|
import { codeService, setLintMarkers, getFunctionArgs } from "../services/code-services.js";
|
|
22
15
|
|
|
@@ -126,15 +119,15 @@ export function renderFunctionEditor() {
|
|
|
126
119
|
|
|
127
120
|
clearTimeout(syncDebounce);
|
|
128
121
|
syncDebounce = setTimeout(() => {
|
|
129
|
-
const S = getState();
|
|
130
122
|
const newBody = view.functionEditor.getValue();
|
|
131
123
|
if (editing.type === "def") {
|
|
132
|
-
|
|
124
|
+
transactDoc(activeTab.value, (t) => mutateUpdateDef(t, editing.defName, { body: newBody }));
|
|
133
125
|
} else if (editing.type === "event") {
|
|
126
|
+
const S = getState();
|
|
134
127
|
const node = getNodeAtPath(S.document, editing.path);
|
|
135
128
|
const current = node?.[editing.eventKey] || {};
|
|
136
|
-
|
|
137
|
-
|
|
129
|
+
transactDoc(activeTab.value, (t) =>
|
|
130
|
+
mutateUpdateProperty(t, editing.path, editing.eventKey, {
|
|
138
131
|
...current,
|
|
139
132
|
$prototype: "Function",
|
|
140
133
|
body: newBody,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/** Elements panel — block/component palette with categorized accordion and search filter. */
|
|
2
2
|
|
|
3
3
|
import { html, nothing } from "lit-html";
|
|
4
|
-
import { getState,
|
|
4
|
+
import { getState, getNodeAtPath } from "../store.js";
|
|
5
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
6
|
+
import { transactDoc, mutateInsertNode } from "../tabs/transact.js";
|
|
5
7
|
import { view } from "../view.js";
|
|
6
8
|
import { getEffectiveElements } from "../site-context.js";
|
|
7
9
|
import { componentRegistry } from "../files/components.js";
|
|
@@ -40,7 +42,9 @@ export function renderElementsTemplate(ctx) {
|
|
|
40
42
|
const parentPath = s.selection || [];
|
|
41
43
|
const parent = getNodeAtPath(s.document, parentPath);
|
|
42
44
|
const idx = parent?.children ? parent.children.length : 0;
|
|
43
|
-
|
|
45
|
+
transactDoc(activeTab.value, (t) =>
|
|
46
|
+
mutateInsertNode(t, parentPath, idx, structuredClone(def)),
|
|
47
|
+
);
|
|
44
48
|
}}
|
|
45
49
|
>
|
|
46
50
|
<div class="element-card-preview"></div>
|
|
@@ -114,7 +118,9 @@ export function renderElementsTemplate(ctx) {
|
|
|
114
118
|
]),
|
|
115
119
|
),
|
|
116
120
|
};
|
|
117
|
-
|
|
121
|
+
transactDoc(activeTab.value, (t) =>
|
|
122
|
+
mutateInsertNode(t, parentPath, idx, structuredClone(instanceDef)),
|
|
123
|
+
);
|
|
118
124
|
}}
|
|
119
125
|
>
|
|
120
126
|
<div class="element-card-preview">
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { getNodeAtPath
|
|
1
|
+
import { getNodeAtPath } from "../store.js";
|
|
2
2
|
import { html, nothing } from "lit-html";
|
|
3
3
|
import { live } from "lit-html/directives/live.js";
|
|
4
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
5
|
+
import { transactDoc, mutateUpdateProperty } from "../tabs/transact.js";
|
|
4
6
|
|
|
5
7
|
export const EVENT_NAMES = [
|
|
6
8
|
"onclick",
|
|
@@ -15,17 +17,17 @@ export const EVENT_NAMES = [
|
|
|
15
17
|
"onmouseleave",
|
|
16
18
|
];
|
|
17
19
|
|
|
18
|
-
/**
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
const
|
|
24
|
-
if (!
|
|
25
|
-
const node = getNodeAtPath(
|
|
20
|
+
/** @param {{ isCustomElementDoc: () => boolean }} helpers */
|
|
21
|
+
export function eventsSidebarTemplate(helpers) {
|
|
22
|
+
const { isCustomElementDoc } = helpers;
|
|
23
|
+
const tab = activeTab.value;
|
|
24
|
+
const selection = tab?.session.selection;
|
|
25
|
+
const document = tab?.doc.document;
|
|
26
|
+
if (!selection) return html`<div class="empty-state">Select an element to edit events</div>`;
|
|
27
|
+
const node = getNodeAtPath(document, selection);
|
|
26
28
|
if (!node) return html`<div class="empty-state">Node not found</div>`;
|
|
27
29
|
|
|
28
|
-
const defs =
|
|
30
|
+
const defs = document.state || {};
|
|
29
31
|
const functionDefs = Object.entries(defs).filter(
|
|
30
32
|
([, d]) => d.$prototype === "Function" || d.$handler,
|
|
31
33
|
);
|
|
@@ -87,9 +89,10 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
87
89
|
@change=${(/** @type {any} */ e) => {
|
|
88
90
|
const newKey = e.target.value;
|
|
89
91
|
if (newKey && newKey !== evKey) {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
92
|
+
transactDoc(activeTab.value, (t) => {
|
|
93
|
+
mutateUpdateProperty(t, selection, evKey, undefined);
|
|
94
|
+
mutateUpdateProperty(t, selection, newKey, node[evKey]);
|
|
95
|
+
});
|
|
93
96
|
}
|
|
94
97
|
}}
|
|
95
98
|
>
|
|
@@ -103,8 +106,8 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
103
106
|
.value=${live(isInline ? "inline" : "ref")}
|
|
104
107
|
@change=${(/** @type {any} */ e) => {
|
|
105
108
|
if (e.target.value === "inline") {
|
|
106
|
-
|
|
107
|
-
|
|
109
|
+
transactDoc(activeTab.value, (t) =>
|
|
110
|
+
mutateUpdateProperty(t, selection, evKey, {
|
|
108
111
|
$prototype: "Function",
|
|
109
112
|
body: "",
|
|
110
113
|
parameters: [],
|
|
@@ -112,10 +115,10 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
112
115
|
);
|
|
113
116
|
} else {
|
|
114
117
|
const firstFn = functionDefs[0];
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
118
|
+
transactDoc(activeTab.value, (t) =>
|
|
119
|
+
mutateUpdateProperty(
|
|
120
|
+
t,
|
|
121
|
+
selection,
|
|
119
122
|
evKey,
|
|
120
123
|
firstFn ? { $ref: `#/state/${firstFn[0]}` } : { $ref: "" },
|
|
121
124
|
),
|
|
@@ -129,7 +132,10 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
129
132
|
<sp-action-button
|
|
130
133
|
size="xs"
|
|
131
134
|
quiet
|
|
132
|
-
@click=${() =>
|
|
135
|
+
@click=${() =>
|
|
136
|
+
transactDoc(activeTab.value, (t) =>
|
|
137
|
+
mutateUpdateProperty(t, selection, evKey, undefined),
|
|
138
|
+
)}
|
|
133
139
|
>
|
|
134
140
|
<sp-icon-delete slot="icon"></sp-icon-delete>
|
|
135
141
|
</sp-action-button>
|
|
@@ -144,8 +150,8 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
144
150
|
placeholder="// handler body"
|
|
145
151
|
.value=${live(evVal.body || "")}
|
|
146
152
|
@input=${(/** @type {any} */ e) => {
|
|
147
|
-
|
|
148
|
-
|
|
153
|
+
transactDoc(activeTab.value, (t) =>
|
|
154
|
+
mutateUpdateProperty(t, selection, evKey, {
|
|
149
155
|
$prototype: "Function",
|
|
150
156
|
body: e.target.value,
|
|
151
157
|
parameters: evVal.parameters || [],
|
|
@@ -159,18 +165,11 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
159
165
|
quiet
|
|
160
166
|
title="Open in editor"
|
|
161
167
|
@click=${() => {
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
editingFunction: {
|
|
167
|
-
type: "event",
|
|
168
|
-
path: S.selection,
|
|
169
|
-
eventKey: evKey,
|
|
170
|
-
},
|
|
171
|
-
},
|
|
168
|
+
tab.session.ui.editingFunction = {
|
|
169
|
+
type: "event",
|
|
170
|
+
path: selection,
|
|
171
|
+
eventKey: evKey,
|
|
172
172
|
};
|
|
173
|
-
renderCanvas();
|
|
174
173
|
}}
|
|
175
174
|
>
|
|
176
175
|
<sp-icon-code slot="icon"></sp-icon-code>
|
|
@@ -184,9 +183,13 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
184
183
|
.value=${live(evVal.$ref || "__none__")}
|
|
185
184
|
@change=${(/** @type {any} */ e) => {
|
|
186
185
|
if (e.target.value && e.target.value !== "__none__") {
|
|
187
|
-
|
|
186
|
+
transactDoc(activeTab.value, (t) =>
|
|
187
|
+
mutateUpdateProperty(t, selection, evKey, { $ref: e.target.value }),
|
|
188
|
+
);
|
|
188
189
|
} else {
|
|
189
|
-
|
|
190
|
+
transactDoc(activeTab.value, (t) =>
|
|
191
|
+
mutateUpdateProperty(t, selection, evKey, undefined),
|
|
192
|
+
);
|
|
190
193
|
}
|
|
191
194
|
}}
|
|
192
195
|
>
|
|
@@ -212,12 +215,14 @@ export function eventsSidebarTemplate(S, helpers) {
|
|
|
212
215
|
}
|
|
213
216
|
}
|
|
214
217
|
if (functionDefs.length > 0) {
|
|
215
|
-
|
|
216
|
-
|
|
218
|
+
transactDoc(activeTab.value, (t) =>
|
|
219
|
+
mutateUpdateProperty(t, selection, evName, {
|
|
220
|
+
$ref: `#/state/${functionDefs[0][0]}`,
|
|
221
|
+
}),
|
|
217
222
|
);
|
|
218
223
|
} else {
|
|
219
|
-
|
|
220
|
-
|
|
224
|
+
transactDoc(activeTab.value, (t) =>
|
|
225
|
+
mutateUpdateProperty(t, selection, evName, {
|
|
221
226
|
$prototype: "Function",
|
|
222
227
|
body: "",
|
|
223
228
|
parameters: [],
|
package/src/panels/git-panel.js
CHANGED
|
@@ -44,8 +44,11 @@ async function gitAction(action, body) {
|
|
|
44
44
|
|
|
45
45
|
let _pollTimer = /** @type {any} */ (null);
|
|
46
46
|
|
|
47
|
-
/**
|
|
48
|
-
|
|
47
|
+
/**
|
|
48
|
+
* @param {any} S
|
|
49
|
+
* @param {any} ctx
|
|
50
|
+
*/
|
|
51
|
+
export function renderGitPanel(S, ctx) {
|
|
49
52
|
const status = S.ui.gitStatus;
|
|
50
53
|
const branches = S.ui.gitBranches;
|
|
51
54
|
const loading = S.ui.gitLoading;
|
|
@@ -156,9 +159,48 @@ export function renderGitPanel(S) {
|
|
|
156
159
|
const parts = file.path.split("/");
|
|
157
160
|
const name = parts.pop();
|
|
158
161
|
const dir = parts.join("/");
|
|
162
|
+
|
|
163
|
+
const onFileClick = async () => {
|
|
164
|
+
// Only support diff for modified/added files
|
|
165
|
+
if (file.status !== "M" && file.status !== "A") return;
|
|
166
|
+
if (!file.path.endsWith(".md") && !file.path.endsWith(".json")) return;
|
|
167
|
+
|
|
168
|
+
try {
|
|
169
|
+
const plat = getPlatform();
|
|
170
|
+
updateUi("gitLoading", true);
|
|
171
|
+
const originalContent = await plat.gitShow({ path: file.path, ref: "HEAD" });
|
|
172
|
+
|
|
173
|
+
// Determine if it's markdown or JSON
|
|
174
|
+
const isMarkdown = file.path.endsWith(".md");
|
|
175
|
+
|
|
176
|
+
// For now, we'll need to pass the original content to the canvas
|
|
177
|
+
// This requires state management which we'll add to studio.js
|
|
178
|
+
updateUi("gitDiffState", {
|
|
179
|
+
filePath: file.path,
|
|
180
|
+
originalContent,
|
|
181
|
+
isMarkdown,
|
|
182
|
+
fileStatus: file.status,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
// Trigger diff mode via context
|
|
186
|
+
if (ctx?.setCanvasMode) {
|
|
187
|
+
ctx.setCanvasMode("git-diff");
|
|
188
|
+
}
|
|
189
|
+
} catch (/** @type {any} */ e) {
|
|
190
|
+
updateUi("gitError", `Failed to load diff: ${e.message}`);
|
|
191
|
+
} finally {
|
|
192
|
+
updateUi("gitLoading", false);
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
|
|
159
196
|
return html`
|
|
160
197
|
<div class="git-file-row">
|
|
161
|
-
<span
|
|
198
|
+
<span
|
|
199
|
+
class="git-file-info"
|
|
200
|
+
style="cursor: pointer; flex: 1;"
|
|
201
|
+
title="Click to view diff"
|
|
202
|
+
@click=${onFileClick}
|
|
203
|
+
>
|
|
162
204
|
<span class="git-file-name" title=${file.path}>${name}</span>
|
|
163
205
|
${dir ? html`<span class="git-file-dir">${dir}</span>` : nothing}
|
|
164
206
|
</span>
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
import { html, nothing } from "lit-html";
|
|
7
7
|
import {
|
|
8
8
|
getState,
|
|
9
|
-
update,
|
|
10
9
|
flattenTree,
|
|
11
10
|
getNodeAtPath,
|
|
12
11
|
pathKey,
|
|
@@ -14,11 +13,10 @@ import {
|
|
|
14
13
|
parentElementPath,
|
|
15
14
|
childIndex,
|
|
16
15
|
nodeLabel,
|
|
17
|
-
selectNode,
|
|
18
|
-
moveNode,
|
|
19
|
-
removeNode,
|
|
20
16
|
VOID_ELEMENTS,
|
|
21
17
|
} from "../store.js";
|
|
18
|
+
import { activeTab } from "../workspace/workspace.js";
|
|
19
|
+
import { transactDoc, mutateMoveNode, mutateRemoveNode } from "../tabs/transact.js";
|
|
22
20
|
import { view } from "../view.js";
|
|
23
21
|
import { isInlineElement } from "../editor/inline-edit.js";
|
|
24
22
|
import { showContextMenu } from "../editor/context-menu.js";
|
|
@@ -34,7 +32,8 @@ export function renderLayersTemplate(ctx) {
|
|
|
34
32
|
view.dndCleanups = [];
|
|
35
33
|
|
|
36
34
|
const rows = flattenTree(S.document);
|
|
37
|
-
const
|
|
35
|
+
const _S = /** @type {any} */ (S);
|
|
36
|
+
const collapsed = _S._collapsed || (_S._collapsed = new Set());
|
|
38
37
|
|
|
39
38
|
/** @type {any[]} */
|
|
40
39
|
const layerRows = [];
|
|
@@ -142,7 +141,7 @@ export function renderLayersTemplate(ctx) {
|
|
|
142
141
|
data-dnd-row=${isElement ? key : nothing}
|
|
143
142
|
data-dnd-depth=${isElement ? depth : nothing}
|
|
144
143
|
data-dnd-void=${isElement && isVoidEl ? "" : nothing}
|
|
145
|
-
@click=${() =>
|
|
144
|
+
@click=${() => (activeTab.value.session.selection = path)}
|
|
146
145
|
@contextmenu=${isElement
|
|
147
146
|
? (/** @type {any} */ e) =>
|
|
148
147
|
showContextMenu(e, path, getState(), {
|
|
@@ -175,7 +174,9 @@ export function renderLayersTemplate(ctx) {
|
|
|
175
174
|
@click=${(/** @type {any} */ e) => {
|
|
176
175
|
e.stopPropagation();
|
|
177
176
|
/** @type {HTMLElement} */ (e.currentTarget).blur();
|
|
178
|
-
|
|
177
|
+
transactDoc(activeTab.value, (t) =>
|
|
178
|
+
mutateMoveNode(t, path, parentPath, idx - 1),
|
|
179
|
+
);
|
|
179
180
|
}}
|
|
180
181
|
>
|
|
181
182
|
<sp-icon-arrow-up slot="icon"></sp-icon-arrow-up>
|
|
@@ -189,7 +190,9 @@ export function renderLayersTemplate(ctx) {
|
|
|
189
190
|
@click=${(/** @type {any} */ e) => {
|
|
190
191
|
e.stopPropagation();
|
|
191
192
|
/** @type {HTMLElement} */ (e.currentTarget).blur();
|
|
192
|
-
|
|
193
|
+
transactDoc(activeTab.value, (t) =>
|
|
194
|
+
mutateMoveNode(t, path, parentPath, idx + 2),
|
|
195
|
+
);
|
|
193
196
|
}}
|
|
194
197
|
>
|
|
195
198
|
<sp-icon-arrow-down slot="icon"></sp-icon-arrow-down>
|
|
@@ -206,7 +209,7 @@ export function renderLayersTemplate(ctx) {
|
|
|
206
209
|
const prevPath = [...parentPath, idx - 1];
|
|
207
210
|
const prev = getNodeAtPath(getState().document, prevPath);
|
|
208
211
|
const len = prev?.children?.length || 0;
|
|
209
|
-
|
|
212
|
+
transactDoc(activeTab.value, (t) => mutateMoveNode(t, path, prevPath, len));
|
|
210
213
|
}}
|
|
211
214
|
>
|
|
212
215
|
<sp-icon-arrow-right slot="icon"></sp-icon-arrow-right>
|
|
@@ -221,7 +224,9 @@ export function renderLayersTemplate(ctx) {
|
|
|
221
224
|
e.stopPropagation();
|
|
222
225
|
/** @type {HTMLElement} */ (e.currentTarget).blur();
|
|
223
226
|
const parentIdx = /** @type {number} */ (childIndex(parentPath));
|
|
224
|
-
|
|
227
|
+
transactDoc(activeTab.value, (t) =>
|
|
228
|
+
mutateMoveNode(t, path, grandparentPath, parentIdx + 1),
|
|
229
|
+
);
|
|
225
230
|
}}
|
|
226
231
|
>
|
|
227
232
|
<sp-icon-arrow-left slot="icon"></sp-icon-arrow-left>
|
|
@@ -234,7 +239,7 @@ export function renderLayersTemplate(ctx) {
|
|
|
234
239
|
title="Delete"
|
|
235
240
|
@click=${(/** @type {any} */ e) => {
|
|
236
241
|
e.stopPropagation();
|
|
237
|
-
|
|
242
|
+
transactDoc(activeTab.value, (t) => mutateRemoveNode(t, path));
|
|
238
243
|
}}
|
|
239
244
|
>
|
|
240
245
|
<sp-icon-close slot="icon"></sp-icon-close>
|