@jxsuite/studio 2.0.0 → 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-0hzentwq.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-0hzentwq.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-2c188n41.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-97qcgvdn.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-97qcgvdn.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-hhj92gcr.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-ygzav7z5.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-n9zmpxjg.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 +23711 -35185
- 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 +34 -9
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +270 -262
- 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 -120
- 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 +75 -2
- 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 +113 -0
- 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-qct0gt8f.js +0 -531
- package/dist/chunks/extension-sections-qct0gt8f.js.map +0 -12
- package/dist/chunks/files-02zn5y24.js +0 -50
- package/dist/chunks/files-02zn5y24.js.map +0 -9
- package/dist/chunks/git-panel-mbb0y0hz.js +0 -28
- package/dist/chunks/git-panel-mbb0y0hz.js.map +0 -9
- package/dist/chunks/layers-panel-9qekmqk1.js +0 -26
- package/dist/chunks/layers-panel-9qekmqk1.js.map +0 -9
- package/dist/chunks/settings-modal-gj0hrah4.js +0 -29
- package/dist/chunks/settings-modal-gj0hrah4.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-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-568nx4t5.js +0 -469
- package/dist/chunks/studio-568nx4t5.js.map +0 -14
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-asvf0j9e.js +0 -429
- package/dist/chunks/studio-asvf0j9e.js.map +0 -13
- package/dist/chunks/studio-d77qm3pk.js +0 -3427
- package/dist/chunks/studio-d77qm3pk.js.map +0 -26
- package/dist/chunks/studio-j6gqyjf4.js +0 -1854
- package/dist/chunks/studio-j6gqyjf4.js.map +0 -18
- package/dist/chunks/studio-n9zmpxjg.js.map +0 -115
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-rq0vxb19.js +0 -3744
- package/dist/chunks/studio-rq0vxb19.js.map +0 -22
- package/dist/chunks/studio-wd6ewdvd.js +0 -853
- package/dist/chunks/studio-wd6ewdvd.js.map +0 -12
- 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-ygzav7z5.js.map +0 -46
- package/dist/chunks/studio-zmy7241e.js +0 -399
- package/dist/chunks/studio-zmy7241e.js.map +0 -12
- 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-2c188n41.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-hhj92gcr.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
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/project-list.ts", "../src/services/automation.ts", "../src/packages/ensure-deps.ts", "../src/files/fs-events.ts", "../src/services/data-service.ts", "../src/grid/grid-source.ts", "../src/grid/edit-buffer.ts", "../src/grid/grid-controller.ts", "../src/grid/csv-codec.ts", "../src/grid/schema-columns.ts", "../src/grid/sources/csv-file-source.ts", "../src/files/file-ops.ts", "../src/grid/sources/content-source.ts", "../src/grid/sources/connector-source.ts", "../src/grid/grid-open.ts", "../src/recent-projects.ts", "../src/files/files.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Project catalogue — a synchronous render cache over the optional `platform.listProjects` PAL\n * member (dev server sites, cloud platforms). Hydrated once at boot (studio.ts) like the\n * recent-projects cache; the welcome screen reads it synchronously.\n */\nimport { getPlatform, hasPlatform } from \"./platform\";\nimport type { ProjectListEntry } from \"./types\";\n\nlet cache: ProjectListEntry[] = [];\n\n/** True when the active platform exposes a project catalogue. */\nexport function platformListsProjects(): boolean {\n return hasPlatform() && typeof getPlatform().listProjects === \"function\";\n}\n\n/** Refresh the cache from the platform; resolves to [] when unsupported or failing. */\nexport async function hydrateProjectList(): Promise<void> {\n if (!platformListsProjects()) {\n cache = [];\n return;\n }\n try {\n cache = (await getPlatform().listProjects?.()) ?? [];\n } catch {\n // Catalogue is progressive enhancement; a failed fetch leaves the section hidden.\n cache = [];\n }\n}\n\n/** Synchronous snapshot for render paths (never awaits). */\nexport function getProjectList(): ProjectListEntry[] {\n return cache;\n}\n\n/** Reset seam for tests. */\nexport function resetProjectList(): void {\n cache = [];\n}\n\n/** Seed seam for tests and the screenshot automation hook (staged catalogues). */\nexport function seedProjectList(entries: ProjectListEntry[]): void {\n cache = entries;\n}\n",
|
|
6
|
-
"/// <reference lib=\"dom\" />\n/**\n * Automation hook — a small, gated scripting surface for driving Studio from a browser-automation\n * runner (see scripts/screenshots/ at the repo root). Installed as `window.__jxAutomation` only\n * when the page URL carries `?automation=1`; without the flag production behavior is untouched.\n *\n * The API mutates the same reactive state the real UI mutates (canvas mode, activity tab,\n * selection, inspector tab, function editor) instead of clicking through Spectrum shadow DOM, so\n * shot definitions stay stable across chrome refactors.\n */\n\nimport { renderOnly, updateUi } from \"../store\";\nimport { setProjectState } from \"../state\";\nimport { seedProjectList } from \"../project-list\";\nimport { activeTab, closeAllTabs, workspace } from \"../workspace/workspace\";\nimport type { ProjectListEntry } from \"../types\";\nimport { applyPanelCollapse, view } from \"../view\";\nimport { setEditZoom as applyEditZoomLevel } from \"../canvas/canvas-utils\";\nimport { collabState } from \"../collab/collab-state\";\nimport type { PeerPresence } from \"../collab/collab-state\";\nimport type { SeededAssistantMessage } from \"../panels/ai-panel\";\nimport type { PagesDeploymentInfo } from \"../publish/pages-service\";\nimport type { JxPath } from \"../state\";\n\n/** Callbacks injected from studio.ts (module-local helpers or imports kept out of this module). */\nexport interface AutomationDeps {\n getCanvasMode: () => string;\n openBrowseModal: () => void;\n openConnectorGrid: (connection: string | undefined, table: string) => void;\n openNewProjectModal: () => void;\n openQuickSearchPalette: () => void;\n openSettingsModal: (section?: string) => void;\n render: () => void;\n renderActivityBar: () => void;\n seedAssistantMessages: (messages: SeededAssistantMessage[]) => void;\n seedPublishConnected: (options: { accountId?: string; deployment: PagesDeploymentInfo }) => void;\n setCanvasMode: (mode: string) => void;\n statusMessage: (text: string) => void;\n}\n\nexport interface AutomationApi {\n editDef: (defName: string) => void;\n editFunction: (path: JxPath, eventKey: string) => void;\n openBrowse: () => void;\n openDataGrid: (options: { connection?: string; table: string }) => void;\n openNewProject: () => void;\n openQuickSearch: () => void;\n openSettings: (section?: string) => void;\n seedAssistant: (options: { messages: SeededAssistantMessage[] }) => void;\n seedCollab: (options: { peers: PeerPresence[] }) => void;\n seedPublish: (options: { accountId?: string; deployment: PagesDeploymentInfo }) => void;\n showWelcome: (options?: { projects?: ProjectListEntry[] }) => void;\n getState: () => {\n activeTabId: string | null;\n canvasMode: string;\n canvasStatus: string | null;\n leftTab: string;\n };\n select: (path: JxPath | null) => void;\n setActivity: (tab: string) => void;\n setCanvasMode: (mode: string) => void;\n setRightTab: (tab: string) => void;\n setStatus: (text: string) => void;\n setTheme: (color: string) => void;\n setZoom: (zoom: number) => void;\n setEditZoom: (zoom: number) => void;\n waitForCanvasReady: (timeoutMs?: number) => Promise<void>;\n}\n\n/** The hook is opt-in per page load: only `?automation=1` installs it. */\nexport function shouldInstallAutomation(search: string): boolean {\n return new URLSearchParams(search).get(\"automation\") === \"1\";\n}\n\nexport function createAutomationApi(deps: AutomationDeps): AutomationApi {\n return {\n editDef(defName: string) {\n updateUi(\"editingFunction\", { defName, type: \"def\" });\n deps.render();\n },\n editFunction(path: JxPath, eventKey: string) {\n updateUi(\"editingFunction\", { eventKey, path, type: \"event\" });\n deps.render();\n },\n openBrowse() {\n deps.openBrowseModal();\n },\n openDataGrid(options: { connection?: string; table: string }) {\n deps.openConnectorGrid(options.connection, options.table);\n },\n openNewProject() {\n deps.openNewProjectModal();\n },\n openQuickSearch() {\n deps.openQuickSearchPalette();\n },\n openSettings(section?: string) {\n deps.openSettingsModal(section);\n },\n seedAssistant(options: { messages: SeededAssistantMessage[] }) {\n deps.seedAssistantMessages(options.messages);\n },\n seedCollab(options: { peers: PeerPresence[] }) {\n // Stage a live co-editing session on the active tab: the toolbar's presence chips and the\n // Canvas peer-selection boxes both read this same reactive store.\n const tab = activeTab.value;\n if (!tab) {\n return;\n }\n const state = collabState(tab);\n state.status = \"synced\";\n state.active = true;\n state.peers = options.peers.map((peer) => ({\n ...peer,\n state: {\n ...peer.state,\n focusedPath: peer.state.focusedPath ?? tab.documentPath,\n },\n }));\n deps.render();\n },\n seedPublish(options: { accountId?: string; deployment: PagesDeploymentInfo }) {\n deps.seedPublishConnected(options);\n },\n showWelcome(options?: { projects?: ProjectListEntry[] }) {\n // The devserver platform auto-opens the repo-root project on boot; the welcome\n // Screen only renders with no project and no tabs, so stage that state directly.\n // A staged catalogue replaces the real one (screenshots must not leak local paths).\n closeAllTabs();\n setProjectState(null);\n if (options?.projects) {\n seedProjectList(options.projects);\n }\n view.chatPanelCollapsed = true;\n applyPanelCollapse();\n deps.render();\n },\n getState() {\n return {\n activeTabId: workspace.activeTabId,\n canvasMode: deps.getCanvasMode(),\n canvasStatus: activeTab.value?.session.canvas.status ?? null,\n leftTab: view.leftTab,\n };\n },\n select(path: JxPath | null) {\n const tab = activeTab.value;\n if (tab) {\n tab.session.selection = path;\n }\n deps.render();\n },\n setActivity(tab: string) {\n view.leftTab = tab;\n view.leftPanelCollapsed = false;\n applyPanelCollapse();\n renderOnly(\"leftPanel\");\n deps.renderActivityBar();\n },\n setCanvasMode(mode: string) {\n deps.setCanvasMode(mode);\n deps.render();\n },\n setRightTab(tab: string) {\n // \"assistant\" now lives in the persistent chat sidebar, not the right panel — keep the\n // Screenshot-manifest verb working by opening that sidebar instead.\n if (tab === \"assistant\") {\n view.chatPanelCollapsed = false;\n applyPanelCollapse();\n renderOnly(\"chatPanel\");\n deps.render();\n return;\n }\n updateUi(\"rightTab\", tab);\n deps.render();\n },\n setStatus(text: string) {\n deps.statusMessage(text);\n },\n setTheme(color: string) {\n document.querySelector(\"sp-theme\")?.setAttribute(\"color\", color);\n },\n setZoom(zoom: number) {\n updateUi(\"zoom\", zoom);\n deps.render();\n },\n setEditZoom(zoom: number) {\n // Deliberately NOT deps.render(): live edit zoom must never re-render the canvas (it would\n // Rebuild the iframe DOM) — setEditZoom applies bare style writes, matching production paths.\n applyEditZoomLevel(zoom);\n },\n waitForCanvasReady(timeoutMs = 30_000) {\n return new Promise((resolve, reject) => {\n const started = Date.now();\n const tick = () => {\n if (activeTab.value?.session.canvas.status === \"ready\") {\n resolve();\n return;\n }\n if (Date.now() - started > timeoutMs) {\n reject(new Error(`canvas not ready after ${timeoutMs}ms`));\n return;\n }\n setTimeout(tick, 50);\n };\n tick();\n });\n },\n };\n}\n\n/**\n * Install the hook on globalThis when the current URL opts in. Returns whether it installed, so\n * callers (and tests) can assert the gate.\n */\nexport function installAutomationHook(deps: AutomationDeps): boolean {\n if (!shouldInstallAutomation(location.search)) {\n return false;\n }\n (globalThis as Record<string, unknown>).__jxAutomation = createAutomationApi(deps);\n return true;\n}\n",
|
|
7
|
-
"/// <reference lib=\"dom\" />\n/**\n * Ensure the active project's dependencies are installed before the editor loads. When the backend\n * reports node_modules is missing, run `bun install` behind a blocking progress modal so component\n * and format resolution see the real dependency tree. No-op on platforms without package support.\n */\n\nimport { getPlatform } from \"../platform\";\nimport { showProgressModal } from \"../ui/progress-modal\";\nimport { shouldInstallAutomation } from \"../services/automation\";\n\nexport async function ensureDependenciesInstalled(): Promise<void> {\n // Automation/screenshot runs open projects read-only to drive the canvas — they must never mutate\n // The project on disk (a `bun install` would litter node_modules/bun.lock into starter templates).\n if (shouldInstallAutomation(location.search)) {\n return;\n }\n const platform = getPlatform();\n if (!platform.dependenciesNeedInstall || !platform.installDependencies) {\n return;\n }\n let needs = false;\n try {\n needs = await platform.dependenciesNeedInstall();\n } catch {\n return;\n }\n if (!needs) {\n return;\n }\n const progress = showProgressModal({\n status: \"Running bun install…\",\n title: \"Installing dependencies\",\n });\n try {\n const result = await platform.installDependencies();\n if (result.ok) {\n progress.done();\n } else {\n progress.fail(result.log ?? \"bun install failed\");\n }\n } catch (error) {\n progress.fail(error instanceof Error ? error.message : String(error));\n }\n}\n",
|
|
8
|
-
"/// <reference lib=\"dom\" />\n/**\n * Fs-events.ts — reconcile backend filesystem events into the cached sidebar tree.\n *\n * `applyFsEvents` is a pure, in-place reducer over `projectState.dirs`/`expanded` (unit-testable\n * without a DOM). `startFsSync` is the only impure part: it feature-detects the platform's\n * `subscribeFileEvents`, debounces bursts, drops the echoes of the user's own local mutations, and\n * triggers a single re-render through the existing left-panel render path (no imperative DOM).\n */\n\nimport { getPlatform } from \"../platform\";\nimport { projectState } from \"../store\";\nimport type { DirEntry, FsEvent } from \"../types\";\n\nconst RECENT_MS = 1500;\nconst recentLocal = new Map<string, number>();\n\nconst norm = (p: string) => p.replaceAll(\"\\\\\", \"/\");\n\n/** Mark paths the user just mutated locally so the watcher's echo of them is ignored briefly. */\nexport function markLocalMutation(...paths: string[]): void {\n const expiry = Date.now() + RECENT_MS;\n for (const p of paths) {\n if (p) {\n recentLocal.set(norm(p), expiry);\n }\n }\n}\n\n/** True while a path is within the recent-local-mutation window (self-cleans on expiry). */\nexport function isRecentLocal(path: string): boolean {\n const key = norm(path);\n const expiry = recentLocal.get(key);\n if (expiry === undefined) {\n return false;\n }\n if (Date.now() > expiry) {\n recentLocal.delete(key);\n return false;\n }\n return true;\n}\n\nfunction parentDir(path: string): string {\n const i = path.lastIndexOf(\"/\");\n return i === -1 ? \".\" : path.slice(0, i);\n}\n\nfunction baseName(path: string): string {\n const i = path.lastIndexOf(\"/\");\n return i === -1 ? path : path.slice(i + 1);\n}\n\n/**\n * Apply backend FS events to the cached directory tree in place, returning the set of directories\n * whose contents changed. Idempotent — re-adding an existing entry or removing an absent one is a\n * no-op, which absorbs watcher echoes. `change` events touch no tree state (name/type are stable).\n */\nexport function applyFsEvents(\n dirs: Map<string, DirEntry[]>,\n expanded: Set<string>,\n events: FsEvent[],\n): Set<string> {\n const changedDirs = new Set<string>();\n for (const ev of events) {\n const parent = parentDir(ev.path);\n if (ev.type === \"add\" || ev.type === \"addDir\") {\n const entries = dirs.get(parent);\n if (entries && !entries.some((e) => e.path === ev.path)) {\n entries.push({\n name: baseName(ev.path),\n path: ev.path,\n type: ev.isDir ? \"directory\" : \"file\",\n });\n changedDirs.add(parent);\n }\n if (ev.type === \"addDir\" && !dirs.has(ev.path)) {\n dirs.set(ev.path, []);\n }\n } else if (ev.type === \"unlink\" || ev.type === \"unlinkDir\") {\n const entries = dirs.get(parent);\n if (entries) {\n const idx = entries.findIndex((e) => e.path === ev.path);\n if (idx !== -1) {\n entries.splice(idx, 1);\n changedDirs.add(parent);\n }\n }\n if (ev.type === \"unlinkDir\") {\n dirs.delete(ev.path);\n const nestedDirs: string[] = [];\n for (const key of dirs.keys()) {\n if (key.startsWith(`${ev.path}/`)) {\n nestedDirs.push(key);\n }\n }\n for (const key of nestedDirs) {\n dirs.delete(key);\n }\n const staleExpanded: string[] = [];\n for (const key of expanded) {\n if (key === ev.path || key.startsWith(`${ev.path}/`)) {\n staleExpanded.push(key);\n }\n }\n for (const key of staleExpanded) {\n expanded.delete(key);\n }\n }\n }\n }\n return changedDirs;\n}\n\nexport interface FsSyncContext {\n renderLeftPanel: () => void;\n /** Optional hook for an external content change to an open file (e.g. reload a clean tab). */\n onContentChange?: (path: string) => void;\n}\n\n/**\n * Subscribe the sidebar to backend filesystem events. Returns an unsubscribe function; a no-op when\n * the platform has no watcher (desktop without one, or tests). Bursts are debounced into one\n * render.\n */\nexport function startFsSync(ctx: FsSyncContext): () => void {\n const platform = getPlatform();\n if (!platform.subscribeFileEvents) {\n return () => {};\n }\n let pending: FsEvent[] = [];\n let timer: ReturnType<typeof setTimeout> | null = null;\n\n const flush = () => {\n timer = null;\n const state = projectState;\n const batch = pending.filter((e) => !isRecentLocal(e.path));\n pending = [];\n if (!state || batch.length === 0) {\n return;\n }\n const changedDirs = applyFsEvents(state.dirs, state.expanded, batch);\n if (ctx.onContentChange) {\n for (const ev of batch) {\n if (ev.type === \"change\") {\n ctx.onContentChange(ev.path);\n }\n }\n }\n if (changedDirs.size > 0) {\n ctx.renderLeftPanel();\n }\n };\n\n return platform.subscribeFileEvents((events) => {\n pending.push(...events);\n if (timer) {\n clearTimeout(timer);\n }\n timer = setTimeout(flush, 50);\n });\n}\n",
|
|
9
|
-
"/**\n * Data-service — thin PAL wrapper over the optional data-surface members\n * (dataConnections/dataConnectionTest/dataPush/dataRows/row CRUD/listSecrets/setSecrets).\n *\n * Every helper degrades cleanly when the platform omits the member family (older backends, cloud\n * without DB reach): list-shaped calls resolve null/empty, action-shaped calls resolve an error\n * result instead of throwing. Secret VALUES only ever flow INTO setSecrets — reads are names-only\n * (specs/extensions.md §13).\n */\n\nimport { getPlatform } from \"../platform\";\nimport type {\n DataConnectionsResponse,\n DataConnectionTestResult,\n DataPushResult,\n DataRowDelete,\n DataRowInsert,\n DataRowsQuery,\n DataRowsResult,\n DataRowUpdate,\n SecretsSetRequest,\n SecretsSetResponse,\n StudioPlatform,\n} from \"../types\";\n\n/** The registered platform, or null before registration (early boot, bare tests). */\nfunction platformOrNull(): StudioPlatform | null {\n try {\n return getPlatform();\n } catch {\n return null;\n }\n}\n\n/** True when the platform serves the data grid (the family's gating member is dataRows). */\nexport function dataSurfaceAvailable(): boolean {\n return typeof platformOrNull()?.dataRows === \"function\";\n}\n\n/** True when the platform can store secret values (backs the \"secret\" form control). */\nexport function secretsAvailable(): boolean {\n return typeof platformOrNull()?.setSecrets === \"function\";\n}\n\n/** Connections with configured state and table names; null when the backend lacks the route. */\nexport async function fetchConnections(): Promise<DataConnectionsResponse | null> {\n const platform = platformOrNull();\n if (typeof platform?.dataConnections !== \"function\") {\n return null;\n }\n return platform.dataConnections();\n}\n\n/** Probe one connection; degrades to an error result instead of throwing. */\nexport async function testConnection(connection: string): Promise<DataConnectionTestResult> {\n const platform = platformOrNull();\n if (typeof platform?.dataConnectionTest !== \"function\") {\n return { error: \"Connection tests are not supported by this backend\", ok: false };\n }\n try {\n return await platform.dataConnectionTest(connection);\n } catch (error) {\n return { error: error instanceof Error ? error.message : String(error), ok: false };\n }\n}\n\n/** Push table schemas (dryRun compiles the plan only); degrades to an error result. */\nexport async function pushSchema(opts?: {\n connection?: string;\n dryRun?: boolean;\n}): Promise<DataPushResult> {\n const platform = platformOrNull();\n if (typeof platform?.dataPush !== \"function\") {\n return { applied: false, errors: [\"Schema push is not supported by this backend\"], plan: [] };\n }\n try {\n return await platform.dataPush(opts);\n } catch (error) {\n return {\n applied: false,\n errors: [error instanceof Error ? error.message : String(error)],\n plan: [],\n };\n }\n}\n\n/** A required data member, throwing a uniform degradation error when absent. */\nfunction requireMember<K extends keyof StudioPlatform>(name: K): NonNullable<StudioPlatform[K]> {\n const platform = platformOrNull();\n const member = platform?.[name];\n if (member === undefined || member === null) {\n throw new Error(`The ${String(name)} surface is not supported by this backend`);\n }\n return member as NonNullable<StudioPlatform[K]>;\n}\n\n/** Page a table's rows (grid callers handle errors per load). */\nexport function fetchRows(query: DataRowsQuery): Promise<DataRowsResult> {\n return requireMember(\"dataRows\")(query);\n}\n\nexport function insertRow(req: DataRowInsert): Promise<{ row: Record<string, unknown> }> {\n return requireMember(\"dataInsertRow\")(req);\n}\n\nexport function updateRow(req: DataRowUpdate): Promise<{ row: Record<string, unknown> }> {\n return requireMember(\"dataUpdateRow\")(req);\n}\n\nexport function deleteRow(req: DataRowDelete): Promise<{ ok: boolean }> {\n return requireMember(\"dataDeleteRow\")(req);\n}\n\n/** Configured secret env-var NAMES; null when the backend has no secrets surface. */\nexport async function listSecretNames(): Promise<string[] | null> {\n const platform = platformOrNull();\n if (typeof platform?.listSecrets !== \"function\") {\n return null;\n }\n return platform.listSecrets();\n}\n\n/** Write/remove secrets through the platform store (values flow in, names come back). */\nexport function saveSecrets(req: SecretsSetRequest): Promise<SecretsSetResponse> {\n return requireMember(\"setSecrets\")(req);\n}\n\n/**\n * Derive the env-var NAME a secret-marked field stores its value under: CONSTANT_CASE of the entry\n * key (falling back to the section key) plus the field key minus its `Env` suffix — e.g. connection\n * \"main\" field \"urlEnv\" → \"MAIN_URL\"; section \"auth\" field \"secretEnv\" → \"AUTH_SECRET\". The NAME\n * goes into project.json; the VALUE goes to setSecrets.\n *\n * @param {string} sectionKey\n * @param {string | null} entryKey - The map-layout entry (connection) name, when any\n * @param {string} fieldKey\n * @returns {string}\n */\nexport function deriveSecretEnvName(\n sectionKey: string,\n entryKey: string | null,\n fieldKey: string,\n): string {\n const constant = (raw: string) =>\n raw\n .replaceAll(/([a-z0-9])([A-Z])/g, \"$1_$2\")\n .replaceAll(/[^A-Za-z0-9]+/g, \"_\")\n .replaceAll(/^_+|_+$/g, \"\")\n .toUpperCase();\n const parts = [entryKey ?? sectionKey, fieldKey.replace(/Env$/, \"\")]\n .map((part) => constant(part))\n .filter(Boolean);\n const name = parts.join(\"_\") || \"SECRET\";\n return /^\\d/.test(name) ? `JX_${name}` : name;\n}\n",
|
|
10
|
-
"/**\n * Grid data-source contracts and grid-tab identity.\n *\n * A GridSource adapts one tabular backing store (a CSV file, a content collection, the pages tree,\n * a connector table) to the grid editor. Sources load columns/rows and commit a batched set of\n * pending edits; they never see the grid engine. Grid tabs over non-file sources are \"virtual\" —\n * their tab id is a `grid://` URI rather than a document path.\n */\nimport type { JsonSchema } from \"../ui/schema-form\";\n\n/** A single cell value. JSON-shaped so batches serialize cleanly. */\nexport type GridCellValue = string | number | boolean | string[] | null | { $ref: string };\n\n/** How a column edits/renders. Drives the cell editor/formatter mapping. */\nexport type GridColumnKind =\n | \"string\"\n | \"text\"\n | \"number\"\n | \"boolean\"\n | \"enum\"\n | \"array\"\n | \"image\"\n | \"date\"\n | \"reference\"\n | \"readonly\";\n\nexport interface GridColumn {\n /** Row-object key. */\n field: string;\n title: string;\n kind: GridColumnKind;\n /** Original JSON-Schema property, when the column came from a schema. */\n schema?: JsonSchema | undefined;\n required?: boolean | undefined;\n editable: boolean;\n /** Row-identity column (frozen first, never editable). */\n pk?: boolean | undefined;\n /** Editable only on pending-insert rows (e.g. a new entry's path). */\n insertOnly?: boolean | undefined;\n /** Preferred initial width in px. */\n widthHint?: number | undefined;\n}\n\nexport interface GridRow {\n /** Stable row id: file path, csv row id, or table pk value. */\n key: string;\n cells: Record<string, GridCellValue>;\n /** Staleness token (raw file text, content hash, …); absent for server-authoritative rows. */\n fingerprint?: string;\n}\n\nexport interface GridQuery {\n offset?: number;\n limit?: number;\n orderBy?: string;\n dir?: \"asc\" | \"desc\";\n}\n\nexport interface GridRowsResult {\n rows: GridRow[];\n total: number;\n}\n\n/** Pending edits, flattened for commit. Cells on pending-insert/delete rows are folded away. */\nexport interface GridEditBatch {\n cells: { rowKey: string; field: string; value: GridCellValue; baseline: GridCellValue }[];\n inserts: { tempKey: string; cells: Record<string, GridCellValue> }[];\n deletes: { rowKey: string }[];\n}\n\nexport interface CommitResult {\n cells: {\n rowKey: string;\n field: string;\n ok: boolean;\n error?: string | undefined;\n stale?: boolean | undefined;\n }[];\n inserts: {\n tempKey: string;\n ok: boolean;\n newKey?: string | undefined;\n error?: string | undefined;\n }[];\n deletes: {\n rowKey: string;\n ok: boolean;\n error?: string | undefined;\n stale?: boolean | undefined;\n }[];\n}\n\nexport interface GridSourceCapabilities {\n insert: boolean;\n delete: boolean;\n /** Rows are paged by the backend — the grid shows a pager instead of loading everything. */\n remotePaging: boolean;\n /** Sorting must go through rows(query) rather than the local engine. */\n remoteSort: boolean;\n}\n\nexport interface GridSource {\n /** Equals the tab id of the grid tab hosting it. */\n id: string;\n label: string;\n capabilities: GridSourceCapabilities;\n columns: () => Promise<GridColumn[]>;\n rows: (query?: GridQuery) => Promise<GridRowsResult>;\n commit: (batch: GridEditBatch) => Promise<CommitResult>;\n /** Re-read the backing store; the next columns()/rows() serve fresh data. */\n refresh?: (() => Promise<void>) | undefined;\n /** Full-file text including pending edits — source-mode display for file-backed grids. */\n serializeForSource?: ((batch: GridEditBatch) => Promise<string>) | undefined;\n /** Project paths backing rows, for fs-watch staleness (path → rowKey; \"*\" = every row). */\n backingPaths?: (() => Map<string, string>) | undefined;\n dispose?: (() => void) | undefined;\n}\n\n// ─── Value comparison ─────────────────────────────────────────────────────────\n\n/** Structural equality over GridCellValue (arrays element-wise, $ref by target). */\nexport function cellValuesEqual(a: GridCellValue, b: GridCellValue): boolean {\n if (a === b) {\n return true;\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n return a.length === b.length && a.every((v, i) => v === b[i]);\n }\n if (\n a !== null &&\n b !== null &&\n typeof a === \"object\" &&\n typeof b === \"object\" &&\n !Array.isArray(a) &&\n !Array.isArray(b)\n ) {\n return a.$ref === b.$ref;\n }\n return false;\n}\n\n// ─── Grid tab identity ────────────────────────────────────────────────────────\n\nconst GRID_SCHEME = \"grid://\";\n\nexport type GridTabRef =\n | { kind: \"pages\" }\n | { kind: \"collection\"; name: string }\n | { kind: \"data\"; connection: string; table: string };\n\n/** Build a virtual grid-tab id (`grid://…`). Segments are URI-encoded so `/` in names survives. */\nexport function makeGridTabId(ref: GridTabRef): string {\n switch (ref.kind) {\n case \"pages\": {\n return `${GRID_SCHEME}pages`;\n }\n case \"collection\": {\n return `${GRID_SCHEME}collection/${encodeURIComponent(ref.name)}`;\n }\n default: {\n return `${GRID_SCHEME}data/${encodeURIComponent(ref.connection)}/${encodeURIComponent(ref.table)}`;\n }\n }\n}\n\n/** Whether a tab id is a virtual grid-tab id. */\nexport function isGridTabId(id: string): boolean {\n return id.startsWith(GRID_SCHEME);\n}\n\n/** Parse a `grid://` tab id back into its source reference; null when not a grid id. */\nexport function parseGridTabId(id: string): GridTabRef | null {\n if (!isGridTabId(id)) {\n return null;\n }\n const parts = id.slice(GRID_SCHEME.length).split(\"/\");\n if (parts[0] === \"pages\" && parts.length === 1) {\n return { kind: \"pages\" };\n }\n if (parts[0] === \"collection\" && parts.length === 2 && parts[1]) {\n return { kind: \"collection\", name: decodeURIComponent(parts[1]) };\n }\n if (parts[0] === \"data\" && parts.length === 3 && parts[1] && parts[2]) {\n return {\n connection: decodeURIComponent(parts[1]),\n kind: \"data\",\n table: decodeURIComponent(parts[2]),\n };\n }\n return null;\n}\n\n/** Short human label for a grid tab (\"posts · grid\", \"users @ main · grid\", \"Pages · grid\"). */\nexport function gridTabLabel(id: string): string | null {\n const ref = parseGridTabId(id);\n if (!ref) {\n return null;\n }\n switch (ref.kind) {\n case \"pages\": {\n return \"Pages · grid\";\n }\n case \"collection\": {\n return `${ref.name} · grid`;\n }\n default: {\n return `${ref.table} @ ${ref.connection} · grid`;\n }\n }\n}\n",
|
|
11
|
-
"/**\n * Engine-agnostic edit buffer for grid tabs — the batch-save model's core.\n *\n * Cell edits, row inserts, and row deletes accumulate here (nothing touches disk/API until the user\n * saves); the grid engine only renders this state. Values equal to their baseline prune back to\n * clean. Undo/redo is an inverse-op stack over the buffer and SURVIVES save: a commit re-baselines\n * instead of clearing history, so a post-save undo simply makes cells dirty again. The one\n * exception is structural history — ops referencing successfully committed row inserts/deletes are\n * filtered out, because their temp keys/rows no longer exist.\n *\n * Baselines are resolved through `opts.resolveBaseline` at comparison time (not captured), which is\n * what lets history outlive commits.\n */\nimport { reactive } from \"../reactivity\";\nimport { cellValuesEqual } from \"./grid-source\";\nimport type { CommitResult, GridCellValue, GridEditBatch } from \"./grid-source\";\n\nexport type BufferOp =\n | {\n kind: \"cell\";\n rowKey: string;\n field: string;\n before: GridCellValue;\n after: GridCellValue;\n at: number;\n }\n | { kind: \"insert\"; tempKey: string; cells: Record<string, GridCellValue> }\n | { kind: \"drop-insert\"; tempKey: string; cells: Record<string, GridCellValue> }\n | { kind: \"delete\"; rowKey: string }\n | { kind: \"group\"; ops: BufferOp[] };\n\nexport type CellState = \"clean\" | \"dirty\" | \"error\" | \"stale\";\n\nexport type RowState = \"clean\" | \"dirty\" | \"pending-insert\" | \"pending-delete\" | \"stale\";\n\nexport interface EditBufferState {\n /** Map of rowKey → field → pending value (existing rows only). */\n pending: Map<string, Map<string, { value: GridCellValue }>>;\n /** Map of tempKey → the new row's cells (inserted rows carry their edits directly). */\n inserts: Map<string, Record<string, GridCellValue>>;\n deletes: Set<string>;\n /** Map of rowKey → field (or \"*\" for whole-row) → error message from the last commit. */\n errors: Map<string, Map<string, string>>;\n stale: Set<string>;\n undoStack: BufferOp[];\n redoStack: BufferOp[];\n}\n\nexport interface EditBufferOptions {\n /** Current committed value of a cell — consulted at comparison time, never captured. */\n resolveBaseline: (rowKey: string, field: string) => GridCellValue;\n /** Merge window for consecutive edits to the same cell (ms). */\n coalesceMs?: number;\n now?: () => number;\n}\n\nexport interface EditBuffer {\n state: EditBufferState;\n setCell: (rowKey: string, field: string, value: GridCellValue) => void;\n /** Add a pending new row; returns its temp key. */\n insertRow: (cells?: Record<string, GridCellValue>) => string;\n deleteRow: (rowKey: string) => void;\n /** Run edits as one undo group (paste, fill, multi-delete). Groups may not nest. */\n group: (fn: () => void) => void;\n /** Imperative group boundaries for edit bursts that span event callbacks (engine paste). */\n beginGroup: () => void;\n endGroup: () => void;\n undo: () => boolean;\n redo: () => boolean;\n canUndo: () => boolean;\n canRedo: () => boolean;\n isDirty: () => boolean;\n /** Pending cells + inserts + deletes — the Save button badge. */\n dirtyCount: () => number;\n isInsertKey: (rowKey: string) => boolean;\n effectiveValue: (rowKey: string, field: string) => GridCellValue;\n cellState: (rowKey: string, field: string) => CellState;\n rowState: (rowKey: string) => RowState;\n cellError: (rowKey: string, field: string) => string | null;\n buildBatch: () => GridEditBatch;\n applyCommitResult: (result: CommitResult) => void;\n markStale: (rowKeys: string[]) => void;\n /** Drop one row's pending edits (and its history — a discard is not undoable). */\n discardRow: (rowKey: string) => void;\n reset: () => void;\n}\n\nlet _tempCounter = 0;\n\n/** Create the reactive edit buffer for one grid tab. */\nexport function createEditBuffer(opts: EditBufferOptions): EditBuffer {\n const coalesceMs = opts.coalesceMs ?? 800;\n const now = opts.now ?? (() => Date.now());\n\n const state: EditBufferState = reactive({\n deletes: new Set<string>(),\n errors: new Map<string, Map<string, string>>(),\n inserts: new Map<string, Record<string, GridCellValue>>(),\n pending: new Map<string, Map<string, { value: GridCellValue }>>(),\n redoStack: [] as BufferOp[],\n stale: new Set<string>(),\n undoStack: [] as BufferOp[],\n }) as EditBufferState;\n\n let groupOps: BufferOp[] | null = null;\n\n // NB: on create paths, inner maps are built COMPLETE before insertion. Inserting an empty raw\n // Map and then mutating the held reference writes past the reactive proxy — effects get\n // Triggered at the empty intermediate state and never hear about the real content.\n const setError = (rowKey: string, field: string, message: string) => {\n const row = state.errors.get(rowKey);\n if (row) {\n row.set(field, message);\n } else {\n state.errors.set(rowKey, new Map([[field, message]]));\n }\n };\n\n const clearCellError = (rowKey: string, field: string) => {\n const row = state.errors.get(rowKey);\n row?.delete(field);\n if (row?.size === 0) {\n state.errors.delete(rowKey);\n }\n };\n\n const pushOp = (op: BufferOp) => {\n state.redoStack.length = 0;\n if (groupOps) {\n groupOps.push(op);\n return;\n }\n const last = state.undoStack.at(-1);\n if (\n op.kind === \"cell\" &&\n last?.kind === \"cell\" &&\n last.rowKey === op.rowKey &&\n last.field === op.field &&\n op.at - last.at <= coalesceMs\n ) {\n last.after = op.after;\n last.at = op.at;\n return;\n }\n state.undoStack.push(op);\n };\n\n /** Write a pending value without recording history (shared by user edits and undo/redo). */\n const writeCell = (rowKey: string, field: string, value: GridCellValue) => {\n const insertCells = state.inserts.get(rowKey);\n if (insertCells) {\n if (value === null) {\n delete insertCells[field];\n } else {\n insertCells[field] = value;\n }\n return;\n }\n if (cellValuesEqual(value, opts.resolveBaseline(rowKey, field))) {\n const row = state.pending.get(rowKey);\n row?.delete(field);\n if (row?.size === 0) {\n state.pending.delete(rowKey);\n }\n return;\n }\n const row = state.pending.get(rowKey);\n if (row) {\n row.set(field, { value });\n } else {\n state.pending.set(rowKey, new Map([[field, { value }]]));\n }\n };\n\n const effectiveValue = (rowKey: string, field: string): GridCellValue => {\n const insertCells = state.inserts.get(rowKey);\n if (insertCells) {\n return insertCells[field] ?? null;\n }\n const pending = state.pending.get(rowKey)?.get(field);\n return pending ? pending.value : opts.resolveBaseline(rowKey, field);\n };\n\n const cellError = (rowKey: string, field: string): string | null => {\n const row = state.errors.get(rowKey);\n return row?.get(field) ?? row?.get(\"*\") ?? null;\n };\n\n const applyOp = (op: BufferOp, direction: \"undo\" | \"redo\") => {\n switch (op.kind) {\n case \"cell\": {\n writeCell(op.rowKey, op.field, direction === \"undo\" ? op.before : op.after);\n break;\n }\n case \"insert\": {\n if (direction === \"undo\") {\n state.inserts.delete(op.tempKey);\n } else {\n state.inserts.set(op.tempKey, { ...op.cells });\n }\n break;\n }\n case \"drop-insert\": {\n if (direction === \"undo\") {\n state.inserts.set(op.tempKey, { ...op.cells });\n } else {\n state.inserts.delete(op.tempKey);\n }\n break;\n }\n case \"delete\": {\n if (direction === \"undo\") {\n state.deletes.delete(op.rowKey);\n } else {\n state.deletes.add(op.rowKey);\n }\n break;\n }\n default: {\n const ops = direction === \"undo\" ? op.ops.toReversed() : op.ops;\n for (const child of ops) {\n applyOp(child, direction);\n }\n break;\n }\n }\n };\n\n const beginGroup = () => {\n if (groupOps) {\n throw new Error(\"edit-buffer: groups may not nest\");\n }\n groupOps = [];\n };\n\n const endGroup = () => {\n const ops = groupOps;\n groupOps = null;\n if (!ops) {\n return;\n }\n if (ops.length === 1) {\n state.undoStack.push(ops[0]!);\n } else if (ops.length > 1) {\n state.undoStack.push({ kind: \"group\", ops });\n }\n };\n\n /** Ops referencing a committed/discarded row can no longer replay — filter them out. */\n const pruneHistory = (dropRow: (rowKey: string) => boolean) => {\n const keep = (op: BufferOp): BufferOp | null => {\n switch (op.kind) {\n case \"cell\": {\n return dropRow(op.rowKey) ? null : op;\n }\n case \"insert\":\n case \"drop-insert\": {\n return dropRow(op.tempKey) ? null : op;\n }\n case \"delete\": {\n return dropRow(op.rowKey) ? null : op;\n }\n default: {\n const ops = op.ops.map((child) => keep(child)).filter((o): o is BufferOp => o !== null);\n return ops.length > 0 ? { kind: \"group\", ops } : null;\n }\n }\n };\n state.undoStack = state.undoStack.map(keep).filter((o): o is BufferOp => o !== null);\n state.redoStack = state.redoStack.map(keep).filter((o): o is BufferOp => o !== null);\n };\n\n return {\n applyCommitResult(result) {\n const committedRows = new Set<string>();\n for (const cell of result.cells) {\n if (cell.ok) {\n const row = state.pending.get(cell.rowKey);\n row?.delete(cell.field);\n if (row?.size === 0) {\n state.pending.delete(cell.rowKey);\n }\n clearCellError(cell.rowKey, cell.field);\n } else {\n setError(cell.rowKey, cell.field, cell.error ?? \"Save failed\");\n if (cell.stale) {\n state.stale.add(cell.rowKey);\n }\n }\n }\n for (const ins of result.inserts) {\n if (ins.ok) {\n state.inserts.delete(ins.tempKey);\n state.errors.delete(ins.tempKey);\n committedRows.add(ins.tempKey);\n } else {\n setError(ins.tempKey, \"*\", ins.error ?? \"Insert failed\");\n }\n }\n for (const del of result.deletes) {\n if (del.ok) {\n state.deletes.delete(del.rowKey);\n state.pending.delete(del.rowKey);\n state.errors.delete(del.rowKey);\n committedRows.add(del.rowKey);\n } else {\n setError(del.rowKey, \"*\", del.error ?? \"Delete failed\");\n if (del.stale) {\n state.stale.add(del.rowKey);\n }\n }\n }\n for (const row of committedRows) {\n state.stale.delete(row);\n }\n if (committedRows.size > 0) {\n pruneHistory((rowKey) => committedRows.has(rowKey));\n }\n },\n\n buildBatch(): GridEditBatch {\n const cells: GridEditBatch[\"cells\"] = [];\n for (const [rowKey, fields] of state.pending) {\n if (state.deletes.has(rowKey)) {\n continue;\n }\n for (const [field, cell] of fields) {\n cells.push({\n baseline: opts.resolveBaseline(rowKey, field),\n field,\n rowKey,\n value: cell.value,\n });\n }\n }\n return {\n cells,\n deletes: [...state.deletes].map((rowKey) => ({ rowKey })),\n inserts: [...state.inserts].map(([tempKey, insertCells]) => ({\n cells: { ...insertCells },\n tempKey,\n })),\n };\n },\n\n canRedo: () => state.redoStack.length > 0,\n canUndo: () => state.undoStack.length > 0,\n cellError,\n\n cellState(rowKey, field) {\n if (cellError(rowKey, field) !== null) {\n return \"error\";\n }\n if (state.stale.has(rowKey)) {\n return \"stale\";\n }\n if (state.inserts.has(rowKey) || state.pending.get(rowKey)?.has(field)) {\n return \"dirty\";\n }\n return \"clean\";\n },\n\n deleteRow(rowKey) {\n if (state.deletes.has(rowKey)) {\n return;\n }\n const insertCells = state.inserts.get(rowKey);\n if (insertCells) {\n // Deleting a not-yet-saved insert just drops it (the row disappears entirely).\n const cells = { ...insertCells };\n state.inserts.delete(rowKey);\n state.errors.delete(rowKey);\n state.stale.delete(rowKey);\n pushOp({ cells, kind: \"drop-insert\", tempKey: rowKey });\n return;\n }\n state.deletes.add(rowKey);\n pushOp({ kind: \"delete\", rowKey });\n },\n\n dirtyCount() {\n let count = state.inserts.size + state.deletes.size;\n for (const [rowKey, fields] of state.pending) {\n if (!state.deletes.has(rowKey)) {\n count += fields.size;\n }\n }\n return count;\n },\n\n discardRow(rowKey) {\n state.pending.delete(rowKey);\n state.deletes.delete(rowKey);\n state.inserts.delete(rowKey);\n state.errors.delete(rowKey);\n state.stale.delete(rowKey);\n pruneHistory((key) => key === rowKey);\n },\n\n effectiveValue,\n\n beginGroup,\n\n endGroup,\n\n group(fn) {\n beginGroup();\n try {\n fn();\n } finally {\n endGroup();\n }\n },\n\n insertRow(cells = {}) {\n _tempCounter += 1;\n const tempKey = `__new-${_tempCounter}`;\n state.inserts.set(tempKey, { ...cells });\n pushOp({ cells: { ...cells }, kind: \"insert\", tempKey });\n return tempKey;\n },\n\n isDirty: () => state.pending.size > 0 || state.inserts.size > 0 || state.deletes.size > 0,\n\n isInsertKey: (rowKey) => state.inserts.has(rowKey),\n\n markStale(rowKeys) {\n for (const rowKey of rowKeys) {\n state.stale.add(rowKey);\n }\n },\n\n redo() {\n const op = state.redoStack.pop();\n if (!op) {\n return false;\n }\n applyOp(op, \"redo\");\n state.undoStack.push(op);\n return true;\n },\n\n reset() {\n state.pending.clear();\n state.inserts.clear();\n state.deletes.clear();\n state.errors.clear();\n state.stale.clear();\n state.undoStack.length = 0;\n state.redoStack.length = 0;\n },\n\n rowState(rowKey) {\n if (state.deletes.has(rowKey)) {\n return \"pending-delete\";\n }\n if (state.inserts.has(rowKey)) {\n return \"pending-insert\";\n }\n if (state.stale.has(rowKey)) {\n return \"stale\";\n }\n if (state.pending.has(rowKey) || state.errors.has(rowKey)) {\n return \"dirty\";\n }\n return \"clean\";\n },\n\n setCell(rowKey, field, value) {\n const before = effectiveValue(rowKey, field);\n if (cellValuesEqual(before, value)) {\n return;\n }\n writeCell(rowKey, field, value);\n pushOp({ after: value, at: now(), before, field, kind: \"cell\", rowKey });\n },\n\n state,\n\n undo() {\n const op = state.undoStack.pop();\n if (!op) {\n return false;\n }\n applyOp(op, \"undo\");\n state.redoStack.push(op);\n return true;\n },\n };\n}\n",
|
|
12
|
-
"/**\n * Per-tab grid orchestration — no DOM, no grid engine.\n *\n * Owns the source, the reactive load state, and the edit buffer for one grid tab. Created inside\n * the tab's effectScope so everything (dirty mirroring, history delegate, fs subscription, the\n * registry entry) tears down when the tab closes. The buffer's dirtiness mirrors onto\n * `tab.doc.dirty`, which makes the existing tab-strip dot and close-confirm flows work unchanged;\n * undo/redo registers as the tab's HistoryDelegate, so Cmd-Z and the toolbar buttons route here\n * without any shortcut edits.\n *\n * Save is explicit and batched: validate required cells → confirm deletes → commit through the\n * source → clear/re-baseline what succeeded, keep failures dirty with errors, mark stale rows.\n */\nimport { effect, onScopeDispose, reactive, toRaw } from \"../reactivity\";\nimport { getPlatform } from \"../platform\";\nimport { setHistoryDelegate } from \"../tabs/transact\";\nimport { isRecentLocal } from \"../files/fs-events\";\nimport { statusMessage } from \"../panels/statusbar\";\nimport { showConfirmDialog } from \"../ui/layers\";\nimport { showProgressModal } from \"../ui/progress-modal\";\nimport { errorMessage } from \"@jxsuite/schema/parse\";\nimport { createEditBuffer } from \"./edit-buffer\";\nimport type { EditBuffer } from \"./edit-buffer\";\nimport type {\n CommitResult,\n GridCellValue,\n GridColumn,\n GridEditBatch,\n GridQuery,\n GridRow,\n GridSource,\n} from \"./grid-source\";\nimport type { Tab } from \"../tabs/tab\";\n\nexport interface GridControllerState {\n columns: GridColumn[];\n /** Committed rows as last loaded/saved — baselines live here. */\n rows: GridRow[];\n total: number;\n loading: boolean;\n saving: boolean;\n error: string | null;\n query: GridQuery;\n}\n\n/** What the engine wrapper exposes back to the controller for out-of-band data changes. */\nexport interface GridViewBinding {\n /** Re-pull effectiveRows() into the table (undo/redo, save, refresh, row add/delete). */\n refreshData: () => void;\n}\n\nexport interface GridController {\n tab: Tab;\n source: GridSource;\n state: GridControllerState;\n buffer: EditBuffer;\n load: () => Promise<void>;\n /** Reload from the source; asks before discarding pending edits. */\n refresh: () => Promise<void>;\n save: () => Promise<void>;\n /** Query change (connector paging/sorting) — reloads rows. */\n setQuery: (query: GridQuery) => Promise<void>;\n /** Plain row objects (committed + pending overlay + pending inserts) for the grid engine. */\n effectiveRows: () => Record<string, GridCellValue>[];\n /** Current file text including pending edits, for source-mode display (file grids only). */\n serializeForSource: () => Promise<string> | null;\n /** Attach/detach the engine wrapper. Edits flowing FROM the table never round-trip back. */\n bindView: (view: GridViewBinding | null) => void;\n /** Buffer a new row (pending insert) and sync the view. Returns its temp key. */\n addRow: (cells?: Record<string, GridCellValue>) => string;\n /** Buffer row deletions as one undo group and sync the view. */\n deleteRows: (rowKeys: string[]) => void;\n /** Drop one row's pending edits (not undoable) and sync the view. */\n discardRow: (rowKey: string) => void;\n /** Replace text across editable string/text cells (one undo group). Returns cells changed. */\n replaceAll: (find: string, replace: string) => number;\n}\n\n/** Row-object key carrying the grid row identity through the engine. */\nexport const ROW_KEY_FIELD = \"__key\";\n\nconst _controllers = new WeakMap<object, GridController>();\n\n/** The grid controller for a tab, if it is a grid tab. */\nexport function getGridController(tab: Tab | null): GridController | null {\n return tab ? (_controllers.get(toRaw(tab as unknown as object)) ?? null) : null;\n}\n\n/** Create and register the controller for a grid tab. One per tab; lives in the tab's scope. */\nexport function createGridController(tab: Tab, source: GridSource): GridController {\n const state: GridControllerState = reactive({\n columns: [] as GridColumn[],\n error: null as string | null,\n loading: false,\n query: {} as GridQuery,\n rows: [] as GridRow[],\n saving: false,\n total: 0,\n }) as GridControllerState;\n\n let rowByKey = new Map<string, GridRow>();\n const indexRows = (rows: GridRow[]) => {\n rowByKey = new Map(rows.map((row) => [row.key, row]));\n };\n\n const buffer = createEditBuffer({\n resolveBaseline: (rowKey, field) => rowByKey.get(rowKey)?.cells[field] ?? null,\n });\n\n const reloadRows = async () => {\n const result = await source.rows(state.query);\n state.rows = result.rows;\n state.total = result.total;\n indexRows(result.rows);\n };\n\n /** Missing required cells block the save (marked as row/cell errors, like a failed commit). */\n const requiredViolations = (batch: GridEditBatch): CommitResult | null => {\n const required = state.columns.filter((c) => c.required && c.editable);\n if (required.length === 0) {\n return null;\n }\n const cells = batch.cells\n .filter((cell) => cell.value === null && required.some((c) => c.field === cell.field))\n .map((cell) => ({ error: \"Required\", field: cell.field, ok: false, rowKey: cell.rowKey }));\n const inserts = batch.inserts\n .filter((insert) =>\n required.some((c) => insert.cells[c.field] === null || insert.cells[c.field] === undefined),\n )\n .map((insert) => {\n const missing = required\n .filter((c) => insert.cells[c.field] === null || insert.cells[c.field] === undefined)\n .map((c) => c.field)\n .join(\", \");\n return { error: `Missing required: ${missing}`, ok: false, tempKey: insert.tempKey };\n });\n if (cells.length === 0 && inserts.length === 0) {\n return null;\n }\n return { cells, deletes: [], inserts };\n };\n\n let viewBinding: GridViewBinding | null = null;\n const syncView = () => viewBinding?.refreshData();\n\n const controller: GridController = {\n addRow(cells = {}) {\n const tempKey = buffer.insertRow(cells);\n syncView();\n return tempKey;\n },\n\n bindView(view) {\n viewBinding = view;\n },\n\n buffer,\n\n deleteRows(rowKeys) {\n if (rowKeys.length === 0) {\n return;\n }\n buffer.group(() => {\n for (const rowKey of rowKeys) {\n buffer.deleteRow(rowKey);\n }\n });\n syncView();\n },\n\n discardRow(rowKey) {\n buffer.discardRow(rowKey);\n syncView();\n },\n\n replaceAll(find, replace) {\n if (find === \"\") {\n return 0;\n }\n const textColumns = state.columns.filter(\n (column) => column.editable && (column.kind === \"string\" || column.kind === \"text\"),\n );\n const rowKeys = [...state.rows.map((row) => row.key), ...buffer.state.inserts.keys()];\n let changed = 0;\n buffer.group(() => {\n for (const rowKey of rowKeys) {\n if (buffer.rowState(rowKey) === \"pending-delete\") {\n continue;\n }\n for (const column of textColumns) {\n const value = buffer.effectiveValue(rowKey, column.field);\n if (typeof value === \"string\" && value.includes(find)) {\n buffer.setCell(rowKey, column.field, value.replaceAll(find, replace));\n changed += 1;\n }\n }\n }\n });\n if (changed > 0) {\n syncView();\n }\n return changed;\n },\n\n effectiveRows() {\n // Detach values from reactive proxies — the grid engine must never hold live proxies.\n const plain = (value: GridCellValue): GridCellValue =>\n Array.isArray(value)\n ? [...value]\n : value !== null && typeof value === \"object\"\n ? { $ref: value.$ref }\n : value;\n const rowObject = (key: string) => {\n const cells: Record<string, GridCellValue> = { [ROW_KEY_FIELD]: key };\n for (const column of state.columns) {\n cells[column.field] = plain(buffer.effectiveValue(key, column.field));\n }\n return cells;\n };\n const rows = state.rows.map((row) => rowObject(row.key));\n for (const [tempKey] of buffer.state.inserts) {\n rows.push(rowObject(tempKey));\n }\n return rows;\n },\n\n async load() {\n state.loading = true;\n state.error = null;\n try {\n state.columns = await source.columns();\n await reloadRows();\n } catch (error) {\n state.error = errorMessage(error);\n } finally {\n state.loading = false;\n }\n syncView();\n },\n\n async refresh() {\n if (buffer.isDirty()) {\n const confirmed = await showConfirmDialog(\n \"Refresh Grid\",\n `Discard ${buffer.dirtyCount()} pending change(s) and reload?`,\n { confirmLabel: \"Discard & Reload\", destructive: true },\n );\n if (!confirmed) {\n return;\n }\n }\n buffer.reset();\n await source.refresh?.();\n await this.load();\n },\n\n async save() {\n if (state.saving) {\n return;\n }\n const batch = buffer.buildBatch();\n const changeCount = batch.cells.length + batch.inserts.length + batch.deletes.length;\n if (changeCount === 0) {\n statusMessage(\"No grid changes to save\");\n return;\n }\n const violations = requiredViolations(batch);\n if (violations) {\n buffer.applyCommitResult(violations);\n statusMessage(\"Required cells are empty — fix the marked rows and save again\", 5000);\n return;\n }\n if (batch.deletes.length > 0) {\n const confirmed = await showConfirmDialog(\n \"Delete Rows\",\n `Save will permanently delete ${batch.deletes.length} row(s). Continue?`,\n { confirmLabel: \"Delete & Save\", destructive: true },\n );\n if (!confirmed) {\n return;\n }\n }\n\n const affectedRows =\n new Set(batch.cells.map((c) => c.rowKey)).size +\n batch.inserts.length +\n batch.deletes.length;\n const progress = affectedRows > 5 ? showProgressModal({ title: \"Saving grid\" }) : null;\n state.saving = true;\n try {\n const result = await source.commit(batch);\n\n // Move baselines for saved cells before the buffer clears their pending entries.\n const cellKey = (rowKey: string, field: string) => `${rowKey}\u0000${field}`;\n const batchCells = new Map(batch.cells.map((c) => [cellKey(c.rowKey, c.field), c]));\n for (const outcome of result.cells) {\n const cell = batchCells.get(cellKey(outcome.rowKey, outcome.field));\n if (outcome.ok && cell) {\n const row = rowByKey.get(outcome.rowKey);\n if (row) {\n row.cells[outcome.field] = cell.value;\n }\n }\n }\n buffer.applyCommitResult(result);\n\n const structural = result.inserts.some((r) => r.ok) || result.deletes.some((r) => r.ok);\n if (structural) {\n await reloadRows();\n }\n\n const okCount =\n result.cells.filter((r) => r.ok).length +\n result.inserts.filter((r) => r.ok).length +\n result.deletes.filter((r) => r.ok).length;\n const failed = changeCount - okCount;\n const staleCount =\n result.cells.filter((r) => r.stale).length + result.deletes.filter((r) => r.stale).length;\n statusMessage(\n failed === 0\n ? `Saved ${okCount} change(s)`\n : `Saved ${okCount} · ${failed} failed${staleCount ? ` (${staleCount} stale)` : \"\"} — kept pending`,\n failed === 0 ? 3000 : 6000,\n );\n } catch (error) {\n statusMessage(`Save error: ${errorMessage(error)}`, 6000);\n } finally {\n state.saving = false;\n progress?.done();\n syncView();\n }\n },\n\n serializeForSource() {\n if (!source.serializeForSource) {\n return null;\n }\n return source.serializeForSource(buffer.buildBatch());\n },\n\n async setQuery(query: GridQuery) {\n state.query = query;\n state.loading = true;\n try {\n await reloadRows();\n } catch (error) {\n state.error = errorMessage(error);\n } finally {\n state.loading = false;\n }\n syncView();\n },\n\n source,\n state,\n tab,\n };\n\n tab.scope.run(() => {\n // Buffer dirtiness IS the tab's dirty flag — tab-strip dot and close-confirm come for free.\n effect(() => {\n tab.doc.dirty = buffer.isDirty();\n });\n\n setHistoryDelegate(tab, {\n canRedo: () => buffer.canRedo(),\n canUndo: () => buffer.canUndo(),\n redo: () => {\n buffer.redo();\n syncView();\n },\n undo: () => {\n buffer.undo();\n syncView();\n },\n });\n\n const platform = getPlatform();\n if (platform.subscribeFileEvents && source.backingPaths) {\n const unsubscribe = platform.subscribeFileEvents((events) => {\n const backing = source.backingPaths!();\n const hitKeys = new Set<string>();\n for (const event of events) {\n if (event.isDir) {\n continue;\n }\n const path = event.path.replaceAll(\"\\\\\", \"/\");\n const rowKey = backing.get(path);\n if (rowKey !== undefined && !isRecentLocal(path)) {\n hitKeys.add(rowKey);\n }\n }\n if (hitKeys.size === 0) {\n return;\n }\n if (buffer.isDirty()) {\n const keys = hitKeys.has(\"*\") ? state.rows.map((row) => row.key) : [...hitKeys];\n buffer.markStale(keys);\n statusMessage(\"Grid rows changed on disk — marked stale (refresh to reload)\", 5000);\n syncView();\n } else {\n void controller.refresh();\n }\n });\n onScopeDispose(unsubscribe);\n }\n\n onScopeDispose(() => {\n setHistoryDelegate(tab, null);\n _controllers.delete(toRaw(tab as unknown as object));\n source.dispose?.();\n });\n });\n\n _controllers.set(toRaw(tab as unknown as object), controller);\n return controller;\n}\n",
|
|
13
|
-
"/**\n * Positional CSV codec for the grid editor.\n *\n * RFC 4180 parse/serialize that keeps what the parser extension's object-row loader discards:\n * column order, duplicate/empty headers, untrimmed whitespace, the file's dominant EOL, and whether\n * it ended with a newline. Values stay raw strings — typing lives in schema-columns. Serialization\n * is canonical (quotes only where required), so an edited file is re-emitted minimally quoted;\n * untouched files are never rewritten.\n */\n\nexport interface CsvDocument {\n headers: string[];\n rows: string[][];\n eol: \"\\n\" | \"\\r\\n\";\n trailingNewline: boolean;\n}\n\n/** Split CSV text into records of raw fields, honoring quotes across commas and newlines. */\nfunction splitRecords(text: string): string[][] {\n const records: string[][] = [];\n let fields: string[] = [];\n let field = \"\";\n let inQuotes = false;\n let fieldStarted = false;\n\n const endField = () => {\n fields.push(field);\n field = \"\";\n fieldStarted = false;\n };\n const endRecord = () => {\n endField();\n // A completely empty line is structure, not data — skip it (common trailing-blank case).\n if (fields.length === 1 && fields[0] === \"\") {\n fields = [];\n return;\n }\n records.push(fields);\n fields = [];\n };\n\n for (let i = 0; i < text.length; i++) {\n const ch = text[i];\n if (inQuotes) {\n if (ch === '\"') {\n if (text[i + 1] === '\"') {\n field += '\"';\n i += 1;\n } else {\n inQuotes = false;\n }\n } else {\n field += ch;\n }\n continue;\n }\n if (ch === '\"' && !fieldStarted) {\n inQuotes = true;\n fieldStarted = true;\n } else if (ch === '\"') {\n // Quote inside an unquoted field — keep it literal (lenient, matches common parsers).\n field += ch;\n } else if (ch === \",\") {\n endField();\n } else if (ch === \"\\n\") {\n endRecord();\n } else if (ch === \"\\r\") {\n if (text[i + 1] === \"\\n\") {\n i += 1;\n }\n endRecord();\n } else {\n field += ch;\n fieldStarted = true;\n }\n }\n if (field !== \"\" || fields.length > 0) {\n endRecord();\n }\n return records;\n}\n\n/**\n * Parse CSV text into headers + positional rows. Rows are padded to the header width; when a data\n * row is wider than the header row, headers are padded with \"\" so no column is lost.\n */\nexport function parseCsv(text: string): CsvDocument {\n const crlf = (text.match(/\\r\\n/g) ?? []).length;\n const bareLf = (text.match(/(?<!\\r)\\n/g) ?? []).length;\n const eol: CsvDocument[\"eol\"] = crlf > bareLf ? \"\\r\\n\" : \"\\n\";\n const trailingNewline = text.endsWith(\"\\n\");\n\n const records = splitRecords(text);\n const headers = records[0] ?? [];\n const rows = records.slice(1);\n const width = Math.max(headers.length, ...rows.map((r) => r.length), 0);\n while (headers.length < width) {\n headers.push(\"\");\n }\n for (const row of rows) {\n while (row.length < width) {\n row.push(\"\");\n }\n }\n return { eol, headers, rows, trailingNewline };\n}\n\n/** Quote a field iff it contains a delimiter, quote, or newline; double embedded quotes. */\nfunction encodeField(value: string): string {\n if (/[\",\\n\\r]/.test(value)) {\n return `\"${value.replaceAll('\"', '\"\"')}\"`;\n }\n return value;\n}\n\n/** Serialize back to CSV text, preserving the document's EOL flavor and trailing-newline flag. */\nexport function serializeCsv(doc: CsvDocument): string {\n const lines = [doc.headers, ...doc.rows].map((fields) =>\n fields.map((field) => encodeField(field)).join(\",\"),\n );\n return lines.join(doc.eol) + (doc.trailingNewline ? doc.eol : \"\");\n}\n",
|
|
14
|
-
"/**\n * Schema → grid-column mapping and cell value coercion.\n *\n * Pure functions shared by every grid source: derive `GridColumn[]` from a content-type JSON Schema\n * (same field-type semantics as settings/schema-field-ui `detectFieldType`), infer columns by\n * sniffing rows when no schema exists (pages, schemaless CSV), and convert between typed cell\n * values and the strings that editors, clipboards, and CSV files traffic in. Coercion mirrors the\n * parser extension's `coerceCSVRows` (currency-stripped numbers, `\"true\"` booleans, comma-split\n * arrays) so grid edits round-trip identically to the runtime content loader.\n */\nimport type { GridCellValue, GridColumn, GridColumnKind } from \"./grid-source\";\nimport type { JsonSchema } from \"../ui/schema-form\";\n\n/** JSON-Schema property as it appears in content-type schemas (superset of ui JsonSchema). */\ninterface PropSchema extends JsonSchema {\n $ref?: string;\n maxLength?: number;\n}\n\nconst KIND_WIDTHS: Record<GridColumnKind, number> = {\n array: 220,\n boolean: 70,\n date: 130,\n enum: 140,\n image: 180,\n number: 110,\n readonly: 200,\n reference: 200,\n string: 180,\n text: 340,\n};\n\n/** Longest-string width clamp used for sampled string/enum columns. */\nfunction clampWidth(maxLen: number): number {\n return Math.min(340, Math.max(90, Math.round(maxLen * 7.5)));\n}\n\n/** Field kind for one schema property — same dispatch as schema-field-ui's detectFieldType. */\nexport function kindForProp(prop: PropSchema): GridColumnKind {\n if (prop.$ref) {\n return \"reference\";\n }\n if (prop.enum !== undefined && Array.isArray(prop.enum)) {\n return \"enum\";\n }\n const format = prop.type === \"array\" ? undefined : prop.format;\n if (format === \"image\") {\n return \"image\";\n }\n if (format === \"date\" || format === \"date-time\") {\n return \"date\";\n }\n switch (prop.type) {\n case \"number\":\n case \"integer\": {\n return \"number\";\n }\n case \"boolean\": {\n return \"boolean\";\n }\n case \"array\": {\n return \"array\";\n }\n case \"object\": {\n // Nested objects have no inline editor — surfaced read-only for now.\n return \"readonly\";\n }\n default: {\n return (prop.maxLength ?? 0) > 200 || prop.format === \"markdown\" ? \"text\" : \"string\";\n }\n }\n}\n\n/** Human column title from a camelCase/snake_case field name. */\nexport function titleForField(field: string): string {\n const spaced = field\n .replaceAll(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replaceAll(/[_-]+/g, \" \")\n .trim();\n return spaced.charAt(0).toUpperCase() + spaced.slice(1);\n}\n\nexport interface ColumnsFromSchemaOptions {\n /** Field to pin as the identity column (frozen first, still editable unless readonly). */\n idField?: string | undefined;\n /** Extra fields to force read-only. */\n readonlyFields?: string[] | undefined;\n}\n\n/**\n * Map a content-type/JSON schema's properties to grid columns. Order: identity field first, then\n * required properties in declaration order, then the rest in declaration order.\n */\nexport function columnsFromSchema(\n schema: { properties?: Record<string, unknown>; required?: string[] } | null | undefined,\n opts: ColumnsFromSchemaOptions = {},\n): GridColumn[] {\n const props = Object.entries(schema?.properties ?? {}) as [string, PropSchema][];\n const required = new Set(schema?.required);\n const readonly = new Set(opts.readonlyFields);\n\n const columns = props.map(([field, prop]): GridColumn => {\n const kind = readonly.has(field) ? \"readonly\" : kindForProp(prop);\n const enumLen = Array.isArray(prop.enum)\n ? Math.max(...(prop.enum as unknown[]).map((v) => String(v).length), 4)\n : 0;\n return {\n editable: kind !== \"readonly\",\n field,\n kind,\n pk: field === opts.idField,\n required: required.has(field),\n schema: prop,\n title: titleForField(field),\n widthHint: kind === \"enum\" ? clampWidth(enumLen + 3) : KIND_WIDTHS[kind],\n };\n });\n\n columns.sort((a, b) => {\n const rank = (c: GridColumn) => (c.pk ? 0 : c.required ? 1 : 2);\n const diff = rank(a) - rank(b);\n return diff === 0 ? 0 : diff;\n });\n return columns;\n}\n\n/**\n * Infer columns by sniffing row values (pages and schemaless CSV). Keys appear in first-seen order;\n * a column's kind is the narrowest type every non-empty sample value satisfies.\n */\nexport function inferColumnsFromRows(\n rows: Record<string, GridCellValue>[],\n sampleLimit = 50,\n): GridColumn[] {\n const sample = rows.slice(0, sampleLimit);\n const fields: string[] = [];\n for (const row of sample) {\n for (const key of Object.keys(row)) {\n if (!fields.includes(key)) {\n fields.push(key);\n }\n }\n }\n\n return fields.map((field): GridColumn => {\n const values = sample\n .map((row) => row[field])\n .filter((v): v is Exclude<GridCellValue, null> => v !== null && v !== undefined && v !== \"\");\n const kind = inferKind(values);\n const maxLen = Math.max(...values.map((v) => cellToText(v).length), field.length, 4);\n return {\n editable: true,\n field,\n kind,\n title: titleForField(field),\n widthHint: kind === \"string\" || kind === \"text\" ? clampWidth(maxLen) : KIND_WIDTHS[kind],\n };\n });\n}\n\nfunction inferKind(values: Exclude<GridCellValue, null>[]): GridColumnKind {\n if (values.length === 0) {\n return \"string\";\n }\n if (values.some((v) => Array.isArray(v))) {\n return \"array\";\n }\n const texts = values.map(String);\n if (\n values.every((v) => typeof v === \"boolean\") ||\n texts.every((t) => /^(true|false)$/i.test(t))\n ) {\n return \"boolean\";\n }\n if (\n values.every((v) => typeof v === \"number\") ||\n texts.every((t) => t.trim() !== \"\" && !Number.isNaN(Number(t.replaceAll(/[$€£¥,\\s]/g, \"\"))))\n ) {\n return \"number\";\n }\n if (texts.every((t) => /^\\d{4}-\\d{2}-\\d{2}([T ].*)?$/.test(t))) {\n return \"date\";\n }\n if (texts.some((t) => t.length > 200)) {\n return \"text\";\n }\n return \"string\";\n}\n\n// ─── Value coercion ───────────────────────────────────────────────────────────\n\n/**\n * Coerce editor/clipboard input to the column's typed value. Empty input clears to null. Number and\n * array semantics mirror the parser extension's coerceCSVRows.\n */\nexport function coerceCellInput(raw: unknown, col: GridColumn): GridCellValue {\n if (raw === null || raw === undefined) {\n return null;\n }\n switch (col.kind) {\n case \"number\": {\n if (typeof raw === \"number\") {\n return Number.isNaN(raw) ? null : raw;\n }\n const cleaned = String(raw)\n .trim()\n .replaceAll(/[$€£¥,\\s]/g, \"\");\n if (cleaned === \"\") {\n return null;\n }\n const n = Number(cleaned);\n return Number.isNaN(n) ? null : n;\n }\n case \"boolean\": {\n if (typeof raw === \"boolean\") {\n return raw;\n }\n return String(raw).trim().toLowerCase() === \"true\";\n }\n case \"array\": {\n if (Array.isArray(raw)) {\n return raw.map(String);\n }\n const text = String(raw).trim();\n return text === \"\"\n ? []\n : text\n .split(\",\")\n .map((s) => s.trim())\n .filter(Boolean);\n }\n case \"reference\": {\n // Relationship VALUES are plain target-entry ids (\"jane-doe\") — the $ref lives on the\n // Schema property, not in the data (specs/relationships.md; parser resolveContentTypeRefs).\n if (typeof raw === \"object\" && raw !== null && \"$ref\" in raw) {\n const ref = (raw as { $ref: unknown }).$ref;\n return typeof ref === \"string\" && ref !== \"\" ? ref : null;\n }\n const text = String(raw).trim();\n return text === \"\" ? null : text;\n }\n default: {\n const text = String(raw);\n return text === \"\" ? null : text;\n }\n }\n}\n\n/** Plain-text projection of a cell value — display, clipboard, and CSV share it. */\nexport function cellToText(value: GridCellValue): string {\n if (value === null || value === undefined) {\n return \"\";\n }\n if (Array.isArray(value)) {\n return value.join(\", \");\n }\n if (typeof value === \"object\") {\n return value.$ref;\n }\n return String(value);\n}\n",
|
|
15
|
-
"/**\n * CSV file grid source — one `.csv` project file edited as a grid.\n *\n * The file loads once into a positional string matrix (csv-codec). Columns are typed by the\n * matching content-type schema when the CSV backs a collection (same resolver as the head panel),\n * otherwise inferred by sampling values. Commit is atomic whole-file: pending edits are applied to\n * the matrix, the document is re-serialized, and a save-time staleness check (file text vs. the\n * load-time text) aborts the entire commit rather than clobber an external change. Only edited\n * cells are canonicalized — untouched cells keep their raw file text.\n */\nimport { getPlatform } from \"../../platform\";\nimport { projectState } from \"../../store\";\nimport { findContentTypeSchema } from \"../../utils/studio-utils\";\nimport { isRecentLocal, markLocalMutation } from \"../../files/fs-events\";\nimport { parseCsv, serializeCsv } from \"../csv-codec\";\nimport {\n cellToText,\n coerceCellInput,\n columnsFromSchema,\n inferColumnsFromRows,\n} from \"../schema-columns\";\nimport type { CsvDocument } from \"../csv-codec\";\nimport type {\n CommitResult,\n GridCellValue,\n GridColumn,\n GridEditBatch,\n GridRow,\n GridRowsResult,\n GridSource,\n} from \"../grid-source\";\n\n/** Candidate identity columns, in the parser extension's fallback order. */\nconst ID_FIELDS = [\"id\", \"sku\", \"slug\", \"Slug\"];\n\ninterface CsvModel {\n doc: CsvDocument;\n /** Unique field name per column position (duplicate/empty headers get positional names). */\n fields: string[];\n columns: GridColumn[];\n /** Map of rowKey → matrix row index. */\n keyToIndex: Map<string, number>;\n /** Matrix row index → rowKey. */\n keys: string[];\n /** File text at load time — the whole-file staleness fingerprint. */\n loadText: string;\n}\n\n/** Unique grid field names for CSV headers (duplicates/empties fall back to positional names). */\nexport function fieldNamesForHeaders(headers: string[]): string[] {\n const used = new Set<string>();\n return headers.map((header, i) => {\n let name = header.trim() === \"\" ? `column${i + 1}` : header;\n if (used.has(name)) {\n name = `${name}__${i + 1}`;\n }\n used.add(name);\n return name;\n });\n}\n\n/** Pick the identity column: first id-chain field whose values are all unique and non-empty. */\nfunction pickIdField(fields: string[], doc: CsvDocument): string | null {\n for (const candidate of ID_FIELDS) {\n const idx = fields.indexOf(candidate);\n if (idx === -1) {\n continue;\n }\n const values = doc.rows.map((row) => row[idx] ?? \"\");\n if (values.every((v) => v !== \"\") && new Set(values).size === values.length) {\n return candidate;\n }\n }\n return null;\n}\n\nfunction buildModel(text: string, path: string): CsvModel {\n const doc = parseCsv(text);\n const fields = fieldNamesForHeaders(doc.headers);\n const idField = pickIdField(fields, doc);\n const idIndex = idField ? fields.indexOf(idField) : -1;\n const keys = doc.rows.map((row, i) => (idIndex === -1 ? String(i) : row[idIndex]!));\n const keyToIndex = new Map(keys.map((key, i) => [key, i]));\n\n // Typed columns when this CSV is a collection source; sniffed kinds otherwise.\n const contentType = findContentTypeSchema(path, projectState?.projectConfig);\n const schemaProps = contentType?.schema?.properties ?? {};\n const sampleRows = doc.rows.slice(0, 50).map((row) => {\n const cells: Record<string, GridCellValue> = {};\n for (const [i, field] of fields.entries()) {\n cells[field] = row[i] ?? \"\";\n }\n return cells;\n });\n const inferred = new Map(inferColumnsFromRows(sampleRows).map((c) => [c.field, c]));\n const typed = new Map(\n columnsFromSchema(contentType?.schema, { idField: idField ?? undefined }).map((c) => [\n c.field,\n c,\n ]),\n );\n\n const columns = fields.map((field, i): GridColumn => {\n const fromSchema = field in schemaProps ? typed.get(field) : undefined;\n const column = fromSchema ??\n inferred.get(field) ?? {\n editable: true,\n field,\n kind: \"string\" as const,\n title: doc.headers[i] || field,\n };\n return { ...column, pk: field === idField, title: doc.headers[i]?.trim() || column.title };\n });\n\n return { columns, doc, fields, keys, keyToIndex, loadText: text };\n}\n\n/** Typed cell values for one matrix row. */\nfunction rowCells(model: CsvModel, rowIndex: number): Record<string, GridCellValue> {\n const cells: Record<string, GridCellValue> = {};\n const row = model.doc.rows[rowIndex] ?? [];\n for (const [i, field] of model.fields.entries()) {\n const column = model.columns[i]!;\n const raw = row[i] ?? \"\";\n cells[field] =\n column.kind === \"string\" || column.kind === \"text\" || column.kind === \"readonly\"\n ? raw\n : coerceCellInput(raw, column);\n }\n return cells;\n}\n\n/** Apply a batch to a copy of the matrix (cells, then inserts, then deletes). */\nfunction applyBatch(model: CsvModel, batch: GridEditBatch): CsvDocument {\n const rows = model.doc.rows.map((row) => [...row]);\n const colFor = (field: string) => model.fields.indexOf(field);\n\n for (const cell of batch.cells) {\n const rowIndex = model.keyToIndex.get(cell.rowKey);\n const colIndex = colFor(cell.field);\n if (rowIndex === undefined || colIndex === -1) {\n continue;\n }\n rows[rowIndex]![colIndex] = cellToText(cell.value);\n }\n for (const insert of batch.inserts) {\n const row = model.fields.map((field) => cellToText(insert.cells[field] ?? null));\n rows.push(row);\n }\n const dropIndexes = batch.deletes\n .map((del) => model.keyToIndex.get(del.rowKey))\n .filter((i): i is number => i !== undefined)\n .toSorted((a, b) => b - a);\n for (const index of dropIndexes) {\n rows.splice(index, 1);\n }\n return { ...model.doc, rows };\n}\n\n/** All batch items resolved with one shared outcome (whole-file commits are atomic). */\nfunction uniformResult(\n batch: GridEditBatch,\n outcome: { ok: boolean; error?: string; stale?: boolean },\n): CommitResult {\n return {\n cells: batch.cells.map((c) => ({ field: c.field, rowKey: c.rowKey, ...outcome })),\n deletes: batch.deletes.map((d) => ({ rowKey: d.rowKey, ...outcome })),\n inserts: batch.inserts.map((i) => ({\n error: outcome.error,\n ok: outcome.ok,\n tempKey: i.tempKey,\n })),\n };\n}\n\n/** Create the grid source for one CSV file. The tab id is the file path. */\nexport function createCsvFileSource(path: string): GridSource {\n let loadPromise: Promise<CsvModel> | null = null;\n\n const load = (force = false): Promise<CsvModel> => {\n if (!force && loadPromise) {\n return loadPromise;\n }\n loadPromise = getPlatform()\n .readFile(path)\n .then((text) => buildModel(text, path));\n return loadPromise;\n };\n\n return {\n backingPaths: () => new Map([[path, \"*\"]]),\n capabilities: { delete: true, insert: true, remotePaging: false, remoteSort: false },\n\n async columns(): Promise<GridColumn[]> {\n const current = await load();\n return current.columns;\n },\n\n async commit(batch: GridEditBatch): Promise<CommitResult> {\n const current = await load();\n const platform = getPlatform();\n\n // Whole-file staleness: abort if the file changed under us (and it wasn't our own write).\n let onDisk: string | null = null;\n try {\n onDisk = await platform.readFile(path);\n } catch {\n onDisk = null; // Deleted underneath — treat as stale.\n }\n if (onDisk !== current.loadText && !isRecentLocal(path)) {\n return uniformResult(batch, {\n error: \"File changed on disk — refresh to reload\",\n ok: false,\n stale: true,\n });\n }\n\n const nextDoc = applyBatch(current, batch);\n const text = serializeCsv(nextDoc);\n markLocalMutation(path);\n await platform.writeFile(path, text);\n loadPromise = Promise.resolve(buildModel(text, path));\n return uniformResult(batch, { ok: true });\n },\n\n id: path,\n label: path.split(\"/\").pop() ?? path,\n\n async refresh(): Promise<void> {\n await load(true);\n },\n\n async rows(): Promise<GridRowsResult> {\n const current = await load();\n const rows: GridRow[] = current.doc.rows.map((_, i) => ({\n cells: rowCells(current, i),\n key: current.keys[i]!,\n }));\n return { rows, total: rows.length };\n },\n\n async serializeForSource(batch: GridEditBatch): Promise<string> {\n const current = await load();\n return serializeCsv(applyBatch(current, batch));\n },\n };\n}\n",
|
|
16
|
-
"/// <reference lib=\"dom\" />\n/**\n * File Operations — open, save, export documents.\n *\n * All functions read/write directly from/to `activeTab.value` (the reactive tab). `.json` is the\n * native document format; every other extension dispatches through the project's format registry\n * (parse to open, serialize to save).\n */\n\nimport { locateDocument } from \"../services/code-services\";\nimport { errorMessage } from \"@jxsuite/schema/parse\";\nimport { statusMessage } from \"../panels/statusbar\";\nimport { validateComponentSlots } from \"../services/cem-export\";\nimport { getPlatform } from \"../platform\";\nimport { getGridController } from \"../grid/grid-controller\";\nimport { activeTab, openTab } from \"../workspace/workspace\";\nimport { collabSave } from \"../collab/collab-session\";\nimport { flushCanvasEdits } from \"../canvas/iframe-host\";\nimport {\n defaultContentFormat,\n formatByName,\n formatForPath,\n formatParse,\n formatSerialize,\n getFormats,\n loadFormats,\n noFormatError,\n splitFormatDocument,\n} from \"../format/format-host\";\nimport type { StudioFormat } from \"../format/format-host\";\nimport type { Tab } from \"../tabs/tab.js\";\n\n/**\n * Parse a format-class source string into document + frontmatter + mode per the format's\n * $studio.documentMode hints.\n *\n * @param {StudioFormat} format\n * @param {string} source\n */\nexport async function parseFormatSource(format: StudioFormat, source: string) {\n const doc = await formatParse(format.name, source);\n return splitFormatDocument(format, doc);\n}\n\n/**\n * Parse a source string for a file path, dispatching by extension through the format registry.\n * Returns null for `.json` (native — callers JSON.parse) and throws when no format class claims the\n * extension.\n *\n * @param {string} path\n * @param {string} source\n */\nexport async function parseSourceForPath(path: string, source: string) {\n await loadFormats();\n const format = formatForPath(path);\n if (!format || !format.capabilities.parse) {\n throw noFormatError(path);\n }\n const result = await parseFormatSource(format, source);\n return { ...result, format };\n}\n\n/** Open a file via the File System Access API (or fallback input). */\nexport async function openFile() {\n try {\n await loadFormats();\n const formats = getFormats();\n const pickerTypes = [\n {\n accept: { \"application/json\": [\".json\"] },\n description: \"Jx Component\",\n },\n ...formats\n .filter((f) => f.capabilities.parse)\n .map((f) => ({\n accept: { [f.mediaType ?? \"text/plain\"]: f.extensions },\n description: f.name,\n })),\n ];\n const acceptExts = [\".json\", ...formats.flatMap((f) => f.extensions)].join(\",\");\n\n const handleSource = async (\n name: string,\n text: string,\n handle: FileSystemFileHandle | null = null,\n ) => {\n const documentPath = handle ? await locateDocument(name) : null;\n const format = formatForPath(name);\n if (format) {\n const { document, frontmatter } = await parseFormatSource(format, text);\n openTab({\n document,\n documentPath,\n fileHandle: handle,\n frontmatter,\n id: name,\n sourceFormat: format.name,\n });\n } else if (name.endsWith(\".json\")) {\n const document = JSON.parse(text) as Record<string, unknown>;\n openTab({ document, documentPath, fileHandle: handle, id: name });\n } else {\n throw noFormatError(name);\n }\n statusMessage(`Opened ${name}`);\n };\n\n if (\"showOpenFilePicker\" in window) {\n const [handle] = await (\n window as unknown as {\n showOpenFilePicker: (options?: unknown) => Promise<FileSystemFileHandle[]>;\n }\n ).showOpenFilePicker({ types: pickerTypes });\n const file = await handle!.getFile();\n await handleSource(handle!.name, await file.text(), handle!);\n } else {\n // Fallback: file input\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.accept = acceptExts;\n input.addEventListener(\"change\", async () => {\n const file = input.files?.[0];\n if (!file) {\n return;\n }\n await handleSource(file.name, await file.text());\n });\n input.click();\n }\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n }\n}\n\n/**\n * Report a slot-validation warning for component documents (root tagName with a hyphen). The save\n * still proceeds — the warning replaces the plain success message.\n *\n * @param {Tab} tab\n * @param {string} savedMsg\n */\nfunction savedMessage(tab: Tab, savedMsg: string) {\n const doc = tab.doc.document;\n const warning =\n typeof doc.tagName === \"string\" && doc.tagName.includes(\"-\")\n ? validateComponentSlots(doc)\n : null;\n if (warning) {\n statusMessage(`${savedMsg} — Warning: ${warning}`, 6000);\n } else {\n statusMessage(savedMsg);\n }\n}\n\n/** Save the current document back to its source location. */\nexport async function saveFile() {\n const tab = activeTab.value;\n if (!tab) {\n return;\n }\n // Text reaches the document on an idle tick, so the words still sitting in the caret's block have\n // To be committed before anything serializes it. This used to be `if (isEditing()) stopEditing()`,\n // Which was dead: editing lives in the canvas IFRAME, and `isEditing()` here reads the parent\n // Realm's copy of that module, where a session never starts. Saving mid-sentence silently wrote\n // The file without the sentence.\n await flushCanvasEdits(tab.id);\n // Grid tabs batch-save through their controller (per-source commit semantics, not a doc write).\n const grid = getGridController(tab);\n if (grid) {\n await grid.save();\n return;\n }\n try {\n // A co-edited tab persists through its provider (a direct file write would reset the room).\n if (await collabSave(tab)) {\n savedMessage(tab, \"Synced\");\n return;\n }\n const output = await serializeDocument(tab);\n\n if (tab.documentPath) {\n const platform = getPlatform();\n await platform.writeFile(tab.documentPath, output);\n tab.doc.dirty = false;\n savedMessage(tab, \"Saved\");\n } else if (tab.fileHandle && \"createWritable\" in tab.fileHandle) {\n const writable =\n await /**\n * @type {{\n * createWritable: () => Promise<{\n * write: (s: string) => Promise<void>;\n * close: () => Promise<void>;\n * }>;\n * }}\n */ tab.fileHandle.createWritable();\n await writable.write(output);\n await writable.close();\n tab.doc.dirty = false;\n savedMessage(tab, \"Saved\");\n } else {\n statusMessage(\"No save target — use Export\");\n }\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n statusMessage(`Save error: ${errorMessage(error)}`);\n }\n }\n}\n\n/** The output format for a tab: its source format, or the default content format. */\nfunction tabFormat(tab: Tab): StudioFormat | undefined {\n return (\n formatByName(tab.doc.sourceFormat) ??\n (tab.doc.mode === \"content\" ? defaultContentFormat() : undefined)\n );\n}\n\n/** Export the current document to a new location (Save As / download). */\nexport async function exportFile() {\n const tab = activeTab.value;\n if (!tab) {\n return;\n }\n try {\n await loadFormats();\n const format = tabFormat(tab);\n const output = await serializeDocument(tab);\n const mimeType = format ? (format.mediaType ?? \"text/plain\") : \"application/json\";\n const ext = format ? format.extensions[0] : \".json\";\n const description = format ? format.name : \"Jx Component\";\n const fallbackName = format ? `content${ext}` : \"component.json\";\n\n if (\"showSaveFilePicker\" in window) {\n const suggestedName = tab.documentPath ? tab.documentPath.split(\"/\").pop() : fallbackName;\n const handle = await (\n window as unknown as {\n showSaveFilePicker: (options?: unknown) => Promise<FileSystemFileHandle>;\n }\n ).showSaveFilePicker({\n suggestedName,\n types: [{ accept: { [mimeType]: [ext] }, description }],\n });\n const writable = await handle.createWritable();\n await writable.write(output);\n await writable.close();\n tab.doc.dirty = false;\n savedMessage(tab, `Exported as ${handle.name}`);\n } else {\n // Fallback: download\n const blob = new Blob([output], { type: mimeType });\n const url = URL.createObjectURL(blob);\n const a = document.createElement(\"a\");\n a.href = url;\n a.download = fallbackName;\n a.click();\n URL.revokeObjectURL(url);\n tab.doc.dirty = false;\n savedMessage(tab, \"Downloaded\");\n }\n } catch (error) {\n if (!(error instanceof Error && error.name === \"AbortError\")) {\n statusMessage(`Export error: ${errorMessage(error)}`);\n }\n }\n}\n\n/**\n * Serialize the current document to its output format. Format tabs round-trip through the format\n * class's serialize capability; everything else is native JSON.\n *\n * @param {import(\"../tabs/tab.js\").Tab} tab\n * @returns {Promise<string>}\n */\nexport async function serializeDocument(tab: Tab): Promise<string> {\n // Grid tabs serialize through their source (pending edits included) — e.g. the Monaco source\n // View of a CSV grid tab shows the live file text.\n const grid = getGridController(tab);\n const gridText = grid?.serializeForSource();\n if (gridText) {\n return gridText;\n }\n await loadFormats();\n const sourceFormat = formatByName(tab.doc.sourceFormat);\n if (sourceFormat?.capabilities.serialize) {\n const fm = tab.doc.content?.frontmatter || {};\n const doc = tab.doc.document;\n const fullDoc = { ...fm, ...doc, children: doc.children ?? [] };\n return formatSerialize(sourceFormat.name, fullDoc, { mode: \"roundtrip\" });\n }\n if (tab.doc.mode === \"content\") {\n const format = defaultContentFormat();\n if (format) {\n const fm = tab.doc.content?.frontmatter ?? {};\n const hasFrontmatter = Object.keys(fm).length > 0;\n const fullDoc = { ...fm, ...tab.doc.document };\n return formatSerialize(format.name, fullDoc, {\n frontmatter: hasFrontmatter,\n mode: \"roundtrip\",\n });\n }\n }\n return JSON.stringify(tab.doc.document, null, 2);\n}\n",
|
|
17
|
-
"/**\n * Frontmatter-file grid sources — content collections and the pages tree.\n *\n * One row per entry file: rows load by enumerating a directory and parsing each file through the\n * format registry (same path the editor tabs use); cells are the entry frontmatter. Commit is\n * per-row with the same guards a tab save gets: a stale-on-disk check against the load-time text,\n * and a skip when the file is open in a dirty tab (a clean open tab reloads after the write).\n * Frontmatter re-serializes through the format's roundtrip capability — the same lossy-YAML\n * semantics as saving a single tab. Inserts write a new file from the required Path cell; deletes\n * remove files (never while a tab is open on them).\n *\n * Collections type their columns from the content-type schema (plus inferred extras found in the\n * data); the pages grid is fully inference-driven.\n */\nimport { getPlatform } from \"../../platform\";\nimport { projectState } from \"../../store\";\nimport { workspace } from \"../../workspace/workspace\";\nimport { isRecentLocal, markLocalMutation } from \"../../files/fs-events\";\nimport {\n defaultContentFormat,\n documentExtensions,\n formatByName,\n formatForPath,\n formatSerialize,\n loadFormats,\n} from \"../../format/format-host\";\nimport { parseSourceForPath } from \"../../files/file-ops\";\nimport { columnsFromSchema, inferColumnsFromRows } from \"../schema-columns\";\nimport { makeGridTabId } from \"../grid-source\";\nimport type {\n CommitResult,\n GridCellValue,\n GridColumn,\n GridEditBatch,\n GridRow,\n GridRowsResult,\n GridSource,\n} from \"../grid-source\";\nimport type { ContentSectionEntry } from \"../../types\";\n\n/** The synthetic identity column: the entry's project path. Editable only on pending inserts. */\nexport const PATH_FIELD = \"__path\";\n\ninterface EntryRecord {\n frontmatter: Record<string, unknown>;\n document: Record<string, unknown>;\n rawText: string;\n formatName: string;\n}\n\ninterface CollectionInfo {\n name: string;\n def: ContentSectionEntry;\n dir: string;\n ext: string;\n}\n\n/** Resolve a content type's definition, source dir, and entry extension from project config. */\nexport function collectionInfo(typeName: string): CollectionInfo | null {\n const content = (projectState?.projectConfig?.content ?? {}) as Record<\n string,\n ContentSectionEntry\n >;\n const def = content[typeName];\n if (!def?.source) {\n return null;\n }\n const dir = def.source.replace(/^\\.\\//, \"\").replace(/\\/$/, \"\");\n const ext =\n def.format === \"json\"\n ? \".json\"\n : (formatByName(def.format)?.extensions[0] ??\n defaultContentFormat()?.extensions[0] ??\n \".json\");\n return { def, dir, ext, name: typeName };\n}\n\n/** Directory-backed collections in the project (for \"Edit collection in Grid\" affordances). */\nexport function collectionDirs(): { name: string; dir: string }[] {\n const content = (projectState?.projectConfig?.content ?? {}) as Record<\n string,\n ContentSectionEntry\n >;\n return Object.entries(content)\n .filter(([, def]) => {\n const source = def.source?.replace(/^\\.\\//, \"\") ?? \"\";\n return source !== \"\" && !/\\.[a-z0-9]+$/i.test(source);\n })\n .map(([name, def]) => ({ dir: def.source!.replace(/^\\.\\//, \"\").replace(/\\/$/, \"\"), name }));\n}\n\n/** Recursively list entry files under a dir matching any of the extensions. */\nasync function listEntryFiles(dir: string, exts: string[]): Promise<string[]> {\n const platform = getPlatform();\n const results: string[] = [];\n const walk = async (current: string) => {\n let children;\n try {\n children = await platform.listDirectory(current);\n } catch {\n return; // Missing/unreadable directory — an empty source, not an error.\n }\n for (const entry of children) {\n if (entry.type === \"directory\") {\n await walk(entry.path);\n } else if (exts.some((ext) => entry.path.endsWith(ext))) {\n results.push(entry.path);\n }\n }\n };\n await walk(dir);\n return results.toSorted();\n}\n\n/** Entry ids (file stems) of a collection — used by relationship cell editors. */\nexport async function listCollectionEntryIds(typeName: string): Promise<string[]> {\n await loadFormats().catch(() => {}); // Extension resolution needs the format registry.\n const info = collectionInfo(typeName);\n if (!info) {\n return [];\n }\n const files = await listEntryFiles(info.dir, [info.ext]);\n return files.map((path) => {\n const base = path.split(\"/\").pop() ?? path;\n return base.slice(0, base.length - info.ext.length);\n });\n}\n\n/** Bounded-concurrency map that preserves item order. */\nasync function mapLimit<T, R>(\n items: T[],\n limit: number,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results: R[] = Array.from({ length: items.length });\n let next = 0;\n const workers = Array.from({ length: Math.min(limit, items.length) }, async () => {\n while (next < items.length) {\n const index = next;\n next += 1;\n results[index] = await fn(items[index]!);\n }\n });\n await Promise.all(workers);\n return results;\n}\n\n/** Frontmatter value → grid cell value. Nested objects surface as read-only JSON text. */\nfunction toCellValue(value: unknown): GridCellValue {\n if (value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n if (Array.isArray(value) && value.every((v) => typeof v !== \"object\" || v === null)) {\n return value.map(String);\n }\n return JSON.stringify(value);\n}\n\n/** A tab open on this path, if any (workspace tabs key by id = path). */\nfunction openTabFor(path: string) {\n for (const tab of workspace.tabs.values()) {\n if (tab.documentPath === path) {\n return tab;\n }\n }\n return null;\n}\n\n/** Whether every sampled value for a field was a genuine string (vs. stringified objects). */\nfunction extraRowsAreStrings(rows: Record<string, GridCellValue>[], field: string): boolean {\n return rows.every((row) => {\n const value = row[field];\n return value === null || value === undefined || typeof value !== \"string\"\n ? true\n : !value.startsWith(\"{\") && !value.startsWith(\"[\");\n });\n}\n\ninterface EntryFileSourceOptions {\n id: string;\n label: string;\n /** List the entry file paths (called on every (re)load). */\n list: () => Promise<string[]>;\n /** Schema driving typed columns; null/undefined → columns are fully inferred. */\n schema: () => ContentSectionEntry[\"schema\"] | null | undefined;\n /** Normalize a Path-cell value into a full project path for inserts. */\n resolveInsertPath: (raw: string) => string;\n /** Format used to serialize a NEW entry at this path; null blocks the insert. */\n insertFormatName: (path: string) => string | null;\n /** Inferred columns to front-load, in order (e.g. title/description for pages). */\n priorityFields?: string[];\n}\n\n/** Shared engine for frontmatter-file sources (collections, pages). */\nfunction createEntryFileSource(opts: EntryFileSourceOptions): GridSource {\n const entries = new Map<string, EntryRecord>();\n let loadPromise: Promise<void> | null = null;\n let columnsCache: GridColumn[] | null = null;\n\n const load = (force = false): Promise<void> => {\n if (!force && loadPromise) {\n return loadPromise;\n }\n loadPromise = (async () => {\n await loadFormats().catch(() => {}); // Extension resolution needs the format registry.\n const platform = getPlatform();\n const files = await opts.list();\n entries.clear();\n columnsCache = null;\n await mapLimit(files, 8, async (path) => {\n try {\n const text = await platform.readFile(path);\n const parsed = await parseSourceForPath(path, text);\n entries.set(path, {\n document: parsed.document,\n formatName: parsed.format.name,\n frontmatter: parsed.frontmatter ?? {},\n rawText: text,\n });\n } catch {\n // Unparseable entry — leave it out rather than failing the whole grid.\n }\n });\n })();\n return loadPromise;\n };\n\n const buildColumns = (): GridColumn[] => {\n if (columnsCache) {\n return columnsCache;\n }\n const pathColumn: GridColumn = {\n editable: false,\n field: PATH_FIELD,\n insertOnly: true,\n kind: \"string\",\n pk: true,\n required: true,\n title: \"Path\",\n widthHint: 220,\n };\n const schemaColumns = columnsFromSchema(opts.schema());\n const known = new Set([PATH_FIELD, ...schemaColumns.map((c) => c.field)]);\n\n // Keys present in entry data but absent from the schema still get (inferred) columns.\n const extraRows = [...entries.values()].map((entry) => {\n const cells: Record<string, GridCellValue> = {};\n for (const [key, value] of Object.entries(entry.frontmatter)) {\n if (!known.has(key) && !key.startsWith(\"$\")) {\n cells[key] = toCellValue(value);\n }\n }\n return cells;\n });\n const extraColumns = inferColumnsFromRows(extraRows);\n for (const column of extraColumns) {\n // Values we had to stringify (nested objects) must not round-trip as strings.\n column.editable = column.kind !== \"text\" || extraRowsAreStrings(extraRows, column.field);\n }\n if (opts.priorityFields?.length) {\n const rank = (c: GridColumn) => {\n const index = opts.priorityFields!.indexOf(c.field);\n return index === -1 ? opts.priorityFields!.length : index;\n };\n extraColumns.sort((a, b) => rank(a) - rank(b));\n }\n\n columnsCache = [pathColumn, ...schemaColumns, ...extraColumns];\n return columnsCache;\n };\n\n const rowFor = (path: string, entry: EntryRecord): GridRow => {\n const cells: Record<string, GridCellValue> = { [PATH_FIELD]: path };\n for (const column of buildColumns()) {\n if (column.field === PATH_FIELD) {\n continue;\n }\n cells[column.field] = toCellValue(entry.frontmatter[column.field]);\n }\n return { cells, fingerprint: entry.rawText, key: path };\n };\n\n /** Re-serialize one entry with patched frontmatter and write it (same path as tab saves). */\n const writeEntry = async (\n path: string,\n entry: EntryRecord,\n patches: { field: string; value: GridCellValue }[],\n ): Promise<void> => {\n const platform = getPlatform();\n const frontmatter = { ...entry.frontmatter };\n for (const patch of patches) {\n if (patch.value === null) {\n delete frontmatter[patch.field];\n } else {\n frontmatter[patch.field] = patch.value;\n }\n }\n const doc = entry.document;\n const fullDoc = { ...frontmatter, ...doc, children: doc.children ?? [] };\n const text = await formatSerialize(entry.formatName, fullDoc, { mode: \"roundtrip\" });\n markLocalMutation(path);\n await platform.writeFile(path, text);\n entries.set(path, { ...entry, frontmatter, rawText: text });\n };\n\n return {\n backingPaths: () => new Map([...entries.keys()].map((path) => [path, path])),\n capabilities: { delete: true, insert: true, remotePaging: false, remoteSort: false },\n\n async columns(): Promise<GridColumn[]> {\n await load();\n return buildColumns();\n },\n\n async commit(batch: GridEditBatch): Promise<CommitResult> {\n await load();\n const platform = getPlatform();\n const result: CommitResult = { cells: [], deletes: [], inserts: [] };\n\n // Cell edits, grouped per file so each entry is read/checked/written once.\n const byRow = new Map<string, { field: string; value: GridCellValue }[]>();\n for (const cell of batch.cells) {\n const list = byRow.get(cell.rowKey) ?? [];\n list.push({ field: cell.field, value: cell.value });\n byRow.set(cell.rowKey, list);\n }\n for (const [path, patches] of byRow) {\n const outcome = (ok: boolean, error?: string, stale?: boolean) => {\n for (const patch of patches) {\n result.cells.push({ error, field: patch.field, ok, rowKey: path, stale });\n }\n };\n const entry = entries.get(path);\n if (!entry) {\n outcome(false, \"Entry no longer loaded — refresh the grid\");\n continue;\n }\n const openTab = openTabFor(path);\n if (openTab?.doc.dirty) {\n outcome(false, \"Open in a tab with unsaved changes — save or close it first\");\n continue;\n }\n let onDisk: string | null = null;\n try {\n onDisk = await platform.readFile(path);\n } catch {\n onDisk = null;\n }\n if (onDisk !== entry.rawText && !isRecentLocal(path)) {\n outcome(false, \"File changed on disk — refresh to reload\", true);\n continue;\n }\n try {\n await writeEntry(path, entry, patches);\n outcome(true);\n if (openTab) {\n // Clean open tab: reload it so the editor reflects the grid's write. Dynamic import —\n // Files.ts imports the grid modules, so a static import here would be a cycle.\n const { reloadFileInTab } = await import(\"../../files/files\");\n void reloadFileInTab(path);\n }\n } catch (error) {\n outcome(false, error instanceof Error ? error.message : String(error));\n }\n }\n\n // Inserts: new entry files from the Path cell.\n for (const insert of batch.inserts) {\n const rawPath = insert.cells[PATH_FIELD];\n if (typeof rawPath !== \"string\" || rawPath.trim() === \"\") {\n result.inserts.push({ error: \"Path is required\", ok: false, tempKey: insert.tempKey });\n continue;\n }\n const path = opts.resolveInsertPath(rawPath);\n let exists = entries.has(path);\n if (!exists) {\n try {\n await platform.readFile(path);\n exists = true;\n } catch {\n exists = false;\n }\n }\n if (exists) {\n result.inserts.push({\n error: `${path} already exists`,\n ok: false,\n tempKey: insert.tempKey,\n });\n continue;\n }\n const formatName = opts.insertFormatName(path);\n if (!formatName) {\n result.inserts.push({\n error: `No format can serialize ${path}`,\n ok: false,\n tempKey: insert.tempKey,\n });\n continue;\n }\n try {\n const frontmatter: Record<string, unknown> = {};\n for (const [field, value] of Object.entries(insert.cells)) {\n if (field !== PATH_FIELD && value !== null) {\n frontmatter[field] = value;\n }\n }\n const text = await formatSerialize(\n formatName,\n { ...frontmatter, children: [] },\n { frontmatter: Object.keys(frontmatter).length > 0, mode: \"roundtrip\" },\n );\n markLocalMutation(path);\n await platform.writeFile(path, text);\n const parsed = await parseSourceForPath(path, text);\n entries.set(path, {\n document: parsed.document,\n formatName: parsed.format.name,\n frontmatter: parsed.frontmatter ?? {},\n rawText: text,\n });\n result.inserts.push({ newKey: path, ok: true, tempKey: insert.tempKey });\n } catch (error) {\n result.inserts.push({\n error: error instanceof Error ? error.message : String(error),\n ok: false,\n tempKey: insert.tempKey,\n });\n }\n }\n\n // Deletes: remove entry files (never while a tab is open on them).\n for (const del of batch.deletes) {\n if (openTabFor(del.rowKey)) {\n result.deletes.push({\n error: \"Open in a tab — close it first\",\n ok: false,\n rowKey: del.rowKey,\n });\n continue;\n }\n try {\n markLocalMutation(del.rowKey);\n await platform.deleteFile(del.rowKey);\n entries.delete(del.rowKey);\n result.deletes.push({ ok: true, rowKey: del.rowKey });\n } catch (error) {\n result.deletes.push({\n error: error instanceof Error ? error.message : String(error),\n ok: false,\n rowKey: del.rowKey,\n });\n }\n }\n\n return result;\n },\n\n id: opts.id,\n label: opts.label,\n\n async refresh(): Promise<void> {\n await load(true);\n },\n\n async rows(): Promise<GridRowsResult> {\n await load();\n const rows = [...entries.entries()].map(([path, entry]) => rowFor(path, entry));\n return { rows, total: rows.length };\n },\n };\n}\n\n/** Create the grid source for one content collection. */\nexport function createCollectionSource(typeName: string): GridSource {\n const requireInfo = (): CollectionInfo => {\n const info = collectionInfo(typeName);\n if (!info) {\n throw new Error(`No content collection named \"${typeName}\" in project.json`);\n }\n return info;\n };\n\n return createEntryFileSource({\n id: makeGridTabId({ kind: \"collection\", name: typeName }),\n insertFormatName: (path) => {\n const info = requireInfo();\n return (\n (info.def.format ? formatByName(info.def.format)?.name : undefined) ??\n formatForPath(path)?.name ??\n defaultContentFormat()?.name ??\n null\n );\n },\n label: typeName,\n list: () => {\n const info = requireInfo();\n return listEntryFiles(info.dir, [info.ext]);\n },\n resolveInsertPath: (raw) => {\n const info = requireInfo();\n let path = raw.trim().replace(/^\\.\\//, \"\").replace(/^\\//, \"\");\n if (!path.includes(\"/\")) {\n path = `${info.dir}/${path}`;\n }\n if (!path.endsWith(info.ext)) {\n path = `${path}${info.ext}`;\n }\n return path;\n },\n schema: () => requireInfo().def.schema,\n });\n}\n\n/** Create the grid source for the pages tree (format-class pages; .json pages are excluded). */\nexport function createPagesSource(): GridSource {\n const pageExts = () => {\n const exts = documentExtensions(\"page\").filter((ext) => ext !== \".json\");\n return exts.length > 0 ? exts : [\".md\"];\n };\n return createEntryFileSource({\n id: makeGridTabId({ kind: \"pages\" }),\n insertFormatName: (path) => formatForPath(path)?.name ?? null,\n label: \"Pages\",\n list: () => listEntryFiles(\"pages\", pageExts()),\n priorityFields: [\"title\", \"description\"],\n resolveInsertPath: (raw) => {\n let path = raw.trim().replace(/^\\.\\//, \"\").replace(/^\\//, \"\");\n if (!path.startsWith(\"pages/\")) {\n path = `pages/${path}`;\n }\n if (!pageExts().some((ext) => path.endsWith(ext))) {\n path = `${path}${pageExts()[0]}`;\n }\n return path;\n },\n schema: () => null,\n });\n}\n",
|
|
18
|
-
"/**\n * Connector-table grid source — SQL rows through the platform data surface.\n *\n * Columns come from backend introspection (DataColumnMeta); the primary key and the\n * created_at/updated_at system columns are read-only (matching the old modal grid's rules). Paging\n * and ordering are remote — rows(query) maps straight onto DataRowsQuery — so the grid shows a\n * pager instead of loading whole tables. Commit flushes the batch as per-row API calls: one\n * dataUpdateRow per edited row (fields merged), dataInsertRow per new row, dataDeleteRow per\n * deletion. The server is authoritative — there are no file fingerprints; conflicts surface as\n * per-row API errors.\n */\nimport { deleteRow, fetchRows, insertRow, updateRow } from \"../../services/data-service\";\nimport { makeGridTabId } from \"../grid-source\";\nimport type { DataColumnMeta, DataRowsQuery } from \"../../types\";\nimport type {\n CommitResult,\n GridCellValue,\n GridColumn,\n GridColumnKind,\n GridEditBatch,\n GridQuery,\n GridRow,\n GridRowsResult,\n GridSource,\n} from \"../grid-source\";\n\n/** Page size when the query does not specify one (matches the old modal grid). */\nexport const DATA_PAGE_SIZE = 50;\n\n/** SQL type → column kind (best-effort across sqlite/postgres type names). */\nexport function kindForSqlType(type: string): GridColumnKind {\n const t = type.toLowerCase();\n if (/(int|real|floa|doub|num|dec)/.test(t)) {\n return \"number\";\n }\n if (t.includes(\"bool\")) {\n return \"boolean\";\n }\n if (/(timestamp|datetime|date)/.test(t)) {\n return \"date\";\n }\n return \"string\";\n}\n\n/** System-managed columns are display-only (same rule as the old modal grid). */\nfunction editableColumn(column: DataColumnMeta): boolean {\n return !column.pk && column.name !== \"created_at\" && column.name !== \"updated_at\";\n}\n\n/** DB value → grid cell value (JSON-ish values surface as text). */\nfunction toCellValue(value: unknown): GridCellValue {\n if (value === null || value === undefined) {\n return null;\n }\n if (typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\") {\n return value;\n }\n return JSON.stringify(value);\n}\n\n/** Create the grid source for one connector table. */\nexport function createConnectorSource(connection: string | undefined, table: string): GridSource {\n let columnsMeta: DataColumnMeta[] = [];\n let pkName = \"id\";\n /** Map of rowKey → the pk value as the backend returned it (numeric pks stay numeric). */\n const pkValues = new Map<string, string | number>();\n\n const applyMeta = (columns: DataColumnMeta[]) => {\n if (columns.length > 0) {\n columnsMeta = columns;\n pkName = columns.find((c) => c.pk)?.name ?? \"id\";\n }\n };\n\n const toQuery = (query?: GridQuery): DataRowsQuery => ({\n table,\n ...(connection ? { connection } : {}),\n limit: query?.limit ?? DATA_PAGE_SIZE,\n offset: query?.offset ?? 0,\n ...(query?.orderBy ? { dir: query.dir ?? \"asc\", orderBy: query.orderBy } : {}),\n });\n\n const rowKeyOf = (row: Record<string, unknown>, index: number): string => {\n const pk = row[pkName];\n if (typeof pk === \"string\" || typeof pk === \"number\") {\n pkValues.set(String(pk), pk);\n return String(pk);\n }\n return `row-${index}`;\n };\n\n return {\n capabilities: { delete: true, insert: true, remotePaging: true, remoteSort: true },\n\n async columns(): Promise<GridColumn[]> {\n if (columnsMeta.length === 0) {\n const result = await fetchRows(toQuery({ limit: 1, offset: 0 }));\n applyMeta(result.columns);\n }\n return columnsMeta.map((meta): GridColumn => {\n const kind = editableColumn(meta) ? kindForSqlType(meta.type) : \"readonly\";\n return {\n editable: kind !== \"readonly\",\n field: meta.name,\n kind,\n pk: meta.pk === true,\n title: meta.name,\n widthHint: meta.pk ? 80 : undefined,\n };\n });\n },\n\n async commit(batch: GridEditBatch): Promise<CommitResult> {\n const result: CommitResult = { cells: [], deletes: [], inserts: [] };\n\n // Cell edits merge into one dataUpdateRow per row.\n const byRow = new Map<string, { field: string; value: GridCellValue }[]>();\n for (const cell of batch.cells) {\n const list = byRow.get(cell.rowKey) ?? [];\n list.push({ field: cell.field, value: cell.value });\n byRow.set(cell.rowKey, list);\n }\n for (const [rowKey, patches] of byRow) {\n const pk = pkValues.get(rowKey);\n const outcome = (ok: boolean, error?: string) => {\n for (const patch of patches) {\n result.cells.push({ error, field: patch.field, ok, rowKey });\n }\n };\n if (pk === undefined) {\n outcome(false, \"Row has no primary key — refresh the grid\");\n continue;\n }\n try {\n const set: Record<string, unknown> = {};\n for (const patch of patches) {\n set[patch.field] = patch.value;\n }\n await updateRow({ pk, set, table, ...(connection ? { connection } : {}) });\n outcome(true);\n } catch (error) {\n outcome(false, error instanceof Error ? error.message : String(error));\n }\n }\n\n for (const insert of batch.inserts) {\n try {\n const values: Record<string, unknown> = {};\n for (const [field, value] of Object.entries(insert.cells)) {\n if (value !== null) {\n values[field] = value;\n }\n }\n const { row } = await insertRow({ table, values, ...(connection ? { connection } : {}) });\n const pk = row[pkName];\n const newKey = typeof pk === \"string\" || typeof pk === \"number\" ? String(pk) : undefined;\n if (newKey !== undefined && (typeof pk === \"string\" || typeof pk === \"number\")) {\n pkValues.set(newKey, pk);\n }\n result.inserts.push({ newKey, ok: true, tempKey: insert.tempKey });\n } catch (error) {\n result.inserts.push({\n error: error instanceof Error ? error.message : String(error),\n ok: false,\n tempKey: insert.tempKey,\n });\n }\n }\n\n for (const del of batch.deletes) {\n const pk = pkValues.get(del.rowKey);\n if (pk === undefined) {\n result.deletes.push({\n error: \"Row has no primary key — refresh the grid\",\n ok: false,\n rowKey: del.rowKey,\n });\n continue;\n }\n try {\n await deleteRow({ pk, table, ...(connection ? { connection } : {}) });\n result.deletes.push({ ok: true, rowKey: del.rowKey });\n } catch (error) {\n result.deletes.push({\n error: error instanceof Error ? error.message : String(error),\n ok: false,\n rowKey: del.rowKey,\n });\n }\n }\n\n return result;\n },\n\n id: makeGridTabId({ connection: connection ?? \"default\", kind: \"data\", table }),\n label: table,\n\n async refresh(): Promise<void> {\n columnsMeta = [];\n pkValues.clear();\n },\n\n async rows(query?: GridQuery): Promise<GridRowsResult> {\n const result = await fetchRows(toQuery(query));\n applyMeta(result.columns);\n const rows: GridRow[] = result.rows.map((row, index) => {\n const key = rowKeyOf(row, index);\n const cells: Record<string, GridCellValue> = {};\n for (const meta of columnsMeta) {\n cells[meta.name] = toCellValue(row[meta.name]);\n }\n return { cells, key };\n });\n return { rows, total: result.total };\n },\n };\n}\n",
|
|
19
|
-
"/**\n * Grid tab openers — create (or activate) the tab + controller pair for a grid surface.\n *\n * CSV files open as REAL file tabs (id = path) whose default canvas mode is \"grid\" with a Monaco\n * \"source\" alternate; collection/pages/connector grids (later phases) open as virtual tabs with\n * `grid://` ids. All openers dedupe by tab id.\n */\nimport { html } from \"lit-html\";\nimport { activateTab, openTab, workspace } from \"../workspace/workspace\";\nimport { formatForPath, loadFormats } from \"../format/format-host\";\nimport { openModal } from \"../ui/layers\";\nimport { dataSurfaceAvailable, fetchConnections } from \"../services/data-service\";\nimport { createGridController } from \"./grid-controller\";\nimport { createCsvFileSource } from \"./sources/csv-file-source\";\nimport {\n collectionDirs,\n createCollectionSource,\n createPagesSource,\n} from \"./sources/content-source\";\nimport { createConnectorSource } from \"./sources/connector-source\";\nimport { makeGridTabId } from \"./grid-source\";\nimport type { GridSource } from \"./grid-source\";\nimport type { Tab } from \"../tabs/tab\";\n\n/** Placeholder document for grid tabs — the grid never reads it; save routes to the controller. */\nconst GRID_STUB_DOCUMENT = { children: [], tagName: \"div\" };\n\n/** Open (or activate) a `.csv` file as a grid tab. */\nexport async function openCsvGridTab(path: string): Promise<Tab> {\n const existing = workspace.tabs.get(path);\n if (existing) {\n activateTab(path);\n return existing;\n }\n\n // Best effort: the format name labels the tab's source mode; the grid works without it.\n try {\n await loadFormats();\n } catch {\n // Format registry unavailable (e.g. no dev server) — grid mode still works.\n }\n\n const source = createCsvFileSource(path);\n const tab = openTab({\n capabilities: { modes: [\"grid\", \"source\"] },\n document: structuredClone(GRID_STUB_DOCUMENT),\n documentPath: path,\n id: path,\n sourceFormat: formatForPath(path)?.name ?? null,\n });\n const controller = createGridController(tab, source);\n void controller.load();\n return tab;\n}\n\n/**\n * Open a virtual grid tab for a source (collections now; more kinds later). Callers dedupe by the\n * same `makeGridTabId` id before constructing the source.\n */\nfunction openVirtualGridTab(source: GridSource): Tab {\n const tab = openTab({\n capabilities: { modes: [\"grid\"] },\n document: structuredClone(GRID_STUB_DOCUMENT),\n documentPath: null,\n id: source.id,\n });\n const controller = createGridController(tab, source);\n void controller.load();\n return tab;\n}\n\n/** Open (or activate) the grid tab for a content collection. */\nexport function openCollectionGrid(typeName: string): Tab {\n const id = makeGridTabId({ kind: \"collection\", name: typeName });\n const existing = workspace.tabs.get(id);\n if (existing) {\n activateTab(id);\n return existing;\n }\n return openVirtualGridTab(createCollectionSource(typeName));\n}\n\n/** Open (or activate) the pages metadata grid. */\nexport function openPagesGrid(): Tab {\n const id = makeGridTabId({ kind: \"pages\" });\n const existing = workspace.tabs.get(id);\n if (existing) {\n activateTab(id);\n return existing;\n }\n return openVirtualGridTab(createPagesSource());\n}\n\n/** Open (or activate) the grid tab for a connector table. */\nexport function openConnectorGrid(connection: string | undefined, table: string): Tab {\n const id = makeGridTabId({ connection: connection ?? \"default\", kind: \"data\", table });\n const existing = workspace.tabs.get(id);\n if (existing) {\n activateTab(id);\n return existing;\n }\n return openVirtualGridTab(createConnectorSource(connection, table));\n}\n\n/**\n * Source picker — one dialog listing every grid-able source: pages, content collections, and (when\n * the platform serves the data surface) each connection's tables.\n */\nexport async function openGridSourcePicker(): Promise<void> {\n const collections = collectionDirs();\n let connections: { name: string; tables: string[] }[] = [];\n if (dataSurfaceAvailable()) {\n const response = await fetchConnections().catch(() => null);\n connections = response?.connections ?? [];\n }\n\n const handle = openModal(\n html`<sp-dialog-wrapper\n open\n dismissable\n underlay\n headline=\"Open Grid\"\n @close=${() => handle.close()}\n >\n <sp-menu class=\"jx-grid-picker\">\n <sp-menu-group>\n <span slot=\"header\">Project</span>\n <sp-menu-item\n @click=${() => {\n handle.close();\n openPagesGrid();\n }}\n >Pages</sp-menu-item\n >\n ${collections.map(\n ({ name }) =>\n html`<sp-menu-item\n @click=${() => {\n handle.close();\n openCollectionGrid(name);\n }}\n >Collection: ${name}</sp-menu-item\n >`,\n )}\n </sp-menu-group>\n ${connections.map(\n (conn) =>\n html`<sp-menu-group>\n <span slot=\"header\">Data · ${conn.name}</span>\n ${\n conn.tables.length === 0\n ? html`<sp-menu-item disabled>No tables — push a schema first</sp-menu-item>`\n : conn.tables.map(\n (table) =>\n html`<sp-menu-item\n @click=${() => {\n handle.close();\n openConnectorGrid(conn.name, table);\n }}\n >${table}</sp-menu-item\n >`,\n )\n }\n </sp-menu-group>`,\n )}\n </sp-menu>\n </sp-dialog-wrapper>`,\n );\n}\n",
|
|
20
|
-
"/// <reference lib=\"dom\" />\nimport { getPlatform, hasPlatform } from \"./platform\";\nimport type { RecentProjectEntry } from \"./types\";\n\ninterface RecentFile {\n path: string;\n name: string;\n /** The project root the file belongs to, so recents can be scoped to the open project. */\n root: string;\n timestamp: number;\n}\n\nconst STORAGE_KEY = \"jx-studio-recent-projects\";\nconst FILES_STORAGE_KEY = \"jx-studio-recent-files\";\nconst MAX_RECENT = 8;\nconst MAX_RECENT_FILES = 10;\n\n/**\n * In-memory mirror of the backend recent-projects store, hydrated once at startup. Render is\n * synchronous, so reads come from here (or directly from localStorage on the dev server) rather\n * than awaiting the backend.\n */\nlet cache: RecentProjectEntry[] = [];\n\n/**\n * The active backend store, or null when none is available (dev server). Desktop and chromium\n * persist a user-level file shared across all projects/windows; the dev server falls back to\n * per-origin localStorage, which already survives reloads.\n */\nfunction backend(): StudioRecentStore | null {\n if (!hasPlatform()) {\n return null;\n }\n const platform = getPlatform();\n return platform.getRecentProjects && platform.saveRecentProjects\n ? (platform as StudioRecentStore)\n : null;\n}\n\ninterface StudioRecentStore {\n getRecentProjects: () => Promise<RecentProjectEntry[]>;\n saveRecentProjects: (projects: RecentProjectEntry[]) => Promise<void>;\n}\n\nfunction loadFromLocalStorage(): RecentProjectEntry[] {\n try {\n const raw = localStorage.getItem(STORAGE_KEY);\n if (!raw) {\n return [];\n }\n const parsed = JSON.parse(raw) as RecentProjectEntry[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/** The current list from whichever store is active (cache for backend, localStorage otherwise). */\nfunction currentList(): RecentProjectEntry[] {\n return backend() ? cache : loadFromLocalStorage();\n}\n\n/** Persist a new list to the active store and keep the in-memory cache in sync. */\nfunction commit(list: RecentProjectEntry[]): void {\n cache = list;\n const store = backend();\n if (store) {\n void store.saveRecentProjects(list);\n } else {\n try {\n localStorage.setItem(STORAGE_KEY, JSON.stringify(list));\n } catch {\n /* Storage unavailable — best effort */\n }\n }\n}\n\n/**\n * Load the recent-projects list into the in-memory cache. Call once after the platform is\n * registered; a no-op (other than priming the cache) on the dev server, where reads hit\n * localStorage directly.\n */\nexport async function hydrateRecentProjects(): Promise<void> {\n const store = backend();\n if (!store) {\n return;\n }\n try {\n cache = await store.getRecentProjects();\n } catch {\n cache = [];\n }\n}\n\n/** @returns {RecentProjectEntry[]} Newest-first */\nexport function getRecentProjects(): RecentProjectEntry[] {\n return currentList().toSorted((a, b) => b.timestamp - a.timestamp);\n}\n\n/**\n * @param {string} name\n * @param {string} root\n */\nexport function addRecentProject(name: string, root: string) {\n const projects = currentList().filter((p) => p.root !== root);\n projects.unshift({ name, root, timestamp: Date.now() });\n if (projects.length > MAX_RECENT) {\n projects.length = MAX_RECENT;\n }\n commit(projects);\n}\n\n/** Drop a single project from the recent list (used by the UI remove action + auto-prune). */\nexport function removeRecentProject(root: string) {\n commit(currentList().filter((p) => p.root !== root));\n}\n\nexport function clearRecentProjects() {\n cache = [];\n const store = backend();\n if (store) {\n void store.saveRecentProjects([]);\n } else {\n localStorage.removeItem(STORAGE_KEY);\n }\n}\n\nfunction loadRecentFiles(): RecentFile[] {\n try {\n const raw = localStorage.getItem(FILES_STORAGE_KEY);\n if (!raw) {\n return [];\n }\n const parsed = JSON.parse(raw) as RecentFile[];\n return Array.isArray(parsed) ? parsed : [];\n } catch {\n return [];\n }\n}\n\n/**\n * Recently-opened files, newest-first. Pass a project `root` to scope the list to that project (the\n * Quick Access modal does this so it only ever shows files from the open project).\n *\n * @param {string} [root]\n * @returns {RecentFile[]}\n */\nexport function getRecentFiles(root?: string) {\n const all = loadRecentFiles().toSorted((a, b) => b.timestamp - a.timestamp);\n return root == null ? all : all.filter((f) => f.root === root);\n}\n\n/** @param {{ path: string; name: string; root: string }} file */\nexport function trackRecentFile(file: { path: string; name: string; root: string }) {\n const all = loadRecentFiles().filter((f) => !(f.root === file.root && f.path === file.path));\n all.unshift({ name: file.name, path: file.path, root: file.root, timestamp: Date.now() });\n // Cap per project so a busy project can't evict another project's history.\n const perRoot = new Map<string, number>();\n const kept: RecentFile[] = [];\n for (const f of all.toSorted((a, b) => b.timestamp - a.timestamp)) {\n const n = (perRoot.get(f.root) ?? 0) + 1;\n perRoot.set(f.root, n);\n if (n <= MAX_RECENT_FILES) {\n kept.push(f);\n }\n }\n localStorage.setItem(FILES_STORAGE_KEY, JSON.stringify(kept));\n}\n",
|
|
21
|
-
"/// <reference lib=\"dom\" />\n/// <reference lib=\"dom.iterable\" />\n/**\n * File tree management — project loading, file tree rendering, and file CRUD.\n *\n * Functions that mutate state accept a context object with callbacks, following the same pattern as\n * file-ops.js. Every name the user supplies (new file, rename) is collected with the Spectrum\n * prompt dialog from ui/layers.ts — never a native browser prompt (studio-ui-guidelines.md §8.7).\n *\n * @docs studio/interface\n */\n\nimport { html, nothing } from \"lit-html\";\nimport { errorMessage } from \"@jxsuite/schema/parse\";\nimport { classMap } from \"lit-html/directives/class-map.js\";\nimport { ref } from \"lit-html/directives/ref.js\";\nimport { renderPopover, showConfirmDialog, showPromptDialog } from \"../ui/layers\";\nimport { createState, projectState, requireProjectState, setProjectState } from \"../store\";\nimport { getPlatform } from \"../platform\";\nimport { statusMessage } from \"../panels/statusbar\";\nimport { loadComponentRegistry } from \"./components\";\nimport { ensureDependenciesInstalled } from \"../packages/ensure-deps\";\nimport { maybePromptJxsuiteUpdate } from \"../packages/jxsuite-update\";\nimport { autoSyncProjectOnOpen } from \"../packages/pull-package-sync\";\nimport { markLocalMutation } from \"./fs-events\";\nimport { UPLOAD_ACCEPT, isImage, uploadAssets } from \"./media-upload\";\nimport { isCollabPath } from \"../collab/collab-state\";\nimport {\n draggable,\n dropTargetForElements,\n monitorForElements,\n} from \"@atlaskit/pragmatic-drag-and-drop/element/adapter\";\nimport { combine } from \"@atlaskit/pragmatic-drag-and-drop/combine\";\nimport {\n activateTab,\n openTab,\n renameTab,\n replaceAllTabs,\n setWorkspaceProject,\n workspace,\n} from \"../workspace/workspace\";\nimport { openCollectionGrid, openCsvGridTab, openPagesGrid } from \"../grid/grid-open\";\nimport { collectionDirs } from \"../grid/sources/content-source\";\nimport { parseSourceForPath, serializeDocument } from \"./file-ops\";\nimport {\n documentExtensions,\n formatForPath,\n loadFormats,\n noFormatError,\n refreshExtensionUi,\n refreshFormats,\n} from \"../format/format-host\";\nimport { view } from \"../view\";\nimport { addRecentProject, trackRecentFile } from \"../recent-projects\";\nimport type { TemplateResult } from \"lit-html\";\nimport type { JxMutableNode } from \"@jxsuite/schema/types\";\nimport type { StudioState } from \"../state.js\";\nimport type { Tab } from \"../tabs/tab.js\";\nimport type { DirEntry, RenameResult } from \"../types\";\nimport { rectOf } from \"../utils/geometry\";\n\n// ─── File icon map ────────────────────────────────────────────────────────────\n\nconst fileIconMap = {\n \"sp-icon-document\": html`<sp-icon-document></sp-icon-document>`,\n \"sp-icon-file-code\": html`<sp-icon-file-code></sp-icon-file-code>`,\n \"sp-icon-file-txt\": html`<sp-icon-file-txt></sp-icon-file-txt>`,\n \"sp-icon-folder\": html`<sp-icon-folder></sp-icon-folder>`,\n \"sp-icon-folder-open\": html`<sp-icon-folder-open></sp-icon-folder-open>`,\n \"sp-icon-image\": html`<sp-icon-image></sp-icon-image>`,\n} as Record<string, TemplateResult>;\n\n// ─── File management ──────────────────────────────────────────────────────────\n\nexport async function loadDirectory(dirPath: string) {\n if (!projectState) {\n return;\n }\n try {\n const platform = getPlatform();\n const entries = await platform.listDirectory(dirPath);\n projectState.dirs.set(dirPath, entries);\n } catch {\n projectState.dirs.set(dirPath, []);\n }\n}\n\n/** Probe the dev server for a root project and populate projectState. */\nexport async function loadProject() {\n try {\n const platform = getPlatform();\n const result = await platform.probeRootProject();\n if (!result) {\n return;\n }\n const { meta, info } = result;\n\n refreshFormats();\n void loadFormats();\n refreshExtensionUi(platform);\n\n setProjectState({\n dirs: new Map(),\n expanded: new Set(),\n isSiteProject: info.isSiteProject,\n name: info.isSiteProject ? info.projectConfig?.name || meta.name : meta.name,\n projectConfig: (info.isSiteProject ? info.projectConfig : null) || null,\n projectDirs: info.directories || [],\n projectRoot: \".\",\n root: meta.root,\n searchQuery: \"\",\n selectedPath: null,\n });\n // Only a site project counts as an open project for the workspace (a bare monorepo root keeps\n // The assistant in bootstrap mode).\n if (info.isSiteProject) {\n setWorkspaceProject(meta.root || \".\", info.projectConfig || null);\n }\n\n if (info.isSiteProject) {\n addRecentProject(requireProjectState().name, meta.root);\n await autoSyncProjectOnOpen();\n await ensureDependenciesInstalled();\n await loadDirectory(\".\");\n await loadComponentRegistry();\n await openHomePage();\n void maybePromptJxsuiteUpdate(meta.root);\n }\n // If not a site project (monorepo) — show welcome prompt, don't load tree\n } catch {\n // Not on dev server — project features disabled\n }\n}\n\n// ─── Open Project (PAL-based) ─────────────────────────────────────────────\n\n/**\n * Open a project via the platform adapter.\n *\n * @param {{\n * renderActivityBar: () => void;\n * renderLeftPanel: () => void;\n * }} ctx\n */\nexport async function openProject({\n renderActivityBar,\n renderLeftPanel,\n}: {\n renderActivityBar: () => void;\n renderLeftPanel: () => void;\n}) {\n try {\n const platform = getPlatform();\n const result = await platform.openProject();\n if (!result) {\n return;\n } // User cancelled\n\n const { config, handle } = result;\n\n replaceAllTabs({\n document: { children: [], tagName: \"div\" },\n id: \"initial\",\n });\n\n refreshFormats();\n void loadFormats();\n refreshExtensionUi(platform);\n\n setProjectState({\n .../** @type {ProjectState} */ projectState,\n dirs: new Map(),\n expanded: new Set(),\n isSiteProject: true,\n name: config.name || handle.name,\n projectConfig: config,\n projectRoot: handle.root,\n searchQuery: \"\",\n selectedPath: null,\n });\n setWorkspaceProject(handle.root, config);\n\n await autoSyncProjectOnOpen();\n await ensureDependenciesInstalled();\n await loadDirectory(\".\");\n await loadComponentRegistry();\n\n // Auto-expand key directories and populate projectDirs for Browse view\n const conventionalDirs = new Set([\n \"pages\",\n \"layouts\",\n \"components\",\n \"content\",\n \"data\",\n \"public\",\n \"styles\",\n ]);\n const entries = requireProjectState().dirs.get(\".\") || [];\n const foundDirs = [];\n for (const e of entries) {\n if (e.type === \"directory\" && conventionalDirs.has(e.name)) {\n foundDirs.push(e.name);\n requireProjectState().expanded.add(e.path || e.name);\n await loadDirectory(e.path || e.name);\n }\n }\n requireProjectState().projectDirs = foundDirs;\n\n view.leftTab = \"files\";\n addRecentProject(requireProjectState().name, requireProjectState().projectRoot);\n renderActivityBar();\n renderLeftPanel();\n statusMessage(`Opened project: ${requireProjectState().name}`);\n\n await openHomePage();\n void maybePromptJxsuiteUpdate(requireProjectState().projectRoot);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n/**\n * The project's home page path (`pages/index.<page-ext>` or `pages/index.json`), or null if none.\n * Lists `pages/` once and matches by name — a directory read returns 200 with `[]` for a missing\n * dir, so this never provokes the console 404s a blind per-candidate read would.\n */\nexport async function findHomePage(): Promise<string | null> {\n await loadFormats();\n const exts = [...documentExtensions(\"page\"), \".json\"];\n let entries: DirEntry[];\n try {\n entries = await getPlatform().listDirectory(\"pages\");\n } catch {\n return null;\n }\n const files = new Set(entries.filter((e) => e.type === \"file\").map((e) => e.name));\n for (const ext of exts) {\n if (files.has(`index${ext}`)) {\n return `pages/index${ext}`;\n }\n }\n return null;\n}\n\nexport async function openHomePage() {\n const home = await findHomePage();\n if (home) {\n await openFileInTab(home);\n }\n}\n\n// ─── File tree templates ──────────────────────────────────────────────────────\n\nfunction fileTypeIconTpl(name: string, type: string) {\n let tag;\n if (type === \"directory\") {\n tag = projectState?.expanded?.has(name) ? \"sp-icon-folder-open\" : \"sp-icon-folder\";\n } else {\n const ext = name.split(\".\").pop()?.toLowerCase();\n switch (ext) {\n case \"json\": {\n tag = \"sp-icon-file-code\";\n break;\n }\n case \"md\": {\n tag = \"sp-icon-file-txt\";\n break;\n }\n case \"js\":\n case \"ts\": {\n tag = \"sp-icon-file-code\";\n break;\n }\n case \"css\": {\n tag = \"sp-icon-file-code\";\n break;\n }\n default: {\n // Every image extension the media layer knows about, so an uploaded .avif/.ico gets the\n // Same icon as a .png instead of falling through to the generic document glyph.\n tag = ext && isImage(ext) ? \"sp-icon-image\" : \"sp-icon-document\";\n break;\n }\n }\n }\n return fileIconMap[tag] || fileIconMap[\"sp-icon-document\"];\n}\n\n/**\n * Render the file tree template for the left panel.\n *\n * @param {{\n * openProject: () => void;\n * openFileFromTree: (path: string) => void;\n * renderLeftPanel: () => void;\n * }} ctx\n */\nexport function renderFilesTemplate({\n openProject: openProjectFn,\n openFileFromTree: openFileFn,\n renderLeftPanel,\n}: {\n openProject: () => void;\n openFileFromTree: (path: string) => void;\n renderLeftPanel: () => void;\n}) {\n if (!projectState) {\n return html`<div class=\"file-tree-empty\">No project loaded</div>`;\n }\n\n // No project selected in a monorepo — show welcome prompt\n if (!projectState.isSiteProject && projectState.projectRoot === \".\") {\n return html`<div class=\"file-tree-empty\">\n <p style=\"margin:0 0 12px\">Open a project folder to get started.</p>\n <sp-button variant=\"accent\" size=\"s\" @click=${openProjectFn}>Open Project</sp-button>\n </div>`;\n }\n\n return html`\n ${\n projectState.isSiteProject\n ? html`\n <div class=\"project-header\">\n <span class=\"project-name\"\n >${projectState.projectConfig?.name || projectState.name}</span\n >\n </div>\n `\n : nothing\n }\n <div class=\"files-toolbar\">\n <sp-action-group size=\"xs\" compact quiet>\n <sp-action-button\n size=\"xs\"\n label=\"New File\"\n @click=${() => createNewFile(\".\", renderLeftPanel)}\n >\n <sp-icon-add slot=\"icon\"></sp-icon-add>\n </sp-action-button>\n <sp-action-button\n size=\"xs\"\n label=\"Refresh\"\n @click=${async () => {\n requireProjectState().dirs.clear();\n await loadDirectory(\".\");\n for (const dir of requireProjectState().expanded) {\n await loadDirectory(dir);\n }\n renderLeftPanel();\n }}\n >\n <sp-icon-refresh slot=\"icon\"></sp-icon-refresh>\n </sp-action-button>\n </sp-action-group>\n <sp-search\n size=\"s\"\n quiet\n placeholder=\"Filter files…\"\n value=${requireProjectState().searchQuery}\n @input=${(e: Event) => {\n requireProjectState().searchQuery = (e.target as HTMLInputElement).value;\n renderLeftPanel();\n }}\n @submit=${(e: Event) => e.preventDefault()}\n ></sp-search>\n </div>\n <div class=\"file-tree\" role=\"tree\" aria-label=\"Project files\">\n ${renderTreeLevelTemplate(\".\", 0, { openFileFn, renderLeftPanel })}\n </div>\n `;\n}\n\n/** @returns {import(\"lit-html\").TemplateResult | import(\"lit-html\").TemplateResult[]} */\nfunction renderTreeLevelTemplate(\n dirPath: string,\n depth: number,\n ctx: { openFileFn: (path: string) => void; renderLeftPanel: () => void },\n): TemplateResult | TemplateResult[] {\n const entries = requireProjectState().dirs.get(dirPath);\n if (!entries) {\n void loadDirectory(dirPath).then(() => ctx.renderLeftPanel());\n return html`<div\n class=\"file-tree-item\"\n style=\"padding-left:${8 + depth * 16}px;color:var(--fg-dim);font-style:italic\"\n >\n Loading…\n </div>`;\n }\n\n const sorted = [...entries].toSorted((a, b) => {\n if (a.type === \"directory\" && b.type !== \"directory\") {\n return -1;\n }\n if (a.type !== \"directory\" && b.type === \"directory\") {\n return 1;\n }\n return a.name.localeCompare(b.name);\n });\n\n const query = requireProjectState().searchQuery.toLowerCase();\n const filtered = query\n ? sorted.filter((e) => e.type === \"directory\" || e.name.toLowerCase().includes(query))\n : sorted;\n\n return filtered.map((entry) => {\n const isDir = entry.type === \"directory\";\n const isExpanded = requireProjectState().expanded.has(entry.path);\n const isSelected = requireProjectState().selectedPath === entry.path;\n\n return html`\n <div\n class=${classMap({ \"file-tree-item\": true, selected: isSelected })}\n style=\"padding-left:${8 + depth * 16}px\"\n role=\"treeitem\"\n aria-level=${depth + 1}\n tabindex=\"-1\"\n data-path=${entry.path}\n data-type=${entry.type}\n aria-expanded=${isDir ? String(isExpanded) : nothing}\n @click=${async (e: MouseEvent) => {\n e.stopPropagation();\n if (isDir) {\n if (isExpanded) {\n requireProjectState().expanded.delete(entry.path);\n } else {\n requireProjectState().expanded.add(entry.path);\n if (!requireProjectState().dirs.has(entry.path)) {\n await loadDirectory(entry.path);\n }\n }\n ctx.renderLeftPanel();\n } else {\n ctx.openFileFn(entry.path);\n }\n }}\n @contextmenu=${(e: MouseEvent) => {\n e.preventDefault();\n e.stopPropagation();\n showFileContextMenu(e, entry, ctx);\n }}\n >\n ${\n isDir\n ? html`<span class=\"file-tree-toggle\">${isExpanded ? \"\\u25BC\" : \"\\u25B6\"}</span>`\n : html`<span class=\"file-tree-toggle empty\"> </span>`\n }\n <span class=\"file-tree-icon\">${fileTypeIconTpl(entry.path, entry.type)}</span>\n <span class=\"file-tree-name\">${entry.name}</span>\n </div>\n ${\n isDir && isExpanded\n ? html`<div role=\"group\">${renderTreeLevelTemplate(entry.path, depth + 1, ctx)}</div>`\n : nothing\n }\n `;\n });\n}\n\nexport function setupTreeKeyboard(tree: HTMLElement) {\n tree.addEventListener(\"keydown\", (e: KeyboardEvent) => {\n const items = [...tree.querySelectorAll(\".file-tree-item\")] as HTMLElement[];\n const focused = tree.querySelector(\".file-tree-item:focus\") as HTMLElement | null;\n if (!focused || items.length === 0) {\n return;\n }\n\n const idx = items.indexOf(focused);\n let handled = true;\n\n switch (e.key) {\n case \"ArrowDown\": {\n if (idx < items.length - 1) {\n items[idx + 1]!.focus();\n }\n break;\n }\n case \"ArrowUp\": {\n if (idx > 0) {\n items[idx - 1]!.focus();\n }\n break;\n }\n case \"ArrowRight\": {\n if (focused.dataset.type === \"directory\") {\n const path = focused.dataset.path as string;\n if (!requireProjectState().expanded.has(path)) {\n requireProjectState().expanded.add(path);\n void loadDirectory(path).then(() => {\n const panel = tree.closest(\".panel-body\");\n if (panel) {\n (panel.querySelector(\".file-tree-item:focus\") as HTMLElement | null)?.click();\n }\n });\n }\n }\n break;\n }\n case \"ArrowLeft\": {\n if (focused.dataset.type === \"directory\") {\n const path = focused.dataset.path as string;\n if (requireProjectState().expanded.has(path)) {\n requireProjectState().expanded.delete(path);\n // RenderLeftPanel will be called by the caller who sets up keyboard\n }\n }\n break;\n }\n case \"Enter\": {\n focused.click();\n break;\n }\n default: {\n handled = false;\n }\n }\n if (handled) {\n e.preventDefault();\n }\n });\n\n // Set first item focusable\n const first = tree.querySelector(\".file-tree-item\");\n if (first) {\n first.setAttribute(\"tabindex\", \"0\");\n }\n}\n\nlet _fileTreeDndCleanups: (() => void)[] = [];\n\n/** Whether a drag carries OS files (as opposed to a pragmatic in-app drag). */\nexport function isFileDrag(e: DragEvent): boolean {\n return [...(e.dataTransfer?.types ?? [])].includes(\"Files\");\n}\n\n/**\n * Attach external-file drop handling to one tree row. Pragmatic-dnd only sees pragmatic sources, so\n * an OS file drag needs the native listeners; `dir` is where a drop lands (the row itself for a\n * directory, its parent for a file, `.` for the tree background).\n */\nfunction registerFileDropTarget(\n element: HTMLElement,\n dir: string,\n activeClass: string,\n renderLeftPanel: () => void,\n): () => void {\n const onDragOver = (e: DragEvent) => {\n if (!isFileDrag(e)) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n if (e.dataTransfer) {\n e.dataTransfer.dropEffect = \"copy\";\n }\n element.classList.add(activeClass);\n };\n const onDragLeave = () => element.classList.remove(activeClass);\n const onDrop = (e: DragEvent) => {\n element.classList.remove(activeClass);\n const files = e.dataTransfer?.files;\n if (!files?.length) {\n return;\n }\n e.preventDefault();\n e.stopPropagation();\n void uploadFilesToDir(files, dir, renderLeftPanel);\n };\n element.addEventListener(\"dragover\", onDragOver);\n element.addEventListener(\"dragleave\", onDragLeave);\n element.addEventListener(\"drop\", onDrop);\n return () => {\n element.removeEventListener(\"dragover\", onDragOver);\n element.removeEventListener(\"dragleave\", onDragLeave);\n element.removeEventListener(\"drop\", onDrop);\n };\n}\n\n/**\n * Upload files into `dir` and reveal them: expand the target directory so the new entries are\n * visible. The listing refresh itself runs in the shared post-upload handler.\n */\nexport async function uploadFilesToDir(\n files: FileList | File[],\n dir: string,\n renderLeftPanel: () => void,\n): Promise<void> {\n const uploaded = await uploadAssets([...files], { dir });\n if (uploaded.length === 0) {\n return;\n }\n if (dir !== \".\") {\n requireProjectState().expanded.add(dir);\n }\n renderLeftPanel();\n}\n\n/**\n * Open the OS file picker and upload the choice into `dir` (the tree's \"Upload Files…\" item). The\n * input is created per invocation and discarded after — the tree template is re-rendered often.\n */\nexport function pickAndUploadTo(dir: string, renderLeftPanel: () => void): void {\n const input = document.createElement(\"input\");\n input.type = \"file\";\n input.multiple = true;\n input.accept = UPLOAD_ACCEPT;\n input.addEventListener(\"change\", () => {\n if (input.files?.length) {\n void uploadFilesToDir(input.files, dir, renderLeftPanel);\n }\n });\n input.click();\n}\n\n/**\n * Register drag-and-drop on file tree items. Called after each file tree render.\n *\n * @param {{ renderLeftPanel: () => void }} ctx\n */\nexport function registerFileTreeDnD({ renderLeftPanel }: { renderLeftPanel: () => void }) {\n // Clean up previous registrations\n for (const fn of _fileTreeDndCleanups) {\n fn();\n }\n _fileTreeDndCleanups = [];\n\n requestAnimationFrame(() => {\n const tree = document.querySelector(\".file-tree\") as HTMLElement | null;\n if (!tree) {\n return;\n }\n\n const items = tree.querySelectorAll(\".file-tree-item\") as NodeListOf<HTMLElement>;\n\n for (const row of items) {\n const { path } = row.dataset;\n const { type } = row.dataset;\n if (!path) {\n continue;\n }\n\n const cleanups = [\n draggable({\n element: row,\n getInitialData() {\n return { entryType: type, path, type: \"file-tree\" };\n },\n onDragStart() {\n row.classList.add(\"dragging\");\n },\n onDrop() {\n row.classList.remove(\"dragging\");\n },\n }),\n // Files dropped from the OS land in the row's own directory; a file row targets its parent\n // So dropping next to a sibling puts the upload beside it.\n registerFileDropTarget(\n row,\n type === \"directory\" ? path : parentDir(path),\n \"drag-over\",\n renderLeftPanel,\n ),\n ];\n\n if (type === \"directory\") {\n cleanups.push(\n dropTargetForElements({\n canDrop({ source }) {\n if (source.data.type !== \"file-tree\") {\n return false;\n }\n const srcPath = source.data.path as string;\n if (srcPath === path) {\n return false;\n }\n if (srcPath.startsWith(`${path}/`)) {\n return false;\n }\n const srcParent = parentDir(srcPath);\n if (srcParent === path) {\n return false;\n }\n return true;\n },\n element: row,\n getData() {\n return { targetDir: path, type: \"file-tree-target\" };\n },\n onDrag() {\n if (!row.classList.contains(\"drag-over\")) {\n row.classList.add(\"drag-over\");\n }\n },\n onDragEnter() {\n row.classList.add(\"drag-over\");\n },\n onDragLeave() {\n row.classList.remove(\"drag-over\");\n },\n onDrop() {\n row.classList.remove(\"drag-over\");\n },\n }),\n );\n }\n\n _fileTreeDndCleanups.push(combine(...cleanups));\n }\n\n // Root-level drop target (move to project root)\n const rootCleanup = dropTargetForElements({\n canDrop({ source }) {\n if (source.data.type !== \"file-tree\") {\n return false;\n }\n const srcPath = source.data.path as string;\n return parentDir(srcPath) !== \".\";\n },\n element: tree,\n getData() {\n return { targetDir: \".\", type: \"file-tree-target\" };\n },\n onDragEnter() {\n tree.classList.add(\"drag-over-root\");\n },\n onDragLeave() {\n tree.classList.remove(\"drag-over-root\");\n },\n onDrop() {\n tree.classList.remove(\"drag-over-root\");\n },\n });\n // The tree background is the project root's drop target for OS files. Row handlers\n // StopPropagation, so a drop on a row never also fires here.\n _fileTreeDndCleanups.push(\n rootCleanup,\n registerFileDropTarget(tree, \".\", \"drag-over-root\", renderLeftPanel),\n );\n\n // Monitor for drop events\n const monitorCleanup = monitorForElements({\n onDrop({ source, location }) {\n const [target] = location.current.dropTargets;\n if (!target) {\n return;\n }\n if (source.data.type !== \"file-tree\") {\n return;\n }\n if (target.data.type !== \"file-tree-target\") {\n return;\n }\n\n const srcPath = source.data.path as string;\n const targetDirPath = target.data.targetDir as string;\n const fileName = srcPath.split(\"/\").pop();\n const newPath = targetDirPath === \".\" ? fileName : `${targetDirPath}/${fileName}`;\n\n if (newPath === srcPath) {\n return;\n }\n\n void moveFileEntry(srcPath, newPath!, renderLeftPanel);\n },\n });\n _fileTreeDndCleanups.push(monitorCleanup);\n });\n}\n\n/**\n * Move a file/directory and update all affected state.\n *\n * @param {string} oldPath\n * @param {string} newPath\n * @param {() => void} renderLeftPanel\n */\nasync function moveFileEntry(oldPath: string, newPath: string, renderLeftPanel: () => void) {\n const platform = getPlatform();\n markLocalMutation(oldPath, newPath);\n try {\n const report = await platform.renameFile(oldPath, newPath);\n\n // Update open tabs referencing the moved path\n for (const [id] of workspace.tabs.entries()) {\n if (id === oldPath) {\n renameTab(oldPath, newPath, newPath);\n } else if (id.startsWith(`${oldPath}/`)) {\n const newTabPath = newPath + id.slice(oldPath.length);\n renameTab(id, newTabPath, newTabPath);\n }\n }\n\n // Refresh affected directories\n const oldParent = parentDir(oldPath);\n const newParent = parentDir(newPath);\n await loadDirectory(oldParent);\n if (newParent !== oldParent) {\n await loadDirectory(newParent);\n }\n\n // Auto-expand target directory\n if (newParent !== \".\") {\n requireProjectState().expanded.add(newParent);\n }\n\n reloadRewrittenTabs(report, newPath);\n renderLeftPanel();\n statusMessage(`Moved to ${newPath}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n/** @param {string} path @returns {string} */\nfunction parentDir(path: string) {\n const normalized = path.replaceAll(\"\\\\\", \"/\");\n const lastSlash = normalized.lastIndexOf(\"/\");\n return lastSlash === -1 ? \".\" : normalized.slice(0, lastSlash);\n}\n\n// ─── Context menu ─────────────────────────────────────────────────────────────\n\nlet _fileCtxHandle: ReturnType<typeof renderPopover> | null = null;\n\nfunction dismissFileContextMenu() {\n if (_fileCtxHandle) {\n _fileCtxHandle.dismiss();\n _fileCtxHandle = null;\n }\n}\n\nfunction showFileContextMenu(\n e: MouseEvent,\n entry: { name: string; path: string; type: string },\n ctx: { openFileFn: (path: string) => void; renderLeftPanel: () => void },\n) {\n e.preventDefault();\n dismissFileContextMenu();\n const isDir = entry.type === \"directory\";\n\n /** @type {{ label: string; action?: () => void; danger?: boolean }[]} */\n const items = [];\n\n if (!isDir) {\n items.push({ action: () => ctx.openFileFn(entry.path), label: \"Open\" });\n }\n if (isDir) {\n items.push(\n {\n action: () => createNewFile(entry.path, ctx.renderLeftPanel),\n label: \"New File\\u2026\",\n },\n {\n action: () => pickAndUploadTo(entry.path, ctx.renderLeftPanel),\n label: \"Upload Files\\u2026\",\n },\n );\n // Directories backing a content collection get a bulk-edit affordance.\n const collection = collectionDirs().find(\n ({ dir }) => entry.path === dir || entry.path.endsWith(`/${dir}`),\n );\n if (collection) {\n items.push({\n action: () => {\n openCollectionGrid(collection.name);\n },\n label: \"Edit Collection in Grid\",\n });\n }\n if (entry.path === \"pages\" || entry.path.endsWith(\"/pages\")) {\n items.push({\n action: () => {\n openPagesGrid();\n },\n label: \"Edit Pages in Grid\",\n });\n }\n }\n items.push(\n { label: \"\\u2014\" },\n {\n action: () => renameFile(entry, ctx.renderLeftPanel),\n label: \"Rename\\u2026\",\n },\n {\n action: () => deleteFile(entry, ctx.renderLeftPanel),\n danger: true,\n label: \"Delete\",\n },\n );\n\n let x = e.clientX,\n y = e.clientY;\n\n _fileCtxHandle = renderPopover(\n html`<sp-popover\n open\n style=\"position:fixed;z-index:10000;left:${x}px;top:${y}px\"\n ${ref((el) => {\n if (!el) {\n return;\n }\n requestAnimationFrame(() => {\n const popover = el as HTMLElement;\n const menuRect = rectOf(popover);\n if (x + menuRect.width > window.innerWidth) {\n x = window.innerWidth - menuRect.width - 4;\n }\n if (y + menuRect.height > window.innerHeight) {\n y = window.innerHeight - menuRect.height - 4;\n }\n popover.style.left = `${x}px`;\n popover.style.top = `${y}px`;\n });\n })}\n >\n <sp-menu>\n ${items.map((item) =>\n item.label === \"\\u2014\"\n ? html`<sp-menu-divider></sp-menu-divider>`\n : html`<sp-menu-item\n style=${item.danger ? \"color: var(--danger)\" : \"\"}\n @click=${() => {\n dismissFileContextMenu();\n void item.action?.();\n }}\n >${item.label}</sp-menu-item\n >`,\n )}\n </sp-menu>\n </sp-popover>`,\n {\n dismissOnOutsideClick: true,\n onDismiss: () => {\n _fileCtxHandle = null;\n },\n },\n );\n}\n\n// ─── File CRUD ────────────────────────────────────────────────────────────────\n\nasync function createNewFile(dirPath: string, renderLeftPanel: () => void) {\n const name = await showPromptDialog(\"New File\", {\n confirmLabel: \"Create\",\n message: dirPath === \".\" ? \"Creating in the project root.\" : `Creating in ${dirPath}/`,\n placeholder: \"untitled.json\",\n select: \"stem\",\n validate: (v) => (v.trim() ? \"\" : \"Enter a file name.\"),\n value: \"untitled.json\",\n });\n if (!name) {\n return;\n }\n const path = dirPath === \".\" ? name : `${dirPath}/${name}`;\n markLocalMutation(path);\n await loadFormats();\n const format = formatForPath(name);\n const content =\n format?.studio?.newFileTemplate ??\n (format\n ? \"\"\n : JSON.stringify({ children: [{ children: [], tagName: \"p\" }], tagName: \"div\" }, null, 2));\n try {\n const platform = getPlatform();\n await platform.writeFile(path, content);\n await loadDirectory(dirPath);\n renderLeftPanel();\n statusMessage(`Created ${path}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n/** @param {string} currentName @returns {Promise<string | null>} */\nfunction showRenameFileDialog(currentName: string): Promise<string | null> {\n return showPromptDialog(\"Rename\", {\n confirmLabel: \"Rename\",\n select: \"stem\",\n validate: (v) => (v.trim() ? \"\" : \"Enter a file name.\"),\n value: currentName,\n });\n}\n\n/** Build the status-bar message for a rename, summarising any reference/tag rewrites. */\nfunction renameStatus(newName: string, report: RenameResult): string {\n const refs = report.references;\n const tagNote = report.tag ? `; tag → <${report.tag.to}> (${report.tag.refsUpdated})` : \"\";\n if (refs && refs.refsUpdated > 0) {\n return `Renamed to ${newName}; updated ${refs.refsUpdated} reference(s) in ${refs.filesChanged} file(s)${tagNote}`;\n }\n if (tagNote) {\n return `Renamed to ${newName}${tagNote}`;\n }\n return `Renamed to ${newName}`;\n}\n\n/** Reload any open tabs whose references the refactor rewrote (so the editor shows new paths). */\nfunction reloadRewrittenTabs(report: RenameResult, skipPath: string): void {\n for (const f of report.references?.files ?? []) {\n if (f.path !== skipPath && workspace.tabs.has(f.path)) {\n void reloadFileInTab(f.path);\n }\n }\n}\n\nasync function renameFile(\n entry: { name: string; path: string; type: string },\n renderLeftPanel: () => void,\n) {\n const newName = await showRenameFileDialog(entry.name);\n if (!newName || newName === entry.name) {\n return;\n }\n const entryPath = entry.path.replaceAll(\"\\\\\", \"/\");\n const parentDirPath = entryPath.includes(\"/\")\n ? entryPath.slice(0, entryPath.lastIndexOf(\"/\"))\n : \".\";\n const newPath = parentDirPath === \".\" ? newName : `${parentDirPath}/${newName}`;\n markLocalMutation(entry.path, newPath);\n try {\n const platform = getPlatform();\n const report = await platform.renameFile(entry.path, newPath);\n await loadDirectory(parentDirPath);\n if (requireProjectState().selectedPath === entry.path) {\n requireProjectState().selectedPath = newPath;\n }\n if (workspace.tabs.has(entry.path)) {\n renameTab(entry.path, newPath, newPath);\n }\n reloadRewrittenTabs(report, newPath);\n renderLeftPanel();\n statusMessage(renameStatus(newName, report));\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\nasync function deleteFile(\n entry: { name: string; path: string; type: string },\n renderLeftPanel: () => void,\n) {\n const confirmed = await showConfirmDialog(\"Delete File\", `Delete \"${entry.name}\"?`, {\n confirmLabel: \"Delete\",\n destructive: true,\n });\n if (!confirmed) {\n return;\n }\n try {\n const platform = getPlatform();\n markLocalMutation(entry.path);\n await platform.deleteFile(entry.path);\n const delPath = entry.path.replaceAll(\"\\\\\", \"/\");\n const parentDirPath = delPath.includes(\"/\") ? delPath.slice(0, delPath.lastIndexOf(\"/\")) : \".\";\n await loadDirectory(parentDirPath);\n if (requireProjectState().selectedPath === entry.path) {\n requireProjectState().selectedPath = null;\n }\n renderLeftPanel();\n statusMessage(`Deleted ${entry.name}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n// ─── Open file from tree ──────────────────────────────────────────────────────\n\n/**\n * Open a file from the file tree — auto-saves current dirty doc, then loads the new one.\n *\n * @param {{\n * S: import(\"../state.js\").StudioState;\n * commit: (s: import(\"../state.js\").StudioState) => void;\n * render: () => void;\n * loadMarkdown: (source: string, handle: unknown) => void;\n * }} ctx\n * @param {string} path\n */\nexport async function openFileFromTree(\n ctx: {\n S: StudioState;\n commit: (s: StudioState) => void;\n render: () => void;\n loadMarkdown: (source: string, handle: unknown) => void;\n },\n path: string,\n) {\n const platform = getPlatform();\n await loadFormats();\n // Auto-save current dirty document\n if (ctx.S.dirty && ctx.S.documentPath) {\n try {\n const tabLike = {\n doc: {\n content: ctx.S.content,\n document: ctx.S.document,\n mode: ctx.S.mode,\n sourceFormat: formatForPath(ctx.S.documentPath)?.name ?? null,\n },\n } as unknown as Tab;\n const output = await serializeDocument(tabLike);\n await platform.writeFile(ctx.S.documentPath, output);\n } catch (error) {\n statusMessage(`Save error: ${errorMessage(error)}`);\n }\n }\n\n // Fetch the file\n try {\n const content = await platform.readFile(path);\n if (!content) {\n return;\n }\n\n if (formatForPath(path)) {\n ctx.loadMarkdown(content, null);\n ctx.S.documentPath = path;\n ctx.S.dirty = false;\n ctx.commit(ctx.S);\n } else if (path.endsWith(\".json\")) {\n const doc = JSON.parse(content) as JxMutableNode;\n const newS = createState(doc);\n newS.documentPath = path;\n newS.dirty = false;\n ctx.commit(newS);\n } else {\n throw noFormatError(path);\n }\n\n // Update tree selection\n requireProjectState().selectedPath = path;\n\n ctx.render();\n statusMessage(`Opened ${path}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n/**\n * Open a file from the tree into a tab. Activates existing tab if already open.\n *\n * @param {string} path\n */\nexport async function openFileInTab(path: string) {\n for (const [id, tab] of workspace.tabs.entries()) {\n if (tab.documentPath === path) {\n activateTab(id);\n requireProjectState().selectedPath = path;\n return;\n }\n }\n\n // CSV files open in the grid editor (source mode remains as the raw-text alternate).\n if (path.toLowerCase().endsWith(\".csv\")) {\n try {\n await openCsvGridTab(path);\n requireProjectState().selectedPath = path;\n trackRecentFile({\n name: path.split(\"/\").pop() || path,\n path,\n root: requireProjectState().projectRoot,\n });\n statusMessage(`Opened ${path.split(\"/\").pop()}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n return;\n }\n\n const platform = getPlatform();\n try {\n const content = await platform.readFile(path);\n if (!content) {\n return;\n }\n\n await loadFormats();\n let document: Record<string, unknown>;\n let frontmatter: Record<string, unknown> | undefined;\n const format = formatForPath(path);\n if (format) {\n const result = await parseSourceForPath(path, content);\n ({ document } = result);\n ({ frontmatter } = result);\n } else if (path.endsWith(\".json\")) {\n document = JSON.parse(content) as Record<string, unknown>;\n } else {\n throw noFormatError(path);\n }\n\n const id = path;\n openTab({\n id,\n documentPath: path,\n document,\n ...(frontmatter != null && { frontmatter }),\n sourceFormat: format?.name ?? null,\n });\n requireProjectState().selectedPath = path;\n trackRecentFile({\n name: path.split(\"/\").pop() || path,\n path,\n root: requireProjectState().projectRoot,\n });\n\n statusMessage(`Opened ${path.split(\"/\").pop()}`);\n } catch (error) {\n statusMessage(`Error: ${errorMessage(error)}`);\n }\n}\n\n/**\n * Reload an already-open tab from disk without changing the active tab. Used to refresh after AI\n * assistant writes to a file.\n *\n * @param {string} path\n */\n/** Reload an open tab from disk when an external change arrives — but only if it is not dirty. */\nexport function reloadCleanTab(path: string): void {\n // Co-edited docs never reload from disk: the shared Y.Doc is ahead of the provider's write-back\n // (Which is what produced this event), and genuine external changes arrive as a collab reset.\n if (isCollabPath(path)) {\n return;\n }\n for (const [, tab] of workspace.tabs.entries()) {\n if (tab.documentPath === path && !tab.doc.dirty) {\n void reloadFileInTab(path);\n return;\n }\n }\n}\n\nexport async function reloadFileInTab(path: string) {\n for (const [, tab] of workspace.tabs.entries()) {\n if (tab.documentPath === path) {\n const platform = getPlatform();\n try {\n const content = await platform.readFile(path);\n if (!content) {\n return;\n }\n await loadFormats();\n if (formatForPath(path)) {\n const { document, frontmatter } = await parseSourceForPath(path, content);\n tab.doc.document = document;\n tab.doc.content.frontmatter = frontmatter;\n } else if (path.endsWith(\".json\")) {\n tab.doc.document = JSON.parse(content) as JxMutableNode;\n }\n tab.doc.dirty = false;\n } catch {}\n return;\n }\n }\n}\n"
|
|
22
|
-
],
|
|
23
|
-
"mappings": "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",
|
|
24
|
-
"debugId": "F6DA95B972A0DA6E64756E2164756E21",
|
|
25
|
-
"names": []
|
|
26
|
-
}
|