@jxsuite/studio 6.1.0 → 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-f2gkpy8d.js +4 -0
- 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-gybvv7a6.js → index-zpjmzqfk.js} +3 -3
- package/dist/chunks/{javascript-rnvdp3k4.js → javascript-m54mnwp6.js} +3 -3
- package/dist/chunks/jsonMode-w15cmrcm.js +13 -0
- 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-5g0ag7c0.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-pxg4ap1e.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-qbj760tx.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-anyrgzvb.js → studio-90pq9km1.js} +4 -4
- package/dist/chunks/studio-924p1tm1.js +6 -0
- package/dist/chunks/{studio-v2bvmbjj.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-txjjzrsm.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-0x3jyb8r.js → studio-tq0rtfwj.js} +4 -4
- package/dist/chunks/{studio-cpxkgjrj.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-y64hrt8p.js +12 -0
- 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-sf49ee9x.js +14 -0
- 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 +98 -98
- package/dist/workers/ts.worker.js +3 -3
- package/package.json +11 -11
- 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 +66 -42
- package/src/canvas/canvas-surface.ts +5 -3
- package/src/canvas/canvas-utils.ts +163 -64
- 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 +203 -118
- package/src/canvas/iframe-inline-edit.ts +69 -32
- package/src/canvas/iframe-insert.ts +5 -4
- package/src/canvas/iframe-interaction.ts +37 -26
- 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 +15 -16
- package/src/canvas/iframe-render.ts +41 -36
- 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/defaults.ts +4 -1
- package/src/commands/keymap.ts +47 -43
- package/src/commands/levels.ts +3 -3
- package/src/commands/live-context.ts +10 -8
- 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 +87 -47
- 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 +6 -1
- 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 +55 -22
- 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 +254 -216
- 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 +174 -127
- 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 +39 -77
- 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 +25 -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.json +126 -73
- package/src/surfaces/rail.ts +38 -12
- 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/tabs/typing.ts +31 -0
- 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 +103 -74
- 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 +47 -36
- package/dist/chunks/2020-nkxms0ay.js +0 -4
- package/dist/chunks/adapter-m948ab5f.js +0 -4
- package/dist/chunks/cf-account-picker-n8hr38v7.js +0 -4
- package/dist/chunks/cf-settings-356xdtne.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-yk3t844e.js +0 -4
- package/dist/chunks/content-source-bawmyc09.js +0 -4
- package/dist/chunks/convert-to-repeater-7wns8kf1.js +0 -4
- package/dist/chunks/dialog-mtm9fq5t.js +0 -4
- package/dist/chunks/editor-6sc8nacq.js +0 -4
- package/dist/chunks/entry-commands-8ay9fh81.js +0 -4
- package/dist/chunks/extension-sections-na7rj3nr.js +0 -4
- package/dist/chunks/file-ops-gye0qw56.js +0 -4
- package/dist/chunks/files-dmc2xvcq.js +0 -4
- package/dist/chunks/format-host-t76b53f8.js +0 -4
- package/dist/chunks/fs-events-cg4tpz06.js +0 -4
- package/dist/chunks/git-panel-yef7bshy.js +0 -4
- package/dist/chunks/grid-view-7tt4bxw1.js +0 -51
- package/dist/chunks/icons-qbh8akb1.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-tmz30gfp.js +0 -4
- package/dist/chunks/index-nag78a9h.js +0 -4
- package/dist/chunks/jsonMode-zhwsprqk.js +0 -13
- package/dist/chunks/jx-validate-3gbp5nkn.js +0 -4
- package/dist/chunks/layers-fvz99859.js +0 -4
- package/dist/chunks/layers-panel-gchmbf9p.js +0 -4
- package/dist/chunks/listbox-s8fkmnq8.js +0 -4
- package/dist/chunks/lit-html-9agdspkt.js +0 -4
- package/dist/chunks/media-picker-rhjvyy00.js +0 -4
- package/dist/chunks/menu-2e4y9j7b.js +0 -4
- package/dist/chunks/menu-37d07z9m.js +0 -4
- package/dist/chunks/monaco-binding-2jnhjjvr.js +0 -4
- package/dist/chunks/monaco-buffer-rp21359g.js +0 -4
- package/dist/chunks/monaco-setup-vhh7gayr.js +0 -4
- package/dist/chunks/notify-h3www560.js +0 -4
- package/dist/chunks/number-field-gw7sq8rn.js +0 -4
- package/dist/chunks/parse-897fvqah.js +0 -4
- package/dist/chunks/platform-hz34wcd7.js +0 -4
- package/dist/chunks/popover-8htra4er.js +0 -4
- package/dist/chunks/publish-panel-exsmjzyj.js +0 -4
- package/dist/chunks/quick-search-pgaqeh0m.js +0 -4
- package/dist/chunks/references-2cgdxnb8.js +0 -4
- package/dist/chunks/right-panel-jf856w5w.js +0 -4
- package/dist/chunks/section-registry-jnf8r5gy.js +0 -4
- package/dist/chunks/select-n3v7gwas.js +0 -4
- package/dist/chunks/split-pff8f3ze.js +0 -4
- package/dist/chunks/studio-0f55h9ye.js +0 -5
- package/dist/chunks/studio-0sqdhnew.js +0 -12
- package/dist/chunks/studio-19x1c75w.js +0 -5
- package/dist/chunks/studio-2sqcndak.js +0 -5
- package/dist/chunks/studio-3aey7dd3.js +0 -5
- package/dist/chunks/studio-3bpdkq2s.js +0 -5
- package/dist/chunks/studio-47y6fbpf.js +0 -5
- package/dist/chunks/studio-4m3826v2.js +0 -5
- package/dist/chunks/studio-4nx2dj1g.js +0 -4
- package/dist/chunks/studio-4xv5s47r.js +0 -9
- package/dist/chunks/studio-5g4t8v6w.js +0 -5
- package/dist/chunks/studio-5py436sf.js +0 -5
- package/dist/chunks/studio-77kt594t.js +0 -5
- package/dist/chunks/studio-8f87n763.js +0 -10
- package/dist/chunks/studio-8mb00b84.js +0 -5
- package/dist/chunks/studio-8p51gq2h.js +0 -6
- package/dist/chunks/studio-954ds834.js +0 -5
- package/dist/chunks/studio-9ft45c83.js +0 -9
- package/dist/chunks/studio-a2138x5k.js +0 -7
- package/dist/chunks/studio-a9yzstqj.js +0 -5
- package/dist/chunks/studio-acdksxx6.js +0 -5
- package/dist/chunks/studio-ar8jcf2y.js +0 -5
- package/dist/chunks/studio-bmn4mn9j.js +0 -7
- package/dist/chunks/studio-e7xxa0sj.js +0 -5
- package/dist/chunks/studio-ecaz25vk.js +0 -5
- package/dist/chunks/studio-ery42sqr.js +0 -4
- package/dist/chunks/studio-fzdywr6p.js +0 -9
- package/dist/chunks/studio-g5fmf0c1.js +0 -5
- package/dist/chunks/studio-g7nse7zb.js +0 -5
- package/dist/chunks/studio-geq1ea6k.js +0 -14
- package/dist/chunks/studio-ghkb32r8.js +0 -5
- package/dist/chunks/studio-ghrhy2y7.js +0 -5
- package/dist/chunks/studio-grawhey1.js +0 -5
- package/dist/chunks/studio-h0xgswew.js +0 -5
- package/dist/chunks/studio-h9c4p2tx.js +0 -5
- package/dist/chunks/studio-jyzj5cxs.js +0 -5
- package/dist/chunks/studio-mgx8yhnz.js +0 -64
- package/dist/chunks/studio-mpb04y1d.js +0 -6
- package/dist/chunks/studio-n17mty64.js +0 -5
- package/dist/chunks/studio-nwh2eqsk.js +0 -6
- package/dist/chunks/studio-q1h883bt.js +0 -16
- package/dist/chunks/studio-q4tv82h7.js +0 -9
- package/dist/chunks/studio-qpqa7vk3.js +0 -5
- package/dist/chunks/studio-qqz8e5gk.js +0 -5
- package/dist/chunks/studio-qvasen3f.js +0 -5
- package/dist/chunks/studio-rggdb3hm.js +0 -5
- package/dist/chunks/studio-sghy936h.js +0 -4
- package/dist/chunks/studio-skprc6ef.js +0 -5
- package/dist/chunks/studio-tt2nactf.js +0 -5
- package/dist/chunks/studio-tyasmc39.js +0 -5
- package/dist/chunks/studio-vk9ezads.js +0 -5
- package/dist/chunks/studio-vzacdfsc.js +0 -4
- package/dist/chunks/studio-w4c0xmrw.js +0 -5
- package/dist/chunks/studio-wfjqhhbk.js +0 -5
- package/dist/chunks/studio-wgh5kxpj.js +0 -5
- package/dist/chunks/studio-xasj0796.js +0 -5
- package/dist/chunks/studio-y78s8r2n.js +0 -5
- package/dist/chunks/studio-z8w183sh.js +0 -5
- package/dist/chunks/studio-zscd9ty4.js +0 -928
- package/dist/chunks/studio-zxp13sss.js +0 -7
- package/dist/chunks/studio-zygnmm01.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/tsMode-gr0m4dzr.js +0 -14
- package/dist/chunks/workspace-m15qtcqp.js +0 -4
- package/dist/chunks/ws-client-nf61frr1.js +0 -4
|
@@ -27,26 +27,55 @@
|
|
|
27
27
|
* this — an id outside a declared set — and one refusal shape is easier to catch than two.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
import { isBoolean, isNonNullObject, isNumber, isString } from "@jxsuite/schema/guards";
|
|
31
|
+
import type { JsonValue } from "@jxsuite/schema/types";
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* One received argument: a JSON value, or `undefined` for a key a caller left out. Every surface
|
|
35
|
+
* that sends arguments speaks JSON (a palette prompt, a manifest step, an AI tool call), and an
|
|
36
|
+
* explicit `undefined` is how a programmatic caller spells "absent" — JSON cannot carry one.
|
|
37
|
+
*/
|
|
38
|
+
export type CommandArgValue = JsonValue | undefined;
|
|
39
|
+
|
|
30
40
|
/** Arguments as they arrive from a palette prompt, a manifest step or an AI tool call. */
|
|
31
|
-
export type CommandArgValues = Record<string,
|
|
41
|
+
export type CommandArgValues = Record<string, CommandArgValue>;
|
|
32
42
|
|
|
33
43
|
/** `command "<id>" argument "<key>": <problem>` — the one sentence shape every failure here uses. */
|
|
34
44
|
function refuse(commandId: string, key: string, problem: string): RangeError {
|
|
35
45
|
return new RangeError(`command "${commandId}" argument "${key}": ${problem}`);
|
|
36
46
|
}
|
|
37
47
|
|
|
48
|
+
/**
|
|
49
|
+
* The `typeof` word for a non-string JSON value, as every refusal sentence has always printed it:
|
|
50
|
+
* `null`, arrays and objects are all `object` to `typeof`, so they are all `object` here.
|
|
51
|
+
*/
|
|
52
|
+
function typeWordOf(value: JsonValue): string {
|
|
53
|
+
if (isNumber(value)) {
|
|
54
|
+
return "number";
|
|
55
|
+
}
|
|
56
|
+
if (isBoolean(value)) {
|
|
57
|
+
return "boolean";
|
|
58
|
+
}
|
|
59
|
+
return isString(value) ? "string" : "object";
|
|
60
|
+
}
|
|
61
|
+
|
|
38
62
|
/** How a received value is quoted back to the caller. Strings keep their quotes; nothing is elided. */
|
|
39
|
-
function describe(value:
|
|
63
|
+
function describe(value: CommandArgValue): string {
|
|
40
64
|
if (value === undefined) {
|
|
41
65
|
return "missing";
|
|
42
66
|
}
|
|
43
|
-
return
|
|
67
|
+
return isString(value) ? `"${value}"` : `${typeWordOf(value)} ${JSON.stringify(value)}`;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Whether a value is a `JxPath`: an array whose every segment is a string key or a numeric index. */
|
|
71
|
+
function isPathSegments(value: CommandArgValue): value is (string | number)[] {
|
|
72
|
+
return Array.isArray(value) && value.every((segment) => isString(segment) || isNumber(segment));
|
|
44
73
|
}
|
|
45
74
|
|
|
46
75
|
/** A required string argument. */
|
|
47
76
|
export function stringArg(commandId: string, args: CommandArgValues, key: string): string {
|
|
48
77
|
const value = args[key];
|
|
49
|
-
if (
|
|
78
|
+
if (!isString(value) || value === "") {
|
|
50
79
|
throw refuse(commandId, key, `expected a non-empty string, got ${describe(value)}`);
|
|
51
80
|
}
|
|
52
81
|
return value;
|
|
@@ -67,7 +96,7 @@ export function optionalStringArg(
|
|
|
67
96
|
/** A required finite number argument. `NaN` and `Infinity` are refusals, not values. */
|
|
68
97
|
export function numberArg(commandId: string, args: CommandArgValues, key: string): number {
|
|
69
98
|
const value = args[key];
|
|
70
|
-
if (
|
|
99
|
+
if (!isNumber(value) || !Number.isFinite(value)) {
|
|
71
100
|
throw refuse(commandId, key, `expected a finite number, got ${describe(value)}`);
|
|
72
101
|
}
|
|
73
102
|
return value;
|
|
@@ -84,7 +113,7 @@ export function numberArg(commandId: string, args: CommandArgValues, key: string
|
|
|
84
113
|
*/
|
|
85
114
|
export function integerArg(commandId: string, args: CommandArgValues, key: string): number {
|
|
86
115
|
const value = args[key];
|
|
87
|
-
if (
|
|
116
|
+
if (!isNumber(value) || !Number.isInteger(value)) {
|
|
88
117
|
throw refuse(commandId, key, `expected an integer, got ${describe(value)}`);
|
|
89
118
|
}
|
|
90
119
|
return value;
|
|
@@ -116,7 +145,7 @@ export function boundedNumberArg(
|
|
|
116
145
|
/** A required boolean argument. A setter's whole point is that `false` is a value, so no default. */
|
|
117
146
|
export function booleanArg(commandId: string, args: CommandArgValues, key: string): boolean {
|
|
118
147
|
const value = args[key];
|
|
119
|
-
if (
|
|
148
|
+
if (!isBoolean(value)) {
|
|
120
149
|
throw refuse(commandId, key, `expected a boolean, got ${describe(value)}`);
|
|
121
150
|
}
|
|
122
151
|
return value;
|
|
@@ -136,7 +165,9 @@ export function enumArg<T extends string>(
|
|
|
136
165
|
declared: readonly T[],
|
|
137
166
|
): T {
|
|
138
167
|
const value = args[key];
|
|
139
|
-
|
|
168
|
+
// `find` hands back the DECLARED entry, typed `T`, which is the same string the caller sent.
|
|
169
|
+
const match = isString(value) ? declared.find((entry) => entry === value) : undefined;
|
|
170
|
+
if (match === undefined) {
|
|
140
171
|
// `none` for an empty set: a derived enum (`derivedEnumProperty`) is honestly empty before the
|
|
141
172
|
// Project supplies its values, and "declared: " with nothing after it reads as a truncation.
|
|
142
173
|
throw refuse(
|
|
@@ -145,7 +176,7 @@ export function enumArg<T extends string>(
|
|
|
145
176
|
`${describe(value)} is not declared — declared: ${declared.join(", ") || "none"}`,
|
|
146
177
|
);
|
|
147
178
|
}
|
|
148
|
-
return
|
|
179
|
+
return match;
|
|
149
180
|
}
|
|
150
181
|
|
|
151
182
|
/**
|
|
@@ -160,17 +191,14 @@ export function pathArg(
|
|
|
160
191
|
key: string,
|
|
161
192
|
): (string | number)[] {
|
|
162
193
|
const value = args[key];
|
|
163
|
-
if (
|
|
164
|
-
!Array.isArray(value) ||
|
|
165
|
-
!value.every((s) => typeof s === "string" || typeof s === "number")
|
|
166
|
-
) {
|
|
194
|
+
if (!isPathSegments(value)) {
|
|
167
195
|
throw refuse(
|
|
168
196
|
commandId,
|
|
169
197
|
key,
|
|
170
198
|
`expected an array of path segments (strings or numbers), got ${describe(value)}`,
|
|
171
199
|
);
|
|
172
200
|
}
|
|
173
|
-
return value
|
|
201
|
+
return value;
|
|
174
202
|
}
|
|
175
203
|
|
|
176
204
|
/** A path argument that may be `null` — "select nothing" is a state a user can be in. */
|
|
@@ -203,17 +231,14 @@ export function pathListArg(
|
|
|
203
231
|
throw refuse(commandId, key, `expected an array of document paths, got ${describe(value)}`);
|
|
204
232
|
}
|
|
205
233
|
return value.map((entry, i) => {
|
|
206
|
-
if (
|
|
207
|
-
!Array.isArray(entry) ||
|
|
208
|
-
!entry.every((s) => typeof s === "string" || typeof s === "number")
|
|
209
|
-
) {
|
|
234
|
+
if (!isPathSegments(entry)) {
|
|
210
235
|
throw refuse(
|
|
211
236
|
commandId,
|
|
212
237
|
key,
|
|
213
238
|
`entry ${i} is not a document path — expected an array of segments, got ${describe(entry)}`,
|
|
214
239
|
);
|
|
215
240
|
}
|
|
216
|
-
return entry
|
|
241
|
+
return entry;
|
|
217
242
|
});
|
|
218
243
|
}
|
|
219
244
|
|
|
@@ -224,11 +249,39 @@ export function pathListArg(
|
|
|
224
249
|
// Them ONE call site, so a schema that disagrees with its coercion is now a refusal rather than a
|
|
225
250
|
// Defect a reviewer has to spot — which is what this module exists to prevent.
|
|
226
251
|
|
|
252
|
+
/**
|
|
253
|
+
* The JSON Schema keywords a command property uses — what the builders below write and what
|
|
254
|
+
* {@link coerceArgs} reads. Read loosely: a keyword with no reader (`description`, `default`) is
|
|
255
|
+
* carried for the palette and the AI tool, and never consulted by the coercion.
|
|
256
|
+
*/
|
|
257
|
+
export interface PropertySchema {
|
|
258
|
+
description?: string;
|
|
259
|
+
title?: string;
|
|
260
|
+
default?: JsonValue;
|
|
261
|
+
type?: string | readonly string[];
|
|
262
|
+
/** Strings only: the `enum` row is {@link enumArg}, which admits nothing but a declared string. */
|
|
263
|
+
enum?: readonly string[];
|
|
264
|
+
const?: JsonValue;
|
|
265
|
+
oneOf?: readonly PropertySchema[];
|
|
266
|
+
items?: PropertySchema;
|
|
267
|
+
minimum?: number;
|
|
268
|
+
maximum?: number;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
/** The object schema {@link argsSchema} writes, as {@link coerceArgs} reads it. */
|
|
272
|
+
export interface CommandArgsSchema {
|
|
273
|
+
additionalProperties?: boolean;
|
|
274
|
+
properties?: Record<string, PropertySchema>;
|
|
275
|
+
required?: readonly string[];
|
|
276
|
+
/** Always `"object"` as {@link argsSchema} writes it; the coercion never reads it. */
|
|
277
|
+
type?: string;
|
|
278
|
+
}
|
|
279
|
+
|
|
227
280
|
/** `{ type: "object", properties, required, additionalProperties: false }` in one call. */
|
|
228
281
|
export function argsSchema(
|
|
229
|
-
properties: Record<string,
|
|
282
|
+
properties: Record<string, PropertySchema>,
|
|
230
283
|
required: readonly string[] = Object.keys(properties),
|
|
231
|
-
):
|
|
284
|
+
): CommandArgsSchema {
|
|
232
285
|
return {
|
|
233
286
|
additionalProperties: false,
|
|
234
287
|
properties,
|
|
@@ -238,7 +291,7 @@ export function argsSchema(
|
|
|
238
291
|
}
|
|
239
292
|
|
|
240
293
|
/** A string property constrained to a declared set, with the human sentence the palette shows. */
|
|
241
|
-
export function enumProperty(declared: readonly string[], description: string):
|
|
294
|
+
export function enumProperty(declared: readonly string[], description: string): PropertySchema {
|
|
242
295
|
return { description, enum: [...declared], type: "string" };
|
|
243
296
|
}
|
|
244
297
|
|
|
@@ -261,7 +314,7 @@ export function enumProperty(declared: readonly string[], description: string):
|
|
|
261
314
|
export function derivedEnumProperty(
|
|
262
315
|
declared: () => readonly string[],
|
|
263
316
|
description: string,
|
|
264
|
-
):
|
|
317
|
+
): PropertySchema {
|
|
265
318
|
return {
|
|
266
319
|
description,
|
|
267
320
|
get enum() {
|
|
@@ -275,17 +328,17 @@ export function derivedEnumProperty(
|
|
|
275
328
|
export function numberProperty(
|
|
276
329
|
description: string,
|
|
277
330
|
bounds: { minimum?: number; maximum?: number } = {},
|
|
278
|
-
):
|
|
331
|
+
): PropertySchema {
|
|
279
332
|
return { description, type: "number", ...bounds };
|
|
280
333
|
}
|
|
281
334
|
|
|
282
335
|
/** A boolean property. Named `open`/`enabled`/… by the caller; the description carries the sense. */
|
|
283
|
-
export function booleanProperty(description: string):
|
|
336
|
+
export function booleanProperty(description: string): PropertySchema {
|
|
284
337
|
return { description, type: "boolean" };
|
|
285
338
|
}
|
|
286
339
|
|
|
287
340
|
/** A `JxPath` property — an array of string keys and numeric indexes. */
|
|
288
|
-
export function pathProperty(description: string, nullable = false):
|
|
341
|
+
export function pathProperty(description: string, nullable = false): PropertySchema {
|
|
289
342
|
const path = {
|
|
290
343
|
items: { type: ["string", "number"] },
|
|
291
344
|
type: "array",
|
|
@@ -294,7 +347,7 @@ export function pathProperty(description: string, nullable = false): object {
|
|
|
294
347
|
}
|
|
295
348
|
|
|
296
349
|
/** A property holding a LIST of `JxPath`s — an array of arrays of segments. */
|
|
297
|
-
export function pathListProperty(description: string):
|
|
350
|
+
export function pathListProperty(description: string): PropertySchema {
|
|
298
351
|
return {
|
|
299
352
|
description,
|
|
300
353
|
items: { items: { type: ["string", "number"] }, type: "array" },
|
|
@@ -303,7 +356,7 @@ export function pathListProperty(description: string): object {
|
|
|
303
356
|
}
|
|
304
357
|
|
|
305
358
|
/** A free-form string property. */
|
|
306
|
-
export function stringProperty(description: string):
|
|
359
|
+
export function stringProperty(description: string): PropertySchema {
|
|
307
360
|
return { description, type: "string" };
|
|
308
361
|
}
|
|
309
362
|
|
|
@@ -314,24 +367,6 @@ export function stringProperty(description: string): object {
|
|
|
314
367
|
// Validator that agrees with them today. What the schema cannot say (a breakpoint the document
|
|
315
368
|
// Defines, a path that addresses a node) stays in `run`; the schema owns the shape.
|
|
316
369
|
|
|
317
|
-
/** The JSON Schema keywords a command property uses. Read loosely; unknown keywords are ignored. */
|
|
318
|
-
interface PropertySchema {
|
|
319
|
-
type?: string | readonly string[];
|
|
320
|
-
enum?: readonly unknown[];
|
|
321
|
-
const?: unknown;
|
|
322
|
-
oneOf?: readonly PropertySchema[];
|
|
323
|
-
items?: PropertySchema;
|
|
324
|
-
minimum?: number;
|
|
325
|
-
maximum?: number;
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
/** The object schema `argsSchema` writes, as {@link coerceArgs} reads it. */
|
|
329
|
-
interface ArgsSchemaShape {
|
|
330
|
-
properties?: Record<string, PropertySchema>;
|
|
331
|
-
required?: readonly string[];
|
|
332
|
-
additionalProperties?: boolean;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
370
|
/**
|
|
336
371
|
* The rows of {@link coerceArgs}'s dispatch table, by name.
|
|
337
372
|
*
|
|
@@ -361,7 +396,7 @@ function isPathSegmentTypes(types: readonly string[]): boolean {
|
|
|
361
396
|
|
|
362
397
|
/** A single JSON type name, or the list form `["number", "null"]`, as a list. */
|
|
363
398
|
function typesOf(type: string | readonly string[]): readonly string[] {
|
|
364
|
-
return
|
|
399
|
+
return isString(type) ? [type] : type;
|
|
365
400
|
}
|
|
366
401
|
|
|
367
402
|
/**
|
|
@@ -371,8 +406,8 @@ function typesOf(type: string | readonly string[]): readonly string[] {
|
|
|
371
406
|
* getter, and this function only classifies. The getter is read by the `enum` row when the value is
|
|
372
407
|
* coerced, which is what makes the list live at that moment rather than at classification.
|
|
373
408
|
*/
|
|
374
|
-
export function
|
|
375
|
-
const p = property
|
|
409
|
+
export function coercionRowOf(property: PropertySchema): CoercionRow {
|
|
410
|
+
const p = property;
|
|
376
411
|
if ("enum" in p) {
|
|
377
412
|
return "enum";
|
|
378
413
|
}
|
|
@@ -427,28 +462,28 @@ export function describeShape(property: object): CoercionRow {
|
|
|
427
462
|
}
|
|
428
463
|
|
|
429
464
|
/** Whether a value is of one JSON type. `number` means FINITE, as {@link numberArg} already insists. */
|
|
430
|
-
function isJsonType(type: string, value:
|
|
465
|
+
function isJsonType(type: string, value: CommandArgValue): boolean {
|
|
431
466
|
switch (type) {
|
|
432
467
|
case "null": {
|
|
433
468
|
return value === null;
|
|
434
469
|
}
|
|
435
470
|
case "boolean": {
|
|
436
|
-
return
|
|
471
|
+
return isBoolean(value);
|
|
437
472
|
}
|
|
438
473
|
case "string": {
|
|
439
|
-
return
|
|
474
|
+
return isString(value);
|
|
440
475
|
}
|
|
441
476
|
case "number": {
|
|
442
|
-
return
|
|
477
|
+
return isNumber(value) && Number.isFinite(value);
|
|
443
478
|
}
|
|
444
479
|
case "integer": {
|
|
445
|
-
return
|
|
480
|
+
return isNumber(value) && Number.isInteger(value);
|
|
446
481
|
}
|
|
447
482
|
case "array": {
|
|
448
483
|
return Array.isArray(value);
|
|
449
484
|
}
|
|
450
485
|
case "object": {
|
|
451
|
-
return
|
|
486
|
+
return isNonNullObject(value) && !Array.isArray(value);
|
|
452
487
|
}
|
|
453
488
|
default: {
|
|
454
489
|
break;
|
|
@@ -478,17 +513,18 @@ export function typedArg(
|
|
|
478
513
|
args: CommandArgValues,
|
|
479
514
|
key: string,
|
|
480
515
|
types: readonly string[],
|
|
481
|
-
):
|
|
516
|
+
): JsonValue {
|
|
482
517
|
const value = args[key];
|
|
483
|
-
|
|
518
|
+
// `undefined` is admitted by no JSON type, so the first test only states what the second proves.
|
|
519
|
+
if (value === undefined || !types.some((type) => isJsonType(type, value))) {
|
|
484
520
|
throw refuse(commandId, key, `expected ${listTypes(types)}, got ${describe(value)}`);
|
|
485
521
|
}
|
|
486
522
|
return value;
|
|
487
523
|
}
|
|
488
524
|
|
|
489
525
|
/** One line per row, for the sentence a `oneOf` refusal prints when no branch admits the value. */
|
|
490
|
-
function
|
|
491
|
-
switch (
|
|
526
|
+
function expectedValueText(property: PropertySchema): string {
|
|
527
|
+
switch (coercionRowOf(property)) {
|
|
492
528
|
case "enum": {
|
|
493
529
|
return `one of ${(property.enum ?? []).map((v) => describe(v)).join(" | ")}`;
|
|
494
530
|
}
|
|
@@ -496,7 +532,7 @@ function shapeOf(property: PropertySchema): string {
|
|
|
496
532
|
return `the constant ${describe(property.const)}`;
|
|
497
533
|
}
|
|
498
534
|
case "one-of": {
|
|
499
|
-
return (property.oneOf ?? []).map((branch) =>
|
|
535
|
+
return (property.oneOf ?? []).map((branch) => expectedValueText(branch)).join(" or ");
|
|
500
536
|
}
|
|
501
537
|
case "typed": {
|
|
502
538
|
return listTypes(typesOf(property.type ?? []));
|
|
@@ -545,7 +581,7 @@ function oneOfArg(
|
|
|
545
581
|
args: CommandArgValues,
|
|
546
582
|
key: string,
|
|
547
583
|
branches: readonly PropertySchema[],
|
|
548
|
-
):
|
|
584
|
+
): CommandArgValue {
|
|
549
585
|
const value = args[key];
|
|
550
586
|
const refusals: unknown[] = [];
|
|
551
587
|
for (const branch of branches) {
|
|
@@ -567,7 +603,7 @@ function oneOfArg(
|
|
|
567
603
|
throw refuse(
|
|
568
604
|
commandId,
|
|
569
605
|
key,
|
|
570
|
-
`expected ${branches.map((branch) =>
|
|
606
|
+
`expected ${branches.map((branch) => expectedValueText(branch)).join(" or ")}, got ${describe(value)}`,
|
|
571
607
|
);
|
|
572
608
|
}
|
|
573
609
|
|
|
@@ -577,11 +613,11 @@ function coerceProperty(
|
|
|
577
613
|
args: CommandArgValues,
|
|
578
614
|
key: string,
|
|
579
615
|
property: PropertySchema,
|
|
580
|
-
):
|
|
581
|
-
switch (
|
|
616
|
+
): CommandArgValue {
|
|
617
|
+
switch (coercionRowOf(property)) {
|
|
582
618
|
case "enum": {
|
|
583
619
|
// The read of `property.enum` is HERE — a derived list is resolved at coercion time.
|
|
584
|
-
return enumArg(commandId, args, key,
|
|
620
|
+
return enumArg(commandId, args, key, property.enum ?? []);
|
|
585
621
|
}
|
|
586
622
|
case "const": {
|
|
587
623
|
const value = args[key];
|
|
@@ -652,12 +688,8 @@ function coerceProperty(
|
|
|
652
688
|
* `run` body keeps its own `stringArg(...)` lines as typed readers and can never disagree with this
|
|
653
689
|
* pass, because they are the same functions reading the same values.
|
|
654
690
|
*/
|
|
655
|
-
export function coerceArgs(
|
|
656
|
-
|
|
657
|
-
schema: object,
|
|
658
|
-
args: CommandArgValues,
|
|
659
|
-
): CommandArgValues {
|
|
660
|
-
const spec = schema as ArgsSchemaShape;
|
|
691
|
+
export function coerceArgs(commandId: string, schema: CommandArgsSchema, args: CommandArgValues) {
|
|
692
|
+
const spec = schema;
|
|
661
693
|
const properties = spec.properties ?? {};
|
|
662
694
|
const declared = Object.keys(properties);
|
|
663
695
|
const required = spec.required ?? [];
|
package/src/commands/context.ts
CHANGED
|
@@ -81,28 +81,28 @@ export type CanvasView = "edit" | "design" | "preview";
|
|
|
81
81
|
*/
|
|
82
82
|
|
|
83
83
|
/** The `canvasMode` strings, mapped onto the editor each one actually names. */
|
|
84
|
-
const EDITOR_KIND_BY_MODE
|
|
85
|
-
design
|
|
86
|
-
edit
|
|
84
|
+
const EDITOR_KIND_BY_MODE = new Map<string, EditorKind>([
|
|
85
|
+
["design", "canvas"],
|
|
86
|
+
["edit", "canvas"],
|
|
87
87
|
/* The Entry editor — `content/entry-editor.ts`'s ENTRY_MODE. A form over ONE content entry's
|
|
88
88
|
frontmatter, typed by its collection's schema; the same document the canvas edits the body of,
|
|
89
89
|
which is why it is a mode of that tab rather than a tab of its own. */
|
|
90
|
-
entry
|
|
91
|
-
"git-diff"
|
|
92
|
-
grid
|
|
93
|
-
manage
|
|
90
|
+
["entry", "entry"],
|
|
91
|
+
["git-diff", "diff"],
|
|
92
|
+
["grid", "grid"],
|
|
93
|
+
["manage", "library"],
|
|
94
94
|
/* The Media viewer — `media/media-pane.ts`. An image, a video, a font specimen: files the studio
|
|
95
95
|
can SHOW but has no document model for, which is why clicking one used to end in "No format
|
|
96
96
|
class imported for …", advice that means nothing about a PNG. */
|
|
97
|
-
media
|
|
98
|
-
preview
|
|
97
|
+
["media", "media"],
|
|
98
|
+
["preview", "canvas"],
|
|
99
99
|
/* Project Settings — `settings/settings-document.ts`'s SETTINGS_MODE. A form over `project.json`,
|
|
100
100
|
which is a configuration object and not a document tree; `stylebook` (Project Styles) is the
|
|
101
101
|
second editor over that same document and answers `config` for the same reason. */
|
|
102
|
-
settings
|
|
103
|
-
source
|
|
104
|
-
stylebook
|
|
105
|
-
|
|
102
|
+
["settings", "config"],
|
|
103
|
+
["source", "code"],
|
|
104
|
+
["stylebook", "config"],
|
|
105
|
+
]);
|
|
106
106
|
|
|
107
107
|
/**
|
|
108
108
|
* The editor kind a mode string names.
|
|
@@ -131,15 +131,15 @@ export const EDITOR_KIND_LABELS: Readonly<Record<EditorKind, string>> = {
|
|
|
131
131
|
};
|
|
132
132
|
|
|
133
133
|
export function editorKindForMode(mode: string): EditorKind {
|
|
134
|
-
return EDITOR_KIND_BY_MODE
|
|
134
|
+
return EDITOR_KIND_BY_MODE.get(mode) ?? "canvas";
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
/** Only the three canvas modes carry a view. */
|
|
138
|
-
const CANVAS_VIEW_BY_MODE
|
|
139
|
-
design
|
|
140
|
-
edit
|
|
141
|
-
preview
|
|
142
|
-
|
|
138
|
+
const CANVAS_VIEW_BY_MODE = new Map<string, CanvasView>([
|
|
139
|
+
["design", "design"],
|
|
140
|
+
["edit", "edit"],
|
|
141
|
+
["preview", "preview"],
|
|
142
|
+
]);
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
145
|
* The Canvas view a mode names — the neutral "design" for a mode that has none.
|
|
@@ -147,7 +147,7 @@ const CANVAS_VIEW_BY_MODE: Readonly<Record<string, CanvasView>> = {
|
|
|
147
147
|
* Meaningful only where {@link editorKindForMode} answers `"canvas"`; every reader pairs the two.
|
|
148
148
|
*/
|
|
149
149
|
export function canvasViewForMode(mode: string): CanvasView {
|
|
150
|
-
return CANVAS_VIEW_BY_MODE
|
|
150
|
+
return CANVAS_VIEW_BY_MODE.get(mode) ?? "design";
|
|
151
151
|
}
|
|
152
152
|
|
|
153
153
|
/** Facts a command may be gated on. Every field is a plain value; predicates read, never write. */
|
|
@@ -332,6 +332,8 @@ export function emptyContext(): CommandContext {
|
|
|
332
332
|
*/
|
|
333
333
|
export function makeContext(patch: CommandContextPatch = {}): CommandContext {
|
|
334
334
|
const base = emptyContext();
|
|
335
|
+
/* SAFETY: a `CommandContextPatch` is a mapped type over `keyof CommandContext`, so every own key
|
|
336
|
+
it carries is a context group; `Object.keys` only widens those names to `string`. */
|
|
335
337
|
for (const key of Object.keys(patch) as (keyof CommandContext)[]) {
|
|
336
338
|
const group = patch[key];
|
|
337
339
|
if (group) {
|
package/src/commands/defaults.ts
CHANGED
|
@@ -236,7 +236,10 @@ export function defaultCommands(deps: CommandDeps): AnyCommand[] {
|
|
|
236
236
|
group: "1_file",
|
|
237
237
|
undo: "none",
|
|
238
238
|
when: documentOpen,
|
|
239
|
-
|
|
239
|
+
// Nothing to save is a disabled button, not a no-op one. A disabled chord is still claimed,
|
|
240
|
+
// So ⌘S on a clean document never falls through to the browser's own Save Page.
|
|
241
|
+
enablement: (ctx) => ctx.document.dirty,
|
|
242
|
+
requires: "unsaved changes",
|
|
240
243
|
run: () => deps.saveDocument(),
|
|
241
244
|
},
|
|
242
245
|
{
|
package/src/commands/keymap.ts
CHANGED
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
* colliding still throws, because that one is a bug in the app and nobody's preference.
|
|
28
28
|
*/
|
|
29
29
|
|
|
30
|
+
import { isString } from "@jxsuite/schema/guards";
|
|
30
31
|
import { KEY_SCOPES } from "./levels";
|
|
31
32
|
import type { KeyScope } from "./levels";
|
|
32
33
|
|
|
@@ -36,33 +37,33 @@ const MODIFIER_ORDER = ["mod", "ctrl", "alt", "shift"] as const;
|
|
|
36
37
|
type Modifier = (typeof MODIFIER_ORDER)[number];
|
|
37
38
|
|
|
38
39
|
/** Spellings people actually write, mapped onto the canonical four. */
|
|
39
|
-
const MODIFIER_ALIASES
|
|
40
|
-
mod
|
|
41
|
-
cmd
|
|
42
|
-
command
|
|
43
|
-
meta
|
|
44
|
-
super
|
|
45
|
-
ctrl
|
|
46
|
-
control
|
|
47
|
-
alt
|
|
48
|
-
opt
|
|
49
|
-
option
|
|
50
|
-
shift
|
|
51
|
-
|
|
40
|
+
const MODIFIER_ALIASES = new Map<string, Modifier>([
|
|
41
|
+
["mod", "mod"],
|
|
42
|
+
["cmd", "mod"],
|
|
43
|
+
["command", "mod"],
|
|
44
|
+
["meta", "mod"],
|
|
45
|
+
["super", "mod"],
|
|
46
|
+
["ctrl", "ctrl"],
|
|
47
|
+
["control", "ctrl"],
|
|
48
|
+
["alt", "alt"],
|
|
49
|
+
["opt", "alt"],
|
|
50
|
+
["option", "alt"],
|
|
51
|
+
["shift", "shift"],
|
|
52
|
+
]);
|
|
52
53
|
|
|
53
54
|
/** Key aliases — arrow/space spellings and the `KeyboardEvent.key` values that differ. */
|
|
54
|
-
const KEY_ALIASES
|
|
55
|
-
up
|
|
56
|
-
down
|
|
57
|
-
left
|
|
58
|
-
right
|
|
59
|
-
esc
|
|
60
|
-
space
|
|
61
|
-
spacebar
|
|
62
|
-
del
|
|
63
|
-
plus
|
|
64
|
-
return
|
|
65
|
-
|
|
55
|
+
const KEY_ALIASES = new Map<string, string>([
|
|
56
|
+
["up", "arrowup"],
|
|
57
|
+
["down", "arrowdown"],
|
|
58
|
+
["left", "arrowleft"],
|
|
59
|
+
["right", "arrowright"],
|
|
60
|
+
["esc", "escape"],
|
|
61
|
+
["space", " "],
|
|
62
|
+
["spacebar", " "],
|
|
63
|
+
["del", "delete"],
|
|
64
|
+
["plus", "="],
|
|
65
|
+
["return", "enter"],
|
|
66
|
+
]);
|
|
66
67
|
|
|
67
68
|
/** How each modifier prints, per platform. */
|
|
68
69
|
const MAC_GLYPHS: Readonly<Record<Modifier, string>> = {
|
|
@@ -80,18 +81,18 @@ const PC_LABELS: Readonly<Record<Modifier, string>> = {
|
|
|
80
81
|
};
|
|
81
82
|
|
|
82
83
|
/** Keys whose printed name is not just the uppercased token. */
|
|
83
|
-
const KEY_LABELS
|
|
84
|
-
arrowup
|
|
85
|
-
arrowdown
|
|
86
|
-
arrowleft
|
|
87
|
-
arrowright
|
|
88
|
-
" "
|
|
89
|
-
escape
|
|
90
|
-
enter
|
|
91
|
-
tab
|
|
92
|
-
delete
|
|
93
|
-
backspace
|
|
94
|
-
|
|
84
|
+
const KEY_LABELS = new Map<string, string>([
|
|
85
|
+
["arrowup", "↑"],
|
|
86
|
+
["arrowdown", "↓"],
|
|
87
|
+
["arrowleft", "←"],
|
|
88
|
+
["arrowright", "→"],
|
|
89
|
+
[" ", "Space"],
|
|
90
|
+
["escape", "Esc"],
|
|
91
|
+
["enter", "Enter"],
|
|
92
|
+
["tab", "Tab"],
|
|
93
|
+
["delete", "Delete"],
|
|
94
|
+
["backspace", "Backspace"],
|
|
95
|
+
]);
|
|
95
96
|
|
|
96
97
|
/**
|
|
97
98
|
* The five fields the keymap reads off a keyboard event.
|
|
@@ -159,12 +160,12 @@ export function parseChord(chord: string): ParsedChord {
|
|
|
159
160
|
// Parses the same as "Cmd+Shift+P".
|
|
160
161
|
const trimmed = token.trim();
|
|
161
162
|
const lower = trimmed === "" ? " " : trimmed.toLowerCase();
|
|
162
|
-
const modifier = MODIFIER_ALIASES
|
|
163
|
+
const modifier = MODIFIER_ALIASES.get(lower);
|
|
163
164
|
if (modifier) {
|
|
164
165
|
parsed[modifier] = true;
|
|
165
166
|
continue;
|
|
166
167
|
}
|
|
167
|
-
parsed.key = KEY_ALIASES
|
|
168
|
+
parsed.key = KEY_ALIASES.get(lower) ?? lower;
|
|
168
169
|
}
|
|
169
170
|
if (!parsed.key) {
|
|
170
171
|
throw new Error(`keybinding "${chord}" has no key — a chord needs more than modifiers`);
|
|
@@ -185,6 +186,9 @@ export function normalizeChord(chord: string): string {
|
|
|
185
186
|
|
|
186
187
|
/** Whether the current platform is a mac. `navigator` is injectable so tests never touch globals. */
|
|
187
188
|
export function isMacPlatform(
|
|
189
|
+
/* SAFETY: this module types without the DOM lib, so `globalThis` does not declare `navigator`.
|
|
190
|
+
Where a host provides one (every webview, Bun), its `platform` and `userAgent` are strings,
|
|
191
|
+
which is all `PlatformInfo` reads; where none exists the `?? {}` default answers. */
|
|
188
192
|
nav: PlatformInfo = (globalThis as { navigator?: PlatformInfo }).navigator ?? {},
|
|
189
193
|
): boolean {
|
|
190
194
|
return /mac/i.test(nav.platform ?? nav.userAgent ?? "");
|
|
@@ -209,7 +213,7 @@ export function chordFromEvent(event: KeyChordEvent, mac: boolean): string {
|
|
|
209
213
|
chord needs more than modifiers") — so every bare modifier press threw out of `resolveEvent`,
|
|
210
214
|
into the keydown listener, and onto the console. `""` is the honest answer, and
|
|
211
215
|
{@link Keymap.resolveEvent} reads it as "no chord yet". */
|
|
212
|
-
if (MODIFIER_ALIASES
|
|
216
|
+
if (MODIFIER_ALIASES.has(key)) {
|
|
213
217
|
return "";
|
|
214
218
|
}
|
|
215
219
|
const parsed: ParsedChord = {
|
|
@@ -219,7 +223,7 @@ export function chordFromEvent(event: KeyChordEvent, mac: boolean): string {
|
|
|
219
223
|
// Shift is implied by an uppercase letter but a chord table cannot rely on that: with ⇧ held
|
|
220
224
|
// `e.key` is "Z" for ⌘⇧Z and "?" for ⇧/, so the flag is the only stable signal.
|
|
221
225
|
shift: event.shiftKey,
|
|
222
|
-
key: KEY_ALIASES
|
|
226
|
+
key: KEY_ALIASES.get(key) ?? key,
|
|
223
227
|
};
|
|
224
228
|
return serializeChord(parsed);
|
|
225
229
|
}
|
|
@@ -229,7 +233,7 @@ export function formatChord(chord: string, mac: boolean): string {
|
|
|
229
233
|
const parsed = parseChord(chord);
|
|
230
234
|
const held = MODIFIER_ORDER.filter((modifier) => parsed[modifier]);
|
|
231
235
|
const key =
|
|
232
|
-
KEY_LABELS
|
|
236
|
+
KEY_LABELS.get(parsed.key) ??
|
|
233
237
|
(parsed.key.length === 1
|
|
234
238
|
? parsed.key.toUpperCase()
|
|
235
239
|
: parsed.key.charAt(0).toUpperCase() + parsed.key.slice(1));
|
|
@@ -386,7 +390,7 @@ export function createKeymap(options: { mac?: boolean } = {}): Keymap {
|
|
|
386
390
|
if (!raw) {
|
|
387
391
|
return [];
|
|
388
392
|
}
|
|
389
|
-
return (
|
|
393
|
+
return (isString(raw) ? [raw] : [...raw]).map((chord) => normalizeChord(chord));
|
|
390
394
|
}
|
|
391
395
|
|
|
392
396
|
function tableFor(scope: KeyScope): Map<string, Claim> {
|