@jxsuite/studio 5.5.0 → 5.7.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/LICENSE +1 -1
- package/dist/chunks/{2020-g8mwpbkq.js → 2020-cs2sb9t1.js} +3 -3
- package/dist/chunks/adapter-y5gdq19c.js +4 -0
- package/dist/chunks/cf-account-picker-882a7ecm.js +4 -0
- package/dist/chunks/cf-settings-20dznc3j.js +4 -0
- package/dist/chunks/components-q037dya7.js +4 -0
- package/dist/chunks/content-source-37x3vsap.js +4 -0
- package/dist/chunks/convert-to-repeater-grfep2w8.js +4 -0
- package/dist/chunks/editor-j5sq149q.js +4 -0
- package/dist/chunks/entry-commands-c5h3nqck.js +4 -0
- package/dist/chunks/extension-sections-dp8endhx.js +4 -0
- package/dist/chunks/file-ops-937cvqk6.js +4 -0
- package/dist/chunks/files-tznwe1p1.js +4 -0
- package/dist/chunks/format-host-e2pjvd25.js +4 -0
- package/dist/chunks/fs-events-fv64ak3s.js +4 -0
- package/dist/chunks/git-panel-gb713ttc.js +4 -0
- package/dist/chunks/grid-view-5amhg604.js +51 -0
- package/dist/chunks/grid-view-5mqv1cbd.css +1 -0
- package/dist/chunks/iframe-host-t819mcg5.js +4 -0
- package/dist/chunks/{index-arg188jq.js → index-9ydfe04y.js} +3 -3
- package/dist/chunks/index-m0x5ztax.js +4 -0
- package/dist/chunks/{javascript-zcdmye2k.js → javascript-d9pqgc2p.js} +2 -2
- package/dist/chunks/{jsonMode-6x5e1nbf.js → jsonMode-800yvbem.js} +5 -5
- package/dist/chunks/jx-validate-zc9zp77s.js +4 -0
- package/dist/chunks/layers-4bsr82wz.js +4 -0
- package/dist/chunks/layers-panel-b6shnaax.js +4 -0
- package/dist/chunks/lit-html-cfn61dn7.js +4 -0
- package/dist/chunks/media-picker-ej0kdh1j.js +4 -0
- package/dist/chunks/menu-rtxf9chb.js +4 -0
- package/dist/chunks/{monaco-binding-4az2kh5p.js → monaco-binding-62dtmgbf.js} +3 -3
- package/dist/chunks/monaco-buffer-nn4dtx27.js +4 -0
- package/dist/chunks/{monaco-setup-d7mwkcx3.js → monaco-setup-tj13ndtm.js} +3 -3
- package/dist/chunks/notify-ahs57a2z.js +4 -0
- package/dist/chunks/platform-v9xyfkbx.js +4 -0
- package/dist/chunks/publish-panel-bq36xcmj.js +4 -0
- package/dist/chunks/quick-search-zm00h9dh.js +4 -0
- package/dist/chunks/references-99ws0b0m.js +4 -0
- package/dist/chunks/right-panel-pq2f71q3.js +4 -0
- package/dist/chunks/section-registry-b2yzp9sw.js +4 -0
- package/dist/chunks/studio-01kbbqg3.js +928 -0
- package/dist/chunks/{studio-hf4qdjc8.js → studio-01qza1n3.js} +4 -4
- package/dist/chunks/{studio-pkkw32j0.js → studio-03wwfvyt.js} +4 -4
- package/dist/chunks/{studio-7gqyhjns.js → studio-0bbxhhce.js} +4 -4
- package/dist/chunks/studio-0k9mvpgj.js +14 -0
- package/dist/chunks/studio-0scebvb9.js +6 -0
- package/dist/chunks/studio-1a99w39s.js +5 -0
- package/dist/chunks/studio-1wvfxkyy.js +5 -0
- package/dist/chunks/studio-1x8x26k3.js +5 -0
- package/dist/chunks/studio-222rqyyc.js +5 -0
- package/dist/chunks/studio-4xppwncr.js +4 -0
- package/dist/chunks/{studio-xcng8nx7.js → studio-54g077x3.js} +5 -5
- package/dist/chunks/studio-56z7evx4.js +10 -0
- package/dist/chunks/studio-5e9zsamh.js +9 -0
- package/dist/chunks/studio-65fhspdd.js +5 -0
- package/dist/chunks/studio-693nhyky.js +5 -0
- package/dist/chunks/{studio-7jazdy6y.js → studio-7pgy3xaf.js} +4 -4
- package/dist/chunks/studio-888knnkc.js +5 -0
- package/dist/chunks/studio-9mqfamps.js +5 -0
- package/dist/chunks/studio-a7xqhc3n.js +5 -0
- package/dist/chunks/studio-aje966s9.js +5 -0
- package/dist/chunks/studio-aqmph6k4.js +5 -0
- package/dist/chunks/studio-c6w3tq7t.js +5 -0
- package/dist/chunks/{studio-6j2jn55a.js → studio-c6zdm25z.js} +8 -8
- package/dist/chunks/{studio-f8jyp45j.js → studio-c9d3pxf7.js} +4 -4
- package/dist/chunks/studio-ceb34dxj.js +5 -0
- package/dist/chunks/studio-cvbkkfqb.js +5 -0
- package/dist/chunks/studio-cxt150pj.js +7 -0
- package/dist/chunks/studio-dkn3x3hz.js +5 -0
- package/dist/chunks/studio-e6re3rk1.js +5 -0
- package/dist/chunks/{studio-5n1km79v.js → studio-edbtvcd1.js} +4 -4
- package/dist/chunks/{studio-xc8ebsts.js → studio-eh0rac07.js} +4 -4
- package/dist/chunks/{studio-625ezz59.js → studio-evwgp1ym.js} +4 -4
- package/dist/chunks/{studio-he2fhrgp.js → studio-f195h2hq.js} +4 -4
- package/dist/chunks/studio-fqq890ap.js +4 -0
- package/dist/chunks/studio-frb0qbf7.js +6 -0
- package/dist/chunks/studio-gfn1kpxj.js +6 -0
- package/dist/chunks/studio-gh97gngt.js +5 -0
- package/dist/chunks/{studio-awqghqxv.js → studio-gp02nqnw.js} +4 -4
- package/dist/chunks/{studio-x9sagq2d.js → studio-hjbg8d5y.js} +7 -7
- package/dist/chunks/studio-j6gnhvaa.js +5 -0
- package/dist/chunks/studio-mwxgyn9h.js +7 -0
- package/dist/chunks/{studio-x5esgzct.js → studio-n78gjfy8.js} +4 -4
- package/dist/chunks/studio-nbxqcgvf.js +5 -0
- package/dist/chunks/{studio-p1eggxcf.js → studio-nt06yybj.js} +4 -4
- package/dist/chunks/{studio-hc9q4j24.js → studio-p7c1agz0.js} +5 -5
- package/dist/chunks/{studio-8r4y2x0z.js → studio-pwqfmt4p.js} +4 -4
- package/dist/chunks/{studio-5wfrgee9.js → studio-r3kaka4d.js} +4 -4
- package/dist/chunks/studio-semd1s8s.js +5 -0
- package/dist/chunks/studio-skzanb0k.js +5 -0
- package/dist/chunks/studio-spf2skgc.js +5 -0
- package/dist/chunks/{studio-b4epb26c.js → studio-st75kn99.js} +7 -7
- package/dist/chunks/{studio-eq27rrr0.js → studio-sxc0zvpt.js} +3 -3
- package/dist/chunks/studio-t1eedsyx.js +4 -0
- package/dist/chunks/{studio-73czgk6a.js → studio-tp642n5g.js} +4 -4
- package/dist/chunks/studio-tw7rre6s.js +5 -0
- package/dist/chunks/{studio-7by9a93k.js → studio-tzegmy4w.js} +4 -4
- package/dist/chunks/studio-vavmwshr.js +5 -0
- package/dist/chunks/studio-wma2c6g8.js +5 -0
- package/dist/chunks/studio-x92tgnee.js +64 -0
- package/dist/chunks/studio-xk0z6msk.js +5 -0
- package/dist/chunks/{studio-c4pnt1c6.js → studio-xry7tk3z.js} +5 -5
- package/dist/chunks/studio-xta2vxp6.js +9 -0
- package/dist/chunks/{studio-21enxdr8.js → studio-xy3tv3az.js} +4 -4
- package/dist/chunks/studio-y7jehjrp.js +5 -0
- package/dist/chunks/{studio-k1eaqyzm.js → studio-yr04mv2j.js} +4 -4
- package/dist/chunks/{studio-mhhc9btt.js → studio-zd4kayn2.js} +4 -4
- package/dist/chunks/studio-zpnk016a.js +16 -0
- package/dist/chunks/{tsMode-rtwt7w1a.js → tsMode-k9s9fcag.js} +5 -5
- package/dist/chunks/workspace-b69mgm0e.js +4 -0
- package/dist/chunks/ws-client-0ja08haa.js +4 -0
- package/dist/iframe-entry.js +14 -14
- package/dist/manifest.json +62 -59
- package/dist/studio.css +1 -1
- package/dist/studio.js +121 -123
- package/package.json +5 -5
- package/src/account/action-flow.ts +294 -0
- package/src/account/action-required.ts +68 -0
- package/src/account-status.ts +29 -1
- package/src/browse/library-model.ts +3 -1
- package/src/browse/library-preview.ts +6 -2
- package/src/canvas/asset-refs.ts +3 -1
- package/src/canvas/asset-resolve.ts +79 -1
- package/src/canvas/iframe-entry.ts +38 -1
- package/src/canvas/iframe-host.ts +85 -0
- package/src/canvas/iframe-protocol.ts +13 -0
- package/src/canvas/stage-scrollbar.ts +7 -7
- package/src/files/asset-versions.ts +294 -0
- package/src/files/file-ops.ts +5 -8
- package/src/files/files.ts +61 -9
- package/src/files/fs-events.ts +279 -28
- package/src/files/media-meta.ts +2 -1
- package/src/files/media-paths.ts +5 -2
- package/src/files/media-upload.ts +5 -1
- package/src/new-project/add-repo-modal.ts +12 -1
- package/src/new-project/new-project-modal.ts +12 -1
- package/src/panels/git-panel.ts +25 -2
- package/src/panels/jump-bar.ts +132 -158
- package/src/panels/pane-context.ts +8 -8
- package/src/panels/pane-grid.ts +18 -26
- package/src/panels/style-panel.ts +2 -2
- package/src/platform-errors.ts +61 -1
- package/src/platforms/cloud.ts +389 -50
- package/src/platforms/devserver.ts +17 -1
- package/src/publish/pages-service.ts +17 -7
- package/src/services/ai-models.ts +30 -6
- package/src/services/ai-system-prompt.ts +81 -51
- package/src/services/context-manager.ts +41 -70
- package/src/services/document-assistant.ts +12 -3
- package/src/services/harness/chat-reducer.ts +115 -0
- package/src/services/harness/turn-hooks.ts +50 -0
- package/src/services/tool-executor.ts +69 -288
- package/src/services/tool-outcomes.ts +12 -10
- package/src/settings/preferences-accounts.ts +42 -3
- package/src/settings/preferences-dialog.ts +8 -1
- package/src/studio.ts +20 -6
- package/src/surfaces/block-action-bar.json +6 -1
- package/src/surfaces/dialog.ts +5 -0
- package/src/surfaces/jump-bar.json +9 -12
- package/src/surfaces/jump-bar.ts +15 -16
- package/src/surfaces/pane-context.json +2 -2
- package/src/surfaces/pane-grid.json +8 -25
- package/src/surfaces/pane-grid.ts +7 -8
- package/src/surfaces/statusbar.json +71 -3
- package/src/surfaces/statusbar.ts +66 -139
- package/src/surfaces/style-panel.json +3 -3
- package/src/surfaces/style-panel.ts +11 -1
- package/src/surfaces/welcome.json +86 -1
- package/src/surfaces/welcome.ts +61 -2
- package/src/types.ts +84 -2
- package/src/ui/ai-managed-connect.ts +41 -4
- package/src/ui/media-picker.ts +2 -1
- package/dist/chunks/adapter-bsbs78x9.js +0 -4
- package/dist/chunks/cf-account-picker-gnm7xeqb.js +0 -4
- package/dist/chunks/cf-settings-9y6jyscp.js +0 -4
- package/dist/chunks/components-s51h3b7c.js +0 -4
- package/dist/chunks/content-source-ty3be0qg.js +0 -4
- package/dist/chunks/convert-to-repeater-c3e7q61z.js +0 -4
- package/dist/chunks/editor-t002b41m.js +0 -4
- package/dist/chunks/entry-commands-sb72e9gy.js +0 -4
- package/dist/chunks/extension-sections-ktn2ntnj.js +0 -4
- package/dist/chunks/file-ops-78zeytkm.js +0 -4
- package/dist/chunks/files-gatzrz8v.js +0 -4
- package/dist/chunks/format-host-r59b1651.js +0 -4
- package/dist/chunks/fs-events-f8h91ndt.js +0 -4
- package/dist/chunks/git-panel-y12zf7nj.js +0 -4
- package/dist/chunks/grid-view-rfd8b2pg.js +0 -51
- package/dist/chunks/grid-view-tafenfm2.css +0 -1
- package/dist/chunks/iframe-host-vsrsj20g.js +0 -4
- package/dist/chunks/index-5aghyrfh.js +0 -4
- package/dist/chunks/jx-validate-653krkrf.js +0 -4
- package/dist/chunks/layers-32p8gtae.js +0 -4
- package/dist/chunks/layers-panel-rs58m105.js +0 -4
- package/dist/chunks/lit-html-54bmkwz3.js +0 -4
- package/dist/chunks/media-picker-5bb04wct.js +0 -4
- package/dist/chunks/menu-cbha7w2e.js +0 -4
- package/dist/chunks/monaco-buffer-9vbbyfr1.js +0 -4
- package/dist/chunks/notify-dc1nz5ar.js +0 -4
- package/dist/chunks/platform-2m49s1zf.js +0 -4
- package/dist/chunks/publish-panel-nx3ycmma.js +0 -4
- package/dist/chunks/quick-search-yzrzh9x3.js +0 -4
- package/dist/chunks/references-vx7mbj9f.js +0 -4
- package/dist/chunks/right-panel-7jzpbxja.js +0 -4
- package/dist/chunks/section-registry-gjryse41.js +0 -4
- package/dist/chunks/studio-3znfhcxg.js +0 -5
- package/dist/chunks/studio-58qam27v.js +0 -4
- package/dist/chunks/studio-6j59fwaw.js +0 -5
- package/dist/chunks/studio-7z69g1gx.js +0 -5
- package/dist/chunks/studio-93j3v6zx.js +0 -5
- package/dist/chunks/studio-9gf6v8zy.js +0 -5
- package/dist/chunks/studio-9rhmettf.js +0 -4
- package/dist/chunks/studio-ac5aq677.js +0 -10
- package/dist/chunks/studio-as65vbns.js +0 -5
- package/dist/chunks/studio-bkv0sga4.js +0 -6
- package/dist/chunks/studio-bttmqef4.js +0 -5
- package/dist/chunks/studio-c3y9d41k.js +0 -5
- package/dist/chunks/studio-ccegp7gz.js +0 -9
- package/dist/chunks/studio-chxabn98.js +0 -6
- package/dist/chunks/studio-cktcdsxz.js +0 -16
- package/dist/chunks/studio-cnspfke5.js +0 -5
- package/dist/chunks/studio-de3p1ktm.js +0 -5
- package/dist/chunks/studio-fsbcn530.js +0 -928
- package/dist/chunks/studio-gftga7a3.js +0 -64
- package/dist/chunks/studio-hf1rpcq0.js +0 -4
- package/dist/chunks/studio-hz02hq70.js +0 -5
- package/dist/chunks/studio-jnb285we.js +0 -5
- package/dist/chunks/studio-jsv3s3s1.js +0 -5
- package/dist/chunks/studio-ks7cksh0.js +0 -5
- package/dist/chunks/studio-nptx0dbs.js +0 -5
- package/dist/chunks/studio-pg0z7k98.js +0 -5
- package/dist/chunks/studio-pve0b2f2.js +0 -5
- package/dist/chunks/studio-q7zmjv3b.js +0 -6
- package/dist/chunks/studio-rpmvw7kj.js +0 -5
- package/dist/chunks/studio-rwhss52s.js +0 -5
- package/dist/chunks/studio-sbg3g3h0.js +0 -5
- package/dist/chunks/studio-sq1bn60g.js +0 -14
- package/dist/chunks/studio-vwz7rma2.js +0 -5
- package/dist/chunks/studio-wa55e8gf.js +0 -5
- package/dist/chunks/studio-x0mzdha2.js +0 -5
- package/dist/chunks/studio-xrgpakvc.js +0 -9
- package/dist/chunks/studio-xt3djk1w.js +0 -7
- package/dist/chunks/studio-yh3nggx1.js +0 -7
- package/dist/chunks/studio-zmecp6hq.js +0 -5
- package/dist/chunks/workspace-g6dvaete.js +0 -4
- package/dist/chunks/ws-client-shf41j5p.js +0 -4
package/src/studio.ts
CHANGED
|
@@ -94,7 +94,6 @@ import { runInsertZoneAction } from "./editor/insert-zone-action";
|
|
|
94
94
|
import { canvasSlashHandler } from "./editor/canvas-slash-bridge";
|
|
95
95
|
import { makeCanvasContextMenuHandler } from "./editor/canvas-context-menu";
|
|
96
96
|
import { mountStatusbar, renderStatusbar } from "./surfaces/statusbar";
|
|
97
|
-
import { mountJumpBar } from "./panels/jump-bar";
|
|
98
97
|
import { cellForPane, paneGridReady } from "./panels/pane-grid";
|
|
99
98
|
import { notify } from "./services/notify";
|
|
100
99
|
import { createLiveSurfaceSaver } from "./services/live-surfaces";
|
|
@@ -126,8 +125,10 @@ import {
|
|
|
126
125
|
openLastSessionOrHome,
|
|
127
126
|
registerFileTreeDnD,
|
|
128
127
|
reloadCleanTab,
|
|
128
|
+
reloadTabsIfChanged,
|
|
129
129
|
} from "./files/files";
|
|
130
130
|
import { resetIgnoreCache } from "./files/gitignore";
|
|
131
|
+
import { resetAssetVersions } from "./files/asset-versions";
|
|
131
132
|
import { startFsSync } from "./files/fs-events";
|
|
132
133
|
import { invalidateParamValues } from "./page-params";
|
|
133
134
|
import {
|
|
@@ -221,6 +222,8 @@ import {
|
|
|
221
222
|
import { initCssData } from "./panels/style-utils";
|
|
222
223
|
import { initQuickSearch } from "./panels/quick-search";
|
|
223
224
|
import { hydrateAccountStatus } from "./account-status";
|
|
225
|
+
import { showToastNotices, wireActionReports } from "./account/action-flow";
|
|
226
|
+
import { isActionRequired } from "./platform-errors";
|
|
224
227
|
import { hydrateProjectList } from "./project-list";
|
|
225
228
|
import { addRecentProject, hydrateRecentProjects, removeRecentProject } from "./recent-projects";
|
|
226
229
|
import {
|
|
@@ -507,6 +510,9 @@ toolbarPanel.mount(toolbarEl, {
|
|
|
507
510
|
});
|
|
508
511
|
|
|
509
512
|
initLayers();
|
|
513
|
+
/* Before anything reaches the backend: an `action-required` refusal (desktop.md §10.4) can be the
|
|
514
|
+
answer to the very first request, and the dialog that offers its actions needs the layers above. */
|
|
515
|
+
wireActionReports();
|
|
510
516
|
initQuickSearch({ openRecentProject: (root: string) => openRecentProject(root) });
|
|
511
517
|
|
|
512
518
|
/* The pane's four surfaces come from its CELL, not from `document.querySelector`.
|
|
@@ -909,11 +915,9 @@ registerRenderer("seoModal", renderSeoModal);
|
|
|
909
915
|
registerRenderer("chatPanel", () => chatPanelMod.render());
|
|
910
916
|
registerRenderer("overlays", () => overlaysPanel.render());
|
|
911
917
|
renderStatusbar();
|
|
918
|
+
// The status bar mounts the jump bar too: the focused pane's breadcrumb trail is its DOCUMENT
|
|
919
|
+
// Field, and the only breadcrumb in the shell.
|
|
912
920
|
mountStatusbar();
|
|
913
|
-
// The jump bar, in the pane's own grid cell above the context bar. It renders the whole address
|
|
914
|
-
// — project › file › node › node — and it is the only breadcrumb in the shell: the pane context
|
|
915
|
-
// Bar drew a second one, and it named a sub-document stack nothing could push onto.
|
|
916
|
-
mountJumpBar(primaryCell?.jump ?? document.createElement("div"));
|
|
917
921
|
mountActivityBar();
|
|
918
922
|
|
|
919
923
|
/* The background-click deselect moved into `editor/shortcuts.ts`'s `installStageGestures`, beside
|
|
@@ -959,6 +963,9 @@ function ensureFsSync() {
|
|
|
959
963
|
paneContext.resetParamValues();
|
|
960
964
|
},
|
|
961
965
|
onContentChange: reloadCleanTab,
|
|
966
|
+
/* A reconnect re-reads the clean, non-collab tabs, and leaves every one whose content did not
|
|
967
|
+
change untouched: most reconnects changed nothing, and a reload is a repaint per tab. */
|
|
968
|
+
onResyncContent: reloadTabsIfChanged,
|
|
962
969
|
renderLeftPanel,
|
|
963
970
|
});
|
|
964
971
|
}
|
|
@@ -979,7 +986,10 @@ if (!_projectParam) {
|
|
|
979
986
|
// No project is bound yet, so this call only warms the canvasUrl; a backend that refuses it
|
|
980
987
|
// Still gets the render below rather than an unhandled rejection.
|
|
981
988
|
?.catch((error: unknown) => {
|
|
982
|
-
|
|
989
|
+
// A refusal that offers an action is the action flow's to explain; it is not a fault.
|
|
990
|
+
if (!isActionRequired(error)) {
|
|
991
|
+
console.error("Boot activation failed:", error);
|
|
992
|
+
}
|
|
983
993
|
})
|
|
984
994
|
.then(() => {
|
|
985
995
|
render();
|
|
@@ -1022,6 +1032,7 @@ if (_projectParam) {
|
|
|
1022
1032
|
}
|
|
1023
1033
|
|
|
1024
1034
|
resetIgnoreCache();
|
|
1035
|
+
resetAssetVersions();
|
|
1025
1036
|
setProjectState({
|
|
1026
1037
|
dirs: new Map(),
|
|
1027
1038
|
expanded: new Set(),
|
|
@@ -1188,6 +1199,8 @@ void hydrateProjectList().then(() => {
|
|
|
1188
1199
|
// The welcome screen's install prompt. No-op on platforms without getAccountStatus.
|
|
1189
1200
|
// oxlint-disable-next-line unicorn/prefer-top-level-await -- deliberate fire-and-forget: hydration must not block initial render
|
|
1190
1201
|
void hydrateAccountStatus().then(() => {
|
|
1202
|
+
// After the status: the platform's one-time notices ride on it (desktop.md §10.4).
|
|
1203
|
+
showToastNotices();
|
|
1191
1204
|
render();
|
|
1192
1205
|
});
|
|
1193
1206
|
|
|
@@ -1355,6 +1368,7 @@ async function openRecentProject(root: string) {
|
|
|
1355
1368
|
|
|
1356
1369
|
closeAllTabs();
|
|
1357
1370
|
resetIgnoreCache();
|
|
1371
|
+
resetAssetVersions();
|
|
1358
1372
|
|
|
1359
1373
|
setProjectState({
|
|
1360
1374
|
...projectState,
|
package/src/surfaces/dialog.ts
CHANGED
|
@@ -96,6 +96,8 @@ export interface DialogSurfacePatch {
|
|
|
96
96
|
*/
|
|
97
97
|
confirmLabel?: string;
|
|
98
98
|
cancelLabel?: string;
|
|
99
|
+
/** The secondary button's text; the empty string takes the button away. */
|
|
100
|
+
secondaryLabel?: string;
|
|
99
101
|
/** The sentence under the headline. Cleared by the empty string. */
|
|
100
102
|
message?: string;
|
|
101
103
|
value?: string;
|
|
@@ -298,6 +300,9 @@ export function openDialogSurface(options: DialogSurfaceOptions): DialogSurfaceH
|
|
|
298
300
|
if (patch.cancelLabel !== undefined) {
|
|
299
301
|
scope.cancelLabel = patch.cancelLabel;
|
|
300
302
|
}
|
|
303
|
+
if (patch.secondaryLabel !== undefined) {
|
|
304
|
+
scope.secondaryLabel = patch.secondaryLabel;
|
|
305
|
+
}
|
|
301
306
|
if (patch.message !== undefined) {
|
|
302
307
|
scope.message = patch.message;
|
|
303
308
|
scope.hasMessage = patch.message !== "";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
3
|
"$id": "StudioJumpBar",
|
|
4
|
-
"$description": "The jump bar:
|
|
4
|
+
"$description": "The jump bar: the focused pane's address as a breadcrumb trail, the document first and the selected element last, every step a command the adapter has already resolved against the registry. It is the status bar's DOCUMENT field, mounted into the slot `surfaces/statusbar.json` leaves for it. A step is a button when its command can run and a readout when it cannot — an address with a hole in it is a lie about containment, so a step never disappears. A step with more than one place to go carries the chevron that opens its siblings, upward, because the bar is the window's floor; one alternative is not a choice and draws no control. Nothing here decides what the bar says, which step is where you are, or what a chevron opens.",
|
|
5
5
|
"tagName": "nav",
|
|
6
6
|
"attributes": {
|
|
7
7
|
"part": "bar",
|
|
@@ -10,22 +10,18 @@
|
|
|
10
10
|
"hidden": "${state.empty ? '' : null}"
|
|
11
11
|
},
|
|
12
12
|
"style": {
|
|
13
|
-
"$description": "
|
|
13
|
+
"$description": "A field of the status bar, so it takes the bar's own row, font and colour rather than drawing a band of its own. It scrolls rather than wraps, because a deep selection must not grow the status bar a second line.",
|
|
14
14
|
"display": "flex",
|
|
15
15
|
"alignItems": "center",
|
|
16
16
|
"gap": "1px",
|
|
17
|
-
"
|
|
18
|
-
"
|
|
17
|
+
"flex": "1",
|
|
18
|
+
"height": "100%",
|
|
19
|
+
"padding": "0 var(--jx-space-2)",
|
|
19
20
|
"minWidth": "0",
|
|
20
21
|
"overflowX": "auto",
|
|
21
22
|
"scrollbarWidth": "none",
|
|
22
23
|
"whiteSpace": "nowrap",
|
|
23
24
|
"boxSizing": "border-box",
|
|
24
|
-
"fontFamily": "var(--jx-font-sans)",
|
|
25
|
-
"fontSize": "var(--jx-text-xs)",
|
|
26
|
-
"color": "var(--jx-fg-dim)",
|
|
27
|
-
"background": "var(--jx-bg-panel)",
|
|
28
|
-
"borderBottom": "1px solid var(--jx-border)",
|
|
29
25
|
"&[hidden]": {
|
|
30
26
|
"display": "none"
|
|
31
27
|
},
|
|
@@ -44,7 +40,7 @@
|
|
|
44
40
|
"opacity": "0.6"
|
|
45
41
|
},
|
|
46
42
|
"& [part=\"crumb\"]": {
|
|
47
|
-
"maxWidth": "
|
|
43
|
+
"maxWidth": "32ch",
|
|
48
44
|
"overflow": "hidden",
|
|
49
45
|
"margin": "0",
|
|
50
46
|
"padding": "0 var(--jx-space-2)",
|
|
@@ -74,7 +70,8 @@
|
|
|
74
70
|
},
|
|
75
71
|
"& [part=\"crumb\"][aria-current]": {
|
|
76
72
|
"$description": "Where you ARE is stated by weight, not by taking the control away: the leaf still selects, which is how a stray click in the canvas is undone without leaving the bar.",
|
|
77
|
-
"color": "var(--jx-fg)"
|
|
73
|
+
"color": "var(--jx-fg)",
|
|
74
|
+
"fontWeight": "600"
|
|
78
75
|
},
|
|
79
76
|
"& span[part=\"crumb\"]": {
|
|
80
77
|
"$description": "A step with no runnable command is a readout, not a dead button. No hover, no pointer, no promise.",
|
|
@@ -213,7 +210,7 @@
|
|
|
213
210
|
"aria-label": "${$map.item.altsLabel}",
|
|
214
211
|
"title": "${$map.item.altsLabel}"
|
|
215
212
|
},
|
|
216
|
-
"textContent": "
|
|
213
|
+
"textContent": "⌃",
|
|
217
214
|
"onclick": {
|
|
218
215
|
"$prototype": "Function",
|
|
219
216
|
"body": [
|
package/src/surfaces/jump-bar.ts
CHANGED
|
@@ -4,19 +4,18 @@
|
|
|
4
4
|
*
|
|
5
5
|
* `jump-bar.json` is the markup, the ARIA and the style; `panels/jump-bar.ts` is the flow — which
|
|
6
6
|
* pane this bar is about, what its address is, which of its steps the registry can actually run,
|
|
7
|
-
* and what a chevron opens. This module is the seam between them: one scope
|
|
8
|
-
*
|
|
7
|
+
* and what a chevron opens. This module is the seam between them: one scope, one document mounted
|
|
8
|
+
* into the slot the status bar leaves for it, and an `update()` that ASSIGNS rather than
|
|
9
|
+
* re-mounts.
|
|
9
10
|
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* node, and the chevron the reader is aiming at does not move under them.
|
|
11
|
+
* The scope is reactive, so a repaint is an assignment to `segments` and the keyed `$map`
|
|
12
|
+
* reconciles: a step whose key survives keeps its node, and the chevron the reader is aiming at
|
|
13
|
+
* does not move under them.
|
|
14
14
|
*
|
|
15
|
-
* **The bar hides rather than un-mounts when
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
* this surface and its stylesheet-free document share.
|
|
15
|
+
* **The bar hides rather than un-mounts when there is no address.** With no tab open there is
|
|
16
|
+
* nothing to print, and the document's own `hidden` takes it off the screen — the mount stays,
|
|
17
|
+
* because the next tab open is one assignment away and re-mounting would cost a frame of blank
|
|
18
|
+
* chrome.
|
|
20
19
|
*
|
|
21
20
|
* @docs studio/interface
|
|
22
21
|
*/
|
|
@@ -81,13 +80,13 @@ interface JumpBarScope extends Record<string, unknown>, JumpBarActions {
|
|
|
81
80
|
}
|
|
82
81
|
|
|
83
82
|
/**
|
|
84
|
-
* Mount
|
|
83
|
+
* Mount the bar into the slot the status bar built for it.
|
|
85
84
|
*
|
|
86
|
-
* The host is CLEARED first:
|
|
87
|
-
*
|
|
85
|
+
* The host is CLEARED first: the slot is the bar's own, and whatever was in it belongs to a mount
|
|
86
|
+
* this bar is no longer drawing.
|
|
88
87
|
*
|
|
89
|
-
* @param {HTMLElement} host The
|
|
90
|
-
* @param {string} region The `data-jx-region` the bar stamps on itself — `
|
|
88
|
+
* @param {HTMLElement} host The status bar's slot for the bar.
|
|
89
|
+
* @param {string} region The `data-jx-region` the bar stamps on itself — `statusbar/document`.
|
|
91
90
|
* @param {JumpBarActions} actions What a press does. Read once, when the scope is made.
|
|
92
91
|
* @returns {JumpBarSurface}
|
|
93
92
|
*/
|
|
@@ -497,7 +497,7 @@
|
|
|
497
497
|
"$ref": "#/state/previewHint"
|
|
498
498
|
}
|
|
499
499
|
},
|
|
500
|
-
"
|
|
500
|
+
"onchange": {
|
|
501
501
|
"$prototype": "Function",
|
|
502
502
|
"body": [
|
|
503
503
|
{
|
|
@@ -1227,7 +1227,7 @@
|
|
|
1227
1227
|
"$ref": "$map/item/hint"
|
|
1228
1228
|
}
|
|
1229
1229
|
},
|
|
1230
|
-
"
|
|
1230
|
+
"onchange": {
|
|
1231
1231
|
"$prototype": "Function",
|
|
1232
1232
|
"body": [
|
|
1233
1233
|
{
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
3
|
"$id": "StudioPaneGrid",
|
|
4
|
-
"$description": "The pane grid (studio.md §18.1): one cell per pane, with a splitter before every cell but the first. Every box here is EMPTY by design — the
|
|
4
|
+
"$description": "The pane grid (studio.md §18.1): one cell per pane, with a splitter before every cell but the first. Every box here is EMPTY by design — the FOUR inside a cell are hosts other modules fill (`panels/tab-strip.ts` the strip, `panels/pane-context.ts` the chrome layer, `canvas/canvas-render.ts` the stage, `panels/pane-grid.ts` itself the right-edge drop zone), and the stage is an ISLAND in the studio-ui-guidelines.md §9.4 sense: the canvas host mounts a cross-origin `<iframe>` into it, so nothing this document draws may ever go inside it. What the document owns is the STRUCTURE and the STYLE — the cell's own two-row grid, the three row-2 children that share its lower cell, and the splitter — which is `styles/shell.css`'s `.pane*` block and `styles/canvas.css`'s `.pane-stage` rule, carried here and keyed on `part`. Two things are load-bearing and easy to undo. (1) **A row that moves reloads an iframe**, so the keyed `$map` is not an optimisation: `workspace.panes[0]` is always the primary and `MAX_PANES` is 2, the key is the pane id, and the runtime's forward-cursor pass therefore never moves a kept row — gaining or losing the side pane leaves the primary's node, and the frame inside it, untouched. (2) **The splitter must sit BETWEEN two cells and inside neither**, so each row is a `display: contents` wrapper holding its own leading splitter and its cell: the wrapper generates no box, so the splitter and the two cells are the grid items of `#pane-grid` in DOM order, and a pointer landing on the splitter is in no cell at all. Every selector below is a `>` chain from the root, because a pane's stage hosts other surface documents and a bare `[part=\"row\"]` descendant rule would reach into them.",
|
|
5
5
|
"tagName": "div",
|
|
6
6
|
"attributes": {
|
|
7
7
|
"part": "grid",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"zIndex": "10"
|
|
28
28
|
},
|
|
29
29
|
"& > [part=\"row\"] > [part=\"pane\"]": {
|
|
30
|
-
"$description": "ONE PANE, and one COLUMN, declared.
|
|
30
|
+
"$description": "ONE PANE, and one COLUMN, declared. Three children name `grid-row: 2` in order to share the lower cell, and auto-placement answers that by inventing an implicit column each: the chrome layer, the stage and the drop zone lined up side by side (with a fourth, the jump bar, that has since moved to the status bar), the stage taking a fraction of the pane and pinning the document to the right edge. `grid-template-columns` is what makes \"share the cell\" mean it, and every row-2 child restates `grid-column: 1` so a future fourth one cannot re-open the same hole. No unit test can see this — happy-dom does no layout, so every rect is zero — which is why the screenshot lane is what caught it.",
|
|
31
31
|
"display": "grid",
|
|
32
32
|
"gridTemplateColumns": "minmax(0, 1fr)",
|
|
33
33
|
"gridTemplateRows": "auto minmax(0, 1fr)",
|
|
@@ -44,21 +44,10 @@
|
|
|
44
44
|
"$description": "A pane with nothing to say costs no band. The strip host is empty until `panels/tab-strip.ts` mounts a document into it, and empty again the moment it disposes.",
|
|
45
45
|
"display": "none"
|
|
46
46
|
},
|
|
47
|
-
"& > [part=\"row\"] > [part=\"pane\"] > [part=\"jump\"]": {
|
|
48
|
-
"$description": "The jump bar. Like the chrome layer below it this shares the pane's lower cell rather than owning a row, so the two bars stack OVER the stage instead of pushing it down. `align-self: start` is what keeps it the height of its own content instead of the height of the cell, so the bar never covers the stage it sits above.",
|
|
49
|
-
"gridRow": "2",
|
|
50
|
-
"gridColumn": "1",
|
|
51
|
-
"alignSelf": "start",
|
|
52
|
-
"position": "relative",
|
|
53
|
-
"zIndex": "3",
|
|
54
|
-
"minWidth": "0",
|
|
55
|
-
"maxWidth": "100%"
|
|
56
|
-
},
|
|
57
47
|
"& > [part=\"row\"] > [part=\"pane\"] > [part=\"chrome\"]": {
|
|
58
|
-
"$description": "The pane context bar and the floating zoom pod. The layer itself is inert and only its children take the pointer; `surfaces/pane-context.json` owns what they look like.
|
|
48
|
+
"$description": "The pane context bar and the floating zoom pod. The layer itself is inert and only its children take the pointer; `surfaces/pane-context.json` owns what they look like.",
|
|
59
49
|
"gridRow": "2",
|
|
60
50
|
"gridColumn": "1",
|
|
61
|
-
"marginTop": "var(--jump-bar-h, 0px)",
|
|
62
51
|
"position": "relative",
|
|
63
52
|
"zIndex": "2",
|
|
64
53
|
"minWidth": "0",
|
|
@@ -71,10 +60,10 @@
|
|
|
71
60
|
"pointerEvents": "auto"
|
|
72
61
|
},
|
|
73
62
|
"& > [part=\"row\"] > [part=\"pane\"] > [part=\"pane-stage\"]": {
|
|
74
|
-
"$description": "The stage: the pane's own axis (`styles/canvas.css`) over its placement in the cell (`styles/shell.css`). Offset by the
|
|
63
|
+
"$description": "The stage: the pane's own axis (`styles/canvas.css`) over its placement in the cell (`styles/shell.css`). Offset by the context bar stacked over this cell — `--pane-context-h`, written by `panels/pane-context.ts` onto the CELL, which is why this reads it by cascade — so the bar never covers the document, and by zero when no tab is open, so the welcome screen does not sit under a band nothing explains. A pane's address used to be a second bar stacked here (`--jump-bar-h`); it is the status bar's breadcrumb trail now, and costs the stage nothing.",
|
|
75
64
|
"gridRow": "2",
|
|
76
65
|
"gridColumn": "1",
|
|
77
|
-
"marginTop": "
|
|
66
|
+
"marginTop": "var(--pane-context-h, 0px)",
|
|
78
67
|
"position": "relative",
|
|
79
68
|
"overflow": "auto",
|
|
80
69
|
"background": "var(--bg-panel)",
|
|
@@ -84,7 +73,7 @@
|
|
|
84
73
|
"alignItems": "flex-start"
|
|
85
74
|
},
|
|
86
75
|
"& > [part=\"row\"] > [part=\"pane\"] > [part=\"drop-zone\"]": {
|
|
87
|
-
"$description": "The right-edge target that creates a second pane (§18.1). Sits ABOVE the stage (`z-index: 4` against the stage's own stacking,
|
|
76
|
+
"$description": "The right-edge target that creates a second pane (§18.1). Sits ABOVE the stage (`z-index: 4` against the stage's own stacking, chrome's 2) so a drag reaches it before it reaches the cross-origin iframe underneath, which would otherwise swallow every drag event with no affordance to say so. `pointer-events: none` when unarmed — a mouse doing anything other than dragging a tab or a file must pass straight through to the stage — and `auto` only while `data-armed` is set, which `panels/pane-grid.ts`'s own arming monitor writes for the DURATION of a drag it recognises, never for a click.",
|
|
88
77
|
"gridRow": "2",
|
|
89
78
|
"gridColumn": "1",
|
|
90
79
|
"position": "relative",
|
|
@@ -108,7 +97,7 @@
|
|
|
108
97
|
},
|
|
109
98
|
"children": [
|
|
110
99
|
{
|
|
111
|
-
"$description": "Keyed on the PANE ID, and that is the whole of §18.1 rule 1's structural half: the key is what makes the runtime MOVE a kept row rather than rebuild it, and re-parenting is not a move for an `<iframe>` — it reloads, dropping its `iframe-channel` connection, its shadow document and every `ready` panel with it. A row renders complete (its cell, its
|
|
100
|
+
"$description": "Keyed on the PANE ID, and that is the whole of §18.1 rule 1's structural half: the key is what makes the runtime MOVE a kept row rather than rebuild it, and re-parenting is not a move for an `<iframe>` — it reloads, dropping its `iframe-channel` connection, its shadow document and every `ready` panel with it. A row renders complete (its cell, its four hosts and its splitter) inside the row's own effect scope before it is inserted, so there is no frame in which a cell exists with no stage inside it.",
|
|
112
101
|
"$prototype": "Array",
|
|
113
102
|
"items": { "$ref": "#/state/rows" },
|
|
114
103
|
"key": { "$ref": "$map/item/id" },
|
|
@@ -181,13 +170,7 @@
|
|
|
181
170
|
}
|
|
182
171
|
},
|
|
183
172
|
{
|
|
184
|
-
"$description": "The
|
|
185
|
-
"tagName": "div",
|
|
186
|
-
"attributes": {
|
|
187
|
-
"part": "jump"
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
{
|
|
173
|
+
"$description": "The context bar is HANDED this box rather than resolving a region into it. It cannot resolve one the way the strip does: nothing inside the strip re-stamps `pane.<id>/tabs`, while the context bar stamps `pane.<id>/context` on markup it renders INSIDE this div — so a region on the wrapper as well would put the same id on two nested elements, and `resolveRegion` takes the LAST match. Sixty shots crop `pane.primary/context`; a second, larger element carrying it is a silently widened crop.",
|
|
191
174
|
"tagName": "div",
|
|
192
175
|
"attributes": {
|
|
193
176
|
"part": "chrome"
|
|
@@ -35,10 +35,10 @@ registerSurface("pane-grid", paneGridDoc as unknown as JxDocument);
|
|
|
35
35
|
/**
|
|
36
36
|
* The `part` a pane's CELL carries.
|
|
37
37
|
*
|
|
38
|
-
* `panels/
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
38
|
+
* `panels/pane-context.ts` writes a `--*-h` custom property onto the cell so the stage can read it
|
|
39
|
+
* back by cascade, and it is handed a box inside the cell rather than the cell itself — so it
|
|
40
|
+
* resolves the cell with {@link PANE_SELECTOR}. It replaces a `.pane` class: a converted surface
|
|
41
|
+
* emits none, and a `part` is the hook a document offers instead.
|
|
42
42
|
*/
|
|
43
43
|
export const PANE_PART = "pane";
|
|
44
44
|
|
|
@@ -63,13 +63,12 @@ export const PANE_SELECTOR = `[part="${PANE_PART}"]`;
|
|
|
63
63
|
*/
|
|
64
64
|
export const STAGE_SELECTOR = `[part="${STAGE_PART}"]`;
|
|
65
65
|
|
|
66
|
-
/** The
|
|
67
|
-
export type PaneCellPart = "pane" | "strip" | "
|
|
66
|
+
/** The five boxes a cell is made of, in the order the document draws them. */
|
|
67
|
+
export type PaneCellPart = "pane" | "strip" | "chrome" | "stage" | "dropZone";
|
|
68
68
|
|
|
69
69
|
const CELL_PARTS: ReadonlyMap<string, PaneCellPart> = new Map([
|
|
70
70
|
["pane", "pane"],
|
|
71
71
|
["strip", "strip"],
|
|
72
|
-
["jump", "jump"],
|
|
73
72
|
["chrome", "chrome"],
|
|
74
73
|
["pane-stage", "stage"],
|
|
75
74
|
["drop-zone", "dropZone"],
|
|
@@ -234,7 +233,7 @@ export function mountPaneGridSurface(
|
|
|
234
233
|
const ready = mountSurface("pane-grid", scope, host, {
|
|
235
234
|
/* No `instanceof` narrowing and no "is there a pane" guard, and both absences are structural.
|
|
236
235
|
`pane-grid.json` draws no text and no `textContent`, so every node the runtime reports here
|
|
237
|
-
is an element; and the
|
|
236
|
+
is an element; and the five cell parts exist only inside the repeater's rows, so a `$map`
|
|
238
237
|
scope is always there to name the pane. A guard on either would be a branch the document
|
|
239
238
|
cannot reach — which is a line no test could ever cover, which is a claim nothing checks. */
|
|
240
239
|
onNodeCreated: (element, _path, def, state) => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
3
|
"$id": "StudioStatusbar",
|
|
4
|
-
"$description": "The status bar: ambient state in the shell's level order, PROJECT then DOCUMENT then SELECTION. The adapter hands in
|
|
4
|
+
"$description": "The status bar: ambient state in the shell's level order, PROJECT then DOCUMENT then SELECTION. The adapter hands in the fields either side of the DOCUMENT field (`leading` and `trailing`), each with its region and its items; an item with a command is a button that runs it through `run`, and an item without one is a readout. The DOCUMENT field between them is the `trail` slot, an empty box `panels/jump-bar.ts` mounts the breadcrumb trail into. Nothing here decides what the bar says.",
|
|
5
5
|
"tagName": "div",
|
|
6
6
|
"attributes": { "part": "bar" },
|
|
7
7
|
"style": {
|
|
@@ -17,7 +17,17 @@
|
|
|
17
17
|
"padding": "0 var(--jx-space-3)"
|
|
18
18
|
},
|
|
19
19
|
"& > [part=\"field\"]:last-child": { "overflow": "hidden" },
|
|
20
|
-
"& > [
|
|
20
|
+
"& > :not([hidden]) ~ :not([hidden])": {
|
|
21
|
+
"$description": "A rule between fields rather than a run of \"|\" characters: the boundary between PROJECT, DOCUMENT and SELECTION is structural. Every visible field after a visible field draws one, so a hidden DOCUMENT slot leaves no doubled rule behind.",
|
|
22
|
+
"borderLeft": "1px solid var(--jx-border)"
|
|
23
|
+
},
|
|
24
|
+
"& > [part=\"trail\"]": {
|
|
25
|
+
"$description": "The DOCUMENT field, filled by `panels/jump-bar.ts`. It takes the width the other two fields leave, so a deep trail scrolls inside it instead of pushing the SELECTION field off the bar.",
|
|
26
|
+
"display": "flex",
|
|
27
|
+
"flex": "1",
|
|
28
|
+
"minWidth": "0"
|
|
29
|
+
},
|
|
30
|
+
"& > [part=\"trail\"][hidden]": { "display": "none" },
|
|
21
31
|
"& [part=\"item\"], & [part=\"state\"]": {
|
|
22
32
|
"maxWidth": "32ch",
|
|
23
33
|
"overflow": "hidden",
|
|
@@ -43,7 +53,65 @@
|
|
|
43
53
|
"children": [
|
|
44
54
|
{
|
|
45
55
|
"$prototype": "Array",
|
|
46
|
-
"items": { "$ref": "#/state/
|
|
56
|
+
"items": { "$ref": "#/state/leading" },
|
|
57
|
+
"key": { "$ref": "$map/item/id" },
|
|
58
|
+
"map": {
|
|
59
|
+
"tagName": "div",
|
|
60
|
+
"attributes": { "part": "field", "data-jx-region": "${$map.item.region}" },
|
|
61
|
+
"children": [
|
|
62
|
+
{
|
|
63
|
+
"$prototype": "Array",
|
|
64
|
+
"items": { "$ref": "$map/item/items" },
|
|
65
|
+
"key": { "$ref": "$map/item/key" },
|
|
66
|
+
"map": {
|
|
67
|
+
"tagName": "span",
|
|
68
|
+
"attributes": { "part": "slot" },
|
|
69
|
+
"style": { "display": "contents" },
|
|
70
|
+
"$switch": { "$ref": "$map/item/kind" },
|
|
71
|
+
"cases": {
|
|
72
|
+
"button": {
|
|
73
|
+
"tagName": "button",
|
|
74
|
+
"attributes": {
|
|
75
|
+
"part": "item",
|
|
76
|
+
"type": "button",
|
|
77
|
+
"title": "${$map.item.title}",
|
|
78
|
+
"disabled": { "$ref": "$map/item/disabled" }
|
|
79
|
+
},
|
|
80
|
+
"textContent": "${$map.item.label}",
|
|
81
|
+
"onclick": {
|
|
82
|
+
"$prototype": "Function",
|
|
83
|
+
"body": [
|
|
84
|
+
{
|
|
85
|
+
"operator": "call",
|
|
86
|
+
"target": { "$ref": "#/state/run" },
|
|
87
|
+
"value": [{ "$ref": "$map/item/key" }]
|
|
88
|
+
}
|
|
89
|
+
]
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"state": {
|
|
93
|
+
"tagName": "span",
|
|
94
|
+
"attributes": { "part": "state", "title": "${$map.item.title}" },
|
|
95
|
+
"textContent": "${$map.item.label}"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
"$description": "The DOCUMENT field's slot. Empty by design: the jump bar is handed this box and mounts its own document into it, so nothing here may ever render a child. `aria-live=\"off\"` because the bar's host is the app's polite status region, and a trail that changes on every click in the canvas would be read aloud on every click; the trail is a `nav` a reader visits, not news.",
|
|
105
|
+
"tagName": "div",
|
|
106
|
+
"attributes": {
|
|
107
|
+
"part": "trail",
|
|
108
|
+
"aria-live": "off",
|
|
109
|
+
"hidden": "${state.hasDocument ? null : ''}"
|
|
110
|
+
}
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"$prototype": "Array",
|
|
114
|
+
"items": { "$ref": "#/state/trailing" },
|
|
47
115
|
"key": { "$ref": "$map/item/id" },
|
|
48
116
|
"map": {
|
|
49
117
|
"tagName": "div",
|