@jxsuite/studio 8.1.0 → 9.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/chunks/{2020-dg097k3e.js → 2020-89fz3pfy.js} +3 -3
- package/dist/chunks/adapter-ay13gema.js +4 -0
- package/dist/chunks/add-new-flow-nmkqpjym.js +4 -0
- package/dist/chunks/cf-account-picker-2e06qxey.js +4 -0
- package/dist/chunks/cf-settings-5y04810c.js +4 -0
- package/dist/chunks/color-04361ttk.js +4 -0
- package/dist/chunks/{color-area-vh9cew51.js → color-area-h8dbasp1.js} +2 -2
- package/dist/chunks/{color-field-e78f16bs.js → color-field-qv5r2b16.js} +3 -3
- package/dist/chunks/{color-slider-fg4yhvk6.js → color-slider-nz2mrzky.js} +2 -2
- package/dist/chunks/components-3vf75n83.js +4 -0
- package/dist/chunks/content-source-4f2raf4a.js +4 -0
- package/dist/chunks/{convert-to-repeater-grnmea6c.js → convert-to-repeater-j9hfcj4f.js} +3 -3
- package/dist/chunks/editor-645krvtz.js +4 -0
- package/dist/chunks/entry-commands-3qmv8wkr.js +4 -0
- package/dist/chunks/{extension-sections-rp7fkega.js → extension-sections-thfke054.js} +3 -3
- package/dist/chunks/file-ops-kkhp9ma7.js +4 -0
- package/dist/chunks/files-yswdhxrf.js +4 -0
- package/dist/chunks/format-host-4g8ex6bz.js +4 -0
- package/dist/chunks/fs-events-z9gpvc6t.js +4 -0
- package/dist/chunks/grid-open-fm4j183c.js +4 -0
- package/dist/chunks/{grid-view-x26rfpz1.js → grid-view-7d2nx83y.js} +10 -10
- package/dist/chunks/{iframe-entry-pkgmcgp0.js → iframe-entry-2x9bn5ng.js} +4 -4
- package/dist/chunks/{iframe-entry-02wzcyvy.js → iframe-entry-btck0e9s.js} +4 -4
- package/dist/chunks/iframe-host-q7fedsmr.js +4 -0
- package/dist/chunks/{index-203h71wy.js → index-jxmt7vh8.js} +3 -3
- package/dist/chunks/index-pt4wh98x.js +4 -0
- package/dist/chunks/{javascript-ww5pv5ae.js → javascript-vmqp56ke.js} +2 -2
- package/dist/chunks/{jsonMode-vwbdwwq3.js → jsonMode-n3wmpant.js} +6 -6
- package/dist/chunks/jx-validate-19y62knt.js +4 -0
- package/dist/chunks/layers-panel-1qvc83y9.js +4 -0
- package/dist/chunks/layers-qf0bc7ze.js +4 -0
- package/dist/chunks/lit-html-wyqw04y2.js +4 -0
- package/dist/chunks/media-library-f9d5qcjb.js +4 -0
- package/dist/chunks/media-picker-rsb1fmk2.js +4 -0
- package/dist/chunks/{monaco-binding-63tqze27.js → monaco-binding-wfhmz89d.js} +3 -3
- package/dist/chunks/monaco-buffer-ak0raadw.js +4 -0
- package/dist/chunks/{monaco-setup-zyyynnj8.js → monaco-setup-fty7a8vg.js} +3 -3
- package/dist/chunks/notify-4qj70q0x.js +4 -0
- package/dist/chunks/parse-n8dfxnqf.js +4 -0
- package/dist/chunks/platform-ehg6t9vd.js +4 -0
- package/dist/chunks/publish-panel-yhmda3cd.js +4 -0
- package/dist/chunks/{publish-quick-ajzdhhs6.js → publish-quick-12hh8926.js} +3 -3
- package/dist/chunks/publish-workspace-hx8qdv9p.js +4 -0
- package/dist/chunks/quick-search-r955m3q1.js +4 -0
- package/dist/chunks/references-8gxv0x7t.js +4 -0
- package/dist/chunks/right-panel-jarwqjpy.js +4 -0
- package/dist/chunks/source-control-84qt25m9.js +4 -0
- package/dist/chunks/studio-0nefxhar.js +7 -0
- package/dist/chunks/studio-0rg30pvs.js +5 -0
- package/dist/chunks/{studio-3q6n9qvq.js → studio-14hh60j8.js} +4 -4
- package/dist/chunks/studio-1cfyd1ys.js +5 -0
- package/dist/chunks/studio-2bq7hheq.js +5 -0
- package/dist/chunks/{studio-mmqr9awv.js → studio-32d8wyxq.js} +33 -33
- package/dist/chunks/studio-3hpcawh8.js +4 -0
- package/dist/chunks/{studio-zm7dnr9g.js → studio-4j35hgsw.js} +4 -4
- package/dist/chunks/{studio-bqgs90r8.js → studio-4qg61g9j.js} +4 -4
- package/dist/chunks/studio-4rgem12q.js +5 -0
- package/dist/chunks/studio-6k9djnxw.js +5 -0
- package/dist/chunks/studio-6rbaedw2.js +9 -0
- package/dist/chunks/studio-732mw0g8.js +5 -0
- package/dist/chunks/studio-79r8msnr.js +7 -0
- package/dist/chunks/studio-7q6jdd4h.js +5 -0
- package/dist/chunks/{studio-jqrg9xxg.js → studio-881z1xrx.js} +4 -4
- package/dist/chunks/{studio-9wyqyfqy.js → studio-8hf8qcm1.js} +4 -4
- package/dist/chunks/{studio-6vrxzkba.js → studio-8pne0rx4.js} +4 -4
- package/dist/chunks/{studio-wcakp5bt.js → studio-9179bsm7.js} +7 -7
- package/dist/chunks/{studio-xddgbwhe.js → studio-9ff0vqff.js} +3 -3
- package/dist/chunks/{studio-25a5by3h.js → studio-9gzvypw4.js} +4 -4
- package/dist/chunks/studio-9ndgd55w.js +5 -0
- package/dist/chunks/studio-9ra9e7m4.js +5 -0
- package/dist/chunks/studio-a6e5fzve.js +5 -0
- package/dist/chunks/studio-a9k86nq6.js +5 -0
- package/dist/chunks/studio-ae7a69jc.js +6 -0
- package/dist/chunks/studio-aghsg0ds.js +7 -0
- package/dist/chunks/{studio-2b8443ms.js → studio-ajw4k8hp.js} +3 -3
- package/dist/chunks/{studio-957jg8g3.js → studio-apapy17g.js} +4 -4
- package/dist/chunks/{studio-hnx1h1pr.js → studio-by8x0jvc.js} +4 -4
- package/dist/chunks/{studio-hxq1ebp0.js → studio-c88gq88j.js} +6 -6
- package/dist/chunks/{studio-a6x058ew.js → studio-cg54vtet.js} +4 -4
- package/dist/chunks/studio-dvhxxxbd.js +5 -0
- package/dist/chunks/{studio-1meqbxns.js → studio-e4rq6x0q.js} +4 -4
- package/dist/chunks/{studio-v2ek69cb.js → studio-ekzbgnjp.js} +4 -4
- package/dist/chunks/{studio-2dtc90zs.js → studio-fg4fj9ec.js} +6 -6
- package/dist/chunks/studio-fj6jzgxw.js +5 -0
- package/dist/chunks/{studio-txkx6586.js → studio-g45r5vm8.js} +7 -7
- package/dist/chunks/{studio-v0gsjav0.js → studio-gczve8zf.js} +4 -4
- package/dist/chunks/studio-ge08zwpv.js +5 -0
- package/dist/chunks/{studio-1gdfsr49.js → studio-gk9yk8dj.js} +7 -7
- package/dist/chunks/{studio-cpdzrdgp.js → studio-gskkgfe3.js} +4 -4
- package/dist/chunks/{studio-94ppxeqy.js → studio-h4jbgne2.js} +8 -8
- package/dist/chunks/{studio-kdseew9m.js → studio-hcy9zeac.js} +4 -4
- package/dist/chunks/studio-ht81xjkr.js +5 -0
- package/dist/chunks/{studio-73wz63nn.js → studio-jr30g4ae.js} +4 -4
- package/dist/chunks/{studio-fqs1a22a.js → studio-k5n4es74.js} +4 -4
- package/dist/chunks/{studio-j5jqvyn3.js → studio-k6hbx2fc.js} +4 -4
- package/dist/chunks/{studio-332hesdk.js → studio-kqh7fxn6.js} +4 -4
- package/dist/chunks/{studio-8nyw10dp.js → studio-kyw47pet.js} +4 -4
- package/dist/chunks/studio-mkw17ngg.js +5 -0
- package/dist/chunks/{studio-02phtmqn.js → studio-myb4mf0h.js} +4 -4
- package/dist/chunks/{studio-d140sy8e.js → studio-n4qq1n57.js} +4 -4
- package/dist/chunks/{studio-bf0rgyf7.js → studio-nfmpmkqb.js} +4 -4
- package/dist/chunks/studio-nfwacw31.js +5 -0
- package/dist/chunks/{studio-z42kysg7.js → studio-nm86874b.js} +136 -136
- package/dist/chunks/studio-nqexty8x.js +16 -0
- package/dist/chunks/studio-nr0kcqc6.js +5 -0
- package/dist/chunks/{studio-dmn7gpba.js → studio-nvfa137z.js} +5 -5
- package/dist/chunks/studio-psh8mwnw.js +4 -0
- package/dist/chunks/{studio-4dsdnan2.js → studio-qd0cycm4.js} +5 -5
- package/dist/chunks/{studio-zht0x0v3.js → studio-qevf5z9d.js} +4 -4
- package/dist/chunks/studio-qs5fmhtj.js +14 -0
- package/dist/chunks/studio-ry4789ng.js +7 -0
- package/dist/chunks/studio-s4fq9jht.js +5 -0
- package/dist/chunks/studio-sc35ttdk.js +5 -0
- package/dist/chunks/studio-sm2f0sc6.js +6 -0
- package/dist/chunks/{studio-rdnezzkd.js → studio-spza69tb.js} +5 -5
- package/dist/chunks/studio-t6dqnnft.js +5 -0
- package/dist/chunks/{studio-hw60n5dh.js → studio-tfmhnwyr.js} +3 -3
- package/dist/chunks/studio-tn7v8gey.js +6 -0
- package/dist/chunks/{studio-nsv7g1qn.js → studio-trcfer2b.js} +4 -4
- package/dist/chunks/studio-tyw7tk0x.js +5 -0
- package/dist/chunks/{studio-533py3yy.js → studio-tyzgte21.js} +4 -4
- package/dist/chunks/studio-vtey9w98.js +5 -0
- package/dist/chunks/studio-ws2r1d7e.js +5 -0
- package/dist/chunks/studio-x2trkhk5.js +5 -0
- package/dist/chunks/{studio-c5dj3dzk.js → studio-xzgp0cp7.js} +4 -4
- package/dist/chunks/studio-y47090vq.js +5 -0
- package/dist/chunks/{studio-nm9qev4p.js → studio-yjh9gddd.js} +5 -5
- package/dist/chunks/studio-ywf9y1e2.js +5 -0
- package/dist/chunks/{studio-x3ge4rts.js → studio-z1p91z5a.js} +4 -4
- package/dist/chunks/studio-ztppbam0.js +5 -0
- package/dist/chunks/{toast-host-1yg5ar8d.js → toast-host-g3r2s0kn.js} +2 -2
- package/dist/chunks/toast-w11qpkyz.js +4 -0
- package/dist/chunks/{tsMode-vra2hh7y.js → tsMode-byje4a01.js} +5 -5
- package/dist/chunks/workspace-7q4arnt3.js +4 -0
- package/dist/chunks/workspace-home-ge027kr6.js +4 -0
- package/dist/chunks/{ws-client-72x5n99j.js → ws-client-h09h6sqg.js} +3 -3
- package/dist/iframe-entry.js +13 -13
- package/dist/manifest.json +77 -77
- package/dist/studio.js +89 -89
- package/package.json +11 -12
- package/src/collab/collab-session.ts +6 -2
- package/src/commands/context.ts +4 -0
- package/src/commands/defaults.ts +2 -0
- package/src/commands/live-context.ts +2 -0
- package/src/files/files.ts +6 -3
- package/src/new-project/new-project-modal.ts +1 -4
- package/src/panels/ai-panel.ts +27 -34
- package/src/platform.ts +20 -0
- package/src/platforms/devserver.ts +2 -120
- package/src/services/ai-ask.ts +29 -171
- package/src/services/ai-command-tools.ts +40 -50
- package/src/services/ai-import-tools.ts +4 -5
- package/src/services/ai-project-tools.ts +13 -3
- package/src/services/ai-tools.ts +26 -564
- package/src/services/ai-writes.ts +84 -2
- package/src/services/document-assistant.ts +29 -58
- package/src/services/harness/assistant-tools.ts +68 -0
- package/src/services/harness/interaction-store.ts +118 -0
- package/src/services/harness/studio-documents.ts +105 -0
- package/src/services/harness/turn-hooks.ts +1 -6
- package/src/services/project-adoption.ts +8 -16
- package/src/services/tool-executor.ts +25 -22
- package/src/state.ts +3 -13
- package/src/surfaces/files-panel.json +12 -0
- package/src/surfaces/files-panel.ts +5 -2
- package/src/surfaces/welcome.ts +4 -1
- package/src/tabs/selection.ts +14 -109
- package/src/tabs/tab.ts +10 -1
- package/src/tabs/transact.ts +316 -124
- package/src/types.ts +13 -8
- package/dist/chunks/adapter-tck81zft.js +0 -4
- package/dist/chunks/add-new-flow-a1w0bnm6.js +0 -4
- package/dist/chunks/cf-account-picker-ce3kp3x1.js +0 -4
- package/dist/chunks/cf-settings-7ye6x7g2.js +0 -4
- package/dist/chunks/color-4gj49xq6.js +0 -4
- package/dist/chunks/components-qce0v93f.js +0 -4
- package/dist/chunks/content-source-jjx8kgzr.js +0 -4
- package/dist/chunks/editor-bkja5dbv.js +0 -4
- package/dist/chunks/entry-commands-1wh0btvg.js +0 -4
- package/dist/chunks/file-ops-6pe4z7an.js +0 -4
- package/dist/chunks/files-ybpp3j38.js +0 -4
- package/dist/chunks/format-host-3mtbhxk1.js +0 -4
- package/dist/chunks/fs-events-xfanfxds.js +0 -4
- package/dist/chunks/grid-open-dg5qmnaj.js +0 -4
- package/dist/chunks/iframe-host-j2bk2xkc.js +0 -4
- package/dist/chunks/index-fkrm7pdk.js +0 -4
- package/dist/chunks/jx-validate-w7v32f6a.js +0 -4
- package/dist/chunks/layers-g7j732cm.js +0 -4
- package/dist/chunks/layers-panel-gjrsxcck.js +0 -4
- package/dist/chunks/lit-html-jdfz9rhc.js +0 -4
- package/dist/chunks/media-library-9j0v4wmk.js +0 -4
- package/dist/chunks/media-picker-cpyyt2m0.js +0 -4
- package/dist/chunks/monaco-buffer-9wcme176.js +0 -4
- package/dist/chunks/notify-rahnnnv4.js +0 -4
- package/dist/chunks/parse-v77xtwv7.js +0 -4
- package/dist/chunks/platform-b2aqv7v5.js +0 -4
- package/dist/chunks/publish-panel-4yk2461b.js +0 -4
- package/dist/chunks/publish-workspace-mxestzcf.js +0 -4
- package/dist/chunks/quick-search-9g6z65b0.js +0 -4
- package/dist/chunks/references-c26enpxs.js +0 -4
- package/dist/chunks/right-panel-9d0e0yg7.js +0 -4
- package/dist/chunks/source-control-xyn3a8ds.js +0 -4
- package/dist/chunks/studio-0khd0xdw.js +0 -5
- package/dist/chunks/studio-1fvzq9vs.js +0 -5
- package/dist/chunks/studio-1yhz0s8p.js +0 -5
- package/dist/chunks/studio-2c2mjyzj.js +0 -6
- package/dist/chunks/studio-3pndhat0.js +0 -9
- package/dist/chunks/studio-4fjqdzrb.js +0 -6
- package/dist/chunks/studio-5abge3wy.js +0 -5
- package/dist/chunks/studio-74nzv280.js +0 -5
- package/dist/chunks/studio-7cg75gtj.js +0 -14
- package/dist/chunks/studio-89cwmnae.js +0 -5
- package/dist/chunks/studio-8m1t83kn.js +0 -7
- package/dist/chunks/studio-a3evp7f6.js +0 -6
- package/dist/chunks/studio-ana67wax.js +0 -5
- package/dist/chunks/studio-b4xhpcwy.js +0 -4
- package/dist/chunks/studio-c4rcaftm.js +0 -5
- package/dist/chunks/studio-cgjt1zce.js +0 -5
- package/dist/chunks/studio-cq87hree.js +0 -5
- package/dist/chunks/studio-e1g64q43.js +0 -5
- package/dist/chunks/studio-e8pzjjhf.js +0 -5
- package/dist/chunks/studio-f8kz3krj.js +0 -7
- package/dist/chunks/studio-fw3jp9m7.js +0 -5
- package/dist/chunks/studio-g6ysm05p.js +0 -7
- package/dist/chunks/studio-gmhd0j3f.js +0 -5
- package/dist/chunks/studio-gqpty626.js +0 -5
- package/dist/chunks/studio-grp684wx.js +0 -5
- package/dist/chunks/studio-h98520qr.js +0 -5
- package/dist/chunks/studio-hvxt8z79.js +0 -5
- package/dist/chunks/studio-j4e627w1.js +0 -5
- package/dist/chunks/studio-kt2j51sa.js +0 -5
- package/dist/chunks/studio-m4w6sygj.js +0 -16
- package/dist/chunks/studio-nqxqf8p2.js +0 -4
- package/dist/chunks/studio-p89w12s2.js +0 -7
- package/dist/chunks/studio-pbagym4j.js +0 -5
- package/dist/chunks/studio-pr23qhrw.js +0 -5
- package/dist/chunks/studio-r4ya3sb2.js +0 -5
- package/dist/chunks/studio-rm9m3z60.js +0 -5
- package/dist/chunks/studio-tpmnbgmt.js +0 -5
- package/dist/chunks/studio-ttxhq5yt.js +0 -5
- package/dist/chunks/studio-y1x65h5r.js +0 -5
- package/dist/chunks/studio-zf188hnd.js +0 -5
- package/dist/chunks/toast-1gv0h53h.js +0 -4
- package/dist/chunks/workspace-3nt93k48.js +0 -4
- package/dist/chunks/workspace-home-zbgyqqws.js +0 -4
- package/src/services/directory-picker.ts +0 -187
- package/src/services/gated-registry.ts +0 -77
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{p,_e}from"./studio-pr23qhrw.js";import{qe,ft,T,R,tt}from"./studio-02phtmqn.js";import{g}from"./studio-hw60n5dh.js";import{us}from"./studio-hnx1h1pr.js";import{He,Ks,Js,nn,Uc}from"./studio-gmhd0j3f.js";import{Wc,sA,Sa,Ob,or}from"./studio-hvxt8z79.js";import{Dd,Nd,qD,Uu,yp,GD,Cw}from"./studio-332hesdk.js";import{Bx,xn}from"./studio-ana67wax.js";import{le}from"./studio-fqs1a22a.js";var C={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaField",$description:"The media field: a thumbnail of what the value names, the value itself, and the two doors to a different one. It is a LEAF a caller interpolates — the Inspector's Content tab, the Signals panel and the grid's image-cell panel each draw an empty host and `ui/media-picker.ts` mounts this into it — so it has no chrome of its own and takes its width from whatever row it lands in. **Browse is addressed through its `part`, not through a class.** `ui/regions.ts` derives `inspector/field:<prop>/browse` by finding the Browse control inside the Inspector's own `[data-prop]` row; the handle used to be `.media-picker-browse`, and a document emits no class, so `[part=\"browse\"]` is the handle now. The four `.media-picker*` rules from `styles/overlays.css` are TRANSCRIBED here rather than shared, because a class a document does not emit cannot style it. `--radius` becomes `--jx-radius-sm` on the way, because a document mounted in a pane's stage is outside `<sp-theme>` and would otherwise take a fallback rather than follow the theme.",tagName:"div",attributes:{part:"media-field"},style:{$description:"The row's own layout and the four transcribed `.media-picker*` rules. Upload and Browse never shrink, so the FIELD is what yields width when the row is narrow — the buttons would otherwise collapse into unreadable stubs before the text did.",display:"flex",alignItems:"center",gap:"var(--jx-space-1)",flex:"1",minWidth:"0",fontFamily:"var(--jx-font-sans)",fontSize:"var(--jx-text-md)",color:"var(--fg)",'& [part="value"]':{flex:"1",minWidth:"0"},'& [part="upload"]':{flexShrink:"0"},'& [part="browse"]':{flexShrink:"0"},'& [part="thumb"]':{width:"24px",height:"24px",objectFit:"cover",borderRadius:"var(--jx-radius-sm)",border:"1px solid var(--border)",flexShrink:"0"}},children:[{tagName:"span",attributes:{part:"thumb-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/thumbState"},cases:{shown:{$description:"Decorative on purpose: the field beside it already states the path in text, so a caption here would be the same fact twice to a screen reader and nothing to anyone else.",tagName:"img",attributes:{part:"thumb",src:"${state.thumbSrc}",alt:""}}}},{tagName:"jx-textfield",attributes:{part:"value"},$props:{size:"sm",label:"${state.label}",placeholder:"/image.jpg",value:{$ref:"#/state/value"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/edit"},value:[{$ref:"event#/target/value"}]}],description:"Every keystroke, because the host debounces it: the canvas follows the typing without a document write per character."},onfocus:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/warm"},value:[]}],description:"Entering the field is the earliest honest signal that a pick is coming, so the project's media are listed then rather than when Browse is pressed."}},{tagName:"jx-action-button",attributes:{part:"upload"},$props:{size:"sm",quiet:!0,icon:"upload-simple",label:"Upload media",hint:"Upload media"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/upload"},value:[]}]}},{tagName:"jx-action-button",attributes:{part:"browse"},$props:{size:"sm",quiet:!0,icon:"image",label:"Browse media",hint:"Browse media"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/browse"},value:[{$ref:"event#/currentTarget"}]}],description:"The button hands over ITSELF: the browser is a popover and the platform wants its invoker, both so a second press on this control toggles rather than reopens and so focus comes back here when it closes."}}]};T("media-field",C);function G(t,e){t.label=e.label,t.value=e.value,t.thumbState=e.thumbState,t.thumbSrc=e.thumbSrc}function D(t,e,o){let i=g({browse:o.browse,edit:o.edit,label:e.label,thumbSrc:e.thumbSrc,thumbState:e.thumbState,upload:o.upload,value:e.value,warm:o.warm}),a=null,r=!1;return R("media-field",i,t).then((n)=>{if(r){n.dispose();return}a=n}),{dispose(){r=!0,a?.dispose(),a=null},update:(n)=>G(i,n)}}function Wu(t){let{anchor:e,name:o,scope:i,slot:a}=t,r=document.createElement("div");r.style.pointerEvents="auto",r.setAttribute(qe,ft("popover",a)),tt("popover").append(r);let n=new AbortController,s=null,l=null,c=!1,N=()=>n.signal.aborted,H=(x)=>{if(c)return;if(c=!0,n.abort(),l?.dispose(),l=null,r.remove(),x)t.onDismissed?.()},U=(async()=>{let x={signal:n.signal};if(t.onNodeCreated)x.onNodeCreated=t.onNodeCreated;let I=await R(o,i,r,x);if(N())return;if(l=I,s=I.root,s.setAttribute(qe,ft("popover",a)),s.addEventListener("toggle",(S)=>{if("newState"in S&&S.newState==="closed")H(!0)}),!s.hasAttribute("popover"))await new Promise((S)=>{s?.addEventListener("jx-ready",()=>S(),{once:!0})});if(N())return;s.showPopover(e?{source:e}:void 0)})();return{close:()=>{if(c)return;if(s?.open)s.hidePopover();H(!1)},host:r,isOpen:()=>!c,ready:U}}var _={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaBrowser",$description:'The project\'s media, offered under whatever control asked for them. **Not the kit menu, and the difference is the thumbnails.** `surfaces/menu.json` is the settled answer to "a list of actions" and a `MenuRowProjection` carries a title, a chord and a gate — there is nowhere in it for a picture, nowhere for the size caption beside it, and a `jx-menu` is itself `popover=auto`, so a filter field cannot stand above one inside a panel. This is a browser: you pick an image by looking at it. **It is a `jx-popover`, so the PLATFORM owns dismissal** — light dismiss, Escape, the top layer and focus back to the invoker are the popover\'s contract, which is why nothing here binds a document listener and why the panel can paint over a modal `<dialog>` that the layer-div popover it replaces could not. The rows are plain buttons in a group, exactly as `grid-views.json`\'s saved views are: a list of buttons is reachable by Tab, and a `role="listbox"` would be a keyboard contract nothing here implements.',tagName:"jx-popover",attributes:{part:"media-browser"},$props:{label:"Project media",x:{$ref:"#/state/x"},y:{$ref:"#/state/y"}},children:[{tagName:"div",attributes:{part:"body"},style:{$description:"A search box that stays put and a list that scrolls under it. The panel itself never scrolls — `jx-popover` says why — so the box is here rather than on the host.",display:"flex",flexDirection:"column",gap:"var(--jx-space-2)",padding:"var(--jx-space-2)",minWidth:"260px",maxHeight:"360px",fontFamily:"var(--jx-font-sans)",fontSize:"var(--jx-text-md)",color:"var(--fg)",'& [part="rows"]':{display:"flex",flexDirection:"column",gap:"2px",overflowY:"auto",minHeight:"0"},'& [part="row"]':{display:"flex",alignItems:"center",gap:"var(--jx-space-2)",textAlign:"left",background:"none",border:"none",color:"var(--fg)",font:"inherit",padding:"var(--jx-space-1) var(--jx-space-2)",borderRadius:"var(--jx-radius-sm)",cursor:"pointer",minWidth:"0"},'& [part="row"]:hover':{background:"var(--bg-hover)"},'& [part="row"]:focus-visible':{outline:"var(--jx-focus-ring)",outlineOffset:"-2px"},'& [part="row-thumb"]':{width:"24px",height:"24px",objectFit:"cover",borderRadius:"var(--jx-radius-sm)",flexShrink:"0"},'& [part="row-text"]':{display:"flex",flexDirection:"column",minWidth:"0"},'& [part="row-name"]':{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},'& [part="row-caption"]':{color:"var(--fg-dim)",fontSize:"var(--jx-text-xs)"},'& [part="empty"]':{margin:"0",color:"var(--fg-dim)",fontSize:"var(--jx-text-xs)"},'& [part="more"]':{justifyContent:"flex-start"},'& [part="browse-all"]':{$description:"The last row, set apart by a rule: it does not pick a file, it opens the picker that shows all of them.",marginTop:"var(--jx-space-1)",paddingTop:"var(--jx-space-2)",borderTop:"1px solid var(--border)",justifyContent:"flex-start"}},children:[{tagName:"jx-textfield",attributes:{part:"filter"},$props:{type:"search",size:"sm",label:"Search media",placeholder:"Search media…",autocomplete:"off",value:{$ref:"#/state/filter"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/setFilter"},value:[{$ref:"event#/target/value"}]}]}},{tagName:"div",attributes:{part:"rows-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/rowsState"},cases:{empty:{tagName:"p",attributes:{part:"empty"},textContent:"${state.emptyLabel}"},listed:{tagName:"div",attributes:{part:"rows"},children:[{$prototype:"Array",items:{$ref:"#/state/rows"},key:{$ref:"$map/item/key"},map:{$description:"One file. The row hands back the value a pick writes — the site URL — rather than an index, so the list may be filtered under it without changing what any row means.",tagName:"button",attributes:{part:"row",type:"button","data-path":"${$map.item.path}"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/pick"},value:[{$ref:"$map/item/path"}]}]},children:[{tagName:"span",attributes:{part:"row-thumb-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"$map/item/thumbState"},cases:{shown:{$description:"Decorative: the row's own text names the file. The load handler is the whole of the dimensions caption — measuring an image is a decode the `<img>` has finished by the time `load` fires, so the numbers are a read of work already done rather than a second fetch per row.",tagName:"img",attributes:{part:"row-thumb",src:"${$map.item.thumbSrc}",alt:""},onload:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/measure"},value:[{$ref:"$map/item/file"},{$ref:"event#/target/naturalWidth"},{$ref:"event#/target/naturalHeight"}]}]}}}},{tagName:"span",attributes:{part:"row-text"},children:[{tagName:"span",attributes:{part:"row-name"},textContent:"${$map.item.name}"},{tagName:"span",attributes:{part:"row-caption-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"$map/item/captionState"},cases:{shown:{tagName:"span",attributes:{part:"row-caption"},textContent:"${$map.item.caption}"}}}]}]}}]}}},{tagName:"div",attributes:{part:"more-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/moreState"},cases:{shown:{$description:'A truncated list says so, and the marker is a control (the rule studio.md §5.6 states for every truncation marker): it raises the cap by fifty, so every file the Media workspace lists can be reached from here without a search. Inert "…21 more" text was the panel holding the answer and not showing it.',tagName:"jx-button",attributes:{part:"more"},$props:{variant:"secondary",size:"sm",quiet:!0},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/showMore"},value:[]}]},children:[{tagName:"span",textContent:"${state.moreLabel}"}]}}},{tagName:"jx-button",attributes:{part:"browse-all"},$props:{variant:"secondary",size:"sm",quiet:!0},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/browseAll"},value:[]}]},children:[{tagName:"span",textContent:"${state.browseAllLabel}"}]}]}]};T("media-browser",_);var X="media-picker";function Y(t,e){t.x=e.x,t.y=e.y,t.filter=e.filter,t.rowsState=e.rowsState,t.rows=e.rows,t.emptyLabel=e.emptyLabel,t.moreState=e.moreState,t.moreLabel=e.moreLabel,t.browseAllLabel=e.browseAllLabel}function V(t,e,o){let i=g({browseAll:e.browseAll,browseAllLabel:t.browseAllLabel,emptyLabel:t.emptyLabel,filter:t.filter,measure:e.measure,moreLabel:t.moreLabel,moreState:t.moreState,pick:e.pick,rows:t.rows,rowsState:t.rowsState,setFilter:e.setFilter,showMore:e.showMore,x:t.x,y:t.y}),a={anchor:o,name:"media-browser",scope:i,slot:X};if(e.dismissed)a.onDismissed=e.dismissed;let r=Wu(a);return r.ready.then(()=>{if(r.isOpen())r.host.querySelector('[part="filter"] [part="input"]')?.focus()}),{close:r.close,host:r.host,isOpen:r.isOpen,ready:r.ready,update:(n)=>Y(i,n)}}var b=[],M=!1,L="images";function ET(t){let e=t.replaceAll("\\","/");return e.startsWith("public/")||new RegExp(`^content/[^/]+/${L}/`).test(e)}async function B(t,e){let o=[];try{let i=await us(()=>e.listDirectory(t));qD(i);for(let a of i)if(a.type==="directory"){let r=await B(a.path,e);o.push(...r)}else{let r=nn(a.name);if(Js.has(r))o.push({file:a.path,isImage:Ks.has(r),kind:sA(a.name),name:a.name,ref:Ob(a.path)})}}catch{}return o}async function Q(t){let e;try{e=(await t.listDirectory("content")).filter((a)=>a.type==="directory").map((a)=>a.path)}catch{return[]}let o=[];for(let i of e){let a=!1;try{a=(await t.listDirectory(i)).some((n)=>n.type==="directory"&&n.name===L)}catch{}if(a)o.push(...await B(`${i}/${L}`,t))}return o}async function Z(t){try{let e=await t.listDirectory(".");return new Set(e.filter((o)=>o.type==="directory").map((o)=>o.name).filter((o)=>o==="public"||o==="content"))}catch{return new Set(["public","content"])}}var h=null,E=0,O=new Set;function TT(t){return O.add(t),()=>{O.delete(t)}}function q(){for(let t of O)t()}function k(){if(M)return Promise.resolve();if(h)return h;if(!_e())return Promise.resolve();let t=E,e=(async()=>{let o=p(),i=await Z(o),[a,r]=await Promise.all([i.has("public")?B("public",o):[],i.has("content")?Q(o):[]]);if(t!==E)return;b=[...a,...r],M=!0,h=null,xn("leftPanel","rightPanel"),q()})();return h=e,e}function Vu(){if(!M)return k(),null;return b}function xw(){b=[],M=!1,E+=1,h=null,GD(),q()}var z=null;function ee(){return z??=(le("9j0v4wmk"),import("./media-library-9j0v4wmk.js")),z}async function I2(t,e={}){(await ee()).openMediaPickDialog({images:e.images===!0,onPick:t})}var y=50,d=null,f=null,v="",u=y,w={},A={x:0,y:0};function m(){let t=v.toLowerCase(),e=w.images?b.filter((r)=>r.isImage):b,o=t?e.filter((r)=>r.ref.toLowerCase().includes(t)||r.name.toLowerCase().includes(t)):e,a=o.slice(0,u).map((r)=>{let n=Cw(Nd(r.file));return{caption:n,captionState:n?"shown":"hidden",file:r.file,key:r.file,name:r.name,path:r.ref,thumbSrc:r.isImage?or(r.file):"",thumbState:r.isImage?"shown":"hidden"}});return{browseAllLabel:w.images?"Browse all images…":"Browse all media…",emptyLabel:e.length>0?"No matches":w.images?"No images in this project yet":"No media in this project yet",filter:v,moreLabel:`Show ${Math.min(o.length-u,y)} more`,moreState:o.length>u?"shown":"hidden",rows:a,rowsState:a.length>0?"listed":"empty",x:A.x,y:A.y}}function P(){let t=d;d=null,f=null,v="",u=y,t?.close()}var j=0;function te(t,e,o){if(!yp(t,e,o)){if(!Dd(t))Uu(t).then(()=>d?.update(m()));return}if(j!==0)return;j=requestAnimationFrame(()=>{j=0,d?.update(m())})}function pS(t,e,o={}){P(),k().then(()=>d?.update(m())),f=e,w=o;let i=He(t);A={x:i.left,y:i.bottom+4},d=V(m(),{browseAll:()=>{let a=f,r=w;if(P(),a)I2(a,r)},dismissed:()=>{d=null,f=null,v="",u=y},measure:te,pick:(a)=>{let r=f;P(),r?.(a)},showMore:()=>{u+=y,d?.update(m())},setFilter:(a)=>{v=a,d?.update(m())}},t)}async function R2(t,e){let o=await Sa([...t]),[i]=o;if(i)e(i.ref)}function fS(t){let e=document.createElement("input");e.type="file",e.multiple=!0,e.accept=Wc(),e.addEventListener("change",()=>{if(e.files?.length)R2(e.files,t)}),e.click()}var re=400,F=new WeakMap;function W(t,e){let o=Ks.has(nn(e));return{label:t,thumbSrc:o&&e?Uc(e):"",thumbState:o&&e?"shown":"hidden",value:e}}function jl(t,e,o,i,a={}){k();let r=F.get(t);if(r){r.prop=e,r.commit=i,r.options=a,r.handle.update(W(e,o));return}let n={commit:i,options:a,prop:e},s=D(t,W(e,o),{browse:(l)=>{pS(l,(c)=>n.commit(c),n.options)},edit:(l)=>Bx(`media:${n.prop}`,re,(c)=>n.commit(c))(l),upload:()=>fS((l)=>n.commit(l)),warm:()=>{k()}});F.set(t,Object.assign(n,{handle:s}))}function fm(t){let e=F.get(t);if(e)F.delete(t),e.handle.dispose()}
|
|
2
|
-
export{
|
|
1
|
+
import{p,_e}from"./studio-9ndgd55w.js";import{Ue,ft,T,R,tt}from"./studio-myb4mf0h.js";import{g}from"./studio-tfmhnwyr.js";import{us}from"./studio-by8x0jvc.js";import{He,Ks,Js,nn,Vc}from"./studio-t6dqnnft.js";import{zc,cA,Sa,jb,tr}from"./studio-vtey9w98.js";import{Rd,Dd,iN,qu,_p,oN,Aw}from"./studio-kqh7fxn6.js";import{zx,xn}from"./studio-9ra9e7m4.js";import{le}from"./studio-k5n4es74.js";var C={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaField",$description:"The media field: a thumbnail of what the value names, the value itself, and the two doors to a different one. It is a LEAF a caller interpolates — the Inspector's Content tab, the Signals panel and the grid's image-cell panel each draw an empty host and `ui/media-picker.ts` mounts this into it — so it has no chrome of its own and takes its width from whatever row it lands in. **Browse is addressed through its `part`, not through a class.** `ui/regions.ts` derives `inspector/field:<prop>/browse` by finding the Browse control inside the Inspector's own `[data-prop]` row; the handle used to be `.media-picker-browse`, and a document emits no class, so `[part=\"browse\"]` is the handle now. The four `.media-picker*` rules from `styles/overlays.css` are TRANSCRIBED here rather than shared, because a class a document does not emit cannot style it. `--radius` becomes `--jx-radius-sm` on the way, because a document mounted in a pane's stage is outside `<sp-theme>` and would otherwise take a fallback rather than follow the theme.",tagName:"div",attributes:{part:"media-field"},style:{$description:"The row's own layout and the four transcribed `.media-picker*` rules. Upload and Browse never shrink, so the FIELD is what yields width when the row is narrow — the buttons would otherwise collapse into unreadable stubs before the text did.",display:"flex",alignItems:"center",gap:"var(--jx-space-1)",flex:"1",minWidth:"0",fontFamily:"var(--jx-font-sans)",fontSize:"var(--jx-text-md)",color:"var(--fg)",'& [part="value"]':{flex:"1",minWidth:"0"},'& [part="upload"]':{flexShrink:"0"},'& [part="browse"]':{flexShrink:"0"},'& [part="thumb"]':{width:"24px",height:"24px",objectFit:"cover",borderRadius:"var(--jx-radius-sm)",border:"1px solid var(--border)",flexShrink:"0"}},children:[{tagName:"span",attributes:{part:"thumb-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/thumbState"},cases:{shown:{$description:"Decorative on purpose: the field beside it already states the path in text, so a caption here would be the same fact twice to a screen reader and nothing to anyone else.",tagName:"img",attributes:{part:"thumb",src:"${state.thumbSrc}",alt:""}}}},{tagName:"jx-textfield",attributes:{part:"value"},$props:{size:"sm",label:"${state.label}",placeholder:"/image.jpg",value:{$ref:"#/state/value"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/edit"},value:[{$ref:"event#/target/value"}]}],description:"Every keystroke, because the host debounces it: the canvas follows the typing without a document write per character."},onfocus:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/warm"},value:[]}],description:"Entering the field is the earliest honest signal that a pick is coming, so the project's media are listed then rather than when Browse is pressed."}},{tagName:"jx-action-button",attributes:{part:"upload"},$props:{size:"sm",quiet:!0,icon:"upload-simple",label:"Upload media",hint:"Upload media"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/upload"},value:[]}]}},{tagName:"jx-action-button",attributes:{part:"browse"},$props:{size:"sm",quiet:!0,icon:"image",label:"Browse media",hint:"Browse media"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/browse"},value:[{$ref:"event#/currentTarget"}]}],description:"The button hands over ITSELF: the browser is a popover and the platform wants its invoker, both so a second press on this control toggles rather than reopens and so focus comes back here when it closes."}}]};T("media-field",C);function G(t,e){t.label=e.label,t.value=e.value,t.thumbState=e.thumbState,t.thumbSrc=e.thumbSrc}function D(t,e,o){let i=g({browse:o.browse,edit:o.edit,label:e.label,thumbSrc:e.thumbSrc,thumbState:e.thumbState,upload:o.upload,value:e.value,warm:o.warm}),a=null,r=!1;return R("media-field",i,t).then((n)=>{if(r){n.dispose();return}a=n}),{dispose(){r=!0,a?.dispose(),a=null},update:(n)=>G(i,n)}}function zu(t){let{anchor:e,name:o,scope:i,slot:a}=t,r=document.createElement("div");r.style.pointerEvents="auto",r.setAttribute(Ue,ft("popover",a)),tt("popover").append(r);let n=new AbortController,s=null,l=null,c=!1,N=()=>n.signal.aborted,H=(x)=>{if(c)return;if(c=!0,n.abort(),l?.dispose(),l=null,r.remove(),x)t.onDismissed?.()},U=(async()=>{let x={signal:n.signal};if(t.onNodeCreated)x.onNodeCreated=t.onNodeCreated;let I=await R(o,i,r,x);if(N())return;if(l=I,s=I.root,s.setAttribute(Ue,ft("popover",a)),s.addEventListener("toggle",(S)=>{if("newState"in S&&S.newState==="closed")H(!0)}),!s.hasAttribute("popover"))await new Promise((S)=>{s?.addEventListener("jx-ready",()=>S(),{once:!0})});if(N())return;s.showPopover(e?{source:e}:void 0)})();return{close:()=>{if(c)return;if(s?.open)s.hidePopover();H(!1)},host:r,isOpen:()=>!c,ready:U}}var _={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaBrowser",$description:'The project\'s media, offered under whatever control asked for them. **Not the kit menu, and the difference is the thumbnails.** `surfaces/menu.json` is the settled answer to "a list of actions" and a `MenuRowProjection` carries a title, a chord and a gate — there is nowhere in it for a picture, nowhere for the size caption beside it, and a `jx-menu` is itself `popover=auto`, so a filter field cannot stand above one inside a panel. This is a browser: you pick an image by looking at it. **It is a `jx-popover`, so the PLATFORM owns dismissal** — light dismiss, Escape, the top layer and focus back to the invoker are the popover\'s contract, which is why nothing here binds a document listener and why the panel can paint over a modal `<dialog>` that the layer-div popover it replaces could not. The rows are plain buttons in a group, exactly as `grid-views.json`\'s saved views are: a list of buttons is reachable by Tab, and a `role="listbox"` would be a keyboard contract nothing here implements.',tagName:"jx-popover",attributes:{part:"media-browser"},$props:{label:"Project media",x:{$ref:"#/state/x"},y:{$ref:"#/state/y"}},children:[{tagName:"div",attributes:{part:"body"},style:{$description:"A search box that stays put and a list that scrolls under it. The panel itself never scrolls — `jx-popover` says why — so the box is here rather than on the host.",display:"flex",flexDirection:"column",gap:"var(--jx-space-2)",padding:"var(--jx-space-2)",minWidth:"260px",maxHeight:"360px",fontFamily:"var(--jx-font-sans)",fontSize:"var(--jx-text-md)",color:"var(--fg)",'& [part="rows"]':{display:"flex",flexDirection:"column",gap:"2px",overflowY:"auto",minHeight:"0"},'& [part="row"]':{display:"flex",alignItems:"center",gap:"var(--jx-space-2)",textAlign:"left",background:"none",border:"none",color:"var(--fg)",font:"inherit",padding:"var(--jx-space-1) var(--jx-space-2)",borderRadius:"var(--jx-radius-sm)",cursor:"pointer",minWidth:"0"},'& [part="row"]:hover':{background:"var(--bg-hover)"},'& [part="row"]:focus-visible':{outline:"var(--jx-focus-ring)",outlineOffset:"-2px"},'& [part="row-thumb"]':{width:"24px",height:"24px",objectFit:"cover",borderRadius:"var(--jx-radius-sm)",flexShrink:"0"},'& [part="row-text"]':{display:"flex",flexDirection:"column",minWidth:"0"},'& [part="row-name"]':{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap"},'& [part="row-caption"]':{color:"var(--fg-dim)",fontSize:"var(--jx-text-xs)"},'& [part="empty"]':{margin:"0",color:"var(--fg-dim)",fontSize:"var(--jx-text-xs)"},'& [part="more"]':{justifyContent:"flex-start"},'& [part="browse-all"]':{$description:"The last row, set apart by a rule: it does not pick a file, it opens the picker that shows all of them.",marginTop:"var(--jx-space-1)",paddingTop:"var(--jx-space-2)",borderTop:"1px solid var(--border)",justifyContent:"flex-start"}},children:[{tagName:"jx-textfield",attributes:{part:"filter"},$props:{type:"search",size:"sm",label:"Search media",placeholder:"Search media…",autocomplete:"off",value:{$ref:"#/state/filter"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/setFilter"},value:[{$ref:"event#/target/value"}]}]}},{tagName:"div",attributes:{part:"rows-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/rowsState"},cases:{empty:{tagName:"p",attributes:{part:"empty"},textContent:"${state.emptyLabel}"},listed:{tagName:"div",attributes:{part:"rows"},children:[{$prototype:"Array",items:{$ref:"#/state/rows"},key:{$ref:"$map/item/key"},map:{$description:"One file. The row hands back the value a pick writes — the site URL — rather than an index, so the list may be filtered under it without changing what any row means.",tagName:"button",attributes:{part:"row",type:"button","data-path":"${$map.item.path}"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/pick"},value:[{$ref:"$map/item/path"}]}]},children:[{tagName:"span",attributes:{part:"row-thumb-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"$map/item/thumbState"},cases:{shown:{$description:"Decorative: the row's own text names the file. The load handler is the whole of the dimensions caption — measuring an image is a decode the `<img>` has finished by the time `load` fires, so the numbers are a read of work already done rather than a second fetch per row.",tagName:"img",attributes:{part:"row-thumb",src:"${$map.item.thumbSrc}",alt:""},onload:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/measure"},value:[{$ref:"$map/item/file"},{$ref:"event#/target/naturalWidth"},{$ref:"event#/target/naturalHeight"}]}]}}}},{tagName:"span",attributes:{part:"row-text"},children:[{tagName:"span",attributes:{part:"row-name"},textContent:"${$map.item.name}"},{tagName:"span",attributes:{part:"row-caption-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"$map/item/captionState"},cases:{shown:{tagName:"span",attributes:{part:"row-caption"},textContent:"${$map.item.caption}"}}}]}]}}]}}},{tagName:"div",attributes:{part:"more-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/moreState"},cases:{shown:{$description:'A truncated list says so, and the marker is a control (the rule studio.md §5.6 states for every truncation marker): it raises the cap by fifty, so every file the Media workspace lists can be reached from here without a search. Inert "…21 more" text was the panel holding the answer and not showing it.',tagName:"jx-button",attributes:{part:"more"},$props:{variant:"secondary",size:"sm",quiet:!0},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/showMore"},value:[]}]},children:[{tagName:"span",textContent:"${state.moreLabel}"}]}}},{tagName:"jx-button",attributes:{part:"browse-all"},$props:{variant:"secondary",size:"sm",quiet:!0},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/browseAll"},value:[]}]},children:[{tagName:"span",textContent:"${state.browseAllLabel}"}]}]}]};T("media-browser",_);var X="media-picker";function Y(t,e){t.x=e.x,t.y=e.y,t.filter=e.filter,t.rowsState=e.rowsState,t.rows=e.rows,t.emptyLabel=e.emptyLabel,t.moreState=e.moreState,t.moreLabel=e.moreLabel,t.browseAllLabel=e.browseAllLabel}function V(t,e,o){let i=g({browseAll:e.browseAll,browseAllLabel:t.browseAllLabel,emptyLabel:t.emptyLabel,filter:t.filter,measure:e.measure,moreLabel:t.moreLabel,moreState:t.moreState,pick:e.pick,rows:t.rows,rowsState:t.rowsState,setFilter:e.setFilter,showMore:e.showMore,x:t.x,y:t.y}),a={anchor:o,name:"media-browser",scope:i,slot:X};if(e.dismissed)a.onDismissed=e.dismissed;let r=zu(a);return r.ready.then(()=>{if(r.isOpen())r.host.querySelector('[part="filter"] [part="input"]')?.focus()}),{close:r.close,host:r.host,isOpen:r.isOpen,ready:r.ready,update:(n)=>Y(i,n)}}var b=[],M=!1,L="images";function DT(t){let e=t.replaceAll("\\","/");return e.startsWith("public/")||new RegExp(`^content/[^/]+/${L}/`).test(e)}async function B(t,e){let o=[];try{let i=await us(()=>e.listDirectory(t));iN(i);for(let a of i)if(a.type==="directory"){let r=await B(a.path,e);o.push(...r)}else{let r=nn(a.name);if(Js.has(r))o.push({file:a.path,isImage:Ks.has(r),kind:cA(a.name),name:a.name,ref:jb(a.path)})}}catch{}return o}async function Q(t){let e;try{e=(await t.listDirectory("content")).filter((a)=>a.type==="directory").map((a)=>a.path)}catch{return[]}let o=[];for(let i of e){let a=!1;try{a=(await t.listDirectory(i)).some((n)=>n.type==="directory"&&n.name===L)}catch{}if(a)o.push(...await B(`${i}/${L}`,t))}return o}async function Z(t){try{let e=await t.listDirectory(".");return new Set(e.filter((o)=>o.type==="directory").map((o)=>o.name).filter((o)=>o==="public"||o==="content"))}catch{return new Set(["public","content"])}}var h=null,E=0,O=new Set;function NT(t){return O.add(t),()=>{O.delete(t)}}function q(){for(let t of O)t()}function k(){if(M)return Promise.resolve();if(h)return h;if(!_e())return Promise.resolve();let t=E,e=(async()=>{let o=p(),i=await Z(o),[a,r]=await Promise.all([i.has("public")?B("public",o):[],i.has("content")?Q(o):[]]);if(t!==E)return;b=[...a,...r],M=!0,h=null,xn("leftPanel","rightPanel"),q()})();return h=e,e}function Wu(){if(!M)return k(),null;return b}function kw(){b=[],M=!1,E+=1,h=null,oN(),q()}var z=null;function ee(){return z??=(le("f9d5qcjb"),import("./media-library-f9d5qcjb.js")),z}async function P2(t,e={}){(await ee()).openMediaPickDialog({images:e.images===!0,onPick:t})}var y=50,d=null,f=null,v="",u=y,w={},A={x:0,y:0};function m(){let t=v.toLowerCase(),e=w.images?b.filter((r)=>r.isImage):b,o=t?e.filter((r)=>r.ref.toLowerCase().includes(t)||r.name.toLowerCase().includes(t)):e,a=o.slice(0,u).map((r)=>{let n=Aw(Dd(r.file));return{caption:n,captionState:n?"shown":"hidden",file:r.file,key:r.file,name:r.name,path:r.ref,thumbSrc:r.isImage?tr(r.file):"",thumbState:r.isImage?"shown":"hidden"}});return{browseAllLabel:w.images?"Browse all images…":"Browse all media…",emptyLabel:e.length>0?"No matches":w.images?"No images in this project yet":"No media in this project yet",filter:v,moreLabel:`Show ${Math.min(o.length-u,y)} more`,moreState:o.length>u?"shown":"hidden",rows:a,rowsState:a.length>0?"listed":"empty",x:A.x,y:A.y}}function P(){let t=d;d=null,f=null,v="",u=y,t?.close()}var j=0;function te(t,e,o){if(!_p(t,e,o)){if(!Rd(t))qu(t).then(()=>d?.update(m()));return}if(j!==0)return;j=requestAnimationFrame(()=>{j=0,d?.update(m())})}function vS(t,e,o={}){P(),k().then(()=>d?.update(m())),f=e,w=o;let i=He(t);A={x:i.left,y:i.bottom+4},d=V(m(),{browseAll:()=>{let a=f,r=w;if(P(),a)P2(a,r)},dismissed:()=>{d=null,f=null,v="",u=y},measure:te,pick:(a)=>{let r=f;P(),r?.(a)},showMore:()=>{u+=y,d?.update(m())},setFilter:(a)=>{v=a,d?.update(m())}},t)}async function F2(t,e){let o=await Sa([...t]),[i]=o;if(i)e(i.ref)}function yS(t){let e=document.createElement("input");e.type="file",e.multiple=!0,e.accept=zc(),e.addEventListener("change",()=>{if(e.files?.length)F2(e.files,t)}),e.click()}var re=400,F=new WeakMap;function W(t,e){let o=Ks.has(nn(e));return{label:t,thumbSrc:o&&e?Vc(e):"",thumbState:o&&e?"shown":"hidden",value:e}}function Hl(t,e,o,i,a={}){k();let r=F.get(t);if(r){r.prop=e,r.commit=i,r.options=a,r.handle.update(W(e,o));return}let n={commit:i,options:a,prop:e},s=D(t,W(e,o),{browse:(l)=>{vS(l,(c)=>n.commit(c),n.options)},edit:(l)=>zx(`media:${n.prop}`,re,(c)=>n.commit(c))(l),upload:()=>yS((l)=>n.commit(l)),warm:()=>{k()}});F.set(t,Object.assign(n,{handle:s}))}function bm(t){let e=F.get(t);if(e)F.delete(t),e.handle.dispose()}
|
|
2
|
+
export{zu,DT,NT,Wu,kw,P2,vS,F2,yS,Hl,bm};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=studio-
|
|
4
|
+
//# debugId=F8B774E9E132CA7764756E2164756E21
|
|
5
|
+
//# sourceMappingURL=studio-cg54vtet.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{te}from"./studio-psh8mwnw.js";import{p}from"./studio-9ndgd55w.js";import{g,C}from"./studio-tfmhnwyr.js";import{hh,Sr,E$}from"./studio-7q6jdd4h.js";import{Ot,Nt}from"./studio-qs5fmhtj.js";import{Ue,wi,ft,T,R,Jt,tt}from"./studio-myb4mf0h.js";import{m,u,Kd}from"./studio-ztppbam0.js";import{zd}from"./studio-by8x0jvc.js";import{He}from"./studio-t6dqnnft.js";import{zc,_a,XL,dA,QL,Sa,hA,pA,Fb,tr}from"./studio-vtey9w98.js";import{Ow,Gu}from"./studio-9179bsm7.js";import{NT,Wu}from"./studio-cg54vtet.js";import{jT,HT,BT,zT,_b}from"./studio-4qg61g9j.js";import{bp}from"./studio-ae7a69jc.js";import{Rd,Dd,qu,_p,Aw}from"./studio-kqh7fxn6.js";import{n,_}from"./studio-ywf9y1e2.js";import{le}from"./studio-k5n4es74.js";var D=[{key:"all",label:"All media"},{key:"image",label:"Images"},{key:"video",label:"Video"},{key:"audio",label:"Audio"},{key:"document",label:"Documents"},{key:"font",label:"Fonts"},{key:"unused",label:"Unused"}],pS=D.map((e)=>e.key);function ae(e){return pS.some((t)=>t===e)}function F(e){return D.find((t)=>t.key===e)?.label??"All media"}var K=[{key:"newest",label:"Newest"},{key:"name",label:"Name"},{key:"size",label:"Size"}],Ne=K.map((e)=>e.key);function re(e){return Ne.some((t)=>t===e)}function z(e,t,i){switch(t){case"all":return!0;case"unused":return i!==null&&i.has(e.file);default:return e.kind===t}}function U(e,t){let i=t.trim().toLowerCase();return i===""||e.name.toLowerCase().includes(i)}function W(e,t){return e.filter((a)=>z(a,t.filter,t.unused)&&U(a,t.query)).toSorted((a,r)=>je(t.sort,a,r)||a.file.localeCompare(r.file))}function je(e,t,i){switch(e){case"name":return t.name.localeCompare(i.name,void 0,{numeric:!0,sensitivity:"base"});case"size":return(i.bytes??-1)-(t.bytes??-1);default:return(i.modified??"").localeCompare(t.modified??"")}}function ne(e,t){let i={all:e.length,audio:0,document:0,font:0,image:0,unused:t===null?null:e.filter((a)=>t.has(a.file)).length,video:0};for(let a of e)i[a.kind]=(i[a.kind]??0)+1;return i}var Ce=132,ie=12;function oe(e){return Math.max(1,Math.floor((e+ie)/(Ce+ie)))}function se(e,t,i,a,r=!1){if(a===0)return null;let o=Math.min(Math.max(e,0),a-1),l=o-o%i,c;switch(t){case"ArrowRight":{c=o+1;break}case"ArrowLeft":{c=o-1;break}case"ArrowDown":{c=o+i;break}case"ArrowUp":{c=o-i;break}case"Home":{c=r?0:l;break}case"End":{c=r?a-1:Math.min(l+i-1,a-1);break}default:return null}return c<0||c>=a?o:c}var de={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaLibrary",$description:"The Media workspace's library (`specs/studio.md` §22.6): the project's media as filters, a grid and the selected file's detail. ONE document in two modes. In `manage` it is the Media home tab, with Replace, Open in viewer and Delete under the detail; in `pick` it is the full-size picker inside a `jx-dialog` (`media-pick-dialog.json`), and the dialog's own footer answers Cancel or Use <file>. `media/media-library.ts` keeps every decision (which files a filter keeps, the sort, what a count may claim, where an arrow lands, what Replace writes) and hands this document strings and discriminants. **Unused is drawn with no number until the usage sweep has settled**, and Missing alt text and tags are not drawn at all: each needs a store that does not exist, and a filter that cannot be answered is not shipped as one that always answers nothing.",tagName:"div",attributes:{part:"media-library","data-jx-region":"${state.region}","data-mode":"${state.mode}","data-drop":"${state.dropActive}"},style:{$description:"Three columns over the whole stage: the filters, the grid with its toolbar, and the selected file's detail. Fills the pane's stage by its own geometry, as the workspace home does: the stage is `position: relative` (`pane-grid.json`). In pick mode the same columns fill the dialog's body instead, so the root's box is the only thing that differs between the two modes.",position:"absolute",inset:"0",display:"grid",gridTemplateColumns:"200px minmax(0, 1fr) 300px",boxSizing:"border-box",fontFamily:"var(--jx-font-sans)",fontSize:"var(--jx-text-md)",color:"var(--fg)",background:"var(--bg)",'&[data-mode="pick"]':{$description:"Inside a dialog there is no stage to fill: the box is the dialog body's, at a height the dialog can scroll within.",position:"relative",inset:"auto",height:"min(70vh, 620px)",gridTemplateColumns:"150px minmax(0, 1fr) 210px"},'&[data-drop="true"]':{$description:"The drop affordance is a STATE the flow holds, not a class a handler adds and forgets to take off.",outline:"2px dashed var(--accent)",outlineOffset:"-4px"},'& [part="filters"]':{display:"flex",flexDirection:"column",gap:"2px",padding:"var(--jx-space-3) var(--jx-space-2)",borderRight:"1px solid var(--border)",background:"var(--bg-panel)",overflowY:"auto"},'& [part="filters-heading"]':{margin:"0",padding:"var(--jx-space-2) var(--jx-space-2) var(--jx-space-1)",fontSize:"var(--jx-text-xs)",fontWeight:"600",letterSpacing:"0.06em",textTransform:"uppercase",color:"var(--fg-dim)"},'& [part="filter"]':{display:"flex",alignItems:"center",gap:"var(--jx-space-2)",height:"30px",padding:"0 var(--jx-space-2)",border:"none",borderRadius:"var(--radius)",background:"none",color:"var(--fg)",font:"inherit",textAlign:"left",cursor:"pointer"},'& [part="filter"]:hover':{background:"var(--hover-bg)"},'& [part="filter"][aria-pressed="true"]':{background:"color-mix(in srgb, var(--accent) 16%, transparent)",color:"var(--fg)",fontWeight:"600"},'& [part="filter"]:focus-visible':{outline:"var(--jx-focus-ring)",outlineOffset:"-2px"},'& [part="filter-count"]':{marginLeft:"auto",fontSize:"var(--jx-text-xs)",color:"var(--fg-dim)",fontWeight:"400"},'& [part="main"]':{display:"flex",flexDirection:"column",minWidth:"0",minHeight:"0"},'& [part="toolbar"]':{display:"flex",alignItems:"center",flexWrap:"wrap",gap:"var(--jx-space-3)",padding:"var(--jx-space-3) var(--jx-space-4)",borderBottom:"1px solid var(--border)"},'& [part="title"]':{margin:"0 auto 0 0",fontSize:"var(--jx-text-lg)",fontWeight:"600"},'& [part="search"]':{width:"220px"},'& [part="sort"]':{width:"130px"},'& [part="upload"], & [part="empty-upload"]':{$description:"A LABEL around the file picker, not a button that clicks a hidden one: the picker is the control, so it takes focus, Enter opens it and a screen reader announces a file upload. A plain element because a label forwards a click to the input it contains and a custom element between the two would break that.",position:"relative",display:"inline-flex",alignItems:"center",gap:"6px",height:"28px",padding:"0 var(--jx-space-3)",border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg-panel)",color:"var(--fg)",font:"inherit",cursor:"pointer",":hover":{background:"var(--hover-bg)"},":has(:focus-visible)":{outline:"var(--jx-focus-ring)",outlineOffset:"2px"}},'& [part="upload-input"], & [part="replace-input"]':{$description:"Out of the way but still FOCUSABLE: `display: none` would take the control out of the tab order, and the label around it draws the focus ring for it.",position:"absolute",width:"1px",height:"1px",opacity:"0",pointerEvents:"none"},'& [part="upload-glyph"]':{"--jx-icon-size":"16px"},'& [part="body"]':{flex:"1",minHeight:"0",overflowY:"auto",padding:"var(--jx-space-4)"},'& [part="grid"]':{$description:"auto-fill over a minimum tile width; `media/media-library-model.ts` `gridColumns` does the same arithmetic, so ArrowDown lands on the tile drawn under the current one. Keep the two numbers in step.",display:"grid",gridTemplateColumns:"repeat(auto-fill, minmax(132px, 1fr))",gap:"12px",alignContent:"start"},'& [part="tile"]':{display:"flex",flexDirection:"column",gap:"4px",padding:"4px",borderRadius:"var(--jx-radius-md, 6px)",border:"2px solid transparent",cursor:"pointer",minWidth:"0",outline:"none"},'& [part="tile"]:hover':{background:"var(--hover-bg)"},'& [part="tile"][aria-selected="true"]':{borderColor:"var(--accent)"},'& [part="tile"]:focus-visible':{outline:"var(--jx-focus-ring)",outlineOffset:"2px"},'& [part="thumb"]':{display:"flex",alignItems:"center",justifyContent:"center",aspectRatio:"4 / 3",borderRadius:"var(--radius)",background:"var(--bg-input)",overflow:"hidden",color:"var(--fg-dim)","--jx-icon-size":"28px"},'& [part="thumb-img"]':{width:"100%",height:"100%",objectFit:"cover"},'& [part="tile-name"]':{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontSize:"var(--jx-text-sm)"},'& [part="tile-caption"]':{overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontSize:"var(--jx-text-xs)",color:"var(--fg-dim)",minHeight:"1em"},'& [part="empty"]':{display:"flex",flexDirection:"column",alignItems:"center",gap:"var(--jx-space-3)",padding:"48px var(--jx-space-6)",textAlign:"center",color:"var(--fg-dim)","--jx-icon-size":"40px"},'& [part="empty-title"]':{margin:"0",fontSize:"var(--jx-text-lg)",fontWeight:"600",color:"var(--fg)"},'& [part="empty-detail"]':{margin:"0",maxWidth:"42ch",lineHeight:"1.5"},'& [part="detail"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-3)",padding:"var(--jx-space-4)",borderLeft:"1px solid var(--border)",background:"var(--bg-panel)",overflowY:"auto",minWidth:"0"},'& [part="detail-hint"]':{margin:"auto 0",textAlign:"center",color:"var(--fg-dim)"},'& [part="detail-preview"]':{display:"flex",alignItems:"center",justifyContent:"center",minHeight:"140px",maxHeight:"220px",borderRadius:"var(--radius)",background:"var(--bg-input)",overflow:"hidden",color:"var(--fg-dim)","--jx-icon-size":"40px"},'& [part="preview-img"], & [part="preview-video"]':{maxWidth:"100%",maxHeight:"220px",objectFit:"contain"},'& [part="preview-audio"]':{width:"100%"},'& [part="preview-specimen"]':{$description:"The viewer's specimen at a side pane's size. The face arrives as the `@font-face` the flow writes under a family name generated from the path (`media/media-pane.ts` `specimenOf`); the element carries only that name, as a custom property, and the fallback stack is a rule, here.",display:"flex",flexDirection:"column",gap:"var(--jx-space-2)",padding:"var(--jx-space-4)",maxWidth:"100%",color:"var(--fg)",fontFamily:"var(--jx-specimen-family, system-ui), system-ui, sans-serif"},'& [part="specimen-line"]':{margin:"0",lineHeight:"1.3",overflowWrap:"anywhere"},'& [part="specimen-line"][data-size="32"]':{fontSize:"32px"},'& [part="specimen-line"][data-size="14"]':{fontSize:"var(--jx-text-md)"},'& [part="detail-name"]':{margin:"0",fontSize:"var(--jx-text-md)",fontWeight:"600",overflowWrap:"anywhere"},'& [part="facts"]':{margin:"0",color:"var(--fg-dim)",fontSize:"var(--jx-text-sm)"},'& [part="group-title"]':{margin:"0",fontSize:"var(--jx-text-xs)",fontWeight:"600",color:"var(--fg-dim)"},'& [part="url"]':{display:"flex",alignItems:"center",gap:"var(--jx-space-2)",minWidth:"0"},'& [part="url-value"]':{flex:"1",minWidth:"0",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",fontFamily:"var(--jx-font-mono)",fontSize:"var(--jx-text-sm)"},'& [part="usage"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-1)"},'& [part="usage-headline"]':{margin:"0",fontSize:"var(--jx-text-sm)"},'& [part="usage-list"]':{margin:"0",padding:"0",listStyle:"none",display:"flex",flexDirection:"column",gap:"2px"},'& [part="usage-row"]':{display:"flex",alignItems:"center",gap:"var(--jx-space-2)"},'& [part="usage-link"]':{flex:"1",minWidth:"0",overflow:"hidden",textOverflow:"ellipsis",whiteSpace:"nowrap",border:"none",background:"none",padding:"0",color:"var(--accent)",font:"inherit",fontSize:"var(--jx-text-sm)",textAlign:"left",cursor:"pointer",":hover":{textDecoration:"underline"},":focus-visible":{outline:"var(--jx-focus-ring)"}},'& [part="usage-count"]':{fontSize:"var(--jx-text-xs)",color:"var(--fg-dim)"},'& [part="actions"]':{display:"flex",flexWrap:"wrap",gap:"var(--jx-space-2)",marginTop:"var(--jx-space-2)"},'& [part="replace"]':{position:"relative",display:"inline-flex",alignItems:"center",height:"28px",padding:"0 var(--jx-space-3)",border:"1px solid var(--border)",borderRadius:"var(--radius)",background:"var(--bg)",color:"var(--fg)",font:"inherit",cursor:"pointer",":hover":{background:"var(--hover-bg)"},":has(:focus-visible)":{outline:"var(--jx-focus-ring)",outlineOffset:"2px"}}},ondragover:{$prototype:"Function",body:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/dragOver"},value:[]}],description:"A file dropped ANYWHERE on the library uploads, to the destination the Upload label names before the drop: public/media/."},ondragleave:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/dragOut"},value:[]}]},ondrop:{$prototype:"Function",body:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/drop"},value:[{$ref:"event#/dataTransfer/files"}]}]},children:[{tagName:"nav",attributes:{part:"filters","aria-label":"Media filters"},children:[{tagName:"h2",attributes:{part:"filters-heading"},textContent:"Library"},{$prototype:"Array",items:{$ref:"#/state/filters"},key:{$ref:"$map/item/key"},map:{tagName:"button",attributes:{part:"filter",type:"button","aria-pressed":"${$map.item.pressed}","data-filter":"${$map.item.key}"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/setFilter"},value:[{$ref:"$map/item/key"}]}]},children:[{tagName:"span",attributes:{part:"filter-label"},textContent:"${$map.item.label}"},{tagName:"span",attributes:{part:"filter-count"},textContent:"${$map.item.count}"}]}}]},{tagName:"section",attributes:{part:"main","aria-labelledby":"${state.titleId}"},children:[{tagName:"header",attributes:{part:"toolbar"},children:[{tagName:"h2",attributes:{part:"title",id:"${state.titleId}"},textContent:"${state.title}"},{tagName:"jx-textfield",attributes:{part:"search"},$props:{type:"search",size:"sm",label:"Search media",placeholder:"Search by name…",autocomplete:"off",value:{$ref:"#/state/query"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/setQuery"},value:[{$ref:"event#/target/value"}]}]}},{tagName:"jx-select",attributes:{part:"sort"},$props:{label:"Sort",size:"sm",options:{$ref:"#/state/sortOptions"},value:{$ref:"#/state/sort"}},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/setSort"},value:[{$ref:"event#/target/value"}]}]}},{tagName:"label",attributes:{part:"upload",title:"${state.uploadHint}"},children:[{tagName:"input",attributes:{part:"upload-input",type:"file",multiple:!0,accept:"${state.uploadAccept}"},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/upload"},value:[{$ref:"event#/target"}]}],description:"The picker itself, so the destination in the label's tooltip is visible BEFORE the files are chosen. The flow takes the element rather than the file list because a file input that is not cleared refuses the same file twice."}},{tagName:"jx-icon",attributes:{part:"upload-glyph","aria-hidden":"true"},$props:{name:"upload-simple"}},{tagName:"span",textContent:"Upload"}]}]},{tagName:"div",attributes:{part:"body"},children:[{tagName:"div",attributes:{part:"grid-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/gridState"},cases:{loading:{tagName:"p",attributes:{part:"empty",role:"status"},textContent:"Reading the project's media…"},counting:{tagName:"p",attributes:{part:"empty",role:"status"},textContent:"${state.countingLabel}"},empty:{tagName:"div",attributes:{part:"empty"},children:[{tagName:"jx-icon",attributes:{part:"empty-glyph","aria-hidden":"true"},$props:{name:"image"}},{tagName:"p",attributes:{part:"empty-title"},textContent:"${state.emptyTitle}"},{tagName:"p",attributes:{part:"empty-detail"},textContent:"${state.emptyDetail}"},{tagName:"label",attributes:{part:"empty-upload",title:"${state.uploadHint}"},children:[{tagName:"input",attributes:{part:"upload-input",type:"file",multiple:!0,accept:"${state.uploadAccept}"},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/upload"},value:[{$ref:"event#/target"}]}],description:"The picker itself, so the destination in the label's tooltip is visible BEFORE the files are chosen. The flow takes the element rather than the file list because a file input that is not cleared refuses the same file twice."}},{tagName:"jx-icon",attributes:{part:"upload-glyph","aria-hidden":"true"},$props:{name:"upload-simple"}},{tagName:"span",textContent:"Upload"}]}]},nomatch:{tagName:"div",attributes:{part:"empty"},children:[{tagName:"jx-icon",attributes:{part:"empty-glyph","aria-hidden":"true"},$props:{name:"image"}},{tagName:"p",attributes:{part:"empty-title"},textContent:"${state.emptyTitle}"},{tagName:"p",attributes:{part:"empty-detail"},textContent:"${state.emptyDetail}"},{tagName:"jx-button",attributes:{part:"reset"},$props:{size:"sm",variant:"secondary"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/reset"},value:[]}]},children:[{tagName:"span",textContent:"Show all media"}]}]},listed:{tagName:"div",attributes:{part:"grid",role:"listbox","aria-labelledby":"${state.titleId}"},onkeydown:{$prototype:"Function",body:[{$switch:{$ref:"event#/key"},cases:{ArrowRight:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],ArrowLeft:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],ArrowDown:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],ArrowUp:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],Home:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],End:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/key"},value:[{$ref:"event#/key"},{$ref:"event#/ctrlKey"}]}],Enter:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/activateSelected"},value:[]}]}}],description:"The grid pattern: arrows move one tile, Home and End to the ends of the row, Ctrl+Home and Ctrl+End to the ends of the grid, and Enter opens the selected file (in pick mode, uses it). The flow computes where the move lands; the tile that receives it takes focus, so the roving tabindex follows the selection."},children:[{$prototype:"Array",items:{$ref:"#/state/tiles"},key:{$ref:"$map/item/key"},map:{tagName:"div",attributes:{part:"tile",role:"option","aria-selected":"${$map.item.selected}",tabindex:"${$map.item.tabindex}","data-file":"${$map.item.file}",title:"${$map.item.name}"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/select"},value:[{$ref:"$map/item/file"}]}]},onfocus:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/focusTile"},value:[{$ref:"$map/item/file"}]}],description:"Selection follows focus, the listbox pattern: a Tab onto the grid lands on the roving stop and selects it, so the first Enter opens (in pick mode, uses) the tile the focus ring is on rather than nothing."},ondblclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/activate"},value:[{$ref:"$map/item/file"}]}]},children:[{tagName:"div",attributes:{part:"thumb"},children:[{tagName:"div",attributes:{part:"thumb-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"$map/item/thumbState"},cases:{image:{tagName:"img",attributes:{part:"thumb-img",src:"${$map.item.thumbSrc}",alt:"",draggable:"false"},onload:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/measure"},value:[{$ref:"$map/item/file"},{$ref:"event#/target/naturalWidth"},{$ref:"event#/target/naturalHeight"}]}]}},pending:{tagName:"span",attributes:{part:"thumb-pending","aria-hidden":"true"}},glyph:{tagName:"jx-icon",attributes:{part:"thumb-glyph","aria-hidden":"true"},$props:{name:{$ref:"$map/item/glyph"}}}},$description:"The thumbnail is asked for when the tile scrolls into view, not when the grid is built: `pending` until the flow's observer reports the tile, then the picture. A file the browser draws no picture of shows its kind's glyph."}]},{tagName:"span",attributes:{part:"tile-name"},textContent:"${$map.item.name}"},{tagName:"span",attributes:{part:"tile-caption"},textContent:"${$map.item.caption}"}]}}]}}}]}]},{tagName:"aside",attributes:{part:"detail","aria-label":"Details"},children:[{tagName:"div",attributes:{part:"detail-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/detailState"},cases:{none:{tagName:"p",attributes:{part:"detail-hint"},textContent:"${state.detailHint}"},shown:{tagName:"div",attributes:{part:"detail-body",role:"none"},style:{display:"contents"},children:[{tagName:"div",attributes:{part:"detail-preview"},children:[{tagName:"div",attributes:{part:"preview-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/previewKind"},cases:{image:{tagName:"img",attributes:{part:"preview-img",src:"${state.previewSrc}",alt:""},onload:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/measure"},value:[{$ref:"#/state/selectedFile"},{$ref:"event#/target/naturalWidth"},{$ref:"event#/target/naturalHeight"}]}]}},video:{tagName:"video",attributes:{part:"preview-video",src:"${state.previewSrc}",controls:!0}},audio:{tagName:"audio",attributes:{part:"preview-audio",src:"${state.previewSrc}",controls:!0}},font:{tagName:"div",attributes:{part:"preview-specimen",style:"${state.previewSpecimenFamily}"},children:[{tagName:"style",textContent:"${state.previewFontFace}"},{tagName:"p",attributes:{part:"specimen-line","data-size":"32"},textContent:"Aa"},{tagName:"p",attributes:{part:"specimen-line","data-size":"14"},textContent:"${state.previewSpecimen}"}]},glyph:{tagName:"jx-icon",attributes:{part:"preview-glyph","aria-hidden":"true"},$props:{name:{$ref:"#/state/previewGlyph"}}}}}]},{tagName:"h3",attributes:{part:"detail-name"},textContent:"${state.detailName}"},{tagName:"p",attributes:{part:"facts"},textContent:"${state.detailFacts}"},{tagName:"div",attributes:{part:"url-group"},children:[{tagName:"h4",attributes:{part:"group-title"},textContent:"Site URL"},{tagName:"div",attributes:{part:"url"},children:[{tagName:"code",attributes:{part:"url-value"},textContent:"${state.detailRef}"},{tagName:"jx-action-button",attributes:{part:"copy"},$props:{size:"sm",quiet:!0,hint:"Copy the site URL"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/copyRef"},value:[]}]},children:[{tagName:"span",textContent:"Copy"}]}]}]},{tagName:"div",attributes:{part:"usage-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/usageState"},cases:{shown:{tagName:"div",attributes:{part:"usage"},children:[{tagName:"h4",attributes:{part:"group-title"},textContent:"Used on"},{tagName:"p",attributes:{part:"usage-headline"},textContent:"${state.usageHeadline}"},{tagName:"div",attributes:{part:"usage-list-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/hasUsageFiles"},cases:{true:{tagName:"ul",attributes:{part:"usage-list"},children:[{$prototype:"Array",items:{$ref:"#/state/usageFiles"},key:{$ref:"$map/item/path"},map:{tagName:"li",attributes:{part:"usage-row","data-usage":"${$map.item.path}"},children:[{tagName:"button",attributes:{part:"usage-link",type:"button",title:"Open ${$map.item.path}"},textContent:"${$map.item.path}",onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openDocument"},value:[{$ref:"$map/item/path"}]}]}},{tagName:"span",attributes:{part:"usage-count"},textContent:"${$map.item.count}"}]}}]}}}]}},$description:'Hidden on a host with no reference index, which is a different fact from "nothing uses it": a confident zero is the one answer this pane must never invent.'},{tagName:"div",attributes:{part:"actions-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/mode"},cases:{manage:{tagName:"div",attributes:{part:"actions"},children:[{tagName:"label",attributes:{part:"replace",title:"Replace ${state.detailName} everywhere it is used"},children:[{tagName:"input",attributes:{part:"replace-input",type:"file",accept:"${state.replaceAccept}"},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/replace"},value:[{$ref:"event#/target"}]}],description:"Replace writes the chosen file over this one's path, so every reference keeps resolving and now shows the new bytes (studio.md §9.3). The element rather than the list, so the input can be cleared."}},{tagName:"span",textContent:"Replace"}]},{tagName:"jx-button",attributes:{part:"open-viewer"},$props:{size:"sm",variant:"secondary"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openViewer"},value:[]}]},children:[{tagName:"span",textContent:"Open in viewer"}]},{tagName:"jx-button",attributes:{part:"delete"},$props:{size:"sm",variant:"negative"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/remove"},value:[]}]},children:[{tagName:"span",textContent:"Delete"}]}]}},$description:"Manage mode's actions. Pick mode has none here: its answer is the dialog's own footer, Cancel and Use <file>."}]}}}]}]};T("media-library",de);function Ee(){return{countingLabel:"",detailFacts:"",detailHint:"",detailName:"",detailRef:"",detailState:"none",dropActive:"false",emptyDetail:"",emptyTitle:"",filters:[],gridState:"loading",mode:"manage",previewFontFace:"",previewGlyph:"",previewKind:"glyph",previewSpecimen:"",previewSpecimenFamily:"",previewSrc:"",query:"",region:"",replaceAccept:"",selectedFile:"",sort:"",sortOptions:[],tiles:[],title:"",titleId:"",uploadAccept:"",uploadHint:"",usageFiles:[],usageHeadline:"",usageState:"hidden"}}function pe(e,t){Object.assign(e,t),e.hasUsageFiles=t.usageFiles.length>0}function Ae(e){let t=n(e)?void 0:e.attributes?.part;return n(t)?t:""}function Ie(e){let t=e?.$map,i=_(t)&&"item"in t?t.item:void 0;return _(i)&&"file"in i&&n(i.file)?i.file:null}function q(e,t,i,a){if(a.clear)e.replaceChildren();let{tileHost:r,gridHost:o,inputHost:l,...c}=i,s=g({...Ee(),...c,hasUsageFiles:!1});pe(s,t);let h=null,w=!1,P=R("media-library",s,e,{onNodeCreated:(f,d,k,Te)=>{if(w||!(f instanceof HTMLElement))return;let H=Ae(k);if(H==="tile"){let ee=Ie(Te);if(ee!==null)r(f,ee)}else if(H==="grid")o(f);else if(f instanceof HTMLInputElement&&H==="upload-input")l(f,"upload");else if(f instanceof HTMLInputElement&&H==="replace-input")l(f,"replace")}}).then((f)=>{if(w)f.dispose();else h=f;return f.root});return{attached:()=>{if(w)return!1;let f=h?.root;return f===void 0?!0:f instanceof HTMLElement&&e.contains(f)},dispose(){w=!0,h?.dispose(),h=null},ready:P,update:(f)=>pe(s,f)}}var ce={$schema:"https://jxsuite.com/schema/v1",$id:"StudioMediaPickDialog",$description:"The full-size media picker (`specs/studio.md` §9.3): a `jx-dialog` whose body is the Media workspace's own library surface in pick mode, so the picker and the workspace are one surface at two sizes. The dialog owns modality, Escape, the backdrop and focus restoration, and its footer is the answer: Cancel, or Use <file>, disabled until a file is chosen. The body is an ISLAND: this document draws the slot and nothing in it, and `surfaces/media-pick-dialog.ts` mounts `media-library.json` there through `onNodeCreated`.",tagName:"jx-dialog",$props:{headline:{$ref:"#/state/headline"},confirmLabel:{$ref:"#/state/confirmLabel"},confirmDisabled:{$ref:"#/state/blocked"},cancelLabel:"Cancel",dismissible:!0,size:"xl"},attributes:{part:"media-pick"},onconfirm:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/confirm"},value:[]}]},oncancel:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},onclose:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},children:[{tagName:"div",attributes:{part:"library-slot"},style:{$description:"The library's box in pick mode is its own (`media-library.json`, `data-mode=\"pick\"`); the slot only gives it the dialog body's width.",minWidth:"0"}}]};T("media-pick-dialog",ce);var V="media-picker";function Oe(e){let t=n(e)?void 0:e.attributes?.part;return n(t)?t:""}function ue(e){let t=document.createElement("div");t.style.pointerEvents="auto",t.setAttribute(Ue,ft("dialog",V)),e.layer.append(t);let i=!1,a=()=>{if(i)return;i=!0,e.closed()},r=()=>i,o=g({...e.view,closed:a,confirm:e.confirm}),l=null,c=R("media-pick-dialog",o,t,{onNodeCreated:(s,h,w)=>{if(!r()&&s instanceof HTMLElement&&Oe(w)==="library-slot")e.body(s)}}).then(async(s)=>{l=s;let h=s.root;if(r())return s.dispose(),h;if(await Jt(h),!r())Ot(h);return h});return{close(){let s=l?.root;if(s instanceof HTMLElement)Nt(s);l?.dispose(),l=null,t.remove(),a()},host:t,ready:c,update(s){Object.assign(o,s)}}}var tP="media-home",ve={audio:"play",document:"file-text",font:"text-aa",image:"image",video:"play"},Pe={audio:"Audio",document:"Document",font:"Font",image:"Image",video:"Video"},y={filter:"all",query:"",sort:"newest",selected:null},j=null,x=null,A=0,I=0,E=!1,G=0;function Y(){x=null,E=!1,A=0,I=0,G+=1}function Ke(){return[...S].some((e)=>!e.disposed&&e.choice.filter==="unused")}async function ze(e){if(E||x!==null||!hh())return;let t=G;E=!0,A=0,I=e.length;let i=new Set;for(let a of e){let r=await Gu(a.file);if(t!==G)return;if(!Ke()){Y();return}if(r.status==="ready"&&r.result.files.length===0)i.add(a.file);A+=1,b()}x=i,E=!1,b()}var S=new Set,M=new Map,J=new Set,L=null;function be(){if(L!==null)return;let e=()=>{Y(),b()},t=NT(e),i=E$(e);L=()=>{t(),i()}}function _e(){if(S.size===0&&L)L(),L=null}function v(e){if(!e.disposed){if(e.handle?.update(X(e)),e.onSelect?.(),We(e),e.focusOwed)queueMicrotask(()=>Le(e));we(e)}}function We(e){let t=e.reveal,i=t===null?void 0:e.tiles.get(t);if(i?.isConnected)e.reveal=null,i.scrollIntoView({block:"nearest"})}function we(e){if(e.sweepTimer!==null||e.disposed)return;e.sweepTimer=setTimeout(()=>{e.sweepTimer=null,e.observer.releaseDetached();for(let[t,i]of e.tiles)if(!i.isConnected)e.tiles.delete(t);for(let t of[e.inputs.upload,e.inputs.replace])for(let i of t)if(!i.isConnected)t.delete(i)},0)}function xe(e){return[...e].find((t)=>t.isConnected)??null}function b(){for(let e of S)v(e)}function Q(e){if(e.disposed=!0,e.sweepTimer!==null)clearTimeout(e.sweepTimer),e.sweepTimer=null;e.inputs.upload.clear(),e.inputs.replace.clear(),e.observer.destroy(),e.handle?.dispose(),e.handle=null,e.tiles.clear(),S.delete(e),_e()}function $e(e){let t=Wu(),i=t===null?null:e.images?t.filter((r)=>r.isImage):t;return{files:(i??[]).map((r)=>{let o=Dd(r.file);return{bytes:o?.bytes??null,file:r.file,kind:r.kind,modified:o?.modified??null,name:r.name}}),listed:i}}function qe(e){return D.filter((t)=>(t.key!=="unused"||hh())&&(!e.images||t.key==="image"||t.key==="unused"))}function xw(e){let{filter:t,query:i,selected:a}=e.choice;if(a===null)return null;let r=Wu()?.find((l)=>l.file===a)??null;if(r===null||e.images&&!r.isImage)return null;let o={bytes:null,file:r.file,kind:r.kind,modified:null,name:r.name};return z(o,t,x)&&U(o,i)?r:null}function Ve(e,t){if(t===0)return{emptyDetail:`Upload files or drop them anywhere here. They are saved under ${e.uploadDir}/, and anything already under public/ or a collection's images/ folder is listed here too.`,emptyTitle:e.images?"No images yet":"No media yet"};let{filter:i,query:a}=e.choice;if(a.trim()!=="")return{emptyDetail:`Nothing in ${F(i)} matches it.`,emptyTitle:`No matches for “${a.trim()}”`};if(i==="unused")return{emptyDetail:"Every file is referenced by at least one document.",emptyTitle:"No unused media"};return{emptyDetail:`${t} ${t===1?"file":"files"} in the project, none of them ${F(i).toLowerCase()}.`,emptyTitle:`No ${F(i).toLowerCase()}`}}function X(e){let{choice:t}=e,{files:i,listed:a}=$e(e),r=ne(i,x),o=qe(e);if(!o.some((d)=>d.key===t.filter))t.filter=o[0]?.key??"all";let l=W(i,{filter:t.filter,query:t.query,sort:t.sort,unused:x}),c=Wu();if(t.filter==="unused"&&c!==null)ze(c);let s="listed";if(a===null)s="loading";else if(t.filter==="unused"&&x===null)s="counting";else if(i.length===0||l.length===0)s=i.length===0?"empty":"nomatch";let h=xw(e),w=l.some((d)=>d.file===t.selected)?t.selected:l[0]?.file??null,P=l.map((d)=>{let k=d.kind==="image";return{caption:Aw(Dd(d.file))||Pe[d.kind],file:d.file,glyph:ve[d.kind],key:d.file,name:d.name,selected:d.file===t.selected?"true":"false",tabindex:d.file===w?"0":"-1",thumbSrc:k&&e.visible.has(d.file)?tr(d.file):"",thumbState:k?e.visible.has(d.file)?"image":"pending":"glyph"}}),f=e.images&&t.filter==="image"?"Images":F(t.filter);return{countingLabel:I>0?`Counting references… ${A} of ${I}`:"Counting references…",dropActive:e.dropActive?"true":"false",filters:o.map((d)=>{let k=r[d.key];return{count:k===null?"":String(k),key:d.key,label:e.images&&d.key==="image"?"All images":d.label,pressed:d.key===t.filter?"true":"false"}}),gridState:s,mode:e.mode,query:t.query,region:e.region,sort:t.sort,sortOptions:K.map((d)=>({label:d.label,value:d.key})),tiles:P,title:f,titleId:`media-library-title-${e.region.replaceAll(/[^\w-]/g,"-")}`,uploadAccept:e.images?"image/*":zc(),uploadHint:`Upload into ${e.uploadDir}/`,...Ve(e,i.length),...Be(e,h)}}function Be(e,t){if(t===null)return{detailFacts:"",detailHint:e.mode==="pick"?"Choose a file to use it.":"Select a file to see its details.",detailName:"",detailRef:"",detailState:"none",previewFontFace:"",previewGlyph:"",previewKind:"glyph",previewSpecimen:"",previewSpecimenFamily:"",previewSrc:"",replaceAccept:"",selectedFile:"",usageFiles:[],usageHeadline:"",usageState:"hidden"};let i=Dd(t.file),a=Ow(t.file);if(!Rd(t.file))qu(t.file).then(b);if(a===null||a.status==="pending")Gu(t.file).then(b);let r=jT(t.file),o=r==="image"||r==="video"||r==="audio"||r==="font"?r:"glyph",l=o==="font"?BT(t.file):{fontFace:"",specimen:"",specimenFamily:""};return{detailFacts:HT(t.file,i),detailHint:"",detailName:t.name,detailRef:t.ref,detailState:"shown",previewFontFace:l.fontFace,previewGlyph:ve[t.kind],previewKind:o,previewSpecimen:l.specimen,previewSpecimenFamily:l.specimenFamily,previewSrc:o==="glyph"?"":tr(t.file),replaceAccept:hA(t.file),selectedFile:t.file,...zT(a)}}var fe=null,me=null;function Ge(){return fe??=(le("yswdhxrf"),import("./files-yswdhxrf.js")),fe}function Ye(){return me??=(le("kkhp9ma7"),import("./file-ops-kkhp9ma7.js")),me}function Z(e){try{e.showPicker()}catch{e.focus()}}function N(e,t){e.choice.selected=t,v(e)}async function ge(e,t){let i=await Sa([...t],{dir:e.uploadDir,only:e.images?"image":"media"}),[a]=i;if(!a)return;if(e.choice.filter!=="all"&&e.choice.filter!==a.kind)e.choice.filter=e.images?"image":"all";e.choice.query="",e.reveal=a.path,N(e,a.path)}async function O2(e){let t=e.split("/").pop()??e,{confirmFileDelete:i}=await Ye();if(!await i({name:t,path:e}))return!1;let{markLocalMutation:a}=await (le("z9gpvc6t"),import("./fs-events-z9gpvc6t.js"));try{a(e),await p().deleteFile(e)}catch(l){return C.error(`Could not delete ${t}.`,{detail:te(l),path:e,source:"Media"}),!1}if(zd([e]),Sr(),m.tabs.has(e))Kd(e);for(let l of S)if(l.choice.selected===e)l.choice.selected=null;if(y.selected===e)y.selected=null;let r=Fb(e),o=await Je(r,a);return await QL(o?Fb(r):r),C.success(`Deleted ${t}`),!0}async function Je(e,t){if(!dA(e))return!1;let i=p();try{if((await i.listDirectory(e)).length>0)return!1;return t(e),await i.deleteFile(e),!0}catch{return!1}}function Me(e){return{activate:(t)=>{N(e,t),he(e,t)},activateSelected:()=>{let{selected:t}=e.choice;if(t!==null)he(e,t)},copyRef:()=>{let t=xw(e);if(t&&"clipboard"in navigator)navigator.clipboard.writeText(t.ref)},dragOut:()=>{if(e.dropActive)e.dropActive=!1,v(e)},dragOver:()=>{if(!e.dropActive)e.dropActive=!0,v(e)},drop:(t)=>{if(e.dropActive=!1,v(e),t?.length)ge(e,t)},focusTile:(t)=>{if(e.choice.selected!==t)N(e,t)},gridHost:(t)=>{e.grid=t},inputHost:(t,i)=>{e.inputs[i].add(t),we(e);let a=j;if(e.mode==="manage"&&a?.role===i&&(i==="upload"||a.file===e.choice.selected))j=null,Z(t)},key:(t,i)=>Qe(e,t,i),measure:(t,i,a)=>{if(_p(t,i,a))b();else if(!Rd(t))qu(t).then(b)},openDocument:(t)=>{Ge().then(({openFileInTab:i})=>i(t))},openViewer:()=>{let{selected:t}=e.choice;if(t!==null)_b(t)},remove:()=>{let{selected:t}=e.choice;if(t!==null)O2(t)},replace:(t)=>{let[i]=t.files??[];t.value="";let{selected:a}=e.choice;if(i&&a!==null)pA(a,i).then(b)},reset:()=>{e.choice.filter=e.images?"image":"all",e.choice.query="",v(e)},select:(t)=>N(e,t),setFilter:(t)=>{if(ae(t))e.choice.filter=t,v(e)},setQuery:(t)=>{e.choice.query=t,v(e)},setSort:(t)=>{if(re(t))e.choice.sort=t,v(e)},tileHost:(t,i)=>{e.tiles.set(i,t),ke.set(t,i),e.observer.observe(t)},upload:(t)=>{let i=[...t.files??[]];if(t.value="",i.length>0)ge(e,i)}}}function he(e,t){if(e.mode==="pick"){let i=xw(e);if(i)e.onPick?.(i);return}_b(t)}function Qe(e,t,i){let{files:a}=$e(e),r=W(a,{filter:e.choice.filter,query:e.choice.query,sort:e.choice.sort,unused:x}),o=r.findIndex((h)=>h.file===e.choice.selected),l=e.grid?oe(He(e.grid).width):1,c=o===-1?r.length>0?0:null:se(o,t,l,r.length,i),s=c===null?void 0:r[c];if(!s)return;N(e,s.file),e.tiles.get(s.file)?.focus()}var ke=new WeakMap;function Se(e,t,i,a,r,o){let l={choice:t,disposed:!1,dropActive:!1,grid:null,handle:null,images:r,inputs:{replace:new Set,upload:new Set},mode:e,observer:bp((c)=>{let s=ke.get(c);if(s!==void 0&&!l.visible.has(s))l.visible.add(s),Xe(l)}),onPick:null,onSelect:null,paneId:a,reveal:null,focusOwed:!1,region:i,sweepTimer:null,tiles:new Map,uploadDir:o,visible:new Set};return l}var B=new Set;function Xe(e){if(B.has(e))return;B.add(e),queueMicrotask(()=>{B.delete(e),v(e)})}function fS(e,t){let i=M.get(e);return i!==void 0&&i.tabId===t.id&&i.wrap.isConnected&&i.mount.handle!==null&&i.mount.handle.attached()}function _w(e){let t=M.get(e);if(!t)return;Q(t.mount),M.delete(e)}function LT(e,t){let{paneId:i,wrap:a}=e;if(fS(i,t))return;_w(i);let r=Se("manage",y,wi(i,"media-library"),i,!1,_a);if(S.add(r),be(),r.handle=q(a,X(r),Me(r),{clear:!0}),M.set(i,{mount:r,tabId:t.id,wrap:a}),J.delete(i))Fe(r)}async function Fe(e){await e.handle?.ready,Le(e,!0)}function Le(e,t=e.focusOwed){if(!t||e.disposed)return;let{selected:i}=e.choice,a=(i===null?void 0:e.tiles.get(i))??[...e.tiles.values()].find((r)=>r.getAttribute("tabindex")==="0");if(a?.isConnected){e.focusOwed=!1,a.focus();return}e.focusOwed=!0}function $T(e){let t=M.get(e);if(t?.wrap.isConnected&&t.mount.handle?.attached()===!0){Fe(t.mount);return}J.add(e)}function M2(e){if(e.filter!==void 0)y.filter=e.filter;if(e.query!==void 0)y.query=e.query;if(e.select!==void 0){if(y.selected=e.select,y.filter!=="all")y.filter="all";y.query=""}b()}function nP(){let e=[...M.values()].map((t)=>xe(t.mount.inputs.upload)).find((t)=>t!==null)??null;if(e){Z(e);return}j={file:null,role:"upload"}}function iP(e){M2({select:e});let t=null;for(let i of M.values())if(i.mount.choice.selected===e)t??=xe(i.mount.inputs.replace);if(t){Z(t);return}j={file:e,role:"replace"}}var O=null;function ye(e){let t=xw(e);return{blocked:t===null,confirmLabel:t?`Use ${t.name}`:e.images?"Use image":"Use file",headline:e.images?"Choose an image":"Choose media"}}function mS(){let e=O;if(O=null,e)Q(e.mount),e.dialog.close()}function oP(e){mS();let t={filter:e.images?"image":"all",query:"",selected:null,sort:"newest"},i=Se("pick",t,`${ft("dialog",V)}/library`,null,e.images,XL(u.value?.documentPath??null)),a=(o)=>{mS(),e.onPick(o.ref)};i.onPick=a,S.add(i),be();let r=ue({body:(o)=>{i.handle=q(o,X(i),Me(i),{clear:!1})},closed:()=>{if(O?.mount===i)mS();else Q(i)},confirm:()=>{let o=xw(i);if(o)a(o)},layer:tt("dialog"),view:ye(i)});i.onSelect=()=>r.update(ye(i)),O={dialog:r,mount:i}}function IT(){mS();for(let e of M.keys())_w(e);y.filter="all",y.query="",y.selected=null,y.sort="newest",j=null,J.clear(),Y()}
|
|
2
|
+
export{pS,tP,xw,O2,fS,_w,LT,$T,M2,nP,iP,mS,oP,IT};
|
|
3
|
+
|
|
4
|
+
//# debugId=06DC0765C6515CCB64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=studio-dvhxxxbd.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{Q}from"./studio-nqxqf8p2.js";import{p}from"./studio-pr23qhrw.js";import{g,C}from"./studio-hw60n5dh.js";import{Qb}from"./studio-y1x65h5r.js";import{Mt,Nt,ae}from"./studio-7cg75gtj.js";import{Fl,gp}from"./studio-bf0rgyf7.js";import{qe,ft,T,R,Jt,rt,tt}from"./studio-02phtmqn.js";import{zu}from"./studio-73wz63nn.js";import{FD}from"./studio-74nzv280.js";import{Gl}from"./studio-m4w6sygj.js";import{S}from"./studio-ana67wax.js";import{n,te,_,v}from"./studio-kt2j51sa.js";var B=[{id:"general",intro:"",label:"General",note:""},{id:"integrations",intro:"Turn on what your site needs. Each one adds its own options where you use it.",label:"Integrations",note:""},{id:"advanced",intro:"Changes here affect every page. Most sites never need them.",label:"Advanced",note:"For developers"}],NR="integrations";function AR(e){return B.some((o)=>o.id===e)}var ve="overview",E=new Map,G=new Set;function D(){for(let e of G)e()}function Sd(){D()}function S_(e){return G.add(e),()=>{G.delete(e)}}function Ol(e){E.set(e.key,e),D()}function OR(e){if(E.delete(e))D()}function we(){return[...E.values()].toSorted((e,o)=>e.order-o.order)}function Py(){let e=we();return B.flatMap((o)=>{let s=e.filter((t)=>(t.group??"integrations")===o.id);return s.length===0?[]:[{id:o.id,intro:o.intro,label:o.label,note:o.note,sections:s}]})}function Hk(){return Py().flatMap((e)=>e.sections.map((o)=>o.key))}function H(e){return E.get(e)}var L=null,P=ve;function V(){if(L!==null&&E.has(L))return P=L,L=null,P;if(E.has(P))return P;return Hk()[0]??P}function C_(e){if(E.has(e))P=e,L=null;else L=e;D()}var X={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsDialog",$description:"Project Settings (§17.1): a `jx-dialog` whose body is the settings editor's two columns, the grouped section list and the section body. The dialog owns modality, Escape and focus restoration, and its one footer answer is Close: every section writes as it is edited, so there is nothing to confirm or cancel. The body is an ISLAND: this document draws the slot and nothing in it, and `settings/settings-dialog.ts` mounts `settings-pane.json` there through `onNodeCreated` (studio-ui-guidelines.md §9.4).",tagName:"jx-dialog",$props:{headline:"Project settings",confirmLabel:"",cancelLabel:"Close",size:"xl"},attributes:{part:"settings"},oncancel:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},onclose:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},children:[{tagName:"div",attributes:{part:"pane-slot"},style:{$description:"The editor's box is its own (`settings-pane.json`); the slot only gives it the dialog body's width.",minWidth:"0"}}]};T("settings-dialog",X);var W=ft("dialog","settings");function xe(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function Z(e){let o=document.createElement("div");o.style.pointerEvents="auto",e.layer.append(o);let s=!0,t=!1,i=()=>{if(!s)return;s=!1,e.closed()},r=g({closed:i}),l=null,a=(d)=>{if(!t&&s)Mt(d);return d},c=R("settings-dialog",r,o,{onNodeCreated:(d,m,h)=>{if(!t&&d instanceof HTMLElement&&xe(h)==="pane-slot")e.body(d)}}).then(async(d)=>{let m=d.root;if(t)return d.dispose(),m;return l=d,await Jt(m),(m.querySelector('dialog[part="dialog"]')??m).setAttribute(qe,W),a(m)}),u=()=>{let d=l?.root;if(d instanceof HTMLElement)Nt(d);i()};return{close:u,dispose(){if(t)return;u(),t=!0,l?.dispose(),l=null,o.remove()},host:o,ready:c,show(){if(!t)s=!0;return c.then(a)}}}var ee={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsContributed",$description:'The generic settings section behind `$studio.settings` (specs/extensions.md §9.1), as a Jx document over the kit. One document serves both layouts an extension may declare: "form" is a single schema form over the whole section value, "map" is master-detail — the entry keys on the left, the selected entry\'s form on the right. The adapter (`surfaces/settings-contributed.ts`) hands in the title, the layout, the entry rows already marked as selected, and whatever the reader is part-way through typing; `settings/contributed-section.ts` decides what an entry may be named, what reaches `project.json`, and what the validator said about it. The schema form itself is an ISLAND: this document renders `form-host` and nothing inside it, because a form built from a JSON Schema is `ui/schema-form.ts`\'s surface rather than this one\'s — the section places the element that surface hands back. The actions row is the second island: `panels/data-grid.ts` contributes it, and that one is still lit over Spectrum.',tagName:"section",attributes:{part:"contributed"},style:{$description:"What `.settings-section-title`, `.settings-two-col`, `.settings-list-panel`, `.settings-editor-panel`, `.settings-editor-header`, `.settings-empty-state` and `.settings-inline-form` said in `styles/overlays.css`, keyed on `part` and re-pointed at the studio token layer. This section was the LAST emitter of every one of them except `.settings-empty-state`, which `panels/settings-pane.ts` still writes when a project closes with the editor open — so those rules are dead in the stylesheet from here, and a central sweep removes them rather than this change, which owns no stylesheet. Two values could not come across. `.settings-editor-header h3` read `var(--spectrum-font-size-100, 14px)`, and a document is mounted in the pane rather than inside `<sp-theme>`, so it would have taken its hard-coded fallback every time; the entry name is a kit textfield now and carries the kit's own type ramp. And `.entry-name-input`, `.settings-form-panel`, `.settings-section` and `.contributed-section` had no rule anywhere at all — they were four entries on `check-styles.ts`'s orphan ledger, which is the ledger's point.",display:"block",'& [part="title"]':{margin:"0 0 16px",fontSize:"16px",fontWeight:"600",color:"var(--fg)"},'& [part="actions"]':{$description:"The host-contributed actions row — Test Connection, Push Schema, Open Data Grid on the data sections. `.data-section-actions` never had a rule anywhere, so the row was whatever the buttons stacked up to; it is a row with a gap under it now.",display:"flex",alignItems:"center",flexWrap:"wrap",gap:"8px",marginBottom:"12px"},'& [part="columns"]':{$description:"The 1px gap over the border colour is the divider between the two columns: two panels on `--bg-panel` with `--border` showing through the gap, so nothing draws a rule of its own.",display:"flex",height:"100%",gap:"1px",background:"var(--border)"},'& [part="list"]':{display:"flex",flexDirection:"column",gap:"4px",padding:"12px",width:"200px",minWidth:"200px",background:"var(--bg-panel)",overflowY:"auto"},'& [part="entry"], & [part="new-open"]':{width:"100%"},'& [part="entry"] > [part="control"], & [part="new-open"] > [part="control"]':{$description:"`.settings-list-panel sp-action-button` said `width: 100%; justify-content: flex-start`, and both halves belong to the button the row is made of rather than to the row: a kit action button centres its glyph and its label, which reads as a list of centred names.",width:"100%",justifyContent:"flex-start"},'& [part="new-form"]':{display:"flex",alignItems:"center",gap:"6px"},'& [part="new-field"]':{flex:"1",minWidth:"0"},'& [part="empty"]':{flex:"1",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--bg-panel)",color:"var(--fg-dim)",fontSize:"13px"},'& [part="editor"]':{$description:"`min-width: 0` is the one line `.settings-editor-panel` did not have and needed: a flex child's floor is its content, and the schema form inside this one is a whole form rather than the short cards Data Shapes puts here — so a long pointer or a wide row pushed the column past the right edge of the pane instead of scrolling inside it.",flex:"1",padding:"16px",background:"var(--bg-panel)",overflowY:"auto",minWidth:"0"},'& [part="editor-header"]':{display:"flex",alignItems:"center",gap:"12px",marginBottom:"16px"},'& [part="entry-name"]':{flex:"1",minWidth:"0",maxWidth:"220px"}},children:[{tagName:"h3",attributes:{part:"title"},textContent:"${state.title}"},{tagName:"div",attributes:{part:"actions-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/actionsState"},cases:{slot:{$description:"An island: the host renders its own actions into this node and the document renders nothing inside it.",tagName:"div",attributes:{part:"actions"}}}},{tagName:"div",attributes:{part:"body-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/layout"},cases:{form:{$description:"An island: `ui/schema-form.ts` draws the whole section value into this node.",tagName:"div",attributes:{part:"form-host"}},map:{tagName:"div",attributes:{part:"columns"},children:[{tagName:"div",attributes:{part:"list"},children:[{$prototype:"Array",items:{$ref:"#/state/entries"},key:{$ref:"$map/item/key"},map:{tagName:"jx-action-button",attributes:{part:"entry","data-entry":"${$map.item.key}","data-jx-region":"${$map.item.region}"},$props:{label:"${$map.item.key}",selected:{$ref:"$map/item/selected"},quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/select"},value:[{$ref:"$map/item/key"}]}]},children:[{tagName:"span",textContent:"${$map.item.key}"}]}},{tagName:"div",attributes:{part:"new-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/newState"},cases:{closed:{tagName:"jx-action-button",attributes:{part:"new-open"},$props:{label:"${state.newLabel}",icon:"plus",quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openNew"},value:[]}]},children:[{tagName:"span",textContent:"${state.newLabel}"}]},open:{tagName:"div",attributes:{part:"new-form"},children:[{tagName:"jx-textfield",attributes:{part:"new-field"},$props:{label:"${state.newFieldLabel}",placeholder:"${state.newPlaceholder}",size:"sm",value:{$ref:"#/state/newName"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/editNew"},value:[{$ref:"event#/target/value"}]}]},onkeydown:{$prototype:"Function",body:[{$switch:{$ref:"event#/key"},cases:{Enter:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/createNew"},value:[]}],Escape:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/cancelNew"},value:[]}]}}]}},{tagName:"jx-button",attributes:{part:"new-create"},$props:{size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/createNew"},value:[]}]},children:[{tagName:"span",textContent:"Create"}]}]}}}]},{tagName:"div",attributes:{part:"editor-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/editorState"},cases:{empty:{tagName:"div",attributes:{part:"empty"},textContent:"${state.emptyText}"},editing:{tagName:"div",attributes:{part:"editor","data-jx-region":"${state.editorRegion}"},children:[{tagName:"div",attributes:{part:"editor-header"},children:[{tagName:"jx-textfield",attributes:{part:"entry-name"},$props:{label:"Entry name",size:"sm",value:{$ref:"#/state/entryName"}},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/renameEntry"},value:[{$ref:"event#/target/value"}]}]},onkeydown:{$prototype:"Function",body:[{$switch:{$ref:"event#/key"},cases:{Enter:[{operator:"call",target:{$ref:"#/state/renameEntry"},value:[{$ref:"event#/target/value"}]}],Escape:[{operator:"call",target:{$ref:"#/state/cancelRename"},value:[{$ref:"event#/target/value"}]}]}}]}},{tagName:"jx-action-button",attributes:{part:"delete-entry"},$props:{label:"Delete entry",hint:"Delete entry",icon:"trash",quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/removeEntry"},value:[]}]}}]},{$description:"An island: `ui/schema-form.ts` draws the selected entry into this node.",tagName:"div",attributes:{part:"form-host"}}]}}}]}}}]};T("settings-contributed",ee);function Te(){return{actionsState:"none",editorRegion:"",editorState:"empty",entries:[],entryName:"",layout:"form",newName:"",newState:"closed",title:"",emptyText:"",newFieldLabel:"",newLabel:"",newPlaceholder:""}}function Ne(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function ne(e,o,s){e.textContent="";let t=g({...Te(),...o}),i=null,r=!1,l=R("settings-contributed",t,e,{onNodeCreated:(a,c,u)=>{if(!(a instanceof HTMLElement))return;let d=Ne(u);if(d==="form-host")s.formSlot(a);else if(d==="actions")s.actionsSlot(a)}}).then((a)=>{let c=a.root;if(r)return a.dispose(),c;return i=a,c});return{attached:()=>{if(r)return!1;let a=i?.root;return a===void 0?!0:a instanceof HTMLElement&&e.contains(a)},dispose(){r=!0,i?.dispose(),i=null},host:e,ready:l,update(a){t.actionsState=a.actionsState,t.editorRegion=a.editorRegion,t.editorState=a.editorState,t.entries=a.entries,t.entryName=a.entryName,t.layout=a.layout,t.newName=a.newName,t.newState=a.newState,t.title=a.title,t.emptyText=a.emptyText,t.newFieldLabel=a.newFieldLabel,t.newLabel=a.newLabel,t.newPlaceholder=a.newPlaceholder}}}var x=new Map,A=new Set,I=new Map;function MR(e,o){let s=S?.projectConfig?.[e],t=v(s)?s:{};if(!Object.hasOwn(t,o))return Object.keys(t);return x.set(e,o),null}var J=new Map;function ke(e,o){let s={},t=[];for(let i of o){let r=i.indexOf(": "),l=r===-1?"":i.slice(0,r),a=r===-1?i:i.slice(r+2);if(l===e){t.push(a);continue}if(!l.startsWith(`${e}/`))continue;let[c]=l.slice(e.length+1).split("/");if(c&&s[c]===void 0)s[c]=a}return{fields:s,section:t}}async function z(e,o){let s=S?.projectConfig;if(!s)return;if(!(await Gl()).ok)return;let i=[];try{i=await zu(s)}catch(r){C.warn(`Could not validate project.json — ${Q(r)}`,{key:"settings:validator",path:"project.json",source:"Settings",tier:"problem"});return}J.set(e,ke(e,i).fields),o()}function oe(e,o){for(let[s,t]of Object.entries(o))if(t===void 0)delete e[s];else e[s]=t}function U(e){return e.toLowerCase().replaceAll(/\s+/g,"-").replaceAll(/[^a-z0-9-]/g,"")}function Ce(e,o){if(!e)return{};let s=(i)=>{let r={};for(let[l,a]of Object.entries(i))r[l]=t(a);return r},t=(i)=>{if(n(i))return i.replaceAll("${key}",o);if(Array.isArray(i))return i.map((r)=>t(r));if(v(i))return s(i);return i};return s(e)}function ie(e,o,s=null){let t=p(),i={fieldKeyPrefix:`$settings.${e}`,resolvePointer:(r,l)=>{let a={projectConfig:S?.projectConfig??{}};if(v(l))a.scope=l;if(o.formats!==void 0)a.formats=o.formats;return gp(r,a)}};if(te(t.setSecrets))i.commitSecret=async(r,l)=>{let a=FD(e,s,r);return await t.setSecrets({set:{[a]:l}}),a};return i}function j(e){let o=S?.projectConfig;if(!o)return null;let s=o[e];if(v(s))return s;let t={};return o[e]=t,t}function re(e){return`${W}/${e}`}var se=new WeakMap;function w(e){Bk(e.container,e.contribution,e.opts)}function le(e,o){e.echo=o,w(e)}var Ee="entry";function je(e){let o=e?.trim().toLowerCase()||Ee,s=`${o.charAt(0).toUpperCase()}${o.slice(1)}`;return{emptyText:`Select ${/^[aeiou]/u.test(o)?"an":"a"} ${o} or create one`,newFieldLabel:`${s} name`,newLabel:`New ${o}`,newPlaceholder:`${U(o)}-name`}}function Me(e){let{contribution:o,opts:s}=e,t=o.key,i=o.title??t,r=s.actions?"slot":"none",l=re("editor"),a=je(o.settings.entry?.noun);if((o.settings.layout??"form")!=="map")return{actionsState:r,editorRegion:l,editorState:"empty",entries:[],entryName:"",layout:"form",newName:"",newState:"closed",title:i,...a};let c=j(t)??{},u=x.get(t)??null,d=u===null?void 0:c[u],m=u!==null&&_(d);return{actionsState:r,editorRegion:l,editorState:m?"editing":"empty",entries:Object.keys(c).map((h)=>({key:h,region:re(`entry:${h}`),selected:h===u})),entryName:e.echo??(m?u:""),layout:"map",newName:I.get(t)??"",newState:A.has(t)?"open":"closed",title:i,...a}}function ce(e){let o=e.formHost;if(!o)return;let{contribution:s,opts:t}=e,i=s.key,r=s.settings.entry?.ui,l=()=>w(e),a=(N)=>{if(N.parentNode!==o)o.replaceChildren(N)};if((s.settings.layout??"form")!=="map"){let N=`/${i}`;a(Fl(`section:${i}`,s.entrySchema,j(i)??{},{context:ie(i,t,null),errors:J.get(N)??{},onChange:(y)=>{let f=j(i);if(!f)return;oe(f,y),l(),z(N,l)},rerender:l,...r!==void 0&&{ui:r}}));return}let c=j(i)??{},u=x.get(i)??null,d=u===null?void 0:c[u];if(u===null||!_(d)){o.replaceChildren();return}let m=d,h=`/${i}/${u}`;a(Fl(`section:${i}:${u}`,s.entrySchema,m,{context:ie(i,t,u),errors:J.get(h)??{},onChange:(N)=>{oe(m,N),l(),z(h,l)},rerender:l,...r!==void 0&&{ui:r}}))}function de(e){let o=e.actionsHost,{actions:s}=e.opts;if(!o)return;if(!s){o.replaceChildren();return}let t=e.contribution.key,i=(e.contribution.settings.layout??"form")==="map"?x.get(t)??null:null;s(o,{rerender:()=>w(e),sectionKey:t,selected:i})}function Pe(e){let o=(i)=>{e.echo=null,w(e),z(i,()=>w(e))},s=()=>{e.echo=null,w(e)},t=()=>e.contribution.key;return{cancelNew(){A.delete(t()),I.delete(t()),w(e)},cancelRename(i){le(e,i),s()},createNew(){let i=t(),r=U(I.get(i)??""),l=j(i);if(!r||!l||l[r])return;l[r]=Ce(e.contribution.settings.entry?.newEntry,r),x.set(i,r),A.delete(i),I.delete(i),o(`/${i}`)},editNew(i){I.set(t(),i),w(e)},openNew(){A.add(t()),w(e)},removeEntry(){let i=t(),r=x.get(i)??null,l=j(i);if(!r||!l?.[r])return;delete l[r],x.set(i,null),o(`/${i}`)},renameEntry(i){le(e,i);let r=t(),l=x.get(r)??null,a=j(r),c=U(i.trim());if(!l||!a||!c||c===l||a[c]){s();return}let u={};for(let[d,m]of Object.entries(a))u[d===l?c:d]=m,delete a[d];Object.assign(a,u),x.set(r,c),o(`/${r}`)},select(i){x.set(t(),i),e.echo=null,w(e)}}}function Bk(e,o,s={}){let t=se.get(e);if(t)t.contribution=o,t.opts=s;let i=t?.handle??null;if(!t||!i?.attached()){i?.dispose();let r={actionsHost:null,container:e,contribution:o,echo:null,formHost:null,handle:null,opts:s};se.set(e,r),i=ne(e,Pe(r),{actionsSlot:(l)=>{r.actionsHost=l,de(r)},formSlot:(l)=>{r.formHost=l,ce(r)}}),r.handle=i,t=r}i.update(Me(t)),de(t),ce(t)}var pe={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsPane",$description:'The Project Settings dialog\'s two columns: the grouped section list and the section body (§17.1). It draws no section: `panels/settings-pane.ts` keeps the registry, decides which section is current, and renders whichever one that is into the one empty `[part="section-host"]` island this document leaves for it (studio-ui-guidelines.md §9.4), because a section renderer may be a lit template or a mounted document and neither can share a container with this one. The list is three vertical `tablist`s, one per group (General, Integrations, Advanced), each named by its group heading: a tablist may own only tabs, so a heading between two runs of rows has to END one list rather than sit inside it. Each group is one tab stop and the arrow keys move within it. Under the groups, a Moved footnote names what left Project Settings for a workspace, each with a button that goes there.',tagName:"div",attributes:{part:"doc"},style:{$description:'No part below is named `body`, `field`, `label`, `error`, `text` or `actions`: this document is mounted inside a `jx-dialog`, the kit is light DOM, and the dialog draws its own `[part="body"]` around this one, so a rule keyed on that name here would also be a rule the dialog\'s own styles reach.',display:"flex",height:"min(68vh, 640px)",minHeight:"0",background:"var(--bg)",color:"var(--fg)",fontFamily:"var(--jx-font-sans)",textAlign:"initial",'& [part="nav"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-4)",width:"200px",minWidth:"200px",flexShrink:"0",padding:"var(--jx-space-2) var(--jx-space-3) var(--jx-space-2) 0",borderRight:"1px solid var(--border)",overflowY:"auto",fontSize:"13px"},'& [part="group"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-1)"},'& [part="group-title"]':{display:"flex",alignItems:"baseline",gap:"var(--jx-space-2)",margin:"0",padding:"0 var(--jx-space-3)",color:"var(--fg-dim)",fontSize:"var(--jx-text-sm)",fontWeight:"600",letterSpacing:"0.04em",textTransform:"uppercase"},'& [part="group-note"]':{$description:`The Advanced group's "For developers": a qualifier on the heading, not a second heading, so it reads at the heading's size without its weight.`,fontWeight:"400",letterSpacing:"0",textTransform:"none"},'& [part="group-note"]:empty':{display:"none"},'& [part="group-tabs"]':{$description:"The rule a vertical strip draws on its trailing edge is the column's own here: the nav draws one border for all three groups, so each strip drawing its own would stack three short rules beside it.",borderInlineEnd:"0"},'& [part="nav-item"]':{$description:"Full-bleed rows, which a tab is not by default: `jx-tab` centres its label and caps itself at 220px because a horizontal strip is a row of chips. In the nav column the row IS the target, so the label goes to the leading edge and the cap comes off.",maxWidth:"none",justifyContent:"flex-start",padding:"var(--jx-space-2) var(--jx-space-3)"},'& [part="moved"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-1)",marginTop:"auto",padding:"var(--jx-space-3)",borderTop:"1px solid var(--border)",color:"var(--fg-dim)",fontSize:"var(--jx-text-md)"},'& [part="moved-title"]':{margin:"0",fontWeight:"600",color:"var(--fg)"},'& [part="moved-row"]':{display:"flex",alignItems:"center",flexWrap:"wrap",gap:"var(--jx-space-1)"},'& [part="content"]':{flex:"1",minWidth:"0",overflowY:"auto",padding:"var(--jx-space-2) var(--jx-space-5)"},'& [part="group-intro"]':{margin:"0 0 var(--jx-space-3)",color:"var(--fg-dim)",fontSize:"13px"},'& [part="group-intro"]:empty':{display:"none"},'& [part="section-host"]':{display:"block",minWidth:"0"},'& [part="empty"]':{$description:"What the body says when the active section is registered by nobody: every section unregistering at once, which is a project closing while the dialog is open. A blank column beside a list reads as a broken dialog, so it says which it is.",display:"flex",alignItems:"center",justifyContent:"center",minHeight:"120px",margin:"0",color:"var(--fg-dim)",fontSize:"13px"},'& [part="failure"]':{$description:"A section whose renderer threw or rejected. It is said where the section would have been, in the reader's line of sight, because a section that silently draws nothing is indistinguishable from one with nothing to say.",margin:"0",padding:"var(--jx-space-3)",border:"1px solid var(--danger)",borderRadius:"var(--radius)",color:"var(--fg)",fontSize:"13px"}},children:[{tagName:"div",attributes:{part:"nav",role:"none"},children:[{$prototype:"Array",items:{$ref:"#/state/groups"},key:{$ref:"$map/item/id"},map:{tagName:"div",attributes:{part:"group",role:"none","data-group":"${$map.item.id}"},children:[{tagName:"h3",attributes:{part:"group-title",id:"${$map.item.titleId}"},children:[{tagName:"span",textContent:"${$map.item.label}"},{tagName:"span",attributes:{part:"group-note"},textContent:"${$map.item.note}"}]},{tagName:"jx-tabs",attributes:{part:"group-tabs",selected:"${state.active}",orientation:"vertical"},$props:{label:{$ref:"$map/item/tabsLabel"}},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/selectSection"},value:[{$ref:"event#/detail"}]}]},children:[{$prototype:"Array",items:{$ref:"$map/item/sections"},key:{$ref:"$map/item/key"},map:{tagName:"jx-tab",attributes:{part:"nav-item",id:"${$map.item.tabId}","data-section":"${$map.item.key}",value:"${$map.item.key}",label:"${$map.item.label}",panel:"settings-pane-panel"}}}]}]}},{tagName:"div",attributes:{part:"moved",role:"group","aria-labelledby":"settings-pane-moved"},children:[{tagName:"p",attributes:{part:"moved-title",id:"settings-pane-moved"},textContent:"Moved"},{$prototype:"Array",items:{$ref:"#/state/moved"},key:{$ref:"$map/item/workspace"},map:{tagName:"div",attributes:{part:"moved-row","data-moved":"${$map.item.workspace}"},children:[{tagName:"span",textContent:"${$map.item.what} →"},{tagName:"jx-button",attributes:{part:"moved-link"},$props:{size:"sm",quiet:!0,label:{$ref:"$map/item/linkLabel"}},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openMoved"},value:[{$ref:"$map/item/workspace"}]}]},children:[{tagName:"span",textContent:"${$map.item.place}"}]}]}}]}]},{tagName:"jx-tab-panel",attributes:{part:"content",id:"settings-pane-panel"},$props:{active:!0,labelledby:{$ref:"#/state/activeTabId"}},children:[{$description:`The current group's intro ("Changes here affect every page. Most sites never need them."), above whichever of its sections is showing. General has none, and an empty sentence draws nothing.`,tagName:"p",attributes:{part:"group-intro"},textContent:"${state.intro}"},{$description:"The island, and it stays empty: a settings section renders itself, into a host this document never writes into and never reads back (studio-ui-guidelines.md §9.4).",tagName:"div",attributes:{part:"section-host"}},{tagName:"div",attributes:{part:"empty-slot",role:"none"},$switch:{$ref:"#/state/hasSection"},cases:{false:{tagName:"p",attributes:{part:"empty"},textContent:"${state.empty}"}}},{tagName:"div",attributes:{part:"failure-slot",role:"none"},$switch:{$ref:"#/state/failureState"},cases:{failed:{tagName:"p",attributes:{part:"failure",role:"alert"},textContent:"${state.failure}"}}}]}]};T("settings-pane",pe);function He(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function ue(e){return e===""?"ok":"failed"}function me(e,o,s){let t=g({...o,...s,failureState:ue(o.failure)});e.textContent="",delete e._$litPart$;let i=null,r=!1,l=null,a=R("settings-pane",t,e,{onNodeCreated:(c,u,d)=>{if(!r&&c instanceof HTMLElement&&He(d)==="section-host")l=c}}).then((c)=>{if(r){c.dispose();return}i=c});return{body:()=>l,dispose(){r=!0,i?.dispose(),i=null,l=null},focusActive(){let c=i?.root;if(c instanceof HTMLElement)c.querySelector('[part="nav-item"][aria-selected="true"]')?.focus()},ready:a,update(c){t.groups=c.groups,t.moved=c.moved,t.activeTabId=c.activeTabId,t.empty=c.empty,t.intro=c.intro,t.hasSection=c.hasSection,t.failure=c.failure,t.failureState=ue(c.failure),t.active=c.active}}}var Ie="No settings sections.",fe=[{place:"Styles › Variables",view:"variables",what:"Colors and fonts",workspace:"styles"},{place:"Publish › Hosting",publishTab:"hosting",what:"Hosting and domain",workspace:"publish"},{inspector:"page",place:"Page tab",what:"Head and SEO defaults",workspace:"design"}];function ge(e){return`settings-nav-${e}`}function Oe(e){return fe.find((o)=>o.workspace===e)??null}function F(e){let o=V(),s=Py();return{active:o,activeTabId:ge(o),empty:Ie,failure:e,groups:s.map((t)=>({id:t.id,label:t.label,note:t.note,sections:t.sections.map((i)=>({key:i.key,label:i.label,tabId:ge(i.key)})),tabsLabel:t.note===""?t.label:`${t.label}, ${t.note.toLowerCase()}`,titleId:`settings-group-${t.id}`})),hasSection:H(o)!==void 0,intro:H(o)?.intro||(s.find((t)=>t.sections.some((i)=>i.key===o))?.intro??""),moved:fe.map((t)=>{let{title:i}=Qb(t.workspace),r=t.place??i;return{linkLabel:`${t.what}: ${r}. Go to ${i}`,place:r,what:t.what,workspace:t.workspace}})}}function he(e,o){let s=!1,t=null,i=null,r=null,l="",a=0,c=me(e,F(l),{openMoved:(y)=>{let f=Oe(y);if(f!==null)o.openMoved(f.workspace,f.inspector,f.view,f.publishTab)},selectSection:(y)=>{C_(y)}});function u(y,f,k){if(s||k!==a)return;l=`Could not show ${H(y)?.label??y}: ${f}`,c.update(F(l))}function d(y){if(s)return;let f=V(),k=c.body();if(k!==t)t=k,r=null;if(!k||!y&&r===f){c.update(F(l));return}let q=r!==f;r=f,l="",c.update(F(l));let K=H(f);if(!K){i=null,k.replaceChildren();return}if(q||!i||i.parentElement!==k)i=document.createElement("div"),k.replaceChildren(i);a+=1;let Y=a;try{let O=K.render(i);if(O instanceof Promise)O.catch((ye)=>{u(f,Q(ye),Y)})}catch(O){u(f,Q(O),Y)}}let m=()=>S_(()=>{d(!0)}),h=m(),N=c.ready.then(()=>{d(!0)});return{dispose(){if(s)return;s=!0,h?.(),h=null,c.dispose()},focusActive:()=>{c.focusActive()},ready:N,resume(){if(s||h!==null)return;h=m(),i=null,d(!0)},suspend(){h?.(),h=null}}}var b=null,M=!1;function be(){return M}function De(){let e={dialog:Z({body:(o)=>{e.pane=he(o,{openMoved:(s,t,i,r)=>{Ae(s,t,i,r)}})},closed:()=>{if(b===e)Ru()},layer:tt("dialog")}),pane:null};return e}async function Ae(e,o,s,t){if(Ru(),s!==void 0){await rt("styles.open",{view:s},"Settings");return}if(t!==void 0){await rt("publish.open",{tab:t},"Settings");return}if(await rt("view.setWorkspace",{workspace:e},"Settings"),o===void 0)return;if(await rt("view.setRightPanel",{open:!0},"Settings"),ae()?.isEnabled("view.setRightTab")===!0)await rt("view.setRightTab",{tab:o},"Settings")}async function PR(){if(M&&b){await b.dialog.ready;return}if(M=!0,b&&!b.dialog.host.isConnected)Re(),M=!0;let e=b;if(e)e.pane?.resume(),await e.dialog.show();else e=De(),b=e,await e.dialog.ready;let o=e.pane;if(o===null||b!==e||!be())return;if(await o.ready,b===e&&be())o.focusActive()}function Ru(){if(!M)return;M=!1,b?.pane?.suspend(),b?.dialog.close()}function Re(){M=!1;let e=b;b=null,e?.pane?.dispose(),e?.dialog.dispose()}
|
|
2
|
-
export{
|
|
1
|
+
import{te}from"./studio-psh8mwnw.js";import{p}from"./studio-9ndgd55w.js";import{g,C}from"./studio-tfmhnwyr.js";import{iv}from"./studio-ztppbam0.js";import{Ot,Nt,ae}from"./studio-qs5fmhtj.js";import{Fl,mp}from"./studio-nfmpmkqb.js";import{Ue,ft,T,R,Jt,rt,tt}from"./studio-myb4mf0h.js";import{Bu}from"./studio-jr30g4ae.js";import{BD}from"./studio-1cfyd1ys.js";import{Gl}from"./studio-nqexty8x.js";import{S}from"./studio-9ra9e7m4.js";import{n,Q,_,v}from"./studio-ywf9y1e2.js";var B=[{id:"general",intro:"",label:"General",note:""},{id:"integrations",intro:"Turn on what your site needs. Each one adds its own options where you use it.",label:"Integrations",note:""},{id:"advanced",intro:"Changes here affect every page. Most sites never need them.",label:"Advanced",note:"For developers"}],MR="integrations";function PR(e){return B.some((o)=>o.id===e)}var ve="overview",E=new Map,G=new Set;function D(){for(let e of G)e()}function xd(){D()}function E_(e){return G.add(e),()=>{G.delete(e)}}function Ol(e){E.set(e.key,e),D()}function FR(e){if(E.delete(e))D()}function we(){return[...E.values()].toSorted((e,o)=>e.order-o.order)}function By(){let e=we();return B.flatMap((o)=>{let s=e.filter((t)=>(t.group??"integrations")===o.id);return s.length===0?[]:[{id:o.id,intro:o.intro,label:o.label,note:o.note,sections:s}]})}function zk(){return By().flatMap((e)=>e.sections.map((o)=>o.key))}function H(e){return E.get(e)}var L=null,P=ve;function V(){if(L!==null&&E.has(L))return P=L,L=null,P;if(E.has(P))return P;return zk()[0]??P}function T_(e){if(E.has(e))P=e,L=null;else L=e;D()}var X={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsDialog",$description:"Project Settings (§17.1): a `jx-dialog` whose body is the settings editor's two columns, the grouped section list and the section body. The dialog owns modality, Escape and focus restoration, and its one footer answer is Close: every section writes as it is edited, so there is nothing to confirm or cancel. The body is an ISLAND: this document draws the slot and nothing in it, and `settings/settings-dialog.ts` mounts `settings-pane.json` there through `onNodeCreated` (studio-ui-guidelines.md §9.4).",tagName:"jx-dialog",$props:{headline:"Project settings",confirmLabel:"",cancelLabel:"Close",size:"xl"},attributes:{part:"settings"},oncancel:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},onclose:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/closed"},value:[]}]},children:[{tagName:"div",attributes:{part:"pane-slot"},style:{$description:"The editor's box is its own (`settings-pane.json`); the slot only gives it the dialog body's width.",minWidth:"0"}}]};T("settings-dialog",X);var W=ft("dialog","settings");function xe(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function Z(e){let o=document.createElement("div");o.style.pointerEvents="auto",e.layer.append(o);let s=!0,t=!1,i=()=>{if(!s)return;s=!1,e.closed()},r=g({closed:i}),l=null,a=(d)=>{if(!t&&s)Ot(d);return d},c=R("settings-dialog",r,o,{onNodeCreated:(d,m,h)=>{if(!t&&d instanceof HTMLElement&&xe(h)==="pane-slot")e.body(d)}}).then(async(d)=>{let m=d.root;if(t)return d.dispose(),m;return l=d,await Jt(m),(m.querySelector('dialog[part="dialog"]')??m).setAttribute(Ue,W),a(m)}),u=()=>{let d=l?.root;if(d instanceof HTMLElement)Nt(d);i()};return{close:u,dispose(){if(t)return;u(),t=!0,l?.dispose(),l=null,o.remove()},host:o,ready:c,show(){if(!t)s=!0;return c.then(a)}}}var ee={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsContributed",$description:'The generic settings section behind `$studio.settings` (specs/extensions.md §9.1), as a Jx document over the kit. One document serves both layouts an extension may declare: "form" is a single schema form over the whole section value, "map" is master-detail — the entry keys on the left, the selected entry\'s form on the right. The adapter (`surfaces/settings-contributed.ts`) hands in the title, the layout, the entry rows already marked as selected, and whatever the reader is part-way through typing; `settings/contributed-section.ts` decides what an entry may be named, what reaches `project.json`, and what the validator said about it. The schema form itself is an ISLAND: this document renders `form-host` and nothing inside it, because a form built from a JSON Schema is `ui/schema-form.ts`\'s surface rather than this one\'s — the section places the element that surface hands back. The actions row is the second island: `panels/data-grid.ts` contributes it, and that one is still lit over Spectrum.',tagName:"section",attributes:{part:"contributed"},style:{$description:"What `.settings-section-title`, `.settings-two-col`, `.settings-list-panel`, `.settings-editor-panel`, `.settings-editor-header`, `.settings-empty-state` and `.settings-inline-form` said in `styles/overlays.css`, keyed on `part` and re-pointed at the studio token layer. This section was the LAST emitter of every one of them except `.settings-empty-state`, which `panels/settings-pane.ts` still writes when a project closes with the editor open — so those rules are dead in the stylesheet from here, and a central sweep removes them rather than this change, which owns no stylesheet. Two values could not come across. `.settings-editor-header h3` read `var(--spectrum-font-size-100, 14px)`, and a document is mounted in the pane rather than inside `<sp-theme>`, so it would have taken its hard-coded fallback every time; the entry name is a kit textfield now and carries the kit's own type ramp. And `.entry-name-input`, `.settings-form-panel`, `.settings-section` and `.contributed-section` had no rule anywhere at all — they were four entries on `check-styles.ts`'s orphan ledger, which is the ledger's point.",display:"block",'& [part="title"]':{margin:"0 0 16px",fontSize:"16px",fontWeight:"600",color:"var(--fg)"},'& [part="actions"]':{$description:"The host-contributed actions row — Test Connection, Push Schema, Open Data Grid on the data sections. `.data-section-actions` never had a rule anywhere, so the row was whatever the buttons stacked up to; it is a row with a gap under it now.",display:"flex",alignItems:"center",flexWrap:"wrap",gap:"8px",marginBottom:"12px"},'& [part="columns"]':{$description:"The 1px gap over the border colour is the divider between the two columns: two panels on `--bg-panel` with `--border` showing through the gap, so nothing draws a rule of its own.",display:"flex",height:"100%",gap:"1px",background:"var(--border)"},'& [part="list"]':{display:"flex",flexDirection:"column",gap:"4px",padding:"12px",width:"200px",minWidth:"200px",background:"var(--bg-panel)",overflowY:"auto"},'& [part="entry"], & [part="new-open"]':{width:"100%"},'& [part="entry"] > [part="control"], & [part="new-open"] > [part="control"]':{$description:"`.settings-list-panel sp-action-button` said `width: 100%; justify-content: flex-start`, and both halves belong to the button the row is made of rather than to the row: a kit action button centres its glyph and its label, which reads as a list of centred names.",width:"100%",justifyContent:"flex-start"},'& [part="new-form"]':{display:"flex",alignItems:"center",gap:"6px"},'& [part="new-field"]':{flex:"1",minWidth:"0"},'& [part="empty"]':{flex:"1",display:"flex",alignItems:"center",justifyContent:"center",background:"var(--bg-panel)",color:"var(--fg-dim)",fontSize:"13px"},'& [part="editor"]':{$description:"`min-width: 0` is the one line `.settings-editor-panel` did not have and needed: a flex child's floor is its content, and the schema form inside this one is a whole form rather than the short cards Data Shapes puts here — so a long pointer or a wide row pushed the column past the right edge of the pane instead of scrolling inside it.",flex:"1",padding:"16px",background:"var(--bg-panel)",overflowY:"auto",minWidth:"0"},'& [part="editor-header"]':{display:"flex",alignItems:"center",gap:"12px",marginBottom:"16px"},'& [part="entry-name"]':{flex:"1",minWidth:"0",maxWidth:"220px"}},children:[{tagName:"h3",attributes:{part:"title"},textContent:"${state.title}"},{tagName:"div",attributes:{part:"actions-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/actionsState"},cases:{slot:{$description:"An island: the host renders its own actions into this node and the document renders nothing inside it.",tagName:"div",attributes:{part:"actions"}}}},{tagName:"div",attributes:{part:"body-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/layout"},cases:{form:{$description:"An island: `ui/schema-form.ts` draws the whole section value into this node.",tagName:"div",attributes:{part:"form-host"}},map:{tagName:"div",attributes:{part:"columns"},children:[{tagName:"div",attributes:{part:"list"},children:[{$prototype:"Array",items:{$ref:"#/state/entries"},key:{$ref:"$map/item/key"},map:{tagName:"jx-action-button",attributes:{part:"entry","data-entry":"${$map.item.key}","data-jx-region":"${$map.item.region}"},$props:{label:"${$map.item.key}",selected:{$ref:"$map/item/selected"},quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/select"},value:[{$ref:"$map/item/key"}]}]},children:[{tagName:"span",textContent:"${$map.item.key}"}]}},{tagName:"div",attributes:{part:"new-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/newState"},cases:{closed:{tagName:"jx-action-button",attributes:{part:"new-open"},$props:{label:"${state.newLabel}",icon:"plus",quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openNew"},value:[]}]},children:[{tagName:"span",textContent:"${state.newLabel}"}]},open:{tagName:"div",attributes:{part:"new-form"},children:[{tagName:"jx-textfield",attributes:{part:"new-field"},$props:{label:"${state.newFieldLabel}",placeholder:"${state.newPlaceholder}",size:"sm",value:{$ref:"#/state/newName"}},oninput:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/editNew"},value:[{$ref:"event#/target/value"}]}]},onkeydown:{$prototype:"Function",body:[{$switch:{$ref:"event#/key"},cases:{Enter:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/createNew"},value:[]}],Escape:[{preventDefault:!0},{operator:"call",target:{$ref:"#/state/cancelNew"},value:[]}]}}]}},{tagName:"jx-button",attributes:{part:"new-create"},$props:{size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/createNew"},value:[]}]},children:[{tagName:"span",textContent:"Create"}]}]}}}]},{tagName:"div",attributes:{part:"editor-slot",role:"none"},style:{display:"contents"},$switch:{$ref:"#/state/editorState"},cases:{empty:{tagName:"div",attributes:{part:"empty"},textContent:"${state.emptyText}"},editing:{tagName:"div",attributes:{part:"editor","data-jx-region":"${state.editorRegion}"},children:[{tagName:"div",attributes:{part:"editor-header"},children:[{tagName:"jx-textfield",attributes:{part:"entry-name"},$props:{label:"Entry name",size:"sm",value:{$ref:"#/state/entryName"}},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/renameEntry"},value:[{$ref:"event#/target/value"}]}]},onkeydown:{$prototype:"Function",body:[{$switch:{$ref:"event#/key"},cases:{Enter:[{operator:"call",target:{$ref:"#/state/renameEntry"},value:[{$ref:"event#/target/value"}]}],Escape:[{operator:"call",target:{$ref:"#/state/cancelRename"},value:[{$ref:"event#/target/value"}]}]}}]}},{tagName:"jx-action-button",attributes:{part:"delete-entry"},$props:{label:"Delete entry",hint:"Delete entry",icon:"trash",quiet:!0,size:"sm"},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/removeEntry"},value:[]}]}}]},{$description:"An island: `ui/schema-form.ts` draws the selected entry into this node.",tagName:"div",attributes:{part:"form-host"}}]}}}]}}}]};T("settings-contributed",ee);function Te(){return{actionsState:"none",editorRegion:"",editorState:"empty",entries:[],entryName:"",layout:"form",newName:"",newState:"closed",title:"",emptyText:"",newFieldLabel:"",newLabel:"",newPlaceholder:""}}function Ne(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function ne(e,o,s){e.textContent="";let t=g({...Te(),...o}),i=null,r=!1,l=R("settings-contributed",t,e,{onNodeCreated:(a,c,u)=>{if(!(a instanceof HTMLElement))return;let d=Ne(u);if(d==="form-host")s.formSlot(a);else if(d==="actions")s.actionsSlot(a)}}).then((a)=>{let c=a.root;if(r)return a.dispose(),c;return i=a,c});return{attached:()=>{if(r)return!1;let a=i?.root;return a===void 0?!0:a instanceof HTMLElement&&e.contains(a)},dispose(){r=!0,i?.dispose(),i=null},host:e,ready:l,update(a){t.actionsState=a.actionsState,t.editorRegion=a.editorRegion,t.editorState=a.editorState,t.entries=a.entries,t.entryName=a.entryName,t.layout=a.layout,t.newName=a.newName,t.newState=a.newState,t.title=a.title,t.emptyText=a.emptyText,t.newFieldLabel=a.newFieldLabel,t.newLabel=a.newLabel,t.newPlaceholder=a.newPlaceholder}}}var x=new Map,A=new Set,I=new Map;function jR(e,o){let s=S?.projectConfig?.[e],t=v(s)?s:{};if(!Object.hasOwn(t,o))return Object.keys(t);return x.set(e,o),null}var J=new Map;function ke(e,o){let s={},t=[];for(let i of o){let r=i.indexOf(": "),l=r===-1?"":i.slice(0,r),a=r===-1?i:i.slice(r+2);if(l===e){t.push(a);continue}if(!l.startsWith(`${e}/`))continue;let[c]=l.slice(e.length+1).split("/");if(c&&s[c]===void 0)s[c]=a}return{fields:s,section:t}}async function z(e,o){let s=S?.projectConfig;if(!s)return;if(!(await Gl()).ok)return;let i=[];try{i=await Bu(s)}catch(r){C.warn(`Could not validate project.json — ${te(r)}`,{key:"settings:validator",path:"project.json",source:"Settings",tier:"problem"});return}J.set(e,ke(e,i).fields),o()}function oe(e,o){for(let[s,t]of Object.entries(o))if(t===void 0)delete e[s];else e[s]=t}function U(e){return e.toLowerCase().replaceAll(/\s+/g,"-").replaceAll(/[^a-z0-9-]/g,"")}function Ce(e,o){if(!e)return{};let s=(i)=>{let r={};for(let[l,a]of Object.entries(i))r[l]=t(a);return r},t=(i)=>{if(n(i))return i.replaceAll("${key}",o);if(Array.isArray(i))return i.map((r)=>t(r));if(v(i))return s(i);return i};return s(e)}function ie(e,o,s=null){let t=p(),i={fieldKeyPrefix:`$settings.${e}`,resolvePointer:(r,l)=>{let a={projectConfig:S?.projectConfig??{}};if(v(l))a.scope=l;if(o.formats!==void 0)a.formats=o.formats;return mp(r,a)}};if(Q(t.setSecrets))i.commitSecret=async(r,l)=>{let a=BD(e,s,r);return await t.setSecrets({set:{[a]:l}}),a};return i}function j(e){let o=S?.projectConfig;if(!o)return null;let s=o[e];if(v(s))return s;let t={};return o[e]=t,t}function re(e){return`${W}/${e}`}var se=new WeakMap;function w(e){Wk(e.container,e.contribution,e.opts)}function le(e,o){e.echo=o,w(e)}var Ee="entry";function je(e){let o=e?.trim().toLowerCase()||Ee,s=`${o.charAt(0).toUpperCase()}${o.slice(1)}`;return{emptyText:`Select ${/^[aeiou]/u.test(o)?"an":"a"} ${o} or create one`,newFieldLabel:`${s} name`,newLabel:`New ${o}`,newPlaceholder:`${U(o)}-name`}}function Me(e){let{contribution:o,opts:s}=e,t=o.key,i=o.title??t,r=s.actions?"slot":"none",l=re("editor"),a=je(o.settings.entry?.noun);if((o.settings.layout??"form")!=="map")return{actionsState:r,editorRegion:l,editorState:"empty",entries:[],entryName:"",layout:"form",newName:"",newState:"closed",title:i,...a};let c=j(t)??{},u=x.get(t)??null,d=u===null?void 0:c[u],m=u!==null&&_(d);return{actionsState:r,editorRegion:l,editorState:m?"editing":"empty",entries:Object.keys(c).map((h)=>({key:h,region:re(`entry:${h}`),selected:h===u})),entryName:e.echo??(m?u:""),layout:"map",newName:I.get(t)??"",newState:A.has(t)?"open":"closed",title:i,...a}}function ce(e){let o=e.formHost;if(!o)return;let{contribution:s,opts:t}=e,i=s.key,r=s.settings.entry?.ui,l=()=>w(e),a=(N)=>{if(N.parentNode!==o)o.replaceChildren(N)};if((s.settings.layout??"form")!=="map"){let N=`/${i}`;a(Fl(`section:${i}`,s.entrySchema,j(i)??{},{context:ie(i,t,null),errors:J.get(N)??{},onChange:(y)=>{let f=j(i);if(!f)return;oe(f,y),l(),z(N,l)},rerender:l,...r!==void 0&&{ui:r}}));return}let c=j(i)??{},u=x.get(i)??null,d=u===null?void 0:c[u];if(u===null||!_(d)){o.replaceChildren();return}let m=d,h=`/${i}/${u}`;a(Fl(`section:${i}:${u}`,s.entrySchema,m,{context:ie(i,t,u),errors:J.get(h)??{},onChange:(N)=>{oe(m,N),l(),z(h,l)},rerender:l,...r!==void 0&&{ui:r}}))}function de(e){let o=e.actionsHost,{actions:s}=e.opts;if(!o)return;if(!s){o.replaceChildren();return}let t=e.contribution.key,i=(e.contribution.settings.layout??"form")==="map"?x.get(t)??null:null;s(o,{rerender:()=>w(e),sectionKey:t,selected:i})}function Pe(e){let o=(i)=>{e.echo=null,w(e),z(i,()=>w(e))},s=()=>{e.echo=null,w(e)},t=()=>e.contribution.key;return{cancelNew(){A.delete(t()),I.delete(t()),w(e)},cancelRename(i){le(e,i),s()},createNew(){let i=t(),r=U(I.get(i)??""),l=j(i);if(!r||!l||l[r])return;l[r]=Ce(e.contribution.settings.entry?.newEntry,r),x.set(i,r),A.delete(i),I.delete(i),o(`/${i}`)},editNew(i){I.set(t(),i),w(e)},openNew(){A.add(t()),w(e)},removeEntry(){let i=t(),r=x.get(i)??null,l=j(i);if(!r||!l?.[r])return;delete l[r],x.set(i,null),o(`/${i}`)},renameEntry(i){le(e,i);let r=t(),l=x.get(r)??null,a=j(r),c=U(i.trim());if(!l||!a||!c||c===l||a[c]){s();return}let u={};for(let[d,m]of Object.entries(a))u[d===l?c:d]=m,delete a[d];Object.assign(a,u),x.set(r,c),o(`/${r}`)},select(i){x.set(t(),i),e.echo=null,w(e)}}}function Wk(e,o,s={}){let t=se.get(e);if(t)t.contribution=o,t.opts=s;let i=t?.handle??null;if(!t||!i?.attached()){i?.dispose();let r={actionsHost:null,container:e,contribution:o,echo:null,formHost:null,handle:null,opts:s};se.set(e,r),i=ne(e,Pe(r),{actionsSlot:(l)=>{r.actionsHost=l,de(r)},formSlot:(l)=>{r.formHost=l,ce(r)}}),r.handle=i,t=r}i.update(Me(t)),de(t),ce(t)}var pe={$schema:"https://jxsuite.com/schema/v1",$id:"StudioSettingsPane",$description:'The Project Settings dialog\'s two columns: the grouped section list and the section body (§17.1). It draws no section: `panels/settings-pane.ts` keeps the registry, decides which section is current, and renders whichever one that is into the one empty `[part="section-host"]` island this document leaves for it (studio-ui-guidelines.md §9.4), because a section renderer may be a lit template or a mounted document and neither can share a container with this one. The list is three vertical `tablist`s, one per group (General, Integrations, Advanced), each named by its group heading: a tablist may own only tabs, so a heading between two runs of rows has to END one list rather than sit inside it. Each group is one tab stop and the arrow keys move within it. Under the groups, a Moved footnote names what left Project Settings for a workspace, each with a button that goes there.',tagName:"div",attributes:{part:"doc"},style:{$description:'No part below is named `body`, `field`, `label`, `error`, `text` or `actions`: this document is mounted inside a `jx-dialog`, the kit is light DOM, and the dialog draws its own `[part="body"]` around this one, so a rule keyed on that name here would also be a rule the dialog\'s own styles reach.',display:"flex",height:"min(68vh, 640px)",minHeight:"0",background:"var(--bg)",color:"var(--fg)",fontFamily:"var(--jx-font-sans)",textAlign:"initial",'& [part="nav"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-4)",width:"200px",minWidth:"200px",flexShrink:"0",padding:"var(--jx-space-2) var(--jx-space-3) var(--jx-space-2) 0",borderRight:"1px solid var(--border)",overflowY:"auto",fontSize:"13px"},'& [part="group"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-1)"},'& [part="group-title"]':{display:"flex",alignItems:"baseline",gap:"var(--jx-space-2)",margin:"0",padding:"0 var(--jx-space-3)",color:"var(--fg-dim)",fontSize:"var(--jx-text-sm)",fontWeight:"600",letterSpacing:"0.04em",textTransform:"uppercase"},'& [part="group-note"]':{$description:`The Advanced group's "For developers": a qualifier on the heading, not a second heading, so it reads at the heading's size without its weight.`,fontWeight:"400",letterSpacing:"0",textTransform:"none"},'& [part="group-note"]:empty':{display:"none"},'& [part="group-tabs"]':{$description:"The rule a vertical strip draws on its trailing edge is the column's own here: the nav draws one border for all three groups, so each strip drawing its own would stack three short rules beside it.",borderInlineEnd:"0"},'& [part="nav-item"]':{$description:"Full-bleed rows, which a tab is not by default: `jx-tab` centres its label and caps itself at 220px because a horizontal strip is a row of chips. In the nav column the row IS the target, so the label goes to the leading edge and the cap comes off.",maxWidth:"none",justifyContent:"flex-start",padding:"var(--jx-space-2) var(--jx-space-3)"},'& [part="moved"]':{display:"flex",flexDirection:"column",gap:"var(--jx-space-1)",marginTop:"auto",padding:"var(--jx-space-3)",borderTop:"1px solid var(--border)",color:"var(--fg-dim)",fontSize:"var(--jx-text-md)"},'& [part="moved-title"]':{margin:"0",fontWeight:"600",color:"var(--fg)"},'& [part="moved-row"]':{display:"flex",alignItems:"center",flexWrap:"wrap",gap:"var(--jx-space-1)"},'& [part="content"]':{flex:"1",minWidth:"0",overflowY:"auto",padding:"var(--jx-space-2) var(--jx-space-5)"},'& [part="group-intro"]':{margin:"0 0 var(--jx-space-3)",color:"var(--fg-dim)",fontSize:"13px"},'& [part="group-intro"]:empty':{display:"none"},'& [part="section-host"]':{display:"block",minWidth:"0"},'& [part="empty"]':{$description:"What the body says when the active section is registered by nobody: every section unregistering at once, which is a project closing while the dialog is open. A blank column beside a list reads as a broken dialog, so it says which it is.",display:"flex",alignItems:"center",justifyContent:"center",minHeight:"120px",margin:"0",color:"var(--fg-dim)",fontSize:"13px"},'& [part="failure"]':{$description:"A section whose renderer threw or rejected. It is said where the section would have been, in the reader's line of sight, because a section that silently draws nothing is indistinguishable from one with nothing to say.",margin:"0",padding:"var(--jx-space-3)",border:"1px solid var(--danger)",borderRadius:"var(--radius)",color:"var(--fg)",fontSize:"13px"}},children:[{tagName:"div",attributes:{part:"nav",role:"none"},children:[{$prototype:"Array",items:{$ref:"#/state/groups"},key:{$ref:"$map/item/id"},map:{tagName:"div",attributes:{part:"group",role:"none","data-group":"${$map.item.id}"},children:[{tagName:"h3",attributes:{part:"group-title",id:"${$map.item.titleId}"},children:[{tagName:"span",textContent:"${$map.item.label}"},{tagName:"span",attributes:{part:"group-note"},textContent:"${$map.item.note}"}]},{tagName:"jx-tabs",attributes:{part:"group-tabs",selected:"${state.active}",orientation:"vertical"},$props:{label:{$ref:"$map/item/tabsLabel"}},onchange:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/selectSection"},value:[{$ref:"event#/detail"}]}]},children:[{$prototype:"Array",items:{$ref:"$map/item/sections"},key:{$ref:"$map/item/key"},map:{tagName:"jx-tab",attributes:{part:"nav-item",id:"${$map.item.tabId}","data-section":"${$map.item.key}",value:"${$map.item.key}",label:"${$map.item.label}",panel:"settings-pane-panel"}}}]}]}},{tagName:"div",attributes:{part:"moved",role:"group","aria-labelledby":"settings-pane-moved"},children:[{tagName:"p",attributes:{part:"moved-title",id:"settings-pane-moved"},textContent:"Moved"},{$prototype:"Array",items:{$ref:"#/state/moved"},key:{$ref:"$map/item/workspace"},map:{tagName:"div",attributes:{part:"moved-row","data-moved":"${$map.item.workspace}"},children:[{tagName:"span",textContent:"${$map.item.what} →"},{tagName:"jx-button",attributes:{part:"moved-link"},$props:{size:"sm",quiet:!0,label:{$ref:"$map/item/linkLabel"}},onclick:{$prototype:"Function",body:[{operator:"call",target:{$ref:"#/state/openMoved"},value:[{$ref:"$map/item/workspace"}]}]},children:[{tagName:"span",textContent:"${$map.item.place}"}]}]}}]}]},{tagName:"jx-tab-panel",attributes:{part:"content",id:"settings-pane-panel"},$props:{active:!0,labelledby:{$ref:"#/state/activeTabId"}},children:[{$description:`The current group's intro ("Changes here affect every page. Most sites never need them."), above whichever of its sections is showing. General has none, and an empty sentence draws nothing.`,tagName:"p",attributes:{part:"group-intro"},textContent:"${state.intro}"},{$description:"The island, and it stays empty: a settings section renders itself, into a host this document never writes into and never reads back (studio-ui-guidelines.md §9.4).",tagName:"div",attributes:{part:"section-host"}},{tagName:"div",attributes:{part:"empty-slot",role:"none"},$switch:{$ref:"#/state/hasSection"},cases:{false:{tagName:"p",attributes:{part:"empty"},textContent:"${state.empty}"}}},{tagName:"div",attributes:{part:"failure-slot",role:"none"},$switch:{$ref:"#/state/failureState"},cases:{failed:{tagName:"p",attributes:{part:"failure",role:"alert"},textContent:"${state.failure}"}}}]}]};T("settings-pane",pe);function He(e){let o=n(e)?void 0:e.attributes?.part;return n(o)?o:""}function ue(e){return e===""?"ok":"failed"}function me(e,o,s){let t=g({...o,...s,failureState:ue(o.failure)});e.textContent="",delete e._$litPart$;let i=null,r=!1,l=null,a=R("settings-pane",t,e,{onNodeCreated:(c,u,d)=>{if(!r&&c instanceof HTMLElement&&He(d)==="section-host")l=c}}).then((c)=>{if(r){c.dispose();return}i=c});return{body:()=>l,dispose(){r=!0,i?.dispose(),i=null,l=null},focusActive(){let c=i?.root;if(c instanceof HTMLElement)c.querySelector('[part="nav-item"][aria-selected="true"]')?.focus()},ready:a,update(c){t.groups=c.groups,t.moved=c.moved,t.activeTabId=c.activeTabId,t.empty=c.empty,t.intro=c.intro,t.hasSection=c.hasSection,t.failure=c.failure,t.failureState=ue(c.failure),t.active=c.active}}}var Ie="No settings sections.",fe=[{place:"Styles › Variables",view:"variables",what:"Colors and fonts",workspace:"styles"},{place:"Publish › Hosting",publishTab:"hosting",what:"Hosting and domain",workspace:"publish"},{inspector:"page",place:"Page tab",what:"Head and SEO defaults",workspace:"design"}];function ge(e){return`settings-nav-${e}`}function Oe(e){return fe.find((o)=>o.workspace===e)??null}function F(e){let o=V(),s=By();return{active:o,activeTabId:ge(o),empty:Ie,failure:e,groups:s.map((t)=>({id:t.id,label:t.label,note:t.note,sections:t.sections.map((i)=>({key:i.key,label:i.label,tabId:ge(i.key)})),tabsLabel:t.note===""?t.label:`${t.label}, ${t.note.toLowerCase()}`,titleId:`settings-group-${t.id}`})),hasSection:H(o)!==void 0,intro:H(o)?.intro||(s.find((t)=>t.sections.some((i)=>i.key===o))?.intro??""),moved:fe.map((t)=>{let{title:i}=iv(t.workspace),r=t.place??i;return{linkLabel:`${t.what}: ${r}. Go to ${i}`,place:r,what:t.what,workspace:t.workspace}})}}function he(e,o){let s=!1,t=null,i=null,r=null,l="",a=0,c=me(e,F(l),{openMoved:(y)=>{let f=Oe(y);if(f!==null)o.openMoved(f.workspace,f.inspector,f.view,f.publishTab)},selectSection:(y)=>{T_(y)}});function u(y,f,k){if(s||k!==a)return;l=`Could not show ${H(y)?.label??y}: ${f}`,c.update(F(l))}function d(y){if(s)return;let f=V(),k=c.body();if(k!==t)t=k,r=null;if(!k||!y&&r===f){c.update(F(l));return}let q=r!==f;r=f,l="",c.update(F(l));let K=H(f);if(!K){i=null,k.replaceChildren();return}if(q||!i||i.parentElement!==k)i=document.createElement("div"),k.replaceChildren(i);a+=1;let Y=a;try{let O=K.render(i);if(O instanceof Promise)O.catch((ye)=>{u(f,te(ye),Y)})}catch(O){u(f,te(O),Y)}}let m=()=>E_(()=>{d(!0)}),h=m(),N=c.ready.then(()=>{d(!0)});return{dispose(){if(s)return;s=!0,h?.(),h=null,c.dispose()},focusActive:()=>{c.focusActive()},ready:N,resume(){if(s||h!==null)return;h=m(),i=null,d(!0)},suspend(){h?.(),h=null}}}var b=null,M=!1;function be(){return M}function De(){let e={dialog:Z({body:(o)=>{e.pane=he(o,{openMoved:(s,t,i,r)=>{Ae(s,t,i,r)}})},closed:()=>{if(b===e)Iu()},layer:tt("dialog")}),pane:null};return e}async function Ae(e,o,s,t){if(Iu(),s!==void 0){await rt("styles.open",{view:s},"Settings");return}if(t!==void 0){await rt("publish.open",{tab:t},"Settings");return}if(await rt("view.setWorkspace",{workspace:e},"Settings"),o===void 0)return;if(await rt("view.setRightPanel",{open:!0},"Settings"),ae()?.isEnabled("view.setRightTab")===!0)await rt("view.setRightTab",{tab:o},"Settings")}async function HR(){if(M&&b){await b.dialog.ready;return}if(M=!0,b&&!b.dialog.host.isConnected)Re(),M=!0;let e=b;if(e)e.pane?.resume(),await e.dialog.show();else e=De(),b=e,await e.dialog.ready;let o=e.pane;if(o===null||b!==e||!be())return;if(await o.ready,b===e&&be())o.focusActive()}function Iu(){if(!M)return;M=!1,b?.pane?.suspend(),b?.dialog.close()}function Re(){M=!1;let e=b;b=null,e?.pane?.dispose(),e?.dialog.dispose()}
|
|
2
|
+
export{MR,PR,xd,E_,Ol,FR,By,zk,T_,jR,Wk,HR,Iu};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=studio-
|
|
4
|
+
//# debugId=0079ADA8364B8C0964756E2164756E21
|
|
5
|
+
//# sourceMappingURL=studio-e4rq6x0q.js.map
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import{p}from"./studio-
|
|
2
|
-
export{
|
|
1
|
+
import{p}from"./studio-9ndgd55w.js";import{S}from"./studio-9ra9e7m4.js";import{n,Z,_,v}from"./studio-ywf9y1e2.js";function y(e,o=[]){if(!v(e))return o;let{children:t}=e;if(e.tagName==="slot"){let s=e.attributes,r=v(s)?s.name:void 0,l={name:n(r)?r.trim():""};if(Array.isArray(t)&&t.length>0)l.fallback=t;o.push(l)}if(Array.isArray(t))for(let s of t)y(s,o);return o}function YS(e,o=new Set){if(!v(e))return o;let t=(i)=>{if(v(i)){if(n(i.tagName)&&i.tagName.includes("-"))o.add(i.tagName);YS(i,o)}},{cases:s,children:r,map:l}=e,a=[...Array.isArray(r)?r:[r],l];if(v(s))a.push(...Object.values(s));for(let i of a)t(i);return o}function h(e){if(n(e))return"string";return Z(e)?"number":"boolean"}function x(e,o){if(o==null)return null;if(!_(o))return{default:o,name:e,type:h(o)};let t=v(o)?o:{};if(t.$prototype||t.$handler||t.$compute)return null;return{default:t.default,format:t.format,name:e,type:t.type}}function ZS(e,o){if(!v(e))return null;let{tagName:t}=e;if(!n(t)||!t.includes("-"))return null;let s=y(e),r=e.state,l=v(r)||Array.isArray(r)||n(r)?Object.entries(r):[],a={$id:n(e.$id)&&e.$id?e.$id:null,hasElements:Array.isArray(e.$elements)&&e.$elements.length>0,path:o,props:l.flatMap(([u,f])=>{let m=x(u,f);return m===null?[]:[m]})};if(s.length>0)a.slots=s;let i=[...YS(e)].filter((u)=>u!==t).toSorted();if(i.length>0)a.uses=i;return{...a,tagName:t}}var Ne=[],Zw=!1,g=0,b=Promise.resolve();function xa(){g+=1;let e=g,o=(async()=>{let t=null;try{t=await p().discoverComponents(S?.projectRoot||void 0)}catch{t=null}if(e!==g){await b;return}if(t)Ne=t;Zw=!0})();return b=o,o}function Ob(e,o){if(!e)return!1;let t=Ne.findIndex((l)=>l.path===e),s=ZS(o,e);if(!s){if(t===-1)return!1;return Ne.splice(t,1),!0}let r=s;if(t===-1)Ne.push(r);else Ne[t]=r;return!0}function Fc(e){let o=Object.fromEntries((e.props??[]).map((r)=>[r.name,r.default!==void 0?r.default:""])),t=[];for(let r of e.slots??[])for(let l of structuredClone(r.fallback??[]))if(!r.name)t.push(l);else if(_(l)&&n(l.tagName))l.attributes={slot:r.name,...l.attributes},t.push(l);else t.push({attributes:{slot:r.name},children:[l],tagName:"span"});let s={$props:o,tagName:e.tagName};if(t.length>0)s.children=t;return s}function c(e){let o=[];for(let t of e){if(t===".")continue;if(t===".."&&o.length>0&&o.at(-1)!=="..")o.pop();else o.push(t)}return o}function jc(e,o,t=S?.projectRoot??null){if(!e)return`./${o}`;let s=e.replaceAll("\\","/"),r=o.replaceAll("\\","/"),l=s.includes("/")?s.slice(0,s.lastIndexOf("/")):"",a=c(l.split("/").filter(Boolean)),i=c(r.split("/").filter(Boolean));if(a[0]===".."&&t){let d=t.replaceAll("\\","/").split("/").filter(Boolean);a=c([...d,...a]),i=c([...d,...i])}let u=0;while(u<a.length&&u<i.length&&a[u]===i[u])u+=1;let f=a.length-u,m=i.slice(u);return(f>0?"../".repeat(f):"./")+m.join("/")}
|
|
2
|
+
export{YS,ZS,Ne,Zw,xa,Ob,Fc,jc};
|
|
3
3
|
|
|
4
|
-
//# debugId=
|
|
5
|
-
//# sourceMappingURL=studio-
|
|
4
|
+
//# debugId=017D8E9D7994B89464756E2164756E21
|
|
5
|
+
//# sourceMappingURL=studio-ekzbgnjp.js.map
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import{p}from"./studio-
|
|
1
|
+
import{p}from"./studio-9ndgd55w.js";import{Wd,m}from"./studio-ztppbam0.js";import{g}from"./studio-tfmhnwyr.js";import{Ht,Wi,fn,ul,lr,Aa}from"./studio-a6e5fzve.js";import{Lo}from"./studio-8pne0rx4.js";import{Ta,Hd}from"./studio-8hf8qcm1.js";import{Fw}from"./studio-0rg30pvs.js";import{ls,Tw,Lw,er,jr}from"./studio-x2trkhk5.js";import{S}from"./studio-9ra9e7m4.js";import{n,Z,_,lf}from"./studio-ywf9y1e2.js";import{le}from"./studio-k5n4es74.js";var Cs="draft",gp="Marked a draft. Studio filters drafts out of its own lists; the build does not exclude them yet.";function jl(e){return e?.[Cs]===!0}function M(e){return e?.properties?.[Cs]?.type==="boolean"}function Rc(e,t){return M(e)||jl(t)}var k=g({includeDrafts:!1});function I(){return k.includeDrafts}function WD(e){k.includeDrafts=e}function T(e,t,r){return r?e:e.filter((o)=>!jl(t(o)))}function W(e){let t=[],r=[],o="",s=!1,l=!1,u=()=>{r.push(o),o="",l=!1},x=()=>{if(u(),r.length===1&&r[0]===""){r=[];return}t.push(r),r=[]};for(let C=0;C<e.length;C++){let F=e[C];if(s){if(F==='"')if(e[C+1]==='"')o+='"',C+=1;else s=!1;else o+=F;continue}if(F==='"'&&!l)s=!0,l=!0;else if(F==='"')o+=F;else if(F===",")u();else if(F===`
|
|
2
2
|
`)x();else if(F==="\r"){if(e[C+1]===`
|
|
3
|
-
`)C+=1;x()}else o+=F,l=!0}if(o!==""||r.length>0)x();return t}function
|
|
3
|
+
`)C+=1;x()}else o+=F,l=!0}if(o!==""||r.length>0)x();return t}function Id(e){let t=(e.match(/\r\n/g)??[]).length,r=(e.match(/(?<!\r)\n/g)??[]).length,o=t>r?`\r
|
|
4
4
|
`:`
|
|
5
5
|
`,s=e.endsWith(`
|
|
6
|
-
`),l=W(e),u=l[0]??[],x=l.slice(1),C=Math.max(u.length,...x.map((F)=>F.length),0);while(u.length<C)u.push("");for(let F of x)while(F.length<C)F.push("");return{eol:o,headers:u,rows:x,trailingNewline:s}}function z(e){if(/[",\n\r]/.test(e))return`"${e.replaceAll('"','""')}"`;return e}function
|
|
7
|
-
export{
|
|
6
|
+
`),l=W(e),u=l[0]??[],x=l.slice(1),C=Math.max(u.length,...x.map((F)=>F.length),0);while(u.length<C)u.push("");for(let F of x)while(F.length<C)F.push("");return{eol:o,headers:u,rows:x,trailingNewline:s}}function z(e){if(/[",\n\r]/.test(e))return`"${e.replaceAll('"','""')}"`;return e}function eT(e){return[e.headers,...e.rows].map((r)=>r.map((o)=>z(o)).join(",")).join(e.eol)+(e.trailingNewline?e.eol:"")}function q(e,t){let{headers:r,rows:o}=Id(e),s=[t,"id","sku","slug","Slug"].flatMap((l)=>{let u=l===void 0?-1:r.indexOf(l);return u===-1?[]:[u]});return o.filter((l)=>l.some((u)=>u.trim()!=="")).map((l,u)=>{let x=s.find((C)=>(l[C]??"")!=="");return x===void 0?String(u):l[x]})}function B(e,t){let r;try{r=JSON.parse(e)}catch{return[]}let o=(s,l)=>{let u=_(s)&&!Array.isArray(s)?s.id:void 0;return n(u)||Z(u)?String(u):l};if(!Array.isArray(r))return[o(r,t)];return r.map((s,l)=>o(s,`${t}-${l}`))}function K(e,t,r){let o=e.toLowerCase();if(o.endsWith(".csv"))return q(t,r);if(o.endsWith(".json")){let s=(e.split("/").pop()??e).replace(/\.json$/i,"");return B(t,s)}return[]}var R="__path";function N(){return S?.projectConfig?.content??{}}function fb(e){let t=N()[e];if(!t?.source)return null;let r=t.source.replace(/^\.\//,"").replace(/\/$/,""),o=t.format==="json"?".json":Wi(t.format)?.extensions[0]??lr()?.extensions[0]??".json";return{def:t,dir:r,ext:o,name:e}}function rS(){return Object.entries(N()).filter(([,e])=>{let t=e.source?.replace(/^\.\//,"")??"";return t!==""&&!/\.[a-z0-9]+$/i.test(t)}).map(([e,t])=>({dir:t.source.replace(/^\.\//,"").replace(/\/$/,""),name:e}))}async function O(e,t){let r=p(),o=[],s=async(l)=>{let u;try{u=await r.listDirectory(l)}catch{return}for(let x of u)if(x.type==="directory")await s(x.path);else if(t.some((C)=>x.path.endsWith(C)))o.push(x.path)};return await s(e),o.toSorted()}async function sS(e){let t=e.dir.indexOf(Lo);if(t===-1)return[e.dir];let r=e.dir.slice(0,t).replace(/\/$/,""),o=e.dir.slice(t+Lo.length),s;try{s=await p().listDirectory(r)}catch{return[]}return s.filter((l)=>l.type==="directory").map((l)=>`${l.path}${o}`.replace(/\/$/,"")).filter((l)=>Wd(l)?.name===e.name).toSorted()}async function V(e){let t=await sS(e);return(await Promise.all(t.map((o)=>O(o,[e.ext])))).flat().toSorted()}async function H(e){let t=Fw(e.name);if(t===null)return null;let r;try{r=await p().readFile(t)}catch{return[]}return K(t,r,e.def.idField)}async function mb(e){await Ht().catch(()=>{});let t=fb(e);if(!t)return[];let r=await H(t);if(r!==null)return r;return(await V(t)).map((s)=>{let l=s.split("/").pop()??s;return l.slice(0,l.length-t.ext.length)})}async function Q(e,t,r){let o=Array.from({length:e.length}),s=0,l=Array.from({length:Math.min(t,e.length)},async()=>{while(s<e.length){let u=s;s+=1,o[u]=await r(e[u])}});return await Promise.all(l),o}function j(e){if(e===void 0)return null;if(lf(e))return e;if(Array.isArray(e)&&e.every((t)=>!_(t)))return e.map(String);return JSON.stringify(e)}function A(e){for(let t of m.tabs.values())if(t.documentPath===e)return t;return null}function U(e,t){return e.every((r)=>{let o=r[t];return!n(o)||!o.startsWith("{")&&!o.startsWith("[")})}var L=new WeakSet;async function tT(){let e=[];for(let t of m.tabs.values()){let r=er(t);if(r&&L.has(r.source))e.push(r.load())}await Promise.all(e)}function J(e){let t=X(e);if(e.drafts)L.add(t);return t}function X(e){let t=new Map,r=null,o=null,s=(d=!1)=>{if(!d&&r)return r;return r=(async()=>{await Ht().catch(()=>{});let h=p(),f=await e.list();t.clear(),o=null;let y=await Q(f,32,async(i)=>{try{let a=await h.readFile(i),c=await jr(i,a);return{document:c.document,formatName:c.format.name,frontmatter:c.frontmatter,rawText:a}}catch{return null}});for(let[i,a]of f.entries()){let c=y[i];if(c)t.set(a,c)}})(),r},l=()=>{if(o)return o;let d={editable:!1,field:R,insertOnly:!0,kind:"string",pk:!0,required:!0,title:"Path",widthHint:220},h=Tw(e.schema()),f=new Set([R,...h.map((a)=>a.field)]),y=[...t.values()].map((a)=>{let c={};for(let[w,b]of Object.entries(a.frontmatter))if(!f.has(w)&&!w.startsWith("$"))c[w]=j(b);return c}),i=Lw(y);for(let a of i)a.editable=a.kind!=="text"||U(y,a.field);if(e.priorityFields?.length){let a=(c)=>{let w=e.priorityFields.indexOf(c.field);return w===-1?e.priorityFields.length:w};i.sort((c,w)=>a(c)-a(w))}return o=x([d,...h,...i]),o},u=()=>{if(!e.drafts)return!1;let d=e.schema();return Rc(d)||[...t.values()].some((h)=>Rc(d,h.frontmatter))},x=(d)=>{let h=d.findIndex((y)=>y.field===Cs);if(h<1||!u())return d;let f=d.filter((y)=>y.field!==Cs);return[f[0],d[h],...f.slice(1)]},C=(d,h)=>{let f={[R]:d};for(let y of l()){if(y.field===R)continue;f[y.field]=j(h.frontmatter[y.field])}return{cells:f,fingerprint:h.rawText,key:d}},F=async(d,h,f)=>{let y=p(),i={...h.frontmatter};for(let b of f)if(b.value===null)delete i[b.field];else i[b.field]=b.value;let a=h.document,c={...i,...a,children:a.children??[]},w=await Aa(h.formatName,c,{mode:"roundtrip",source:h.rawText});Ta(d),await y.writeFile(d,w),t.set(d,{...h,frontmatter:i,rawText:w})};return{backingPaths:()=>new Map([...t.keys()].map((d)=>[d,d])),capabilities:{delete:!0,insert:!0,remotePaging:!1,remoteSort:!1},async columns(){return await s(),l()},async commit(d){await s();let h=p(),f={cells:[],deletes:[],inserts:[]},y=new Map;for(let i of d.cells){let a=y.get(i.rowKey)??[];a.push({field:i.field,value:i.value}),y.set(i.rowKey,a)}for(let[i,a]of y){let c=(P,D,v)=>{for(let G of a)f.cells.push({error:D,field:G.field,ok:P,rowKey:i,stale:v})},w=t.get(i);if(!w){c(!1,"Entry no longer loaded — refresh the grid");continue}let b=A(i);if(b?.doc.dirty){c(!1,"Open in a tab with unsaved changes — save or close it first");continue}let E=null;try{E=await h.readFile(i)}catch{E=null}if(E!==w.rawText&&!Hd(i)){c(!1,"File changed on disk — refresh to reload",!0);continue}try{if(await F(i,w,a),c(!0),b){let{reloadFileInTab:P}=await (le("yswdhxrf"),import("./files-yswdhxrf.js"));P(i)}}catch(P){c(!1,P instanceof Error?P.message:String(P))}}for(let i of d.inserts){let a=i.cells[R];if(!n(a)||a.trim()===""){f.inserts.push({error:"Path is required",ok:!1,tempKey:i.tempKey});continue}let c=e.resolveInsertPath(a),w=t.has(c);if(!w)try{await h.readFile(c),w=!0}catch{w=!1}if(w){f.inserts.push({error:`${c} already exists`,ok:!1,tempKey:i.tempKey});continue}let b=e.insertFormatName(c);if(!b){f.inserts.push({error:`No format can serialize ${c}`,ok:!1,tempKey:i.tempKey});continue}try{let E={};for(let[v,G]of Object.entries(i.cells))if(v!==R&&G!==null)E[v]=G;let P=await Aa(b,{...E,children:[]},{frontmatter:Object.keys(E).length>0,mode:"roundtrip"});Ta(c),await h.writeFile(c,P);let D=await jr(c,P);t.set(c,{document:D.document,formatName:D.format.name,frontmatter:D.frontmatter,rawText:P}),f.inserts.push({newKey:c,ok:!0,tempKey:i.tempKey})}catch(E){f.inserts.push({error:E instanceof Error?E.message:String(E),ok:!1,tempKey:i.tempKey})}}for(let i of d.deletes){if(A(i.rowKey)){f.deletes.push({error:"Open in a tab — close it first",ok:!1,rowKey:i.rowKey});continue}try{Ta(i.rowKey),await h.deleteFile(i.rowKey),t.delete(i.rowKey),f.deletes.push({ok:!0,rowKey:i.rowKey})}catch(a){f.deletes.push({error:a instanceof Error?a.message:String(a),ok:!1,rowKey:i.rowKey})}}return f},id:e.id,label:e.label,async refresh(){await s(!0)},async rows(){await s();let h=(e.drafts?T([...t.entries()],([,f])=>f.frontmatter,I()):[...t.entries()]).map(([f,y])=>C(f,y));return{rows:h,total:h.length}}}}function nT(e){let t=()=>{let r=fb(e);if(!r)throw Error(`No content collection named "${e}" in project.json`);return r};return J({drafts:!0,id:ls({kind:"collection",name:e}),insertFormatName:(r)=>{let o=t();return(o.def.format?Wi(o.def.format)?.name:void 0)??fn(r)?.name??lr()?.name??null},label:e,list:()=>V(t()),resolveInsertPath:(r)=>{let o=t(),s=r.trim().replace(/^\.\//,"").replace(/^\//,"");if(!s.includes("/"))s=`${o.dir}/${s}`;if(!s.endsWith(o.ext))s=`${s}${o.ext}`;return s},schema:()=>t().def.schema})}function iT(){let e=()=>{let t=ul("page").filter((r)=>r!==".json");return t.length>0?t:[".md"]};return J({id:ls({kind:"pages"}),insertFormatName:(t)=>fn(t)?.name??null,label:"Pages",list:()=>O("pages",e()),priorityFields:["title","description"],resolveInsertPath:(t)=>{let r=t.trim().replace(/^\.\//,"").replace(/^\//,"");if(!r.startsWith("pages/"))r=`pages/${r}`;if(!e().some((o)=>r.endsWith(o)))r=`${r}${e()[0]}`;return r},schema:()=>null})}
|
|
7
|
+
export{Id,eT,Cs,gp,jl,Rc,WD,fb,rS,sS,mb,tT,nT,iT};
|
|
8
8
|
|
|
9
|
-
//# debugId=
|
|
10
|
-
//# sourceMappingURL=studio-
|
|
9
|
+
//# debugId=0DBB8BFAE846B55C64756E2164756E21
|
|
10
|
+
//# sourceMappingURL=studio-fg4fj9ec.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import{te}from"./studio-psh8mwnw.js";import{Oe,ir,Vd,u}from"./studio-ztppbam0.js";import{C}from"./studio-tfmhnwyr.js";import{p}from"./studio-9ndgd55w.js";import{Ne,xa,jc}from"./studio-ekzbgnjp.js";import{xi}from"./studio-myb4mf0h.js";import{aw,ab}from"./studio-k6hbx2fc.js";import{xS}from"./studio-x2trkhk5.js";import{Co}from"./studio-nqexty8x.js";import{Vt,zi}from"./studio-9ra9e7m4.js";import{oe}from"./studio-nfwacw31.js";import{_,it}from"./studio-ywf9y1e2.js";function Qy(){let t=u.value,e=Oe(t?.session.selection);if(!t||!e||e.length<2)return null;let o=oe(t.doc.document,e);if(!o||!o.tagName)return null;return{node:o,path:e}}async function rm(){let t=Qy();if(!t)return;let e=await b(g(t.node));if(!e)return;await cE(e.toLowerCase())}async function cE(t){let e=u.value,o=Qy();if(!e||!o)return null;let{node:m,path:d}=o,l=v(m);l.tagName=t;let r=`components/${t}.json`,c=jc(e.documentPath,r),f=d;if(!Vd(e,(n)=>{let s=Vt(f)??[],h=zi(f),a=n;for(let i of s)a=a[i];if(!Array.isArray(a.children))a.children=[];if(a.children[h]={tagName:t},!n.$elements)n.$elements=[];if(!n.$elements.some((i)=>_(i)&&("$ref"in i)&&i.$ref===c))n.$elements.push({$ref:c})}))return null;try{await p().writeFile(r,Co(l,null)),await xa();let s=xS(l);if(C.success(`Converted to <${t}>`),s)C.warn(`<${t}> has a slot problem: ${s}`,{path:r,source:"Components",tier:"problem"});return r}catch(n){return C.error(`Could not save the <${t}> component.`,{detail:te(n),path:r,source:"Components"}),null}}function g(t){if(t.$id){let o=ab(t.$id);if(o!=="")return o}let e=(it(t.tagName)||"div").toLowerCase();return e.includes("-")?e:ab(e)}function v(t){let e=ir(t);return delete e.$id,delete e.$layout,delete e.$paths,e}function N(t){let e=t.trim().toLowerCase(),o=aw(e);if(o!=="")return o;return Ne.some((m)=>m.tagName===e)?`Component <${e}> already exists`:""}function b(t){return xi("Convert to Component",{confirmLabel:"Convert",message:"Enter a hyphenated tag name for the new component.",placeholder:"my-component",validate:N,value:t})}
|
|
2
|
+
export{Qy,rm,cE};
|
|
3
|
+
|
|
4
|
+
//# debugId=B779E539D8F1AECD64756E2164756E21
|
|
5
|
+
//# sourceMappingURL=studio-fj6jzgxw.js.map
|