@jxsuite/studio 10.1.0 → 10.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/{2020-mkb0qa6p.js → 2020-bx702wqa.js} +3 -3
- package/dist/chunks/adapter-pp011m5x.js +4 -0
- package/dist/chunks/add-new-flow-ecqmzz76.js +4 -0
- package/dist/chunks/cf-account-picker-c07znkqt.js +4 -0
- package/dist/chunks/cf-settings-0v2bmqy0.js +4 -0
- package/dist/chunks/components-yn0dn2pq.js +4 -0
- package/dist/chunks/content-source-g0j41yy6.js +4 -0
- package/dist/chunks/{convert-to-repeater-f92ey3kp.js → convert-to-repeater-sbjk7tgn.js} +3 -3
- package/dist/chunks/editor-xz02jeh1.js +4 -0
- package/dist/chunks/entry-commands-kmt02crp.js +4 -0
- package/dist/chunks/extension-sections-0rprf12d.js +4 -0
- package/dist/chunks/file-ops-mexj5qed.js +4 -0
- package/dist/chunks/files-b2tcppdd.js +4 -0
- package/dist/chunks/format-host-btsevv0c.js +4 -0
- package/dist/chunks/fs-events-r0apejva.js +4 -0
- package/dist/chunks/grid-open-n2a8xkht.js +4 -0
- package/dist/chunks/{grid-view-r22jsqht.js → grid-view-tghcwrrt.js} +12 -12
- package/dist/chunks/iframe-host-gx0ypyh3.js +4 -0
- package/dist/chunks/index-bs4k9tr6.js +4 -0
- package/dist/chunks/{index-pxwwf00y.js → index-vr006kbt.js} +3 -3
- package/dist/chunks/{javascript-pzqryby6.js → javascript-z1g3s9fd.js} +2 -2
- package/dist/chunks/{jsonMode-tcnyxyap.js → jsonMode-7szwg8c4.js} +5 -5
- package/dist/chunks/jx-validate-ymf10teh.js +4 -0
- package/dist/chunks/layers-p9nfya38.js +4 -0
- package/dist/chunks/layers-panel-tt1hzhhf.js +4 -0
- package/dist/chunks/lit-html-x18n2sfz.js +4 -0
- package/dist/chunks/media-library-0n45gv8r.js +4 -0
- package/dist/chunks/media-picker-s09at95z.js +4 -0
- package/dist/chunks/{monaco-binding-bqpge64f.js → monaco-binding-v42w9c1v.js} +3 -3
- package/dist/chunks/monaco-buffer-een2ea0v.js +4 -0
- package/dist/chunks/{monaco-setup-1mkab762.js → monaco-setup-7bffxd6v.js} +3 -3
- package/dist/chunks/notify-qwb8radt.js +4 -0
- package/dist/chunks/parse-v77xtwv7.js +4 -0
- package/dist/chunks/platform-8jnez0wr.js +4 -0
- package/dist/chunks/publish-panel-aysnj611.js +4 -0
- package/dist/chunks/{publish-quick-m9vkhahq.js → publish-quick-kpbqs9mz.js} +3 -3
- package/dist/chunks/publish-workspace-nd0a8q99.js +4 -0
- package/dist/chunks/quick-search-vg0jkhk2.js +4 -0
- package/dist/chunks/references-a7v6a0e2.js +4 -0
- package/dist/chunks/right-panel-cvk1vxx5.js +4 -0
- package/dist/chunks/source-control-fsqzc6he.js +4 -0
- package/dist/chunks/studio-05jfwbmf.js +5 -0
- package/dist/chunks/{studio-qyb5bebs.js → studio-0q5jwddh.js} +7 -7
- package/dist/chunks/{studio-cvz0e00f.js → studio-0w2dr0q8.js} +4 -4
- package/dist/chunks/{studio-eesyjg7h.js → studio-1tzpds97.js} +5 -5
- package/dist/chunks/{studio-a3s6frde.js → studio-216b27sv.js} +3 -3
- package/dist/chunks/studio-2ejhqns4.js +5 -0
- package/dist/chunks/studio-2r90cts3.js +16 -0
- package/dist/chunks/{studio-dy2xtt7a.js → studio-399a25za.js} +4 -4
- package/dist/chunks/studio-399xknkb.js +6 -0
- package/dist/chunks/{studio-jh6t5qz4.js → studio-43y04qck.js} +4 -4
- package/dist/chunks/{studio-skynbac3.js → studio-4g8yb6jn.js} +2 -2
- package/dist/chunks/{studio-jw0q5j6k.js → studio-4jhw38b2.js} +4 -4
- package/dist/chunks/{studio-4smcnv33.js → studio-4ncmwqw5.js} +4 -4
- package/dist/chunks/studio-5atwjgkj.js +7 -0
- package/dist/chunks/{studio-vcz63n42.js → studio-5frqk7c0.js} +4 -4
- package/dist/chunks/{studio-hsr3k06v.js → studio-646nn2ys.js} +5 -5
- package/dist/chunks/{studio-ch8gt8vt.js → studio-6cwj6xrx.js} +4 -4
- package/dist/chunks/studio-6hzdjfv0.js +5 -0
- package/dist/chunks/{studio-9cp96v90.js → studio-71m92v9s.js} +7 -7
- package/dist/chunks/{studio-brdp85q7.js → studio-75kcdbsk.js} +4 -4
- package/dist/chunks/{studio-6vwvshw8.js → studio-78pywnp2.js} +5 -5
- package/dist/chunks/{studio-ggm7zf70.js → studio-86r8hp7r.js} +5 -5
- package/dist/chunks/studio-886t6ztg.js +5 -0
- package/dist/chunks/{studio-5dmgmyw4.js → studio-8wnvtr4z.js} +4 -4
- package/dist/chunks/studio-8z66jk4z.js +5 -0
- package/dist/chunks/{studio-x2metr13.js → studio-9rbe2xpw.js} +3 -3
- package/dist/chunks/{studio-8qejv8yf.js → studio-awxwjawq.js} +4 -4
- package/dist/chunks/studio-b2qpt0xy.js +14 -0
- package/dist/chunks/{studio-9rcbvksg.js → studio-bvs9kpst.js} +7 -7
- package/dist/chunks/studio-c71806xz.js +7 -0
- package/dist/chunks/{studio-vjhej0w5.js → studio-cbwks69x.js} +140 -140
- package/dist/chunks/studio-cg1bfyhf.js +9 -0
- package/dist/chunks/studio-cg710sk9.js +5 -0
- package/dist/chunks/studio-cw0wb9qk.js +7 -0
- package/dist/chunks/studio-cyheys7k.js +5 -0
- package/dist/chunks/studio-ea5m9kg5.js +5 -0
- package/dist/chunks/{studio-4nkm4404.js → studio-ea74s8c1.js} +4 -4
- package/dist/chunks/{studio-37twdaf7.js → studio-efdxjwyp.js} +34 -34
- package/dist/chunks/{studio-pmzg17fj.js → studio-egmw2837.js} +4 -4
- package/dist/chunks/{studio-8jb31dcf.js → studio-er5f383a.js} +4 -4
- package/dist/chunks/studio-f746039f.js +5 -0
- package/dist/chunks/studio-fmdymd9v.js +5 -0
- package/dist/chunks/studio-gcm12z00.js +6 -0
- package/dist/chunks/{studio-t3j8htp7.js → studio-gj98m8gy.js} +5 -5
- package/dist/chunks/{studio-cgb97rwv.js → studio-hasbgjah.js} +4 -4
- package/dist/chunks/studio-hhp4x8xf.js +6 -0
- package/dist/chunks/{studio-848rk4p1.js → studio-hz5n7x27.js} +4 -4
- package/dist/chunks/{studio-0g2sm01j.js → studio-j3d2fjqz.js} +4 -4
- package/dist/chunks/studio-jeraxdgv.js +7 -0
- package/dist/chunks/studio-jvgek9xt.js +5 -0
- package/dist/chunks/studio-jws1a87n.js +5 -0
- package/dist/chunks/studio-k2sz13zg.js +5 -0
- package/dist/chunks/studio-k3m4jkdk.js +5 -0
- package/dist/chunks/{studio-7vb997ff.js → studio-kg1abnz0.js} +4 -4
- package/dist/chunks/{studio-s0fg2wav.js → studio-kg5ya5r2.js} +4 -4
- package/dist/chunks/studio-khwbgrtg.js +5 -0
- package/dist/chunks/studio-mx6wzh25.js +5 -0
- package/dist/chunks/studio-mxs3ar9t.js +5 -0
- package/dist/chunks/studio-nm4szey4.js +5 -0
- package/dist/chunks/studio-nqxqf8p2.js +4 -0
- package/dist/chunks/{studio-07k0geap.js → studio-pjtntksy.js} +4 -4
- package/dist/chunks/studio-qh8berdz.js +5 -0
- package/dist/chunks/studio-qn7z4krm.js +5 -0
- package/dist/chunks/studio-qyed0ah6.js +5 -0
- package/dist/chunks/{studio-5e7p1vgd.js → studio-r4bcdwhq.js} +4 -4
- package/dist/chunks/{studio-mwnmzx7g.js → studio-r7pf0rkv.js} +6 -6
- package/dist/chunks/studio-rtfnhrdg.js +5 -0
- package/dist/chunks/{studio-zacvfm31.js → studio-rzqaz21g.js} +4 -4
- package/dist/chunks/studio-s5tzw84t.js +5 -0
- package/dist/chunks/{studio-nf0pqpbj.js → studio-sevbc3xv.js} +4 -4
- package/dist/chunks/{studio-va0e63sk.js → studio-sxdb9h3q.js} +6 -6
- package/dist/chunks/studio-t51y8v1d.js +5 -0
- package/dist/chunks/{studio-pd9dsqpq.js → studio-t98vq4r6.js} +4 -4
- package/dist/chunks/studio-th7z3fg7.js +5 -0
- package/dist/chunks/studio-tsxpqvh0.js +6 -0
- package/dist/chunks/{studio-7823f0g8.js → studio-v1yascv2.js} +4 -4
- package/dist/chunks/{studio-tpy3rdxn.js → studio-wc6za3zs.js} +4 -4
- package/dist/chunks/{studio-5m0w815d.js → studio-wxq6v5sv.js} +4 -4
- package/dist/chunks/{studio-ahf3cspq.js → studio-y60sts62.js} +3 -3
- package/dist/chunks/studio-ybnwymxw.js +5 -0
- package/dist/chunks/studio-zndrqawb.js +5 -0
- package/dist/chunks/studio-zwaxn5s2.js +5 -0
- package/dist/chunks/{tsMode-6vwhy6ty.js → tsMode-f54j66ym.js} +5 -5
- package/dist/chunks/workspace-home-x1787wpv.js +4 -0
- package/dist/chunks/workspace-zpe1np43.js +4 -0
- package/dist/chunks/{ws-client-zcxkfgmf.js → ws-client-e8kj684q.js} +3 -3
- package/dist/manifest.json +76 -75
- package/dist/studio.js +81 -82
- package/package.json +4 -4
- package/src/browse/library-model.ts +56 -23
- package/src/commands/context.ts +1 -0
- package/src/editor/shortcuts.ts +3 -0
- package/src/panels/data-grid.ts +0 -4
- package/src/panels/settings-menu.ts +3 -3
- package/src/panels/settings-pane.ts +42 -56
- package/src/services/ai-import-tools.ts +6 -3
- package/src/services/ai-models.ts +65 -11
- package/src/services/ai-settings.ts +45 -5
- package/src/services/document-assistant.ts +5 -2
- package/src/services/settings/definitions.ts +19 -0
- package/src/settings/contributed-section.ts +16 -7
- package/src/settings/css-vars-editor.ts +4 -4
- package/src/settings/general-settings.ts +1 -4
- package/src/settings/preferences-accounts.ts +2 -2
- package/src/settings/preferences-dialog.ts +4 -2
- package/src/settings/project-sections.ts +1 -1
- package/src/settings/section-registry.ts +5 -4
- package/src/settings/settings-document.ts +33 -24
- package/src/settings/settings-workspace.ts +205 -0
- package/src/shell.ts +31 -6
- package/src/surfaces/ai-credentials-form.json +59 -5
- package/src/surfaces/ai-credentials-form.ts +15 -2
- package/src/surfaces/commandbar.ts +7 -3
- package/src/surfaces/settings-contributed.json +4 -4
- package/src/surfaces/settings-contributed.ts +2 -2
- package/src/surfaces/settings-pane.json +262 -180
- package/src/surfaces/settings-pane.ts +63 -14
- package/src/ui/ai-credentials-form.ts +128 -11
- package/src/ui/regions.ts +5 -5
- package/src/workspace/tab-workspace.ts +3 -2
- package/src/workspace/workspace-home.ts +18 -4
- package/src/workspace/workspace-ids.ts +40 -7
- package/dist/chunks/adapter-xcpsmecx.js +0 -4
- package/dist/chunks/add-new-flow-ptmhmzr9.js +0 -4
- package/dist/chunks/cf-account-picker-z1sgwpwd.js +0 -4
- package/dist/chunks/cf-settings-xqvhxxe9.js +0 -4
- package/dist/chunks/components-whsc81a7.js +0 -4
- package/dist/chunks/content-source-jwtxg78w.js +0 -4
- package/dist/chunks/editor-zdqdpq1x.js +0 -4
- package/dist/chunks/entry-commands-w8p2fbpt.js +0 -4
- package/dist/chunks/extension-sections-y2p1te2r.js +0 -4
- package/dist/chunks/file-ops-13ab4swj.js +0 -4
- package/dist/chunks/files-zbc8p6v1.js +0 -4
- package/dist/chunks/format-host-zjsbktbx.js +0 -4
- package/dist/chunks/fs-events-t6x0hch6.js +0 -4
- package/dist/chunks/grid-open-fyzdwpkh.js +0 -4
- package/dist/chunks/iframe-host-kbyqc7pt.js +0 -4
- package/dist/chunks/index-6nvj89vb.js +0 -4
- package/dist/chunks/jx-validate-5sp8a4rm.js +0 -4
- package/dist/chunks/layers-panel-qrxj9vr2.js +0 -4
- package/dist/chunks/layers-tpzayggx.js +0 -4
- package/dist/chunks/lit-html-x6nrxsx3.js +0 -4
- package/dist/chunks/media-library-ywppnjrz.js +0 -4
- package/dist/chunks/media-picker-etxgc8qq.js +0 -4
- package/dist/chunks/monaco-buffer-qrnqhk0b.js +0 -4
- package/dist/chunks/notify-kcv38wwe.js +0 -4
- package/dist/chunks/parse-df2kkmhc.js +0 -4
- package/dist/chunks/platform-dtsysmyd.js +0 -4
- package/dist/chunks/publish-panel-evb1rcxt.js +0 -4
- package/dist/chunks/publish-workspace-ktk9h536.js +0 -4
- package/dist/chunks/quick-search-2f47fxcw.js +0 -4
- package/dist/chunks/references-5w6ajjv7.js +0 -4
- package/dist/chunks/right-panel-kz0a6byf.js +0 -4
- package/dist/chunks/source-control-1phx90zk.js +0 -4
- package/dist/chunks/studio-0hr000ba.js +0 -5
- package/dist/chunks/studio-1wyp7dt5.js +0 -5
- package/dist/chunks/studio-20ap8dds.js +0 -5
- package/dist/chunks/studio-291gqh98.js +0 -5
- package/dist/chunks/studio-4zqfw5ha.js +0 -5
- package/dist/chunks/studio-56egy6vf.js +0 -5
- package/dist/chunks/studio-695k95bw.js +0 -5
- package/dist/chunks/studio-732mw0g8.js +0 -5
- package/dist/chunks/studio-76t560kn.js +0 -6
- package/dist/chunks/studio-8486jn4r.js +0 -5
- package/dist/chunks/studio-8x8616xd.js +0 -5
- package/dist/chunks/studio-bkmv1h3e.js +0 -9
- package/dist/chunks/studio-cqf1k4qk.js +0 -5
- package/dist/chunks/studio-dbgv4fv9.js +0 -16
- package/dist/chunks/studio-et6t8g4m.js +0 -4
- package/dist/chunks/studio-f2j9et3h.js +0 -14
- package/dist/chunks/studio-fep7hr66.js +0 -7
- package/dist/chunks/studio-fyf7j57j.js +0 -5
- package/dist/chunks/studio-g5prntab.js +0 -5
- package/dist/chunks/studio-ga77mf07.js +0 -5
- package/dist/chunks/studio-h7gy12h2.js +0 -5
- package/dist/chunks/studio-j933k8nr.js +0 -5
- package/dist/chunks/studio-jgbvqcgh.js +0 -5
- package/dist/chunks/studio-k4xc5g6h.js +0 -5
- package/dist/chunks/studio-p0nf2e1f.js +0 -6
- package/dist/chunks/studio-pzfa2vmb.js +0 -5
- package/dist/chunks/studio-rf8d6p9f.js +0 -7
- package/dist/chunks/studio-rt498t2v.js +0 -5
- package/dist/chunks/studio-sd07xva5.js +0 -6
- package/dist/chunks/studio-thj81e98.js +0 -7
- package/dist/chunks/studio-tyw7tk0x.js +0 -5
- package/dist/chunks/studio-vffwe9k7.js +0 -5
- package/dist/chunks/studio-vxjap704.js +0 -5
- package/dist/chunks/studio-w67vfgy5.js +0 -5
- package/dist/chunks/studio-xebavr9s.js +0 -5
- package/dist/chunks/studio-yg5n49za.js +0 -5
- package/dist/chunks/studio-yhz5b313.js +0 -5
- package/dist/chunks/studio-zsjpsw08.js +0 -5
- package/dist/chunks/studio-zxm98z2m.js +0 -7
- package/dist/chunks/workspace-d65bz1qk.js +0 -4
- package/dist/chunks/workspace-home-vbg9b3jh.js +0 -4
- package/src/settings/settings-dialog.ts +0 -192
- package/src/surfaces/settings-dialog.json +0 -51
- package/src/surfaces/settings-dialog.ts +0 -169
|
@@ -1,192 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/**
|
|
3
|
-
* Project Settings as a dialog (§17.1): the flow that opens it, mounts the settings editor into it,
|
|
4
|
-
* and takes both down.
|
|
5
|
-
*
|
|
6
|
-
* Project Settings was a document in the pane, the `project.json` tab under a `settings` editor
|
|
7
|
-
* mode. The five workspaces made that the wrong home: a tab belongs to exactly one workspace, and
|
|
8
|
-
* configuration belongs to all of them, so a settings TAB either pulled the author out of the
|
|
9
|
-
* workspace they were in or had to be special-cased in every one. A dialog is reachable from every
|
|
10
|
-
* workspace and leaves the one underneath where it was. What made the old modal a problem (a form
|
|
11
|
-
* that hid the canvas it was tuning) left with the design tokens, which are the Styles workspace's
|
|
12
|
-
* now; every section still here writes `project.json` as it is edited, through the one chokepoint
|
|
13
|
-
* (`tabs/project-config.ts`), so the dialog has nothing to confirm and its one answer is Close.
|
|
14
|
-
*
|
|
15
|
-
* **Which section shows is the registry's, not this module's.** `settings/section-registry.ts`
|
|
16
|
-
* holds the requested and the displayed section and outlives the dialog, which is what makes the
|
|
17
|
-
* dialog reopen where the author left it for the rest of the session.
|
|
18
|
-
*
|
|
19
|
-
* Modality, Escape and focus restoration are the platform's: a `jx-dialog` in the dialog layer,
|
|
20
|
-
* opened with `showModal()`, which puts focus back on whatever opened it when it closes.
|
|
21
|
-
*
|
|
22
|
-
* **The frame and the editor are built once per session** and kept, closed, in the dialog layer. A
|
|
23
|
-
* close suspends the editor (it stops following the section registry) and closes the platform's
|
|
24
|
-
* dialog; an open resumes it, which redraws the current section, and shows the same dialog again.
|
|
25
|
-
* Rebuilding both on every open was most of what opening Settings cost, and disposing them inside
|
|
26
|
-
* the dialog's own `cancel` handler removed a subtree that still held focus from the top layer,
|
|
27
|
-
* which the browser re-styled on the way out. {@link disposeSettingsDialog} is the teardown, and a
|
|
28
|
-
* frame whose layer was replaced under it is rebuilt rather than shown.
|
|
29
|
-
*
|
|
30
|
-
* @docs studio/projects/settings
|
|
31
|
-
*/
|
|
32
|
-
|
|
33
|
-
import { activeRegistry } from "../commands/active-registry";
|
|
34
|
-
import { runActiveReported } from "../commands/run-reported";
|
|
35
|
-
import { mountSettingsPane } from "../panels/settings-pane";
|
|
36
|
-
import { openSettingsDialogSurface } from "../surfaces/settings-dialog";
|
|
37
|
-
import { layerHost } from "../ui/layers";
|
|
38
|
-
import type { SettingsPaneMount } from "../panels/settings-pane";
|
|
39
|
-
import type { SettingsDialogHandle } from "../surfaces/settings-dialog";
|
|
40
|
-
import type { InspectorTabId } from "../shell";
|
|
41
|
-
import type { WorkspaceId } from "../workspace/workspace-ids";
|
|
42
|
-
import type { StylesView } from "../style/project-styles";
|
|
43
|
-
import type { PublishTab } from "../publish/publish-ids";
|
|
44
|
-
|
|
45
|
-
/** The frame, built on the first open and kept across closes; `null` before then. */
|
|
46
|
-
interface SettingsFrame {
|
|
47
|
-
dialog: SettingsDialogHandle;
|
|
48
|
-
/** The editor in the frame's body, once the body has been created. */
|
|
49
|
-
pane: SettingsPaneMount | null;
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
let _frame: SettingsFrame | null = null;
|
|
53
|
-
|
|
54
|
-
/** Whether the dialog is asked to be up: true from an open until the close that ends it. */
|
|
55
|
-
let _open = false;
|
|
56
|
-
|
|
57
|
-
/** {@link _open}, read through a call so a check after an `await` is not narrowed to before it. */
|
|
58
|
-
function isOpen(): boolean {
|
|
59
|
-
return _open;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
/** Build the frame (it opens itself once mounted). */
|
|
63
|
-
function buildFrame(): SettingsFrame {
|
|
64
|
-
const frame: SettingsFrame = {
|
|
65
|
-
dialog: openSettingsDialogSurface({
|
|
66
|
-
body: (host) => {
|
|
67
|
-
frame.pane = mountSettingsPane(host, {
|
|
68
|
-
openMoved: (workspace, inspector, view, publishTab) => {
|
|
69
|
-
void openMoved(workspace, inspector, view, publishTab);
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
},
|
|
73
|
-
/* Escape or Close: the platform closed the dialog, so the flow follows. `close()` is
|
|
74
|
-
idempotent, so the flow's own close running first is fine. */
|
|
75
|
-
closed: () => {
|
|
76
|
-
if (_frame === frame) {
|
|
77
|
-
closeSettingsDialog();
|
|
78
|
-
}
|
|
79
|
-
},
|
|
80
|
-
layer: layerHost("dialog"),
|
|
81
|
-
}),
|
|
82
|
-
pane: null,
|
|
83
|
-
};
|
|
84
|
-
return frame;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Leave Settings for the workspace something moved to: the Moved footnote's buttons.
|
|
89
|
-
*
|
|
90
|
-
* Closed FIRST, so the workspace the author asked for is what they see and focus returns to the
|
|
91
|
-
* frame rather than to a row that is going away. A refusal (the switch is gated on an open project)
|
|
92
|
-
* is filed in Problems under this surface's name instead of being dropped.
|
|
93
|
-
*
|
|
94
|
-
* A row that names an Inspector tab ("Head and SEO defaults → Page tab") also shows the Inspector
|
|
95
|
-
* on that tab, AFTER the switch, because entering a workspace applies its frame preset and would
|
|
96
|
-
* otherwise put the dock back as the preset has it. The tab is a document-level view, so with no
|
|
97
|
-
* document open there is no tab to show and asking would only file a refusal; the dock is still
|
|
98
|
-
* opened, which is where the tab appears once one is.
|
|
99
|
-
*
|
|
100
|
-
* A row that names a Styles view ("Colors and fonts → Styles › Variables") runs `styles.open` with
|
|
101
|
-
* that view instead, which is the same workspace switch followed by the view.
|
|
102
|
-
*
|
|
103
|
-
* @param {WorkspaceId} workspace
|
|
104
|
-
* @param {InspectorTabId} [inspector]
|
|
105
|
-
* @param {StylesView} [view]
|
|
106
|
-
* @returns {Promise<void>} Settles once every command the row runs has settled
|
|
107
|
-
*/
|
|
108
|
-
async function openMoved(
|
|
109
|
-
workspace: WorkspaceId,
|
|
110
|
-
inspector?: InspectorTabId,
|
|
111
|
-
view?: StylesView,
|
|
112
|
-
publishTab?: PublishTab,
|
|
113
|
-
): Promise<void> {
|
|
114
|
-
closeSettingsDialog();
|
|
115
|
-
if (view !== undefined) {
|
|
116
|
-
await runActiveReported("styles.open", { view }, "Settings");
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
// Hosting is a Publish sub-tab, not the workspace's first: the button says where it lands.
|
|
120
|
-
if (publishTab !== undefined) {
|
|
121
|
-
await runActiveReported("publish.open", { tab: publishTab }, "Settings");
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
await runActiveReported("view.setWorkspace", { workspace }, "Settings");
|
|
125
|
-
if (inspector === undefined) {
|
|
126
|
-
return;
|
|
127
|
-
}
|
|
128
|
-
await runActiveReported("view.setRightPanel", { open: true }, "Settings");
|
|
129
|
-
if (activeRegistry()?.isEnabled("view.setRightTab") === true) {
|
|
130
|
-
await runActiveReported("view.setRightTab", { tab: inspector }, "Settings");
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
/**
|
|
135
|
-
* Open Project Settings, or leave it up when it already is.
|
|
136
|
-
*
|
|
137
|
-
* Re-opening while it is up does not stack a second dialog: the section the caller asked for has
|
|
138
|
-
* already been written to the registry, which redraws the editor that is showing.
|
|
139
|
-
*
|
|
140
|
-
* @returns {Promise<void>} Settles once the dialog is showing and the current section's row holds
|
|
141
|
-
* the keyboard
|
|
142
|
-
*/
|
|
143
|
-
export async function openSettingsDialog(): Promise<void> {
|
|
144
|
-
if (_open && _frame) {
|
|
145
|
-
await _frame.dialog.ready;
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
_open = true;
|
|
149
|
-
// A frame whose layer went away (a shell remount) is dead weight, not something to show.
|
|
150
|
-
if (_frame && !_frame.dialog.host.isConnected) {
|
|
151
|
-
disposeSettingsDialog();
|
|
152
|
-
_open = true;
|
|
153
|
-
}
|
|
154
|
-
let frame = _frame;
|
|
155
|
-
if (frame) {
|
|
156
|
-
frame.pane?.resume();
|
|
157
|
-
await frame.dialog.show();
|
|
158
|
-
} else {
|
|
159
|
-
frame = buildFrame();
|
|
160
|
-
_frame = frame;
|
|
161
|
-
await frame.dialog.ready;
|
|
162
|
-
}
|
|
163
|
-
/* Read after the wait, from the frame: the body is created while the dialog mounts, and a close
|
|
164
|
-
in between leaves the editor built but not to be focused. */
|
|
165
|
-
const mounted = frame.pane;
|
|
166
|
-
if (mounted === null || _frame !== frame || !isOpen()) {
|
|
167
|
-
return;
|
|
168
|
-
}
|
|
169
|
-
await mounted.ready;
|
|
170
|
-
if (_frame === frame && isOpen()) {
|
|
171
|
-
mounted.focusActive();
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
/** Close Project Settings if it is open. Idempotent. The frame stays built for the next open. */
|
|
176
|
-
export function closeSettingsDialog(): void {
|
|
177
|
-
if (!_open) {
|
|
178
|
-
return;
|
|
179
|
-
}
|
|
180
|
-
_open = false;
|
|
181
|
-
_frame?.pane?.suspend();
|
|
182
|
-
_frame?.dialog.close();
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/** Close Project Settings and take its frame and editor down. Idempotent. */
|
|
186
|
-
export function disposeSettingsDialog(): void {
|
|
187
|
-
_open = false;
|
|
188
|
-
const frame = _frame;
|
|
189
|
-
_frame = null;
|
|
190
|
-
frame?.pane?.dispose();
|
|
191
|
-
frame?.dialog.dispose();
|
|
192
|
-
}
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
|
-
"$id": "StudioSettingsDialog",
|
|
4
|
-
"$description": "Project Settings (§17.1): a `jx-dialog` whose body is the settings editor's two columns, the grouped section list and the section body. The dialog owns modality, Escape and focus restoration, and its one footer answer is Close: every section writes as it is edited, so there is nothing to confirm or cancel. The body is an ISLAND: this document draws the slot and nothing in it, and `settings/settings-dialog.ts` mounts `settings-pane.json` there through `onNodeCreated` (studio-ui-guidelines.md §9.4).",
|
|
5
|
-
"tagName": "jx-dialog",
|
|
6
|
-
"$props": {
|
|
7
|
-
"headline": "Project settings",
|
|
8
|
-
"confirmLabel": "",
|
|
9
|
-
"cancelLabel": "Close",
|
|
10
|
-
"size": "xl"
|
|
11
|
-
},
|
|
12
|
-
"attributes": {
|
|
13
|
-
"part": "settings"
|
|
14
|
-
},
|
|
15
|
-
"oncancel": {
|
|
16
|
-
"$prototype": "Function",
|
|
17
|
-
"body": [
|
|
18
|
-
{
|
|
19
|
-
"operator": "call",
|
|
20
|
-
"target": {
|
|
21
|
-
"$ref": "#/state/closed"
|
|
22
|
-
},
|
|
23
|
-
"value": []
|
|
24
|
-
}
|
|
25
|
-
]
|
|
26
|
-
},
|
|
27
|
-
"onclose": {
|
|
28
|
-
"$prototype": "Function",
|
|
29
|
-
"body": [
|
|
30
|
-
{
|
|
31
|
-
"operator": "call",
|
|
32
|
-
"target": {
|
|
33
|
-
"$ref": "#/state/closed"
|
|
34
|
-
},
|
|
35
|
-
"value": []
|
|
36
|
-
}
|
|
37
|
-
]
|
|
38
|
-
},
|
|
39
|
-
"children": [
|
|
40
|
-
{
|
|
41
|
-
"tagName": "div",
|
|
42
|
-
"attributes": {
|
|
43
|
-
"part": "pane-slot"
|
|
44
|
-
},
|
|
45
|
-
"style": {
|
|
46
|
-
"$description": "The editor's box is its own (`settings-pane.json`); the slot only gives it the dialog body's width.",
|
|
47
|
-
"minWidth": "0"
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
]
|
|
51
|
-
}
|
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
/// <reference lib="dom" />
|
|
2
|
-
/**
|
|
3
|
-
* The Project Settings dialog, as a mounted document.
|
|
4
|
-
*
|
|
5
|
-
* A `jx-dialog` in the dialog layer whose body is an island: `settings-dialog.json` draws the slot,
|
|
6
|
-
* and the flow (`settings/settings-dialog.ts`) mounts the settings editor's columns into it through
|
|
7
|
-
* the `onNodeCreated` seam (`studio-ui-guidelines.md` §9.4). The dialog is only the frame and the
|
|
8
|
-
* one answer, Close.
|
|
9
|
-
*
|
|
10
|
-
* **Mounted once, shown many times.** Every open used to mount this document and the whole editor
|
|
11
|
-
* into it, and every close disposed both while the dialog was still on the top layer, which made
|
|
12
|
-
* each close re-style the subtree it was removing. Now a close is the platform's `close()` and the
|
|
13
|
-
* document stays in the dialog layer, closed (so `display: none`, and inert), until the flow
|
|
14
|
-
* disposes it; the next open is one `showModal()`.
|
|
15
|
-
*
|
|
16
|
-
* **Await the ELEMENT, not just the mount.** `mountSurface` resolving means the document rendered;
|
|
17
|
-
* a `jx-dialog`'s own template is one `connectedCallback` later, and `showModal` in between finds
|
|
18
|
-
* no `<dialog>` to open. `whenReady` is shared with `surfaces/dialog.ts`.
|
|
19
|
-
*
|
|
20
|
-
* @docs studio/projects/settings
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { isString } from "@jxsuite/schema/guards";
|
|
24
|
-
import { close, showModal } from "@jxsuite/ui/behaviors/dialog";
|
|
25
|
-
import { reactive } from "../reactivity";
|
|
26
|
-
import { overlayRegion, REGION_ATTR } from "../ui/regions";
|
|
27
|
-
import { mountSurface, registerSurface } from "../ui/surface";
|
|
28
|
-
import { whenReady } from "./dialog";
|
|
29
|
-
import settingsDialogDoc from "./settings-dialog.json";
|
|
30
|
-
import type { JxElement } from "@jxsuite/schema/types";
|
|
31
|
-
import type { SurfaceHandle } from "../ui/surface";
|
|
32
|
-
|
|
33
|
-
registerSurface("settings-dialog", settingsDialogDoc);
|
|
34
|
-
|
|
35
|
-
/** The dialog's region: `overlay.dialog:settings`. Section regions are named under it. */
|
|
36
|
-
export const SETTINGS_DIALOG_REGION = overlayRegion("dialog", "settings");
|
|
37
|
-
|
|
38
|
-
export interface SettingsDialogOptions {
|
|
39
|
-
/** The dialog layer host, handed in so this module never reaches back into `layers.ts`. */
|
|
40
|
-
layer: HTMLElement;
|
|
41
|
-
/** The body slot was created: where the flow mounts the settings editor. Called once. */
|
|
42
|
-
body: (host: HTMLElement) => void;
|
|
43
|
-
/** The dialog closed, for any reason: once per time it was shown. */
|
|
44
|
-
closed: () => void;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* The settings frame, mounted once and shown as often as it is asked for.
|
|
49
|
-
*
|
|
50
|
-
* Closing it closes the platform's `<dialog>` and leaves the document standing in the dialog layer,
|
|
51
|
-
* so the next open is one `showModal()` on a frame whose editor is already built, not a mount of
|
|
52
|
-
* the whole editor. Only {@link SettingsDialogHandle.dispose} takes it down.
|
|
53
|
-
*/
|
|
54
|
-
export interface SettingsDialogHandle {
|
|
55
|
-
/** The slot in the dialog layer that carries the region. */
|
|
56
|
-
host: HTMLElement;
|
|
57
|
-
/** Resolves with the `jx-dialog` element once it has rendered (and been opened, if still asked). */
|
|
58
|
-
ready: Promise<HTMLElement>;
|
|
59
|
-
/** Show it again after a close. Resolves once it is showing. */
|
|
60
|
-
show: () => Promise<HTMLElement>;
|
|
61
|
-
/** Close the dialog (the platform restores focus); the document stays mounted. Idempotent. */
|
|
62
|
-
close: () => void;
|
|
63
|
-
/** Close it and take the document and its slot down for good. Idempotent. */
|
|
64
|
-
dispose: () => void;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
interface SettingsDialogScope {
|
|
68
|
-
closed: () => void;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/** The `part` a node's definition carries, or `""` for a text node or an unmarked element. */
|
|
72
|
-
function partOf(def: JxElement | string): string {
|
|
73
|
-
const part = isString(def) ? undefined : def.attributes?.["part"];
|
|
74
|
-
return isString(part) ? part : "";
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
/**
|
|
78
|
-
* Mount the dialog and open it. The handle's `ready` resolves once it is showing.
|
|
79
|
-
*
|
|
80
|
-
* @param {SettingsDialogOptions} options
|
|
81
|
-
* @returns {SettingsDialogHandle}
|
|
82
|
-
*/
|
|
83
|
-
export function openSettingsDialogSurface(options: SettingsDialogOptions): SettingsDialogHandle {
|
|
84
|
-
const slot = document.createElement("div");
|
|
85
|
-
/* The layer is `pointer-events: none` so a click passes through it when nothing is up, and every
|
|
86
|
-
slot in it turns them back on for its own content. `pointer-events` INHERITS, and the top layer
|
|
87
|
-
changes paint order rather than inheritance, so a modal `<dialog>` in a slot that skipped this
|
|
88
|
-
is painted above everything and hit-tests to nothing. */
|
|
89
|
-
slot.style.pointerEvents = "auto";
|
|
90
|
-
options.layer.append(slot);
|
|
91
|
-
|
|
92
|
-
/** Whether the dialog is asked to be showing: true from each open until its close. */
|
|
93
|
-
let wanted = true;
|
|
94
|
-
let disposed = false;
|
|
95
|
-
/** Say this showing is over, once: the platform's own `close` and `close()` can each be first. */
|
|
96
|
-
const finish = (): void => {
|
|
97
|
-
if (!wanted) {
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
wanted = false;
|
|
101
|
-
options.closed();
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
const scope = reactive<SettingsDialogScope>({ closed: finish });
|
|
105
|
-
|
|
106
|
-
let mounted: SurfaceHandle | null = null;
|
|
107
|
-
/** Open the platform's dialog, if it is still asked for. Read through a call after each await. */
|
|
108
|
-
const open = (element: HTMLElement): HTMLElement => {
|
|
109
|
-
if (!disposed && wanted) {
|
|
110
|
-
showModal(element);
|
|
111
|
-
}
|
|
112
|
-
return element;
|
|
113
|
-
};
|
|
114
|
-
const ready = mountSurface("settings-dialog", scope, slot, {
|
|
115
|
-
onNodeCreated: (element, _path, def) => {
|
|
116
|
-
if (!disposed && element instanceof HTMLElement && partOf(def) === "pane-slot") {
|
|
117
|
-
options.body(element);
|
|
118
|
-
}
|
|
119
|
-
},
|
|
120
|
-
}).then(async (surface) => {
|
|
121
|
-
/* SAFETY: `settings-dialog.json`'s root definition is a `jx-dialog` element, so the runtime
|
|
122
|
-
mounts an HTMLElement. */
|
|
123
|
-
const element = surface.root as HTMLElement;
|
|
124
|
-
if (disposed) {
|
|
125
|
-
surface.dispose();
|
|
126
|
-
return element;
|
|
127
|
-
}
|
|
128
|
-
mounted = surface;
|
|
129
|
-
await whenReady(element);
|
|
130
|
-
/* The region goes on the platform's own `<dialog>`, the one element here that HAS a box:
|
|
131
|
-
`jx-dialog` is `display: contents`, and the slot wraps a dialog the top layer takes out of
|
|
132
|
-
flow, so both measure 0×0, and a region whose box is empty is refused by the screenshot
|
|
133
|
-
pipeline. The kit's own behaviour sidecar finds that node by exactly this selector. */
|
|
134
|
-
const box = element.querySelector<HTMLElement>('dialog[part="dialog"]') ?? element;
|
|
135
|
-
box.setAttribute(REGION_ATTR, SETTINGS_DIALOG_REGION);
|
|
136
|
-
return open(element);
|
|
137
|
-
});
|
|
138
|
-
|
|
139
|
-
const hide = (): void => {
|
|
140
|
-
const element = mounted?.root;
|
|
141
|
-
if (element instanceof HTMLElement) {
|
|
142
|
-
// The platform's close, so focus goes back where it came from before anything else moves.
|
|
143
|
-
close(element);
|
|
144
|
-
}
|
|
145
|
-
finish();
|
|
146
|
-
};
|
|
147
|
-
|
|
148
|
-
return {
|
|
149
|
-
close: hide,
|
|
150
|
-
dispose() {
|
|
151
|
-
if (disposed) {
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
hide();
|
|
155
|
-
disposed = true;
|
|
156
|
-
mounted?.dispose();
|
|
157
|
-
mounted = null;
|
|
158
|
-
slot.remove();
|
|
159
|
-
},
|
|
160
|
-
host: slot,
|
|
161
|
-
ready,
|
|
162
|
-
show() {
|
|
163
|
-
if (!disposed) {
|
|
164
|
-
wanted = true;
|
|
165
|
-
}
|
|
166
|
-
return ready.then(open);
|
|
167
|
-
},
|
|
168
|
-
};
|
|
169
|
-
}
|