@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/studio.ts
CHANGED
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
|
|
56
56
|
import { isEditing } from "./editor/inline-edit";
|
|
57
57
|
import { applyTransform, registerCanvasViewCommands } from "./canvas/canvas-utils";
|
|
58
|
-
import { diffCommands } from "./canvas/diff-toolbar";
|
|
58
|
+
import { diffCommands, setDiffChromeRepaint } from "./canvas/diff-toolbar";
|
|
59
59
|
import type { CanvasSurface } from "./canvas/canvas-surface";
|
|
60
60
|
import {
|
|
61
61
|
initCanvasRender,
|
|
@@ -107,8 +107,8 @@ import {
|
|
|
107
107
|
setDocumentSavedListener,
|
|
108
108
|
} from "./files/file-ops";
|
|
109
109
|
import { serializeDocument } from "./files/serialize-document";
|
|
110
|
-
import { parseJsonDocument } from "
|
|
111
|
-
import type { JsonLayout } from "
|
|
110
|
+
import { parseJsonDocument } from "@jxsuite/schema/json-layout";
|
|
111
|
+
import type { JsonLayout } from "@jxsuite/schema/json-layout";
|
|
112
112
|
import {
|
|
113
113
|
formatForPath,
|
|
114
114
|
loadFormats,
|
|
@@ -154,7 +154,7 @@ import { seedPublishConnected } from "./publish/publish-panel";
|
|
|
154
154
|
|
|
155
155
|
import { getPlatform, hasPlatform, registerPlatform } from "./platform";
|
|
156
156
|
import { parseMediaEntries } from "./utils/canvas-media";
|
|
157
|
-
import { resolveDefaultPlatform } from "./platforms/default-platform";
|
|
157
|
+
import { PlatformUnavailableError, resolveDefaultPlatform } from "./platforms/default-platform";
|
|
158
158
|
import { mountResizeEdges } from "./resize-edges";
|
|
159
159
|
import {
|
|
160
160
|
defBadgeLabel,
|
|
@@ -266,7 +266,7 @@ import type { GitDiffState } from "./types";
|
|
|
266
266
|
import type { Tab } from "./tabs/tab";
|
|
267
267
|
import type { JxDocument, JxMutableNode, ProjectConfig } from "@jxsuite/schema/types";
|
|
268
268
|
import { setBundleBase } from "./services/bundle-base";
|
|
269
|
-
import { mountShellTree } from "./shell/tree";
|
|
269
|
+
import { mountBootFailureTree, mountShellTree } from "./shell/tree";
|
|
270
270
|
|
|
271
271
|
// The bundler's `<link rel=modulepreload>` batching is installed on the module scope: before the
|
|
272
272
|
// First lazy `import()` of any surface that runs, so the palette's first open does not pay a
|
|
@@ -388,9 +388,9 @@ function setCanvasMode(tab: Tab | null, mode: string) {
|
|
|
388
388
|
*
|
|
389
389
|
* Four deliberate properties, three of them new and each with a failure behind it:
|
|
390
390
|
*
|
|
391
|
-
* 1. **To the side.** §
|
|
392
|
-
* `openFileInTab` → `openTab` → `activePane()`, so "open the
|
|
393
|
-
* it ON TOP of the page it was teaching about.
|
|
391
|
+
* 1. **To the side.** §14.2 says so, the shell redesign had promised it since its chrome phase, and it
|
|
392
|
+
* never shipped — the chain ran `openFileInTab` → `openTab` → `activePane()`, so "open the
|
|
393
|
+
* layout that wraps this page" opened it ON TOP of the page it was teaching about.
|
|
394
394
|
* 2. **The focus FOLLOWS.** The open is a gesture, not a read: the author asked to edit the component,
|
|
395
395
|
* so the pane it lands in takes the keyboard. The failure it replaces is the opposite one — an
|
|
396
396
|
* assistant pane that takes the keyboard means the author's next keystroke edits the definition
|
|
@@ -453,8 +453,24 @@ initCssData(webdata);
|
|
|
453
453
|
// Register the default platform adapter (PAL) if none was pre-registered (desktop registers its own
|
|
454
454
|
// On window.__jxPlatform). resolveDefaultPlatform picks cloud when the shell signalled it, creating
|
|
455
455
|
// The cloud adapter inside THIS bundle so collab shares studio's single yjs, else the dev server.
|
|
456
|
+
//
|
|
457
|
+
// Unless a launcher was declared or announced and registered nothing: then there is no adapter to
|
|
458
|
+
// Pick, and resolveDefaultPlatform throws rather than hand a desktop window the dev-server adapter
|
|
459
|
+
// (what 5.0.0-5.1.3 did — a frame that drew, and a first click that said "Failed to fetch"). The
|
|
460
|
+
// Boot-failure screen is drawn INSTEAD of the frame, and the error is rethrown because ESM has no
|
|
461
|
+
// Top-level return: stopping the module is the only way to keep every line below from running
|
|
462
|
+
// Against no platform, and the uncaught error is the console's copy of what the screen says.
|
|
463
|
+
// Nothing above this line may call getPlatform(), or it would throw first with a message about
|
|
464
|
+
// Registration order instead of this one.
|
|
456
465
|
if (!hasPlatform()) {
|
|
457
|
-
|
|
466
|
+
try {
|
|
467
|
+
registerPlatform(resolveDefaultPlatform());
|
|
468
|
+
} catch (error) {
|
|
469
|
+
if (error instanceof PlatformUnavailableError) {
|
|
470
|
+
await mountBootFailureTree(error.refusal);
|
|
471
|
+
}
|
|
472
|
+
throw error;
|
|
473
|
+
}
|
|
458
474
|
}
|
|
459
475
|
|
|
460
476
|
mountResizeEdges();
|
|
@@ -510,6 +526,9 @@ paneContext.mount(primaryCell?.chrome ?? document.createElement("div"), {
|
|
|
510
526
|
parseMediaEntries,
|
|
511
527
|
setCanvasMode,
|
|
512
528
|
});
|
|
529
|
+
/* The diff's Visual/Code switch decides whether the zoom pod is drawn, and the half it writes is
|
|
530
|
+
not reactive — so the switch repaints the chrome as well as the stage. See `setDiffChromeRepaint`. */
|
|
531
|
+
setDiffChromeRepaint(paneContext.render);
|
|
513
532
|
|
|
514
533
|
overlaysPanel.mount({
|
|
515
534
|
isEditing,
|
|
@@ -611,7 +630,7 @@ export function hasUnsavedTabs(): boolean {
|
|
|
611
630
|
}
|
|
612
631
|
|
|
613
632
|
window.addEventListener("beforeunload", (e: BeforeUnloadEvent) => {
|
|
614
|
-
// The session, so a relaunch reopens what was open (§
|
|
633
|
+
// The session, so a relaunch reopens what was open (§14.8). Before the prompt, not after: the
|
|
615
634
|
// Author may cancel the close, and the record is the same either way.
|
|
616
635
|
flushSession();
|
|
617
636
|
if (hasUnsavedTabs()) {
|
|
@@ -667,11 +686,10 @@ initWelcome({
|
|
|
667
686
|
}
|
|
668
687
|
},
|
|
669
688
|
cloneRepository: () => cloneRepository({ openRecentProject }),
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
}
|
|
689
|
+
// The wizard adopts what it creates itself now (new-project-modal.ts's finishCreated) — there is
|
|
690
|
+
// Nothing left for the welcome screen to do with the result.
|
|
691
|
+
openNewProject: (options) => {
|
|
692
|
+
void openNewProjectModal(options);
|
|
675
693
|
},
|
|
676
694
|
openProject: () => openProject(),
|
|
677
695
|
openRecentProject: (root: string) => openRecentProject(root),
|
|
@@ -892,7 +910,7 @@ registerRenderer("chatPanel", () => chatPanelMod.render());
|
|
|
892
910
|
registerRenderer("overlays", () => overlaysPanel.render());
|
|
893
911
|
renderStatusbar();
|
|
894
912
|
mountStatusbar();
|
|
895
|
-
//
|
|
913
|
+
// The jump bar, in the pane's own grid cell above the context bar. It renders the whole address
|
|
896
914
|
// — project › file › node › node — and it is the only breadcrumb in the shell: the pane context
|
|
897
915
|
// Bar drew a second one, and it named a sub-document stack nothing could push onto.
|
|
898
916
|
mountJumpBar(primaryCell?.jump ?? document.createElement("div"));
|
|
@@ -1056,7 +1074,7 @@ if (_projectParam) {
|
|
|
1056
1074
|
*
|
|
1057
1075
|
* A named document is an instruction and wins, whether it came from `?file=` or from a
|
|
1058
1076
|
* `?project=` that pointed INTO the project. A bare `?project=<dir>` is "open this
|
|
1059
|
-
* project", and what that means is the documents it was last left with (§
|
|
1077
|
+
* project", and what that means is the documents it was last left with (§14.8) — the
|
|
1060
1078
|
* `project.json → home page` redirect below is the answer this replaces.
|
|
1061
1079
|
*
|
|
1062
1080
|
* This branch opens inline and never went near `openHomePage`, so it was the one door of
|
|
@@ -1130,7 +1148,7 @@ if (_projectParam) {
|
|
|
1130
1148
|
render();
|
|
1131
1149
|
// Opening a file is stated by the tab strip and the status bar's DOCUMENT field.
|
|
1132
1150
|
}
|
|
1133
|
-
/* This window may now write its session (§
|
|
1151
|
+
/* This window may now write its session (§14.8). The `?file=` branch above opens inline and
|
|
1134
1152
|
never reaches `openLastSessionOrHome`, which is the other place that says this — so
|
|
1135
1153
|
without it a window opened at a named file would restore other windows' sessions and
|
|
1136
1154
|
never record its own. */
|
|
@@ -1477,11 +1495,11 @@ commandRegistry.registerAll(derivationCommands(derivationDeps));
|
|
|
1477
1495
|
/*
|
|
1478
1496
|
* The rest of the app's contribution points, each defined beside the state it writes.
|
|
1479
1497
|
*
|
|
1480
|
-
* This block is the bootstrap's whole share of
|
|
1481
|
-
* in the module that implements it, and this is the ONE place that composes them into the
|
|
1482
|
-
* `__jxAutomation.run` projects. Nothing here decides what a command is called, when it is
|
|
1483
|
-
* available or what it does — that would be the second definition site the design exists to
|
|
1484
|
-
*
|
|
1498
|
+
* This block is the bootstrap's whole share of the registry work (§13, §13.5): every record below
|
|
1499
|
+
* lives in the module that implements it, and this is the ONE place that composes them into the
|
|
1500
|
+
* registry `__jxAutomation.run` projects. Nothing here decides what a command is called, when it is
|
|
1501
|
+
* available or what it does — that would be the second definition site the design exists to prevent
|
|
1502
|
+
* (§13).
|
|
1485
1503
|
*/
|
|
1486
1504
|
registerShellViewCommands(commandRegistry, {
|
|
1487
1505
|
// The registry's own answer, so a gated-off panel cannot be persisted as a showing tab.
|
|
@@ -1568,11 +1586,11 @@ registerGridViewCommands(commandRegistry);
|
|
|
1568
1586
|
registerRedirectsCommands(commandRegistry);
|
|
1569
1587
|
registerAboutCommands(commandRegistry);
|
|
1570
1588
|
registerCollabCommands(commandRegistry);
|
|
1571
|
-
/* The `Assistant:` family (§
|
|
1572
|
-
and Stop. Every one existed as a button in the chat view and as nothing else, so
|
|
1573
|
-
zero records and none of them was in the palette, bindable, or reachable by
|
|
1574
|
-
and the error row render these ids through the registry now, which is what
|
|
1575
|
-
definition site rather than a second copy. */
|
|
1589
|
+
/* The `Assistant:` family (`ai.md` §3.0) — Focus Composer, New Chat, Chat History, Attach
|
|
1590
|
+
Selection, Retry and Stop. Every one existed as a button in the chat view and as nothing else, so
|
|
1591
|
+
the category held zero records and none of them was in the palette, bindable, or reachable by
|
|
1592
|
+
name. The chat header and the error row render these ids through the registry now, which is what
|
|
1593
|
+
makes this line the definition site rather than a second copy. */
|
|
1576
1594
|
commandRegistry.registerAll(assistantCommands());
|
|
1577
1595
|
/*
|
|
1578
1596
|
* The structural selection verbs — Move Up/Down/In/Out, Convert to Component, Edit Component.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Pushing a project-style edit to every live canvas — one definition site.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
4
|
+
* §7.1's promise is that tuning a token shows the page changing, and until now that was true of
|
|
5
|
+
* exactly one kind of canvas. `postSiteStyleToLiveHosts` skips stylebook hosts by construction
|
|
6
|
+
* ({@link file://../canvas/iframe-host.ts}: `host.ready && !host.stylebook`), because a specimen
|
|
7
|
+
* canvas does not render the site sheet — it renders a GENERATED document whose root carries the
|
|
8
|
+
* transposed effective style, and its live channel is `styleUpdate`, not `siteStyleUpdate`. So a
|
|
9
|
+
* token edited in the token editor reached every page canvas immediately and left the Project
|
|
10
|
+
* Styles canvas — the one §7.1 puts _beside_ the editor — showing the old palette until something
|
|
11
|
+
* forced a full re-render.
|
|
12
12
|
*
|
|
13
13
|
* Two hosts, two messages, one event. Every surface that writes `projectConfig.style` calls this
|
|
14
14
|
* instead of picking one of the two posts, which is the only arrangement in which the pair cannot
|
|
@@ -3,13 +3,12 @@
|
|
|
3
3
|
*
|
|
4
4
|
* ## The name and the wire value are different things
|
|
5
5
|
*
|
|
6
|
-
* The surface a user reaches is called **Project Styles** (
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* surface that needs one must not reach for the other.
|
|
6
|
+
* The surface a user reaches is called **Project Styles** (§7.1). The canvas view it opens is the
|
|
7
|
+
* string `"stylebook"`, a member of `CANVAS_MODES` in {@link file://../canvas/iframe-protocol.ts}
|
|
8
|
+
* and therefore half of a `ParentToIframe` union: the studio bundle and `dist/iframe-entry.js`
|
|
9
|
+
* agree on it, and changing it means rebuilding both in lockstep. So it is not a name and may never
|
|
10
|
+
* be renamed to follow one. {@link PROJECT_STYLES_TITLE} is the name; {@link PROJECT_STYLES_VIEW}
|
|
11
|
+
* is the wire value; a surface that needs one must not reach for the other.
|
|
13
12
|
*
|
|
14
13
|
* ## One vocabulary for the `@` blocks
|
|
15
14
|
*
|
|
@@ -19,7 +18,7 @@
|
|
|
19
18
|
* {@link TokenContext} list so a surface cannot grow a second override path for the second kind (a
|
|
20
19
|
* per-scheme writer and a per-media writer that disagreed about pruning an emptied block is exactly
|
|
21
20
|
* what this replaces). Contexts are **defined** in Project Settings › Contexts and only selected or
|
|
22
|
-
* overridden here — §2
|
|
21
|
+
* overridden here — §6.2.
|
|
23
22
|
*
|
|
24
23
|
* On-disk format is unchanged by anything in this module: it reads and writes the same
|
|
25
24
|
* `style["--token"]` and `style["@--ctx"]["--token"]` shapes the compiler already consumes.
|
|
@@ -55,7 +54,7 @@ export interface TokenGroup {
|
|
|
55
54
|
|
|
56
55
|
/**
|
|
57
56
|
* The groups, in order. `other` is rendered only when something lands in it — a bucket named
|
|
58
|
-
* "Other" over an empty list teaches nothing (§
|
|
57
|
+
* "Other" over an empty list teaches nothing (`studio-ui-guidelines.md` §11.1).
|
|
59
58
|
*
|
|
60
59
|
* A group is a name and a prefix and nothing else. The example values an add row hints with are a
|
|
61
60
|
* property of the FORM, not of the model, and they live beside the form that shows them.
|
package/src/style/token-ref.ts
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* text says so only to a reader who already knows CSS: `var(--color-brand)` is eleven characters of
|
|
6
6
|
* syntax around a name, and the thing the author actually wants to know — _which_ token, and what
|
|
7
7
|
* it currently resolves to — is the part that is not shown. So a bound value renders as a **chip**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
8
|
+
* in the same vocabulary as the provenance chips (§6.7): the token's friendly name, and for a
|
|
9
|
+
* colour, its resolved swatch.
|
|
10
10
|
*
|
|
11
11
|
* The resolver follows a chain of references, because an alias token (`--color-accent:
|
|
12
12
|
* var(--color-brand)`) is the normal way a palette is built and a chip that stopped at the first
|
package/src/surfaces/about.json
CHANGED
|
@@ -59,9 +59,11 @@
|
|
|
59
59
|
"color": "var(--fg-dim)"
|
|
60
60
|
},
|
|
61
61
|
"& [part=\"meta-value\"]": {
|
|
62
|
+
"$description": "One of the two places in the chrome that opt back in to selection (`STYLING.md` §Text selection). The root sets `user-select: none` and `styles/tokens.json` restates it on every modal `dialog`, but this dialog's body IS its message: the version, the build date, the commit and the channel exist to be pasted into a bug report, and Studio offers no copy action for them.",
|
|
62
63
|
"margin": "0",
|
|
63
64
|
"color": "var(--fg)",
|
|
64
|
-
"wordBreak": "break-word"
|
|
65
|
+
"wordBreak": "break-word",
|
|
66
|
+
"userSelect": "text"
|
|
65
67
|
},
|
|
66
68
|
"& [part=\"links\"]": {
|
|
67
69
|
"display": "flex",
|
|
@@ -99,10 +101,12 @@
|
|
|
99
101
|
"gap": "4px"
|
|
100
102
|
},
|
|
101
103
|
"& [part=\"package-row\"]": {
|
|
104
|
+
"$description": "Selectable for the same reason `meta-value` is, and on the ROW rather than on the version alone: what a reader pastes is the pair, `@jxsuite/ai 0.37.0`, so a drag has to be able to cross from the name to the number and on down the list.",
|
|
102
105
|
"display": "flex",
|
|
103
106
|
"justifyContent": "space-between",
|
|
104
107
|
"gap": "12px",
|
|
105
|
-
"fontSize": "var(--jx-text-md)"
|
|
108
|
+
"fontSize": "var(--jx-text-md)",
|
|
109
|
+
"userSelect": "text"
|
|
106
110
|
},
|
|
107
111
|
"& [part=\"package-name\"]": {
|
|
108
112
|
"color": "var(--fg-dim)"
|
|
@@ -113,10 +113,10 @@
|
|
|
113
113
|
"color": "var(--danger)"
|
|
114
114
|
},
|
|
115
115
|
"& [part=\"access\"]": {
|
|
116
|
-
"$description": "The listing is bounded by what the Jx Suite GitHub App was granted, so the dialog always offers a way out of that boundary rather than only saying the list is short.",
|
|
116
|
+
"$description": "The listing is bounded by what the Jx Suite GitHub App was granted, so the dialog always offers a way out of that boundary rather than only saying the list is short. `center`, not `baseline`: the `Refresh` beside the note is a small kit button, and a small kit control is layout-contained so its outset hit area adds nothing to a scrolling ancestor's overflow, which leaves it with no baseline to export; a baseline row would synthesise one from its bottom edge and drop the note and the links onto it. surface-baseline-rows.test.ts holds the rule for every surface.",
|
|
117
117
|
"display": "flex",
|
|
118
118
|
"flexWrap": "wrap",
|
|
119
|
-
"alignItems": "
|
|
119
|
+
"alignItems": "center",
|
|
120
120
|
"gap": "var(--jx-space-2)",
|
|
121
121
|
"paddingTop": "var(--jx-space-3)",
|
|
122
122
|
"borderTop": "1px solid var(--border)",
|
package/src/surfaces/add-repo.ts
CHANGED
|
@@ -187,8 +187,8 @@ export function openAddRepoSurface(options: AddRepoSurfaceOptions): AddRepoSurfa
|
|
|
187
187
|
setFilter: (value: string) => {
|
|
188
188
|
/* What the control holds, first and unconditionally. A binding only writes when the scope
|
|
189
189
|
CHANGES, so a surface that decided a value without announcing the raw one would leave the
|
|
190
|
-
field showing text the scope does not have (§9.3). Nothing
|
|
191
|
-
is what makes a refusal possible at all. */
|
|
190
|
+
field showing text the scope does not have (`studio-ui-guidelines.md` §9.3). Nothing
|
|
191
|
+
refuses a filter today; the echo is what makes a refusal possible at all. */
|
|
192
192
|
scope.filter = value;
|
|
193
193
|
options.onFilter(value);
|
|
194
194
|
},
|
|
@@ -97,12 +97,15 @@
|
|
|
97
97
|
"color": "var(--fg-dim)"
|
|
98
98
|
},
|
|
99
99
|
"& [part=\"user-body\"]": {
|
|
100
|
+
"$description": "The transcript is content, not interface, and the panel offers no copy action, so each message body opts back in to selection against the root's `user-select: none`: this bubble, the model's `md`, the `streaming` text and the `import-log`. The header, the chips and the composer's buttons around them stay unselectable.",
|
|
100
101
|
"whiteSpace": "pre-wrap",
|
|
101
|
-
"overflowWrap": "anywhere"
|
|
102
|
+
"overflowWrap": "anywhere",
|
|
103
|
+
"userSelect": "text"
|
|
102
104
|
},
|
|
103
105
|
"& [part=\"md\"]": {
|
|
104
|
-
"$description": "The island `panels/ai-chat/chat-markdown.ts` fills — the app's ONE injection sink, and the markup reaching it has been through `markdownToHtml` and the Trusted Types policy that asserts it did. The document renders the host node and nothing inside it (specs/studio-ui-guidelines.md §9.4).",
|
|
105
|
-
"overflowWrap": "anywhere"
|
|
106
|
+
"$description": "The island `panels/ai-chat/chat-markdown.ts` fills — the app's ONE injection sink, and the markup reaching it has been through `markdownToHtml` and the Trusted Types policy that asserts it did. The document renders the host node and nothing inside it (specs/studio-ui-guidelines.md §9.4). A reply is the text a reader most often copies out of this panel, code blocks included, so it is selectable.",
|
|
107
|
+
"overflowWrap": "anywhere",
|
|
108
|
+
"userSelect": "text"
|
|
106
109
|
},
|
|
107
110
|
"& [part=\"md\"] > *:first-child": {
|
|
108
111
|
"marginTop": "0"
|
|
@@ -137,8 +140,10 @@
|
|
|
137
140
|
"padding": "var(--jx-space-1) 6px"
|
|
138
141
|
},
|
|
139
142
|
"& [part=\"streaming\"]": {
|
|
143
|
+
"$description": "The reply while it arrives, selectable for the reason `[part=\"md\"]` is. The cursor is generated content, which no selection ever includes.",
|
|
140
144
|
"whiteSpace": "pre-wrap",
|
|
141
145
|
"overflowWrap": "anywhere",
|
|
146
|
+
"userSelect": "text",
|
|
142
147
|
"::after": {
|
|
143
148
|
"content": "\"▋\"",
|
|
144
149
|
"color": "var(--accent)",
|
|
@@ -314,6 +319,8 @@
|
|
|
314
319
|
"marginRight": "var(--jx-space-2)"
|
|
315
320
|
},
|
|
316
321
|
"& [part=\"import-log\"]": {
|
|
322
|
+
"$description": "A captured log, kept selectable against the root's `user-select: none`: its lines are what a reader pastes into a bug report, and nothing here offers to copy them.",
|
|
323
|
+
"userSelect": "text",
|
|
317
324
|
"marginTop": "var(--jx-space-2)",
|
|
318
325
|
"maxHeight": "40vh",
|
|
319
326
|
"overflowY": "auto",
|
|
@@ -369,7 +376,8 @@
|
|
|
369
376
|
"color": "var(--warning)",
|
|
370
377
|
"fontStyle": "normal"
|
|
371
378
|
},
|
|
372
|
-
"& [part=\"error\"]": {
|
|
379
|
+
"& [part=\"error-card\"]": {
|
|
380
|
+
"$description": "The failed turn's card. It is `error-card` rather than `error` because the model picker mounted into the composer is a `jx-select`, and every kit field draws a permanent, empty `[part=\"error\"]` of its own in this same light-DOM tree: under that name this rule, padding and wash drew an 18×12 red bar over the picker's top-left corner that took the click. Its children keep the `error-` prefix, which the kit does not use.",
|
|
373
381
|
"borderLeft": "2px solid var(--danger)",
|
|
374
382
|
"borderRadius": "var(--jx-radius-sm)",
|
|
375
383
|
"background": "var(--hover-bg)",
|
|
@@ -552,7 +560,7 @@
|
|
|
552
560
|
"& [part=\"tool-chip\"][data-outcome=\"failed\"]": {
|
|
553
561
|
"borderLeftColor": "LinkText"
|
|
554
562
|
},
|
|
555
|
-
"& [part=\"error\"]": {
|
|
563
|
+
"& [part=\"error-card\"]": {
|
|
556
564
|
"borderLeftColor": "LinkText"
|
|
557
565
|
}
|
|
558
566
|
},
|
|
@@ -1511,7 +1519,7 @@
|
|
|
1511
1519
|
"shown": {
|
|
1512
1520
|
"tagName": "div",
|
|
1513
1521
|
"attributes": {
|
|
1514
|
-
"part": "error",
|
|
1522
|
+
"part": "error-card",
|
|
1515
1523
|
"role": "alert"
|
|
1516
1524
|
},
|
|
1517
1525
|
"children": [
|
package/src/surfaces/ai-chat.ts
CHANGED
|
@@ -48,7 +48,8 @@ const LOG_STICK_THRESHOLD = 24;
|
|
|
48
48
|
*
|
|
49
49
|
* The flow asks the registry; the document draws what it is told. A command the registry does not
|
|
50
50
|
* hold, or whose `when` is false, never becomes one of these — which is what keeps the panel a
|
|
51
|
-
* rendering of the registry rather than a second place its capabilities are decided
|
|
51
|
+
* rendering of the registry rather than a second place its capabilities are decided
|
|
52
|
+
* (`studio-ui-guidelines.md` §12.5).
|
|
52
53
|
*/
|
|
53
54
|
export interface ChatCommandView extends Record<string, unknown> {
|
|
54
55
|
/** The reconcile key. The command id, because a button is drawn once per bar. */
|
|
@@ -458,7 +459,8 @@ export function mountAiChatSurface(
|
|
|
458
459
|
host.replaceChildren();
|
|
459
460
|
/* Nothing is called on an element here, so the mount is all there is to wait for: the islands
|
|
460
461
|
announce themselves through `onNodeCreated` as they are created, which is one
|
|
461
|
-
`connectedCallback` EARLIER than awaiting the element would be
|
|
462
|
+
`connectedCallback` EARLIER than awaiting the element would be
|
|
463
|
+
(`studio-ui-guidelines.md` §1.1, "await the element"). */
|
|
462
464
|
void mountSurface("ai-chat", scope, host, {
|
|
463
465
|
onNodeCreated: (element, _path, def, state) => {
|
|
464
466
|
const part = partOf(def);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://jxsuite.com/schema/v1",
|
|
3
3
|
"$id": "StudioAiCredentialsForm",
|
|
4
|
-
"$description": "The AI provider credentials form every gate embeds below the keyless offer: a key, a model, an endpoint, and the two buttons that keep or abandon them. Everything here is a projection — `ui/ai-credentials-form.ts` keeps the drafts, decides what a fetch is sent with, what Save actually persists and whether
|
|
4
|
+
"$description": "The AI provider credentials form every gate embeds below the keyless offer: a key, a model, an endpoint, and the two buttons that keep or abandon them. Everything here is a projection — `ui/ai-credentials-form.ts` keeps the drafts, decides what a fetch is sent with, what Save actually persists and whether there is anything to Save or Cancel at all. This document never reads a setting and never calls the proxy.",
|
|
5
5
|
"tagName": "div",
|
|
6
6
|
"attributes": {
|
|
7
7
|
"part": "ai-creds-form",
|
|
@@ -17,8 +17,7 @@
|
|
|
17
17
|
"maxWidth": "320px",
|
|
18
18
|
"textAlign": "left",
|
|
19
19
|
"& [part=\"title\"]": {
|
|
20
|
-
"$description": "
|
|
21
|
-
"alignSelf": "center",
|
|
20
|
+
"$description": "Weight alone, and no `align-self`. It was centred over the column on the grounds that the form is a titled block rather than a list of labelled rows, and in Preferences it is neither: the sheet's own heading, the blurb, this note, the `Model` label and all three fields start at the column's inline edge, so a centred line 102px wide in a 320px column read as a stray, not as a title. A heading belongs over the first character of the thing it names.",
|
|
22
21
|
"fontWeight": "600"
|
|
23
22
|
},
|
|
24
23
|
"& [part=\"note\"]": {
|
|
@@ -38,17 +37,22 @@
|
|
|
38
37
|
"width": "100%"
|
|
39
38
|
},
|
|
40
39
|
"& [part=\"models\"]": {
|
|
40
|
+
"$description": "A wrapping row that holds the button and, when there is one, the reason the listing did not finish — and the reason always takes a line of its own, which is what `flex-basis: 100%` on it (below) is for. Beside the button it began 96px into a 320px column, so a six-line upstream body read as a paragraph indented past the control it answers for, while the button floated at that block's vertical middle with about 40px of dead space around it. Under the button, at the column's own inline edge, the reason starts where every other line in the form starts. `flex-start` rather than `center` so that a line which does hold two boxes lines up their first lines and not their middles.",
|
|
41
41
|
"display": "flex",
|
|
42
|
-
"
|
|
42
|
+
"flexWrap": "wrap",
|
|
43
|
+
"alignItems": "flex-start",
|
|
43
44
|
"gap": "var(--jx-space-3)"
|
|
44
45
|
},
|
|
45
46
|
"& [part=\"models-error\"]": {
|
|
46
|
-
"$description": "Why the listing did not finish,
|
|
47
|
+
"$description": "Why the listing did not finish, said under the button that would try it again. Named `models-error` rather than `error` because the kit's own fields render a permanent `[part=\"error\"]` region of their own, and a surface that reused the name would be addressing three empty paragraphs before it reached its own. `flexBasis: 100%` is what puts it under the button rather than beside it: the row wraps, and a basis of the whole line cannot share one, so however short the reason is it always reads as a line of the form (`[part=\"models\"]`). `minWidth: 0` and `overflowWrap: anywhere` because the reason is often an upstream body passed through whole — a 401's JSON is one unbroken word — and a flex item's automatic minimum is its min-content width: one measured 853px inside the 320px column, and scrolled the whole Preferences section sideways over the buttons below it.",
|
|
47
48
|
"color": "var(--danger)",
|
|
48
|
-
"fontSize": "var(--jx-text-sm)"
|
|
49
|
+
"fontSize": "var(--jx-text-sm)",
|
|
50
|
+
"flexBasis": "100%",
|
|
51
|
+
"minWidth": "0",
|
|
52
|
+
"overflowWrap": "anywhere"
|
|
49
53
|
},
|
|
50
54
|
"& [part=\"actions\"]": {
|
|
51
|
-
"$description": "Buttons at the end of the column, in the order a dismissal precedes a commitment.",
|
|
55
|
+
"$description": "Buttons at the end of the column, in the order a dismissal precedes a commitment. Still a flex item of the column although it is drawn inside `[part=\"actions-slot\"]`, because that slot is `display: contents` — which is what keeps `alignSelf` meaning the column's end.",
|
|
52
56
|
"display": "flex",
|
|
53
57
|
"alignSelf": "flex-end",
|
|
54
58
|
"gap": "var(--jx-space-3)"
|
|
@@ -250,26 +254,26 @@
|
|
|
250
254
|
}
|
|
251
255
|
},
|
|
252
256
|
{
|
|
257
|
+
"$description": "The commit pair exists only while there is something to commit: `dirty` is the flow's answer to whether Save would change what is stored, compared after the store's own normalisation, so a pasted key's whitespace is not an edit. At rest neither button is drawn. The rule this replaced offered Cancel whenever a key was stored and Save always, so Preferences › Assistant showed a Save that would re-store what was there and a Cancel that abandoned nothing, beside the dialog's own Close. Absent rather than disabled, against the house rule for a control that cannot act, because the pair IS the pending edit's affordance: a disabled pair at rest would still be the two buttons the reader reported seeing with nothing to save, each needing a reason to give for being there. Answering either takes away the button that was pressed, so `surfaces/ai-credentials-form.ts` lands focus on the key field rather than letting it fall out of the sheet.",
|
|
253
258
|
"tagName": "div",
|
|
254
259
|
"attributes": {
|
|
255
|
-
"part": "actions"
|
|
260
|
+
"part": "actions-slot",
|
|
261
|
+
"role": "none"
|
|
256
262
|
},
|
|
257
|
-
"
|
|
258
|
-
|
|
263
|
+
"style": {
|
|
264
|
+
"display": "contents"
|
|
265
|
+
},
|
|
266
|
+
"$switch": {
|
|
267
|
+
"$ref": "#/state/dirty"
|
|
268
|
+
},
|
|
269
|
+
"cases": {
|
|
270
|
+
"true": {
|
|
259
271
|
"tagName": "div",
|
|
260
272
|
"attributes": {
|
|
261
|
-
"part": "
|
|
262
|
-
"role": "none"
|
|
263
|
-
},
|
|
264
|
-
"style": {
|
|
265
|
-
"display": "contents"
|
|
266
|
-
},
|
|
267
|
-
"$switch": {
|
|
268
|
-
"$ref": "#/state/haveKey"
|
|
273
|
+
"part": "actions"
|
|
269
274
|
},
|
|
270
|
-
"
|
|
271
|
-
|
|
272
|
-
"$description": "Only offered once a key exists: with nothing stored there is nothing to go back to, and a Cancel that abandons an empty form to an empty form is a button that does nothing.",
|
|
275
|
+
"children": [
|
|
276
|
+
{
|
|
273
277
|
"tagName": "jx-button",
|
|
274
278
|
"attributes": {
|
|
275
279
|
"part": "cancel"
|
|
@@ -295,38 +299,38 @@
|
|
|
295
299
|
"textContent": "Cancel"
|
|
296
300
|
}
|
|
297
301
|
]
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
},
|
|
301
|
-
{
|
|
302
|
-
"tagName": "jx-button",
|
|
303
|
-
"attributes": {
|
|
304
|
-
"part": "save"
|
|
305
|
-
},
|
|
306
|
-
"$props": {
|
|
307
|
-
"size": "sm",
|
|
308
|
-
"variant": "accent"
|
|
309
|
-
},
|
|
310
|
-
"onclick": {
|
|
311
|
-
"$prototype": "Function",
|
|
312
|
-
"body": [
|
|
313
|
-
{
|
|
314
|
-
"operator": "call",
|
|
315
|
-
"target": {
|
|
316
|
-
"$ref": "#/state/save"
|
|
317
|
-
},
|
|
318
|
-
"value": []
|
|
319
|
-
}
|
|
320
|
-
]
|
|
321
|
-
},
|
|
322
|
-
"children": [
|
|
302
|
+
},
|
|
323
303
|
{
|
|
324
|
-
"tagName": "
|
|
325
|
-
"
|
|
304
|
+
"tagName": "jx-button",
|
|
305
|
+
"attributes": {
|
|
306
|
+
"part": "save"
|
|
307
|
+
},
|
|
308
|
+
"$props": {
|
|
309
|
+
"size": "sm",
|
|
310
|
+
"variant": "accent"
|
|
311
|
+
},
|
|
312
|
+
"onclick": {
|
|
313
|
+
"$prototype": "Function",
|
|
314
|
+
"body": [
|
|
315
|
+
{
|
|
316
|
+
"operator": "call",
|
|
317
|
+
"target": {
|
|
318
|
+
"$ref": "#/state/save"
|
|
319
|
+
},
|
|
320
|
+
"value": []
|
|
321
|
+
}
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
"children": [
|
|
325
|
+
{
|
|
326
|
+
"tagName": "span",
|
|
327
|
+
"textContent": "Save"
|
|
328
|
+
}
|
|
329
|
+
]
|
|
326
330
|
}
|
|
327
331
|
]
|
|
328
332
|
}
|
|
329
|
-
|
|
333
|
+
}
|
|
330
334
|
}
|
|
331
335
|
]
|
|
332
336
|
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
* The AI provider credentials form as a mounted document.
|
|
4
4
|
*
|
|
5
5
|
* `ui/ai-credentials-form.ts` is the flow — it holds the three drafts, decides which credentials a
|
|
6
|
-
* listing is made with, what Save persists and re-reads, and whether
|
|
7
|
-
* is the surface it draws into.
|
|
6
|
+
* listing is made with, what Save persists and re-reads, and whether there is anything to commit —
|
|
7
|
+
* and this is the surface it draws into.
|
|
8
8
|
*
|
|
9
9
|
* **The host element belongs to this module, not to the gate.** Every credentials gate is still a
|
|
10
10
|
* lit template that interpolates the form beside the keyless offer, so there is no container in the
|
|
@@ -58,8 +58,12 @@ export interface AiCredentialsView {
|
|
|
58
58
|
fetchLabel: string;
|
|
59
59
|
/** Why the last listing did not finish. Empty draws nothing. */
|
|
60
60
|
modelsError: string;
|
|
61
|
-
/**
|
|
62
|
-
|
|
61
|
+
/**
|
|
62
|
+
* The drafts differ from what is stored — there is something to Save and something to Cancel. The
|
|
63
|
+
* flow compares them as the store would hold them, so whitespace a Save would trim is not a
|
|
64
|
+
* difference. False at rest, which is when the document draws neither button.
|
|
65
|
+
*/
|
|
66
|
+
dirty: boolean;
|
|
63
67
|
}
|
|
64
68
|
|
|
65
69
|
/** Everything the reader can do here. */
|
|
@@ -134,7 +138,17 @@ export function createAiCredentialsSurface(
|
|
|
134
138
|
return {
|
|
135
139
|
host,
|
|
136
140
|
update(next) {
|
|
141
|
+
/* Save and Cancel exist only while the form is dirty, so answering either takes away the
|
|
142
|
+
button the reader just pressed — and a removed element's focus falls to `<body>`, which in
|
|
143
|
+
a modal sheet leaves a keyboard or screen-reader user nowhere. The key field is where it
|
|
144
|
+
lands instead: the top of the form that now shows what is stored. Only when focus WAS on
|
|
145
|
+
the pair and the update actually lost it, so a repaint never takes the caret from a field. */
|
|
146
|
+
const answering =
|
|
147
|
+
!next.dirty && host.querySelector('[part="actions"]')?.contains(document.activeElement);
|
|
137
148
|
Object.assign(scope, derive(next));
|
|
149
|
+
if (answering && !host.contains(document.activeElement)) {
|
|
150
|
+
host.querySelector<HTMLElement>('[part="key"] [part="input"]')?.focus();
|
|
151
|
+
}
|
|
138
152
|
/* A standing mount is only ASSIGNED to: rebuilding it on every repaint of the gate around it
|
|
139
153
|
would empty the field the reader is typing in. The remount below answers the one case
|
|
140
154
|
assignment cannot — a host the document has been taken out of — and it cannot fire while a
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
"maxWidth": "280px",
|
|
23
23
|
"textAlign": "center"
|
|
24
24
|
},
|
|
25
|
-
"& [part=\"
|
|
26
|
-
"$description": "Why the last attempt did not finish, said under the button that would try it again. Narrower than the lede: a refusal is a sentence to read once, not the thing the surface is about.",
|
|
25
|
+
"& [part=\"connect-failure\"]": {
|
|
26
|
+
"$description": "Why the last attempt did not finish, said under the button that would try it again. Narrower than the lede: a refusal is a sentence to read once, not the thing the surface is about. The name is qualified, and BOTH halves of it are load-bearing. Not `error`, because every kit field draws a permanent, empty `[part=\"error\"]` of its own and the kit is light DOM, so a rule on that name would reach any field this surface ever holds. Not the bare `failure` every panel banner uses either, because this document is MOUNTED inside another one: `new-project.json` puts it in `[part=\"managed-island\"]` and styles its own backend refusal with a descendant `[part=\"failure\"]`, which would draw this sentence with that dialog's footer border and padding. A guest surface picks a name its host does not write, and `tests/surface-part-names.test.ts` holds the two island hosts to it.",
|
|
27
27
|
"margin": "0",
|
|
28
28
|
"color": "var(--danger)",
|
|
29
29
|
"fontSize": "var(--jx-text-sm)",
|
|
@@ -78,7 +78,7 @@
|
|
|
78
78
|
{
|
|
79
79
|
"tagName": "div",
|
|
80
80
|
"attributes": {
|
|
81
|
-
"part": "
|
|
81
|
+
"part": "connect-failure-slot",
|
|
82
82
|
"role": "none"
|
|
83
83
|
},
|
|
84
84
|
"style": {
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
"true": {
|
|
92
92
|
"tagName": "p",
|
|
93
93
|
"attributes": {
|
|
94
|
-
"part": "
|
|
94
|
+
"part": "connect-failure"
|
|
95
95
|
},
|
|
96
96
|
"textContent": "${state.error}"
|
|
97
97
|
}
|