@jxsuite/studio 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-799jpvhm.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-799jpvhm.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-8jxwts2p.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-gs6kqdt1.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-gs6kqdt1.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-esrewxap.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-v7jkjqng.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-jm0z592w.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +21080 -32585
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +7 -0
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +221 -245
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -53
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +30 -1
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +7 -1
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qr3drkkw.js +0 -531
- package/dist/chunks/extension-sections-qr3drkkw.js.map +0 -12
- package/dist/chunks/files-j8a1t06k.js +0 -50
- package/dist/chunks/files-j8a1t06k.js.map +0 -9
- package/dist/chunks/git-panel-xtq5z81x.js +0 -28
- package/dist/chunks/git-panel-xtq5z81x.js.map +0 -9
- package/dist/chunks/layers-panel-ancn2wpq.js +0 -26
- package/dist/chunks/layers-panel-ancn2wpq.js.map +0 -9
- package/dist/chunks/settings-modal-17ttr96g.js +0 -29
- package/dist/chunks/settings-modal-17ttr96g.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-0xgs7xrs.js +0 -429
- package/dist/chunks/studio-0xgs7xrs.js.map +0 -13
- package/dist/chunks/studio-4d8hzcz5.js +0 -3427
- package/dist/chunks/studio-4d8hzcz5.js.map +0 -26
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-jm0z592w.js.map +0 -115
- package/dist/chunks/studio-m2t4mdg5.js +0 -1854
- package/dist/chunks/studio-m2t4mdg5.js.map +0 -18
- package/dist/chunks/studio-n4p11dfy.js +0 -853
- package/dist/chunks/studio-n4p11dfy.js.map +0 -12
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-sjh1wt1a.js +0 -3744
- package/dist/chunks/studio-sjh1wt1a.js.map +0 -22
- package/dist/chunks/studio-v7jkjqng.js.map +0 -46
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-yfcstdzy.js +0 -399
- package/dist/chunks/studio-yfcstdzy.js.map +0 -12
- package/dist/chunks/studio-zp7jncs8.js +0 -469
- package/dist/chunks/studio-zp7jncs8.js.map +0 -14
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-8jxwts2p.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-esrewxap.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
package/src/ui/media-picker.ts
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
* project and assigns it, and a Browse dropdown of media already in the project's public/
|
|
7
7
|
* directory, with thumbnail previews for images.
|
|
8
8
|
*
|
|
9
|
+
* **The browse list carries metadata, and it costs nothing.** Size comes from the directory listing
|
|
10
|
+
* the widget already performs to enumerate the files (`seedMediaMeta`), and pixel dimensions come
|
|
11
|
+
* from the thumbnails it already loads (`recordImageSize`) — measuring an image is a decode the
|
|
12
|
+
* `<img>` has finished by the time `load` fires, so the caption is a read of work already done
|
|
13
|
+
* rather than a second fetch per row. What is NOT here is a usage count: `findReferences` sweeps
|
|
14
|
+
* every document in the project per query, and fifty of those to caption a dropdown is the wrong
|
|
15
|
+
* trade. Usage is asked once, about one file, where it changes a decision — the delete confirmation
|
|
16
|
+
* (`files/media-usage.ts`).
|
|
17
|
+
*
|
|
9
18
|
* @docs studio/projects/media
|
|
10
19
|
*/
|
|
11
20
|
|
|
@@ -14,7 +23,8 @@ import { live } from "lit-html/directives/live.js";
|
|
|
14
23
|
import { ref } from "lit-html/directives/ref.js";
|
|
15
24
|
import { getPlatform } from "../platform";
|
|
16
25
|
import { debouncedStyleCommit, renderOnly } from "../store";
|
|
17
|
-
import { getLayerSlot } from "./layers";
|
|
26
|
+
import { getLayerSlot, popoverLayerFor } from "./layers";
|
|
27
|
+
import type { LayerKind } from "./layers";
|
|
18
28
|
import { rectOf } from "../utils/geometry";
|
|
19
29
|
import { loopbackAssetSrc } from "../canvas/canvas-origin";
|
|
20
30
|
import { previewAssetSrc } from "../canvas/content-assets";
|
|
@@ -25,28 +35,42 @@ import {
|
|
|
25
35
|
extensionOf,
|
|
26
36
|
uploadAssets,
|
|
27
37
|
} from "../files/media-upload";
|
|
38
|
+
import {
|
|
39
|
+
invalidateMediaMeta,
|
|
40
|
+
mediaMetaSummary,
|
|
41
|
+
peekMediaMeta,
|
|
42
|
+
recordImageSize,
|
|
43
|
+
seedMediaMeta,
|
|
44
|
+
} from "../files/media-meta";
|
|
45
|
+
import { mediaSiteUrl } from "../files/media-paths";
|
|
28
46
|
|
|
29
47
|
// ─── Media file cache ────────────────────────────────────────────────────────
|
|
30
48
|
|
|
31
|
-
/**
|
|
32
|
-
|
|
49
|
+
/** One browsable media file: the ref a pick writes, and the file that ref names. */
|
|
50
|
+
interface MediaEntry {
|
|
51
|
+
/** The value committed to the field — the site URL, which is the authored form. */
|
|
52
|
+
path: string;
|
|
53
|
+
/** Project-relative path on disk, the key everything in `media-meta` is stored under. */
|
|
54
|
+
file: string;
|
|
55
|
+
name: string;
|
|
56
|
+
isImage: boolean;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let mediaCache: MediaEntry[] = [];
|
|
33
60
|
let mediaCacheLoaded = false;
|
|
34
61
|
|
|
35
62
|
/**
|
|
36
|
-
* Recursively collect media files from a directory
|
|
37
|
-
*
|
|
38
|
-
* @param {string} dir
|
|
39
|
-
* @param {ReturnType<typeof getPlatform>} platform
|
|
40
|
-
* @returns {Promise<{ path: string; name: string; isImage: boolean }[]>}
|
|
63
|
+
* Recursively collect media files from a directory, seeding {@link seedMediaMeta} with the listing
|
|
64
|
+
* on the way past — the size of every row is already in the response that enumerated it.
|
|
41
65
|
*/
|
|
42
66
|
async function collectMedia(
|
|
43
67
|
dir: string,
|
|
44
68
|
platform: ReturnType<typeof getPlatform>,
|
|
45
|
-
): Promise<
|
|
46
|
-
|
|
47
|
-
const results = [];
|
|
69
|
+
): Promise<MediaEntry[]> {
|
|
70
|
+
const results: MediaEntry[] = [];
|
|
48
71
|
try {
|
|
49
72
|
const entries = await platform.listDirectory(dir);
|
|
73
|
+
seedMediaMeta(entries);
|
|
50
74
|
for (const entry of entries) {
|
|
51
75
|
if (entry.type === "directory") {
|
|
52
76
|
const sub = await collectMedia(entry.path, platform);
|
|
@@ -55,9 +79,12 @@ async function collectMedia(
|
|
|
55
79
|
const ext = extensionOf(entry.name);
|
|
56
80
|
if (MEDIA_EXTENSIONS.has(ext)) {
|
|
57
81
|
results.push({
|
|
82
|
+
file: entry.path,
|
|
58
83
|
isImage: IMAGE_EXTENSIONS.has(ext),
|
|
59
84
|
name: entry.name,
|
|
60
|
-
|
|
85
|
+
// The site URL is what production serves and therefore what a document should say.
|
|
86
|
+
// Media-paths holds the one definition of that mapping.
|
|
87
|
+
path: mediaSiteUrl(entry.path),
|
|
61
88
|
});
|
|
62
89
|
}
|
|
63
90
|
}
|
|
@@ -74,20 +101,22 @@ async function loadMediaCache() {
|
|
|
74
101
|
}
|
|
75
102
|
const platform = getPlatform();
|
|
76
103
|
mediaCache = await collectMedia("public", platform);
|
|
77
|
-
// Strip "public/" prefix so paths match production (public/ contents served at root)
|
|
78
|
-
for (const m of mediaCache) {
|
|
79
|
-
m.path = m.path.replace(/^\/public\//, "/");
|
|
80
|
-
}
|
|
81
104
|
mediaCacheLoaded = true;
|
|
82
105
|
// Re-render the host panels so the browse popover has entries to show once the async listing
|
|
83
106
|
// Resolves. Mirrors loadLayoutEntries()'s renderOnly() in head-panel.
|
|
84
107
|
renderOnly("leftPanel", "rightPanel", "frontmatterPanel");
|
|
85
108
|
}
|
|
86
109
|
|
|
87
|
-
/**
|
|
110
|
+
/**
|
|
111
|
+
* Force media cache reload (e.g. after upload).
|
|
112
|
+
*
|
|
113
|
+
* The metadata cache goes with it, and for the same reason: both were derived from a listing that
|
|
114
|
+
* is now out of date, and a size that survives the write it contradicts is worse than no size.
|
|
115
|
+
*/
|
|
88
116
|
export function invalidateMediaCache() {
|
|
89
117
|
mediaCache = [];
|
|
90
118
|
mediaCacheLoaded = false;
|
|
119
|
+
invalidateMediaMeta();
|
|
91
120
|
}
|
|
92
121
|
|
|
93
122
|
// ─── Popover state ───────────────────────────────────────────────────────────
|
|
@@ -97,6 +126,32 @@ let _popoverOnCommit: ((val: string) => void) | null = null;
|
|
|
97
126
|
|
|
98
127
|
/** @type {HTMLElement | null} */
|
|
99
128
|
let _popoverAnchorEl: HTMLElement | null = null;
|
|
129
|
+
/**
|
|
130
|
+
* Which layer the open popover is living in.
|
|
131
|
+
*
|
|
132
|
+
* Chosen from the anchor at open time and then REMEMBERED, because `getLayerSlot` keys its slots by
|
|
133
|
+
* `${layer}:${id}`: dismissing through a different layer than the one that opened would clear an
|
|
134
|
+
* empty slot and leave the real popover on screen.
|
|
135
|
+
*/
|
|
136
|
+
let _popoverLayer: LayerKind = "popover";
|
|
137
|
+
|
|
138
|
+
/** The open popover's slot — the one place that names the layer and the id together. */
|
|
139
|
+
function popoverSlot(): HTMLElement {
|
|
140
|
+
return getLayerSlot(_popoverLayer, "media-picker");
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The popover's z-index, which depends on the company it is keeping.
|
|
145
|
+
*
|
|
146
|
+
* In `#layer-popover` it has the layer to itself and 30 is enough — that is what it has always
|
|
147
|
+
* been, and every panel-hosted picker keeps rendering identically. Sharing a layer with a modal
|
|
148
|
+
* body is different: those declare `z-index: 1000` (`.seo-modal`, `.about-modal`, `.settings-modal`
|
|
149
|
+
* — the house shape), so a picker anchored inside one is a later sibling that still paints beneath
|
|
150
|
+
* it. Beating that number is the whole point of moving layers in the first place.
|
|
151
|
+
*/
|
|
152
|
+
function popoverZIndex(): number {
|
|
153
|
+
return _popoverLayer === "popover" ? 30 : 1001;
|
|
154
|
+
}
|
|
100
155
|
|
|
101
156
|
/** @type {HTMLInputElement | null} */
|
|
102
157
|
let _popoverFilterEl: HTMLInputElement | null = null;
|
|
@@ -110,7 +165,7 @@ function dismissMediaPickerPopover() {
|
|
|
110
165
|
_popoverFilterEl = null;
|
|
111
166
|
document.removeEventListener("keydown", onPopoverKeydown, true);
|
|
112
167
|
document.removeEventListener("mousedown", onPopoverOutsideClick, true);
|
|
113
|
-
litRender(nothing,
|
|
168
|
+
litRender(nothing, popoverSlot());
|
|
114
169
|
}
|
|
115
170
|
|
|
116
171
|
/** @param {KeyboardEvent} e */
|
|
@@ -124,14 +179,38 @@ function onPopoverKeydown(e: KeyboardEvent) {
|
|
|
124
179
|
|
|
125
180
|
/** @param {MouseEvent} e */
|
|
126
181
|
function onPopoverOutsideClick(e: MouseEvent) {
|
|
127
|
-
const host =
|
|
182
|
+
const host = popoverSlot();
|
|
128
183
|
if (!host.contains(e.target as Node)) {
|
|
129
184
|
dismissMediaPickerPopover();
|
|
130
185
|
}
|
|
131
186
|
}
|
|
132
187
|
|
|
188
|
+
/** A repaint scheduled by a thumbnail that just reported its size, or 0 when none is pending. */
|
|
189
|
+
let _sizeRepaint = 0;
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Fold a loaded thumbnail's intrinsic size into the metadata cache and, if that was news, repaint
|
|
193
|
+
* the popover once so the caption appears.
|
|
194
|
+
*
|
|
195
|
+
* The repaint is coalesced across a whole grid of images landing in the same frame, and it cannot
|
|
196
|
+
* loop: re-rendering recreates the `<img>` elements, whose `load` fires again from cache, and
|
|
197
|
+
* `recordImageSize` returns false the second time because the measurement has not changed.
|
|
198
|
+
*/
|
|
199
|
+
function noteImageSize(file: string, target: EventTarget | null) {
|
|
200
|
+
const img = target as HTMLImageElement | null;
|
|
201
|
+
if (!img || !recordImageSize(file, img.naturalWidth, img.naturalHeight) || _sizeRepaint !== 0) {
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
_sizeRepaint = requestAnimationFrame(() => {
|
|
205
|
+
_sizeRepaint = 0;
|
|
206
|
+
if (_popoverAnchorEl) {
|
|
207
|
+
renderMediaPickerPopover();
|
|
208
|
+
}
|
|
209
|
+
});
|
|
210
|
+
}
|
|
211
|
+
|
|
133
212
|
function renderMediaPickerPopover() {
|
|
134
|
-
const host =
|
|
213
|
+
const host = popoverSlot();
|
|
135
214
|
const rect = _popoverAnchorEl ? rectOf(_popoverAnchorEl) : undefined;
|
|
136
215
|
if (!rect) {
|
|
137
216
|
return;
|
|
@@ -166,10 +245,11 @@ function renderMediaPickerPopover() {
|
|
|
166
245
|
html`
|
|
167
246
|
<sp-popover
|
|
168
247
|
open
|
|
248
|
+
data-jx-region="overlay.menu:media-picker"
|
|
169
249
|
${ref((el) => {
|
|
170
250
|
_popoverEl = (el as HTMLElement | undefined) || null;
|
|
171
251
|
})}
|
|
172
|
-
style="position:fixed;left:${left}px;top:${top}px;z-index
|
|
252
|
+
style="position:fixed;left:${left}px;top:${top}px;z-index:${popoverZIndex()};max-height:360px;overflow-y:auto;min-width:240px"
|
|
173
253
|
>
|
|
174
254
|
<input
|
|
175
255
|
class="media-picker-filter"
|
|
@@ -195,8 +275,9 @@ function renderMediaPickerPopover() {
|
|
|
195
275
|
>
|
|
196
276
|
${
|
|
197
277
|
options.length > 0
|
|
198
|
-
? options.map(
|
|
199
|
-
(m)
|
|
278
|
+
? options.map((m) => {
|
|
279
|
+
const caption = mediaMetaSummary(peekMediaMeta(m.file));
|
|
280
|
+
return html`
|
|
200
281
|
<sp-menu-item value=${m.path}>
|
|
201
282
|
${
|
|
202
283
|
m.isImage
|
|
@@ -205,13 +286,15 @@ function renderMediaPickerPopover() {
|
|
|
205
286
|
src=${loopbackAssetSrc(m.path)}
|
|
206
287
|
alt=""
|
|
207
288
|
style="width:24px;height:24px;object-fit:cover;border-radius:var(--spectrum-corner-radius-75, 2px)"
|
|
289
|
+
@load=${(e: Event) => noteImageSize(m.file, e.target)}
|
|
208
290
|
/>`
|
|
209
291
|
: nothing
|
|
210
292
|
}
|
|
211
293
|
${m.name}
|
|
294
|
+
${caption ? html`<span slot="description">${caption}</span>` : nothing}
|
|
212
295
|
</sp-menu-item>
|
|
213
|
-
|
|
214
|
-
)
|
|
296
|
+
`;
|
|
297
|
+
})
|
|
215
298
|
: html`<sp-menu-item disabled>No matches</sp-menu-item>`
|
|
216
299
|
}
|
|
217
300
|
${
|
|
@@ -270,6 +353,8 @@ function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: string) =
|
|
|
270
353
|
dismissMediaPickerPopover();
|
|
271
354
|
_popoverOnCommit = onCommit;
|
|
272
355
|
_popoverAnchorEl = anchorEl;
|
|
356
|
+
// Before the first render, so every later `popoverSlot()` agrees with where it was drawn.
|
|
357
|
+
_popoverLayer = popoverLayerFor(anchorEl);
|
|
273
358
|
_popoverFilter = "";
|
|
274
359
|
renderMediaPickerPopover();
|
|
275
360
|
document.addEventListener("keydown", onPopoverKeydown, true);
|
|
@@ -362,6 +447,11 @@ export function renderMediaPicker(prop: string, value: string, onCommit: (val: s
|
|
|
362
447
|
>
|
|
363
448
|
<sp-icon-upload slot="icon"></sp-icon-upload>
|
|
364
449
|
</sp-action-button>
|
|
450
|
+
<!-- No data-jx-region here. The class IS the handle: ui/regions.ts derives
|
|
451
|
+
inspector/field:PROP/browse by finding this button inside the Inspector's own
|
|
452
|
+
[data-prop] row, so the id resolves to one element however many panes are drawing a
|
|
453
|
+
media picker. The stamp claimed an inspector/... id on every picker the app renders,
|
|
454
|
+
including the two the Document Header card draws inside each pane's STAGE. -->
|
|
365
455
|
<sp-action-button
|
|
366
456
|
class="media-picker-browse"
|
|
367
457
|
size="xs"
|
package/src/ui/panel-resize.ts
CHANGED
|
@@ -1,76 +1,88 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
* Panel-resize.js — Draggable resize handles for
|
|
3
|
+
* Panel-resize.js — Draggable resize handles for the three docks.
|
|
4
4
|
*
|
|
5
|
-
* Self-initializing module. Import it and the resize handles become interactive.
|
|
6
|
-
*
|
|
5
|
+
* Self-initializing module. Import it and the resize handles become interactive.
|
|
6
|
+
*
|
|
7
|
+
* The handles are the only thing here: dock sizes, their persistence and their projection onto the
|
|
8
|
+
* grid's CSS custom properties all belong to the reactive `shell` record (`../shell`). A drag
|
|
9
|
+
* writes `setDockSize()` and the shell's own effect moves the track; release persists once.
|
|
7
10
|
*/
|
|
8
11
|
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
import {
|
|
13
|
+
DOCK_DEFAULT_SIZES,
|
|
14
|
+
persistDocks,
|
|
15
|
+
registerShellSurface,
|
|
16
|
+
setDockSize,
|
|
17
|
+
shell,
|
|
18
|
+
} from "../shell";
|
|
19
|
+
import type { DockId } from "../shell";
|
|
17
20
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
/**
|
|
22
|
+
* What a handle drags.
|
|
23
|
+
*
|
|
24
|
+
* Generalised out of the three dock rows so the pane splitter can be the fourth. A dock is sized in
|
|
25
|
+
* px and a pane split is a ratio, which is the whole of the difference: `scale` converts a pointer
|
|
26
|
+
* delta in px into the target's own units, and everything else — capture, the dragging class, the
|
|
27
|
+
* text-selection suppression, the double-click reset, the one persist on release — is identical and
|
|
28
|
+
* was worth having once.
|
|
29
|
+
*/
|
|
30
|
+
export interface ResizeTarget {
|
|
31
|
+
/** Which coordinate the drag reads. */
|
|
32
|
+
axis: "x" | "y";
|
|
33
|
+
/** The current value. */
|
|
34
|
+
read: () => number;
|
|
35
|
+
/** Set it. Called on every pointermove, so it must be cheap and idempotent. */
|
|
36
|
+
write: (value: number) => void;
|
|
37
|
+
/** The value a double-click restores. */
|
|
38
|
+
reset: () => number;
|
|
39
|
+
/** Lower and upper bounds, read fresh because both can depend on the viewport. */
|
|
40
|
+
min: () => number;
|
|
41
|
+
max: () => number;
|
|
42
|
+
/** Target units per pixel of pointer movement, signed: negative grows toward the origin. */
|
|
43
|
+
scale: () => number;
|
|
44
|
+
/** Persist. Called once on release and once on reset — never during the drag. */
|
|
45
|
+
settle: () => void;
|
|
23
46
|
}
|
|
24
47
|
|
|
25
|
-
|
|
48
|
+
/**
|
|
49
|
+
* The smallest a dock may be dragged to, per axis.
|
|
50
|
+
*
|
|
51
|
+
* The Bottom dock's floor is lower because its content is rows of text: 120px is four problems or
|
|
52
|
+
* two activity rows, which is a useful dock, where 160px of a 24-row list is not meaningfully
|
|
53
|
+
* more.
|
|
54
|
+
*/
|
|
55
|
+
const MIN_SIZE: Readonly<Record<"x" | "y", number>> = { x: 160, y: 120 };
|
|
26
56
|
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
left?: number;
|
|
30
|
-
right?: number;
|
|
31
|
-
chat?: number;
|
|
32
|
-
leftCollapsed?: boolean;
|
|
33
|
-
rightCollapsed?: boolean;
|
|
34
|
-
chatCollapsed?: boolean;
|
|
35
|
-
};
|
|
36
|
-
if (saved.left) {
|
|
37
|
-
root.style.setProperty("--panel-w-left", `${saved.left}px`);
|
|
38
|
-
}
|
|
39
|
-
if (saved.right) {
|
|
40
|
-
root.style.setProperty("--panel-w-right", `${saved.right}px`);
|
|
41
|
-
}
|
|
42
|
-
if (saved.chat) {
|
|
43
|
-
root.style.setProperty("--panel-w-chat", `${saved.chat}px`);
|
|
44
|
-
}
|
|
45
|
-
if (saved.leftCollapsed) {
|
|
46
|
-
view.leftPanelCollapsed = true;
|
|
47
|
-
}
|
|
48
|
-
if (saved.rightCollapsed) {
|
|
49
|
-
view.rightPanelCollapsed = true;
|
|
50
|
-
}
|
|
51
|
-
if (saved.chatCollapsed) {
|
|
52
|
-
view.chatPanelCollapsed = true;
|
|
53
|
-
}
|
|
54
|
-
applyPanelCollapse();
|
|
55
|
-
} catch {
|
|
56
|
-
// Ignore
|
|
57
|
-
}
|
|
57
|
+
/** The largest, as a fraction of the viewport along the dragged axis. */
|
|
58
|
+
const MAX_RATIO = 0.5;
|
|
58
59
|
|
|
59
|
-
|
|
60
|
+
/**
|
|
61
|
+
* Which handle drives which dock, and which direction grows it.
|
|
62
|
+
*
|
|
63
|
+
* Three rows, and the third resizes on the other axis: `grow` is the sign a pointer moving in the
|
|
64
|
+
* positive direction of `axis` contributes, so the Navigator grows rightward, and the Inspector and
|
|
65
|
+
* the Bottom dock grow back toward the pointer's origin. The assistant is not here and never will
|
|
66
|
+
* be — it is an Inspector TAB, resized by resizing the Inspector.
|
|
67
|
+
*/
|
|
68
|
+
const HANDLES: { selector: string; dock: DockId; axis: "x" | "y"; grow: 1 | -1 }[] = [
|
|
69
|
+
{ axis: "x", dock: "left", grow: 1, selector: "#resize-left" },
|
|
70
|
+
{ axis: "x", dock: "right", grow: -1, selector: "#resize-right" },
|
|
71
|
+
{ axis: "y", dock: "bottom", grow: -1, selector: "#resize-bottom" },
|
|
72
|
+
];
|
|
60
73
|
|
|
61
74
|
/**
|
|
75
|
+
* Wire one handle to one dock.
|
|
76
|
+
*
|
|
62
77
|
* @param {HTMLElement} handle
|
|
63
|
-
* @param {
|
|
64
|
-
* @param {"
|
|
65
|
-
* @param {
|
|
78
|
+
* @param {DockId} dock
|
|
79
|
+
* @param {"x" | "y"} axis — which coordinate the drag reads
|
|
80
|
+
* @param {1 | -1} grow — the sign a positive move along `axis` contributes to the dock's size
|
|
66
81
|
*/
|
|
67
|
-
function setupHandle(
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
defaultWidth: number,
|
|
72
|
-
) {
|
|
73
|
-
let drag: { startX: number; startWidth: number } | null = null;
|
|
82
|
+
export function setupHandle(handle: HTMLElement, target: ResizeTarget) {
|
|
83
|
+
const { axis } = target;
|
|
84
|
+
let drag: { start: number; startSize: number } | null = null;
|
|
85
|
+
const coord = (e: { clientX: number; clientY: number }) => (axis === "x" ? e.clientX : e.clientY);
|
|
74
86
|
|
|
75
87
|
handle.addEventListener("pointerdown", (e) => {
|
|
76
88
|
e.preventDefault();
|
|
@@ -81,19 +93,17 @@ function setupHandle(
|
|
|
81
93
|
}
|
|
82
94
|
handle.classList.add("dragging");
|
|
83
95
|
document.body.style.userSelect = "none";
|
|
84
|
-
|
|
85
|
-
const current = readPxVar(cssVar) || defaultWidth;
|
|
86
|
-
drag = { startWidth: current, startX: e.clientX };
|
|
96
|
+
drag = { start: coord(e), startSize: target.read() };
|
|
87
97
|
});
|
|
88
98
|
|
|
89
99
|
handle.addEventListener("pointermove", (e) => {
|
|
90
100
|
if (!drag) {
|
|
91
101
|
return;
|
|
92
102
|
}
|
|
93
|
-
const delta =
|
|
94
|
-
const
|
|
95
|
-
const
|
|
96
|
-
|
|
103
|
+
const delta = (coord(e) - drag.start) * target.scale();
|
|
104
|
+
const wanted = drag.startSize + delta;
|
|
105
|
+
const floored = Math.max(target.min(), wanted);
|
|
106
|
+
target.write(Math.min(target.max(), floored));
|
|
97
107
|
});
|
|
98
108
|
|
|
99
109
|
handle.addEventListener("pointerup", (e) => {
|
|
@@ -108,38 +118,46 @@ function setupHandle(
|
|
|
108
118
|
}
|
|
109
119
|
handle.classList.remove("dragging");
|
|
110
120
|
document.body.style.userSelect = "";
|
|
111
|
-
|
|
121
|
+
target.settle();
|
|
112
122
|
});
|
|
113
123
|
|
|
114
124
|
handle.addEventListener("dblclick", () => {
|
|
115
|
-
|
|
116
|
-
|
|
125
|
+
target.write(target.reset());
|
|
126
|
+
target.settle();
|
|
117
127
|
});
|
|
118
128
|
}
|
|
119
129
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
try {
|
|
125
|
-
localStorage.setItem(STORAGE_KEY, JSON.stringify({ chat, left, right }));
|
|
126
|
-
} catch {
|
|
127
|
-
// Storage full or unavailable
|
|
128
|
-
}
|
|
130
|
+
/** The largest a dock may be dragged to along `axis`. */
|
|
131
|
+
function maxDockSize(axis: "x" | "y"): number {
|
|
132
|
+
const viewport = axis === "x" ? window.innerWidth : window.innerHeight;
|
|
133
|
+
return viewport * MAX_RATIO;
|
|
129
134
|
}
|
|
130
135
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
136
|
+
/** A dock, as a {@link ResizeTarget}. The three rows of {@link HANDLES}, given the shared shape. */
|
|
137
|
+
function dockTarget(dock: DockId, axis: "x" | "y", grow: 1 | -1): ResizeTarget {
|
|
138
|
+
return {
|
|
139
|
+
axis,
|
|
140
|
+
max: () => maxDockSize(axis),
|
|
141
|
+
min: () => MIN_SIZE[axis],
|
|
142
|
+
read: () => shell.docks[dock].size,
|
|
143
|
+
reset: () => DOCK_DEFAULT_SIZES[dock],
|
|
144
|
+
scale: () => grow,
|
|
145
|
+
settle: () => persistDocks(),
|
|
146
|
+
write: (value) => setDockSize(dock, Math.round(value)),
|
|
147
|
+
};
|
|
142
148
|
}
|
|
143
|
-
|
|
144
|
-
|
|
149
|
+
|
|
150
|
+
/** Attach every handle present in the document. Idempotent per element by construction. */
|
|
151
|
+
export function mountPanelResize(): void {
|
|
152
|
+
for (const { axis, dock, grow, selector } of HANDLES) {
|
|
153
|
+
const handle = document.querySelector<HTMLElement>(selector);
|
|
154
|
+
if (handle) {
|
|
155
|
+
setupHandle(handle, dockTarget(dock, axis, grow));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
145
158
|
}
|
|
159
|
+
|
|
160
|
+
/* Mounted through the shell's own lifecycle rather than by a bare `mountPanelResize()` at module
|
|
161
|
+
scope. The import-time call read `document` before anything had said the tree existed, which is
|
|
162
|
+
the one part of `registerShellSurface`'s bargain this module was not keeping. */
|
|
163
|
+
registerShellSurface({ mount: mountPanelResize, unmount: () => {} });
|