@jxsuite/studio 5.0.0 → 5.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{cf-account-picker-fyf63pmy.js → cf-account-picker-h4dab9bq.js} +10 -10
- package/dist/chunks/{cf-settings-71bv5zn9.js → cf-settings-adg74qsk.js} +4 -4
- package/dist/chunks/components-5y78e05d.js +20 -0
- package/dist/chunks/content-source-sgg1sv6n.js +46 -0
- package/dist/chunks/{convert-to-repeater-d0cgnb6d.js → convert-to-repeater-mf1cxgfn.js} +25 -25
- package/dist/chunks/entry-commands-w9qsxa6q.js +42 -0
- package/dist/chunks/{extension-sections-fy7q4fe9.js → extension-sections-c6zwzbre.js} +27 -27
- package/dist/chunks/file-ops-vrpq1jjk.js +47 -0
- package/dist/chunks/{files-ef8fgs3w.js → files-msaf95y6.js} +33 -32
- package/dist/chunks/{format-host-3c33nwr8.js → format-host-f64fnesp.js} +2 -2
- package/dist/chunks/{fs-events-13tj6sex.js → fs-events-3y6y0nrm.js} +6 -6
- package/dist/chunks/git-panel-bv5e22j0.js +50 -0
- package/dist/chunks/grid-view-1p6hsyjx.css +8406 -0
- package/dist/chunks/grid-view-paj67nr5.js +15322 -0
- package/dist/chunks/{iframe-host-jgesd924.js → iframe-host-dh5np8vk.js} +14 -14
- package/dist/chunks/{layers-1nq5evsh.js → layers-1vcfdbet.js} +7 -6
- package/dist/chunks/layers-panel-fksbdg4q.js +40 -0
- package/dist/chunks/{media-picker-2qbetq73.js → media-picker-p49nhqhs.js} +14 -14
- package/dist/chunks/menu-qht48vnc.js +15 -0
- package/dist/chunks/{monaco-buffer-bhy3hb6m.js → monaco-buffer-pykwbm92.js} +3 -3
- package/dist/chunks/{notify-628t0anh.js → notify-42gk8ha1.js} +2 -2
- package/dist/chunks/{parse-0zx14y15.js → parse-reg9eevt.js} +2 -2
- package/dist/chunks/publish-panel-vz23wwmg.js +27 -0
- package/dist/chunks/quick-search-e9rp74m8.js +46 -0
- package/dist/chunks/{references-n553f0e1.js → references-h69xp9zz.js} +4 -4
- package/dist/chunks/right-panel-j97t2yvy.js +45 -0
- package/dist/chunks/{studio-18avnhjp.js → studio-01jeck2y.js} +36 -30
- package/dist/chunks/{studio-9xxz1q69.js → studio-14d9tq4d.js} +9 -9
- package/dist/chunks/{studio-xsykpvsh.js → studio-15f3kxqe.js} +19 -19
- package/dist/chunks/studio-1tbjfqv4.js +146 -0
- package/dist/chunks/{studio-79y5sz51.js → studio-28vs5k2y.js} +2 -2
- package/dist/chunks/{studio-3hxkd92t.js → studio-2mdbbc76.js} +10 -10
- package/dist/chunks/{studio-7r42c6ca.js → studio-3ntvq6cg.js} +5 -5
- package/dist/chunks/{studio-8jn5yhyn.js → studio-4c041r8y.js} +3 -3
- package/dist/chunks/{studio-qahxvnan.js → studio-4r14yzyy.js} +4 -4
- package/dist/chunks/{studio-arfpe389.js → studio-4xmjcrg3.js} +6 -6
- package/dist/chunks/{studio-5523bpzt.js → studio-5nz00bhh.js} +3 -3
- package/dist/chunks/{studio-x3rty6tr.js → studio-5t7ena5z.js} +8 -8
- package/dist/chunks/{studio-5rt7sqa0.js → studio-66arbpc2.js} +13 -19
- package/dist/chunks/{studio-fabxk6r9.js → studio-68fydsrj.js} +15 -15
- package/dist/chunks/{studio-tb3ev01j.js → studio-9j6sfeba.js} +6 -6
- package/dist/chunks/{studio-akbww0j5.js → studio-a1pswps3.js} +38 -38
- package/dist/chunks/{studio-6xa21ej9.js → studio-c04nzbby.js} +2 -2
- package/dist/chunks/{studio-4m0haseg.js → studio-c07s5ckd.js} +4 -4
- package/dist/chunks/{studio-57mf66w2.js → studio-ctm7bhx5.js} +14 -14
- package/dist/chunks/{studio-p1dw8wfw.js → studio-d8z5bajd.js} +14 -10
- package/dist/chunks/{studio-vz68yn9e.js → studio-en82c639.js} +6 -6
- package/dist/chunks/{studio-rkstz940.js → studio-etvx9s2g.js} +21 -12
- package/dist/chunks/{studio-az3zd49t.js → studio-ez11dmdh.js} +127 -37
- package/dist/chunks/{studio-sgdc5pfc.js → studio-hdc2jt3z.js} +4 -4
- package/dist/chunks/{studio-s6z853aq.js → studio-hhskq2mr.js} +24 -23
- package/dist/chunks/{studio-6ewqv390.js → studio-m1p9b6c3.js} +5 -5
- package/dist/chunks/{studio-25hkdrkw.js → studio-mpzwze9x.js} +12 -12
- package/dist/chunks/{studio-8qtrpzr3.js → studio-ncn9e189.js} +7 -7
- package/dist/chunks/{studio-81390n6f.js → studio-nq5yf5mp.js} +1 -1
- package/dist/chunks/{studio-5jy81t3s.js → studio-p6pmwkvh.js} +229 -24
- package/dist/chunks/{studio-3gxv60tn.js → studio-qa7fzxan.js} +4 -4
- package/dist/chunks/{studio-7xptrg0j.js → studio-sar8g54p.js} +8 -8
- package/dist/chunks/studio-t171hxhe.js +23 -0
- package/dist/chunks/{studio-em9nw8eh.js → studio-t3adrr56.js} +20 -17
- package/dist/chunks/{studio-hhvs4sdg.js → studio-vn5hske5.js} +10 -4
- package/dist/chunks/{studio-pm6hgy7r.js → studio-vt0tj32j.js} +29 -42
- package/dist/chunks/{studio-d1ja2x9r.js → studio-wjpgxywa.js} +4 -4
- package/dist/chunks/{studio-q3x06vmj.js → studio-wnsyffg1.js} +2 -2
- package/dist/chunks/{studio-rpyah2ew.js → studio-x10fp4tp.js} +64 -24
- package/dist/chunks/{studio-26d7myd1.js → studio-x72j58vw.js} +4 -4
- package/dist/chunks/{studio-cpvb2ed1.js → studio-y4f9fdge.js} +8 -8
- package/dist/chunks/{studio-erdatzvp.js → studio-ympe0n7a.js} +35 -6
- package/dist/chunks/{studio-y9zedyjn.js → studio-z2smx5ce.js} +2 -2
- package/dist/chunks/studio-zjjde71a.js +148 -0
- package/dist/chunks/{workspace-wrew8zk4.js → workspace-bnw54cha.js} +18 -10
- package/dist/iframe-entry.js +102 -11
- package/dist/studio.css +1 -2
- package/dist/studio.js +1113 -16062
- package/package.json +11 -11
- package/src/canvas/canvas-utils.ts +29 -2
- package/src/commands/command-args.ts +37 -2
- package/src/commands/registry.ts +18 -8
- package/src/commands/run-reported.ts +120 -0
- package/src/editor/shortcuts.ts +11 -23
- package/src/files/components.ts +39 -0
- package/src/files/files.ts +41 -17
- package/src/grid/grid-lazy.ts +59 -0
- package/src/grid/grid-open.ts +20 -3
- package/src/grid/grid-panel.ts +43 -9
- package/src/i18n/i18n-commands.ts +10 -0
- package/src/media/media-open.ts +14 -2
- package/src/packages/pull-package-sync.ts +5 -1
- package/src/panels/ai-panel.ts +5 -2
- package/src/panels/block-action-bar.ts +7 -2
- package/src/panels/i18n-panel.ts +8 -15
- package/src/panels/jump-bar.ts +3 -2
- package/src/panels/pane-context.ts +5 -4
- package/src/panels/pane-grid.ts +100 -10
- package/src/panels/problems-panel.ts +6 -2
- package/src/panels/quick-search.ts +6 -12
- package/src/panels/settings-menu.ts +5 -15
- package/src/panels/tab-drop.ts +220 -0
- package/src/panels/tab-strip.ts +238 -33
- package/src/services/ai-command-tools.ts +78 -8
- package/src/services/ai-models.ts +13 -0
- package/src/services/ai-project-tools.ts +8 -2
- package/src/services/ai-system-prompt.ts +4 -8
- package/src/services/ai-tools.ts +8 -69
- package/src/services/document-assistant.ts +9 -6
- package/src/studio.ts +24 -8
- package/src/surfaces/commandbar.json +35 -24
- package/src/surfaces/commandbar.ts +6 -5
- package/src/surfaces/pane-grid.json +35 -3
- package/src/surfaces/pane-grid.ts +26 -4
- package/src/surfaces/statusbar.ts +2 -1
- package/src/surfaces/tab-strip.json +16 -39
- package/src/surfaces/tab-strip.ts +76 -12
- package/src/tabs/project-config.ts +45 -11
- package/src/ui/ai-credentials-form.ts +12 -1
- package/src/ui/layers.ts +4 -1
- package/src/workspace/pane-derive.ts +7 -5
- package/src/workspace/session.ts +3 -3
- package/src/workspace/workspace.ts +220 -43
- package/styles/shell-frame.css +8 -0
- package/styles/shell-frame.json +4 -0
- package/dist/chunks/components-2w1f35qs.js +0 -18
- package/dist/chunks/content-source-3wqeas45.js +0 -46
- package/dist/chunks/entry-commands-d6g50j7s.js +0 -42
- package/dist/chunks/file-ops-3btj6st0.js +0 -47
- package/dist/chunks/git-panel-4wp2rn9b.js +0 -49
- package/dist/chunks/layers-panel-ar2gh90g.js +0 -40
- package/dist/chunks/menu-rf7n72mf.js +0 -14
- package/dist/chunks/publish-panel-98f7sr3g.js +0 -27
- package/dist/chunks/quick-search-srzz83k2.js +0 -45
- package/dist/chunks/right-panel-rrgx2dn3.js +0 -45
- package/dist/chunks/studio-d055c37e.js +0 -62
package/src/grid/grid-open.ts
CHANGED
|
@@ -30,11 +30,25 @@ import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
|
30
30
|
/** Placeholder document for grid tabs — the grid never reads it; save routes to the controller. */
|
|
31
31
|
const GRID_STUB_DOCUMENT = { children: [], tagName: "div" };
|
|
32
32
|
|
|
33
|
-
/**
|
|
34
|
-
|
|
33
|
+
/**
|
|
34
|
+
* Open (or activate) a `.csv` file as a grid tab.
|
|
35
|
+
*
|
|
36
|
+
* The options are `openFileInTab`'s own, passed straight through: `paneId` says which pane the tab
|
|
37
|
+
* lands in (defaulting to the focused one), `focus: false` browses without moving the keyboard, and
|
|
38
|
+
* `preview` opens a disposable tab. An existing tab is activated with the caller's `focus` — the
|
|
39
|
+
* same rule the document path follows.
|
|
40
|
+
*
|
|
41
|
+
* @param {string} path - Project-relative path of the `.csv`
|
|
42
|
+
* @param {{ paneId?: string; focus?: boolean; preview?: boolean }} [opts]
|
|
43
|
+
* @returns {Promise<Tab>}
|
|
44
|
+
*/
|
|
45
|
+
export async function openCsvGridTab(
|
|
46
|
+
path: string,
|
|
47
|
+
opts: { paneId?: string; focus?: boolean; preview?: boolean } = {},
|
|
48
|
+
): Promise<Tab> {
|
|
35
49
|
const existing = workspace.tabs.get(path);
|
|
36
50
|
if (existing) {
|
|
37
|
-
activateTab(path);
|
|
51
|
+
activateTab(path, { focus: opts.focus !== false });
|
|
38
52
|
return existing;
|
|
39
53
|
}
|
|
40
54
|
|
|
@@ -52,6 +66,9 @@ export async function openCsvGridTab(path: string): Promise<Tab> {
|
|
|
52
66
|
documentPath: path,
|
|
53
67
|
id: path,
|
|
54
68
|
sourceFormat: formatForPath(path)?.name ?? null,
|
|
69
|
+
...(opts.paneId !== undefined && { paneId: opts.paneId }),
|
|
70
|
+
...(opts.preview === true && { preview: true }),
|
|
71
|
+
...(opts.focus === false && { focus: false }),
|
|
55
72
|
});
|
|
56
73
|
const controller = createGridController(tab, source);
|
|
57
74
|
void controller.load();
|
package/src/grid/grid-panel.ts
CHANGED
|
@@ -39,7 +39,7 @@ import { rectOf } from "../utils/geometry";
|
|
|
39
39
|
import { activeTab, workspace } from "../workspace/workspace";
|
|
40
40
|
import { createGridController, getGridController } from "./grid-controller";
|
|
41
41
|
import { createCsvFileSource } from "./sources/csv-file-source";
|
|
42
|
-
import {
|
|
42
|
+
import { loadedGridEngine, loadGridEngine } from "./grid-lazy";
|
|
43
43
|
import { parseGridTabId } from "./grid-source";
|
|
44
44
|
import { mountGridPanelSurface } from "../surfaces/grid-panel";
|
|
45
45
|
import { openGridViewsSurface } from "../surfaces/grid-views";
|
|
@@ -473,12 +473,45 @@ export function renderGridMode(surface: CanvasSurface, tab: Tab) {
|
|
|
473
473
|
const engine = controller;
|
|
474
474
|
let hostEl: HTMLElement | null = null;
|
|
475
475
|
|
|
476
|
+
/**
|
|
477
|
+
* (Re)build the Tabulator engine over `host`, destroying whatever view is live first.
|
|
478
|
+
*
|
|
479
|
+
* Synchronous when `tabulator-tables` is already loaded — true for every mount after the
|
|
480
|
+
* session's first, so every existing caller keeps seeing `panel.view` set before this returns. On
|
|
481
|
+
* a cold first load it goes through `loadGridEngine()` instead (see `grid-lazy.ts`) and `onReady`
|
|
482
|
+
* — and, symmetrically with the `ready` handling below, `panel.bump()` — run once the import
|
|
483
|
+
* resolves, guarded against the pane having moved on in the meantime.
|
|
484
|
+
*/
|
|
485
|
+
function rebuildView(onReady?: (view: GridView) => void) {
|
|
486
|
+
panel.view?.destroy();
|
|
487
|
+
panel.view = null;
|
|
488
|
+
if (!hostEl) {
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
const requestedHost = hostEl;
|
|
492
|
+
const loaded = loadedGridEngine();
|
|
493
|
+
if (loaded) {
|
|
494
|
+
const view = loaded.createGridView(requestedHost, engine);
|
|
495
|
+
panel.view = view;
|
|
496
|
+
onReady?.(view);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
void loadGridEngine().then(({ createGridView }) => {
|
|
500
|
+
if (activeIn(paneId) !== panel || hostEl !== requestedHost || panel.view) {
|
|
501
|
+
return;
|
|
502
|
+
}
|
|
503
|
+
const view = createGridView(requestedHost, engine);
|
|
504
|
+
panel.view = view;
|
|
505
|
+
onReady?.(view);
|
|
506
|
+
panel.bump();
|
|
507
|
+
});
|
|
508
|
+
}
|
|
509
|
+
|
|
476
510
|
const panel: ActiveGridPanel = {
|
|
477
511
|
applyLayout(layout) {
|
|
478
512
|
void engine.setSort(layout?.sort ?? null);
|
|
479
513
|
engine.setGrouping(layout?.groupBy ?? null);
|
|
480
|
-
|
|
481
|
-
panel.view?.setSearch(layout?.filter ?? "");
|
|
514
|
+
rebuildView((view) => view.setSearch(layout?.filter ?? ""));
|
|
482
515
|
panel.bump();
|
|
483
516
|
},
|
|
484
517
|
bump() {
|
|
@@ -486,8 +519,7 @@ export function renderGridMode(surface: CanvasSurface, tab: Tab) {
|
|
|
486
519
|
},
|
|
487
520
|
paneId,
|
|
488
521
|
remount() {
|
|
489
|
-
|
|
490
|
-
panel.view = hostEl ? createGridView(hostEl, engine) : null;
|
|
522
|
+
rebuildView();
|
|
491
523
|
},
|
|
492
524
|
replace: null,
|
|
493
525
|
scope,
|
|
@@ -576,14 +608,16 @@ export function renderGridMode(surface: CanvasSurface, tab: Tab) {
|
|
|
576
608
|
|
|
577
609
|
// Create the engine once the columns exist and the host div is in the DOM.
|
|
578
610
|
if (!panel.view && !engine.state.loading && engine.state.columns.length > 0 && hostEl) {
|
|
579
|
-
|
|
580
|
-
|
|
611
|
+
rebuildView((view) => {
|
|
612
|
+
if (restored) {
|
|
613
|
+
return;
|
|
614
|
+
}
|
|
581
615
|
restored = true;
|
|
582
616
|
const layout = loadGridLayout(engine.source.id);
|
|
583
617
|
void engine.setSort(layout?.sort ?? null);
|
|
584
618
|
engine.setGrouping(layout?.groupBy ?? null);
|
|
585
|
-
|
|
586
|
-
}
|
|
619
|
+
view.setSearch(layout?.filter ?? "");
|
|
620
|
+
});
|
|
587
621
|
}
|
|
588
622
|
});
|
|
589
623
|
});
|
|
@@ -195,6 +195,14 @@ export function i18nCommands(): AnyCommand[] {
|
|
|
195
195
|
menus: ["context/tab", "palette"],
|
|
196
196
|
group: "2_navigate",
|
|
197
197
|
requires: "a document open in a project that declares more than one language",
|
|
198
|
+
/* `ctx.document.open` stays in the gate although `path` no longer needs a document open
|
|
199
|
+
(issue 333). `registry.run` evaluates `when` BEFORE `run` and refuses with
|
|
200
|
+
`CommandUnavailableError`, so relaxing it is the only way `{ locale, path }` could run with
|
|
201
|
+
no document open — and `when` reads the context, not the arguments, so the same relaxation
|
|
202
|
+
would light the palette row too, where the record runs with no `path` and would then throw
|
|
203
|
+
`addressedDocument`'s "needs a document open" out of a click instead of standing disabled
|
|
204
|
+
with its `requires` sentence. The palette's availability is the person's contract; an
|
|
205
|
+
argument-only gate needs a shape the registry does not have. Same on `createTranslation`. */
|
|
198
206
|
when: (ctx) => ctx.project.isMultilingual && ctx.document.open,
|
|
199
207
|
/* No `aiTool`, by §12.4's first deletion rule: this opens a surface for a person, and the
|
|
200
208
|
model has `open_document` for the file it names. */
|
|
@@ -247,6 +255,8 @@ export function i18nCommands(): AnyCommand[] {
|
|
|
247
255
|
menus: ["palette"],
|
|
248
256
|
group: "2_navigate",
|
|
249
257
|
requires: "a document open in a project that declares more than one language",
|
|
258
|
+
// `document.open` stays for the reason `i18n.openTranslation` gives: the gate runs before
|
|
259
|
+
// `run`, and it cannot see `path`.
|
|
250
260
|
when: (ctx) => ctx.project.isMultilingual && ctx.document.open,
|
|
251
261
|
/* The document history cannot hold this: the change is a file that did not exist, and
|
|
252
262
|
`undo: "project"` would claim `project.json` moved, which it did not. */
|
package/src/media/media-open.ts
CHANGED
|
@@ -39,13 +39,22 @@ export function mediaTabModes(path: string): string[] {
|
|
|
39
39
|
/**
|
|
40
40
|
* Open (or activate) a media file's viewer tab.
|
|
41
41
|
*
|
|
42
|
+
* The options are `openFileInTab`'s own, passed straight through: `paneId` says which pane the tab
|
|
43
|
+
* lands in (defaulting to the focused one), `focus: false` browses without moving the keyboard, and
|
|
44
|
+
* `preview` opens a disposable tab. An existing tab is activated with the caller's `focus` — the
|
|
45
|
+
* same rule the document path follows.
|
|
46
|
+
*
|
|
42
47
|
* @param {string} path - Project-relative path of the file
|
|
48
|
+
* @param {{ paneId?: string; focus?: boolean; preview?: boolean }} [opts]
|
|
43
49
|
* @returns {Tab}
|
|
44
50
|
*/
|
|
45
|
-
export function openMediaTab(
|
|
51
|
+
export function openMediaTab(
|
|
52
|
+
path: string,
|
|
53
|
+
opts: { paneId?: string; focus?: boolean; preview?: boolean } = {},
|
|
54
|
+
): Tab {
|
|
46
55
|
const existing = workspace.tabs.get(path);
|
|
47
56
|
if (existing) {
|
|
48
|
-
activateTab(path);
|
|
57
|
+
activateTab(path, { focus: opts.focus !== false });
|
|
49
58
|
return existing;
|
|
50
59
|
}
|
|
51
60
|
return openTab({
|
|
@@ -54,5 +63,8 @@ export function openMediaTab(path: string): Tab {
|
|
|
54
63
|
documentPath: path,
|
|
55
64
|
id: path,
|
|
56
65
|
sourceFormat: null,
|
|
66
|
+
...(opts.paneId !== undefined && { paneId: opts.paneId }),
|
|
67
|
+
...(opts.preview === true && { preview: true }),
|
|
68
|
+
...(opts.focus === false && { focus: false }),
|
|
57
69
|
});
|
|
58
70
|
}
|
|
@@ -19,7 +19,11 @@ import type { GitStatusResult } from "../types";
|
|
|
19
19
|
|
|
20
20
|
const PKG_PATHS = ["package.json", "bun.lock", "bun.lockb"];
|
|
21
21
|
|
|
22
|
-
/**
|
|
22
|
+
/**
|
|
23
|
+
* Untracked markers across backends. Every backend says `U` now — the desktop used to pass
|
|
24
|
+
* porcelain v1's raw `??` through, and this set is what kept package sync working while it did.
|
|
25
|
+
* `??` stays accepted so a Studio bundle ahead of its desktop host keeps working.
|
|
26
|
+
*/
|
|
23
27
|
const UNTRACKED_STATUSES = new Set(["??", "U"]);
|
|
24
28
|
|
|
25
29
|
/** Above this many dirty files, skip the per-file upstream comparison and leave the error as-is. */
|
package/src/panels/ai-panel.ts
CHANGED
|
@@ -44,6 +44,7 @@ import { onCredentialsChanged } from "../settings/preferences-accounts";
|
|
|
44
44
|
import { setDockCollapsed } from "../shell";
|
|
45
45
|
import { hasSelection } from "../commands/context";
|
|
46
46
|
import { activeRegistry } from "../commands/active-registry";
|
|
47
|
+
import { runReported } from "../commands/run-reported";
|
|
47
48
|
import { clearMarkdownCache } from "./ai-chat/chat-markdown";
|
|
48
49
|
import {
|
|
49
50
|
formatErrorAdvice,
|
|
@@ -158,12 +159,14 @@ export function renderAiPanel(): void {
|
|
|
158
159
|
* Re-asked at click time, not trusted from the projection: state moves between the two, and
|
|
159
160
|
* `registry.run` THROWS on a refusal. Same bargain `registry.handleKeyEvent` strikes for a chord
|
|
160
161
|
* bound to a disabled command — swallow it here rather than make every surface wrap a dispatch in
|
|
161
|
-
* try/catch.
|
|
162
|
+
* try/catch. What the gate lets through still runs through `commands/run-reported.ts`: a `run` body
|
|
163
|
+
* that rejects, or a schema the record has drifted from, is a sentence in Problems rather than an
|
|
164
|
+
* exception out of the click.
|
|
162
165
|
*/
|
|
163
166
|
function runCommand(id: string): void {
|
|
164
167
|
const registry = activeRegistry();
|
|
165
168
|
if (registry?.isEnabled(id)) {
|
|
166
|
-
void registry
|
|
169
|
+
void runReported(registry, id, undefined, "Assistant");
|
|
167
170
|
}
|
|
168
171
|
}
|
|
169
172
|
|
|
@@ -70,6 +70,7 @@ import { showSlashMenu } from "../editor/slash-menu";
|
|
|
70
70
|
import { getConvertTargets } from "../editor/convert-targets";
|
|
71
71
|
import { rectOf } from "../utils/geometry";
|
|
72
72
|
import { createCommandRegistry } from "../commands/registry";
|
|
73
|
+
import { runReported } from "../commands/run-reported";
|
|
73
74
|
import { editorKindForMode, makeContext } from "../commands/context";
|
|
74
75
|
import { defaultCommands, noopCommandDeps } from "../commands/defaults";
|
|
75
76
|
import { emptyBlockBarView, mountBlockActionBar } from "../surfaces/block-action-bar";
|
|
@@ -845,11 +846,15 @@ export function commandTooltip(registry: CommandRegistry, command: AnyCommand):
|
|
|
845
846
|
return chord ? `${command.title} (${chord})` : command.title;
|
|
846
847
|
}
|
|
847
848
|
|
|
848
|
-
/**
|
|
849
|
+
/**
|
|
850
|
+
* Run a command, swallowing the refusal a disabled control should never have produced — and
|
|
851
|
+
* reporting, through `commands/run-reported.ts`, the one an enabled control can still meet: a `run`
|
|
852
|
+
* body that throws or rejects.
|
|
853
|
+
*/
|
|
849
854
|
export function runCommand(registry: CommandRegistry, id: string, target?: JxPath | null): void {
|
|
850
855
|
const invoke = () => {
|
|
851
856
|
if (registry.isEnabled(id)) {
|
|
852
|
-
void registry
|
|
857
|
+
void runReported(registry, id, undefined, "Editor");
|
|
853
858
|
}
|
|
854
859
|
};
|
|
855
860
|
if (target) {
|
package/src/panels/i18n-panel.ts
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
*/
|
|
42
42
|
|
|
43
43
|
import { activeRegistry } from "../commands/active-registry";
|
|
44
|
+
import { runReported } from "../commands/run-reported";
|
|
44
45
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
45
46
|
import { getEffectiveLocales } from "../site-context";
|
|
46
47
|
import { getPlatform } from "../platform";
|
|
@@ -51,7 +52,6 @@ import {
|
|
|
51
52
|
translationPathFor,
|
|
52
53
|
} from "@jxsuite/schema/locale";
|
|
53
54
|
import { mountI18nSurface } from "../surfaces/panel-i18n";
|
|
54
|
-
import { notify } from "../services/notify";
|
|
55
55
|
import { nothing } from "lit-html";
|
|
56
56
|
import { projectState } from "../store";
|
|
57
57
|
import { registerPanel } from "./panel-registry";
|
|
@@ -386,26 +386,19 @@ function cellTitle(cell: ParityCell, locale: string, refusal: string | undefined
|
|
|
386
386
|
* already there, and a click that produced nothing and printed nothing would leave the author
|
|
387
387
|
* looking at a grid that disagrees with the disk.
|
|
388
388
|
*
|
|
389
|
-
* Both shapes,
|
|
390
|
-
*
|
|
391
|
-
*
|
|
392
|
-
*
|
|
393
|
-
*
|
|
394
|
-
*
|
|
389
|
+
* Both shapes, through `commands/run-reported.ts`: `registry.run` throws SYNCHRONOUSLY when the
|
|
390
|
+
* record refuses the arguments — it coerces `{ locale, path }` against the record's schema before
|
|
391
|
+
* `run` is entered — and a `Promise.resolve(...)` around a call that has already thrown catches
|
|
392
|
+
* nothing. That refusal was every cell click for as long as the records did not declare `path`; the
|
|
393
|
+
* report is what makes the next such drift a sentence in the Problems panel rather than an
|
|
394
|
+
* exception out of a click.
|
|
395
395
|
*/
|
|
396
396
|
function runByName(id: string, args: Record<string, unknown> = {}): void {
|
|
397
397
|
const registry = activeRegistry();
|
|
398
398
|
if (!registry?.get(id)) {
|
|
399
399
|
return;
|
|
400
400
|
}
|
|
401
|
-
|
|
402
|
-
notify("error", errorMessage(error), { source: "Languages" });
|
|
403
|
-
};
|
|
404
|
-
try {
|
|
405
|
-
void Promise.resolve(registry.run(id, args)).catch(report);
|
|
406
|
-
} catch (error) {
|
|
407
|
-
report(error);
|
|
408
|
-
}
|
|
401
|
+
void runReported(registry, id, args, "Languages");
|
|
409
402
|
}
|
|
410
403
|
|
|
411
404
|
/**
|
package/src/panels/jump-bar.ts
CHANGED
|
@@ -58,6 +58,7 @@ import { derivationOfPane, tabOfPane } from "../canvas/canvas-surface";
|
|
|
58
58
|
import { paneRegion } from "../ui/regions";
|
|
59
59
|
import { primarySelection } from "../tabs/selection";
|
|
60
60
|
import { activeRegistry } from "../commands/active-registry";
|
|
61
|
+
import { runReported } from "../commands/run-reported";
|
|
61
62
|
import { openMenu } from "../surfaces/menu";
|
|
62
63
|
import { mountJumpBarSurface } from "../surfaces/jump-bar";
|
|
63
64
|
import { PANE_SELECTOR } from "../surfaces/pane-grid";
|
|
@@ -427,7 +428,7 @@ function openChoices(segment: JumpSegment, anchor: HTMLElement | null): void {
|
|
|
427
428
|
dividerAbove: false,
|
|
428
429
|
id: String(i),
|
|
429
430
|
run: () => {
|
|
430
|
-
void registry
|
|
431
|
+
void runReported(registry, choice.command, choice.args, "Jump Bar");
|
|
431
432
|
},
|
|
432
433
|
title: choice.label,
|
|
433
434
|
}));
|
|
@@ -544,7 +545,7 @@ export function attachJumpBarHost(paneId: string, host: HTMLElement | null): voi
|
|
|
544
545
|
const segment = _bars.get(paneId)?.segments.get(key);
|
|
545
546
|
const registry = activeRegistry();
|
|
546
547
|
if (segment?.command && registry) {
|
|
547
|
-
void registry
|
|
548
|
+
void runReported(registry, segment.command, segment.args, "Jump Bar");
|
|
548
549
|
}
|
|
549
550
|
},
|
|
550
551
|
}),
|
|
@@ -500,10 +500,11 @@ export interface PresetRow {
|
|
|
500
500
|
*
|
|
501
501
|
* The previous round made the row's ANSWER a pure function of the pane and left its ACTION
|
|
502
502
|
* resolving the focus: every one of these three commands takes the focused pane as its subject
|
|
503
|
-
* (`pane.derive`'s `activePane()`/`
|
|
504
|
-
* row read off the secondary pane's menu derived from the
|
|
505
|
-
* by keyboard, which is why it survived a browser pass:
|
|
506
|
-
* POINTERDOWN, and a keyboard activation of a menu item
|
|
503
|
+
* (`pane.derive`'s `activePane()`/`paneBeside(source.id)`, `pane.unsplit`'s
|
|
504
|
+
* `workspace.activePaneId`), so a row read off the secondary pane's menu derived from the
|
|
505
|
+
* primary. Reachable by keyboard and only by keyboard, which is why it survived a browser pass:
|
|
506
|
+
* `panels/pane-grid.ts` focuses a pane on POINTERDOWN, and a keyboard activation of a menu item
|
|
507
|
+
* fires `click` alone.
|
|
507
508
|
*
|
|
508
509
|
* Carried on the row rather than passed as a command argument. A pane id in `args` would make
|
|
509
510
|
* "which pane" a public input of `pane.derive` — a third property on a record the palette already
|
package/src/panels/pane-grid.ts
CHANGED
|
@@ -11,20 +11,22 @@
|
|
|
11
11
|
* that scaffolding was standing in for, and the handover is deleted with it.
|
|
12
12
|
*
|
|
13
13
|
* **The document owns the frame; this module owns the decisions.** `surfaces/pane-grid.json` is the
|
|
14
|
-
* cells, the
|
|
14
|
+
* cells, the five boxes inside each one, the splitter between two of them and every rule that lays
|
|
15
15
|
* them out; `surfaces/pane-grid.ts` is the mount. What is left here is the flow: which panes there
|
|
16
16
|
* are, what a cell's stage is furnished with, in what ORDER a departing cell is taken apart, and
|
|
17
17
|
* what the grid's own tracks are. Everything a cell CONTAINS still arrives through the module that
|
|
18
18
|
* owns it — `canvas/canvas-render.ts` is the render root of the stage and this document puts
|
|
19
19
|
* nothing inside it, `panels/jump-bar.ts` and `panels/pane-context.ts` are handed the jump and
|
|
20
|
-
* chrome boxes,
|
|
20
|
+
* chrome boxes, `panels/tab-strip.ts` is handed the strip, and this module makes the fifth — the
|
|
21
|
+
* right-edge drop zone — a pragmatic target itself.
|
|
21
22
|
*
|
|
22
23
|
* **Three properties survived the conversion, and each is structural rather than remembered:**
|
|
23
24
|
*
|
|
24
25
|
* 1. _A pane is complete before it is published._ The runtime builds a `$map` row inside its own
|
|
25
|
-
* effect scope and inserts it afterwards, so the
|
|
26
|
-
* record, the gestures, the two bars' mounts, the pane-focus listener
|
|
27
|
-
* cell is still detached. There is no frame in which a cell
|
|
26
|
+
* effect scope and inserts it afterwards, so the five `cellPart` calls below — the surface
|
|
27
|
+
* record, the gestures, the two bars' mounts, the pane-focus listener, the drop zone's own
|
|
28
|
+
* registration — all happen while the cell is still detached. There is no frame in which a cell
|
|
29
|
+
* exists with no stage inside it.
|
|
28
30
|
* 2. _A pane's node is never re-parented._ The repeater is keyed on the pane id and the runtime's
|
|
29
31
|
* forward-cursor pass only moves rows that are out of place. `workspace.panes[0]` is always the
|
|
30
32
|
* primary and `MAX_PANES` is 2, so no row ever moves — which matters because re-parenting is not
|
|
@@ -54,6 +56,12 @@
|
|
|
54
56
|
*/
|
|
55
57
|
|
|
56
58
|
import { effect, effectScope } from "../reactivity";
|
|
59
|
+
import {
|
|
60
|
+
dropTargetForElements,
|
|
61
|
+
monitorForElements,
|
|
62
|
+
} from "@atlaskit/pragmatic-drag-and-drop/element/adapter";
|
|
63
|
+
import { isTabDropSource } from "./tab-drop";
|
|
64
|
+
import { rectOf } from "../utils/geometry";
|
|
57
65
|
import {
|
|
58
66
|
DEFAULT_PANE_SPLIT,
|
|
59
67
|
PANE_SPLIT_MAX,
|
|
@@ -74,13 +82,13 @@ import { scheduleCanvasRender } from "../canvas/canvas-render";
|
|
|
74
82
|
import { paneRegion, paneStripRegion } from "../ui/regions";
|
|
75
83
|
import { attachJumpBarHost } from "./jump-bar";
|
|
76
84
|
import { attachPaneChromeHost } from "./pane-context";
|
|
77
|
-
import { focusPane, workspace } from "../workspace/workspace";
|
|
85
|
+
import { MAX_PANES, focusPane, workspace } from "../workspace/workspace";
|
|
78
86
|
import { mountPaneGridSurface } from "../surfaces/pane-grid";
|
|
79
87
|
import type { EffectScope } from "@vue/reactivity";
|
|
80
88
|
import type { CanvasSurface } from "../canvas/canvas-surface";
|
|
81
89
|
import type { PaneCellPart, PaneGridRow, PaneGridSurface } from "../surfaces/pane-grid";
|
|
82
90
|
|
|
83
|
-
/** One drawn pane: its root and the
|
|
91
|
+
/** One drawn pane: its root and the five surfaces inside it. */
|
|
84
92
|
export interface PaneCell {
|
|
85
93
|
paneId: string;
|
|
86
94
|
root: HTMLElement;
|
|
@@ -88,13 +96,16 @@ export interface PaneCell {
|
|
|
88
96
|
jump: HTMLElement;
|
|
89
97
|
chrome: HTMLElement;
|
|
90
98
|
stage: HTMLElement;
|
|
99
|
+
dropZone: HTMLElement;
|
|
91
100
|
surface: CanvasSurface;
|
|
92
101
|
}
|
|
93
102
|
|
|
94
|
-
/** A cell's record, plus the
|
|
103
|
+
/** A cell's record, plus the disposers its stage gestures and its drop zone live behind. */
|
|
95
104
|
interface CellState extends PaneCell {
|
|
96
105
|
/** Stage-gesture disposer, live between the stage's creation and the cell's disposal. */
|
|
97
106
|
releaseGestures: (() => void) | null;
|
|
107
|
+
/** The drop zone's pragmatic registration, live between its creation and the cell's disposal. */
|
|
108
|
+
releaseDropZone: (() => void) | null;
|
|
98
109
|
}
|
|
99
110
|
|
|
100
111
|
const _cells = new Map<string, CellState>();
|
|
@@ -110,6 +121,13 @@ let _drawn: string[] = [];
|
|
|
110
121
|
|
|
111
122
|
let _scope: EffectScope | null = null;
|
|
112
123
|
|
|
124
|
+
/**
|
|
125
|
+
* The monitor that ARMS the right-edge zones — `_surface.drag`'s one writer. It never resolves a
|
|
126
|
+
* drop; `panels/tab-strip.ts`'s own monitor does that, from the same drop targets this one only
|
|
127
|
+
* watches.
|
|
128
|
+
*/
|
|
129
|
+
let _dragMonitor: (() => void) | null = null;
|
|
130
|
+
|
|
113
131
|
/** The cell a pane is drawn in, or null. Test-visible, and the bootstrap's handle on the primary. */
|
|
114
132
|
export function cellForPane(paneId: string): PaneCell | null {
|
|
115
133
|
return _cells.get(paneId) ?? null;
|
|
@@ -120,7 +138,7 @@ export function cellForPane(paneId: string): PaneCell | null {
|
|
|
120
138
|
*
|
|
121
139
|
* The mount is asynchronous — the runtime waits for the kit to be defined and renders one microtask
|
|
122
140
|
* after that — so `mountShell()` starting the grid is not the same event as the grid existing. The
|
|
123
|
-
* bootstrap reads the primary cell's
|
|
141
|
+
* bootstrap reads the primary cell's five boxes on the line after it, exactly as `mountShellTree()`
|
|
124
142
|
* made every caller await the frame for the same reason.
|
|
125
143
|
*/
|
|
126
144
|
export function paneGridReady(): Promise<void> {
|
|
@@ -142,8 +160,10 @@ function cellState(paneId: string): CellState {
|
|
|
142
160
|
}
|
|
143
161
|
const cell: CellState = {
|
|
144
162
|
chrome: null as unknown as HTMLElement,
|
|
163
|
+
dropZone: null as unknown as HTMLElement,
|
|
145
164
|
jump: null as unknown as HTMLElement,
|
|
146
165
|
paneId,
|
|
166
|
+
releaseDropZone: null,
|
|
147
167
|
releaseGestures: null,
|
|
148
168
|
root: null as unknown as HTMLElement,
|
|
149
169
|
stage: null as unknown as HTMLElement,
|
|
@@ -217,7 +237,52 @@ function attachStage(cell: CellState, stage: HTMLElement): void {
|
|
|
217
237
|
}
|
|
218
238
|
|
|
219
239
|
/**
|
|
220
|
-
*
|
|
240
|
+
* The RIGHT BAND of `paneId`'s cell, and only while it is legal to drop there: the grid is still
|
|
241
|
+
* under {@link MAX_PANES}, and `paneId` names the LAST pane — the one a second pane would sit
|
|
242
|
+
* beside. A grid of two panes has no legal edge at all, so the band answers refused everywhere on
|
|
243
|
+
* it.
|
|
244
|
+
*
|
|
245
|
+
* The band itself is `min(120px, half the cell's own width)`: wide enough to aim at, narrow enough
|
|
246
|
+
* that the rest of the stage keeps ordinary canvas gestures — a drag never reaches this at all
|
|
247
|
+
* unless `canDrop` already accepted it, so the band only ever competes with itself.
|
|
248
|
+
*/
|
|
249
|
+
function edgeData(
|
|
250
|
+
paneId: string,
|
|
251
|
+
input: { clientX: number },
|
|
252
|
+
element: HTMLElement,
|
|
253
|
+
): Record<string, unknown> {
|
|
254
|
+
if (workspace.panes.length >= MAX_PANES || workspace.panes.at(-1)?.id !== paneId) {
|
|
255
|
+
return { type: "pane-edge-refused" };
|
|
256
|
+
}
|
|
257
|
+
const rect = rectOf(element);
|
|
258
|
+
const band = Math.min(120, rect.width / 2);
|
|
259
|
+
if (input.clientX < rect.right - band) {
|
|
260
|
+
return { type: "pane-edge-refused" };
|
|
261
|
+
}
|
|
262
|
+
return { paneId, type: "pane-edge" };
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* Make a cell's drop zone a pragmatic target. `canDrop` alone is not enough to keep the zone out of
|
|
267
|
+
* a two-pane grid's way — {@link edgeData} refuses in the DATA, the same "never fall through" rule
|
|
268
|
+
* `files.ts`'s row targets use, because the zone sits ABOVE the stage (`z-index: 4`) and a refusal
|
|
269
|
+
* that let the drop bubble past it would still have kept the pointer from ever reaching the iframe
|
|
270
|
+
* underneath.
|
|
271
|
+
*/
|
|
272
|
+
function attachDropZone(paneId: string, element: HTMLElement): () => void {
|
|
273
|
+
return dropTargetForElements({
|
|
274
|
+
canDrop({ source }) {
|
|
275
|
+
return isTabDropSource(source.data);
|
|
276
|
+
},
|
|
277
|
+
element,
|
|
278
|
+
getData({ input }) {
|
|
279
|
+
return edgeData(paneId, input, element);
|
|
280
|
+
},
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* One of a cell's six boxes has been created. Fill the record in, and wire what belongs to it.
|
|
221
286
|
*
|
|
222
287
|
* The two bars are HANDED their host rather than resolving a region, the same way
|
|
223
288
|
* `panels/frontmatter-panel.ts` is handed the stage. They cannot resolve one the way the tab strip
|
|
@@ -248,6 +313,11 @@ function cellPart(paneId: string, part: PaneCellPart, element: HTMLElement): voi
|
|
|
248
313
|
attachPaneChromeHost(paneId, element);
|
|
249
314
|
return;
|
|
250
315
|
}
|
|
316
|
+
if (part === "dropZone") {
|
|
317
|
+
cell.dropZone = element;
|
|
318
|
+
cell.releaseDropZone = attachDropZone(paneId, element);
|
|
319
|
+
return;
|
|
320
|
+
}
|
|
251
321
|
attachStage(cell, element);
|
|
252
322
|
}
|
|
253
323
|
|
|
@@ -272,6 +342,8 @@ function cellPart(paneId: string, part: PaneCellPart, element: HTMLElement): voi
|
|
|
272
342
|
* the record the hosts resolve through.
|
|
273
343
|
*/
|
|
274
344
|
function disposeCell(cell: CellState): void {
|
|
345
|
+
cell.releaseDropZone?.();
|
|
346
|
+
cell.releaseDropZone = null;
|
|
275
347
|
attachJumpBarHost(cell.paneId, null);
|
|
276
348
|
attachPaneChromeHost(cell.paneId, null);
|
|
277
349
|
cell.releaseGestures?.();
|
|
@@ -396,6 +468,22 @@ export function mount(): void {
|
|
|
396
468
|
{ cellPart, move: setPaneSplit, settle: persistDocks },
|
|
397
469
|
);
|
|
398
470
|
_ready = _surface.ready;
|
|
471
|
+
_dragMonitor = monitorForElements({
|
|
472
|
+
canMonitor({ source }) {
|
|
473
|
+
return isTabDropSource(source.data);
|
|
474
|
+
},
|
|
475
|
+
onDrag({ location }) {
|
|
476
|
+
const [target] = location.current.dropTargets;
|
|
477
|
+
const edgePane = target?.data.type === "pane-edge" ? (target.data.paneId as string) : "";
|
|
478
|
+
_surface?.drag({ armed: true, edgePane });
|
|
479
|
+
},
|
|
480
|
+
onDragStart() {
|
|
481
|
+
_surface?.drag({ armed: true, edgePane: "" });
|
|
482
|
+
},
|
|
483
|
+
onDrop() {
|
|
484
|
+
_surface?.drag({ armed: false, edgePane: "" });
|
|
485
|
+
},
|
|
486
|
+
});
|
|
399
487
|
_scope = effectScope();
|
|
400
488
|
_scope.run(() => {
|
|
401
489
|
effect(() => {
|
|
@@ -412,6 +500,8 @@ export function mount(): void {
|
|
|
412
500
|
export function unmount(): void {
|
|
413
501
|
_scope?.stop();
|
|
414
502
|
_scope = null;
|
|
503
|
+
_dragMonitor?.();
|
|
504
|
+
_dragMonitor = null;
|
|
415
505
|
/* Every cell is taken apart by the same ordered teardown a departing one gets, and BEFORE the
|
|
416
506
|
document goes: doing it afterwards would hand `releaseCanvasHosts` a stage whose frames the
|
|
417
507
|
runtime had already dropped. */
|
|
@@ -58,6 +58,7 @@
|
|
|
58
58
|
import { nothing } from "lit-html";
|
|
59
59
|
import { effect, effectScope } from "../reactivity";
|
|
60
60
|
import { activeRegistry } from "../commands/active-registry";
|
|
61
|
+
import { runReported } from "../commands/run-reported";
|
|
61
62
|
import { clearProblems, dismiss, problemCount, problems } from "../services/notify";
|
|
62
63
|
import { mountProblemsSurface } from "../surfaces/panel-problems";
|
|
63
64
|
import { registerPanel } from "./panel-registry";
|
|
@@ -184,14 +185,17 @@ const ACTIONS: ProblemsActions = {
|
|
|
184
185
|
openProblemPath(path);
|
|
185
186
|
},
|
|
186
187
|
/* By id, because a document can only hand back a value: the record and the registry are both
|
|
187
|
-
looked up at the moment of the click, which is also the moment the gate was last checked.
|
|
188
|
+
looked up at the moment of the click, which is also the moment the gate was last checked.
|
|
189
|
+
The action's `actionArgs` were written by whoever filed the problem, against a schema that
|
|
190
|
+
may have moved since, so the run goes through `commands/run-reported.ts`: a refusal is a new
|
|
191
|
+
row in this same list, keyed by the command, rather than an exception out of the button. */
|
|
188
192
|
runAction: (id) => {
|
|
189
193
|
const record = problems.find((candidate) => candidate.id === id);
|
|
190
194
|
const registry = activeRegistry();
|
|
191
195
|
if (record?.action === undefined || !registry) {
|
|
192
196
|
return;
|
|
193
197
|
}
|
|
194
|
-
void registry
|
|
198
|
+
void runReported(registry, record.action, record.actionArgs, "Problems");
|
|
195
199
|
},
|
|
196
200
|
};
|
|
197
201
|
|
|
@@ -41,6 +41,7 @@ import { reactive } from "../reactivity";
|
|
|
41
41
|
import paletteDoc from "../surfaces/palette.json";
|
|
42
42
|
import { activeTab } from "../workspace/workspace";
|
|
43
43
|
import { activeRegistry } from "../commands/active-registry";
|
|
44
|
+
import { runActiveReported, runReported } from "../commands/run-reported";
|
|
44
45
|
import type { PaletteMode } from "../commands/defaults";
|
|
45
46
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
46
47
|
import type { JxDocument, JxMutableNode } from "@jxsuite/schema/types";
|
|
@@ -671,17 +672,11 @@ function runCommand(command: AnyCommand, args?: Record<string, unknown>) {
|
|
|
671
672
|
}
|
|
672
673
|
trackRecentCommand(command.id);
|
|
673
674
|
closeQuickSearch();
|
|
674
|
-
|
|
675
|
-
console.error(`palette: command "${command.id}" failed`, error);
|
|
676
|
-
};
|
|
677
|
-
// Both shapes, deliberately: `run` may throw synchronously (a coercion refusal from
|
|
675
|
+
// Both shapes, through the one helper: `run` may throw synchronously (a coercion refusal from
|
|
678
676
|
// `command-args.ts` does) or reject later. A palette that let either escape would take the
|
|
679
|
-
// Keydown listener down with it, and the overlay is already closed by then
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
} catch (error) {
|
|
683
|
-
report(error);
|
|
684
|
-
}
|
|
677
|
+
// Keydown listener down with it, and the overlay is already closed by then — and a refusal that
|
|
678
|
+
// Went to the console, as this one did, was read by nobody. Problems is where it is read.
|
|
679
|
+
void runReported(registry, command.id, args, "Palette");
|
|
685
680
|
}
|
|
686
681
|
|
|
687
682
|
function selectRow(row: PaletteRow) {
|
|
@@ -702,9 +697,8 @@ function selectRow(row: PaletteRow) {
|
|
|
702
697
|
return;
|
|
703
698
|
}
|
|
704
699
|
case "node": {
|
|
705
|
-
const registry = activeRegistry();
|
|
706
700
|
closeQuickSearch();
|
|
707
|
-
void
|
|
701
|
+
void runActiveReported("selection.set", { path: row.path }, "Palette");
|
|
708
702
|
return;
|
|
709
703
|
}
|
|
710
704
|
case "arg": {
|