@jxsuite/studio 6.1.1 → 6.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{2020-va2wwra4.js → 2020-f2gkpy8d.js} +3 -3
- package/dist/chunks/{action-group-2mqby73c.js → action-group-4aan7g6g.js} +3 -3
- package/dist/chunks/adapter-4912g339.js +4 -0
- package/dist/chunks/cf-account-picker-wccaenh6.js +4 -0
- package/dist/chunks/cf-settings-br6105tr.js +4 -0
- package/dist/chunks/color-28ksk2qm.js +4 -0
- package/dist/chunks/color-area-0fj8a4ga.js +4 -0
- package/dist/chunks/color-field-xch8kx2g.js +4 -0
- package/dist/chunks/color-slider-jxd8v350.js +4 -0
- package/dist/chunks/combobox-p0efwjke.js +4 -0
- package/dist/chunks/components-db68vsn7.js +4 -0
- package/dist/chunks/content-source-1449qesq.js +4 -0
- package/dist/chunks/convert-to-repeater-5h457egj.js +4 -0
- package/dist/chunks/dialog-c4x05vyx.js +4 -0
- package/dist/chunks/editor-x9jn86a7.js +4 -0
- package/dist/chunks/entry-commands-may24cpt.js +4 -0
- package/dist/chunks/extension-sections-pvr14vxr.js +4 -0
- package/dist/chunks/file-ops-x9v54pcj.js +4 -0
- package/dist/chunks/files-j3knqf0s.js +4 -0
- package/dist/chunks/format-host-tyre2trb.js +4 -0
- package/dist/chunks/fs-events-64ma9htc.js +4 -0
- package/dist/chunks/git-panel-84ps5dex.js +4 -0
- package/dist/chunks/grid-view-d2wq9ezg.js +51 -0
- package/dist/chunks/icons-pnfz478q.js +4 -0
- package/dist/chunks/iframe-entry-fvbk89gm.js +5 -0
- package/dist/chunks/iframe-entry-jdcktez8.js +5 -0
- package/dist/chunks/iframe-entry-x0ygf2yr.js +5 -0
- package/dist/chunks/iframe-entry-zap785cw.js +5 -0
- package/dist/chunks/iframe-host-ck6vejt5.js +4 -0
- package/dist/chunks/index-b8xw3vy9.js +4 -0
- package/dist/chunks/{index-2veqmnhr.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-8nbvs12s.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/{jsonMode-s8kt9dsj.js → jsonMode-w15cmrcm.js} +8 -8
- package/dist/chunks/jx-validate-at3zn8wa.js +4 -0
- package/dist/chunks/layers-h4xp1pss.js +4 -0
- package/dist/chunks/layers-panel-m5hw1d7g.js +4 -0
- package/dist/chunks/listbox-e74qjyq6.js +4 -0
- package/dist/chunks/lit-html-8t8t3dnr.js +4 -0
- package/dist/chunks/media-picker-2cweexc5.js +4 -0
- package/dist/chunks/menu-n6yzswmy.js +4 -0
- package/dist/chunks/menu-ynw13y0s.js +4 -0
- package/dist/chunks/monaco-binding-7gx83x3r.js +4 -0
- package/dist/chunks/monaco-buffer-qzxn567r.js +4 -0
- package/dist/chunks/monaco-setup-gxf6656g.js +4 -0
- package/dist/chunks/notify-cj5zbrs2.js +4 -0
- package/dist/chunks/number-field-y62xq0ty.js +4 -0
- package/dist/chunks/parse-b7ddhr8m.js +4 -0
- package/dist/chunks/platform-3dfws9js.js +4 -0
- package/dist/chunks/popover-jt2gxmzs.js +4 -0
- package/dist/chunks/publish-panel-1gvxbj21.js +4 -0
- package/dist/chunks/quick-search-0dajrwqg.js +4 -0
- package/dist/chunks/references-49qgt404.js +4 -0
- package/dist/chunks/right-panel-jm1bwe53.js +4 -0
- package/dist/chunks/section-registry-6kwc4fky.js +4 -0
- package/dist/chunks/select-rzds841e.js +4 -0
- package/dist/chunks/split-n2gfpm5m.js +4 -0
- package/dist/chunks/{studio-1q1sh2ax.js → studio-0q988f9w.js} +3 -3
- package/dist/chunks/studio-0rt52vpq.js +5 -0
- package/dist/chunks/studio-18vgbhs5.js +5 -0
- package/dist/chunks/{studio-h46vtzk8.js → studio-1fxkaaea.js} +4 -4
- package/dist/chunks/studio-24mccdrj.js +5 -0
- package/dist/chunks/studio-2eh507zk.js +9 -0
- package/dist/chunks/studio-2hcbccfv.js +5 -0
- package/dist/chunks/studio-2j1cb95x.js +5 -0
- package/dist/chunks/studio-2jbs3rxv.js +5 -0
- package/dist/chunks/{studio-rv11kfwa.js → studio-485046te.js} +7 -7
- package/dist/chunks/studio-4h8k4dw9.js +5 -0
- package/dist/chunks/studio-5f6n18kx.js +5 -0
- package/dist/chunks/studio-5gthpky6.js +5 -0
- package/dist/chunks/studio-5ve6bbep.js +5 -0
- package/dist/chunks/studio-6ep3js6b.js +9 -0
- package/dist/chunks/studio-6wkmf3wz.js +9 -0
- package/dist/chunks/studio-841rf3cg.js +5 -0
- package/dist/chunks/studio-8gmwgheg.js +5 -0
- package/dist/chunks/studio-8qm0ep50.js +5 -0
- package/dist/chunks/{studio-8grwxtqk.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-pre0skq6.js → studio-a3g98wjr.js} +4 -4
- package/dist/chunks/studio-a3shpz9y.js +5 -0
- package/dist/chunks/studio-amsbaaar.js +6 -0
- package/dist/chunks/studio-at5spjbc.js +7 -0
- package/dist/chunks/studio-b2xv945e.js +5 -0
- package/dist/chunks/studio-bn5nkafw.js +5 -0
- package/dist/chunks/studio-bw6q5xjf.js +9 -0
- package/dist/chunks/studio-c7q0t9x1.js +5 -0
- package/dist/chunks/studio-camnhc96.js +6 -0
- package/dist/chunks/studio-cffqvnzd.js +5 -0
- package/dist/chunks/studio-d81xfh1g.js +5 -0
- package/dist/chunks/studio-dgz8d0c1.js +5 -0
- package/dist/chunks/studio-efvfrsf8.js +5 -0
- package/dist/chunks/studio-er30bpcx.js +5 -0
- package/dist/chunks/studio-ezscgr64.js +5 -0
- package/dist/chunks/studio-ffrrncvz.js +5 -0
- package/dist/chunks/studio-fpphgn8y.js +10 -0
- package/dist/chunks/studio-j1kvhdjk.js +4 -0
- package/dist/chunks/{studio-vrmcjf9g.js → studio-j430n16g.js} +5 -5
- package/dist/chunks/studio-jjkg84nj.js +5 -0
- package/dist/chunks/studio-m0q32ars.js +4 -0
- package/dist/chunks/studio-m6bdst11.js +5 -0
- package/dist/chunks/studio-nv2cptd4.js +64 -0
- package/dist/chunks/studio-nwfrc98n.js +5 -0
- package/dist/chunks/studio-p1wgvp7r.js +5 -0
- package/dist/chunks/studio-pag2wncm.js +5 -0
- package/dist/chunks/studio-qvanvzfd.js +5 -0
- package/dist/chunks/studio-qwa64kt7.js +5 -0
- package/dist/chunks/studio-rk1zc4x3.js +928 -0
- package/dist/chunks/studio-se2r3ptc.js +5 -0
- package/dist/chunks/studio-sg2a0dh0.js +5 -0
- package/dist/chunks/studio-tjzjhe68.js +5 -0
- package/dist/chunks/{studio-wszjyh0j.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-kggey1jt.js → studio-v0jzqdjm.js} +4 -4
- package/dist/chunks/studio-v2w7q8r1.js +7 -0
- package/dist/chunks/studio-v5vjq1h0.js +4 -0
- package/dist/chunks/studio-v8aga3vp.js +14 -0
- package/dist/chunks/studio-vfcdrfmv.js +5 -0
- package/dist/chunks/studio-vmfkgdjf.js +5 -0
- package/dist/chunks/studio-wt1816jj.js +5 -0
- package/dist/chunks/studio-wz73q5kq.js +4 -0
- package/dist/chunks/studio-y04qtxvp.js +7 -0
- package/dist/chunks/studio-y21g8zzg.js +5 -0
- package/dist/chunks/{studio-zey7zsdw.js → studio-y64hrt8p.js} +7 -7
- package/dist/chunks/studio-ynn90f58.js +16 -0
- package/dist/chunks/studio-yxz682sx.js +5 -0
- package/dist/chunks/studio-zp7snvkq.js +5 -0
- package/dist/chunks/studio-zq4z6tm6.js +5 -0
- package/dist/chunks/swatch-group-ewh24n1f.js +4 -0
- package/dist/chunks/tabs-f5cw3tgp.js +4 -0
- package/dist/chunks/textfield-wewc8rq2.js +4 -0
- package/dist/chunks/toast-c9fn075p.js +4 -0
- package/dist/chunks/toast-host-ke5z4ng7.js +4 -0
- package/dist/chunks/{toolbar-2nnzqhrj.js → toolbar-44cm5cta.js} +3 -3
- package/dist/chunks/tooltip-5v8ngwj2.js +4 -0
- package/dist/chunks/tree-mdq3v5cw.js +4 -0
- package/dist/chunks/{tsMode-2frah6h1.js → tsMode-sf49ee9x.js} +7 -7
- package/dist/chunks/workspace-jtfahpee.js +4 -0
- package/dist/chunks/ws-client-nze0k6mv.js +4 -0
- package/dist/iframe-entry.js +16 -16
- package/dist/manifest.json +63 -63
- package/dist/studio.js +97 -97
- package/package.json +6 -6
- package/src/about/about-modal.ts +4 -3
- package/src/account/action-flow.ts +45 -38
- package/src/account-status.ts +7 -2
- package/src/browse/library-layouts.ts +8 -5
- package/src/browse/library-model.ts +18 -6
- package/src/browse/library-pane.ts +37 -21
- package/src/browse/library-preview.ts +14 -9
- package/src/browse/library-source.ts +1 -1
- package/src/canvas/asset-refs.ts +24 -9
- package/src/canvas/asset-resolve.ts +19 -23
- package/src/canvas/canvas-helpers.ts +7 -6
- package/src/canvas/canvas-live-render.ts +44 -53
- package/src/canvas/canvas-patcher.ts +30 -30
- package/src/canvas/canvas-perf.ts +11 -5
- package/src/canvas/canvas-render.ts +62 -41
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +90 -49
- package/src/canvas/dialog-path.ts +9 -4
- package/src/canvas/dialog-state.ts +1 -2
- package/src/canvas/diff-marks.ts +9 -16
- package/src/canvas/diff-toolbar.ts +8 -7
- package/src/canvas/edit-width-drag.ts +4 -1
- package/src/canvas/edit-width.ts +1 -3
- package/src/canvas/iframe-channel.ts +27 -13
- package/src/canvas/iframe-drop.ts +13 -12
- package/src/canvas/iframe-editable-root.ts +29 -16
- package/src/canvas/iframe-entry.ts +80 -63
- package/src/canvas/iframe-eval.ts +73 -49
- package/src/canvas/iframe-host.ts +135 -96
- package/src/canvas/iframe-inline-edit.ts +49 -30
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +30 -25
- package/src/canvas/iframe-overlay.ts +1 -1
- package/src/canvas/iframe-patch.ts +18 -15
- package/src/canvas/iframe-position.ts +12 -6
- package/src/canvas/iframe-protocol.ts +12 -16
- package/src/canvas/iframe-render.ts +36 -34
- package/src/canvas/iframe-slash.ts +24 -11
- package/src/canvas/iframe-subtree.ts +6 -2
- package/src/canvas/path-mapping.ts +19 -12
- package/src/canvas/popover-path.ts +7 -3
- package/src/canvas/popover-state.ts +1 -2
- package/src/canvas/serialize-scope.ts +13 -5
- package/src/canvas/stage-scrollbar.ts +2 -1
- package/src/canvas/surface-registry.ts +21 -3
- package/src/collab/collab-commands.ts +7 -2
- package/src/collab/collab-session.ts +84 -45
- package/src/collab/collab-state.ts +4 -3
- package/src/collab/monaco-binding.ts +16 -13
- package/src/collab/monaco-cursors.ts +5 -2
- package/src/commands/budget.ts +3 -3
- package/src/commands/command-args.ts +103 -71
- package/src/commands/context.ts +22 -20
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +7 -7
- package/src/commands/reference.ts +2 -1
- package/src/commands/registry.ts +12 -10
- package/src/commands/run-reported.ts +15 -10
- package/src/component-props.ts +46 -30
- package/src/content/collection-match.ts +5 -4
- package/src/content/draft-state.ts +4 -3
- package/src/content/entry-commands.ts +3 -2
- package/src/content/entry-editor.ts +29 -17
- package/src/content/entry-fields.ts +12 -7
- package/src/content/entry-model.ts +21 -12
- package/src/editor/canvas-context-menu.ts +1 -2
- package/src/editor/canvas-slash-bridge.ts +3 -6
- package/src/editor/content-slice.ts +16 -14
- package/src/editor/context-menu.ts +35 -22
- package/src/editor/convert-targets.ts +30 -35
- package/src/editor/convert-to-component.ts +11 -5
- package/src/editor/convert-to-repeater.ts +34 -22
- package/src/editor/editable-tags.ts +17 -2
- package/src/editor/file-drop-action.ts +21 -22
- package/src/editor/inline-edit-apply.ts +35 -17
- package/src/editor/inline-edit.ts +66 -50
- package/src/editor/inline-format.ts +59 -56
- package/src/editor/inline-link.ts +40 -15
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/merge-tags.ts +58 -19
- package/src/editor/repeater-scope.ts +39 -28
- package/src/editor/shortcuts.ts +32 -20
- package/src/editor/slash-menu.ts +1 -6
- package/src/files/asset-versions.ts +4 -4
- package/src/files/components.ts +15 -10
- package/src/files/elements.ts +5 -6
- package/src/files/file-ops.ts +77 -36
- package/src/files/files.ts +90 -95
- package/src/files/media-meta.ts +2 -1
- package/src/files/media-paths.ts +3 -0
- package/src/files/serialize-document.ts +2 -2
- package/src/format/constraints.ts +1 -1
- package/src/format/convert-file.ts +27 -13
- package/src/format/format-choices.ts +2 -1
- package/src/format/format-host.ts +76 -50
- package/src/github/github-auth-status.ts +27 -3
- package/src/github/github-auth.ts +19 -9
- package/src/github/github-publish.ts +24 -20
- package/src/grid/cell-editors.ts +46 -31
- package/src/grid/cell-popovers.ts +5 -3
- package/src/grid/edit-buffer.ts +10 -9
- package/src/grid/grid-controller.ts +20 -22
- package/src/grid/grid-layout.ts +21 -5
- package/src/grid/grid-open.ts +3 -6
- package/src/grid/grid-panel.ts +11 -4
- package/src/grid/grid-source.ts +8 -8
- package/src/grid/grid-view.ts +14 -17
- package/src/grid/redirects-grid.ts +14 -5
- package/src/grid/redirects.ts +16 -14
- package/src/grid/schema-columns.ts +25 -19
- package/src/grid/sources/connector-source.ts +47 -20
- package/src/grid/sources/content-source.ts +25 -24
- package/src/grid/sources/csv-file-source.ts +2 -2
- package/src/grid/tabulator-tables.d.ts +55 -34
- package/src/hosting/stage.ts +7 -7
- package/src/i18n/i18n-commands.ts +1 -2
- package/src/media/media-pane.ts +4 -1
- package/src/new-project/add-repo-modal.ts +20 -19
- package/src/new-project/import-tab.ts +10 -14
- package/src/new-project/location-fields.ts +2 -1
- package/src/new-project/new-project-modal.ts +12 -9
- package/src/packages/jxsuite-update.ts +4 -3
- package/src/packages/pull-package-sync.ts +26 -25
- package/src/page-params.ts +97 -68
- package/src/panels/activity-panel.ts +17 -9
- package/src/panels/ai-chat/attached-context.ts +13 -7
- package/src/panels/ai-chat/chat-view.ts +80 -73
- package/src/panels/ai-chat/composer.ts +30 -33
- package/src/panels/ai-chat/sessions-view.ts +1 -2
- package/src/panels/ai-panel.ts +23 -20
- package/src/panels/block-action-bar.ts +46 -35
- package/src/panels/bottom-dock.ts +5 -3
- package/src/panels/canvas-dnd-bridge.ts +31 -24
- package/src/panels/data-explorer.ts +62 -25
- package/src/panels/data-grid.ts +14 -11
- package/src/panels/dnd.ts +108 -118
- package/src/panels/editors.ts +52 -21
- package/src/panels/elements-panel.ts +10 -3
- package/src/panels/events-panel.ts +84 -69
- package/src/panels/formula-workspace.ts +76 -51
- package/src/panels/frontmatter-fields.ts +24 -19
- package/src/panels/frontmatter-panel.ts +44 -34
- package/src/panels/git-diff-open.ts +4 -4
- package/src/panels/git-panel.ts +49 -61
- package/src/panels/head-panel.ts +131 -111
- package/src/panels/i18n-panel.ts +10 -3
- package/src/panels/imports-panel.ts +23 -47
- package/src/panels/jump-bar.ts +48 -29
- package/src/panels/layers-panel.ts +97 -74
- package/src/panels/left-panel.ts +3 -3
- package/src/panels/pane-context.ts +31 -22
- package/src/panels/pane-grid.ts +49 -20
- package/src/panels/panel-registry.ts +22 -37
- package/src/panels/properties-panel.ts +175 -121
- package/src/panels/quick-search.ts +53 -31
- package/src/panels/right-panel.ts +3 -3
- package/src/panels/seo-modal.ts +13 -17
- package/src/panels/settings-menu.ts +15 -15
- package/src/panels/signals-panel.ts +153 -131
- package/src/panels/statement-editor.ts +230 -140
- package/src/panels/style-panel.ts +218 -205
- package/src/panels/style-utils.ts +114 -51
- package/src/panels/stylebook-doc.ts +57 -54
- package/src/panels/stylebook-layers-panel.ts +9 -9
- package/src/panels/stylebook-panel.ts +13 -17
- package/src/panels/tab-drop.ts +27 -11
- package/src/panels/tab-strip.ts +36 -26
- package/src/platform-errors.ts +57 -43
- package/src/platform.ts +58 -30
- package/src/platforms/cloud.ts +345 -175
- package/src/platforms/default-platform.ts +10 -4
- package/src/platforms/devserver.ts +129 -117
- package/src/platforms/read-batcher.ts +16 -8
- package/src/project-list.ts +2 -1
- package/src/publish/deploy-checklist.ts +8 -2
- package/src/publish/pages-service.ts +28 -13
- package/src/publish/publish-commands.ts +5 -4
- package/src/publish/publish-panel.ts +10 -6
- package/src/recent-projects.ts +15 -8
- package/src/resize-edges.ts +26 -36
- package/src/services/a11y-report.ts +26 -19
- package/src/services/agent-seed.ts +23 -11
- package/src/services/ai-ask.ts +9 -12
- package/src/services/ai-command-tools.ts +68 -62
- package/src/services/ai-import-tools.ts +80 -67
- package/src/services/ai-models.ts +17 -13
- package/src/services/ai-project-tools.ts +68 -32
- package/src/services/ai-session-store.ts +19 -10
- package/src/services/ai-system-prompt.ts +46 -20
- package/src/services/ai-tools.ts +71 -27
- package/src/services/ai-write-report.ts +20 -12
- package/src/services/ai-writes.ts +4 -4
- package/src/services/automation.ts +58 -31
- package/src/services/cem-export.ts +149 -58
- package/src/services/clock.ts +6 -1
- package/src/services/code-services.ts +37 -31
- package/src/services/context-manager.ts +14 -10
- package/src/services/context-resolver.ts +20 -8
- package/src/services/data-service.ts +19 -15
- package/src/services/directory-picker.ts +18 -12
- package/src/services/document-assistant.ts +39 -19
- package/src/services/gated-registry.ts +10 -6
- package/src/services/harness/chat-reducer.ts +23 -1
- package/src/services/import-client.ts +91 -38
- package/src/services/import-seed.ts +8 -2
- package/src/services/jx-validate.ts +28 -31
- package/src/services/live-preview.ts +0 -0
- package/src/services/live-surfaces.ts +6 -3
- package/src/services/model-uri.ts +10 -2
- package/src/services/module-preloads.ts +12 -8
- package/src/services/monaco-buffer.ts +43 -24
- package/src/services/monaco-lazy.ts +7 -8
- package/src/services/monaco-setup.ts +23 -16
- package/src/services/notify.ts +44 -17
- package/src/services/popover-report.ts +25 -10
- package/src/services/preview-eval.ts +20 -8
- package/src/services/profile.ts +13 -6
- package/src/services/project-path.ts +13 -10
- package/src/services/references.ts +0 -0
- package/src/services/render-critic.ts +8 -7
- package/src/services/settings/kernel.ts +13 -4
- package/src/services/settings/write-queue.ts +9 -9
- package/src/services/token-lint.ts +12 -10
- package/src/services/tool-executor.ts +17 -5
- package/src/services/tool-outcomes.ts +44 -24
- package/src/services/trusted-types.ts +24 -7
- package/src/settings/contexts-section.ts +11 -8
- package/src/settings/contributed-section.ts +79 -60
- package/src/settings/css-vars-editor.ts +37 -16
- package/src/settings/defs-editor.ts +38 -35
- package/src/settings/extension-rows.ts +16 -8
- package/src/settings/extension-sections.ts +23 -13
- package/src/settings/extensions-section.ts +4 -1
- package/src/settings/general-settings.ts +11 -8
- package/src/settings/locales-section.ts +20 -12
- package/src/settings/preferences-dialog.ts +9 -6
- package/src/settings/preferences-keymap.ts +7 -5
- package/src/settings/preferences-sections.ts +11 -5
- package/src/settings/project-sections.ts +1 -1
- package/src/settings/schema-field-ui.ts +9 -0
- package/src/settings/settings-document.ts +5 -5
- package/src/shell/tree.ts +6 -5
- package/src/shell.ts +104 -81
- package/src/site-context.ts +37 -22
- package/src/state.ts +41 -49
- package/src/store.ts +54 -34
- package/src/studio.ts +25 -75
- package/src/style/live-preview.ts +1 -1
- package/src/style/project-styles.ts +6 -7
- package/src/style/token-ref.ts +5 -4
- package/src/surfaces/about.ts +18 -19
- package/src/surfaces/add-repo.ts +17 -19
- package/src/surfaces/ai-chat.ts +31 -36
- package/src/surfaces/ai-credentials-form.ts +6 -16
- package/src/surfaces/ai-managed-connect.ts +3 -4
- package/src/surfaces/ai-model-picker.ts +3 -5
- package/src/surfaces/block-action-bar.ts +22 -11
- package/src/surfaces/boot-failure.ts +4 -5
- package/src/surfaces/bottom-dock.ts +9 -18
- package/src/surfaces/canvas-stage.ts +12 -11
- package/src/surfaces/cf-account-picker.ts +17 -18
- package/src/surfaces/commandbar.ts +14 -9
- package/src/surfaces/convert-repeater.ts +17 -19
- package/src/surfaces/data-actions.ts +9 -7
- package/src/surfaces/dialog.ts +26 -28
- package/src/surfaces/diff-toolbar.ts +9 -7
- package/src/surfaces/doc-header.ts +10 -19
- package/src/surfaces/empty-state.ts +7 -10
- package/src/surfaces/entry-editor.ts +14 -11
- package/src/surfaces/expression-editor.ts +11 -25
- package/src/surfaces/files-panel.ts +27 -14
- package/src/surfaces/formula-palette.ts +4 -5
- package/src/surfaces/git-panel.ts +7 -15
- package/src/surfaces/github-auth.ts +16 -20
- package/src/surfaces/github-publish.ts +17 -22
- package/src/surfaces/grid-cell.ts +30 -31
- package/src/surfaces/grid-open.ts +10 -14
- package/src/surfaces/grid-panel.ts +13 -9
- package/src/surfaces/grid-replace.ts +13 -13
- package/src/surfaces/grid-views.ts +15 -18
- package/src/surfaces/inspector-dock.ts +13 -12
- package/src/surfaces/jump-bar.ts +5 -6
- package/src/surfaces/jxsuite-update.ts +16 -22
- package/src/surfaces/library-pane.ts +19 -20
- package/src/surfaces/logic-panel.ts +17 -30
- package/src/surfaces/logic-workspace.ts +13 -15
- package/src/surfaces/media-browser.ts +11 -10
- package/src/surfaces/media-field.ts +4 -5
- package/src/surfaces/media-pane.ts +8 -7
- package/src/surfaces/menu.ts +29 -23
- package/src/surfaces/navigator-dock.ts +11 -12
- package/src/surfaces/new-project.ts +27 -26
- package/src/surfaces/pane-context.ts +20 -25
- package/src/surfaces/pane-grid.ts +15 -10
- package/src/surfaces/panel-activity.ts +5 -6
- package/src/surfaces/panel-data.ts +3 -4
- package/src/surfaces/panel-deploy-checklist.ts +5 -6
- package/src/surfaces/panel-elements.ts +5 -7
- package/src/surfaces/panel-i18n.ts +5 -7
- package/src/surfaces/panel-imports.ts +6 -13
- package/src/surfaces/panel-outline.ts +25 -19
- package/src/surfaces/panel-page.ts +11 -18
- package/src/surfaces/panel-problems.ts +5 -7
- package/src/surfaces/panel-signals.ts +20 -34
- package/src/surfaces/panel-stylebook-layers.ts +5 -8
- package/src/surfaces/preferences.ts +21 -11
- package/src/surfaces/progress-modal.ts +15 -9
- package/src/surfaces/properties-panel.json +1 -1
- package/src/surfaces/properties-panel.ts +20 -42
- package/src/surfaces/publish.ts +18 -18
- package/src/surfaces/push-plan.ts +7 -8
- package/src/surfaces/rail.ts +13 -13
- package/src/surfaces/reference-field.ts +11 -15
- package/src/surfaces/schema-builder.ts +16 -22
- package/src/surfaces/schema-form.ts +15 -25
- package/src/surfaces/secret-field.ts +9 -6
- package/src/surfaces/seo.ts +21 -15
- package/src/surfaces/settings-contexts.ts +9 -7
- package/src/surfaces/settings-contributed.ts +14 -10
- package/src/surfaces/settings-css-vars.ts +5 -12
- package/src/surfaces/settings-defs.json +2 -2
- package/src/surfaces/settings-defs.ts +17 -21
- package/src/surfaces/settings-deploy.ts +8 -15
- package/src/surfaces/settings-extensions.ts +5 -6
- package/src/surfaces/settings-head.ts +33 -39
- package/src/surfaces/settings-locales.ts +8 -20
- package/src/surfaces/settings-overview.ts +5 -6
- package/src/surfaces/settings-packages.ts +8 -7
- package/src/surfaces/settings-pane.ts +9 -18
- package/src/surfaces/settings-rawjson.ts +5 -6
- package/src/surfaces/shell.ts +1 -2
- package/src/surfaces/slash-menu.ts +19 -9
- package/src/surfaces/statements.ts +13 -18
- package/src/surfaces/statusbar.ts +17 -14
- package/src/surfaces/style-panel.ts +18 -31
- package/src/surfaces/stylebook-chrome.ts +3 -5
- package/src/surfaces/tab-strip.ts +14 -13
- package/src/surfaces/target-line.ts +6 -7
- package/src/surfaces/welcome.ts +5 -7
- package/src/tabs/patch-ops.ts +4 -3
- package/src/tabs/project-config.ts +32 -21
- package/src/tabs/selection.ts +36 -8
- package/src/tabs/tab.ts +52 -41
- package/src/tabs/transact.ts +98 -53
- package/src/types.ts +32 -17
- package/src/ui/ai-credentials-form.ts +10 -13
- package/src/ui/ai-model-picker.ts +3 -3
- package/src/ui/cf-account-picker.ts +7 -9
- package/src/ui/color-selector.ts +9 -5
- package/src/ui/dynamic-slot.ts +7 -8
- package/src/ui/expression-editor.ts +112 -105
- package/src/ui/form-controls.ts +57 -48
- package/src/ui/formula-catalog.ts +239 -230
- package/src/ui/formula-chips.ts +33 -18
- package/src/ui/layers.ts +44 -31
- package/src/ui/media-picker.ts +18 -9
- package/src/ui/popover-surface.ts +20 -12
- package/src/ui/progress-modal.ts +13 -8
- package/src/ui/regions.ts +7 -6
- package/src/ui/schema-form.ts +113 -70
- package/src/ui/surface.ts +71 -8
- package/src/ui/timing.ts +9 -0
- package/src/ui/value-source.ts +44 -31
- package/src/ui/virtual-window.ts +3 -2
- package/src/utils/base64.ts +3 -1
- package/src/utils/edit-display.ts +73 -73
- package/src/utils/element-selectors.ts +3 -2
- package/src/utils/google-fonts.ts +15 -14
- package/src/utils/inherited-style.ts +18 -20
- package/src/utils/link-target.ts +1 -1
- package/src/utils/preview-format.ts +25 -3
- package/src/utils/strip-events.ts +49 -22
- package/src/utils/studio-utils.ts +29 -14
- package/src/view.ts +2 -3
- package/src/workspace/pane-derive.ts +10 -12
- package/src/workspace/session.ts +53 -43
- package/src/workspace/workspace.ts +40 -36
- package/dist/chunks/adapter-f93pafd7.js +0 -4
- package/dist/chunks/cf-account-picker-af1h381v.js +0 -4
- package/dist/chunks/cf-settings-125tdm0w.js +0 -4
- package/dist/chunks/color-area-jqhna8zy.js +0 -4
- package/dist/chunks/color-field-embq5ctg.js +0 -4
- package/dist/chunks/color-fpezvnkt.js +0 -4
- package/dist/chunks/color-slider-1qmw7wqy.js +0 -4
- package/dist/chunks/combobox-773hdzyj.js +0 -4
- package/dist/chunks/components-ax2f1fnn.js +0 -4
- package/dist/chunks/content-source-108aqtk1.js +0 -4
- package/dist/chunks/convert-to-repeater-ry5rmppr.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-pfgdmkb0.js +0 -4
- package/dist/chunks/entry-commands-t0k1q0kx.js +0 -4
- package/dist/chunks/extension-sections-6mwh2hf8.js +0 -4
- package/dist/chunks/file-ops-meej5mqf.js +0 -4
- package/dist/chunks/files-44vp8a2s.js +0 -4
- package/dist/chunks/format-host-7q1petb9.js +0 -4
- package/dist/chunks/fs-events-h2mwnxaz.js +0 -4
- package/dist/chunks/git-panel-zngbymvd.js +0 -4
- package/dist/chunks/grid-view-sx9vynsp.js +0 -51
- package/dist/chunks/icons-p44xhjf0.js +0 -4
- package/dist/chunks/iframe-entry-f7mqjwpm.js +0 -5
- package/dist/chunks/iframe-entry-haw7jkvz.js +0 -5
- package/dist/chunks/iframe-entry-z6qrytv3.js +0 -5
- package/dist/chunks/iframe-host-qk3ycq87.js +0 -4
- package/dist/chunks/index-wkyfjeqz.js +0 -4
- package/dist/chunks/jx-validate-psgd7vsx.js +0 -4
- package/dist/chunks/layers-panel-1kq2jyfk.js +0 -4
- package/dist/chunks/layers-xd92fg8d.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-ac4cwwr4.js +0 -4
- package/dist/chunks/media-picker-0svzkdyb.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/menu-5c55ea3d.js +0 -4
- package/dist/chunks/monaco-binding-z6r70pdt.js +0 -4
- package/dist/chunks/monaco-buffer-fz6gq5y7.js +0 -4
- package/dist/chunks/monaco-setup-q4axkgj7.js +0 -4
- package/dist/chunks/notify-0xgtn8q1.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-v1qctbe6.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-ym1fmgq5.js +0 -4
- package/dist/chunks/quick-search-a54e6t5n.js +0 -4
- package/dist/chunks/references-gmqp82fs.js +0 -4
- package/dist/chunks/right-panel-v7t9awbk.js +0 -4
- package/dist/chunks/section-registry-vhyf3zsr.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0bhx5hz6.js +0 -5
- package/dist/chunks/studio-0k1ddnyy.js +0 -6
- package/dist/chunks/studio-1b04pd0j.js +0 -64
- package/dist/chunks/studio-4dwbj6gb.js +0 -5
- package/dist/chunks/studio-4tanh828.js +0 -5
- package/dist/chunks/studio-55h4mstj.js +0 -4
- package/dist/chunks/studio-5tnvjkz4.js +0 -5
- package/dist/chunks/studio-60dqgb0c.js +0 -5
- package/dist/chunks/studio-61dp09qg.js +0 -9
- package/dist/chunks/studio-63epcrj2.js +0 -5
- package/dist/chunks/studio-74k29dy9.js +0 -5
- package/dist/chunks/studio-7vg6jcd3.js +0 -5
- package/dist/chunks/studio-7zx31knw.js +0 -9
- package/dist/chunks/studio-8bxk97km.js +0 -5
- package/dist/chunks/studio-933e30n4.js +0 -5
- package/dist/chunks/studio-98wnwhbg.js +0 -5
- package/dist/chunks/studio-9mccjwjh.js +0 -14
- package/dist/chunks/studio-a2ke1e4t.js +0 -5
- package/dist/chunks/studio-e3a2a6v3.js +0 -4
- package/dist/chunks/studio-e81q1vb9.js +0 -5
- package/dist/chunks/studio-epgrmqqm.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-g1shz58g.js +0 -5
- package/dist/chunks/studio-gf0fz03c.js +0 -5
- package/dist/chunks/studio-gjtpe62q.js +0 -6
- package/dist/chunks/studio-gkskhg7m.js +0 -5
- package/dist/chunks/studio-gx4dnjzd.js +0 -5
- package/dist/chunks/studio-j03zga3y.js +0 -9
- package/dist/chunks/studio-jhpxeckz.js +0 -5
- package/dist/chunks/studio-k01r7ykp.js +0 -5
- package/dist/chunks/studio-kk7h30ne.js +0 -7
- package/dist/chunks/studio-kt1zqney.js +0 -5
- package/dist/chunks/studio-m3cwhvye.js +0 -5
- package/dist/chunks/studio-mcayt6hz.js +0 -5
- package/dist/chunks/studio-myjcghv3.js +0 -5
- package/dist/chunks/studio-n8bxwc3y.js +0 -4
- package/dist/chunks/studio-ngm8gvpb.js +0 -5
- package/dist/chunks/studio-nj5a01jy.js +0 -928
- package/dist/chunks/studio-pcgz8heb.js +0 -5
- package/dist/chunks/studio-qcsq0t15.js +0 -5
- package/dist/chunks/studio-qkstvve9.js +0 -5
- package/dist/chunks/studio-qv1pwd3c.js +0 -5
- package/dist/chunks/studio-rc6dvxjb.js +0 -7
- package/dist/chunks/studio-s8dmmz66.js +0 -5
- package/dist/chunks/studio-sp5xzbj4.js +0 -6
- package/dist/chunks/studio-szsjbj0g.js +0 -5
- package/dist/chunks/studio-t1xzawhr.js +0 -16
- package/dist/chunks/studio-t6b6qe31.js +0 -5
- package/dist/chunks/studio-tdcprbqb.js +0 -5
- package/dist/chunks/studio-vyc0b4he.js +0 -10
- package/dist/chunks/studio-w0cgf6jg.js +0 -5
- package/dist/chunks/studio-w3hskzqk.js +0 -5
- package/dist/chunks/studio-xgrgcdyh.js +0 -9
- package/dist/chunks/studio-xz2yxfcb.js +0 -5
- package/dist/chunks/studio-y6n42tgs.js +0 -5
- package/dist/chunks/studio-yb560vxr.js +0 -5
- package/dist/chunks/studio-yn9f8vtx.js +0 -5
- package/dist/chunks/studio-yw05w8f0.js +0 -7
- package/dist/chunks/studio-z16sgavc.js +0 -5
- package/dist/chunks/studio-zyqn40w4.js +0 -5
- package/dist/chunks/swatch-group-8qh9a3bm.js +0 -4
- package/dist/chunks/tabs-jwthg40w.js +0 -4
- package/dist/chunks/textfield-spy3hc77.js +0 -4
- package/dist/chunks/toast-4d35zd64.js +0 -4
- package/dist/chunks/toast-host-8sjmfed3.js +0 -4
- package/dist/chunks/tooltip-fd6g9xy3.js +0 -4
- package/dist/chunks/tree-h19v1jfz.js +0 -4
- package/dist/chunks/workspace-zt81g1ms.js +0 -4
- package/dist/chunks/ws-client-n2bh4hkf.js +0 -4
|
@@ -30,6 +30,14 @@ export function modelUriFor(path: string): string {
|
|
|
30
30
|
return ENTRY_SCHEMA_FILES.has(path) ? `file:///.jx/generated/${path}` : `file:///${path}`;
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
/** The two Monaco model URIs one pane's comparison of one file uses. */
|
|
34
|
+
export interface DiffModelUris {
|
|
35
|
+
/** The committed (HEAD) side. */
|
|
36
|
+
head: string;
|
|
37
|
+
/** The working-tree side. */
|
|
38
|
+
work: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
33
41
|
/**
|
|
34
42
|
* The two model URIs a comparison's Monaco diff editor mounts at.
|
|
35
43
|
*
|
|
@@ -50,9 +58,9 @@ export function modelUriFor(path: string): string {
|
|
|
50
58
|
*
|
|
51
59
|
* @param {string} paneId
|
|
52
60
|
* @param {string} path - Project-relative file path
|
|
53
|
-
* @returns {
|
|
61
|
+
* @returns {DiffModelUris}
|
|
54
62
|
*/
|
|
55
|
-
export function diffModelUrisFor(paneId: string, path: string):
|
|
63
|
+
export function diffModelUrisFor(paneId: string, path: string): DiffModelUris {
|
|
56
64
|
return {
|
|
57
65
|
head: `file:///.jx/diff/${paneId}/head/${path}`,
|
|
58
66
|
work: `file:///.jx/diff/${paneId}/work/${path}`,
|
|
@@ -19,6 +19,11 @@
|
|
|
19
19
|
* studio's own lazy surfaces runs.
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
+
/** A document head carrying the batcher's install flag. */
|
|
23
|
+
interface BatchedHead extends HTMLHeadElement {
|
|
24
|
+
__modulePreloadsBatched?: boolean;
|
|
25
|
+
}
|
|
26
|
+
|
|
22
27
|
const QUEUED: HTMLLinkElement[] = [];
|
|
23
28
|
let frame: number | null = null;
|
|
24
29
|
let originalAppend: (<T extends Node>(node: T) => T) | null = null;
|
|
@@ -53,15 +58,14 @@ function appendChildPatched<T extends Node>(this: Node, node: T): T {
|
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
export function installModulePreloadBatcher(): void {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
) {
|
|
61
|
+
/* SAFETY: a widening. The DOM standard declares `document.head` nullable (a document with no head
|
|
62
|
+
element has none) where lib.dom says it is always there; the install flag is an optional expando
|
|
63
|
+
this module alone writes. */
|
|
64
|
+
const head = document.head as BatchedHead | null;
|
|
65
|
+
if (!head || head.__modulePreloadsBatched) {
|
|
61
66
|
return;
|
|
62
67
|
}
|
|
63
|
-
const patched = head as HTMLElement & { __modulePreloadsBatched?: boolean };
|
|
64
68
|
originalAppend = Node.prototype.appendChild.bind(head);
|
|
65
|
-
|
|
66
|
-
head.appendChild = appendChildPatched
|
|
69
|
+
head.__modulePreloadsBatched = true;
|
|
70
|
+
head.appendChild = appendChildPatched;
|
|
67
71
|
}
|
|
@@ -105,8 +105,10 @@
|
|
|
105
105
|
* @docs studio/logic/code
|
|
106
106
|
*/
|
|
107
107
|
|
|
108
|
+
import { isFunction, isNonNullObject } from "@jxsuite/schema/guards";
|
|
108
109
|
import { toRaw } from "../reactivity";
|
|
109
110
|
import { notify } from "./notify";
|
|
111
|
+
import type { NotifyOptions } from "./notify";
|
|
110
112
|
import type { Tab } from "../tabs/tab";
|
|
111
113
|
import { view } from "../view";
|
|
112
114
|
import { allCanvasSurfaces } from "../canvas/surface-registry";
|
|
@@ -114,7 +116,7 @@ import { allCanvasSurfaces } from "../canvas/surface-registry";
|
|
|
114
116
|
/** The slice of a Monaco editor this module needs. Both of Studio's Monacos satisfy it. */
|
|
115
117
|
export interface MonacoBuffer {
|
|
116
118
|
getValue: () => string;
|
|
117
|
-
getModel: () =>
|
|
119
|
+
getModel: () => object | null;
|
|
118
120
|
hasTextFocus: () => boolean;
|
|
119
121
|
/** The debounced work armed over THIS buffer. Installed by {@link bufferWrites}. */
|
|
120
122
|
_writes?: BufferWrites;
|
|
@@ -199,6 +201,19 @@ export interface BufferWrites {
|
|
|
199
201
|
*/
|
|
200
202
|
export const BUFFER_COMMIT = "commit";
|
|
201
203
|
|
|
204
|
+
/**
|
|
205
|
+
* Whether a run answered with a promise to wait for, rather than finishing synchronously.
|
|
206
|
+
*
|
|
207
|
+
* Asked of the thenable shape, not of `instanceof Promise`, because that is what `await` itself
|
|
208
|
+
* asks: whatever the armed work handed back is waited on exactly when `await` would wait on it.
|
|
209
|
+
*
|
|
210
|
+
* @param {void | Promise<void>} result What an armed run (or a flush of one) returned.
|
|
211
|
+
* @returns {boolean}
|
|
212
|
+
*/
|
|
213
|
+
function isPending(result: void | Promise<void>): result is Promise<void> {
|
|
214
|
+
return isNonNullObject(result) && isFunction(result.then);
|
|
215
|
+
}
|
|
216
|
+
|
|
202
217
|
/**
|
|
203
218
|
* Install (and return) the debounce holder for `buffer`.
|
|
204
219
|
*
|
|
@@ -223,10 +238,10 @@ export function bufferWrites(buffer: MonacoBuffer): BufferWrites {
|
|
|
223
238
|
* report.
|
|
224
239
|
*/
|
|
225
240
|
function track(key: string, result: void | Promise<void>): void | Promise<void> {
|
|
226
|
-
if (
|
|
241
|
+
if (!isPending(result)) {
|
|
227
242
|
return result;
|
|
228
243
|
}
|
|
229
|
-
const promise =
|
|
244
|
+
const promise = result.finally(() => {
|
|
230
245
|
if (inFlight.get(key) === promise) {
|
|
231
246
|
inFlight.delete(key);
|
|
232
247
|
}
|
|
@@ -340,18 +355,19 @@ function reportDiscarded(
|
|
|
340
355
|
const tab = buffer._editingTab ?? null;
|
|
341
356
|
const where = tab?.documentPath ?? "Untitled";
|
|
342
357
|
const { holds, reached, source } = SURFACE[surface];
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
}
|
|
358
|
+
const options: NotifyOptions = failure ? { detail: describeCommitFailure(failure.error) } : {};
|
|
359
|
+
options.key = `buffer-discarded:${surface}:${tab?.id ?? "none"}`;
|
|
360
|
+
options.source = source;
|
|
361
|
+
if (tab?.documentPath) {
|
|
362
|
+
options.path = tab.documentPath;
|
|
363
|
+
}
|
|
364
|
+
notify.warn(`${holds} was discarded — it was never ${reached} "${where}".`, options);
|
|
349
365
|
return false;
|
|
350
366
|
}
|
|
351
367
|
|
|
352
368
|
/** What a failed commit is worth showing: the stack when there is one, the value otherwise. */
|
|
353
|
-
function describeCommitFailure(
|
|
354
|
-
return
|
|
369
|
+
function describeCommitFailure(cause: unknown): string {
|
|
370
|
+
return cause instanceof Error ? (cause.stack ?? cause.message) : String(cause);
|
|
355
371
|
}
|
|
356
372
|
|
|
357
373
|
/**
|
|
@@ -428,21 +444,21 @@ export function commitBufferWrites(
|
|
|
428
444
|
ran, and a live 500ms timer was left over an editor whose container lit was about to replace.
|
|
429
445
|
A timer reading `""` off a detached model is the exact defect this module was created to
|
|
430
446
|
prevent, so the teardown below must happen whatever the commit does. */
|
|
431
|
-
let pending:
|
|
447
|
+
let pending: void | Promise<void>;
|
|
432
448
|
try {
|
|
433
449
|
// Fire-and-forget on purpose: the disposer is synchronous, and the commit read `getValue()`
|
|
434
450
|
// Before its own first `await`. What is left to await is the write INTO the document, which
|
|
435
451
|
// Does not need this editor to still exist.
|
|
436
|
-
pending = writes.flush(BUFFER_COMMIT)
|
|
452
|
+
pending = writes.flush(BUFFER_COMMIT);
|
|
437
453
|
} catch (error) {
|
|
438
454
|
writes.cancel();
|
|
439
455
|
return reportDiscarded(buffer, surface, { error });
|
|
440
456
|
}
|
|
441
457
|
writes.cancel();
|
|
442
|
-
if (
|
|
458
|
+
if (isPending(pending)) {
|
|
443
459
|
void pending.then(
|
|
444
460
|
() => reportDiscarded(buffer, surface, null),
|
|
445
|
-
(error
|
|
461
|
+
(error) => reportDiscarded(buffer, surface, { error }),
|
|
446
462
|
);
|
|
447
463
|
return true;
|
|
448
464
|
}
|
|
@@ -512,20 +528,20 @@ export function bufferMovedOn(buffer: MonacoBuffer, expected?: string): boolean
|
|
|
512
528
|
* @returns {MonacoBuffer[]}
|
|
513
529
|
*/
|
|
514
530
|
function buffersForTab(tab: Tab): MonacoBuffer[] {
|
|
515
|
-
const raw = toRaw(tab
|
|
531
|
+
const raw = toRaw(tab);
|
|
516
532
|
/* Every stage's source buffer, plus the dock's one function editor.
|
|
517
533
|
The source view is per-PANE now: two Code panes are two Monaco instances over two documents,
|
|
518
534
|
and a close gate that asked only "the" source editor would have missed whichever one it was
|
|
519
535
|
not holding — which is the same half-answer that let ⌘W close a tab over unprompted typing. */
|
|
520
536
|
const mounted: (MonacoBuffer | null)[] = [
|
|
521
|
-
...allCanvasSurfaces().map((surface) => surface.monacoEditor
|
|
537
|
+
...allCanvasSurfaces().map((surface) => surface.monacoEditor),
|
|
522
538
|
view.functionEditor,
|
|
523
539
|
];
|
|
524
540
|
return mounted.filter(
|
|
525
541
|
(buffer): buffer is MonacoBuffer =>
|
|
526
542
|
buffer != null &&
|
|
527
543
|
buffer._editingTab != null &&
|
|
528
|
-
toRaw(buffer._editingTab
|
|
544
|
+
toRaw(buffer._editingTab) === raw &&
|
|
529
545
|
bufferIsLive(buffer),
|
|
530
546
|
);
|
|
531
547
|
}
|
|
@@ -598,14 +614,17 @@ export async function commitTabBuffers(tab: Tab): Promise<void> {
|
|
|
598
614
|
try {
|
|
599
615
|
await buffer._writes?.flush(BUFFER_COMMIT);
|
|
600
616
|
} catch (error) {
|
|
617
|
+
const options: NotifyOptions = {
|
|
618
|
+
detail: describeCommitFailure(error),
|
|
619
|
+
key: `buffer-commit:${tab.id}`,
|
|
620
|
+
source: "Editor",
|
|
621
|
+
};
|
|
622
|
+
if (tab.documentPath) {
|
|
623
|
+
options.path = tab.documentPath;
|
|
624
|
+
}
|
|
601
625
|
notify.error(
|
|
602
626
|
`Could not save the editor's contents into "${tab.documentPath ?? "Untitled"}".`,
|
|
603
|
-
|
|
604
|
-
detail: error instanceof Error ? (error.stack ?? error.message) : String(error),
|
|
605
|
-
key: `buffer-commit:${tab.id}`,
|
|
606
|
-
source: "Editor",
|
|
607
|
-
...(tab.documentPath ? { path: tab.documentPath } : {}),
|
|
608
|
-
},
|
|
627
|
+
options,
|
|
609
628
|
);
|
|
610
629
|
}
|
|
611
630
|
}
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
on the object {@link loadMonaco} resolves to — typing this as the root would make five namespaces
|
|
27
27
|
look available that are not. `./editor` is exactly the editor API surface that import returns. */
|
|
28
28
|
import type * as monacoNs from "monaco-editor/editor";
|
|
29
|
+
import type { ProjectSchemasResponse } from "../types";
|
|
29
30
|
|
|
30
31
|
export type Monaco = typeof monacoNs;
|
|
31
32
|
|
|
@@ -41,7 +42,7 @@ let _loading: Promise<Monaco> | null = null;
|
|
|
41
42
|
* which is precisely what the lazy path exists to avoid. So the schemas wait here instead, and the
|
|
42
43
|
* loader applies whatever is pending once an editor actually needs one.
|
|
43
44
|
*/
|
|
44
|
-
let _pendingSchemas:
|
|
45
|
+
let _pendingSchemas: ProjectSchemasResponse | null = null;
|
|
45
46
|
let _pendingSchemasDirty = false;
|
|
46
47
|
|
|
47
48
|
/**
|
|
@@ -54,9 +55,7 @@ let _pendingSchemasDirty = false;
|
|
|
54
55
|
* @returns Settles once the schemas are in force. Fire-and-forget is a valid use — say so with
|
|
55
56
|
* `void` at the call site rather than having this hide it.
|
|
56
57
|
*/
|
|
57
|
-
export function setProjectSchemasForMonaco(
|
|
58
|
-
schemas: { project?: unknown; document?: unknown } | null,
|
|
59
|
-
): Promise<void> {
|
|
58
|
+
export function setProjectSchemasForMonaco(schemas: ProjectSchemasResponse | null): Promise<void> {
|
|
60
59
|
_pendingSchemas = schemas;
|
|
61
60
|
_pendingSchemasDirty = true;
|
|
62
61
|
/* Resolves when the schemas have REACHED Monaco, not when they were queued. With Monaco already
|
|
@@ -100,7 +99,7 @@ export function loadMonaco(): Promise<Monaco> {
|
|
|
100
99
|
import("monaco-editor/editor"),
|
|
101
100
|
import("./monaco-setup.js"),
|
|
102
101
|
]);
|
|
103
|
-
_monaco = monaco
|
|
102
|
+
_monaco = monaco;
|
|
104
103
|
// The project's schemas may have arrived long before now; register them before the first editor
|
|
105
104
|
// Mounts so its very first validation pass uses the right rules.
|
|
106
105
|
await applyPendingSchemas();
|
|
@@ -138,15 +137,15 @@ export function loadedMonaco(): Monaco | null {
|
|
|
138
137
|
* attached to anything, and no URI briefly claimed by a model nobody holds.
|
|
139
138
|
*
|
|
140
139
|
* @param {Element | null | undefined} container Where the editor was going to be created.
|
|
141
|
-
* @param {
|
|
142
|
-
* `view.functionEditor`). Non-null means another mount already won this race.
|
|
140
|
+
* @param {monacoNs.editor.IEditor | null} existing The surface's editor handle (`view.monacoEditor`
|
|
141
|
+
* / `view.functionEditor`). Non-null means another mount already won this race.
|
|
143
142
|
* @param {() => boolean} stillTargeted Whether the app still wants exactly THIS mount — the same
|
|
144
143
|
* tab, the same mode, the same editing target. Lazy: the two cheap clauses above answer first.
|
|
145
144
|
* @returns {boolean}
|
|
146
145
|
*/
|
|
147
146
|
export function mountStillWanted(
|
|
148
147
|
container: Element | null | undefined,
|
|
149
|
-
existing:
|
|
148
|
+
existing: monacoNs.editor.IEditor | null,
|
|
150
149
|
stillTargeted: () => boolean,
|
|
151
150
|
): boolean {
|
|
152
151
|
if (!container?.isConnected || existing) {
|
|
@@ -80,18 +80,24 @@ import "monaco-editor/languages/definitions/javascript/register";
|
|
|
80
80
|
import { flattenSchema } from "@jxsuite/schema/project-schemas";
|
|
81
81
|
import jxSchema from "@jxsuite/schema/schema.json";
|
|
82
82
|
import projectSchema from "@jxsuite/schema/project-schema.json";
|
|
83
|
+
import type { JsonObject } from "@jxsuite/schema/types";
|
|
84
|
+
import type { ProjectSchemasResponse } from "../types";
|
|
83
85
|
import { bundleUrl } from "./bundle-base";
|
|
84
86
|
|
|
85
87
|
/* Re-exported for the modules that already imported it from here. New callers should reach for
|
|
86
88
|
`./model-uri` directly — it is Monaco-free, and importing this module loads the editor. */
|
|
87
89
|
export { modelUriFor } from "./model-uri";
|
|
88
90
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
91
|
+
/** The worker every label without a language service of its own runs in. */
|
|
92
|
+
const EDITOR_WORKER_FILE = "editor.worker.js";
|
|
93
|
+
|
|
94
|
+
/** Monaco worker label → the pre-bundled worker file that serves it. */
|
|
95
|
+
const WORKER_FILES = new Map([
|
|
96
|
+
["editorWorkerService", EDITOR_WORKER_FILE],
|
|
97
|
+
["javascript", "ts.worker.js"],
|
|
98
|
+
["json", "json.worker.js"],
|
|
99
|
+
["typescript", "ts.worker.js"],
|
|
100
|
+
]);
|
|
95
101
|
|
|
96
102
|
/**
|
|
97
103
|
* Resolve a Monaco worker to the PRE-BUNDLED copy that ships NEXT TO THE ENTRY — `dist/workers/`
|
|
@@ -119,7 +125,7 @@ const WORKER_FILES: Record<string, string> = {
|
|
|
119
125
|
* @returns {string} Absolute URL of the worker bundle
|
|
120
126
|
*/
|
|
121
127
|
export function workerUrl(label: string): string {
|
|
122
|
-
const file = WORKER_FILES
|
|
128
|
+
const file = WORKER_FILES.get(label) ?? EDITOR_WORKER_FILE;
|
|
123
129
|
return bundleUrl(`workers/${file}`);
|
|
124
130
|
}
|
|
125
131
|
|
|
@@ -132,10 +138,13 @@ self.MonacoEnvironment = {
|
|
|
132
138
|
/* Monaco caches glyph widths when an editor is created. JetBrains Mono is a
|
|
133
139
|
vendored webfont (index.html @font-face) and may finish loading after the
|
|
134
140
|
first editor mounts, so remeasure once all document fonts are ready to keep
|
|
135
|
-
cursor and selection alignment correct.
|
|
136
|
-
|
|
141
|
+
cursor and selection alignment correct. `lib.dom` declares `document.fonts` unconditionally, but
|
|
142
|
+
DOM shims (happy-dom under test) ship without it, so the font set is typed as possibly absent. */
|
|
143
|
+
const documentFonts: FontFaceSet | undefined =
|
|
144
|
+
typeof document === "undefined" ? undefined : document.fonts;
|
|
145
|
+
if (documentFonts?.ready) {
|
|
137
146
|
// oxlint-disable-next-line unicorn/prefer-top-level-await -- fire-and-forget: awaiting fonts.ready at top level would block module evaluation (and studio startup) until webfonts load
|
|
138
|
-
void
|
|
147
|
+
void documentFonts.ready.then(async () => {
|
|
139
148
|
const monaco = await import("monaco-editor/editor");
|
|
140
149
|
monaco.editor.remeasureFonts();
|
|
141
150
|
});
|
|
@@ -186,7 +195,7 @@ const DOCUMENT_ENTRY_SCHEMA_ID = "file:///document.schema.json";
|
|
|
186
195
|
* worse, resolved to an empty schema, so the fileMatch registration never ran and REAL violations
|
|
187
196
|
* went unreported behind that one diagnostic.
|
|
188
197
|
*/
|
|
189
|
-
function applyJsonSchemas(documentSchema:
|
|
198
|
+
function applyJsonSchemas(documentSchema: JsonObject, projectJsonSchema: JsonObject) {
|
|
190
199
|
jsonDefaults.setDiagnosticsOptions({
|
|
191
200
|
allowComments: false,
|
|
192
201
|
schemas: [
|
|
@@ -212,8 +221,8 @@ function applyJsonSchemas(documentSchema: unknown, projectJsonSchema: unknown) {
|
|
|
212
221
|
a URI before the `#` by FETCHING it — with `enableSchemaRequest` off that just fails, leaving
|
|
213
222
|
`$paths` reporting an unresolvable ref. Flattening rewrites those refs onto the shipped defaults
|
|
214
223
|
embedded in the same document, which is exactly the right fallback semantics. */
|
|
215
|
-
const FALLBACK_DOCUMENT_SCHEMA = flattenSchema(jxSchema
|
|
216
|
-
const FALLBACK_PROJECT_SCHEMA = flattenSchema(projectSchema
|
|
224
|
+
const FALLBACK_DOCUMENT_SCHEMA = flattenSchema(jxSchema);
|
|
225
|
+
const FALLBACK_PROJECT_SCHEMA = flattenSchema(projectSchema);
|
|
217
226
|
|
|
218
227
|
// Bundled core schemas register at module init — the offline fallback every platform starts from.
|
|
219
228
|
applyJsonSchemas(FALLBACK_DOCUMENT_SCHEMA, FALLBACK_PROJECT_SCHEMA);
|
|
@@ -232,9 +241,7 @@ applyJsonSchemas(FALLBACK_DOCUMENT_SCHEMA, FALLBACK_PROJECT_SCHEMA);
|
|
|
232
241
|
* @param {object | null} schemas - Pre-bundled `{ document, project }` payload
|
|
233
242
|
* @returns {boolean} True when per-project schemas were applied; false on fallback
|
|
234
243
|
*/
|
|
235
|
-
export function applyProjectSchemas(
|
|
236
|
-
schemas: { project?: unknown; document?: unknown } | null | undefined,
|
|
237
|
-
): boolean {
|
|
244
|
+
export function applyProjectSchemas(schemas: ProjectSchemasResponse | null | undefined): boolean {
|
|
238
245
|
const { document, project } = schemas ?? {};
|
|
239
246
|
if (!document && !project) {
|
|
240
247
|
return false;
|
package/src/services/notify.ts
CHANGED
|
@@ -34,6 +34,7 @@
|
|
|
34
34
|
* this module learning it exists.
|
|
35
35
|
*/
|
|
36
36
|
|
|
37
|
+
import type { CommandArgValues } from "../commands/command-args";
|
|
37
38
|
import { reactive } from "../reactivity";
|
|
38
39
|
import { announce } from "./announce";
|
|
39
40
|
import { now } from "./clock";
|
|
@@ -87,7 +88,7 @@ export interface NotifyOptions {
|
|
|
87
88
|
*/
|
|
88
89
|
action?: string;
|
|
89
90
|
/** Args passed to {@link NotifyOptions.action} when it runs. */
|
|
90
|
-
actionArgs?:
|
|
91
|
+
actionArgs?: CommandArgValues;
|
|
91
92
|
/** The long form — a stack, a captured log, a validator's output. Rendered in Problems only. */
|
|
92
93
|
detail?: string;
|
|
93
94
|
/** Who reported it: "Save", "Source Control", "Canvas", "Assistant". Groups the Problems list. */
|
|
@@ -114,7 +115,7 @@ export interface Notification {
|
|
|
114
115
|
/** Epoch ms from {@link now}, so a pinned clock pins the "2m ago" a Problems row renders. */
|
|
115
116
|
readonly at: number;
|
|
116
117
|
readonly action?: string;
|
|
117
|
-
readonly actionArgs?:
|
|
118
|
+
readonly actionArgs?: CommandArgValues;
|
|
118
119
|
readonly detail?: string;
|
|
119
120
|
readonly source?: string;
|
|
120
121
|
readonly path?: string;
|
|
@@ -158,6 +159,45 @@ function storeFor(tier: NotificationTier): Notification[] {
|
|
|
158
159
|
return tier === "problem" ? problems : toasts;
|
|
159
160
|
}
|
|
160
161
|
|
|
162
|
+
/** A record's mutable draft: {@link Notification} is frozen to readers, not to its one builder. */
|
|
163
|
+
type NotificationDraft = { -readonly [K in keyof Notification]: Notification[K] };
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Build the record for one outcome, copying only the options the caller actually set — so a host
|
|
167
|
+
* rendering `record.detail` never meets an explicit `undefined` — in the order every record has
|
|
168
|
+
* always carried its keys.
|
|
169
|
+
*/
|
|
170
|
+
function recordFor(
|
|
171
|
+
severity: Severity,
|
|
172
|
+
message: string,
|
|
173
|
+
tier: NotificationTier,
|
|
174
|
+
options: NotifyOptions,
|
|
175
|
+
): Notification {
|
|
176
|
+
const record: NotificationDraft = { at: now(), id: nextId(), message, severity, tier };
|
|
177
|
+
if (options.action !== undefined) {
|
|
178
|
+
record.action = options.action;
|
|
179
|
+
}
|
|
180
|
+
if (options.actionArgs !== undefined) {
|
|
181
|
+
record.actionArgs = options.actionArgs;
|
|
182
|
+
}
|
|
183
|
+
if (options.detail !== undefined) {
|
|
184
|
+
record.detail = options.detail;
|
|
185
|
+
}
|
|
186
|
+
if (options.source !== undefined) {
|
|
187
|
+
record.source = options.source;
|
|
188
|
+
}
|
|
189
|
+
if (options.path !== undefined) {
|
|
190
|
+
record.path = options.path;
|
|
191
|
+
}
|
|
192
|
+
if (options.key !== undefined) {
|
|
193
|
+
record.key = options.key;
|
|
194
|
+
}
|
|
195
|
+
if (tier === "toast") {
|
|
196
|
+
record.timeoutMs = options.timeoutMs ?? TOAST_LIFETIME_MS[severity];
|
|
197
|
+
}
|
|
198
|
+
return record;
|
|
199
|
+
}
|
|
200
|
+
|
|
161
201
|
/**
|
|
162
202
|
* Record an outcome and return it.
|
|
163
203
|
*
|
|
@@ -170,20 +210,7 @@ export function notify(
|
|
|
170
210
|
options: NotifyOptions = {},
|
|
171
211
|
): Notification {
|
|
172
212
|
const tier = options.tier ?? DEFAULT_TIER[severity];
|
|
173
|
-
const record
|
|
174
|
-
at: now(),
|
|
175
|
-
id: nextId(),
|
|
176
|
-
message,
|
|
177
|
-
severity,
|
|
178
|
-
tier,
|
|
179
|
-
...(options.action === undefined ? {} : { action: options.action }),
|
|
180
|
-
...(options.actionArgs === undefined ? {} : { actionArgs: options.actionArgs }),
|
|
181
|
-
...(options.detail === undefined ? {} : { detail: options.detail }),
|
|
182
|
-
...(options.source === undefined ? {} : { source: options.source }),
|
|
183
|
-
...(options.path === undefined ? {} : { path: options.path }),
|
|
184
|
-
...(options.key === undefined ? {} : { key: options.key }),
|
|
185
|
-
...(tier === "toast" ? { timeoutMs: options.timeoutMs ?? TOAST_LIFETIME_MS[severity] } : {}),
|
|
186
|
-
};
|
|
213
|
+
const record = recordFor(severity, message, tier, options);
|
|
187
214
|
|
|
188
215
|
const store = storeFor(tier);
|
|
189
216
|
if (record.key !== undefined) {
|
|
@@ -273,7 +300,7 @@ export interface ProblemFinding {
|
|
|
273
300
|
path?: string;
|
|
274
301
|
key?: string;
|
|
275
302
|
action?: string;
|
|
276
|
-
actionArgs?:
|
|
303
|
+
actionArgs?: CommandArgValues;
|
|
277
304
|
}
|
|
278
305
|
|
|
279
306
|
/**
|
|
@@ -23,6 +23,7 @@
|
|
|
23
23
|
|
|
24
24
|
import { activeTab } from "../workspace/workspace";
|
|
25
25
|
import { clearProblems, notify, problemFindings } from "./notify";
|
|
26
|
+
import type { NotifyOptions } from "./notify";
|
|
26
27
|
import {
|
|
27
28
|
findPopoverDefects,
|
|
28
29
|
popoverDisplayRepair,
|
|
@@ -39,7 +40,8 @@ import {
|
|
|
39
40
|
} from "../tabs/transact";
|
|
40
41
|
import { getNodeAtPath } from "../state";
|
|
41
42
|
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
42
|
-
import type {
|
|
43
|
+
import type { CommandArgValues } from "../commands/command-args";
|
|
44
|
+
import type { JxElement } from "@jxsuite/schema/types";
|
|
43
45
|
import type { JxPath } from "../state";
|
|
44
46
|
import type { PopoverFix, PopoverPath } from "@jxsuite/schema/overlays";
|
|
45
47
|
|
|
@@ -100,7 +102,7 @@ export function reportPopoverProblems(doc: JxElement, path?: string): number {
|
|
|
100
102
|
const defects = findPopoverDefects(doc, KIT_SCOPE);
|
|
101
103
|
for (const defect of defects) {
|
|
102
104
|
const action = defect.fix === undefined ? undefined : REPAIR_COMMAND[defect.fix];
|
|
103
|
-
|
|
105
|
+
const options: NotifyOptions = {
|
|
104
106
|
detail: defect.detail,
|
|
105
107
|
/* Keyed by RULE AND PATH, not by rule alone: a header with two popovers can carry the same
|
|
106
108
|
defect twice, and a key that collapsed them would report one and silently drop the other.
|
|
@@ -109,32 +111,45 @@ export function reportPopoverProblems(doc: JxElement, path?: string): number {
|
|
|
109
111
|
key: problemKey(seen, "popover", defect.rule, defect.path),
|
|
110
112
|
source: POPOVER_PROBLEM_SOURCE,
|
|
111
113
|
tier: "problem",
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
};
|
|
115
|
+
if (action !== undefined) {
|
|
116
|
+
options.action = action;
|
|
117
|
+
options.actionArgs = { path: defect.path };
|
|
118
|
+
}
|
|
119
|
+
if (path !== undefined) {
|
|
120
|
+
options.path = path;
|
|
121
|
+
}
|
|
122
|
+
notify(defect.severity, defect.message, options);
|
|
115
123
|
}
|
|
116
124
|
/* The dialog and invoker-command rules (`spec.md` §8.7) file under the same source: one report
|
|
117
125
|
for everything the platform overlays. They carry no repair button yet — the popover repairs
|
|
118
126
|
move `display` into `:popover-open`, and a dialog's open rule is a different selector. */
|
|
119
127
|
const dialogDefects = findDialogDefects(doc, KIT_SCOPE);
|
|
120
128
|
for (const defect of dialogDefects) {
|
|
121
|
-
|
|
129
|
+
const options: NotifyOptions = {
|
|
122
130
|
detail: defect.detail,
|
|
123
131
|
key: problemKey(seen, "dialog", defect.rule, defect.path),
|
|
124
132
|
source: POPOVER_PROBLEM_SOURCE,
|
|
125
133
|
tier: "problem",
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
};
|
|
135
|
+
if (path !== undefined) {
|
|
136
|
+
options.path = path;
|
|
137
|
+
}
|
|
138
|
+
notify(defect.severity, defect.message, options);
|
|
128
139
|
}
|
|
129
140
|
return defects.length + dialogDefects.length;
|
|
130
141
|
}
|
|
131
142
|
|
|
132
143
|
/** Read the path argument a repair command was invoked with, or throw naming the command. */
|
|
133
|
-
function repairPath(id: string, args:
|
|
144
|
+
function repairPath(id: string, args: CommandArgValues | undefined): JxPath {
|
|
134
145
|
const path = args?.path;
|
|
135
146
|
if (!Array.isArray(path)) {
|
|
136
147
|
throw new RangeError(`command "${id}" needs a "path" argument naming the popover`);
|
|
137
148
|
}
|
|
149
|
+
/* SAFETY: every repair record below declares `path` as an array whose items are
|
|
150
|
+
`["string", "number"]`, which `coerceArgs` reads as a path argument and checks segment by
|
|
151
|
+
segment (`pathArg`) before `run` is called — so an array that reached here holds only string
|
|
152
|
+
keys and numeric indexes. */
|
|
138
153
|
return path as JxPath;
|
|
139
154
|
}
|
|
140
155
|
|
|
@@ -217,7 +232,7 @@ export function popoverCommands(): AnyCommand[] {
|
|
|
217
232
|
const id = "document.repairPopoverDisplay";
|
|
218
233
|
const tab = repairTab(id);
|
|
219
234
|
const path = repairPath(id, args);
|
|
220
|
-
const node = getNodeAtPath(tab.doc.document, path)
|
|
235
|
+
const node = getNodeAtPath(tab.doc.document, path);
|
|
221
236
|
const repair = popoverDisplayRepair(node?.style);
|
|
222
237
|
if (!repair) {
|
|
223
238
|
throw new RangeError(`command "${id}": nothing to move — this popover sets no display`);
|
|
@@ -10,12 +10,15 @@
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
import { evaluateExpression, isMutating } from "@jxsuite/runtime/expression";
|
|
13
|
+
import { isNonNullObject } from "@jxsuite/schema/guards";
|
|
13
14
|
import { toRaw } from "../reactivity";
|
|
14
15
|
// Imported for local use AND re-exported below so existing consumers keep their import site.
|
|
15
16
|
// oxlint-disable-next-line unicorn/prefer-export-from
|
|
16
17
|
import { formatPreviewValue } from "../utils/preview-format";
|
|
18
|
+
import type { PreviewValue } from "../utils/preview-format";
|
|
17
19
|
|
|
18
|
-
import type {
|
|
20
|
+
import type { JxScope } from "@jxsuite/runtime/types";
|
|
21
|
+
import type { JxExpressionNode, JxExpressionOperand } from "@jxsuite/schema/types";
|
|
19
22
|
|
|
20
23
|
export interface ExpressionPreview {
|
|
21
24
|
/** Path-keyed display values: "" is the root node, "value/target" a nested operand, etc. */
|
|
@@ -36,14 +39,14 @@ export { formatPreviewValue };
|
|
|
36
39
|
* (canvas not yet rendered) — the editor renders no badges rather than wrong ones.
|
|
37
40
|
*/
|
|
38
41
|
export function previewExpression(
|
|
39
|
-
node:
|
|
40
|
-
scope?:
|
|
42
|
+
node: JxExpressionOperand | undefined,
|
|
43
|
+
scope?: JxScope | null,
|
|
41
44
|
): ExpressionPreview | null {
|
|
42
|
-
if (!scope || !node ||
|
|
45
|
+
if (!scope || !isNonNullObject(node) || !("operator" in node)) {
|
|
43
46
|
return null;
|
|
44
47
|
}
|
|
45
48
|
|
|
46
|
-
let state:
|
|
49
|
+
let state: JxScope;
|
|
47
50
|
try {
|
|
48
51
|
// Callers hand over tab.session.canvas.scope, which the reactive session tree wraps in a
|
|
49
52
|
// Proxy — structuredClone rejects proxies, so unwrap to the raw snapshot first.
|
|
@@ -54,11 +57,20 @@ export function previewExpression(
|
|
|
54
57
|
}
|
|
55
58
|
|
|
56
59
|
const values = new Map<string, string>();
|
|
57
|
-
|
|
60
|
+
/* SAFETY: an operand object carrying `operator` is the expression-node member of the operand
|
|
61
|
+
union (the plain-object member is an options bag, which has no operator), and a node whose
|
|
62
|
+
other members are malformed throws inside `evaluateExpression`, which this preview reports
|
|
63
|
+
as its `error` rather than trusting. */
|
|
64
|
+
const expr = node as JxExpressionNode;
|
|
58
65
|
let errorMessage: string | null = null;
|
|
59
66
|
try {
|
|
60
|
-
evaluateExpression(expr, state, null, undefined, {
|
|
61
|
-
report: (path, value) =>
|
|
67
|
+
void evaluateExpression(expr, state, null, undefined, {
|
|
68
|
+
report: (path, value) => {
|
|
69
|
+
/* SAFETY: the trace reports raw runtime values, and PreviewValue names every category a JS
|
|
70
|
+
value falls in (primitive, bigint, symbol, function, array, record); formatting relies on
|
|
71
|
+
nothing beyond what JSON.stringify and String() accept for any value. */
|
|
72
|
+
values.set(path.join("/"), formatPreviewValue(value as PreviewValue));
|
|
73
|
+
},
|
|
62
74
|
});
|
|
63
75
|
} catch (error) {
|
|
64
76
|
errorMessage = error instanceof Error ? error.message : String(error);
|
package/src/services/profile.ts
CHANGED
|
@@ -40,7 +40,7 @@ export interface StartupProfile {
|
|
|
40
40
|
* `default` is not a no-op by omission — it is a named state, so "the app started normally" and
|
|
41
41
|
* "the profile was unrecognised" are different outcomes and the second one is loud.
|
|
42
42
|
*/
|
|
43
|
-
export const STARTUP_PROFILES
|
|
43
|
+
export const STARTUP_PROFILES = {
|
|
44
44
|
default: {
|
|
45
45
|
description: "Resume whatever was persisted — layout, recents, settings, chat history.",
|
|
46
46
|
id: "default",
|
|
@@ -51,7 +51,10 @@ export const STARTUP_PROFILES: Readonly<Record<string, StartupProfile>> = {
|
|
|
51
51
|
id: "fresh",
|
|
52
52
|
reset: "app-state",
|
|
53
53
|
},
|
|
54
|
-
}
|
|
54
|
+
} satisfies Readonly<Record<string, StartupProfile>>;
|
|
55
|
+
|
|
56
|
+
/** {@link STARTUP_PROFILES} by id, for a lookup whose id arrives from the query string. */
|
|
57
|
+
const PROFILES_BY_ID = new Map<string, StartupProfile>(Object.entries(STARTUP_PROFILES));
|
|
55
58
|
|
|
56
59
|
export const DEFAULT_PROFILE_ID = "default";
|
|
57
60
|
|
|
@@ -77,7 +80,8 @@ export function isStudioStorageKey(key: string): boolean {
|
|
|
77
80
|
* @returns The keys removed, so a caller (Preferences, a test) can report what it did.
|
|
78
81
|
*/
|
|
79
82
|
export function clearStudioStorage(): string[] {
|
|
80
|
-
|
|
83
|
+
// `localStorage` is absent outside a browser realm (Bun without a DOM shim), whatever lib.dom says.
|
|
84
|
+
const store = typeof localStorage === "undefined" ? undefined : localStorage;
|
|
81
85
|
if (!store) {
|
|
82
86
|
return [];
|
|
83
87
|
}
|
|
@@ -105,10 +109,10 @@ export function clearStudioStorage(): string[] {
|
|
|
105
109
|
* `default` would start the app in the state the caller was trying to avoid.
|
|
106
110
|
*/
|
|
107
111
|
export function applyProfile(id: string): StartupProfile {
|
|
108
|
-
const profile =
|
|
112
|
+
const profile = PROFILES_BY_ID.get(id);
|
|
109
113
|
if (!profile) {
|
|
110
114
|
throw new RangeError(
|
|
111
|
-
`unknown startup profile "${id}"; declared: ${
|
|
115
|
+
`unknown startup profile "${id}"; declared: ${[...PROFILES_BY_ID.keys()].join(", ")}`,
|
|
112
116
|
);
|
|
113
117
|
}
|
|
114
118
|
if (profile.reset === "app-state") {
|
|
@@ -137,7 +141,10 @@ export function applyStartupProfile(search?: string): StartupState {
|
|
|
137
141
|
if (_startup) {
|
|
138
142
|
return _startup;
|
|
139
143
|
}
|
|
140
|
-
|
|
144
|
+
// `location` is absent outside a browser realm, which is why the tests pass `search` themselves.
|
|
145
|
+
const query = new URLSearchParams(
|
|
146
|
+
search ?? (typeof location === "undefined" ? "" : location.search),
|
|
147
|
+
);
|
|
141
148
|
const profile = applyProfile(query.get("profile") ?? DEFAULT_PROFILE_ID);
|
|
142
149
|
const clockParam = query.get("clock");
|
|
143
150
|
_startup = { clock: clockParam === null ? null : pinClock(clockParam), profile };
|