@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
|
@@ -0,0 +1,1000 @@
|
|
|
1
|
+
import {
|
|
2
|
+
cellToText,
|
|
3
|
+
coerceCellInput,
|
|
4
|
+
collectionDirs,
|
|
5
|
+
columnsFromSchema,
|
|
6
|
+
createCollectionSource,
|
|
7
|
+
createGridController,
|
|
8
|
+
createPagesSource,
|
|
9
|
+
inferColumnsFromRows,
|
|
10
|
+
isRecentLocal,
|
|
11
|
+
makeGridTabId,
|
|
12
|
+
markLocalMutation
|
|
13
|
+
} from "./studio-k2sxjph5.js";
|
|
14
|
+
import {
|
|
15
|
+
MEDIA_EXTENSIONS,
|
|
16
|
+
extensionOf
|
|
17
|
+
} from "./studio-f12h6177.js";
|
|
18
|
+
import {
|
|
19
|
+
activateTab,
|
|
20
|
+
argsSchema,
|
|
21
|
+
errorMessage,
|
|
22
|
+
findContentTypeSchema,
|
|
23
|
+
openModal,
|
|
24
|
+
openTab,
|
|
25
|
+
optionalStringArg,
|
|
26
|
+
resolveI18n,
|
|
27
|
+
servedLocaleOfPath,
|
|
28
|
+
stringArg,
|
|
29
|
+
stringProperty,
|
|
30
|
+
workspace
|
|
31
|
+
} from "./studio-41exgzhq.js";
|
|
32
|
+
import {
|
|
33
|
+
html
|
|
34
|
+
} from "./studio-5x5774ak.js";
|
|
35
|
+
import {
|
|
36
|
+
projectState
|
|
37
|
+
} from "./studio-cjm7fdjf.js";
|
|
38
|
+
import {
|
|
39
|
+
formatForPath,
|
|
40
|
+
loadFormats
|
|
41
|
+
} from "./studio-adn0z1k3.js";
|
|
42
|
+
import {
|
|
43
|
+
getPlatform
|
|
44
|
+
} from "./studio-sas7mt3k.js";
|
|
45
|
+
|
|
46
|
+
// src/services/data-service.ts
|
|
47
|
+
function platformOrNull() {
|
|
48
|
+
try {
|
|
49
|
+
return getPlatform();
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function dataSurfaceAvailable() {
|
|
55
|
+
return typeof platformOrNull()?.dataRows === "function";
|
|
56
|
+
}
|
|
57
|
+
async function fetchConnections() {
|
|
58
|
+
const platform = platformOrNull();
|
|
59
|
+
if (typeof platform?.dataConnections !== "function") {
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
return platform.dataConnections();
|
|
63
|
+
}
|
|
64
|
+
async function testConnection(connection) {
|
|
65
|
+
const platform = platformOrNull();
|
|
66
|
+
if (typeof platform?.dataConnectionTest !== "function") {
|
|
67
|
+
return { error: "Connection tests are not supported by this backend", ok: false };
|
|
68
|
+
}
|
|
69
|
+
try {
|
|
70
|
+
return await platform.dataConnectionTest(connection);
|
|
71
|
+
} catch (error) {
|
|
72
|
+
return { error: error instanceof Error ? error.message : String(error), ok: false };
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function pushSchema(opts) {
|
|
76
|
+
const platform = platformOrNull();
|
|
77
|
+
if (typeof platform?.dataPush !== "function") {
|
|
78
|
+
return { applied: false, errors: ["Schema push is not supported by this backend"], plan: [] };
|
|
79
|
+
}
|
|
80
|
+
try {
|
|
81
|
+
return await platform.dataPush(opts);
|
|
82
|
+
} catch (error) {
|
|
83
|
+
return {
|
|
84
|
+
applied: false,
|
|
85
|
+
errors: [error instanceof Error ? error.message : String(error)],
|
|
86
|
+
plan: []
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function requireMember(name) {
|
|
91
|
+
const platform = platformOrNull();
|
|
92
|
+
const member = platform?.[name];
|
|
93
|
+
if (member === undefined || member === null) {
|
|
94
|
+
throw new Error(`The ${String(name)} surface is not supported by this backend`);
|
|
95
|
+
}
|
|
96
|
+
return member;
|
|
97
|
+
}
|
|
98
|
+
function fetchRows(query) {
|
|
99
|
+
return requireMember("dataRows")(query);
|
|
100
|
+
}
|
|
101
|
+
function insertRow(req) {
|
|
102
|
+
return requireMember("dataInsertRow")(req);
|
|
103
|
+
}
|
|
104
|
+
function updateRow(req) {
|
|
105
|
+
return requireMember("dataUpdateRow")(req);
|
|
106
|
+
}
|
|
107
|
+
function deleteRow(req) {
|
|
108
|
+
return requireMember("dataDeleteRow")(req);
|
|
109
|
+
}
|
|
110
|
+
function deriveSecretEnvName(sectionKey, entryKey, fieldKey) {
|
|
111
|
+
const constant = (raw) => raw.replaceAll(/([a-z0-9])([A-Z])/g, "$1_$2").replaceAll(/[^A-Za-z0-9]+/g, "_").replaceAll(/^_+|_+$/g, "").toUpperCase();
|
|
112
|
+
const parts = [entryKey ?? sectionKey, fieldKey.replace(/Env$/, "")].map((part) => constant(part)).filter(Boolean);
|
|
113
|
+
const name = parts.join("_") || "SECRET";
|
|
114
|
+
return /^\d/.test(name) ? `JX_${name}` : name;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// src/grid/csv-codec.ts
|
|
118
|
+
function splitRecords(text) {
|
|
119
|
+
const records = [];
|
|
120
|
+
let fields = [];
|
|
121
|
+
let field = "";
|
|
122
|
+
let inQuotes = false;
|
|
123
|
+
let fieldStarted = false;
|
|
124
|
+
const endField = () => {
|
|
125
|
+
fields.push(field);
|
|
126
|
+
field = "";
|
|
127
|
+
fieldStarted = false;
|
|
128
|
+
};
|
|
129
|
+
const endRecord = () => {
|
|
130
|
+
endField();
|
|
131
|
+
if (fields.length === 1 && fields[0] === "") {
|
|
132
|
+
fields = [];
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
records.push(fields);
|
|
136
|
+
fields = [];
|
|
137
|
+
};
|
|
138
|
+
for (let i = 0;i < text.length; i++) {
|
|
139
|
+
const ch = text[i];
|
|
140
|
+
if (inQuotes) {
|
|
141
|
+
if (ch === '"') {
|
|
142
|
+
if (text[i + 1] === '"') {
|
|
143
|
+
field += '"';
|
|
144
|
+
i += 1;
|
|
145
|
+
} else {
|
|
146
|
+
inQuotes = false;
|
|
147
|
+
}
|
|
148
|
+
} else {
|
|
149
|
+
field += ch;
|
|
150
|
+
}
|
|
151
|
+
continue;
|
|
152
|
+
}
|
|
153
|
+
if (ch === '"' && !fieldStarted) {
|
|
154
|
+
inQuotes = true;
|
|
155
|
+
fieldStarted = true;
|
|
156
|
+
} else if (ch === '"') {
|
|
157
|
+
field += ch;
|
|
158
|
+
} else if (ch === ",") {
|
|
159
|
+
endField();
|
|
160
|
+
} else if (ch === `
|
|
161
|
+
`) {
|
|
162
|
+
endRecord();
|
|
163
|
+
} else if (ch === "\r") {
|
|
164
|
+
if (text[i + 1] === `
|
|
165
|
+
`) {
|
|
166
|
+
i += 1;
|
|
167
|
+
}
|
|
168
|
+
endRecord();
|
|
169
|
+
} else {
|
|
170
|
+
field += ch;
|
|
171
|
+
fieldStarted = true;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
if (field !== "" || fields.length > 0) {
|
|
175
|
+
endRecord();
|
|
176
|
+
}
|
|
177
|
+
return records;
|
|
178
|
+
}
|
|
179
|
+
function parseCsv(text) {
|
|
180
|
+
const crlf = (text.match(/\r\n/g) ?? []).length;
|
|
181
|
+
const bareLf = (text.match(/(?<!\r)\n/g) ?? []).length;
|
|
182
|
+
const eol = crlf > bareLf ? `\r
|
|
183
|
+
` : `
|
|
184
|
+
`;
|
|
185
|
+
const trailingNewline = text.endsWith(`
|
|
186
|
+
`);
|
|
187
|
+
const records = splitRecords(text);
|
|
188
|
+
const headers = records[0] ?? [];
|
|
189
|
+
const rows = records.slice(1);
|
|
190
|
+
const width = Math.max(headers.length, ...rows.map((r) => r.length), 0);
|
|
191
|
+
while (headers.length < width) {
|
|
192
|
+
headers.push("");
|
|
193
|
+
}
|
|
194
|
+
for (const row of rows) {
|
|
195
|
+
while (row.length < width) {
|
|
196
|
+
row.push("");
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return { eol, headers, rows, trailingNewline };
|
|
200
|
+
}
|
|
201
|
+
function encodeField(value) {
|
|
202
|
+
if (/[",\n\r]/.test(value)) {
|
|
203
|
+
return `"${value.replaceAll('"', '""')}"`;
|
|
204
|
+
}
|
|
205
|
+
return value;
|
|
206
|
+
}
|
|
207
|
+
function serializeCsv(doc) {
|
|
208
|
+
const lines = [doc.headers, ...doc.rows].map((fields) => fields.map((field) => encodeField(field)).join(","));
|
|
209
|
+
return lines.join(doc.eol) + (doc.trailingNewline ? doc.eol : "");
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// src/grid/sources/csv-file-source.ts
|
|
213
|
+
var ID_FIELDS = ["id", "sku", "slug", "Slug"];
|
|
214
|
+
function fieldNamesForHeaders(headers) {
|
|
215
|
+
const used = new Set;
|
|
216
|
+
return headers.map((header, i) => {
|
|
217
|
+
let name = header.trim() === "" ? `column${i + 1}` : header;
|
|
218
|
+
if (used.has(name)) {
|
|
219
|
+
name = `${name}__${i + 1}`;
|
|
220
|
+
}
|
|
221
|
+
used.add(name);
|
|
222
|
+
return name;
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
function pickIdField(fields, doc) {
|
|
226
|
+
for (const candidate of ID_FIELDS) {
|
|
227
|
+
const idx = fields.indexOf(candidate);
|
|
228
|
+
if (idx === -1) {
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const values = doc.rows.map((row) => row[idx] ?? "");
|
|
232
|
+
if (values.every((v) => v !== "") && new Set(values).size === values.length) {
|
|
233
|
+
return candidate;
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
function buildModel(text, path) {
|
|
239
|
+
const doc = parseCsv(text);
|
|
240
|
+
const fields = fieldNamesForHeaders(doc.headers);
|
|
241
|
+
const idField = pickIdField(fields, doc);
|
|
242
|
+
const idIndex = idField ? fields.indexOf(idField) : -1;
|
|
243
|
+
const keys = doc.rows.map((row, i) => idIndex === -1 ? String(i) : row[idIndex]);
|
|
244
|
+
const keyToIndex = new Map(keys.map((key, i) => [key, i]));
|
|
245
|
+
const contentType = findContentTypeSchema(path, projectState?.projectConfig);
|
|
246
|
+
const schemaProps = contentType?.schema?.properties ?? {};
|
|
247
|
+
const sampleRows = doc.rows.slice(0, 50).map((row) => {
|
|
248
|
+
const cells = {};
|
|
249
|
+
for (const [i, field] of fields.entries()) {
|
|
250
|
+
cells[field] = row[i] ?? "";
|
|
251
|
+
}
|
|
252
|
+
return cells;
|
|
253
|
+
});
|
|
254
|
+
const inferred = new Map(inferColumnsFromRows(sampleRows).map((c) => [c.field, c]));
|
|
255
|
+
const typed = new Map(columnsFromSchema(contentType?.schema, { idField: idField ?? undefined }).map((c) => [
|
|
256
|
+
c.field,
|
|
257
|
+
c
|
|
258
|
+
]));
|
|
259
|
+
const columns = fields.map((field, i) => {
|
|
260
|
+
const fromSchema = field in schemaProps ? typed.get(field) : undefined;
|
|
261
|
+
const column = fromSchema ?? inferred.get(field) ?? {
|
|
262
|
+
editable: true,
|
|
263
|
+
field,
|
|
264
|
+
kind: "string",
|
|
265
|
+
title: doc.headers[i] || field
|
|
266
|
+
};
|
|
267
|
+
return { ...column, pk: field === idField, title: doc.headers[i]?.trim() || column.title };
|
|
268
|
+
});
|
|
269
|
+
return { columns, doc, fields, keys, keyToIndex, loadText: text };
|
|
270
|
+
}
|
|
271
|
+
function rowCells(model, rowIndex) {
|
|
272
|
+
const cells = {};
|
|
273
|
+
const row = model.doc.rows[rowIndex] ?? [];
|
|
274
|
+
for (const [i, field] of model.fields.entries()) {
|
|
275
|
+
const column = model.columns[i];
|
|
276
|
+
const raw = row[i] ?? "";
|
|
277
|
+
cells[field] = column.kind === "string" || column.kind === "text" || column.kind === "readonly" ? raw : coerceCellInput(raw, column);
|
|
278
|
+
}
|
|
279
|
+
return cells;
|
|
280
|
+
}
|
|
281
|
+
function applyBatch(model, batch) {
|
|
282
|
+
const rows = model.doc.rows.map((row) => [...row]);
|
|
283
|
+
const colFor = (field) => model.fields.indexOf(field);
|
|
284
|
+
for (const cell of batch.cells) {
|
|
285
|
+
const rowIndex = model.keyToIndex.get(cell.rowKey);
|
|
286
|
+
const colIndex = colFor(cell.field);
|
|
287
|
+
if (rowIndex === undefined || colIndex === -1) {
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
rows[rowIndex][colIndex] = cellToText(cell.value);
|
|
291
|
+
}
|
|
292
|
+
for (const insert of batch.inserts) {
|
|
293
|
+
const row = model.fields.map((field) => cellToText(insert.cells[field] ?? null));
|
|
294
|
+
rows.push(row);
|
|
295
|
+
}
|
|
296
|
+
const dropIndexes = batch.deletes.map((del) => model.keyToIndex.get(del.rowKey)).filter((i) => i !== undefined).toSorted((a, b) => b - a);
|
|
297
|
+
for (const index of dropIndexes) {
|
|
298
|
+
rows.splice(index, 1);
|
|
299
|
+
}
|
|
300
|
+
return { ...model.doc, rows };
|
|
301
|
+
}
|
|
302
|
+
function uniformResult(batch, outcome) {
|
|
303
|
+
return {
|
|
304
|
+
cells: batch.cells.map((c) => ({ field: c.field, rowKey: c.rowKey, ...outcome })),
|
|
305
|
+
deletes: batch.deletes.map((d) => ({ rowKey: d.rowKey, ...outcome })),
|
|
306
|
+
inserts: batch.inserts.map((i) => ({
|
|
307
|
+
error: outcome.error,
|
|
308
|
+
ok: outcome.ok,
|
|
309
|
+
tempKey: i.tempKey
|
|
310
|
+
}))
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
function createCsvFileSource(path) {
|
|
314
|
+
let loadPromise = null;
|
|
315
|
+
const load = (force = false) => {
|
|
316
|
+
if (!force && loadPromise) {
|
|
317
|
+
return loadPromise;
|
|
318
|
+
}
|
|
319
|
+
loadPromise = getPlatform().readFile(path).then((text) => buildModel(text, path));
|
|
320
|
+
return loadPromise;
|
|
321
|
+
};
|
|
322
|
+
return {
|
|
323
|
+
backingPaths: () => new Map([[path, "*"]]),
|
|
324
|
+
capabilities: { delete: true, insert: true, remotePaging: false, remoteSort: false },
|
|
325
|
+
async columns() {
|
|
326
|
+
const current = await load();
|
|
327
|
+
return current.columns;
|
|
328
|
+
},
|
|
329
|
+
async commit(batch) {
|
|
330
|
+
const current = await load();
|
|
331
|
+
const platform = getPlatform();
|
|
332
|
+
let onDisk = null;
|
|
333
|
+
try {
|
|
334
|
+
onDisk = await platform.readFile(path);
|
|
335
|
+
} catch {
|
|
336
|
+
onDisk = null;
|
|
337
|
+
}
|
|
338
|
+
if (onDisk !== current.loadText && !isRecentLocal(path)) {
|
|
339
|
+
return uniformResult(batch, {
|
|
340
|
+
error: "File changed on disk — refresh to reload",
|
|
341
|
+
ok: false,
|
|
342
|
+
stale: true
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
const nextDoc = applyBatch(current, batch);
|
|
346
|
+
const text = serializeCsv(nextDoc);
|
|
347
|
+
markLocalMutation(path);
|
|
348
|
+
await platform.writeFile(path, text);
|
|
349
|
+
loadPromise = Promise.resolve(buildModel(text, path));
|
|
350
|
+
return uniformResult(batch, { ok: true });
|
|
351
|
+
},
|
|
352
|
+
id: path,
|
|
353
|
+
label: path.split("/").pop() ?? path,
|
|
354
|
+
async refresh() {
|
|
355
|
+
await load(true);
|
|
356
|
+
},
|
|
357
|
+
async rows() {
|
|
358
|
+
const current = await load();
|
|
359
|
+
const rows = current.doc.rows.map((_, i) => ({
|
|
360
|
+
cells: rowCells(current, i),
|
|
361
|
+
key: current.keys[i]
|
|
362
|
+
}));
|
|
363
|
+
return { rows, total: rows.length };
|
|
364
|
+
},
|
|
365
|
+
async serializeForSource(batch) {
|
|
366
|
+
const current = await load();
|
|
367
|
+
return serializeCsv(applyBatch(current, batch));
|
|
368
|
+
}
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// src/grid/sources/connector-source.ts
|
|
373
|
+
var DATA_PAGE_SIZE = 50;
|
|
374
|
+
function kindForSqlType(type) {
|
|
375
|
+
const t = type.toLowerCase();
|
|
376
|
+
if (/(int|real|floa|doub|num|dec)/.test(t)) {
|
|
377
|
+
return "number";
|
|
378
|
+
}
|
|
379
|
+
if (t.includes("bool")) {
|
|
380
|
+
return "boolean";
|
|
381
|
+
}
|
|
382
|
+
if (/(timestamp|datetime|date)/.test(t)) {
|
|
383
|
+
return "date";
|
|
384
|
+
}
|
|
385
|
+
return "string";
|
|
386
|
+
}
|
|
387
|
+
function editableColumn(column) {
|
|
388
|
+
return !column.pk && column.name !== "created_at" && column.name !== "updated_at";
|
|
389
|
+
}
|
|
390
|
+
function toCellValue(value) {
|
|
391
|
+
if (value === null || value === undefined) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
if (typeof value === "string" || typeof value === "number" || typeof value === "boolean") {
|
|
395
|
+
return value;
|
|
396
|
+
}
|
|
397
|
+
return JSON.stringify(value);
|
|
398
|
+
}
|
|
399
|
+
function createConnectorSource(connection, table) {
|
|
400
|
+
let columnsMeta = [];
|
|
401
|
+
let pkName = "id";
|
|
402
|
+
const pkValues = new Map;
|
|
403
|
+
const applyMeta = (columns) => {
|
|
404
|
+
if (columns.length > 0) {
|
|
405
|
+
columnsMeta = columns;
|
|
406
|
+
pkName = columns.find((c) => c.pk)?.name ?? "id";
|
|
407
|
+
}
|
|
408
|
+
};
|
|
409
|
+
const toQuery = (query) => ({
|
|
410
|
+
table,
|
|
411
|
+
...connection ? { connection } : {},
|
|
412
|
+
limit: query?.limit ?? DATA_PAGE_SIZE,
|
|
413
|
+
offset: query?.offset ?? 0,
|
|
414
|
+
...query?.orderBy ? { dir: query.dir ?? "asc", orderBy: query.orderBy } : {}
|
|
415
|
+
});
|
|
416
|
+
const rowKeyOf = (row, index) => {
|
|
417
|
+
const pk = row[pkName];
|
|
418
|
+
if (typeof pk === "string" || typeof pk === "number") {
|
|
419
|
+
pkValues.set(String(pk), pk);
|
|
420
|
+
return String(pk);
|
|
421
|
+
}
|
|
422
|
+
return `row-${index}`;
|
|
423
|
+
};
|
|
424
|
+
return {
|
|
425
|
+
capabilities: { delete: true, insert: true, remotePaging: true, remoteSort: true },
|
|
426
|
+
async columns() {
|
|
427
|
+
if (columnsMeta.length === 0) {
|
|
428
|
+
const result = await fetchRows(toQuery({ limit: 1, offset: 0 }));
|
|
429
|
+
applyMeta(result.columns);
|
|
430
|
+
}
|
|
431
|
+
return columnsMeta.map((meta) => {
|
|
432
|
+
const kind = editableColumn(meta) ? kindForSqlType(meta.type) : "readonly";
|
|
433
|
+
return {
|
|
434
|
+
editable: kind !== "readonly",
|
|
435
|
+
field: meta.name,
|
|
436
|
+
kind,
|
|
437
|
+
pk: meta.pk === true,
|
|
438
|
+
title: meta.name,
|
|
439
|
+
widthHint: meta.pk ? 80 : undefined
|
|
440
|
+
};
|
|
441
|
+
});
|
|
442
|
+
},
|
|
443
|
+
async commit(batch) {
|
|
444
|
+
const result = { cells: [], deletes: [], inserts: [] };
|
|
445
|
+
const byRow = new Map;
|
|
446
|
+
for (const cell of batch.cells) {
|
|
447
|
+
const list = byRow.get(cell.rowKey) ?? [];
|
|
448
|
+
list.push({ field: cell.field, value: cell.value });
|
|
449
|
+
byRow.set(cell.rowKey, list);
|
|
450
|
+
}
|
|
451
|
+
for (const [rowKey, patches] of byRow) {
|
|
452
|
+
const pk = pkValues.get(rowKey);
|
|
453
|
+
const outcome = (ok, error) => {
|
|
454
|
+
for (const patch of patches) {
|
|
455
|
+
result.cells.push({ error, field: patch.field, ok, rowKey });
|
|
456
|
+
}
|
|
457
|
+
};
|
|
458
|
+
if (pk === undefined) {
|
|
459
|
+
outcome(false, "Row has no primary key — refresh the grid");
|
|
460
|
+
continue;
|
|
461
|
+
}
|
|
462
|
+
try {
|
|
463
|
+
const set = {};
|
|
464
|
+
for (const patch of patches) {
|
|
465
|
+
set[patch.field] = patch.value;
|
|
466
|
+
}
|
|
467
|
+
await updateRow({ pk, set, table, ...connection ? { connection } : {} });
|
|
468
|
+
outcome(true);
|
|
469
|
+
} catch (error) {
|
|
470
|
+
outcome(false, error instanceof Error ? error.message : String(error));
|
|
471
|
+
}
|
|
472
|
+
}
|
|
473
|
+
for (const insert of batch.inserts) {
|
|
474
|
+
try {
|
|
475
|
+
const values = {};
|
|
476
|
+
for (const [field, value] of Object.entries(insert.cells)) {
|
|
477
|
+
if (value !== null) {
|
|
478
|
+
values[field] = value;
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
const { row } = await insertRow({ table, values, ...connection ? { connection } : {} });
|
|
482
|
+
const pk = row[pkName];
|
|
483
|
+
const newKey = typeof pk === "string" || typeof pk === "number" ? String(pk) : undefined;
|
|
484
|
+
if (newKey !== undefined && (typeof pk === "string" || typeof pk === "number")) {
|
|
485
|
+
pkValues.set(newKey, pk);
|
|
486
|
+
}
|
|
487
|
+
result.inserts.push({ newKey, ok: true, tempKey: insert.tempKey });
|
|
488
|
+
} catch (error) {
|
|
489
|
+
result.inserts.push({
|
|
490
|
+
error: error instanceof Error ? error.message : String(error),
|
|
491
|
+
ok: false,
|
|
492
|
+
tempKey: insert.tempKey
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
for (const del of batch.deletes) {
|
|
497
|
+
const pk = pkValues.get(del.rowKey);
|
|
498
|
+
if (pk === undefined) {
|
|
499
|
+
result.deletes.push({
|
|
500
|
+
error: "Row has no primary key — refresh the grid",
|
|
501
|
+
ok: false,
|
|
502
|
+
rowKey: del.rowKey
|
|
503
|
+
});
|
|
504
|
+
continue;
|
|
505
|
+
}
|
|
506
|
+
try {
|
|
507
|
+
await deleteRow({ pk, table, ...connection ? { connection } : {} });
|
|
508
|
+
result.deletes.push({ ok: true, rowKey: del.rowKey });
|
|
509
|
+
} catch (error) {
|
|
510
|
+
result.deletes.push({
|
|
511
|
+
error: error instanceof Error ? error.message : String(error),
|
|
512
|
+
ok: false,
|
|
513
|
+
rowKey: del.rowKey
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
return result;
|
|
518
|
+
},
|
|
519
|
+
id: makeGridTabId({ connection: connection ?? "default", kind: "data", table }),
|
|
520
|
+
label: table,
|
|
521
|
+
async refresh() {
|
|
522
|
+
columnsMeta = [];
|
|
523
|
+
pkValues.clear();
|
|
524
|
+
},
|
|
525
|
+
async rows(query) {
|
|
526
|
+
const result = await fetchRows(toQuery(query));
|
|
527
|
+
applyMeta(result.columns);
|
|
528
|
+
const rows = result.rows.map((row, index) => {
|
|
529
|
+
const key = rowKeyOf(row, index);
|
|
530
|
+
const cells = {};
|
|
531
|
+
for (const meta of columnsMeta) {
|
|
532
|
+
cells[meta.name] = toCellValue(row[meta.name]);
|
|
533
|
+
}
|
|
534
|
+
return { cells, key };
|
|
535
|
+
});
|
|
536
|
+
return { rows, total: result.total };
|
|
537
|
+
}
|
|
538
|
+
};
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
// src/browse/library-model.ts
|
|
542
|
+
var LIBRARY_CATEGORIES = [
|
|
543
|
+
{ key: "all", label: "All" },
|
|
544
|
+
{ dir: "pages", key: "pages", label: "Pages" },
|
|
545
|
+
{ dir: "layouts", key: "layouts", label: "Layouts" },
|
|
546
|
+
{ dir: "components", key: "components", label: "Components" },
|
|
547
|
+
{ dir: "content", key: "content", label: "Content" },
|
|
548
|
+
{ dir: "public", key: "media", label: "Media" }
|
|
549
|
+
];
|
|
550
|
+
var LIBRARY_CATEGORY_KEYS = LIBRARY_CATEGORIES.map((c) => c.key);
|
|
551
|
+
function libraryCategory(key) {
|
|
552
|
+
return LIBRARY_CATEGORIES.find((c) => c.key === key);
|
|
553
|
+
}
|
|
554
|
+
function uploadDirForCategory(key) {
|
|
555
|
+
return libraryCategory(key)?.dir;
|
|
556
|
+
}
|
|
557
|
+
function categoryFor(dir, ext) {
|
|
558
|
+
if (ext && MEDIA_EXTENSIONS.has(ext)) {
|
|
559
|
+
return "Media";
|
|
560
|
+
}
|
|
561
|
+
if (dir.startsWith("pages")) {
|
|
562
|
+
return "Pages";
|
|
563
|
+
}
|
|
564
|
+
if (dir.startsWith("layouts")) {
|
|
565
|
+
return "Layouts";
|
|
566
|
+
}
|
|
567
|
+
if (dir.startsWith("components")) {
|
|
568
|
+
return "Components";
|
|
569
|
+
}
|
|
570
|
+
if (dir.startsWith("content")) {
|
|
571
|
+
return "Content";
|
|
572
|
+
}
|
|
573
|
+
if (dir.startsWith("public")) {
|
|
574
|
+
return "Media";
|
|
575
|
+
}
|
|
576
|
+
if (dir.startsWith("data")) {
|
|
577
|
+
return "Content";
|
|
578
|
+
}
|
|
579
|
+
if (dir.startsWith("styles")) {
|
|
580
|
+
return "Components";
|
|
581
|
+
}
|
|
582
|
+
return "Other";
|
|
583
|
+
}
|
|
584
|
+
function contentTypeFor(filePath) {
|
|
585
|
+
const content = projectState?.projectConfig?.content ?? {};
|
|
586
|
+
for (const [name, entry] of Object.entries(content)) {
|
|
587
|
+
if (!entry.source) {
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const prefix = entry.source.replace(/^\.\//, "").replace(/\/$/, "");
|
|
591
|
+
if (filePath.startsWith(`${prefix}/`) || filePath === prefix) {
|
|
592
|
+
return name.charAt(0).toUpperCase() + name.slice(1);
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
return null;
|
|
596
|
+
}
|
|
597
|
+
var SKIP_DIRS = new Set(["node_modules", ".git", ".jx", "dist", "build", ".cache"]);
|
|
598
|
+
async function walk(dir, platform, out, failures, i18n) {
|
|
599
|
+
let entries;
|
|
600
|
+
try {
|
|
601
|
+
entries = await platform.listDirectory(dir);
|
|
602
|
+
} catch (error) {
|
|
603
|
+
failures.push({ dir, error: errorMessage(error) });
|
|
604
|
+
return;
|
|
605
|
+
}
|
|
606
|
+
const subdirectories = [];
|
|
607
|
+
for (const entry of entries) {
|
|
608
|
+
if (entry.type === "directory") {
|
|
609
|
+
if (!SKIP_DIRS.has(entry.name)) {
|
|
610
|
+
subdirectories.push(entry.path);
|
|
611
|
+
}
|
|
612
|
+
continue;
|
|
613
|
+
}
|
|
614
|
+
const ext = extensionOf(entry.name);
|
|
615
|
+
const category = categoryFor(entry.path, ext);
|
|
616
|
+
out.push({
|
|
617
|
+
category,
|
|
618
|
+
ext,
|
|
619
|
+
locale: servedLocaleOfPath(entry.path, i18n) ?? undefined,
|
|
620
|
+
modified: entry.modified,
|
|
621
|
+
name: entry.name,
|
|
622
|
+
path: entry.path,
|
|
623
|
+
size: entry.size,
|
|
624
|
+
type: category === "Content" ? contentTypeFor(entry.path) ?? ext ?? "file" : ext || "file"
|
|
625
|
+
});
|
|
626
|
+
}
|
|
627
|
+
await Promise.all(subdirectories.map((sub) => walk(sub, platform, out, failures, i18n)));
|
|
628
|
+
}
|
|
629
|
+
async function scanLibrary(dirs, platform) {
|
|
630
|
+
const files = [];
|
|
631
|
+
const failures = [];
|
|
632
|
+
const { i18n } = resolveI18n(projectState?.projectConfig ?? {});
|
|
633
|
+
await Promise.all(dirs.map((dir) => walk(dir, platform, files, failures, i18n)));
|
|
634
|
+
files.sort((a, b) => a.path.localeCompare(b.path));
|
|
635
|
+
return { failures, files };
|
|
636
|
+
}
|
|
637
|
+
function filterLibrary(files, filter) {
|
|
638
|
+
let result = files;
|
|
639
|
+
const category = libraryCategory(filter.category);
|
|
640
|
+
if (category && category.key !== "all") {
|
|
641
|
+
result = result.filter((f) => f.category === category.label);
|
|
642
|
+
}
|
|
643
|
+
const query = filter.query.trim().toLowerCase();
|
|
644
|
+
if (query) {
|
|
645
|
+
result = result.filter((f) => f.name.toLowerCase().includes(query) || f.path.toLowerCase().includes(query));
|
|
646
|
+
}
|
|
647
|
+
const locale = filter.locale?.trim();
|
|
648
|
+
if (locale) {
|
|
649
|
+
result = result.filter((f) => f.locale === locale);
|
|
650
|
+
}
|
|
651
|
+
return result;
|
|
652
|
+
}
|
|
653
|
+
var LIBRARY_LAYOUTS = ["table", "cards", "media", "calendar", "board"];
|
|
654
|
+
var LIBRARY_LAYOUT_LABELS = {
|
|
655
|
+
board: "Board",
|
|
656
|
+
calendar: "Calendar",
|
|
657
|
+
cards: "Cards",
|
|
658
|
+
media: "Media",
|
|
659
|
+
table: "Table"
|
|
660
|
+
};
|
|
661
|
+
var PREVIEW_LAYOUTS = new Set([
|
|
662
|
+
"cards",
|
|
663
|
+
"media"
|
|
664
|
+
]);
|
|
665
|
+
var DATE_PREFIX = /^(\d{4}-\d{2}-\d{2})/;
|
|
666
|
+
function libraryDate(file) {
|
|
667
|
+
const prefix = DATE_PREFIX.exec(file.name);
|
|
668
|
+
if (prefix) {
|
|
669
|
+
return prefix[1];
|
|
670
|
+
}
|
|
671
|
+
if (file.modified) {
|
|
672
|
+
const parsed = new Date(file.modified);
|
|
673
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
674
|
+
return parsed.toISOString().slice(0, 10);
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
function projectLocales() {
|
|
680
|
+
return resolveI18n(projectState?.projectConfig ?? {}).i18n?.locales ?? [];
|
|
681
|
+
}
|
|
682
|
+
function libraryLocales(files) {
|
|
683
|
+
const present = new Set;
|
|
684
|
+
for (const file of files) {
|
|
685
|
+
if (file.locale) {
|
|
686
|
+
present.add(file.locale);
|
|
687
|
+
}
|
|
688
|
+
}
|
|
689
|
+
return projectLocales().filter((tag) => present.has(tag));
|
|
690
|
+
}
|
|
691
|
+
function groupByDate(files) {
|
|
692
|
+
const byDay = new Map;
|
|
693
|
+
const undated = [];
|
|
694
|
+
for (const file of files) {
|
|
695
|
+
const date = libraryDate(file);
|
|
696
|
+
if (date === null) {
|
|
697
|
+
undated.push(file);
|
|
698
|
+
continue;
|
|
699
|
+
}
|
|
700
|
+
const bucket = byDay.get(date);
|
|
701
|
+
if (bucket) {
|
|
702
|
+
bucket.push(file);
|
|
703
|
+
} else {
|
|
704
|
+
byDay.set(date, [file]);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
const days = [...byDay.entries()].map(([date, dayFiles]) => ({ date, files: dayFiles })).toSorted((a, b) => b.date.localeCompare(a.date));
|
|
708
|
+
return { days, undated };
|
|
709
|
+
}
|
|
710
|
+
function groupByCategory(files) {
|
|
711
|
+
const byGroup = new Map;
|
|
712
|
+
for (const file of files) {
|
|
713
|
+
const bucket = byGroup.get(file.category);
|
|
714
|
+
if (bucket) {
|
|
715
|
+
bucket.push(file);
|
|
716
|
+
} else {
|
|
717
|
+
byGroup.set(file.category, [file]);
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
const order = LIBRARY_CATEGORIES.map((c) => c.label);
|
|
721
|
+
return [...byGroup.entries()].map(([group, groupFiles]) => ({ files: groupFiles, group })).toSorted((a, b) => {
|
|
722
|
+
const ai = order.indexOf(a.group);
|
|
723
|
+
const bi = order.indexOf(b.group);
|
|
724
|
+
if (ai === bi) {
|
|
725
|
+
return a.group.localeCompare(b.group);
|
|
726
|
+
}
|
|
727
|
+
return (ai === -1 ? order.length : ai) - (bi === -1 ? order.length : bi);
|
|
728
|
+
});
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// src/browse/library-source.ts
|
|
732
|
+
var LIBRARY_READ_ONLY = "The Library lists files; it does not edit them. Rename, duplicate or delete from the file's " + "context menu, or open the file to edit it.";
|
|
733
|
+
function libraryColumns() {
|
|
734
|
+
return [
|
|
735
|
+
{ editable: false, field: "name", kind: "string", pk: true, title: "Name", widthHint: 260 },
|
|
736
|
+
{ editable: false, field: "category", kind: "string", title: "Category", widthHint: 120 },
|
|
737
|
+
{ editable: false, field: "locale", kind: "string", title: "Locale", widthHint: 90 },
|
|
738
|
+
{ editable: false, field: "type", kind: "string", title: "Type", widthHint: 120 },
|
|
739
|
+
{ editable: false, field: "size", kind: "number", title: "Size", widthHint: 90 },
|
|
740
|
+
{ editable: false, field: "modified", kind: "date", title: "Modified", widthHint: 160 },
|
|
741
|
+
{ editable: false, field: "path", kind: "readonly", title: "Path", widthHint: 320 }
|
|
742
|
+
];
|
|
743
|
+
}
|
|
744
|
+
function libraryRow(file) {
|
|
745
|
+
return {
|
|
746
|
+
cells: {
|
|
747
|
+
category: file.category,
|
|
748
|
+
locale: file.locale ?? null,
|
|
749
|
+
modified: file.modified ?? null,
|
|
750
|
+
name: file.name,
|
|
751
|
+
path: file.path,
|
|
752
|
+
size: file.size ?? null,
|
|
753
|
+
type: file.type
|
|
754
|
+
},
|
|
755
|
+
key: file.path
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
function libraryTabId() {
|
|
759
|
+
return makeGridTabId({ kind: "library" });
|
|
760
|
+
}
|
|
761
|
+
function createLibrarySource(dirs) {
|
|
762
|
+
let scan = null;
|
|
763
|
+
let inFlight = null;
|
|
764
|
+
const projectDirs = dirs ?? (() => projectState?.projectDirs ?? []);
|
|
765
|
+
async function ensureScan() {
|
|
766
|
+
if (scan) {
|
|
767
|
+
return scan;
|
|
768
|
+
}
|
|
769
|
+
inFlight ??= scanLibrary(projectDirs(), getPlatform()).then((result) => {
|
|
770
|
+
scan = result;
|
|
771
|
+
inFlight = null;
|
|
772
|
+
return result;
|
|
773
|
+
});
|
|
774
|
+
return inFlight;
|
|
775
|
+
}
|
|
776
|
+
return {
|
|
777
|
+
capabilities: { delete: false, insert: false, remotePaging: false, remoteSort: false },
|
|
778
|
+
columns: () => Promise.resolve(libraryColumns()),
|
|
779
|
+
commit(batch) {
|
|
780
|
+
return Promise.resolve({
|
|
781
|
+
cells: batch.cells.map((cell) => ({
|
|
782
|
+
error: LIBRARY_READ_ONLY,
|
|
783
|
+
field: cell.field,
|
|
784
|
+
ok: false,
|
|
785
|
+
rowKey: cell.rowKey
|
|
786
|
+
})),
|
|
787
|
+
deletes: batch.deletes.map((row) => ({
|
|
788
|
+
error: LIBRARY_READ_ONLY,
|
|
789
|
+
ok: false,
|
|
790
|
+
rowKey: row.rowKey
|
|
791
|
+
})),
|
|
792
|
+
inserts: batch.inserts.map((row) => ({
|
|
793
|
+
error: LIBRARY_READ_ONLY,
|
|
794
|
+
ok: false,
|
|
795
|
+
tempKey: row.tempKey
|
|
796
|
+
}))
|
|
797
|
+
});
|
|
798
|
+
},
|
|
799
|
+
failures: () => scan?.failures ?? [],
|
|
800
|
+
files: () => scan?.files ?? [],
|
|
801
|
+
id: libraryTabId(),
|
|
802
|
+
label: "Library",
|
|
803
|
+
async refresh() {
|
|
804
|
+
scan = null;
|
|
805
|
+
inFlight = null;
|
|
806
|
+
await ensureScan();
|
|
807
|
+
},
|
|
808
|
+
async rows() {
|
|
809
|
+
const result = await ensureScan();
|
|
810
|
+
return { rows: result.files.map((file) => libraryRow(file)), total: result.files.length };
|
|
811
|
+
},
|
|
812
|
+
scanned: () => scan !== null
|
|
813
|
+
};
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
// src/grid/grid-open.ts
|
|
817
|
+
var GRID_STUB_DOCUMENT = { children: [], tagName: "div" };
|
|
818
|
+
async function openCsvGridTab(path) {
|
|
819
|
+
const existing = workspace.tabs.get(path);
|
|
820
|
+
if (existing) {
|
|
821
|
+
activateTab(path);
|
|
822
|
+
return existing;
|
|
823
|
+
}
|
|
824
|
+
try {
|
|
825
|
+
await loadFormats();
|
|
826
|
+
} catch {}
|
|
827
|
+
const source = createCsvFileSource(path);
|
|
828
|
+
const tab = openTab({
|
|
829
|
+
capabilities: { modes: ["grid", "source"] },
|
|
830
|
+
document: structuredClone(GRID_STUB_DOCUMENT),
|
|
831
|
+
documentPath: path,
|
|
832
|
+
id: path,
|
|
833
|
+
sourceFormat: formatForPath(path)?.name ?? null
|
|
834
|
+
});
|
|
835
|
+
const controller = createGridController(tab, source);
|
|
836
|
+
controller.load();
|
|
837
|
+
return tab;
|
|
838
|
+
}
|
|
839
|
+
function openVirtualGridTab(source) {
|
|
840
|
+
const tab = openTab({
|
|
841
|
+
capabilities: { modes: ["grid"] },
|
|
842
|
+
document: structuredClone(GRID_STUB_DOCUMENT),
|
|
843
|
+
documentPath: null,
|
|
844
|
+
id: source.id
|
|
845
|
+
});
|
|
846
|
+
const controller = createGridController(tab, source);
|
|
847
|
+
controller.load();
|
|
848
|
+
return tab;
|
|
849
|
+
}
|
|
850
|
+
function openCollectionGrid(typeName) {
|
|
851
|
+
const id = makeGridTabId({ kind: "collection", name: typeName });
|
|
852
|
+
const existing = workspace.tabs.get(id);
|
|
853
|
+
if (existing) {
|
|
854
|
+
activateTab(id);
|
|
855
|
+
return existing;
|
|
856
|
+
}
|
|
857
|
+
return openVirtualGridTab(createCollectionSource(typeName));
|
|
858
|
+
}
|
|
859
|
+
function openLibraryTab() {
|
|
860
|
+
const id = libraryTabId();
|
|
861
|
+
const existing = workspace.tabs.get(id);
|
|
862
|
+
if (existing) {
|
|
863
|
+
activateTab(id);
|
|
864
|
+
return existing;
|
|
865
|
+
}
|
|
866
|
+
return openTab({
|
|
867
|
+
capabilities: { modes: ["manage"] },
|
|
868
|
+
document: structuredClone(GRID_STUB_DOCUMENT),
|
|
869
|
+
documentPath: null,
|
|
870
|
+
id
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
function openPagesGrid() {
|
|
874
|
+
const id = makeGridTabId({ kind: "pages" });
|
|
875
|
+
const existing = workspace.tabs.get(id);
|
|
876
|
+
if (existing) {
|
|
877
|
+
activateTab(id);
|
|
878
|
+
return existing;
|
|
879
|
+
}
|
|
880
|
+
return openVirtualGridTab(createPagesSource());
|
|
881
|
+
}
|
|
882
|
+
function openConnectorGrid(connection, table) {
|
|
883
|
+
const id = makeGridTabId({ connection: connection ?? "default", kind: "data", table });
|
|
884
|
+
const existing = workspace.tabs.get(id);
|
|
885
|
+
if (existing) {
|
|
886
|
+
activateTab(id);
|
|
887
|
+
return existing;
|
|
888
|
+
}
|
|
889
|
+
return openVirtualGridTab(createConnectorSource(connection, table));
|
|
890
|
+
}
|
|
891
|
+
async function openGridSourcePicker() {
|
|
892
|
+
const collections = collectionDirs();
|
|
893
|
+
let connections = [];
|
|
894
|
+
if (dataSurfaceAvailable()) {
|
|
895
|
+
const response = await fetchConnections().catch(() => null);
|
|
896
|
+
connections = response?.connections ?? [];
|
|
897
|
+
}
|
|
898
|
+
const handle = openModal(html`<sp-dialog-wrapper
|
|
899
|
+
open
|
|
900
|
+
dismissable
|
|
901
|
+
underlay
|
|
902
|
+
headline="Open Grid"
|
|
903
|
+
@close=${() => handle.close()}
|
|
904
|
+
>
|
|
905
|
+
<sp-menu class="jx-grid-picker">
|
|
906
|
+
<sp-menu-group>
|
|
907
|
+
<span slot="header">Project</span>
|
|
908
|
+
<sp-menu-item
|
|
909
|
+
@click=${() => {
|
|
910
|
+
handle.close();
|
|
911
|
+
openPagesGrid();
|
|
912
|
+
}}
|
|
913
|
+
>Pages</sp-menu-item
|
|
914
|
+
>
|
|
915
|
+
${collections.map(({ name }) => html`<sp-menu-item
|
|
916
|
+
@click=${() => {
|
|
917
|
+
handle.close();
|
|
918
|
+
openCollectionGrid(name);
|
|
919
|
+
}}
|
|
920
|
+
>Collection: ${name}</sp-menu-item
|
|
921
|
+
>`)}
|
|
922
|
+
</sp-menu-group>
|
|
923
|
+
${connections.map((conn) => html`<sp-menu-group>
|
|
924
|
+
<span slot="header">Data · ${conn.name}</span>
|
|
925
|
+
${conn.tables.length === 0 ? html`<sp-menu-item disabled>No tables — push a schema first</sp-menu-item>` : conn.tables.map((table) => html`<sp-menu-item
|
|
926
|
+
@click=${() => {
|
|
927
|
+
handle.close();
|
|
928
|
+
openConnectorGrid(conn.name, table);
|
|
929
|
+
}}
|
|
930
|
+
>${table}</sp-menu-item
|
|
931
|
+
>`)}
|
|
932
|
+
</sp-menu-group>`)}
|
|
933
|
+
</sp-menu>
|
|
934
|
+
</sp-dialog-wrapper>`, { label: "Open Grid" });
|
|
935
|
+
}
|
|
936
|
+
function gridCommands() {
|
|
937
|
+
return [
|
|
938
|
+
{
|
|
939
|
+
args: argsSchema({
|
|
940
|
+
name: stringProperty("The content collection's name, as project.json declares it.")
|
|
941
|
+
}),
|
|
942
|
+
category: "Project",
|
|
943
|
+
id: "collection.editInGrid",
|
|
944
|
+
level: "project",
|
|
945
|
+
menus: ["context/file", "palette"],
|
|
946
|
+
group: "5_data",
|
|
947
|
+
requires: "a project that declares content collections",
|
|
948
|
+
when: (ctx) => ctx.project.open,
|
|
949
|
+
aiTool: {
|
|
950
|
+
description: "Open a content collection's entries as an editable grid in a new tab.",
|
|
951
|
+
name: "open_collection_grid"
|
|
952
|
+
},
|
|
953
|
+
run: (_commandCtx, args) => {
|
|
954
|
+
const name = stringArg("collection.editInGrid", args, "name");
|
|
955
|
+
const declared = collectionDirs().map((c) => c.name);
|
|
956
|
+
if (!declared.includes(name)) {
|
|
957
|
+
throw new RangeError(`command "collection.editInGrid" argument "name": "${name}" is not a content ` + `collection this project declares — it declares: ` + `${declared.length > 0 ? declared.join(", ") : "none"}`);
|
|
958
|
+
}
|
|
959
|
+
openCollectionGrid(name);
|
|
960
|
+
},
|
|
961
|
+
title: "Edit Collection in Grid"
|
|
962
|
+
},
|
|
963
|
+
{
|
|
964
|
+
args: {
|
|
965
|
+
additionalProperties: false,
|
|
966
|
+
properties: {
|
|
967
|
+
connection: stringProperty('The connection name from project.json. Defaults to "default".'),
|
|
968
|
+
table: stringProperty("The table to open.")
|
|
969
|
+
},
|
|
970
|
+
required: ["table"],
|
|
971
|
+
type: "object"
|
|
972
|
+
},
|
|
973
|
+
category: "Project",
|
|
974
|
+
id: "data.openGrid",
|
|
975
|
+
level: "project",
|
|
976
|
+
menus: ["palette"],
|
|
977
|
+
group: "5_data",
|
|
978
|
+
requires: "a platform that serves the data routes",
|
|
979
|
+
when: (ctx) => ctx.project.open,
|
|
980
|
+
enablement: (ctx) => ctx.capability.dataRows,
|
|
981
|
+
aiTool: {
|
|
982
|
+
description: "Open a connector table as an editable grid in a new tab.",
|
|
983
|
+
name: "open_data_grid"
|
|
984
|
+
},
|
|
985
|
+
run: (_commandCtx, args) => {
|
|
986
|
+
const table = stringArg("data.openGrid", args, "table");
|
|
987
|
+
openConnectorGrid(optionalStringArg("data.openGrid", args, "connection"), table);
|
|
988
|
+
},
|
|
989
|
+
title: "Open Data Grid"
|
|
990
|
+
}
|
|
991
|
+
];
|
|
992
|
+
}
|
|
993
|
+
function registerGridCommands(registry) {
|
|
994
|
+
registry.registerAll(gridCommands());
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
export { dataSurfaceAvailable, testConnection, pushSchema, deriveSecretEnvName, parseCsv, createCsvFileSource, LIBRARY_CATEGORIES, LIBRARY_CATEGORY_KEYS, libraryCategory, uploadDirForCategory, scanLibrary, filterLibrary, LIBRARY_LAYOUTS, LIBRARY_LAYOUT_LABELS, PREVIEW_LAYOUTS, projectLocales, libraryLocales, groupByDate, groupByCategory, libraryColumns, createLibrarySource, openCsvGridTab, openLibraryTab, openPagesGrid, openGridSourcePicker, registerGridCommands };
|
|
998
|
+
|
|
999
|
+
//# debugId=B5A73986FCDCB07464756E2164756E21
|
|
1000
|
+
//# sourceMappingURL=studio-9je6w5sq.js.map
|