@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
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* studio.ts, and lets a test state a context without standing up the app.
|
|
26
26
|
*/
|
|
27
27
|
|
|
28
|
+
import { isFunction, isString } from "@jxsuite/schema/guards";
|
|
28
29
|
import { resolveI18n } from "@jxsuite/schema/locale";
|
|
29
30
|
import { componentRegistry } from "../files/components";
|
|
30
31
|
import { getNodeAtPath, projectState } from "../store";
|
|
@@ -36,7 +37,7 @@ import { hasTyping } from "../tabs/typing";
|
|
|
36
37
|
import { collabState } from "../collab/collab-state";
|
|
37
38
|
|
|
38
39
|
import { canvasViewForMode, editorKindForMode, emptyContext } from "./context";
|
|
39
|
-
import type { CommandContext
|
|
40
|
+
import type { CommandContext } from "./context";
|
|
40
41
|
import type { StudioPlatform } from "../types";
|
|
41
42
|
|
|
42
43
|
/** Elements that own the keyboard while focused. Matches the old listener's target test exactly. */
|
|
@@ -86,7 +87,7 @@ export interface LiveContextSources {
|
|
|
86
87
|
|
|
87
88
|
/** `capability.*` is presence-of-method on the PAL — the check every call site does by hand today. */
|
|
88
89
|
function capabilities(platform: StudioPlatform | null): CommandContext["capability"] {
|
|
89
|
-
const has = (key: keyof StudioPlatform) =>
|
|
90
|
+
const has = (key: keyof StudioPlatform) => isFunction(platform?.[key]);
|
|
90
91
|
return {
|
|
91
92
|
dataRows: has("dataRows"),
|
|
92
93
|
// The real member now, not the `codeService` stand-in it was minted against: the usage query is
|
|
@@ -161,18 +162,17 @@ export function createLiveContext(sources: LiveContextSources): () => CommandCon
|
|
|
161
162
|
const selection = primarySelection(paths);
|
|
162
163
|
if (selection) {
|
|
163
164
|
const node = getNodeAtPath(tab!.doc.document, selection);
|
|
165
|
+
const tagName = node?.tagName;
|
|
164
166
|
ctx.selection.count = paths.length;
|
|
165
167
|
ctx.selection.paths = paths.map((path) => [...path]);
|
|
166
168
|
// Every remaining fact describes the PRIMARY — the one node a single-target verb addresses —
|
|
167
169
|
// Except `isRoot`, which is the batch's own gate: a batch containing the document element
|
|
168
170
|
// Cannot be deleted or duplicated any more than that element could be on its own.
|
|
169
|
-
ctx.selection.kind =
|
|
171
|
+
ctx.selection.kind = isString(tagName) ? tagName : "";
|
|
170
172
|
// A path of fewer than two segments addresses the document element itself — the same test
|
|
171
173
|
// `shortcuts.ts` spelled as `selection.length >= 2` at four separate call sites.
|
|
172
174
|
ctx.selection.isRoot = paths.some((path) => path.length < 2);
|
|
173
|
-
ctx.selection.isComponentInstance = componentRegistry.some(
|
|
174
|
-
(c) => c.tagName === node?.tagName,
|
|
175
|
-
);
|
|
175
|
+
ctx.selection.isComponentInstance = componentRegistry.some((c) => c.tagName === tagName);
|
|
176
176
|
ctx.selection.isRepeater = node?.$prototype === "Array";
|
|
177
177
|
}
|
|
178
178
|
// Layout chrome is NOT a document selection: the node is not in the open page at all.
|
|
@@ -187,7 +187,7 @@ export function createLiveContext(sources: LiveContextSources): () => CommandCon
|
|
|
187
187
|
being typed into. The stack asks "is something being typed into"; a record asks "is the
|
|
188
188
|
thing being typed into the page". */
|
|
189
189
|
ctx.caret.inCanvas = sources.isCaretActive();
|
|
190
|
-
ctx.focus.region = shell.focusRegion
|
|
190
|
+
ctx.focus.region = shell.focusRegion;
|
|
191
191
|
ctx.modal.open = sources.isModalOpen();
|
|
192
192
|
|
|
193
193
|
if (tab) {
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* between runs is a CI diff nobody can review.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
+
import { isString } from "@jxsuite/schema/guards";
|
|
20
21
|
import { formatChord, normalizeChord } from "./keymap";
|
|
21
22
|
import { CATEGORIES } from "./levels";
|
|
22
23
|
import type { KeybindingOverrides } from "./keymap";
|
|
@@ -83,7 +84,7 @@ function chordsOf(command: AnyCommand): string[] {
|
|
|
83
84
|
if (!raw) {
|
|
84
85
|
return [];
|
|
85
86
|
}
|
|
86
|
-
return (
|
|
87
|
+
return (isString(raw) ? [raw] : [...raw]).map((chord) => normalizeChord(chord));
|
|
87
88
|
}
|
|
88
89
|
|
|
89
90
|
/**
|
package/src/commands/registry.ts
CHANGED
|
@@ -36,13 +36,12 @@ import { createKeymap } from "./keymap";
|
|
|
36
36
|
import type { KeyChordEvent, Keymap, KeymapMatch } from "./keymap";
|
|
37
37
|
import { checkRecordPlacements } from "./levels";
|
|
38
38
|
import type { Category, KeyScope, Level, Placement } from "./levels";
|
|
39
|
+
import { isFunction } from "@jxsuite/schema/guards";
|
|
39
40
|
import { coerceArgs } from "./command-args";
|
|
41
|
+
import type { CommandArgsSchema, CommandArgValues } from "./command-args";
|
|
40
42
|
import { runReported } from "./run-reported";
|
|
41
43
|
import type { CommandContext } from "./context";
|
|
42
44
|
|
|
43
|
-
/** Arguments as they arrive from a palette prompt, an automation manifest step or an AI tool call. */
|
|
44
|
-
export type CommandArgs = Record<string, unknown>;
|
|
45
|
-
|
|
46
45
|
/** How an action's effect is undone — surfaced to the user before an agent runs it. */
|
|
47
46
|
export type UndoScope = "document" | "project" | "none";
|
|
48
47
|
|
|
@@ -77,7 +76,7 @@ export interface Command<A = void> {
|
|
|
77
76
|
* shot check's contract AND what {@link CommandRegistry.run} coerces the received record against
|
|
78
77
|
* before `run` sees it (`command-args.ts`'s `coerceArgs`). One object, four readers.
|
|
79
78
|
*/
|
|
80
|
-
args?:
|
|
79
|
+
args?: CommandArgsSchema;
|
|
81
80
|
/** Surfaces this command renders in. Defaults to `["palette"]`. */
|
|
82
81
|
menus?: readonly Placement[];
|
|
83
82
|
/** Menu ordering key: "1_clipboard", "3_structure", "9_danger". */
|
|
@@ -216,7 +215,7 @@ export interface CommandRegistry {
|
|
|
216
215
|
* `RangeError` naming the argument when `args` does not fit the record's schema — synchronously,
|
|
217
216
|
* before `run` is entered, whichever surface the call came from.
|
|
218
217
|
*/
|
|
219
|
-
run: (id: string, args?:
|
|
218
|
+
run: (id: string, args?: CommandArgValues) => void | Promise<void>;
|
|
220
219
|
/** The chord index, conflict-checked at registration. */
|
|
221
220
|
keymap: Keymap;
|
|
222
221
|
/** Resolve a keyboard event through a scope stack and run what it hits. */
|
|
@@ -254,7 +253,7 @@ function checkProjection(command: AnyCommand, toolNames: ReadonlyMap<string, str
|
|
|
254
253
|
`command "${command.id}" aiTool name "${tool.name}" is already projected by "${claimant}"`,
|
|
255
254
|
);
|
|
256
255
|
}
|
|
257
|
-
if (
|
|
256
|
+
if (!isFunction(tool.report)) {
|
|
258
257
|
throw new TypeError(
|
|
259
258
|
`command "${command.id}" declares aiTool without a report: a tool that can only say ` +
|
|
260
259
|
`"done" is refused`,
|
|
@@ -270,8 +269,7 @@ function checkProjection(command: AnyCommand, toolNames: ReadonlyMap<string, str
|
|
|
270
269
|
selector's `paths` property in FRONT of the record's own `args`, so a record that declares its
|
|
271
270
|
own `paths` would have two definitions of one argument — the model would read the record's
|
|
272
271
|
description and the bridge would hand the value to the selector. */
|
|
273
|
-
const properties =
|
|
274
|
-
?.properties;
|
|
272
|
+
const properties = command.args?.properties;
|
|
275
273
|
if (command.level === "selection" && properties && Object.hasOwn(properties, "paths")) {
|
|
276
274
|
throw new Error(
|
|
277
275
|
`command "${command.id}" is selection-level and may not declare "paths": the assistant ` +
|
|
@@ -341,11 +339,11 @@ export function createCommandRegistry(options: CommandRegistryOptions): CommandR
|
|
|
341
339
|
if (violations.length > 0) {
|
|
342
340
|
throw new Error(`command "${command.id}" ${violations[0]!.message}`);
|
|
343
341
|
}
|
|
344
|
-
checkProjection(command
|
|
342
|
+
checkProjection(command, toolNames);
|
|
345
343
|
// Chord conflicts throw from the keymap; do this LAST so a rejected record leaves the
|
|
346
344
|
// Registry untouched in every failure mode — the tool name is claimed only after it.
|
|
347
345
|
keymap.add(command);
|
|
348
|
-
commands.set(command.id, command
|
|
346
|
+
commands.set(command.id, command);
|
|
349
347
|
if (command.aiTool) {
|
|
350
348
|
toolNames.set(command.aiTool.name, command.id);
|
|
351
349
|
}
|
|
@@ -404,6 +402,10 @@ export function createCommandRegistry(options: CommandRegistryOptions): CommandR
|
|
|
404
402
|
their typed readers; `coerceArgs` dispatches to the same functions, so the two cannot
|
|
405
403
|
disagree. A record with no `args` takes whatever it was handed, as it always has. */
|
|
406
404
|
const coerced = command.args ? coerceArgs(id, command.args, args) : args;
|
|
405
|
+
/* SAFETY: a stored record is `Command<never>` because the map erases each record's own `A`.
|
|
406
|
+
The runtime contract for that erased `A` is the record's `args` schema, which `coerceArgs`
|
|
407
|
+
has just applied (every key its reader's return value, an undeclared key refused); a
|
|
408
|
+
record with no schema takes the caller's record as it always has. */
|
|
407
409
|
return command.run(ctx, coerced as never);
|
|
408
410
|
},
|
|
409
411
|
keymap,
|
|
@@ -55,7 +55,8 @@
|
|
|
55
55
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
56
56
|
import { notify } from "../services/notify";
|
|
57
57
|
import { activeRegistry } from "./active-registry";
|
|
58
|
-
import type {
|
|
58
|
+
import type { CommandArgValues } from "./command-args";
|
|
59
|
+
import type { CommandRegistry } from "./registry";
|
|
59
60
|
|
|
60
61
|
/**
|
|
61
62
|
* Whether an error is one of the two REFUSAL shapes, whose message is written to be read whole.
|
|
@@ -64,10 +65,10 @@ import type { CommandArgs, CommandRegistry } from "./registry";
|
|
|
64
65
|
* `handleKeyEvent`, and a value import back would close a cycle for one class whose constructor
|
|
65
66
|
* sets exactly this name. `RangeError` is the shape `coerceArgs` and a `run` body refuse with.
|
|
66
67
|
*/
|
|
67
|
-
function isRefusal(
|
|
68
|
+
function isRefusal(cause: unknown): boolean {
|
|
68
69
|
return (
|
|
69
|
-
|
|
70
|
-
(
|
|
70
|
+
cause instanceof RangeError ||
|
|
71
|
+
(cause instanceof Error && cause.name === "CommandUnavailableError")
|
|
71
72
|
);
|
|
72
73
|
}
|
|
73
74
|
|
|
@@ -86,15 +87,15 @@ function isRefusal(error: unknown): boolean {
|
|
|
86
87
|
export function runReported(
|
|
87
88
|
registry: CommandRegistry,
|
|
88
89
|
id: string,
|
|
89
|
-
args?:
|
|
90
|
+
args?: CommandArgValues,
|
|
90
91
|
source: string = id,
|
|
91
92
|
): Promise<void> {
|
|
92
|
-
const report = (
|
|
93
|
-
if (!isRefusal(
|
|
93
|
+
const report = (cause: unknown) => {
|
|
94
|
+
if (!isRefusal(cause)) {
|
|
94
95
|
// A crash, not a refusal: the row below carries the sentence, the console keeps the stack.
|
|
95
|
-
console.error(`${source}: command "${id}" failed`,
|
|
96
|
+
console.error(`${source}: command "${id}" failed`, cause);
|
|
96
97
|
}
|
|
97
|
-
notify.error(errorMessage(
|
|
98
|
+
notify.error(errorMessage(cause), { key: `command.run:${id}`, source });
|
|
98
99
|
};
|
|
99
100
|
let result: void | Promise<void>;
|
|
100
101
|
try {
|
|
@@ -114,7 +115,11 @@ export function runReported(
|
|
|
114
115
|
* registry to refuse it, so there is no refusal to file. The resolved promise keeps the caller's
|
|
115
116
|
* `void` honest either way.
|
|
116
117
|
*/
|
|
117
|
-
export function runActiveReported(
|
|
118
|
+
export function runActiveReported(
|
|
119
|
+
id: string,
|
|
120
|
+
args?: CommandArgValues,
|
|
121
|
+
source?: string,
|
|
122
|
+
): Promise<void> {
|
|
118
123
|
const registry = activeRegistry();
|
|
119
124
|
return registry ? runReported(registry, id, args, source) : Promise.resolve();
|
|
120
125
|
}
|
package/src/component-props.ts
CHANGED
|
@@ -11,8 +11,13 @@
|
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
import type { JsonValue } from "./types";
|
|
14
|
-
import type {
|
|
15
|
-
|
|
14
|
+
import type {
|
|
15
|
+
JsonPrimitive,
|
|
16
|
+
JxMutableNode,
|
|
17
|
+
JxStateDefinition,
|
|
18
|
+
JxStateObject,
|
|
19
|
+
} from "@jxsuite/schema/types";
|
|
20
|
+
import { isNonNullObject, isPrivateStateKey, isString } from "@jxsuite/schema/guards";
|
|
16
21
|
|
|
17
22
|
/** One editable prop row: the state key and its current default value (undefined = none). */
|
|
18
23
|
export interface ComponentPropEntry {
|
|
@@ -22,7 +27,16 @@ export interface ComponentPropEntry {
|
|
|
22
27
|
|
|
23
28
|
/** Whether the doc is a component definition (a custom-element root) rather than a page. */
|
|
24
29
|
export function isComponentDoc(doc: JxMutableNode | null | undefined): boolean {
|
|
25
|
-
|
|
30
|
+
const tagName = doc?.tagName;
|
|
31
|
+
return isString(tagName) && tagName.includes("-");
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/** The object shapes a state entry can take: every `JxStateDefinition` but a primitive or array. */
|
|
35
|
+
type StateEntryObject = Exclude<JxStateDefinition, JsonPrimitive | JsonValue[]>;
|
|
36
|
+
|
|
37
|
+
/** Whether a state entry is one of its object shapes — a signal, a typed def, a naked object. */
|
|
38
|
+
function isStateEntryObject(def: JxStateDefinition | undefined): def is StateEntryObject {
|
|
39
|
+
return isNonNullObject(def) && !Array.isArray(def);
|
|
26
40
|
}
|
|
27
41
|
|
|
28
42
|
/**
|
|
@@ -31,26 +45,20 @@ export function isComponentDoc(doc: JxMutableNode | null | undefined): boolean {
|
|
|
31
45
|
* templates, or $prototype data sources (overriding those would clobber behavior, the boundPropKey
|
|
32
46
|
* rule).
|
|
33
47
|
*/
|
|
34
|
-
function
|
|
35
|
-
if (def ===
|
|
36
|
-
return
|
|
37
|
-
}
|
|
38
|
-
if (typeof def === "string") {
|
|
39
|
-
return def.includes("${") ? null : "literal"; // Template strings render computed values.
|
|
40
|
-
}
|
|
41
|
-
if (Array.isArray(def)) {
|
|
42
|
-
return "literal";
|
|
48
|
+
function propKind(def: JxStateDefinition | undefined): "literal" | "signal" | null {
|
|
49
|
+
if (def === undefined) {
|
|
50
|
+
return null;
|
|
43
51
|
}
|
|
44
|
-
if (
|
|
45
|
-
|
|
46
|
-
if (d.$expression || d.$compute || d.$prototype || d.$handler) {
|
|
52
|
+
if (isStateEntryObject(def)) {
|
|
53
|
+
if (def.$expression || def.$compute || def.$prototype || def.$handler) {
|
|
47
54
|
return null;
|
|
48
55
|
}
|
|
49
56
|
// An expanded signal ({default}) or a typed prop def ({type}/schema keywords) seeds through
|
|
50
57
|
// Its `default`; any other plain object is a Shape-1 naked value.
|
|
51
|
-
return "default" in
|
|
58
|
+
return "default" in def || "type" in def ? "signal" : "literal";
|
|
52
59
|
}
|
|
53
|
-
|
|
60
|
+
// Null, numbers, booleans and arrays are naked literals. Template strings render computed values.
|
|
61
|
+
return isString(def) && def.includes("${") ? null : "literal";
|
|
54
62
|
}
|
|
55
63
|
|
|
56
64
|
/**
|
|
@@ -58,20 +66,20 @@ function propShape(def: unknown): "literal" | "signal" | null {
|
|
|
58
66
|
* entries with their current default values (the CEM-export "field" subset).
|
|
59
67
|
*/
|
|
60
68
|
export function componentPropEntries(doc: JxMutableNode | null | undefined): ComponentPropEntry[] {
|
|
61
|
-
const state =
|
|
69
|
+
const state: Record<string, JxStateDefinition> = doc?.state ?? {};
|
|
62
70
|
const out: ComponentPropEntry[] = [];
|
|
63
71
|
for (const [name, def] of Object.entries(state)) {
|
|
64
72
|
if (isPrivateStateKey(name)) {
|
|
65
73
|
continue; // Private entries are not props (spec.md §5.6).
|
|
66
74
|
}
|
|
67
|
-
const
|
|
68
|
-
if (!
|
|
75
|
+
const kind = propKind(def);
|
|
76
|
+
if (!kind) {
|
|
69
77
|
continue;
|
|
70
78
|
}
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
79
|
+
/* SAFETY: `propKind` refused every behavioral shape (expressions, computeds, `$prototype`
|
|
80
|
+
sources, handlers, template strings), so what is left is the document's plain data: a
|
|
81
|
+
literal entry IS the JSON value, and a signal entry is an object whose `default` is one. */
|
|
82
|
+
const value = kind === "signal" ? (def as { default?: JsonValue }).default : (def as JsonValue);
|
|
75
83
|
out.push({ name, value });
|
|
76
84
|
}
|
|
77
85
|
return out;
|
|
@@ -87,19 +95,27 @@ export function substitutePreviewProps(
|
|
|
87
95
|
renderDoc: JxMutableNode,
|
|
88
96
|
props: Record<string, JsonValue>,
|
|
89
97
|
): JxMutableNode {
|
|
90
|
-
const state = { ...
|
|
98
|
+
const state = { ...renderDoc.state };
|
|
91
99
|
let seeded = false;
|
|
92
100
|
for (const [name, value] of Object.entries(props)) {
|
|
93
|
-
const
|
|
94
|
-
|
|
101
|
+
const current = state[name];
|
|
102
|
+
const kind = propKind(current);
|
|
103
|
+
if (!kind) {
|
|
95
104
|
continue; // Unknown/behavioral entries are never overridden by a stale test value.
|
|
96
105
|
}
|
|
97
|
-
|
|
98
|
-
|
|
106
|
+
/* SAFETY: `propKind` answers "signal" only for an object that carries `default` or `type` and
|
|
107
|
+
none of the behavioral keys (`$expression`, `$compute`, `$prototype`, `$handler`) — the
|
|
108
|
+
expanded-signal / typed-def shape `JxStateObject` describes. A literal is replaced by the
|
|
109
|
+
JSON test value itself, which is a Shape-1 naked entry; `JxStateDefinition` spells that
|
|
110
|
+
shape as `JxStateObject`, whose typed keys neither a `JsonObject` nor a spread copy can prove
|
|
111
|
+
statically (the spread drops the index signature its typed keys are checked against). */
|
|
112
|
+
state[name] = (
|
|
113
|
+
kind === "signal" ? { ...(current as JxStateObject), default: value } : value
|
|
114
|
+
) as JxStateDefinition;
|
|
99
115
|
seeded = true;
|
|
100
116
|
}
|
|
101
117
|
if (!seeded) {
|
|
102
118
|
return renderDoc;
|
|
103
119
|
}
|
|
104
|
-
return { ...renderDoc, state }
|
|
120
|
+
return { ...renderDoc, state };
|
|
105
121
|
}
|
|
@@ -32,12 +32,10 @@
|
|
|
32
32
|
import { defaultContentFormat, formatByName } from "../format/format-host";
|
|
33
33
|
import { projectState } from "../store";
|
|
34
34
|
import { resolveI18n } from "@jxsuite/schema/locale";
|
|
35
|
+
import { LOCALE_PLACEHOLDER } from "../canvas/asset-resolve";
|
|
35
36
|
import type { ContentSectionEntry } from "../types";
|
|
36
37
|
import type { ProjectConfig } from "@jxsuite/schema/types";
|
|
37
38
|
|
|
38
|
-
/** The placeholder a localized `source` carries, standing for one directory per declared locale. */
|
|
39
|
-
export const LOCALE_PLACEHOLDER = "{locale}";
|
|
40
|
-
|
|
41
39
|
/** What a path's collection is, and everything a caller needs in order to act on it. */
|
|
42
40
|
export interface CollectionMatch {
|
|
43
41
|
name: string;
|
|
@@ -69,11 +67,14 @@ function normalize(path: string): string {
|
|
|
69
67
|
|
|
70
68
|
/** The config a lookup reads: the caller's, or the open project's. */
|
|
71
69
|
function configOf(config: ProjectConfig | null | undefined): ProjectConfig | null {
|
|
72
|
-
return config ??
|
|
70
|
+
return config ?? projectState?.projectConfig ?? null;
|
|
73
71
|
}
|
|
74
72
|
|
|
75
73
|
/** The `content` section of a config, or an empty one. */
|
|
76
74
|
function contentSection(config: ProjectConfig | null): Record<string, ContentSectionEntry> {
|
|
75
|
+
/* SAFETY: `content` is the parser extension's section — collection name → entry object, its
|
|
76
|
+
project fragment schema the source of truth. `ContentSectionEntry` names only the fields Studio
|
|
77
|
+
reads, every one optional, and each reader below tests `source` before using it. */
|
|
77
78
|
return (config?.content ?? {}) as Record<string, ContentSectionEntry>;
|
|
78
79
|
}
|
|
79
80
|
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
|
|
21
21
|
import { reactive } from "../reactivity";
|
|
22
22
|
import type { ContentTypeSchema } from "@jxsuite/schema/types";
|
|
23
|
+
import type { EntryFields } from "./entry-fields";
|
|
23
24
|
|
|
24
25
|
/** The conventional frontmatter boolean that marks an entry a draft (site-architecture.md §7.6). */
|
|
25
26
|
export const DRAFT_FIELD = "draft";
|
|
@@ -44,7 +45,7 @@ export const DRAFT_MEANING =
|
|
|
44
45
|
* Takes the entry's FIELDS, whichever record they live in — `content/entry-fields.ts` answers that,
|
|
45
46
|
* because a JSON collection's entry has no frontmatter and its `draft` key is on the document.
|
|
46
47
|
*/
|
|
47
|
-
export function isDraftEntry(fields:
|
|
48
|
+
export function isDraftEntry(fields: EntryFields | null | undefined): boolean {
|
|
48
49
|
return fields?.[DRAFT_FIELD] === true;
|
|
49
50
|
}
|
|
50
51
|
|
|
@@ -63,7 +64,7 @@ export function schemaDeclaresDraft(schema: ContentTypeSchema | null | undefined
|
|
|
63
64
|
*/
|
|
64
65
|
export function hasDraftAxis(
|
|
65
66
|
schema: ContentTypeSchema | null | undefined,
|
|
66
|
-
fields?:
|
|
67
|
+
fields?: EntryFields | null,
|
|
67
68
|
): boolean {
|
|
68
69
|
return schemaDeclaresDraft(schema) || isDraftEntry(fields);
|
|
69
70
|
}
|
|
@@ -100,7 +101,7 @@ export function setIncludeDrafts(include: boolean): void {
|
|
|
100
101
|
*/
|
|
101
102
|
export function applyDraftFilter<T>(
|
|
102
103
|
items: readonly T[],
|
|
103
|
-
fieldsOf: (item: T) =>
|
|
104
|
+
fieldsOf: (item: T) => EntryFields | null | undefined,
|
|
104
105
|
includeDrafts: boolean,
|
|
105
106
|
): readonly T[] {
|
|
106
107
|
return includeDrafts ? items : items.filter((item) => !isDraftEntry(fieldsOf(item)));
|
|
@@ -33,7 +33,8 @@ import { invalidateReferenceEntries } from "../ui/form-controls";
|
|
|
33
33
|
import { reloadDraftAwareGrids } from "../grid/sources/content-source";
|
|
34
34
|
import { setIncludeDrafts } from "./draft-state";
|
|
35
35
|
import { collectionOfPath, entryCollection, entryCollections, seedEntry } from "./entry-model";
|
|
36
|
-
import {
|
|
36
|
+
import { collectionForDirectory } from "./collection-match";
|
|
37
|
+
import { LOCALE_PLACEHOLDER } from "../canvas/asset-resolve";
|
|
37
38
|
import { openEntryEditor, setEntryDraft } from "./entry-editor";
|
|
38
39
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
39
40
|
import type { EntryCollection } from "./entry-model";
|
|
@@ -167,7 +168,7 @@ export async function createEntry(
|
|
|
167
168
|
|
|
168
169
|
/** The active tab, when it is a content entry — the subject of the document-level verbs. */
|
|
169
170
|
function activeEntryTab(): Tab | null {
|
|
170
|
-
const tab = activeTab.value
|
|
171
|
+
const tab = activeTab.value;
|
|
171
172
|
return tab && collectionOfPath(tab.documentPath) ? tab : null;
|
|
172
173
|
}
|
|
173
174
|
|
|
@@ -50,6 +50,7 @@ import { mountEntryEditorSurface } from "../surfaces/entry-editor";
|
|
|
50
50
|
import { paneRegion } from "../ui/regions";
|
|
51
51
|
import { activateTab, workspace } from "../workspace/workspace";
|
|
52
52
|
import { commitEntryFields, entryFields, mutateEntryField } from "./entry-fields";
|
|
53
|
+
import type { EntryFields } from "./entry-fields";
|
|
53
54
|
import { DRAFT_FIELD, DRAFT_MEANING, hasDraftAxis, isDraftEntry } from "./draft-state";
|
|
54
55
|
import { collectionOfPath, missingRequired } from "./entry-model";
|
|
55
56
|
import type { EntryCollection } from "./entry-model";
|
|
@@ -57,7 +58,7 @@ import type { EntryEditorSurfaceHandle, EntryEditorView } from "../surfaces/entr
|
|
|
57
58
|
import type { JsonSchema, SchemaFormContext } from "../ui/schema-form";
|
|
58
59
|
import type { Tab } from "../tabs/tab";
|
|
59
60
|
import type { CanvasSurface } from "../canvas/canvas-surface";
|
|
60
|
-
import type {
|
|
61
|
+
import type { JsonObject } from "@jxsuite/schema/types";
|
|
61
62
|
|
|
62
63
|
/** The `canvasMode` the entry form draws under. */
|
|
63
64
|
export const ENTRY_MODE = "entry";
|
|
@@ -120,7 +121,7 @@ export function detachEntryPane(paneId: string): void {
|
|
|
120
121
|
* has explicitly published something should be able to see that they did.
|
|
121
122
|
*/
|
|
122
123
|
export function setEntryDraft(tab: Tab, draft: boolean): void {
|
|
123
|
-
transactDoc(tab, (t) => mutateEntryField(t, DRAFT_FIELD, draft
|
|
124
|
+
transactDoc(tab, (t) => mutateEntryField(t, DRAFT_FIELD, draft));
|
|
124
125
|
}
|
|
125
126
|
|
|
126
127
|
/** What the tab chip's draft pill says. A value, drawn by `surfaces/tab-strip.json`. */
|
|
@@ -169,7 +170,7 @@ function formContext(tab: Tab): SchemaFormContext {
|
|
|
169
170
|
fieldKeyPrefix: `entry:${tab.id}`,
|
|
170
171
|
resolvePointer: (pointer, scope) =>
|
|
171
172
|
resolveContextPointer(pointer, {
|
|
172
|
-
projectConfig:
|
|
173
|
+
projectConfig: projectState?.projectConfig ?? {},
|
|
173
174
|
scope,
|
|
174
175
|
}),
|
|
175
176
|
};
|
|
@@ -185,13 +186,14 @@ function formContext(tab: Tab): SchemaFormContext {
|
|
|
185
186
|
*/
|
|
186
187
|
function absentRequiredErrors(
|
|
187
188
|
collection: EntryCollection,
|
|
188
|
-
fields:
|
|
189
|
+
fields: EntryFields,
|
|
189
190
|
): Record<string, string> {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
191
|
+
return Object.fromEntries(
|
|
192
|
+
missingRequired(collection.schema, fields).map((field) => [
|
|
193
|
+
field,
|
|
194
|
+
"Required — this entry does not have one.",
|
|
195
|
+
]),
|
|
196
|
+
);
|
|
195
197
|
}
|
|
196
198
|
|
|
197
199
|
/** What the document says when the file belongs to no collection: the reason, then the fix. */
|
|
@@ -280,12 +282,22 @@ export function renderEntryMode(surface: CanvasSurface, tab: Tab): void {
|
|
|
280
282
|
return;
|
|
281
283
|
}
|
|
282
284
|
const fields = entryFields(tab);
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
285
|
+
/* SAFETY: `collection` comes from `collectionOfPath`, which matches only a content type that
|
|
286
|
+
declares a `schema` (`findContentTypeSchema` refuses one without), and that schema is the
|
|
287
|
+
collection's JSON Schema — the shape `JsonSchema` names for the form. `fields` is a
|
|
288
|
+
frontmatter block or a JSON entry's own root (entry-fields.ts), both parsed from YAML or
|
|
289
|
+
JSON text, so every value is JSON; a key an editor cleared reads as absent either way. */
|
|
290
|
+
const form = mountSchemaForm(
|
|
291
|
+
`entry:${paneId}`,
|
|
292
|
+
collection.schema as JsonSchema,
|
|
293
|
+
fields as JsonObject,
|
|
294
|
+
{
|
|
295
|
+
context: formContext(tab),
|
|
296
|
+
errors: absentRequiredErrors(collection, fields),
|
|
297
|
+
onChange: (patch) => commitEntryFields(tab, patch),
|
|
298
|
+
rerender: redraw,
|
|
299
|
+
},
|
|
300
|
+
);
|
|
289
301
|
if (form.parentNode !== formHost) {
|
|
290
302
|
formHost.replaceChildren(form);
|
|
291
303
|
}
|
|
@@ -332,7 +344,7 @@ export function renderEntryMode(surface: CanvasSurface, tab: Tab): void {
|
|
|
332
344
|
// Never this effect's guess. `tab.doc.document` is also the reference every transaction
|
|
333
345
|
// Replaces, so it is how an undo reaches the form whichever store the edit was in.
|
|
334
346
|
void tab.doc.document;
|
|
335
|
-
void tab.doc.content
|
|
347
|
+
void tab.doc.content.frontmatter;
|
|
336
348
|
void projectState?.projectConfig?.content;
|
|
337
349
|
draw();
|
|
338
350
|
});
|
|
@@ -365,7 +377,7 @@ export async function openEntryEditor(path: string): Promise<Tab | null> {
|
|
|
365
377
|
tab.session.ui.canvasMode = ENTRY_MODE;
|
|
366
378
|
tab.session.ui.preview = false;
|
|
367
379
|
activateTab(id);
|
|
368
|
-
return tab
|
|
380
|
+
return tab;
|
|
369
381
|
}
|
|
370
382
|
return null;
|
|
371
383
|
}
|
|
@@ -32,9 +32,16 @@ import { cloneValue } from "@jxsuite/schema/doc-ops";
|
|
|
32
32
|
import { notePreviewOverlayEdit } from "../preview/preview-overlay";
|
|
33
33
|
import { recordDocOp } from "../tabs/patch-ops";
|
|
34
34
|
import { mutateUpdateFrontmatter, transactDoc } from "../tabs/transact";
|
|
35
|
+
import type { JxDocumentValue } from "@jxsuite/schema/types";
|
|
35
36
|
import type { Tab } from "../tabs/tab";
|
|
36
37
|
import type { JsonValue } from "../types";
|
|
37
38
|
|
|
39
|
+
/**
|
|
40
|
+
* An entry's fields, whichever record holds them: a frontmatter block's keys, or a JSON entry's own
|
|
41
|
+
* document keys. `undefined` is a key an editor has cleared.
|
|
42
|
+
*/
|
|
43
|
+
export type EntryFields = Record<string, JxDocumentValue | undefined>;
|
|
44
|
+
|
|
38
45
|
/**
|
|
39
46
|
* Whether this tab's entry fields are the document itself rather than a frontmatter block.
|
|
40
47
|
*
|
|
@@ -56,10 +63,8 @@ function fieldsAreDocument(tab: Tab): boolean {
|
|
|
56
63
|
* reactive tab, and a copy would break that. It is also the identity a caller can compare against
|
|
57
64
|
* `tab.doc.document` to see which store answered.
|
|
58
65
|
*/
|
|
59
|
-
export function entryFields(tab: Tab):
|
|
60
|
-
return fieldsAreDocument(tab)
|
|
61
|
-
? (tab.doc.document as unknown as Record<string, unknown>)
|
|
62
|
-
: (tab.doc.content?.frontmatter ?? {});
|
|
66
|
+
export function entryFields(tab: Tab): EntryFields {
|
|
67
|
+
return fieldsAreDocument(tab) ? tab.doc.document : tab.doc.content.frontmatter;
|
|
63
68
|
}
|
|
64
69
|
|
|
65
70
|
/**
|
|
@@ -72,7 +77,7 @@ export function entryFields(tab: Tab): Record<string, unknown> {
|
|
|
72
77
|
* is already the "not surgically patchable, fall back" signal `transactDoc` reads.
|
|
73
78
|
*/
|
|
74
79
|
function mutateDocumentField(tab: Tab, field: string, value?: JsonValue): void {
|
|
75
|
-
const doc = tab.doc.document
|
|
80
|
+
const doc = tab.doc.document;
|
|
76
81
|
const before = Object.hasOwn(doc, field) ? cloneValue(doc[field]) : undefined;
|
|
77
82
|
const deletes = value === undefined || value === null || value === "";
|
|
78
83
|
if (deletes) {
|
|
@@ -113,10 +118,10 @@ export function mutateEntryField(tab: Tab, field: string, value?: JsonValue): vo
|
|
|
113
118
|
* `renderForm` emits single-key patches today, but committing per key would put a multi-key patch
|
|
114
119
|
* on the undo stack as several steps — and an author who changed one thing expects one ⌘Z.
|
|
115
120
|
*/
|
|
116
|
-
export function commitEntryFields(tab: Tab, patch: Record<string,
|
|
121
|
+
export function commitEntryFields(tab: Tab, patch: Record<string, JsonValue | undefined>): void {
|
|
117
122
|
transactDoc(tab, (t) => {
|
|
118
123
|
for (const [field, value] of Object.entries(patch)) {
|
|
119
|
-
mutateEntryField(t, field, value
|
|
124
|
+
mutateEntryField(t, field, value);
|
|
120
125
|
}
|
|
121
126
|
});
|
|
122
127
|
}
|