@jxsuite/studio 3.0.0 → 4.0.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 +5 -5
- package/dist/chunks/Overlay.dev-723bv0df.js +23 -0
- package/dist/chunks/{cf-settings-zj2cj1ar.js → cf-settings-45fgyx8y.js} +6 -5
- package/dist/chunks/{components-z6cnkyy1.js → components-zmx10t62.js} +6 -5
- package/dist/chunks/content-source-t88vb2dr.js +49 -0
- package/dist/chunks/{convert-to-repeater-6vvx96n2.js → convert-to-repeater-dhw1nrz9.js} +27 -19
- package/dist/chunks/entry-commands-6z6bhxg0.js +46 -0
- package/dist/chunks/{extension-sections-kwzvpemr.js → extension-sections-3ydgjbdy.js} +32 -24
- package/dist/chunks/file-ops-rskmhxyq.js +48 -0
- package/dist/chunks/files-0cratsr0.js +92 -0
- package/dist/chunks/{format-host-8fr3545e.js → format-host-tgcmfs4p.js} +3 -3
- package/dist/chunks/fs-events-hrrg328g.js +21 -0
- package/dist/chunks/{git-panel-g01d93vc.js → git-panel-0yywyk76.js} +21 -16
- package/dist/chunks/{jx-validate-jj9rnt4n.js → jx-validate-8q2g05x1.js} +6 -4
- package/dist/chunks/layers-panel-z3tqe5cd.js +67 -0
- package/dist/chunks/layers-q75tj2mf.js +45 -0
- package/dist/chunks/lit-html-j055mkh8.js +22 -0
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +25 -0
- package/dist/chunks/{monaco-setup-a5wkmbgh.js → monaco-setup-rws7k4br.js} +4 -4
- package/dist/chunks/notify-yjm79n4s.js +30 -0
- package/dist/chunks/parse-24d0gay3.js +19 -0
- package/dist/chunks/platform-ba1j1gbh.js +16 -0
- package/dist/chunks/publish-panel-54jvhskq.js +28 -0
- package/dist/chunks/quick-search-cgfmjwq5.js +65 -0
- package/dist/chunks/references-3qx8fkyp.js +29 -0
- package/dist/chunks/right-panel-cqp8bc4v.js +46 -0
- package/dist/chunks/sp-overlay.dev-yztmtrs1.js +18 -0
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +9 -0
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +15 -0
- package/dist/chunks/sp-tooltip.dev-xcvpnqr0.js +15 -0
- package/dist/chunks/{sp-tray.dev-64v4pxw8.js → sp-tray.dev-tkbscm06.js} +5 -5
- package/dist/chunks/{studio-8ezdegcx.js → studio-1hbqnt19.js} +36 -32
- package/dist/chunks/{studio-r5xbtctf.js → studio-2zkz8evn.js} +446 -2451
- package/dist/chunks/{studio-pkp61mh8.js → studio-4pqqxbrt.js} +23 -15
- package/dist/chunks/{studio-kvfx9z2c.js → studio-4rzyrtjz.js} +70 -31
- package/dist/chunks/{studio-3dkcd4c5.js → studio-5q69gfag.js} +60 -56
- package/dist/chunks/{studio-rh1cnamv.js → studio-5rywrkxz.js} +563 -133
- package/dist/chunks/{studio-6kv3apa9.js → studio-68n67094.js} +25 -9
- package/dist/chunks/{studio-0rqqhrdy.js → studio-7nte2hj4.js} +2 -2
- package/dist/chunks/{studio-xntfdy1x.js → studio-8swrjbny.js} +31 -18
- package/dist/chunks/studio-92ab2jqe.js +282 -0
- package/dist/chunks/{studio-sas7mt3k.js → studio-9ab8gqsm.js} +2 -2
- package/dist/chunks/{studio-ry1vz5sv.js → studio-9c4k4vhv.js} +15 -13
- package/dist/chunks/studio-9n4mrmnb.js +184 -0
- package/dist/chunks/{studio-tr20m8g8.js → studio-9r6j5ev1.js} +37 -2
- package/dist/chunks/{studio-2x9zbxmx.js → studio-ahjfdy6e.js} +9 -7
- package/dist/chunks/{studio-s519zc99.js → studio-bgxt93ga.js} +3 -3
- package/dist/chunks/{studio-dc8s8heb.js → studio-cb12yz9w.js} +8528 -8780
- package/dist/chunks/studio-cft9r4r7.js +119 -0
- package/dist/chunks/{studio-hcxzyk3x.js → studio-eenfkt4e.js} +6 -6
- package/dist/chunks/studio-eesa1myv.js +498 -0
- package/dist/chunks/{studio-ay8wcr2b.js → studio-eqq1w638.js} +7 -9
- package/dist/chunks/{studio-7p35254k.js → studio-ex8zyp98.js} +30 -26
- package/dist/chunks/studio-gv8vvshc.js +118 -0
- package/dist/chunks/studio-hbtp0eh1.js +1315 -0
- package/dist/chunks/{studio-a0yp7syn.js → studio-htsf0w6m.js} +29 -114
- package/dist/chunks/{studio-j595e748.js → studio-kjjsjak4.js} +139 -63
- package/dist/chunks/{studio-5x5774ak.js → studio-kryvsw6j.js} +3 -3
- package/dist/chunks/{studio-kfpek536.js → studio-kyh9avvv.js} +2 -2
- package/dist/chunks/{studio-g5gdqnyd.js → studio-kyk2v92a.js} +14 -14
- package/dist/chunks/{studio-twsafr1e.js → studio-m3hwn7y1.js} +3 -3
- package/dist/chunks/{studio-tzx3xmvx.js → studio-mmv72a27.js} +8 -8
- package/dist/chunks/{studio-vhk5fmfv.js → studio-n8b9wqwy.js} +5 -5
- package/dist/chunks/{studio-cjm7fdjf.js → studio-p4ngc046.js} +8 -104
- package/dist/chunks/{studio-p5dja96s.js → studio-p8j86wag.js} +2 -2
- package/dist/chunks/{studio-6z5eyjwn.js → studio-pdfjntbk.js} +66 -129
- package/dist/chunks/studio-q43a5y9h.js +394 -0
- package/dist/chunks/studio-q7v10cg2.js +106 -0
- package/dist/chunks/{studio-2w11grav.js → studio-qq6jym04.js} +3 -3
- package/dist/chunks/studio-r1r7afxx.js +1066 -0
- package/dist/chunks/{studio-3fk1ac9z.js → studio-rdx8jcxy.js} +4 -4
- package/dist/chunks/{studio-4mqb9a0j.js → studio-rn9ta2mz.js} +4 -4
- package/dist/chunks/studio-sf7zjgv1.js +91 -0
- package/dist/chunks/studio-t7qb9db8.js +665 -0
- package/dist/chunks/studio-tmc5emrw.js +8 -0
- package/dist/chunks/{studio-wdt9y92a.js → studio-txwkm6p9.js} +2 -2
- package/dist/chunks/{studio-k4jvjcfx.js → studio-v38hmvx1.js} +7 -7
- package/dist/chunks/{studio-7ejemhej.js → studio-vadzgkrz.js} +6 -6
- package/dist/chunks/studio-wcy8trfx.js +263 -0
- package/dist/chunks/{studio-5efrtn1m.js → studio-wx5609xd.js} +21 -17
- package/dist/chunks/{studio-qpfq7xhm.js → studio-xrapxwwc.js} +22 -285
- package/dist/chunks/{studio-hj2se583.js → studio-yxrkyv8a.js} +41 -31
- package/dist/chunks/{studio-xm3dbxvn.js → studio-zczps70q.js} +2 -2
- package/dist/chunks/workspace-xpres40v.js +89 -0
- package/dist/iframe-entry.js +108 -24
- package/dist/studio.js +2362 -1695
- package/package.json +16 -15
- package/src/browse/library-pane.ts +57 -3
- package/src/canvas/canvas-render.ts +23 -1
- package/src/canvas/iframe-patch.ts +47 -21
- package/src/canvas/iframe-render.ts +22 -6
- package/src/commands/app-commands.ts +4 -0
- package/src/commands/command-args.ts +29 -0
- package/src/commands/context.ts +15 -1
- package/src/commands/defaults.ts +29 -1
- package/src/commands/levels.ts +16 -0
- package/src/commands/live-context.ts +3 -0
- package/src/content/collection-match.ts +267 -0
- package/src/content/entry-commands.ts +38 -29
- package/src/content/entry-fields.ts +6 -0
- package/src/editor/shortcuts.ts +5 -0
- package/src/files/file-ops.ts +10 -42
- package/src/files/files.ts +485 -59
- package/src/files/fs-events.ts +9 -0
- package/src/files/gitignore.ts +432 -0
- package/src/files/serialize-document.ts +60 -0
- package/src/format/convert-file.ts +511 -0
- package/src/format/format-choices.ts +199 -0
- package/src/grid/grid-view.ts +16 -2
- package/src/media/media-open.ts +58 -0
- package/src/media/media-pane.ts +310 -0
- package/src/new-project/import-tab.ts +332 -160
- package/src/new-project/new-project-modal.ts +27 -34
- package/src/packages/ensure-deps.ts +14 -7
- package/src/packages/jxsuite-update.ts +11 -11
- package/src/page-params.ts +10 -46
- package/src/panels/activity-bar.ts +45 -16
- package/src/panels/ai-chat/attached-context.ts +6 -1
- package/src/panels/ai-chat/chat-view.ts +255 -13
- package/src/panels/ai-chat/composer.ts +21 -97
- package/src/panels/ai-panel.ts +116 -2
- package/src/panels/navigator-panels.ts +7 -6
- package/src/panels/settings-menu.ts +799 -0
- package/src/panels/toolbar.ts +135 -15
- package/src/platforms/cloud.ts +20 -0
- package/src/platforms/devserver.ts +67 -33
- package/src/preview/preview-overlay.ts +226 -0
- package/src/services/ai-ask.ts +247 -0
- package/src/services/ai-import-tools.ts +494 -0
- package/src/services/ai-project-tools.ts +20 -26
- package/src/services/ai-system-prompt.ts +88 -2
- package/src/services/ai-turn-signal.ts +70 -0
- package/src/services/connection.ts +74 -0
- package/src/services/context-manager.ts +89 -0
- package/src/services/document-assistant.ts +45 -4
- package/src/services/import-client.ts +33 -6
- package/src/services/import-run.ts +158 -0
- package/src/services/import-seed.ts +120 -0
- package/src/services/jx-validate.ts +58 -6
- package/src/services/project-adoption.ts +71 -0
- package/src/services/references.ts +0 -0
- package/src/services/settings/definitions.ts +17 -0
- package/src/services/tool-executor.ts +34 -2
- package/src/settings/contexts-section.ts +45 -3
- package/src/settings/dependencies-editor.ts +43 -23
- package/src/settings/general-settings.ts +30 -12
- package/src/settings/preferences-dialog.ts +18 -41
- package/src/settings/preferences-sections.ts +57 -0
- package/src/settings/settings-document.ts +65 -9
- package/src/studio.ts +33 -6
- package/src/tabs/transact.ts +42 -19
- package/src/types.ts +103 -5
- package/src/ui/ai-model-picker.ts +162 -0
- package/src/ui/choice-field.ts +72 -0
- package/src/ui/layers.ts +83 -5
- package/src/utils/studio-utils.ts +22 -52
- package/styles/forced-colors.css +7 -0
- package/styles/overlays.css +256 -0
- package/styles/panels.css +13 -1
- package/styles/shell.css +111 -0
- package/dist/chunks/Overlay.dev-d2ajy6sj.js +0 -23
- package/dist/chunks/content-source-7fy9qrm0.js +0 -40
- package/dist/chunks/files-xcybanxe.js +0 -70
- package/dist/chunks/layers-panel-27essgkc.js +0 -60
- package/dist/chunks/publish-panel-09sy2bab.js +0 -22
- package/dist/chunks/quick-search-sefb61v8.js +0 -55
- package/dist/chunks/right-panel-9r32jd5j.js +0 -39
- package/dist/chunks/sp-overlay.dev-s18hymn9.js +0 -18
- package/dist/chunks/sp-popover.dev-dj9x7e7a.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-0zxcyz3r.js +0 -15
- package/dist/chunks/sp-tooltip.dev-5c6d1kjz.js +0 -15
- package/dist/chunks/studio-c31yb4t6.js +0 -55
- package/src/canvas/site-style-css.ts +0 -117
|
@@ -1,69 +1,46 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
} from "./studio-kvfx9z2c.js";
|
|
2
|
+
commitTabBuffers
|
|
3
|
+
} from "./studio-wcy8trfx.js";
|
|
5
4
|
import {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
computed,
|
|
6
|
+
effect,
|
|
7
|
+
effectScope,
|
|
8
|
+
notify,
|
|
9
|
+
onScopeDispose,
|
|
10
|
+
reactive,
|
|
11
|
+
toRaw
|
|
12
|
+
} from "./studio-xrapxwwc.js";
|
|
13
|
+
import {
|
|
14
|
+
applyDocOpToDoc,
|
|
15
|
+
childArray,
|
|
16
|
+
cloneValue
|
|
17
|
+
} from "./studio-5ehhackm.js";
|
|
10
18
|
import {
|
|
11
19
|
childIndex,
|
|
12
|
-
ensureNestedStyle,
|
|
13
|
-
getNestedStyle,
|
|
14
20
|
getNodeAtPath,
|
|
15
21
|
isAncestor,
|
|
16
|
-
isEventBinding,
|
|
17
22
|
normalizeArrayChildren,
|
|
18
23
|
parentElementPath,
|
|
19
24
|
pathsEqual,
|
|
20
|
-
projectState
|
|
21
|
-
|
|
22
|
-
setProjectState
|
|
23
|
-
} from "./studio-cjm7fdjf.js";
|
|
25
|
+
projectState
|
|
26
|
+
} from "./studio-p4ngc046.js";
|
|
24
27
|
import {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
effectScope,
|
|
30
|
-
notify,
|
|
31
|
-
onScopeDispose,
|
|
32
|
-
pinClock,
|
|
33
|
-
reactive,
|
|
34
|
-
readStoredSetting,
|
|
35
|
-
setSetting,
|
|
36
|
-
shallowRef,
|
|
37
|
-
toRaw,
|
|
38
|
-
toasts
|
|
39
|
-
} from "./studio-qpfq7xhm.js";
|
|
28
|
+
ensureNestedStyle,
|
|
29
|
+
getNestedStyle,
|
|
30
|
+
isEventBinding
|
|
31
|
+
} from "./studio-q7v10cg2.js";
|
|
40
32
|
import {
|
|
41
33
|
defaultContentFormat,
|
|
42
34
|
formatByName,
|
|
43
|
-
formatForPath
|
|
44
|
-
|
|
45
|
-
} from "./studio-hcxzyk3x.js";
|
|
35
|
+
formatForPath
|
|
36
|
+
} from "./studio-eenfkt4e.js";
|
|
46
37
|
import {
|
|
47
38
|
getPlatform
|
|
48
|
-
} from "./studio-
|
|
49
|
-
import {
|
|
50
|
-
applyDocOpToDoc,
|
|
51
|
-
childArray,
|
|
52
|
-
cloneValue
|
|
53
|
-
} from "./studio-5ehhackm.js";
|
|
39
|
+
} from "./studio-9ab8gqsm.js";
|
|
54
40
|
import {
|
|
55
41
|
__require
|
|
56
42
|
} from "./studio-a0tswy0w.js";
|
|
57
43
|
|
|
58
|
-
// ../schema/src/ijson.ts
|
|
59
|
-
var WHITESPACE = new Set([" ", "\t", `
|
|
60
|
-
`, "\r"]);
|
|
61
|
-
|
|
62
|
-
// ../schema/src/parse.ts
|
|
63
|
-
function errorMessage(e) {
|
|
64
|
-
return e instanceof Error ? e.message : String(e);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
44
|
// ../schema/src/locale.ts
|
|
68
45
|
var RTL_SCRIPTS = new Set([
|
|
69
46
|
"Adlm",
|
|
@@ -230,346 +207,115 @@ function localeSlot(segments) {
|
|
|
230
207
|
return -1;
|
|
231
208
|
}
|
|
232
209
|
|
|
233
|
-
// src/
|
|
234
|
-
var
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
selDragCleanup: null,
|
|
238
|
-
dndCleanups: [],
|
|
239
|
-
elementsCollapsed: new Set,
|
|
240
|
-
elementsFilter: "",
|
|
241
|
-
_currentDropTargetRow: null,
|
|
242
|
-
layerDragSourceHeight: 0,
|
|
243
|
-
_completionRegistered: false,
|
|
244
|
-
_layersCollapsed: null
|
|
245
|
-
};
|
|
246
|
-
|
|
247
|
-
// src/canvas/surface-registry.ts
|
|
248
|
-
var STAGE_CLASS = "pane-stage";
|
|
249
|
-
var _nextGen = 0;
|
|
250
|
-
function nextRenderGeneration() {
|
|
251
|
-
_nextGen += 1;
|
|
252
|
-
return _nextGen;
|
|
253
|
-
}
|
|
254
|
-
var _surfaces = new Map;
|
|
255
|
-
function surfaceForPane(paneId) {
|
|
256
|
-
let surface = _surfaces.get(paneId);
|
|
257
|
-
if (!surface) {
|
|
258
|
-
surface = freshSurface(paneId);
|
|
259
|
-
_surfaces.set(paneId, surface);
|
|
260
|
-
}
|
|
261
|
-
return surface;
|
|
262
|
-
}
|
|
263
|
-
function freshSurface(paneId) {
|
|
264
|
-
return {
|
|
265
|
-
centerObserver: null,
|
|
266
|
-
monacoEditor: null,
|
|
267
|
-
needsCenter: true,
|
|
268
|
-
panX: 0,
|
|
269
|
-
panY: 0,
|
|
270
|
-
panels: [],
|
|
271
|
-
paneId,
|
|
272
|
-
panzoomWrap: null,
|
|
273
|
-
prevCanvasMode: null,
|
|
274
|
-
prevStylebookCustomizedOnly: null,
|
|
275
|
-
prevStylebookFilter: null,
|
|
276
|
-
renderGeneration: 0,
|
|
277
|
-
sourceCollabCleanup: null,
|
|
278
|
-
wrap: null
|
|
279
|
-
};
|
|
210
|
+
// src/content/collection-match.ts
|
|
211
|
+
var LOCALE_PLACEHOLDER = "{locale}";
|
|
212
|
+
function escapeLiteral(part) {
|
|
213
|
+
return part.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
280
214
|
}
|
|
281
|
-
function
|
|
282
|
-
return
|
|
215
|
+
function normalize(path) {
|
|
216
|
+
return path.replaceAll("\\", "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
283
217
|
}
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
return null;
|
|
287
|
-
}
|
|
288
|
-
for (const surface of _surfaces.values()) {
|
|
289
|
-
if (surface.wrap?.contains(node)) {
|
|
290
|
-
return surface;
|
|
291
|
-
}
|
|
292
|
-
}
|
|
293
|
-
return null;
|
|
218
|
+
function configOf(config) {
|
|
219
|
+
return config ?? projectState?.projectConfig ?? null;
|
|
294
220
|
}
|
|
295
|
-
function
|
|
296
|
-
|
|
297
|
-
panel.renderScope?.stop();
|
|
298
|
-
panel.renderScope = null;
|
|
299
|
-
}
|
|
300
|
-
surface.panels.length = 0;
|
|
301
|
-
surface.prevCanvasMode = null;
|
|
221
|
+
function contentSection(config) {
|
|
222
|
+
return config?.content ?? {};
|
|
302
223
|
}
|
|
303
|
-
function
|
|
304
|
-
const
|
|
305
|
-
|
|
306
|
-
releaseMountedPanels(surface);
|
|
307
|
-
return surface;
|
|
224
|
+
function declaredLocales(config) {
|
|
225
|
+
const locales = resolveI18n(config ?? {}).i18n?.locales ?? [];
|
|
226
|
+
return locales.length > 0 ? [...locales] : null;
|
|
308
227
|
}
|
|
309
|
-
function
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
disposePaneSurface(paneId);
|
|
228
|
+
function isFileBacked(source) {
|
|
229
|
+
if (source.endsWith("/")) {
|
|
230
|
+
return false;
|
|
313
231
|
}
|
|
314
|
-
const
|
|
315
|
-
|
|
316
|
-
return surface;
|
|
232
|
+
const base = source.slice(source.lastIndexOf("/") + 1);
|
|
233
|
+
return /\.[a-z\d]+$/i.test(base);
|
|
317
234
|
}
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
}
|
|
322
|
-
function disposePaneSurface(paneId) {
|
|
323
|
-
const surface = _surfaces.get(paneId);
|
|
324
|
-
if (!surface) {
|
|
325
|
-
return;
|
|
235
|
+
function resolveExt(def) {
|
|
236
|
+
if (def.format === "json") {
|
|
237
|
+
return { ext: ".json", unresolvedFormat: null };
|
|
326
238
|
}
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
unregisterCanvasSurface(paneId);
|
|
330
|
-
}
|
|
331
|
-
function unregisterCanvasSurface(paneId) {
|
|
332
|
-
_surfaces.delete(paneId);
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
// src/services/monaco-buffer.ts
|
|
336
|
-
var BUFFER_COMMIT = "commit";
|
|
337
|
-
function bufferWrites(buffer) {
|
|
338
|
-
const timers = new Map;
|
|
339
|
-
const runs = new Map;
|
|
340
|
-
const inFlight = new Map;
|
|
341
|
-
let isAhead = false;
|
|
342
|
-
let isTyped = false;
|
|
343
|
-
let isShared = false;
|
|
344
|
-
function track(key, result) {
|
|
345
|
-
if (typeof result?.then !== "function") {
|
|
346
|
-
return result;
|
|
347
|
-
}
|
|
348
|
-
const promise = result.finally(() => {
|
|
349
|
-
if (inFlight.get(key) === promise) {
|
|
350
|
-
inFlight.delete(key);
|
|
351
|
-
}
|
|
352
|
-
});
|
|
353
|
-
inFlight.set(key, promise);
|
|
354
|
-
return promise;
|
|
355
|
-
}
|
|
356
|
-
const writes = {
|
|
357
|
-
arm(key, ms, run) {
|
|
358
|
-
clearTimeout(timers.get(key));
|
|
359
|
-
runs.set(key, run);
|
|
360
|
-
timers.set(key, setTimeout(() => {
|
|
361
|
-
timers.delete(key);
|
|
362
|
-
runs.delete(key);
|
|
363
|
-
track(key, run());
|
|
364
|
-
}, ms));
|
|
365
|
-
},
|
|
366
|
-
cancel() {
|
|
367
|
-
for (const timer of timers.values()) {
|
|
368
|
-
clearTimeout(timer);
|
|
369
|
-
}
|
|
370
|
-
timers.clear();
|
|
371
|
-
runs.clear();
|
|
372
|
-
},
|
|
373
|
-
flush(key) {
|
|
374
|
-
const run = runs.get(key);
|
|
375
|
-
if (!run) {
|
|
376
|
-
return inFlight.get(key);
|
|
377
|
-
}
|
|
378
|
-
clearTimeout(timers.get(key));
|
|
379
|
-
timers.delete(key);
|
|
380
|
-
runs.delete(key);
|
|
381
|
-
return track(key, run());
|
|
382
|
-
},
|
|
383
|
-
ahead: () => isAhead,
|
|
384
|
-
markAhead() {
|
|
385
|
-
isAhead = true;
|
|
386
|
-
},
|
|
387
|
-
typed: () => isTyped,
|
|
388
|
-
markTyped() {
|
|
389
|
-
isAhead = true;
|
|
390
|
-
isTyped = true;
|
|
391
|
-
},
|
|
392
|
-
markSettled() {
|
|
393
|
-
isAhead = false;
|
|
394
|
-
isTyped = false;
|
|
395
|
-
},
|
|
396
|
-
shared: () => isShared,
|
|
397
|
-
markShared() {
|
|
398
|
-
isShared = true;
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
buffer._writes = writes;
|
|
402
|
-
return writes;
|
|
403
|
-
}
|
|
404
|
-
var SURFACE = {
|
|
405
|
-
logic: { holds: "The handler you were typing", reached: "written into", source: "Logic" },
|
|
406
|
-
source: { holds: "The source you were typing", reached: "parsed into", source: "Editor" }
|
|
407
|
-
};
|
|
408
|
-
function reportDiscarded(buffer, surface, failure) {
|
|
409
|
-
const writes = buffer._writes;
|
|
410
|
-
if (writes?.typed() !== true) {
|
|
411
|
-
return true;
|
|
239
|
+
if (def.format === undefined || def.format === "") {
|
|
240
|
+
return { ext: defaultContentFormat()?.extensions[0] ?? ".json", unresolvedFormat: null };
|
|
412
241
|
}
|
|
413
|
-
const
|
|
414
|
-
|
|
415
|
-
const { holds, reached, source } = SURFACE[surface];
|
|
416
|
-
notify.warn(`${holds} was discarded — it was never ${reached} "${where}".`, {
|
|
417
|
-
...failure ? { detail: describeCommitFailure(failure.error) } : {},
|
|
418
|
-
key: `buffer-discarded:${surface}:${tab?.id ?? "none"}`,
|
|
419
|
-
source,
|
|
420
|
-
...tab?.documentPath ? { path: tab.documentPath } : {}
|
|
421
|
-
});
|
|
422
|
-
return false;
|
|
242
|
+
const format = formatByName(def.format);
|
|
243
|
+
return format?.extensions[0] === undefined ? { ext: null, unresolvedFormat: def.format } : { ext: format.extensions[0], unresolvedFormat: null };
|
|
423
244
|
}
|
|
424
|
-
function
|
|
425
|
-
|
|
245
|
+
function sourcePattern(source, locales) {
|
|
246
|
+
const segment = locales === null ? "[^/]+" : `(?:${locales.map((locale) => escapeLiteral(locale)).join("|")})`;
|
|
247
|
+
const body = normalize(source).split(LOCALE_PLACEHOLDER).map((part) => escapeLiteral(part)).join(segment);
|
|
248
|
+
return new RegExp(`^${body}(?:/|$)`, "i");
|
|
426
249
|
}
|
|
427
|
-
function
|
|
428
|
-
const
|
|
429
|
-
if (!
|
|
430
|
-
return
|
|
431
|
-
}
|
|
432
|
-
let pending;
|
|
433
|
-
try {
|
|
434
|
-
pending = writes.flush(BUFFER_COMMIT);
|
|
435
|
-
} catch (error) {
|
|
436
|
-
writes.cancel();
|
|
437
|
-
return reportDiscarded(buffer, surface, { error });
|
|
438
|
-
}
|
|
439
|
-
writes.cancel();
|
|
440
|
-
if (typeof pending?.then === "function") {
|
|
441
|
-
pending.then(() => reportDiscarded(buffer, surface, null), (error) => reportDiscarded(buffer, surface, { error }));
|
|
442
|
-
return true;
|
|
250
|
+
function matchedRoot(source, target, locales) {
|
|
251
|
+
const hit = sourcePattern(source, locales).exec(target);
|
|
252
|
+
if (!hit) {
|
|
253
|
+
return null;
|
|
443
254
|
}
|
|
444
|
-
return
|
|
445
|
-
}
|
|
446
|
-
function cancelBufferWrites(buffer) {
|
|
447
|
-
buffer?._writes?.cancel();
|
|
255
|
+
return hit[0].replace(/\/$/, "");
|
|
448
256
|
}
|
|
449
|
-
function
|
|
450
|
-
return
|
|
257
|
+
function sourceWeight(source) {
|
|
258
|
+
return normalize(source).replaceAll(LOCALE_PLACEHOLDER, "").length;
|
|
451
259
|
}
|
|
452
|
-
function
|
|
453
|
-
if (
|
|
454
|
-
return
|
|
260
|
+
function collectionForDirectory(dir, config) {
|
|
261
|
+
if (dir === null || dir === undefined || dir === "") {
|
|
262
|
+
return null;
|
|
455
263
|
}
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
return mounted.filter((buffer) => buffer != null && buffer._editingTab != null && toRaw(buffer._editingTab) === raw && bufferIsLive(buffer));
|
|
465
|
-
}
|
|
466
|
-
async function commitTabBuffers(tab) {
|
|
467
|
-
for (const buffer of buffersForTab(tab)) {
|
|
468
|
-
if (!bufferIsLive(buffer)) {
|
|
264
|
+
const resolved = configOf(config);
|
|
265
|
+
const locales = declaredLocales(resolved);
|
|
266
|
+
const target = normalize(dir);
|
|
267
|
+
let best = null;
|
|
268
|
+
let bestWeight = -1;
|
|
269
|
+
for (const [name, def] of Object.entries(contentSection(resolved))) {
|
|
270
|
+
const { source } = def;
|
|
271
|
+
if (source === undefined || source === "" || isFileBacked(source)) {
|
|
469
272
|
continue;
|
|
470
273
|
}
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
} catch (error) {
|
|
474
|
-
notify.error(`Could not save the editor's contents into "${tab.documentPath ?? "Untitled"}".`, {
|
|
475
|
-
detail: error instanceof Error ? error.stack ?? error.message : String(error),
|
|
476
|
-
key: `buffer-commit:${tab.id}`,
|
|
477
|
-
source: "Editor",
|
|
478
|
-
...tab.documentPath ? { path: tab.documentPath } : {}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
}
|
|
482
|
-
}
|
|
483
|
-
function tabBufferUnsaved(tab) {
|
|
484
|
-
return buffersForTab(tab).some((buffer) => buffer._writes?.typed() === true);
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
// src/tabs/selection.ts
|
|
488
|
-
function primarySelection(selection) {
|
|
489
|
-
return selection && selection.length > 0 ? selection.at(-1) : null;
|
|
490
|
-
}
|
|
491
|
-
function selectionAnchor(selection) {
|
|
492
|
-
return selection && selection.length > 0 ? selection[0] : null;
|
|
493
|
-
}
|
|
494
|
-
function isSelected(selection, path) {
|
|
495
|
-
if (!path || !selection) {
|
|
496
|
-
return false;
|
|
497
|
-
}
|
|
498
|
-
return selection.some((p) => pathsEqual(p, path));
|
|
499
|
-
}
|
|
500
|
-
function cloneSelection(paths) {
|
|
501
|
-
return clonePaths(paths);
|
|
502
|
-
}
|
|
503
|
-
function clonePaths(paths) {
|
|
504
|
-
const out = [];
|
|
505
|
-
for (const path of paths) {
|
|
506
|
-
out.push([...path]);
|
|
507
|
-
}
|
|
508
|
-
return out;
|
|
509
|
-
}
|
|
510
|
-
function toggleSelected(selection, path) {
|
|
511
|
-
if (isSelected(selection, path)) {
|
|
512
|
-
return clonePaths(selection.filter((p) => !pathsEqual(p, path)));
|
|
513
|
-
}
|
|
514
|
-
return [...clonePaths(selection), [...path]];
|
|
515
|
-
}
|
|
516
|
-
function rangeSelection(rows, anchor, target) {
|
|
517
|
-
const to = rows.findIndex((p) => pathsEqual(p, target));
|
|
518
|
-
const from = anchor ? rows.findIndex((p) => pathsEqual(p, anchor)) : -1;
|
|
519
|
-
if (to === -1 || from === -1) {
|
|
520
|
-
return [[...target]];
|
|
521
|
-
}
|
|
522
|
-
const slice = from <= to ? rows.slice(from, to + 1) : rows.slice(to, from + 1).toReversed();
|
|
523
|
-
return clonePaths(slice);
|
|
524
|
-
}
|
|
525
|
-
function pruneSelection(selection, removed) {
|
|
526
|
-
return clonePaths(selection.filter((p) => !isAncestor(removed, p)));
|
|
527
|
-
}
|
|
528
|
-
function comparePaths(a, b) {
|
|
529
|
-
const len = Math.min(a.length, b.length);
|
|
530
|
-
for (let i = 0;i < len; i++) {
|
|
531
|
-
const x = a[i];
|
|
532
|
-
const y = b[i];
|
|
533
|
-
if (x === y) {
|
|
274
|
+
const weight = sourceWeight(source);
|
|
275
|
+
if (weight <= bestWeight) {
|
|
534
276
|
continue;
|
|
535
277
|
}
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
return String(x) < String(y) ? -1 : 1;
|
|
540
|
-
}
|
|
541
|
-
return a.length - b.length;
|
|
542
|
-
}
|
|
543
|
-
function topLevelSelection(selection) {
|
|
544
|
-
return clonePaths(selection.filter((p) => !selection.some((q) => !pathsEqual(q, p) && isAncestor(q, p))));
|
|
545
|
-
}
|
|
546
|
-
function isSpliceablePath(path) {
|
|
547
|
-
return path.at(-2) === "children" && typeof path.at(-1) === "number";
|
|
548
|
-
}
|
|
549
|
-
function structuralBatch(selection) {
|
|
550
|
-
return topLevelSelection(selection).filter((path) => isSpliceablePath(path)).toSorted((a, b) => comparePaths(b, a));
|
|
551
|
-
}
|
|
552
|
-
function uniquePaths(paths) {
|
|
553
|
-
const out = [];
|
|
554
|
-
for (const path of paths) {
|
|
555
|
-
if (!out.some((p) => pathsEqual(p, path))) {
|
|
556
|
-
out.push([...path]);
|
|
278
|
+
const root = matchedRoot(source, target, locales);
|
|
279
|
+
if (root === null) {
|
|
280
|
+
continue;
|
|
557
281
|
}
|
|
282
|
+
best = {
|
|
283
|
+
def,
|
|
284
|
+
dir: target,
|
|
285
|
+
fileBacked: false,
|
|
286
|
+
isSourceRoot: target.length === root.length,
|
|
287
|
+
name,
|
|
288
|
+
...resolveExt(def)
|
|
289
|
+
};
|
|
290
|
+
bestWeight = weight;
|
|
558
291
|
}
|
|
559
|
-
return
|
|
292
|
+
return best;
|
|
560
293
|
}
|
|
561
|
-
function
|
|
562
|
-
if (
|
|
563
|
-
return
|
|
294
|
+
function collectionForFile(path, config) {
|
|
295
|
+
if (path === null || path === undefined || path === "") {
|
|
296
|
+
return null;
|
|
564
297
|
}
|
|
565
|
-
const
|
|
566
|
-
const
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
298
|
+
const resolved = configOf(config);
|
|
299
|
+
const target = normalize(path);
|
|
300
|
+
const lower = target.toLowerCase();
|
|
301
|
+
for (const [name, def] of Object.entries(contentSection(resolved))) {
|
|
302
|
+
const { source } = def;
|
|
303
|
+
if (source === undefined || source === "" || !isFileBacked(source)) {
|
|
304
|
+
continue;
|
|
305
|
+
}
|
|
306
|
+
const src = normalize(source).toLowerCase();
|
|
307
|
+
if (lower === src || lower.endsWith(`/${src}`)) {
|
|
308
|
+
return {
|
|
309
|
+
def,
|
|
310
|
+
dir: target.includes("/") ? target.slice(0, target.lastIndexOf("/")) : ".",
|
|
311
|
+
fileBacked: true,
|
|
312
|
+
isSourceRoot: false,
|
|
313
|
+
name,
|
|
314
|
+
...resolveExt(def)
|
|
315
|
+
};
|
|
570
316
|
}
|
|
571
317
|
}
|
|
572
|
-
return
|
|
318
|
+
return collectionForDirectory(target.includes("/") ? target.slice(0, target.lastIndexOf("/")) : ".", resolved);
|
|
573
319
|
}
|
|
574
320
|
|
|
575
321
|
// src/utils/studio-utils.ts
|
|
@@ -621,7 +367,6 @@ function abbreviateValue(val) {
|
|
|
621
367
|
};
|
|
622
368
|
return map[val] || val;
|
|
623
369
|
}
|
|
624
|
-
var LOCALE_PLACEHOLDER = "{locale}";
|
|
625
370
|
function isMediaFormat(format) {
|
|
626
371
|
return format === "image" || format === "uri-reference";
|
|
627
372
|
}
|
|
@@ -659,27 +404,17 @@ function findContentTypeSchema(documentPath, projectConfig) {
|
|
|
659
404
|
if (!documentPath || !projectConfig?.content) {
|
|
660
405
|
return null;
|
|
661
406
|
}
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
const
|
|
668
|
-
|
|
669
|
-
|
|
670
|
-
if (docPath === src || docPath.endsWith(`/${src}`)) {
|
|
671
|
-
return { name, schema: def.schema };
|
|
672
|
-
}
|
|
673
|
-
} else {
|
|
674
|
-
const ext = def.format === "json" ? ".json" : formatByName(def.format)?.extensions[0] ?? defaultContentFormat()?.extensions[0] ?? ".json";
|
|
675
|
-
const prefix = src.includes(LOCALE_PLACEHOLDER) ? new RegExp(`^${src.split(LOCALE_PLACEHOLDER).map((part) => part.replaceAll(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`)).join("[^/]+")}/`) : null;
|
|
676
|
-
const matches = prefix ? prefix.test(docPath) : docPath.startsWith(`${src}/`);
|
|
677
|
-
if (matches && docPath.endsWith(ext)) {
|
|
678
|
-
return { name, schema: def.schema };
|
|
679
|
-
}
|
|
407
|
+
const match = collectionForFile(documentPath, projectConfig);
|
|
408
|
+
if (!match || !match.def.schema) {
|
|
409
|
+
return null;
|
|
410
|
+
}
|
|
411
|
+
if (!match.fileBacked) {
|
|
412
|
+
const ext = match.ext ?? defaultContentFormat()?.extensions[0] ?? ".json";
|
|
413
|
+
if (!documentPath.toLowerCase().endsWith(ext.toLowerCase())) {
|
|
414
|
+
return null;
|
|
680
415
|
}
|
|
681
416
|
}
|
|
682
|
-
return
|
|
417
|
+
return { name: match.name, schema: match.def.schema };
|
|
683
418
|
}
|
|
684
419
|
function friendlyNameToVar(name, prefix) {
|
|
685
420
|
const slug = name.trim().toLowerCase().replaceAll(/[^a-z0-9\s-]/g, "").replaceAll(/\s+/g, "-").replaceAll(/-+/g, "-").replaceAll(/^-|-$/g, "");
|
|
@@ -712,67 +447,155 @@ function parseCemType(typeText) {
|
|
|
712
447
|
function jsonClone(value) {
|
|
713
448
|
return JSON.parse(JSON.stringify(value));
|
|
714
449
|
}
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
function
|
|
718
|
-
|
|
719
|
-
}
|
|
720
|
-
function getPatchConsumer() {
|
|
721
|
-
return _consumer;
|
|
450
|
+
|
|
451
|
+
// src/tabs/selection.ts
|
|
452
|
+
function primarySelection(selection) {
|
|
453
|
+
return selection && selection.length > 0 ? selection.at(-1) : null;
|
|
722
454
|
}
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
var _fmOps = null;
|
|
726
|
-
var _invertible = true;
|
|
727
|
-
function beginRecording() {
|
|
728
|
-
_recording = [];
|
|
729
|
-
_docOps = [];
|
|
730
|
-
_fmOps = [];
|
|
731
|
-
_invertible = true;
|
|
455
|
+
function selectionAnchor(selection) {
|
|
456
|
+
return selection && selection.length > 0 ? selection[0] : null;
|
|
732
457
|
}
|
|
733
|
-
function
|
|
734
|
-
if (
|
|
735
|
-
|
|
458
|
+
function isSelected(selection, path) {
|
|
459
|
+
if (!path || !selection) {
|
|
460
|
+
return false;
|
|
736
461
|
}
|
|
462
|
+
return selection.some((p) => pathsEqual(p, path));
|
|
737
463
|
}
|
|
738
|
-
function
|
|
739
|
-
|
|
740
|
-
_docOps.push(pair);
|
|
741
|
-
}
|
|
464
|
+
function cloneSelection(paths) {
|
|
465
|
+
return clonePaths(paths);
|
|
742
466
|
}
|
|
743
|
-
function
|
|
744
|
-
|
|
745
|
-
|
|
467
|
+
function clonePaths(paths) {
|
|
468
|
+
const out = [];
|
|
469
|
+
for (const path of paths) {
|
|
470
|
+
out.push([...path]);
|
|
746
471
|
}
|
|
472
|
+
return out;
|
|
747
473
|
}
|
|
748
|
-
function
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
ops: _recording ?? []
|
|
754
|
-
};
|
|
755
|
-
_recording = null;
|
|
756
|
-
_docOps = null;
|
|
757
|
-
_fmOps = null;
|
|
758
|
-
_invertible = true;
|
|
759
|
-
return record;
|
|
474
|
+
function toggleSelected(selection, path) {
|
|
475
|
+
if (isSelected(selection, path)) {
|
|
476
|
+
return clonePaths(selection.filter((p) => !pathsEqual(p, path)));
|
|
477
|
+
}
|
|
478
|
+
return [...clonePaths(selection), [...path]];
|
|
760
479
|
}
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
try {
|
|
767
|
-
return typeof localStorage === "undefined" || !localStorage.getItem("jx-legacy-history");
|
|
768
|
-
} catch {
|
|
769
|
-
return true;
|
|
480
|
+
function rangeSelection(rows, anchor, target) {
|
|
481
|
+
const to = rows.findIndex((p) => pathsEqual(p, target));
|
|
482
|
+
const from = anchor ? rows.findIndex((p) => pathsEqual(p, anchor)) : -1;
|
|
483
|
+
if (to === -1 || from === -1) {
|
|
484
|
+
return [[...target]];
|
|
770
485
|
}
|
|
486
|
+
const slice = from <= to ? rows.slice(from, to + 1) : rows.slice(to, from + 1).toReversed();
|
|
487
|
+
return clonePaths(slice);
|
|
771
488
|
}
|
|
772
|
-
function
|
|
773
|
-
return
|
|
774
|
-
|
|
775
|
-
|
|
489
|
+
function pruneSelection(selection, removed) {
|
|
490
|
+
return clonePaths(selection.filter((p) => !isAncestor(removed, p)));
|
|
491
|
+
}
|
|
492
|
+
function comparePaths(a, b) {
|
|
493
|
+
const len = Math.min(a.length, b.length);
|
|
494
|
+
for (let i = 0;i < len; i++) {
|
|
495
|
+
const x = a[i];
|
|
496
|
+
const y = b[i];
|
|
497
|
+
if (x === y) {
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (typeof x === "number" && typeof y === "number") {
|
|
501
|
+
return x - y;
|
|
502
|
+
}
|
|
503
|
+
return String(x) < String(y) ? -1 : 1;
|
|
504
|
+
}
|
|
505
|
+
return a.length - b.length;
|
|
506
|
+
}
|
|
507
|
+
function topLevelSelection(selection) {
|
|
508
|
+
return clonePaths(selection.filter((p) => !selection.some((q) => !pathsEqual(q, p) && isAncestor(q, p))));
|
|
509
|
+
}
|
|
510
|
+
function isSpliceablePath(path) {
|
|
511
|
+
return path.at(-2) === "children" && typeof path.at(-1) === "number";
|
|
512
|
+
}
|
|
513
|
+
function structuralBatch(selection) {
|
|
514
|
+
return topLevelSelection(selection).filter((path) => isSpliceablePath(path)).toSorted((a, b) => comparePaths(b, a));
|
|
515
|
+
}
|
|
516
|
+
function uniquePaths(paths) {
|
|
517
|
+
const out = [];
|
|
518
|
+
for (const path of paths) {
|
|
519
|
+
if (!out.some((p) => pathsEqual(p, path))) {
|
|
520
|
+
out.push([...path]);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
return out;
|
|
524
|
+
}
|
|
525
|
+
function unifyValues(values) {
|
|
526
|
+
if (values.length === 0) {
|
|
527
|
+
return { mixed: false, value: undefined };
|
|
528
|
+
}
|
|
529
|
+
const first = values[0];
|
|
530
|
+
const key = JSON.stringify(first ?? null);
|
|
531
|
+
for (let i = 1;i < values.length; i++) {
|
|
532
|
+
if (JSON.stringify(values[i] ?? null) !== key) {
|
|
533
|
+
return { mixed: true, value: undefined };
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
return { mixed: false, value: first };
|
|
537
|
+
}
|
|
538
|
+
// src/tabs/patch-ops.ts
|
|
539
|
+
var _consumer = null;
|
|
540
|
+
function setPatchConsumer(consumer) {
|
|
541
|
+
_consumer = consumer;
|
|
542
|
+
}
|
|
543
|
+
function getPatchConsumer() {
|
|
544
|
+
return _consumer;
|
|
545
|
+
}
|
|
546
|
+
var _recording = null;
|
|
547
|
+
var _docOps = null;
|
|
548
|
+
var _fmOps = null;
|
|
549
|
+
var _invertible = true;
|
|
550
|
+
function beginRecording() {
|
|
551
|
+
_recording = [];
|
|
552
|
+
_docOps = [];
|
|
553
|
+
_fmOps = [];
|
|
554
|
+
_invertible = true;
|
|
555
|
+
}
|
|
556
|
+
function recordPatch(op) {
|
|
557
|
+
if (_recording) {
|
|
558
|
+
_recording.push(op);
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
function recordDocOp(pair) {
|
|
562
|
+
if (_docOps) {
|
|
563
|
+
_docOps.push(pair);
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
function recordFmOp(op) {
|
|
567
|
+
if (_fmOps) {
|
|
568
|
+
_fmOps.push(op);
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
function endRecording() {
|
|
572
|
+
const record = {
|
|
573
|
+
docOps: _docOps ?? [],
|
|
574
|
+
fmOps: _fmOps ?? [],
|
|
575
|
+
invertible: _invertible,
|
|
576
|
+
ops: _recording ?? []
|
|
577
|
+
};
|
|
578
|
+
_recording = null;
|
|
579
|
+
_docOps = null;
|
|
580
|
+
_fmOps = null;
|
|
581
|
+
_invertible = true;
|
|
582
|
+
return record;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
// src/tabs/transact.ts
|
|
586
|
+
var HISTORY_LIMIT = 100;
|
|
587
|
+
var CHECKPOINT_INTERVAL = 20;
|
|
588
|
+
function patchHistoryEnabled() {
|
|
589
|
+
try {
|
|
590
|
+
return typeof localStorage === "undefined" || !localStorage.getItem("jx-legacy-history");
|
|
591
|
+
} catch {
|
|
592
|
+
return true;
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
function setKeyPair(path, key, before, after) {
|
|
596
|
+
return {
|
|
597
|
+
forward: { key, op: "set-key", path, value: after },
|
|
598
|
+
inverse: { key, op: "set-key", path, value: before }
|
|
776
599
|
};
|
|
777
600
|
}
|
|
778
601
|
function shiftPrefixedIndex(parentPath, path, spliceIndex, delta, inclusive) {
|
|
@@ -1380,6 +1203,24 @@ function mutateUpdateMediaNestedStyle(tab, path, mediaName, selector, prop, valu
|
|
|
1380
1203
|
recordDocOp(setKeyPair(path, "style", styleBefore, cloneValue(node.style)));
|
|
1381
1204
|
recordPatch({ op: "set-style", path });
|
|
1382
1205
|
}
|
|
1206
|
+
function pruneEmptyStylePath(root, stylePath) {
|
|
1207
|
+
const owners = [root];
|
|
1208
|
+
for (const seg of stylePath) {
|
|
1209
|
+
const next = getNestedStyle(owners.at(-1), seg);
|
|
1210
|
+
if (!next) {
|
|
1211
|
+
break;
|
|
1212
|
+
}
|
|
1213
|
+
owners.push(next);
|
|
1214
|
+
}
|
|
1215
|
+
for (let i = owners.length - 2;i >= 0; i--) {
|
|
1216
|
+
const owner = owners[i];
|
|
1217
|
+
const seg = stylePath[i];
|
|
1218
|
+
const block = getNestedStyle(owner, seg);
|
|
1219
|
+
if (block && Object.keys(block).length === 0) {
|
|
1220
|
+
delete owner[seg];
|
|
1221
|
+
}
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1383
1224
|
function mutateUpdateNestedStylePath(tab, path, stylePath, prop, value) {
|
|
1384
1225
|
const node = getNodeAtPath(tab.doc.document, path);
|
|
1385
1226
|
const styleBefore = cloneValue(node.style);
|
|
@@ -1392,15 +1233,7 @@ function mutateUpdateNestedStylePath(tab, path, stylePath, prop, value) {
|
|
|
1392
1233
|
}
|
|
1393
1234
|
if (value === undefined || value === "") {
|
|
1394
1235
|
delete obj[prop];
|
|
1395
|
-
|
|
1396
|
-
for (let i = 0;i < stylePath.length && cur; i++) {
|
|
1397
|
-
const child = getNestedStyle(cur, stylePath[i]);
|
|
1398
|
-
if (child && Object.keys(child).length === 0) {
|
|
1399
|
-
delete cur[stylePath[i]];
|
|
1400
|
-
break;
|
|
1401
|
-
}
|
|
1402
|
-
cur = child;
|
|
1403
|
-
}
|
|
1236
|
+
pruneEmptyStylePath(node.style, stylePath);
|
|
1404
1237
|
} else {
|
|
1405
1238
|
obj[prop] = value;
|
|
1406
1239
|
}
|
|
@@ -1424,15 +1257,7 @@ function mutateUpdateMediaNestedStylePath(tab, path, mediaName, stylePath, prop,
|
|
|
1424
1257
|
}
|
|
1425
1258
|
if (value === undefined || value === "") {
|
|
1426
1259
|
delete obj[prop];
|
|
1427
|
-
|
|
1428
|
-
for (let i = 0;i < stylePath.length && cur; i++) {
|
|
1429
|
-
const child = getNestedStyle(cur, stylePath[i]);
|
|
1430
|
-
if (child && Object.keys(child).length === 0) {
|
|
1431
|
-
delete cur[stylePath[i]];
|
|
1432
|
-
break;
|
|
1433
|
-
}
|
|
1434
|
-
cur = child;
|
|
1435
|
-
}
|
|
1260
|
+
pruneEmptyStylePath(media, stylePath);
|
|
1436
1261
|
if (Object.keys(media).length === 0) {
|
|
1437
1262
|
delete node.style[key];
|
|
1438
1263
|
}
|
|
@@ -1575,743 +1400,116 @@ function applyFmState(tab, field, value) {
|
|
|
1575
1400
|
}
|
|
1576
1401
|
}
|
|
1577
1402
|
|
|
1578
|
-
// src/
|
|
1579
|
-
var
|
|
1580
|
-
|
|
1581
|
-
"
|
|
1582
|
-
"
|
|
1583
|
-
"
|
|
1584
|
-
"
|
|
1585
|
-
"
|
|
1586
|
-
"
|
|
1587
|
-
"
|
|
1588
|
-
"
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
if (instance === "") {
|
|
1606
|
-
return null;
|
|
1607
|
-
}
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
if (!REGION_SURFACES.includes(surface)) {
|
|
1611
|
-
return null;
|
|
1612
|
-
}
|
|
1613
|
-
return instance === undefined ? part === undefined ? { surface } : { part, surface } : part === undefined ? { instance, surface } : { instance, part, surface };
|
|
1403
|
+
// src/commands/context.ts
|
|
1404
|
+
var EDITOR_KIND_BY_MODE = {
|
|
1405
|
+
design: "canvas",
|
|
1406
|
+
edit: "canvas",
|
|
1407
|
+
entry: "entry",
|
|
1408
|
+
"git-diff": "diff",
|
|
1409
|
+
grid: "grid",
|
|
1410
|
+
manage: "library",
|
|
1411
|
+
media: "media",
|
|
1412
|
+
preview: "canvas",
|
|
1413
|
+
settings: "config",
|
|
1414
|
+
source: "code",
|
|
1415
|
+
stylebook: "config"
|
|
1416
|
+
};
|
|
1417
|
+
var EDITOR_KIND_LABELS = {
|
|
1418
|
+
canvas: "Canvas",
|
|
1419
|
+
code: "Code",
|
|
1420
|
+
config: "Project Styles",
|
|
1421
|
+
diff: "Diff",
|
|
1422
|
+
entry: "Entry",
|
|
1423
|
+
grid: "Grid",
|
|
1424
|
+
media: "Media",
|
|
1425
|
+
library: "Library",
|
|
1426
|
+
none: "None"
|
|
1427
|
+
};
|
|
1428
|
+
function editorKindForMode(mode) {
|
|
1429
|
+
return EDITOR_KIND_BY_MODE[mode] ?? "canvas";
|
|
1614
1430
|
}
|
|
1615
|
-
|
|
1616
|
-
|
|
1431
|
+
var CANVAS_VIEW_BY_MODE = {
|
|
1432
|
+
design: "design",
|
|
1433
|
+
edit: "edit",
|
|
1434
|
+
preview: "preview"
|
|
1435
|
+
};
|
|
1436
|
+
function canvasViewForMode(mode) {
|
|
1437
|
+
return CANVAS_VIEW_BY_MODE[mode] ?? "design";
|
|
1617
1438
|
}
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
return
|
|
1439
|
+
var inCanvas = (ctx) => ctx.editor.kind === "canvas";
|
|
1440
|
+
var hasSelection = (ctx) => inCanvas(ctx) && ctx.selection.count > 0;
|
|
1441
|
+
var hasElementSelection = (ctx) => hasSelection(ctx) && !ctx.selection.isRoot;
|
|
1442
|
+
function emptyContext() {
|
|
1443
|
+
return {
|
|
1444
|
+
project: { open: false, isSite: false, isRepo: false, isMultilingual: false },
|
|
1445
|
+
git: { ahead: 0, behind: 0, dirtyCount: 0 },
|
|
1446
|
+
document: { open: false, dirty: false, mode: "", canUndo: false, canRedo: false },
|
|
1447
|
+
editor: { kind: "none" },
|
|
1448
|
+
canvas: { view: "design" },
|
|
1449
|
+
pane: { count: 1, derived: false },
|
|
1450
|
+
selection: {
|
|
1451
|
+
count: 0,
|
|
1452
|
+
paths: [],
|
|
1453
|
+
kind: "",
|
|
1454
|
+
isRoot: false,
|
|
1455
|
+
isComponentInstance: false,
|
|
1456
|
+
isLayoutNode: false,
|
|
1457
|
+
isRepeater: false
|
|
1458
|
+
},
|
|
1459
|
+
caret: { active: false, inCanvas: false },
|
|
1460
|
+
focus: { region: "pane" },
|
|
1461
|
+
modal: { open: false },
|
|
1462
|
+
collab: { attached: false, readOnly: false, sourceCanonical: false },
|
|
1463
|
+
ai: { configured: false, streaming: false, waiting: false },
|
|
1464
|
+
capability: {
|
|
1465
|
+
gitClone: false,
|
|
1466
|
+
importSite: false,
|
|
1467
|
+
openProjectInNewWindow: false,
|
|
1468
|
+
dataRows: false,
|
|
1469
|
+
windowControls: false,
|
|
1470
|
+
findReferences: false
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1623
1473
|
}
|
|
1624
|
-
function
|
|
1625
|
-
|
|
1474
|
+
function makeContext(patch = {}) {
|
|
1475
|
+
const base = emptyContext();
|
|
1476
|
+
for (const key of Object.keys(patch)) {
|
|
1477
|
+
const group = patch[key];
|
|
1478
|
+
if (group) {
|
|
1479
|
+
Object.assign(base[key], group);
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1482
|
+
return base;
|
|
1626
1483
|
}
|
|
1627
|
-
var
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
locate: ([, prop], root) => {
|
|
1638
|
-
const inspector = resolveRegion("inspector", root);
|
|
1639
|
-
return inspector ? [...inspector.querySelectorAll(`[data-prop="${CSS.escape(prop)}"]`)] : [];
|
|
1640
|
-
},
|
|
1641
|
-
pattern: /^inspector\/field:(.+)$/
|
|
1484
|
+
var MODAL_STACK = ["palette"];
|
|
1485
|
+
var CARET_STACK = ["caret", "global"];
|
|
1486
|
+
var DOCK_STACK = ["dock", "global"];
|
|
1487
|
+
var CANVAS_STACK = ["canvas", "global"];
|
|
1488
|
+
var GRID_STACK = ["grid", "global"];
|
|
1489
|
+
var CODE_STACK = ["code", "global"];
|
|
1490
|
+
var GLOBAL_STACK = ["global"];
|
|
1491
|
+
function keyScopeStack(ctx) {
|
|
1492
|
+
if (ctx.modal.open) {
|
|
1493
|
+
return MODAL_STACK;
|
|
1642
1494
|
}
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
const canonical = canonicalRegionId(id);
|
|
1646
|
-
if (!isRegionId(canonical)) {
|
|
1647
|
-
return [];
|
|
1495
|
+
if (ctx.caret.active) {
|
|
1496
|
+
return CARET_STACK;
|
|
1648
1497
|
}
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
];
|
|
1652
|
-
if (stamped.length > 0) {
|
|
1653
|
-
return stamped;
|
|
1498
|
+
if (ctx.focus.region !== "pane") {
|
|
1499
|
+
return DOCK_STACK;
|
|
1654
1500
|
}
|
|
1655
|
-
|
|
1656
|
-
|
|
1657
|
-
|
|
1658
|
-
return resolver.locate(match, regionRoot(root));
|
|
1501
|
+
switch (ctx.editor.kind) {
|
|
1502
|
+
case "grid": {
|
|
1503
|
+
return GRID_STACK;
|
|
1659
1504
|
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
}
|
|
1663
|
-
function resolveRegion(id, root) {
|
|
1664
|
-
const all = resolveAllRegions(id, root);
|
|
1665
|
-
return all.at(-1) ?? null;
|
|
1666
|
-
}
|
|
1667
|
-
var REGION_FOR_FOCUS = {
|
|
1668
|
-
dock: "dock.bottom",
|
|
1669
|
-
inspector: "inspector",
|
|
1670
|
-
navigator: "navigator",
|
|
1671
|
-
pane: "pane.primary",
|
|
1672
|
-
rail: "rail",
|
|
1673
|
-
status: "statusbar"
|
|
1674
|
-
};
|
|
1675
|
-
function paneRegion(paneId, part) {
|
|
1676
|
-
return part ? `pane.${paneId}/${part}` : `pane.${paneId}`;
|
|
1677
|
-
}
|
|
1678
|
-
function paneStripRegion(paneId) {
|
|
1679
|
-
return paneRegion(paneId, "tabs");
|
|
1680
|
-
}
|
|
1681
|
-
function navigatorPanelRegion(panelId) {
|
|
1682
|
-
return `navigator/panel:${panelId}`;
|
|
1683
|
-
}
|
|
1684
|
-
function inspectorTabRegion(tabId) {
|
|
1685
|
-
return `inspector/tab:${tabId}`;
|
|
1686
|
-
}
|
|
1687
|
-
var NAVIGATOR_STATEMENTS_REGION = "navigator/statements";
|
|
1688
|
-
function inspectorStatementsRegion(eventKey) {
|
|
1689
|
-
return `inspector/statements:${eventKey}`;
|
|
1690
|
-
}
|
|
1691
|
-
function bottomPanelRegion(panelId) {
|
|
1692
|
-
return `dock.bottom/panel:${panelId}`;
|
|
1693
|
-
}
|
|
1694
|
-
var OVERLAY_INSTANCE = {
|
|
1695
|
-
dialog: "dialog",
|
|
1696
|
-
modal: "dialog",
|
|
1697
|
-
popover: "menu",
|
|
1698
|
-
toast: "toasts"
|
|
1699
|
-
};
|
|
1700
|
-
function overlayRegion(layer, id) {
|
|
1701
|
-
const instance = OVERLAY_INSTANCE[layer];
|
|
1702
|
-
return id ? `overlay.${instance}:${id}` : `overlay.${instance}`;
|
|
1703
|
-
}
|
|
1704
|
-
|
|
1705
|
-
// src/commands/active-registry.ts
|
|
1706
|
-
var _registry = shallowRef(null);
|
|
1707
|
-
function setActiveRegistry(registry) {
|
|
1708
|
-
_registry.value = registry;
|
|
1709
|
-
}
|
|
1710
|
-
function activeRegistry() {
|
|
1711
|
-
return _registry.value;
|
|
1712
|
-
}
|
|
1713
|
-
|
|
1714
|
-
// src/ui/layers.ts
|
|
1715
|
-
var _popoverLayer;
|
|
1716
|
-
var _modalLayer;
|
|
1717
|
-
var _dialogLayer;
|
|
1718
|
-
var _toastLayer;
|
|
1719
|
-
function layerHost(kind) {
|
|
1720
|
-
const host = kind === "popover" ? _popoverLayer : kind === "modal" ? _modalLayer : kind === "toast" ? _toastLayer : _dialogLayer;
|
|
1721
|
-
return host || document.body;
|
|
1722
|
-
}
|
|
1723
|
-
function initLayers() {
|
|
1724
|
-
_popoverLayer = document.querySelector("#layer-popover");
|
|
1725
|
-
_modalLayer = document.querySelector("#layer-modal");
|
|
1726
|
-
_dialogLayer = document.querySelector("#layer-dialog");
|
|
1727
|
-
_toastLayer = document.querySelector("#layer-toast");
|
|
1728
|
-
mountToastHost();
|
|
1729
|
-
}
|
|
1730
|
-
var UNDERLAID = "sp-dialog-wrapper[open], sp-underlay[open]";
|
|
1731
|
-
function isModalOpen() {
|
|
1732
|
-
return Boolean(_dialogLayer?.querySelector(UNDERLAID) || _modalLayer?.querySelector(UNDERLAID));
|
|
1733
|
-
}
|
|
1734
|
-
var BODY_FOCUSABLE = 'a[href], input, textarea, select, button, sp-textfield, sp-button, sp-action-button, sp-picker, sp-checkbox, sp-menu-item, [tabindex]:not([tabindex="-1"])';
|
|
1735
|
-
function focusablesIn(slot) {
|
|
1736
|
-
return [...slot.querySelectorAll(BODY_FOCUSABLE)].filter((el) => !el.hasAttribute("disabled") && el.getAttribute("aria-hidden") !== "true");
|
|
1737
|
-
}
|
|
1738
|
-
function focusOverlay(slot) {
|
|
1739
|
-
requestAnimationFrame(() => {
|
|
1740
|
-
if (!slot.isConnected || slot.contains(document.activeElement)) {
|
|
1741
|
-
return;
|
|
1505
|
+
case "code": {
|
|
1506
|
+
return CODE_STACK;
|
|
1742
1507
|
}
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
target.focus();
|
|
1746
|
-
});
|
|
1747
|
-
}
|
|
1748
|
-
function trapTab(slot, e) {
|
|
1749
|
-
e.preventDefault();
|
|
1750
|
-
const items = focusablesIn(slot);
|
|
1751
|
-
if (items.length === 0) {
|
|
1752
|
-
return;
|
|
1753
|
-
}
|
|
1754
|
-
const at = items.indexOf(document.activeElement);
|
|
1755
|
-
const next = e.shiftKey ? items[at <= 0 ? items.length - 1 : at - 1] : items[at === -1 || at === items.length - 1 ? 0 : at + 1];
|
|
1756
|
-
next?.focus();
|
|
1757
|
-
}
|
|
1758
|
-
function openOverlaySlot(opts) {
|
|
1759
|
-
const slot = document.createElement("div");
|
|
1760
|
-
slot.style.pointerEvents = "auto";
|
|
1761
|
-
slot.setAttribute(REGION_ATTR, overlayRegion(opts.kind, opts.regionId));
|
|
1762
|
-
slot.tabIndex = -1;
|
|
1763
|
-
slot.style.outline = "none";
|
|
1764
|
-
opts.layer.append(slot);
|
|
1765
|
-
const restoreTo = document.activeElement instanceof HTMLElement ? document.activeElement : null;
|
|
1766
|
-
const onKeydown = (e) => {
|
|
1767
|
-
if (e.key === "Escape") {
|
|
1768
|
-
opts.onEscape?.(e, slot);
|
|
1769
|
-
return;
|
|
1508
|
+
case "canvas": {
|
|
1509
|
+
return ctx.canvas.view === "preview" ? GLOBAL_STACK : CANVAS_STACK;
|
|
1770
1510
|
}
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
}
|
|
1774
|
-
};
|
|
1775
|
-
slot.addEventListener("keydown", onKeydown);
|
|
1776
|
-
return {
|
|
1777
|
-
release() {
|
|
1778
|
-
slot.removeEventListener("keydown", onKeydown);
|
|
1779
|
-
render(nothing, slot);
|
|
1780
|
-
slot.remove();
|
|
1781
|
-
if (restoreTo?.isConnected) {
|
|
1782
|
-
restoreTo.focus();
|
|
1783
|
-
}
|
|
1784
|
-
},
|
|
1785
|
-
slot
|
|
1786
|
-
};
|
|
1787
|
-
}
|
|
1788
|
-
function showDialog(templateFn, opts = {}) {
|
|
1789
|
-
return new Promise((resolve) => {
|
|
1790
|
-
const { release, slot } = openOverlaySlot({
|
|
1791
|
-
kind: "dialog",
|
|
1792
|
-
layer: layerHost("dialog"),
|
|
1793
|
-
regionId: opts.region,
|
|
1794
|
-
onEscape(e, host) {
|
|
1795
|
-
const wrapper = host.querySelector("sp-dialog-wrapper");
|
|
1796
|
-
if (!wrapper) {
|
|
1797
|
-
return;
|
|
1798
|
-
}
|
|
1799
|
-
e.preventDefault();
|
|
1800
|
-
e.stopPropagation();
|
|
1801
|
-
wrapper.dispatchEvent(new Event("close", { bubbles: true }));
|
|
1802
|
-
}
|
|
1803
|
-
});
|
|
1804
|
-
slot.setAttribute("role", "dialog");
|
|
1805
|
-
slot.setAttribute("aria-modal", "true");
|
|
1806
|
-
let resolved = false;
|
|
1807
|
-
const done = (value) => {
|
|
1808
|
-
if (resolved) {
|
|
1809
|
-
return;
|
|
1810
|
-
}
|
|
1811
|
-
resolved = true;
|
|
1812
|
-
release();
|
|
1813
|
-
resolve(value);
|
|
1814
|
-
};
|
|
1815
|
-
render(templateFn(done), slot);
|
|
1816
|
-
const headline = opts.label ?? slot.querySelector("sp-dialog-wrapper")?.getAttribute("headline") ?? null;
|
|
1817
|
-
if (headline !== null && headline !== "") {
|
|
1818
|
-
slot.setAttribute("aria-label", headline);
|
|
1819
|
-
}
|
|
1820
|
-
focusOverlay(slot);
|
|
1821
|
-
});
|
|
1822
|
-
}
|
|
1823
|
-
function showConfirmDialog(headline, message, opts = {}) {
|
|
1824
|
-
const { confirmLabel = "Confirm", cancelLabel = "Cancel", destructive = false } = opts;
|
|
1825
|
-
return showDialog((done) => html`
|
|
1826
|
-
<sp-dialog-wrapper
|
|
1827
|
-
open
|
|
1828
|
-
underlay
|
|
1829
|
-
headline=${headline}
|
|
1830
|
-
confirm-label=${confirmLabel}
|
|
1831
|
-
cancel-label=${cancelLabel}
|
|
1832
|
-
size="s"
|
|
1833
|
-
@confirm=${() => done(true)}
|
|
1834
|
-
@cancel=${() => done(false)}
|
|
1835
|
-
@close=${() => done(false)}
|
|
1836
|
-
class=${destructive ? "dialog-destructive" : ""}
|
|
1837
|
-
>
|
|
1838
|
-
<p>${message}</p>
|
|
1839
|
-
</sp-dialog-wrapper>
|
|
1840
|
-
`);
|
|
1841
|
-
}
|
|
1842
|
-
function showSaveDiscardDialog(headline, message, opts = {}) {
|
|
1843
|
-
const { saveLabel = "Save", discardLabel = "Discard", cancelLabel = "Cancel" } = opts;
|
|
1844
|
-
return showDialog((done) => html`
|
|
1845
|
-
<sp-dialog-wrapper
|
|
1846
|
-
open
|
|
1847
|
-
underlay
|
|
1848
|
-
headline=${headline}
|
|
1849
|
-
confirm-label=${saveLabel}
|
|
1850
|
-
secondary-label=${discardLabel}
|
|
1851
|
-
cancel-label=${cancelLabel}
|
|
1852
|
-
size="s"
|
|
1853
|
-
@confirm=${() => done("save")}
|
|
1854
|
-
@secondary=${() => done("discard")}
|
|
1855
|
-
@cancel=${() => done("cancel")}
|
|
1856
|
-
@close=${() => done("cancel")}
|
|
1857
|
-
>
|
|
1858
|
-
<p>${message}</p>
|
|
1859
|
-
</sp-dialog-wrapper>
|
|
1860
|
-
`);
|
|
1861
|
-
}
|
|
1862
|
-
function showPromptDialog(headline, opts = {}) {
|
|
1863
|
-
const {
|
|
1864
|
-
cancelLabel = "Cancel",
|
|
1865
|
-
confirmLabel = "OK",
|
|
1866
|
-
message,
|
|
1867
|
-
placeholder = "",
|
|
1868
|
-
select = "all",
|
|
1869
|
-
validate,
|
|
1870
|
-
value: initialValue = ""
|
|
1871
|
-
} = opts;
|
|
1872
|
-
const check = (candidate) => validate ? validate(candidate) : candidate.trim() ? "" : "Enter a value.";
|
|
1873
|
-
let value = initialValue;
|
|
1874
|
-
let error = "";
|
|
1875
|
-
let wrapperEl = null;
|
|
1876
|
-
let focusRequested = false;
|
|
1877
|
-
return showDialog((done) => {
|
|
1878
|
-
function rerender() {
|
|
1879
|
-
const host = wrapperEl?.parentElement;
|
|
1880
|
-
if (host) {
|
|
1881
|
-
render(buildTpl(), host);
|
|
1882
|
-
}
|
|
1883
|
-
}
|
|
1884
|
-
function confirm() {
|
|
1885
|
-
error = check(value);
|
|
1886
|
-
if (error) {
|
|
1887
|
-
rerender();
|
|
1888
|
-
return;
|
|
1889
|
-
}
|
|
1890
|
-
done(value.trim());
|
|
1891
|
-
}
|
|
1892
|
-
function onInput(e) {
|
|
1893
|
-
value = e.target.value || "";
|
|
1894
|
-
const next = check(value);
|
|
1895
|
-
if (next !== error) {
|
|
1896
|
-
error = next;
|
|
1897
|
-
rerender();
|
|
1898
|
-
}
|
|
1899
|
-
}
|
|
1900
|
-
function onKeydown(e) {
|
|
1901
|
-
if (e.key === "Enter") {
|
|
1902
|
-
confirm();
|
|
1903
|
-
}
|
|
1904
|
-
}
|
|
1905
|
-
function onWrapperRef(el) {
|
|
1906
|
-
if (el) {
|
|
1907
|
-
wrapperEl = el;
|
|
1908
|
-
}
|
|
1909
|
-
}
|
|
1910
|
-
function onFieldRef(el) {
|
|
1911
|
-
if (!el || focusRequested) {
|
|
1912
|
-
return;
|
|
1913
|
-
}
|
|
1914
|
-
focusRequested = true;
|
|
1915
|
-
const field = el;
|
|
1916
|
-
requestAnimationFrame(() => {
|
|
1917
|
-
field.focus();
|
|
1918
|
-
const input = field.shadowRoot?.querySelector("input");
|
|
1919
|
-
if (!input || select === "none") {
|
|
1920
|
-
return;
|
|
1921
|
-
}
|
|
1922
|
-
if (select === "stem") {
|
|
1923
|
-
const dot = input.value.lastIndexOf(".");
|
|
1924
|
-
input.setSelectionRange(0, dot > 0 ? dot : input.value.length);
|
|
1925
|
-
return;
|
|
1926
|
-
}
|
|
1927
|
-
input.select();
|
|
1928
|
-
});
|
|
1929
|
-
}
|
|
1930
|
-
function buildTpl() {
|
|
1931
|
-
return html`
|
|
1932
|
-
<sp-dialog-wrapper
|
|
1933
|
-
open
|
|
1934
|
-
underlay
|
|
1935
|
-
headline=${headline}
|
|
1936
|
-
confirm-label=${confirmLabel}
|
|
1937
|
-
cancel-label=${cancelLabel}
|
|
1938
|
-
size="s"
|
|
1939
|
-
@confirm=${confirm}
|
|
1940
|
-
@cancel=${() => done(null)}
|
|
1941
|
-
@close=${() => done(null)}
|
|
1942
|
-
${ref(onWrapperRef)}
|
|
1943
|
-
>
|
|
1944
|
-
${message ? html`<p style="margin:0 0 8px">${message}</p>` : nothing}
|
|
1945
|
-
<sp-textfield
|
|
1946
|
-
style="width:100%"
|
|
1947
|
-
placeholder=${placeholder}
|
|
1948
|
-
value=${value}
|
|
1949
|
-
?invalid=${Boolean(error)}
|
|
1950
|
-
@input=${onInput}
|
|
1951
|
-
@keydown=${onKeydown}
|
|
1952
|
-
${ref(onFieldRef)}
|
|
1953
|
-
>
|
|
1954
|
-
${error ? html`<sp-help-text slot="negative-help-text">${error}</sp-help-text>` : nothing}
|
|
1955
|
-
</sp-textfield>
|
|
1956
|
-
</sp-dialog-wrapper>
|
|
1957
|
-
`;
|
|
1958
|
-
}
|
|
1959
|
-
return buildTpl();
|
|
1960
|
-
});
|
|
1961
|
-
}
|
|
1962
|
-
function openModal(template, opts) {
|
|
1963
|
-
const { release, slot } = openOverlaySlot({
|
|
1964
|
-
kind: "modal",
|
|
1965
|
-
layer: layerHost("modal"),
|
|
1966
|
-
onEscape(e) {
|
|
1967
|
-
if (opts.dismissible === false) {
|
|
1968
|
-
return;
|
|
1969
|
-
}
|
|
1970
|
-
e.preventDefault();
|
|
1971
|
-
e.stopPropagation();
|
|
1972
|
-
(opts.onDismiss ?? handle.close)();
|
|
1973
|
-
},
|
|
1974
|
-
regionId: opts.region,
|
|
1975
|
-
trapFocus: true
|
|
1976
|
-
});
|
|
1977
|
-
slot.setAttribute("role", "dialog");
|
|
1978
|
-
slot.setAttribute("aria-modal", "true");
|
|
1979
|
-
slot.setAttribute("aria-label", opts.label);
|
|
1980
|
-
const handle = {
|
|
1981
|
-
close() {
|
|
1982
|
-
release();
|
|
1983
|
-
},
|
|
1984
|
-
host: slot,
|
|
1985
|
-
update(tpl) {
|
|
1986
|
-
render(tpl, slot);
|
|
1987
|
-
}
|
|
1988
|
-
};
|
|
1989
|
-
render(template, slot);
|
|
1990
|
-
focusOverlay(slot);
|
|
1991
|
-
return handle;
|
|
1992
|
-
}
|
|
1993
|
-
function renderPopover(template, opts = {}) {
|
|
1994
|
-
const kind = opts.layer ?? "popover";
|
|
1995
|
-
const slot = document.createElement("div");
|
|
1996
|
-
slot.style.pointerEvents = "auto";
|
|
1997
|
-
slot.setAttribute(REGION_ATTR, overlayRegion(kind, opts.region));
|
|
1998
|
-
layerHost(kind).append(slot);
|
|
1999
|
-
render(template, slot);
|
|
2000
|
-
let outsideClickHandler = null;
|
|
2001
|
-
if (opts.dismissOnOutsideClick !== false) {
|
|
2002
|
-
outsideClickHandler = (e) => {
|
|
2003
|
-
if (!slot.contains(e.target)) {
|
|
2004
|
-
handle.dismiss();
|
|
2005
|
-
opts.onDismiss?.();
|
|
2006
|
-
}
|
|
2007
|
-
};
|
|
2008
|
-
requestAnimationFrame(() => {
|
|
2009
|
-
if (outsideClickHandler) {
|
|
2010
|
-
document.addEventListener("mousedown", outsideClickHandler, true);
|
|
2011
|
-
}
|
|
2012
|
-
});
|
|
2013
|
-
}
|
|
2014
|
-
const handle = {
|
|
2015
|
-
dismiss() {
|
|
2016
|
-
if (outsideClickHandler) {
|
|
2017
|
-
document.removeEventListener("mousedown", outsideClickHandler, true);
|
|
2018
|
-
outsideClickHandler = null;
|
|
2019
|
-
}
|
|
2020
|
-
render(nothing, slot);
|
|
2021
|
-
slot.remove();
|
|
2022
|
-
},
|
|
2023
|
-
host: slot,
|
|
2024
|
-
update(tpl) {
|
|
2025
|
-
render(tpl, slot);
|
|
2026
|
-
}
|
|
2027
|
-
};
|
|
2028
|
-
return handle;
|
|
2029
|
-
}
|
|
2030
|
-
var _namedSlots = new Map;
|
|
2031
|
-
function popoverLayerFor(anchor) {
|
|
2032
|
-
if (anchor?.closest("#layer-dialog")) {
|
|
2033
|
-
return "dialog";
|
|
2034
|
-
}
|
|
2035
|
-
return anchor?.closest("#layer-modal") ? "modal" : "popover";
|
|
2036
|
-
}
|
|
2037
|
-
function getLayerSlot(layer, id) {
|
|
2038
|
-
const key = `${layer}:${id}`;
|
|
2039
|
-
let slot = _namedSlots.get(key);
|
|
2040
|
-
if (slot && slot.parentElement) {
|
|
2041
|
-
return slot;
|
|
2042
|
-
}
|
|
2043
|
-
slot = document.createElement("div");
|
|
2044
|
-
slot.style.pointerEvents = "auto";
|
|
2045
|
-
slot.setAttribute(REGION_ATTR, overlayRegion(layer, id));
|
|
2046
|
-
layerHost(layer).append(slot);
|
|
2047
|
-
_namedSlots.set(key, slot);
|
|
2048
|
-
return slot;
|
|
2049
|
-
}
|
|
2050
|
-
var TOAST_ENTER_MS = 180;
|
|
2051
|
-
var TOAST_ICON = {
|
|
2052
|
-
error: "✕",
|
|
2053
|
-
info: "ℹ",
|
|
2054
|
-
success: "✓",
|
|
2055
|
-
warn: "!"
|
|
2056
|
-
};
|
|
2057
|
-
var _toastScope = null;
|
|
2058
|
-
var _toastTimers = new Map;
|
|
2059
|
-
var _toastEntering = new Set;
|
|
2060
|
-
function reducedMotion() {
|
|
2061
|
-
return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
2062
|
-
}
|
|
2063
|
-
function toastsAreHeld() {
|
|
2064
|
-
try {
|
|
2065
|
-
return new URLSearchParams(globalThis.location?.search ?? "").get("automation") === "1";
|
|
2066
|
-
} catch {
|
|
2067
|
-
return false;
|
|
2068
|
-
}
|
|
2069
|
-
}
|
|
2070
|
-
function overlayIdleBlockers() {
|
|
2071
|
-
return [..._toastEntering].map((id) => `overlay: toast ${id} settling in`);
|
|
2072
|
-
}
|
|
2073
|
-
function retireToast(id) {
|
|
2074
|
-
const timer = _toastTimers.get(id);
|
|
2075
|
-
if (timer !== undefined) {
|
|
2076
|
-
clearTimeout(timer);
|
|
2077
|
-
_toastTimers.delete(id);
|
|
2078
|
-
}
|
|
2079
|
-
_toastEntering.delete(id);
|
|
2080
|
-
dismiss(id);
|
|
2081
|
-
}
|
|
2082
|
-
function scheduleToast(record) {
|
|
2083
|
-
if (_toastTimers.has(record.id) || _toastEntering.has(record.id)) {
|
|
2084
|
-
return;
|
|
2085
|
-
}
|
|
2086
|
-
const settle = reducedMotion() ? 0 : TOAST_ENTER_MS;
|
|
2087
|
-
if (settle > 0) {
|
|
2088
|
-
_toastEntering.add(record.id);
|
|
2089
|
-
setTimeout(() => _toastEntering.delete(record.id), settle);
|
|
2090
|
-
}
|
|
2091
|
-
const rest = record.timeoutMs ?? 0;
|
|
2092
|
-
if (rest <= 0 || toastsAreHeld()) {
|
|
2093
|
-
return;
|
|
2094
|
-
}
|
|
2095
|
-
_toastTimers.set(record.id, setTimeout(() => retireToast(record.id), rest));
|
|
2096
|
-
}
|
|
2097
|
-
function toastActionTpl(record) {
|
|
2098
|
-
const registry = record.action === undefined ? null : activeRegistry();
|
|
2099
|
-
const id = record.action;
|
|
2100
|
-
if (!registry || id === undefined || !registry.get(id) || !registry.isVisible(id)) {
|
|
2101
|
-
return nothing;
|
|
2102
|
-
}
|
|
2103
|
-
const command = registry.get(id);
|
|
2104
|
-
const reason = registry.disabledReason(id);
|
|
2105
|
-
return html`
|
|
2106
|
-
<button
|
|
2107
|
-
class="toast-action"
|
|
2108
|
-
?disabled=${reason !== undefined}
|
|
2109
|
-
title=${reason === undefined ? command.title : `${command.title} — requires ${reason}`}
|
|
2110
|
-
@click=${() => {
|
|
2111
|
-
retireToast(record.id);
|
|
2112
|
-
registry.run(id, record.actionArgs);
|
|
2113
|
-
}}
|
|
2114
|
-
>
|
|
2115
|
-
${command.title}
|
|
2116
|
-
</button>
|
|
2117
|
-
`;
|
|
2118
|
-
}
|
|
2119
|
-
function toastTpl(record) {
|
|
2120
|
-
return html`
|
|
2121
|
-
<div class="toast toast--${record.severity}">
|
|
2122
|
-
<span class="toast-icon" aria-hidden="true">${TOAST_ICON[record.severity]}</span>
|
|
2123
|
-
<span class="toast-message">${record.message}</span>
|
|
2124
|
-
${toastActionTpl(record)}
|
|
2125
|
-
<button
|
|
2126
|
-
class="toast-dismiss"
|
|
2127
|
-
title="Dismiss"
|
|
2128
|
-
aria-label="Dismiss notification"
|
|
2129
|
-
@click=${() => retireToast(record.id)}
|
|
2130
|
-
>
|
|
2131
|
-
<span aria-hidden="true">×</span>
|
|
2132
|
-
</button>
|
|
2133
|
-
</div>
|
|
2134
|
-
`;
|
|
2135
|
-
}
|
|
2136
|
-
function toastStackTemplate() {
|
|
2137
|
-
return html`
|
|
2138
|
-
<div class="toast-stack">
|
|
2139
|
-
${repeat(toasts, (record) => record.id, (record) => toastTpl(record))}
|
|
2140
|
-
</div>
|
|
2141
|
-
`;
|
|
2142
|
-
}
|
|
2143
|
-
function mountToastHost() {
|
|
2144
|
-
unmountToastHost();
|
|
2145
|
-
if (!_toastLayer) {
|
|
2146
|
-
return;
|
|
2147
|
-
}
|
|
2148
|
-
_toastScope = effectScope();
|
|
2149
|
-
_toastScope.run(() => {
|
|
2150
|
-
effect(() => {
|
|
2151
|
-
toasts.length;
|
|
2152
|
-
activeRegistry();
|
|
2153
|
-
for (const record of toasts) {
|
|
2154
|
-
scheduleToast(record);
|
|
2155
|
-
}
|
|
2156
|
-
render(toastStackTemplate(), _toastLayer);
|
|
2157
|
-
});
|
|
2158
|
-
});
|
|
2159
|
-
}
|
|
2160
|
-
function unmountToastHost() {
|
|
2161
|
-
_toastScope?.stop();
|
|
2162
|
-
_toastScope = null;
|
|
2163
|
-
for (const timer of _toastTimers.values()) {
|
|
2164
|
-
clearTimeout(timer);
|
|
2165
|
-
}
|
|
2166
|
-
_toastTimers.clear();
|
|
2167
|
-
_toastEntering.clear();
|
|
2168
|
-
if (_toastLayer) {
|
|
2169
|
-
render(nothing, _toastLayer);
|
|
2170
|
-
}
|
|
2171
|
-
}
|
|
2172
|
-
|
|
2173
|
-
// src/collab/collab-state.ts
|
|
2174
|
-
var states = new WeakMap;
|
|
2175
|
-
var attachedPaths = new Map;
|
|
2176
|
-
function collabState(tab) {
|
|
2177
|
-
const key = toRaw(tab);
|
|
2178
|
-
let state = states.get(key);
|
|
2179
|
-
if (!state) {
|
|
2180
|
-
state = reactive({
|
|
2181
|
-
active: false,
|
|
2182
|
-
attachError: "",
|
|
2183
|
-
peers: [],
|
|
2184
|
-
readOnly: false,
|
|
2185
|
-
sourceCanonical: false,
|
|
2186
|
-
status: "unavailable"
|
|
2187
|
-
});
|
|
2188
|
-
states.set(key, state);
|
|
2189
|
-
}
|
|
2190
|
-
return state;
|
|
2191
|
-
}
|
|
2192
|
-
function registerCollabPath(path) {
|
|
2193
|
-
attachedPaths.set(path, (attachedPaths.get(path) ?? 0) + 1);
|
|
2194
|
-
}
|
|
2195
|
-
function unregisterCollabPath(path) {
|
|
2196
|
-
const count = attachedPaths.get(path) ?? 0;
|
|
2197
|
-
if (count <= 1) {
|
|
2198
|
-
attachedPaths.delete(path);
|
|
2199
|
-
} else {
|
|
2200
|
-
attachedPaths.set(path, count - 1);
|
|
2201
|
-
}
|
|
2202
|
-
}
|
|
2203
|
-
function isCollabPath(path) {
|
|
2204
|
-
return attachedPaths.has(path.replaceAll("\\", "/"));
|
|
2205
|
-
}
|
|
2206
|
-
|
|
2207
|
-
// src/commands/context.ts
|
|
2208
|
-
var EDITOR_KIND_BY_MODE = {
|
|
2209
|
-
design: "canvas",
|
|
2210
|
-
edit: "canvas",
|
|
2211
|
-
entry: "entry",
|
|
2212
|
-
"git-diff": "diff",
|
|
2213
|
-
grid: "grid",
|
|
2214
|
-
manage: "library",
|
|
2215
|
-
preview: "canvas",
|
|
2216
|
-
settings: "config",
|
|
2217
|
-
source: "code",
|
|
2218
|
-
stylebook: "config"
|
|
2219
|
-
};
|
|
2220
|
-
var EDITOR_KIND_LABELS = {
|
|
2221
|
-
canvas: "Canvas",
|
|
2222
|
-
code: "Code",
|
|
2223
|
-
config: "Project Styles",
|
|
2224
|
-
diff: "Diff",
|
|
2225
|
-
entry: "Entry",
|
|
2226
|
-
grid: "Grid",
|
|
2227
|
-
library: "Library",
|
|
2228
|
-
none: "None"
|
|
2229
|
-
};
|
|
2230
|
-
function editorKindForMode(mode) {
|
|
2231
|
-
return EDITOR_KIND_BY_MODE[mode] ?? "canvas";
|
|
2232
|
-
}
|
|
2233
|
-
var CANVAS_VIEW_BY_MODE = {
|
|
2234
|
-
design: "design",
|
|
2235
|
-
edit: "edit",
|
|
2236
|
-
preview: "preview"
|
|
2237
|
-
};
|
|
2238
|
-
function canvasViewForMode(mode) {
|
|
2239
|
-
return CANVAS_VIEW_BY_MODE[mode] ?? "design";
|
|
2240
|
-
}
|
|
2241
|
-
var inCanvas = (ctx) => ctx.editor.kind === "canvas";
|
|
2242
|
-
var hasSelection = (ctx) => inCanvas(ctx) && ctx.selection.count > 0;
|
|
2243
|
-
var hasElementSelection = (ctx) => hasSelection(ctx) && !ctx.selection.isRoot;
|
|
2244
|
-
function emptyContext() {
|
|
2245
|
-
return {
|
|
2246
|
-
project: { open: false, isSite: false, isRepo: false, isMultilingual: false },
|
|
2247
|
-
git: { ahead: 0, behind: 0, dirtyCount: 0 },
|
|
2248
|
-
document: { open: false, dirty: false, mode: "", canUndo: false, canRedo: false },
|
|
2249
|
-
editor: { kind: "none" },
|
|
2250
|
-
canvas: { view: "design" },
|
|
2251
|
-
pane: { count: 1, derived: false },
|
|
2252
|
-
selection: {
|
|
2253
|
-
count: 0,
|
|
2254
|
-
paths: [],
|
|
2255
|
-
kind: "",
|
|
2256
|
-
isRoot: false,
|
|
2257
|
-
isComponentInstance: false,
|
|
2258
|
-
isLayoutNode: false,
|
|
2259
|
-
isRepeater: false
|
|
2260
|
-
},
|
|
2261
|
-
caret: { active: false, inCanvas: false },
|
|
2262
|
-
focus: { region: "pane" },
|
|
2263
|
-
modal: { open: false },
|
|
2264
|
-
collab: { attached: false, readOnly: false, sourceCanonical: false },
|
|
2265
|
-
ai: { configured: false, streaming: false },
|
|
2266
|
-
capability: {
|
|
2267
|
-
gitClone: false,
|
|
2268
|
-
importSite: false,
|
|
2269
|
-
openProjectInNewWindow: false,
|
|
2270
|
-
dataRows: false,
|
|
2271
|
-
windowControls: false,
|
|
2272
|
-
findReferences: false
|
|
2273
|
-
}
|
|
2274
|
-
};
|
|
2275
|
-
}
|
|
2276
|
-
function makeContext(patch = {}) {
|
|
2277
|
-
const base = emptyContext();
|
|
2278
|
-
for (const key of Object.keys(patch)) {
|
|
2279
|
-
const group = patch[key];
|
|
2280
|
-
if (group) {
|
|
2281
|
-
Object.assign(base[key], group);
|
|
2282
|
-
}
|
|
2283
|
-
}
|
|
2284
|
-
return base;
|
|
2285
|
-
}
|
|
2286
|
-
var MODAL_STACK = ["palette"];
|
|
2287
|
-
var CARET_STACK = ["caret", "global"];
|
|
2288
|
-
var DOCK_STACK = ["dock", "global"];
|
|
2289
|
-
var CANVAS_STACK = ["canvas", "global"];
|
|
2290
|
-
var GRID_STACK = ["grid", "global"];
|
|
2291
|
-
var CODE_STACK = ["code", "global"];
|
|
2292
|
-
var GLOBAL_STACK = ["global"];
|
|
2293
|
-
function keyScopeStack(ctx) {
|
|
2294
|
-
if (ctx.modal.open) {
|
|
2295
|
-
return MODAL_STACK;
|
|
2296
|
-
}
|
|
2297
|
-
if (ctx.caret.active) {
|
|
2298
|
-
return CARET_STACK;
|
|
2299
|
-
}
|
|
2300
|
-
if (ctx.focus.region !== "pane") {
|
|
2301
|
-
return DOCK_STACK;
|
|
2302
|
-
}
|
|
2303
|
-
switch (ctx.editor.kind) {
|
|
2304
|
-
case "grid": {
|
|
2305
|
-
return GRID_STACK;
|
|
2306
|
-
}
|
|
2307
|
-
case "code": {
|
|
2308
|
-
return CODE_STACK;
|
|
2309
|
-
}
|
|
2310
|
-
case "canvas": {
|
|
2311
|
-
return ctx.canvas.view === "preview" ? GLOBAL_STACK : CANVAS_STACK;
|
|
2312
|
-
}
|
|
2313
|
-
default: {
|
|
2314
|
-
return GLOBAL_STACK;
|
|
1511
|
+
default: {
|
|
1512
|
+
return GLOBAL_STACK;
|
|
2315
1513
|
}
|
|
2316
1514
|
}
|
|
2317
1515
|
}
|
|
@@ -2349,7 +1547,7 @@ function createTab({
|
|
|
2349
1547
|
id,
|
|
2350
1548
|
documentPath = null,
|
|
2351
1549
|
fileHandle = null,
|
|
2352
|
-
document
|
|
1550
|
+
document,
|
|
2353
1551
|
frontmatter,
|
|
2354
1552
|
sourceFormat = null,
|
|
2355
1553
|
capabilities,
|
|
@@ -2357,7 +1555,7 @@ function createTab({
|
|
|
2357
1555
|
preview: previewTab = false
|
|
2358
1556
|
}) {
|
|
2359
1557
|
const scope = effectScope();
|
|
2360
|
-
normalizeArrayChildren(
|
|
1558
|
+
normalizeArrayChildren(document);
|
|
2361
1559
|
const resolvedModes = capabilities?.modes ?? inferModes(documentPath, sourceFormat);
|
|
2362
1560
|
const initialCanvasMode = resolvedModes.find((m) => m !== "preview") ?? "edit";
|
|
2363
1561
|
const initialPreview = resolvedModes[0] === "preview";
|
|
@@ -2366,7 +1564,7 @@ function createTab({
|
|
|
2366
1564
|
doc: reactive({
|
|
2367
1565
|
content: { frontmatter: frontmatter || {} },
|
|
2368
1566
|
dirty: false,
|
|
2369
|
-
document
|
|
1567
|
+
document,
|
|
2370
1568
|
handlersSource: null,
|
|
2371
1569
|
mode: inferDocumentMode(documentPath, sourceFormat),
|
|
2372
1570
|
sourceFormat
|
|
@@ -2375,7 +1573,7 @@ function createTab({
|
|
|
2375
1573
|
fileHandle,
|
|
2376
1574
|
history: reactive({
|
|
2377
1575
|
index: 0,
|
|
2378
|
-
snapshots: [{ document: structuredClone(
|
|
1576
|
+
snapshots: [{ document: structuredClone(document), selection: [] }]
|
|
2379
1577
|
}),
|
|
2380
1578
|
id,
|
|
2381
1579
|
pinned: false,
|
|
@@ -2439,6 +1637,40 @@ function disposeTab(tab) {
|
|
|
2439
1637
|
tab.scope.stop();
|
|
2440
1638
|
}
|
|
2441
1639
|
|
|
1640
|
+
// src/collab/collab-state.ts
|
|
1641
|
+
var states = new WeakMap;
|
|
1642
|
+
var attachedPaths = new Map;
|
|
1643
|
+
function collabState(tab) {
|
|
1644
|
+
const key = toRaw(tab);
|
|
1645
|
+
let state = states.get(key);
|
|
1646
|
+
if (!state) {
|
|
1647
|
+
state = reactive({
|
|
1648
|
+
active: false,
|
|
1649
|
+
attachError: "",
|
|
1650
|
+
peers: [],
|
|
1651
|
+
readOnly: false,
|
|
1652
|
+
sourceCanonical: false,
|
|
1653
|
+
status: "unavailable"
|
|
1654
|
+
});
|
|
1655
|
+
states.set(key, state);
|
|
1656
|
+
}
|
|
1657
|
+
return state;
|
|
1658
|
+
}
|
|
1659
|
+
function registerCollabPath(path) {
|
|
1660
|
+
attachedPaths.set(path, (attachedPaths.get(path) ?? 0) + 1);
|
|
1661
|
+
}
|
|
1662
|
+
function unregisterCollabPath(path) {
|
|
1663
|
+
const count = attachedPaths.get(path) ?? 0;
|
|
1664
|
+
if (count <= 1) {
|
|
1665
|
+
attachedPaths.delete(path);
|
|
1666
|
+
} else {
|
|
1667
|
+
attachedPaths.set(path, count - 1);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
function isCollabPath(path) {
|
|
1671
|
+
return attachedPaths.has(path.replaceAll("\\", "/"));
|
|
1672
|
+
}
|
|
1673
|
+
|
|
2442
1674
|
// src/collab/collab-session.ts
|
|
2443
1675
|
var SYNC_TIMEOUT_MS = 8000;
|
|
2444
1676
|
var MIRROR_DEBOUNCE_MS = 800;
|
|
@@ -3116,14 +2348,14 @@ function createSession(tab, path, collab, handle) {
|
|
|
3116
2348
|
}
|
|
3117
2349
|
});
|
|
3118
2350
|
effect(() => {
|
|
3119
|
-
const
|
|
2351
|
+
const ref = toRaw(tab.doc.document);
|
|
3120
2352
|
queueMicrotask(() => {
|
|
3121
2353
|
const current = runtimeOf(tab)?.session;
|
|
3122
2354
|
if (current !== session || !session.synced || !session.canWrite) {
|
|
3123
2355
|
return;
|
|
3124
2356
|
}
|
|
3125
2357
|
const nowRef = toRaw(tab.doc.document);
|
|
3126
|
-
if (nowRef !==
|
|
2358
|
+
if (nowRef !== ref || nowRef === session.lastSeenRef) {
|
|
3127
2359
|
return;
|
|
3128
2360
|
}
|
|
3129
2361
|
session.lastSeenRef = nowRef;
|
|
@@ -3245,10 +2477,19 @@ function argsSchema(properties, required = Object.keys(properties)) {
|
|
|
3245
2477
|
function enumProperty(declared, description) {
|
|
3246
2478
|
return { description, enum: [...declared], type: "string" };
|
|
3247
2479
|
}
|
|
3248
|
-
function
|
|
3249
|
-
return {
|
|
3250
|
-
|
|
3251
|
-
|
|
2480
|
+
function derivedEnumProperty(declared, description) {
|
|
2481
|
+
return {
|
|
2482
|
+
description,
|
|
2483
|
+
get enum() {
|
|
2484
|
+
return [...declared()];
|
|
2485
|
+
},
|
|
2486
|
+
type: "string"
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2489
|
+
function numberProperty(description, bounds = {}) {
|
|
2490
|
+
return { description, type: "number", ...bounds };
|
|
2491
|
+
}
|
|
2492
|
+
function booleanProperty(description) {
|
|
3252
2493
|
return { description, type: "boolean" };
|
|
3253
2494
|
}
|
|
3254
2495
|
function pathProperty(description, nullable = false) {
|
|
@@ -3273,6 +2514,7 @@ function stringProperty(description) {
|
|
|
3273
2514
|
var CLOSED_TAB_LIMIT = 20;
|
|
3274
2515
|
var PRIMARY_PANE = "primary";
|
|
3275
2516
|
var SECONDARY_PANE = "secondary";
|
|
2517
|
+
var MAX_PANES = 2;
|
|
3276
2518
|
var workspace = reactive({
|
|
3277
2519
|
activePaneId: PRIMARY_PANE,
|
|
3278
2520
|
clipboard: null,
|
|
@@ -3338,6 +2580,12 @@ function focusPane(paneId) {
|
|
|
3338
2580
|
function isPaneFocused(paneId) {
|
|
3339
2581
|
return workspace.activePaneId === paneId;
|
|
3340
2582
|
}
|
|
2583
|
+
function focusOtherPane() {
|
|
2584
|
+
const other = workspace.panes.find((pane) => pane.id !== workspace.activePaneId);
|
|
2585
|
+
if (other) {
|
|
2586
|
+
focusPane(other.id);
|
|
2587
|
+
}
|
|
2588
|
+
}
|
|
3341
2589
|
function splitRight() {
|
|
3342
2590
|
const source = activePane();
|
|
3343
2591
|
const tabId = source.activeTabId;
|
|
@@ -3633,6 +2881,13 @@ function cycleTab(step) {
|
|
|
3633
2881
|
setActiveTab(id, { cycling: true });
|
|
3634
2882
|
return id;
|
|
3635
2883
|
}
|
|
2884
|
+
function endTabCycle() {
|
|
2885
|
+
const settled = workspace.activeTabId;
|
|
2886
|
+
resetTabCycle();
|
|
2887
|
+
if (settled) {
|
|
2888
|
+
promoteMru(settled);
|
|
2889
|
+
}
|
|
2890
|
+
}
|
|
3636
2891
|
function replaceAllTabs(newTabOpts) {
|
|
3637
2892
|
const oldIds = [...workspace.tabs.keys()];
|
|
3638
2893
|
const oldTabs = [...workspace.tabs.values()];
|
|
@@ -3902,1267 +3157,7 @@ function runUnsplit() {
|
|
|
3902
3157
|
closePane(derived?.id ?? SECONDARY_PANE);
|
|
3903
3158
|
}
|
|
3904
3159
|
|
|
3905
|
-
|
|
3906
|
-
var PANE_IDS = new Set([PRIMARY_PANE, SECONDARY_PANE]);
|
|
3907
|
-
var SCHEMES = new Set(["auto", "light", "dark"]);
|
|
3908
|
-
function uiOf(tab) {
|
|
3909
|
-
const { ui } = tab.session;
|
|
3910
|
-
return {
|
|
3911
|
-
activeMedia: ui.activeMedia,
|
|
3912
|
-
canvasMode: ui.canvasMode,
|
|
3913
|
-
editZoom: ui.editZoom,
|
|
3914
|
-
preview: ui.preview,
|
|
3915
|
-
previewColorScheme: ui.previewColorScheme,
|
|
3916
|
-
previewLocale: ui.previewLocale,
|
|
3917
|
-
showLayout: ui.showLayout,
|
|
3918
|
-
zoom: ui.zoom
|
|
3919
|
-
};
|
|
3920
|
-
}
|
|
3921
|
-
function captureSession() {
|
|
3922
|
-
const ui = {};
|
|
3923
|
-
const panes = [];
|
|
3924
|
-
for (const pane of workspace.panes) {
|
|
3925
|
-
if (pane.derived) {
|
|
3926
|
-
continue;
|
|
3927
|
-
}
|
|
3928
|
-
const files = [];
|
|
3929
|
-
for (const tabId of pane.tabOrder) {
|
|
3930
|
-
const tab = workspace.tabs.get(tabId);
|
|
3931
|
-
if (!tab?.documentPath) {
|
|
3932
|
-
continue;
|
|
3933
|
-
}
|
|
3934
|
-
files.push(tab.documentPath);
|
|
3935
|
-
ui[tab.documentPath] = uiOf(tab);
|
|
3936
|
-
}
|
|
3937
|
-
if (files.length === 0) {
|
|
3938
|
-
continue;
|
|
3939
|
-
}
|
|
3940
|
-
const activeTab2 = pane.activeTabId ? workspace.tabs.get(pane.activeTabId) : null;
|
|
3941
|
-
panes.push({
|
|
3942
|
-
activeFile: activeTab2?.documentPath ?? null,
|
|
3943
|
-
files,
|
|
3944
|
-
id: pane.id
|
|
3945
|
-
});
|
|
3946
|
-
}
|
|
3947
|
-
return { focusedPane: workspace.activePaneId, panes, ui };
|
|
3948
|
-
}
|
|
3949
|
-
function readTabUi(value) {
|
|
3950
|
-
if (typeof value !== "object" || value === null) {
|
|
3951
|
-
return {};
|
|
3952
|
-
}
|
|
3953
|
-
const raw = value;
|
|
3954
|
-
const out = {};
|
|
3955
|
-
if (typeof raw.canvasMode === "string") {
|
|
3956
|
-
out.canvasMode = raw.canvasMode;
|
|
3957
|
-
}
|
|
3958
|
-
if (typeof raw.preview === "boolean") {
|
|
3959
|
-
out.preview = raw.preview;
|
|
3960
|
-
}
|
|
3961
|
-
if (typeof raw.zoom === "number" && Number.isFinite(raw.zoom)) {
|
|
3962
|
-
out.zoom = raw.zoom;
|
|
3963
|
-
}
|
|
3964
|
-
if (typeof raw.editZoom === "number" && Number.isFinite(raw.editZoom)) {
|
|
3965
|
-
out.editZoom = raw.editZoom;
|
|
3966
|
-
}
|
|
3967
|
-
if (raw.activeMedia === null || typeof raw.activeMedia === "string") {
|
|
3968
|
-
out.activeMedia = raw.activeMedia;
|
|
3969
|
-
}
|
|
3970
|
-
if (typeof raw.previewColorScheme === "string" && SCHEMES.has(raw.previewColorScheme)) {
|
|
3971
|
-
out.previewColorScheme = raw.previewColorScheme;
|
|
3972
|
-
}
|
|
3973
|
-
if (raw.previewLocale === null || isWellFormedLocale(raw.previewLocale)) {
|
|
3974
|
-
out.previewLocale = raw.previewLocale;
|
|
3975
|
-
}
|
|
3976
|
-
if (typeof raw.showLayout === "boolean") {
|
|
3977
|
-
out.showLayout = raw.showLayout;
|
|
3978
|
-
}
|
|
3979
|
-
return out;
|
|
3980
|
-
}
|
|
3981
|
-
function readSession(value) {
|
|
3982
|
-
if (typeof value !== "object" || value === null) {
|
|
3983
|
-
return null;
|
|
3984
|
-
}
|
|
3985
|
-
const raw = value;
|
|
3986
|
-
if (!Array.isArray(raw.panes)) {
|
|
3987
|
-
return null;
|
|
3988
|
-
}
|
|
3989
|
-
const panes = [];
|
|
3990
|
-
for (const entry of raw.panes) {
|
|
3991
|
-
if (typeof entry !== "object" || entry === null) {
|
|
3992
|
-
continue;
|
|
3993
|
-
}
|
|
3994
|
-
const pane = entry;
|
|
3995
|
-
if (typeof pane.id !== "string" || !PANE_IDS.has(pane.id)) {
|
|
3996
|
-
continue;
|
|
3997
|
-
}
|
|
3998
|
-
const files = Array.isArray(pane.files) ? pane.files.filter((file) => typeof file === "string" && file !== "") : [];
|
|
3999
|
-
if (files.length === 0) {
|
|
4000
|
-
continue;
|
|
4001
|
-
}
|
|
4002
|
-
panes.push({
|
|
4003
|
-
activeFile: typeof pane.activeFile === "string" && files.includes(pane.activeFile) ? pane.activeFile : null,
|
|
4004
|
-
files,
|
|
4005
|
-
id: pane.id
|
|
4006
|
-
});
|
|
4007
|
-
}
|
|
4008
|
-
if (panes.length === 0) {
|
|
4009
|
-
return null;
|
|
4010
|
-
}
|
|
4011
|
-
const ui = {};
|
|
4012
|
-
if (typeof raw.ui === "object" && raw.ui !== null) {
|
|
4013
|
-
for (const [path, entry] of Object.entries(raw.ui)) {
|
|
4014
|
-
ui[path] = readTabUi(entry);
|
|
4015
|
-
}
|
|
4016
|
-
}
|
|
4017
|
-
return {
|
|
4018
|
-
focusedPane: typeof raw.focusedPane === "string" && PANE_IDS.has(raw.focusedPane) ? raw.focusedPane : PRIMARY_PANE,
|
|
4019
|
-
panes,
|
|
4020
|
-
ui
|
|
4021
|
-
};
|
|
4022
|
-
}
|
|
4023
|
-
async function restoreSession(session, deps) {
|
|
4024
|
-
let opened = 0;
|
|
4025
|
-
if (session.panes.some((pane) => pane.id === SECONDARY_PANE)) {
|
|
4026
|
-
deps.ensureSecondPane();
|
|
4027
|
-
}
|
|
4028
|
-
for (const pane of session.panes) {
|
|
4029
|
-
for (const file of pane.files) {
|
|
4030
|
-
try {
|
|
4031
|
-
await deps.openFile(file, pane.id);
|
|
4032
|
-
} catch {}
|
|
4033
|
-
if ([...workspace.tabs.values()].some((tab) => tab.documentPath === file)) {
|
|
4034
|
-
opened += 1;
|
|
4035
|
-
}
|
|
4036
|
-
}
|
|
4037
|
-
}
|
|
4038
|
-
if (opened === 0) {
|
|
4039
|
-
return 0;
|
|
4040
|
-
}
|
|
4041
|
-
for (const tab of workspace.tabs.values()) {
|
|
4042
|
-
const stored = tab.documentPath ? session.ui[tab.documentPath] : undefined;
|
|
4043
|
-
if (!stored) {
|
|
4044
|
-
continue;
|
|
4045
|
-
}
|
|
4046
|
-
const { ui } = tab.session;
|
|
4047
|
-
if (stored.canvasMode && tab.capabilities.modes.includes(stored.canvasMode)) {
|
|
4048
|
-
ui.canvasMode = stored.canvasMode;
|
|
4049
|
-
}
|
|
4050
|
-
if (stored.preview !== undefined) {
|
|
4051
|
-
ui.preview = stored.preview;
|
|
4052
|
-
}
|
|
4053
|
-
if (stored.zoom !== undefined) {
|
|
4054
|
-
ui.zoom = stored.zoom;
|
|
4055
|
-
}
|
|
4056
|
-
if (stored.editZoom !== undefined) {
|
|
4057
|
-
ui.editZoom = stored.editZoom;
|
|
4058
|
-
}
|
|
4059
|
-
if (stored.activeMedia !== undefined) {
|
|
4060
|
-
ui.activeMedia = stored.activeMedia;
|
|
4061
|
-
}
|
|
4062
|
-
if (stored.previewColorScheme !== undefined) {
|
|
4063
|
-
ui.previewColorScheme = stored.previewColorScheme;
|
|
4064
|
-
}
|
|
4065
|
-
if (stored.previewLocale !== undefined) {
|
|
4066
|
-
ui.previewLocale = stored.previewLocale;
|
|
4067
|
-
}
|
|
4068
|
-
if (stored.showLayout !== undefined) {
|
|
4069
|
-
ui.showLayout = stored.showLayout;
|
|
4070
|
-
}
|
|
4071
|
-
}
|
|
4072
|
-
for (const stored of session.panes) {
|
|
4073
|
-
const pane = workspace.panes.find((p) => p.id === stored.id);
|
|
4074
|
-
if (!pane || !stored.activeFile) {
|
|
4075
|
-
continue;
|
|
4076
|
-
}
|
|
4077
|
-
const match = pane.tabOrder.find((tabId) => workspace.tabs.get(tabId)?.documentPath === stored.activeFile);
|
|
4078
|
-
if (match) {
|
|
4079
|
-
pane.activeTabId = match;
|
|
4080
|
-
}
|
|
4081
|
-
}
|
|
4082
|
-
if (workspace.panes.some((pane) => pane.id === session.focusedPane)) {
|
|
4083
|
-
focusPane(session.focusedPane);
|
|
4084
|
-
}
|
|
4085
|
-
return opened;
|
|
4086
|
-
}
|
|
4087
|
-
|
|
4088
|
-
// src/services/profile.ts
|
|
4089
|
-
var STARTUP_PROFILES = {
|
|
4090
|
-
default: {
|
|
4091
|
-
description: "Resume whatever was persisted — layout, recents, settings, chat history.",
|
|
4092
|
-
id: "default",
|
|
4093
|
-
reset: "none"
|
|
4094
|
-
},
|
|
4095
|
-
fresh: {
|
|
4096
|
-
description: "A first-run app: no layout, no recents, no settings, no history.",
|
|
4097
|
-
id: "fresh",
|
|
4098
|
-
reset: "app-state"
|
|
4099
|
-
}
|
|
4100
|
-
};
|
|
4101
|
-
var DEFAULT_PROFILE_ID = "default";
|
|
4102
|
-
var OWNED_KEY_PATTERN = /^jx[-._:]/;
|
|
4103
|
-
function isStudioStorageKey(key) {
|
|
4104
|
-
return OWNED_KEY_PATTERN.test(key);
|
|
4105
|
-
}
|
|
4106
|
-
function clearStudioStorage() {
|
|
4107
|
-
const store = globalThis.localStorage;
|
|
4108
|
-
if (!store) {
|
|
4109
|
-
return [];
|
|
4110
|
-
}
|
|
4111
|
-
const doomed = [];
|
|
4112
|
-
try {
|
|
4113
|
-
for (let i = 0;i < store.length; i++) {
|
|
4114
|
-
const key = store.key(i);
|
|
4115
|
-
if (key && isStudioStorageKey(key)) {
|
|
4116
|
-
doomed.push(key);
|
|
4117
|
-
}
|
|
4118
|
-
}
|
|
4119
|
-
for (const key of doomed) {
|
|
4120
|
-
store.removeItem(key);
|
|
4121
|
-
}
|
|
4122
|
-
} catch {}
|
|
4123
|
-
return doomed;
|
|
4124
|
-
}
|
|
4125
|
-
function applyProfile(id) {
|
|
4126
|
-
const profile = STARTUP_PROFILES[id];
|
|
4127
|
-
if (!profile) {
|
|
4128
|
-
throw new RangeError(`unknown startup profile "${id}"; declared: ${Object.keys(STARTUP_PROFILES).join(", ")}`);
|
|
4129
|
-
}
|
|
4130
|
-
if (profile.reset === "app-state") {
|
|
4131
|
-
clearStudioStorage();
|
|
4132
|
-
}
|
|
4133
|
-
return profile;
|
|
4134
|
-
}
|
|
4135
|
-
var _startup = null;
|
|
4136
|
-
function applyStartupProfile(search) {
|
|
4137
|
-
if (_startup) {
|
|
4138
|
-
return _startup;
|
|
4139
|
-
}
|
|
4140
|
-
const query = new URLSearchParams(search ?? globalThis.location?.search ?? "");
|
|
4141
|
-
const profile = applyProfile(query.get("profile") ?? DEFAULT_PROFILE_ID);
|
|
4142
|
-
const clockParam = query.get("clock");
|
|
4143
|
-
_startup = { clock: clockParam === null ? null : pinClock(clockParam), profile };
|
|
4144
|
-
return _startup;
|
|
4145
|
-
}
|
|
4146
|
-
|
|
4147
|
-
// src/shell.ts
|
|
4148
|
-
var NAVIGATOR_PANEL_IDS = [
|
|
4149
|
-
"files",
|
|
4150
|
-
"search",
|
|
4151
|
-
"git",
|
|
4152
|
-
"i18n",
|
|
4153
|
-
"layers",
|
|
4154
|
-
"page",
|
|
4155
|
-
"data",
|
|
4156
|
-
"packages",
|
|
4157
|
-
"insert"
|
|
4158
|
-
];
|
|
4159
|
-
var RENAMED_PANEL_IDS = {
|
|
4160
|
-
blocks: "insert",
|
|
4161
|
-
head: "page",
|
|
4162
|
-
imports: "packages",
|
|
4163
|
-
state: "data"
|
|
4164
|
-
};
|
|
4165
|
-
var DEFAULT_PANEL_ID = "layers";
|
|
4166
|
-
function isNavigatorPanelId(value) {
|
|
4167
|
-
return typeof value === "string" && NAVIGATOR_PANEL_IDS.includes(value);
|
|
4168
|
-
}
|
|
4169
|
-
function requireNavigatorPanelId(value, source) {
|
|
4170
|
-
if (!isNavigatorPanelId(value)) {
|
|
4171
|
-
throw new Error(`${source}: "${value}" is not a declared Navigator panel id.`);
|
|
4172
|
-
}
|
|
4173
|
-
return value;
|
|
4174
|
-
}
|
|
4175
|
-
function migratePanelId(stored) {
|
|
4176
|
-
if (typeof stored !== "string") {
|
|
4177
|
-
return null;
|
|
4178
|
-
}
|
|
4179
|
-
const renamed = RENAMED_PANEL_IDS[stored];
|
|
4180
|
-
if (renamed) {
|
|
4181
|
-
return renamed;
|
|
4182
|
-
}
|
|
4183
|
-
return isNavigatorPanelId(stored) ? stored : null;
|
|
4184
|
-
}
|
|
4185
|
-
var INSPECTOR_TAB_IDS = ["properties", "style", "events", "assistant"];
|
|
4186
|
-
var DEFAULT_INSPECTOR_TAB = "properties";
|
|
4187
|
-
function isInspectorTabId(value) {
|
|
4188
|
-
return typeof value === "string" && INSPECTOR_TAB_IDS.includes(value);
|
|
4189
|
-
}
|
|
4190
|
-
var BOTTOM_TAB_IDS = ["problems", "logic", "activity"];
|
|
4191
|
-
var DEFAULT_BOTTOM_TAB = "problems";
|
|
4192
|
-
function isBottomTabId(value) {
|
|
4193
|
-
return typeof value === "string" && BOTTOM_TAB_IDS.includes(value);
|
|
4194
|
-
}
|
|
4195
|
-
var CHROME_THEMES = ["light", "dark"];
|
|
4196
|
-
var DOCK_STORAGE_KEY = "jx-studio-panel-widths";
|
|
4197
|
-
var PROJECT_STORAGE_PREFIX = "jx-studio-project::";
|
|
4198
|
-
var DEFAULT_THEME = "dark";
|
|
4199
|
-
function isChromeTheme(value) {
|
|
4200
|
-
return typeof value === "string" && CHROME_THEMES.includes(value);
|
|
4201
|
-
}
|
|
4202
|
-
function readPersistedTheme() {
|
|
4203
|
-
const stored = readStoredSetting(SETTINGS.theme);
|
|
4204
|
-
return isChromeTheme(stored) ? stored : DEFAULT_THEME;
|
|
4205
|
-
}
|
|
4206
|
-
var DOCK_IDS = ["left", "right", "bottom"];
|
|
4207
|
-
var DOCK_DEFAULTS = {
|
|
4208
|
-
bottom: { collapsed: true, size: 220 },
|
|
4209
|
-
left: { collapsed: false, size: 240 },
|
|
4210
|
-
right: { collapsed: false, size: 280 }
|
|
4211
|
-
};
|
|
4212
|
-
var DOCK_DEFAULT_SIZES = {
|
|
4213
|
-
bottom: DOCK_DEFAULTS.bottom.size,
|
|
4214
|
-
left: DOCK_DEFAULTS.left.size,
|
|
4215
|
-
right: DOCK_DEFAULTS.right.size
|
|
4216
|
-
};
|
|
4217
|
-
var DOCK_CSS_VAR = {
|
|
4218
|
-
bottom: "--dock-h-bottom",
|
|
4219
|
-
left: "--panel-w-left",
|
|
4220
|
-
right: "--panel-w-right"
|
|
4221
|
-
};
|
|
4222
|
-
var DOCK_CLASS = {
|
|
4223
|
-
bottom: "bottom-collapsed",
|
|
4224
|
-
left: "left-collapsed",
|
|
4225
|
-
right: "right-collapsed"
|
|
4226
|
-
};
|
|
4227
|
-
var DEFAULT_PANE_SPLIT = 0.5;
|
|
4228
|
-
function clampPaneSplit(value) {
|
|
4229
|
-
return typeof value === "number" && value >= 0.2 && value <= 0.8 ? value : DEFAULT_PANE_SPLIT;
|
|
4230
|
-
}
|
|
4231
|
-
function setPaneSplit(value) {
|
|
4232
|
-
shell.paneSplit = Math.min(0.8, Math.max(0.2, value));
|
|
4233
|
-
}
|
|
4234
|
-
function readPersistedDocks() {
|
|
4235
|
-
try {
|
|
4236
|
-
return JSON.parse(localStorage.getItem(DOCK_STORAGE_KEY) || "{}");
|
|
4237
|
-
} catch {
|
|
4238
|
-
return {};
|
|
4239
|
-
}
|
|
4240
|
-
}
|
|
4241
|
-
function freshGit() {
|
|
4242
|
-
return {
|
|
4243
|
-
branches: null,
|
|
4244
|
-
commitMessage: "",
|
|
4245
|
-
diffState: null,
|
|
4246
|
-
error: null,
|
|
4247
|
-
lastUpdated: null,
|
|
4248
|
-
loading: false,
|
|
4249
|
-
logEntries: null,
|
|
4250
|
-
status: null,
|
|
4251
|
-
subTab: "changes"
|
|
4252
|
-
};
|
|
4253
|
-
}
|
|
4254
|
-
function freshStylebook() {
|
|
4255
|
-
return { customizedOnly: false, filter: "", selection: null, tab: "elements" };
|
|
4256
|
-
}
|
|
4257
|
-
function builtInLayouts() {
|
|
4258
|
-
return [
|
|
4259
|
-
{
|
|
4260
|
-
bottomTab: "problems",
|
|
4261
|
-
docks: {
|
|
4262
|
-
bottom: { collapsed: true, size: 220 },
|
|
4263
|
-
left: { collapsed: false, size: 240 },
|
|
4264
|
-
right: { collapsed: true, size: 280 }
|
|
4265
|
-
},
|
|
4266
|
-
id: "write",
|
|
4267
|
-
inspectorTab: "properties",
|
|
4268
|
-
name: "Write",
|
|
4269
|
-
navigatorPanel: "files"
|
|
4270
|
-
},
|
|
4271
|
-
{
|
|
4272
|
-
bottomTab: "problems",
|
|
4273
|
-
docks: {
|
|
4274
|
-
bottom: { collapsed: true, size: 220 },
|
|
4275
|
-
left: { collapsed: false, size: 240 },
|
|
4276
|
-
right: { collapsed: false, size: 320 }
|
|
4277
|
-
},
|
|
4278
|
-
id: "design",
|
|
4279
|
-
inspectorTab: "style",
|
|
4280
|
-
name: "Design",
|
|
4281
|
-
navigatorPanel: "layers"
|
|
4282
|
-
},
|
|
4283
|
-
{
|
|
4284
|
-
bottomTab: "logic",
|
|
4285
|
-
docks: {
|
|
4286
|
-
bottom: { collapsed: true, size: 260 },
|
|
4287
|
-
left: { collapsed: false, size: 280 },
|
|
4288
|
-
right: { collapsed: false, size: 300 }
|
|
4289
|
-
},
|
|
4290
|
-
id: "build",
|
|
4291
|
-
inspectorTab: "events",
|
|
4292
|
-
name: "Build",
|
|
4293
|
-
navigatorPanel: "data"
|
|
4294
|
-
},
|
|
4295
|
-
{
|
|
4296
|
-
bottomTab: "activity",
|
|
4297
|
-
docks: {
|
|
4298
|
-
bottom: { collapsed: false, size: 240 },
|
|
4299
|
-
left: { collapsed: false, size: 300 },
|
|
4300
|
-
right: { collapsed: true, size: 280 }
|
|
4301
|
-
},
|
|
4302
|
-
id: "ship",
|
|
4303
|
-
inspectorTab: "properties",
|
|
4304
|
-
name: "Ship",
|
|
4305
|
-
navigatorPanel: "git"
|
|
4306
|
-
}
|
|
4307
|
-
];
|
|
4308
|
-
}
|
|
4309
|
-
var DEFAULT_LAYOUT_ID = "design";
|
|
4310
|
-
function createShellState() {
|
|
4311
|
-
const saved = readPersistedDocks();
|
|
4312
|
-
const docks = {};
|
|
4313
|
-
for (const id of DOCK_IDS) {
|
|
4314
|
-
const width = saved[id];
|
|
4315
|
-
const collapsed = saved[`${id}Collapsed`];
|
|
4316
|
-
docks[id] = {
|
|
4317
|
-
collapsed: typeof collapsed === "boolean" ? collapsed : DOCK_DEFAULTS[id].collapsed,
|
|
4318
|
-
size: typeof width === "number" && width > 0 ? width : DOCK_DEFAULTS[id].size
|
|
4319
|
-
};
|
|
4320
|
-
}
|
|
4321
|
-
return {
|
|
4322
|
-
bottomTab: isBottomTabId(saved.bottomTab) ? saved.bottomTab : DEFAULT_BOTTOM_TAB,
|
|
4323
|
-
docks,
|
|
4324
|
-
focusRegion: "pane",
|
|
4325
|
-
paneSplit: clampPaneSplit(saved.paneSplit),
|
|
4326
|
-
git: freshGit(),
|
|
4327
|
-
layout: DEFAULT_LAYOUT_ID,
|
|
4328
|
-
layoutSelection: null,
|
|
4329
|
-
layouts: builtInLayouts(),
|
|
4330
|
-
leftTab: migratePanelId(saved.leftTab) ?? DEFAULT_PANEL_ID,
|
|
4331
|
-
settingsTab: "stylebook",
|
|
4332
|
-
stylebook: freshStylebook(),
|
|
4333
|
-
theme: readPersistedTheme()
|
|
4334
|
-
};
|
|
4335
|
-
}
|
|
4336
|
-
applyStartupProfile();
|
|
4337
|
-
var shell = reactive(createShellState());
|
|
4338
|
-
function persistDocks() {
|
|
4339
|
-
try {
|
|
4340
|
-
localStorage.setItem(DOCK_STORAGE_KEY, JSON.stringify({
|
|
4341
|
-
bottom: shell.docks.bottom.size,
|
|
4342
|
-
bottomCollapsed: shell.docks.bottom.collapsed,
|
|
4343
|
-
bottomTab: shell.bottomTab,
|
|
4344
|
-
left: shell.docks.left.size,
|
|
4345
|
-
leftCollapsed: shell.docks.left.collapsed,
|
|
4346
|
-
leftTab: shell.leftTab,
|
|
4347
|
-
paneSplit: shell.paneSplit,
|
|
4348
|
-
right: shell.docks.right.size,
|
|
4349
|
-
rightCollapsed: shell.docks.right.collapsed
|
|
4350
|
-
}));
|
|
4351
|
-
} catch {}
|
|
4352
|
-
}
|
|
4353
|
-
var _layoutRoot;
|
|
4354
|
-
function isLayoutPreset(value) {
|
|
4355
|
-
if (typeof value !== "object" || value === null) {
|
|
4356
|
-
return false;
|
|
4357
|
-
}
|
|
4358
|
-
const preset = value;
|
|
4359
|
-
return typeof preset.id === "string" && preset.id !== "" && typeof preset.name === "string" && isNavigatorPanelId(preset.navigatorPanel) && isInspectorTabId(preset.inspectorTab) && isBottomTabId(preset.bottomTab) && DOCK_IDS.every((dock) => typeof preset.docks?.[dock]?.size === "number");
|
|
4360
|
-
}
|
|
4361
|
-
function rawPersistedProject(root) {
|
|
4362
|
-
if (!root) {
|
|
4363
|
-
return {};
|
|
4364
|
-
}
|
|
4365
|
-
try {
|
|
4366
|
-
return JSON.parse(localStorage.getItem(`${PROJECT_STORAGE_PREFIX}${root}`) || "{}");
|
|
4367
|
-
} catch {
|
|
4368
|
-
return {};
|
|
4369
|
-
}
|
|
4370
|
-
}
|
|
4371
|
-
function readPersistedProject(root) {
|
|
4372
|
-
const fresh = { activeLayout: null, layouts: builtInLayouts() };
|
|
4373
|
-
if (!root) {
|
|
4374
|
-
return fresh;
|
|
4375
|
-
}
|
|
4376
|
-
const parsed = rawPersistedProject(root);
|
|
4377
|
-
const layouts = Array.isArray(parsed.layouts) ? parsed.layouts.filter(isLayoutPreset) : [];
|
|
4378
|
-
if (layouts.length === 0) {
|
|
4379
|
-
return fresh;
|
|
4380
|
-
}
|
|
4381
|
-
return {
|
|
4382
|
-
activeLayout: typeof parsed.activeLayout === "string" ? parsed.activeLayout : null,
|
|
4383
|
-
layouts
|
|
4384
|
-
};
|
|
4385
|
-
}
|
|
4386
|
-
function persistedSession(root) {
|
|
4387
|
-
return readSession(rawPersistedProject(root).session);
|
|
4388
|
-
}
|
|
4389
|
-
var _sessionRoot = null;
|
|
4390
|
-
function markSessionRestored(root) {
|
|
4391
|
-
_sessionRoot = root;
|
|
4392
|
-
}
|
|
4393
|
-
function flushSession() {
|
|
4394
|
-
persistProjectShell();
|
|
4395
|
-
}
|
|
4396
|
-
function persistProjectShell() {
|
|
4397
|
-
const root = workspace.projectRoot;
|
|
4398
|
-
if (!root) {
|
|
4399
|
-
return;
|
|
4400
|
-
}
|
|
4401
|
-
try {
|
|
4402
|
-
localStorage.setItem(`${PROJECT_STORAGE_PREFIX}${root}`, JSON.stringify({
|
|
4403
|
-
activeLayout: shell.layout,
|
|
4404
|
-
layouts: shell.layouts,
|
|
4405
|
-
session: root === _sessionRoot ? captureSession() : rawPersistedProject(root).session
|
|
4406
|
-
}));
|
|
4407
|
-
} catch {}
|
|
4408
|
-
}
|
|
4409
|
-
function syncProjectLayouts(root) {
|
|
4410
|
-
if (root === _layoutRoot) {
|
|
4411
|
-
return;
|
|
4412
|
-
}
|
|
4413
|
-
_layoutRoot = root;
|
|
4414
|
-
const { activeLayout, layouts } = readPersistedProject(root);
|
|
4415
|
-
shell.layouts = layouts;
|
|
4416
|
-
const has = (id) => id !== null && layouts.some((preset) => preset.id === id);
|
|
4417
|
-
shell.layout = has(activeLayout) ? activeLayout : has(shell.layout) ? shell.layout : has(DEFAULT_LAYOUT_ID) ? DEFAULT_LAYOUT_ID : layouts[0]?.id ?? DEFAULT_LAYOUT_ID;
|
|
4418
|
-
}
|
|
4419
|
-
function layoutById(id) {
|
|
4420
|
-
return shell.layouts.find((preset) => preset.id === id);
|
|
4421
|
-
}
|
|
4422
|
-
function layoutIdFor(name) {
|
|
4423
|
-
const slug = name.trim().toLowerCase().replaceAll(/[^a-z0-9]+/g, "-").replaceAll(/^-|-$/g, "");
|
|
4424
|
-
return slug || "layout";
|
|
4425
|
-
}
|
|
4426
|
-
function applyLayout(id, deps) {
|
|
4427
|
-
const preset = layoutById(id);
|
|
4428
|
-
if (!preset) {
|
|
4429
|
-
throw new RangeError(`no layout named "${id}" — this project has: ${shell.layouts.map((p) => p.id).join(", ")}`);
|
|
4430
|
-
}
|
|
4431
|
-
shell.layout = preset.id;
|
|
4432
|
-
shell.leftTab = preset.navigatorPanel;
|
|
4433
|
-
shell.bottomTab = preset.bottomTab;
|
|
4434
|
-
for (const dock of DOCK_IDS) {
|
|
4435
|
-
shell.docks[dock].collapsed = preset.docks[dock].collapsed;
|
|
4436
|
-
shell.docks[dock].size = preset.docks[dock].size;
|
|
4437
|
-
}
|
|
4438
|
-
deps.setInspectorTab(preset.inspectorTab);
|
|
4439
|
-
persistDocks();
|
|
4440
|
-
persistProjectShell();
|
|
4441
|
-
}
|
|
4442
|
-
function saveLayout(name, deps) {
|
|
4443
|
-
const trimmed = name.trim();
|
|
4444
|
-
const id = layoutIdFor(trimmed);
|
|
4445
|
-
const docks = {};
|
|
4446
|
-
for (const dock of DOCK_IDS) {
|
|
4447
|
-
docks[dock] = { collapsed: shell.docks[dock].collapsed, size: shell.docks[dock].size };
|
|
4448
|
-
}
|
|
4449
|
-
const preset = {
|
|
4450
|
-
bottomTab: isBottomTabId(shell.bottomTab) ? shell.bottomTab : DEFAULT_BOTTOM_TAB,
|
|
4451
|
-
docks,
|
|
4452
|
-
id,
|
|
4453
|
-
inspectorTab: deps.inspectorTab(),
|
|
4454
|
-
name: trimmed || id,
|
|
4455
|
-
navigatorPanel: migratePanelId(shell.leftTab) ?? DEFAULT_PANEL_ID
|
|
4456
|
-
};
|
|
4457
|
-
const existing = shell.layouts.findIndex((entry) => entry.id === id);
|
|
4458
|
-
if (existing === -1) {
|
|
4459
|
-
shell.layouts.push(preset);
|
|
4460
|
-
} else {
|
|
4461
|
-
shell.layouts.splice(existing, 1, preset);
|
|
4462
|
-
}
|
|
4463
|
-
shell.layout = id;
|
|
4464
|
-
persistProjectShell();
|
|
4465
|
-
return preset;
|
|
4466
|
-
}
|
|
4467
|
-
function renameLayout(id, name) {
|
|
4468
|
-
const preset = layoutById(id);
|
|
4469
|
-
const trimmed = name.trim();
|
|
4470
|
-
if (!preset || !trimmed) {
|
|
4471
|
-
return;
|
|
4472
|
-
}
|
|
4473
|
-
preset.name = trimmed;
|
|
4474
|
-
persistProjectShell();
|
|
4475
|
-
}
|
|
4476
|
-
function deleteLayout(id) {
|
|
4477
|
-
if (shell.layouts.length < 2) {
|
|
4478
|
-
return;
|
|
4479
|
-
}
|
|
4480
|
-
const index = shell.layouts.findIndex((preset) => preset.id === id);
|
|
4481
|
-
if (index === -1) {
|
|
4482
|
-
return;
|
|
4483
|
-
}
|
|
4484
|
-
shell.layouts.splice(index, 1);
|
|
4485
|
-
if (shell.layout === id) {
|
|
4486
|
-
shell.layout = shell.layouts[0].id;
|
|
4487
|
-
}
|
|
4488
|
-
persistProjectShell();
|
|
4489
|
-
}
|
|
4490
|
-
function resetLayout(deps) {
|
|
4491
|
-
applyLayout(shell.layout, deps);
|
|
4492
|
-
}
|
|
4493
|
-
function monacoTheme(theme = shell.theme) {
|
|
4494
|
-
return theme === "light" ? "vs" : "vs-dark";
|
|
4495
|
-
}
|
|
4496
|
-
function applyChromeTheme() {
|
|
4497
|
-
document.querySelector("sp-theme")?.setAttribute("color", shell.theme);
|
|
4498
|
-
document.documentElement.dataset.theme = shell.theme;
|
|
4499
|
-
loadedMonaco()?.editor.setTheme(monacoTheme());
|
|
4500
|
-
}
|
|
4501
|
-
function applyDockLayout() {
|
|
4502
|
-
const root = document.documentElement;
|
|
4503
|
-
for (const id of DOCK_IDS) {
|
|
4504
|
-
root.style.setProperty(DOCK_CSS_VAR[id], `${shell.docks[id].size}px`);
|
|
4505
|
-
}
|
|
4506
|
-
const app = document.querySelector("#app");
|
|
4507
|
-
if (!app) {
|
|
4508
|
-
return;
|
|
4509
|
-
}
|
|
4510
|
-
for (const id of DOCK_IDS) {
|
|
4511
|
-
app.classList.toggle(DOCK_CLASS[id], shell.docks[id].collapsed);
|
|
4512
|
-
}
|
|
4513
|
-
}
|
|
4514
|
-
var _scope = null;
|
|
4515
|
-
var _surfaces2 = [];
|
|
4516
|
-
function registerShellSurface(surface) {
|
|
4517
|
-
if (!_surfaces2.includes(surface)) {
|
|
4518
|
-
_surfaces2.push(surface);
|
|
4519
|
-
}
|
|
4520
|
-
}
|
|
4521
|
-
function mountShell() {
|
|
4522
|
-
if (_scope) {
|
|
4523
|
-
return;
|
|
4524
|
-
}
|
|
4525
|
-
for (const surface of _surfaces2) {
|
|
4526
|
-
surface.mount();
|
|
4527
|
-
}
|
|
4528
|
-
_scope = effectScope();
|
|
4529
|
-
_scope.run(() => {
|
|
4530
|
-
effect(() => {
|
|
4531
|
-
applyDockLayout();
|
|
4532
|
-
});
|
|
4533
|
-
effect(() => {
|
|
4534
|
-
applyChromeTheme();
|
|
4535
|
-
});
|
|
4536
|
-
effect(() => {
|
|
4537
|
-
syncProjectLayouts(workspace.projectRoot);
|
|
4538
|
-
});
|
|
4539
|
-
effect(() => {
|
|
4540
|
-
const root = workspace.projectRoot;
|
|
4541
|
-
workspace.activePaneId;
|
|
4542
|
-
for (const pane of workspace.panes) {
|
|
4543
|
-
pane.id;
|
|
4544
|
-
pane.activeTabId;
|
|
4545
|
-
pane.tabOrder.join("\x00");
|
|
4546
|
-
}
|
|
4547
|
-
if (root) {
|
|
4548
|
-
persistProjectShell();
|
|
4549
|
-
}
|
|
4550
|
-
});
|
|
4551
|
-
});
|
|
4552
|
-
}
|
|
4553
|
-
function setDockCollapsed(dock, collapsed) {
|
|
4554
|
-
if (shell.docks[dock].collapsed === collapsed) {
|
|
4555
|
-
persistDocks();
|
|
4556
|
-
return;
|
|
4557
|
-
}
|
|
4558
|
-
shell.docks[dock].collapsed = collapsed;
|
|
4559
|
-
persistDocks();
|
|
4560
|
-
}
|
|
4561
|
-
function toggleDock(dock) {
|
|
4562
|
-
setDockCollapsed(dock, !shell.docks[dock].collapsed);
|
|
4563
|
-
}
|
|
4564
|
-
function setDockSize(dock, size) {
|
|
4565
|
-
shell.docks[dock].size = size;
|
|
4566
|
-
}
|
|
4567
|
-
function setActivityTab(tab) {
|
|
4568
|
-
shell.leftTab = tab;
|
|
4569
|
-
setDockCollapsed("left", false);
|
|
4570
|
-
persistDocks();
|
|
4571
|
-
}
|
|
4572
|
-
function setBottomTab(tab) {
|
|
4573
|
-
shell.bottomTab = tab;
|
|
4574
|
-
setDockCollapsed("bottom", false);
|
|
4575
|
-
persistDocks();
|
|
4576
|
-
}
|
|
4577
|
-
function setChromeTheme(theme) {
|
|
4578
|
-
if (shell.theme === theme) {
|
|
4579
|
-
return;
|
|
4580
|
-
}
|
|
4581
|
-
shell.theme = theme;
|
|
4582
|
-
setSetting(SETTINGS.theme, theme);
|
|
4583
|
-
}
|
|
4584
|
-
function toggleActivityTab(tab) {
|
|
4585
|
-
if (tab === shell.leftTab && !shell.docks.left.collapsed) {
|
|
4586
|
-
setDockCollapsed("left", true);
|
|
4587
|
-
return;
|
|
4588
|
-
}
|
|
4589
|
-
setActivityTab(tab);
|
|
4590
|
-
}
|
|
4591
|
-
function setLayoutSelection(selection) {
|
|
4592
|
-
shell.layoutSelection = selection;
|
|
4593
|
-
}
|
|
4594
|
-
function resetProjectShell() {
|
|
4595
|
-
Object.assign(shell.git, freshGit());
|
|
4596
|
-
Object.assign(shell.stylebook, freshStylebook());
|
|
4597
|
-
shell.settingsTab = "stylebook";
|
|
4598
|
-
shell.layoutSelection = null;
|
|
4599
|
-
_sessionRoot = null;
|
|
4600
|
-
_layoutRoot = undefined;
|
|
4601
|
-
}
|
|
4602
|
-
var projectOpen = (ctx) => ctx.project.open;
|
|
4603
|
-
function shellViewCommands(deps) {
|
|
4604
|
-
return [
|
|
4605
|
-
{
|
|
4606
|
-
args: argsSchema({
|
|
4607
|
-
tab: enumProperty(NAVIGATOR_PANEL_IDS, "Which Navigator panel to show.")
|
|
4608
|
-
}),
|
|
4609
|
-
category: "View",
|
|
4610
|
-
id: "view.setActivity",
|
|
4611
|
-
level: "application",
|
|
4612
|
-
menus: ["commandbar/overflow", "palette"],
|
|
4613
|
-
group: "4_docks",
|
|
4614
|
-
requires: "an open project",
|
|
4615
|
-
when: projectOpen,
|
|
4616
|
-
aiTool: {
|
|
4617
|
-
description: "Show one of the Navigator panels (Files, Search, Source Control, Languages, Outline, " + "Page, Data, Packages, Insert) and open the Navigator dock if it is closed. Languages is " + "the translation-parity grid, and it exists only in a project that declares two or more " + "locales. Problems is a Bottom dock tab — use show_bottom_tab for it.",
|
|
4618
|
-
name: "show_navigator_panel"
|
|
4619
|
-
},
|
|
4620
|
-
run: (_ctx, args) => {
|
|
4621
|
-
const tab = enumArg("view.setActivity", args, "tab", NAVIGATOR_PANEL_IDS);
|
|
4622
|
-
if (deps.panelAvailable && !deps.panelAvailable(tab)) {
|
|
4623
|
-
throw new RangeError(`command "view.setActivity" argument "tab": "${tab}" names a panel that is registered but not ` + `available right now, so showing it would persist a Navigator tab nothing can draw`);
|
|
4624
|
-
}
|
|
4625
|
-
setActivityTab(tab);
|
|
4626
|
-
},
|
|
4627
|
-
title: "Show Navigator Panel"
|
|
4628
|
-
},
|
|
4629
|
-
{
|
|
4630
|
-
args: argsSchema({
|
|
4631
|
-
tab: enumProperty(INSPECTOR_TAB_IDS, "Which Inspector tab to show.")
|
|
4632
|
-
}),
|
|
4633
|
-
category: "View",
|
|
4634
|
-
id: "view.setRightTab",
|
|
4635
|
-
level: "document",
|
|
4636
|
-
menus: ["palette"],
|
|
4637
|
-
group: "4_docks",
|
|
4638
|
-
requires: "an open document",
|
|
4639
|
-
when: (ctx) => ctx.document.open,
|
|
4640
|
-
run: (_ctx, args) => {
|
|
4641
|
-
deps.setInspectorTab(enumArg("view.setRightTab", args, "tab", INSPECTOR_TAB_IDS));
|
|
4642
|
-
},
|
|
4643
|
-
title: "Show Inspector Tab"
|
|
4644
|
-
},
|
|
4645
|
-
{
|
|
4646
|
-
args: argsSchema({
|
|
4647
|
-
open: booleanProperty("True to show the Navigator dock, false to collapse it.")
|
|
4648
|
-
}),
|
|
4649
|
-
category: "View",
|
|
4650
|
-
id: "view.setNavigator",
|
|
4651
|
-
level: "application",
|
|
4652
|
-
menus: ["palette"],
|
|
4653
|
-
group: "4_docks",
|
|
4654
|
-
run: (_ctx, args) => {
|
|
4655
|
-
setDockCollapsed("left", !booleanArg("view.setNavigator", args, "open"));
|
|
4656
|
-
},
|
|
4657
|
-
title: "Show Navigator Dock"
|
|
4658
|
-
},
|
|
4659
|
-
{
|
|
4660
|
-
args: argsSchema({
|
|
4661
|
-
open: booleanProperty("True to show the Inspector dock, false to collapse it.")
|
|
4662
|
-
}),
|
|
4663
|
-
category: "View",
|
|
4664
|
-
id: "view.setRightPanel",
|
|
4665
|
-
level: "application",
|
|
4666
|
-
menus: ["palette"],
|
|
4667
|
-
group: "4_docks",
|
|
4668
|
-
run: (_ctx, args) => {
|
|
4669
|
-
setDockCollapsed("right", !booleanArg("view.setRightPanel", args, "open"));
|
|
4670
|
-
},
|
|
4671
|
-
title: "Show Inspector Dock"
|
|
4672
|
-
},
|
|
4673
|
-
{
|
|
4674
|
-
args: argsSchema({
|
|
4675
|
-
open: booleanProperty("True to show the Bottom dock, false to collapse it.")
|
|
4676
|
-
}),
|
|
4677
|
-
category: "View",
|
|
4678
|
-
id: "view.setBottomDock",
|
|
4679
|
-
level: "application",
|
|
4680
|
-
menus: ["palette"],
|
|
4681
|
-
group: "4_docks",
|
|
4682
|
-
run: (_ctx, args) => {
|
|
4683
|
-
setDockCollapsed("bottom", !booleanArg("view.setBottomDock", args, "open"));
|
|
4684
|
-
},
|
|
4685
|
-
title: "Show Bottom Dock"
|
|
4686
|
-
},
|
|
4687
|
-
{
|
|
4688
|
-
category: "View",
|
|
4689
|
-
id: "view.toggleBottomDock",
|
|
4690
|
-
keybinding: "mod+j",
|
|
4691
|
-
level: "application",
|
|
4692
|
-
menus: ["commandbar/overflow", "palette"],
|
|
4693
|
-
group: "4_docks",
|
|
4694
|
-
run: () => {
|
|
4695
|
-
toggleDock("bottom");
|
|
4696
|
-
},
|
|
4697
|
-
title: "Toggle Bottom Dock"
|
|
4698
|
-
},
|
|
4699
|
-
{
|
|
4700
|
-
args: argsSchema({
|
|
4701
|
-
tab: enumProperty(BOTTOM_TAB_IDS, "Which Bottom dock tab to show.")
|
|
4702
|
-
}),
|
|
4703
|
-
category: "View",
|
|
4704
|
-
id: "view.setBottomTab",
|
|
4705
|
-
level: "application",
|
|
4706
|
-
menus: ["palette"],
|
|
4707
|
-
group: "4_docks",
|
|
4708
|
-
aiTool: {
|
|
4709
|
-
description: "Show one of the Bottom dock's tabs (Problems, Diff, Logic, Activity) and open the " + "Bottom dock if it is closed.",
|
|
4710
|
-
name: "show_bottom_tab"
|
|
4711
|
-
},
|
|
4712
|
-
run: (_ctx, args) => {
|
|
4713
|
-
const tab = enumArg("view.setBottomTab", args, "tab", BOTTOM_TAB_IDS);
|
|
4714
|
-
if (deps.panelAvailable && !deps.panelAvailable(tab)) {
|
|
4715
|
-
throw new RangeError(`command "view.setBottomTab" argument "tab": "${tab}" names a panel that is registered but not ` + `available right now, so showing it would persist a Bottom dock tab nothing can draw`);
|
|
4716
|
-
}
|
|
4717
|
-
setBottomTab(tab);
|
|
4718
|
-
},
|
|
4719
|
-
title: "Show Bottom Dock Tab"
|
|
4720
|
-
},
|
|
4721
|
-
{
|
|
4722
|
-
args: argsSchema({
|
|
4723
|
-
open: booleanProperty("True to show the Assistant tab, false to step off it.")
|
|
4724
|
-
}),
|
|
4725
|
-
category: "View",
|
|
4726
|
-
id: "view.setAssistant",
|
|
4727
|
-
level: "application",
|
|
4728
|
-
menus: ["never"],
|
|
4729
|
-
group: "4_docks",
|
|
4730
|
-
run: (_ctx, args) => {
|
|
4731
|
-
if (booleanArg("view.setAssistant", args, "open")) {
|
|
4732
|
-
setDockCollapsed("right", false);
|
|
4733
|
-
deps.setInspectorTab("assistant");
|
|
4734
|
-
return;
|
|
4735
|
-
}
|
|
4736
|
-
if (deps.inspectorTab() === "assistant") {
|
|
4737
|
-
deps.setInspectorTab(DEFAULT_INSPECTOR_TAB);
|
|
4738
|
-
}
|
|
4739
|
-
},
|
|
4740
|
-
title: "Show Assistant"
|
|
4741
|
-
},
|
|
4742
|
-
{
|
|
4743
|
-
args: argsSchema({
|
|
4744
|
-
layout: stringProperty("The layout's id — one of this project's saved layouts.")
|
|
4745
|
-
}),
|
|
4746
|
-
category: "View",
|
|
4747
|
-
id: "view.setLayout",
|
|
4748
|
-
level: "application",
|
|
4749
|
-
menus: ["palette"],
|
|
4750
|
-
group: "4_layouts",
|
|
4751
|
-
requires: "an open project",
|
|
4752
|
-
when: projectOpen,
|
|
4753
|
-
aiTool: {
|
|
4754
|
-
description: "Adopt one of the project's named layouts (Write, Design, Build, Ship, or one the user " + "saved): its Navigator panel, its dock widths and visibility, and its Inspector tab.",
|
|
4755
|
-
name: "set_layout"
|
|
4756
|
-
},
|
|
4757
|
-
run: (_ctx, args) => {
|
|
4758
|
-
applyLayout(stringArg("view.setLayout", args, "layout"), deps);
|
|
4759
|
-
},
|
|
4760
|
-
title: "Switch Layout"
|
|
4761
|
-
},
|
|
4762
|
-
{
|
|
4763
|
-
args: argsSchema({
|
|
4764
|
-
name: stringProperty("What to call this arrangement. An existing name is overwritten.")
|
|
4765
|
-
}),
|
|
4766
|
-
category: "View",
|
|
4767
|
-
id: "view.saveLayout",
|
|
4768
|
-
level: "application",
|
|
4769
|
-
menus: ["palette"],
|
|
4770
|
-
group: "4_layouts",
|
|
4771
|
-
requires: "an open project",
|
|
4772
|
-
when: projectOpen,
|
|
4773
|
-
run: (_ctx, args) => {
|
|
4774
|
-
saveLayout(stringArg("view.saveLayout", args, "name"), deps);
|
|
4775
|
-
},
|
|
4776
|
-
title: "Save Layout"
|
|
4777
|
-
},
|
|
4778
|
-
{
|
|
4779
|
-
args: argsSchema({
|
|
4780
|
-
layout: stringProperty("The layout's id."),
|
|
4781
|
-
name: stringProperty("Its new name. The id, and every reference to it, is unchanged.")
|
|
4782
|
-
}),
|
|
4783
|
-
category: "View",
|
|
4784
|
-
id: "view.renameLayout",
|
|
4785
|
-
level: "application",
|
|
4786
|
-
menus: ["palette"],
|
|
4787
|
-
group: "4_layouts",
|
|
4788
|
-
requires: "an open project",
|
|
4789
|
-
when: projectOpen,
|
|
4790
|
-
run: (_ctx, args) => {
|
|
4791
|
-
renameLayout(stringArg("view.renameLayout", args, "layout"), stringArg("view.renameLayout", args, "name"));
|
|
4792
|
-
},
|
|
4793
|
-
title: "Rename Layout"
|
|
4794
|
-
},
|
|
4795
|
-
{
|
|
4796
|
-
args: argsSchema({
|
|
4797
|
-
layout: stringProperty("The layout's id. The last remaining layout is kept.")
|
|
4798
|
-
}),
|
|
4799
|
-
category: "View",
|
|
4800
|
-
id: "view.deleteLayout",
|
|
4801
|
-
level: "application",
|
|
4802
|
-
menus: ["palette"],
|
|
4803
|
-
group: "4_layouts",
|
|
4804
|
-
requires: "an open project",
|
|
4805
|
-
when: projectOpen,
|
|
4806
|
-
run: (_ctx, args) => {
|
|
4807
|
-
deleteLayout(stringArg("view.deleteLayout", args, "layout"));
|
|
4808
|
-
},
|
|
4809
|
-
title: "Delete Layout"
|
|
4810
|
-
},
|
|
4811
|
-
{
|
|
4812
|
-
category: "View",
|
|
4813
|
-
id: "view.resetLayout",
|
|
4814
|
-
level: "application",
|
|
4815
|
-
menus: ["palette"],
|
|
4816
|
-
group: "4_layouts",
|
|
4817
|
-
requires: "an open project",
|
|
4818
|
-
when: projectOpen,
|
|
4819
|
-
run: () => {
|
|
4820
|
-
resetLayout(deps);
|
|
4821
|
-
},
|
|
4822
|
-
title: "Reset Layout"
|
|
4823
|
-
},
|
|
4824
|
-
{
|
|
4825
|
-
args: argsSchema({
|
|
4826
|
-
color: enumProperty(CHROME_THEMES, "The Studio chrome's theme.")
|
|
4827
|
-
}),
|
|
4828
|
-
category: "View",
|
|
4829
|
-
id: "view.setTheme",
|
|
4830
|
-
level: "application",
|
|
4831
|
-
menus: ["palette"],
|
|
4832
|
-
group: "6_appearance",
|
|
4833
|
-
run: (_ctx, args) => {
|
|
4834
|
-
setChromeTheme(enumArg("view.setTheme", args, "color", CHROME_THEMES));
|
|
4835
|
-
},
|
|
4836
|
-
title: "Set Theme"
|
|
4837
|
-
}
|
|
4838
|
-
];
|
|
4839
|
-
}
|
|
4840
|
-
function registerShellViewCommands(registry, deps) {
|
|
4841
|
-
registry.registerAll(shellViewCommands(deps));
|
|
4842
|
-
}
|
|
4843
|
-
|
|
4844
|
-
// src/tabs/project-config.ts
|
|
4845
|
-
function serializeProjectConfig(config) {
|
|
4846
|
-
return JSON.stringify(config, null, 2);
|
|
4847
|
-
}
|
|
4848
|
-
var _bound = null;
|
|
4849
|
-
var _detached = null;
|
|
4850
|
-
var _committed = null;
|
|
4851
|
-
var _seeding = null;
|
|
4852
|
-
function openConfigTab() {
|
|
4853
|
-
const tab = workspace.tabs.get(PROJECT_CONFIG_PATH);
|
|
4854
|
-
return tab ? toRaw(tab) : null;
|
|
4855
|
-
}
|
|
4856
|
-
function unbind() {
|
|
4857
|
-
if (_detached) {
|
|
4858
|
-
disposeTab(_detached);
|
|
4859
|
-
_detached = null;
|
|
4860
|
-
}
|
|
4861
|
-
_bound = null;
|
|
4862
|
-
_committed = null;
|
|
4863
|
-
_seeding = null;
|
|
4864
|
-
}
|
|
4865
|
-
function seedCommitted() {
|
|
4866
|
-
_seeding ??= (async () => {
|
|
4867
|
-
try {
|
|
4868
|
-
const text = await getPlatform().readFile(PROJECT_CONFIG_PATH);
|
|
4869
|
-
_committed = serializeProjectConfig(JSON.parse(text));
|
|
4870
|
-
} catch {
|
|
4871
|
-
_committed = null;
|
|
4872
|
-
}
|
|
4873
|
-
})();
|
|
4874
|
-
return _seeding;
|
|
4875
|
-
}
|
|
4876
|
-
function syncProjectState(config) {
|
|
4877
|
-
const state = requireProjectState();
|
|
4878
|
-
if (state.projectConfig === config) {
|
|
4879
|
-
return;
|
|
4880
|
-
}
|
|
4881
|
-
setProjectState({ ...state, projectConfig: config });
|
|
4882
|
-
setWorkspaceProject(workspace.projectRoot, config);
|
|
4883
|
-
}
|
|
4884
|
-
function liveConfig() {
|
|
4885
|
-
const config = requireProjectState()?.projectConfig;
|
|
4886
|
-
return config ? toRaw(config) : null;
|
|
4887
|
-
}
|
|
4888
|
-
function replaceContents(target, source) {
|
|
4889
|
-
for (const key of Object.keys(target)) {
|
|
4890
|
-
if (!Object.hasOwn(source, key)) {
|
|
4891
|
-
delete target[key];
|
|
4892
|
-
}
|
|
4893
|
-
}
|
|
4894
|
-
Object.assign(target, source);
|
|
4895
|
-
}
|
|
4896
|
-
function bind(tab) {
|
|
4897
|
-
_bound = tab;
|
|
4898
|
-
tab.scope.run(() => {
|
|
4899
|
-
effect(() => {
|
|
4900
|
-
const doc = tab.doc.document;
|
|
4901
|
-
if (_bound !== tab || !requireProjectState()) {
|
|
4902
|
-
return;
|
|
4903
|
-
}
|
|
4904
|
-
syncProjectState(toRaw(doc));
|
|
4905
|
-
});
|
|
4906
|
-
});
|
|
4907
|
-
return tab;
|
|
4908
|
-
}
|
|
4909
|
-
function projectConfigDocument() {
|
|
4910
|
-
const state = requireProjectState();
|
|
4911
|
-
const open = openConfigTab();
|
|
4912
|
-
if (_bound && (_bound !== (open ?? _detached) || toRaw(_bound.doc.document) !== state.projectConfig)) {
|
|
4913
|
-
unbind();
|
|
4914
|
-
}
|
|
4915
|
-
if (_bound) {
|
|
4916
|
-
return _bound;
|
|
4917
|
-
}
|
|
4918
|
-
if (open) {
|
|
4919
|
-
return bind(open);
|
|
4920
|
-
}
|
|
4921
|
-
_detached = createTab({
|
|
4922
|
-
document: state.projectConfig ?? {},
|
|
4923
|
-
documentPath: PROJECT_CONFIG_PATH,
|
|
4924
|
-
id: PROJECT_CONFIG_PATH
|
|
4925
|
-
});
|
|
4926
|
-
return bind(_detached);
|
|
4927
|
-
}
|
|
4928
|
-
function extensionsKey(config) {
|
|
4929
|
-
return JSON.stringify(config.extensions ?? null);
|
|
4930
|
-
}
|
|
4931
|
-
async function refreshExtensionSurfaces() {
|
|
4932
|
-
const { loadFormats, refreshExtensionUi, refreshFormats } = await import("./format-host-8fr3545e.js");
|
|
4933
|
-
refreshFormats();
|
|
4934
|
-
loadFormats();
|
|
4935
|
-
refreshExtensionUi(getPlatform());
|
|
4936
|
-
}
|
|
4937
|
-
async function commitProjectConfig(patch) {
|
|
4938
|
-
const live = liveConfig();
|
|
4939
|
-
const tab = projectConfigDocument();
|
|
4940
|
-
await seedCommitted();
|
|
4941
|
-
const current = toRaw(tab.doc.document);
|
|
4942
|
-
const currentText = serializeProjectConfig(current);
|
|
4943
|
-
const rival = live && live !== current && serializeProjectConfig(live) !== currentText ? live : null;
|
|
4944
|
-
if (rival && tab.doc.dirty) {
|
|
4945
|
-
const error = new Error(`${PROJECT_CONFIG_PATH} has unsaved changes in its editor tab`);
|
|
4946
|
-
notify.error(`Could not save ${PROJECT_CONFIG_PATH} — the file is open with unsaved changes. Save or ` + `revert that tab, then make the settings change again.`, { key: `save:${PROJECT_CONFIG_PATH}`, path: PROJECT_CONFIG_PATH, source: "Settings" });
|
|
4947
|
-
return { error, ok: false };
|
|
4948
|
-
}
|
|
4949
|
-
const base = rival ?? current;
|
|
4950
|
-
const next = patch ? { ...base, ...patch } : base;
|
|
4951
|
-
const text = serializeProjectConfig(next);
|
|
4952
|
-
if (!rival && !tab.doc.dirty && text === _committed) {
|
|
4953
|
-
return { ok: true };
|
|
4954
|
-
}
|
|
4955
|
-
const before = extensionsKey(current);
|
|
4956
|
-
transactDoc(tab, (t) => {
|
|
4957
|
-
const doc = t.doc.document;
|
|
4958
|
-
if (rival) {
|
|
4959
|
-
replaceContents(doc, rival);
|
|
4960
|
-
}
|
|
4961
|
-
for (const [key, value] of Object.entries(patch ?? {})) {
|
|
4962
|
-
doc[key] = value;
|
|
4963
|
-
}
|
|
4964
|
-
});
|
|
4965
|
-
const config = toRaw(tab.doc.document);
|
|
4966
|
-
const output = serializeProjectConfig(config);
|
|
4967
|
-
try {
|
|
4968
|
-
await getPlatform().writeFile(PROJECT_CONFIG_PATH, output);
|
|
4969
|
-
} catch (error) {
|
|
4970
|
-
notify.error(`Could not save ${PROJECT_CONFIG_PATH} — ${errorMessage(error)}`, {
|
|
4971
|
-
key: `save:${PROJECT_CONFIG_PATH}`,
|
|
4972
|
-
path: PROJECT_CONFIG_PATH,
|
|
4973
|
-
source: "Settings"
|
|
4974
|
-
});
|
|
4975
|
-
return { error, ok: false };
|
|
4976
|
-
}
|
|
4977
|
-
_committed = output;
|
|
4978
|
-
tab.doc.dirty = false;
|
|
4979
|
-
if (extensionsKey(config) !== before) {
|
|
4980
|
-
await refreshExtensionSurfaces();
|
|
4981
|
-
}
|
|
4982
|
-
return { ok: true };
|
|
4983
|
-
}
|
|
4984
|
-
async function adoptProjectConfig(config) {
|
|
4985
|
-
if (!requireProjectState()) {
|
|
4986
|
-
setWorkspaceProject(workspace.projectRoot, config);
|
|
4987
|
-
return;
|
|
4988
|
-
}
|
|
4989
|
-
const tab = projectConfigDocument();
|
|
4990
|
-
transactDoc(tab, (t) => replaceContents(t.doc.document, config), { skipHistory: true });
|
|
4991
|
-
tab.doc.dirty = false;
|
|
4992
|
-
await seedCommitted();
|
|
4993
|
-
_committed = serializeProjectConfig(config);
|
|
4994
|
-
}
|
|
4995
|
-
|
|
4996
|
-
// src/site-context.ts
|
|
4997
|
-
function getEffectiveMedia(docMedia) {
|
|
4998
|
-
const siteMedia = projectState?.projectConfig?.$media;
|
|
4999
|
-
if (!siteMedia) {
|
|
5000
|
-
return docMedia || {};
|
|
5001
|
-
}
|
|
5002
|
-
if (!docMedia) {
|
|
5003
|
-
return { ...siteMedia };
|
|
5004
|
-
}
|
|
5005
|
-
return { ...siteMedia, ...docMedia };
|
|
5006
|
-
}
|
|
5007
|
-
function getEffectiveStyle(docStyle) {
|
|
5008
|
-
const siteStyle = projectState?.projectConfig?.style;
|
|
5009
|
-
if (!siteStyle) {
|
|
5010
|
-
return docStyle || {};
|
|
5011
|
-
}
|
|
5012
|
-
if (!docStyle) {
|
|
5013
|
-
return { ...siteStyle };
|
|
5014
|
-
}
|
|
5015
|
-
const merged = { ...siteStyle };
|
|
5016
|
-
for (const [k, v] of Object.entries(docStyle)) {
|
|
5017
|
-
merged[k] = typeof v === "object" && v !== null && typeof merged[k] === "object" && merged[k] !== null ? { ...merged[k], ...v } : v;
|
|
5018
|
-
}
|
|
5019
|
-
return merged;
|
|
5020
|
-
}
|
|
5021
|
-
function getEffectiveImports(docImports) {
|
|
5022
|
-
const siteImports = projectState?.projectConfig?.imports;
|
|
5023
|
-
if (!siteImports) {
|
|
5024
|
-
return docImports || {};
|
|
5025
|
-
}
|
|
5026
|
-
if (!docImports) {
|
|
5027
|
-
return { ...siteImports };
|
|
5028
|
-
}
|
|
5029
|
-
return { ...siteImports, ...docImports };
|
|
5030
|
-
}
|
|
5031
|
-
function getEffectiveElements(docElements) {
|
|
5032
|
-
const siteElements = projectState?.projectConfig?.$elements;
|
|
5033
|
-
if (!siteElements?.length) {
|
|
5034
|
-
return docElements || [];
|
|
5035
|
-
}
|
|
5036
|
-
if (!docElements?.length) {
|
|
5037
|
-
return [...siteElements];
|
|
5038
|
-
}
|
|
5039
|
-
const seen = new Set;
|
|
5040
|
-
const merged = [];
|
|
5041
|
-
for (const entry of [...siteElements, ...docElements]) {
|
|
5042
|
-
const key = typeof entry === "string" ? entry : entry?.$ref;
|
|
5043
|
-
if (key && !seen.has(key)) {
|
|
5044
|
-
seen.add(key);
|
|
5045
|
-
merged.push(entry);
|
|
5046
|
-
}
|
|
5047
|
-
}
|
|
5048
|
-
return merged;
|
|
5049
|
-
}
|
|
5050
|
-
function getEffectiveHead(docHead) {
|
|
5051
|
-
const siteHead = projectState?.projectConfig?.$head;
|
|
5052
|
-
if (!siteHead?.length) {
|
|
5053
|
-
return docHead || [];
|
|
5054
|
-
}
|
|
5055
|
-
if (!docHead?.length) {
|
|
5056
|
-
return [...siteHead];
|
|
5057
|
-
}
|
|
5058
|
-
const seen = new Set;
|
|
5059
|
-
const merged = [];
|
|
5060
|
-
for (const entry of [...siteHead, ...docHead]) {
|
|
5061
|
-
const key = String(entry?.attributes?.href || entry?.attributes?.src || "") || JSON.stringify(entry);
|
|
5062
|
-
if (!seen.has(key)) {
|
|
5063
|
-
seen.add(key);
|
|
5064
|
-
merged.push(entry);
|
|
5065
|
-
}
|
|
5066
|
-
}
|
|
5067
|
-
return merged;
|
|
5068
|
-
}
|
|
5069
|
-
function getEffectiveLocales() {
|
|
5070
|
-
const config = projectState?.projectConfig;
|
|
5071
|
-
return config ? resolveI18n(config).i18n : null;
|
|
5072
|
-
}
|
|
5073
|
-
var layoutCache = new Map;
|
|
5074
|
-
function invalidateLayoutCache() {
|
|
5075
|
-
layoutCache.clear();
|
|
5076
|
-
}
|
|
5077
|
-
function getEffectiveLayoutPath(docLayout) {
|
|
5078
|
-
if (docLayout === false) {
|
|
5079
|
-
return null;
|
|
5080
|
-
}
|
|
5081
|
-
const defaultLayout = projectState?.projectConfig?.defaults?.layout;
|
|
5082
|
-
return docLayout || defaultLayout || null;
|
|
5083
|
-
}
|
|
5084
|
-
async function resolveLayoutDoc(layoutPath) {
|
|
5085
|
-
const normalized = layoutPath.replace(/^\.\//, "");
|
|
5086
|
-
if (layoutCache.has(normalized)) {
|
|
5087
|
-
return structuredClone(layoutCache.get(normalized));
|
|
5088
|
-
}
|
|
5089
|
-
try {
|
|
5090
|
-
const platform = getPlatform();
|
|
5091
|
-
const content = await platform.readFile(normalized);
|
|
5092
|
-
const doc = JSON.parse(content);
|
|
5093
|
-
layoutCache.set(normalized, doc);
|
|
5094
|
-
return structuredClone(doc);
|
|
5095
|
-
} catch {
|
|
5096
|
-
return null;
|
|
5097
|
-
}
|
|
5098
|
-
}
|
|
5099
|
-
function distributePageIntoLayout(layoutDoc, pageDoc) {
|
|
5100
|
-
const pageChildren = pageDoc.children ?? [];
|
|
5101
|
-
const children = Array.isArray(pageChildren) ? pageChildren : [];
|
|
5102
|
-
const named = new Map;
|
|
5103
|
-
const defaults = [];
|
|
5104
|
-
for (const child of children) {
|
|
5105
|
-
const slotName = typeof child === "object" ? child.attributes?.slot : undefined;
|
|
5106
|
-
if (typeof child === "object" && typeof slotName === "string" && slotName) {
|
|
5107
|
-
if (!named.has(slotName)) {
|
|
5108
|
-
named.set(slotName, []);
|
|
5109
|
-
}
|
|
5110
|
-
named.get(slotName).push(child);
|
|
5111
|
-
} else {
|
|
5112
|
-
defaults.push(child);
|
|
5113
|
-
}
|
|
5114
|
-
}
|
|
5115
|
-
fillSlots(layoutDoc, named, defaults);
|
|
5116
|
-
if (pageDoc.state) {
|
|
5117
|
-
layoutDoc.state = { ...layoutDoc.state, ...pageDoc.state };
|
|
5118
|
-
}
|
|
5119
|
-
if (pageDoc.$media) {
|
|
5120
|
-
layoutDoc.$media = { ...layoutDoc.$media, ...pageDoc.$media };
|
|
5121
|
-
}
|
|
5122
|
-
if (pageDoc.style) {
|
|
5123
|
-
layoutDoc.style = { ...layoutDoc.style, ...pageDoc.style };
|
|
5124
|
-
}
|
|
5125
|
-
if (pageDoc.attributes) {
|
|
5126
|
-
layoutDoc.attributes = { ...layoutDoc.attributes, ...pageDoc.attributes };
|
|
5127
|
-
}
|
|
5128
|
-
return layoutDoc;
|
|
5129
|
-
}
|
|
5130
|
-
function fillSlots(node, named, defaults) {
|
|
5131
|
-
if (!node || typeof node !== "object") {
|
|
5132
|
-
return;
|
|
5133
|
-
}
|
|
5134
|
-
if (!Array.isArray(node.children)) {
|
|
5135
|
-
return;
|
|
5136
|
-
}
|
|
5137
|
-
const newChildren = [];
|
|
5138
|
-
for (const child of node.children) {
|
|
5139
|
-
if (child && typeof child === "object" && child.tagName === "slot") {
|
|
5140
|
-
const slotName = child.attributes?.name;
|
|
5141
|
-
if (typeof slotName === "string" && slotName && named.has(slotName)) {
|
|
5142
|
-
newChildren.push(...named.get(slotName));
|
|
5143
|
-
named.delete(slotName);
|
|
5144
|
-
} else if (!slotName && defaults.length > 0) {
|
|
5145
|
-
newChildren.push(...defaults);
|
|
5146
|
-
} else if (Array.isArray(child.children)) {
|
|
5147
|
-
newChildren.push(...child.children);
|
|
5148
|
-
}
|
|
5149
|
-
} else {
|
|
5150
|
-
if (typeof child !== "string") {
|
|
5151
|
-
fillSlots(child, named, defaults);
|
|
5152
|
-
}
|
|
5153
|
-
newChildren.push(child);
|
|
5154
|
-
}
|
|
5155
|
-
}
|
|
5156
|
-
node.children = newChildren;
|
|
5157
|
-
}
|
|
5158
|
-
async function updateSiteConfig(patch) {
|
|
5159
|
-
const result = await commitProjectConfig(patch);
|
|
5160
|
-
if (!result.ok) {
|
|
5161
|
-
throw result.error;
|
|
5162
|
-
}
|
|
5163
|
-
}
|
|
5164
|
-
|
|
5165
|
-
export { errorMessage, LANGUAGE_TAG_PATTERN, canonicalizeLocale, isWellFormedLocale, localeDirection, localeLabel, resolveI18n, localeOfPath, servedLocaleOfPath, translationKeyOfPath, translationPathFor, EDITOR_KIND_LABELS, editorKindForMode, canvasViewForMode, inCanvas, hasSelection, hasElementSelection, emptyContext, makeContext, keyScopeStack, view, STAGE_CLASS, nextRenderGeneration, surfaceForPane, allCanvasSurfaces, stageContaining, registerCanvasSurface, createPaneSurface, setSurfaceTeardown, disposePaneSurface, BUFFER_COMMIT, bufferWrites, commitBufferWrites, cancelBufferWrites, bufferIsLive, bufferMovedOn, commitTabBuffers, tabBufferUnsaved, PROJECT_CONFIG_PATH, editorKindOf, editorKindsOf, modeForEditorKind, primarySelection, selectionAnchor, isSelected, cloneSelection, toggleSelected, rangeSelection, isSpliceablePath, structuralBatch, uniquePaths, unifyValues, setPatchConsumer, recordDocOp, transactDoc, transact, beginBatch, endBatch, isBatching, batchTab, setHistoryDelegate, canUndo, canRedo, undo, redo, mutateInsertNode, mutateRemoveNode, mutateDuplicateNode, mutateRemoveNodes, mutateDuplicateNodes, mutateWrapNode, mutateMoveNode, mutateUpdateProperty, mutateUpdateStyle, mutateUpdateAttribute, mutateUpdateMediaStyle, mutateUpdateNestedStyle, mutateUpdateMediaNestedStyle, mutateUpdateNestedStylePath, mutateUpdateMediaNestedStylePath, mutateReplaceStyle, mutateAddDef, mutateRemoveDef, mutateUpdateDef, mutateRenameDef, mutateUpdateProp, mutateAddSwitchCase, mutateRemoveSwitchCase, mutateRenameSwitchCase, mutateUpdateFrontmatter, serializeProjectConfig, commitProjectConfig, adoptProjectConfig, REGION_ATTR, resolveRegion, REGION_FOR_FOCUS, paneRegion, paneStripRegion, navigatorPanelRegion, inspectorTabRegion, NAVIGATOR_STATEMENTS_REGION, inspectorStatementsRegion, bottomPanelRegion, overlayRegion, setActiveRegistry, activeRegistry, initLayers, isModalOpen, showDialog, showConfirmDialog, showSaveDiscardDialog, showPromptDialog, openModal, renderPopover, popoverLayerFor, getLayerSlot, overlayIdleBlockers, getEffectiveMedia, getEffectiveStyle, getEffectiveImports, getEffectiveElements, getEffectiveHead, getEffectiveLocales, invalidateLayoutCache, getEffectiveLayoutPath, resolveLayoutDoc, distributePageIntoLayout, updateSiteConfig, collabState, isCollabPath, stringArg, optionalStringArg, boundedNumberArg, booleanArg, enumArg, pathArg, nullablePathArg, pathListArg, argsSchema, enumProperty, numberProperty, booleanProperty, pathProperty, pathListProperty, stringProperty, restoreSession, camelToKebab, camelToLabel, toCamelCase, kebabToLabel, propLabel, attrLabel, abbreviateValue, isMediaFormat, inferInputType, findContentTypeSchema, friendlyNameToVar, varDisplayName, parseCemType, jsonClone, configureCollabSerializer, configureCollabParser, configureCollabNotifier, collabSourceContext, collabReadOnly, collabSave, flushAllCollab, setCollabEnabled, isCollabEnabled, PRIMARY_PANE, workspace, activeTab, activePane, paneById, paneOfTab, focusPane, isPaneFocused, sidePane, receivingPane, detachTab, insertIntoPane, setWorkspaceProject, isTabActive, tabIsLive, openTab, promoteTab, promoteDirtyPreviewTabs, setTabPinned, moveTab, closeTab, closeAllTabs, replaceAllTabs, activateTab, moveTabToPane, renameTab, registerTabCommands, requireNavigatorPanelId, DEFAULT_INSPECTOR_TAB, isInspectorTabId, BOTTOM_TAB_IDS, DEFAULT_BOTTOM_TAB, isBottomTabId, CHROME_THEMES, DOCK_IDS, DOCK_DEFAULT_SIZES, setPaneSplit, shell, persistDocks, persistedSession, markSessionRestored, flushSession, monacoTheme, registerShellSurface, mountShell, setDockCollapsed, setDockSize, setActivityTab, setBottomTab, setChromeTheme, toggleActivityTab, setLayoutSelection, resetProjectShell, registerShellViewCommands };
|
|
3160
|
+
export { LANGUAGE_TAG_PATTERN, canonicalizeLocale, isWellFormedLocale, localeDirection, localeLabel, resolveI18n, localeOfPath, servedLocaleOfPath, translationKeyOfPath, translationPathFor, EDITOR_KIND_LABELS, editorKindForMode, canvasViewForMode, inCanvas, hasSelection, hasElementSelection, emptyContext, makeContext, keyScopeStack, PROJECT_CONFIG_PATH, createTab, editorKindOf, editorKindsOf, modeForEditorKind, disposeTab, primarySelection, selectionAnchor, isSelected, cloneSelection, toggleSelected, rangeSelection, isSpliceablePath, structuralBatch, uniquePaths, unifyValues, setPatchConsumer, recordDocOp, transactDoc, transact, beginBatch, endBatch, isBatching, batchTab, setHistoryDelegate, canUndo, canRedo, undo, redo, mutateInsertNode, mutateRemoveNode, mutateDuplicateNode, mutateRemoveNodes, mutateDuplicateNodes, mutateWrapNode, mutateMoveNode, mutateUpdateProperty, mutateUpdateStyle, mutateUpdateAttribute, mutateUpdateMediaStyle, mutateUpdateNestedStyle, mutateUpdateMediaNestedStyle, mutateUpdateNestedStylePath, mutateUpdateMediaNestedStylePath, mutateReplaceStyle, mutateAddDef, mutateRemoveDef, mutateUpdateDef, mutateRenameDef, mutateUpdateProp, mutateAddSwitchCase, mutateRemoveSwitchCase, mutateRenameSwitchCase, mutateUpdateFrontmatter, collabState, isCollabPath, stringArg, optionalStringArg, boundedNumberArg, booleanArg, enumArg, pathArg, nullablePathArg, pathListArg, argsSchema, enumProperty, derivedEnumProperty, numberProperty, booleanProperty, pathProperty, pathListProperty, stringProperty, LOCALE_PLACEHOLDER, collectionForDirectory, collectionForFile, camelToKebab, camelToLabel, toCamelCase, kebabToLabel, propLabel, attrLabel, abbreviateValue, isMediaFormat, inferInputType, findContentTypeSchema, friendlyNameToVar, varDisplayName, parseCemType, jsonClone, configureCollabSerializer, configureCollabParser, configureCollabNotifier, collabSourceContext, collabReadOnly, collabSave, flushAllCollab, setCollabEnabled, isCollabEnabled, PRIMARY_PANE, SECONDARY_PANE, MAX_PANES, workspace, activeTab, activePane, paneById, paneOfTab, focusPane, isPaneFocused, focusOtherPane, splitRight, sidePane, receivingPane, closePane, detachTab, insertIntoPane, setWorkspaceProject, isTabActive, tabIsLive, openTab, promoteTab, promoteDirtyPreviewTabs, setTabPinned, moveTab, closeTab, closeAllTabs, takeClosedTabPath, cycleTab, endTabCycle, replaceAllTabs, activateTab, moveTabToPane, renameTab, registerTabCommands, tabCommands, paneCommands };
|
|
5166
3161
|
|
|
5167
|
-
//# debugId=
|
|
5168
|
-
//# sourceMappingURL=studio-
|
|
3162
|
+
//# debugId=FC372971F7D8792C64756E2164756E21
|
|
3163
|
+
//# sourceMappingURL=studio-2zkz8evn.js.map
|