@jxsuite/studio 5.3.0 → 5.4.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/data/css-meta.json +28 -27
- package/dist/chunks/{cf-account-picker-nwnwdm6p.js → cf-account-picker-3f08rry6.js} +21 -18
- package/dist/chunks/{cf-settings-adg74qsk.js → cf-settings-m79r7p5y.js} +4 -4
- package/dist/chunks/{components-5y78e05d.js → components-xm826zjw.js} +3 -3
- package/dist/chunks/{content-source-4rzvmp0m.js → content-source-jt7rbcbc.js} +22 -22
- package/dist/chunks/{convert-to-repeater-jxsv62v7.js → convert-to-repeater-vg38bq99.js} +22 -22
- package/dist/chunks/{editor-3qhbg51x.js → editor-ddy019sn.js} +2 -2
- package/dist/chunks/entry-commands-64nb2a9a.js +42 -0
- package/dist/chunks/{extension-sections-2mrptyek.js → extension-sections-r73an5s6.js} +30 -29
- package/dist/chunks/{file-ops-knfqshrm.js → file-ops-3xan8mnj.js} +21 -21
- package/dist/chunks/{files-y6fr4he9.js → files-egsb0ry8.js} +28 -28
- package/dist/chunks/{format-host-1k4qrcqd.js → format-host-mym8qnd0.js} +3 -3
- package/dist/chunks/{fs-events-3y6y0nrm.js → fs-events-z2gg8qjt.js} +4 -4
- package/dist/chunks/{git-panel-2rkrsjva.js → git-panel-a05atk6q.js} +20 -20
- package/dist/chunks/{grid-view-1p6hsyjx.css → grid-view-3g1h2re8.css} +956 -139
- package/dist/chunks/{grid-view-a7b87n2c.js → grid-view-qaqer9kr.js} +24 -24
- package/dist/chunks/{icons-yy10wk9r.js → icons-drxq9q10.js} +8 -2
- package/dist/chunks/{iframe-host-scpw01h8.js → iframe-host-psetcv20.js} +11 -11
- package/dist/chunks/{index-n4j7qxyr.js → index-9yjae3hz.js} +4 -4
- package/dist/chunks/{javascript-4abzjcy9.css → javascript-bc9z461d.css} +688 -54
- package/dist/chunks/{javascript-xvrfrpkb.js → javascript-hr5sg57n.js} +2 -2
- package/dist/chunks/{jsonMode-vvmpmk34.css → jsonMode-qqd9nm1t.css} +1120 -303
- package/dist/chunks/{jsonMode-tyx2kj6p.js → jsonMode-zs88v0wr.js} +4 -4
- package/dist/chunks/layers-panel-83a16ytx.js +41 -0
- package/dist/chunks/{layers-jnvdbqva.js → layers-s6mc01ry.js} +3 -3
- package/dist/chunks/{media-picker-f66nav16.js → media-picker-nhn6rv4w.js} +11 -11
- package/dist/chunks/{menu-1dfhry4s.js → menu-8j4qxjrp.js} +4 -4
- package/dist/chunks/{monaco-binding-sw6en4dw.js → monaco-binding-e8d9wzyk.js} +3 -3
- package/dist/chunks/{monaco-buffer-pykwbm92.js → monaco-buffer-jaq1t9zj.js} +2 -2
- package/dist/chunks/{monaco-setup-8vbyqnhr.css → monaco-setup-ey9cjcm3.css} +954 -137
- package/dist/chunks/{monaco-setup-km6abc6q.js → monaco-setup-gsjdysze.js} +6 -6
- package/dist/chunks/{platform-ts9cg1a4.js → platform-fnchmhy7.js} +5 -3
- package/dist/chunks/publish-panel-ak6hxfma.js +27 -0
- package/dist/chunks/quick-search-c63mkt3b.js +47 -0
- package/dist/chunks/{references-h69xp9zz.js → references-f7bdv3z5.js} +3 -3
- package/dist/chunks/right-panel-t5n8wttg.js +45 -0
- package/dist/chunks/{studio-ze46gzjh.js → studio-01269reb.js} +7 -7
- package/dist/chunks/{studio-rnyf3f8e.js → studio-0a4gncx0.js} +3 -3
- package/dist/chunks/{studio-e1f24eff.js → studio-0d4p4wxj.js} +6778 -2993
- package/dist/chunks/{studio-4wbb9ct0.js → studio-1tejxvba.js} +3006 -1855
- package/dist/chunks/{studio-d1n2bykn.js → studio-3nprwbd9.js} +117 -25
- package/dist/chunks/{studio-4c041r8y.js → studio-40z39dme.js} +3 -3
- package/dist/chunks/{studio-151w0xnh.js → studio-482eeazk.js} +20 -20
- package/dist/chunks/{studio-cgprcdxn.js → studio-4998spet.js} +10 -9
- package/dist/chunks/{studio-nq5yf5mp.js → studio-557bmn0x.js} +2 -2
- package/dist/chunks/{studio-rtskkm43.js → studio-5w26wza5.js} +3 -3
- package/dist/chunks/{studio-6nzaktvy.js → studio-6pwn9j8c.js} +6 -3
- package/dist/chunks/{studio-wnsyffg1.js → studio-6vg0x5fz.js} +3 -2
- package/dist/chunks/{studio-vn5hske5.js → studio-7d3c1m59.js} +12 -5
- package/dist/chunks/{studio-6gryj0sg.js → studio-9vsvz7w7.js} +6 -6
- package/dist/chunks/{studio-50wfwy44.js → studio-9wm0xzpf.js} +19 -19
- package/dist/chunks/{studio-0j7r7s9g.js → studio-ag3z6shb.js} +10 -4
- package/dist/chunks/studio-aj9drheq.js +177 -0
- package/dist/chunks/{studio-xajk70w0.js → studio-apv9x70c.js} +189 -130
- package/dist/chunks/{studio-c04nzbby.js → studio-b9q3znz8.js} +2 -2
- package/dist/chunks/{studio-nfx354t1.js → studio-bh47w0cy.js} +9 -10
- package/dist/chunks/{studio-gk2twyh4.js → studio-dgdm6vvt.js} +264 -52
- package/dist/chunks/{studio-gtfq1dkz.js → studio-dwdcr2e8.js} +4 -4
- package/dist/chunks/{studio-nqgawfks.js → studio-fbcyz234.js} +146 -139
- package/dist/chunks/{studio-27q131j3.js → studio-fqpkpq1t.js} +7 -4
- package/dist/chunks/{studio-c0qgc3tn.js → studio-fy320dfc.js} +62 -68
- package/dist/chunks/{studio-zjjde71a.js → studio-gjj4bbfx.js} +2 -2
- package/dist/chunks/{studio-g33v4fe9.js → studio-jfhxy8h3.js} +7 -7
- package/dist/chunks/{studio-ab87phj1.js → studio-kwewmhhq.js} +4 -4
- package/dist/chunks/{studio-7rrb1esn.js → studio-m58xn8at.js} +25 -24
- package/dist/chunks/{studio-fzjx96t2.js → studio-mfkh1q8d.js} +17 -17
- package/dist/chunks/{studio-drg8qj9k.js → studio-mrh0a92f.js} +17 -17
- package/dist/chunks/{studio-jt27ta6x.js → studio-mt79tn56.js} +3 -3
- package/dist/chunks/{studio-b66rsh78.js → studio-ne593z1j.js} +38 -31
- package/dist/chunks/{studio-h4nvnjvz.js → studio-ptfcxkz5.js} +418 -232
- package/dist/chunks/{studio-dd1qqkry.js → studio-qxye31h7.js} +7 -7
- package/dist/chunks/{studio-ye9drbk8.js → studio-rav5bpmp.js} +73 -52
- package/dist/chunks/{studio-6kvgrkrp.js → studio-rwmmbrth.js} +6 -6
- package/dist/chunks/{studio-b7xacrwe.js → studio-sceg8ws0.js} +8 -8
- package/dist/chunks/{studio-msc1ee1m.js → studio-sjas5b3a.js} +19 -13
- package/dist/chunks/{studio-a65w20ex.js → studio-vd67b66d.js} +3 -3
- package/dist/chunks/{studio-7144epdr.js → studio-w475cbf9.js} +10 -10
- package/dist/chunks/{studio-4f3psrk1.js → studio-w7gpcvfj.js} +9 -9
- package/dist/chunks/{studio-nsgw7dbk.js → studio-xrbfdxgk.js} +7 -7
- package/dist/chunks/{studio-ke09tn9k.js → studio-y49b6mjv.js} +35 -35
- package/dist/chunks/{studio-j0w60gft.js → studio-ygvr9e4q.js} +10 -10
- package/dist/chunks/{studio-z2smx5ce.js → studio-yxmmjy2a.js} +9 -6
- package/dist/chunks/{tsMode-jy4m86rv.js → tsMode-ay4c78ne.js} +4 -4
- package/dist/chunks/{tsMode-hnxxb73h.css → tsMode-c72wyz27.css} +954 -137
- package/dist/chunks/{workspace-np10mayv.js → workspace-b9k2frks.js} +5 -5
- package/dist/chunks/{ws-client-ny4zc51r.js → ws-client-erze4czt.js} +356 -20
- package/dist/codicon.ttf +0 -0
- package/dist/iframe-entry.js +18 -16
- package/dist/studio.css +956 -139
- package/dist/studio.js +1453 -830
- package/dist/workers/editor.worker.js +196 -107
- package/dist/workers/json.worker.js +196 -107
- package/dist/workers/ts.worker.js +196 -107
- package/package.json +15 -14
- package/src/about/about-modal.ts +4 -3
- package/src/browse/library-commands.ts +15 -13
- package/src/browse/library-pane.ts +2 -2
- package/src/canvas/canvas-render.ts +97 -83
- package/src/canvas/canvas-surface.ts +2 -2
- package/src/canvas/canvas-utils.ts +42 -32
- package/src/canvas/diff-toolbar.ts +21 -2
- package/src/canvas/diff-view.ts +30 -6
- package/src/canvas/iframe-entry.ts +2 -2
- package/src/canvas/iframe-host.ts +5 -5
- package/src/canvas/iframe-interaction.ts +7 -6
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-protocol.ts +6 -5
- package/src/canvas/iframe-render.ts +3 -3
- package/src/canvas/popover-state.ts +1 -1
- package/src/canvas/stage-scrollbar.ts +112 -0
- package/src/canvas/surface-registry.ts +9 -2
- package/src/collab/collab-commands.ts +8 -6
- package/src/collab/collab-session.ts +4 -4
- package/src/collab/collab-state.ts +4 -4
- package/src/collab/presence-chips.ts +3 -3
- package/src/commands/app-commands.ts +7 -7
- package/src/commands/budget.ts +17 -16
- package/src/commands/command-args.ts +10 -9
- package/src/commands/context.ts +20 -10
- package/src/commands/defaults.ts +30 -29
- package/src/commands/levels.ts +8 -6
- package/src/commands/live-context.ts +12 -10
- package/src/commands/reference.ts +5 -5
- package/src/commands/registry.ts +2 -2
- package/src/content/draft-state.ts +9 -8
- package/src/content/entry-commands.ts +16 -14
- package/src/content/entry-editor.ts +2 -2
- package/src/content/entry-fields.ts +1 -1
- package/src/editor/context-menu.ts +4 -4
- package/src/editor/convert-to-component.ts +6 -5
- package/src/editor/inline-edit.ts +3 -3
- package/src/editor/shortcuts.ts +88 -20
- package/src/editor/slash-menu.ts +11 -10
- package/src/files/elements.ts +4 -5
- package/src/files/file-ops.ts +1 -1
- package/src/files/files.ts +21 -17
- package/src/files/serialize-document.ts +1 -1
- package/src/format/convert-file.ts +5 -5
- package/src/github/github-auth-status.ts +107 -0
- package/src/github/github-auth.ts +18 -82
- package/src/github/github-publish.ts +7 -6
- package/src/grid/cell-editors.ts +8 -7
- package/src/grid/grid-layout.ts +1 -1
- package/src/grid/grid-open.ts +6 -5
- package/src/grid/grid-panel.ts +13 -12
- package/src/grid/redirects-grid.ts +14 -11
- package/src/grid/redirects.ts +10 -5
- package/src/grid/sources/content-source.ts +10 -9
- package/src/hosting/document.ts +28 -1
- package/src/hosting/stage.ts +15 -4
- package/src/i18n/i18n-commands.ts +9 -7
- package/src/new-project/location-fields.ts +16 -3
- package/src/new-project/new-project-modal.ts +23 -7
- package/src/page-params.ts +6 -6
- package/src/panels/activity-panel.ts +11 -10
- package/src/panels/ai-chat/chat-view.ts +27 -14
- package/src/panels/ai-chat/composer.ts +10 -3
- package/src/panels/ai-panel.ts +87 -29
- package/src/panels/block-action-bar.ts +59 -33
- package/src/panels/bottom-dock.ts +22 -22
- package/src/panels/data-explorer.ts +9 -9
- package/src/panels/data-grid.ts +1 -1
- package/src/panels/editors.ts +8 -8
- package/src/panels/elements-panel.ts +7 -8
- package/src/panels/empty-state.ts +1 -1
- package/src/panels/events-panel.ts +13 -12
- package/src/panels/formula-workspace.ts +8 -5
- package/src/panels/frontmatter-fields.ts +4 -1
- package/src/panels/frontmatter-panel.ts +18 -18
- package/src/panels/git-panel.ts +19 -13
- package/src/panels/head-panel.ts +9 -10
- package/src/panels/i18n-panel.ts +6 -4
- package/src/panels/imports-panel.ts +1 -1
- package/src/panels/jump-bar.ts +20 -18
- package/src/panels/layers-panel.ts +19 -17
- package/src/panels/left-panel.ts +3 -3
- package/src/panels/navigator-panels.ts +8 -8
- package/src/panels/overlays.ts +1 -1
- package/src/panels/pane-context.ts +56 -28
- package/src/panels/pane-grid.ts +9 -8
- package/src/panels/panel-registry.ts +47 -19
- package/src/panels/problems-panel.ts +11 -12
- package/src/panels/properties-panel.ts +21 -20
- package/src/panels/provenance.ts +3 -3
- package/src/panels/quick-search.ts +15 -11
- package/src/panels/right-panel.ts +4 -3
- package/src/panels/seo-modal.ts +5 -4
- package/src/panels/settings-menu.ts +9 -9
- package/src/panels/settings-pane.ts +3 -3
- package/src/panels/signals-panel.ts +16 -9
- package/src/panels/statement-editor.ts +12 -9
- package/src/panels/style-panel.ts +45 -41
- package/src/panels/stylebook-panel.ts +0 -1
- package/src/panels/tab-strip.ts +26 -23
- package/src/platform-errors.ts +2 -2
- package/src/platform.ts +44 -4
- package/src/platforms/cloud.ts +11 -1
- package/src/platforms/default-platform.ts +141 -4
- package/src/platforms/devserver.ts +23 -3
- package/src/publish/deploy-checklist.ts +11 -10
- package/src/publish/publish-commands.ts +9 -8
- package/src/services/a11y-report.ts +1 -1
- package/src/services/ai-ask.ts +39 -16
- package/src/services/ai-command-tools.ts +28 -14
- package/src/services/ai-import-tools.ts +43 -29
- package/src/services/ai-project-tools.ts +20 -38
- package/src/services/ai-settings.ts +55 -2
- package/src/services/ai-tools.ts +69 -58
- package/src/services/ai-write-report.ts +4 -4
- package/src/services/ai-writes.ts +74 -55
- package/src/services/automation.ts +12 -12
- package/src/services/clock.ts +2 -1
- package/src/services/connection.ts +2 -2
- package/src/services/context-manager.ts +69 -6
- package/src/services/directory-picker.ts +93 -27
- package/src/services/document-assistant.ts +86 -17
- package/src/services/gated-registry.ts +4 -3
- package/src/services/idle.ts +5 -4
- package/src/services/live-surfaces.ts +2 -1
- package/src/services/notify.ts +9 -7
- package/src/services/popover-report.ts +3 -3
- package/src/services/preview-eval.ts +1 -1
- package/src/services/project-adoption.ts +34 -1
- package/src/services/project-path.ts +53 -0
- package/src/services/settings/kernel.ts +13 -2
- package/src/services/tool-executor.ts +135 -30
- package/src/services/tool-outcomes.ts +143 -0
- package/src/settings/contexts-section.ts +8 -8
- package/src/settings/contributed-section.ts +6 -6
- package/src/settings/css-vars-editor.ts +6 -5
- package/src/settings/extension-commands.ts +19 -18
- package/src/settings/extension-sections.ts +7 -7
- package/src/settings/extensions-section.ts +3 -3
- package/src/settings/general-settings.ts +21 -18
- package/src/settings/preferences-accounts.ts +3 -3
- package/src/settings/preferences-dialog.ts +9 -8
- package/src/settings/preferences-sections.ts +1 -1
- package/src/settings/project-sections.ts +2 -2
- package/src/settings/section-registry.ts +7 -6
- package/src/settings/settings-document.ts +41 -43
- package/src/shell/tree.ts +29 -0
- package/src/shell.ts +63 -55
- package/src/site-context.ts +1 -1
- package/src/store.ts +2 -2
- package/src/studio.ts +46 -28
- package/src/style/live-preview.ts +8 -8
- package/src/style/project-styles.ts +8 -9
- package/src/style/token-ref.ts +2 -2
- package/src/surfaces/about.json +6 -2
- package/src/surfaces/add-repo.json +2 -2
- package/src/surfaces/add-repo.ts +2 -2
- package/src/surfaces/ai-chat.json +14 -6
- package/src/surfaces/ai-chat.ts +4 -2
- package/src/surfaces/ai-credentials-form.json +53 -49
- package/src/surfaces/ai-credentials-form.ts +18 -4
- package/src/surfaces/ai-managed-connect.json +4 -4
- package/src/surfaces/block-action-bar.json +4 -4
- package/src/surfaces/block-action-bar.ts +3 -3
- package/src/surfaces/boot-failure.json +228 -0
- package/src/surfaces/boot-failure.ts +156 -0
- package/src/surfaces/bottom-dock.json +1 -1
- package/src/surfaces/canvas-stage.json +9 -40
- package/src/surfaces/canvas-stage.ts +9 -9
- package/src/surfaces/cf-account-picker.json +11 -8
- package/src/surfaces/commandbar.ts +11 -10
- package/src/surfaces/convert-repeater.ts +3 -2
- package/src/surfaces/dialog.json +7 -1
- package/src/surfaces/dialog.ts +2 -2
- package/src/surfaces/doc-header.json +6 -13
- package/src/surfaces/doc-header.ts +4 -5
- package/src/surfaces/entry-editor.json +1 -1
- package/src/surfaces/entry-editor.ts +2 -1
- package/src/surfaces/expression-editor.json +5 -5
- package/src/surfaces/files-panel.json +4 -3
- package/src/surfaces/files-panel.ts +1 -1
- package/src/surfaces/formula-palette.json +2 -2
- package/src/surfaces/formula-palette.ts +1 -1
- package/src/surfaces/git-panel.json +167 -109
- package/src/surfaces/git-panel.ts +2 -2
- package/src/surfaces/github-auth.json +2 -1
- package/src/surfaces/github-publish.ts +3 -3
- package/src/surfaces/grid-open.json +1 -1
- package/src/surfaces/grid-panel.json +2 -2
- package/src/surfaces/grid-views.json +1 -1
- package/src/surfaces/inspector-dock.json +2 -2
- package/src/surfaces/jump-bar.json +1 -1
- package/src/surfaces/jump-bar.ts +1 -1
- package/src/surfaces/library-pane.ts +2 -1
- package/src/surfaces/logic-panel.json +7 -7
- package/src/surfaces/logic-panel.ts +6 -4
- package/src/surfaces/logic-workspace.json +2 -2
- package/src/surfaces/logic-workspace.ts +2 -2
- package/src/surfaces/media-browser.ts +3 -3
- package/src/surfaces/media-pane.ts +2 -1
- package/src/surfaces/menu.ts +5 -5
- package/src/surfaces/new-project.json +1 -1
- package/src/surfaces/pane-context.json +86 -57
- package/src/surfaces/pane-context.ts +2 -1
- package/src/surfaces/pane-grid.json +3 -3
- package/src/surfaces/panel-activity.json +2 -1
- package/src/surfaces/panel-deploy-checklist.json +1 -1
- package/src/surfaces/panel-elements.ts +2 -1
- package/src/surfaces/panel-i18n.ts +2 -1
- package/src/surfaces/panel-outline.json +1 -1
- package/src/surfaces/panel-outline.ts +4 -3
- package/src/surfaces/panel-page.json +2 -2
- package/src/surfaces/panel-page.ts +4 -1
- package/src/surfaces/panel-problems.json +4 -3
- package/src/surfaces/panel-problems.ts +2 -2
- package/src/surfaces/panel-signals.json +23 -8
- package/src/surfaces/panel-signals.ts +5 -1
- package/src/surfaces/panel-stylebook-layers.json +1 -1
- package/src/surfaces/panel-stylebook-layers.ts +2 -2
- package/src/surfaces/preferences.json +21 -8
- package/src/surfaces/preferences.ts +9 -1
- package/src/surfaces/properties-panel.json +4 -4
- package/src/surfaces/properties-panel.ts +2 -2
- package/src/surfaces/publish.json +1 -1
- package/src/surfaces/publish.ts +2 -1
- package/src/surfaces/push-plan.json +4 -3
- package/src/surfaces/rail.json +2 -2
- package/src/surfaces/rail.ts +10 -4
- package/src/surfaces/reference-field.json +1 -1
- package/src/surfaces/schema-form.json +2 -2
- package/src/surfaces/schema-form.ts +1 -1
- package/src/surfaces/seo.json +1 -1
- package/src/surfaces/seo.ts +2 -2
- package/src/surfaces/settings-contributed.ts +2 -1
- package/src/surfaces/settings-css-vars.json +4 -4
- package/src/surfaces/settings-deploy.json +4 -4
- package/src/surfaces/settings-deploy.ts +2 -1
- package/src/surfaces/settings-extensions.json +6 -6
- package/src/surfaces/settings-extensions.ts +6 -2
- package/src/surfaces/settings-locales.json +4 -4
- package/src/surfaces/settings-overview.ts +2 -1
- package/src/surfaces/settings-pane.ts +3 -2
- package/src/surfaces/settings-rawjson.ts +1 -1
- package/src/surfaces/slash-menu.ts +4 -4
- package/src/surfaces/statements.json +3 -3
- package/src/surfaces/statusbar.ts +23 -23
- package/src/surfaces/style-panel.json +9 -5
- package/src/surfaces/style-panel.ts +3 -3
- package/src/surfaces/tab-strip.json +2 -2
- package/src/surfaces/target-line.json +1 -1
- package/src/surfaces/target-line.ts +12 -10
- package/src/surfaces/welcome.json +7 -2
- package/src/tabs/doc-op-apply.ts +5 -5
- package/src/tabs/patch-ops.ts +3 -3
- package/src/tabs/project-config.ts +10 -10
- package/src/tabs/selection.ts +1 -1
- package/src/tabs/tab.ts +13 -14
- package/src/tabs/transact.ts +18 -24
- package/src/types.ts +27 -3
- package/src/ui/ai-credentials-form.ts +74 -16
- package/src/ui/ai-managed-connect.ts +68 -19
- package/src/ui/color-selector.ts +1 -1
- package/src/ui/expression-editor.ts +3 -3
- package/src/ui/form-controls.ts +6 -5
- package/src/ui/formula-catalog.ts +4 -4
- package/src/ui/formula-chips.ts +2 -2
- package/src/ui/layers.ts +20 -18
- package/src/ui/panel-resize.ts +5 -5
- package/src/ui/popover-surface.ts +2 -2
- package/src/ui/progress-modal.ts +3 -3
- package/src/ui/regions.ts +14 -9
- package/src/ui/schema-form.ts +10 -9
- package/src/ui/timing.ts +9 -7
- package/src/ui/value-source.ts +4 -4
- package/src/ui/virtual-window.ts +1 -1
- package/src/utils/base64.ts +20 -1
- package/src/utils/canvas-media.ts +1 -1
- package/src/utils/studio-utils.ts +0 -31
- package/src/view.ts +4 -3
- package/src/workspace/pane-derive.ts +14 -13
- package/src/workspace/session.ts +7 -6
- package/src/workspace/workspace.ts +49 -39
- package/styles/canvas.css +1 -27
- package/styles/inspector.css +4 -3
- package/styles/overlays.css +1 -1
- package/styles/tokens.css +17 -1
- package/styles/tokens.json +6 -1
- package/dist/chunks/entry-commands-1wnsqn5d.js +0 -42
- package/dist/chunks/layers-panel-73gfkcga.js +0 -41
- package/dist/chunks/publish-panel-z1zd2da1.js +0 -27
- package/dist/chunks/quick-search-zdv7h8ht.js +0 -47
- package/dist/chunks/right-panel-889vbnm5.js +0 -45
- package/dist/chunks/studio-727xh0e3.js +0 -76
- package/src/files/json-layout.ts +0 -474
- package/src/services/ai-turn-signal.ts +0 -70
package/src/tabs/transact.ts
CHANGED
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
pruneSelection,
|
|
10
10
|
structuralBatch,
|
|
11
11
|
} from "./selection";
|
|
12
|
-
import { applyDocOpToDoc, childArray, cloneValue } from "./doc-op-apply";
|
|
12
|
+
import { applyDocOpToDoc, childArray, cloneValue, inverseOf } from "./doc-op-apply";
|
|
13
13
|
import {
|
|
14
14
|
beginRecording,
|
|
15
15
|
endRecording,
|
|
@@ -773,7 +773,7 @@ export function mutateDuplicateNode(tab: Tab, path: JxPath) {
|
|
|
773
773
|
}
|
|
774
774
|
|
|
775
775
|
/**
|
|
776
|
-
* Remove every selected node, in ONE transaction and therefore ONE undo step (§6.
|
|
776
|
+
* Remove every selected node, in ONE transaction and therefore ONE undo step (§6.7).
|
|
777
777
|
*
|
|
778
778
|
* Three things make a batch different from a loop. `structuralBatch` drops paths contained by
|
|
779
779
|
* another selected path — deleting a `<section>` and a paragraph inside it is one deletion — drops
|
|
@@ -878,35 +878,29 @@ export function mutateMoveNode(tab: Tab, fromPath: JxPath, toParentPath: JxPath,
|
|
|
878
878
|
if (!fromParent || !Array.isArray(fromParent.children) || !toParent) {
|
|
879
879
|
return;
|
|
880
880
|
}
|
|
881
|
-
|
|
882
|
-
if (node === undefined) {
|
|
881
|
+
if (fromParent.children[fromIdx] === undefined) {
|
|
883
882
|
return;
|
|
884
883
|
}
|
|
885
884
|
let adjustedIndex = toIndex;
|
|
886
885
|
if (fromParent === toParent && fromIdx < toIndex) {
|
|
887
886
|
adjustedIndex -= 1;
|
|
888
887
|
}
|
|
889
|
-
|
|
888
|
+
const forward: JxDocOp = {
|
|
889
|
+
fromIndex: fromIdx,
|
|
890
|
+
fromParentPath,
|
|
891
|
+
op: "move-child",
|
|
892
|
+
toIndex: adjustedIndex,
|
|
893
|
+
toParentPath,
|
|
894
|
+
};
|
|
895
|
+
/* Computed BEFORE the splice, against the document the move applies to. The inverse runs against
|
|
896
|
+
the post-move document, so `inverseOf` writes both of its parent paths in post-move
|
|
897
|
+
coordinates: the removal shifted paths under the source parent, the insertion paths under the
|
|
898
|
+
target. One implementation of that rule, shared with every other host that moves a node. */
|
|
899
|
+
const inverse = inverseOf(doc, forward);
|
|
900
|
+
const [node] = fromParent.children.splice(fromIdx, 1);
|
|
901
|
+
childArray(toParent).splice(adjustedIndex, 0, node!);
|
|
890
902
|
recordPatch({ fromPath, op: "move", toIndex: adjustedIndex, toParentPath });
|
|
891
|
-
recordDocOp({
|
|
892
|
-
forward: {
|
|
893
|
-
fromIndex: fromIdx,
|
|
894
|
-
fromParentPath,
|
|
895
|
-
op: "move-child",
|
|
896
|
-
toIndex: adjustedIndex,
|
|
897
|
-
toParentPath,
|
|
898
|
-
},
|
|
899
|
-
inverse: {
|
|
900
|
-
fromIndex: adjustedIndex,
|
|
901
|
-
// The inverse runs against the post-move document, so both parent paths are translated
|
|
902
|
-
// Into post-move coordinates: the removal shifted paths under fromParent, the insertion
|
|
903
|
-
// Shifted paths under toParent.
|
|
904
|
-
fromParentPath: shiftPrefixedIndex(fromParentPath, toParentPath, fromIdx, -1, false),
|
|
905
|
-
op: "move-child",
|
|
906
|
-
toIndex: fromIdx,
|
|
907
|
-
toParentPath: shiftPrefixedIndex(toParentPath, fromParentPath, adjustedIndex, 1, true),
|
|
908
|
-
},
|
|
909
|
-
});
|
|
903
|
+
recordDocOp({ forward, inverse });
|
|
910
904
|
|
|
911
905
|
if (pathsEqual(primarySelection(tab.session.selection), fromPath)) {
|
|
912
906
|
let idx = toIndex;
|
package/src/types.ts
CHANGED
|
@@ -298,6 +298,26 @@ export interface StudioPlatform {
|
|
|
298
298
|
} | null>;
|
|
299
299
|
listDirectory: (dir: string) => Promise<DirEntry[]>;
|
|
300
300
|
readFile: (path: string) => Promise<string>;
|
|
301
|
+
/**
|
|
302
|
+
* A project file's raw bytes — what {@link readFile} cannot answer.
|
|
303
|
+
*
|
|
304
|
+
* `readFile` decodes as UTF-8, and every byte sequence that is not valid UTF-8 becomes U+FFFD on
|
|
305
|
+
* the way through. That is invisible and irreversible: a JPEG read this way is not a corrupted
|
|
306
|
+
* JPEG, it is a string of replacement characters that no decoder will ever turn back into an
|
|
307
|
+
* image. So a caller that must DECODE a project file — the image editor — needs this instead.
|
|
308
|
+
*
|
|
309
|
+
* **The `<img>` route is not an alternative, on the one platform that matters most.** A preview
|
|
310
|
+
* `src` from `files/media-paths.ts` is a cross-origin loopback URL on the electrobun desktop
|
|
311
|
+
* while the shell sits on `views://`, so drawing it into a canvas taints the canvas and
|
|
312
|
+
* `toBlob()` throws; and `server.md` §4.2 bans CORS outright, because the whole loopback security
|
|
313
|
+
* model rests on the browser refusing cross-origin reads. Bytes through the PAL become a
|
|
314
|
+
* same-origin `Blob`, so tainting stops being a thing that can happen rather than a thing that is
|
|
315
|
+
* worked around.
|
|
316
|
+
*
|
|
317
|
+
* Optional, and feature-detected like every optional member: a backend without it simply does not
|
|
318
|
+
* offer the image editor, which is the honest degradation `specs/desktop.md` §3.1 asks for.
|
|
319
|
+
*/
|
|
320
|
+
readFileBytes?: (path: string) => Promise<ArrayBuffer>;
|
|
301
321
|
writeFile: (path: string, content: string) => Promise<void>;
|
|
302
322
|
/**
|
|
303
323
|
* Store bytes at a project path, and report where they really landed.
|
|
@@ -547,9 +567,13 @@ export interface StudioPlatform {
|
|
|
547
567
|
onReady?: (evt: ImportReadyEvent) => void,
|
|
548
568
|
) => Promise<{ root: string; config: ProjectConfig; result?: ImportSiteSummary }>;
|
|
549
569
|
/**
|
|
550
|
-
* Open a native directory picker and return the chosen absolute path
|
|
551
|
-
*
|
|
552
|
-
*
|
|
570
|
+
* Open a native directory picker and return the chosen absolute path. Backs the New Project
|
|
571
|
+
* modal's **Browse…** button on `createDestination: "path"` platforms: desktop (the system
|
|
572
|
+
* dialog), and the dev server in a browser that has `showDirectoryPicker` (Chromium-based).
|
|
573
|
+
*
|
|
574
|
+
* Resolves `null` only when the user cancels; rejects with a displayable Error otherwise. The
|
|
575
|
+
* modal shows that message under the Location field, and typing a path clears it. A picker that
|
|
576
|
+
* resolves `null` for a failure is a dead button: the click visibly does nothing.
|
|
553
577
|
*/
|
|
554
578
|
pickDirectory?: () => Promise<string | null>;
|
|
555
579
|
/** Stack B AI assistant: URL of the OpenAI-compatible SSE chat proxy (`/__studio/ai/chat`). */
|
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
*
|
|
9
9
|
* The interim `Assistant: Settings…` dialog that used to host it is deleted: a provider key is an
|
|
10
10
|
* application setting, and the surface that owns application settings is also the one that can list
|
|
11
|
-
* it and revoke it (
|
|
11
|
+
* it and revoke it (§15). Nothing about this form changed for the move, which is the argument
|
|
12
12
|
* for it having been a reusable form rather than a section of a dialog.
|
|
13
13
|
*
|
|
14
14
|
* This module is the FLOW; `surfaces/ai-credentials-form.json` is what it draws. It keeps the three
|
|
15
15
|
* drafts, decides which credentials a listing is sent with, what Save persists and re-reads, and
|
|
16
|
-
* whether
|
|
17
|
-
* hands back the surface's own host element rather than a template, because
|
|
18
|
-
* lit template that interpolates the form beside the keyless offer — see
|
|
16
|
+
* whether there is anything to Save or Cancel; the surface renders those and reports what the
|
|
17
|
+
* reader did. `render()` hands back the surface's own host element rather than a template, because
|
|
18
|
+
* every gate is still a lit template that interpolates the form beside the keyless offer — see
|
|
19
19
|
* `surfaces/ai-credentials-form.ts` for why that element is the mount point and why re-rendering
|
|
20
20
|
* the gate cannot disturb it.
|
|
21
21
|
*
|
|
@@ -25,12 +25,15 @@
|
|
|
25
25
|
|
|
26
26
|
import { fetchAvailableModels, proxyModelsErrorMessage } from "../services/ai-models";
|
|
27
27
|
import {
|
|
28
|
+
aiProviderDiffers,
|
|
28
29
|
getBaseUrl,
|
|
29
30
|
getOpenAiKey,
|
|
30
|
-
hasOpenAiKey,
|
|
31
31
|
saveAiProvider,
|
|
32
|
+
storedEquals,
|
|
32
33
|
storedModel,
|
|
33
34
|
} from "../services/ai-settings";
|
|
35
|
+
import { SETTINGS } from "../services/settings/definitions";
|
|
36
|
+
import type { AiProvider } from "../services/ai-settings";
|
|
34
37
|
import { createAiCredentialsSurface } from "../surfaces/ai-credentials-form";
|
|
35
38
|
import type {
|
|
36
39
|
AiCredentialsSurface,
|
|
@@ -47,7 +50,10 @@ export interface AiCredentialsFormOptions {
|
|
|
47
50
|
requestRender: () => void;
|
|
48
51
|
/** Called after Save persists the credentials. */
|
|
49
52
|
onSaved?: () => void;
|
|
50
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Called when Cancel puts the drafts back to what is stored (Cancel is only offered while they
|
|
55
|
+
* differ from it).
|
|
56
|
+
*/
|
|
51
57
|
onCancel?: () => void;
|
|
52
58
|
/**
|
|
53
59
|
* Optional context line replacing the default blurb.
|
|
@@ -85,21 +91,65 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
85
91
|
let modelsLoading = false;
|
|
86
92
|
let modelsError = "";
|
|
87
93
|
|
|
94
|
+
/**
|
|
95
|
+
* What the store held when the drafts last agreed with it — the answer to "has the reader touched
|
|
96
|
+
* this field?". A draft still equal to its basis is a VIEW of the store, not an edit, so
|
|
97
|
+
* {@link followStore} may move it; one that differs is the reader's and nothing but a Save or a
|
|
98
|
+
* Cancel replaces it. Starts blank because the drafts do, which is what lets a host that never
|
|
99
|
+
* calls `startEdit` still open on what is stored.
|
|
100
|
+
*/
|
|
101
|
+
let basis: AiProvider = { apiKey: "", baseUrl: "", model: "" };
|
|
102
|
+
|
|
88
103
|
/** Made on the first render, and kept for the life of the controller. */
|
|
89
104
|
let surface: AiCredentialsSurface | null = null;
|
|
90
105
|
|
|
91
106
|
/**
|
|
92
|
-
*
|
|
107
|
+
* What is stored, in the shape the drafts take.
|
|
93
108
|
*
|
|
94
109
|
* The model comes from {@link storedModel} rather than `getModel()`, so a user who has never
|
|
95
110
|
* picked one drafts an empty field instead of the `"gpt-4o"` default. Saving a prefilled default
|
|
96
111
|
* writes a choice nobody made, and `jx.ai.model: "gpt-4o"` is exactly what a broken install was
|
|
97
112
|
* left holding.
|
|
98
113
|
*/
|
|
114
|
+
function stored(): AiProvider {
|
|
115
|
+
return { apiKey: getOpenAiKey(), baseUrl: getBaseUrl(), model: storedModel() };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Load the drafts from what is stored, discarding any edit, and take that as the new basis. */
|
|
99
119
|
function loadDrafts() {
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
120
|
+
basis = stored();
|
|
121
|
+
keyDraft = basis.apiKey;
|
|
122
|
+
baseUrlDraft = basis.baseUrl;
|
|
123
|
+
modelDraft = basis.model;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Bring every untouched draft up to what is stored now, and keep every edited one.
|
|
128
|
+
*
|
|
129
|
+
* Without this a draft could drift from the store with nobody having typed, and a form that
|
|
130
|
+
* offers Save and Cancel only while it differs would offer them for an edit nobody made. Two
|
|
131
|
+
* hosts did exactly that: the New Project gates never call `startEdit`, so their drafts began
|
|
132
|
+
* blank over a stored endpoint or model — and Save then overwrote both with nothing — and a
|
|
133
|
+
* Disconnect in Preferences › Accounts left the Assistant form holding the key it had just
|
|
134
|
+
* revoked, which its Save would have stored again. Run from {@link render}, the host's repaint,
|
|
135
|
+
* and never from a setter, so a keystroke is never rebased onto the store under the reader.
|
|
136
|
+
*
|
|
137
|
+
* **"Untouched" is judged by the same rule as `dirty`**, through the store's own normalisation,
|
|
138
|
+
* because the two questions have to agree. Raw string equality made a draft that differed only by
|
|
139
|
+
* whitespace, or by an endpoint's trailing slash, TOUCHED here and not-dirty there: no Save and
|
|
140
|
+
* no Cancel were drawn, so nothing could reset it, and yet this function refused to move it — so
|
|
141
|
+
* a Disconnect in Accounts left the revoked key sitting in the field, and once the store was
|
|
142
|
+
* empty the form turned dirty and offered to store it back. A draft Save would not move is a view
|
|
143
|
+
* of the store, whatever it was typed as.
|
|
144
|
+
*/
|
|
145
|
+
function followStore() {
|
|
146
|
+
const now = stored();
|
|
147
|
+
keyDraft = storedEquals(SETTINGS.aiOpenAiKey, keyDraft, basis.apiKey) ? now.apiKey : keyDraft;
|
|
148
|
+
baseUrlDraft = storedEquals(SETTINGS.aiBaseUrl, baseUrlDraft, basis.baseUrl)
|
|
149
|
+
? now.baseUrl
|
|
150
|
+
: baseUrlDraft;
|
|
151
|
+
modelDraft = storedEquals(SETTINGS.aiModel, modelDraft, basis.model) ? now.model : modelDraft;
|
|
152
|
+
basis = now;
|
|
103
153
|
}
|
|
104
154
|
|
|
105
155
|
/** Open the form pre-filled with the current settings, and load the model list. */
|
|
@@ -122,7 +172,8 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
122
172
|
* `setOpenAiKey`/`setBaseUrl` treat as _clear_, so pressing Save a second time on the emptied
|
|
123
173
|
* form deleted the key and endpoint that the first press had just stored. Reading back through
|
|
124
174
|
* the getters also shows what was actually kept — trimmed, and with the endpoint's trailing slash
|
|
125
|
-
* stripped — rather than what was typed.
|
|
175
|
+
* stripped — rather than what was typed. And because the drafts then equal the store, the form is
|
|
176
|
+
* no longer `dirty`: Save and Cancel go away, so a second press has nothing to land on.
|
|
126
177
|
*/
|
|
127
178
|
function save() {
|
|
128
179
|
saveAiProvider({ apiKey: keyDraft, baseUrl: baseUrlDraft, model: modelDraft });
|
|
@@ -135,7 +186,10 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
135
186
|
opts.requestRender();
|
|
136
187
|
}
|
|
137
188
|
|
|
138
|
-
/**
|
|
189
|
+
/**
|
|
190
|
+
* Put the drafts back to what is stored. Only offered while they differ from it, so it always
|
|
191
|
+
* abandons something — which is also why it takes itself away.
|
|
192
|
+
*/
|
|
139
193
|
function cancel() {
|
|
140
194
|
loadDrafts();
|
|
141
195
|
modelsError = "";
|
|
@@ -196,12 +250,14 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
196
250
|
function view(): AiCredentialsView {
|
|
197
251
|
return {
|
|
198
252
|
baseUrlDraft,
|
|
253
|
+
/* Compared as the store would hold each value, so what Save would erase — whitespace, an
|
|
254
|
+
endpoint's trailing slash — is not an edit. See `aiProviderDiffers`. */
|
|
255
|
+
dirty: aiProviderDiffers({ apiKey: keyDraft, baseUrl: baseUrlDraft, model: modelDraft }),
|
|
199
256
|
fetchLabel: modelsLoading
|
|
200
257
|
? "Fetching…"
|
|
201
258
|
: availableModels.length > 0
|
|
202
259
|
? "Refresh models"
|
|
203
260
|
: "Fetch models",
|
|
204
|
-
haveKey: hasOpenAiKey(),
|
|
205
261
|
intro: opts.intro ?? DEFAULT_INTRO,
|
|
206
262
|
keyDraft,
|
|
207
263
|
modelDraft,
|
|
@@ -214,9 +270,10 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
214
270
|
/**
|
|
215
271
|
* What the reader typed, announced on the scope before anything else reads it.
|
|
216
272
|
*
|
|
217
|
-
* A document's binding writes only when the value it reads CHANGES (
|
|
218
|
-
*
|
|
219
|
-
* does not have. Nothing rewrites a draft today;
|
|
273
|
+
* A document's binding writes only when the value it reads CHANGES (the controlled-input rule of
|
|
274
|
+
* studio-ui-guidelines.md §9.3), so a draft the flow decided without the raw text passing through
|
|
275
|
+
* would leave the field holding something the flow does not have. Nothing rewrites a draft today;
|
|
276
|
+
* the echo is what makes a rewrite possible.
|
|
220
277
|
*/
|
|
221
278
|
function setKey(value: string) {
|
|
222
279
|
keyDraft = value;
|
|
@@ -238,6 +295,7 @@ export function createAiCredentialsForm(opts: AiCredentialsFormOptions): AiCrede
|
|
|
238
295
|
}
|
|
239
296
|
|
|
240
297
|
function render(): HTMLElement {
|
|
298
|
+
followStore();
|
|
241
299
|
if (surface) {
|
|
242
300
|
surface.update(view());
|
|
243
301
|
} else {
|
|
@@ -66,6 +66,13 @@ const LEDE_FRESH =
|
|
|
66
66
|
"Recommended — run the assistant on Workers AI in your own Cloudflare account. No API key to create, copy or rotate.";
|
|
67
67
|
const LEDE_LAPSED =
|
|
68
68
|
"Your Cloudflare connection has expired. Reconnect to keep using the assistant.";
|
|
69
|
+
/**
|
|
70
|
+
* A live grant that reaches more than one account and has none chosen (`cf_account_required`).
|
|
71
|
+
* Re-authorizing lands back in exactly this state, so the button opens the account picker instead
|
|
72
|
+
* of the OAuth flow, and the words say which of the two is missing.
|
|
73
|
+
*/
|
|
74
|
+
const LEDE_ACCOUNT =
|
|
75
|
+
"Cloudflare is connected, but no account is chosen yet. Pick the account the assistant should run on.";
|
|
69
76
|
|
|
70
77
|
/**
|
|
71
78
|
* Create a managed-connect controller bound to a host's render scheduler.
|
|
@@ -98,6 +105,51 @@ export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnec
|
|
|
98
105
|
return !isProxyConfigured() || proxyStateCode() === "cf_reconnect_required";
|
|
99
106
|
}
|
|
100
107
|
|
|
108
|
+
/**
|
|
109
|
+
* The grant is live but names no account — the one state a connect flow cannot fix. Read from the
|
|
110
|
+
* shared probe alone, so it can never outlive the state it describes: a disconnect, or an account
|
|
111
|
+
* picked in Preferences, changes what the probe answers and this answer with it.
|
|
112
|
+
*/
|
|
113
|
+
const needsAccount = () => proxyStateCode() === "cf_account_required";
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Re-probe after the connection changed, and CHECK the answer, because a change the backend does
|
|
117
|
+
* not honour must not look like one that worked. This is the only place that can tell.
|
|
118
|
+
*/
|
|
119
|
+
async function verifyConnection(): Promise<void> {
|
|
120
|
+
// Re-probe: /models flips to configured once the connection lands, opening the gate.
|
|
121
|
+
resetModelCache();
|
|
122
|
+
await fetchAvailableModels({ force: true });
|
|
123
|
+
/* Each refusal gets the advice that can fix it: reconnecting cannot choose an account, and a
|
|
124
|
+
pick cannot revive a lapsed grant. */
|
|
125
|
+
if (proxyStateCode() === "cf_account_required") {
|
|
126
|
+
connectError =
|
|
127
|
+
"Cloudflare still reports no account chosen for the assistant. Pick one again, or use your own API key below.";
|
|
128
|
+
} else if (!isProxyConfigured() || proxyStateCode() === "cf_reconnect_required") {
|
|
129
|
+
connectError =
|
|
130
|
+
"Cloudflare connected, but the assistant backend still reports the connection as unusable. " +
|
|
131
|
+
"Try reconnecting, or use your own API key below.";
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Open the account picker, and verify the connection once an account is chosen. */
|
|
136
|
+
async function chooseAccount(): Promise<void> {
|
|
137
|
+
/* Lazily, because the picker pulls the dialog layer in and this module is imported by every
|
|
138
|
+
credentials gate — including ones that render before layers are bound. */
|
|
139
|
+
const { openCfAccountPicker } = await import("./cf-account-picker");
|
|
140
|
+
if (!(await openCfAccountPicker())) {
|
|
141
|
+
/* Re-probe, because the probe still answers from before the connect. The backend reports a
|
|
142
|
+
live grant with no account as `cf_account_required`, so after this the button offers the
|
|
143
|
+
picker again rather than an OAuth round trip that would land right back here. */
|
|
144
|
+
resetModelCache();
|
|
145
|
+
await fetchAvailableModels({ force: true });
|
|
146
|
+
connectError =
|
|
147
|
+
"Cloudflare is connected, but no account is chosen yet — pick one to finish setting up the assistant.";
|
|
148
|
+
return;
|
|
149
|
+
}
|
|
150
|
+
await verifyConnection();
|
|
151
|
+
}
|
|
152
|
+
|
|
101
153
|
function ensureProbe() {
|
|
102
154
|
ensureProxyProbe(opts.requestRender);
|
|
103
155
|
}
|
|
@@ -126,25 +178,10 @@ export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnec
|
|
|
126
178
|
return;
|
|
127
179
|
}
|
|
128
180
|
if (!outcome.connection.accountId) {
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
const { openCfAccountPicker } = await import("./cf-account-picker");
|
|
132
|
-
if (!(await openCfAccountPicker())) {
|
|
133
|
-
connectError =
|
|
134
|
-
"Cloudflare is connected, but no account is chosen yet — pick one to finish setting up the assistant.";
|
|
135
|
-
return;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
// Re-probe: /models flips to configured once the connection lands, opening the gate.
|
|
139
|
-
resetModelCache();
|
|
140
|
-
await fetchAvailableModels({ force: true });
|
|
141
|
-
/* And then CHECK, because a connect the backend does not honour must not look like one that
|
|
142
|
-
worked. This is the only place that can tell the difference. */
|
|
143
|
-
if (!isProxyConfigured() || proxyStateCode() === "cf_reconnect_required") {
|
|
144
|
-
connectError =
|
|
145
|
-
"Cloudflare connected, but the assistant backend still reports the connection as unusable. " +
|
|
146
|
-
"Try reconnecting, or use your own API key below.";
|
|
181
|
+
await chooseAccount();
|
|
182
|
+
return;
|
|
147
183
|
}
|
|
184
|
+
await verifyConnection();
|
|
148
185
|
}
|
|
149
186
|
|
|
150
187
|
async function connect() {
|
|
@@ -155,7 +192,11 @@ export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnec
|
|
|
155
192
|
connectError = "";
|
|
156
193
|
opts.requestRender();
|
|
157
194
|
try {
|
|
158
|
-
|
|
195
|
+
/* `cf_account_required` is a grant that already works for authorization and names no
|
|
196
|
+
account; the OAuth flow would land straight back here (ai.md §2.1). */
|
|
197
|
+
await (needsAccount()
|
|
198
|
+
? chooseAccount()
|
|
199
|
+
: settle((await getPlatform().cfConnect?.()) ?? null));
|
|
159
200
|
} catch (error) {
|
|
160
201
|
connectError = error instanceof Error ? error.message : String(error);
|
|
161
202
|
}
|
|
@@ -165,6 +206,14 @@ export function createManagedConnect(opts: ManagedConnectOptions): ManagedConnec
|
|
|
165
206
|
|
|
166
207
|
/** What the offer says right now — the whole of what the surface is told. */
|
|
167
208
|
function view(): ManagedConnectView {
|
|
209
|
+
if (needsAccount()) {
|
|
210
|
+
return {
|
|
211
|
+
buttonLabel: busy ? "Choosing…" : "Choose Cloudflare account",
|
|
212
|
+
busy,
|
|
213
|
+
error: connectError,
|
|
214
|
+
intro: LEDE_ACCOUNT,
|
|
215
|
+
};
|
|
216
|
+
}
|
|
168
217
|
const lapsed = proxyStateCode() === "cf_reconnect_required";
|
|
169
218
|
const idleLabel = lapsed ? "Reconnect Cloudflare" : "Connect Cloudflare";
|
|
170
219
|
return {
|
package/src/ui/color-selector.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* Spectrum surface in Studio, and the island `studio-ui-guidelines.md` §9.4 describes: the Style
|
|
8
8
|
* tab and the Content tab each drew an empty `[part="control-host"]` and this filled it with lit.
|
|
9
9
|
*
|
|
10
|
-
* §5.6 landed, so the control is `jx-color-field` and both tabs draw it inline in their own
|
|
10
|
+
* `ui.md` §5.6 landed, so the control is `jx-color-field` and both tabs draw it inline in their own
|
|
11
11
|
* documents. What no kit element can answer is what is LEFT here: which colours this project has
|
|
12
12
|
* given a name to. That is a question about the document being edited — the `--color-*` custom
|
|
13
13
|
* properties of the effective style, site and document together — and it is Studio's to answer.
|
|
@@ -185,7 +185,7 @@ function restrictGroups(operators: readonly string[]): ExprSelectGroup[] {
|
|
|
185
185
|
})).filter((group) => group.rows.length > 0);
|
|
186
186
|
}
|
|
187
187
|
|
|
188
|
-
/** The three rungs of the value ladder, spelled the way `ui/value-source.ts` spells them (§6.
|
|
188
|
+
/** The three rungs of the value ladder, spelled the way `ui/value-source.ts` spells them (§6.6). */
|
|
189
189
|
const SOURCE_OPTIONS: ExprOption[] = [
|
|
190
190
|
{ label: VALUE_SOURCE_LABELS.literal, value: "literal" },
|
|
191
191
|
{ label: VALUE_SOURCE_LABELS.ref, value: "ref" },
|
|
@@ -298,7 +298,7 @@ function operatorInfo(op: string): OperatorInfo {
|
|
|
298
298
|
/**
|
|
299
299
|
* Which rung of the value ladder an operand occupies. The three answers are the same three the
|
|
300
300
|
* Properties, Style and Logic tabs give, and they are spelled the same way — `ui/value-source.ts`
|
|
301
|
-
* owns the words, so `lit / $ref / expr` is gone from the operand picker (
|
|
301
|
+
* owns the words, so `lit / $ref / expr` is gone from the operand picker (§6.6).
|
|
302
302
|
*
|
|
303
303
|
* @param {unknown} operand
|
|
304
304
|
* @returns {"ref" | "expression" | "literal"}
|
|
@@ -1058,7 +1058,7 @@ export function flattenExpression(
|
|
|
1058
1058
|
|
|
1059
1059
|
/**
|
|
1060
1060
|
* The projection ONE operand slot reads as — a statement's `if` test, a `$switch` discriminant, a
|
|
1061
|
-
* `dispatchEvent` detail (spec §20). The same rows, with no operator row above them.
|
|
1061
|
+
* `dispatchEvent` detail (spec.md §20). The same rows, with no operator row above them.
|
|
1062
1062
|
*/
|
|
1063
1063
|
export function flattenOperand(
|
|
1064
1064
|
operand: unknown,
|
package/src/ui/form-controls.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* JSON-Schema field editor), "secret" (value committed via the host's secret store, never
|
|
5
5
|
* project.json) and "reference" (an entry of another content collection).
|
|
6
6
|
*
|
|
7
|
-
* Three, not the four the spec still lists: `"binding"` was the signal/route-param picker, and
|
|
8
|
-
*
|
|
7
|
+
* Three, not the four the spec still lists: `"binding"` was the signal/route-param picker, and the
|
|
8
|
+
* value-source ladder every scalar field now carries replaced it (§6.6; `ui/dynamic-slot.ts`,
|
|
9
9
|
* `ui/value-source.ts`). Nothing has registered it since, so a descriptor naming it falls through
|
|
10
10
|
* to the control its type would have had anyway.
|
|
11
11
|
*
|
|
@@ -705,13 +705,14 @@ registerFormControl("secret", secretControl);
|
|
|
705
705
|
|
|
706
706
|
/**
|
|
707
707
|
* An entry of another content collection — site-architecture.md §6.1's `{ "$ref": "#/content/x" }`
|
|
708
|
-
* and §7.4's "entry picker (dropdown of collection entries)".
|
|
708
|
+
* and site-architecture.md §7.4's "entry picker (dropdown of collection entries)".
|
|
709
709
|
*
|
|
710
710
|
* **Registered once, consulted by everything.** `ui/schema-form.ts` dispatches to it for any
|
|
711
711
|
* property whose `$ref` names a collection, so the settings forms, the entry editor and the
|
|
712
712
|
* frontmatter card all draw the same picker without any of them knowing it exists. That is the
|
|
713
|
-
* whole point:
|
|
714
|
-
* their own, so this one arrives as a registration rather than as a fourth
|
|
713
|
+
* whole point: the value-source ladder (§6.6) collapsed six vocabularies into one and three call
|
|
714
|
+
* sites still spoke their own, so this one arrives as a registration rather than as a fourth
|
|
715
|
+
* renderer.
|
|
715
716
|
*
|
|
716
717
|
* Three states, and none of them lies:
|
|
717
718
|
*
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Formula catalog — the metadata registry behind the formula palette, chip labels, and Monaco
|
|
3
|
-
* completions (spec §19). Merges three sources into one uniform entry shape:
|
|
3
|
+
* completions (spec.md §19). Merges three sources into one uniform entry shape:
|
|
4
4
|
*
|
|
5
5
|
* 1. Blessed operators (hand-authored metadata for every member of `BLESSED_OPERATORS`),
|
|
6
6
|
* 2. Blessed pure globals (derived programmatically from `BLESSED_GLOBALS`),
|
|
@@ -314,7 +314,7 @@ export function operatorEntries(): FormulaCatalogEntry[] {
|
|
|
314
314
|
return out;
|
|
315
315
|
}
|
|
316
316
|
|
|
317
|
-
// ─── Pure standard-library methods (derived, spec §19.4d)
|
|
317
|
+
// ─── Pure standard-library methods (derived, spec.md §19.4d) ────────────────
|
|
318
318
|
|
|
319
319
|
/** Prototype owner per pure method — drives grouping and the derived description. */
|
|
320
320
|
const PURE_METHOD_PROTO: Record<string, string> = {
|
|
@@ -367,7 +367,7 @@ export const ZERO_ARG_METHODS = new Set([
|
|
|
367
367
|
"trimStart",
|
|
368
368
|
]);
|
|
369
369
|
|
|
370
|
-
/** The derived catalog entry for one pure method operator (spec §19.4d). */
|
|
370
|
+
/** The derived catalog entry for one pure method operator (spec.md §19.4d). */
|
|
371
371
|
function pureMethodEntry(op: string): FormulaCatalogEntry {
|
|
372
372
|
const proto = PURE_METHOD_PROTO[op] ?? "Standard library";
|
|
373
373
|
return {
|
|
@@ -387,7 +387,7 @@ function pureMethodEntry(op: string): FormulaCatalogEntry {
|
|
|
387
387
|
// ─── Blessed globals (derived) ──────────────────────────────────────────────
|
|
388
388
|
|
|
389
389
|
/**
|
|
390
|
-
* Synthetic blessed helpers wrap constructor-shaped standard-library APIs (spec §19.4c); their
|
|
390
|
+
* Synthetic blessed helpers wrap constructor-shaped standard-library APIs (spec.md §19.4c); their
|
|
391
391
|
* catalog descriptions name the wrapped API rather than claiming a literal global exists.
|
|
392
392
|
*/
|
|
393
393
|
const HELPER_DESCRIPTIONS: Record<string, string> = {
|
package/src/ui/formula-chips.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Formula chips — the MODEL behind the chip pipeline (spec §19.9): an expression tree read as a
|
|
3
|
-
* of chips, left to right. The `target` chain unrolls deepest-first, so the head chip is the
|
|
2
|
+
* Formula chips — the MODEL behind the chip pipeline (spec.md §19.9): an expression tree read as a
|
|
3
|
+
* row of chips, left to right. The `target` chain unrolls deepest-first, so the head chip is the
|
|
4
4
|
* innermost target operand (a ref or a literal) and each operator follows it out to the root;
|
|
5
5
|
* nested non-target operands (`value`, `initial`, a `switch` case, a positional arg) become
|
|
6
6
|
* parenthesized group chips beside the link they belong to.
|
package/src/ui/layers.ts
CHANGED
|
@@ -4,13 +4,13 @@
|
|
|
4
4
|
*
|
|
5
5
|
* Everything renders into one of the four fixed hosts declared in index.html (#layer-popover,
|
|
6
6
|
* #layer-modal, #layer-dialog, #layer-toast), bound once at boot by initLayers(). Native browser
|
|
7
|
-
* dialogs (`prompt`, `confirm`, `alert`) are not permitted anywhere in Studio
|
|
8
|
-
* `showPromptDialog`, `showConfirmDialog`, or
|
|
9
|
-
*
|
|
7
|
+
* dialogs (`prompt`, `confirm`, `alert`) are not permitted anywhere in Studio
|
|
8
|
+
* (studio-ui-guidelines.md §8.7) — use `showPromptDialog`, `showConfirmDialog`, or
|
|
9
|
+
* `showSaveDiscardDialog`.
|
|
10
10
|
*
|
|
11
|
-
* The toast host is the fourth layer (
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* The toast host is the fourth layer (§16.1). It is a rendering of `services/notify.ts`'s `toasts`
|
|
12
|
+
* array and owns exactly two things that array does not: the timer that retires a resting toast,
|
|
13
|
+
* and the transition account {@link overlayIdleBlockers} publishes.
|
|
14
14
|
*/
|
|
15
15
|
import { render as litRender, nothing } from "lit-html";
|
|
16
16
|
import { overlayRegion, REGION_ATTR } from "./regions";
|
|
@@ -117,7 +117,8 @@ export function isModalOpen(): boolean {
|
|
|
117
117
|
* `showPromptDialog` below are the three named questions, and they go through the same document.
|
|
118
118
|
*
|
|
119
119
|
* A body that is genuinely richer than a sentence is an ISLAND, not a new dialog: `message` accepts
|
|
120
|
-
* a lit template and `messageOptions` renders it into the document's `[part="island"]`
|
|
120
|
+
* a lit template and `messageOptions` renders it into the document's `[part="island"]`
|
|
121
|
+
* (studio-ui-guidelines.md §9.4).
|
|
121
122
|
*/
|
|
122
123
|
|
|
123
124
|
/**
|
|
@@ -208,7 +209,7 @@ export function showSaveDiscardDialog(
|
|
|
208
209
|
|
|
209
210
|
/**
|
|
210
211
|
* A message as the surface takes it: a sentence, or a lit template rendered into the document's
|
|
211
|
-
* island once the element is ready — the island rule of studio-ui-guidelines §9.4.
|
|
212
|
+
* island once the element is ready — the island rule of studio-ui-guidelines.md §9.4.
|
|
212
213
|
*/
|
|
213
214
|
function messageOptions(
|
|
214
215
|
message: string | TemplateResult,
|
|
@@ -485,19 +486,20 @@ const _toastEntering = new Set<string>();
|
|
|
485
486
|
/**
|
|
486
487
|
* Whether the reader has asked for less movement.
|
|
487
488
|
*
|
|
488
|
-
* Read per call rather than cached:
|
|
489
|
-
* the
|
|
489
|
+
* Read per call rather than cached: motion is not among the three things §13.5 lets `?automation=1`
|
|
490
|
+
* change, so the app must HONOUR this rather than have the runner inject a freeze stylesheet, which
|
|
491
|
+
* means the answer has to be able to change.
|
|
490
492
|
*/
|
|
491
493
|
function reducedMotion(): boolean {
|
|
492
494
|
return globalThis.matchMedia?.("(prefers-reduced-motion: reduce)").matches === true;
|
|
493
495
|
}
|
|
494
496
|
|
|
495
497
|
/**
|
|
496
|
-
* **One of the three
|
|
497
|
-
*
|
|
498
|
-
*
|
|
499
|
-
* `
|
|
500
|
-
*
|
|
498
|
+
* **One of the three exceptions §13.5 lists** — behaviour that differs under `?automation=1` beyond
|
|
499
|
+
* installing the hook, pinning the clock and selecting a profile. The other two are both refusals
|
|
500
|
+
* to touch the project on disk: `packages/ensure-deps.ts` declines to run `bun install`, and
|
|
501
|
+
* `packages/jxsuite-update.ts` declines to prompt for a dependency update. This one is the only
|
|
502
|
+
* exception that changes what a picture SHOWS rather than what it avoids doing.
|
|
501
503
|
*
|
|
502
504
|
* A toast is the single surface in the app whose lifetime is a TIMER rather than a state. Every
|
|
503
505
|
* other surface a shot can photograph is there because the app is in a state, and it stays there
|
|
@@ -507,9 +509,9 @@ function reducedMotion(): boolean {
|
|
|
507
509
|
* as long as they cared to look, instead of showing the toast that happened to still be there.
|
|
508
510
|
*
|
|
509
511
|
* The gate is re-derived from `location.search` rather than imported from `services/automation.ts`
|
|
510
|
-
* deliberately:
|
|
511
|
-
*
|
|
512
|
-
* pulls in would ship it everywhere. One line of duplication, on purpose.
|
|
512
|
+
* deliberately: the scripting surface must stay out of the desktop and cloud bundles (no spec
|
|
513
|
+
* states it and `check-bundle-budget.ts` does not assert it yet), and importing it from a module
|
|
514
|
+
* every layer pulls in would ship it everywhere. One line of duplication, on purpose.
|
|
513
515
|
*/
|
|
514
516
|
export function toastsAreHeld(): boolean {
|
|
515
517
|
try {
|
package/src/ui/panel-resize.ts
CHANGED
|
@@ -58,11 +58,11 @@ import type { SplitModifiers } from "@jxsuite/ui/behaviors/split";
|
|
|
58
58
|
*
|
|
59
59
|
* **There is no pointer path left in this module**, and it is worth recording why rather than
|
|
60
60
|
* quietly dropping it: a handle driven by pointer events alone is unreachable from a keyboard,
|
|
61
|
-
* which is an SC 2.1.1 failure however it is drawn. The pane split moved to `jx-split` first
|
|
62
|
-
* §5.5), the three docks followed, and the Edit column was last because its handle SNAPS —
|
|
63
|
-
* element had no way to tell a host which modifiers a step carried. It has now: every
|
|
64
|
-
* carries them, so a snap lives in {@link bindSplit} rather than in a pointer handler of
|
|
65
|
-
* module's own.
|
|
61
|
+
* which is an SC 2.1.1 failure however it is drawn. The pane split moved to `jx-split` first
|
|
62
|
+
* (`ui.md` §5.5), the three docks followed, and the Edit column was last because its handle SNAPS —
|
|
63
|
+
* and the element had no way to tell a host which modifiers a step carried. It has now: every
|
|
64
|
+
* `input` carries them, so a snap lives in {@link bindSplit} rather than in a pointer handler of
|
|
65
|
+
* this module's own.
|
|
66
66
|
*/
|
|
67
67
|
export interface ResizeTarget {
|
|
68
68
|
/** Which coordinate the drag reads. */
|
|
@@ -66,8 +66,8 @@ export interface OpenPopoverSurfaceOptions {
|
|
|
66
66
|
/** The platform closed it — clicked outside, Escape, or a second press on the invoker. */
|
|
67
67
|
onDismissed?: () => void;
|
|
68
68
|
/**
|
|
69
|
-
* A node the document made exists. The one seam an island reaches its host through
|
|
70
|
-
* straight to the runtime.
|
|
69
|
+
* A node the document made exists. The one seam an island reaches its host through
|
|
70
|
+
* (studio-ui-guidelines.md §9.4), passed straight to the runtime.
|
|
71
71
|
*/
|
|
72
72
|
onNodeCreated?: JxMountOptions["onNodeCreated"];
|
|
73
73
|
}
|