@jxsuite/studio 2.0.1 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/canvas.html +21 -0
- package/dist/chunks/Overlay.dev-qfjzkms8.js +23 -0
- package/dist/chunks/{Overlay.dev-cszx7yn5.js.map → Overlay.dev-qfjzkms8.js.map} +1 -1
- package/dist/chunks/{adapter-z8fkmbmv.js → adapter-qfnesn5v.js} +2 -2
- package/dist/chunks/{cf-settings-mmyv436d.js → cf-settings-73sh5z4p.js} +3 -3
- package/dist/chunks/{components-799jpvhm.js → components-2bpqp4mq.js} +5 -7
- package/dist/chunks/{components-799jpvhm.js.map → components-2bpqp4mq.js.map} +1 -1
- package/dist/chunks/content-source-34gnkbnn.js +38 -0
- package/dist/chunks/content-source-34gnkbnn.js.map +9 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js +258 -0
- package/dist/chunks/convert-to-repeater-t8kxre5s.js.map +10 -0
- package/dist/chunks/extension-sections-6mqydz35.js +301 -0
- package/dist/chunks/extension-sections-6mqydz35.js.map +11 -0
- package/dist/chunks/files-8kn321h1.js +70 -0
- package/dist/chunks/files-8kn321h1.js.map +9 -0
- package/dist/chunks/{format-host-8jxwts2p.js → format-host-mkwsmt8d.js} +3 -3
- package/dist/chunks/git-panel-tjbr191d.js +51 -0
- package/dist/chunks/git-panel-tjbr191d.js.map +9 -0
- package/dist/chunks/{index-baeg2x3y.js → index-7pxchcce.js} +4 -3
- package/dist/chunks/{index-baeg2x3y.js.map → index-7pxchcce.js.map} +3 -3
- package/dist/chunks/{jx-validate-qx8degj7.js → jx-validate-v6qgknrs.js} +3 -3
- package/dist/chunks/layers-panel-87pb25km.js +58 -0
- package/dist/chunks/layers-panel-87pb25km.js.map +9 -0
- package/dist/chunks/{monaco-setup-zjdp9zdw.js → monaco-setup-e0yh25j4.js} +4 -75
- package/dist/chunks/{monaco-setup-zjdp9zdw.js.map → monaco-setup-e0yh25j4.js.map} +3 -4
- package/dist/chunks/publish-panel-m0fcgdrt.js +21 -0
- package/dist/chunks/publish-panel-m0fcgdrt.js.map +9 -0
- package/dist/chunks/quick-search-rhs6cbsb.js +53 -0
- package/dist/chunks/quick-search-rhs6cbsb.js.map +9 -0
- package/dist/chunks/right-panel-zpdxd98t.js +37 -0
- package/dist/chunks/right-panel-zpdxd98t.js.map +9 -0
- package/dist/chunks/section-registry-zmckaxf4.js +30 -0
- package/dist/chunks/section-registry-zmckaxf4.js.map +9 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js +18 -0
- package/dist/chunks/sp-overlay.dev-9ran0sfq.js.map +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js +9 -0
- package/dist/chunks/sp-popover.dev-rebmdncr.js.map +9 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js +15 -0
- package/dist/chunks/sp-progress-circle.dev-5vkppfkt.js.map +9 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js +15 -0
- package/dist/chunks/sp-tooltip.dev-ykqrg8h5.js.map +9 -0
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js → sp-tray.dev-ey59vfh7.js} +10 -8
- package/dist/chunks/{sp-tray.dev-pb2fsd65.js.map → sp-tray.dev-ey59vfh7.js.map} +2 -2
- package/dist/chunks/{studio-9qr6fq7p.js → studio-0rqqhrdy.js} +10 -378
- package/dist/chunks/{studio-9qr6fq7p.js.map → studio-0rqqhrdy.js.map} +4 -14
- package/dist/chunks/{studio-5x6tqqec.js → studio-2sj1jj3v.js} +10 -8
- package/dist/chunks/{studio-5x6tqqec.js.map → studio-2sj1jj3v.js.map} +2 -2
- package/dist/chunks/{studio-h3fw0wn8.js → studio-3fk1ac9z.js} +6 -4
- package/dist/chunks/{studio-h3fw0wn8.js.map → studio-3fk1ac9z.js.map} +2 -2
- package/dist/chunks/studio-41exgzhq.js +6690 -0
- package/dist/chunks/studio-41exgzhq.js.map +38 -0
- package/dist/chunks/{studio-7v2bpweq.js → studio-4mqb9a0j.js} +6 -4
- package/dist/chunks/{studio-7v2bpweq.js.map → studio-4mqb9a0j.js.map} +2 -2
- package/dist/chunks/studio-50k77cca.js +1787 -0
- package/dist/chunks/studio-50k77cca.js.map +18 -0
- package/dist/chunks/{studio-56v3zwk6.js → studio-6a0h7sne.js} +10 -8
- package/dist/chunks/{studio-56v3zwk6.js.map → studio-6a0h7sne.js.map} +2 -2
- package/dist/chunks/studio-6f0am8f2.js +53 -0
- package/dist/chunks/studio-6f0am8f2.js.map +10 -0
- package/dist/chunks/studio-6nmjc5qk.js +7002 -0
- package/dist/chunks/studio-6nmjc5qk.js.map +32 -0
- package/dist/chunks/studio-7afd21nw.js +67 -0
- package/dist/chunks/studio-7afd21nw.js.map +10 -0
- package/dist/chunks/{studio-xze4zrs1.js → studio-7bmdvzne.js} +2 -2
- package/dist/chunks/studio-7bmdvzne.js.map +10 -0
- package/dist/chunks/studio-8jpzqk5s.js +128 -0
- package/dist/chunks/studio-8jpzqk5s.js.map +10 -0
- package/dist/chunks/studio-94m77tgk.js +1482 -0
- package/dist/chunks/studio-94m77tgk.js.map +13 -0
- package/dist/chunks/studio-9je6w5sq.js +1000 -0
- package/dist/chunks/studio-9je6w5sq.js.map +16 -0
- package/dist/chunks/{studio-w7c6kvk7.js → studio-a7pzveq1.js} +2 -2
- package/dist/chunks/{studio-gs6kqdt1.js → studio-adn0z1k3.js} +14 -8
- package/dist/chunks/{studio-gs6kqdt1.js.map → studio-adn0z1k3.js.map} +3 -3
- package/dist/chunks/{studio-kr88ryr7.js → studio-bsxxx3x2.js} +17 -15
- package/dist/chunks/{studio-kr88ryr7.js.map → studio-bsxxx3x2.js.map} +7 -6
- package/dist/chunks/studio-bw5dz6km.js +608 -0
- package/dist/chunks/studio-bw5dz6km.js.map +21 -0
- package/dist/chunks/studio-c6s5getc.js +4232 -0
- package/dist/chunks/studio-c6s5getc.js.map +39 -0
- package/dist/chunks/studio-cjm7fdjf.js +451 -0
- package/dist/chunks/studio-cjm7fdjf.js.map +14 -0
- package/dist/chunks/{studio-cx91mnh8.js → studio-ckwz4d3x.js} +53 -53
- package/dist/chunks/{studio-cx91mnh8.js.map → studio-ckwz4d3x.js.map} +5 -5
- package/dist/chunks/studio-dg7zyt5x.js +28 -0
- package/dist/chunks/studio-dg7zyt5x.js.map +10 -0
- package/dist/chunks/studio-dzcyvvvz.js +166 -0
- package/dist/chunks/studio-dzcyvvvz.js.map +10 -0
- package/dist/chunks/{studio-7kqe41sa.js → studio-evkr5d3b.js} +15 -7
- package/dist/chunks/{studio-7kqe41sa.js.map → studio-evkr5d3b.js.map} +5 -4
- package/dist/chunks/studio-f12h6177.js +411 -0
- package/dist/chunks/studio-f12h6177.js.map +13 -0
- package/dist/chunks/studio-hbp1s8m9.js +1817 -0
- package/dist/chunks/studio-hbp1s8m9.js.map +14 -0
- package/dist/chunks/studio-k2sxjph5.js +15295 -0
- package/dist/chunks/studio-k2sxjph5.js.map +235 -0
- package/dist/chunks/studio-myje51t3.js +385 -0
- package/dist/chunks/studio-myje51t3.js.map +12 -0
- package/dist/chunks/studio-na6rwzhw.js +353 -0
- package/dist/chunks/studio-na6rwzhw.js.map +11 -0
- package/dist/chunks/{studio-4k0m4fmp.js → studio-p471gg5n.js} +126 -3
- package/dist/chunks/studio-p471gg5n.js.map +14 -0
- package/dist/chunks/{studio-9bjwf0d4.js → studio-rgwcpast.js} +5 -46
- package/dist/chunks/{studio-9bjwf0d4.js.map → studio-rgwcpast.js.map} +4 -5
- package/dist/chunks/{studio-esrewxap.js → studio-s519zc99.js} +3 -3
- package/dist/chunks/studio-sas7mt3k.js +75 -0
- package/dist/chunks/studio-sas7mt3k.js.map +10 -0
- package/dist/chunks/studio-t5wqwzdh.js +74 -0
- package/dist/chunks/studio-t5wqwzdh.js.map +10 -0
- package/dist/chunks/{studio-9qpspwfn.js → studio-temv5bw4.js} +5 -5
- package/dist/chunks/{studio-9qpspwfn.js.map → studio-temv5bw4.js.map} +1 -1
- package/dist/chunks/{studio-qkvt37c0.js → studio-tr20m8g8.js} +669 -18
- package/dist/chunks/studio-tr20m8g8.js.map +9 -0
- package/dist/chunks/{studio-v7jkjqng.js → studio-v96qfnww.js} +5514 -4291
- package/dist/chunks/studio-v96qfnww.js.map +54 -0
- package/dist/chunks/studio-vcetc91k.js +659 -0
- package/dist/chunks/studio-vcetc91k.js.map +10 -0
- package/dist/chunks/{studio-jm0z592w.js → studio-vmymjefp.js} +2972 -4937
- package/dist/chunks/studio-vmymjefp.js.map +98 -0
- package/dist/chunks/{studio-bghqfmea.js → studio-wwseqyw0.js} +2 -2
- package/dist/chunks/studio-x9hmy5kr.js +390 -0
- package/dist/chunks/studio-x9hmy5kr.js.map +10 -0
- package/dist/chunks/studio-xa0ce0n7.js +335 -0
- package/dist/chunks/studio-xa0ce0n7.js.map +10 -0
- package/dist/chunks/studio-xm3dbxvn.js +378 -0
- package/dist/chunks/studio-xm3dbxvn.js.map +19 -0
- package/dist/chunks/{studio-nqw433kv.js → studio-xmvbhg31.js} +2 -2
- package/dist/chunks/studio-zv37yrfa.js +1054 -0
- package/dist/chunks/studio-zv37yrfa.js.map +13 -0
- package/dist/chunks/{ws-client-q7hkz3j9.js → ws-client-654ts66j.js} +6 -4
- package/dist/chunks/ws-client-654ts66j.js.map +11 -0
- package/dist/iframe-entry.js +668 -230
- package/dist/studio.js +21080 -32585
- package/index.html +35 -4685
- package/package.json +17 -15
- package/src/about/about-modal.ts +42 -11
- package/src/browse/library-commands.ts +240 -0
- package/src/browse/library-layouts.ts +369 -0
- package/src/browse/library-model.ts +396 -0
- package/src/browse/library-pane.ts +1049 -0
- package/src/browse/library-preview.ts +252 -0
- package/src/browse/library-source.ts +150 -0
- package/src/canvas/canvas-helpers.ts +33 -9
- package/src/canvas/canvas-live-render.ts +45 -29
- package/src/canvas/canvas-patcher.ts +151 -31
- package/src/canvas/canvas-perf.ts +46 -7
- package/src/canvas/canvas-render.ts +1092 -220
- package/src/canvas/canvas-surface.ts +240 -0
- package/src/canvas/canvas-utils.ts +1166 -124
- package/src/canvas/iframe-drop.ts +2 -1
- package/src/canvas/iframe-entry.ts +241 -4
- package/src/canvas/iframe-host.ts +1226 -143
- package/src/canvas/iframe-inline-edit.ts +31 -0
- package/src/canvas/iframe-interaction.ts +76 -16
- package/src/canvas/iframe-keys.ts +107 -45
- package/src/canvas/iframe-overlay.ts +38 -1
- package/src/canvas/iframe-protocol.ts +137 -2
- package/src/canvas/iframe-render.ts +70 -2
- package/src/canvas/iframe-slash.ts +6 -0
- package/src/canvas/path-mapping.ts +56 -6
- package/src/canvas/surface-registry.ts +292 -0
- package/src/collab/collab-commands.ts +244 -0
- package/src/collab/collab-session.ts +198 -32
- package/src/collab/collab-state.ts +28 -2
- package/src/collab/presence-chips.ts +100 -9
- package/src/commands/active-registry.ts +42 -0
- package/src/commands/app-commands.ts +176 -0
- package/src/commands/budget.ts +158 -0
- package/src/commands/command-args.ts +253 -0
- package/src/commands/context.ts +387 -0
- package/src/commands/defaults.ts +580 -0
- package/src/commands/keymap.ts +571 -0
- package/src/commands/levels.ts +345 -0
- package/src/commands/live-context.ts +193 -0
- package/src/commands/reference.ts +227 -0
- package/src/commands/registry.ts +293 -0
- package/src/component-props.ts +3 -2
- package/src/content/draft-state.ts +106 -0
- package/src/content/entry-commands.ts +282 -0
- package/src/content/entry-editor.ts +327 -0
- package/src/content/entry-fields.ts +116 -0
- package/src/content/entry-model.ts +175 -0
- package/src/editor/canvas-context-menu.ts +17 -11
- package/src/editor/canvas-slash-bridge.ts +11 -4
- package/src/editor/context-menu.ts +804 -204
- package/src/editor/convert-to-component.ts +31 -10
- package/src/editor/convert-to-repeater.ts +3 -2
- package/src/editor/inline-edit-apply.ts +5 -5
- package/src/editor/inline-edit.ts +86 -50
- package/src/editor/insert-zone-action.ts +1 -1
- package/src/editor/shortcuts.ts +1043 -329
- package/src/editor/slash-menu.ts +1 -0
- package/src/files/elements.ts +166 -0
- package/src/files/file-ops.ts +178 -31
- package/src/files/files.ts +898 -268
- package/src/files/fs-events.ts +21 -0
- package/src/files/media-meta.ts +203 -0
- package/src/files/media-paths.ts +141 -0
- package/src/files/media-upload.ts +7 -3
- package/src/files/media-usage.ts +189 -0
- package/src/github/github-auth.ts +235 -33
- package/src/github/github-publish.ts +80 -21
- package/src/grid/grid-controller.ts +152 -12
- package/src/grid/grid-layout.ts +225 -20
- package/src/grid/grid-open.ts +120 -0
- package/src/grid/grid-panel.ts +554 -39
- package/src/grid/grid-source.ts +27 -1
- package/src/grid/redirects-grid.ts +599 -0
- package/src/grid/redirects.ts +398 -0
- package/src/grid/sources/content-source.ts +108 -2
- package/src/i18n/i18n-commands.ts +322 -0
- package/src/new-project/add-repo-modal.ts +8 -10
- package/src/new-project/import-tab.ts +7 -0
- package/src/new-project/location-fields.ts +9 -1
- package/src/new-project/new-project-modal.ts +221 -245
- package/src/packages/jxsuite-update.ts +97 -48
- package/src/packages/pull-package-sync.ts +18 -9
- package/src/page-params.ts +2 -1
- package/src/panels/activity-bar.ts +152 -91
- package/src/panels/activity-panel.ts +481 -0
- package/src/panels/ai-chat/chat-markdown.ts +8 -3
- package/src/panels/ai-chat/chat-view.ts +245 -18
- package/src/panels/ai-chat/composer.ts +31 -5
- package/src/panels/ai-chat/sessions-view.ts +17 -10
- package/src/panels/ai-panel.ts +279 -53
- package/src/panels/block-action-bar.ts +1115 -224
- package/src/panels/bottom-dock.ts +337 -0
- package/src/panels/canvas-dnd-bridge.ts +37 -8
- package/src/panels/chat-panel.ts +29 -12
- package/src/panels/data-explorer.ts +254 -112
- package/src/panels/data-grid.ts +10 -4
- package/src/panels/dnd.ts +28 -51
- package/src/panels/editors.ts +434 -107
- package/src/panels/elements-panel.ts +66 -2
- package/src/panels/empty-state.ts +112 -0
- package/src/panels/events-panel.ts +596 -82
- package/src/panels/formula-workspace.ts +408 -218
- package/src/panels/frontmatter-fields.ts +51 -10
- package/src/panels/frontmatter-panel.ts +357 -79
- package/src/panels/git-panel.ts +375 -164
- package/src/panels/head-panel.ts +791 -85
- package/src/panels/i18n-panel.ts +592 -0
- package/src/panels/imports-panel.ts +95 -85
- package/src/panels/jump-bar.ts +584 -0
- package/src/panels/layers-panel.ts +1106 -328
- package/src/panels/left-panel.ts +109 -204
- package/src/panels/navigator-panels.ts +131 -0
- package/src/panels/overlays.ts +7 -2
- package/src/panels/pane-context.ts +1477 -0
- package/src/panels/pane-grid.ts +406 -0
- package/src/panels/panel-registry.ts +340 -0
- package/src/panels/panel-scheduler.ts +75 -0
- package/src/panels/problems-panel.ts +234 -0
- package/src/panels/properties-panel.ts +946 -1139
- package/src/panels/provenance.ts +258 -0
- package/src/panels/quick-search.ts +791 -122
- package/src/panels/right-panel.ts +228 -102
- package/src/panels/seo-modal.ts +395 -0
- package/src/panels/settings-pane.ts +203 -0
- package/src/panels/signals-panel.ts +354 -137
- package/src/panels/statement-editor.ts +41 -25
- package/src/panels/statusbar.ts +342 -106
- package/src/panels/style-panel.ts +974 -463
- package/src/panels/style-utils.ts +3 -3
- package/src/panels/stylebook-doc.ts +4 -2
- package/src/panels/stylebook-layers-panel.ts +3 -2
- package/src/panels/stylebook-panel.ts +51 -26
- package/src/panels/tab-strip.ts +1058 -78
- package/src/panels/target-line.ts +274 -0
- package/src/panels/toolbar.ts +631 -484
- package/src/panels/welcome-screen.ts +301 -198
- package/src/platform-errors.ts +26 -3
- package/src/platform.ts +96 -2
- package/src/platforms/cloud.ts +71 -8
- package/src/platforms/devserver.ts +92 -29
- package/src/publish/deploy-checklist.ts +383 -0
- package/src/publish/pages-service.ts +10 -1
- package/src/publish/publish-commands.ts +218 -0
- package/src/publish/publish-panel.ts +110 -16
- package/src/recent-projects.ts +3 -2
- package/src/services/a11y-report.ts +505 -0
- package/src/services/ai-models.ts +30 -1
- package/src/services/ai-project-tools.ts +29 -10
- package/src/services/ai-system-prompt.ts +53 -14
- package/src/services/ai-tools.ts +39 -3
- package/src/services/ai-writes.ts +154 -0
- package/src/services/announce.ts +97 -0
- package/src/services/automation.ts +424 -175
- package/src/services/cem-export.ts +9 -4
- package/src/services/clock.ts +61 -0
- package/src/services/document-assistant.ts +36 -8
- package/src/services/idle.ts +179 -0
- package/src/services/import-client.ts +26 -0
- package/src/services/monaco-buffer.ts +627 -0
- package/src/services/monaco-lazy.ts +36 -0
- package/src/services/notify.ts +271 -0
- package/src/services/profile.ts +155 -0
- package/src/services/references.ts +0 -0
- package/src/services/token-lint.ts +3 -2
- package/src/services/tool-executor.ts +53 -7
- package/src/services/trusted-types.ts +123 -0
- package/src/settings/contexts-section.ts +427 -0
- package/src/settings/contributed-section.ts +149 -11
- package/src/settings/css-vars-editor.ts +306 -349
- package/src/settings/defs-editor.ts +93 -34
- package/src/settings/dependencies-editor.ts +7 -7
- package/src/settings/extension-sections.ts +37 -5
- package/src/settings/general-settings.ts +204 -121
- package/src/settings/locales-section.ts +347 -0
- package/src/settings/preferences-accounts.ts +140 -0
- package/src/settings/preferences-dialog.ts +620 -0
- package/src/settings/preferences-keymap.ts +270 -0
- package/src/settings/project-sections.ts +260 -0
- package/src/settings/section-registry.ts +169 -0
- package/src/settings/settings-document.ts +385 -0
- package/src/shell.ts +1549 -0
- package/src/site-context.ts +45 -20
- package/src/state.ts +14 -275
- package/src/store.ts +88 -43
- package/src/studio.ts +790 -346
- package/src/style/live-preview.ts +36 -0
- package/src/style/project-styles.ts +349 -0
- package/src/style/token-ref.ts +123 -0
- package/src/tabs/patch-ops.ts +16 -4
- package/src/tabs/project-config.ts +416 -0
- package/src/tabs/selection.ts +323 -0
- package/src/tabs/tab.ts +182 -47
- package/src/tabs/transact.ts +209 -28
- package/src/types.ts +68 -13
- package/src/ui/ai-credentials-form.ts +39 -35
- package/src/ui/ai-managed-connect.ts +7 -1
- package/src/ui/dynamic-slot.ts +224 -81
- package/src/ui/expression-editor.ts +71 -63
- package/src/ui/field-input.ts +4 -6
- package/src/ui/field-row.ts +215 -38
- package/src/ui/form-controls.ts +194 -7
- package/src/ui/layers.ts +492 -69
- package/src/ui/media-picker.ts +115 -25
- package/src/ui/panel-resize.ts +109 -91
- package/src/ui/progress-modal.ts +131 -50
- package/src/ui/regions.ts +462 -0
- package/src/ui/schema-form.ts +229 -45
- package/src/ui/spectrum.ts +24 -8
- package/src/ui/timing.ts +49 -0
- package/src/ui/value-selector.ts +20 -0
- package/src/ui/value-source.ts +348 -0
- package/src/ui/virtual-window.ts +400 -0
- package/src/utils/edit-display.ts +3 -2
- package/src/utils/inherited-style.ts +67 -37
- package/src/view.ts +64 -78
- package/src/workspace/pane-derive.ts +1258 -0
- package/src/workspace/session.ts +317 -0
- package/src/workspace/workspace.ts +1345 -23
- package/styles/canvas.css +653 -0
- package/styles/forced-colors.css +106 -0
- package/styles/inspector.css +1454 -0
- package/styles/overlays.css +2704 -0
- package/styles/panels.css +1701 -0
- package/styles/shell.css +1423 -0
- package/styles/tokens.css +151 -0
- package/dist/chunks/Overlay.dev-cszx7yn5.js +0 -22
- package/dist/chunks/extension-sections-qr3drkkw.js +0 -531
- package/dist/chunks/extension-sections-qr3drkkw.js.map +0 -12
- package/dist/chunks/files-j8a1t06k.js +0 -50
- package/dist/chunks/files-j8a1t06k.js.map +0 -9
- package/dist/chunks/git-panel-xtq5z81x.js +0 -28
- package/dist/chunks/git-panel-xtq5z81x.js.map +0 -9
- package/dist/chunks/layers-panel-ancn2wpq.js +0 -26
- package/dist/chunks/layers-panel-ancn2wpq.js.map +0 -9
- package/dist/chunks/settings-modal-17ttr96g.js +0 -29
- package/dist/chunks/settings-modal-17ttr96g.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-earn5as8.js +0 -17
- package/dist/chunks/sp-overlay.dev-earn5as8.js.map +0 -9
- package/dist/chunks/sp-popover.dev-frxtfejn.js +0 -8
- package/dist/chunks/sp-popover.dev-frxtfejn.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js +0 -14
- package/dist/chunks/sp-progress-circle.dev-7tvw34h8.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js +0 -21
- package/dist/chunks/sp-tooltip.dev-a9fywesm.js.map +0 -10
- package/dist/chunks/studio-0xgs7xrs.js +0 -429
- package/dist/chunks/studio-0xgs7xrs.js.map +0 -13
- package/dist/chunks/studio-4d8hzcz5.js +0 -3427
- package/dist/chunks/studio-4d8hzcz5.js.map +0 -26
- package/dist/chunks/studio-4k0m4fmp.js.map +0 -13
- package/dist/chunks/studio-9smfzqhc.js +0 -19
- package/dist/chunks/studio-9smfzqhc.js.map +0 -10
- package/dist/chunks/studio-jm0z592w.js.map +0 -115
- package/dist/chunks/studio-m2t4mdg5.js +0 -1854
- package/dist/chunks/studio-m2t4mdg5.js.map +0 -18
- package/dist/chunks/studio-n4p11dfy.js +0 -853
- package/dist/chunks/studio-n4p11dfy.js.map +0 -12
- package/dist/chunks/studio-qkvt37c0.js.map +0 -9
- package/dist/chunks/studio-sjh1wt1a.js +0 -3744
- package/dist/chunks/studio-sjh1wt1a.js.map +0 -22
- package/dist/chunks/studio-v7jkjqng.js.map +0 -46
- package/dist/chunks/studio-xq0t7n5t.js +0 -140
- package/dist/chunks/studio-xq0t7n5t.js.map +0 -10
- package/dist/chunks/studio-xze4zrs1.js.map +0 -10
- package/dist/chunks/studio-yfcstdzy.js +0 -399
- package/dist/chunks/studio-yfcstdzy.js.map +0 -12
- package/dist/chunks/studio-zp7jncs8.js +0 -469
- package/dist/chunks/studio-zp7jncs8.js.map +0 -14
- package/dist/chunks/ws-client-q7hkz3j9.js.map +0 -11
- package/src/browse/browse-modal.ts +0 -69
- package/src/browse/browse.ts +0 -904
- package/src/canvas/canvas-diff.ts +0 -216
- package/src/canvas/nested-site-style.ts +0 -58
- package/src/new-project/design-fields.ts +0 -264
- package/src/new-project/templates.ts +0 -61
- package/src/panels/tab-bar.ts +0 -548
- package/src/settings/settings-modal.ts +0 -203
- /package/dist/chunks/{adapter-z8fkmbmv.js.map → adapter-qfnesn5v.js.map} +0 -0
- /package/dist/chunks/{cf-settings-mmyv436d.js.map → cf-settings-73sh5z4p.js.map} +0 -0
- /package/dist/chunks/{format-host-8jxwts2p.js.map → format-host-mkwsmt8d.js.map} +0 -0
- /package/dist/chunks/{jx-validate-qx8degj7.js.map → jx-validate-v6qgknrs.js.map} +0 -0
- /package/dist/chunks/{studio-w7c6kvk7.js.map → studio-a7pzveq1.js.map} +0 -0
- /package/dist/chunks/{studio-esrewxap.js.map → studio-s519zc99.js.map} +0 -0
- /package/dist/chunks/{studio-bghqfmea.js.map → studio-wwseqyw0.js.map} +0 -0
- /package/dist/chunks/{studio-nqw433kv.js.map → studio-xmvbhg31.js.map} +0 -0
package/src/panels/git-panel.ts
CHANGED
|
@@ -7,50 +7,37 @@
|
|
|
7
7
|
import { html, nothing } from "lit-html";
|
|
8
8
|
import { errorMessage } from "@jxsuite/schema/parse";
|
|
9
9
|
import { flushAllCollab } from "../collab/collab-session";
|
|
10
|
-
import type {
|
|
11
|
-
GitBranchesResult,
|
|
12
|
-
GitDiffState,
|
|
13
|
-
GitFileStatus,
|
|
14
|
-
GitStatusResult,
|
|
15
|
-
StudioPlatform,
|
|
16
|
-
} from "../types";
|
|
10
|
+
import type { GitDiffState, GitFileStatus, StudioPlatform } from "../types";
|
|
17
11
|
import { live } from "lit-html/directives/live.js";
|
|
18
12
|
import { repeat } from "lit-html/directives/repeat.js";
|
|
19
13
|
import { getPlatform } from "../platform";
|
|
14
|
+
import { now } from "../services/clock";
|
|
20
15
|
import { formatForPath } from "../format/format-host";
|
|
21
|
-
import { projectState
|
|
16
|
+
import { projectState } from "../store";
|
|
22
17
|
import { activeTab } from "../workspace/workspace";
|
|
23
|
-
import {
|
|
18
|
+
import type { Tab } from "../tabs/tab";
|
|
19
|
+
import { shell } from "../shell";
|
|
20
|
+
import type { GitLogEntry } from "../shell";
|
|
24
21
|
import { showConfirmDialog, showPromptDialog } from "../ui/layers";
|
|
25
|
-
import {
|
|
26
|
-
import {
|
|
22
|
+
import { POLL_GIT } from "../ui/timing";
|
|
23
|
+
import { renderEmptyState } from "./empty-state";
|
|
24
|
+
import { registerPanel } from "./panel-registry";
|
|
25
|
+
import { notify } from "../services/notify";
|
|
26
|
+
import { authenticateGithub } from "../github/github-auth";
|
|
27
|
+
import { createGithubRepository } from "../github/github-publish";
|
|
27
28
|
import { pullWithPackageSync } from "../packages/pull-package-sync";
|
|
28
|
-
|
|
29
|
-
interface GitLogEntry {
|
|
30
|
-
hash: string;
|
|
31
|
-
message: string;
|
|
32
|
-
author: string;
|
|
33
|
-
date: string;
|
|
34
|
-
}
|
|
29
|
+
import type { AnyCommand, CommandRegistry } from "../commands/registry";
|
|
35
30
|
|
|
36
31
|
type GitFileEntry = GitFileStatus;
|
|
37
32
|
|
|
38
|
-
interface GitUiState {
|
|
39
|
-
gitStatus?: Partial<GitStatusResult> | null;
|
|
40
|
-
gitBranches?: Partial<GitBranchesResult> | null;
|
|
41
|
-
gitLoading?: boolean;
|
|
42
|
-
gitError?: string | null;
|
|
43
|
-
gitCommitMessage?: string;
|
|
44
|
-
gitLogEntries?: GitLogEntry[] | null;
|
|
45
|
-
}
|
|
46
|
-
|
|
47
33
|
export async function refreshGitStatus() {
|
|
48
34
|
if (!projectState) {
|
|
49
35
|
return;
|
|
50
36
|
}
|
|
51
37
|
const plat = getPlatform();
|
|
52
|
-
|
|
53
|
-
|
|
38
|
+
const { git } = shell;
|
|
39
|
+
git.loading = true;
|
|
40
|
+
git.error = null;
|
|
54
41
|
try {
|
|
55
42
|
// Settled independently, not Promise.all: outside a work tree `git branch` exits non-zero
|
|
56
43
|
// While `git status` answers cleanly with isRepo:false. Letting the branch lookup reject the
|
|
@@ -58,10 +45,10 @@ export async function refreshGitStatus() {
|
|
|
58
45
|
// Again, and span — a request per render for as long as the tab stayed open.
|
|
59
46
|
const [status, branches] = await Promise.allSettled([plat.gitStatus(), plat.gitBranches()]);
|
|
60
47
|
if (status.status === "fulfilled") {
|
|
61
|
-
|
|
48
|
+
git.status = status.value;
|
|
62
49
|
}
|
|
63
50
|
if (branches.status === "fulfilled") {
|
|
64
|
-
|
|
51
|
+
git.branches = branches.value;
|
|
65
52
|
}
|
|
66
53
|
// A branch lookup that fails on a repo-less project is expected, not an error worth showing;
|
|
67
54
|
// Anything else (including a failed status) surfaces.
|
|
@@ -72,14 +59,13 @@ export async function refreshGitStatus() {
|
|
|
72
59
|
? branches.reason
|
|
73
60
|
: null;
|
|
74
61
|
if (failure) {
|
|
75
|
-
|
|
62
|
+
git.error = errorMessage(failure);
|
|
76
63
|
}
|
|
77
|
-
|
|
64
|
+
git.lastUpdated = now();
|
|
78
65
|
} catch (error) {
|
|
79
|
-
|
|
66
|
+
git.error = errorMessage(error);
|
|
80
67
|
} finally {
|
|
81
|
-
|
|
82
|
-
renderOnly("leftPanel");
|
|
68
|
+
git.loading = false;
|
|
83
69
|
}
|
|
84
70
|
}
|
|
85
71
|
|
|
@@ -91,7 +77,7 @@ export async function refreshGitStatus() {
|
|
|
91
77
|
export async function cloneRepository(ctx: { openRecentProject: (root: string) => Promise<void> }) {
|
|
92
78
|
const platform = getPlatform();
|
|
93
79
|
if (!platform.gitClone) {
|
|
94
|
-
|
|
80
|
+
notify.warn("Cloning is not supported on this platform.", { source: "Source Control" });
|
|
95
81
|
return;
|
|
96
82
|
}
|
|
97
83
|
|
|
@@ -107,14 +93,18 @@ export async function cloneRepository(ctx: { openRecentProject: (root: string) =
|
|
|
107
93
|
}
|
|
108
94
|
|
|
109
95
|
try {
|
|
110
|
-
|
|
96
|
+
notify.info("Cloning repository…", { key: "git.clone", source: "Source Control" });
|
|
111
97
|
const result = await platform.gitClone(url);
|
|
112
98
|
if (result?.root) {
|
|
113
|
-
|
|
99
|
+
notify.success("Clone complete.", { key: "git.clone" });
|
|
114
100
|
await ctx.openRecentProject(result.root);
|
|
115
101
|
}
|
|
116
102
|
} catch (error) {
|
|
117
|
-
|
|
103
|
+
notify.error("Could not clone the repository.", {
|
|
104
|
+
detail: errorMessage(error),
|
|
105
|
+
key: "git.clone",
|
|
106
|
+
source: "Source Control",
|
|
107
|
+
});
|
|
118
108
|
}
|
|
119
109
|
}
|
|
120
110
|
|
|
@@ -123,6 +113,100 @@ export function platformSupportsClone() {
|
|
|
123
113
|
return Boolean(getPlatform().gitClone);
|
|
124
114
|
}
|
|
125
115
|
|
|
116
|
+
/**
|
|
117
|
+
* One file's comparison against HEAD: the committed text and the working copy.
|
|
118
|
+
*
|
|
119
|
+
* **One definition site, because there are now two callers.** This panel's row click has always
|
|
120
|
+
* made this pair of reads; `workspace/pane-derive.ts`'s Diff lens needs the same answer for the
|
|
121
|
+
* document its source pane is showing, and it must not reach `shell.git.diffState` — that slot
|
|
122
|
+
* holds whatever THIS panel last opened, which is a different file (§18.4, finding 4). A second
|
|
123
|
+
* copy of these five lines is how the panel and the lens would come to disagree about what "the
|
|
124
|
+
* diff of this file" means, which is the rule {@link initRepository} is written under too.
|
|
125
|
+
*
|
|
126
|
+
* `A` (added) has no `HEAD` copy, so its original is the empty string rather than a `gitShow` that
|
|
127
|
+
* would throw. Callers narrow to `M`/`A` before asking.
|
|
128
|
+
*
|
|
129
|
+
* @param {string} path
|
|
130
|
+
* @param {string} fileStatus
|
|
131
|
+
* @returns {Promise<GitDiffState>}
|
|
132
|
+
*/
|
|
133
|
+
export async function readGitDiff(path: string, fileStatus: string): Promise<GitDiffState> {
|
|
134
|
+
const plat = getPlatform();
|
|
135
|
+
const [originalContent, currentContent] = await Promise.all([
|
|
136
|
+
fileStatus === "A" ? Promise.resolve("") : plat.gitShow({ path, ref: "HEAD" }),
|
|
137
|
+
plat.readFile(path),
|
|
138
|
+
]);
|
|
139
|
+
return { currentContent, filePath: path, fileStatus, originalContent };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The Diff lens's reader: {@link readGitDiff}, with a failure the PANE can state.
|
|
144
|
+
*
|
|
145
|
+
* A rejection here is not an error the shell should raise — the author asked to see a comparison
|
|
146
|
+
* beside their page, and "could not read it" is a sentence the derived pane draws in its own empty
|
|
147
|
+
* state. `applyDerivation` turns the `null` into exactly that.
|
|
148
|
+
*
|
|
149
|
+
* @param {string} path
|
|
150
|
+
* @param {string} fileStatus
|
|
151
|
+
* @returns {Promise<GitDiffState | null>}
|
|
152
|
+
*/
|
|
153
|
+
export async function loadDiffForLens(
|
|
154
|
+
path: string,
|
|
155
|
+
fileStatus: string,
|
|
156
|
+
): Promise<GitDiffState | null> {
|
|
157
|
+
try {
|
|
158
|
+
return await readGitDiff(path, fileStatus);
|
|
159
|
+
} catch (error) {
|
|
160
|
+
// Reported where it can be acted on — the pane says so — rather than as a toast over a
|
|
161
|
+
// Document the author did not ask about.
|
|
162
|
+
console.warn("loadDiffForLens:", errorMessage(error));
|
|
163
|
+
return null;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Start tracking this project with git.
|
|
169
|
+
*
|
|
170
|
+
* A function rather than an inline click handler because it is now also a command ({@link
|
|
171
|
+
* sourceControlCommands}) and the first step of the deploy checklist, and three call sites of the
|
|
172
|
+
* same three lines is how the panel and the palette come to disagree about what a verb does.
|
|
173
|
+
*/
|
|
174
|
+
export async function initRepository(): Promise<void> {
|
|
175
|
+
try {
|
|
176
|
+
notify.info("Initializing repository…", { key: "git.init" });
|
|
177
|
+
await getPlatform().gitInit();
|
|
178
|
+
notify.success("Repository initialized.", { key: "git.init" });
|
|
179
|
+
} catch (error) {
|
|
180
|
+
notify.error("Could not initialize the repository.", {
|
|
181
|
+
action: "git.init",
|
|
182
|
+
detail: errorMessage(error),
|
|
183
|
+
key: "git.init",
|
|
184
|
+
source: "Source Control",
|
|
185
|
+
});
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
await refreshGitStatus();
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/** Push the current branch. Same loading/error contract as every other panel verb. */
|
|
192
|
+
export async function pushCurrentBranch(): Promise<void> {
|
|
193
|
+
await gitAction("gitPush");
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Sign in to GitHub, or report why it could not.
|
|
198
|
+
*
|
|
199
|
+
* The report belongs to `github/github-auth.ts` — this only says what a SUCCESS was, which that
|
|
200
|
+
* module cannot, because it is also called mid-flow by "Create GitHub Repository" where a toast
|
|
201
|
+
* saying "Signed in" in front of a half-finished operation would be noise.
|
|
202
|
+
*/
|
|
203
|
+
export async function signInToGithub(): Promise<void> {
|
|
204
|
+
const token = await authenticateGithub();
|
|
205
|
+
if (token) {
|
|
206
|
+
notify.success("Signed in to GitHub.", { key: "github.auth" });
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
126
210
|
/**
|
|
127
211
|
* @param {string} action
|
|
128
212
|
* @param {unknown} [body]
|
|
@@ -130,87 +214,87 @@ export function platformSupportsClone() {
|
|
|
130
214
|
async function gitAction(action: string, body?: unknown) {
|
|
131
215
|
const plat = getPlatform() as Record<string, (...args: unknown[]) => Promise<unknown>> &
|
|
132
216
|
StudioPlatform;
|
|
133
|
-
|
|
134
|
-
|
|
217
|
+
shell.git.loading = true;
|
|
218
|
+
shell.git.error = null;
|
|
135
219
|
try {
|
|
136
220
|
await plat[action]!(body);
|
|
137
221
|
await refreshGitStatus();
|
|
138
222
|
} catch (error) {
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
renderOnly("leftPanel");
|
|
223
|
+
shell.git.error = errorMessage(error);
|
|
224
|
+
shell.git.loading = false;
|
|
142
225
|
}
|
|
143
226
|
}
|
|
144
227
|
|
|
145
228
|
/** Pull via the package-aware orchestrator; same loading/error contract as gitAction. */
|
|
146
229
|
async function doPull() {
|
|
147
|
-
|
|
148
|
-
|
|
230
|
+
shell.git.loading = true;
|
|
231
|
+
shell.git.error = null;
|
|
149
232
|
try {
|
|
150
233
|
await pullWithPackageSync();
|
|
151
234
|
await refreshGitStatus();
|
|
152
235
|
} catch (error) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
renderOnly("leftPanel");
|
|
236
|
+
shell.git.error = errorMessage(error);
|
|
237
|
+
shell.git.loading = false;
|
|
156
238
|
}
|
|
157
239
|
}
|
|
158
240
|
|
|
241
|
+
/**
|
|
242
|
+
* The background refresh handle. The interval itself is infrastructure, not state — the sub-tab and
|
|
243
|
+
* the "last updated" stamp it used to sit beside are on `shell.git`, so opening a second project no
|
|
244
|
+
* longer inherits the first one's History selection and timestamp.
|
|
245
|
+
*/
|
|
159
246
|
let _pollTimer = null as ReturnType<typeof setInterval> | null;
|
|
160
|
-
let _lastUpdated = null as Date | null;
|
|
161
|
-
let _gitSubTab = "changes";
|
|
162
247
|
|
|
163
248
|
async function fetchGitLog() {
|
|
164
249
|
const plat = getPlatform();
|
|
165
250
|
try {
|
|
166
|
-
|
|
167
|
-
updateUi("gitLogEntries", entries);
|
|
168
|
-
renderOnly("leftPanel");
|
|
251
|
+
shell.git.logEntries = await plat.gitLog(30);
|
|
169
252
|
} catch (error) {
|
|
170
|
-
|
|
171
|
-
renderOnly("leftPanel");
|
|
253
|
+
shell.git.error = errorMessage(error);
|
|
172
254
|
}
|
|
173
255
|
}
|
|
174
256
|
|
|
175
257
|
/**
|
|
176
|
-
*
|
|
258
|
+
* Render the Source Control panel.
|
|
259
|
+
*
|
|
260
|
+
* Takes no state argument: everything it reads is project-level and lives on `shell.git`, which is
|
|
261
|
+
* the whole point of the hoist — the panel renders identically with no document open.
|
|
262
|
+
*
|
|
177
263
|
* @param {{
|
|
178
|
-
* setCanvasMode?: (mode: string) => void;
|
|
264
|
+
* setCanvasMode?: (tab: Tab | null, mode: string) => void;
|
|
179
265
|
* setGitDiffState?: (state: GitDiffState | null) => void;
|
|
180
266
|
* cloneRepository?: () => void;
|
|
181
267
|
* }} ctx
|
|
182
268
|
*/
|
|
183
|
-
export function renderGitPanel(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
cloneRepository?: () => void;
|
|
189
|
-
},
|
|
190
|
-
) {
|
|
269
|
+
export function renderGitPanel(ctx: {
|
|
270
|
+
setCanvasMode?: (tab: Tab | null, mode: string) => void;
|
|
271
|
+
setGitDiffState?: (state: GitDiffState | null) => void;
|
|
272
|
+
cloneRepository?: () => void;
|
|
273
|
+
}) {
|
|
191
274
|
if (!projectState) {
|
|
192
275
|
return html`<div class="git-panel git-panel-empty">
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
276
|
+
${renderEmptyState({
|
|
277
|
+
actions: platformSupportsClone()
|
|
278
|
+
? [
|
|
279
|
+
{
|
|
280
|
+
icon: html`<sp-icon-download slot="icon"></sp-icon-download>`,
|
|
281
|
+
label: "Clone Git Repository",
|
|
282
|
+
run: () => ctx.cloneRepository?.(),
|
|
283
|
+
},
|
|
284
|
+
]
|
|
285
|
+
: [],
|
|
286
|
+
message:
|
|
287
|
+
"Source control keeps every version of a project, so any change can be undone. " +
|
|
288
|
+
"Open a project to see its history.",
|
|
289
|
+
})}
|
|
204
290
|
</div>`;
|
|
205
291
|
}
|
|
206
|
-
const status =
|
|
207
|
-
const branches = S.ui.gitBranches;
|
|
208
|
-
const loading = S.ui.gitLoading;
|
|
292
|
+
const { branches, loading, status } = shell.git;
|
|
209
293
|
|
|
210
294
|
// First paint kicks off the fetch. A refresh that already failed must NOT re-arm it here, or the
|
|
211
295
|
// Render it triggers becomes the next render's reason to fetch again; the Refresh button and the
|
|
212
296
|
// Poll timer are the ways back.
|
|
213
|
-
if (!status && !loading && !
|
|
297
|
+
if (!status && !loading && !shell.git.error) {
|
|
214
298
|
void refreshGitStatus();
|
|
215
299
|
return html`<div class="git-panel">
|
|
216
300
|
<div class="git-loading">Loading...</div>
|
|
@@ -219,42 +303,38 @@ export function renderGitPanel(
|
|
|
219
303
|
|
|
220
304
|
if (status && !status.isRepo) {
|
|
221
305
|
return html`<div class="git-panel git-panel-empty">
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
<sp-icon-share slot="icon"></sp-icon-share>
|
|
246
|
-
Publish to GitHub
|
|
247
|
-
</sp-action-button>
|
|
248
|
-
</div>
|
|
306
|
+
${renderEmptyState({
|
|
307
|
+
actions: [
|
|
308
|
+
{
|
|
309
|
+
disabled: Boolean(loading),
|
|
310
|
+
icon: html`<sp-icon-add slot="icon"></sp-icon-add>`,
|
|
311
|
+
label: "Initialize Repository",
|
|
312
|
+
run: () => {
|
|
313
|
+
void initRepository();
|
|
314
|
+
},
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
disabled: Boolean(loading),
|
|
318
|
+
icon: html`<sp-icon-share slot="icon"></sp-icon-share>`,
|
|
319
|
+
label: "Create GitHub repository",
|
|
320
|
+
run: () => {
|
|
321
|
+
void createGithubRepository({ projectName: projectState?.name || "my-project" });
|
|
322
|
+
},
|
|
323
|
+
},
|
|
324
|
+
],
|
|
325
|
+
message:
|
|
326
|
+
"This project is not tracked by git yet. Start tracking it to keep a history " +
|
|
327
|
+
"of every change and to publish it anywhere.",
|
|
328
|
+
})}
|
|
249
329
|
</div>`;
|
|
250
330
|
}
|
|
251
331
|
|
|
252
332
|
if (!_pollTimer) {
|
|
253
333
|
_pollTimer = setInterval(() => {
|
|
254
|
-
if (
|
|
334
|
+
if (shell.leftTab === "git" && !shell.git.loading) {
|
|
255
335
|
void refreshGitStatus();
|
|
256
336
|
}
|
|
257
|
-
},
|
|
337
|
+
}, POLL_GIT);
|
|
258
338
|
}
|
|
259
339
|
|
|
260
340
|
const stagedFiles = status?.files?.filter((f: GitFileEntry) => f.staged) || [];
|
|
@@ -262,12 +342,11 @@ export function renderGitPanel(
|
|
|
262
342
|
const totalChanges = status?.files?.length || 0;
|
|
263
343
|
|
|
264
344
|
const doCommit = async () => {
|
|
265
|
-
const
|
|
266
|
-
const msg = tab?.session.ui.gitCommitMessage?.trim();
|
|
345
|
+
const msg = shell.git.commitMessage.trim();
|
|
267
346
|
if (!msg) {
|
|
268
347
|
return;
|
|
269
348
|
}
|
|
270
|
-
|
|
349
|
+
shell.git.commitMessage = "";
|
|
271
350
|
// Fold co-editing sessions into the backend's tree first so the commit never misses
|
|
272
351
|
// Trailing keystrokes (the mirror is debounced).
|
|
273
352
|
await flushAllCollab();
|
|
@@ -275,14 +354,13 @@ export function renderGitPanel(
|
|
|
275
354
|
};
|
|
276
355
|
|
|
277
356
|
const doCommitAndSync = async () => {
|
|
278
|
-
const
|
|
279
|
-
const msg = tab?.session.ui.gitCommitMessage?.trim();
|
|
357
|
+
const msg = shell.git.commitMessage.trim();
|
|
280
358
|
if (!msg) {
|
|
281
359
|
return;
|
|
282
360
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
361
|
+
shell.git.commitMessage = "";
|
|
362
|
+
shell.git.loading = true;
|
|
363
|
+
shell.git.error = null;
|
|
286
364
|
await flushAllCollab();
|
|
287
365
|
const plat = getPlatform();
|
|
288
366
|
try {
|
|
@@ -290,9 +368,8 @@ export function renderGitPanel(
|
|
|
290
368
|
await plat.gitPush();
|
|
291
369
|
await refreshGitStatus();
|
|
292
370
|
} catch (error) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
renderOnly("leftPanel");
|
|
371
|
+
shell.git.error = errorMessage(error);
|
|
372
|
+
shell.git.loading = false;
|
|
296
373
|
}
|
|
297
374
|
};
|
|
298
375
|
|
|
@@ -301,8 +378,8 @@ export function renderGitPanel(
|
|
|
301
378
|
const syncLabel = isUpToDate
|
|
302
379
|
? "Up to date"
|
|
303
380
|
: `${status?.ahead ? `${status.ahead} ahead` : ""}${status?.ahead && status?.behind ? ", " : ""}${status?.behind ? `${status.behind} behind` : ""}`;
|
|
304
|
-
const lastUpdatedStr =
|
|
305
|
-
?
|
|
381
|
+
const lastUpdatedStr = shell.git.lastUpdated
|
|
382
|
+
? new Date(shell.git.lastUpdated).toLocaleTimeString([], {
|
|
306
383
|
hour: "2-digit",
|
|
307
384
|
minute: "2-digit",
|
|
308
385
|
})
|
|
@@ -341,7 +418,9 @@ export function renderGitPanel(
|
|
|
341
418
|
</sp-action-button>
|
|
342
419
|
<sp-action-button
|
|
343
420
|
title="Pull${status?.behind ? ` (${status.behind} behind)` : ""}"
|
|
344
|
-
@click=${() =>
|
|
421
|
+
@click=${() => {
|
|
422
|
+
void doPull();
|
|
423
|
+
}}
|
|
345
424
|
?disabled=${loading}
|
|
346
425
|
>
|
|
347
426
|
<sp-icon-arrow-down slot="icon" size="xs"></sp-icon-arrow-down>
|
|
@@ -374,13 +453,13 @@ export function renderGitPanel(
|
|
|
374
453
|
<sp-action-button
|
|
375
454
|
size="s"
|
|
376
455
|
@click=${() =>
|
|
377
|
-
|
|
456
|
+
createGithubRepository({
|
|
378
457
|
projectName: projectState?.name || "my-project",
|
|
379
458
|
})}
|
|
380
459
|
?disabled=${loading}
|
|
381
460
|
>
|
|
382
461
|
<sp-icon-share slot="icon"></sp-icon-share>
|
|
383
|
-
|
|
462
|
+
Create GitHub repository
|
|
384
463
|
</sp-action-button>
|
|
385
464
|
</div>
|
|
386
465
|
`;
|
|
@@ -445,23 +524,22 @@ export function renderGitPanel(
|
|
|
445
524
|
|
|
446
525
|
// ─── 3. Tabs: Local Changes / History ────────────────────────────────────
|
|
447
526
|
const switchTab = (tab: string) => {
|
|
448
|
-
|
|
449
|
-
if (tab === "history" && !
|
|
527
|
+
shell.git.subTab = tab;
|
|
528
|
+
if (tab === "history" && !shell.git.logEntries) {
|
|
450
529
|
void fetchGitLog();
|
|
451
530
|
}
|
|
452
|
-
renderOnly("leftPanel");
|
|
453
531
|
};
|
|
454
532
|
|
|
455
533
|
const tabsT = html`
|
|
456
534
|
<div class="git-tabs">
|
|
457
535
|
<button
|
|
458
|
-
class="git-tab ${
|
|
536
|
+
class="git-tab ${shell.git.subTab === "changes" ? "active" : ""}"
|
|
459
537
|
@click=${() => switchTab("changes")}
|
|
460
538
|
>
|
|
461
539
|
Local Changes${totalChanges > 0 ? ` (${totalChanges})` : ""}
|
|
462
540
|
</button>
|
|
463
541
|
<button
|
|
464
|
-
class="git-tab ${
|
|
542
|
+
class="git-tab ${shell.git.subTab === "history" ? "active" : ""}"
|
|
465
543
|
@click=${() => switchTab("history")}
|
|
466
544
|
>
|
|
467
545
|
History
|
|
@@ -470,16 +548,21 @@ export function renderGitPanel(
|
|
|
470
548
|
`;
|
|
471
549
|
|
|
472
550
|
// ─── 4. Commit form ──────────────────────────────────────────────────────
|
|
551
|
+
// `navigator/panel:git/commit` is a HAND-STAMPED leaf: the panel host derives
|
|
552
|
+
// `navigator/panel:git`, but nothing derives the parts inside a panel body. Leaves are the one
|
|
553
|
+
// Category of region id that is authored, and they are counted for exactly that reason.
|
|
473
554
|
const commitT = html`
|
|
474
|
-
<div class="git-commit-area">
|
|
555
|
+
<div class="git-commit-area" data-jx-region="navigator/panel:git/commit">
|
|
475
556
|
<label class="git-commit-label">Please write a commit message</label>
|
|
476
557
|
<sp-textfield
|
|
477
558
|
size="s"
|
|
478
559
|
multiline
|
|
479
560
|
class="git-commit-input"
|
|
480
561
|
placeholder="Describe your changes"
|
|
481
|
-
.value=${live(
|
|
482
|
-
@input=${(e: Event) =>
|
|
562
|
+
.value=${live(shell.git.commitMessage)}
|
|
563
|
+
@input=${(e: Event) => {
|
|
564
|
+
shell.git.commitMessage = (e.target as HTMLInputElement).value;
|
|
565
|
+
}}
|
|
483
566
|
@keydown=${(e: KeyboardEvent) => {
|
|
484
567
|
if ((e.ctrlKey || e.metaKey) && e.key === "Enter") {
|
|
485
568
|
e.preventDefault();
|
|
@@ -545,35 +628,22 @@ export function renderGitPanel(
|
|
|
545
628
|
}
|
|
546
629
|
|
|
547
630
|
try {
|
|
548
|
-
|
|
549
|
-
updateUi("gitLoading", true);
|
|
631
|
+
shell.git.loading = true;
|
|
550
632
|
|
|
551
|
-
const
|
|
552
|
-
file.status === "A"
|
|
553
|
-
? Promise.resolve("")
|
|
554
|
-
: plat.gitShow({ path: file.path, ref: "HEAD" }),
|
|
555
|
-
plat.readFile(file.path),
|
|
556
|
-
]);
|
|
633
|
+
const diffState = await readGitDiff(file.path, file.status);
|
|
557
634
|
|
|
558
|
-
|
|
559
|
-
currentContent,
|
|
560
|
-
filePath: file.path,
|
|
561
|
-
fileStatus: file.status,
|
|
562
|
-
originalContent,
|
|
563
|
-
};
|
|
564
|
-
|
|
565
|
-
updateUi("gitDiffState", diffState);
|
|
635
|
+
shell.git.diffState = diffState;
|
|
566
636
|
|
|
567
637
|
if (ctx?.setCanvasMode) {
|
|
568
638
|
if (ctx.setGitDiffState) {
|
|
569
639
|
ctx.setGitDiffState(diffState);
|
|
570
640
|
}
|
|
571
|
-
ctx.setCanvasMode("git-diff");
|
|
641
|
+
ctx.setCanvasMode(activeTab.value, "git-diff");
|
|
572
642
|
}
|
|
573
643
|
} catch (error) {
|
|
574
|
-
|
|
644
|
+
shell.git.error = `Failed to load diff: ${errorMessage(error)}`;
|
|
575
645
|
} finally {
|
|
576
|
-
|
|
646
|
+
shell.git.loading = false;
|
|
577
647
|
}
|
|
578
648
|
};
|
|
579
649
|
|
|
@@ -733,18 +803,24 @@ export function renderGitPanel(
|
|
|
733
803
|
`,
|
|
734
804
|
)}
|
|
735
805
|
`
|
|
736
|
-
:
|
|
806
|
+
: renderEmptyState({
|
|
807
|
+
compact: true,
|
|
808
|
+
message: "Nothing to commit. Files you edit and save show up here.",
|
|
809
|
+
})
|
|
737
810
|
}
|
|
738
811
|
</div>
|
|
739
812
|
`;
|
|
740
813
|
|
|
741
814
|
// ─── 6. History tab content ──────────────────────────────────────────────
|
|
742
|
-
const logEntries =
|
|
815
|
+
const logEntries = shell.git.logEntries || [];
|
|
743
816
|
const historyT = html`
|
|
744
817
|
<div class="git-history">
|
|
745
818
|
${
|
|
746
819
|
logEntries.length === 0
|
|
747
|
-
?
|
|
820
|
+
? renderEmptyState({
|
|
821
|
+
compact: true,
|
|
822
|
+
message: "No commits yet. Each commit you make is a version you can come back to.",
|
|
823
|
+
})
|
|
748
824
|
: repeat(
|
|
749
825
|
logEntries,
|
|
750
826
|
(e: GitLogEntry) => e.hash,
|
|
@@ -753,7 +829,7 @@ export function renderGitPanel(
|
|
|
753
829
|
<span class="git-history-hash">${entry.hash.slice(0, 7)}</span>
|
|
754
830
|
<span class="git-history-message">${entry.message}</span>
|
|
755
831
|
<span class="git-history-meta"
|
|
756
|
-
>${entry.author} · ${
|
|
832
|
+
>${entry.author} · ${relativeDate(entry.date)}</span
|
|
757
833
|
>
|
|
758
834
|
</div>
|
|
759
835
|
`,
|
|
@@ -765,18 +841,25 @@ export function renderGitPanel(
|
|
|
765
841
|
return html`
|
|
766
842
|
<div class="git-panel">
|
|
767
843
|
${syncBarT} ${branchSelectorT} ${tabsT}
|
|
768
|
-
${
|
|
844
|
+
${shell.git.subTab === "changes" ? html`${commitT}${changesT}` : historyT}
|
|
769
845
|
${loading ? html`<div class="git-loading">Loading...</div>` : nothing}
|
|
770
|
-
${
|
|
846
|
+
${shell.git.error ? html`<div class="git-error">${shell.git.error}</div>` : nothing}
|
|
771
847
|
</div>
|
|
772
848
|
`;
|
|
773
849
|
}
|
|
774
850
|
|
|
775
|
-
/**
|
|
776
|
-
|
|
851
|
+
/**
|
|
852
|
+
* A commit age, relative to {@link now}.
|
|
853
|
+
*
|
|
854
|
+
* Exported so it is testable at all: reading the wall clock inline meant "yesterday" and the
|
|
855
|
+
* locale-date fallback could only be asserted against an offset from the real present, and two
|
|
856
|
+
* captures minutes apart legitimately disagreed.
|
|
857
|
+
*
|
|
858
|
+
* @param {string} iso
|
|
859
|
+
*/
|
|
860
|
+
export function relativeDate(iso: string) {
|
|
777
861
|
const d = new Date(iso);
|
|
778
|
-
const
|
|
779
|
-
const diff = now - d.getTime();
|
|
862
|
+
const diff = now() - d.getTime();
|
|
780
863
|
const mins = Math.floor(diff / 60_000);
|
|
781
864
|
if (mins < 1) {
|
|
782
865
|
return "just now";
|
|
@@ -795,9 +878,137 @@ function _relativeDate(iso: string) {
|
|
|
795
878
|
return d.toLocaleDateString();
|
|
796
879
|
}
|
|
797
880
|
|
|
881
|
+
/**
|
|
882
|
+
* The `Source Control:` family — the four verbs that were only ever buttons.
|
|
883
|
+
*
|
|
884
|
+
* Every one of them was reachable from exactly one place: two from an empty state that disappears
|
|
885
|
+
* the moment the repository exists, one from a 20px icon with a `title` attribute, and the fourth —
|
|
886
|
+
* signing in to GitHub — from nowhere at all, because it only ever happened as a side effect of
|
|
887
|
+
* something else. That is why a failed sign-in had no Retry to name: there was no record to point
|
|
888
|
+
* at. Naming them here gives the palette, `__jxAutomation`, the assistant, the deploy checklist and
|
|
889
|
+
* every `notify` Retry the same four ids.
|
|
890
|
+
*
|
|
891
|
+
* `git.signInToGithub` is `application`-level and the other three are `project`-level, and the
|
|
892
|
+
* split is the credential's: a GitHub token is one per machine and is revoked in Preferences ›
|
|
893
|
+
* Accounts, while a branch, a remote and a push belong to one repository.
|
|
894
|
+
*/
|
|
895
|
+
export function sourceControlCommands(): AnyCommand[] {
|
|
896
|
+
return [
|
|
897
|
+
{
|
|
898
|
+
category: "Source Control",
|
|
899
|
+
id: "git.init",
|
|
900
|
+
level: "project",
|
|
901
|
+
menus: ["commandbar/overflow", "palette"],
|
|
902
|
+
group: "7_scm",
|
|
903
|
+
requires: "an open project that git is not already tracking",
|
|
904
|
+
when: (ctx) => ctx.project.open,
|
|
905
|
+
// `when` already asked about the project; an `enablement` that re-asks is the same rule
|
|
906
|
+
// Written twice, and the two places drift.
|
|
907
|
+
enablement: (ctx) => !ctx.project.isRepo,
|
|
908
|
+
aiTool: {
|
|
909
|
+
description:
|
|
910
|
+
"Run git init in the project root so the project has a history and can be pushed.",
|
|
911
|
+
name: "init_repository",
|
|
912
|
+
},
|
|
913
|
+
run: async () => {
|
|
914
|
+
await initRepository();
|
|
915
|
+
},
|
|
916
|
+
title: "Initialize Repository",
|
|
917
|
+
},
|
|
918
|
+
{
|
|
919
|
+
category: "Source Control",
|
|
920
|
+
id: "git.createGithubRepository",
|
|
921
|
+
level: "project",
|
|
922
|
+
menus: ["commandbar/overflow", "palette"],
|
|
923
|
+
group: "7_scm",
|
|
924
|
+
/* THE STRICTEST OF THE THREE, because it is the one that leaves something behind on a
|
|
925
|
+
server. It declared no `enablement` at all while `git.push` — which does strictly less —
|
|
926
|
+
required a tracked repository, so on an untracked project Push was correctly disabled and
|
|
927
|
+
this was fully live from the palette, the overflow, the deploy checklist and the
|
|
928
|
+
`create_github_repository` AI tool. Its flow creates the repository on GitHub BEFORE it
|
|
929
|
+
touches the local one, so `gitAddRemote` then throws and it reports "The repository was
|
|
930
|
+
created, but the remote could not be added." The refused verb leaves nothing behind; the
|
|
931
|
+
unrefused one leaves an empty repository on the user's account. */
|
|
932
|
+
requires: "a project tracked by git",
|
|
933
|
+
when: (ctx) => ctx.project.open,
|
|
934
|
+
enablement: (ctx) => ctx.project.isRepo,
|
|
935
|
+
aiTool: {
|
|
936
|
+
description:
|
|
937
|
+
"Create a new GitHub repository for this project, add it as the origin remote, and push. " +
|
|
938
|
+
"This creates a repository; it does not deploy a site — that is publish.setUp.",
|
|
939
|
+
name: "create_github_repository",
|
|
940
|
+
},
|
|
941
|
+
run: async () => {
|
|
942
|
+
await createGithubRepository({ projectName: projectState?.name || "my-project" });
|
|
943
|
+
},
|
|
944
|
+
title: "Create GitHub Repository",
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
category: "Source Control",
|
|
948
|
+
id: "git.push",
|
|
949
|
+
level: "project",
|
|
950
|
+
menus: ["commandbar/overflow", "palette"],
|
|
951
|
+
group: "7_scm",
|
|
952
|
+
requires: "a project tracked by git",
|
|
953
|
+
when: (ctx) => ctx.project.open,
|
|
954
|
+
enablement: (ctx) => ctx.project.isRepo,
|
|
955
|
+
aiTool: {
|
|
956
|
+
description: "Push the current branch to its remote.",
|
|
957
|
+
name: "git_push",
|
|
958
|
+
},
|
|
959
|
+
run: async () => {
|
|
960
|
+
await pushCurrentBranch();
|
|
961
|
+
},
|
|
962
|
+
title: "Push",
|
|
963
|
+
},
|
|
964
|
+
{
|
|
965
|
+
category: "Source Control",
|
|
966
|
+
id: "git.signInToGithub",
|
|
967
|
+
level: "application",
|
|
968
|
+
menus: ["palette"],
|
|
969
|
+
group: "7_scm",
|
|
970
|
+
run: async () => {
|
|
971
|
+
await signInToGithub();
|
|
972
|
+
},
|
|
973
|
+
title: "Sign In to GitHub",
|
|
974
|
+
},
|
|
975
|
+
];
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
/** Register the `Source Control:` family. */
|
|
979
|
+
export function registerSourceControlCommands(registry: CommandRegistry): void {
|
|
980
|
+
registry.registerAll(sourceControlCommands());
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
/** Stop the background refresh. Called on unmount and whenever a different project is opened. */
|
|
798
984
|
export function cleanupGitPanel() {
|
|
799
985
|
if (_pollTimer) {
|
|
800
986
|
clearInterval(_pollTimer);
|
|
801
987
|
_pollTimer = null;
|
|
802
988
|
}
|
|
803
989
|
}
|
|
990
|
+
|
|
991
|
+
/**
|
|
992
|
+
* Contribute the Source Control panel.
|
|
993
|
+
*
|
|
994
|
+
* `level: "project"` — a branch, a working tree and a commit belong to the repository, not to
|
|
995
|
+
* whichever document happens to be focused. That is why the badge below reads `ctx.git.dirtyCount`
|
|
996
|
+
* (sourced from the hoisted `shell.git` record) and why this panel's render ignores `ctx.doc`
|
|
997
|
+
* entirely: the count used to come from `activeTab.session.ui.gitStatus`, so it vanished when the
|
|
998
|
+
* last tab closed and two tabs could disagree about the branch.
|
|
999
|
+
*/
|
|
1000
|
+
export function registerGitPanel(): void {
|
|
1001
|
+
registerPanel({
|
|
1002
|
+
id: "git",
|
|
1003
|
+
title: "Source Control",
|
|
1004
|
+
level: "project",
|
|
1005
|
+
dock: "navigator",
|
|
1006
|
+
// A KEY into `activity-bar.ts`'s `tabIcon()` map, not a tag: this one resolves to
|
|
1007
|
+
// `gitBranchIcon`, a hand-drawn inline SVG, because the workflow set has no Git family.
|
|
1008
|
+
icon: "sp-icon-git-branch",
|
|
1009
|
+
badge: (ctx) => ctx.git.dirtyCount || null,
|
|
1010
|
+
// Through `deps`, not the local binding: `studio.ts` owns the wiring (the clone action and the
|
|
1011
|
+
// Diff-state setter come from the bootstrap), and the Navigator has injected it all along.
|
|
1012
|
+
render: (ctx) => ctx.deps.renderGitPanel(ctx.deps),
|
|
1013
|
+
});
|
|
1014
|
+
}
|