@jxsuite/studio 4.1.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/data/elements-meta.json +5 -15
- package/data/html-meta.json +51 -6
- package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
- package/dist/chunks/action-group-sp6tna8v.js +118 -0
- package/dist/chunks/adapter-nj7tnjfn.js +13 -0
- package/dist/chunks/cf-account-picker-qwkm9zrf.js +495 -0
- package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
- package/dist/chunks/color-area-v17df7b8.js +154 -0
- package/dist/chunks/color-field-anwybnkn.js +208 -0
- package/dist/chunks/color-slider-44ez96fc.js +79 -0
- package/dist/chunks/color-xgg3kfw7.js +35 -0
- package/dist/chunks/combobox-5e7jev23.js +236 -0
- package/dist/chunks/components-vj72gqtq.js +20 -0
- package/dist/chunks/content-source-5mex4x1h.js +46 -0
- package/dist/chunks/convert-to-repeater-n64h8znc.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-234hjnqw.js +42 -0
- package/dist/chunks/extension-sections-3hpcambp.js +651 -0
- package/dist/chunks/file-ops-8yhd83xr.js +47 -0
- package/dist/chunks/files-hnxqxtsg.js +72 -0
- package/dist/chunks/format-host-779sfp2n.js +40 -0
- package/dist/chunks/fs-events-b88z7g4h.js +18 -0
- package/dist/chunks/git-panel-xwj8fpab.js +49 -0
- package/dist/chunks/icons-yy10wk9r.js +402 -0
- package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
- package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
- package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
- package/dist/chunks/iframe-host-syr0f9sb.js +115 -0
- package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
- package/dist/chunks/index-n4j7qxyr.js +109 -0
- package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
- package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
- package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
- package/dist/chunks/layers-ff81wthn.js +30 -0
- package/dist/chunks/layers-panel-pnnghw12.js +40 -0
- package/dist/chunks/listbox-6v2ac08j.js +44 -0
- package/dist/chunks/lit-html-m244w9nh.js +17 -0
- package/dist/chunks/media-picker-cqhhxhhe.js +33 -0
- package/dist/chunks/menu-9p2w46gj.js +15 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -0
- package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
- package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
- package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
- package/dist/chunks/notify-628t0anh.js +21 -0
- package/dist/chunks/number-field-5cndyft8.js +72 -0
- package/dist/chunks/parse-0zx14y15.js +10 -0
- package/dist/chunks/platform-ts9cg1a4.js +15 -0
- package/dist/chunks/popover-47z3ytva.js +25 -0
- package/dist/chunks/publish-panel-5zt840sy.js +27 -0
- package/dist/chunks/quick-search-3748564r.js +45 -0
- package/dist/chunks/references-qvvxej7h.js +26 -0
- package/dist/chunks/right-panel-eccz92qt.js +45 -0
- package/dist/chunks/section-registry-5pq32t0q.js +25 -0
- package/dist/chunks/select-2r16ez41.js +49 -0
- package/dist/chunks/split-g7nm1rgb.js +191 -0
- package/dist/chunks/studio-0hqbpbd0.js +62 -0
- package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-b55y6ewx.js → studio-1knfqgy7.js} +58 -58
- package/dist/chunks/{studio-2b946z26.js → studio-1z1kcjv4.js} +3628 -6095
- package/dist/chunks/studio-3773086z.js +111 -0
- package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
- package/dist/chunks/{studio-x813zp48.js → studio-3rz5md06.js} +30 -30
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/studio-5wt9nvhd.js +4763 -0
- package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
- package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
- package/dist/chunks/studio-6xa21ej9.js +28 -0
- package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
- package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xnmgv66.js +13615 -0
- package/dist/chunks/studio-8scdew0e.js +258 -0
- package/dist/chunks/{studio-fbf92ckf.js → studio-93zafjcm.js} +275 -163
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-a79k90n9.js +1162 -0
- package/dist/chunks/studio-aj37eer3.js +422 -0
- package/dist/chunks/studio-b0k5tqgp.js +2432 -0
- package/dist/chunks/studio-b4s9eykd.js +2811 -0
- package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/studio-e1pgga3k.js +839 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/{studio-q43a5y9h.js → studio-g3jevyjt.js} +16 -16
- package/dist/chunks/studio-gb13095a.js +2806 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
- package/dist/chunks/{studio-x4qkdat5.js → studio-js8nv53n.js} +1749 -2481
- package/dist/chunks/{studio-qjy2z9bv.js → studio-jxp12rnj.js} +32 -137
- package/dist/chunks/{studio-trxrabqf.js → studio-k75n7vhp.js} +527 -283
- package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/studio-kkqkcp3d.js +17668 -0
- package/dist/chunks/studio-mhhyamxf.js +763 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-nq5yf5mp.js} +22 -22
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/studio-nzzpvzx9.js +185 -0
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/{studio-3bqpr0zh.js → studio-pxbgypmg.js} +299 -110
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/{studio-6yw4y3my.js → studio-qhhm6hbt.js} +8 -8
- package/dist/chunks/studio-qk4bfsq2.js +362 -0
- package/dist/chunks/{studio-msd847zn.js → studio-qk90fgqm.js} +361 -90
- package/dist/chunks/{studio-jkftxyvz.js → studio-r6nvacqs.js} +5861 -2154
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/studio-sbjyc8bt.js +954 -0
- package/dist/chunks/{studio-1wagb550.js → studio-syg2tadj.js} +11 -11
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-tqgryxwg.js +1171 -0
- package/dist/chunks/studio-try13h8c.js +8448 -0
- package/dist/chunks/studio-vfq8qpjt.js +1219 -0
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-ahn3pdgx.js → studio-vw7mzp6z.js} +52 -38
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/studio-wqz6dggm.js +1356 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/studio-zdn2g6dt.js +148 -0
- package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
- package/dist/chunks/tabs-wbp1cdws.js +156 -0
- package/dist/chunks/textfield-abk6qyee.js +73 -0
- package/dist/chunks/toast-780pvfbv.js +27 -0
- package/dist/chunks/toast-host-3sqv46sn.js +116 -0
- package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
- package/dist/chunks/tooltip-eptb614w.js +369 -0
- package/dist/chunks/tree-a73p0pqm.js +367 -0
- package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
- package/dist/chunks/workspace-t55jdjbx.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1873 -673
- package/dist/studio.js +52757 -36535
- package/dist/workers/editor.worker.js +1040 -1085
- package/dist/workers/json.worker.js +1946 -1991
- package/dist/workers/ts.worker.js +4960 -5005
- package/index.html +1 -0
- package/package.json +18 -52
- package/src/about/about-modal.ts +72 -123
- package/src/browse/library-commands.ts +20 -49
- package/src/browse/library-layouts.ts +87 -218
- package/src/browse/library-pane.ts +406 -438
- package/src/canvas/canvas-helpers.ts +0 -49
- package/src/canvas/canvas-live-render.ts +25 -2
- package/src/canvas/canvas-render.ts +666 -231
- package/src/canvas/canvas-surface.ts +0 -1
- package/src/canvas/canvas-utils.ts +333 -113
- package/src/canvas/dialog-path.ts +76 -0
- package/src/canvas/dialog-state.ts +67 -0
- package/src/canvas/diff-marks.ts +252 -0
- package/src/canvas/diff-toolbar.ts +349 -0
- package/src/canvas/diff-view.ts +123 -0
- package/src/canvas/edit-width-drag.ts +187 -0
- package/src/canvas/edit-width.ts +150 -0
- package/src/canvas/iframe-entry.ts +125 -8
- package/src/canvas/iframe-host.ts +271 -15
- package/src/canvas/iframe-interaction.ts +133 -13
- package/src/canvas/iframe-patch.ts +7 -1
- package/src/canvas/iframe-position.ts +5 -6
- package/src/canvas/iframe-protocol.ts +106 -5
- package/src/canvas/iframe-render.ts +373 -5
- package/src/canvas/iframe-slash.ts +2 -2
- package/src/canvas/iframe-subtree.ts +5 -8
- package/src/canvas/path-mapping.ts +25 -3
- package/src/canvas/popover-path.ts +106 -0
- package/src/canvas/popover-state.ts +155 -0
- package/src/canvas/surface-registry.ts +21 -10
- package/src/collab/presence-chips.ts +51 -73
- package/src/commands/app-commands.ts +10 -0
- package/src/commands/budget.ts +12 -0
- package/src/commands/command-args.ts +404 -6
- package/src/commands/defaults.ts +44 -14
- package/src/commands/live-context.ts +11 -5
- package/src/commands/reference.ts +12 -2
- package/src/commands/registry.ts +177 -10
- package/src/commands/run-reported.ts +120 -0
- package/src/content/entry-commands.ts +16 -23
- package/src/content/entry-editor.ts +144 -101
- package/src/editor/canvas-slash-bridge.ts +2 -2
- package/src/editor/context-menu.ts +49 -200
- package/src/editor/convert-to-component.ts +42 -82
- package/src/editor/convert-to-repeater.ts +132 -173
- package/src/editor/inline-edit.ts +11 -0
- package/src/editor/shortcuts.ts +76 -49
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/components.ts +39 -0
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +944 -660
- package/src/files/json-layout.ts +474 -0
- package/src/files/serialize-document.ts +8 -1
- package/src/format/convert-file.ts +16 -10
- package/src/format/format-host.ts +50 -1
- package/src/github/github-auth.ts +71 -29
- package/src/github/github-publish.ts +57 -65
- package/src/grid/cell-editors.ts +46 -4
- package/src/grid/cell-popovers.ts +65 -62
- package/src/grid/grid-open.ts +86 -64
- package/src/grid/grid-panel.ts +390 -469
- package/src/grid/redirects-grid.ts +40 -44
- package/src/hosting/layout.ts +2 -0
- package/src/i18n/i18n-commands.ts +137 -62
- package/src/media/media-pane.ts +83 -133
- package/src/new-project/add-repo-modal.ts +125 -176
- package/src/new-project/import-tab.ts +181 -252
- package/src/new-project/location-fields.ts +93 -160
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/packages/pull-package-sync.ts +5 -1
- package/src/panels/activity-panel.ts +137 -104
- package/src/panels/ai-chat/chat-markdown.ts +15 -13
- package/src/panels/ai-chat/chat-view.ts +307 -472
- package/src/panels/ai-chat/composer.ts +175 -163
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +213 -185
- package/src/panels/block-action-bar.ts +444 -645
- package/src/panels/bottom-dock.ts +112 -47
- package/src/panels/chat-panel.ts +19 -14
- package/src/panels/data-explorer.ts +141 -102
- package/src/panels/data-grid.ts +183 -150
- package/src/panels/dnd.ts +75 -20
- package/src/panels/editors.ts +26 -19
- package/src/panels/elements-panel.ts +243 -186
- package/src/panels/empty-state.ts +26 -42
- package/src/panels/events-panel.ts +950 -729
- package/src/panels/formula-workspace.ts +434 -207
- package/src/panels/frontmatter-fields.ts +185 -153
- package/src/panels/frontmatter-panel.ts +411 -187
- package/src/panels/git-diff-open.ts +148 -0
- package/src/panels/git-panel.ts +679 -605
- package/src/panels/head-panel.ts +617 -435
- package/src/panels/i18n-panel.ts +148 -135
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +175 -147
- package/src/panels/layers-panel.ts +785 -671
- package/src/panels/left-panel.ts +166 -94
- package/src/panels/navigator-panels.ts +1 -1
- package/src/panels/pane-context.ts +529 -677
- package/src/panels/pane-grid.ts +265 -241
- package/src/panels/panel-registry.ts +15 -4
- package/src/panels/problems-panel.ts +181 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +223 -184
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +114 -661
- package/src/panels/settings-pane.ts +102 -86
- package/src/panels/signals-panel.ts +1318 -1172
- package/src/panels/statement-editor.ts +556 -428
- package/src/panels/style-panel.ts +1367 -630
- package/src/panels/style-utils.ts +36 -32
- package/src/panels/stylebook-doc.ts +30 -73
- package/src/panels/stylebook-layers-panel.ts +202 -109
- package/src/panels/stylebook-panel.ts +124 -88
- package/src/panels/tab-strip.ts +386 -288
- package/src/platforms/cloud.ts +106 -16
- package/src/platforms/devserver.ts +13 -0
- package/src/publish/deploy-checklist.ts +124 -78
- package/src/publish/publish-commands.ts +4 -12
- package/src/publish/publish-panel.ts +134 -328
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +538 -0
- package/src/services/ai-project-tools.ts +8 -2
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +112 -24
- package/src/services/ai-tools.ts +36 -212
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/document-assistant.ts +59 -8
- package/src/services/idle.ts +16 -14
- package/src/services/live-surfaces.ts +237 -0
- package/src/services/model-uri.ts +75 -0
- package/src/services/notify.ts +63 -6
- package/src/services/popover-report.ts +325 -0
- package/src/services/surface-registry.ts +56 -0
- package/src/services/tool-executor.ts +6 -0
- package/src/settings/contexts-section.ts +301 -299
- package/src/settings/contributed-section.ts +361 -222
- package/src/settings/css-vars-editor.ts +320 -325
- package/src/settings/defs-editor.ts +572 -535
- package/src/settings/dependencies-editor.ts +79 -107
- package/src/settings/extension-commands.ts +379 -0
- package/src/settings/extension-rows.ts +113 -0
- package/src/settings/extensions-section.ts +287 -0
- package/src/settings/general-settings.ts +130 -181
- package/src/settings/head-editor.ts +10 -305
- package/src/settings/locales-section.ts +146 -196
- package/src/settings/preferences-accounts.ts +1 -1
- package/src/settings/preferences-dialog.ts +350 -330
- package/src/settings/project-sections.ts +108 -181
- package/src/settings/schema-field-ui.ts +11 -399
- package/src/settings/section-registry.ts +8 -1
- package/src/settings/settings-document.ts +31 -29
- package/src/shell/tree.ts +42 -87
- package/src/shell.ts +48 -36
- package/src/studio.ts +104 -69
- package/src/style/token-ref.ts +0 -39
- package/src/surfaces/about.json +263 -0
- package/src/surfaces/about.ts +163 -0
- package/src/surfaces/add-repo.json +486 -0
- package/src/surfaces/add-repo.ts +236 -0
- package/src/surfaces/ai-chat.json +2185 -0
- package/src/surfaces/ai-chat.ts +549 -0
- package/src/surfaces/ai-credentials-form.json +332 -0
- package/src/surfaces/ai-credentials-form.ts +151 -0
- package/src/surfaces/ai-managed-connect.json +108 -0
- package/src/surfaces/ai-managed-connect.ts +123 -0
- package/src/surfaces/ai-model-picker.json +114 -0
- package/src/surfaces/ai-model-picker.ts +139 -0
- package/src/surfaces/block-action-bar.json +640 -0
- package/src/surfaces/block-action-bar.ts +368 -0
- package/src/surfaces/bottom-dock.json +154 -0
- package/src/surfaces/bottom-dock.ts +125 -0
- package/src/surfaces/canvas-stage.json +444 -0
- package/src/surfaces/canvas-stage.ts +253 -0
- package/src/surfaces/cf-account-picker.json +300 -0
- package/src/surfaces/cf-account-picker.ts +214 -0
- package/src/surfaces/commandbar.json +985 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +417 -391
- package/src/surfaces/convert-repeater.json +309 -0
- package/src/surfaces/convert-repeater.ts +276 -0
- package/src/surfaces/data-actions.json +157 -0
- package/src/surfaces/data-actions.ts +115 -0
- package/src/surfaces/dialog.json +289 -0
- package/src/surfaces/dialog.ts +343 -0
- package/src/surfaces/diff-toolbar.json +266 -0
- package/src/surfaces/diff-toolbar.ts +139 -0
- package/src/surfaces/doc-header.json +739 -0
- package/src/surfaces/doc-header.ts +223 -0
- package/src/surfaces/empty-state.json +152 -0
- package/src/surfaces/empty-state.ts +173 -0
- package/src/surfaces/entry-editor.json +281 -0
- package/src/surfaces/entry-editor.ts +191 -0
- package/src/surfaces/expression-editor.json +977 -0
- package/src/surfaces/expression-editor.ts +266 -0
- package/src/surfaces/files-panel.json +592 -0
- package/src/surfaces/files-panel.ts +301 -0
- package/src/surfaces/formula-palette.json +364 -0
- package/src/surfaces/formula-palette.ts +340 -0
- package/src/surfaces/git-panel.json +1822 -0
- package/src/surfaces/git-panel.ts +272 -0
- package/src/surfaces/github-auth.json +112 -0
- package/src/surfaces/github-auth.ts +139 -0
- package/src/surfaces/github-publish.json +206 -0
- package/src/surfaces/github-publish.ts +169 -0
- package/src/surfaces/grid-cell.json +218 -0
- package/src/surfaces/grid-cell.ts +120 -0
- package/src/surfaces/grid-open.json +147 -0
- package/src/surfaces/grid-open.ts +87 -0
- package/src/surfaces/grid-panel.json +706 -0
- package/src/surfaces/grid-panel.ts +206 -0
- package/src/surfaces/grid-replace.json +179 -0
- package/src/surfaces/grid-replace.ts +89 -0
- package/src/surfaces/grid-views.json +446 -0
- package/src/surfaces/grid-views.ts +172 -0
- package/src/surfaces/inspector-dock.json +187 -0
- package/src/surfaces/inspector-dock.ts +161 -0
- package/src/surfaces/jump-bar.json +243 -0
- package/src/surfaces/jump-bar.ts +129 -0
- package/src/surfaces/jxsuite-update.json +146 -0
- package/src/surfaces/jxsuite-update.ts +149 -0
- package/src/surfaces/library-pane.json +1509 -0
- package/src/surfaces/library-pane.ts +363 -0
- package/src/surfaces/logic-panel.json +1949 -0
- package/src/surfaces/logic-panel.ts +369 -0
- package/src/surfaces/logic-workspace.json +685 -0
- package/src/surfaces/logic-workspace.ts +238 -0
- package/src/surfaces/media-browser.json +303 -0
- package/src/surfaces/media-browser.ts +145 -0
- package/src/surfaces/media-field.json +163 -0
- package/src/surfaces/media-field.ts +116 -0
- package/src/surfaces/media-pane.json +513 -0
- package/src/surfaces/media-pane.ts +197 -0
- package/src/surfaces/menu.json +232 -0
- package/src/surfaces/menu.ts +375 -0
- package/src/surfaces/navigator-dock.json +113 -0
- package/src/surfaces/navigator-dock.ts +130 -0
- package/src/surfaces/new-project.json +1654 -0
- package/src/surfaces/new-project.ts +411 -0
- package/src/surfaces/palette.json +535 -0
- package/src/surfaces/pane-context.json +1497 -0
- package/src/surfaces/pane-context.ts +513 -0
- package/src/surfaces/pane-grid.json +188 -0
- package/src/surfaces/pane-grid.ts +250 -0
- package/src/surfaces/panel-activity.json +563 -0
- package/src/surfaces/panel-activity.ts +187 -0
- package/src/surfaces/panel-data.json +141 -0
- package/src/surfaces/panel-data.ts +156 -0
- package/src/surfaces/panel-deploy-checklist.json +283 -0
- package/src/surfaces/panel-deploy-checklist.ts +175 -0
- package/src/surfaces/panel-elements.json +367 -0
- package/src/surfaces/panel-elements.ts +175 -0
- package/src/surfaces/panel-i18n.json +569 -0
- package/src/surfaces/panel-i18n.ts +212 -0
- package/src/surfaces/panel-imports.json +780 -0
- package/src/surfaces/panel-imports.ts +209 -0
- package/src/surfaces/panel-outline.json +734 -0
- package/src/surfaces/panel-outline.ts +326 -0
- package/src/surfaces/panel-page.json +1017 -0
- package/src/surfaces/panel-page.ts +240 -0
- package/src/surfaces/panel-problems.json +497 -0
- package/src/surfaces/panel-problems.ts +157 -0
- package/src/surfaces/panel-signals.json +1973 -0
- package/src/surfaces/panel-signals.ts +436 -0
- package/src/surfaces/panel-stylebook-layers.json +317 -0
- package/src/surfaces/panel-stylebook-layers.ts +155 -0
- package/src/surfaces/preferences.json +850 -0
- package/src/surfaces/preferences.ts +332 -0
- package/src/surfaces/progress-modal.json +110 -0
- package/src/surfaces/progress-modal.ts +150 -0
- package/src/surfaces/properties-panel.json +1578 -0
- package/src/surfaces/properties-panel.ts +337 -0
- package/src/surfaces/publish.json +945 -0
- package/src/surfaces/publish.ts +392 -0
- package/src/surfaces/push-plan.json +110 -0
- package/src/surfaces/push-plan.ts +87 -0
- package/src/surfaces/rail.json +255 -0
- package/src/surfaces/rail.ts +206 -0
- package/src/surfaces/reference-field.json +191 -0
- package/src/surfaces/reference-field.ts +168 -0
- package/src/surfaces/schema-builder.json +1011 -0
- package/src/surfaces/schema-builder.ts +181 -0
- package/src/surfaces/schema-form.json +1013 -0
- package/src/surfaces/schema-form.ts +287 -0
- package/src/surfaces/secret-field.json +60 -0
- package/src/surfaces/secret-field.ts +146 -0
- package/src/surfaces/seo.json +932 -0
- package/src/surfaces/seo.ts +334 -0
- package/src/surfaces/settings-contexts.json +538 -0
- package/src/surfaces/settings-contexts.ts +196 -0
- package/src/surfaces/settings-contributed.json +489 -0
- package/src/surfaces/settings-contributed.ts +199 -0
- package/src/surfaces/settings-css-vars.json +820 -0
- package/src/surfaces/settings-css-vars.ts +199 -0
- package/src/surfaces/settings-defs.json +1363 -0
- package/src/surfaces/settings-defs.ts +232 -0
- package/src/surfaces/settings-deploy.json +108 -0
- package/src/surfaces/settings-deploy.ts +135 -0
- package/src/surfaces/settings-extensions.json +486 -0
- package/src/surfaces/settings-extensions.ts +201 -0
- package/src/surfaces/settings-head.json +779 -0
- package/src/surfaces/settings-head.ts +397 -0
- package/src/surfaces/settings-locales.json +420 -0
- package/src/surfaces/settings-locales.ts +137 -0
- package/src/surfaces/settings-overview.json +423 -0
- package/src/surfaces/settings-overview.ts +218 -0
- package/src/surfaces/settings-packages.json +549 -0
- package/src/surfaces/settings-packages.ts +158 -0
- package/src/surfaces/settings-pane.json +147 -0
- package/src/surfaces/settings-pane.ts +150 -0
- package/src/surfaces/settings-rawjson.json +104 -0
- package/src/surfaces/settings-rawjson.ts +107 -0
- package/src/surfaces/shell.json +99 -0
- package/src/surfaces/shell.ts +30 -0
- package/src/surfaces/slash-menu.json +180 -0
- package/src/surfaces/slash-menu.ts +272 -0
- package/src/surfaces/statements.json +607 -0
- package/src/surfaces/statements.ts +238 -0
- package/src/surfaces/statusbar.json +94 -0
- package/src/{panels → surfaces}/statusbar.ts +164 -90
- package/src/surfaces/style-panel.json +1643 -0
- package/src/surfaces/style-panel.ts +338 -0
- package/src/surfaces/stylebook-chrome.json +122 -0
- package/src/surfaces/stylebook-chrome.ts +122 -0
- package/src/surfaces/tab-strip.json +448 -0
- package/src/surfaces/tab-strip.ts +200 -0
- package/src/surfaces/target-line.json +419 -0
- package/src/surfaces/target-line.ts +349 -0
- package/src/surfaces/toasts.json +189 -0
- package/src/surfaces/welcome.json +571 -0
- package/src/surfaces/welcome.ts +338 -0
- package/src/tabs/project-config.ts +111 -21
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +22 -0
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +54 -36
- package/src/ui/ai-model-picker.ts +75 -47
- package/src/ui/cf-account-picker.ts +76 -141
- package/src/ui/color-selector.ts +80 -301
- package/src/ui/dynamic-slot.ts +43 -283
- package/src/ui/expression-editor.ts +797 -576
- package/src/ui/field-input.ts +8 -181
- package/src/ui/form-controls.ts +838 -366
- package/src/ui/formula-chips.ts +80 -85
- package/src/ui/kit.ts +33 -0
- package/src/ui/layers.ts +296 -593
- package/src/ui/media-picker.ts +203 -284
- package/src/ui/panel-resize.ts +251 -64
- package/src/ui/popover-surface.ts +153 -0
- package/src/ui/progress-modal.ts +22 -60
- package/src/ui/regions.ts +13 -7
- package/src/ui/schema-form.ts +906 -440
- package/src/ui/surface.ts +122 -0
- package/src/ui/unit-selector.ts +15 -131
- package/src/ui/value-source.ts +14 -0
- package/src/ui/virtual-window.ts +88 -9
- package/src/utils/canvas-media.ts +72 -0
- package/src/utils/edit-display.ts +7 -2
- package/src/utils/element-selectors.ts +69 -0
- package/src/utils/link-target.ts +2 -2
- package/src/utils/studio-utils.ts +0 -10
- package/src/view.ts +15 -0
- package/src/workspace/pane-derive.ts +36 -14
- package/src/workspace/workspace.ts +75 -6
- package/styles/canvas.css +72 -467
- package/styles/forced-colors.css +48 -82
- package/styles/forced-colors.json +41 -0
- package/styles/inspector.css +2 -1301
- package/styles/overlays.css +96 -2823
- package/styles/panels.css +6 -1423
- package/styles/shell-frame.css +272 -0
- package/styles/shell-frame.json +227 -0
- package/styles/shell.css +0 -1568
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-48xg86wj.js +0 -49
- package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
- package/dist/chunks/extension-sections-txv08xxg.js +0 -311
- package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
- package/dist/chunks/files-3kfkwhk4.js +0 -93
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-w16q81tf.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-532whr1y.js +0 -59
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
- package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
- package/dist/chunks/layers-q75tj2mf.js +0 -45
- package/dist/chunks/lit-html-j055mkh8.js +0 -22
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
- package/dist/chunks/notify-yjm79n4s.js +0 -30
- package/dist/chunks/parse-24d0gay3.js +0 -19
- package/dist/chunks/platform-ba1j1gbh.js +0 -16
- package/dist/chunks/publish-panel-v9st96ja.js +0 -29
- package/dist/chunks/quick-search-zccjp6gv.js +0 -66
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
- package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
- package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
- package/dist/chunks/studio-0a5qrh01.js +0 -3
- package/dist/chunks/studio-0bq6eh7v.js +0 -12
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1ngbejft.js +0 -181
- package/dist/chunks/studio-4b5z1x43.js +0 -424
- package/dist/chunks/studio-4n2b5gzb.js +0 -357
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5fx3g9jg.js +0 -4325
- package/dist/chunks/studio-5myknm0a.js +0 -1903
- package/dist/chunks/studio-7afd21nw.js +0 -67
- package/dist/chunks/studio-7nte2hj4.js +0 -613
- package/dist/chunks/studio-8jpzqk5s.js +0 -128
- package/dist/chunks/studio-8q517dfr.js +0 -24
- package/dist/chunks/studio-950k0dx6.js +0 -6939
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-bgxt93ga.js +0 -62
- package/dist/chunks/studio-cmb03bg5.js +0 -13890
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-ef49pnzx.js +0 -387
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ew0djmhg.js +0 -341
- package/dist/chunks/studio-gfgb8pe6.js +0 -1652
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-jc994dnr.js +0 -1066
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mtfnaqs9.js +0 -659
- package/dist/chunks/studio-n6j9t10q.js +0 -318
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-qcy05dp8.js +0 -1743
- package/dist/chunks/studio-qq6jym04.js +0 -53
- package/dist/chunks/studio-rdx8jcxy.js +0 -83
- package/dist/chunks/studio-rn9ta2mz.js +0 -111
- package/dist/chunks/studio-t7qb9db8.js +0 -665
- package/dist/chunks/studio-tmc5emrw.js +0 -8
- package/dist/chunks/studio-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/studio-zqazsct2.js +0 -1823
- package/dist/chunks/workspace-fjx52ryv.js +0 -89
- package/src/panels/activity-bar.ts +0 -251
- package/src/panels/panel-scheduler.ts +0 -219
- package/src/panels/style-inputs.ts +0 -237
- package/src/panels/target-line.ts +0 -274
- package/src/panels/welcome-screen.ts +0 -346
- package/src/ui/button-group.ts +0 -102
- package/src/ui/choice-field.ts +0 -72
- package/src/ui/field-row.ts +0 -249
- package/src/ui/formula-palette.ts +0 -213
- package/src/ui/icons.ts +0 -52
- package/src/ui/jx-theme.ts +0 -130
- package/src/ui/spectrum.ts +0 -340
- package/src/ui/value-selector.ts +0 -174
- package/src/ui/widgets.ts +0 -172
- /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
- /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
- /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
- /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
/// <reference lib="dom" />
|
|
2
|
+
/**
|
|
3
|
+
* Start pane — the pane-grid surface shown when no project is loaded and no document tabs are open.
|
|
4
|
+
*
|
|
5
|
+
* Three regions, in the order a first run needs them: **Start** (the ways to get a project in front
|
|
6
|
+
* of you), **Recent** (projects you have opened, identified by name + the folder that tells two
|
|
7
|
+
* same-named projects apart + when you last opened them), and **Projects** (the catalogue a cloud
|
|
8
|
+
* platform enumerates). A repository-access prompt sits above them when the account has no GitHub
|
|
9
|
+
* App installation yet, because nothing else on the pane can succeed until it does.
|
|
10
|
+
*
|
|
11
|
+
* Recents never render a raw absolute path: `recentLocations()` gives every row the shortest
|
|
12
|
+
* trailing path that distinguishes it from the other rows sharing its name.
|
|
13
|
+
*
|
|
14
|
+
* The pane is the `welcome` surface (`surfaces/welcome.json`): this module is the projection —
|
|
15
|
+
* which start actions the platform offers, the recents with their labels, the catalogue minus the
|
|
16
|
+
* recents — and the four things a click can do. The scope is reactive, so a removed recent
|
|
17
|
+
* reconciles in place.
|
|
18
|
+
*
|
|
19
|
+
* @docs studio/interface/welcome-screen
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
import { getAccountStatus, needsAppInstall } from "../account-status";
|
|
23
|
+
import { platformSupportsAddRepo } from "../new-project/add-repo-modal";
|
|
24
|
+
import { getProjectList } from "../project-list";
|
|
25
|
+
import { reactive } from "../reactivity";
|
|
26
|
+
import { now } from "../services/clock";
|
|
27
|
+
import { clearRecentProjects, getRecentProjects, removeRecentProject } from "../recent-projects";
|
|
28
|
+
import { platformSupportsClone } from "../panels/git-panel";
|
|
29
|
+
import { mountSurface, registerSurface } from "../ui/surface";
|
|
30
|
+
import welcomeDoc from "./welcome.json";
|
|
31
|
+
import type { JxDocument } from "@jxsuite/schema/types";
|
|
32
|
+
import type { SurfaceHandle } from "../ui/surface";
|
|
33
|
+
|
|
34
|
+
registerSurface("welcome", welcomeDoc as unknown as JxDocument);
|
|
35
|
+
|
|
36
|
+
interface WelcomeCtx {
|
|
37
|
+
openProject: () => void;
|
|
38
|
+
openRecentProject: (root: string) => void;
|
|
39
|
+
openNewProject: (options?: { tab?: "starter" }) => void;
|
|
40
|
+
cloneRepository: () => void;
|
|
41
|
+
addExistingRepo: () => void;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
let _ctx: WelcomeCtx | null = null;
|
|
45
|
+
|
|
46
|
+
/** @param {WelcomeCtx} ctx */
|
|
47
|
+
export function initWelcome(ctx: WelcomeCtx) {
|
|
48
|
+
_ctx = ctx;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// ─── Location labels ──────────────────────────────────────────────────────────
|
|
52
|
+
|
|
53
|
+
/** Home-relative form of an absolute path (`/home/you/x` → `~/x`); other paths are unchanged. */
|
|
54
|
+
export function shortenPath(path: string): string {
|
|
55
|
+
const match = /^\/(?:home|Users)\/[^/]+(?=\/|$)/.exec(path);
|
|
56
|
+
return match ? `~${path.slice(match[0].length)}` : path;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** The ancestor segments of a root, home-shortened — everything above the project folder itself. */
|
|
60
|
+
function ancestorSegments(root: string): string[] {
|
|
61
|
+
const segments = shortenPath(root).split("/").filter(Boolean);
|
|
62
|
+
return segments.slice(0, -1);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The last `depth` ancestor folders of a root, as a path. Truncated labels lead with `…/`; a
|
|
67
|
+
* complete absolute one keeps its leading `/`, so the string always says how much it is showing.
|
|
68
|
+
*/
|
|
69
|
+
function ancestorLabel(root: string, depth: number): string {
|
|
70
|
+
const segments = ancestorSegments(root);
|
|
71
|
+
if (segments.length === 0) {
|
|
72
|
+
return shortenPath(root);
|
|
73
|
+
}
|
|
74
|
+
const tail = segments.slice(Math.max(0, segments.length - depth));
|
|
75
|
+
if (tail.length < segments.length) {
|
|
76
|
+
return `…/${tail.join("/")}`;
|
|
77
|
+
}
|
|
78
|
+
return tail[0] === "~" || !root.startsWith("/") ? tail.join("/") : `/${tail.join("/")}`;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The location line for each entry: the shortest trailing path that tells apart the entries sharing
|
|
83
|
+
* a display name. One folder deep is enough for almost every list; same-named projects under the
|
|
84
|
+
* same parent fall back to their whole home-shortened root, which is unique because roots are.
|
|
85
|
+
*
|
|
86
|
+
* @param entries Projects to label, in any order.
|
|
87
|
+
* @returns Root → location label, one entry per distinct root.
|
|
88
|
+
*/
|
|
89
|
+
export function recentLocations(
|
|
90
|
+
entries: readonly { name: string; root: string }[],
|
|
91
|
+
): Map<string, string> {
|
|
92
|
+
const groups = new Map<string, { name: string; root: string }[]>();
|
|
93
|
+
for (const entry of entries) {
|
|
94
|
+
const group = groups.get(entry.name);
|
|
95
|
+
if (group) {
|
|
96
|
+
group.push(entry);
|
|
97
|
+
} else {
|
|
98
|
+
groups.set(entry.name, [entry]);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const labels = new Map<string, string>();
|
|
103
|
+
for (const group of groups.values()) {
|
|
104
|
+
const maxDepth = Math.max(...group.map((e) => ancestorSegments(e.root).length), 1);
|
|
105
|
+
let chosen = group.map((e) => ancestorLabel(e.root, maxDepth));
|
|
106
|
+
for (let depth = 1; depth <= maxDepth; depth++) {
|
|
107
|
+
const candidate = group.map((e) => ancestorLabel(e.root, depth));
|
|
108
|
+
if (new Set(candidate).size === group.length) {
|
|
109
|
+
chosen = candidate;
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (new Set(chosen).size !== group.length) {
|
|
114
|
+
chosen = group.map((e) => shortenPath(e.root));
|
|
115
|
+
}
|
|
116
|
+
for (const [index, entry] of group.entries()) {
|
|
117
|
+
labels.set(entry.root, chosen[index]!);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return labels;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const MINUTE = 60_000;
|
|
124
|
+
const HOUR = 60 * MINUTE;
|
|
125
|
+
const DAY = 24 * HOUR;
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* "When you last opened it", in the coarse units a project list is read in. Deliberately vague past
|
|
129
|
+
* a week — the exact timestamp is in the row's tooltip.
|
|
130
|
+
*
|
|
131
|
+
* @param timestamp Epoch milliseconds.
|
|
132
|
+
* @param at Epoch milliseconds to measure against. Defaults to the {@link now} seam, so a pinned
|
|
133
|
+
* clock makes "last opened" answer the same on every read.
|
|
134
|
+
*/
|
|
135
|
+
export function lastOpenedLabel(timestamp: number, at: number = now()): string {
|
|
136
|
+
const elapsed = Math.max(0, at - timestamp);
|
|
137
|
+
if (elapsed < MINUTE) {
|
|
138
|
+
return "just now";
|
|
139
|
+
}
|
|
140
|
+
if (elapsed < HOUR) {
|
|
141
|
+
const minutes = Math.floor(elapsed / MINUTE);
|
|
142
|
+
return `${minutes} minute${minutes === 1 ? "" : "s"} ago`;
|
|
143
|
+
}
|
|
144
|
+
if (elapsed < DAY) {
|
|
145
|
+
const hours = Math.floor(elapsed / HOUR);
|
|
146
|
+
return `${hours} hour${hours === 1 ? "" : "s"} ago`;
|
|
147
|
+
}
|
|
148
|
+
const days = Math.floor(elapsed / DAY);
|
|
149
|
+
if (days === 1) {
|
|
150
|
+
return "yesterday";
|
|
151
|
+
}
|
|
152
|
+
if (days < 30) {
|
|
153
|
+
return `${days} days ago`;
|
|
154
|
+
}
|
|
155
|
+
const months = Math.floor(days / 30);
|
|
156
|
+
return months < 12 ? `${months} month${months === 1 ? "" : "s"} ago` : "over a year ago";
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// ─── The surface ──────────────────────────────────────────────────────────────
|
|
160
|
+
|
|
161
|
+
/** One Start-list action: a labelled, icon-led button, run through `run`. */
|
|
162
|
+
interface StartAction {
|
|
163
|
+
id: "new" | "open" | "clone" | "add";
|
|
164
|
+
title: string;
|
|
165
|
+
icon: string;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
interface RecentRow {
|
|
169
|
+
root: string;
|
|
170
|
+
name: string;
|
|
171
|
+
location: string;
|
|
172
|
+
when: string;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface CatalogueRow {
|
|
176
|
+
root: string;
|
|
177
|
+
name: string;
|
|
178
|
+
detail: string;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
interface WelcomeScope extends Record<string, unknown> {
|
|
182
|
+
actions: StartAction[];
|
|
183
|
+
installNeeded: boolean;
|
|
184
|
+
installUrl: string;
|
|
185
|
+
hasRecent: boolean;
|
|
186
|
+
recent: RecentRow[];
|
|
187
|
+
hasCatalogue: boolean;
|
|
188
|
+
catalogue: CatalogueRow[];
|
|
189
|
+
run: (id: string) => void;
|
|
190
|
+
open: (root: string) => void;
|
|
191
|
+
remove: (root: string) => void;
|
|
192
|
+
clear: () => void;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
let _state: WelcomeScope | null = null;
|
|
196
|
+
let _host: HTMLElement | null = null;
|
|
197
|
+
let _mount: Promise<SurfaceHandle> | null = null;
|
|
198
|
+
let _handle: SurfaceHandle | null = null;
|
|
199
|
+
|
|
200
|
+
/** The pane, as the surface reads it, from the platform and the stores as they stand now. */
|
|
201
|
+
function project(): Omit<WelcomeScope, "run" | "open" | "remove" | "clear"> {
|
|
202
|
+
const recent = getRecentProjects();
|
|
203
|
+
// Catalogue entries already in Recent stay in that section only.
|
|
204
|
+
const catalogue = getProjectList().filter((p) => !recent.some((r) => r.root === p.root));
|
|
205
|
+
const recentLabels = recentLocations(recent);
|
|
206
|
+
const catalogueLabels = recentLocations(catalogue);
|
|
207
|
+
const actions: StartAction[] = [
|
|
208
|
+
// One entry, not two: the starter gallery IS the first step of New Project now, so the
|
|
209
|
+
// Separate "Start from an Example…" button it used to hide behind is gone.
|
|
210
|
+
{ icon: "plus", id: "new", title: "New Project…" },
|
|
211
|
+
{ icon: "folder-open", id: "open", title: "Open Project…" },
|
|
212
|
+
...(platformSupportsClone()
|
|
213
|
+
? [{ icon: "download-simple", id: "clone", title: "Clone Git Repository…" } as const]
|
|
214
|
+
: []),
|
|
215
|
+
...(platformSupportsAddRepo()
|
|
216
|
+
? [{ icon: "cube", id: "add", title: "Add Existing Repository…" } as const]
|
|
217
|
+
: []),
|
|
218
|
+
];
|
|
219
|
+
return {
|
|
220
|
+
actions,
|
|
221
|
+
catalogue: catalogue.map((entry) => ({
|
|
222
|
+
detail: entry.description ?? catalogueLabels.get(entry.root) ?? entry.root,
|
|
223
|
+
name: entry.name,
|
|
224
|
+
root: entry.root,
|
|
225
|
+
})),
|
|
226
|
+
hasCatalogue: catalogue.length > 0,
|
|
227
|
+
hasRecent: recent.length > 0,
|
|
228
|
+
/* The GitHub-App install prompt, gated on `needsAppInstall()`: the account is connected,
|
|
229
|
+
reports zero installations, and told us where to fix that — the recovery path for the
|
|
230
|
+
structured needs-installation 403 that `platform-errors.ts` decodes. */
|
|
231
|
+
installNeeded: needsAppInstall(),
|
|
232
|
+
installUrl: getAccountStatus()?.appInstallUrl ?? "#",
|
|
233
|
+
recent: recent.map((entry) => ({
|
|
234
|
+
location: recentLabels.get(entry.root) ?? entry.root,
|
|
235
|
+
name: entry.name,
|
|
236
|
+
root: entry.root,
|
|
237
|
+
when: lastOpenedLabel(entry.timestamp),
|
|
238
|
+
})),
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** The reactive scope the surface reads, made once. */
|
|
243
|
+
function state(): WelcomeScope {
|
|
244
|
+
_state ??= reactive({
|
|
245
|
+
actions: [],
|
|
246
|
+
catalogue: [],
|
|
247
|
+
clear: () => {
|
|
248
|
+
clearRecentProjects();
|
|
249
|
+
refresh();
|
|
250
|
+
},
|
|
251
|
+
hasCatalogue: false,
|
|
252
|
+
hasRecent: false,
|
|
253
|
+
installNeeded: false,
|
|
254
|
+
installUrl: "#",
|
|
255
|
+
open: (root: string) => {
|
|
256
|
+
_ctx?.openRecentProject(root);
|
|
257
|
+
},
|
|
258
|
+
recent: [],
|
|
259
|
+
remove: (root: string) => {
|
|
260
|
+
removeRecentProject(root);
|
|
261
|
+
refresh();
|
|
262
|
+
},
|
|
263
|
+
run: (id: string) => {
|
|
264
|
+
switch (id) {
|
|
265
|
+
case "new": {
|
|
266
|
+
_ctx?.openNewProject();
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
case "open": {
|
|
270
|
+
_ctx?.openProject();
|
|
271
|
+
break;
|
|
272
|
+
}
|
|
273
|
+
case "clone": {
|
|
274
|
+
_ctx?.cloneRepository();
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
case "add": {
|
|
278
|
+
_ctx?.addExistingRepo();
|
|
279
|
+
break;
|
|
280
|
+
}
|
|
281
|
+
default: {
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
},
|
|
286
|
+
}) as WelcomeScope;
|
|
287
|
+
return _state;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/** Recompute the projection; the surface follows. */
|
|
291
|
+
function refresh(): void {
|
|
292
|
+
Object.assign(state(), project());
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/**
|
|
296
|
+
* Draw the pane into `host`, or bring the one already there up to date.
|
|
297
|
+
*
|
|
298
|
+
* The canvas calls this on every render while nothing is open, into the same wrap it clears when
|
|
299
|
+
* something opens — so a mount whose root has since left the document is disposed and remade, and
|
|
300
|
+
* one still standing is only refreshed.
|
|
301
|
+
*
|
|
302
|
+
* @param {HTMLElement} host
|
|
303
|
+
*/
|
|
304
|
+
export function renderWelcome(host: HTMLElement): void {
|
|
305
|
+
refresh();
|
|
306
|
+
const standing = _host === host && _handle !== null && _handle.root.isConnected;
|
|
307
|
+
if (standing) {
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
if (_mount && _host === host && !_handle) {
|
|
311
|
+
// Still mounting into this very host.
|
|
312
|
+
return;
|
|
313
|
+
}
|
|
314
|
+
disposeWelcome();
|
|
315
|
+
_host = host;
|
|
316
|
+
const pending = mountSurface("welcome", state(), host);
|
|
317
|
+
_mount = pending;
|
|
318
|
+
void pending.then((handle) => {
|
|
319
|
+
if (_mount === pending) {
|
|
320
|
+
_handle = handle;
|
|
321
|
+
} else {
|
|
322
|
+
handle.dispose();
|
|
323
|
+
}
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
/** Take the pane down and forget its host. */
|
|
328
|
+
export function disposeWelcome(): void {
|
|
329
|
+
const pending = _mount;
|
|
330
|
+
_mount = null;
|
|
331
|
+
if (_handle) {
|
|
332
|
+
_handle.dispose();
|
|
333
|
+
_handle = null;
|
|
334
|
+
} else if (pending) {
|
|
335
|
+
void pending.then((handle) => handle.dispose());
|
|
336
|
+
}
|
|
337
|
+
_host = null;
|
|
338
|
+
}
|
|
@@ -33,21 +33,30 @@
|
|
|
33
33
|
* from the other side: a config that reached disk without passing through here (the assistant's
|
|
34
34
|
* `write_file`) is put INTO the document rather than left beside it as a rival.
|
|
35
35
|
*
|
|
36
|
-
* **One serialisation.** {@link serializeProjectConfig} is `
|
|
37
|
-
* byte-for-byte what `files/
|
|
38
|
-
* settings edit produce the same file. The predecessor
|
|
39
|
-
* `"\t"` in both `settings/contributed-section.ts` and
|
|
40
|
-
* edit re-indented the entire file — every `project.json`
|
|
41
|
-
* spaces.
|
|
36
|
+
* **One serialisation.** {@link serializeProjectConfig} is `files/json-layout.ts`'s serializer over
|
|
37
|
+
* the layout the file was read in — byte-for-byte what `files/serialize-document.ts`'s native-JSON
|
|
38
|
+
* branch writes, so a ⌘S on the open tab and a settings edit produce the same file. The predecessor
|
|
39
|
+
* had `null, 2` in `site-context.ts` and `"\t"` in both `settings/contributed-section.ts` and
|
|
40
|
+
* `settings/defs-editor.ts`, so a settings edit re-indented the entire file — every `project.json`
|
|
41
|
+
* in this repository is on disk with two spaces. It was then `JSON.stringify(config, null, 2)`,
|
|
42
|
+
* which agreed with the tab's save and disagreed with the formatter: a one-field edit re-laid every
|
|
43
|
+
* short array in the file (issue 308).
|
|
42
44
|
*
|
|
43
45
|
* **A no-op edit writes nothing.** A form that re-commits the value it already holds — and every
|
|
44
46
|
* one of these surfaces has such a path — used to rewrite the whole file. A commit now compares the
|
|
45
47
|
* serialised result against what the file itself says and returns without a transaction, without a
|
|
46
48
|
* write, and therefore with an empty diff.
|
|
47
49
|
*
|
|
50
|
+
* **A real edit is a one-line diff.** The file's layout — which objects sit on one line, where a
|
|
51
|
+
* blank line falls — is read once per binding ({@link seedCommitted}), replaced by the record of
|
|
52
|
+
* whatever bytes reached the file another way ({@link adoptProjectConfig}), and every serialisation
|
|
53
|
+
* here honours it, so what changes on disk is the field that changed.
|
|
54
|
+
*
|
|
48
55
|
* **Collaboration.** `project.json` is out of collab replication; the gate is in
|
|
49
56
|
* `collab/collab-session.ts`'s `ensureCollab`, which is what would otherwise register the Yjs
|
|
50
57
|
* history delegate over this tab.
|
|
58
|
+
*
|
|
59
|
+
* @docs studio/projects/settings
|
|
51
60
|
*/
|
|
52
61
|
|
|
53
62
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
@@ -58,6 +67,8 @@ import { requireProjectState, setProjectState } from "../state";
|
|
|
58
67
|
import { setWorkspaceProject, workspace } from "../workspace/workspace";
|
|
59
68
|
import { PROJECT_CONFIG_PATH, createTab, disposeTab } from "./tab";
|
|
60
69
|
import { transactDoc } from "./transact";
|
|
70
|
+
import { deriveJsonLayout, parseJsonDocument, serializeJson } from "../files/json-layout";
|
|
71
|
+
import type { JsonLayout } from "../files/json-layout";
|
|
61
72
|
|
|
62
73
|
import type { Tab } from "./tab";
|
|
63
74
|
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
@@ -67,15 +78,16 @@ export { PROJECT_CONFIG_PATH } from "./tab";
|
|
|
67
78
|
/**
|
|
68
79
|
* The project configuration, as a file.
|
|
69
80
|
*
|
|
70
|
-
* The ONE serialisation. Identical to the native-JSON branch of `files/
|
|
81
|
+
* The ONE serialisation. Identical to the native-JSON branch of `files/serialize-document.ts`'s
|
|
71
82
|
* `serializeDocument`, which is what ⌘S on the open `project.json` tab goes through — the two must
|
|
72
|
-
* agree or every save would fight the last one.
|
|
83
|
+
* agree or every save would fight the last one. Both honour the layout the file was read in ({@link
|
|
84
|
+
* configLayout}); with none known, the formatter's layout for fresh output.
|
|
73
85
|
*
|
|
74
86
|
* @param {ProjectConfig} config
|
|
75
87
|
* @returns {string}
|
|
76
88
|
*/
|
|
77
89
|
export function serializeProjectConfig(config: ProjectConfig): string {
|
|
78
|
-
return
|
|
90
|
+
return serializeJson(config, configLayout());
|
|
79
91
|
}
|
|
80
92
|
|
|
81
93
|
// ─── The document of record ───────────────────────────────────────────────────
|
|
@@ -94,15 +106,35 @@ let _detached: Tab | null = null;
|
|
|
94
106
|
* variables editor writes into `config.style` and then hands the same object over as a patch. A
|
|
95
107
|
* value taken from memory would call every one of those edits a no-op.
|
|
96
108
|
*
|
|
97
|
-
* Comparing two
|
|
98
|
-
* not a textual one, which is the point: `project.json`
|
|
99
|
-
*
|
|
100
|
-
*
|
|
109
|
+
* Comparing two renderings of the same key order through the same serializer is a SEMANTIC test,
|
|
110
|
+
* not a textual one, which is the point: a `project.json` formatted some other way than the
|
|
111
|
+
* serializer would lay it out — every array expanded, say — would otherwise look changed on every
|
|
112
|
+
* commit, and a byte comparison against the file would rewrite it whole. This calls it unchanged
|
|
113
|
+
* and writes nothing.
|
|
101
114
|
*
|
|
102
115
|
* `null` means "unknown" — no project file, or one that would not parse — and every commit writes.
|
|
103
116
|
*/
|
|
104
117
|
let _committed: string | null = null;
|
|
105
118
|
|
|
119
|
+
/**
|
|
120
|
+
* The layout the file was read in ({@link seedCommitted}) or last written in ({@link
|
|
121
|
+
* adoptProjectConfig}), for a binding with no open tab to carry it. Reset with the binding: a
|
|
122
|
+
* different project is a different file.
|
|
123
|
+
*/
|
|
124
|
+
let _layout: JsonLayout | null = null;
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* The layout a configuration write honours.
|
|
128
|
+
*
|
|
129
|
+
* The open tab's, when there is one — it read the file when it opened, or was lent the seed's
|
|
130
|
+
* record ({@link lendProjectConfigLayout}), and a source-view commit or a reload from disk keeps it
|
|
131
|
+
* current — and otherwise what the seed read. The two describe the same file, so the choice only
|
|
132
|
+
* matters for freshness, and the tab is the fresher.
|
|
133
|
+
*/
|
|
134
|
+
function configLayout(): JsonLayout | null {
|
|
135
|
+
return openConfigTab()?.doc.layout ?? _layout;
|
|
136
|
+
}
|
|
137
|
+
|
|
106
138
|
/** Whether {@link _committed} has been sought for the current binding. One read per project. */
|
|
107
139
|
let _seeding: Promise<void> | null = null;
|
|
108
140
|
|
|
@@ -126,6 +158,7 @@ function unbind(): void {
|
|
|
126
158
|
}
|
|
127
159
|
_bound = null;
|
|
128
160
|
_committed = null;
|
|
161
|
+
_layout = null;
|
|
129
162
|
_seeding = null;
|
|
130
163
|
}
|
|
131
164
|
|
|
@@ -134,7 +167,9 @@ function seedCommitted(): Promise<void> {
|
|
|
134
167
|
_seeding ??= (async () => {
|
|
135
168
|
try {
|
|
136
169
|
const text = await getPlatform().readFile(PROJECT_CONFIG_PATH);
|
|
137
|
-
|
|
170
|
+
const { document, layout } = parseJsonDocument(text);
|
|
171
|
+
_layout = layout;
|
|
172
|
+
_committed = serializeProjectConfig(document as unknown as ProjectConfig);
|
|
138
173
|
} catch {
|
|
139
174
|
// No file, an unreadable one, or one that does not parse. "Unknown" is the honest answer,
|
|
140
175
|
// And an unknown file is one every commit must write.
|
|
@@ -144,6 +179,29 @@ function seedCommitted(): Promise<void> {
|
|
|
144
179
|
return _seeding;
|
|
145
180
|
}
|
|
146
181
|
|
|
182
|
+
/**
|
|
183
|
+
* Lend the file's layout to `tab` when it has none of its own.
|
|
184
|
+
*
|
|
185
|
+
* The Settings door (`settings/settings-document.ts`) opens the `project.json` tab over the
|
|
186
|
+
* configuration object the project was loaded with — an object the platform parsed, with no text
|
|
187
|
+
* behind it — so that tab arrives with `doc.layout === null`. Left there, a ⌘S on it would write
|
|
188
|
+
* the formatter's layout for fresh output while a settings commit on the SAME document wrote the
|
|
189
|
+
* file's: every short object in the file blown open by the save the settings edit had just kept,
|
|
190
|
+
* which is the one disagreement this module exists to make impossible. The file is read once per
|
|
191
|
+
* binding anyway ({@link seedCommitted}); this hands the record that read made to the tab, and
|
|
192
|
+
* {@link configLayout} then takes it back from the tab like every other writer. A tab that read the
|
|
193
|
+
* file itself — the Files tree, a reload, a source-view commit — keeps the fresher record it has.
|
|
194
|
+
*
|
|
195
|
+
* @param {Tab} tab
|
|
196
|
+
* @returns {Promise<void>}
|
|
197
|
+
*/
|
|
198
|
+
export async function lendProjectConfigLayout(tab: Tab): Promise<void> {
|
|
199
|
+
await seedCommitted();
|
|
200
|
+
if (tab.doc.layout === null && _layout !== null) {
|
|
201
|
+
tab.doc.layout = _layout;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
147
205
|
/**
|
|
148
206
|
* Forget the configuration document — the project-switch and test hook.
|
|
149
207
|
*
|
|
@@ -187,16 +245,28 @@ function liveConfig(): ProjectConfig | null {
|
|
|
187
245
|
}
|
|
188
246
|
|
|
189
247
|
/**
|
|
190
|
-
* Make `target` hold exactly `source`'s keys
|
|
248
|
+
* Make `target` hold exactly `source`'s keys, in `source`'s ORDER.
|
|
249
|
+
*
|
|
250
|
+
* Every key goes, the ones `source` keeps included, before `source` is assigned over the empty
|
|
251
|
+
* object. Assignment alone would leave the removals behind; deleting only the removals would leave
|
|
252
|
+
* the ORDER behind, because a key that survives keeps the position it had and only a new one takes
|
|
253
|
+
* `source`'s. Key order is what the serializer writes the file in, so a document holding the
|
|
254
|
+
* assistant's configuration in the previous file's order re-lays the file the assistant just wrote
|
|
255
|
+
* on the next commit — even a no-op one, which then disagrees with {@link _committed} (issue 331).
|
|
256
|
+
* The rival handover in {@link commitProjectConfig} is the same case from the other side: the
|
|
257
|
+
* object of record is the source, and its order is the file's.
|
|
258
|
+
*
|
|
259
|
+
* The transient — an observer of a single key would see it gone and back within the transaction —
|
|
260
|
+
* is one the removals already had, and nothing observes the configuration document key by key: the
|
|
261
|
+
* settings surfaces render from `projectState` and mutate it in place, and every reader of the
|
|
262
|
+
* document follows the root reference {@link transactDoc} replaces when the transaction ends.
|
|
191
263
|
*
|
|
192
264
|
* @param {Record<string, unknown>} target
|
|
193
265
|
* @param {ProjectConfig} source
|
|
194
266
|
*/
|
|
195
267
|
function replaceContents(target: Record<string, unknown>, source: ProjectConfig): void {
|
|
196
268
|
for (const key of Object.keys(target)) {
|
|
197
|
-
|
|
198
|
-
delete target[key];
|
|
199
|
-
}
|
|
269
|
+
delete target[key];
|
|
200
270
|
}
|
|
201
271
|
Object.assign(target, source);
|
|
202
272
|
}
|
|
@@ -307,7 +377,9 @@ export async function commitProjectConfig(
|
|
|
307
377
|
// Tab's own parse, and the caller has already mutated the object it rendered from.
|
|
308
378
|
const live = liveConfig();
|
|
309
379
|
const tab = projectConfigDocument();
|
|
310
|
-
|
|
380
|
+
// The seed, and the record it read handed to the document — so the tab the Settings door opened
|
|
381
|
+
// Writes the same bytes from ⌘S that this commit is about to.
|
|
382
|
+
await lendProjectConfigLayout(tab);
|
|
311
383
|
const current = toRaw(tab.doc.document) as unknown as ProjectConfig;
|
|
312
384
|
const currentText = serializeProjectConfig(current);
|
|
313
385
|
|
|
@@ -388,14 +460,26 @@ export async function commitProjectConfig(
|
|
|
388
460
|
* assistant's write back out of existence. Putting the bytes into the document instead keeps the
|
|
389
461
|
* one-object rule true, and the state sync follows from the bind effect like every other change.
|
|
390
462
|
*
|
|
463
|
+
* **The layout record travels with the write.** The assistant authored the whole file, and the text
|
|
464
|
+
* it wrote is the file now — so the record the next commit honours is derived from THAT text
|
|
465
|
+
* (`json-layout.ts`'s `deriveJsonLayout`), exactly as a reload from disk would derive it, and it
|
|
466
|
+
* replaces both the seed's record and the open tab's. Keeping the record the chokepoint read BEFORE
|
|
467
|
+
* the write is what turned the settings edit after an assistant rewrite into a whole-file diff: the
|
|
468
|
+
* file was on disk in the assistant's layout and the commit re-laid it in the previous one (issue
|
|
469
|
+
* 331). The key order travels the same way: {@link replaceContents} installs `config`'s order on
|
|
470
|
+
* the document, so a rewrite that moved a top-level key stays moved. Nothing here re-reads the file
|
|
471
|
+
* to learn any of this: the caller just produced the bytes, and a second parse of `project.json` is
|
|
472
|
+
* the rival object this door exists to prevent.
|
|
473
|
+
*
|
|
391
474
|
* `skipHistory`, because this is a RELOAD and not an edit: the file already says this, and
|
|
392
475
|
* `write_file` tells the model in as many words that its disk writes are not undoable. A history
|
|
393
476
|
* entry here would offer ⌘Z a change it could not take back from the file.
|
|
394
477
|
*
|
|
395
478
|
* @param {ProjectConfig} config The configuration as written — already past the schema gate.
|
|
479
|
+
* @param {string} text The bytes that reached the file, which `config` is the parse of.
|
|
396
480
|
* @returns {Promise<void>}
|
|
397
481
|
*/
|
|
398
|
-
export async function adoptProjectConfig(config: ProjectConfig): Promise<void> {
|
|
482
|
+
export async function adoptProjectConfig(config: ProjectConfig, text: string): Promise<void> {
|
|
399
483
|
if (!requireProjectState()) {
|
|
400
484
|
// No project state is no configuration document either ({@link projectConfigDocument} reads
|
|
401
485
|
// One). The workspace copy is then the only thing there is to keep true.
|
|
@@ -410,7 +494,13 @@ export async function adoptProjectConfig(config: ProjectConfig): Promise<void> {
|
|
|
410
494
|
);
|
|
411
495
|
tab.doc.dirty = false;
|
|
412
496
|
// Settle a read already in flight before saying what the file holds, or it would resolve after
|
|
413
|
-
//
|
|
497
|
+
// These lines with the PREVIOUS bytes and record, and make the next real commit look like a
|
|
498
|
+
// No-op — or re-lay the file the assistant just formatted.
|
|
414
499
|
await seedCommitted();
|
|
500
|
+
// The record of the bytes just written, on the tab as well as on the seed: `configLayout`
|
|
501
|
+
// Prefers the open tab's, and the tab's is the record of the file it opened, which the write has
|
|
502
|
+
// Just replaced. The tab holds the config now; it holds the config's layout too.
|
|
503
|
+
_layout = deriveJsonLayout(text);
|
|
504
|
+
tab.doc.layout = _layout;
|
|
415
505
|
_committed = serializeProjectConfig(config);
|
|
416
506
|
}
|