@jxsuite/studio 4.1.0 → 5.0.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/README.md +1 -1
- package/data/elements-meta.json +5 -15
- package/data/html-meta.json +51 -6
- package/dist/chunks/{2020-n6tfwnda.js → 2020-g79n01v9.js} +14 -14
- package/dist/chunks/action-group-sp6tna8v.js +118 -0
- package/dist/chunks/adapter-nj7tnjfn.js +13 -0
- package/dist/chunks/cf-account-picker-fyf63pmy.js +495 -0
- package/dist/chunks/cf-settings-71bv5zn9.js +20 -0
- package/dist/chunks/color-area-v17df7b8.js +154 -0
- package/dist/chunks/color-field-anwybnkn.js +208 -0
- package/dist/chunks/color-slider-44ez96fc.js +79 -0
- package/dist/chunks/color-xgg3kfw7.js +35 -0
- package/dist/chunks/combobox-5e7jev23.js +236 -0
- package/dist/chunks/components-2w1f35qs.js +18 -0
- package/dist/chunks/content-source-3wqeas45.js +46 -0
- package/dist/chunks/convert-to-repeater-d0cgnb6d.js +639 -0
- package/dist/chunks/dialog-s890b918.js +85 -0
- package/dist/chunks/editor-3qhbg51x.js +35 -0
- package/dist/chunks/entry-commands-d6g50j7s.js +42 -0
- package/dist/chunks/extension-sections-fy7q4fe9.js +651 -0
- package/dist/chunks/file-ops-3btj6st0.js +47 -0
- package/dist/chunks/files-ef8fgs3w.js +72 -0
- package/dist/chunks/format-host-3c33nwr8.js +40 -0
- package/dist/chunks/fs-events-13tj6sex.js +18 -0
- package/dist/chunks/git-panel-4wp2rn9b.js +49 -0
- package/dist/chunks/icons-yy10wk9r.js +402 -0
- package/dist/chunks/iframe-entry-15g3n6xv.js +114 -0
- package/dist/chunks/iframe-entry-b27vq81n.js +203 -0
- package/dist/chunks/iframe-entry-nbyxee1y.js +154 -0
- package/dist/chunks/iframe-host-jgesd924.js +115 -0
- package/dist/chunks/{index-wcnt3r9g.js → index-mdmyx6s2.js} +11 -11
- package/dist/chunks/index-n4j7qxyr.js +109 -0
- package/dist/chunks/{javascript-q8kpmfah.js → javascript-xvrfrpkb.js} +8 -9
- package/dist/chunks/{jsonMode-dkr040ga.js → jsonMode-tyx2kj6p.js} +526 -527
- package/dist/chunks/jx-validate-j0wxk72w.js +15 -0
- package/dist/chunks/layers-1nq5evsh.js +29 -0
- package/dist/chunks/layers-panel-ar2gh90g.js +40 -0
- package/dist/chunks/listbox-6v2ac08j.js +44 -0
- package/dist/chunks/lit-html-m244w9nh.js +17 -0
- package/dist/chunks/media-picker-2qbetq73.js +33 -0
- package/dist/chunks/menu-q99sy9rf.js +285 -0
- package/dist/chunks/menu-rf7n72mf.js +14 -0
- package/dist/chunks/{monaco-binding-rj6xpx9y.js → monaco-binding-sw6en4dw.js} +12 -15
- package/dist/chunks/monaco-buffer-bhy3hb6m.js +24 -0
- package/dist/chunks/{monaco-setup-vx9bhp1d.js → monaco-setup-8r62fj6y.js} +27 -37
- package/dist/chunks/notify-628t0anh.js +21 -0
- package/dist/chunks/number-field-5cndyft8.js +72 -0
- package/dist/chunks/parse-0zx14y15.js +10 -0
- package/dist/chunks/platform-ts9cg1a4.js +15 -0
- package/dist/chunks/popover-47z3ytva.js +25 -0
- package/dist/chunks/publish-panel-98f7sr3g.js +27 -0
- package/dist/chunks/quick-search-srzz83k2.js +45 -0
- package/dist/chunks/references-n553f0e1.js +26 -0
- package/dist/chunks/right-panel-rrgx2dn3.js +45 -0
- package/dist/chunks/section-registry-5pq32t0q.js +25 -0
- package/dist/chunks/select-2r16ez41.js +49 -0
- package/dist/chunks/split-g7nm1rgb.js +191 -0
- package/dist/chunks/studio-0hqbpbd0.js +62 -0
- package/dist/chunks/studio-18avnhjp.js +2430 -0
- package/dist/chunks/{studio-kryvsw6j.js → studio-1k325pwf.js} +48 -48
- package/dist/chunks/{studio-msd847zn.js → studio-25hkdrkw.js} +357 -86
- package/dist/chunks/studio-26d7myd1.js +258 -0
- package/dist/chunks/{studio-4r1pv6zf.js → studio-38emantv.js} +22 -5
- package/dist/chunks/studio-3gxv60tn.js +422 -0
- package/dist/chunks/{studio-fbf92ckf.js → studio-3hxkd92t.js} +275 -163
- package/dist/chunks/studio-4m0haseg.js +185 -0
- package/dist/chunks/{studio-ynxwkrzd.js → studio-4wbb9ct0.js} +1953 -1785
- package/dist/chunks/{studio-1wagb550.js → studio-5523bpzt.js} +11 -11
- package/dist/chunks/{studio-x4qkdat5.js → studio-57mf66w2.js} +1749 -2481
- package/dist/chunks/studio-5jy81t3s.js +17463 -0
- package/dist/chunks/studio-5rt7sqa0.js +1168 -0
- package/dist/chunks/studio-5te5tqng.js +81 -0
- package/dist/chunks/{studio-p4ngc046.js → studio-6ewqv390.js} +9 -9
- package/dist/chunks/{studio-9ab8gqsm.js → studio-6nzaktvy.js} +7 -7
- package/dist/chunks/studio-6xa21ej9.js +28 -0
- package/dist/chunks/{studio-5ehhackm.js → studio-727xh0e3.js} +19 -19
- package/dist/chunks/{studio-ahn3pdgx.js → studio-79y5sz51.js} +52 -38
- package/dist/chunks/{studio-gcye7qka.js → studio-7e11jpa9.js} +21 -21
- package/dist/chunks/{studio-q7v10cg2.js → studio-7r42c6ca.js} +17 -7
- package/dist/chunks/studio-7xptrg0j.js +954 -0
- package/dist/chunks/{studio-cft9r4r7.js → studio-81390n6f.js} +22 -22
- package/dist/chunks/{studio-q43a5y9h.js → studio-8jn5yhyn.js} +16 -16
- package/dist/chunks/studio-8qtrpzr3.js +839 -0
- package/dist/chunks/{studio-dg7zyt5x.js → studio-98b3z07n.js} +1 -1
- package/dist/chunks/studio-9xxz1q69.js +1356 -0
- package/dist/chunks/studio-akbww0j5.js +13615 -0
- package/dist/chunks/{studio-x813zp48.js → studio-arfpe389.js} +30 -30
- package/dist/chunks/{studio-trxrabqf.js → studio-az3zd49t.js} +475 -283
- package/dist/chunks/studio-cpvb2ed1.js +1171 -0
- package/dist/chunks/{studio-f3wqjtk5.js → studio-d0300636.js} +5076 -18
- package/dist/chunks/{studio-bgxt93ga.js → studio-d055c37e.js} +13 -13
- package/dist/chunks/studio-d1ja2x9r.js +362 -0
- package/dist/chunks/{studio-b9b6t1dg.js → studio-e1f24eff.js} +5664 -5666
- package/dist/chunks/{studio-3bqpr0zh.js → studio-em9nw8eh.js} +299 -110
- package/dist/chunks/studio-erdatzvp.js +1190 -0
- package/dist/chunks/{studio-g1wdche0.js → studio-esrxgwh6.js} +80 -80
- package/dist/chunks/studio-fabxk6r9.js +2811 -0
- package/dist/chunks/{studio-3n4ndrzh.js → studio-h4nvnjvz.js} +303 -303
- package/dist/chunks/{studio-dm19q43r.js → studio-hhvs4sdg.js} +10 -10
- package/dist/chunks/{studio-q9jd1a60.js → studio-kcgff4r0.js} +15 -18
- package/dist/chunks/{studio-685s0ytq.js → studio-nqgawfks.js} +572 -572
- package/dist/chunks/{studio-xrapxwwc.js → studio-p1dw8wfw.js} +55 -29
- package/dist/chunks/studio-pm6hgy7r.js +4763 -0
- package/dist/chunks/studio-q0a3yk4n.js +33 -0
- package/dist/chunks/{studio-wcy8trfx.js → studio-q3x06vmj.js} +23 -22
- package/dist/chunks/studio-qahxvnan.js +111 -0
- package/dist/chunks/{studio-53n8bp04.js → studio-r6xmmtfh.js} +1 -1
- package/dist/chunks/{studio-2b946z26.js → studio-rkstz940.js} +3658 -6134
- package/dist/chunks/{studio-tvgyw9xw.js → studio-rnyf3f8e.js} +83 -250
- package/dist/chunks/studio-rpyah2ew.js +2805 -0
- package/dist/chunks/studio-rs76k67r.js +12 -0
- package/dist/chunks/{studio-jkftxyvz.js → studio-s6z853aq.js} +5858 -2152
- package/dist/chunks/{studio-6yw4y3my.js → studio-sgdc5pfc.js} +8 -8
- package/dist/chunks/studio-tb3ev01j.js +763 -0
- package/dist/chunks/{studio-t5wqwzdh.js → studio-tjjk7jvk.js} +1 -1
- package/dist/chunks/studio-vhv5tgxm.js +51 -0
- package/dist/chunks/{studio-qjy2z9bv.js → studio-vz68yn9e.js} +32 -137
- package/dist/chunks/studio-wqpngpsk.js +174 -0
- package/dist/chunks/{studio-b55y6ewx.js → studio-x3rty6tr.js} +58 -58
- package/dist/chunks/studio-xsykpvsh.js +8448 -0
- package/dist/chunks/{studio-92ab2jqe.js → studio-y9zedyjn.js} +14 -14
- package/dist/chunks/studio-yxa81f45.js +12 -0
- package/dist/chunks/swatch-group-t0n6h2rn.js +139 -0
- package/dist/chunks/tabs-wbp1cdws.js +156 -0
- package/dist/chunks/textfield-abk6qyee.js +73 -0
- package/dist/chunks/toast-780pvfbv.js +27 -0
- package/dist/chunks/toast-host-3sqv46sn.js +116 -0
- package/dist/chunks/toolbar-xbh5bhtr.js +194 -0
- package/dist/chunks/tooltip-eptb614w.js +369 -0
- package/dist/chunks/tree-a73p0pqm.js +367 -0
- package/dist/chunks/{tsMode-76kr53q0.js → tsMode-jy4m86rv.js} +83 -85
- package/dist/chunks/workspace-wrew8zk4.js +69 -0
- package/dist/chunks/{ws-client-6shc5rze.js → ws-client-ny4zc51r.js} +20 -22
- package/dist/iframe-entry.js +1780 -667
- package/dist/studio.js +52819 -36480
- package/dist/workers/editor.worker.js +1040 -1085
- package/dist/workers/json.worker.js +1946 -1991
- package/dist/workers/ts.worker.js +4960 -5005
- package/index.html +1 -0
- package/package.json +18 -52
- package/src/about/about-modal.ts +72 -123
- package/src/browse/library-commands.ts +20 -49
- package/src/browse/library-layouts.ts +87 -218
- package/src/browse/library-pane.ts +406 -438
- package/src/canvas/canvas-helpers.ts +0 -49
- package/src/canvas/canvas-live-render.ts +25 -2
- package/src/canvas/canvas-render.ts +666 -231
- package/src/canvas/canvas-surface.ts +0 -1
- package/src/canvas/canvas-utils.ts +310 -117
- package/src/canvas/dialog-path.ts +76 -0
- package/src/canvas/dialog-state.ts +67 -0
- package/src/canvas/diff-marks.ts +252 -0
- package/src/canvas/diff-toolbar.ts +349 -0
- package/src/canvas/diff-view.ts +123 -0
- package/src/canvas/edit-width-drag.ts +187 -0
- package/src/canvas/edit-width.ts +150 -0
- package/src/canvas/iframe-entry.ts +125 -8
- package/src/canvas/iframe-host.ts +271 -15
- package/src/canvas/iframe-interaction.ts +133 -13
- package/src/canvas/iframe-patch.ts +7 -1
- package/src/canvas/iframe-position.ts +5 -6
- package/src/canvas/iframe-protocol.ts +106 -5
- package/src/canvas/iframe-render.ts +373 -5
- package/src/canvas/iframe-slash.ts +2 -2
- package/src/canvas/iframe-subtree.ts +5 -8
- package/src/canvas/path-mapping.ts +25 -3
- package/src/canvas/popover-path.ts +106 -0
- package/src/canvas/popover-state.ts +155 -0
- package/src/canvas/surface-registry.ts +21 -10
- package/src/collab/presence-chips.ts +51 -73
- package/src/commands/app-commands.ts +10 -0
- package/src/commands/budget.ts +12 -0
- package/src/commands/command-args.ts +369 -6
- package/src/commands/defaults.ts +44 -14
- package/src/commands/live-context.ts +11 -5
- package/src/commands/reference.ts +12 -2
- package/src/commands/registry.ts +165 -8
- package/src/content/entry-commands.ts +16 -23
- package/src/content/entry-editor.ts +144 -101
- package/src/editor/canvas-slash-bridge.ts +2 -2
- package/src/editor/context-menu.ts +49 -200
- package/src/editor/convert-to-component.ts +42 -82
- package/src/editor/convert-to-repeater.ts +132 -173
- package/src/editor/inline-edit.ts +11 -0
- package/src/editor/shortcuts.ts +65 -26
- package/src/editor/slash-menu.ts +150 -157
- package/src/files/file-ops.ts +117 -11
- package/src/files/files.ts +943 -660
- package/src/files/json-layout.ts +474 -0
- package/src/files/serialize-document.ts +8 -1
- package/src/format/convert-file.ts +16 -10
- package/src/format/format-host.ts +50 -1
- package/src/github/github-auth.ts +71 -29
- package/src/github/github-publish.ts +57 -65
- package/src/grid/cell-editors.ts +46 -4
- package/src/grid/cell-popovers.ts +65 -62
- package/src/grid/grid-open.ts +86 -64
- package/src/grid/grid-panel.ts +390 -469
- package/src/grid/redirects-grid.ts +40 -44
- package/src/hosting/layout.ts +2 -0
- package/src/i18n/i18n-commands.ts +127 -62
- package/src/media/media-pane.ts +83 -133
- package/src/new-project/add-repo-modal.ts +125 -176
- package/src/new-project/import-tab.ts +181 -252
- package/src/new-project/location-fields.ts +93 -160
- package/src/new-project/new-project-modal.ts +376 -367
- package/src/packages/jxsuite-update.ts +76 -18
- package/src/panels/activity-panel.ts +137 -104
- package/src/panels/ai-chat/chat-markdown.ts +15 -13
- package/src/panels/ai-chat/chat-view.ts +307 -472
- package/src/panels/ai-chat/composer.ts +175 -163
- package/src/panels/ai-chat/sessions-view.ts +31 -62
- package/src/panels/ai-panel.ts +210 -185
- package/src/panels/block-action-bar.ts +437 -643
- package/src/panels/bottom-dock.ts +112 -47
- package/src/panels/chat-panel.ts +19 -14
- package/src/panels/data-explorer.ts +141 -102
- package/src/panels/data-grid.ts +183 -150
- package/src/panels/dnd.ts +75 -20
- package/src/panels/editors.ts +26 -19
- package/src/panels/elements-panel.ts +243 -186
- package/src/panels/empty-state.ts +26 -42
- package/src/panels/events-panel.ts +950 -729
- package/src/panels/formula-workspace.ts +434 -207
- package/src/panels/frontmatter-fields.ts +185 -153
- package/src/panels/frontmatter-panel.ts +411 -187
- package/src/panels/git-diff-open.ts +148 -0
- package/src/panels/git-panel.ts +679 -605
- package/src/panels/head-panel.ts +617 -435
- package/src/panels/i18n-panel.ts +153 -133
- package/src/panels/imports-panel.ts +388 -414
- package/src/panels/jump-bar.ts +174 -147
- package/src/panels/layers-panel.ts +785 -671
- package/src/panels/left-panel.ts +166 -94
- package/src/panels/navigator-panels.ts +1 -1
- package/src/panels/pane-context.ts +529 -677
- package/src/panels/pane-grid.ts +265 -241
- package/src/panels/panel-registry.ts +15 -4
- package/src/panels/problems-panel.ts +177 -99
- package/src/panels/properties-panel.ts +1525 -966
- package/src/panels/provenance.ts +31 -113
- package/src/panels/quick-search.ts +217 -172
- package/src/panels/right-panel.ts +135 -169
- package/src/panels/seo-modal.ts +346 -167
- package/src/panels/settings-menu.ts +109 -646
- package/src/panels/settings-pane.ts +102 -86
- package/src/panels/signals-panel.ts +1318 -1172
- package/src/panels/statement-editor.ts +556 -428
- package/src/panels/style-panel.ts +1367 -630
- package/src/panels/style-utils.ts +36 -32
- package/src/panels/stylebook-doc.ts +30 -73
- package/src/panels/stylebook-layers-panel.ts +202 -109
- package/src/panels/stylebook-panel.ts +124 -88
- package/src/panels/tab-strip.ts +385 -287
- package/src/platforms/cloud.ts +106 -16
- package/src/platforms/devserver.ts +13 -0
- package/src/publish/deploy-checklist.ts +124 -78
- package/src/publish/publish-commands.ts +4 -12
- package/src/publish/publish-panel.ts +134 -328
- package/src/services/a11y-report.ts +100 -43
- package/src/services/ai-command-tools.ts +468 -0
- package/src/services/ai-session-store.ts +6 -0
- package/src/services/ai-system-prompt.ts +110 -18
- package/src/services/ai-tools.ts +28 -143
- package/src/services/ai-write-report.ts +174 -0
- package/src/services/document-assistant.ts +50 -2
- package/src/services/idle.ts +16 -14
- package/src/services/live-surfaces.ts +237 -0
- package/src/services/model-uri.ts +75 -0
- package/src/services/notify.ts +63 -6
- package/src/services/popover-report.ts +325 -0
- package/src/services/surface-registry.ts +56 -0
- package/src/services/tool-executor.ts +6 -0
- package/src/settings/contexts-section.ts +301 -299
- package/src/settings/contributed-section.ts +361 -222
- package/src/settings/css-vars-editor.ts +320 -325
- package/src/settings/defs-editor.ts +572 -535
- package/src/settings/dependencies-editor.ts +79 -107
- package/src/settings/extension-commands.ts +379 -0
- package/src/settings/extension-rows.ts +113 -0
- package/src/settings/extensions-section.ts +287 -0
- package/src/settings/general-settings.ts +130 -181
- package/src/settings/head-editor.ts +10 -305
- package/src/settings/locales-section.ts +146 -196
- package/src/settings/preferences-accounts.ts +1 -1
- package/src/settings/preferences-dialog.ts +350 -330
- package/src/settings/project-sections.ts +108 -181
- package/src/settings/schema-field-ui.ts +11 -399
- package/src/settings/section-registry.ts +8 -1
- package/src/settings/settings-document.ts +31 -29
- package/src/shell/tree.ts +42 -87
- package/src/shell.ts +48 -36
- package/src/studio.ts +90 -67
- package/src/style/token-ref.ts +0 -39
- package/src/surfaces/about.json +263 -0
- package/src/surfaces/about.ts +163 -0
- package/src/surfaces/add-repo.json +486 -0
- package/src/surfaces/add-repo.ts +236 -0
- package/src/surfaces/ai-chat.json +2185 -0
- package/src/surfaces/ai-chat.ts +549 -0
- package/src/surfaces/ai-credentials-form.json +332 -0
- package/src/surfaces/ai-credentials-form.ts +151 -0
- package/src/surfaces/ai-managed-connect.json +108 -0
- package/src/surfaces/ai-managed-connect.ts +123 -0
- package/src/surfaces/ai-model-picker.json +114 -0
- package/src/surfaces/ai-model-picker.ts +139 -0
- package/src/surfaces/block-action-bar.json +640 -0
- package/src/surfaces/block-action-bar.ts +368 -0
- package/src/surfaces/bottom-dock.json +154 -0
- package/src/surfaces/bottom-dock.ts +125 -0
- package/src/surfaces/canvas-stage.json +444 -0
- package/src/surfaces/canvas-stage.ts +253 -0
- package/src/surfaces/cf-account-picker.json +300 -0
- package/src/surfaces/cf-account-picker.ts +214 -0
- package/src/surfaces/commandbar.json +984 -0
- package/src/{panels/toolbar.ts → surfaces/commandbar.ts} +414 -389
- package/src/surfaces/convert-repeater.json +309 -0
- package/src/surfaces/convert-repeater.ts +276 -0
- package/src/surfaces/data-actions.json +157 -0
- package/src/surfaces/data-actions.ts +115 -0
- package/src/surfaces/dialog.json +289 -0
- package/src/surfaces/dialog.ts +343 -0
- package/src/surfaces/diff-toolbar.json +266 -0
- package/src/surfaces/diff-toolbar.ts +139 -0
- package/src/surfaces/doc-header.json +739 -0
- package/src/surfaces/doc-header.ts +223 -0
- package/src/surfaces/empty-state.json +152 -0
- package/src/surfaces/empty-state.ts +173 -0
- package/src/surfaces/entry-editor.json +281 -0
- package/src/surfaces/entry-editor.ts +191 -0
- package/src/surfaces/expression-editor.json +977 -0
- package/src/surfaces/expression-editor.ts +266 -0
- package/src/surfaces/files-panel.json +592 -0
- package/src/surfaces/files-panel.ts +301 -0
- package/src/surfaces/formula-palette.json +364 -0
- package/src/surfaces/formula-palette.ts +340 -0
- package/src/surfaces/git-panel.json +1822 -0
- package/src/surfaces/git-panel.ts +272 -0
- package/src/surfaces/github-auth.json +112 -0
- package/src/surfaces/github-auth.ts +139 -0
- package/src/surfaces/github-publish.json +206 -0
- package/src/surfaces/github-publish.ts +169 -0
- package/src/surfaces/grid-cell.json +218 -0
- package/src/surfaces/grid-cell.ts +120 -0
- package/src/surfaces/grid-open.json +147 -0
- package/src/surfaces/grid-open.ts +87 -0
- package/src/surfaces/grid-panel.json +706 -0
- package/src/surfaces/grid-panel.ts +206 -0
- package/src/surfaces/grid-replace.json +179 -0
- package/src/surfaces/grid-replace.ts +89 -0
- package/src/surfaces/grid-views.json +446 -0
- package/src/surfaces/grid-views.ts +172 -0
- package/src/surfaces/inspector-dock.json +187 -0
- package/src/surfaces/inspector-dock.ts +161 -0
- package/src/surfaces/jump-bar.json +243 -0
- package/src/surfaces/jump-bar.ts +129 -0
- package/src/surfaces/jxsuite-update.json +146 -0
- package/src/surfaces/jxsuite-update.ts +149 -0
- package/src/surfaces/library-pane.json +1509 -0
- package/src/surfaces/library-pane.ts +363 -0
- package/src/surfaces/logic-panel.json +1949 -0
- package/src/surfaces/logic-panel.ts +369 -0
- package/src/surfaces/logic-workspace.json +685 -0
- package/src/surfaces/logic-workspace.ts +238 -0
- package/src/surfaces/media-browser.json +303 -0
- package/src/surfaces/media-browser.ts +145 -0
- package/src/surfaces/media-field.json +163 -0
- package/src/surfaces/media-field.ts +116 -0
- package/src/surfaces/media-pane.json +513 -0
- package/src/surfaces/media-pane.ts +197 -0
- package/src/surfaces/menu.json +232 -0
- package/src/surfaces/menu.ts +375 -0
- package/src/surfaces/navigator-dock.json +113 -0
- package/src/surfaces/navigator-dock.ts +130 -0
- package/src/surfaces/new-project.json +1654 -0
- package/src/surfaces/new-project.ts +411 -0
- package/src/surfaces/palette.json +535 -0
- package/src/surfaces/pane-context.json +1497 -0
- package/src/surfaces/pane-context.ts +513 -0
- package/src/surfaces/pane-grid.json +188 -0
- package/src/surfaces/pane-grid.ts +250 -0
- package/src/surfaces/panel-activity.json +563 -0
- package/src/surfaces/panel-activity.ts +187 -0
- package/src/surfaces/panel-data.json +141 -0
- package/src/surfaces/panel-data.ts +156 -0
- package/src/surfaces/panel-deploy-checklist.json +283 -0
- package/src/surfaces/panel-deploy-checklist.ts +175 -0
- package/src/surfaces/panel-elements.json +367 -0
- package/src/surfaces/panel-elements.ts +175 -0
- package/src/surfaces/panel-i18n.json +569 -0
- package/src/surfaces/panel-i18n.ts +212 -0
- package/src/surfaces/panel-imports.json +780 -0
- package/src/surfaces/panel-imports.ts +209 -0
- package/src/surfaces/panel-outline.json +734 -0
- package/src/surfaces/panel-outline.ts +326 -0
- package/src/surfaces/panel-page.json +1017 -0
- package/src/surfaces/panel-page.ts +240 -0
- package/src/surfaces/panel-problems.json +497 -0
- package/src/surfaces/panel-problems.ts +157 -0
- package/src/surfaces/panel-signals.json +1973 -0
- package/src/surfaces/panel-signals.ts +436 -0
- package/src/surfaces/panel-stylebook-layers.json +317 -0
- package/src/surfaces/panel-stylebook-layers.ts +155 -0
- package/src/surfaces/preferences.json +850 -0
- package/src/surfaces/preferences.ts +332 -0
- package/src/surfaces/progress-modal.json +110 -0
- package/src/surfaces/progress-modal.ts +150 -0
- package/src/surfaces/properties-panel.json +1578 -0
- package/src/surfaces/properties-panel.ts +337 -0
- package/src/surfaces/publish.json +945 -0
- package/src/surfaces/publish.ts +392 -0
- package/src/surfaces/push-plan.json +110 -0
- package/src/surfaces/push-plan.ts +87 -0
- package/src/surfaces/rail.json +255 -0
- package/src/surfaces/rail.ts +206 -0
- package/src/surfaces/reference-field.json +191 -0
- package/src/surfaces/reference-field.ts +168 -0
- package/src/surfaces/schema-builder.json +1011 -0
- package/src/surfaces/schema-builder.ts +181 -0
- package/src/surfaces/schema-form.json +1013 -0
- package/src/surfaces/schema-form.ts +287 -0
- package/src/surfaces/secret-field.json +60 -0
- package/src/surfaces/secret-field.ts +146 -0
- package/src/surfaces/seo.json +932 -0
- package/src/surfaces/seo.ts +334 -0
- package/src/surfaces/settings-contexts.json +538 -0
- package/src/surfaces/settings-contexts.ts +196 -0
- package/src/surfaces/settings-contributed.json +489 -0
- package/src/surfaces/settings-contributed.ts +199 -0
- package/src/surfaces/settings-css-vars.json +820 -0
- package/src/surfaces/settings-css-vars.ts +199 -0
- package/src/surfaces/settings-defs.json +1363 -0
- package/src/surfaces/settings-defs.ts +232 -0
- package/src/surfaces/settings-deploy.json +108 -0
- package/src/surfaces/settings-deploy.ts +135 -0
- package/src/surfaces/settings-extensions.json +486 -0
- package/src/surfaces/settings-extensions.ts +201 -0
- package/src/surfaces/settings-head.json +779 -0
- package/src/surfaces/settings-head.ts +397 -0
- package/src/surfaces/settings-locales.json +420 -0
- package/src/surfaces/settings-locales.ts +137 -0
- package/src/surfaces/settings-overview.json +423 -0
- package/src/surfaces/settings-overview.ts +218 -0
- package/src/surfaces/settings-packages.json +549 -0
- package/src/surfaces/settings-packages.ts +158 -0
- package/src/surfaces/settings-pane.json +147 -0
- package/src/surfaces/settings-pane.ts +150 -0
- package/src/surfaces/settings-rawjson.json +104 -0
- package/src/surfaces/settings-rawjson.ts +107 -0
- package/src/surfaces/shell.json +99 -0
- package/src/surfaces/shell.ts +30 -0
- package/src/surfaces/slash-menu.json +180 -0
- package/src/surfaces/slash-menu.ts +272 -0
- package/src/surfaces/statements.json +607 -0
- package/src/surfaces/statements.ts +238 -0
- package/src/surfaces/statusbar.json +94 -0
- package/src/{panels → surfaces}/statusbar.ts +163 -90
- package/src/surfaces/style-panel.json +1643 -0
- package/src/surfaces/style-panel.ts +338 -0
- package/src/surfaces/stylebook-chrome.json +122 -0
- package/src/surfaces/stylebook-chrome.ts +122 -0
- package/src/surfaces/tab-strip.json +448 -0
- package/src/surfaces/tab-strip.ts +200 -0
- package/src/surfaces/target-line.json +419 -0
- package/src/surfaces/target-line.ts +349 -0
- package/src/surfaces/toasts.json +189 -0
- package/src/surfaces/welcome.json +571 -0
- package/src/surfaces/welcome.ts +338 -0
- package/src/tabs/project-config.ts +71 -15
- package/src/tabs/tab.ts +52 -1
- package/src/types.ts +22 -0
- package/src/ui/ai-credentials-form.ts +104 -100
- package/src/ui/ai-managed-connect.ts +54 -36
- package/src/ui/ai-model-picker.ts +75 -47
- package/src/ui/cf-account-picker.ts +76 -141
- package/src/ui/color-selector.ts +80 -301
- package/src/ui/dynamic-slot.ts +43 -283
- package/src/ui/expression-editor.ts +797 -576
- package/src/ui/field-input.ts +8 -181
- package/src/ui/form-controls.ts +838 -366
- package/src/ui/formula-chips.ts +80 -85
- package/src/ui/kit.ts +33 -0
- package/src/ui/layers.ts +293 -593
- package/src/ui/media-picker.ts +203 -284
- package/src/ui/panel-resize.ts +251 -64
- package/src/ui/popover-surface.ts +153 -0
- package/src/ui/progress-modal.ts +22 -60
- package/src/ui/regions.ts +13 -7
- package/src/ui/schema-form.ts +906 -440
- package/src/ui/surface.ts +122 -0
- package/src/ui/unit-selector.ts +15 -131
- package/src/ui/value-source.ts +14 -0
- package/src/ui/virtual-window.ts +88 -9
- package/src/utils/canvas-media.ts +72 -0
- package/src/utils/edit-display.ts +7 -2
- package/src/utils/element-selectors.ts +69 -0
- package/src/utils/link-target.ts +2 -2
- package/src/utils/studio-utils.ts +0 -10
- package/src/view.ts +15 -0
- package/src/workspace/pane-derive.ts +36 -14
- package/src/workspace/workspace.ts +15 -6
- package/styles/canvas.css +72 -467
- package/styles/forced-colors.css +48 -82
- package/styles/forced-colors.json +41 -0
- package/styles/inspector.css +2 -1301
- package/styles/overlays.css +96 -2823
- package/styles/panels.css +6 -1423
- package/styles/shell-frame.css +272 -0
- package/styles/shell-frame.json +227 -0
- package/styles/shell.css +0 -1568
- package/styles/tokens.css +65 -136
- package/styles/tokens.json +84 -0
- package/dist/chunks/Overlay.dev-etqjwyf9.js +0 -23
- package/dist/chunks/adapter-jkcyhgtr.js +0 -14
- package/dist/chunks/cf-account-picker-en86v7x7.js +0 -163
- package/dist/chunks/cf-settings-45fgyx8y.js +0 -21
- package/dist/chunks/components-zmx10t62.js +0 -21
- package/dist/chunks/content-source-48xg86wj.js +0 -49
- package/dist/chunks/convert-to-repeater-43tfn7cs.js +0 -268
- package/dist/chunks/editor-cptq5jp1.js +0 -37
- package/dist/chunks/entry-commands-e63f1xc0.js +0 -46
- package/dist/chunks/extension-sections-txv08xxg.js +0 -311
- package/dist/chunks/file-ops-wbh4hhsx.js +0 -48
- package/dist/chunks/files-3kfkwhk4.js +0 -93
- package/dist/chunks/flow-qbfgrpeh.js +0 -634
- package/dist/chunks/focus-trap.esm-9t2drp0g.js +0 -1025
- package/dist/chunks/focus-visible-6eg70z18.js +0 -167
- package/dist/chunks/format-host-w16q81tf.js +0 -43
- package/dist/chunks/fs-events-hrrg328g.js +0 -21
- package/dist/chunks/git-panel-532whr1y.js +0 -59
- package/dist/chunks/index-zqxmqxmh.js +0 -109
- package/dist/chunks/jx-validate-8er6gbxy.js +0 -19
- package/dist/chunks/layers-panel-07hm7g5j.js +0 -67
- package/dist/chunks/layers-q75tj2mf.js +0 -45
- package/dist/chunks/lit-html-j055mkh8.js +0 -22
- package/dist/chunks/monaco-buffer-dqw0xxpx.js +0 -25
- package/dist/chunks/notify-yjm79n4s.js +0 -30
- package/dist/chunks/parse-24d0gay3.js +0 -19
- package/dist/chunks/platform-ba1j1gbh.js +0 -16
- package/dist/chunks/publish-panel-v9st96ja.js +0 -29
- package/dist/chunks/quick-search-zccjp6gv.js +0 -66
- package/dist/chunks/references-3qx8fkyp.js +0 -29
- package/dist/chunks/right-panel-vm3b6kwy.js +0 -46
- package/dist/chunks/section-registry-sx1ykvkw.js +0 -30
- package/dist/chunks/sp-overlay.dev-qgvhnxf4.js +0 -18
- package/dist/chunks/sp-popover.dev-n2etmqdp.js +0 -9
- package/dist/chunks/sp-progress-circle.dev-hryhj0es.js +0 -15
- package/dist/chunks/sp-tooltip.dev-4sastdnw.js +0 -15
- package/dist/chunks/sp-tray.dev-tkbscm06.js +0 -199
- package/dist/chunks/studio-0a5qrh01.js +0 -3
- package/dist/chunks/studio-0bq6eh7v.js +0 -12
- package/dist/chunks/studio-18j3bmcz.js +0 -14
- package/dist/chunks/studio-1ngbejft.js +0 -181
- package/dist/chunks/studio-4b5z1x43.js +0 -424
- package/dist/chunks/studio-4n2b5gzb.js +0 -357
- package/dist/chunks/studio-4rzyrtjz.js +0 -426
- package/dist/chunks/studio-5fx3g9jg.js +0 -4325
- package/dist/chunks/studio-5myknm0a.js +0 -1903
- package/dist/chunks/studio-7afd21nw.js +0 -67
- package/dist/chunks/studio-7nte2hj4.js +0 -613
- package/dist/chunks/studio-8jpzqk5s.js +0 -128
- package/dist/chunks/studio-8q517dfr.js +0 -24
- package/dist/chunks/studio-950k0dx6.js +0 -6939
- package/dist/chunks/studio-9n4mrmnb.js +0 -184
- package/dist/chunks/studio-a0tswy0w.js +0 -58
- package/dist/chunks/studio-ahnzd9rg.js +0 -23
- package/dist/chunks/studio-cmb03bg5.js +0 -13890
- package/dist/chunks/studio-d1ks410h.js +0 -175
- package/dist/chunks/studio-ef49pnzx.js +0 -387
- package/dist/chunks/studio-eqq1w638.js +0 -113
- package/dist/chunks/studio-ew0djmhg.js +0 -341
- package/dist/chunks/studio-gfgb8pe6.js +0 -1652
- package/dist/chunks/studio-h4rxscfc.js +0 -10
- package/dist/chunks/studio-jc994dnr.js +0 -1066
- package/dist/chunks/studio-kyh9avvv.js +0 -28
- package/dist/chunks/studio-m3hwn7y1.js +0 -120
- package/dist/chunks/studio-mtfnaqs9.js +0 -659
- package/dist/chunks/studio-n6j9t10q.js +0 -318
- package/dist/chunks/studio-n8b9wqwy.js +0 -291
- package/dist/chunks/studio-qcy05dp8.js +0 -1743
- package/dist/chunks/studio-qq6jym04.js +0 -53
- package/dist/chunks/studio-rdx8jcxy.js +0 -83
- package/dist/chunks/studio-rn9ta2mz.js +0 -111
- package/dist/chunks/studio-t7qb9db8.js +0 -665
- package/dist/chunks/studio-tmc5emrw.js +0 -8
- package/dist/chunks/studio-z6nw2ek2.js +0 -18
- package/dist/chunks/studio-zczps70q.js +0 -378
- package/dist/chunks/studio-zqazsct2.js +0 -1823
- package/dist/chunks/workspace-fjx52ryv.js +0 -89
- package/src/panels/activity-bar.ts +0 -251
- package/src/panels/panel-scheduler.ts +0 -219
- package/src/panels/style-inputs.ts +0 -237
- package/src/panels/target-line.ts +0 -274
- package/src/panels/welcome-screen.ts +0 -346
- package/src/ui/button-group.ts +0 -102
- package/src/ui/choice-field.ts +0 -72
- package/src/ui/field-row.ts +0 -249
- package/src/ui/formula-palette.ts +0 -213
- package/src/ui/icons.ts +0 -52
- package/src/ui/jx-theme.ts +0 -130
- package/src/ui/spectrum.ts +0 -340
- package/src/ui/value-selector.ts +0 -174
- package/src/ui/widgets.ts +0 -172
- /package/dist/chunks/{javascript-s56a8dpk.css → javascript-4abzjcy9.css} +0 -0
- /package/dist/chunks/{jsonMode-zr9sw0c7.css → jsonMode-vvmpmk34.css} +0 -0
- /package/dist/chunks/{monaco-setup-pav68602.css → monaco-setup-8vbyqnhr.css} +0 -0
- /package/dist/chunks/{tsMode-ef187txx.css → tsMode-hnxxb73h.css} +0 -0
package/src/ui/media-picker.ts
CHANGED
|
@@ -1,30 +1,35 @@
|
|
|
1
1
|
/// <reference lib="dom" />
|
|
2
2
|
/**
|
|
3
|
-
* Media Picker —
|
|
3
|
+
* Media Picker — the project's media, and the two surfaces that offer them.
|
|
4
4
|
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
5
|
+
* The FIELD (`surfaces/media-field.json`) is a control a row draws: a thumbnail of what the value
|
|
6
|
+
* names, the value itself, an Upload button that adds a new file to the project and assigns it, and
|
|
7
|
+
* a Browse button. The BROWSER (`surfaces/media-browser.json`) is the panel Browse opens: a search
|
|
8
|
+
* box over the files under `public/`, with thumbnail previews for images.
|
|
9
|
+
*
|
|
10
|
+
* **This module is the flow, not the markup.** Both surfaces are Jx documents now; what is left
|
|
11
|
+
* here is which files count as media, what a row's caption says, how long a keystroke waits before
|
|
12
|
+
* it becomes a document write, and what a pick commits. Callers that used to interpolate a template
|
|
13
|
+
* returned from here draw an empty box and call {@link mountMediaPicker} instead — a document
|
|
14
|
+
* cannot be handed back as a value, and a document CLEARS the host it is given, so the two could
|
|
15
|
+
* never have shared a container anyway.
|
|
8
16
|
*
|
|
9
17
|
* **The browse list carries metadata, and it costs nothing.** Size comes from the directory listing
|
|
10
18
|
* the widget already performs to enumerate the files (`seedMediaMeta`), and pixel dimensions come
|
|
11
19
|
* from the thumbnails it already loads (`recordImageSize`) — measuring an image is a decode the
|
|
12
20
|
* `<img>` has finished by the time `load` fires, so the caption is a read of work already done
|
|
13
21
|
* 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
|
|
15
|
-
*
|
|
22
|
+
* every document in the project per query, and fifty of those to caption a list is the wrong trade.
|
|
23
|
+
* Usage is asked once, about one file, where it changes a decision — the delete confirmation
|
|
16
24
|
* (`files/media-usage.ts`).
|
|
17
25
|
*
|
|
18
26
|
* @docs studio/projects/media
|
|
19
27
|
*/
|
|
20
28
|
|
|
21
|
-
import { html, render as litRender, nothing } from "lit-html";
|
|
22
|
-
import { live } from "lit-html/directives/live.js";
|
|
23
|
-
import { ref } from "lit-html/directives/ref.js";
|
|
24
29
|
import { getPlatform } from "../platform";
|
|
25
30
|
import { debouncedStyleCommit, renderOnly } from "../store";
|
|
26
|
-
import {
|
|
27
|
-
import
|
|
31
|
+
import { mountMediaFieldSurface } from "../surfaces/media-field";
|
|
32
|
+
import { openMediaBrowserSurface } from "../surfaces/media-browser";
|
|
28
33
|
import { rectOf } from "../utils/geometry";
|
|
29
34
|
import { previewAssetSrc } from "../canvas/asset-refs";
|
|
30
35
|
import {
|
|
@@ -42,6 +47,8 @@ import {
|
|
|
42
47
|
seedMediaMeta,
|
|
43
48
|
} from "../files/media-meta";
|
|
44
49
|
import { mediaSiteUrl, previewFileSrc } from "../files/media-paths";
|
|
50
|
+
import type { MediaBrowserRow, MediaBrowserSurfaceHandle } from "../surfaces/media-browser";
|
|
51
|
+
import type { MediaFieldHandle, MediaFieldView } from "../surfaces/media-field";
|
|
45
52
|
|
|
46
53
|
// ─── Media file cache ────────────────────────────────────────────────────────
|
|
47
54
|
|
|
@@ -101,7 +108,7 @@ async function loadMediaCache() {
|
|
|
101
108
|
const platform = getPlatform();
|
|
102
109
|
mediaCache = await collectMedia("public", platform);
|
|
103
110
|
mediaCacheLoaded = true;
|
|
104
|
-
// Re-render the host panels so the browse
|
|
111
|
+
// Re-render the host panels so the browse panel has entries to show once the async listing
|
|
105
112
|
// Resolves. Mirrors loadLayoutEntries()'s renderOnly() in head-panel.
|
|
106
113
|
renderOnly("leftPanel", "rightPanel", "frontmatterPanel");
|
|
107
114
|
}
|
|
@@ -118,70 +125,59 @@ export function invalidateMediaCache() {
|
|
|
118
125
|
invalidateMediaMeta();
|
|
119
126
|
}
|
|
120
127
|
|
|
121
|
-
// ───
|
|
122
|
-
|
|
123
|
-
/** @type {((val: string) => void) | null} */
|
|
124
|
-
let _popoverOnCommit: ((val: string) => void) | null = null;
|
|
128
|
+
// ─── The browser ─────────────────────────────────────────────────────────────
|
|
125
129
|
|
|
126
|
-
/**
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Which layer the open popover is living in.
|
|
130
|
-
*
|
|
131
|
-
* Chosen from the anchor at open time and then REMEMBERED, because `getLayerSlot` keys its slots by
|
|
132
|
-
* `${layer}:${id}`: dismissing through a different layer than the one that opened would clear an
|
|
133
|
-
* empty slot and leave the real popover on screen.
|
|
134
|
-
*/
|
|
135
|
-
let _popoverLayer: LayerKind = "popover";
|
|
130
|
+
/** The most rows the panel lists. Everything past it is counted rather than drawn. */
|
|
131
|
+
const BROWSE_LIMIT = 50;
|
|
136
132
|
|
|
137
|
-
/** The open
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
133
|
+
/** The open panel, and what a pick in it commits. One at a time. */
|
|
134
|
+
let _browser: MediaBrowserSurfaceHandle | null = null;
|
|
135
|
+
let _browserCommit: ((value: string) => void) | null = null;
|
|
136
|
+
let _browserFilter = "";
|
|
137
|
+
/** Where the panel was opened, kept so a filter keystroke does not move it. */
|
|
138
|
+
let _browserOrigin = { x: 0, y: 0 };
|
|
141
139
|
|
|
142
|
-
/**
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
140
|
+
/** What the panel shows for the filter that stands now. */
|
|
141
|
+
function browserView() {
|
|
142
|
+
const query = _browserFilter.toLowerCase();
|
|
143
|
+
const filtered = query
|
|
144
|
+
? mediaCache.filter(
|
|
145
|
+
(m) => m.path.toLowerCase().includes(query) || m.name.toLowerCase().includes(query),
|
|
146
|
+
)
|
|
147
|
+
: mediaCache;
|
|
148
|
+
const listed = filtered.slice(0, BROWSE_LIMIT);
|
|
149
|
+
const rows: MediaBrowserRow[] = listed.map((m) => {
|
|
150
|
+
const caption = mediaMetaSummary(peekMediaMeta(m.file));
|
|
151
|
+
return {
|
|
152
|
+
caption,
|
|
153
|
+
captionState: caption ? "shown" : "hidden",
|
|
154
|
+
file: m.file,
|
|
155
|
+
key: m.file,
|
|
156
|
+
name: m.name,
|
|
157
|
+
path: m.path,
|
|
158
|
+
thumbSrc: m.isImage ? previewFileSrc(m.file) : "",
|
|
159
|
+
thumbState: m.isImage ? "shown" : "hidden",
|
|
160
|
+
};
|
|
161
|
+
});
|
|
162
|
+
return {
|
|
163
|
+
emptyLabel: "No matches",
|
|
164
|
+
filter: _browserFilter,
|
|
165
|
+
moreLabel: `…${filtered.length - BROWSE_LIMIT} more`,
|
|
166
|
+
moreState: (filtered.length > BROWSE_LIMIT ? "shown" : "hidden") as "hidden" | "shown",
|
|
167
|
+
rows,
|
|
168
|
+
rowsState: (rows.length > 0 ? "listed" : "empty") as "empty" | "listed",
|
|
169
|
+
x: _browserOrigin.x,
|
|
170
|
+
y: _browserOrigin.y,
|
|
171
|
+
};
|
|
153
172
|
}
|
|
154
173
|
|
|
155
|
-
/**
|
|
156
|
-
let _popoverFilterEl: HTMLInputElement | null = null;
|
|
157
|
-
|
|
158
|
-
let _popoverFilter = "";
|
|
159
|
-
|
|
174
|
+
/** Take the panel down. Idempotent, and it forgets what a pick would have committed. */
|
|
160
175
|
function dismissMediaPickerPopover() {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
document.removeEventListener("mousedown", onPopoverOutsideClick, true);
|
|
167
|
-
litRender(nothing, popoverSlot());
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/** @param {KeyboardEvent} e */
|
|
171
|
-
function onPopoverKeydown(e: KeyboardEvent) {
|
|
172
|
-
if (e.key === "Escape") {
|
|
173
|
-
dismissMediaPickerPopover();
|
|
174
|
-
e.preventDefault();
|
|
175
|
-
e.stopPropagation();
|
|
176
|
-
}
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
/** @param {MouseEvent} e */
|
|
180
|
-
function onPopoverOutsideClick(e: MouseEvent) {
|
|
181
|
-
const host = popoverSlot();
|
|
182
|
-
if (!host.contains(e.target as Node)) {
|
|
183
|
-
dismissMediaPickerPopover();
|
|
184
|
-
}
|
|
176
|
+
const open = _browser;
|
|
177
|
+
_browser = null;
|
|
178
|
+
_browserCommit = null;
|
|
179
|
+
_browserFilter = "";
|
|
180
|
+
open?.close();
|
|
185
181
|
}
|
|
186
182
|
|
|
187
183
|
/** A repaint scheduled by a thumbnail that just reported its size, or 0 when none is pending. */
|
|
@@ -189,180 +185,65 @@ let _sizeRepaint = 0;
|
|
|
189
185
|
|
|
190
186
|
/**
|
|
191
187
|
* Fold a loaded thumbnail's intrinsic size into the metadata cache and, if that was news, repaint
|
|
192
|
-
* the
|
|
188
|
+
* the panel once so the caption appears.
|
|
193
189
|
*
|
|
194
|
-
* The repaint is coalesced across a whole
|
|
195
|
-
* loop:
|
|
196
|
-
* `recordImageSize` returns false the second time
|
|
190
|
+
* The repaint is coalesced across a whole list of images landing in the same frame, and it cannot
|
|
191
|
+
* loop: a repaint that changes nothing about a row leaves its `<img>` alone, and a row that IS
|
|
192
|
+
* rebuilt fires `load` again from cache, where `recordImageSize` returns false the second time
|
|
193
|
+
* because the measurement has not changed.
|
|
197
194
|
*/
|
|
198
|
-
function noteImageSize(file: string,
|
|
199
|
-
|
|
200
|
-
if (!img || !recordImageSize(file, img.naturalWidth, img.naturalHeight) || _sizeRepaint !== 0) {
|
|
195
|
+
function noteImageSize(file: string, width: number, height: number) {
|
|
196
|
+
if (!recordImageSize(file, width, height) || _sizeRepaint !== 0) {
|
|
201
197
|
return;
|
|
202
198
|
}
|
|
203
199
|
_sizeRepaint = requestAnimationFrame(() => {
|
|
204
200
|
_sizeRepaint = 0;
|
|
205
|
-
|
|
206
|
-
renderMediaPickerPopover();
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function renderMediaPickerPopover() {
|
|
212
|
-
const host = popoverSlot();
|
|
213
|
-
const rect = _popoverAnchorEl ? rectOf(_popoverAnchorEl) : undefined;
|
|
214
|
-
if (!rect) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const query = _popoverFilter.toLowerCase();
|
|
219
|
-
const filtered = query
|
|
220
|
-
? mediaCache.filter(
|
|
221
|
-
(m) => m.path.toLowerCase().includes(query) || m.name.toLowerCase().includes(query),
|
|
222
|
-
)
|
|
223
|
-
: mediaCache;
|
|
224
|
-
const options = filtered.slice(0, 50);
|
|
225
|
-
|
|
226
|
-
// Compute initial position below the anchor
|
|
227
|
-
let { left } = rect;
|
|
228
|
-
let top = rect.bottom + 4;
|
|
229
|
-
|
|
230
|
-
// Estimate popover dimensions for viewport clamping before first paint
|
|
231
|
-
const estimatedWidth = 280;
|
|
232
|
-
const estimatedHeight = Math.min(options.length * 36 + 48, 360);
|
|
233
|
-
|
|
234
|
-
if (left + estimatedWidth > window.innerWidth - 8) {
|
|
235
|
-
left = Math.max(8, window.innerWidth - estimatedWidth - 8);
|
|
236
|
-
}
|
|
237
|
-
if (top + estimatedHeight > window.innerHeight - 8) {
|
|
238
|
-
top = Math.max(8, rect.top - estimatedHeight - 4);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
let _popoverEl: HTMLElement | null = null;
|
|
242
|
-
|
|
243
|
-
litRender(
|
|
244
|
-
html`
|
|
245
|
-
<sp-popover
|
|
246
|
-
open
|
|
247
|
-
data-jx-region="overlay.menu:media-picker"
|
|
248
|
-
${ref((el) => {
|
|
249
|
-
_popoverEl = (el as HTMLElement | undefined) || null;
|
|
250
|
-
})}
|
|
251
|
-
style="position:fixed;left:${left}px;top:${top}px;z-index:${popoverZIndex()};max-height:360px;overflow-y:auto;min-width:240px"
|
|
252
|
-
>
|
|
253
|
-
<input
|
|
254
|
-
class="media-picker-filter"
|
|
255
|
-
type="text"
|
|
256
|
-
placeholder="Search images…"
|
|
257
|
-
autocomplete="off"
|
|
258
|
-
style="display:block;width:100%;box-sizing:border-box;padding:6px 10px;border:none;border-bottom:1px solid var(--border, #444);outline:none;font-size:13px;background:transparent;color:inherit"
|
|
259
|
-
${ref((el) => {
|
|
260
|
-
_popoverFilterEl = (el as HTMLInputElement | null) || null;
|
|
261
|
-
})}
|
|
262
|
-
@input=${(e: Event) => {
|
|
263
|
-
_popoverFilter = (e.target as HTMLInputElement).value;
|
|
264
|
-
renderMediaPickerPopover();
|
|
265
|
-
}}
|
|
266
|
-
@click=${(e: MouseEvent) => e.stopPropagation()}
|
|
267
|
-
/>
|
|
268
|
-
<sp-menu
|
|
269
|
-
style="min-width:220px"
|
|
270
|
-
@change=${(e: Event) => {
|
|
271
|
-
_popoverOnCommit?.((e.target as HTMLInputElement).value);
|
|
272
|
-
dismissMediaPickerPopover();
|
|
273
|
-
}}
|
|
274
|
-
>
|
|
275
|
-
${
|
|
276
|
-
options.length > 0
|
|
277
|
-
? options.map((m) => {
|
|
278
|
-
const caption = mediaMetaSummary(peekMediaMeta(m.file));
|
|
279
|
-
return html`
|
|
280
|
-
<sp-menu-item value=${m.path}>
|
|
281
|
-
${
|
|
282
|
-
m.isImage
|
|
283
|
-
? html`<img
|
|
284
|
-
slot="icon"
|
|
285
|
-
src=${previewFileSrc(m.file)}
|
|
286
|
-
alt=""
|
|
287
|
-
style="width:24px;height:24px;object-fit:cover;border-radius:var(--spectrum-corner-radius-75, 2px)"
|
|
288
|
-
@load=${(e: Event) => noteImageSize(m.file, e.target)}
|
|
289
|
-
/>`
|
|
290
|
-
: nothing
|
|
291
|
-
}
|
|
292
|
-
${m.name}
|
|
293
|
-
${caption ? html`<span slot="description">${caption}</span>` : nothing}
|
|
294
|
-
</sp-menu-item>
|
|
295
|
-
`;
|
|
296
|
-
})
|
|
297
|
-
: html`<sp-menu-item disabled>No matches</sp-menu-item>`
|
|
298
|
-
}
|
|
299
|
-
${
|
|
300
|
-
filtered.length > 50
|
|
301
|
-
? html`<sp-menu-item disabled>…${filtered.length - 50} more</sp-menu-item>`
|
|
302
|
-
: nothing
|
|
303
|
-
}
|
|
304
|
-
</sp-menu>
|
|
305
|
-
</sp-popover>
|
|
306
|
-
`,
|
|
307
|
-
host,
|
|
308
|
-
);
|
|
309
|
-
|
|
310
|
-
// Fine-tune position after render using actual measured dimensions
|
|
311
|
-
requestAnimationFrame(() => {
|
|
312
|
-
if (_popoverEl) {
|
|
313
|
-
const popoverRect = rectOf(_popoverEl);
|
|
314
|
-
let adjLeft = popoverRect.left;
|
|
315
|
-
let adjTop = popoverRect.top;
|
|
316
|
-
let needsAdjust = false;
|
|
317
|
-
|
|
318
|
-
if (popoverRect.right > window.innerWidth - 4) {
|
|
319
|
-
adjLeft = Math.max(4, window.innerWidth - popoverRect.width - 4);
|
|
320
|
-
needsAdjust = true;
|
|
321
|
-
}
|
|
322
|
-
if (popoverRect.bottom > window.innerHeight - 4) {
|
|
323
|
-
adjTop = Math.max(4, window.innerHeight - popoverRect.height - 4);
|
|
324
|
-
needsAdjust = true;
|
|
325
|
-
}
|
|
326
|
-
if (popoverRect.left < 4) {
|
|
327
|
-
adjLeft = 4;
|
|
328
|
-
needsAdjust = true;
|
|
329
|
-
}
|
|
330
|
-
if (popoverRect.top < 4) {
|
|
331
|
-
adjTop = 4;
|
|
332
|
-
needsAdjust = true;
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
if (needsAdjust) {
|
|
336
|
-
_popoverEl.style.left = `${adjLeft}px`;
|
|
337
|
-
_popoverEl.style.top = `${adjTop}px`;
|
|
338
|
-
}
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
if (_popoverFilterEl) {
|
|
342
|
-
_popoverFilterEl.focus();
|
|
343
|
-
}
|
|
201
|
+
_browser?.update(browserView());
|
|
344
202
|
});
|
|
345
203
|
}
|
|
346
204
|
|
|
347
205
|
/**
|
|
206
|
+
* Open the media browser under `anchorEl` and commit whatever is picked.
|
|
207
|
+
*
|
|
208
|
+
* Exported because the panel is a SURFACE OF ITS OWN — it renders into the popover layer, not into
|
|
209
|
+
* the field that opened it — so a converted surface can offer the same browser without
|
|
210
|
+
* re-implementing it. `surfaces/doc-header.ts`'s Browse button is the first such caller.
|
|
211
|
+
*
|
|
348
212
|
* @param {HTMLElement} anchorEl
|
|
349
213
|
* @param {(val: string) => void} onCommit
|
|
350
214
|
*/
|
|
351
|
-
function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: string) => void) {
|
|
215
|
+
export function showMediaPickerPopover(anchorEl: HTMLElement, onCommit: (val: string) => void) {
|
|
352
216
|
dismissMediaPickerPopover();
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
217
|
+
_browserCommit = onCommit;
|
|
218
|
+
const box = rectOf(anchorEl);
|
|
219
|
+
/* Where it opens, once. `jx-popover` clamps a freshly shown panel into the viewport itself, so
|
|
220
|
+
nothing here measures the panel or flips it above a low anchor — that was the layer-div
|
|
221
|
+
popover's job because a layer div has no platform behind it. */
|
|
222
|
+
_browserOrigin = { x: box.left, y: box.bottom + 4 };
|
|
223
|
+
_browser = openMediaBrowserSurface(
|
|
224
|
+
browserView(),
|
|
225
|
+
{
|
|
226
|
+
dismissed: () => {
|
|
227
|
+
_browser = null;
|
|
228
|
+
_browserCommit = null;
|
|
229
|
+
_browserFilter = "";
|
|
230
|
+
},
|
|
231
|
+
measure: noteImageSize,
|
|
232
|
+
pick: (path: string) => {
|
|
233
|
+
const commit = _browserCommit;
|
|
234
|
+
dismissMediaPickerPopover();
|
|
235
|
+
commit?.(path);
|
|
236
|
+
},
|
|
237
|
+
setFilter: (value: string) => {
|
|
238
|
+
_browserFilter = value;
|
|
239
|
+
_browser?.update(browserView());
|
|
240
|
+
},
|
|
241
|
+
},
|
|
242
|
+
anchorEl,
|
|
243
|
+
);
|
|
363
244
|
}
|
|
364
245
|
|
|
365
|
-
// ───
|
|
246
|
+
// ─── Upload ──────────────────────────────────────────────────────────────────
|
|
366
247
|
|
|
367
248
|
/**
|
|
368
249
|
* Upload files chosen in a media field's file input and assign the first one to the field. Exported
|
|
@@ -385,11 +266,14 @@ export async function uploadAndAssign(
|
|
|
385
266
|
|
|
386
267
|
/**
|
|
387
268
|
* Open the OS file picker for a media field. The input is created per click and discarded after — a
|
|
388
|
-
* persistent hidden input
|
|
269
|
+
* persistent hidden input would be one more node every host has to own.
|
|
270
|
+
*
|
|
271
|
+
* Exported for the same reason {@link showMediaPickerPopover} is: it opens an OS dialog rather than
|
|
272
|
+
* rendering anything, so a surface that is a document can offer Upload without drawing a widget.
|
|
389
273
|
*
|
|
390
274
|
* @param {(val: string) => void} onCommit
|
|
391
275
|
*/
|
|
392
|
-
function pickAndUpload(onCommit: (val: string) => void) {
|
|
276
|
+
export function pickAndUpload(onCommit: (val: string) => void) {
|
|
393
277
|
const input = document.createElement("input");
|
|
394
278
|
input.type = "file";
|
|
395
279
|
input.multiple = true;
|
|
@@ -402,63 +286,98 @@ function pickAndUpload(onCommit: (val: string) => void) {
|
|
|
402
286
|
input.click();
|
|
403
287
|
}
|
|
404
288
|
|
|
289
|
+
// ─── The field ───────────────────────────────────────────────────────────────
|
|
290
|
+
|
|
291
|
+
/** The standard live-preview debounce for a typed media path. */
|
|
292
|
+
const FIELD_DEBOUNCE_MS = 400;
|
|
293
|
+
|
|
294
|
+
/** One mounted field, and the decisions that move under it between repaints. */
|
|
295
|
+
interface FieldEntry {
|
|
296
|
+
handle: MediaFieldHandle;
|
|
297
|
+
prop: string;
|
|
298
|
+
commit: (value: string) => void;
|
|
299
|
+
}
|
|
300
|
+
|
|
405
301
|
/**
|
|
406
|
-
*
|
|
302
|
+
* The fields this module has mounted, by the host they were mounted into.
|
|
407
303
|
*
|
|
408
|
-
*
|
|
409
|
-
* @
|
|
410
|
-
*
|
|
411
|
-
* @
|
|
304
|
+
* A WeakMap rather than a list: the caller owns the box, and a box that has gone should take its
|
|
305
|
+
* entry with it. It is not a substitute for {@link unmountMediaPicker} — a mount is recorded in
|
|
306
|
+
* `services/surface-registry.ts`, which holds the host — but it is what makes a repeated
|
|
307
|
+
* {@link mountMediaPicker} an update instead of a second document in the same box.
|
|
412
308
|
*/
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
309
|
+
const _fields = new WeakMap<HTMLElement, FieldEntry>();
|
|
310
|
+
|
|
311
|
+
/** What the control draws for a value. */
|
|
312
|
+
function fieldView(prop: string, value: string): MediaFieldView {
|
|
313
|
+
const isImage = IMAGE_EXTENSIONS.has(extensionOf(value));
|
|
314
|
+
return {
|
|
315
|
+
label: prop,
|
|
316
|
+
thumbSrc: isImage && value ? previewAssetSrc(value) : "",
|
|
317
|
+
thumbState: isImage && value ? "shown" : "hidden",
|
|
318
|
+
value,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
416
321
|
|
|
417
|
-
|
|
418
|
-
|
|
322
|
+
/**
|
|
323
|
+
* Draw the media field into a host the caller owns, or bring the one already there up to date.
|
|
324
|
+
*
|
|
325
|
+
* The idempotence is the point: the Content tab repaints its controls on every projection, and a
|
|
326
|
+
* second mount into the same box would be a second document over the first. A repeat call moves the
|
|
327
|
+
* scope instead, so the field the reader is typing in keeps its caret.
|
|
328
|
+
*
|
|
329
|
+
* @param {HTMLElement} host - An empty box the caller drew
|
|
330
|
+
* @param {string} prop - The attribute or prop being edited; the field's accessible name
|
|
331
|
+
* @param {string} value - What it holds now
|
|
332
|
+
* @param {(val: string) => void} onCommit - What a pick or a settled keystroke writes
|
|
333
|
+
*/
|
|
334
|
+
export function mountMediaPicker(
|
|
335
|
+
host: HTMLElement,
|
|
336
|
+
prop: string,
|
|
337
|
+
value: string,
|
|
338
|
+
onCommit: (val: string) => void,
|
|
339
|
+
): void {
|
|
340
|
+
// Kick off async load (won't block the mount)
|
|
341
|
+
void loadMediaCache();
|
|
342
|
+
const existing = _fields.get(host);
|
|
343
|
+
if (existing) {
|
|
344
|
+
existing.prop = prop;
|
|
345
|
+
existing.commit = onCommit;
|
|
346
|
+
existing.handle.update(fieldView(prop, value));
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
const entry: FieldEntry = { commit: onCommit, handle: null as unknown as MediaFieldHandle, prop };
|
|
350
|
+
entry.handle = mountMediaFieldSurface(host, fieldView(prop, value), {
|
|
351
|
+
browse: (anchor: HTMLElement) => {
|
|
352
|
+
void loadMediaCache();
|
|
353
|
+
showMediaPickerPopover(anchor, (val: string) => entry.commit(val));
|
|
354
|
+
},
|
|
355
|
+
/* Debounced under the prop's own key, so the canvas follows the typing without a document write
|
|
356
|
+
per keystroke and two fields never share a timer. */
|
|
357
|
+
edit: (next: string) =>
|
|
358
|
+
debouncedStyleCommit(`media:${entry.prop}`, FIELD_DEBOUNCE_MS, (v: string) =>
|
|
359
|
+
entry.commit(v),
|
|
360
|
+
)(next),
|
|
361
|
+
upload: () => pickAndUpload((val: string) => entry.commit(val)),
|
|
362
|
+
warm: () => {
|
|
363
|
+
void loadMediaCache();
|
|
364
|
+
},
|
|
365
|
+
});
|
|
366
|
+
_fields.set(host, entry);
|
|
367
|
+
}
|
|
419
368
|
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
@focus=${() => loadMediaCache()}
|
|
435
|
-
></sp-textfield>
|
|
436
|
-
<sp-action-button
|
|
437
|
-
class="media-picker-upload"
|
|
438
|
-
size="xs"
|
|
439
|
-
quiet
|
|
440
|
-
title="Upload media"
|
|
441
|
-
@click=${() => pickAndUpload(onCommit)}
|
|
442
|
-
>
|
|
443
|
-
<sp-icon-upload slot="icon"></sp-icon-upload>
|
|
444
|
-
</sp-action-button>
|
|
445
|
-
<!-- No data-jx-region here. The class IS the handle: ui/regions.ts derives
|
|
446
|
-
inspector/field:PROP/browse by finding this button inside the Inspector's own
|
|
447
|
-
[data-prop] row, so the id resolves to one element however many panes are drawing a
|
|
448
|
-
media picker. The stamp claimed an inspector/... id on every picker the app renders,
|
|
449
|
-
including the two the Document Header card draws inside each pane's STAGE. -->
|
|
450
|
-
<sp-action-button
|
|
451
|
-
class="media-picker-browse"
|
|
452
|
-
size="xs"
|
|
453
|
-
quiet
|
|
454
|
-
title="Browse media"
|
|
455
|
-
@click=${(e: MouseEvent) => {
|
|
456
|
-
void loadMediaCache();
|
|
457
|
-
showMediaPickerPopover(e.currentTarget as HTMLElement, onCommit);
|
|
458
|
-
}}
|
|
459
|
-
>
|
|
460
|
-
<sp-icon-image slot="icon"></sp-icon-image>
|
|
461
|
-
</sp-action-button>
|
|
462
|
-
</div>
|
|
463
|
-
`;
|
|
369
|
+
/**
|
|
370
|
+
* Take a mounted field down and forget its host.
|
|
371
|
+
*
|
|
372
|
+
* The caller has to say so: a mount is recorded in the surface registry, which holds the host
|
|
373
|
+
* strongly, so a box dropped from a projection would otherwise keep its document alive.
|
|
374
|
+
*
|
|
375
|
+
* @param {HTMLElement} host
|
|
376
|
+
*/
|
|
377
|
+
export function unmountMediaPicker(host: HTMLElement): void {
|
|
378
|
+
const entry = _fields.get(host);
|
|
379
|
+
if (entry) {
|
|
380
|
+
_fields.delete(host);
|
|
381
|
+
entry.handle.dispose();
|
|
382
|
+
}
|
|
464
383
|
}
|