@jxsuite/studio 2.2.2 → 2.4.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/data/css-meta.json +1487 -0
- package/data/elements-meta.json +370 -0
- package/data/html-meta.json +366 -0
- package/data/stylebook-meta.json +200 -0
- package/data/webdata.json +1621 -0
- package/dist/chunks/{Overlay.dev-ymy3et3y.js → Overlay.dev-d2ajy6sj.js} +7 -7
- package/dist/chunks/{content-source-r2n7v682.js → content-source-jrvn5vwy.js} +13 -12
- package/dist/chunks/{convert-to-repeater-cnpyvj74.js → convert-to-repeater-109dwcj7.js} +12 -11
- package/dist/chunks/{extension-sections-vpcm4jvx.js → extension-sections-2zjyty05.js} +17 -16
- package/dist/chunks/{files-zeg88k2d.js → files-jdbtammm.js} +18 -19
- package/dist/chunks/{format-host-taymsw55.js → format-host-kq6963gs.js} +2 -2
- package/dist/chunks/{git-panel-qp4rrwr9.js → git-panel-2stf3ahg.js} +12 -11
- package/dist/chunks/{layers-panel-kj93w2zg.js → layers-panel-a8wjsdjj.js} +15 -14
- package/dist/chunks/{monaco-setup-xy3bs05d.js → monaco-setup-a5wkmbgh.js} +6 -3
- package/dist/chunks/{publish-panel-6qz6kp41.js → publish-panel-2we6smjv.js} +6 -6
- package/dist/chunks/{quick-search-9wwa09hh.js → quick-search-hmpwdgys.js} +19 -18
- package/dist/chunks/right-panel-hn3y3j0j.js +38 -0
- package/dist/chunks/{sp-overlay.dev-h6kdx076.js → sp-overlay.dev-s18hymn9.js} +8 -8
- package/dist/chunks/sp-progress-circle.dev-0zxcyz3r.js +15 -0
- package/dist/chunks/sp-tooltip.dev-5c6d1kjz.js +15 -0
- package/dist/chunks/{studio-753znj4c.js → studio-0evba9z5.js} +5 -5
- package/dist/chunks/{studio-qhh8r5fz.js → studio-102jzb8r.js} +4 -4
- package/dist/chunks/{studio-22xr4q8q.js → studio-1dgqagzz.js} +18 -29
- package/dist/chunks/{studio-6f0am8f2.js → studio-2w11grav.js} +2 -2
- package/dist/chunks/{studio-pv8m0h4a.js → studio-377bbhtz.js} +28 -23
- package/dist/chunks/{studio-6zzbyx17.js → studio-53dn6e6t.js} +2 -2
- package/dist/chunks/studio-53n8bp04.js +16 -0
- package/dist/chunks/{studio-tqemhphj.js → studio-6gcrk1bq.js} +4 -4
- package/dist/chunks/{studio-3z8jjm2p.js → studio-7ejemhej.js} +3 -3
- package/dist/chunks/{studio-nqq8jk8f.js → studio-8x4399kc.js} +14 -14
- package/dist/chunks/{studio-rgwcpast.js → studio-ay8wcr2b.js} +2 -2
- package/dist/chunks/{studio-xmvbhg31.js → studio-c31yb4t6.js} +2 -2
- package/dist/chunks/{studio-5kt960pk.js → studio-ddgrc5hs.js} +133 -147
- package/dist/chunks/{studio-zqv3w24n.js → studio-eqyybj2e.js} +5 -5
- package/dist/chunks/{studio-p471gg5n.js → studio-kvfx9z2c.js} +7 -3
- package/dist/chunks/{studio-8sdyjfd6.js → studio-kwavhmdr.js} +2 -2
- package/dist/chunks/{studio-300zsz1k.js → studio-ky68mp85.js} +6 -6
- package/dist/chunks/{studio-x0et2z9g.js → studio-ng5gbxkj.js} +15 -15
- package/dist/chunks/{studio-hekaagev.js → studio-q07vj7p9.js} +17 -17
- package/dist/chunks/{studio-fys6z73y.js → studio-qd4k0h80.js} +7 -7
- package/dist/chunks/{studio-yphy4z9m.js → studio-rdsvb808.js} +5 -5
- package/dist/chunks/{studio-g8t7g0gp.js → studio-tqr02xaa.js} +3 -3
- package/dist/chunks/{studio-ckwz4d3x.js → studio-twsafr1e.js} +2 -2
- package/dist/chunks/{studio-qrsfh1w7.js → studio-tzx3xmvx.js} +5 -5
- package/dist/chunks/{studio-6a0h7sne.js → studio-vhk5fmfv.js} +2 -2
- package/dist/chunks/{studio-hrajjyt2.js → studio-wdt9y92a.js} +2 -2
- package/dist/chunks/{studio-r8vx7bkz.js → studio-wxthr2x1.js} +14 -13
- package/dist/chunks/{studio-yz9s88s0.js → studio-yk7037sg.js} +40 -14
- package/dist/chunks/{studio-1kgfcv7s.js → studio-yz06mkfj.js} +12 -11
- package/dist/codicon.ttf +0 -0
- package/dist/iframe-entry.js +14 -3
- package/dist/manifest.json +82 -0
- package/dist/studio.js +247 -106
- package/index.html +0 -50
- package/package.json +16 -9
- package/src/canvas/canvas-live-render.ts +2 -4
- package/src/canvas/canvas-origin.ts +25 -0
- package/src/canvas/iframe-entry.ts +5 -0
- package/src/canvas/iframe-host.ts +45 -4
- package/src/content/entry-editor.ts +2 -1
- package/src/editor/context-menu.ts +13 -2
- package/src/editor/slash-menu.ts +26 -11
- package/src/files/files.ts +11 -23
- package/src/grid/grid-panel.ts +27 -6
- package/src/hosting/document.ts +109 -0
- package/src/hosting/layout.ts +211 -0
- package/src/hosting/stage.ts +166 -0
- package/src/hosting/tsconfig.json +18 -0
- package/src/panels/ai-chat/chat-view.ts +25 -14
- package/src/panels/git-panel.ts +17 -14
- package/src/panels/head-panel.ts +32 -14
- package/src/panels/imports-panel.ts +32 -13
- package/src/panels/layers-panel.ts +9 -1
- package/src/panels/panel-registry.ts +0 -1
- package/src/panels/properties-panel.ts +3 -3
- package/src/panels/settings-pane.ts +1 -1
- package/src/panels/style-panel.ts +3 -3
- package/src/panels/stylebook-panel.ts +10 -1
- package/src/panels/toolbar.ts +1 -1
- package/src/platforms/cloud.ts +9 -0
- package/src/services/ai-models.ts +14 -1
- package/src/services/bundle-base.ts +69 -0
- package/src/services/monaco-setup.ts +19 -13
- package/src/shell/tree.ts +155 -0
- package/src/shell.ts +0 -2
- package/src/studio.ts +22 -2
- package/src/types.ts +32 -0
- package/src/ui/ai-managed-connect.ts +18 -3
- package/src/ui/regions.ts +10 -45
- package/styles/overlays.css +35 -0
- package/styles/shell.css +7 -0
- package/dist/chunks/2020-xp8vnwma.js.map +0 -24
- package/dist/chunks/Overlay.dev-ymy3et3y.js.map +0 -9
- package/dist/chunks/adapter-jkcyhgtr.js.map +0 -9
- package/dist/chunks/cf-settings-g5fbf2zp.js.map +0 -9
- package/dist/chunks/components-z6cnkyy1.js.map +0 -9
- package/dist/chunks/content-source-r2n7v682.js.map +0 -9
- package/dist/chunks/convert-to-repeater-cnpyvj74.js.map +0 -10
- package/dist/chunks/editor-cptq5jp1.js.map +0 -9
- package/dist/chunks/extension-sections-vpcm4jvx.js.map +0 -11
- package/dist/chunks/files-zeg88k2d.js.map +0 -9
- package/dist/chunks/flow-qbfgrpeh.js.map +0 -12
- package/dist/chunks/focus-trap.esm-ggawf1hy.js.map +0 -11
- package/dist/chunks/focus-visible-6eg70z18.js.map +0 -10
- package/dist/chunks/format-host-taymsw55.js.map +0 -9
- package/dist/chunks/git-panel-qp4rrwr9.js.map +0 -9
- package/dist/chunks/index-nj44jpzj.js.map +0 -14
- package/dist/chunks/index-zqxmqxmh.js.map +0 -9
- package/dist/chunks/javascript-q8kpmfah.js.map +0 -11
- package/dist/chunks/jsonMode-dkr040ga.js.map +0 -18
- package/dist/chunks/jx-validate-jj9rnt4n.js.map +0 -9
- package/dist/chunks/layers-panel-kj93w2zg.js.map +0 -9
- package/dist/chunks/monaco-binding-rj6xpx9y.js.map +0 -10
- package/dist/chunks/monaco-setup-xy3bs05d.js.map +0 -15
- package/dist/chunks/publish-panel-6qz6kp41.js.map +0 -9
- package/dist/chunks/quick-search-9wwa09hh.js.map +0 -9
- package/dist/chunks/right-panel-faf816ch.js +0 -37
- package/dist/chunks/right-panel-faf816ch.js.map +0 -9
- package/dist/chunks/section-registry-sx1ykvkw.js.map +0 -9
- package/dist/chunks/sp-overlay.dev-h6kdx076.js.map +0 -9
- package/dist/chunks/sp-popover.dev-dj9x7e7a.js.map +0 -9
- package/dist/chunks/sp-progress-circle.dev-0fpvhm52.js +0 -15
- package/dist/chunks/sp-progress-circle.dev-0fpvhm52.js.map +0 -9
- package/dist/chunks/sp-tooltip.dev-rvepkw4r.js +0 -15
- package/dist/chunks/sp-tooltip.dev-rvepkw4r.js.map +0 -9
- package/dist/chunks/sp-tray.dev-64v4pxw8.js.map +0 -12
- package/dist/chunks/studio-0a5qrh01.js.map +0 -9
- package/dist/chunks/studio-0rqqhrdy.js.map +0 -12
- package/dist/chunks/studio-18j3bmcz.js.map +0 -10
- package/dist/chunks/studio-1kgfcv7s.js.map +0 -13
- package/dist/chunks/studio-22xr4q8q.js.map +0 -13
- package/dist/chunks/studio-300zsz1k.js.map +0 -39
- package/dist/chunks/studio-3fk1ac9z.js.map +0 -12
- package/dist/chunks/studio-3n4ndrzh.js.map +0 -41
- package/dist/chunks/studio-3z8jjm2p.js.map +0 -13
- package/dist/chunks/studio-4mqb9a0j.js.map +0 -14
- package/dist/chunks/studio-4q0wznzf.js.map +0 -73
- package/dist/chunks/studio-5ehhackm.js.map +0 -10
- package/dist/chunks/studio-5kt960pk.js.map +0 -38
- package/dist/chunks/studio-5x5774ak.js.map +0 -10
- package/dist/chunks/studio-685s0ytq.js.map +0 -76
- package/dist/chunks/studio-6a0h7sne.js.map +0 -15
- package/dist/chunks/studio-6f0am8f2.js.map +0 -10
- package/dist/chunks/studio-6kv3apa9.js.map +0 -10
- package/dist/chunks/studio-6zzbyx17.js.map +0 -12
- package/dist/chunks/studio-753znj4c.js.map +0 -16
- package/dist/chunks/studio-7afd21nw.js.map +0 -10
- package/dist/chunks/studio-8jpzqk5s.js.map +0 -10
- package/dist/chunks/studio-8q517dfr.js.map +0 -10
- package/dist/chunks/studio-8sdyjfd6.js.map +0 -10
- package/dist/chunks/studio-a0tswy0w.js.map +0 -9
- package/dist/chunks/studio-a7pzveq1.js.map +0 -11
- package/dist/chunks/studio-ahnzd9rg.js.map +0 -10
- package/dist/chunks/studio-b9b6t1dg.js.map +0 -651
- package/dist/chunks/studio-bw5dz6km.js.map +0 -21
- package/dist/chunks/studio-cjm7fdjf.js.map +0 -14
- package/dist/chunks/studio-ckwz4d3x.js.map +0 -12
- package/dist/chunks/studio-d1ks410h.js.map +0 -10
- package/dist/chunks/studio-dg7zyt5x.js.map +0 -10
- package/dist/chunks/studio-fys6z73y.js.map +0 -10
- package/dist/chunks/studio-g1wdche0.js.map +0 -56
- package/dist/chunks/studio-g8t7g0gp.js.map +0 -10
- package/dist/chunks/studio-h4rxscfc.js.map +0 -10
- package/dist/chunks/studio-hekaagev.js.map +0 -18
- package/dist/chunks/studio-hrajjyt2.js.map +0 -10
- package/dist/chunks/studio-nqq8jk8f.js.map +0 -14
- package/dist/chunks/studio-p471gg5n.js.map +0 -14
- package/dist/chunks/studio-pv8m0h4a.js.map +0 -98
- package/dist/chunks/studio-qhh8r5fz.js.map +0 -13
- package/dist/chunks/studio-qrsfh1w7.js.map +0 -41
- package/dist/chunks/studio-r8vx7bkz.js.map +0 -235
- package/dist/chunks/studio-rgwcpast.js.map +0 -12
- package/dist/chunks/studio-s519zc99.js.map +0 -10
- package/dist/chunks/studio-sas7mt3k.js.map +0 -10
- package/dist/chunks/studio-t5wqwzdh.js.map +0 -10
- package/dist/chunks/studio-tqemhphj.js.map +0 -11
- package/dist/chunks/studio-tr20m8g8.js.map +0 -9
- package/dist/chunks/studio-tvgyw9xw.js.map +0 -14
- package/dist/chunks/studio-x0et2z9g.js.map +0 -32
- package/dist/chunks/studio-xm3dbxvn.js.map +0 -19
- package/dist/chunks/studio-xmvbhg31.js.map +0 -10
- package/dist/chunks/studio-ynxwkrzd.js.map +0 -246
- package/dist/chunks/studio-yphy4z9m.js.map +0 -10
- package/dist/chunks/studio-yz9s88s0.js.map +0 -54
- package/dist/chunks/studio-z6nw2ek2.js.map +0 -10
- package/dist/chunks/studio-zqv3w24n.js.map +0 -11
- package/dist/chunks/tsMode-76kr53q0.js.map +0 -13
- package/dist/chunks/ws-client-6shc5rze.js.map +0 -12
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../node_modules/@spectrum-web-components/progress-circle/src/progress-circle.css.js", "../../../node_modules/@spectrum-web-components/reactive-controllers/src/LanguageResolution.dev.js", "../../../node_modules/@spectrum-web-components/progress-circle/src/ProgressCircle.types.dev.js", "../../../node_modules/@spectrum-web-components/progress-circle/src/ProgressCircle.base.dev.js", "../../../node_modules/@spectrum-web-components/progress-circle/src/ProgressCircle.dev.js", "../../../node_modules/@spectrum-web-components/progress-circle/sp-progress-circle.dev.js"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"\"use strict\";import{css as r}from\"@spectrum-web-components/base\";const e=r`\n @media (forced-colors:active){:host{--highcontrast-progress-circle-fill-border-color:Highlight;--highcontrast-progress-circle-fill-border-color-over-background:Highlight}.track{--spectrum-progress-circle-track-border-style:double}}:host{--spectrum-progress-circle-track-border-color:var(--spectrum-gray-300);--spectrum-progress-circle-fill-border-color:var(--spectrum-accent-content-color-default);--spectrum-progress-circle-track-border-color-over-background:var(--spectrum-transparent-white-300);--spectrum-progress-circle-fill-border-color-over-background:var(--spectrum-transparent-white-900);--spectrum-progress-circle-track-border-style:solid;position:var(--mod-progress-circle-position,relative);inline-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));block-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));direction:ltr;display:inline-block;position:relative;transform:translateZ(0)}:host([size=s]){--spectrum-progress-circle-size:var(--spectrum-progress-circle-size-small);--spectrum-progress-circle-thickness:var(--spectrum-progress-circle-thickness-small)}:host{--spectrum-progress-circle-size:var(--spectrum-progress-circle-size-medium);--spectrum-progress-circle-thickness:var(--spectrum-progress-circle-thickness-medium)}:host([size=l]){--spectrum-progress-circle-size:var(--spectrum-progress-circle-size-large);--spectrum-progress-circle-thickness:var(--spectrum-progress-circle-thickness-large)}.track{box-sizing:border-box;inline-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));block-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));border-color:var(--mod-progress-circle-track-border-color,var(--spectrum-progress-circle-track-border-color));border-style:var(--mod-progress-circle-track-border-style,var(--spectrum-progress-circle-track-border-style));border-width:var(--mod-progress-circle-thickness,var(--spectrum-progress-circle-thickness));border-radius:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size))}.fills{block-size:100%;inline-size:100%;position:absolute;inset-block-start:0;inset-inline-start:0}.fill{box-sizing:border-box;inline-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));block-size:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size));border-color:var(--highcontrast-progress-circle-fill-border-color,var(--mod-progress-circle-fill-border-color,var(--spectrum-progress-circle-fill-border-color)));border-style:solid;border-width:var(--mod-progress-circle-thickness,var(--spectrum-progress-circle-thickness));border-radius:var(--mod-progress-circle-size,var(--spectrum-progress-circle-size))}:host([static-color=white]) .track{border-color:var(--mod-progress-circle-track-border-color-over-background,var(--spectrum-progress-circle-track-border-color-over-background))}:host([static-color=white]) .fill{border-color:var(--highcontrast-progress-circle-fill-border-color-over-background,var(--mod-progress-circle-fill-border-color-over-background,var(--spectrum-progress-circle-fill-border-color-over-background)))}.fillMask1,.fillMask2{transform-origin:100%;block-size:100%;inline-size:50%;position:absolute;overflow:hidden;transform:rotate(180deg)}.fillSubMask1,.fillSubMask2{transform-origin:100%;block-size:100%;inline-size:100%;overflow:hidden;transform:rotate(-180deg)}.fillMask2{transform:rotate(0)}:host([indeterminate]) .fills{transform-origin:50%;will-change:transform;animation:1s cubic-bezier(.25,.78,.48,.89) infinite spectrum-fills-rotate;transform:translateZ(0)}:host([indeterminate]) .fillSubMask1{will-change:transform;animation:1s linear infinite spectrum-fill-mask-1;transform:translateZ(0)}:host([indeterminate]) .fillSubMask2{will-change:transform;animation:1s linear infinite spectrum-fill-mask-2;transform:translateZ(0)}.fill-submask-2{animation:1s linear infinite spectrum-fill-mask-2}@keyframes spectrum-fill-mask-1{0%{transform:rotate(90deg)}1.69%{transform:rotate(72.3deg)}3.39%{transform:rotate(55.5deg)}5.08%{transform:rotate(40.3deg)}6.78%{transform:rotate(25deg)}8.47%{transform:rotate(10.6deg)}10.17%{transform:rotate(0)}11.86%{transform:rotate(0)}13.56%{transform:rotate(0)}15.25%{transform:rotate(0)}16.95%{transform:rotate(0)}18.64%{transform:rotate(0)}20.34%{transform:rotate(0)}22.03%{transform:rotate(0)}23.73%{transform:rotate(0)}25.42%{transform:rotate(0)}27.12%{transform:rotate(0)}28.81%{transform:rotate(0)}30.51%{transform:rotate(0)}32.2%{transform:rotate(0)}33.9%{transform:rotate(0)}35.59%{transform:rotate(0)}37.29%{transform:rotate(0)}38.98%{transform:rotate(0)}40.68%{transform:rotate(0)}42.37%{transform:rotate(5.3deg)}44.07%{transform:rotate(13.4deg)}45.76%{transform:rotate(20.6deg)}47.46%{transform:rotate(29deg)}49.15%{transform:rotate(36.5deg)}50.85%{transform:rotate(42.6deg)}52.54%{transform:rotate(48.8deg)}54.24%{transform:rotate(54.2deg)}55.93%{transform:rotate(59.4deg)}57.63%{transform:rotate(63.2deg)}59.32%{transform:rotate(67.2deg)}61.02%{transform:rotate(70.8deg)}62.71%{transform:rotate(73.8deg)}64.41%{transform:rotate(76.2deg)}66.1%{transform:rotate(78.7deg)}67.8%{transform:rotate(80.6deg)}69.49%{transform:rotate(82.6deg)}71.19%{transform:rotate(83.7deg)}72.88%{transform:rotate(85deg)}74.58%{transform:rotate(86.3deg)}76.27%{transform:rotate(87deg)}77.97%{transform:rotate(87.7deg)}79.66%{transform:rotate(88.3deg)}81.36%{transform:rotate(88.6deg)}83.05%{transform:rotate(89.2deg)}84.75%{transform:rotate(89.2deg)}86.44%{transform:rotate(89.5deg)}88.14%{transform:rotate(89.9deg)}89.83%{transform:rotate(89.7deg)}91.53%{transform:rotate(90.1deg)}93.22%{transform:rotate(90.2deg)}94.92%{transform:rotate(90.1deg)}96.61%{transform:rotate(90deg)}98.31%{transform:rotate(89.8deg)}to{transform:rotate(90deg)}}@keyframes spectrum-fill-mask-2{0%{transform:rotate(180deg)}1.69%{transform:rotate(180deg)}3.39%{transform:rotate(180deg)}5.08%{transform:rotate(180deg)}6.78%{transform:rotate(180deg)}8.47%{transform:rotate(180deg)}10.17%{transform:rotate(179.2deg)}11.86%{transform:rotate(164deg)}13.56%{transform:rotate(151.8deg)}15.25%{transform:rotate(140.8deg)}16.95%{transform:rotate(130.3deg)}18.64%{transform:rotate(120.4deg)}20.34%{transform:rotate(110.8deg)}22.03%{transform:rotate(101.6deg)}23.73%{transform:rotate(93.5deg)}25.42%{transform:rotate(85.4deg)}27.12%{transform:rotate(78.1deg)}28.81%{transform:rotate(71.2deg)}30.51%{transform:rotate(89.1deg)}32.2%{transform:rotate(105.5deg)}33.9%{transform:rotate(121.3deg)}35.59%{transform:rotate(135.5deg)}37.29%{transform:rotate(148.4deg)}38.98%{transform:rotate(161deg)}40.68%{transform:rotate(173.5deg)}42.37%{transform:rotate(180deg)}44.07%{transform:rotate(180deg)}45.76%{transform:rotate(180deg)}47.46%{transform:rotate(180deg)}49.15%{transform:rotate(180deg)}50.85%{transform:rotate(180deg)}52.54%{transform:rotate(180deg)}54.24%{transform:rotate(180deg)}55.93%{transform:rotate(180deg)}57.63%{transform:rotate(180deg)}59.32%{transform:rotate(180deg)}61.02%{transform:rotate(180deg)}62.71%{transform:rotate(180deg)}64.41%{transform:rotate(180deg)}66.1%{transform:rotate(180deg)}67.8%{transform:rotate(180deg)}69.49%{transform:rotate(180deg)}71.19%{transform:rotate(180deg)}72.88%{transform:rotate(180deg)}74.58%{transform:rotate(180deg)}76.27%{transform:rotate(180deg)}77.97%{transform:rotate(180deg)}79.66%{transform:rotate(180deg)}81.36%{transform:rotate(180deg)}83.05%{transform:rotate(180deg)}84.75%{transform:rotate(180deg)}86.44%{transform:rotate(180deg)}88.14%{transform:rotate(180deg)}89.83%{transform:rotate(180deg)}91.53%{transform:rotate(180deg)}93.22%{transform:rotate(180deg)}94.92%{transform:rotate(180deg)}96.61%{transform:rotate(180deg)}98.31%{transform:rotate(180deg)}to{transform:rotate(180deg)}}@keyframes spectrum-fills-rotate{0%{transform:rotate(-90deg)}to{transform:rotate(270deg)}}:host{--spectrum-progress-circle-track-border-color:var(--system-progress-circle-track-border-color);--spectrum-progress-circle-track-border-color-over-background:var(--system-progress-circle-track-border-color-over-background);--spectrum-progress-circle-fill-border-color-over-background:var(--system-progress-circle-fill-border-color-over-background)}:host{inline-size:var(--mod-progress-circle-size,var(--_spectrum-progress-circle-size));block-size:var(--mod-progress-circle-size,var(--_spectrum-progress-circle-size));--spectrum-progress-circle-size:inherit;--spectrum-progresscircle-m-over-background-track-fill-color:var(--spectrum-alias-track-fill-color-overbackground);--_spectrum-progress-circle-size:var(--spectrum-progress-circle-size,var(--spectrum-progress-circle-size-medium))}:host([size=s]){--_spectrum-progress-circle-size:var(--spectrum-progress-circle-size,var(--spectrum-progress-circle-size-small))}:host([size=l]){--_spectrum-progress-circle-size:var(--spectrum-progress-circle-size,var(--spectrum-progress-circle-size-large))}slot{display:none}.track,.fill{inline-size:var(--mod-progress-circle-size,var(--_spectrum-progress-circle-size));block-size:var(--mod-progress-circle-size,var(--_spectrum-progress-circle-size));border-radius:var(--mod-progress-circle-size,var(--_spectrum-progress-circle-size))}:host([indeterminate]) .fills,:host([indeterminate]) .fillSubMask1,:host([indeterminate]) .fillSubMask2{animation-duration:var(--spectrum-animation-duration-2000)}\n`;export default e;\n//# sourceMappingURL=progress-circle.css.js.map\n",
|
|
6
|
-
"\"use strict\";\nexport const languageResolverUpdatedSymbol = Symbol(\n \"language resolver updated\"\n);\nconst listeners = /* @__PURE__ */ new Set();\nlet sharedObserver;\nfunction addLangListener(listener) {\n listeners.add(listener);\n if (!sharedObserver) {\n sharedObserver = new MutationObserver(() => {\n for (const cb of listeners) {\n cb();\n }\n });\n sharedObserver.observe(document.documentElement, {\n attributes: true,\n attributeFilter: [\"lang\"]\n });\n }\n return () => {\n listeners.delete(listener);\n if (listeners.size === 0) {\n sharedObserver == null ? void 0 : sharedObserver.disconnect();\n sharedObserver = void 0;\n }\n };\n}\nexport class LanguageResolutionController {\n constructor(host) {\n /**\n * The currently resolved language/locale code (e.g., 'en-US', 'fr-FR').\n * Defaults to document language, browser language, or 'en-US'.\n */\n this.language = this.getDocumentLanguage();\n this.host = host;\n this.host.addController(this);\n }\n /**\n * Reads language from document and validates. Used for initial value and\n * when syncing from `<html lang>` changes.\n */\n getDocumentLanguage() {\n const raw = document.documentElement.lang || navigator.language || \"en-US\";\n try {\n Intl.DateTimeFormat.supportedLocalesOf([raw]);\n return raw;\n } catch (e) {\n return \"en-US\";\n }\n }\n hostConnected() {\n this.resolveLanguage();\n this.removeLangListener = addLangListener(this.handleLangChange.bind(this));\n }\n hostDisconnected() {\n var _a, _b;\n (_a = this.unsubscribe) == null ? void 0 : _a.call(this);\n this.unsubscribe = void 0;\n (_b = this.removeLangListener) == null ? void 0 : _b.call(this);\n this.removeLangListener = void 0;\n }\n /**\n * Called by the shared observer when `<html lang>` changes.\n * Skipped when a provider (e.g. sp-theme) is the source of truth.\n */\n handleLangChange() {\n if (this.unsubscribe) {\n return;\n }\n const next = this.getDocumentLanguage();\n if (next === this.language) {\n return;\n }\n const previous = this.language;\n this.language = next;\n this.host.requestUpdate(languageResolverUpdatedSymbol, previous);\n }\n /**\n * Resolves the language: syncs from document, then queries for a provider\n * (e.g. sp-theme) via 'sp-language-context'. If a provider calls the\n * callback, it becomes the source of truth until disconnected.\n */\n resolveLanguage() {\n this.language = this.getDocumentLanguage();\n const queryThemeEvent = new CustomEvent(\n \"sp-language-context\",\n {\n bubbles: true,\n composed: true,\n detail: {\n callback: (lang, unsubscribe) => {\n const previous = this.language;\n this.language = lang;\n this.unsubscribe = unsubscribe;\n this.host.requestUpdate(languageResolverUpdatedSymbol, previous);\n }\n },\n cancelable: true\n }\n );\n this.host.dispatchEvent(queryThemeEvent);\n }\n}\n//# sourceMappingURL=LanguageResolution.dev.js.map\n",
|
|
7
|
-
"\"use strict\";\nexport const PROGRESS_CIRCLE_VALID_SIZES = [\n \"s\",\n \"m\",\n \"l\"\n];\nexport const PROGRESS_CIRCLE_STATIC_COLORS_S1 = [\"white\"];\nexport const PROGRESS_CIRCLE_STATIC_COLORS_S2 = [\n ...PROGRESS_CIRCLE_STATIC_COLORS_S1,\n \"black\"\n];\n//# sourceMappingURL=ProgressCircle.types.dev.js.map\n",
|
|
8
|
-
"\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __decorateClass = (decorators, target, key, kind) => {\n var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;\n for (var i = decorators.length - 1, decorator; i >= 0; i--)\n if (decorator = decorators[i])\n result = (kind ? decorator(target, key, result) : decorator(result)) || result;\n if (kind && result) __defProp(target, key, result);\n return result;\n};\nimport { SpectrumElement } from \"@spectrum-web-components/base\";\nimport {\n property,\n query\n} from \"@spectrum-web-components/base/src/decorators.js\";\nimport { SizedMixin } from \"@spectrum-web-components/base/src/sizedMixin.js\";\nimport {\n LanguageResolutionController,\n languageResolverUpdatedSymbol\n} from \"@spectrum-web-components/reactive-controllers/src/LanguageResolution.js\";\nimport { getLabelFromSlot } from \"@spectrum-web-components/shared/src/get-label-from-slot.js\";\nimport {\n PROGRESS_CIRCLE_VALID_SIZES\n} from \"./ProgressCircle.types.dev.js\";\nexport class ProgressCircleBase extends SizedMixin(SpectrumElement, {\n validSizes: PROGRESS_CIRCLE_VALID_SIZES\n}) {\n constructor() {\n super(...arguments);\n this.indeterminate = false;\n this.label = \"\";\n this.progress = 0;\n this.languageResolver = new LanguageResolutionController(this);\n }\n makeRotation(rotation) {\n return this.indeterminate ? void 0 : `transform: rotate(${rotation}deg);`;\n }\n handleSlotchange() {\n const labelFromSlot = getLabelFromSlot(this.label, this.slotEl);\n if (labelFromSlot) {\n this.label = labelFromSlot;\n }\n }\n firstUpdated(changes) {\n super.firstUpdated(changes);\n if (!this.hasAttribute(\"role\")) {\n this.setAttribute(\"role\", \"progressbar\");\n }\n }\n formatProgress() {\n return new Intl.NumberFormat(this.languageResolver.language, {\n style: \"percent\",\n unitDisplay: \"narrow\"\n }).format(this.progress / 100);\n }\n updated(changes) {\n var _a, _b, _c;\n super.updated(changes);\n if (changes.has(\"indeterminate\")) {\n if (this.indeterminate) {\n this.removeAttribute(\"aria-valuemin\");\n this.removeAttribute(\"aria-valuemax\");\n this.removeAttribute(\"aria-valuenow\");\n this.removeAttribute(\"aria-valuetext\");\n } else {\n this.setAttribute(\"aria-valuemin\", \"0\");\n this.setAttribute(\"aria-valuemax\", \"100\");\n this.setAttribute(\"aria-valuenow\", \"\" + this.progress);\n this.setAttribute(\"aria-valuetext\", this.formatProgress());\n }\n }\n if (!this.indeterminate && changes.has(\"progress\")) {\n this.setAttribute(\"aria-valuenow\", \"\" + this.progress);\n this.setAttribute(\"aria-valuetext\", this.formatProgress());\n }\n if (!this.indeterminate && changes.has(languageResolverUpdatedSymbol)) {\n this.setAttribute(\"aria-valuetext\", this.formatProgress());\n }\n if (changes.has(\"label\")) {\n if (this.label.length) {\n this.setAttribute(\"aria-label\", this.label);\n } else if (changes.get(\"label\") === this.getAttribute(\"aria-label\")) {\n this.removeAttribute(\"aria-label\");\n }\n }\n const hasAccessibleName = () => {\n return Boolean(\n this.label || this.getAttribute(\"aria-label\") || this.getAttribute(\"aria-labelledby\") || this.slotEl.assignedNodes().length\n );\n };\n if (true) {\n if (changes.has(\"indeterminate\") && this.indeterminate) {\n window.__swc.warn(\n this,\n `<${this.localName}> the \"indeterminate\" attribute is deprecated and will be removed in Spectrum 2. Omit the \"progress\" attribute (or set it to null) to indicate indeterminate progress.`,\n \"https://opensource.adobe.com/spectrum-web-components/second-gen/?path=/docs/progress-circle-consumer-migration-guide--docs\",\n { level: \"deprecation\" }\n );\n }\n const hasLightDomChildren = Array.from(\n (_b = (_a = this.slotEl) == null ? void 0 : _a.assignedNodes()) != null ? _b : []\n ).some(\n (node) => {\n var _a2;\n return node.nodeType === Node.ELEMENT_NODE || node.nodeType === Node.TEXT_NODE && ((_a2 = node.textContent) == null ? void 0 : _a2.trim());\n }\n );\n if (hasLightDomChildren) {\n window.__swc.warn(\n this,\n `<${this.localName}> light DOM children are deprecated as a labelling mechanism and will not be rendered in Spectrum 2. Use the \"label\" attribute or \"aria-label\" on the host instead.`,\n \"https://opensource.adobe.com/spectrum-web-components/second-gen/?path=/docs/progress-circle-consumer-migration-guide--docs\",\n { level: \"deprecation\" }\n );\n }\n if (!hasAccessibleName() && this.getAttribute(\"role\") === \"progressbar\") {\n (_c = window.__swc) == null ? void 0 : _c.warn(\n this,\n \"<sp-progress-circle> elements need one of the following to be accessible:\",\n \"https://opensource.adobe.com/spectrum-web-components/components/progress-circle/#accessibility\",\n {\n type: \"accessibility\",\n issues: [\n 'value supplied to the \"label\" attribute, which will be displayed visually as part of the element, or',\n \"text content supplied directly to the <sp-progress-circle> element, or\",\n 'value supplied to the \"aria-label\" attribute, which will only be provided to screen readers, or',\n 'an element ID reference supplied to the \"aria-labelledby\" attribute, which will be provided by screen readers and will need to be managed manually by the parent application.'\n ]\n }\n );\n }\n }\n }\n}\n__decorateClass([\n property({ type: String, reflect: true, attribute: \"static-color\" })\n], ProgressCircleBase.prototype, \"staticColor\", 2);\n__decorateClass([\n property({ type: Boolean, reflect: true })\n], ProgressCircleBase.prototype, \"indeterminate\", 2);\n__decorateClass([\n property({ type: String })\n], ProgressCircleBase.prototype, \"label\", 2);\n__decorateClass([\n property({ type: Number })\n], ProgressCircleBase.prototype, \"progress\", 2);\n__decorateClass([\n query(\"slot\")\n], ProgressCircleBase.prototype, \"slotEl\", 2);\n//# sourceMappingURL=ProgressCircle.base.dev.js.map\n",
|
|
9
|
-
"\"use strict\";\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __decorateClass = (decorators, target, key, kind) => {\n var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;\n for (var i = decorators.length - 1, decorator; i >= 0; i--)\n if (decorator = decorators[i])\n result = (kind ? decorator(target, key, result) : decorator(result)) || result;\n if (kind && result) __defProp(target, key, result);\n return result;\n};\nimport {\n html\n} from \"@spectrum-web-components/base\";\nimport { property } from \"@spectrum-web-components/base/src/decorators.js\";\nimport { ifDefined } from \"@spectrum-web-components/base/src/directives.js\";\nimport progressCircleStyles from \"./progress-circle.css.js\";\nimport { ProgressCircleBase } from \"./ProgressCircle.base.dev.js\";\nimport {\n PROGRESS_CIRCLE_STATIC_COLORS_S1\n} from \"./ProgressCircle.types.dev.js\";\nexport class ProgressCircle extends ProgressCircleBase {\n // ──────────────────────────────\n // RENDERING & STYLING\n // ──────────────────────────────\n static get styles() {\n return [progressCircleStyles];\n }\n render() {\n const styles = [\n this.makeRotation(-180 + 180 / 50 * Math.min(this.progress, 50)),\n this.makeRotation(-180 + 180 / 50 * Math.max(this.progress - 50, 0))\n ];\n const masks = [\"Mask1\", \"Mask2\"];\n return html`\n <slot @slotchange=${this.handleSlotchange}></slot>\n <div class=\"track\"></div>\n <div class=\"fills\">\n ${masks.map(\n (mask, index) => html`\n <div class=\"fill${mask}\">\n <div class=\"fillSub${mask}\" style=${ifDefined(styles[index])}>\n <div class=\"fill\"></div>\n </div>\n </div>\n `\n )}\n </div>\n `;\n }\n}\n// ────────────────────\n// API OVERRIDES\n// ────────────────────\n/**\n * @internal\n */\nProgressCircle.STATIC_COLORS = PROGRESS_CIRCLE_STATIC_COLORS_S1;\n__decorateClass([\n property({ type: String, reflect: true, attribute: \"static-color\" })\n], ProgressCircle.prototype, \"staticColor\", 2);\n//# sourceMappingURL=ProgressCircle.dev.js.map\n",
|
|
10
|
-
"\"use strict\";\nimport { defineElement } from \"@spectrum-web-components/base/src/define-element.js\";\nimport { ProgressCircle } from \"./src/ProgressCircle.dev.js\";\ndefineElement(\"sp-progress-circle\", ProgressCircle);\n//# sourceMappingURL=sp-progress-circle.dev.js.map\n"
|
|
11
|
-
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "D9778D0A36E46FD364756E2164756E21",
|
|
14
|
-
"names": []
|
|
15
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../node_modules/lit-html/development/directives/unsafe-html.js"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * @license\n * Copyright 2017 Google LLC\n * SPDX-License-Identifier: BSD-3-Clause\n */\nimport { nothing, noChange } from '../lit-html.js';\nimport { directive, Directive, PartType } from '../directive.js';\nconst HTML_RESULT = 1;\nexport class UnsafeHTMLDirective extends Directive {\n constructor(partInfo) {\n super(partInfo);\n this._value = nothing;\n if (partInfo.type !== PartType.CHILD) {\n throw new Error(`${this.constructor.directiveName}() can only be used in child bindings`);\n }\n }\n render(value) {\n if (value === nothing || value == null) {\n this._templateResult = undefined;\n return (this._value = value);\n }\n if (value === noChange) {\n return value;\n }\n if (typeof value != 'string') {\n throw new Error(`${this.constructor.directiveName}() called with a non-string value`);\n }\n if (value === this._value) {\n return this._templateResult;\n }\n this._value = value;\n const strings = [value];\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n strings.raw = strings;\n // WARNING: impersonating a TemplateResult like this is extremely\n // dangerous. Third-party directives should not do this.\n return (this._templateResult = {\n // Cast to a known set of integers that satisfy ResultType so that we\n // don't have to export ResultType and possibly encourage this pattern.\n // This property needs to remain unminified.\n ['_$litType$']: this.constructor\n .resultType,\n strings,\n values: [],\n });\n }\n}\nUnsafeHTMLDirective.directiveName = 'unsafeHTML';\nUnsafeHTMLDirective.resultType = HTML_RESULT;\n/**\n * Renders the result as HTML, rather than text.\n *\n * The values `undefined`, `null`, and `nothing`, will all result in no content\n * (empty string) being rendered.\n *\n * Note, this is unsafe to use with any user-provided input that hasn't been\n * sanitized or escaped, as it may lead to cross-site-scripting\n * vulnerabilities.\n */\nexport const unsafeHTML = directive(UnsafeHTMLDirective);\n//# sourceMappingURL=unsafe-html.js.map"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;;;AAOA,IAAM,cAAc;AAAA;AACb,MAAM,4BAA4B,UAAU;AAAA,EAC/C,WAAW,CAAC,UAAU;AAAA,IAClB,MAAM,QAAQ;AAAA,IACd,KAAK,SAAS;AAAA,IACd,IAAI,SAAS,SAAS,SAAS,OAAO;AAAA,MAClC,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,oDAAoD;AAAA,IAC5F;AAAA;AAAA,EAEJ,MAAM,CAAC,OAAO;AAAA,IACV,IAAI,UAAU,WAAW,SAAS,MAAM;AAAA,MACpC,KAAK,kBAAkB;AAAA,MACvB,OAAQ,KAAK,SAAS;AAAA,IAC1B;AAAA,IACA,IAAI,UAAU,UAAU;AAAA,MACpB,OAAO;AAAA,IACX;AAAA,IACA,IAAI,OAAO,SAAS,UAAU;AAAA,MAC1B,MAAM,IAAI,MAAM,GAAG,KAAK,YAAY,gDAAgD;AAAA,IACxF;AAAA,IACA,IAAI,UAAU,KAAK,QAAQ;AAAA,MACvB,OAAO,KAAK;AAAA,IAChB;AAAA,IACA,KAAK,SAAS;AAAA,IACd,MAAM,UAAU,CAAC,KAAK;AAAA,IAEtB,QAAQ,MAAM;AAAA,IAGd,OAAQ,KAAK,kBAAkB;AAAA,OAI1B,eAAe,KAAK,YAChB;AAAA,MACL;AAAA,MACA,QAAQ,CAAC;AAAA,IACb;AAAA;AAER;AACA,oBAAoB,gBAAgB;AACpC,oBAAoB,aAAa;AAW1B,IAAM,aAAa,UAAU,mBAAmB;",
|
|
8
|
-
"debugId": "2A5B539DDAEE5D8464756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/services/jx-validate.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Jx-validate.js — cached Jx schema validation for the AI assistant.\n *\n * Validates against the ACTIVE project's generated entry documents (`document.schema.json` /\n * `project.schema.json`, extensions.md §5.2) once {@link applyProjectSchemas} has been handed them,\n * and against `@jxsuite/schema`'s pre-generated core schemas until then. Matching what Monaco shows\n * in the code view is the point: the entry documents close the composition with\n * `unevaluatedProperties: false` and union in each enabled extension's shapes, so validating the\n * agent loop against core alone lets the model write a `$paths` source or a `search:` section that\n * its own tool call reports clean and the editor paints red the moment a human opens the file.\n *\n * We import the generated JSON rather than the generator itself: `generateSchema()` pulls in\n * `@webref/*` + Node builtins (node:path/process) and would crash a browser bundle. Validators are\n * compiled once per schema swap — `@jxsuite/schema`'s `validateDocument` recompiles on every call,\n * which is too slow to run after every mutation in the loop.\n *\n * @license MIT\n */\n\nimport coreDocumentSchema from \"@jxsuite/schema/schema.json\";\nimport coreProjectSchema from \"@jxsuite/schema/project-schema.json\";\n\ntype ValidateFn = ((doc: unknown) => boolean) & {\n errors?: { instancePath?: string; message?: string }[] | null;\n};\n\n/** Which of the two entry documents a validator covers. */\ntype SchemaKind = \"document\" | \"project\";\n\nconst CORE: Record<SchemaKind, object> = {\n document: coreDocumentSchema as object,\n project: coreProjectSchema as object,\n};\n\nconst active: Record<SchemaKind, object> = { ...CORE };\nconst compiling: Record<SchemaKind, Promise<ValidateFn | null> | null> = {\n document: null,\n project: null,\n};\n\n/**\n * One console report per session — a validator that cannot compile is otherwise indistinguishable\n * from a clean document, in the agent loop AND in the eval scoreboard.\n */\nlet reportedFailure = false;\n\n/**\n * Compile (once per active schema) and return the ajv validate function, or null when ajv is\n * unavailable or the schema will not compile.\n *\n * @param {SchemaKind} kind - Which entry document to compile\n * @returns {Promise<ValidateFn | null>} The compiled validator, or null when unavailable\n */\nfunction getValidator(kind: SchemaKind): Promise<ValidateFn | null> {\n compiling[kind] ??= (async () => {\n try {\n // The generated schemas are JSON Schema draft 2020-12, so they need Ajv's 2020 build —\n // The default export only knows draft-07 and throws on the 2020 meta-schema ref.\n // Optional peer dependency: validation degrades to a no-op if ajv is absent or the\n // Schema fails to compile.\n const { default: Ajv2020 } = await import(\"ajv/dist/2020.js\");\n const { default: addFormats } = await import(\"ajv-formats\");\n const ajv = new Ajv2020({ allErrors: true, strict: false, allowUnionTypes: true });\n addFormats(ajv);\n return ajv.compile(active[kind]) as ValidateFn;\n } catch (error) {\n if (!reportedFailure) {\n reportedFailure = true;\n console.error(\n `[jx] ${kind} schema validation is unavailable — the AI assistant's schema gate is a ` +\n `no-op for this session:`,\n error,\n );\n }\n return null;\n }\n })();\n return compiling[kind];\n}\n\n/**\n * Swap in the active project's pre-bundled entry documents (the payload behind the platform's\n * `fetchProjectSchemas` member). Each half falls back to its core schema when absent, so a partial\n * payload still upgrades the half it carries. Discards the compiled validators so the next call\n * recompiles.\n *\n * @param {object | null} schemas - Pre-bundled `{ document, project }`, or null to restore core\n * @returns {boolean} True when at least one per-project schema was applied\n */\nexport function applyProjectSchemas(\n schemas: { project?: unknown; document?: unknown } | null,\n): boolean {\n const document = (schemas?.document as object | undefined) ?? CORE.document;\n const project = (schemas?.project as object | undefined) ?? CORE.project;\n if (document === active.document && project === active.project) {\n return Boolean(schemas?.document || schemas?.project);\n }\n active.document = document;\n active.project = project;\n compiling.document = null;\n compiling.project = null;\n return Boolean(schemas?.document || schemas?.project);\n}\n\n/** Restore the core schemas (project closed / tests). */\nexport function resetProjectSchemas(): void {\n applyProjectSchemas(null);\n}\n\n/**\n * Format ajv errors the way the agent loop consumes them (see ai-tools.ts\n * `translateValidationError`).\n *\n * @param {ValidateFn} validate - The validator that just ran\n * @returns {string[]} One formatted string per error\n */\nfunction formatErrors(validate: ValidateFn): string[] {\n return (validate.errors || []).map((e) => `${e.instancePath || \"(root)\"}: ${e.message}`);\n}\n\n/**\n * Validate a Jx document against the active document schema.\n *\n * @param {unknown} doc - Parsed document\n * @returns {Promise<string[]>} Formatted error strings; empty when valid or validation unavailable\n */\nexport async function validateDoc(doc: unknown): Promise<string[]> {\n const validate = await getValidator(\"document\");\n if (!validate || validate(doc)) {\n return [];\n }\n return formatErrors(validate);\n}\n\n/**\n * Validate a `project.json` config against the active project schema. The per-project entry\n * document is what closes the composition (`unevaluatedProperties: false` over core + every enabled\n * extension's fragment), so this is the only gate that catches a typo'd section key or a misshapen\n * extension section before the write lands.\n *\n * @param {unknown} config - Parsed project.json\n * @returns {Promise<string[]>} Formatted error strings; empty when valid or validation unavailable\n */\nexport async function validateProjectConfig(config: unknown): Promise<string[]> {\n const validate = await getValidator(\"project\");\n if (!validate || validate(config)) {\n return [];\n }\n return formatErrors(validate);\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";;;;;;;;;;AA6BA,IAAM,OAAmC;AAAA,EACvC,UAAU;AAAA,EACV,SAAS;AACX;AAEA,IAAM,SAAqC,KAAK,KAAK;AACrD,IAAM,YAAmE;AAAA,EACvE,UAAU;AAAA,EACV,SAAS;AACX;AAMA,IAAI,kBAAkB;AAStB,SAAS,YAAY,CAAC,MAA8C;AAAA,EAClE,UAAU,WAAW,YAAY;AAAA,IAC/B,IAAI;AAAA,MAKF,QAAQ,SAAS,YAAY,MAAa;AAAA,MAC1C,QAAQ,SAAS,eAAe,MAAa;AAAA,MAC7C,MAAM,MAAM,IAAI,QAAQ,EAAE,WAAW,MAAM,QAAQ,OAAO,iBAAiB,KAAK,CAAC;AAAA,MACjF,WAAW,GAAG;AAAA,MACd,OAAO,IAAI,QAAQ,OAAO,KAAK;AAAA,MAC/B,OAAO,OAAO;AAAA,MACd,IAAI,CAAC,iBAAiB;AAAA,QACpB,kBAAkB;AAAA,QAClB,QAAQ,MACN,QAAQ,iFACN,2BACF,KACF;AAAA,MACF;AAAA,MACA,OAAO;AAAA;AAAA,KAER;AAAA,EACH,OAAO,UAAU;AAAA;AAYZ,SAAS,mBAAmB,CACjC,SACS;AAAA,EACT,MAAM,WAAY,SAAS,YAAmC,KAAK;AAAA,EACnE,MAAM,UAAW,SAAS,WAAkC,KAAK;AAAA,EACjE,IAAI,aAAa,OAAO,YAAY,YAAY,OAAO,SAAS;AAAA,IAC9D,OAAO,QAAQ,SAAS,YAAY,SAAS,OAAO;AAAA,EACtD;AAAA,EACA,OAAO,WAAW;AAAA,EAClB,OAAO,UAAU;AAAA,EACjB,UAAU,WAAW;AAAA,EACrB,UAAU,UAAU;AAAA,EACpB,OAAO,QAAQ,SAAS,YAAY,SAAS,OAAO;AAAA;AAI/C,SAAS,mBAAmB,GAAS;AAAA,EAC1C,oBAAoB,IAAI;AAAA;AAU1B,SAAS,YAAY,CAAC,UAAgC;AAAA,EACpD,QAAQ,SAAS,UAAU,CAAC,GAAG,IAAI,CAAC,MAAM,GAAG,EAAE,gBAAgB,aAAa,EAAE,SAAS;AAAA;AASzF,eAAsB,WAAW,CAAC,KAAiC;AAAA,EACjE,MAAM,WAAW,MAAM,aAAa,UAAU;AAAA,EAC9C,IAAI,CAAC,YAAY,SAAS,GAAG,GAAG;AAAA,IAC9B,OAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAO,aAAa,QAAQ;AAAA;AAY9B,eAAsB,qBAAqB,CAAC,QAAoC;AAAA,EAC9E,MAAM,WAAW,MAAM,aAAa,SAAS;AAAA,EAC7C,IAAI,CAAC,YAAY,SAAS,MAAM,GAAG;AAAA,IACjC,OAAO,CAAC;AAAA,EACV;AAAA,EACA,OAAO,aAAa,QAAQ;AAAA;",
|
|
8
|
-
"debugId": "65EFF2410CACDD1964756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../create/scaffold.ts", "../src/publish/pages-service.ts", "../src/publish/deploy-checklist.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Pure scaffolding helpers — zero node imports so Studio can run them in the browser (the publish\n * flow writes wrangler.jsonc through the PAL) and cloud platforms can seed repos through the Git\n * Data API. generate.ts wraps these with filesystem I/O.\n */\n\nconst CF_ADAPTERS = new Set([\"cloudflare-pages\", \"cloudflare-workers\"]);\n\n/** True when the adapter deploys through wrangler (needs a wrangler.jsonc). */\nexport function adapterNeedsWrangler(adapter: string | undefined): boolean {\n return Boolean(adapter && CF_ADAPTERS.has(adapter));\n}\n\n/**\n * A fresh wrangler.jsonc for the adapter. `name` becomes the Cloudflare project name — when the\n * project has a `build.deploy` block, pass its projectName so the config and the connected Pages\n * project agree.\n */\nexport function buildWranglerJsonc({ slug, adapter }: { slug: string; adapter: string }): string {\n const compatibilityDate = new Date().toISOString().slice(0, 10);\n\n // Nodejs_compat: server functions routinely pull in Node-flavored npm packages\n const config =\n adapter === \"cloudflare-workers\"\n ? {\n assets: { binding: \"ASSETS\", directory: \"./dist\" },\n compatibility_date: compatibilityDate,\n compatibility_flags: [\"nodejs_compat\"],\n main: \"./dist/worker.js\",\n name: slug,\n }\n : {\n compatibility_date: compatibilityDate,\n compatibility_flags: [\"nodejs_compat\"],\n name: slug,\n pages_build_output_dir: \"./dist\",\n };\n\n return `${JSON.stringify(config, null, \"\\t\")}\\n`;\n}\n\n/**\n * Deep-merge connector binding fragments into a wrangler.jsonc (plan Part 4a; consumed by `jx db\n * push`). Fragments are the `bindings` connector-capability results — e.g. `{ d1_databases: [{\n * binding, database_id }] }` or `{ hyperdrive: [{ binding, id }] }`.\n *\n * Merge rules: objects merge recursively; arrays whose elements carry a `binding` key are keyed by\n * it (same-binding entries merge, new ones append — user-added keys on an entry survive); other\n * values only land when the user has not set them (user keys are preserved). Unparseable\n * (comment-bearing) JSONC is returned unchanged with `patched: false` rather than risking data\n * loss.\n *\n * @param {string | null} existing - Current wrangler.jsonc content, or null when absent\n * @param {Record<string, unknown>[]} fragments - Binding fragments, applied in order\n * @returns {{ content: string; patched: boolean }}\n */\nexport function applyBindingFragments(\n existing: string | null,\n fragments: Record<string, unknown>[],\n): { content: string; patched: boolean } {\n if (fragments.length === 0) {\n return { content: existing ?? \"\", patched: false };\n }\n let config: Record<string, unknown> = {};\n if (existing) {\n try {\n config = JSON.parse(existing) as Record<string, unknown>;\n } catch {\n // Comment-bearing JSONC — leave the user's file alone.\n return { content: existing, patched: false };\n }\n }\n for (const fragment of fragments) {\n mergeBindingValue(config, fragment);\n }\n return { content: `${JSON.stringify(config, null, \"\\t\")}\\n`, patched: true };\n}\n\n/** Recursively merge one fragment object into the target, per the applyBindingFragments rules. */\nfunction mergeBindingValue(target: Record<string, unknown>, fragment: Record<string, unknown>) {\n for (const [key, incoming] of Object.entries(fragment)) {\n const current = target[key];\n if (Array.isArray(incoming)) {\n target[key] = mergeBindingArrays(Array.isArray(current) ? current : [], incoming);\n continue;\n }\n if (isPlainObject(incoming)) {\n if (isPlainObject(current)) {\n mergeBindingValue(current, incoming);\n } else if (current === undefined) {\n target[key] = structuredClone(incoming);\n }\n continue;\n }\n if (current === undefined) {\n target[key] = incoming;\n }\n }\n}\n\n/** Merge fragment array entries into an existing array, keyed by each entry's `binding`. */\nfunction mergeBindingArrays(current: unknown[], incoming: unknown[]): unknown[] {\n const merged = [...current];\n for (const entry of incoming) {\n if (!isPlainObject(entry) || typeof entry.binding !== \"string\") {\n // Non-binding-keyed values: append when missing (dedupe by deep equality).\n const exists = merged.some((m) => JSON.stringify(m) === JSON.stringify(entry));\n if (!exists) {\n merged.push(structuredClone(entry));\n }\n continue;\n }\n const index = merged.findIndex(\n (m) => isPlainObject(m) && (m as Record<string, unknown>).binding === entry.binding,\n );\n if (index === -1) {\n merged.push(structuredClone(entry));\n } else {\n // Fragment values win for connector-owned keys; user-added extra keys survive.\n merged[index] = { ...(merged[index] as Record<string, unknown>), ...entry };\n }\n }\n return merged;\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\n/**\n * Patch an existing wrangler.jsonc for an adapter change (or a Pages project rename), touching only\n * the adapter-shape keys and preserving everything else the user added. Regenerates from scratch\n * when the input is missing or unparseable (wrangler.jsonc supports comments, which JSON.parse does\n * not — a commented config falls back to regeneration rather than data loss... it is returned\n * unchanged with `patched: false` so callers can warn).\n */\nexport function updateWranglerConfig(\n existing: string | null,\n { slug, adapter }: { slug: string; adapter: string },\n): { content: string; patched: boolean } {\n if (!existing) {\n return { content: buildWranglerJsonc({ adapter, slug }), patched: true };\n }\n let config: Record<string, unknown>;\n try {\n config = JSON.parse(existing) as Record<string, unknown>;\n } catch {\n // Comment-bearing JSONC — leave the user's file alone.\n return { content: existing, patched: false };\n }\n config[\"name\"] = slug;\n if (adapter === \"cloudflare-workers\") {\n delete config[\"pages_build_output_dir\"];\n config[\"main\"] = \"./dist/worker.js\";\n config[\"assets\"] = { binding: \"ASSETS\", directory: \"./dist\" };\n } else {\n delete config[\"main\"];\n delete config[\"assets\"];\n config[\"pages_build_output_dir\"] = \"./dist\";\n }\n return { content: `${JSON.stringify(config, null, \"\\t\")}\\n`, patched: true };\n}\n",
|
|
6
|
-
"/// <reference lib=\"dom\" />\n/**\n * Pages-service — Cloudflare Pages publish domain logic over the PAL's\n * `cfApi` passthrough. Works identically on every platform that provides it:\n * the dev server / desktop (user API token via cf-settings → /__studio/cf/proxy)\n * and the cloud platform (hosted OAuth). Publish state is written to\n * project.json `build.deploy` — it travels with the repo, so any Studio can\n * tell whether the publish workflow already exists.\n *\n * @license MIT\n */\n\nimport { updateWranglerConfig } from \"@jxsuite/create/scaffold\";\nimport type { DeployConfig, ProjectConfig } from \"@jxsuite/schema/types\";\nimport { getPlatform } from \"../platform\";\nimport { updateSiteConfig } from \"../site-context\";\n\nexport interface CfAccount {\n id: string;\n name: string;\n}\n\nexport interface PagesDeploymentInfo {\n id: string;\n url: string;\n environment: string;\n /** Latest stage name/status, e.g. \"deploy: success\" or \"build: failure\". */\n stage: string;\n status: string;\n createdOn: string;\n}\n\nexport interface ConnectOptions {\n accountId: string;\n projectName: string;\n productionBranch: string;\n owner: string;\n repo: string;\n}\n\n/** True when the active platform can reach the Cloudflare API. */\nexport function platformSupportsPublish(): boolean {\n // Answers false before a platform is registered rather than throwing. This is read by ambient\n // Surfaces — the status bar's deploy item, the Activity tab's checklist — which paint during boot\n // And in tests that register no platform, and neither has any business crashing because\n // Publishing is not available yet. \"Can this host publish?\" has a truthful answer before the host\n // Exists, and it is no.\n try {\n return typeof getPlatform().cfApi === \"function\";\n } catch {\n return false;\n }\n}\n\nasync function cfApi<T>(path: string, init?: { method?: string; body?: unknown }): Promise<T> {\n const api = getPlatform().cfApi;\n if (!api) {\n throw new Error(\"This platform cannot reach the Cloudflare API\");\n }\n return (await api(path, init)) as T;\n}\n\nexport async function listAccounts(): Promise<CfAccount[]> {\n return cfApi<CfAccount[]>(\"/accounts\");\n}\n\ninterface PagesProjectWire {\n name: string;\n subdomain?: string;\n domains?: string[];\n}\n\n/** The Pages project, or null when it does not exist yet. */\nexport async function getPagesProject(\n accountId: string,\n projectName: string,\n): Promise<PagesProjectWire | null> {\n try {\n return await cfApi<PagesProjectWire>(`/accounts/${accountId}/pages/projects/${projectName}`);\n } catch {\n return null;\n }\n}\n\n/**\n * Create a GitHub-connected Pages project that builds `bunx jx build` on every push. Requires the\n * Cloudflare Pages GitHub App on the repo — the characteristic failure is surfaced to the caller\n * with an install hint.\n */\nexport async function createPagesProject(opts: ConnectOptions): Promise<PagesProjectWire> {\n return cfApi<PagesProjectWire>(`/accounts/${opts.accountId}/pages/projects`, {\n method: \"POST\",\n body: {\n name: opts.projectName,\n production_branch: opts.productionBranch,\n build_config: {\n build_command: \"bunx jx build\",\n destination_dir: \"dist\",\n },\n source: {\n type: \"github\",\n config: {\n owner: opts.owner,\n repo_name: opts.repo,\n production_branch: opts.productionBranch,\n deployments_enabled: true,\n },\n },\n },\n });\n}\n\ninterface DeploymentWire {\n id: string;\n url: string;\n environment: string;\n latest_stage?: { name?: string; status?: string };\n created_on: string;\n}\n\n/** The most recent deployment of the connected project, or null when none. */\nexport async function latestDeployment(deploy: DeployConfig): Promise<PagesDeploymentInfo | null> {\n const deployments = await cfApi<DeploymentWire[]>(\n `/accounts/${deploy.accountId}/pages/projects/${deploy.projectName}/deployments`,\n );\n const [latest] = deployments;\n if (!latest) {\n return null;\n }\n return {\n id: latest.id,\n url: latest.url,\n environment: latest.environment,\n stage: latest.latest_stage?.name ?? \"unknown\",\n status: latest.latest_stage?.status ?? \"unknown\",\n createdOn: latest.created_on,\n };\n}\n\n/**\n * Write (or with null, remove) the `build.deploy` block, preserving the rest of `build`. On\n * connect, wrangler.jsonc is patched so its `name` matches the connected Pages project\n * (comment-bearing JSONC is left alone).\n */\nexport async function writeDeployConfig(\n config: ProjectConfig,\n deploy: DeployConfig | null,\n): Promise<void> {\n const build: NonNullable<ProjectConfig[\"build\"]> = { ...config.build };\n if (deploy === null) {\n delete build.deploy;\n } else {\n build.deploy = deploy;\n }\n await updateSiteConfig({ build });\n\n if (deploy !== null) {\n const platform = getPlatform();\n let existing: string | null = null;\n try {\n existing = await platform.readFile(\"wrangler.jsonc\");\n } catch {\n existing = null;\n }\n const adapter =\n build.adapter === \"cloudflare-workers\" ? \"cloudflare-workers\" : \"cloudflare-pages\";\n const { content, patched } = updateWranglerConfig(existing, {\n adapter,\n slug: deploy.projectName,\n });\n if (patched) {\n await platform.writeFile(\"wrangler.jsonc\", content);\n }\n }\n}\n\n/**\n * The whole connect flow: reuse the Pages project when it already exists, create it otherwise, then\n * persist `build.deploy` (+ wrangler.jsonc sync).\n */\nexport async function connectDeploy(\n config: ProjectConfig,\n opts: ConnectOptions,\n): Promise<DeployConfig> {\n const existing = await getPagesProject(opts.accountId, opts.projectName);\n const project = existing ?? (await createPagesProject(opts));\n const deploy: DeployConfig = {\n provider: \"cloudflare-pages\",\n accountId: opts.accountId,\n projectName: opts.projectName,\n ...(project.subdomain ? { productionUrl: `https://${project.subdomain}` } : {}),\n };\n await writeDeployConfig(config, deploy);\n return deploy;\n}\n",
|
|
7
|
-
"/// <reference lib=\"dom\" />\n/**\n * Deploy-checklist.ts — what is MISSING before this project can ship, as an ordered list.\n *\n * What this replaces: a Cloudflare form that opened asking for a GitHub owner and repository on a\n * project that had never been `git init`-ed, failed with a Cloudflare API error naming neither\n * fact, and offered no way forward. Publishing is a CHAIN — the repository exists, it has a remote\n * and the remote is current, a provider is connected, a deployment happened — and every link is a\n * different command owned by a different module. Nothing in Studio held the chain, so no surface\n * could say which link was missing.\n *\n * This module is the chain (plan §9.5):\n *\n * - {@link deployChecklist} is the ordered prerequisite list, each step carrying **the command that\n * satisfies it** rather than a sentence telling the reader to go and find one;\n * - {@link renderDeployChecklist} is its rendering, and it lives in the Bottom dock's **Activity**\n * tab because a deploy is a long operation with a log and the dock cap is four (§2 principle 9).\n * It draws in the Activity vocabulary — `activity-row`, `activity-steps`, `activity-step--done` —\n * for the same reason: a fifth visual idiom for \"an ordered list of stages that finish\" would be\n * a second design of a thing the tab already has;\n * - {@link deployStatusItem} is the status bar's project-field item, whose **label is the next\n * blocking prerequisite** — the shortcut and the explanation in one 24px item, and ambient state\n * rather than a transient message, which is the only thing that bar carries (§3.2 ⑫).\n *\n * **A step it cannot answer says `unknown`.** `services/references.ts` established the rule and it\n * matters more here: \"no deployment\" and \"we have not asked Cloudflare\" look identical from inside\n * the app, and a checklist that renders the second as the first tells the user to redo a deploy\n * that already succeeded. The observation cache ({@link noteDeployment}) is written by the code\n * that actually asked — the Publish panel's load and {@link import(\"./publish-commands\").runDeploy}\n * — and by nothing else.\n *\n * **No secret reaches this module.** A provider is connected or it is not; the token that proves it\n * is read by `platforms/devserver.ts` on its way to the same-origin proxy and by nothing that\n * renders (`studio.md` §15 rule 1).\n */\n\nimport { html, nothing } from \"lit-html\";\nimport { activeRegistry } from \"../commands/active-registry\";\nimport { platformSupportsPublish } from \"./pages-service\";\nimport { projectState } from \"../store\";\nimport { shell } from \"../shell\";\nimport type { DeployConfig, ProjectConfig } from \"@jxsuite/schema/types\";\nimport type { PagesDeploymentInfo } from \"./pages-service\";\nimport type { TemplateResult } from \"lit-html\";\n\n/** The chain, in the order the links must be forged. */\nexport const DEPLOY_STEP_IDS = [\"repo\", \"remote\", \"provider\", \"deployed\"] as const;\n\nexport type DeployStepId = (typeof DEPLOY_STEP_IDS)[number];\n\n/**\n * Whether a link is forged.\n *\n * `unknown` is not a third kind of \"no\": it is the honest answer when the fact lives on a server\n * nobody has asked. It blocks like a `todo` and it READS differently, which is the whole point.\n */\nexport type DeployStepState = \"done\" | \"todo\" | \"unknown\";\n\n/** One prerequisite. */\nexport interface DeployStep {\n readonly id: DeployStepId;\n /** Imperative, and short enough to be a 24px status-bar label. */\n readonly label: string;\n readonly state: DeployStepState;\n /** One sentence: what is true now, or what satisfying it buys. Never a secret. */\n readonly detail: string;\n /** The command that satisfies it — an id, so the row inherits title, chord and refusal. */\n readonly command: string;\n}\n\n/** The active project's configuration, or null when no project is open. */\nfunction currentConfig(): ProjectConfig | null {\n return (projectState?.projectConfig as ProjectConfig | undefined) ?? null;\n}\n\n/**\n * The connected provider block, or `undefined`.\n *\n * Exported because the Publish panel asks the same question and P6's lesson was that two copies of\n * one derivation drift apart in silence — there is one reader of `build.deploy` in the app.\n */\nexport function currentDeploy(): DeployConfig | undefined {\n return currentConfig()?.build?.deploy;\n}\n\n/**\n * The last deployment anybody actually observed, or null when nobody has asked.\n *\n * Module state rather than a field on the config: a deployment is a fact about Cloudflare, not\n * about this repository, and writing it into `project.json` would commit a timestamp that is stale\n * the moment it is pushed.\n */\nlet _observed: PagesDeploymentInfo | null = null;\n\n/** Whether anybody has asked at all — the difference between `todo` and `unknown`. */\nlet _asked = false;\n\n/** Record what Cloudflare answered. `null` means \"asked, and there are none\". */\nexport function noteDeployment(info: PagesDeploymentInfo | null): void {\n _observed = info;\n _asked = true;\n}\n\n/** The observed deployment, or null. */\nexport function observedDeployment(): PagesDeploymentInfo | null {\n return _observed;\n}\n\n/** Forget the observation — project close, and every test that asserts the `unknown` branch. */\nexport function forgetDeployment(): void {\n _observed = null;\n _asked = false;\n}\n\nfunction repoStep(): DeployStep {\n const { status } = shell.git;\n if (status === null) {\n return {\n command: \"git.init\",\n detail: \"Source control has not reported on this project yet.\",\n id: \"repo\",\n label: \"Track this project with git\",\n state: \"unknown\",\n };\n }\n return status.isRepo\n ? {\n command: \"git.init\",\n detail: `Tracked${status.branch ? ` — on branch ${status.branch}` : \"\"}.`,\n id: \"repo\",\n label: \"Track this project with git\",\n state: \"done\",\n }\n : {\n command: \"git.init\",\n detail: \"A deploy ships what the repository holds, so the repository comes first.\",\n id: \"repo\",\n label: \"Track this project with git\",\n state: \"todo\",\n };\n}\n\nfunction remoteStep(): DeployStep {\n const { status } = shell.git;\n if (status === null || !status.isRepo) {\n return {\n command: \"git.createGithubRepository\",\n detail: \"A remote is where the provider builds from.\",\n id: \"remote\",\n label: \"Push to a remote\",\n state: status === null ? \"unknown\" : \"todo\",\n };\n }\n // A GitStatus from a host that reports no remotes array is not a repo with remotes — it is a\n // Host that did not say. Reading through it took the whole status bar down with a TypeError.\n if ((status.remotes ?? []).length === 0) {\n return {\n command: \"git.createGithubRepository\",\n detail: \"This repository is local only — nothing outside this machine can build it.\",\n id: \"remote\",\n label: \"Push to a remote\",\n state: \"todo\",\n };\n }\n return status.ahead > 0\n ? {\n command: \"git.push\",\n detail: `${status.ahead} commit(s) are not on ${status.remotes[0]} yet, so a build would ship the older tree.`,\n id: \"remote\",\n label: \"Push to a remote\",\n state: \"todo\",\n }\n : {\n command: \"git.push\",\n detail: `Up to date with ${status.remotes[0]}.`,\n id: \"remote\",\n label: \"Push to a remote\",\n state: \"done\",\n };\n}\n\nfunction providerStep(): DeployStep {\n const deploy = currentDeploy();\n if (deploy) {\n return {\n command: \"publish.setUp\",\n detail: `Cloudflare Pages project ${deploy.projectName}.`,\n id: \"provider\",\n label: \"Connect a deploy provider\",\n state: \"done\",\n };\n }\n return platformSupportsPublish()\n ? {\n command: \"publish.setUp\",\n detail: \"Connecting one makes every commit build and publish on its own.\",\n id: \"provider\",\n label: \"Connect a deploy provider\",\n state: \"todo\",\n }\n : {\n command: \"publish.setUp\",\n detail:\n \"This platform cannot reach the Cloudflare API. Commit and push instead — your host \" +\n \"runs bunx jx build and serves dist/.\",\n id: \"provider\",\n label: \"Connect a deploy provider\",\n state: \"unknown\",\n };\n}\n\nfunction deployedStep(): DeployStep {\n if (!currentDeploy()) {\n return {\n command: \"publish.deploy\",\n detail: \"Nothing has been deployed, because no provider is connected.\",\n id: \"deployed\",\n label: \"Deploy\",\n state: \"todo\",\n };\n }\n if (!_asked) {\n return {\n command: \"publish.deploy\",\n detail: \"Cloudflare has not been asked yet, so this is not a claim that nothing shipped.\",\n id: \"deployed\",\n label: \"Deploy\",\n state: \"unknown\",\n };\n }\n if (_observed === null) {\n return {\n command: \"publish.deploy\",\n detail: \"Cloudflare reports no deployments for this project.\",\n id: \"deployed\",\n label: \"Deploy\",\n state: \"todo\",\n };\n }\n return _observed.status === \"success\"\n ? {\n command: \"publish.deploy\",\n detail: `${_observed.environment} — ${_observed.url}`,\n id: \"deployed\",\n label: \"Deploy\",\n state: \"done\",\n }\n : {\n command: \"publish.deploy\",\n detail: `Last deployment ${_observed.stage}: ${_observed.status}.`,\n id: \"deployed\",\n label: \"Deploy\",\n state: \"todo\",\n };\n}\n\n/** The four prerequisites, in order. */\nexport function deployChecklist(): DeployStep[] {\n return [repoStep(), remoteStep(), providerStep(), deployedStep()];\n}\n\n/**\n * The first link that is not forged, or null when the chain is whole.\n *\n * `unknown` counts as not forged: the app may not claim a step is done on the strength of not\n * having asked.\n */\nexport function nextDeployStep(): DeployStep | null {\n return deployChecklist().find((step) => step.state !== \"done\") ?? null;\n}\n\n/** What the status bar's project field shows. `null` when there is no project to deploy. */\nexport interface DeployStatusItem {\n readonly command: string;\n readonly label: string;\n readonly title: string;\n}\n\n/**\n * The status-bar item — ambient state, never a transient message.\n *\n * Its LABEL is the next blocking prerequisite, so the item explains itself: a reader who does not\n * know what is missing learns it from the same 24px string that fixes it.\n */\nexport function deployStatusItem(): DeployStatusItem | null {\n if (!projectState) {\n return null;\n }\n const next = nextDeployStep();\n if (next) {\n return { command: next.command, label: next.label, title: next.detail };\n }\n const url = currentDeploy()?.productionUrl;\n return {\n command: \"publish.openDashboard\",\n label: \"Deployed\",\n title: url ?? \"Everything this project needs to ship is in place.\",\n };\n}\n\n// ─── Rendering ────────────────────────────────────────────────────────────────\n\n/** Checklist state → the Activity tab's step classes, so one vocabulary draws both. */\nconst STEP_CLASS: Readonly<Record<DeployStepState, string>> = {\n done: \"done\",\n todo: \"pending\",\n unknown: \"pending\",\n};\n\nconst STEP_ICON: Readonly<Record<DeployStepState, string>> = {\n done: \"✓\",\n todo: \"·\",\n unknown: \"?\",\n};\n\n/**\n * The next action, as a button — or nothing.\n *\n * A command the registry does not have, or whose `when` is false, renders NOTHING rather than a\n * dead label. The status bar's `itemTpl` takes the same position for the same reason: a surface may\n * choose whether to show a command, never whether it exists.\n */\nfunction actionTpl(step: DeployStep | null): TemplateResult | typeof nothing {\n if (!step) {\n return nothing;\n }\n const registry = activeRegistry();\n const command = registry?.get(step.command);\n if (!registry || !command || !registry.isVisible(step.command)) {\n return nothing;\n }\n const reason = registry.disabledReason(step.command);\n return html`<sp-action-button\n size=\"s\"\n ?disabled=${reason !== undefined}\n title=${reason ? `${command.title} — requires ${reason}` : command.title}\n @click=${() => {\n void registry.run(step.command);\n }}\n >${command.title}</sp-action-button\n >`;\n}\n\n/**\n * The checklist, as the Activity tab draws it — or nothing, when no project is open.\n *\n * Rendered ABOVE the operation list rather than as an entry in it: an activity is something that\n * happened, and this is something that has not. It carries no `data-jx-region` stamp — the region\n * is `dock.bottom/panel:activity`, which the dock derives, and a hand-stamped leaf is a committed\n * budget (§13.2) that this does not need to spend.\n */\nexport function renderDeployChecklist(): TemplateResult | typeof nothing {\n if (!projectState) {\n return nothing;\n }\n const steps = deployChecklist();\n const next = steps.find((step) => step.state !== \"done\") ?? null;\n return html`\n <ul class=\"activity-list\">\n <li class=\"activity-row ${next ? \"activity-row--running\" : \"activity-row--done\"}\">\n <span class=\"activity-icon\" aria-hidden=\"true\">${next ? \"⋯\" : \"✓\"}</span>\n <div class=\"activity-body\">\n <div class=\"activity-head\">\n <span class=\"activity-title\">Deploy checklist</span>\n <span class=\"activity-source\">Publish</span>\n </div>\n <div class=\"activity-status\">\n ${next ? next.detail : \"Everything this project needs to ship is in place.\"}\n </div>\n <ol class=\"activity-steps\">\n ${steps.map(\n (step) => html`<li class=\"activity-step activity-step--${STEP_CLASS[step.state]}\">\n <span class=\"activity-step-icon\" aria-hidden=\"true\">${STEP_ICON[step.state]}</span>\n ${step.label}${step.state === \"done\" ? \"\" : ` — ${step.detail}`}\n </li>`,\n )}\n </ol>\n ${actionTpl(next)}\n </div>\n </li>\n </ul>\n `;\n}\n"
|
|
8
|
-
],
|
|
9
|
-
"mappings": "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",
|
|
10
|
-
"debugId": "F16370A3EAFA6BE564756E2164756E21",
|
|
11
|
-
"names": []
|
|
12
|
-
}
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/services/data-service.ts", "../src/grid/csv-codec.ts", "../src/grid/sources/csv-file-source.ts", "../src/grid/sources/connector-source.ts", "../src/browse/library-model.ts", "../src/browse/library-source.ts", "../src/grid/grid-open.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\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",
|
|
6
|
-
"/**\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",
|
|
7
|
-
"/**\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",
|
|
8
|
-
"/**\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",
|
|
9
|
-
"/**\n * The Library's data model — what a project contains, and how a scan can fail.\n *\n * Two facts the Manage view it replaces could not state:\n *\n * 1. **A scan has failures.** `collectFiles` swallowed every `listDirectory` rejection in an empty\n * catch block, so a project directory the platform could not read simply contributed nothing. A\n * 500 from the dev server and an empty `content/` produced the identical file list and the\n * identical sentence — \"No files found\" — which is the lie §16 exists to end.\n * {@link scanLibrary} returns {@link LibraryScan.failures} beside the files; the pane raises\n * them as Problems with a Retry and refuses to call an incomplete listing empty.\n * 2. **A category has a directory.** The Manage view filtered by category and uploaded to whatever\n * directory the active filter happened to name, which for \"All\" was nothing at all — the upload\n * landed wherever `uploadAssets` defaulted. {@link uploadDirForCategory} still answers, but the\n * pane never uploads to an unnamed destination: it asks.\n *\n * Everything here is pure over its inputs (the scan takes the platform as an argument) so the\n * 300-page acceptance case can be measured without a DOM.\n */\n\nimport { MEDIA_EXTENSIONS, extensionOf } from \"../files/media-upload\";\nimport { projectState } from \"../store\";\nimport { errorMessage } from \"@jxsuite/schema/parse\";\nimport { resolveI18n, servedLocaleOfPath } from \"@jxsuite/schema/locale\";\nimport type { ResolvedI18n } from \"@jxsuite/schema/locale\";\nimport type { ContentSectionEntry, DirEntry, StudioPlatform } from \"../types\";\n\n// ─── Files ───────────────────────────────────────────────────────────────────\n\n/** One row of the Library, whichever layout is drawing it. */\nexport interface LibraryFile {\n name: string;\n path: string;\n /** The content type name for a content file; the extension otherwise. */\n type: string;\n category: string;\n ext: string;\n /** Bytes, when the platform reported them. */\n size?: number | undefined;\n /** ISO timestamp, when the platform reported one. Drives the Calendar layout. */\n modified?: string | undefined;\n /**\n * The locale this file is **served as**, from `@jxsuite/schema/locale`'s `servedLocaleOfPath` —\n * the canonical tag, never the spelling on disk.\n *\n * The path answers it wherever there is a locale directory. Where there is not, `routing` does:\n * under `prefix-except-default` an unprefixed page IS the default locale's copy, and a facet that\n * could filter to French and Arabic but never to English cannot answer the question it is most\n * often asked. That reading stops at `pages/` — an unlocalized collection expands under every\n * locale's route, so calling its entries the default language would be a claim about content that\n * is in none.\n */\n locale?: string | undefined;\n}\n\n/** A directory the scan could not read. Its presence means the listing is INCOMPLETE, not empty. */\nexport interface ScanFailure {\n dir: string;\n error: string;\n}\n\n/** The result of one pass over the project's directories. */\nexport interface LibraryScan {\n files: LibraryFile[];\n failures: ScanFailure[];\n}\n\n// ─── Categories ──────────────────────────────────────────────────────────────\n\n/** A Library category: what it is called, and the directory an upload into it lands in. */\nexport interface LibraryCategory {\n key: string;\n label: string;\n /** Absent for \"All\" — which is why \"All\" has no upload destination and must ask for one. */\n dir?: string;\n}\n\nexport const LIBRARY_CATEGORIES: readonly LibraryCategory[] = [\n { key: \"all\", label: \"All\" },\n { dir: \"pages\", key: \"pages\", label: \"Pages\" },\n { dir: \"layouts\", key: \"layouts\", label: \"Layouts\" },\n { dir: \"components\", key: \"components\", label: \"Components\" },\n { dir: \"content\", key: \"content\", label: \"Content\" },\n { dir: \"public\", key: \"media\", label: \"Media\" },\n];\n\n/** The category keys, for a command's `enum` — so `library.setCategory` refuses an unknown one. */\nexport const LIBRARY_CATEGORY_KEYS: readonly string[] = LIBRARY_CATEGORIES.map((c) => c.key);\n\n/** The category with this key, or undefined. */\nexport function libraryCategory(key: string): LibraryCategory | undefined {\n return LIBRARY_CATEGORIES.find((c) => c.key === key);\n}\n\n/**\n * The directory a drop on the Library targets while `key` is the active category.\n *\n * `undefined` for \"All\" and for any category without one, and the caller MUST treat that as \"ask\",\n * never as \"use the default\": an upload that lands somewhere the author did not choose is the same\n * class of surprise as a rename that silently rewrites files.\n */\nexport function uploadDirForCategory(key: string): string | undefined {\n return libraryCategory(key)?.dir;\n}\n\n/** Map a file path to a display category. Media files override by extension. */\nexport function categoryFor(dir: string, ext: string): string {\n if (ext && MEDIA_EXTENSIONS.has(ext)) {\n return \"Media\";\n }\n if (dir.startsWith(\"pages\")) {\n return \"Pages\";\n }\n if (dir.startsWith(\"layouts\")) {\n return \"Layouts\";\n }\n if (dir.startsWith(\"components\")) {\n return \"Components\";\n }\n if (dir.startsWith(\"content\")) {\n return \"Content\";\n }\n if (dir.startsWith(\"public\")) {\n return \"Media\";\n }\n if (dir.startsWith(\"data\")) {\n return \"Content\";\n }\n if (dir.startsWith(\"styles\")) {\n return \"Components\";\n }\n return \"Other\";\n}\n\n/**\n * The content type a path belongs to, from the project's `content` section — capitalized, or null.\n *\n * @param {string} filePath\n * @returns {string | null}\n */\nexport function contentTypeFor(filePath: string): string | null {\n const content = (projectState?.projectConfig?.content ?? {}) as Record<\n string,\n ContentSectionEntry\n >;\n for (const [name, entry] of Object.entries(content)) {\n if (!entry.source) {\n continue;\n }\n const prefix = entry.source.replace(/^\\.\\//, \"\").replace(/\\/$/, \"\");\n if (filePath.startsWith(`${prefix}/`) || filePath === prefix) {\n return name.charAt(0).toUpperCase() + name.slice(1);\n }\n }\n return null;\n}\n\n// ─── The scan ────────────────────────────────────────────────────────────────\n\n/** Directory names never worth walking — a `node_modules` scan is minutes, not milliseconds. */\nconst SKIP_DIRS = new Set([\"node_modules\", \".git\", \".jx\", \"dist\", \"build\", \".cache\"]);\n\n/**\n * Walk one directory tree, collecting files and recording — never swallowing — what it could not\n * read. A failure at depth is reported against the directory that failed, not the root, so the\n * Problem names the path the author can act on.\n */\nasync function walk(\n dir: string,\n platform: Pick<StudioPlatform, \"listDirectory\">,\n out: LibraryFile[],\n failures: ScanFailure[],\n i18n: ResolvedI18n | null,\n): Promise<void> {\n let entries: DirEntry[];\n try {\n entries = await platform.listDirectory(dir);\n } catch (error) {\n failures.push({ dir, error: errorMessage(error) });\n return;\n }\n const subdirectories: string[] = [];\n for (const entry of entries) {\n if (entry.type === \"directory\") {\n if (!SKIP_DIRS.has(entry.name)) {\n subdirectories.push(entry.path);\n }\n continue;\n }\n const ext = extensionOf(entry.name);\n const category = categoryFor(entry.path, ext);\n out.push({\n category,\n ext,\n locale: servedLocaleOfPath(entry.path, i18n) ?? undefined,\n modified: entry.modified,\n name: entry.name,\n path: entry.path,\n size: entry.size,\n type: category === \"Content\" ? (contentTypeFor(entry.path) ?? ext ?? \"file\") : ext || \"file\",\n });\n }\n // Siblings in parallel, depth serialized per branch: the platform counts every call as in-flight,\n // So `probe.idle()` already knows the scan is running without the Library declaring a source.\n await Promise.all(subdirectories.map((sub) => walk(sub, platform, out, failures, i18n)));\n}\n\n/**\n * Scan the project's declared directories.\n *\n * Never rejects: a scan that half-worked is a real, useful answer that the caller must be able to\n * render honestly, and an exception would throw the good half away with the bad.\n */\nexport async function scanLibrary(\n dirs: readonly string[],\n platform: Pick<StudioPlatform, \"listDirectory\">,\n): Promise<LibraryScan> {\n const files: LibraryFile[] = [];\n const failures: ScanFailure[] = [];\n // Resolved ONCE for the whole walk. `resolveI18n` canonicalizes every declared tag through\n // `Intl.Locale`, and a project with 300 pages would otherwise pay for that per file.\n const { i18n } = resolveI18n(projectState?.projectConfig ?? {});\n await Promise.all(dirs.map((dir) => walk(dir, platform, files, failures, i18n)));\n files.sort((a, b) => a.path.localeCompare(b.path));\n return { failures, files };\n}\n\n// ─── Filtering ───────────────────────────────────────────────────────────────\n\nexport interface LibraryFilter {\n category: string;\n query: string;\n /** A canonical tag, or \"\" for every language. Never a label — the labels are not unique. */\n locale?: string;\n}\n\n/**\n * Category, then text over name and path, then language. Returns the input array unchanged when\n * nothing filters.\n */\nexport function filterLibrary(\n files: readonly LibraryFile[],\n filter: LibraryFilter,\n): readonly LibraryFile[] {\n let result = files;\n const category = libraryCategory(filter.category);\n if (category && category.key !== \"all\") {\n result = result.filter((f) => f.category === category.label);\n }\n const query = filter.query.trim().toLowerCase();\n if (query) {\n result = result.filter(\n (f) => f.name.toLowerCase().includes(query) || f.path.toLowerCase().includes(query),\n );\n }\n const locale = filter.locale?.trim();\n if (locale) {\n result = result.filter((f) => f.locale === locale);\n }\n return result;\n}\n\n// ─── Layouts ─────────────────────────────────────────────────────────────────\n\nexport const LIBRARY_LAYOUTS = [\"table\", \"cards\", \"media\", \"calendar\", \"board\"] as const;\n\nexport type LibraryLayout = (typeof LIBRARY_LAYOUTS)[number];\n\nexport const LIBRARY_LAYOUT_LABELS: Readonly<Record<LibraryLayout, string>> = {\n board: \"Board\",\n calendar: \"Calendar\",\n cards: \"Cards\",\n media: \"Media\",\n table: \"Table\",\n};\n\n/** Whether a string names a layout — the guard behind `library.setLayout`'s argument. */\nexport function isLibraryLayout(value: string): value is LibraryLayout {\n return (LIBRARY_LAYOUTS as readonly string[]).includes(value);\n}\n\n/** Layouts that draw a live preview per item. Table and Board draw text, and stay cheap. */\nexport const PREVIEW_LAYOUTS: ReadonlySet<LibraryLayout> = new Set<LibraryLayout>([\n \"cards\",\n \"media\",\n]);\n\n// ─── Derived axes (Calendar and Board) ───────────────────────────────────────\n\n/** `YYYY-MM-DD` at the head of a filename — the dated-post convention, used when there is no mtime. */\nconst DATE_PREFIX = /^(\\d{4}-\\d{2}-\\d{2})/;\n\n/**\n * The day a file belongs to, as `YYYY-MM-DD`, or null when nothing states one.\n *\n * The filename prefix wins over the filesystem's mtime: a dated post's date is authored content,\n * and mtime is a fact about the last save. A file with neither is not placed on the calendar at all\n * rather than being parked on today — the Calendar says how many it could not date.\n */\nexport function libraryDate(file: LibraryFile): string | null {\n const prefix = DATE_PREFIX.exec(file.name);\n if (prefix) {\n return prefix[1]!;\n }\n if (file.modified) {\n const parsed = new Date(file.modified);\n if (!Number.isNaN(parsed.getTime())) {\n return parsed.toISOString().slice(0, 10);\n }\n }\n return null;\n}\n\n/**\n * The locales this project DECLARES, canonical and in declaration order — the value space of the\n * Library's language facet and of `library.setLocale`'s `enum`.\n *\n * Read at call time rather than cached: `projectState` is a plain binding replaced wholesale on a\n * project switch, so a cached list would describe the project before last.\n */\nexport function projectLocales(): readonly string[] {\n return resolveI18n(projectState?.projectConfig ?? {}).i18n?.locales ?? [];\n}\n\n/**\n * The locales actually PRESENT among these files, in the project's declaration order.\n *\n * Ordered by the project and not by the scan for the reason {@link groupByCategory} orders its\n * columns by {@link LIBRARY_CATEGORIES}: a facet whose options reshuffle when a file is added is a\n * facet nobody can build muscle memory for. Declaration order also puts the default locale first,\n * because {@link resolveI18n} guarantees it is `locales[0]`.\n *\n * Only declared tags can appear — `localeOfPath` matches nothing else — so filtering the\n * declaration through the presence set loses no file.\n */\nexport function libraryLocales(files: readonly LibraryFile[]): string[] {\n const present = new Set<string>();\n for (const file of files) {\n if (file.locale) {\n present.add(file.locale);\n }\n }\n return projectLocales().filter((tag) => present.has(tag));\n}\n\n/** Calendar buckets, newest day first, plus the files no date could be derived for. */\nexport function groupByDate(files: readonly LibraryFile[]): {\n days: { date: string; files: LibraryFile[] }[];\n undated: LibraryFile[];\n} {\n const byDay = new Map<string, LibraryFile[]>();\n const undated: LibraryFile[] = [];\n for (const file of files) {\n const date = libraryDate(file);\n if (date === null) {\n undated.push(file);\n continue;\n }\n const bucket = byDay.get(date);\n if (bucket) {\n bucket.push(file);\n } else {\n byDay.set(date, [file]);\n }\n }\n const days = [...byDay.entries()]\n .map(([date, dayFiles]) => ({ date, files: dayFiles }))\n .toSorted((a, b) => b.date.localeCompare(a.date));\n return { days, undated };\n}\n\n/** Board columns — one per category present, in the Library's own category order, then the rest. */\nexport function groupByCategory(\n files: readonly LibraryFile[],\n): { group: string; files: LibraryFile[] }[] {\n const byGroup = new Map<string, LibraryFile[]>();\n for (const file of files) {\n const bucket = byGroup.get(file.category);\n if (bucket) {\n bucket.push(file);\n } else {\n byGroup.set(file.category, [file]);\n }\n }\n const order = LIBRARY_CATEGORIES.map((c) => c.label);\n return [...byGroup.entries()]\n .map(([group, groupFiles]) => ({ files: groupFiles, group }))\n .toSorted((a, b) => {\n const ai = order.indexOf(a.group);\n const bi = order.indexOf(b.group);\n if (ai === bi) {\n return a.group.localeCompare(b.group);\n }\n return (ai === -1 ? order.length : ai) - (bi === -1 ? order.length : bi);\n });\n}\n",
|
|
10
|
-
"/**\n * The Library as a {@link GridSource}.\n *\n * The Library is one more source over the same contract the CSV, collection, pages and connector\n * grids already use, which is what makes Table a real grid rather than a fifth hand-written table:\n * columns come from {@link libraryColumns}, rows are the scan, and every layout — Cards, Media,\n * Calendar, Board — draws the SAME rows through a different arrangement. A layout switch never\n * re-reads the project.\n *\n * It is a **read-only** source, and says so rather than pretending. Renaming, duplicating and\n * deleting a file are real operations with real consequences (a rename rewrites references; a\n * delete needs the reference count in its confirmation), and they belong to the commands that\n * already do that work correctly. A grid cell that silently renamed a file on blur would bypass\n * both. {@link LibrarySource.commit} therefore refuses, naming the surface that can.\n */\n\nimport { getPlatform } from \"../platform\";\nimport { projectState } from \"../store\";\nimport { makeGridTabId } from \"../grid/grid-source\";\nimport { scanLibrary } from \"./library-model\";\nimport type { LibraryFile, LibraryScan, ScanFailure } from \"./library-model\";\nimport type {\n CommitResult,\n GridColumn,\n GridEditBatch,\n GridRow,\n GridRowsResult,\n GridSource,\n} from \"../grid/grid-source\";\n\n/** Why a cell edit is refused — printed by the grid, so the author is told where to go instead. */\nexport const LIBRARY_READ_ONLY =\n \"The Library lists files; it does not edit them. Rename, duplicate or delete from the file's \" +\n \"context menu, or open the file to edit it.\";\n\n/** The Table layout's columns. `path` is the row key and is never editable. */\nexport function libraryColumns(): GridColumn[] {\n return [\n { editable: false, field: \"name\", kind: \"string\", pk: true, title: \"Name\", widthHint: 260 },\n { editable: false, field: \"category\", kind: \"string\", title: \"Category\", widthHint: 120 },\n { editable: false, field: \"locale\", kind: \"string\", title: \"Locale\", widthHint: 90 },\n { editable: false, field: \"type\", kind: \"string\", title: \"Type\", widthHint: 120 },\n { editable: false, field: \"size\", kind: \"number\", title: \"Size\", widthHint: 90 },\n { editable: false, field: \"modified\", kind: \"date\", title: \"Modified\", widthHint: 160 },\n { editable: false, field: \"path\", kind: \"readonly\", title: \"Path\", widthHint: 320 },\n ];\n}\n\n/** One scanned file as a grid row. */\nexport function libraryRow(file: LibraryFile): GridRow {\n return {\n cells: {\n category: file.category,\n // Null, not \"\": the platform reported no locale directory for this file, and a grid cell\n // Distinguishes \"no value\" from \"the empty string\" everywhere else in this contract.\n locale: file.locale ?? null,\n modified: file.modified ?? null,\n name: file.name,\n path: file.path,\n size: file.size ?? null,\n type: file.type,\n },\n key: file.path,\n };\n}\n\n/**\n * A Library source, plus the two questions a grid source cannot ask but the Library must answer:\n * what the scan could not read, and the files behind the rows (the non-table layouts want the typed\n * record, not a cell bag).\n */\nexport interface LibrarySource extends GridSource {\n /** The scanned files, in path order. Empty before the first {@link GridSource.rows} call. */\n files: () => readonly LibraryFile[];\n /** Directories the last scan could not read. NON-EMPTY MEANS THE LISTING IS INCOMPLETE. */\n failures: () => readonly ScanFailure[];\n /** Whether a scan has completed at least once — \"not loaded yet\" is not \"empty\". */\n scanned: () => boolean;\n}\n\n/** The Library's tab id. One Library per window; category and layout are view state, not identity. */\nexport function libraryTabId(): string {\n return makeGridTabId({ kind: \"library\" });\n}\n\n/**\n * Build the Library source. The scan is lazy: nothing is read until the first `rows()`.\n *\n * @param {() => readonly string[]} [dirs] Project directories to scan, injectable for tests and for\n * the perf measurement; defaults to the open project's own list.\n */\nexport function createLibrarySource(dirs?: () => readonly string[]): LibrarySource {\n let scan: LibraryScan | null = null;\n let inFlight: Promise<LibraryScan> | null = null;\n\n const projectDirs = dirs ?? (() => (projectState?.projectDirs ?? []) as readonly string[]);\n\n async function ensureScan(): Promise<LibraryScan> {\n if (scan) {\n return scan;\n }\n // Coalesce: five layouts and a command can all ask at once on the first paint, and the answer\n // Is one walk of the project, not six.\n inFlight ??= scanLibrary(projectDirs(), getPlatform()).then((result) => {\n scan = result;\n inFlight = null;\n return result;\n });\n return inFlight;\n }\n\n return {\n capabilities: { delete: false, insert: false, remotePaging: false, remoteSort: false },\n columns: () => Promise.resolve(libraryColumns()),\n commit(batch: GridEditBatch): Promise<CommitResult> {\n return Promise.resolve({\n cells: batch.cells.map((cell) => ({\n error: LIBRARY_READ_ONLY,\n field: cell.field,\n ok: false,\n rowKey: cell.rowKey,\n })),\n deletes: batch.deletes.map((row) => ({\n error: LIBRARY_READ_ONLY,\n ok: false,\n rowKey: row.rowKey,\n })),\n inserts: batch.inserts.map((row) => ({\n error: LIBRARY_READ_ONLY,\n ok: false,\n tempKey: row.tempKey,\n })),\n });\n },\n failures: () => scan?.failures ?? [],\n files: () => scan?.files ?? [],\n id: libraryTabId(),\n label: \"Library\",\n async refresh() {\n scan = null;\n inFlight = null;\n await ensureScan();\n },\n async rows(): Promise<GridRowsResult> {\n const result = await ensureScan();\n return { rows: result.files.map((file) => libraryRow(file)), total: result.files.length };\n },\n scanned: () => scan !== null,\n };\n}\n",
|
|
11
|
-
"/**\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 { libraryTabId } from \"../browse/library-source\";\nimport { argsSchema, optionalStringArg, stringArg, stringProperty } from \"../commands/command-args\";\nimport type { GridSource } from \"./grid-source\";\nimport type { Tab } from \"../tabs/tab\";\nimport type { AnyCommand, CommandRegistry } from \"../commands/registry\";\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/**\n * Open (or activate) the Library.\n *\n * A real tab, in the primary pane, with `manage` as its only mode — `commands/context.ts` maps that\n * to the `library` editor kind, so the status bar and the pane context bar can name what is on\n * screen. It is opened here rather than in `browse/` because this is the module that knows how a\n * virtual tab is made; the pane itself resolves its own source and its own view state.\n *\n * Idempotent by construction, which is what lets a shot say \"the Library is open\" without caring\n * whether an earlier step opened it.\n */\nexport function openLibraryTab(): Tab {\n const id = libraryTabId();\n const existing = workspace.tabs.get(id);\n if (existing) {\n activateTab(id);\n return existing;\n }\n return openTab({\n capabilities: { modes: [\"manage\"] },\n document: structuredClone(GRID_STUB_DOCUMENT),\n documentPath: null,\n id,\n });\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 { label: \"Open Grid\" },\n );\n}\n\n// ─── Commands ─────────────────────────────────────────────────────────────────\n\n/**\n * The grid openers, as commands.\n *\n * `collection.editInGrid` used to be a press on the file tree's context-menu row, matched by the\n * item's rendered label (\"Edit Collection in Grid\") through an XPath — so the shot that used it\n * also had to open the menu first, and renaming the row broke both steps. Naming the COLLECTION\n * instead of the control is what plan §13's R1 asks for: the menu row and the command are the same\n * action, and only one of them is addressable.\n *\n * Both refuse a source the project does not declare. `data.openGrid` is additionally gated on the\n * platform serving the data routes (`capability.dataRows`), so on a build without them the command\n * is visible-but-disabled with a reason rather than opening a tab that can never load.\n *\n * @returns {AnyCommand[]}\n */\nexport function gridCommands(): AnyCommand[] {\n return [\n {\n args: argsSchema({\n name: stringProperty(\"The content collection's name, as project.json declares it.\"),\n }),\n category: \"Project\",\n id: \"collection.editInGrid\",\n level: \"project\",\n menus: [\"context/file\", \"palette\"],\n group: \"5_data\",\n requires: \"a project that declares content collections\",\n when: (ctx) => ctx.project.open,\n aiTool: {\n description: \"Open a content collection's entries as an editable grid in a new tab.\",\n name: \"open_collection_grid\",\n },\n run: (_commandCtx, args) => {\n const name = stringArg(\"collection.editInGrid\", args, \"name\");\n const declared = collectionDirs().map((c) => c.name);\n if (!declared.includes(name)) {\n throw new RangeError(\n `command \"collection.editInGrid\" argument \"name\": \"${name}\" is not a content ` +\n `collection this project declares — it declares: ` +\n `${declared.length > 0 ? declared.join(\", \") : \"none\"}`,\n );\n }\n openCollectionGrid(name);\n },\n title: \"Edit Collection in Grid\",\n },\n {\n args: {\n additionalProperties: false,\n properties: {\n connection: stringProperty(\n 'The connection name from project.json. Defaults to \"default\".',\n ),\n table: stringProperty(\"The table to open.\"),\n },\n required: [\"table\"],\n type: \"object\",\n },\n category: \"Project\",\n id: \"data.openGrid\",\n level: \"project\",\n menus: [\"palette\"],\n group: \"5_data\",\n requires: \"a platform that serves the data routes\",\n when: (ctx) => ctx.project.open,\n enablement: (ctx) => ctx.capability.dataRows,\n aiTool: {\n description: \"Open a connector table as an editable grid in a new tab.\",\n name: \"open_data_grid\",\n },\n run: (_commandCtx, args) => {\n const table = stringArg(\"data.openGrid\", args, \"table\");\n openConnectorGrid(optionalStringArg(\"data.openGrid\", args, \"connection\"), table);\n },\n title: \"Open Data Grid\",\n },\n ];\n}\n\n/**\n * Register the grid openers.\n *\n * @param {CommandRegistry} registry\n */\nexport function registerGridCommands(registry: CommandRegistry): void {\n registry.registerAll(gridCommands());\n}\n"
|
|
12
|
-
],
|
|
13
|
-
"mappings": "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",
|
|
14
|
-
"debugId": "B5A73986FCDCB07464756E2164756E21",
|
|
15
|
-
"names": []
|
|
16
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/settings/section-registry.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * The Project Settings section registry, and which of its sections the document is showing.\n *\n * `registerSettingsSection` is a **preserved public contract** (specs/extensions.md §9.1): an\n * extension's `project` class declares a `$studio.settings` block and `settings/extension-sections`\n * turns it into one of these records. P6 moved Project Settings out of a modal and into a document\n * in the pane; the registry did not move with it, because a section is a contribution to\n * CONFIGURATION, not to a dialog. Splitting it out is what lets the host be replaced without the\n * contribution point being touched.\n *\n * **This module holds no renderer and imports nothing.** That is load-bearing rather than tidy:\n * `panels/settings-pane.ts` is reached from `canvas/canvas-render.ts`, so anything this module\n * imports becomes part of the canvas's import graph. The section RENDERERS are registered by\n * `settings/settings-document.ts`, which the app loads when it registers its commands.\n *\n * **What is requested and what is displayed are two variables, and unregistering touches neither.**\n * The modal had one, and its `unregisterSettingsSection` reset it to `\"general\"` — which is half of\n * the deep-link race P6 exists to close. The contribution sync unregisters stale keys before it\n * registers fresh ones, so a section merely being REFRESHED took the caller's requested section\n * down with it, silently, after the awaited readiness promise had already resolved. Here a request\n * outlives its section going away and is satisfied the moment the key comes back.\n */\n\n/** A Project Settings section: an inner-nav entry plus a renderer for the content area. */\nexport interface SettingsSection {\n key: string;\n label: string;\n /** Nav icon name (reserved for future nav treatments). */\n icon?: string | undefined;\n /** Sort position — lower orders render higher in the inner nav. */\n order: number;\n render: (container: HTMLElement) => void;\n}\n\n/** Where a settings document lands when nobody named a section. */\nexport const DEFAULT_SETTINGS_SECTION = \"overview\";\n\nconst sections = new Map<string, SettingsSection>();\n\nconst listeners = new Set<() => void>();\n\n/**\n * Tell every subscriber something changed.\n *\n * A `Set` tolerates deletion during its own iteration, so a listener that unsubscribes itself (the\n * pane host, on unmount) is safe without copying.\n */\nfunction announce(): void {\n for (const listener of listeners) {\n listener();\n }\n}\n\n/**\n * Redraw the settings document — for a change this module cannot see, such as a command selecting\n * an entry inside the section that is already on screen.\n */\nexport function notifySettingsDocument(): void {\n announce();\n}\n\n/**\n * Subscribe to everything that changes what the settings document draws: the section set (an\n * extension registering or going away) and the chosen section. Returns the unsubscribe.\n *\n * @param {() => void} listener\n * @returns {() => void}\n */\nexport function onSettingsDocumentChanged(listener: () => void): () => void {\n listeners.add(listener);\n return () => {\n listeners.delete(listener);\n };\n}\n\n// ─── Registration ─────────────────────────────────────────────────────────────\n\n/**\n * Register (or replace) a settings section.\n *\n * @param {SettingsSection} section\n */\nexport function registerSettingsSection(section: SettingsSection): void {\n sections.set(section.key, section);\n announce();\n}\n\n/**\n * Remove a registered section — used when a descriptor-contributed section's extension is disabled\n * (see ./extension-sections). Built-ins are never unregistered.\n *\n * @param {string} key\n */\nexport function unregisterSettingsSection(key: string): void {\n if (sections.delete(key)) {\n announce();\n }\n}\n\n/** Registered sections sorted by order (registration order breaks ties). */\nexport function sortedSettingsSections(): SettingsSection[] {\n return [...sections.values()].toSorted((a, b) => a.order - b.order);\n}\n\n/** Every registered section key, built-ins and contributions alike, in display order. */\nexport function settingsSectionKeys(): string[] {\n return sortedSettingsSections().map((section) => section.key);\n}\n\n/**\n * One section by key, or `undefined`.\n *\n * @param {string} key\n * @returns {SettingsSection | undefined}\n */\nexport function settingsSection(key: string): SettingsSection | undefined {\n return sections.get(key);\n}\n\n// ─── Which section is on screen ───────────────────────────────────────────────\n\n/** The section the last caller ASKED for, kept until it is satisfied. */\nlet _requested: string | null = null;\n\n/** The section the document is drawing. Only a nav click and a satisfied request move it. */\nlet _displayed = DEFAULT_SETTINGS_SECTION;\n\n/**\n * The section key the document should render right now.\n *\n * A pending request wins as soon as its section exists. Otherwise the displayed one, and — when\n * that has been unregistered too — the first section there is, so the content area is never blank\n * because of bookkeeping.\n *\n * @returns {string}\n */\nexport function settingsDocumentSection(): string {\n if (_requested !== null && sections.has(_requested)) {\n _displayed = _requested;\n _requested = null;\n return _displayed;\n }\n if (sections.has(_displayed)) {\n return _displayed;\n }\n return settingsSectionKeys()[0] ?? _displayed;\n}\n\n/**\n * Show a section. A nav click satisfies itself immediately; a deep link to a section that has not\n * registered yet is remembered until it does.\n *\n * @param {string} key\n */\nexport function setSettingsSection(key: string): void {\n if (sections.has(key)) {\n _displayed = key;\n _requested = null;\n } else {\n _requested = key;\n }\n announce();\n}\n\n/** Forget the chosen section — the project-close and test hook. */\nexport function resetSettingsDocumentState(): void {\n _requested = null;\n _displayed = DEFAULT_SETTINGS_SECTION;\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";AAmCO,IAAM,2BAA2B;AAExC,IAAM,WAAW,IAAI;AAErB,IAAM,YAAY,IAAI;AAQtB,SAAS,QAAQ,GAAS;AAAA,EACxB,WAAW,YAAY,WAAW;AAAA,IAChC,SAAS;AAAA,EACX;AAAA;AAOK,SAAS,sBAAsB,GAAS;AAAA,EAC7C,SAAS;AAAA;AAUJ,SAAS,yBAAyB,CAAC,UAAkC;AAAA,EAC1E,UAAU,IAAI,QAAQ;AAAA,EACtB,OAAO,MAAM;AAAA,IACX,UAAU,OAAO,QAAQ;AAAA;AAAA;AAWtB,SAAS,uBAAuB,CAAC,SAAgC;AAAA,EACtE,SAAS,IAAI,QAAQ,KAAK,OAAO;AAAA,EACjC,SAAS;AAAA;AASJ,SAAS,yBAAyB,CAAC,KAAmB;AAAA,EAC3D,IAAI,SAAS,OAAO,GAAG,GAAG;AAAA,IACxB,SAAS;AAAA,EACX;AAAA;AAIK,SAAS,sBAAsB,GAAsB;AAAA,EAC1D,OAAO,CAAC,GAAG,SAAS,OAAO,CAAC,EAAE,SAAS,CAAC,GAAG,MAAM,EAAE,QAAQ,EAAE,KAAK;AAAA;AAI7D,SAAS,mBAAmB,GAAa;AAAA,EAC9C,OAAO,uBAAuB,EAAE,IAAI,CAAC,YAAY,QAAQ,GAAG;AAAA;AASvD,SAAS,eAAe,CAAC,KAA0C;AAAA,EACxE,OAAO,SAAS,IAAI,GAAG;AAAA;AAMzB,IAAI,aAA4B;AAGhC,IAAI,aAAa;AAWV,SAAS,uBAAuB,GAAW;AAAA,EAChD,IAAI,eAAe,QAAQ,SAAS,IAAI,UAAU,GAAG;AAAA,IACnD,aAAa;AAAA,IACb,aAAa;AAAA,IACb,OAAO;AAAA,EACT;AAAA,EACA,IAAI,SAAS,IAAI,UAAU,GAAG;AAAA,IAC5B,OAAO;AAAA,EACT;AAAA,EACA,OAAO,oBAAoB,EAAE,MAAM;AAAA;AAS9B,SAAS,kBAAkB,CAAC,KAAmB;AAAA,EACpD,IAAI,SAAS,IAAI,GAAG,GAAG;AAAA,IACrB,aAAa;AAAA,IACb,aAAa;AAAA,EACf,EAAO;AAAA,IACL,aAAa;AAAA;AAAA,EAEf,SAAS;AAAA;AAIJ,SAAS,0BAA0B,GAAS;AAAA,EACjD,aAAa;AAAA,EACb,aAAa;AAAA;",
|
|
8
|
-
"debugId": "19468228E71CB42E64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/panels/panel-scheduler.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/// <reference lib=\"dom\" />\n/**\n * Panel-scheduler.ts — Shared focus-aware render scheduler for Studio panels.\n *\n * Generalizes the guard that previously lived only in the right panel: render requests are\n * coalesced via requestAnimationFrame and DEFERRED while a text input inside the panel root is\n * focused, then flushed on focusout. Routing every render path (reactive effect, renderOnly(...),\n * explicit calls) through one scheduler means a focused field is never rebuilt mid-edit — which is\n * what previously truncated or dropped characters in the document/head sidebar.\n */\n\n/**\n * Is the element (or its shadow-DOM active descendant) a text-entry control whose value would be\n * clobbered by a re-render? Covers native inputs and the Spectrum web components used in panels.\n *\n * @param {Element | null} el\n * @returns {boolean}\n */\nexport function isTextInput(el: Element | null): boolean {\n if (!el) {\n return false;\n }\n const tag = el.tagName.toLowerCase();\n if (tag === \"input\" || tag === \"textarea\") {\n return true;\n }\n if (tag === \"sp-textfield\" || tag === \"sp-number-field\" || tag === \"sp-search\") {\n return true;\n }\n if (el.shadowRoot?.activeElement) {\n return isTextInput(el.shadowRoot.activeElement);\n }\n return false;\n}\n\n/**\n * Every bound scheduler, so \"is any panel still owing a repaint?\" has one answer.\n *\n * Condition 2 of the `probe.idle()` predicate (`services/idle.ts`, spec §13.5). Each scheduler\n * already knew whether it had a frame queued or a render withheld; nothing could ask all of them at\n * once. P4.4 makes the withheld case visible to the author too — a panel silently showing stale\n * state is a bug whichever consumer notices it first.\n */\nconst boundSchedulers = new Set<TrackedScheduler>();\n\ninterface TrackedScheduler {\n /** The panel root, for the human-readable blocker string. */\n root: HTMLElement;\n /** A coalescing frame is queued and will paint. */\n hasFrame: () => boolean;\n /** A render was requested and is being WITHHELD because a field in the panel has focus. */\n isDeferring: () => boolean;\n}\n\n/** `#right-panel`, `.frontmatter-panel`, `div` — the most specific handle the root offers. */\nfunction describeRoot(root: HTMLElement): string {\n if (root.id) {\n return `#${root.id}`;\n }\n const first = root.className.split(/\\s+/).find(Boolean);\n return first ? `.${first}` : root.tagName.toLowerCase();\n}\n\n/**\n * One line per panel that still owes a repaint — empty when every panel's DOM matches its state.\n *\n * A withheld render is reported separately from a queued one because they end differently: a queued\n * frame lands on its own, a withheld one waits for a focusout that may never come. A predicate that\n * conflated them would either hang or lie.\n */\nexport function pendingSchedulers(): string[] {\n const blockers: string[] = [];\n for (const entry of boundSchedulers) {\n if (entry.hasFrame()) {\n blockers.push(`${describeRoot(entry.root)} has a frame queued`);\n } else if (entry.isDeferring()) {\n blockers.push(`${describeRoot(entry.root)} is withholding a render (a field has focus)`);\n }\n }\n return blockers;\n}\n\nexport interface PanelScheduler {\n /** Request a render. Coalesced; deferred while a text input in the panel is focused. */\n schedule: () => void;\n /** True when a render would currently be deferred (text input focused or blockWhile()). */\n isEditing: () => boolean;\n /** Attach focusin/focusout listeners to the panel root. */\n bindFocus: () => void;\n /** Detach listeners and cancel any pending frame. */\n unbind: () => void;\n /** Render immediately, bypassing the rAF coalescing (still respects the focus guard). */\n flushNow: () => void;\n}\n\n/**\n * Create a focus-aware render scheduler bound to a panel root.\n *\n * @param {{\n * root: HTMLElement;\n * render: () => void;\n * blockWhile?: () => boolean;\n * }} opts\n * - `render` does the actual DOM paint; `blockWhile` is an extra defer predicate (e.g. a color\n * popover being open).\n * @returns {PanelScheduler}\n */\nexport function createPanelScheduler(opts: {\n root: HTMLElement;\n render: () => void;\n blockWhile?: () => boolean;\n}): PanelScheduler {\n const { root, render, blockWhile } = opts;\n let editing = false;\n let scheduled = false;\n let pending = false;\n let rendering = false;\n let rafId = 0;\n\n const blocked = () => editing || (blockWhile ? blockWhile() : false);\n\n /**\n * Publish the withheld render to the person looking at the panel.\n *\n * A deferred render is the panel deciding, correctly, that finishing your sentence matters more\n * than being current — but until P4 it made that trade in silence, so a panel showing state from\n * before your last edit was indistinguishable from a panel that had stopped working. The\n * attribute is the whole mechanism: `styles/overlays.css` hangs the hint off it, so every panel\n * that already routes through this scheduler inherits it without a line of its own.\n */\n function markStale(stale: boolean) {\n if (stale) {\n root.dataset.jxStale = \"\";\n } else {\n delete root.dataset.jxStale;\n }\n }\n\n function flush() {\n scheduled = false;\n rafId = 0;\n if (rendering) {\n return;\n }\n // Defer while a field is focused — flushed later by focusout (or the next schedule()).\n if (blocked()) {\n pending = true;\n markStale(true);\n return;\n }\n pending = false;\n markStale(false);\n rendering = true;\n try {\n render();\n } finally {\n rendering = false;\n }\n }\n\n function schedule() {\n if (scheduled) {\n return;\n }\n scheduled = true;\n rafId = requestAnimationFrame(flush);\n }\n\n function onFocusIn(e: FocusEvent) {\n editing = isTextInput(e.target as Element);\n }\n\n function onFocusOut() {\n // Clear the editing flag and schedule a flush. If focus is merely moving to another field in\n // The same panel, the synchronous focusin that follows re-sets `editing` before the rAF runs,\n // So the deferred render keeps waiting (no mid-edit clobber).\n editing = false;\n if (pending) {\n schedule();\n }\n }\n\n const tracked: TrackedScheduler = {\n hasFrame: () => scheduled,\n isDeferring: () => pending,\n root,\n };\n boundSchedulers.add(tracked);\n\n return {\n bindFocus() {\n root.addEventListener(\"focusin\", onFocusIn);\n root.addEventListener(\"focusout\", onFocusOut);\n },\n flushNow() {\n if (rafId) {\n cancelAnimationFrame(rafId);\n }\n rafId = 0;\n scheduled = false;\n flush();\n },\n isEditing: () => blocked(),\n schedule,\n unbind() {\n boundSchedulers.delete(tracked);\n root.removeEventListener(\"focusin\", onFocusIn);\n root.removeEventListener(\"focusout\", onFocusOut);\n if (rafId) {\n cancelAnimationFrame(rafId);\n }\n scheduled = false;\n pending = false;\n editing = false;\n markStale(false);\n rendering = false;\n },\n };\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "590200A08A20676A64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../node_modules/@spectrum-web-components/shared/src/focusable-selectors.dev.js"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"\"use strict\";\nconst focusables = [\n \"input:not([inert])\",\n \"select:not([inert])\",\n \"textarea:not([inert])\",\n \"a[href]:not([inert])\",\n \"button:not([inert])\",\n \"label:not([inert])\",\n \"[tabindex]:not([inert])\",\n \"audio[controls]:not([inert])\",\n \"video[controls]:not([inert])\",\n '[contenteditable]:not([contenteditable=\"false\"]):not([inert])',\n \"details>summary:first-of-type:not([inert])\",\n \"details:not([inert])\",\n '[focusable]:not([focusable=\"false\"])'\n // custom dev use-case\n];\nconst userFocuable = ':not([tabindex=\"-1\"])';\nexport const userFocusableSelector = focusables.join(`${userFocuable}, `) + userFocuable;\nexport const focusableSelector = focusables.join(\", \");\n//# sourceMappingURL=focusable-selectors.dev.js.map\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": ";AACA,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAEF;AACA,IAAM,eAAe;AACd,IAAM,wBAAwB,WAAW,KAAK,GAAG,gBAAgB,IAAI;AACrE,IAAM,oBAAoB,WAAW,KAAK,IAAI;",
|
|
8
|
-
"debugId": "C459DDE0C838F70964756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/ui/virtual-window.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"/**\n * Virtual-window.ts — the windowing primitive behind every long list in Studio.\n *\n * **Why this is the acceptance criterion and not a nicety.** The Manage view the Library replaces\n * rendered one card per file with no cap, and each Pages/Layouts/Components/Content card mounted a\n * REAL `@jxsuite/runtime` render of that document. Opening \"All\" on a 300-page project therefore\n * built 300 live documents, in one synchronous lit pass, and kept every one of them alive in an\n * unbounded `Map`. The window is what makes the cost proportional to the VIEWPORT instead of to the\n * project. The two trees pay a smaller version of the same bill — a 5 000-node page drew 5 000\n * rows, each an `sp-icon` custom element — and they now pay it through this file.\n *\n * **It lives in `ui/`, not in `browse/`.** P3 workstream 11 promised \"one virtual-list primitive\n * behind the Files tree and the Outline tree, reused by the Library grid\", and what shipped sat\n * inside the Library and was imported by the Library alone. A primitive two surfaces share cannot\n * live inside one of them: the next surface that needs it either reaches across a feature boundary\n * or writes a second copy, and a second copy is how \"the tree renders every row\" survived a phase\n * that had already solved it.\n *\n * The maths is deliberately a pure function ({@link computeWindow}) rather than a class: it is the\n * part that has to be right, it is the part the perf test measures, and it needs no DOM to state.\n * {@link createVirtualWindow} is the thin observer that feeds it scroll positions, and the\n * {@link nearestScroller} half below is the small amount of DOM a list that does NOT own its own\n * scrollbar needs — both trees scroll inside `#left-panel`, which also holds their toolbars.\n *\n * One primitive, three surfaces: the Library (Table rows, Cards, Media), the Files tree and the\n * Outline. The geometry never mentions what an item IS.\n */\n\n/// <reference lib=\"dom\" />\n\nimport { rectOf } from \"../utils/geometry\";\n\n/** The measurement a window is computed from. Everything is in CSS pixels. */\nexport interface WindowSpec {\n /** How many items exist in total. */\n count: number;\n /** Height of one ROW. A grid row holds {@link WindowSpec.columns} items. */\n rowHeight: number;\n /** Items per row. 1 for a list. Clamped to at least 1. */\n columns?: number;\n /** The scroller's current `scrollTop`. */\n scrollTop: number;\n /** The scroller's visible height. */\n viewportHeight: number;\n /** Extra rows rendered above and below the viewport. Defaults to {@link DEFAULT_OVERSCAN_ROWS}. */\n overscanRows?: number;\n}\n\n/**\n * Which items to render, and how much empty space to reserve either side of them.\n *\n * `padTop`/`padBottom` are spacer heights rather than absolute positioning, so a windowed list is\n * still an ordinary flow container: it wraps, it prints, and a focused control inside it scrolls\n * into view without anything computing coordinates.\n */\nexport interface WindowRange {\n /** First item index, inclusive. */\n start: number;\n /** Last item index, EXCLUSIVE. */\n end: number;\n /** Pixels of spacer above the first rendered row. */\n padTop: number;\n /** Pixels of spacer below the last rendered row. */\n padBottom: number;\n /** Total rows the full list would occupy — what the scrollbar is sized from. */\n totalRows: number;\n}\n\n/**\n * Rows kept beyond each edge of the viewport.\n *\n * Three, not zero: a window with no overscan repaints on every scroll frame and shows a blank strip\n * for one frame at speed. Three is the smallest value at which neither is observable at a normal\n * wheel velocity, and it is small enough that the LRU preview cap still dominates.\n */\nexport const DEFAULT_OVERSCAN_ROWS = 3;\n\n/** Clamp `value` into `[low, high]`. */\nfunction clamp(value: number, low: number, high: number): number {\n return Math.min(high, Math.max(low, value));\n}\n\n/**\n * The visible window for a spec.\n *\n * Total-safe by construction: a zero or negative `rowHeight` (an unmeasured container, a display:\n * none pane) yields the whole list rather than an infinite loop or an empty render, because a\n * Library that renders nothing is indistinguishable from a Library that found nothing — the exact\n * confusion this phase exists to remove.\n */\nexport function computeWindow(spec: WindowSpec): WindowRange {\n const count = Math.max(0, Math.trunc(spec.count));\n const columns = Math.max(1, Math.trunc(spec.columns ?? 1));\n const totalRows = Math.ceil(count / columns);\n\n if (!(spec.rowHeight > 0) || !(spec.viewportHeight > 0)) {\n return { end: count, padBottom: 0, padTop: 0, start: 0, totalRows };\n }\n\n const overscan = Math.max(0, Math.trunc(spec.overscanRows ?? DEFAULT_OVERSCAN_ROWS));\n const scrollTop = Math.max(0, spec.scrollTop);\n const firstVisibleRow = Math.floor(scrollTop / spec.rowHeight);\n const visibleRows = Math.ceil(spec.viewportHeight / spec.rowHeight) + 1;\n\n const startRow = clamp(firstVisibleRow - overscan, 0, totalRows);\n const endRow = clamp(firstVisibleRow + visibleRows + overscan, startRow, totalRows);\n\n return {\n end: Math.min(count, endRow * columns),\n padBottom: (totalRows - endRow) * spec.rowHeight,\n padTop: startRow * spec.rowHeight,\n start: Math.min(count, startRow * columns),\n totalRows,\n };\n}\n\n/** Two ranges are the same window — the guard that keeps scrolling from repainting every frame. */\nexport function sameWindow(a: WindowRange, b: WindowRange): boolean {\n return a.start === b.start && a.end === b.end && a.totalRows === b.totalRows;\n}\n\n// ─── The observer ────────────────────────────────────────────────────────────\n\nexport interface VirtualWindow {\n /** The current range. Read during render; never stale by more than one frame. */\n range: () => WindowRange;\n /** Re-measure and recompute (count changed, layout changed, container resized). */\n measure: () => void;\n /** Stop listening. Idempotent. */\n destroy: () => void;\n}\n\nexport interface VirtualWindowOptions {\n /** The element that scrolls. */\n scroller: HTMLElement;\n /**\n * The list inside `scroller`, when the scroller carries more than the list.\n *\n * Both trees scroll inside `#left-panel`, which also holds a project header, a toolbar and — for\n * the Files tree — a search field. Their first row is therefore NOT at `scrollTop` 0, and a\n * window computed from the scroller's own `scrollTop` would be that header's height out from the\n * first scroll onwards. Omit it when the list IS the scroller (the Library's pane).\n */\n list?: HTMLElement;\n /** Item count right now — read on every measure, so it may change without re-creating. */\n count: () => number;\n /** Row height right now. */\n rowHeight: () => number;\n /** Items per row right now. */\n columns?: () => number;\n /** Called only when the window actually CHANGED. */\n onChange: (range: WindowRange) => void;\n overscanRows?: number;\n}\n\n/**\n * Watch a scroller and report window changes.\n *\n * Scroll is listened to passively and answered synchronously: the range is cheap to compute and a\n * rAF hop would paint the spacer before the content one frame in three. `ResizeObserver` covers the\n * pane being resized; where the environment has none (happy-dom), `measure()` is the whole contract\n * and the caller drives it — which is also how the perf test drives it.\n */\nexport function createVirtualWindow(options: VirtualWindowOptions): VirtualWindow {\n const { scroller, list, count, rowHeight, columns, onChange, overscanRows } = options;\n let current: WindowRange = { end: 0, padBottom: 0, padTop: 0, start: 0, totalRows: 0 };\n let destroyed = false;\n\n function measure() {\n if (destroyed) {\n return;\n }\n const next = computeWindow({\n columns: columns?.() ?? 1,\n count: count(),\n overscanRows: overscanRows ?? DEFAULT_OVERSCAN_ROWS,\n rowHeight: rowHeight(),\n scrollTop: list ? listScrollTop(scroller, list) : scroller.scrollTop,\n viewportHeight: scroller.clientHeight,\n });\n const changed = !sameWindow(current, next);\n current = next;\n if (changed) {\n onChange(next);\n }\n }\n\n scroller.addEventListener(\"scroll\", measure, { passive: true });\n\n let resizeObserver: ResizeObserver | null = null;\n if (typeof ResizeObserver === \"function\") {\n resizeObserver = new ResizeObserver(() => measure());\n resizeObserver.observe(scroller);\n }\n\n measure();\n\n return {\n destroy() {\n destroyed = true;\n scroller.removeEventListener(\"scroll\", measure);\n resizeObserver?.disconnect();\n resizeObserver = null;\n },\n measure,\n range: () => current,\n };\n}\n\n// ─── A list that does not own its scrollbar ──────────────────────────────────\n\n/**\n * The element that scrolls `el`, or null when nothing does.\n *\n * TWO conditions, and the second is the one that makes this honest. An element is the scroller only\n * if it both declares a scrolling overflow AND currently has something to scroll. `.file-tree`\n * declares `overflow-y: auto` (styles/panels.css) but is never given a height, so it grows with its\n * content and never scrolls — treating it as the scroller would read its full content height as the\n * VIEWPORT height and window nothing at all, silently. The `scrollHeight > clientHeight` test walks\n * past it to `#left-panel`, which is where both trees actually scroll.\n *\n * The same test is why a list whose content fits is never windowed: there is nothing to scroll, so\n * there is nothing to save, and the whole list renders exactly as it always did.\n */\nexport function nearestScroller(el: HTMLElement | null): HTMLElement | null {\n for (let node: HTMLElement | null = el; node; node = node.parentElement) {\n // Cheap test first: happy-dom performs no layout, so this is 0 > 0 for every element and no\n // Test ever pays for a `getComputedStyle` walk it cannot answer.\n if (node.scrollHeight <= node.clientHeight) {\n continue;\n }\n const overflow = getComputedStyle(node).overflowY;\n if (overflow === \"auto\" || overflow === \"scroll\" || overflow === \"overlay\") {\n return node;\n }\n }\n return null;\n}\n\n/**\n * How far `list`'s first row has scrolled above the top of `scroller`'s viewport.\n *\n * Measured from the two rects rather than from `offsetTop`, because the chrome between them is not\n * a fixed height: the Files tree's toolbar and the project header are both conditional. When the\n * list IS the scroller there is no chrome and its own `scrollTop` is the answer.\n */\nexport function listScrollTop(scroller: HTMLElement, list: HTMLElement): number {\n if (scroller === list) {\n return Math.max(0, scroller.scrollTop);\n }\n return Math.max(0, rectOf(scroller).top - rectOf(list).top);\n}\n\n/**\n * The window for a list rendered inside whatever scrolls it — the trees' entry point.\n *\n * Answers \"the whole list\" for a list that has not been rendered yet, has been detached, or is not\n * inside anything that scrolls. That is not a fallback bolted on for tests: it is the FIRST paint\n * of every session (nothing can be measured before the rows exist), and it is every list short\n * enough to fit. Both must render everything, and both are what the trees did before they\n * windowed.\n */\nexport function listWindow(\n list: HTMLElement | null,\n spec: { count: number; rowHeight: number; columns?: number; overscanRows?: number },\n): WindowRange {\n const scroller = list?.isConnected === true ? nearestScroller(list) : null;\n if (!scroller || !list) {\n const count = Math.max(0, Math.trunc(spec.count));\n return { end: count, padBottom: 0, padTop: 0, start: 0, totalRows: count };\n }\n return computeWindow({\n columns: spec.columns ?? 1,\n count: spec.count,\n ...(spec.overscanRows === undefined ? {} : { overscanRows: spec.overscanRows }),\n rowHeight: spec.rowHeight,\n scrollTop: listScrollTop(scroller, list),\n viewportHeight: scroller.clientHeight,\n });\n}\n\n/**\n * The `scrollTop` that brings row `index` into view, or null when it already is.\n *\n * `block: \"nearest\"` semantics, stated as arithmetic: a windowed list cannot delegate this to\n * `Element.scrollIntoView`, because the row it must reveal is precisely the one that has no\n * element. Pure, so the reveal rule is testable without a scroller.\n */\nexport function scrollTopToReveal(spec: {\n index: number;\n rowHeight: number;\n /** Where the list's first row sits in the scroller's CONTENT, not its viewport. */\n listOffset: number;\n scrollTop: number;\n viewportHeight: number;\n}): number | null {\n const top = spec.listOffset + spec.index * spec.rowHeight;\n const bottom = top + spec.rowHeight;\n if (top < spec.scrollTop) {\n return Math.max(0, top);\n }\n if (bottom > spec.scrollTop + spec.viewportHeight) {\n return Math.max(0, bottom - spec.viewportHeight);\n }\n return null;\n}\n\n/**\n * Scroll `list` so that its row at `index` is inside the window on the next render.\n *\n * Returns whether anything moved. The re-render is deliberately NOT triggered here: assigning\n * `scrollTop` fires a `scroll` event, and the watch installed by {@link watchListWindow} is already\n * the one thing that decides when a scroll is worth a repaint. A caller that repainted as well\n * would paint twice for one keystroke.\n */\nexport function revealListRow(list: HTMLElement | null, index: number, rowHeight: number): boolean {\n const scroller = list?.isConnected === true ? nearestScroller(list) : null;\n if (!scroller || !list || index < 0 || !(rowHeight > 0)) {\n return false;\n }\n const { scrollTop } = scroller;\n const next = scrollTopToReveal({\n index,\n listOffset: scrollTop - listScrollTop(scroller, list),\n rowHeight,\n scrollTop,\n viewportHeight: scroller.clientHeight,\n });\n if (next === null) {\n return false;\n }\n scroller.scrollTop = next;\n return true;\n}\n\n/**\n * The height one row actually has, measured, with the stylesheet's declared height as the answer\n * until a row exists to measure.\n *\n * Both are needed. The DECLARED height (`styles/panels.css` gives `.layer-row` and\n * `.file-tree-item` a `block-size`) is what lets the FIRST render window anything at all, before\n * any row has been laid out. The MEASUREMENT is what stops that constant becoming a lie the day\n * someone changes the row's padding, a user zooms, or a locale's font raises the line box: a window\n * computed from a stale height does not fail loudly, it drifts, and the list quietly ends a few\n * rows short of its own scrollbar.\n */\nexport function measuredRowHeight(\n list: HTMLElement | null,\n selector: string,\n declared: number,\n): number {\n const row = list?.querySelector<HTMLElement>(selector);\n return row && row.offsetHeight > 0 ? row.offsetHeight : declared;\n}\n\n/** A live scroll watch over one list element. Held at module scope by the surface that renders it. */\nexport interface ListWindowWatch {\n /** The list this watch is bound to. A different element means a different watch. */\n list: HTMLElement;\n /** The scroller it resolved to when it was bound. */\n scroller: HTMLElement;\n window: VirtualWindow;\n}\n\n/**\n * Bind — or keep — the scroll watch that repaints a windowed list.\n *\n * Called from the surface's `afterRender`, where the rows exist and the scroller can be resolved,\n * and handed back its own previous handle so re-binding is the exception rather than the rule: the\n * tree element survives every re-render (lit reuses it), so the steady state is \"same list, same\n * scroller, nothing to do\". A new element — the panel remounted, or moved dock — moves the\n * listener, and a list that no longer scrolls drops it.\n *\n * Returns the handle to keep, or null when nothing scrolls this list.\n */\nexport function watchListWindow(\n previous: ListWindowWatch | null,\n list: HTMLElement,\n spec: { count: () => number; rowHeight: () => number; onChange: () => void },\n): ListWindowWatch | null {\n const scroller = nearestScroller(list);\n if (previous && previous.list === list && previous.scroller === scroller) {\n return previous;\n }\n previous?.window.destroy();\n if (!scroller) {\n return null;\n }\n return {\n list,\n scroller,\n window: createVirtualWindow({\n count: spec.count,\n list,\n onChange: () => spec.onChange(),\n rowHeight: spec.rowHeight,\n scroller,\n }),\n };\n}\n"
|
|
6
|
-
],
|
|
7
|
-
"mappings": "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",
|
|
8
|
-
"debugId": "4C38350338F9781B64756E2164756E21",
|
|
9
|
-
"names": []
|
|
10
|
-
}
|