@macrulez/devtoolz 0.4.3 → 0.5.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/README.md +14 -172
- package/dist/cli.js +13 -125
- package/dist/cli.js.map +1 -1
- package/dist/commands/ui/cli.js +1 -1
- package/dist/commands/ui/cli.js.map +1 -1
- package/dist/commands/ui/fs-routes.d.ts +0 -4
- package/dist/commands/ui/fs-routes.js +5 -78
- package/dist/commands/ui/fs-routes.js.map +1 -1
- package/dist/commands/ui/modules/cleanup.js +2 -2
- package/dist/commands/ui/modules/cleanup.js.map +1 -1
- package/dist/commands/ui/modules/index.js +1 -8
- package/dist/commands/ui/modules/index.js.map +1 -1
- package/dist/index.d.ts +0 -9
- package/dist/index.js +0 -5
- package/dist/index.js.map +1 -1
- package/dist/ui/assets/ChecksPage-FhzZT8lq.js +1 -0
- package/dist/ui/assets/ChecksPage-ZoPlxU6J.css +1 -0
- package/dist/ui/assets/CleanupPage-9PuXSO_G.css +1 -0
- package/dist/ui/assets/CleanupPage-LpbZ2AB-.js +4 -0
- package/dist/ui/assets/highlight-Ba7TPCSA.js +2 -0
- package/dist/ui/assets/highlight-fNCqOka7.css +1 -0
- package/dist/ui/assets/{index-Ch5kTxCO.css → index-BzfkjuG8.css} +1 -1
- package/dist/ui/assets/index-DTj3rBik.js +3 -0
- package/dist/ui/index.html +2 -2
- package/dist/utils/atomic-write.d.ts +1 -0
- package/dist/utils/atomic-write.js +15 -0
- package/dist/utils/atomic-write.js.map +1 -0
- package/dist/utils/backup-error.d.ts +2 -0
- package/dist/utils/backup-error.js +3 -0
- package/dist/utils/backup-error.js.map +1 -0
- package/dist/utils/backup.d.ts +19 -0
- package/dist/utils/backup.js +33 -0
- package/dist/utils/backup.js.map +1 -0
- package/dist/utils/restore.d.ts +28 -0
- package/dist/utils/restore.js +88 -0
- package/dist/utils/restore.js.map +1 -0
- package/package.json +1 -6
- package/dist/ui/assets/ChecksPage-Ia4QJkV3.js +0 -1
- package/dist/ui/assets/ChecksPage-VewKhd5A.css +0 -1
- package/dist/ui/assets/CleanupPage-DqqrgWSI.js +0 -4
- package/dist/ui/assets/CleanupPage-nxJE8S0P.css +0 -1
- package/dist/ui/assets/FolderBrowser-Cdzt7edI.js +0 -1
- package/dist/ui/assets/FolderBrowser-CkH9R4jg.css +0 -1
- package/dist/ui/assets/ImageBatchPage-9HgS9uVf.js +0 -4
- package/dist/ui/assets/ImageBatchPage-EhlvnXbP.css +0 -1
- package/dist/ui/assets/ImageHashPage-BT4S8t3Y.css +0 -1
- package/dist/ui/assets/ImageHashPage-C0ltmpOF.js +0 -1
- package/dist/ui/assets/SourcePicker-6fQmtLgo.css +0 -1
- package/dist/ui/assets/SourcePicker-xk00AG2e.js +0 -1
- package/dist/ui/assets/UiSegmented-BT3dOelo.css +0 -1
- package/dist/ui/assets/UiSegmented-CsTRUZoX.js +0 -1
- package/dist/ui/assets/highlight-DT7vvdYt.js +0 -2
- package/dist/ui/assets/index-D8H-zVzo.js +0 -11
- package/dist/ui/assets/useCopy-i_vlQfC-.js +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.overview[data-v-21773826]{display:flex;flex-direction:column;gap:16px}.block[data-v-21773826]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-21773826]{font-size:12px}.progress-wrap[data-v-21773826]{display:flex;flex-direction:column;gap:8px}.progress[data-v-21773826]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-21773826]{height:100%;background:var(--accent);transition:width .15s}.chips[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.sev[data-v-21773826]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px}.sev--error[data-v-21773826]{background:var(--danger-soft);color:var(--danger)}.sev--warning[data-v-21773826]{background:var(--warn-soft);color:var(--warn)}.sev--ok[data-v-21773826]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.group[data-v-21773826]{display:flex;flex-direction:column;gap:8px}.group__title[data-v-21773826]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.cards[data-v-21773826]{display:grid;grid-template-columns:repeat(auto-fill,minmax(260px,1fr));gap:12px}.tile[data-v-21773826]{display:flex;flex-direction:column;gap:8px;background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);padding:12px 16px;text-align:left;cursor:pointer;transition:border-color .15s}.tile[data-v-21773826]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.tile[data-v-21773826]:hover{border-color:var(--accent)}.tile--clean[data-v-21773826]{border-left:3px solid var(--ok)}.tile--found[data-v-21773826]{border-left:3px solid var(--warn)}.tile--broken[data-v-21773826]{border-left:3px solid var(--danger)}.tile__top[data-v-21773826]{display:flex;align-items:center;justify-content:space-between;gap:8px}.tile__state[data-v-21773826]{color:var(--muted);font-size:12px;font-weight:600}.tile--clean .tile__state[data-v-21773826]{color:var(--ok)}.tile--found .tile__state[data-v-21773826]{color:var(--warn)}.tile--broken .tile__state[data-v-21773826]{color:var(--danger)}.tile__text[data-v-21773826]{font-size:12px}.tile__sev[data-v-21773826]{display:flex;flex-wrap:wrap;align-items:center;gap:4px}.tile__slow[data-v-21773826]{font-size:11px}.graph[data-v-613d80bb]{display:flex;flex-direction:column;gap:8px}.graph__svg[data-v-613d80bb]{width:100%;height:520px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);cursor:grab;touch-action:none}.graph__svg--drag[data-v-613d80bb]{cursor:grabbing}.graph__bar[data-v-613d80bb]{display:flex;flex-wrap:wrap;align-items:center;gap:16px;font-size:12px}.spacer[data-v-613d80bb]{flex:1}.small[data-v-613d80bb]{font-size:12px}.edge[data-v-613d80bb]{fill:none;stroke:var(--muted);stroke-width:1.4;opacity:.75;transition:opacity .15s}.edge--strong[data-v-613d80bb]{stroke-width:2.2}.edge--type[data-v-613d80bb]{stroke-dasharray:5 4}.edge--on[data-v-613d80bb]{stroke:var(--accent);stroke-width:2.6;opacity:1}.edge--dim[data-v-613d80bb]{opacity:.12}.arrow[data-v-613d80bb]{fill:var(--muted)}.arrow--on[data-v-613d80bb]{fill:var(--accent)}.node[data-v-613d80bb]{cursor:pointer;outline:none;transition:opacity .15s}.node__dot[data-v-613d80bb]{stroke:var(--surface);stroke-width:2}.node--single .node__dot[data-v-613d80bb]{fill:var(--warn)}.node--hub .node__dot[data-v-613d80bb]{fill:var(--danger)}.node:hover .node__dot[data-v-613d80bb],.node:focus-visible .node__dot[data-v-613d80bb]{stroke:var(--accent);stroke-width:3}.node--dim[data-v-613d80bb]{opacity:.2}.node__label[data-v-613d80bb]{fill:var(--text);font-size:13px;font-weight:600;paint-order:stroke;stroke:var(--surface-2);stroke-width:4px;stroke-linejoin:round}.node__dir[data-v-613d80bb]{fill:var(--muted);font-size:10px;paint-order:stroke;stroke:var(--surface-2);stroke-width:3px}.legend[data-v-613d80bb]{display:inline-flex;align-items:center;gap:6px}.legend__dot[data-v-613d80bb]{width:10px;height:10px;border-radius:50%}.legend__dot--single[data-v-613d80bb]{background:var(--warn)}.legend__dot--hub[data-v-613d80bb]{background:var(--danger)}.legend__line[data-v-613d80bb]{width:22px;border-top:2px dashed var(--muted)}.legend__line--type[data-v-613d80bb]{border-top-style:dashed}.groups[data-v-917e27d1]{display:flex;flex-direction:column;gap:8px}.group[data-v-917e27d1]{border:1px solid var(--border);border-radius:9px;overflow:hidden}.group__head[data-v-917e27d1]{display:flex;align-items:center;gap:8px;width:100%;padding:8px 12px;border:0;background:var(--surface-2);text-align:left;cursor:pointer}.group__head[data-v-917e27d1]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.group__caret[data-v-917e27d1]{flex:none;color:var(--muted);transition:transform .15s}.group__caret--open[data-v-917e27d1]{transform:rotate(90deg)}.group__file[data-v-917e27d1]{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.group__count[data-v-917e27d1]{flex:none;padding:0 8px;border-radius:999px;background:var(--surface);color:var(--muted);font-size:11px}.items[data-v-917e27d1]{margin:0;padding:0;list-style:none}.item[data-v-917e27d1]{border-top:1px solid var(--border)}.item__main[data-v-917e27d1]{display:flex;align-items:flex-start;gap:12px;width:100%;padding:8px 12px;border:0;background:transparent;text-align:left;cursor:pointer;transition:background .15s}.item__main[data-v-917e27d1]:hover:not(:disabled){background:var(--surface-2)}.item__main[data-v-917e27d1]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.item__place[data-v-917e27d1]{flex:none;width:56px;color:var(--muted);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;text-align:right}.item__text[data-v-917e27d1]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.item__hint[data-v-917e27d1]{font-size:12px}.item__code[data-v-917e27d1]{flex:none;padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.dot[data-v-917e27d1]{flex:none;width:8px;height:8px;margin-top:7px;border-radius:50%;background:var(--muted)}.dot--error[data-v-917e27d1]{background:var(--danger)}.dot--warning[data-v-917e27d1]{background:var(--warn)}.more[data-v-917e27d1]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.cycles[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:12px}.split[data-v-dbccb5a2]{display:grid;grid-template-columns:minmax(0,1fr) 280px;gap:16px;align-items:start}@media(max-width:1100px){.split[data-v-dbccb5a2]{grid-template-columns:1fr}}.side[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:8px;max-height:600px;overflow-y:auto}.side__title[data-v-dbccb5a2]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.side__list[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.cycle[data-v-dbccb5a2]{display:flex;flex-direction:column;gap:2px;width:100%;padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);text-align:left;cursor:pointer}.cycle[data-v-dbccb5a2]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.cycle--on[data-v-dbccb5a2]{border-color:var(--accent);background:var(--accent-soft)}.cycle__head[data-v-dbccb5a2]{display:flex;align-items:center;gap:8px;font-size:12px}.cycle__tag[data-v-dbccb5a2]{padding:0 8px;border-radius:999px;background:var(--surface-2);font-size:11px}.cycle__chain[data-v-dbccb5a2]{color:var(--muted);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:11px;word-break:break-all}.code[data-v-e79e57a2]{position:relative;overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;tab-size:2}.code[data-v-e79e57a2]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.code__note[data-v-e79e57a2]{position:sticky;top:0;z-index:1;padding:6px 12px;background:var(--warn-soft);color:var(--warn)}.code__link[data-v-e79e57a2]{padding:0;border:0;background:transparent;color:inherit;text-decoration:underline;cursor:pointer}.line[data-v-e79e57a2]{position:relative;display:flex;min-width:max-content}.line--focus[data-v-e79e57a2]{background:color-mix(in srgb,var(--warn) 22%,transparent);box-shadow:inset 3px 0 0 var(--warn)}.line__no[data-v-e79e57a2]{flex:none;padding:0 12px;color:var(--muted);text-align:right;user-select:none;box-sizing:content-box}.line__text[data-v-e79e57a2]{white-space:pre;padding-right:16px}.line__marker[data-v-e79e57a2]{position:absolute;bottom:0;width:1ch;height:2px;background:var(--danger);pointer-events:none}.tok[data-v-e79e57a2]{color:var(--light)}.tok--bold[data-v-e79e57a2]{font-weight:600}.tok--italic[data-v-e79e57a2]{font-style:italic}@media(prefers-color-scheme:dark){.tok[data-v-e79e57a2]{color:var(--dark)}}.counter[data-v-88d2cb60]{font-size:12px}.body[data-v-88d2cb60]{display:flex;flex-direction:column;gap:12px;padding:16px;min-height:0}.finding[data-v-88d2cb60]{display:flex;flex-direction:column;gap:4px}.bar[data-v-88d2cb60]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.path[data-v-88d2cb60]{flex:1;min-width:0;font-size:12px;word-break:break-all}.viewer[data-v-88d2cb60]{max-height:58vh}.badge[data-v-88d2cb60]{align-self:flex-start;padding:1px 8px;border-radius:999px;background:var(--surface-2);font-size:11px;text-transform:uppercase;letter-spacing:.03em}.badge--error[data-v-88d2cb60]{background:var(--danger-soft);color:var(--danger)}.badge--warning[data-v-88d2cb60]{background:var(--warn-soft);color:var(--warn)}a.btn[data-v-88d2cb60]{text-decoration:none}.page[data-v-2621f21d]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-2621f21d]{padding:18px 14px 40px}}.page__head p[data-v-2621f21d]{margin-top:4px}.project[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.project code[data-v-2621f21d]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}.layout[data-v-2621f21d]{display:grid;grid-template-columns:250px minmax(0,1fr);gap:20px;align-items:start}@media(max-width:760px){.layout[data-v-2621f21d]{grid-template-columns:1fr}}.menu[data-v-2621f21d]{display:flex;flex-direction:column;gap:2px}.menu__title[data-v-2621f21d]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase;margin:12px 0 4px 8px}.menu__item[data-v-2621f21d]{display:flex;align-items:center;gap:8px;padding:9px 10px;border:0;border-radius:9px;background:transparent;text-align:left;cursor:pointer;transition:background .15s}.menu__item[data-v-2621f21d]:hover:not(:disabled){background:var(--surface-2)}.menu__item[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.menu__item--on[data-v-2621f21d]{background:var(--accent-soft);color:var(--accent);font-weight:600}.menu__name[data-v-2621f21d]{flex:1}.menu__count[data-v-2621f21d]{padding:0 8px;border-radius:999px;background:var(--warn-soft);color:var(--warn);font-size:11px;font-weight:600}.menu__count--clean[data-v-2621f21d]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.main[data-v-2621f21d]{display:flex;flex-direction:column;gap:16px;min-width:0}.block[data-v-2621f21d]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-2621f21d]{font-size:12px}.link[data-v-2621f21d]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.options[data-v-2621f21d]{display:flex;flex-direction:column;gap:12px}.textarea[data-v-2621f21d]{padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.textarea[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.filters[data-v-2621f21d]{display:flex;flex-direction:column;gap:8px}.search[data-v-2621f21d]{max-width:420px}.chips[data-v-2621f21d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-2621f21d]{padding:2px 10px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.chip[data-v-2621f21d]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.chip--on[data-v-2621f21d]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent)}.clean[data-v-2621f21d]{display:flex;align-items:center;gap:8px;color:var(--ok);font-weight:600}.empty[data-v-2621f21d]{text-align:center}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{d as ne,r as d,w as ye,q as se,a as oe,o as a,c as i,F as _,b as P,h as s,t as o,n as T,s as me,j as C,l as v,x as z,g as D,e as be,I as we,y as Se,i as K,k as xe,z as Ce,p as te}from"./index-D8H-zVzo.js";import{F as je}from"./FolderBrowser-Cdzt7edI.js";import{U as Ne}from"./UiSegmented-CsTRUZoX.js";import{h as Oe}from"./highlight-DT7vvdYt.js";const Pe=ne({__name:"DiffView",props:{diff:{type:String,required:!0},lang:{type:String,required:!0}},setup(E,{expose:c}){c();const p=E;function e(u){const w=[];let f,k=0,m=0;for(const h of u.split(`
|
|
2
|
-
`)){const N=/^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@(.*)$/.exec(h);if(N){k=Number(N[1]),m=Number(N[2]),f={header:h,lines:[]},w.push(f);continue}if(!f||h.startsWith("\\"))continue;const S=h[0];S==="+"?f.lines.push({type:"add",text:h.slice(1),oldNo:null,newNo:m++}):S==="-"?f.lines.push({type:"del",text:h.slice(1),oldNo:k++,newNo:null}):S===" "&&f.lines.push({type:"ctx",text:h.slice(1),oldNo:k++,newNo:m++})}return w}const j=d(e(p.diff));async function y(){const u=e(p.diff);j.value=u;for(const w of u){const f=await Oe(w.lines.map(k=>k.text).join(`
|
|
3
|
-
`),p.lang);w.lines.forEach((k,m)=>{k.tokens=f[m]})}j.value=[...u]}ye(()=>[p.diff,p.lang],y),se(y);function t(u){return u==="add"?"+":u==="del"?"−":" "}const r={props:p,parse:e,hunks:j,colour:y,sign:t};return Object.defineProperty(r,"__isScriptSetup",{enumerable:!1,value:!0}),r}}),Ee={class:"diff",role:"region","aria-label":"Changes in this file"},Ie={class:"hunk__head"},Be={class:"row__no"},Ve={class:"row__no"},ze={class:"row__sign"},De={class:"row__text"},Fe={key:2};function Ue(E,c,p,e,j,y){return a(),i("div",Ee,[(a(!0),i(_,null,P(e.hunks,(t,r)=>(a(),i("section",{key:r,class:"hunk"},[s("div",Ie,o(t.header),1),(a(!0),i(_,null,P(t.lines,(u,w)=>(a(),i("div",{key:w,class:T(["row",`row--${u.type}`])},[s("span",Be,o(u.oldNo??""),1),s("span",Ve,o(u.newNo??""),1),s("span",ze,o(e.sign(u.type)),1),s("span",De,[u.tokens?(a(!0),i(_,{key:0},P(u.tokens,(f,k)=>(a(),i("span",{key:k,class:"tok",style:me({"--light":f.light||"var(--text)","--dark":f.dark||"var(--text)"})},o(f.text),5))),128)):(a(),i(_,{key:1},[C(o(u.text),1)],64)),u.text===""?(a(),i("span",Fe," ")):v("v-if",!0)])],2))),128))]))),128))])}const qe=oe(Pe,[["render",Ue],["__scopeId","data-v-fab0cc77"],["__file","C:/work/NPM/devtoolz/ui/src/modules/cleanup/DiffView.vue"]]),Y="devtoolz-ui.checks-project",Q=40,Ae=ne({__name:"CleanupPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(E,{expose:c}){c();const p=E,e={"embedded-in-expression":"inside a larger expression","braceless-body":"the only statement of an if/loop without braces"},j=d([]),y=d("strip-comments"),t=d(""),r=d({}),u=d(!1),w=d(!1),f=d(!1),k=d(!1),m=d(),h=d(new Set),N=d(new Set),S=d(new Set),X=d(""),O=d(""),F=d(""),U=d([]),I=d(""),W=d([]),M=d(Q);let B;const G=z(()=>j.value.find(n=>n.id===y.value)),H=z(()=>{const n=X.value.trim().toLowerCase();return(m.value?.files??[]).filter(l=>n===""||l.file.toLowerCase().includes(n))}),le=z(()=>H.value.slice(0,M.value)),q=z(()=>h.value.size),J=z(()=>(m.value?.files??[]).filter(n=>h.value.has(n.file)).reduce((n,l)=>n+l.count,0));function Z(n){try{localStorage.setItem(Y,n)}catch{return}}function $(){try{return localStorage.getItem(Y)??""}catch{return""}}function A(){const n=G.value;return n?{...Object.fromEntries(n.options.map(g=>[g.key,g.default])),...r.value[n.id]??{}}:{}}function ae(n,l){r.value={...r.value,[y.value]:{...A(),[n]:l}}}function ie(n){const l=n.slice(n.lastIndexOf(".")+1).toLowerCase();return l==="ts"?"ts":l==="tsx"?"tsx":l==="vue"?"vue":l==="jsx"?"jsx":"js"}function ce(n){let l=0,g=0;for(const b of(n??"").split(`
|
|
4
|
-
`))b.startsWith("+")&&!b.startsWith("+++")?l+=1:b.startsWith("-")&&!b.startsWith("---")&&(g+=1);return{added:l,removed:g}}function re(n){const l=new Set(h.value);l.has(n)?l.delete(n):l.add(n),h.value=l}function de(n){const l=new Set(N.value);l.has(n)?l.delete(n):l.add(n),N.value=l}function ue(){h.value=new Set(H.value.filter(n=>!S.value.has(n.file)).map(n=>n.file))}function fe(){h.value=new Set}function he(n){w.value=!1;const l=n[0];!l||l===t.value||(t.value=l,Z(l),R(),V())}function R(){m.value=void 0,h.value=new Set,N.value=new Set,S.value=new Set,U.value=[],I.value="",F.value="",O.value=""}function ve(n){y.value=n,R()}async function _e(){if(!f.value){B?.(),R(),f.value=!0,M.value=Q;try{const{jobId:n}=await D.post(`/api/cleanup/${y.value}/scan`,{project:t.value,options:A()});B=Se(n,{onDone:l=>{m.value=l,f.value=!1},onFailed:l=>{O.value=l,f.value=!1}})}catch(n){O.value=n instanceof Error?n.message:String(n),f.value=!1}}}async function V(){try{const n=await D.get(`/api/cleanup/history?project=${encodeURIComponent(t.value)}`);W.value=n.backups}catch{W.value=[]}}async function pe(){const n=m.value;if(!(!n||q.value===0||k.value||!window.confirm(`Change ${q.value} file${q.value===1?"":"s"}? ${J.value} ${G.value?.verb??"item"}${J.value===1?"":"s"} will be removed. A backup is saved first, and you can undo this afterwards.`))){k.value=!0,O.value="";try{const g=n.files.filter(x=>h.value.has(x.file)),b=await D.post(`/api/cleanup/${y.value}/apply`,{project:t.value,options:A(),files:g.map(x=>({file:x.file,hash:x.hash}))});U.value=b.results,I.value=b.backupDir??"";const L=b.results.filter(x=>x.status==="applied").map(x=>x.file);S.value=new Set([...S.value,...L]),h.value=new Set([...h.value].filter(x=>!L.includes(x))),F.value=`${L.length} file${L.length===1?"":"s"} changed.`,await V()}catch(g){O.value=g instanceof Error?g.message:String(g)}finally{k.value=!1}}}async function ke(n){if(window.confirm("Put the files back as they were before this cleanup?"))try{const l=await D.post("/api/cleanup/undo",{project:t.value,dir:n}),g=l.counts.restored??0,b=l.counts.modified??0;F.value=`Restored ${g} file${g===1?"":"s"}.`+(b?` ${b} changed since and were left alone.`:""),n===I.value&&(I.value="",U.value=[],S.value=new Set),await V()}catch(l){O.value=l instanceof Error?l.message:String(l)}}function ge(n){const l=new Date(n);return Number.isNaN(l.getTime())?n:l.toLocaleString()}se(async()=>{t.value=$()||p.status?.cwd||"";try{j.value=await D.get("/api/cleanup/tools")}catch(n){O.value=n instanceof Error?n.message:String(n)}await V()}),be(()=>B?.());const ee={props:p,PROJECT_KEY:Y,PAGE:Q,REASONS:e,tools:j,toolId:y,project:t,options:r,optionsOpen:u,browsing:w,scanning:f,applying:k,scan:m,picked:h,expanded:N,done:S,query:X,failure:O,note:F,results:U,lastBackup:I,history:W,shown:M,get stop(){return B},set stop(n){B=n},tool:G,files:H,visible:le,pickedCount:q,pickedRemovals:J,remember:Z,recall:$,currentOptions:A,setOption:ae,langOf:ie,stats:ce,togglePicked:re,toggleExpanded:de,selectAll:ue,selectNone:fe,setProject:he,reset:R,chooseTool:ve,runScan:_e,loadHistory:V,apply:pe,undo:ke,when:ge,FolderBrowser:je,Icon:we,UiSegmented:Ne,DiffView:qe};return Object.defineProperty(ee,"__isScriptSetup",{enumerable:!1,value:!0}),ee}}),Re={class:"page"},Le={class:"page__head"},Te={class:"muted"},We={class:"project"},Me=["title"],Ge={key:0,class:"card block"},He={class:"head"},Je=["disabled"],Ke={class:"muted"},Ye={key:0,class:"options"},Qe={key:0,class:"check"},Xe=["checked","onChange"],Ze={class:"muted"},$e={key:1,class:"field"},et={class:"muted"},tt=["value","onInput"],nt={key:1,class:"notice notice--error"},st={key:2,class:"notice"},ot={key:3,class:"card block"},lt={class:"results"},at={class:"muted"},it={key:0,class:"actions"},ct={key:4,class:"card block",role:"status"},rt={key:5,class:"card block"},dt={class:"head"},ut={class:"muted small"},ft={key:0,class:"notice notice--warn"},ht={class:"skipped"},vt={class:"toolbar"},_t=["disabled"],pt={class:"files"},kt={class:"file__row"},gt=["checked","disabled","aria-label","onChange"],yt=["aria-expanded","onClick"],mt={class:"file__name"},bt={class:"file__count"},wt={class:"file__stat file__stat--del"},St={key:0,class:"file__stat file__stat--add"},xt={key:1,class:"file__done"},Ct={key:0,class:"actions"},jt={key:6,class:"card block"},Nt={class:"history"},Ot={class:"muted"},Pt=["onClick"];function Et(E,c,p,e,j,y){return a(),i("div",Re,[s("header",Le,[s("h1",null,o(p.module.title),1),s("p",Te,o(p.module.description),1),s("p",We,[K(e.Icon,{name:"folder",size:15}),c[7]||(c[7]=s("span",{class:"muted"},"Project",-1)),s("code",{title:e.project},o(e.project),9,Me),s("button",{class:"btn btn--small",onClick:c[0]||(c[0]=t=>e.browsing=!0)},"Change…")])]),e.tool?(a(),i("section",Ge,[s("div",He,[K(e.UiSegmented,{"model-value":e.toolId,label:"What to remove",options:e.tools.map(t=>({value:t.id,label:t.title})),"onUpdate:modelValue":e.chooseTool},null,8,["model-value","options"]),s("button",{class:"btn btn--primary",disabled:e.scanning||e.applying||e.project==="",onClick:e.runScan},[K(e.Icon,{name:"search",size:15}),C(" "+o(e.scanning?"Scanning…":e.scan?"Scan again":"Scan the project"),1)],8,Je)]),s("p",Ke,o(e.tool.description)+" Nothing is changed until you choose the files and confirm. ",1),s("button",{class:"link",onClick:c[1]||(c[1]=t=>e.optionsOpen=!e.optionsOpen)},o(e.optionsOpen?"Hide":"Show")+" options ",1),e.optionsOpen?(a(),i("div",Ye,[(a(!0),i(_,null,P(e.tool.options,t=>(a(),i(_,{key:t.key},[t.type==="boolean"?(a(),i("label",Qe,[s("input",{type:"checkbox",checked:e.currentOptions()[t.key]===!0,onChange:r=>e.setOption(t.key,r.target.checked)},null,40,Xe),s("span",null,[C(o(t.label)+" ",1),s("small",Ze,"— "+o(t.help),1)])])):(a(),i("label",$e,[s("span",null,[C(o(t.label)+" ",1),s("small",et,"— "+o(t.help),1)]),s("textarea",{class:"textarea",rows:"3",spellcheck:"false",value:String(e.currentOptions()[t.key]??""),onInput:r=>e.setOption(t.key,r.target.value)},null,40,tt)]))],64))),128))])):v("v-if",!0)])):v("v-if",!0),e.failure?(a(),i("p",nt,o(e.failure),1)):v("v-if",!0),e.note?(a(),i("p",st,o(e.note),1)):v("v-if",!0),e.lastBackup||e.results.length?(a(),i("section",ot,[c[8]||(c[8]=s("h2",null,"Result",-1)),s("ul",lt,[(a(!0),i(_,null,P(e.results,t=>(a(),i("li",{key:t.file,class:T(["result",`result--${t.status}`])},[s("code",null,o(t.file),1),s("span",at,[t.status==="applied"?(a(),i(_,{key:0},[C("changed, "+o(t.count)+" removed",1)],64)):(a(),i(_,{key:1},[C(o(t.message??t.status),1)],64))])],2))),128))]),e.lastBackup?(a(),i("div",it,[s("button",{class:"btn",onClick:c[2]||(c[2]=t=>e.undo(e.lastBackup))},"Undo this cleanup")])):v("v-if",!0)])):v("v-if",!0),e.scanning?(a(),i("section",ct,[...c[9]||(c[9]=[s("p",{class:"muted"},"Scanning the project…",-1)])])):e.scan?(a(),i("section",rt,[s("div",dt,[s("div",null,[s("h2",null,[e.scan.files.length===0?(a(),i(_,{key:0},[C("Nothing to remove")],64)):(a(),i(_,{key:1},[C(o(e.scan.total)+" "+o(e.tool?.verb)+o(e.scan.total===1?"":"s")+" in "+o(e.scan.files.length)+" file"+o(e.scan.files.length===1?"":"s"),1)],64))]),s("p",ut,o(e.scan.filesScanned)+" files scanned · "+o((e.scan.tookMs/1e3).toFixed(1))+" s ",1)])]),e.scan.skipped.length?(a(),i("div",ft,[s("strong",null,o(e.scan.skipped.length)+" call"+o(e.scan.skipped.length===1?"":"s")+" left alone",1),c[10]||(c[10]=C(", because removing them is not safe: ",-1)),s("ul",ht,[(a(!0),i(_,null,P(e.scan.skipped,(t,r)=>(a(),i("li",{key:r},[s("code",null,o(t.file)+":"+o(t.line),1),C(" — "+o(e.REASONS[t.reason]??t.reason),1)]))),128))])])):v("v-if",!0),e.scan.files.length?(a(),i(_,{key:1},[s("div",vt,[xe(s("input",{"onUpdate:modelValue":c[3]||(c[3]=t=>e.query=t),class:"input search",placeholder:"Filter files","aria-label":"Filter files"},null,512),[[Ce,e.query]]),s("button",{class:"btn btn--small",onClick:e.selectAll},"Select all"),s("button",{class:"btn btn--small",onClick:e.selectNone},"Select none"),c[11]||(c[11]=s("span",{class:"spacer"},null,-1)),s("button",{class:"btn btn--primary",disabled:e.pickedCount===0||e.applying,onClick:e.apply},o(e.applying?"Changing…":`Change ${e.pickedCount} file${e.pickedCount===1?"":"s"}`),9,_t)]),s("ul",pt,[(a(!0),i(_,null,P(e.visible,t=>(a(),i("li",{key:t.file,class:T(["file",{"file--done":e.done.has(t.file)}])},[s("div",kt,[s("input",{type:"checkbox",checked:e.picked.has(t.file),disabled:e.done.has(t.file),"aria-label":`Change ${t.file}`,onChange:r=>e.togglePicked(t.file)},null,40,gt),s("button",{class:"file__main","aria-expanded":e.expanded.has(t.file),onClick:r=>e.toggleExpanded(t.file)},[s("span",{class:T(["file__caret",{"file__caret--open":e.expanded.has(t.file)}])},"▸",2),s("code",mt,o(t.file),1),s("span",bt,o(t.count)+" "+o(e.tool?.verb)+o(t.count===1?"":"s"),1),s("span",wt,"−"+o(e.stats(t.diff).removed),1),e.stats(t.diff).added?(a(),i("span",St,"+"+o(e.stats(t.diff).added),1)):v("v-if",!0),e.done.has(t.file)?(a(),i("span",xt,"✓ changed")):v("v-if",!0)],8,yt)]),e.expanded.has(t.file)&&t.diff?(a(),te(e.DiffView,{key:0,diff:t.diff,lang:e.langOf(t.file)},null,8,["diff","lang"])):v("v-if",!0)],2))),128))]),e.shown<e.files.length?(a(),i("div",Ct,[s("button",{class:"btn",onClick:c[4]||(c[4]=t=>e.shown+=e.PAGE)}," Show more ("+o(e.files.length-e.shown)+" left) ",1),s("button",{class:"btn",onClick:c[5]||(c[5]=t=>e.shown=e.files.length)},"Show all")])):v("v-if",!0)],64)):v("v-if",!0)])):v("v-if",!0),e.history.length?(a(),i("section",jt,[c[12]||(c[12]=s("h2",null,"Recent cleanups",-1)),s("ul",Nt,[(a(!0),i(_,null,P(e.history,t=>(a(),i("li",{key:t.dir,class:"history__row"},[s("span",null,[s("strong",null,o(e.tools.find(r=>r.id===t.tool)?.title??t.tool),1),s("span",Ot," · "+o(t.files)+" file"+o(t.files===1?"":"s")+" · "+o(e.when(t.createdAt)),1)]),s("button",{class:"btn btn--small",onClick:r=>e.undo(t.dir)},"Undo",8,Pt)]))),128))])])):v("v-if",!0),e.browsing?(a(),te(e.FolderBrowser,{key:7,start:e.project||p.status?.cwd||"",mode:"folder",title:"Choose the project folder",onClose:c[6]||(c[6]=t=>e.browsing=!1),onConfirm:e.setProject},null,8,["start"])):v("v-if",!0)])}const Dt=oe(Ae,[["render",Et],["__scopeId","data-v-70a493ad"],["__file","C:/work/NPM/devtoolz/ui/src/modules/cleanup/CleanupPage.vue"]]);export{Dt as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.diff[data-v-fab0cc77]{overflow:auto;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;line-height:1.6;max-height:460px}.hunk[data-v-fab0cc77]{min-width:max-content}.hunk__head[data-v-fab0cc77]{padding:2px 12px;background:var(--accent-soft);color:var(--accent);font-size:11px}.row[data-v-fab0cc77]{display:flex}.row--add[data-v-fab0cc77]{background:color-mix(in srgb,var(--ok) 16%,transparent)}.row--del[data-v-fab0cc77]{background:color-mix(in srgb,var(--danger) 16%,transparent)}.row__no[data-v-fab0cc77]{flex:none;width:4ch;padding:0 6px;color:var(--muted);text-align:right;user-select:none}.row__sign[data-v-fab0cc77]{flex:none;width:2ch;color:var(--muted);user-select:none}.row--add .row__sign[data-v-fab0cc77]{color:var(--ok)}.row--del .row__sign[data-v-fab0cc77]{color:var(--danger)}.row__text[data-v-fab0cc77]{white-space:pre;padding-right:16px}.tok[data-v-fab0cc77]{color:var(--light)}@media(prefers-color-scheme:dark){.tok[data-v-fab0cc77]{color:var(--dark)}}.page[data-v-70a493ad]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-70a493ad]{padding:18px 14px 40px}}.page__head p[data-v-70a493ad]{margin-top:4px}.project[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.project code[data-v-70a493ad]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}.block[data-v-70a493ad]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-70a493ad]{font-size:12px}.link[data-v-70a493ad]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.options[data-v-70a493ad]{display:flex;flex-direction:column;gap:12px}.textarea[data-v-70a493ad]{padding:8px 12px;border:1px solid var(--border);border-radius:9px;background:var(--surface);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.textarea[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.toolbar[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.search[data-v-70a493ad]{width:260px}.spacer[data-v-70a493ad]{flex:1}.actions[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.skipped[data-v-70a493ad]{margin:8px 0 0;padding-left:20px;font-size:12px}.files[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.file[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;padding:4px 12px 8px;border:1px solid var(--border);border-radius:9px}.file--done[data-v-70a493ad]{opacity:.6}.file__row[data-v-70a493ad]{display:flex;align-items:center;gap:12px}.file__main[data-v-70a493ad]{display:flex;flex:1;align-items:center;gap:8px;min-width:0;padding:8px 0;border:0;background:transparent;text-align:left;cursor:pointer}.file__main[data-v-70a493ad]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.file__caret[data-v-70a493ad]{flex:none;color:var(--muted);transition:transform .15s}.file__caret--open[data-v-70a493ad]{transform:rotate(90deg)}.file__name[data-v-70a493ad]{flex:1;min-width:0;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.file__count[data-v-70a493ad]{flex:none;color:var(--muted);font-size:12px}.file__stat[data-v-70a493ad]{flex:none;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:11px}.file__stat--del[data-v-70a493ad]{color:var(--danger)}.file__stat--add[data-v-70a493ad]{color:var(--ok)}.file__done[data-v-70a493ad]{flex:none;color:var(--ok);font-size:12px}.results[data-v-70a493ad]{display:flex;flex-direction:column;gap:4px;margin:0;padding:0;list-style:none}.result[data-v-70a493ad]{display:flex;gap:12px;font-size:12px}.result--changed[data-v-70a493ad],.result--error[data-v-70a493ad],.result--refused[data-v-70a493ad]{color:var(--danger)}.history[data-v-70a493ad]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.history__row[data-v-70a493ad]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:8px 12px;border:1px solid var(--border);border-radius:9px}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as V,q as A,e as Q,I as D,r as g,a as W,o as s,c as l,h as n,t as u,A as I,i as y,l as v,s as X,n as z,B as L,x as U,g as Y,C as Z,D as $,f as ee,p as oe,E as P,j as B,F as E,b as N,k as T,z as te,v as ie}from"./index-D8H-zVzo.js";const ne=V({__name:"UiModal",props:{title:{type:String,required:!0},width:{type:String,required:!1,default:"820px"},fixedHeight:{type:Boolean,required:!1,default:!1}},emits:["close"],setup(f,{expose:o,emit:c}){o();const e=f,m=c,r=g();function t(b){b.key==="Escape"&&m("close")}A(()=>{window.addEventListener("keydown",t),document.body.style.overflow="hidden",r.value?.focus()}),Q(()=>{window.removeEventListener("keydown",t),document.body.style.overflow=""});const _={props:e,emit:m,dialog:r,onKey:t,Icon:D};return Object.defineProperty(_,"__isScriptSetup",{enumerable:!1,value:!0}),_}}),se=["aria-label"],ae={class:"dialog__head"},le={class:"dialog__title"},de={class:"dialog__body"},re={key:0,class:"dialog__foot"};function ce(f,o,c,e,m,r){return s(),l("div",{class:"overlay",onMousedown:o[1]||(o[1]=L(t=>e.emit("close"),["self"]))},[n("div",{ref:"dialog",class:z(["dialog",{"dialog--fixed":e.props.fixedHeight}]),style:X({"--dialog-width":e.props.width}),role:"dialog","aria-modal":"true","aria-label":e.props.title,tabindex:"-1"},[n("header",ae,[n("h2",le,u(e.props.title),1),I(f.$slots,"actions",{},void 0),n("button",{class:"btn btn--ghost btn--small","aria-label":"Close",onClick:o[0]||(o[0]=t=>e.emit("close"))},[y(e.Icon,{name:"close"})])]),n("div",de,[I(f.$slots,"default",{},void 0)]),f.$slots.footer?(s(),l("footer",re,[I(f.$slots,"footer",{},void 0)])):v("v-if",!0)],14,se)],32)}const fe=W(ne,[["render",ce],["__scopeId","data-v-8bd877a3"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiModal.vue"]]),me=V({__name:"FolderBrowser",props:{start:{type:String,required:!0},mode:{type:String,required:!1,default:"sources"},title:{type:String,required:!1,default:""}},emits:["close","confirm"],setup(f,{expose:o,emit:c}){o();const e=f,m=c,r=g(),t=g(e.start),_=g(!1),b=g(!1),C=g(""),k=g(new Set),S=g(),h=new Map,p=U(()=>r.value?.path.includes("\\")?"\\":"/"),O=U(()=>(r.value?.entries??[]).filter(i=>e.mode!=="folder"||i.kind==="dir")),R=U(()=>r.value?.entries.filter(i=>i.kind==="image").length??0);function w(i){const a=r.value?.path??"";return a.endsWith(p.value)?a+i:a+p.value+i}function M(i,a){const d=a.endsWith("\\")||a.endsWith("/")?a:a+p.value;return i!==a&&i.startsWith(d)}async function x(i){const a=r.value?.path;a!==void 0&&h.set(a,S.value?.scrollTop??0),b.value=!0,C.value="";try{const d=await Y.get(`/api/fs/list?path=${encodeURIComponent(i)}&hidden=${_.value?1:0}`);r.value=d,t.value=d.path;for(const F of[...h.keys()])M(F,d.path)&&h.delete(F);await Z(),S.value?.scrollTo({top:h.get(d.path)??0})}catch(d){C.value=d instanceof Error?d.message:String(d)}finally{b.value=!1}}function H(i){i.kind==="dir"&&x(w(i.name))}function j(i){const a=w(i.name),d=new Set(k.value);d.has(a)?d.delete(a):d.add(a),k.value=d}function G(i){i.kind==="dir"?H(i):e.mode==="image"?m("confirm",[w(i.name)]):j(i)}function K(){r.value&&m("confirm",[r.value.path])}function J(){m("confirm",[...k.value])}A(()=>{x(e.start)});const q={props:e,emit:m,listing:r,pathInput:t,showHidden:_,loading:b,failure:C,picked:k,list:S,positions:h,separator:p,entries:O,imageCount:R,join:w,isInside:M,load:x,enter:H,toggle:j,onRow:G,addCurrent:K,addPicked:J,get formatBytes(){return ee},get imageUrl(){return $},UiModal:fe,Icon:D};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}}),ue={class:"bar"},ve=["disabled"],ge=["value"],_e=["value"],be={class:"check muted"},he={key:0,class:"notice notice--error notice-inset"},ke=["aria-busy"],pe={key:0,class:"muted empty"},we=["checked","aria-label","onChange"],ye=["onClick"],Ce={key:0,class:"row__icon"},Se=["src"],xe={class:"row__name"},Ie={key:2,class:"muted"},Ue={key:1,class:"muted empty"},Be={class:"muted"},ze=["disabled"],Me=["disabled"];function He(f,o,c,e,m,r){return s(),oe(e.UiModal,{title:c.title||(c.mode==="folder"?"Choose a folder":c.mode==="image"?"Choose an image":"Add folders or images"),"fixed-height":"",onClose:o[8]||(o[8]=t=>e.emit("close"))},{footer:P(()=>[n("span",Be,u(e.imageCount)+" image"+u(e.imageCount===1?"":"s")+" here",1),o[13]||(o[13]=n("span",{class:"spacer"},null,-1)),c.mode!=="image"?(s(),l("button",{key:0,class:z(["btn",{"btn--primary":c.mode==="folder"}]),disabled:!e.listing,onClick:e.addCurrent},u(c.mode==="folder"?"Use this folder":"Add this folder"),11,ze)):v("v-if",!0),c.mode==="sources"?(s(),l("button",{key:1,class:"btn btn--primary",disabled:e.picked.size===0,onClick:e.addPicked}," Add "+u(e.picked.size)+" selected ",9,Me)):v("v-if",!0)]),default:P(()=>[n("div",ue,[n("button",{class:"btn btn--small",disabled:!e.listing?.parent,title:"Parent folder",onClick:o[0]||(o[0]=t=>e.listing?.parent&&e.load(e.listing.parent))},[y(e.Icon,{name:"up",size:15}),o[9]||(o[9]=B(" Up ",-1))],8,ve),n("button",{class:"btn btn--small",title:"Home folder",onClick:o[1]||(o[1]=t=>e.listing&&e.load(e.listing.home))},[y(e.Icon,{name:"home",size:15}),o[10]||(o[10]=B(" Home ",-1))]),n("button",{class:"btn btn--small",title:"Start folder",onClick:o[2]||(o[2]=t=>e.listing&&e.load(e.listing.cwd))}," Start folder "),(e.listing?.roots.length??0)>1?(s(),l("select",{key:0,class:"select bar__roots",value:e.listing?.root,"aria-label":"Drive",onChange:o[3]||(o[3]=t=>e.load(t.target.value))},[(s(!0),l(E,null,N(e.listing?.roots,t=>(s(),l("option",{key:t,value:t},u(t),9,_e))),128))],40,ge)):v("v-if",!0),n("form",{class:"bar__path",onSubmit:o[5]||(o[5]=L(t=>e.load(e.pathInput),["prevent"]))},[T(n("input",{"onUpdate:modelValue":o[4]||(o[4]=t=>e.pathInput=t),class:"input",spellcheck:"false","aria-label":"Folder path"},null,512),[[te,e.pathInput]]),o[11]||(o[11]=n("button",{class:"btn btn--small",type:"submit"},"Go",-1))],32),n("label",be,[T(n("input",{"onUpdate:modelValue":o[6]||(o[6]=t=>e.showHidden=t),type:"checkbox",onChange:o[7]||(o[7]=t=>e.listing&&e.load(e.listing.path))},null,544),[[ie,e.showHidden]]),o[12]||(o[12]=B(" Hidden ",-1))])]),e.failure?(s(),l("div",he,u(e.failure),1)):v("v-if",!0),n("div",{ref:"list",class:"list","aria-busy":e.loading},[e.listing&&e.entries.length===0?(s(),l("div",pe," This folder has no subfolders or images. ")):v("v-if",!0),(s(!0),l(E,null,N(e.entries,t=>(s(),l("div",{key:t.name,class:z(["row",{"row--picked":e.picked.has(e.join(t.name))}])},[c.mode==="sources"?(s(),l("input",{key:0,type:"checkbox",checked:e.picked.has(e.join(t.name)),"aria-label":`Select ${t.name}`,onChange:_=>e.toggle(t)},null,40,we)):v("v-if",!0),n("button",{class:"row__main",onClick:_=>e.onRow(t)},[t.kind==="dir"?(s(),l("span",Ce,[y(e.Icon,{name:"folder"})])):(s(),l("img",{key:1,class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(e.join(t.name),96)},null,8,Se)),n("span",xe,u(t.name),1),t.size!==void 0?(s(),l("span",Ie,u(e.formatBytes(t.size)),1)):v("v-if",!0)],8,ye)],2))),128)),e.listing?.truncated?(s(),l("div",Ue,"Only the first entries are shown.")):v("v-if",!0)],8,ke)]),_:1},8,["title"])}const qe=W(me,[["render",He],["__scopeId","data-v-93beb91d"],["__file","C:/work/NPM/devtoolz/ui/src/components/FolderBrowser.vue"]]);export{qe as F,fe as U};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.overlay[data-v-8bd877a3]{position:fixed;inset:0;z-index:20;display:flex;align-items:center;justify-content:center;padding:20px;overflow:hidden;background:var(--backdrop)}.dialog[data-v-8bd877a3]{background:var(--surface);border:1px solid var(--border);border-radius:12px;box-shadow:var(--shadow);box-shadow:var(--shadow-lg);display:flex;flex-direction:column;width:min(var(--dialog-width),100%);max-height:100%;outline:none}.dialog--fixed[data-v-8bd877a3]{height:min(680px,100%)}.dialog__head[data-v-8bd877a3],.dialog__foot[data-v-8bd877a3]{display:flex;align-items:center;gap:10px;padding:12px 16px}.dialog__head[data-v-8bd877a3]{border-bottom:1px solid var(--border)}.dialog__title[data-v-8bd877a3]{flex:1;font-size:16px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.dialog__body[data-v-8bd877a3]{flex:1;min-height:0;display:flex;flex-direction:column}.dialog__foot[data-v-8bd877a3]{border-top:1px solid var(--border)}.bar[data-v-93beb91d]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 16px}.bar__path[data-v-93beb91d]{display:flex;flex:1;gap:6px;min-width:200px}.bar__path .input[data-v-93beb91d]{flex:1;height:28px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.bar__roots[data-v-93beb91d]{height:28px}.notice-inset[data-v-93beb91d]{margin:0 16px 12px}.spacer[data-v-93beb91d]{flex:1}.list[data-v-93beb91d]{flex:1;min-height:0;padding:0 8px 8px;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.empty[data-v-93beb91d]{padding:24px;text-align:center}.row[data-v-93beb91d]{display:flex;align-items:center;gap:8px;padding:2px 8px;border-radius:9px}.row[data-v-93beb91d]:hover{background:var(--surface-2)}.row--picked[data-v-93beb91d]{background:var(--accent-soft)}.row__main[data-v-93beb91d]{display:flex;flex:1;align-items:center;gap:10px;min-width:0;padding:4px 0;border:0;background:transparent;text-align:left;cursor:pointer}.row__icon[data-v-93beb91d]{display:grid;place-items:center;width:40px;height:40px;color:var(--accent)}.row__thumb[data-v-93beb91d]{width:40px;height:40px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__name[data-v-93beb91d]{flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
|
|
@@ -1,4 +0,0 @@
|
|
|
1
|
-
import{d as oe,x as E,q as ce,I as ue,r as c,g as F,D as Ue,f as Me,a as ne,o as s,c as l,h as n,t as a,l as d,j as b,F as p,b as N,B as Xe,k as T,z as Y,i as U,n as te,v as fe,p as $,L as $e,M as pe,u as et,m as tt,w as ge,e as xe,J as De,K as ae,y as ot,s as Ve,N as Ne}from"./index-D8H-zVzo.js";import{U as he}from"./UiSegmented-CsTRUZoX.js";import{F as Oe}from"./FolderBrowser-Cdzt7edI.js";import{S as nt}from"./SourcePicker-xk00AG2e.js";const ke="devtoolz-ui.open-backup",we=30,st=oe({__name:"BackupsView",props:{cwd:{type:String,required:!0}},setup(f,{expose:t}){t();const i={restored:"restored","would-restore":"can be restored",modified:"changed since","missing-backup":"copy missing","damaged-backup":"copy damaged",error:"error"},e=c(""),m=c([]),g=c(),o=c(""),r=c(""),y=c(!1),S=c(!1),M=c(we),A=c(""),B=c(!1),z=E(()=>{const w=g.value?.counts;return w?w.modified+w["missing-backup"]+w["damaged-backup"]+w.error:0}),O=E(()=>g.value?.counts["would-restore"]??0),k=E(()=>g.value?.entries.slice(0,M.value)??[]);function v(w){const I=new Date(w);return Number.isNaN(I.getTime())?w:I.toLocaleString()}function C(w){return w==="would-restore"||w==="restored"?"good":w==="modified"?"warn":"bad"}function j(w){o.value=w instanceof Error?w.message:String(w)}async function R(){try{const w=await F.get("/api/image-batch/backups");e.value=w.root,m.value=w.backups}catch(w){j(w)}}async function P(w){o.value="",r.value="",S.value=!1,M.value=we;try{g.value=await F.get(`/api/image-batch/backup?dir=${encodeURIComponent(w)}`)}catch(I){g.value=void 0,j(I)}}function Z(w){const I=w?.[0]??A.value;B.value=!1,I.trim()!==""&&(A.value=I,P(I))}async function D(){const w=g.value;if(!w)return;const I=S.value?w.files:O.value;if(window.confirm(`Put back ${I} original file${I===1?"":"s"} from this backup?`+(S.value?" Files changed after the replacement will be overwritten too.":""))){y.value=!0;try{const H=await F.post("/api/image-batch/backup/restore",{dir:w.dir,force:S.value});r.value=`Restored ${H.counts.restored} file${H.counts.restored===1?"":"s"}.`,await P(w.dir)}catch(H){j(H)}finally{y.value=!1}}}async function K(w){if(window.confirm("Delete this backup for good? The saved originals cannot be recovered afterwards."))try{await F.post("/api/image-batch/backup/delete",{dir:w}),r.value="The backup was deleted.",g.value?.dir===w&&(g.value=void 0),await R()}catch(I){j(I)}}ce(async()=>{await R();try{const w=localStorage.getItem(ke);w&&(localStorage.removeItem(ke),await P(w))}catch{g.value=void 0}});const q={OPEN_KEY:ke,PAGE:we,LABELS:i,root:e,rows:m,detail:g,failure:o,note:r,busy:y,force:S,shown:M,customDir:A,browsing:B,problems:z,restorable:O,visible:k,when:v,tone:C,fail:j,load:R,open:P,openCustom:Z,restore:D,remove:K,get formatBytes(){return Me},get imageUrl(){return Ue},FolderBrowser:Oe,Icon:ue};return Object.defineProperty(q,"__isScriptSetup",{enumerable:!1,value:!0}),q}}),lt={class:"view"},it={key:0,class:"card block"},at={key:0,class:"notice"},rt={key:1,class:"notice notice--error"},dt={key:2,class:"muted"},ct={class:"list"},ut={class:"item__main"},ft={class:"muted"},vt=["title"],mt={class:"item__actions"},pt=["onClick"],gt=["onClick"],ht={class:"custom"},bt=["disabled"],_t={key:1,class:"card block"},yt={class:"head"},kt={class:"muted"},wt={class:"item__path"},St={key:0,class:"notice"},Ct={key:1,class:"notice notice--error"},Vt={class:"chips"},xt={key:2,class:"notice notice--warn"},Ot={class:"actions"},Et=["disabled"],zt={key:0,class:"check"},Bt={class:"rows"},jt=["src"],Nt=["src"],Tt={class:"row__text"},At=["title"],It={class:"muted small"},Ut={key:0,class:"small row__message"},Mt={key:3,class:"actions"},Dt={key:4,class:"muted small"};function qt(f,t,i,e,m,g){return s(),l("div",lt,[e.detail?(s(),l("section",_t,[n("div",yt,[n("div",null,[n("h2",null,"Backup of "+a(e.when(e.detail.createdAt)),1),n("p",kt,a(e.detail.files)+" file"+a(e.detail.files===1?"":"s")+" · "+a(e.formatBytes(e.detail.bytesBefore))+" originals, "+a(e.formatBytes(e.detail.bytesAfter))+" after the replacement ",1),n("code",wt,a(e.detail.dir),1)]),n("button",{class:"btn btn--ghost",onClick:t[3]||(t[3]=o=>(e.detail=void 0,e.load()))},[U(e.Icon,{name:"close",size:16}),t[15]||(t[15]=b(" Back to the list ",-1))])]),e.note?(s(),l("p",St,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",Ct,a(e.failure),1)):d("v-if",!0),n("div",Vt,[(s(!0),l(p,null,N(e.detail.counts,(o,r)=>T((s(),l("span",{key:r,class:te(["chip",`chip--${e.tone(r)}`])},a(o)+" "+a(e.LABELS[r]),3)),[[$e,o>0]])),128))]),e.detail.counts.modified?(s(),l("p",xt,a(e.detail.counts.modified)+" file"+a(e.detail.counts.modified===1?" was":"s were")+" changed after the replacement. They are left alone unless you tick the box below. ",1)):d("v-if",!0),n("div",Ot,[n("button",{class:"btn btn--primary",disabled:e.busy||e.restorable===0&&!e.force,onClick:e.restore}," Restore "+a(e.force?"everything":`${e.restorable} file${e.restorable===1?"":"s"}`),9,Et),e.detail.counts.modified?(s(),l("label",zt,[T(n("input",{"onUpdate:modelValue":t[4]||(t[4]=o=>e.force=o),type:"checkbox"},null,512),[[fe,e.force]]),t[16]||(t[16]=b(" Overwrite files that changed since ",-1))])):d("v-if",!0),n("button",{class:"btn btn--danger",onClick:t[5]||(t[5]=o=>e.remove(e.detail.dir))},"Delete this backup")]),n("ul",Bt,[(s(!0),l(p,null,N(e.visible,o=>(s(),l("li",{key:o.path,class:"row"},[n("img",{class:"row__thumb",loading:"lazy",alt:"Original",src:e.imageUrl(o.backup,120)},null,8,jt),t[17]||(t[17]=n("span",{class:"row__arrow muted"},"⇄",-1)),n("img",{class:"row__thumb",loading:"lazy",alt:"Now",src:e.imageUrl(o.path,120)},null,8,Nt),n("div",Tt,[n("span",{class:"row__name",title:o.path},a(o.path),9,At),n("span",It," original "+a(e.formatBytes(o.bytesBefore))+" · replaced with "+a(e.formatBytes(o.bytesAfter)),1),o.message?(s(),l("span",Ut,a(o.message),1)):d("v-if",!0)]),n("span",{class:te(["chip",`chip--${e.tone(o.status)}`])},a(e.LABELS[o.status]),3)]))),128))]),e.detail&&e.shown<e.detail.entries.length?(s(),l("div",Mt,[n("button",{class:"btn",onClick:t[6]||(t[6]=o=>e.shown+=e.PAGE)}," Show more ("+a(e.detail.entries.length-e.shown)+" left) ",1),n("button",{class:"btn",onClick:t[7]||(t[7]=o=>e.shown=e.detail.entries.length)}," Show all ("+a(e.detail.entries.length)+") ",1)])):d("v-if",!0),e.problems?(s(),l("p",Dt," The left picture is the saved original, the right one is the file as it is now on disk. ")):d("v-if",!0)])):(s(),l("section",it,[t[14]||(t[14]=n("div",{class:"head"},[n("div",null,[n("h2",null,"Backups"),n("p",{class:"muted"}," “Replace the originals” copies each file here first, so a replacement can be undone. ")])],-1)),e.note?(s(),l("p",at,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",rt,a(e.failure),1)):d("v-if",!0),e.rows.length===0?(s(),l("p",dt,[t[9]||(t[9]=b(" No backups in ",-1)),n("code",null,a(e.root),1),t[10]||(t[10]=b(" yet. ",-1))])):d("v-if",!0),n("ul",ct,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.dir,class:"item"},[n("div",ut,[n("strong",null,a(e.when(o.createdAt)),1),n("span",ft,a(o.files)+" file"+a(o.files===1?"":"s")+" · "+a(e.formatBytes(o.bytesBefore))+" → "+a(e.formatBytes(o.bytesAfter)),1),n("code",{class:"item__path",title:o.dir},a(o.dir),9,vt)]),n("div",mt,[n("button",{class:"btn btn--small",onClick:r=>e.open(o.dir)},"Open",8,pt),n("button",{class:"btn btn--small btn--danger",onClick:r=>e.remove(o.dir)},"Delete",8,gt)])]))),128))]),n("div",ht,[t[12]||(t[12]=n("h3",null,"Another backup folder",-1)),t[13]||(t[13]=n("p",{class:"muted small"},[b(" If you chose your own backup folder, pick the dated folder inside it (the one with a "),n("code",null,"journal.json"),b("). ")],-1)),n("form",{class:"pathrow",onSubmit:t[2]||(t[2]=Xe(o=>e.openCustom(),["prevent"]))},[T(n("input",{"onUpdate:modelValue":t[0]||(t[0]=o=>e.customDir=o),class:"input",spellcheck:"false",placeholder:"Path to the dated backup folder"},null,512),[[Y,e.customDir]]),n("button",{class:"btn",type:"button",onClick:t[1]||(t[1]=o=>e.browsing=!0)},[U(e.Icon,{name:"folder",size:16}),t[11]||(t[11]=b(" Browse ",-1))]),n("button",{class:"btn btn--primary",type:"submit",disabled:e.customDir.trim()===""}," Open ",8,bt)],32)])])),e.browsing?(s(),$(e.FolderBrowser,{key:2,start:i.cwd,mode:"folder",title:"Choose the backup folder",onClose:t[8]||(t[8]=o=>e.browsing=!1),onConfirm:e.openCustom},null,8,["start"])):d("v-if",!0)])}const Lt=ne(st,[["render",qt],["__scopeId","data-v-276a3888"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/BackupsView.vue"]]),be=Symbol("image-batch-navigate"),Ee=Symbol("image-batch-project"),qe={cwd:"",name:"this project",home:""};function Pt(f,t){const i=f.split(/[\\/]/).filter(Boolean);return{cwd:f,home:t,name:i[i.length-1]??f}}const Rt=oe({__name:"SharpenSettings",props:tt({options:{type:Object,required:!0},manage:{type:Boolean,required:!1}},{modelValue:{type:Object,required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{}),m=et(f,"modelValue"),g=c([]),o=c(!1),r=E(()=>g.value.filter(O=>!O.error)),y=E(()=>g.value.find(O=>O.name===m.value.preset));function S(O){const k=O.fields??{};return Object.entries(k).map(([v,C])=>`${v} ${C}`).join(", ")}function M(O){m.value={...m.value,mode:O},O==="preset"&&!m.value.preset&&r.value[0]&&(m.value={...m.value,mode:O,preset:r.value[0].name})}function A(O,k){m.value={...m.value,fine:{...m.value.fine,[O]:k}}}function B(O){const k=i.options.sharpen.fine.find(v=>v.key===O);return k?`${k.range[0]}–${k.range[1]}`:""}ce(async()=>{try{g.value=await F.get("/api/image-batch/sharpen-presets")}catch{g.value=[]}});const z={props:i,navigate:e,state:m,presets:g,fineOpen:o,usable:r,chosen:y,describe:S,setMode:M,setFine:A,rangeText:B,UiSegmented:he};return Object.defineProperty(z,"__isScriptSetup",{enumerable:!1,value:!0}),z}}),Ft={class:"sharpen"},Jt={key:0,class:"grid"},Ht={class:"field"},Wt=["value"],Gt=["value"],Kt={key:1,class:"hint muted"},Qt={class:"grid"},Yt={class:"field"},Zt=["value"],Xt=["value"],$t={class:"field"},eo=["value"],to=["value"],oo={key:0,class:"grid"},no={class:"muted"},so=["value","onInput"];function lo(f,t,i,e,m,g){return s(),l("div",Ft,[U(e.UiSegmented,{"model-value":e.state.mode,label:"Sharpening",options:[{value:"none",label:"None"},{value:"preset",label:"Saved preset"},{value:"custom",label:"Custom"}],"onUpdate:modelValue":e.setMode},null,8,["model-value"]),e.state.mode==="preset"?(s(),l("div",Jt,[n("label",Ht,[t[5]||(t[5]=n("span",null,"Preset",-1)),n("select",{class:"select",value:e.state.preset,onChange:t[0]||(t[0]=o=>e.state={...e.state,preset:o.target.value})},[(s(!0),l(p,null,N(e.usable,o=>(s(),l("option",{key:o.name,value:o.name},a(o.name)+" · "+a(o.scope),9,Gt))),128))],40,Wt)]),i.manage?(s(),l("button",{key:0,class:"link",onClick:t[1]||(t[1]=o=>e.navigate("sharpen"))},"Manage presets")):d("v-if",!0),e.chosen?(s(),l("p",Kt,[e.chosen.description?(s(),l(p,{key:0},[b(a(e.chosen.description)+" — ",1)],64)):d("v-if",!0),b(" "+a(e.describe(e.chosen)),1)])):d("v-if",!0)])):d("v-if",!0),e.state.mode==="custom"?(s(),l(p,{key:1},[n("div",Qt,[n("label",Yt,[t[6]||(t[6]=n("span",null,"Sharpen for",-1)),n("select",{class:"select",value:e.state.for,onChange:t[2]||(t[2]=o=>e.state={...e.state,for:o.target.value})},[(s(!0),l(p,null,N(i.options.sharpen.targets,o=>(s(),l("option",{key:o,value:o},a(o),9,Xt))),128))],40,Zt)]),n("label",$t,[t[7]||(t[7]=n("span",null,"Amount",-1)),n("select",{class:"select",value:e.state.amount,onChange:t[3]||(t[3]=o=>e.state={...e.state,amount:o.target.value})},[(s(!0),l(p,null,N(i.options.sharpen.amounts,o=>(s(),l("option",{key:o,value:o},a(o),9,to))),128))],40,eo)])]),n("button",{class:"link",onClick:t[4]||(t[4]=o=>e.fineOpen=!e.fineOpen)},a(e.fineOpen?"Hide":"Show")+" fine settings ",1),e.fineOpen?(s(),l("div",oo,[(s(!0),l(p,null,N(i.options.sharpen.fine,o=>(s(),l("label",{key:o.key,class:"field"},[n("span",null,[b(a(o.key)+" ",1),n("small",no,"("+a(e.rangeText(o.key))+")",1)]),n("input",{class:"input",inputmode:"decimal",placeholder:"table value",value:e.state.fine[o.key],onInput:r=>e.setFine(o.key,r.target.value)},null,40,so)]))),128))])):d("v-if",!0)],64)):d("v-if",!0)])}const Le=ne(Rt,[["render",lo],["__scopeId","data-v-1a683036"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenSettings.vue"]]);function Pe(){return{mode:"none",preset:"",for:"screen",amount:"standard",fine:{radius:"",flat:"",jagged:"",threshold:""}}}function io(f){if(f.mode==="none")return;if(f.mode==="preset")return f.preset?{preset:f.preset}:void 0;const t={for:f.for,amount:f.amount};for(const[i,e]of Object.entries(f.fine))e.trim()!==""&&(t[i]=Number(e));return t}const Re=["widths","heights","size","longEdge","shortEdge","megapixels","percent"],ao={widths:[800,1600],heights:[600],size:"1920x1080",longEdge:[1600],shortEdge:[1080],megapixels:[2],percent:[50]};function ro(f,t,i){const e={...f};return i===void 0||i===""||Array.isArray(i)&&i.length===0||typeof i=="number"&&Number.isNaN(i)?delete e[t]:e[t]=i,e}function co(f){for(const t of Re)if(f[t]!==void 0)return t;return"original"}function uo(f,t){const i={...f};for(const e of Re)delete i[e];return delete i.matchOrientation,t!=="original"&&(i[t]=ao[t]),i}function fo(f,t){if(t==="original")return"";const i=f[t];return Array.isArray(i)?i.join(", "):String(i??"")}function vo(f){const t=f.split(/[,\s]+/).filter(Boolean);if(t.length===0)return[];const i=t.map(Number);return i.some(e=>!Number.isFinite(e))?void 0:i}function Te(f){const t=Pe();if(f==null)return{state:t,lossy:!1};if(typeof f=="string")return{state:{...t,mode:"preset",preset:f},lossy:!1};if(typeof f!="object"||Array.isArray(f))return{state:t,lossy:!0};const i=f;if(typeof i.preset=="string")return Object.keys(i).filter(g=>g!=="preset").length===0?{state:{...t,mode:"preset",preset:i.preset},lossy:!1}:{state:{...t,mode:"preset",preset:i.preset},lossy:!0};const e={...t,mode:"custom"};typeof i.for=="string"&&(e.for=i.for),typeof i.amount=="string"&&(e.amount=i.amount);for(const m of["radius","flat","jagged","threshold"])i[m]!==void 0&&(e.fine[m]=String(i[m]));return{state:e,lossy:!1}}function Ae(f){if(f.mode==="none")return;if(f.mode==="preset")return f.preset||void 0;const t={for:f.for,amount:f.amount};for(const[i,e]of Object.entries(f.fine))e.trim()!==""&&(t[i]=Number(e));return t}function mo(){return{name:"New config",outputs:[{id:"responsive",widths:[400,800,1200],formats:["webp","jpg"],quality:"high"}]}}function po(f){return{id:`recipe-${f}`,widths:[800],formats:["webp"],quality:"high"}}const go=oe({__name:"RecipeForm",props:{modelValue:{type:Object,required:!0},options:{type:Object,required:!0},presetNames:{type:Array,required:!1},isDefaults:{type:Boolean,required:!1}},emits:["update:modelValue"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g={original:"Keep the original size",widths:"By width (px)",heights:"By height (px)",size:"Fit into a box",longEdge:"By the long side (px)",shortEdge:"By the short side (px)",megapixels:"By area (megapixels)",percent:"By percentage"},o=[{key:"metadata",label:"Metadata",options:["strip","keep","keep-icc"]},{key:"rotate",label:"Rotate (degrees)",options:["90","180","270"]}],r=[{key:"withoutEnlargement",label:"Never enlarge"},{key:"autoOrient",label:"Turn by EXIF orientation"},{key:"grayscale",label:"Grayscale"},{key:"flip",label:"Flip vertically"},{key:"flop",label:"Mirror horizontally"}],y=c(""),S=c(!1),M=c(!1),A=c(!1),B=c(Te(e.modelValue.sharpen).state),z=E(()=>co(e.modelValue)),O=E(()=>Array.isArray(e.modelValue.formats)?e.modelValue.formats:void 0),k=E(()=>e.modelValue.formats!==void 0&&O.value===void 0),v=E(()=>e.modelValue.quality),C=E(()=>v.value!==void 0&&typeof v.value=="object"),j=E(()=>{const u=v.value;return u===void 0?"":typeof u=="number"?"custom":String(u)}),R=E(()=>typeof e.modelValue.name=="string"?e.modelValue.name:""),P=E(()=>e.modelValue.maxBytes===void 0?"":String(e.modelValue.maxBytes)),Z=E(()=>{const u=e.modelValue.sharpen;return u!==void 0&&typeof u!="string"&&typeof u!="object"});function D(u,_){m("update:modelValue",ro(e.modelValue,u,_))}function K(){y.value=fo(e.modelValue,z.value),S.value=!1}ge(z,K,{immediate:!0}),ge(()=>e.modelValue.sharpen,u=>{const _=Te(u);A.value=_.lossy,JSON.stringify(Ae(B.value))!==JSON.stringify(u)&&(B.value=_.state)},{immediate:!0});function q(u){m("update:modelValue",uo(e.modelValue,u.target.value))}function w(u){y.value=u;const _=vo(u);S.value=_===void 0,_&&_.length>0&&z.value!=="original"&&z.value!=="size"&&D(z.value,_)}function I(u){const _=O.value??[];D("formats",_.includes(u)?_.filter(X=>X!==u):[..._,u])}function J(u){u===""?D("quality",void 0):u==="custom"?D("quality",82):D("quality",u)}function H(u){const _=u.trim();_===""?D("maxBytes",void 0):D("maxBytes",/^\d+$/.test(_)?Number(_):_)}function re(u){B.value=u,D("sharpen",Ae(u))}function ee(u){const _=e.modelValue[u];return _===void 0?"":String(_)}function Q(u,_){D(u,_===""?void 0:_==="true")}function de(u){D("name",(R.value||"{dir}/{name}")+"{"+u+"}")}function W(u){return"{"+u+"}"}const G={props:e,emit:m,METHOD_LABELS:g,ADVANCED_SELECTS:o,ADVANCED_FLAGS:r,draft:y,draftError:S,advancedOpen:M,sharpenLossy:A,sharpenState:B,method:z,formatsList:O,formatsComplex:k,qualityValue:v,qualityComplex:C,qualityChoice:j,template:R,maxBytesText:P,sharpenMissing:Z,update:D,syncDraft:K,changeMethod:q,changeValues:w,toggleFormat:I,changeQuality:J,changeMaxBytes:H,changeSharpen:re,triState:ee,setTriState:Q,insertToken:de,tokenLabel:W,SharpenSettings:Le};return Object.defineProperty(G,"__isScriptSetup",{enumerable:!1,value:!0}),G}}),ho={class:"recipe"},bo={key:0,class:"grid"},_o={class:"field"},yo=["value"],ko={key:0,class:"field"},wo=["value"],So=["value"],Co={class:"group"},Vo={class:"grid"},xo={class:"field"},Oo=["value"],Eo=["value"],zo={key:0,class:"field"},Bo=["value"],jo={key:1,class:"field"},No=["value"],To={key:2,class:"field"},Ao=["value"],Io=["value"],Uo={key:0,class:"check"},Mo=["checked"],Do={class:"group"},qo={key:0,class:"notice notice--warn"},Lo={key:1,class:"pills"},Po=["checked","onChange"],Ro={key:0,class:"muted small"},Fo={class:"grid"},Jo={key:0,class:"field"},Ho=["value"],Wo=["value"],Go={key:1,class:"field"},Ko=["value"],Qo={key:2,class:"notice notice--warn"},Yo={class:"field"},Zo=["value"],Xo={class:"group"},$o=["value","placeholder"],en={class:"pills"},tn=["onClick"],on={class:"group"},nn={key:0,class:"notice notice--warn"},sn={class:"group"},ln={key:0,class:"grid"},an=["value","onChange"],rn=["value"],dn=["value","onChange"],cn={class:"field"},un=["value"],fn={class:"field"},vn=["value"];function mn(f,t,i,e,m,g){return s(),l("div",ho,[i.isDefaults?d("v-if",!0):(s(),l("div",bo,[n("label",_o,[t[13]||(t[13]=n("span",null,"Recipe name",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.id??""),onInput:t[0]||(t[0]=o=>e.update("id",o.target.value))},null,40,yo)]),i.presetNames&&i.presetNames.length?(s(),l("label",ko,[t[15]||(t[15]=n("span",null,"Based on preset",-1)),n("select",{class:"select",value:String(i.modelValue.preset??""),onChange:t[1]||(t[1]=o=>e.update("preset",o.target.value))},[t[14]||(t[14]=n("option",{value:""},"None",-1)),(s(!0),l(p,null,N(i.presetNames,o=>(s(),l("option",{key:o,value:o},a(o),9,So))),128))],40,wo)])):d("v-if",!0)])),n("div",Co,[t[21]||(t[21]=n("h4",null,"Size",-1)),n("div",Vo,[n("label",xo,[t[16]||(t[16]=n("span",null,"Method",-1)),n("select",{class:"select",value:e.method,onChange:e.changeMethod},[(s(!0),l(p,null,N(i.options.sizeMethods,o=>(s(),l("option",{key:o,value:o},a(e.METHOD_LABELS[o]),9,Eo))),128))],40,Oo)]),e.method==="size"?(s(),l("label",zo,[t[17]||(t[17]=n("span",null,"Box (width × height)",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.size??""),onInput:t[2]||(t[2]=o=>e.update("size",o.target.value))},null,40,Bo)])):e.method!=="original"?(s(),l("label",jo,[t[18]||(t[18]=n("span",null,"Values (comma-separated)",-1)),n("input",{class:te(["input",{"input--bad":e.draftError}]),spellcheck:"false",value:e.draft,onInput:t[3]||(t[3]=o=>e.changeValues(o.target.value))},null,42,No)])):d("v-if",!0),e.method==="size"?(s(),l("label",To,[t[19]||(t[19]=n("span",null,"How it fills the box",-1)),n("select",{class:"select",value:String(i.modelValue.fit??"inside"),onChange:t[4]||(t[4]=o=>e.update("fit",o.target.value))},[(s(!0),l(p,null,N(i.options.fitModes,o=>(s(),l("option",{key:o,value:o},a(o),9,Io))),128))],40,Ao)])):d("v-if",!0)]),e.method==="size"?(s(),l("label",Uo,[n("input",{type:"checkbox",checked:i.modelValue.matchOrientation===!0,onChange:t[5]||(t[5]=o=>e.update("matchOrientation",o.target.checked||void 0))},null,40,Mo),t[20]||(t[20]=b(" Turn the box around for portrait images ",-1))])):d("v-if",!0)]),n("div",Do,[t[27]||(t[27]=n("h4",null,"Formats and quality",-1)),e.formatsComplex?(s(),l("p",qo," The formats of this recipe are set in a form the editor cannot show. Use the JSON tab. ")):(s(),l("div",Lo,[(s(!0),l(p,null,N(i.options.formats,o=>(s(),l("label",{key:o,class:te(["pill",{"pill--on":e.formatsList?.includes(o)}])},[n("input",{type:"checkbox",checked:e.formatsList?.includes(o),onChange:r=>e.toggleFormat(o)},null,40,Po),b(" "+a(o),1)],2))),128)),e.formatsList?d("v-if",!0):(s(),l("span",Ro,"none chosen — inherited from the defaults"))])),n("div",Fo,[e.qualityComplex?d("v-if",!0):(s(),l("label",Jo,[t[24]||(t[24]=n("span",null,"Quality",-1)),n("select",{class:"select",value:e.qualityChoice,onChange:t[6]||(t[6]=o=>e.changeQuality(o.target.value))},[t[22]||(t[22]=n("option",{value:""},"Default (high)",-1)),(s(!0),l(p,null,N(i.options.qualityLevels,o=>(s(),l("option",{key:o,value:o},a(o),9,Wo))),128)),t[23]||(t[23]=n("option",{value:"custom"},"A number…",-1))],40,Ho)])),e.qualityChoice==="custom"?(s(),l("label",Go,[t[25]||(t[25]=n("span",null,"Quality (1–100)",-1)),n("input",{class:"input",inputmode:"numeric",value:String(i.modelValue.quality),onInput:t[7]||(t[7]=o=>e.update("quality",Number(o.target.value)))},null,40,Ko)])):d("v-if",!0),e.qualityComplex?(s(),l("p",Qo," Quality is set per format here. Use the JSON tab to change it. ")):d("v-if",!0),n("label",Yo,[t[26]||(t[26]=n("span",null,"Largest file size",-1)),n("input",{class:"input",spellcheck:"false",placeholder:"e.g. 200KB (optional)",value:e.maxBytesText,onInput:t[8]||(t[8]=o=>e.changeMaxBytes(o.target.value))},null,40,Zo)])])]),n("div",Xo,[t[28]||(t[28]=n("h4",null,"File names",-1)),n("input",{class:"input",spellcheck:"false",value:e.template,placeholder:i.options.defaultTemplates[e.method],"aria-label":"File name template",onInput:t[9]||(t[9]=o=>e.update("name",o.target.value))},null,40,$o),n("div",en,[(s(!0),l(p,null,N(i.options.templateVariables,o=>(s(),l("button",{key:o,class:"pill pill--button",onClick:r=>e.insertToken(o)},a(e.tokenLabel(o)),9,tn))),128))])]),n("div",on,[t[29]||(t[29]=n("h4",null,"Sharpening",-1)),e.sharpenLossy||e.sharpenMissing?(s(),l("p",nn," This sharpening combines a preset with extra values. Use the JSON tab to edit it. ")):(s(),$(e.SharpenSettings,{key:1,"model-value":e.sharpenState,options:i.options,"onUpdate:modelValue":e.changeSharpen},null,8,["model-value","options"]))]),n("div",sn,[n("button",{class:"link",onClick:t[10]||(t[10]=o=>e.advancedOpen=!e.advancedOpen)},a(e.advancedOpen?"Hide":"Show")+" advanced settings ",1),e.advancedOpen?(s(),l("div",ln,[(s(),l(p,null,N(e.ADVANCED_SELECTS,o=>n("label",{key:o.key,class:"field"},[n("span",null,a(o.label),1),n("select",{class:"select",value:o.key==="rotate"?String(i.modelValue.rotate??""):String(i.modelValue[o.key]??""),onChange:r=>e.update(o.key,o.key==="rotate"&&r.target.value?Number(r.target.value):r.target.value)},[t[30]||(t[30]=n("option",{value:""},"Default",-1)),(s(!0),l(p,null,N(o.options,r=>(s(),l("option",{key:r,value:r},a(r),9,rn))),128))],40,an)])),64)),(s(),l(p,null,N(e.ADVANCED_FLAGS,o=>n("label",{key:o.key,class:"field"},[n("span",null,a(o.label),1),n("select",{class:"select",value:e.triState(o.key),onChange:r=>e.setTriState(o.key,r.target.value)},[...t[31]||(t[31]=[n("option",{value:""},"Default",-1),n("option",{value:"true"},"Yes",-1),n("option",{value:"false"},"No",-1)])],40,dn)])),64)),n("label",cn,[t[32]||(t[32]=n("span",null,"Blur (sigma)",-1)),n("input",{class:"input",inputmode:"decimal",value:i.modelValue.blur===void 0?"":String(i.modelValue.blur),onInput:t[11]||(t[11]=o=>e.update("blur",o.target.value===""?void 0:Number(o.target.value)))},null,40,un)]),n("label",fn,[t[33]||(t[33]=n("span",null,"Background (#rrggbb)",-1)),n("input",{class:"input",spellcheck:"false",value:String(i.modelValue.background??""),onInput:t[12]||(t[12]=o=>e.update("background",o.target.value))},null,40,vn)])])):d("v-if",!0)])])}const pn=ne(go,[["render",mn],["__scopeId","data-v-92a49f1e"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/RecipeForm.vue"]]),gn=oe({__name:"ConfigEditor",props:{options:{type:Object,required:!0},initial:{type:null,required:!1},copyOf:{type:null,required:!1}},emits:["saved","cancel"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g=pe(Ee,qe),o=c(e.initial!==void 0),r=c(e.copyOf?structuredClone(e.copyOf.raw):mo()),y=c(e.initial?e.initial.name:e.copyOf?`${e.copyOf.name}-copy`:""),S=c(e.initial?.scope??"project"),M=c("form"),A=c(""),B=c(""),z=c(),O=c(""),k=c(!1),v=c(0);let C;const j=E(()=>Array.isArray(r.value.outputs)?r.value.outputs:[]),R=E(()=>r.value.defaults&&typeof r.value.defaults=="object"?r.value.defaults:{}),P=E(()=>r.value.presets&&typeof r.value.presets=="object"?Object.keys(r.value.presets):[]),Z=E(()=>{const h=[];return P.value.length&&h.push(`${P.value.length} preset(s)`),Array.isArray(r.value.match)&&r.value.match.length&&h.push(`${r.value.match.length} rule(s)`),r.value.placeholders&&h.push("placeholders"),h}),D=E(()=>(z.value?.lines??[]).join(`
|
|
2
|
-
`)),K=E(()=>!k.value&&y.value.trim()!==""&&z.value?.ok===!0&&B.value==="");function q(h){r.value=h}function w(h,V){const L={...r.value};V.trim()===""?delete L[h]:L[h]=V,q(L)}function I(h){const V={...r.value};Object.keys(h).length===0?delete V.defaults:V.defaults=h,q(V)}function J(h,V){const L=[...j.value];L[h]=V,q({...r.value,outputs:L})}function H(){q({...r.value,outputs:[...j.value,po(j.value.length+1)]}),v.value=j.value.length}function re(h){q({...r.value,outputs:j.value.filter((V,L)=>L!==h)}),v.value=Math.max(0,v.value-1)}function ee(h){const V=structuredClone(j.value[h]??{});typeof V.id=="string"&&(V.id=`${V.id}-copy`);const L=[...j.value];L.splice(h+1,0,V),q({...r.value,outputs:L}),v.value=h+1}function Q(h,V){const L=h+V;if(L<0||L>=j.value.length)return;const ve=[...j.value],[_e]=ve.splice(h,1);ve.splice(L,0,_e),q({...r.value,outputs:ve}),v.value=L}function de(h,V){return typeof h.id=="string"&&h.id?h.id:`Recipe ${V+1}`}function W(h){const V=[];for(const L of["widths","heights","longEdge","shortEdge","megapixels","percent"])Array.isArray(h[L])&&V.push(`${L} ${h[L].join(", ")}`);return typeof h.size=="string"&&V.push(`box ${h.size}`),Array.isArray(h.formats)&&V.push(h.formats.join("/")),V.join(" · ")}function G(h){A.value=h;try{const V=JSON.parse(h);if(V===null||typeof V!="object"||Array.isArray(V)){B.value="A config is a JSON object.";return}B.value="",r.value=V}catch(V){B.value=V instanceof Error?V.message:String(V)}}function u(h){if(h==="json"){A.value=JSON.stringify(r.value,null,2),B.value="",M.value="json";return}B.value||(M.value="form")}async function _(){try{z.value=await F.post("/api/image-batch/config/validate",{raw:r.value})}catch(h){z.value={ok:!1,error:h instanceof Error?h.message:String(h)}}}ge(r,()=>{clearTimeout(C),C=setTimeout(()=>{_()},350)},{deep:!0});async function X(h=!1){k.value=!0,O.value="";try{await F.post("/api/image-batch/config/save",{name:y.value,scope:S.value,raw:r.value,overwrite:h,...e.initial?{originalName:e.initial.name,originalScope:e.initial.scope}:{}}),m("saved",y.value)}catch(V){if(V instanceof De&&V.status===409&&V.body.exists===!0){if(window.confirm(`${V.message}. Replace it?`)){await X(!0);return}}else O.value=V instanceof Error?V.message:String(V)}finally{k.value=!1}}ce(async()=>{if(e.initial)try{const h=await F.get(`/api/image-batch/config?name=${encodeURIComponent(e.initial.name)}&scope=${e.initial.scope}`);r.value=h.raw}catch(h){O.value=h instanceof Error?h.message:String(h)}finally{o.value=!1}_()}),xe(()=>clearTimeout(C));const se={props:e,emit:m,project:g,loading:o,raw:r,name:y,scope:S,tab:M,jsonText:A,jsonError:B,check:z,failure:O,saving:k,openRecipe:v,get timer(){return C},set timer(h){C=h},outputs:j,defaults:R,presetNames:P,extras:Z,checkText:D,canSave:K,setRaw:q,setTitle:w,setDefaults:I,setOutput:J,addRecipe:H,removeRecipe:re,duplicateRecipe:ee,moveRecipe:Q,recipeTitle:de,recipeSummary:W,onJson:G,switchTab:u,validate:_,save:X,Icon:ue,UiSegmented:he,RecipeForm:pn};return Object.defineProperty(se,"__isScriptSetup",{enumerable:!1,value:!0}),se}}),hn={class:"card block"},bn={class:"head"},_n={key:0,class:"muted"},yn={class:"grid"},kn={class:"field"},wn={class:"field"},Sn={value:"project"},Cn={class:"field"},Vn=["value"],xn={class:"field"},On=["value"],En={key:0,class:"notice"},zn={class:"panel"},Bn={class:"panel__body"},jn={class:"recipes"},Nn={class:"panel__head"},Tn=["onClick"],An={class:"muted small"},In={class:"panel__actions"},Un=["disabled","onClick"],Mn=["disabled","onClick"],Dn=["onClick"],qn=["onClick"],Ln={key:0,class:"panel__body"},Pn=["value"],Rn={key:0,class:"notice notice--error"},Fn={key:0,class:"lines"},Jn={key:3,class:"notice notice--error"},Hn={class:"actions"},Wn=["disabled"];function Gn(f,t,i,e,m,g){return s(),l("section",hn,[n("div",bn,[n("h2",null,a(i.initial?`Edit ${i.initial.name}`:i.copyOf?"Copy of a config":"New config"),1),n("button",{class:"btn btn--ghost",onClick:t[0]||(t[0]=o=>e.emit("cancel"))},[U(e.Icon,{name:"close",size:16}),t[8]||(t[8]=b(" Close ",-1))])]),e.loading?(s(),l("p",_n,"Loading…")):(s(),l(p,{key:1},[n("div",yn,[n("label",kn,[t[9]||(t[9]=n("span",null,"File name",-1)),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.name=o),class:"input",spellcheck:"false",placeholder:"web"},null,512),[[Y,e.name]])]),n("label",wn,[t[11]||(t[11]=n("span",null,"Where to keep it",-1)),T(n("select",{"onUpdate:modelValue":t[2]||(t[2]=o=>e.scope=o),class:"select"},[n("option",Sn,"This project ("+a(e.project.name)+")",1),t[10]||(t[10]=n("option",{value:"global"},"All projects (your home folder)",-1))],512),[[ae,e.scope]])]),n("label",Cn,[t[12]||(t[12]=n("span",null,"Title",-1)),n("input",{class:"input",value:String(e.raw.name??""),onInput:t[3]||(t[3]=o=>e.setTitle("name",o.target.value))},null,40,Vn)]),n("label",xn,[t[13]||(t[13]=n("span",null,"Description",-1)),n("input",{class:"input",value:String(e.raw.description??""),onInput:t[4]||(t[4]=o=>e.setTitle("description",o.target.value))},null,40,On)])]),U(e.UiSegmented,{"model-value":e.tab,label:"Editor mode",options:[{value:"form",label:"Form"},{value:"json",label:"JSON"}],"onUpdate:modelValue":e.switchTab},null,8,["model-value"]),e.tab==="form"?(s(),l(p,{key:0},[e.extras.length?(s(),l("p",En," This config also has "+a(e.extras.join(", "))+". They are kept as they are; edit them in the JSON tab. ",1)):d("v-if",!0),n("details",zn,[t[14]||(t[14]=n("summary",null,"Defaults for every recipe",-1)),n("div",Bn,[U(e.RecipeForm,{"model-value":e.defaults,options:i.options,"preset-names":e.presetNames,"is-defaults":"","onUpdate:modelValue":e.setDefaults},null,8,["model-value","options","preset-names"])])]),n("div",jn,[(s(!0),l(p,null,N(e.outputs,(o,r)=>(s(),l("div",{key:r,class:te(["panel",{"panel--open":e.openRecipe===r}])},[n("div",Nn,[n("button",{class:"panel__title",onClick:y=>e.openRecipe=e.openRecipe===r?-1:r},[n("strong",null,a(e.recipeTitle(o,r)),1),n("span",An,a(e.recipeSummary(o)),1)],8,Tn),n("div",In,[n("button",{class:"btn btn--ghost btn--small",disabled:r===0,"aria-label":"Move up",onClick:y=>e.moveRecipe(r,-1)},[U(e.Icon,{name:"up",size:14})],8,Un),n("button",{class:"btn btn--ghost btn--small",disabled:r===e.outputs.length-1,"aria-label":"Move down",onClick:y=>e.moveRecipe(r,1)},[U(e.Icon,{name:"down",size:14})],8,Mn),n("button",{class:"btn btn--ghost btn--small","aria-label":"Duplicate recipe",onClick:y=>e.duplicateRecipe(r)},[U(e.Icon,{name:"copy",size:14})],8,Dn),n("button",{class:"btn btn--ghost btn--small btn--danger","aria-label":"Remove recipe",onClick:y=>e.removeRecipe(r)},[U(e.Icon,{name:"close",size:14})],8,qn)])]),e.openRecipe===r?(s(),l("div",Ln,[U(e.RecipeForm,{"model-value":o,options:i.options,"preset-names":e.presetNames,"onUpdate:modelValue":y=>e.setOutput(r,y)},null,8,["model-value","options","preset-names","onUpdate:modelValue"])])):d("v-if",!0)],2))),128))]),n("button",{class:"btn",onClick:e.addRecipe},[U(e.Icon,{name:"plus",size:16}),t[15]||(t[15]=b(" Add a recipe",-1))])],64)):(s(),l(p,{key:1},[n("textarea",{class:"json",spellcheck:"false",value:e.jsonText,"aria-label":"Config JSON",onInput:t[5]||(t[5]=o=>e.onJson(o.target.value))},null,40,Pn),e.jsonError?(s(),l("p",Rn,a(e.jsonError),1)):d("v-if",!0)],64)),e.check?(s(),l("div",{key:2,class:te(["check-panel",e.check.ok?"check-panel--ok":"check-panel--bad"]),role:"status"},[e.check.ok?(s(),l(p,{key:0},[t[16]||(t[16]=n("strong",null,"The config is valid.",-1)),e.check.lines?.length?(s(),l("pre",Fn,a(e.checkText),1)):d("v-if",!0)],64)):(s(),l(p,{key:1},[b(a(e.check.error),1)],64))],2)):d("v-if",!0),e.failure?(s(),l("p",Jn,a(e.failure),1)):d("v-if",!0),n("div",Hn,[n("button",{class:"btn btn--primary",disabled:!e.canSave,onClick:t[6]||(t[6]=o=>e.save(!1))},[U(e.Icon,{name:"save",size:15}),t[17]||(t[17]=b(" Save config ",-1))],8,Wn),n("button",{class:"btn",onClick:t[7]||(t[7]=o=>e.emit("cancel"))},"Cancel")])],64))])}const Kn=ne(gn,[["render",Gn],["__scopeId","data-v-6b6acd65"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConfigEditor.vue"]]),Qn=oe({__name:"ConfigsView",props:{options:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=c([]),e=c(""),m=c(""),g=c("list"),o=c(),r=c();async function y(){try{i.value=await F.get("/api/image-batch/configs")}catch(k){e.value=k instanceof Error?k.message:String(k)}}function S(){o.value=void 0,r.value=void 0,g.value="edit"}function M(k){o.value=k,r.value=void 0,g.value="edit"}async function A(k){try{const v=await F.get(`/api/image-batch/config?name=${encodeURIComponent(k.name)}&scope=${k.scope}`);o.value=void 0,r.value={name:k.name,raw:v.raw},g.value="edit"}catch(v){e.value=v instanceof Error?v.message:String(v)}}async function B(k){if(window.confirm(`Delete the config “${k.name}”? A .bak copy is kept next to it.`))try{await F.post("/api/image-batch/config/delete",{name:k.name,scope:k.scope}),m.value=`Deleted ${k.name}.`,await y()}catch(v){e.value=v instanceof Error?v.message:String(v)}}async function z(k){g.value="list",m.value=`Saved ${k}.`,await y()}ce(y);const O={rows:i,failure:e,note:m,mode:g,editing:o,copying:r,load:y,create:S,edit:M,duplicate:A,remove:B,saved:z,Icon:ue,ConfigEditor:Kn};return Object.defineProperty(O,"__isScriptSetup",{enumerable:!1,value:!0}),O}}),Yn={class:"view"},Zn={key:1,class:"card block"},Xn={class:"head"},$n={key:0,class:"notice"},es={key:1,class:"notice notice--error"},ts={key:2,class:"muted"},os={class:"list"},ns={class:"item__main"},ss={class:"item__title"},ls={class:"tag"},is={key:0,class:"tag"},as={key:0,class:"item__error"},rs={key:1,class:"muted"},ds=["title"],cs={class:"item__actions"},us=["onClick"],fs=["onClick"],vs=["onClick"];function ms(f,t,i,e,m,g){return s(),l("div",Yn,[e.mode==="edit"?(s(),$(e.ConfigEditor,{key:0,options:i.options,initial:e.editing?{name:e.editing.name,scope:e.editing.scope}:void 0,"copy-of":e.copying,onSaved:e.saved,onCancel:t[0]||(t[0]=o=>e.mode="list")},null,8,["options","initial","copy-of"])):(s(),l("section",Zn,[n("div",Xn,[t[2]||(t[2]=n("div",null,[n("h2",null,"Configs"),n("p",{class:"muted"}," A config is a reusable set of rules: sizes, formats, quality, names, sharpening. Apply it to any folder from the Convert tab. ")],-1)),n("button",{class:"btn btn--primary",onClick:e.create},[U(e.Icon,{name:"plus",size:16}),t[1]||(t[1]=b(" New config ",-1))])]),e.note?(s(),l("p",$n,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",es,a(e.failure),1)):d("v-if",!0),e.rows.length===0&&!e.failure?(s(),l("p",ts," No configs yet. Create the first one, or use quick settings on the Convert tab. ")):d("v-if",!0),n("ul",os,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.scope+o.name+o.path,class:"item"},[n("div",ns,[n("div",ss,[n("strong",null,a(o.name),1),n("span",ls,a(o.scope),1),o.kind!=="json"?(s(),l("span",is,"."+a(o.kind),1)):d("v-if",!0)]),o.error?(s(),l("p",as,a(o.error),1)):(s(),l("p",rs,[o.title?(s(),l(p,{key:0},[b(a(o.title)+" — ",1)],64)):d("v-if",!0),b(" "+a(o.recipes)+" recipe"+a(o.recipes===1?"":"s")+" ",1),o.rules?(s(),l(p,{key:1},[b(", "+a(o.rules)+" rule"+a(o.rules===1?"":"s"),1)],64)):d("v-if",!0),o.description?(s(),l(p,{key:2},[b(" · "+a(o.description),1)],64)):d("v-if",!0)])),n("code",{class:"item__path",title:o.path},a(o.path),9,ds)]),n("div",cs,[o.editable?(s(),l("button",{key:0,class:"btn btn--small",onClick:r=>e.edit(o)},"Edit",8,us)):d("v-if",!0),o.editable&&!o.error?(s(),l("button",{key:1,class:"btn btn--small",onClick:r=>e.duplicate(o)}," Duplicate ",8,fs)):d("v-if",!0),n("button",{class:"btn btn--small btn--danger",onClick:r=>e.remove(o)},"Delete",8,vs)])]))),128))])]))])}const ps=ne(Qn,[["render",ms],["__scopeId","data-v-2e26c039"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConfigsView.vue"]]),Ie=30,gs=oe({__name:"BatchResults",props:{report:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{});function m(){try{i.report.backupDir&&localStorage.setItem("devtoolz-ui.open-backup",i.report.backupDir)}catch{e("backups");return}e("backups")}const g=c(Ie),o={written:"written","up-to-date":"up to date",skipped:"skipped",conflict:"conflict","would-write":"would write","would-overwrite":"would overwrite",replaced:"replaced",kept:"kept original","already-processed":"already processed","would-replace":"would replace","would-keep":"would keep",error:"error"},r=new Set(["written","replaced","up-to-date"]),y=new Set(["error","conflict"]),S=new Set(["written","replaced","up-to-date","skipped","kept"]),M=E(()=>Object.entries(i.report.counts).filter(([,C])=>C>0)),A=E(()=>{const{bytesIn:C,bytesOut:j}=i.report;if(!(i.report.dryRun||C<=0||j<=0))return{bytes:C-j,percent:Math.round((1-j/C)*100)}}),B=E(()=>i.report.results.slice(0,g.value));function z(C){return r.has(C)?"good":y.has(C)?"bad":"neutral"}function O(C){if(C.before===void 0||C.bytes===void 0||C.before<=0)return"";const j=Math.round((C.bytes/C.before-1)*100);return`${j>0?"+":""}${j}%`}function k(C){return!i.report.dryRun&&S.has(C.status)&&C.status!=="skipped"}const v={props:i,navigate:e,openBackup:m,PAGE:Ie,shown:g,LABELS:o,GOOD:r,BAD:y,HAS_OUTPUT:S,counts:M,saved:A,rows:B,tone:z,delta:O,showsOutput:k,get formatBytes(){return Me},get imageUrl(){return Ue}};return Object.defineProperty(v,"__isScriptSetup",{enumerable:!1,value:!0}),v}}),hs={class:"card block"},bs={class:"head"},_s={class:"muted"},ys={class:"chips"},ks={key:0,class:"chip"},ws={key:1,class:"chip chip--good"},Ss={key:0,class:"notice"},Cs={key:1,class:"notice"},Vs={key:2,class:"muted small"},xs={key:3,class:"muted small"},Os={key:4,class:"errors"},Es={class:"rows"},zs=["src"],Bs=["src"],js={key:1,class:"row__thumb row__thumb--empty muted"},Ns={class:"row__text"},Ts=["title"],As={class:"muted small"},Is={key:0,class:"small row__message"},Us={class:"row__sizes"},Ms={key:0},Ds={key:1,class:"muted"},qs={key:2},Ls={key:5,class:"more"};function Ps(f,t,i,e,m,g){return s(),l("section",hs,[n("div",bs,[n("h2",null,a(i.report.dryRun?"Plan":"Result"),1),n("span",_s,[b(a(i.report.results.length)+" file"+a(i.report.results.length===1?"":"s")+" ",1),i.report.configLabel?(s(),l(p,{key:0},[b(" · config "+a(i.report.configLabel),1)],64)):d("v-if",!0)])]),n("div",ys,[(s(!0),l(p,null,N(e.counts,([o,r])=>(s(),l("span",{key:o,class:te(["chip",`chip--${e.tone(o)}`])},a(r)+" "+a(e.LABELS[o]),3))),128)),i.report.deduped?(s(),l("span",ks,a(i.report.deduped)+" merged (same result)",1)):d("v-if",!0),e.saved?(s(),l("span",ws,[b(" saved "+a(e.formatBytes(Math.max(e.saved.bytes,0)))+" ",1),e.saved.percent>0?(s(),l(p,{key:0},[b("(−"+a(e.saved.percent)+"%)",1)],64)):d("v-if",!0)])):d("v-if",!0)]),i.report.dryRun?(s(),l("p",Ss," This is a preview: nothing was written. Press “Convert” to do it. ")):d("v-if",!0),i.report.backupDir&&!i.report.dryRun?(s(),l("p",Cs,[t[2]||(t[2]=b(" Originals were copied to ",-1)),n("code",null,a(i.report.backupDir),1),t[3]||(t[3]=b(" first. ",-1)),n("button",{class:"link",onClick:e.openBackup},"View or restore this backup")])):d("v-if",!0),i.report.derived.length?(s(),l("p",Vs,a(i.report.derived.length)+" earlier result"+a(i.report.derived.length===1?" was":"s were")+" not treated as sources. ",1)):d("v-if",!0),i.report.vectors.length?(s(),l("p",xs,a(i.report.vectors.length)+" SVG file"+a(i.report.vectors.length===1?" was":"s were")+" left out of the replacement. ",1)):d("v-if",!0),i.report.failures.length?(s(),l("ul",Os,[(s(!0),l(p,null,N(i.report.failures,o=>(s(),l("li",{key:o.file},[n("code",null,a(o.file),1),b(" — "+a(o.message),1)]))),128))])):d("v-if",!0),n("ul",Es,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:`${o.sourceAbs}|${o.outputAbs}|${o.recipe}`,class:"row"},[n("img",{class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(o.sourceAbs,120)},null,8,zs),t[4]||(t[4]=n("span",{class:"row__arrow muted"},"→",-1)),e.showsOutput(o)?(s(),l("img",{key:0,class:"row__thumb",loading:"lazy",alt:"",src:e.imageUrl(o.outputAbs,120)},null,8,Bs)):(s(),l("span",js,a(i.report.dryRun?"plan":"—"),1)),n("div",Ns,[n("span",{class:"row__name",title:o.outputAbs},a(o.output),9,Ts),n("span",As,[b(" from "+a(o.source)+" · "+a(o.width)+"×"+a(o.height)+" · "+a(o.format)+" ",1),o.recipe?(s(),l(p,{key:0},[b(" · "+a(o.recipe),1)],64)):d("v-if",!0)]),o.message?(s(),l("span",Is,a(o.message),1)):d("v-if",!0)]),n("div",Us,[o.before!==void 0?(s(),l("span",Ms,a(e.formatBytes(o.before)),1)):d("v-if",!0),o.before!==void 0&&o.bytes!==void 0?(s(),l("span",Ds,"→")):d("v-if",!0),o.bytes!==void 0?(s(),l("strong",qs,a(e.formatBytes(o.bytes)),1)):d("v-if",!0),e.delta(o)?(s(),l("span",{key:3,class:te(["row__delta",{"row__delta--down":e.delta(o).startsWith("-")}])},a(e.delta(o)),3)):d("v-if",!0)]),n("span",{class:te(["chip",`chip--${e.tone(o.status)}`])},a(e.LABELS[o.status]),3)]))),128))]),e.shown<i.report.results.length?(s(),l("div",Ls,[n("button",{class:"btn",onClick:t[0]||(t[0]=o=>e.shown+=e.PAGE)}," Show more ("+a(i.report.results.length-e.shown)+" left) ",1),n("button",{class:"btn",onClick:t[1]||(t[1]=o=>e.shown=i.report.results.length)}," Show all ("+a(i.report.results.length)+") ",1)])):d("v-if",!0)])}const Rs=ne(gs,[["render",Ps],["__scopeId","data-v-7e5d47ea"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/BatchResults.vue"]]),Fs=oe({__name:"ConvertView",props:{cwd:{type:String,required:!0},options:{type:Object,required:!0}},setup(f,{expose:t}){t();const i=f,e=pe(be,()=>{}),m={original:"Keep the original size",widths:"By width (px)",heights:"By height (px)",size:"Fit into a box",longEdge:"By the long side (px)",shortEdge:"By the short side (px)",megapixels:"By area (megapixels)",percent:"By percentage"},g={original:"",widths:"e.g. 400, 800, 1200 — one file per size",heights:"e.g. 300, 600",size:"",longEdge:"e.g. 1600 — the same for landscape and portrait",shortEdge:"e.g. 1080",megapixels:"e.g. 2, 0.5",percent:"e.g. 50, 25"},o={name:"photo",ext:"jpg",orig:"photo.jpg",dir:"trips/2026",format:"webp",width:"800",height:"600",size:"800x600",long:"800",short:"600",mp:"0.48",percent:"50",scale:"2",index:"001",hash:"a1b2c3d4",date:"2026-10-08"},r=E(()=>i.options),y=c([]),S=c([]),M=c(!0),A=c(0),B=c("out"),z=c(""),O=c(!1),k=c("skip"),v=c(!0),C=c(!0),j=c(!1),R=c("quick"),P=c(""),Z=c(!1),D=c("widths"),K=c("800, 1600"),q=c("1920x1080"),w=c("inside"),I=c(!1),J=c(["webp"]),H=c(""),re=c("82"),ee=c(""),Q=c(""),de=c(Pe()),W=c("idle"),G=c({done:0,total:0}),u=c(""),_=c();let X;const se=E(()=>Z.value?D.value:"original"),h=E(()=>(r.value?.sizeMethods??[]).filter(x=>x!=="original")),V=E(()=>i.cwd.includes("\\")?"\\":"/"),L=E(()=>u.value.toLowerCase().includes("sharp")),ve=E(()=>y.value.find(x=>x.name===P.value)),_e=E(()=>G.value.total>0?Math.round(G.value.done/G.value.total*100):0),ye=E(()=>r.value?.defaultTemplates[se.value]??"{dir}/{name}.{format}"),Fe=E(()=>(Q.value.trim()||ye.value).replace(/\{([a-zA-Z]+)(?::(\d+))?\}/g,(le,ie)=>o[ie]??`{${ie}}`)),ze=E(()=>S.value.length===0?"Add at least one folder or image.":A.value===0&&S.value.length>0?"No images found in the added sources.":B.value==="out"&&z.value.trim()===""?"Choose the folder for the results.":R.value==="config"&&P.value===""?"Choose a saved config.":R.value==="quick"&&B.value!=="replace"&&J.value.length===0?"Pick at least one format.":""),Je=E(()=>ze.value===""&&W.value!=="running");function He(x){A.value=x?.total.files??0,S.value.length>0&&x===void 0&&(A.value=1)}function We(x){J.value=J.value.includes(x)?J.value.filter(le=>le!==x):[...J.value,x]}function Ge(x){return"{"+x+"}"}function Ke(x){z.value=x[0]??z.value,j.value=!1}function Qe(x){Q.value=(Q.value||ye.value)+`{${x}}`}function Ye(){const x=S.value[0];if(z.value!==""||!x)return;const le=x.replace(/[\\/]+$/,"");z.value=`${le}${V.value}converted`}function Be(){const x={sizeMethod:se.value};se.value==="size"?(x.box=q.value,x.fit=w.value,x.matchOrientation=I.value):se.value!=="original"&&(x.values=K.value.split(/[,\s]+/).filter(Boolean).map(Number)),x.formats=B.value==="replace"?["original"]:J.value,H.value==="custom"?x.quality=Number(re.value):H.value&&(x.quality=H.value),ee.value.trim()&&(x.maxBytes=ee.value.trim()),B.value!=="replace"&&Q.value.trim()&&(x.name=Q.value.trim());const le=io(de.value);return le&&(x.sharpen=le),x}async function Ze(x,le=!1){if(!(!x&&B.value==="replace"&&!window.confirm(`This rewrites ${A.value} original file${A.value===1?"":"s"} in place.`+(v.value?" The originals are copied to a backup folder first.":" No backup will be made.")+`
|
|
3
|
-
|
|
4
|
-
Continue?`))){X?.(),W.value="running",u.value="",_.value=void 0,G.value={done:0,total:0};try{const{jobId:ie}=await F.post("/api/image-batch/run",{paths:S.value,recursive:M.value,placement:B.value,out:z.value,flat:O.value,overwrite:k.value,backup:v.value,onlyIfSmaller:C.value,config:R.value==="config"?P.value:void 0,settings:R.value==="quick"?Be():void 0,dryRun:x,installSharp:le});X=ot(ie,{onProgress:me=>{G.value=me},onDone:me=>{_.value=me,W.value="done"},onFailed:me=>{u.value=me,W.value="failed"}})}catch(ie){u.value=ie instanceof Error?ie.message:String(ie),W.value="failed"}}}ce(async()=>{try{y.value=await F.get("/api/image-batch/configs")}catch(x){u.value=x instanceof Error?x.message:String(x),W.value="failed"}}),xe(()=>X?.());const je={props:i,navigate:e,METHOD_LABELS:m,METHOD_HINTS:g,SAMPLE_TOKENS:o,options:r,configs:y,sources:S,recursive:M,scanTotal:A,placement:B,outDir:z,flat:O,overwrite:k,backup:v,onlyIfSmaller:C,browsingOut:j,mode:R,configName:P,resize:Z,chosenMethod:D,sizeValues:K,box:q,fit:w,matchOrientation:I,formats:J,qualityLevel:H,qualityCustom:re,maxSize:ee,nameTemplate:Q,sharpen:de,phase:W,progress:G,failure:u,report:_,get stopWatching(){return X},set stopWatching(x){X=x},sizeMethod:se,resizeMethods:h,separator:V,needsSharp:L,chosenConfig:ve,percent:_e,defaultTemplate:ye,templateExample:Fe,problem:ze,canRun:Je,onScanned:He,toggleFormat:We,tokenLabel:Ge,chooseOut:Ke,insertToken:Qe,suggestOutDir:Ye,buildSettings:Be,run:Ze,FolderBrowser:Oe,Icon:ue,SourcePicker:nt,UiSegmented:he,BatchResults:Rs,SharpenSettings:Le};return Object.defineProperty(je,"__isScriptSetup",{enumerable:!1,value:!0}),je}}),Js={class:"view"},Hs={key:0,class:"notice notice--warn"},Ws={class:"card block"},Gs={class:"pathrow"},Ks={class:"check"},Qs={key:1,class:"muted"},Ys={class:"check"},Zs={class:"check"},Xs={key:3,class:"field narrow"},$s={class:"card block"},el={class:"head"},tl={key:0,class:"muted"},ol={class:"field narrow"},nl=["value","disabled"],sl={key:0,class:"muted"},ll={class:"group"},il={class:"check"},al={key:0,class:"muted small"},rl={key:1,class:"grid"},dl={class:"field"},cl=["value"],ul={key:0,class:"field"},fl={key:1,class:"field"},vl=["placeholder"],ml={key:2,class:"field"},pl=["value"],gl={key:2,class:"check"},hl={key:3,class:"muted small"},bl={class:"group"},_l={key:0,class:"muted small"},yl={key:1,class:"pills"},kl=["checked","onChange"],wl={class:"grid"},Sl={class:"field"},Cl=["value"],Vl={key:0,class:"field"},xl={class:"field"},Ol={key:0,class:"group"},El=["placeholder"],zl={class:"pills"},Bl=["onClick"],jl={class:"muted small"},Nl={class:"group"},Tl={class:"runbar"},Al=["disabled"],Il=["disabled"],Ul={key:0,class:"muted"},Ml={key:1,class:"card block",role:"status"},Dl={class:"progress"},ql={class:"muted"},Ll={key:2,class:"notice notice--error"};function Pl(f,t,i,e,m,g){return s(),l("div",Js,[e.options&&!e.options.sharp?(s(),l("div",Hs," The sharp image library is not installed yet. Previews are limited, and the first run will offer to install it. ")):d("v-if",!0),U(e.SourcePicker,{sources:e.sources,"onUpdate:sources":t[0]||(t[0]=o=>e.sources=o),recursive:e.recursive,"onUpdate:recursive":t[1]||(t[1]=o=>e.recursive=o),"scan-url":"/api/image-batch/scan",start:i.cwd,onScanned:e.onScanned},null,8,["sources","recursive","start"]),n("section",Ws,[t[35]||(t[35]=n("h2",null,"Where the results go",-1)),U(e.UiSegmented,{modelValue:e.placement,"onUpdate:modelValue":[t[2]||(t[2]=o=>e.placement=o),e.suggestOutDir],label:"Placement",options:[{value:"out",label:"A separate folder",hint:"the sources are not touched"},{value:"beside",label:"Next to each original",hint:"new files beside the sources"},{value:"replace",label:"Replace the originals",hint:"rewrites the files, with a backup"}]},null,8,["modelValue"]),e.placement==="out"?(s(),l(p,{key:0},[n("div",Gs,[T(n("input",{"onUpdate:modelValue":t[3]||(t[3]=o=>e.outDir=o),class:"input",spellcheck:"false",placeholder:"Folder for the results","aria-label":"Folder for the results"},null,512),[[Y,e.outDir]]),n("button",{class:"btn",onClick:t[4]||(t[4]=o=>e.browsingOut=!0)},[U(e.Icon,{name:"folder",size:16}),t[28]||(t[28]=b(" Browse ",-1))])]),n("label",Ks,[T(n("input",{"onUpdate:modelValue":t[5]||(t[5]=o=>e.flat=o),type:"checkbox"},null,512),[[fe,e.flat]]),t[29]||(t[29]=b(" Put everything in one folder (no subfolders) ",-1))])],64)):e.placement==="beside"?(s(),l("p",Qs," Each result is written next to its original, with the size or format in the name. ")):(s(),l(p,{key:2},[t[32]||(t[32]=n("p",{class:"notice notice--warn"}," Each original is overwritten with its converted version, keeping its own format. Use the preview first. ",-1)),n("label",Ys,[T(n("input",{"onUpdate:modelValue":t[6]||(t[6]=o=>e.backup=o),type:"checkbox"},null,512),[[fe,e.backup]]),t[30]||(t[30]=b(" Copy the originals to a backup folder first",-1))]),n("label",Zs,[T(n("input",{"onUpdate:modelValue":t[7]||(t[7]=o=>e.onlyIfSmaller=o),type:"checkbox"},null,512),[[fe,e.onlyIfSmaller]]),t[31]||(t[31]=b(" Replace a file only when the result is smaller ",-1))])],64)),e.placement!=="replace"?(s(),l("label",Xs,[t[34]||(t[34]=n("span",null,"If a result already exists",-1)),T(n("select",{"onUpdate:modelValue":t[8]||(t[8]=o=>e.overwrite=o),class:"select"},[...t[33]||(t[33]=[n("option",{value:"skip"},"Skip it",-1),n("option",{value:"overwrite"},"Overwrite it",-1),n("option",{value:"error"},"Stop and report it",-1)])],512),[[ae,e.overwrite]])])):d("v-if",!0)]),n("section",$s,[n("div",el,[t[36]||(t[36]=n("h2",null,"What to do",-1)),U(e.UiSegmented,{modelValue:e.mode,"onUpdate:modelValue":t[9]||(t[9]=o=>e.mode=o),label:"Settings source",options:[{value:"quick",label:"Quick settings"},{value:"config",label:"Saved config"}]},null,8,["modelValue"])]),e.mode==="config"?(s(),l(p,{key:0},[e.configs.length===0?(s(),l("p",tl,[t[37]||(t[37]=b(" No configs yet. ",-1)),n("button",{class:"link",onClick:t[10]||(t[10]=o=>e.navigate("configs"))},"Create the first one"),t[38]||(t[38]=b(" or use quick settings. ",-1))])):(s(),l(p,{key:1},[n("label",ol,[t[40]||(t[40]=n("span",null,"Config",-1)),T(n("select",{"onUpdate:modelValue":t[11]||(t[11]=o=>e.configName=o),class:"select"},[t[39]||(t[39]=n("option",{value:"",disabled:""},"Choose a config…",-1)),(s(!0),l(p,null,N(e.configs,o=>(s(),l("option",{key:o.name+o.scope,value:o.name,disabled:!!o.error},a(o.name)+" · "+a(o.scope),9,nl))),128))],512),[[ae,e.configName]])]),n("button",{class:"link",onClick:t[12]||(t[12]=o=>e.navigate("configs"))},"Manage configs"),e.chosenConfig?(s(),l("p",sl,[e.chosenConfig.title?(s(),l(p,{key:0},[b(a(e.chosenConfig.title)+" — ",1)],64)):d("v-if",!0),b(" "+a(e.chosenConfig.recipes)+" recipe"+a(e.chosenConfig.recipes===1?"":"s")+" ",1),e.chosenConfig.rules?(s(),l(p,{key:1},[b(", "+a(e.chosenConfig.rules)+" rule"+a(e.chosenConfig.rules===1?"":"s"),1)],64)):d("v-if",!0),e.chosenConfig.description?(s(),l(p,{key:2},[b(" · "+a(e.chosenConfig.description),1)],64)):d("v-if",!0)])):d("v-if",!0)],64))],64)):e.options?(s(),l(p,{key:1},[n("div",ll,[t[47]||(t[47]=n("h3",null,"Size",-1)),n("label",il,[T(n("input",{"onUpdate:modelValue":t[13]||(t[13]=o=>e.resize=o),type:"checkbox"},null,512),[[fe,e.resize]]),t[41]||(t[41]=b(" Resize the images ",-1))]),e.resize?d("v-if",!0):(s(),l("p",al," The size does not change: the images are only converted to the chosen format. ")),e.resize?(s(),l("div",rl,[n("label",dl,[t[42]||(t[42]=n("span",null,"Method",-1)),T(n("select",{"onUpdate:modelValue":t[14]||(t[14]=o=>e.chosenMethod=o),class:"select"},[(s(!0),l(p,null,N(e.resizeMethods,o=>(s(),l("option",{key:o,value:o},a(e.METHOD_LABELS[o]),9,cl))),128))],512),[[ae,e.chosenMethod]])]),e.resize&&e.sizeMethod==="size"?(s(),l("label",ul,[t[43]||(t[43]=n("span",null,"Box (width × height)",-1)),T(n("input",{"onUpdate:modelValue":t[15]||(t[15]=o=>e.box=o),class:"input",spellcheck:"false",placeholder:"1920x1080"},null,512),[[Y,e.box]])])):e.resize?(s(),l("label",fl,[t[44]||(t[44]=n("span",null,"Values",-1)),T(n("input",{"onUpdate:modelValue":t[16]||(t[16]=o=>e.sizeValues=o),class:"input",spellcheck:"false",placeholder:e.METHOD_HINTS[e.sizeMethod]},null,8,vl),[[Y,e.sizeValues]])])):d("v-if",!0),e.resize&&e.sizeMethod==="size"?(s(),l("label",ml,[t[45]||(t[45]=n("span",null,"How it fills the box",-1)),T(n("select",{"onUpdate:modelValue":t[17]||(t[17]=o=>e.fit=o),class:"select"},[(s(!0),l(p,null,N(e.options.fitModes,o=>(s(),l("option",{key:o,value:o},a(o),9,pl))),128))],512),[[ae,e.fit]])])):d("v-if",!0)])):d("v-if",!0),e.sizeMethod==="size"?(s(),l("label",gl,[T(n("input",{"onUpdate:modelValue":t[18]||(t[18]=o=>e.matchOrientation=o),type:"checkbox"},null,512),[[fe,e.matchOrientation]]),t[46]||(t[46]=b(" Turn the box around for portrait images ",-1))])):e.resize&&e.METHOD_HINTS[e.sizeMethod]?(s(),l("p",hl,a(e.METHOD_HINTS[e.sizeMethod])+". Images are never enlarged. ",1)):d("v-if",!0)]),n("div",bl,[t[53]||(t[53]=n("h3",null,"Formats",-1)),e.placement==="replace"?(s(),l("p",_l," Each file keeps its own format when the originals are replaced. ")):(s(),l("div",yl,[(s(!0),l(p,null,N(e.options.formats,o=>(s(),l("label",{key:o,class:te(["pill",{"pill--on":e.formats.includes(o)}])},[n("input",{type:"checkbox",checked:e.formats.includes(o),onChange:r=>e.toggleFormat(o)},null,40,kl),b(" "+a(o),1)],2))),128))])),n("div",wl,[n("label",Sl,[t[50]||(t[50]=n("span",null,"Quality",-1)),T(n("select",{"onUpdate:modelValue":t[19]||(t[19]=o=>e.qualityLevel=o),class:"select"},[t[48]||(t[48]=n("option",{value:""},"Default (high)",-1)),(s(!0),l(p,null,N(e.options.qualityLevels,o=>(s(),l("option",{key:o,value:o},a(o),9,Cl))),128)),t[49]||(t[49]=n("option",{value:"custom"},"A number…",-1))],512),[[ae,e.qualityLevel]])]),e.qualityLevel==="custom"?(s(),l("label",Vl,[t[51]||(t[51]=n("span",null,"Quality (1–100)",-1)),T(n("input",{"onUpdate:modelValue":t[20]||(t[20]=o=>e.qualityCustom=o),class:"input",inputmode:"numeric"},null,512),[[Y,e.qualityCustom]])])):d("v-if",!0),n("label",xl,[t[52]||(t[52]=n("span",null,"Largest file size",-1)),T(n("input",{"onUpdate:modelValue":t[21]||(t[21]=o=>e.maxSize=o),class:"input",spellcheck:"false",placeholder:"e.g. 200KB (optional)"},null,512),[[Y,e.maxSize]])])])]),e.placement!=="replace"?(s(),l("div",Ol,[t[55]||(t[55]=n("h3",null,"File names",-1)),T(n("input",{"onUpdate:modelValue":t[22]||(t[22]=o=>e.nameTemplate=o),class:"input",spellcheck:"false",placeholder:e.defaultTemplate,"aria-label":"File name template"},null,8,El),[[Y,e.nameTemplate]]),n("div",zl,[(s(!0),l(p,null,N(e.options.templateVariables,o=>(s(),l("button",{key:o,class:"pill pill--button",onClick:r=>e.insertToken(o)},a(e.tokenLabel(o)),9,Bl))),128))]),n("p",jl,[t[54]||(t[54]=b(" Example: ",-1)),n("code",null,a(e.templateExample),1),e.nameTemplate.trim()?d("v-if",!0):(s(),l(p,{key:0},[b(" (the default for this size method)")],64))])])):d("v-if",!0),n("div",Nl,[t[56]||(t[56]=n("h3",null,"Sharpening",-1)),U(e.SharpenSettings,{modelValue:e.sharpen,"onUpdate:modelValue":t[23]||(t[23]=o=>e.sharpen=o),options:e.options,manage:""},null,8,["modelValue","options"])])],64)):d("v-if",!0)]),n("div",Tl,[n("button",{class:"btn",disabled:!e.canRun,onClick:t[24]||(t[24]=o=>e.run(!0))},"Preview",8,Al),n("button",{class:"btn btn--primary",disabled:!e.canRun,onClick:t[25]||(t[25]=o=>e.run(!1))},[U(e.Icon,{name:"play",size:15}),b(" "+a(e.phase==="running"?"Working…":"Convert"),1)],8,Il),e.problem?(s(),l("span",Ul,a(e.problem),1)):d("v-if",!0)]),e.phase==="running"?(s(),l("div",Ml,[n("div",Dl,[n("div",{class:"progress__bar",style:Ve({width:`${e.percent}%`})},null,4)]),n("span",ql,a(e.progress.done)+" of "+a(e.progress.total||"…")+" files",1)])):d("v-if",!0),e.phase==="failed"?(s(),l("div",Ll,[n("p",null,a(e.failure),1),e.needsSharp?(s(),l("button",{key:0,class:"btn btn--small",onClick:t[26]||(t[26]=o=>e.run(!1,!0))}," Install sharp and retry ")):d("v-if",!0)])):d("v-if",!0),e.report?(s(),$(e.BatchResults,{key:3,report:e.report},null,8,["report"])):d("v-if",!0),e.browsingOut?(s(),$(e.FolderBrowser,{key:4,start:e.outDir||e.sources[0]||i.cwd,mode:"folder",title:"Choose the folder for the results",onClose:t[27]||(t[27]=o=>e.browsingOut=!1),onConfirm:e.chooseOut},null,8,["start"])):d("v-if",!0)])}const Rl=ne(Fs,[["render",Pl],["__scopeId","data-v-f483fd55"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ConvertView.vue"]]),Fl=oe({__name:"UiCompare",props:{before:{type:String,required:!0},after:{type:String,required:!0},beforeLabel:{type:String,required:!1},afterLabel:{type:String,required:!1}},setup(f,{expose:t}){t();const i=c(50),e=c(!0),m={position:i,loading:e};return Object.defineProperty(m,"__isScriptSetup",{enumerable:!1,value:!0}),m}}),Jl=["aria-busy"],Hl={class:"compare__scroll"},Wl={class:"compare__stage"},Gl=["src"],Kl=["src"],Ql={class:"compare__tag compare__tag--left"},Yl={class:"compare__tag compare__tag--right"};function Zl(f,t,i,e,m,g){return s(),l("div",{class:"compare","aria-busy":e.loading},[n("div",Hl,[n("div",Wl,[n("img",{class:"compare__img",alt:"Before",src:i.before,onLoad:t[0]||(t[0]=o=>e.loading=!1)},null,40,Gl),n("img",{class:"compare__img compare__img--top",alt:"After",src:i.after,style:Ve({clipPath:`inset(0 0 0 ${e.position}%)`})},null,12,Kl),n("span",{class:"compare__line",style:Ve({left:`${e.position}%`})},null,4),n("span",Ql,a(i.beforeLabel??"Before"),1),n("span",Yl,a(i.afterLabel??"After"),1)])]),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.position=o),class:"compare__range",type:"range",min:"0",max:"100","aria-label":"Comparison position"},null,512),[[Y,e.position,void 0,{number:!0}]])],8,Jl)}const Xl=ne(Fl,[["render",Zl],["__scopeId","data-v-04dcb8d4"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiCompare.vue"]]),Se="devtoolz-ui.sharpen-sample",$l=oe({__name:"SharpenEditor",props:{options:{type:Object,required:!0},cwd:{type:String,required:!0},initial:{type:null,required:!1},copyOf:{type:null,required:!1}},emits:["saved","cancel"],setup(f,{expose:t,emit:i}){t();const e=f,m=i,g=pe(Ee,qe),o=["radius","flat","jagged","threshold"];function r(){return e.initial??e.copyOf}function y(u){const _=r()?.fields?.[u];return _===void 0?"":String(_)}const S=E(()=>e.initial!==void 0),M=c(e.initial?e.initial.name:e.copyOf?.name??""),A=c(e.initial&&e.initial.scope!=="built-in"?e.initial.scope:"project"),B=c(r()?.description??""),z=c(String(r()?.fields?.for??"")),O=c(String(r()?.fields?.amount??"")),k=c({radius:y("radius"),flat:y("flat"),jagged:y("jagged"),threshold:y("threshold")}),v=c(""),C=c("800"),j=c(!1),R=c(),P=c(""),Z=c(""),D=c(!1),K=c("");let q;const w=E(()=>Object.fromEntries(e.options.sharpen.fine.map(u=>[u.key,u.range])));function I(){const u={};z.value&&(u.for=z.value),O.value&&(u.amount=O.value);for(const _ of o)k.value[_].trim()!==""&&(u[_]=Number(k.value[_]));return u}function J(u){const _=new URLSearchParams({path:v.value,width:C.value||"800"});if(u){_.set("sharpen","1");for(const[X,se]of Object.entries(I()))_.set(X,String(se))}return`/api/image-batch/sharpen-preview?${_.toString()}&v=${K.value}`}const H=E(()=>v.value?J(!1):""),re=E(()=>v.value?J(!0):"");async function ee(){try{const u=await F.post("/api/image-batch/sharpen-preset/params",{fields:I()});R.value=u.params,P.value=""}catch(u){R.value=void 0,P.value=u instanceof Error?u.message:String(u)}K.value=JSON.stringify(I())+C.value}function Q(){clearTimeout(q),q=setTimeout(()=>{ee()},300)}ge([z,O,k,C],Q,{deep:!0});function de(u){v.value=u[0]??"",j.value=!1;try{localStorage.setItem(Se,v.value)}catch{v.value=u[0]??""}}async function W(u=!1){D.value=!0,Z.value="";try{await F.post("/api/image-batch/sharpen-preset/save",{name:M.value,scope:A.value,description:B.value,fields:I(),overwrite:u,...e.initial?{originalName:e.initial.name,originalScope:e.initial.scope}:{}}),m("saved",M.value)}catch(_){if(_ instanceof De&&_.status===409){if(window.confirm(`${_.message}. Replace it?`)){await W(!0);return}}else Z.value=_ instanceof Error?_.message:String(_)}finally{D.value=!1}}ce(()=>{try{v.value=localStorage.getItem(Se)??""}catch{v.value=""}ee()}),xe(()=>clearTimeout(q));const G={props:e,emit:m,project:g,FINE:o,SAMPLE_KEY:Se,seed:r,initialFine:y,editing:S,name:M,scope:A,description:B,target:z,amount:O,fine:k,sample:v,width:C,browsing:j,params:R,paramsError:P,failure:Z,saving:D,applied:K,get timer(){return q},set timer(u){q=u},rangeOf:w,fields:I,query:J,beforeUrl:H,afterUrl:re,refresh:ee,schedule:Q,chooseSample:de,save:W,FolderBrowser:Oe,Icon:ue,UiCompare:Xl};return Object.defineProperty(G,"__isScriptSetup",{enumerable:!1,value:!0}),G}}),ei={class:"card block"},ti={class:"head"},oi={class:"grid"},ni={class:"field"},si={class:"field"},li={value:"project"},ii={class:"field wide"},ai={class:"grid"},ri={class:"field"},di=["value"],ci={class:"field"},ui=["value"],fi={class:"grid"},vi={class:"muted"},mi=["onUpdate:modelValue"],pi={key:0,class:"notice notice--error"},gi={key:1,class:"muted small"},hi={class:"preview"},bi={class:"head"},_i={class:"previewbar"},yi={class:"field inline"},ki={key:0,class:"muted"},wi={key:2,class:"muted small"},Si={key:2,class:"notice notice--error"},Ci={class:"actions"},Vi=["disabled"];function xi(f,t,i,e,m,g){return s(),l("section",ei,[n("div",ti,[n("h2",null,a(e.editing?"Edit preset":i.copyOf?"Copy of a built-in preset":"New sharpening preset"),1),n("button",{class:"btn btn--ghost",onClick:t[0]||(t[0]=o=>e.emit("cancel"))},[U(e.Icon,{name:"close",size:16}),t[11]||(t[11]=b(" Close ",-1))])]),n("div",oi,[n("label",ni,[t[12]||(t[12]=n("span",null,"Name",-1)),T(n("input",{"onUpdate:modelValue":t[1]||(t[1]=o=>e.name=o),class:"input",spellcheck:"false",placeholder:"web-crisp"},null,512),[[Y,e.name]])]),n("label",si,[t[14]||(t[14]=n("span",null,"Where to keep it",-1)),T(n("select",{"onUpdate:modelValue":t[2]||(t[2]=o=>e.scope=o),class:"select"},[n("option",li,"This project ("+a(e.project.name)+")",1),t[13]||(t[13]=n("option",{value:"global"},"All projects (your home folder)",-1))],512),[[ae,e.scope]])]),n("label",ii,[t[15]||(t[15]=n("span",null,"Note (optional)",-1)),T(n("input",{"onUpdate:modelValue":t[3]||(t[3]=o=>e.description=o),class:"input",placeholder:"What it is for"},null,512),[[Y,e.description]])])]),n("div",ai,[n("label",ri,[t[17]||(t[17]=n("span",null,"Sharpen for",-1)),T(n("select",{"onUpdate:modelValue":t[4]||(t[4]=o=>e.target=o),class:"select"},[t[16]||(t[16]=n("option",{value:""},"Default (screen)",-1)),(s(!0),l(p,null,N(i.options.sharpen.targets,o=>(s(),l("option",{key:o,value:o},a(o),9,di))),128))],512),[[ae,e.target]])]),n("label",ci,[t[19]||(t[19]=n("span",null,"Amount",-1)),T(n("select",{"onUpdate:modelValue":t[5]||(t[5]=o=>e.amount=o),class:"select"},[t[18]||(t[18]=n("option",{value:""},"Default (standard)",-1)),(s(!0),l(p,null,N(i.options.sharpen.amounts,o=>(s(),l("option",{key:o,value:o},a(o),9,ui))),128))],512),[[ae,e.amount]])])]),n("div",fi,[(s(),l(p,null,N(e.FINE,o=>n("label",{key:o,class:"field"},[n("span",null,[b(a(o)+" ",1),n("small",vi,"("+a(e.rangeOf[o]?.[0])+"–"+a(e.rangeOf[o]?.[1])+")",1)]),T(n("input",{"onUpdate:modelValue":r=>e.fine[o]=r,class:"input",inputmode:"decimal",placeholder:"value from the table"},null,8,mi),[[Y,e.fine[o]]])])),64))]),e.paramsError?(s(),l("p",pi,a(e.paramsError),1)):e.params?(s(),l("p",gi,[b(" sharp receives: sigma "+a(e.params.sigma)+", flat "+a(e.params.m1)+", jagged "+a(e.params.m2),1),e.params.x1!==void 0?(s(),l(p,{key:0},[b(", threshold "+a(e.params.x1),1)],64)):d("v-if",!0)])):d("v-if",!0),n("div",hi,[n("div",bi,[t[21]||(t[21]=n("h3",null,"Preview",-1)),n("div",_i,[n("label",yi,[t[20]||(t[20]=n("span",null,"Width",-1)),T(n("input",{"onUpdate:modelValue":t[6]||(t[6]=o=>e.width=o),class:"input narrow",inputmode:"numeric","aria-label":"Preview width"},null,512),[[Y,e.width]])]),n("button",{class:"btn btn--small",onClick:t[7]||(t[7]=o=>e.browsing=!0)},[U(e.Icon,{name:"image",size:15}),b(" "+a(e.sample?"Change image":"Choose an image"),1)])])]),e.sample?e.paramsError?d("v-if",!0):(s(),$(e.UiCompare,{key:e.sample,before:e.beforeUrl,after:e.afterUrl,"before-label":"Without sharpening","after-label":"Sharpened"},null,8,["before","after"])):(s(),l("p",ki," Pick any photo to see the preset applied at the output size. Drag the slider to compare. ")),e.sample?(s(),l("p",wi,a(e.sample)+" — resized to "+a(e.width||800)+" px wide, then sharpened, as it would be at the output size. ",1)):d("v-if",!0)]),e.failure?(s(),l("p",Si,a(e.failure),1)):d("v-if",!0),n("div",Ci,[n("button",{class:"btn btn--primary",disabled:e.saving||e.name.trim()==="",onClick:t[8]||(t[8]=o=>e.save(!1))},[U(e.Icon,{name:"save",size:15}),t[22]||(t[22]=b(" Save preset ",-1))],8,Vi),n("button",{class:"btn",onClick:t[9]||(t[9]=o=>e.emit("cancel"))},"Cancel")]),e.browsing?(s(),$(e.FolderBrowser,{key:3,start:e.sample?e.sample.replace(/[\\/][^\\/]*$/,""):i.cwd,mode:"image",onClose:t[10]||(t[10]=o=>e.browsing=!1),onConfirm:e.chooseSample},null,8,["start"])):d("v-if",!0)])}const Oi=ne($l,[["render",xi],["__scopeId","data-v-064cdf5b"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenEditor.vue"]]),Ei=oe({__name:"SharpenView",props:{options:{type:Object,required:!0},cwd:{type:String,required:!0}},setup(f,{expose:t}){t();const i=c([]),e=c(""),m=c(""),g=c("list"),o=c(),r=c();async function y(){try{i.value=await F.get("/api/image-batch/sharpen-presets")}catch(v){e.value=v instanceof Error?v.message:String(v)}}function S(){o.value=void 0,r.value=void 0,g.value="edit"}function M(v){o.value=v,r.value=void 0,g.value="edit"}function A(v){o.value=void 0,r.value=v,g.value="edit"}async function B(v){if(window.confirm(`Delete the preset “${v.name}”? A .bak copy is kept next to it.`))try{await F.post("/api/image-batch/sharpen-preset/delete",{name:v.name,scope:v.scope}),m.value=`Deleted ${v.name}.`,await y()}catch(C){e.value=C instanceof Error?C.message:String(C)}}async function z(v){g.value="list",m.value=`Saved ${v}.`,await y()}function O(v){return Object.entries(v.fields??{}).map(([C,j])=>`${C} ${j}`).join(" · ")}ce(y);const k={rows:i,failure:e,note:m,mode:g,editing:o,copying:r,load:y,create:S,edit:M,copy:A,remove:B,saved:z,summary:O,Icon:ue,SharpenEditor:Oi};return Object.defineProperty(k,"__isScriptSetup",{enumerable:!1,value:!0}),k}}),zi={class:"view"},Bi={key:1,class:"card block"},ji={class:"head"},Ni={key:0,class:"notice"},Ti={key:1,class:"notice notice--error"},Ai={class:"list"},Ii={class:"item__main"},Ui={class:"item__title"},Mi={key:0,class:"item__error"},Di={key:0,class:"muted"},qi={class:"item__facts"},Li={key:0,class:"muted"},Pi={class:"item__actions"},Ri=["onClick"],Fi=["onClick"],Ji=["onClick"];function Hi(f,t,i,e,m,g){return s(),l("div",zi,[e.mode==="edit"?(s(),$(e.SharpenEditor,{key:0,options:i.options,cwd:i.cwd,initial:e.editing,"copy-of":e.copying,onSaved:e.saved,onCancel:t[0]||(t[0]=o=>e.mode="list")},null,8,["options","cwd","initial","copy-of"])):(s(),l("section",Bi,[n("div",ji,[t[2]||(t[2]=n("div",null,[n("h2",null,"Sharpening presets"),n("p",{class:"muted"}," Save a set of sharpening values once and use it by name in any config or run. ")],-1)),n("button",{class:"btn btn--primary",onClick:e.create},[U(e.Icon,{name:"plus",size:16}),t[1]||(t[1]=b(" New preset ",-1))])]),e.note?(s(),l("p",Ni,a(e.note),1)):d("v-if",!0),e.failure?(s(),l("p",Ti,a(e.failure),1)):d("v-if",!0),n("ul",Ai,[(s(!0),l(p,null,N(e.rows,o=>(s(),l("li",{key:o.scope+o.name,class:"item"},[n("div",Ii,[n("div",Ui,[n("strong",null,a(o.name),1),n("span",{class:te(["tag",{"tag--builtin":o.scope==="built-in"}])},a(o.scope),3)]),o.error?(s(),l("p",Mi,a(o.error),1)):(s(),l(p,{key:1},[o.description?(s(),l("p",Di,a(o.description),1)):d("v-if",!0),n("p",qi,[b(a(e.summary(o))+" ",1),o.params?(s(),l("span",Li," — sigma "+a(o.params.sigma)+", flat "+a(o.params.m1)+", jagged "+a(o.params.m2),1)):d("v-if",!0)])],64))]),n("div",Pi,[o.scope!=="built-in"&&!o.error?(s(),l("button",{key:0,class:"btn btn--small",onClick:r=>e.edit(o)}," Edit ",8,Ri)):d("v-if",!0),o.error?d("v-if",!0):(s(),l("button",{key:1,class:"btn btn--small",onClick:r=>e.copy(o)},a(o.scope==="built-in"?"Copy to my presets":"Duplicate"),9,Fi)),o.scope!=="built-in"?(s(),l("button",{key:2,class:"btn btn--small btn--danger",onClick:r=>e.remove(o)}," Delete ",8,Ji)):d("v-if",!0)])]))),128))])]))])}const Wi=ne(Ei,[["render",Hi],["__scopeId","data-v-8f664bc5"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/SharpenView.vue"]]),Ce="devtoolz-ui.image-batch-tab",Gi=oe({__name:"ImageBatchPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(f,{expose:t}){t();const i=f;function e(){try{const S=localStorage.getItem(Ce);if(S==="convert"||S==="configs"||S==="sharpen"||S==="backups")return S}catch{return"convert"}return"convert"}const m=c(e()),g=c(),o=c("");function r(S){m.value=S;try{localStorage.setItem(Ce,S)}catch{m.value=S}}Ne(be,r),Ne(Ee,E(()=>Pt(i.status?.cwd??"",i.status?.home??"")).value),ce(async()=>{try{g.value=await F.get("/api/image-batch/options")}catch(S){o.value=S instanceof Error?S.message:String(S)}});const y={props:i,TAB_KEY:Ce,initialTab:e,tab:m,options:g,failure:o,go:r,Icon:ue,UiSegmented:he,BackupsView:Lt,ConfigsView:ps,ConvertView:Rl,SharpenView:Wi};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),Ki={class:"page"},Qi={class:"page__head"},Yi={class:"muted"},Zi=["title"],Xi={key:0,class:"notice notice--error"};function $i(f,t,i,e,m,g){return s(),l("div",Ki,[n("header",Qi,[n("h1",null,a(i.module.title),1),n("p",Yi,a(i.module.description),1),i.status?.cwd?(s(),l("p",{key:0,class:"context",title:`Everything marked “This project” lives in ${i.status.cwd}`},[U(e.Icon,{name:"folder",size:15}),t[0]||(t[0]=n("span",{class:"muted"},"Project folder",-1)),n("code",null,a(i.status.cwd),1)],8,Zi)):d("v-if",!0)]),U(e.UiSegmented,{"model-value":e.tab,label:"Image Batch sections",options:[{value:"convert",label:"Convert"},{value:"configs",label:"Configs"},{value:"sharpen",label:"Sharpening"},{value:"backups",label:"Backups"}],"onUpdate:modelValue":e.go},null,8,["model-value"]),e.failure?(s(),l("p",Xi,a(e.failure),1)):e.options?(s(),l(p,{key:1},[e.tab==="convert"?(s(),$(e.ConvertView,{key:0,cwd:e.props.status?.cwd??"",options:e.options},null,8,["cwd","options"])):e.tab==="configs"?(s(),$(e.ConfigsView,{key:1,options:e.options},null,8,["options"])):e.tab==="sharpen"?(s(),$(e.SharpenView,{key:2,options:e.options,cwd:e.props.status?.cwd??""},null,8,["options","cwd"])):(s(),$(e.BackupsView,{key:3,cwd:e.props.status?.cwd??""},null,8,["cwd"]))],64)):d("v-if",!0)])}const sa=ne(Gi,[["render",$i],["__scopeId","data-v-ec718b70"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-batch/ImageBatchPage.vue"]]);export{sa as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.view[data-v-276a3888]{display:flex;flex-direction:column;gap:16px}.block[data-v-276a3888]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.small[data-v-276a3888]{font-size:12px}.list[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-276a3888]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__path[data-v-276a3888]{color:var(--muted);font-size:11px;word-break:break-all}.item__actions[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.custom[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;padding-top:12px;border-top:1px solid var(--border)}.custom h3[data-v-276a3888]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.pathrow[data-v-276a3888]{display:flex;flex-wrap:wrap;gap:8px}.pathrow .input[data-v-276a3888]{flex:1;min-width:220px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.actions[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:12px}.chips[data-v-276a3888]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-276a3888]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px;white-space:nowrap}.chip--good[data-v-276a3888]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.chip--warn[data-v-276a3888]{background:var(--warn-soft);color:var(--warn)}.chip--bad[data-v-276a3888]{background:var(--danger-soft);color:var(--danger)}.rows[data-v-276a3888]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.row[data-v-276a3888]{display:flex;align-items:center;gap:12px;padding:8px;border:1px solid var(--border);border-radius:9px}.row__thumb[data-v-276a3888]{flex:none;width:64px;height:64px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__text[data-v-276a3888]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.row__name[data-v-276a3888]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row__message[data-v-276a3888]{color:var(--danger)}.sharpen[data-v-1a683036]{display:flex;flex-direction:column;gap:12px}.grid[data-v-1a683036]{display:grid;grid-template-columns:repeat(auto-fill,minmax(180px,1fr));gap:12px}.hint[data-v-1a683036]{align-self:end;font-size:12px}.link[data-v-1a683036]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-1a683036]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.recipe[data-v-92a49f1e]{display:flex;flex-direction:column;gap:16px}.group[data-v-92a49f1e]{display:flex;flex-direction:column;gap:10px}.group h4[data-v-92a49f1e]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase;margin:0}.grid[data-v-92a49f1e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:14px}.small[data-v-92a49f1e]{font-size:12px}.input--bad[data-v-92a49f1e]{border-color:var(--danger)}.pills[data-v-92a49f1e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pill[data-v-92a49f1e]{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.pill input[data-v-92a49f1e]{display:none}.pill--on[data-v-92a49f1e]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);font-weight:600}.pill--button[data-v-92a49f1e]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace}.pill--button[data-v-92a49f1e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.link[data-v-92a49f1e]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-92a49f1e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.block[data-v-6b6acd65]{display:flex;flex-direction:column;gap:16px;padding:18px}.head[data-v-6b6acd65]{display:flex;align-items:center;justify-content:space-between;gap:12px}.grid[data-v-6b6acd65]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.small[data-v-6b6acd65]{font-size:12px}.recipes[data-v-6b6acd65]{display:flex;flex-direction:column;gap:8px}.panel[data-v-6b6acd65]{border:1px solid var(--border);border-radius:9px}.panel--open[data-v-6b6acd65]{border-color:var(--accent)}.panel__head[data-v-6b6acd65]{display:flex;align-items:center;gap:8px;padding:4px 8px 4px 12px}.panel__title[data-v-6b6acd65]{display:flex;flex-direction:column;gap:0;flex:1;min-width:0;padding:8px 0;border:0;background:transparent;text-align:left;cursor:pointer}.panel__title[data-v-6b6acd65]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.panel__title .small[data-v-6b6acd65]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.panel__actions[data-v-6b6acd65]{display:flex;flex-wrap:wrap;align-items:center;gap:2px;flex:none}.panel__body[data-v-6b6acd65]{padding:12px 16px 16px;border-top:1px solid var(--border)}.panel summary[data-v-6b6acd65]{padding:12px;cursor:pointer;font-weight:600}details.panel>.panel__body[data-v-6b6acd65]{border-top:1px solid var(--border)}.json[data-v-6b6acd65]{min-height:420px;padding:12px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2);font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;resize:vertical;tab-size:2}.json[data-v-6b6acd65]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.check-panel[data-v-6b6acd65]{padding:10px 14px;border-radius:9px}.check-panel--ok[data-v-6b6acd65]{background:color-mix(in srgb,var(--ok) 14%,transparent)}.check-panel--bad[data-v-6b6acd65]{background:var(--danger-soft);color:var(--danger)}.lines[data-v-6b6acd65]{margin:8px 0 0;font-size:12px;white-space:pre-wrap}.actions[data-v-6b6acd65]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.view[data-v-2e26c039]{display:flex;flex-direction:column;gap:16px}.block[data-v-2e26c039]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.list[data-v-2e26c039]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-2e26c039]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__title[data-v-2e26c039]{display:flex;align-items:center;gap:8px}.item__path[data-v-2e26c039]{color:var(--muted);font-size:11px;word-break:break-all}.item__error[data-v-2e26c039]{color:var(--danger);font-size:12px}.item__actions[data-v-2e26c039]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.tag[data-v-2e26c039]{padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.block[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-7e5d47ea]{display:flex;align-items:center;justify-content:space-between;gap:12px}.small[data-v-7e5d47ea]{font-size:12px}.chips[data-v-7e5d47ea]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.chip[data-v-7e5d47ea]{padding:2px 10px;border-radius:999px;background:var(--surface-2);font-size:12px;white-space:nowrap}.chip--good[data-v-7e5d47ea]{background:color-mix(in srgb,var(--ok) 18%,transparent);color:var(--ok)}.chip--bad[data-v-7e5d47ea]{background:var(--danger-soft);color:var(--danger)}.errors[data-v-7e5d47ea]{margin:0;padding:10px 14px 10px 28px;border-radius:10px;background:var(--danger-soft);color:var(--danger)}.rows[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.row[data-v-7e5d47ea]{display:flex;align-items:center;gap:12px;padding:8px;border:1px solid var(--border);border-radius:9px}.row__thumb[data-v-7e5d47ea]{flex:none;width:64px;height:64px;border-radius:6px;background:var(--surface-2);object-fit:cover}.row__thumb--empty[data-v-7e5d47ea]{display:grid;place-items:center;font-size:11px}.row__text[data-v-7e5d47ea]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:0}.row__name[data-v-7e5d47ea]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.row__message[data-v-7e5d47ea]{color:var(--danger)}.row__sizes[data-v-7e5d47ea]{display:flex;align-items:baseline;gap:6px;flex:none;font-size:12px}.row__delta[data-v-7e5d47ea]{color:var(--muted)}.row__delta--down[data-v-7e5d47ea]{color:var(--ok)}@media(max-width:760px){.row[data-v-7e5d47ea]{flex-wrap:wrap}.row__text[data-v-7e5d47ea]{flex-basis:60%}}.link[data-v-7e5d47ea]{padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer;text-decoration:underline}.more[data-v-7e5d47ea]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.view[data-v-f483fd55]{display:flex;flex-direction:column;gap:16px}.block[data-v-f483fd55]{display:flex;flex-direction:column;gap:14px;padding:18px}.head[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px}.group[data-v-f483fd55]{display:flex;flex-direction:column;gap:10px}.group h3[data-v-f483fd55]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.grid[data-v-f483fd55]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.narrow[data-v-f483fd55]{max-width:320px}.small[data-v-f483fd55]{font-size:12px}.pathrow[data-v-f483fd55]{display:flex;gap:8px}.pathrow .input[data-v-f483fd55]{flex:1;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.pills[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.pill[data-v-f483fd55]{display:inline-flex;align-items:center;gap:6px;padding:4px 12px;border:1px solid var(--border);border-radius:999px;background:var(--surface);font-size:12px;cursor:pointer}.pill input[data-v-f483fd55]{display:none}.pill--on[data-v-f483fd55]{border-color:var(--accent);background:var(--accent-soft);color:var(--accent);font-weight:600}.pill--button[data-v-f483fd55]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace}.pill--button[data-v-f483fd55]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.runbar[data-v-f483fd55]{display:flex;flex-wrap:wrap;align-items:center;gap:14px}.link[data-v-f483fd55]{align-self:flex-start;padding:0;border:0;background:transparent;color:var(--accent);cursor:pointer}.link[data-v-f483fd55]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.progress[data-v-f483fd55]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-f483fd55]{height:100%;background:var(--accent);transition:width .15s}.compare[data-v-04dcb8d4]{display:flex;flex-direction:column;gap:8px}.compare__scroll[data-v-04dcb8d4]{overflow:auto;border-radius:9px;background:var(--surface-2);max-height:70vh}.compare__stage[data-v-04dcb8d4]{position:relative;width:fit-content;margin:0 auto;line-height:0}.compare__img[data-v-04dcb8d4]{display:block;max-width:none}.compare__img--top[data-v-04dcb8d4]{position:absolute;inset:0}.compare__line[data-v-04dcb8d4]{position:absolute;top:0;bottom:0;width:2px;background:var(--accent);pointer-events:none}.compare__tag[data-v-04dcb8d4]{position:absolute;top:8px;padding:2px 8px;border-radius:6px;background:#0009;color:#fff;font-size:11px;line-height:1.4}.compare__tag--left[data-v-04dcb8d4]{left:8px}.compare__tag--right[data-v-04dcb8d4]{right:8px}.compare__range[data-v-04dcb8d4]{width:100%}.block[data-v-064cdf5b]{display:flex;flex-direction:column;gap:16px;padding:18px}.head[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px}.grid[data-v-064cdf5b]{display:grid;grid-template-columns:repeat(auto-fill,minmax(200px,1fr));gap:14px}.wide[data-v-064cdf5b]{grid-column:1/-1}.small[data-v-064cdf5b]{font-size:12px}.preview[data-v-064cdf5b]{display:flex;flex-direction:column;gap:12px}.previewbar[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.inline[data-v-064cdf5b]{flex-direction:row;align-items:center}.narrow[data-v-064cdf5b]{width:90px}.actions[data-v-064cdf5b]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.view[data-v-8f664bc5]{display:flex;flex-direction:column;gap:16px}.block[data-v-8f664bc5]{display:flex;flex-direction:column;gap:12px;padding:18px}.head[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:space-between;gap:12px}.list[data-v-8f664bc5]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.item[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:12px;padding:12px;border:1px solid var(--border);border-radius:9px}.item__main[data-v-8f664bc5]{display:flex;flex-direction:column;gap:2px;flex:1;min-width:260px}.item__title[data-v-8f664bc5]{display:flex;align-items:center;gap:8px}.item__facts[data-v-8f664bc5]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.item__error[data-v-8f664bc5]{color:var(--danger);font-size:12px}.item__actions[data-v-8f664bc5]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.tag[data-v-8f664bc5]{padding:1px 8px;border-radius:999px;background:var(--surface-2);color:var(--muted);font-size:11px}.tag--builtin[data-v-8f664bc5]{background:var(--accent-soft);color:var(--accent)}.page[data-v-ec718b70]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-ec718b70]{padding:18px 14px 40px}}.page__head p[data-v-ec718b70]{margin-top:4px}.context[data-v-ec718b70]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-top:8px;font-size:12px}.context code[data-v-ec718b70]{padding:2px 8px;border-radius:6px;background:var(--surface-2);word-break:break-all}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.canvas[data-v-512bf9cf]{display:block;width:100%;height:100%;object-fit:cover;background:var(--surface-2)}.canvas--bad[data-v-512bf9cf]{display:grid;place-items:center;color:var(--danger)}.item[data-v-e50ba89f]{display:flex;flex-direction:column;gap:10px;padding:10px;min-width:0}.item__open[data-v-e50ba89f]{display:flex;flex-direction:column;gap:10px;padding:0;border:0;background:transparent;text-align:left;cursor:zoom-in}.item__open[data-v-e50ba89f]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.shots[data-v-e50ba89f]{display:block;overflow:hidden;border-radius:8px;background:var(--surface-2)}.shot[data-v-e50ba89f]{display:block;width:100%;height:100%;object-fit:cover;transition:transform .15s}.item__open:hover .shot[data-v-e50ba89f]{transform:scale(1.02)}.strip[data-v-e50ba89f]{display:flex;overflow:hidden;border-radius:8px}.strip__cell[data-v-e50ba89f]{position:relative;flex:1}.strip__label[data-v-e50ba89f]{position:absolute;left:4px;bottom:3px;padding:0 5px;border-radius:4px;background:#0000008c;color:#fff;font-size:10px}.preview[data-v-e50ba89f]{width:100%;border-radius:8px}.meta[data-v-e50ba89f]{display:flex;align-items:baseline;justify-content:space-between;gap:8px}.meta__name[data-v-e50ba89f]{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.hashes[data-v-e50ba89f]{display:flex;flex-direction:column;gap:2px;margin:0;padding:0;list-style:none}.hashes li[data-v-e50ba89f]{display:flex;align-items:center;gap:8px}.hashes__key[data-v-e50ba89f]{display:flex;align-items:center;gap:6px;flex:none;width:84px;color:var(--muted);font-size:12px}.hashes__value[data-v-e50ba89f]{flex:1;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.swatch[data-v-e50ba89f]{display:inline-block;width:12px;height:12px;border:1px solid var(--border);border-radius:4px}.counter[data-v-6aef2e16]{font-size:12px}.scroll[data-v-6aef2e16]{display:flex;flex-direction:column;gap:16px;padding:16px;min-height:0;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--border) transparent}.stage[data-v-6aef2e16]{display:flex;align-items:center;justify-content:center;padding:12px;border-radius:9px;background:repeating-conic-gradient(var(--surface-2) 0% 25%,transparent 0% 50%) 50%/20px 20px}.stage__img[data-v-6aef2e16]{display:block;max-width:100%;max-height:56vh;border-radius:6px;object-fit:contain}.compare[data-v-6aef2e16]{display:grid;grid-template-columns:repeat(auto-fit,minmax(220px,1fr));gap:12px}.compare__item[data-v-6aef2e16]{display:flex;flex-direction:column;gap:6px;margin:0}.compare__item figcaption[data-v-6aef2e16]{font-size:12px;font-weight:600;letter-spacing:.02em;color:var(--muted);text-transform:uppercase}.compare__frame[data-v-6aef2e16]{overflow:hidden;border-radius:9px;background:var(--surface-2)}.compare__preview[data-v-6aef2e16]{display:block;width:100%;height:100%;object-fit:cover}.facts[data-v-6aef2e16]{display:flex;flex-direction:column;gap:4px;margin:0}.facts__row[data-v-6aef2e16]{display:flex;align-items:center;gap:12px;min-height:32px}.facts dt[data-v-6aef2e16]{display:flex;align-items:center;gap:6px;flex:none;width:96px;color:var(--muted);font-size:12px}.facts dd[data-v-6aef2e16]{flex:1;min-width:0;margin:0}.facts__mono[data-v-6aef2e16]{font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;word-break:break-all}.swatch[data-v-6aef2e16]{display:inline-block;width:12px;height:12px;border:1px solid var(--border);border-radius:4px}.page[data-v-0458e07e]{display:flex;flex-direction:column;gap:16px;padding:28px 28px 60px}@media(max-width:760px){.page[data-v-0458e07e]{padding:18px 14px 40px}}.page__head p[data-v-0458e07e]{margin-top:4px}.block[data-v-0458e07e]{display:flex;flex-direction:column;gap:14px;padding:18px}.block__head[data-v-0458e07e]{display:flex;align-items:center;justify-content:space-between;gap:12px}.types[data-v-0458e07e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(210px,1fr));gap:10px}.type[data-v-0458e07e]{display:grid;grid-template-columns:auto 1fr;column-gap:10px;row-gap:2px;padding:12px;border:1px solid var(--border);border-radius:10px;cursor:pointer}.type--on[data-v-0458e07e]{border-color:var(--accent);background:var(--accent-soft)}.type input[data-v-0458e07e]{grid-row:1/3;margin-top:3px}.type__title[data-v-0458e07e]{font-weight:600}.type__text[data-v-0458e07e]{font-size:12px}.grid[data-v-0458e07e]{display:grid;grid-template-columns:repeat(auto-fill,minmax(220px,1fr));gap:14px}.runbar[data-v-0458e07e]{display:flex;align-items:center;gap:14px}.progress[data-v-0458e07e]{height:8px;overflow:hidden;border-radius:999px;background:var(--surface-2)}.progress__bar[data-v-0458e07e]{height:100%;background:var(--accent);transition:width .15s}.errors[data-v-0458e07e]{margin:0;padding:10px 14px 10px 28px;border-radius:10px;background:var(--danger-soft);color:var(--danger)}.tabs[data-v-0458e07e]{display:flex;gap:4px;border-bottom:1px solid var(--border)}.tab[data-v-0458e07e]{padding:8px 14px;border:0;border-bottom:2px solid transparent;background:transparent;color:var(--muted);cursor:pointer}.tab[data-v-0458e07e]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.tab--on[data-v-0458e07e]{border-bottom-color:var(--accent);color:var(--text);font-weight:600}.gallery[data-v-0458e07e]{width:100%}.more[data-v-0458e07e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px;justify-content:center}.outbar[data-v-0458e07e]{display:flex;flex-wrap:wrap;align-items:center;gap:8px}.outbar__path[data-v-0458e07e]{flex:1;min-width:220px;height:28px;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px}.output[data-v-0458e07e]{max-height:420px;margin:0;padding:14px;border-radius:10px;background:var(--surface-2);font-size:12px;white-space:pre-wrap;word-break:break-all;overflow:auto}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as _e,G as Xe,x as V,q as Me,w as Fe,e as Ve,H as ke,r as O,a as Se,o as _,c as k,I as Ge,D as rt,h as u,s as me,F as re,b as ue,i as J,t as C,l as L,j as le,p as lt,E as He,g as Ee,y as yt,J as gt,n as Oe,k as ve,z as Le,K as Ye}from"./index-D8H-zVzo.js";import{S as pt}from"./SourcePicker-xk00AG2e.js";import{u as it}from"./useCopy-i_vlQfC-.js";import{U as bt}from"./FolderBrowser-Cdzt7edI.js";function _t(t,n,s,e){if(t==="auto")return Math.max(1,Math.floor((n+e)/(s+e)));if(typeof t=="number")return Math.max(1,Math.floor(t));const a=Object.keys(t).filter(c=>c!=="default").map(Number).sort((c,o)=>c-o);for(const c of a)if(n<=c)return Math.max(1,Math.floor(t[c]));return Math.max(1,Math.floor(t.default))}function wt(t,n,s){return Math.max(0,(t-(n-1)*s)/n)}function kt(t,n){return n!==void 0?Math.max(1,Math.floor(n)):t===void 0||t==="auto"?2:typeof t=="number"?Math.max(1,Math.floor(t)):Math.max(1,Math.floor(t.default))}function xt(t,n,s,e="balanced"){const a=Math.max(1,Math.floor(n)||1),c=new Array(a).fill(0),o=[];let i=0;for(const M of t){const w=Math.min(Math.max(1,Math.floor(M.span)||1),a);let y;if(e==="ordered")y=i+w<=a?i:0,i=y+w,i>=a&&(i=0);else{let g=0,I=1/0;for(let b=0;b<=a-w;b++){let v=0;for(let z=b;z<b+w;z++)v=Math.max(v,c[z]);v<I&&(I=v,g=b)}y=g}let h=0;for(let g=y;g<y+w;g++)h=Math.max(h,c[g]);o.push({id:M.id,laneIndex:y,span:w,mainPos:h});const S=h+M.mainSize+s;for(let g=y;g<y+w;g++)c[g]=S}const m=o.length?Math.max(0,Math.max(...c)-s):0;return{items:o,totalMainSize:m}}function Mt(t){const n=new Set;let s=!1;function e(){s||(s=!0,requestAnimationFrame(()=>{s=!1,t()}))}const a=typeof ResizeObserver>"u"?null:new ResizeObserver(e);return{observe(c){n.has(c)||(n.add(c),a?.observe(c))},unobserveAll(){for(const c of n)a?.unobserve(c);n.clear()},scheduleNow:e,destroy(){a?.disconnect(),n.clear()}}}var St=240,Je=16,Ze=600,Ct=250,It="cubic-bezier(0.2, 0, 0, 1)";function Re(t){return typeof t.el=="function"?t.el():t.el??null}function zt(t){return(t instanceof HTMLImageElement?[t]:Array.from(t.querySelectorAll("img"))).filter(s=>!s.complete)}function At(t,n={}){const s=n.direction??"vertical",e=n.minLaneSize??St,a=n.placement??"balanced",c=typeof n.gap=="number"?n.gap:n.gap?.main??Je,o=typeof n.gap=="number"?n.gap:n.gap?.cross??Je,i=s==="horizontal"?n.rows??"auto":n.columns??"auto",m=!!n.virtualize,M=typeof n.virtualize=="object"?n.virtualize.overscan??Ze:Ze,w=n.scrollContainer??(s==="vertical"?"window":"self"),y=n.estimateSize,h=n.animate??!0,S=n.transitionDuration??Ct,g=n.transitionEasing??It,I=`transform ${S}ms ${g}, opacity ${S}ms ${g}`;t.style.position="relative",h&&(t.style.setProperty("--mk-transition-duration",`${S}ms`),t.style.setProperty("--mk-transition-easing",g));let b=null;s==="horizontal"?(t.style.overflowX="auto",t.style.overflowY="hidden",b=document.createElement("div"),b.setAttribute("aria-hidden","true"),b.style.position="absolute",b.style.top="0",b.style.left="0",b.style.width="1px",b.style.height="1px",b.style.visibility="hidden",b.style.pointerEvents="none",t.appendChild(b)):t.style.overflowX="clip";const v=new Map;let z=[],E=[],j=[];const R=new Map,U=new WeakSet;let Z=!1,Q=null;const se=new Map;function de(r,f){for(const p of se.get(r)??[])p(f)}const D=Mt(l);function F(){D.scheduleNow()}const $=m?w==="window"?window:w==="self"?t:w:null;$?.addEventListener("scroll",F,{passive:!0});function ee(){return z.map((r,f)=>({id:r,key:v.get(r)?.order??f})).sort((r,f)=>r.key-f.key).map(r=>r.id)}function G(){D.unobserveAll(),D.observe(t);for(const r of z){const f=Re(v.get(r));f&&D.observe(f)}}function q(r){if(!h)return;const f=v.get(r),p=f?Re(f):null;p&&(p.classList.add("mk-item-leave"),p.style.transition=I,p.style.opacity="0")}function W(r){const f=p=>{p.target===r&&(r.style.willChange="auto",r.classList.remove("mk-item-moving"),r.removeEventListener("transitionend",f))};r.style.willChange="transform",r.addEventListener("transitionend",f)}function T(r,f,p){const P=`translate(${f}px, ${p}px)`;return r.style.transform===""?h?(r.style.transition="none",r.style.transform=P,r.style.opacity="0",r.classList.add("mk-item-enter"),!0):(r.style.transform=P,!1):(r.style.transform===P||(h&&(r.style.transition=I,r.classList.add("mk-item-moving"),W(r)),r.style.transform=P),!1)}function te(){if(w==="self"){const x=s==="vertical"?t.scrollTop:t.scrollLeft,N=s==="vertical"?t.clientHeight:t.clientWidth;return[x-M,x+N+M]}const r=t.getBoundingClientRect(),f=s==="vertical"?r.top:r.left;let p,P;if(w==="window")p=0,P=s==="vertical"?window.innerHeight:window.innerWidth;else{const x=w.getBoundingClientRect();p=s==="vertical"?x.top:x.left,P=s==="vertical"?w.clientHeight:w.clientWidth}return[p-f-M,p+P-f+M]}function K(r,f){if(m&&r.estimatedSize!==void 0)return r.estimatedSize;if(r.aspectRatio)return s==="vertical"?f/r.aspectRatio:f*r.aspectRatio;if(!m)return;if(y)return y(r);Z||(Z=!0,console.warn("[masonry-kit] `virtualize` is on but an item has no `estimatedSize`, no `aspectRatio`, and `estimateSize` returned nothing — falling back to a guessed size. Set one of these for accurate initial positions."));const p=[...R.values()];return p.length>0?p.reduce((P,x)=>P+x,0)/p.length:f}function l(){const r=t.getBoundingClientRect(),f=s==="vertical"?r.width:r.height,p=_t(i,f,e,o),P=wt(f,p,o),x=ee().filter(A=>A!==Q),N=new Map,B=new Map,ne=new Map;for(const A of x){const ie=v.get(A),he=s==="vertical"?ie.colSpan??1:ie.rowSpan??1,oe=Math.min(Math.max(1,Math.floor(he)||1),p);B.set(A,oe);const H=oe*P+(oe-1)*o;ne.set(A,H);const X=Re(ie);X&&(N.set(A,X),X.style.position="absolute",X.style.top="0",X.style.left="0",s==="vertical"?X.style.width=`${H}px`:X.style.height=`${H}px`)}const fe=new Map,We=[];for(const A of x){const ie=v.get(A),he=ne.get(A),oe=N.get(A);let H;if(oe){const X=zt(oe);if(X.length===0){const ae=s==="vertical"?oe.getBoundingClientRect().height:oe.getBoundingClientRect().width;ae>0&&(H=ae,R.set(A,ae))}else for(const ae of X)U.has(ae)||(U.add(ae),ae.addEventListener("load",l,{once:!0}),ae.addEventListener("error",l,{once:!0}))}H===void 0&&(H=R.get(A)),H===void 0&&(H=K(ie,he)),H!==void 0&&(fe.set(A,H),We.push({id:A,span:B.get(A),mainSize:H}))}const{items:mt,totalMainSize:Ke}=xt(We,p,c,a),Ce=m?te():null,Ie=[],ze=[],we=[];for(const A of mt){const ie=ne.get(A.id),he=fe.get(A.id),oe=A.laneIndex*(P+o),H=s==="vertical"?oe:A.mainPos,X=s==="vertical"?A.mainPos:oe,ae=s==="vertical"?ie:he,vt=s==="vertical"?he:ie,Ae=N.get(A.id);Ae&&T(Ae,H,X)&&we.push(Ae),Ie.push({id:A.id,x:H,y:X,width:ae,height:vt}),(!Ce||A.mainPos+he>=Ce[0]&&A.mainPos<=Ce[1])&&ze.push(A.id)}if(s==="vertical"?t.style.height=`${Ke}px`:b&&(b.style.transform=`translate(${Ke}px, 0)`),we.length>0){we[0].offsetHeight;for(const A of we)A.style.transition=I,A.style.opacity="1",W(A)}E=Ie,j=ze,de("layout",{items:Ie,visibleIds:ze})}function d(r){const f=new Set(r.map(p=>p.id));for(const p of z)f.has(p)||(q(p),R.delete(p));v.clear(),z=r.map(p=>p.id);for(const p of r)v.set(p.id,p);G()}return D.observe(t),{setItems(r){d(r),l()},updateItem(r,f){const p=v.get(r);p&&(v.set(r,{...p,...f}),G(),l())},addItem(r,f){v.set(r.id,r),f===void 0||f>=z.length?z.push(r.id):z.splice(f,0,r.id),G(),l()},removeItem(r){q(r),v.delete(r),z=z.filter(f=>f!==r),R.delete(r),G(),l()},relayout:l,getLayout(){return[...E]},getVisibleIds(){return[...j]},setDragging(r){Q!==r&&(Q=r,l())},on(r,f){se.has(r)||se.set(r,new Set);const p=se.get(r);return p.add(f),()=>p.delete(f)},destroy(){D.destroy(),$?.removeEventListener("scroll",F),b?.remove(),v.clear(),z=[],E=[],j=[],R.clear(),Q=null,se.clear()}}}function ct(t,n){if(t===n)return!0;if(typeof t!="object"||typeof n!="object"||t===null||n===null||typeof Node<"u"&&(t instanceof Node||n instanceof Node))return!1;const s=Object.keys(t),e=Object.keys(n);return s.length!==e.length?!1:s.every(a=>ct(t[a],n[a]))}function Et(t,n){if(t===n)return!0;const s=new Set([...Object.keys(t),...Object.keys(n)]);for(const e of s)if(!ct(t[e],n[e]))return!1;return!0}var ce={},Qe=new WeakMap,Ot=0;function Y(t){if(t.id!==void 0)return t.id;let n=Qe.get(t);return n===void 0&&(n=`mk-auto-${++Ot}`,Qe.set(t,n)),n}var Lt=0,$e={position:"absolute",width:"1px",height:"1px",padding:"0",margin:"-1px",overflow:"hidden",clip:"rect(0, 0, 0, 0)",whiteSpace:"nowrap",border:"0"},Rt=_e({name:"MasonryGrid",props:{items:{type:Array,required:!0},options:{type:Object,default:()=>({})},sortable:{type:Boolean,default:!1}},emits:["layout","reorder"],setup(t,{slots:n,emit:s}){const e=`mk-${++Lt}`,a=O(null),c=new Map,o=new Map;let i=null,m=null,M=null,w=null,y=!1;const h=Xe(t.options.virtualize?new Set:null),S=O(!1),g=Xe(new Map),I=new Map;let b=new Set;const v=V(()=>{const l=h.value===null?t.items:t.items.filter(f=>h.value.has(Y(f)));if(g.value.size===0)return l;const d=new Set(l.map(f=>Y(f))),r=[...g.value.values()].filter(f=>!d.has(Y(f)));return r.length===0?l:[...l,...r]});function z(l,d){if(l.size!==d.size)return!1;for(const r of l)if(!d.has(r))return!1;return!0}function E(){return t.options.animate??ce.animate??!0}function j(){return t.options.transitionDuration??ce.transitionDuration??250}function R(){const l=t.options.gap??ce.gap;return typeof l=="number"?{main:l,cross:l}:{main:l?.main??16,cross:l?.cross??16}}function U(){const d=(t.options.direction??ce.direction)==="horizontal"?t.options.rows??ce.rows:t.options.columns??ce.columns;return kt(d,t.options.ssrColumns??ce.ssrColumns)}function Z(l){const d=new Set(l.map(f=>Y(f)));for(const f of l)I.set(Y(f),f);let r=null;for(const f of b){if(d.has(f)||g.value.has(f)||!c.get(f)||!E())continue;const p=I.get(f);p&&(r??(r=new Map(g.value)),r.set(f,p),setTimeout(()=>{const P=new Map(g.value);P.delete(f),g.value=P,I.delete(f)},j()))}r&&(g.value=r),b=d}function Q(){if(!i)return;const l=t.items.map(d=>{const r=Y(d);return{id:r,el:c.get(r),colSpan:d.colSpan,rowSpan:d.rowSpan,aspectRatio:d.aspectRatio,estimatedSize:d.estimatedSize,order:d.order}});i.setItems(l)}function se(){y||(y=!0,queueMicrotask(()=>{y=!1,Q()}))}function de(l){let d=o.get(l);return d||(d=r=>{r!==c.get(l)&&(r?c.set(l,r):(c.delete(l),o.delete(l)),se())},o.set(l,d),d)}function D(){if(a.value){h.value=t.options.virtualize?new Set:null,b=new Set(t.items.map(l=>Y(l))),I.clear();for(const l of t.items)I.set(Y(l),l);i=At(a.value,{...ce,...t.options}),m=i.on("layout",l=>{if(S.value=!0,s("layout",l.items),t.options.virtualize){const d=new Set(l.visibleIds);(!h.value||!z(h.value,d))&&(h.value=d)}}),Q()}}const F=O(null),$=O(""),ee=`${e}-instructions`,G=`${e}-live`;function q(l){$.value=l}function W(l,d){return`item ${d.findIndex(f=>Y(f)===l)+1} of ${d.length}`}let T=null;function te(l,d,r){const f=l.findIndex(x=>Y(x)===d);if(f===-1)return l;const p=[...l],[P]=p.splice(f,1);return p.splice(Math.max(0,Math.min(r,p.length)),0,P),p}function K(l,d){if(!t.sortable||!i)return;const r=Y(d);if(l.key===" "||l.key==="Enter"){l.preventDefault(),F.value===r?(F.value=null,T=null,i.setDragging(null),q(`Dropped ${W(r,t.items)}.`)):F.value===null&&(F.value=r,T=t.items,i.setDragging(r),q(`Picked up ${W(r,t.items)}. Use arrow keys to move, space to drop, escape to cancel.`));return}if(F.value!==r)return;if(l.key==="Escape"){l.preventDefault(),F.value=null,i.setDragging(null),T&&s("reorder",T),T=null,q("Reordering cancelled.");return}const f=t.options.direction==="horizontal",p=f?"ArrowRight":"ArrowDown",P=f?"ArrowLeft":"ArrowUp";if(l.key!==p&&l.key!==P)return;l.preventDefault();const x=t.items.findIndex(fe=>Y(fe)===r),N=l.key===p?1:-1,B=x+N;if(B<0||B>=t.items.length)return;const ne=te(t.items,r,B);s("reorder",ne),q(`Moved to ${W(r,ne)}.`)}return Me(()=>{!a.value||typeof window>"u"||(D(),M=Fe(()=>t.items,l=>{Z(l),Q()},{deep:!0}),w=Fe(()=>t.options,(l,d)=>{Et(l,d)||(m?.(),i?.destroy(),D())},{deep:!0}))}),Ve(()=>{M?.(),w?.(),m?.(),i?.destroy()}),()=>ke("div",{ref:a,class:"mk-grid",style:S.value?{}:{columns:U(),columnGap:`${R().cross}px`}},[...v.value.map(l=>{const d=Y(l),r=g.value.has(d),f=t.sortable?{tabindex:0,role:"button","aria-roledescription":"Reorderable item","aria-describedby":ee,"aria-pressed":F.value===d?"true":"false",onKeydown:p=>K(p,l)}:{};return ke("div",{key:d,class:"mk-item",style:{...S.value?{}:{breakInside:"avoid",marginBottom:`${R().main}px`},...r?{pointerEvents:"none"}:{}},ref:de(d),...f},n.item?.({item:l}))}),t.sortable?ke("span",{id:ee,style:$e},"Press space or enter to pick up this item. While picked up, use the arrow keys to move it, space or enter to drop it, or escape to cancel."):null,t.sortable?ke("span",{id:G,role:"status","aria-live":"polite",style:$e},$.value):null])}});const Pt=_e({__name:"PlaceholderCanvas",props:{rgba:{type:[Object,null],required:!0}},setup(t,{expose:n}){n();const s=t,e=O();function a(){const o=e.value;if(!o||!s.rgba)return;o.width=s.rgba.width,o.height=s.rgba.height;const i=o.getContext("2d");if(!i)return;const m=i.createImageData(s.rgba.width,s.rgba.height);m.data.set(s.rgba.data),i.putImageData(m,0,0)}Me(a),Fe(()=>s.rgba,a);const c={props:s,canvas:e,draw:a};return Object.defineProperty(c,"__isScriptSetup",{enumerable:!1,value:!0}),c}}),Nt={key:0,ref:"canvas",class:"canvas"},Tt={key:1,class:"canvas canvas--bad",title:"Could not decode this hash"};function jt(t,n,s,e,a,c){return s.rgba?(_(),k("canvas",Nt,null,512)):(_(),k("div",Tt,"?"))}const ut=Se(Pt,[["render",jt],["__scopeId","data-v-512bf9cf"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-hash/PlaceholderCanvas.vue"]]);var Ut=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F","G","H","I","J","K","L","M","N","O","P","Q","R","S","T","U","V","W","X","Y","Z","a","b","c","d","e","f","g","h","i","j","k","l","m","n","o","p","q","r","s","t","u","v","w","x","y","z","#","$","%","*","+",",","-",".",":",";","=","?","@","[","]","^","_","{","|","}","~"],ye=t=>{let n=0;for(let s=0;s<t.length;s++){let e=t[s],a=Ut.indexOf(e);n=n*83+a}return n},Pe=t=>{let n=t/255;return n<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)},Ne=t=>{let n=Math.max(0,Math.min(1,t));return n<=.0031308?Math.trunc(n*12.92*255+.5):Math.trunc((1.055*Math.pow(n,.4166666666666667)-.055)*255+.5)},Dt=t=>t<0?-1:1,Te=(t,n)=>Dt(t)*Math.pow(Math.abs(t),n),et=class extends Error{constructor(t){super(t),this.name="ValidationError",this.message=t}},Bt=t=>{if(!t||t.length<6)throw new et("The blurhash string must be at least 6 characters");let n=ye(t[0]),s=Math.floor(n/9)+1,e=n%9+1;if(t.length!==4+2*e*s)throw new et(`blurhash length mismatch: length is ${t.length} but it should be ${4+2*e*s}`)},Ft=t=>{let n=t>>16,s=t>>8&255,e=t&255;return[Pe(n),Pe(s),Pe(e)]},Ht=(t,n)=>{let s=Math.floor(t/361),e=Math.floor(t/19)%19,a=t%19;return[Te((s-9)/9,2)*n,Te((e-9)/9,2)*n,Te((a-9)/9,2)*n]},Vt=(t,n,s,e)=>{Bt(t),e=e|1;let a=ye(t[0]),c=Math.floor(a/9)+1,o=a%9+1,i=(ye(t[1])+1)/166,m=new Array(o*c);for(let y=0;y<m.length;y++)if(y===0){let h=ye(t.substring(2,6));m[y]=Ft(h)}else{let h=ye(t.substring(4+y*2,6+y*2));m[y]=Ht(h,i*e)}let M=n*4,w=new Uint8ClampedArray(M*s);for(let y=0;y<s;y++)for(let h=0;h<n;h++){let S=0,g=0,I=0;for(let E=0;E<c;E++)for(let j=0;j<o;j++){let R=Math.cos(Math.PI*h*j/n)*Math.cos(Math.PI*y*E/s),U=m[j+E*o];S+=U[0]*R,g+=U[1]*R,I+=U[2]*R}let b=Ne(S),v=Ne(g),z=Ne(I);w[4*h+0+y*M]=b,w[4*h+1+y*M]=v,w[4*h+2+y*M]=z,w[4*h+3+y*M]=255}return w},Gt=Vt;const tt=new Map;function nt(t,n){const s=t*4096+n;let e=tt.get(s);if(!e){e=new Float64Array(t*n);for(let a=0;a<t;a++)for(let c=0;c<n;c++)e[a*n+c]=Math.cos(Math.PI*a*(c+.5)/n);tt.set(s,e)}return e}function qt(t,n,s,e,a,c,o){const i=nt(s,a),m=nt(e,c),M=new Float64Array(s);for(let w=0;w<c;w++){for(let y=0;y<s;y++){let h=0;for(let S=0;S<e;S++){const g=t[S*n+y];g!==0&&(h+=g*m[S*c+w])}M[y]=h}for(let y=0;y<a;y++){let h=0;for(let S=0;S<s;S++)h+=M[S]*i[S*a+y];o[w*a+y]=h}}}var pe=class extends Error{constructor(t,n){super(n?`${t}: ${n}`:t),this.name="PlaceholderError",this.code=t}};const Wt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_",dt=new Int8Array(128).fill(-1);for(let t=0;t<64;t++)dt[Wt.charCodeAt(t)]=t;function Kt(t){const n=t.length;if(n%4===1)throw new pe("InvalidLength");const s=new Uint8Array(Math.floor(n*6/8));let e=0,a=0,c=0;for(let o=0;o<n;o++){const i=t.charCodeAt(o),m=i<128?dt[i]:-1;if(m<0)throw new pe("InvalidCharacter");e=e<<6|m,a+=6,a>=8&&(a-=8,s[c++]=e>>a&255,e&=(1<<a)-1)}return s}function Xt(t){return typeof t=="string"?Kt(t):t}var ft=class{constructor(t,n=0){this.bytes=t,this.pos=n*8,this.end=t.length*8}bit(){if(this.pos>=this.end)return 0;const t=this.pos++;return this.bytes[t>>3]>>7-(t&7)&1}bits(t){let n=0;for(let s=0;s<t;s++)n=n<<1|this.bit();return n>>>0}};function Yt(t,n){let s=0;for(;t.bit()===1;)s++;const e=s*(1<<n)+(n>0?t.bits(n):0);return e&1?-((e+1)/2):e/2}function Jt(t){return t?9:7}function Zt(t){return Math.pow(2,(t-32)/8)}function Qt(t,n){return t>=1?[n,Math.max(1,Math.round(n/t))]:[Math.max(1,Math.round(n*t)),n]}function $t(t){if(t.length<7||t.length>1024)throw new pe("InvalidLength");const n=new ft(t);if(n.bits(2)!==0)throw new pe("UnsupportedVersion");const s=n.bit()===1;if(s&&t.length<9)throw new pe("InvalidLength");const e={aspectCode:n.bits(6),alpha:s,Lx:n.bits(3)+1,Ly:n.bits(3)+1,Cx:n.bits(2)+1,Cy:n.bits(2)+1,Ax:1,Ay:1,dc:[0,0,0,0],scale:[0,0,0,0],k:[0,0,0,0]};for(let a=0;a<3;a++)e.dc[a]=n.bits(6);for(let a=0;a<3;a++)e.scale[a]=n.bits(4);for(let a=0;a<3;a++)e.k[a]=n.bits(2);return n.bit(),s&&(e.dc[3]=n.bits(5),e.Ax=n.bits(2)+1,e.Ay=n.bits(2)+1,e.scale[3]=n.bits(4),e.k[3]=n.bits(2)),e}const be={qmaxL:7,qmaxC:3,smaxL:.64,smaxC:.32,reconOffset:0};function en(t){return t===0?be.qmaxL:be.qmaxC}function tn(t,n,s,e){return 2*(t*e+n*s)<3*s*e}function qe(t,n){return n===0?[t.Lx,t.Ly]:n===3?[t.Ax,t.Ay]:[t.Cx,t.Cy]}function nn(t){const n=[],s=t.alpha?[0,1,2,3]:[0,1,2];for(const e of s){const[a,c]=qe(t,e);for(let o=0;o<c;o++)for(let i=0;i<a;i++)i===0&&o===0||!tn(i,o,a,c)||n.push({ch:e,i,j:o,nx:a,ny:c,qmax:en(e)})}return n.sort((e,a)=>{const c=e.i*e.i*e.ny*e.ny+e.j*e.j*e.nx*e.nx,o=e.nx*e.nx*e.ny*e.ny,i=a.i*a.i*a.ny*a.ny+a.j*a.j*a.nx*a.nx,m=c*(a.nx*a.nx*a.ny*a.ny)-i*o;return m!==0?m:e.ch!==a.ch?e.ch-a.ch:e.j!==a.j?e.j-a.j:e.i-a.i}),n}function xe(t,n,s){return t<n?n:t>s?s:t}function sn(t,n){return t===0?n/63:t===3?n/31:n*.64/63-.32}const on=Array.from({length:16},(t,n)=>Math.pow(2,-(15-n)/3));function an(t,n){return(t===1||t===2?be.smaxC:be.smaxL)*on[n]}function rn(t,n,s){if(t===0)return 0;const e=(Math.abs(t)-be.reconOffset)/s,a=n*e*e;return t<0?-a:a}function ln(t){return t<=.0031308?12.92*t:1.055*Math.pow(t,1/2.4)-.055}function je(t,n,s,e){const a=t+.3963377774*n+.2158037573*s,c=t-.1055613458*n-.0638541728*s,o=t-.0894841775*n-1.291485548*s,i=a*a*a,m=c*c*c,M=o*o*o;e[0]=4.0767416621*i-3.3077115913*m+.2309699292*M,e[1]=-1.2684380046*i+2.6097574011*m-.3413193965*M,e[2]=-.0041960863*i-.7034186147*m+1.707614701*M}const Ue=-5e-4,De=1.0005,st=[0,0,0];function ot(t){return t[0]>=Ue&&t[0]<=De&&t[1]>=Ue&&t[1]<=De&&t[2]>=Ue&&t[2]<=De}function cn(t,n,s,e){if(je(t,n,s,e),!ot(e)){let a=0,c=1;for(let o=0;o<8;o++){const i=(a+c)/2;je(t,n*i,s*i,st),ot(st)?a=i:c=i}je(t,n*a,s*a,e)}for(let a=0;a<3;a++)e[a]=e[a]<0?0:e[a]>1?1:e[a]}function un(t,n){const s=n,e=n.alpha?[0,1,2,3]:[0,1,2],a=[];for(const i of e){const[m,M]=qe(s,i),w=new Float64Array(m*M);w[0]=sn(i,n.dc[i]),a[i]=w}const c=e.map(i=>an(i,n.scale[i])),o=new ft(t,Jt(n.alpha));for(const i of nn(s)){let m=Yt(o,n.k[i.ch]);m=m>i.qmax?i.qmax:m<-i.qmax?-i.qmax:m,a[i.ch][i.j*i.nx+i.i]=rn(m,c[i.ch],i.qmax)}return a}function dn(t,n={}){const s=Xt(t),e=$t(s),a=Math.round(xe(n.size??32,4,128)),c=n.dither??!0,[o,i]=Qt(Zt(e.aspectCode),a),m=un(s,e),M=e,w=o*i,y=[];for(let g=0;g<m.length;g++){const[I,b]=qe(M,g),v=new Float64Array(w);qt(m[g],I,I,b,o,i,v),y.push(v)}const h=new Uint8ClampedArray(w*4),S=[0,0,0];for(let g=0;g<i;g++)for(let I=0;I<o;I++){const b=g*o+I;cn(xe(y[0][b],0,1),y[1][b],y[2][b],S);const v=c?at(52.9829189*at(.06711056*I+.00583715*g)):.5,z=b*4;for(let E=0;E<3;E++){const j=ln(S[E])*255;h[z+E]=xe(Math.floor(j+v),0,255)}h[z+3]=e.alpha?Math.round(xe(y[3][b],0,1)*255):255}return{width:o,height:i,data:h}}function at(t){return t-Math.floor(t)}function fn(t){let{PI:n,min:s,max:e,cos:a,round:c}=Math,o=t[0]|t[1]<<8|t[2]<<16,i=t[3]|t[4]<<8,m=(o&63)/63,M=(o>>6&63)/31.5-1,w=(o>>12&63)/31.5-1,y=(o>>18&31)/31,h=o>>23,S=(i>>3&63)/63,g=(i>>9&63)/63,I=i>>15,b=e(3,I?h?5:7:i&7),v=e(3,I?i&7:h?5:7),z=h?(t[5]&15)/15:1,E=(t[5]>>4)/15,j=h?6:5,R=0,U=(W,T,te)=>{let K=[];for(let l=0;l<T;l++)for(let d=l?0:1;d*T<W*(T-l);d++)K.push(((t[j+(R>>1)]>>((R++&1)<<2)&15)/7.5-1)*te);return K},Z=U(b,v,y),Q=U(3,3,S*1.25),se=U(3,3,g*1.25),de=h&&U(5,5,E),D=hn(t),F=c(D>1?32:32*D),$=c(D>1?32/D:32),ee=new Uint8Array(F*$*4),G=[],q=[];for(let W=0,T=0;W<$;W++)for(let te=0;te<F;te++,T+=4){let K=m,l=M,d=w,r=z;for(let x=0,N=e(b,h?5:3);x<N;x++)G[x]=a(n/F*(te+.5)*x);for(let x=0,N=e(v,h?5:3);x<N;x++)q[x]=a(n/$*(W+.5)*x);for(let x=0,N=0;x<v;x++)for(let B=x?0:1,ne=q[x]*2;B*v<b*(v-x);B++,N++)K+=Z[N]*G[B]*ne;for(let x=0,N=0;x<3;x++)for(let B=x?0:1,ne=q[x]*2;B<3-x;B++,N++){let fe=G[B]*ne;l+=Q[N]*fe,d+=se[N]*fe}if(h)for(let x=0,N=0;x<5;x++)for(let B=x?0:1,ne=q[x]*2;B<5-x;B++,N++)r+=de[N]*G[B]*ne;let f=K-2/3*l,p=(3*K-f+d)/2,P=p-d;ee[T]=e(0,255*s(1,p)),ee[T+1]=e(0,255*s(1,P)),ee[T+2]=e(0,255*s(1,f)),ee[T+3]=e(0,255*s(1,r))}return{w:F,h:$,rgba:ee}}function hn(t){let n=t[3],s=t[2]&128,e=t[4]&128,a=e?s?5:7:n&7,c=e?n&7:s?5:7;return a/c}const ge=32;function mn(t,n,s){const e=n>0&&s>0?n/s:1,a=e>=1?ge:Math.max(1,Math.round(ge*e)),c=e>=1?Math.max(1,Math.round(ge/e)):ge;try{return{width:a,height:c,data:Gt(t,a,c)}}catch{return null}}function vn(t){try{const n=atob(t),s=Uint8Array.from(n,a=>a.charCodeAt(0)),e=fn(s);return{width:e.w,height:e.h,data:new Uint8ClampedArray(e.rgba)}}catch{return null}}function yn(t){try{const n=dn(t,{size:ge});return{width:n.width,height:n.height,data:new Uint8ClampedArray(n.data)}}catch{return null}}function ht(t,n,s,e){return t==="blurhash"?mn(n,s,e):t==="thumbhash"?vn(n):yn(n)}const gn=_e({__name:"ResultCard",props:{entry:{type:Object,required:!0}},emits:["open"],setup(t,{expose:n,emit:s}){n();const e=t,a=s,c=["hazehash","blurhash","thumbhash"],{copied:o,copy:i}=it(),m=V(()=>{const{width:h,height:S}=e.entry;return h>0&&S>0?Math.min(Math.max(h/S,.5),2):1}),M=V(()=>c.filter(h=>e.entry[h]!==void 0).map(h=>({type:h,rgba:ht(h,e.entry[h],e.entry.width,e.entry.height)}))),w=V(()=>{const h=[];for(const S of["hazehash","blurhash","thumbhash","color"]){const g=e.entry[S];g!==void 0&&h.push({key:S,value:g})}return h}),y={props:e,emit:a,DECODABLE:c,copied:o,copy:i,aspect:m,decoded:M,lines:w,get imageUrl(){return rt},Icon:Ge,PlaceholderCanvas:ut};return Object.defineProperty(y,"__isScriptSetup",{enumerable:!1,value:!0}),y}}),pn={class:"item card"},bn=["aria-label"],_n=["alt","src"],wn={class:"strip__label"},kn=["src"],xn={class:"meta"},Mn=["title"],Sn={class:"muted"},Cn={class:"hashes"},In={class:"hashes__key"},zn=["title"],An=["aria-label","onClick"];function En(t,n,s,e,a,c){return _(),k("article",pn,[u("button",{class:"item__open","aria-label":`Open ${s.entry.file}`,onClick:n[0]||(n[0]=o=>e.emit("open"))},[u("span",{class:"shots",style:me({aspectRatio:String(e.aspect)})},[u("img",{class:"shot",loading:"lazy",alt:s.entry.file,src:e.imageUrl(s.entry.path,480)},null,8,_n)],4),e.decoded.length>0?(_(),k("span",{key:0,class:"strip",style:me({aspectRatio:String(e.aspect*e.decoded.length)})},[(_(!0),k(re,null,ue(e.decoded,o=>(_(),k("span",{key:o.type,class:"strip__cell"},[J(e.PlaceholderCanvas,{rgba:o.rgba},null,8,["rgba"]),u("span",wn,C(o.type),1)]))),128))],4)):L("v-if",!0),s.entry.preview?(_(),k("img",{key:1,class:"preview",alt:"Tiny preview",src:s.entry.preview},null,8,kn)):L("v-if",!0)],8,bn),u("div",xn,[u("strong",{class:"meta__name",title:s.entry.path},C(s.entry.file),9,Mn),u("span",Sn,C(s.entry.width)+"×"+C(s.entry.height),1)]),u("ul",Cn,[(_(!0),k(re,null,ue(e.lines,o=>(_(),k("li",{key:o.key},[u("span",In,[o.key==="color"?(_(),k("span",{key:0,class:"swatch",style:me({background:o.value})},null,4)):L("v-if",!0),le(" "+C(o.key),1)]),u("code",{class:"hashes__value",title:o.value},C(o.value),9,zn),u("button",{class:"btn btn--ghost btn--small","aria-label":`Copy ${o.key}`,onClick:i=>e.copy(o.key,o.value)},[J(e.Icon,{name:e.copied===o.key?"check":"copy",size:14},null,8,["name"])],8,An)]))),128))])])}const On=Se(gn,[["render",En],["__scopeId","data-v-e50ba89f"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-hash/ResultCard.vue"]]),Ln=_e({__name:"ResultModal",props:{entries:{type:Array,required:!0},index:{type:Number,required:!0}},emits:["close","update:index"],setup(t,{expose:n,emit:s}){n();const e=t,a=s,c=["hazehash","blurhash","thumbhash"],{copied:o,copy:i}=it(),m=V(()=>e.entries[e.index]),M=V(()=>e.index>0),w=V(()=>e.index<e.entries.length-1),y=V(()=>{const{width:v,height:z}=m.value;return v>0&&z>0?v/z:1}),h=V(()=>c.filter(v=>m.value[v]!==void 0).map(v=>({type:v,rgba:ht(v,m.value[v],m.value.width,m.value.height)}))),S=V(()=>{const v=[];for(const z of["hazehash","blurhash","thumbhash","color"]){const E=m.value[z];E!==void 0&&v.push({key:z,value:E})}return v});function g(v){const z=e.index+v;z>=0&&z<e.entries.length&&a("update:index",z)}function I(v){v.target instanceof HTMLInputElement||(v.key==="ArrowLeft"&&g(-1),v.key==="ArrowRight"&&g(1))}Me(()=>window.addEventListener("keydown",I)),Ve(()=>window.removeEventListener("keydown",I));const b={props:e,emit:a,DECODABLE:c,copied:o,copy:i,entry:m,hasPrev:M,hasNext:w,aspect:y,decoded:h,lines:S,go:g,onKey:I,get imageUrl(){return rt},Icon:Ge,UiModal:bt,PlaceholderCanvas:ut};return Object.defineProperty(b,"__isScriptSetup",{enumerable:!1,value:!0}),b}}),Rn={class:"muted counter"},Pn=["disabled"],Nn=["disabled"],Tn={class:"scroll"},jn={class:"stage"},Un=["alt","src"],Dn={key:0,class:"compare"},Bn={key:0,class:"compare__item"},Fn=["src"],Hn={class:"facts"},Vn={class:"facts__row"},Gn={class:"facts__mono"},qn={class:"facts__row"},Wn={class:"facts__mono facts__hash"},Kn=["aria-label","onClick"];function Xn(t,n,s,e,a,c){return _(),lt(e.UiModal,{title:e.entry.file,width:"1040px",onClose:n[2]||(n[2]=o=>e.emit("close"))},{actions:He(()=>[u("span",Rn,C(s.index+1)+" / "+C(s.entries.length),1),u("button",{class:"btn btn--small",disabled:!e.hasPrev,"aria-label":"Previous image",onClick:n[0]||(n[0]=o=>e.go(-1))},[J(e.Icon,{name:"left",size:15})],8,Pn),u("button",{class:"btn btn--small",disabled:!e.hasNext,"aria-label":"Next image",onClick:n[1]||(n[1]=o=>e.go(1))},[J(e.Icon,{name:"right",size:15})],8,Nn)]),default:He(()=>[u("div",Tn,[u("div",jn,[(_(),k("img",{key:e.entry.path,class:"stage__img",alt:e.entry.file,src:e.imageUrl(e.entry.path,1600)},null,8,Un))]),e.decoded.length?(_(),k("div",Dn,[(_(!0),k(re,null,ue(e.decoded,o=>(_(),k("figure",{key:o.type,class:"compare__item"},[u("div",{class:"compare__frame",style:me({aspectRatio:String(e.aspect)})},[J(e.PlaceholderCanvas,{rgba:o.rgba},null,8,["rgba"])],4),u("figcaption",null,C(o.type),1)]))),128)),e.entry.preview?(_(),k("figure",Bn,[u("div",{class:"compare__frame",style:me({aspectRatio:String(e.aspect)})},[u("img",{class:"compare__preview",alt:"Tiny preview",src:e.entry.preview},null,8,Fn)],4),n[3]||(n[3]=u("figcaption",null,"preview",-1))])):L("v-if",!0)])):L("v-if",!0),u("dl",Hn,[u("div",Vn,[n[4]||(n[4]=u("dt",null,"File",-1)),u("dd",Gn,C(e.entry.path),1)]),u("div",qn,[n[5]||(n[5]=u("dt",null,"Size",-1)),u("dd",null,C(e.entry.width)+" × "+C(e.entry.height)+" px",1)]),(_(!0),k(re,null,ue(e.lines,o=>(_(),k("div",{key:o.key,class:"facts__row"},[u("dt",null,[o.key==="color"?(_(),k("span",{key:0,class:"swatch",style:me({background:o.value})},null,4)):L("v-if",!0),le(" "+C(o.key),1)]),u("dd",Wn,C(o.value),1),u("button",{class:"btn btn--ghost btn--small","aria-label":`Copy ${o.key}`,onClick:i=>e.copy(o.key,o.value)},[J(e.Icon,{name:e.copied===o.key?"check":"copy",size:14},null,8,["name"])],8,Kn)]))),128))])])]),_:1},8,["title"])}const Yn=Se(Ln,[["render",Xn],["__scopeId","data-v-6aef2e16"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-hash/ResultModal.vue"]]),Be=48,Jn=_e({__name:"ImageHashPage",props:{module:{type:Object,required:!0},status:{type:null,required:!0}},setup(t,{expose:n}){n();const s={columns:"auto",minLaneSize:250,gap:14},e=["auto","3x3","4x3","4x4","5x4","6x4","8x6"],a={json:"json",plain:"txt",csv:"csv",ts:"ts",js:"js"},c=O(),o=O([]),i=O(!0),m=O(["hazehash","color"]),M=O(28),w=O("auto"),y=O("json"),h=O("imageHashes"),S=O(null),g=O("idle"),I=O({done:0,total:0,cached:0}),b=O(""),v=O(),z=O("gallery"),E=O(Be),j=O(""),R=O(""),U=O(!1);let Z;const Q=V(()=>b.value.toLowerCase().includes("sharp")),se=V(()=>o.value.length>0&&m.value.length>0&&g.value!=="running"),de=V(()=>I.value.total>0?Math.round(I.value.done/I.value.total*100):0),D=V(()=>v.value?.entries.slice(0,E.value)??[]),F=V(()=>D.value.map((l,d)=>({id:l.path,position:d})));function $(l){return D.value[Number(l.position)]}function ee(l){m.value=m.value.includes(l)?m.value.filter(d=>d!==l):[...m.value,l]}function G(l,d){const r=l.includes("\\")?"\\":"/";return`${l}${l.endsWith(r)?"":r}image-hashes.${a[d]??"txt"}`}async function q(l=!1){Z?.(),g.value="running",b.value="",v.value=void 0,R.value="",I.value={done:0,total:0,cached:0},E.value=Be,S.value=null;try{const{jobId:d}=await Ee.post("/api/image-hash/run",{paths:o.value,recursive:i.value,types:m.value,components:w.value,budget:M.value,format:y.value,exportName:h.value,installSharp:l});Z=yt(d,{onProgress:r=>{I.value=r},onDone:r=>{v.value=r,g.value="done",z.value="gallery",j.value=G(r.base,r.format)},onFailed:r=>{b.value=r,g.value="failed"}})}catch(d){b.value=d instanceof Error?d.message:String(d),g.value="failed"}}async function W(){if(v.value?.output)try{await navigator.clipboard.writeText(v.value.output),U.value=!0,setTimeout(()=>U.value=!1,1200)}catch{U.value=!1}}function T(){const l=v.value?.output;if(!l)return;const d=new Blob([l],{type:"text/plain;charset=utf-8"}),r=document.createElement("a");r.href=URL.createObjectURL(d),r.download=`image-hashes.${a[v.value?.format??"json"]??"txt"}`,r.click(),URL.revokeObjectURL(r.href)}async function te(l=!1){if(v.value?.output){R.value="";try{const d=await Ee.post("/api/image-hash/save",{path:j.value,content:v.value.output,overwrite:l});R.value=`Saved to ${d.path}`}catch(d){if(d instanceof gt&&d.status===409){window.confirm(`${d.message}. Replace it?`)&&await te(!0);return}R.value=d instanceof Error?d.message:String(d)}}}Me(async()=>{try{c.value=await Ee.get("/api/image-hash/options"),M.value=c.value.budget.default,w.value=c.value.components.auto?"auto":c.value.components.default,h.value=c.value.exportName}catch(l){b.value=l instanceof Error?l.message:String(l),g.value="failed"}}),Ve(()=>{Z?.()});const K={PAGE:Be,MASONRY_OPTIONS:s,COMPONENT_CHOICES:e,EXTENSIONS:a,options:c,sources:o,recursive:i,types:m,budget:M,components:w,format:y,exportName:h,viewing:S,phase:g,progress:I,failure:b,result:v,tab:z,shown:E,savePath:j,saveNote:R,copiedOutput:U,get stopWatching(){return Z},set stopWatching(l){Z=l},needsSharp:Q,canRun:se,percent:de,visible:D,masonryItems:F,entryOf:$,toggleType:ee,defaultSavePath:G,run:q,copyOutput:W,download:T,save:te,get MasonryGrid(){return Rt},SourcePicker:pt,Icon:Ge,ResultCard:On,ResultModal:Yn};return Object.defineProperty(K,"__isScriptSetup",{enumerable:!1,value:!0}),K}}),Zn={class:"page"},Qn={class:"page__head"},$n={class:"muted"},es={key:0,class:"notice notice--warn"},ts={class:"card block"},ns={class:"types"},ss=["checked","onChange"],os={class:"type__title"},as={class:"type__text muted"},rs={class:"grid"},ls={key:0,class:"field"},is=["min","max"],cs={key:1,class:"field"},us=["value"],ds={class:"field"},fs=["value"],hs={key:2,class:"field"},ms={class:"runbar"},vs=["disabled"],ys={key:0,class:"muted"},gs={key:1,class:"muted"},ps={key:1,class:"card block",role:"status"},bs={class:"progress"},_s={class:"muted"},ws={key:0},ks={key:2,class:"notice notice--error"},xs={key:3,class:"card block"},Ms={class:"block__head"},Ss={class:"muted"},Cs={key:0},Is={key:1},zs={key:0,class:"errors"},As={class:"tabs",role:"tablist"},Es=["aria-selected"],Os=["aria-selected"],Ls={key:0,class:"muted"},Rs={key:1,class:"more"},Ps={class:"outbar"},Ns=["disabled"],Ts={key:0,class:"muted"},js={class:"output"};function Us(t,n,s,e,a,c){return _(),k("div",Zn,[u("header",Qn,[u("h1",null,C(s.module.title),1),u("p",$n,C(s.module.description),1)]),e.options&&!e.options.sharp?(_(),k("div",es," The sharp image library is not installed yet. Previews are limited, and the first run will offer to install it. ")):L("v-if",!0),J(e.SourcePicker,{sources:e.sources,"onUpdate:sources":n[0]||(n[0]=o=>e.sources=o),recursive:e.recursive,"onUpdate:recursive":n[1]||(n[1]=o=>e.recursive=o),"scan-url":"/api/image-hash/scan",start:s.status?.cwd??""},null,8,["sources","recursive","start"]),u("section",ts,[n[19]||(n[19]=u("h2",null,"Placeholders",-1)),u("div",ns,[(_(!0),k(re,null,ue(e.options?.types,o=>(_(),k("label",{key:o.id,class:Oe(["type",{"type--on":e.types.includes(o.id)}])},[u("input",{type:"checkbox",checked:e.types.includes(o.id),onChange:i=>e.toggleType(o.id)},null,40,ss),u("span",os,C(o.title),1),u("span",as,C(o.description),1)],2))),128))]),u("div",rs,[e.types.includes("hazehash")?(_(),k("label",ls,[u("span",null,"Hazehash size: "+C(e.budget)+" bytes",1),ve(u("input",{"onUpdate:modelValue":n[2]||(n[2]=o=>e.budget=o),type:"range",min:e.options?.budget.min,max:e.options?.budget.max},null,8,is),[[Le,e.budget,void 0,{number:!0}]])])):L("v-if",!0),e.types.includes("blurhash")?(_(),k("label",cs,[n[16]||(n[16]=u("span",null,"Blurhash components",-1)),ve(u("select",{"onUpdate:modelValue":n[3]||(n[3]=o=>e.components=o),class:"select"},[(_(),k(re,null,ue(e.COMPONENT_CHOICES,o=>u("option",{key:o,value:o},C(o==="auto"?"auto (by aspect ratio)":o),9,us)),64))],512),[[Ye,e.components]])])):L("v-if",!0),u("label",ds,[n[17]||(n[17]=u("span",null,"Output format",-1)),ve(u("select",{"onUpdate:modelValue":n[4]||(n[4]=o=>e.format=o),class:"select"},[(_(!0),k(re,null,ue(e.options?.formats,o=>(_(),k("option",{key:o,value:o},C(o),9,fs))),128))],512),[[Ye,e.format]])]),e.format==="ts"||e.format==="js"?(_(),k("label",hs,[n[18]||(n[18]=u("span",null,"Export name",-1)),ve(u("input",{"onUpdate:modelValue":n[5]||(n[5]=o=>e.exportName=o),class:"input",spellcheck:"false"},null,512),[[Le,e.exportName]])])):L("v-if",!0)])]),u("div",ms,[u("button",{class:"btn btn--primary",disabled:!e.canRun,onClick:n[6]||(n[6]=o=>e.run(!1))},[J(e.Icon,{name:"play",size:15}),le(" "+C(e.phase==="running"?"Working…":"Compute hashes"),1)],8,vs),e.sources.length===0?(_(),k("span",ys,"Add at least one folder or image.")):e.types.length===0?(_(),k("span",gs,"Pick at least one placeholder.")):L("v-if",!0)]),e.phase==="running"?(_(),k("div",ps,[u("div",bs,[u("div",{class:"progress__bar",style:me({width:`${e.percent}%`})},null,4)]),u("span",_s,[le(C(e.progress.done)+" of "+C(e.progress.total||"…")+" images",1),e.progress.cached?(_(),k("span",ws," · "+C(e.progress.cached)+" from cache",1)):L("v-if",!0)])])):L("v-if",!0),e.phase==="failed"?(_(),k("div",ks,[u("p",null,C(e.failure),1),e.needsSharp?(_(),k("button",{key:0,class:"btn btn--small",onClick:n[7]||(n[7]=o=>e.run(!0))}," Install sharp and retry ")):L("v-if",!0)])):L("v-if",!0),e.result?(_(),k("section",xs,[u("div",Ms,[n[20]||(n[20]=u("h2",null,"Result",-1)),u("span",Ss,[le(C(e.result.entries.length)+" image"+C(e.result.entries.length===1?"":"s")+" ",1),e.result.cached?(_(),k("span",Cs,"· "+C(e.result.cached)+" cached",1)):L("v-if",!0),e.result.errors.length?(_(),k("span",Is,"· "+C(e.result.errors.length)+" failed",1)):L("v-if",!0)])]),e.result.errors.length?(_(),k("ul",zs,[(_(!0),k(re,null,ue(e.result.errors,o=>(_(),k("li",{key:o.file},[u("code",null,C(o.file),1),le(" — "+C(o.message),1)]))),128))])):L("v-if",!0),u("div",As,[u("button",{class:Oe(["tab",{"tab--on":e.tab==="gallery"}]),role:"tab","aria-selected":e.tab==="gallery",onClick:n[8]||(n[8]=o=>e.tab="gallery")}," Gallery ",10,Es),u("button",{class:Oe(["tab",{"tab--on":e.tab==="output"}]),role:"tab","aria-selected":e.tab==="output",onClick:n[9]||(n[9]=o=>e.tab="output")}," Output ("+C(e.result.format)+") ",11,Os)]),e.tab==="gallery"?(_(),k(re,{key:1},[e.result.entries.length===0?(_(),k("p",Ls,"No images were found.")):L("v-if",!0),J(e.MasonryGrid,{class:"gallery",items:e.masonryItems,options:e.MASONRY_OPTIONS},{item:He(({item:o})=>[J(e.ResultCard,{entry:e.entryOf(o),onOpen:i=>e.viewing=Number(o.position)},null,8,["entry","onOpen"])]),_:1},8,["items"]),e.shown<e.result.entries.length?(_(),k("div",Rs,[u("button",{class:"btn",onClick:n[10]||(n[10]=o=>e.shown+=e.PAGE)}," Show more ("+C(e.result.entries.length-e.shown)+" left) ",1),u("button",{class:"btn",onClick:n[11]||(n[11]=o=>e.shown=e.result.entries.length)}," Show all ("+C(e.result.entries.length)+") ",1)])):L("v-if",!0)],64)):(_(),k(re,{key:2},[u("div",Ps,[u("button",{class:"btn btn--small",onClick:e.copyOutput},[J(e.Icon,{name:e.copiedOutput?"check":"copy",size:15},null,8,["name"]),le(" "+C(e.copiedOutput?"Copied":"Copy"),1)]),u("button",{class:"btn btn--small",onClick:e.download},[J(e.Icon,{name:"download",size:15}),n[21]||(n[21]=le(" Download ",-1))]),ve(u("input",{"onUpdate:modelValue":n[12]||(n[12]=o=>e.savePath=o),class:"input outbar__path",spellcheck:"false","aria-label":"File to write"},null,512),[[Le,e.savePath]]),u("button",{class:"btn btn--small",disabled:e.savePath.trim()==="",onClick:n[13]||(n[13]=o=>e.save(!1))},[J(e.Icon,{name:"save",size:15}),n[22]||(n[22]=le(" Write to file ",-1))],8,Ns)]),e.saveNote?(_(),k("p",Ts,C(e.saveNote),1)):L("v-if",!0),u("pre",js,C(e.result.output),1)],64))])):L("v-if",!0),e.result&&e.viewing!==null?(_(),lt(e.ResultModal,{key:4,index:e.viewing,"onUpdate:index":n[14]||(n[14]=o=>e.viewing=o),entries:e.result.entries,onClose:n[15]||(n[15]=o=>e.viewing=null)},null,8,["index","entries"])):L("v-if",!0)])}const Vs=Se(Jn,[["render",Us],["__scopeId","data-v-0458e07e"],["__file","C:/work/NPM/devtoolz/ui/src/modules/image-hash/ImageHashPage.vue"]]);export{Vs as default};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.block[data-v-297ee74f]{display:flex;flex-direction:column;gap:14px;padding:18px}.block__head[data-v-297ee74f]{display:flex;align-items:center;justify-content:space-between;gap:12px}.sources[data-v-297ee74f]{display:flex;flex-direction:column;gap:8px;margin:0;padding:0;list-style:none}.source[data-v-297ee74f]{display:flex;align-items:center;gap:10px;padding:6px 6px 6px 12px;border-radius:9px;background:var(--surface-2)}.source--bad[data-v-297ee74f]{background:var(--danger-soft);color:var(--danger)}.source__path[data-v-297ee74f]{flex:1;min-width:0;font-family:ui-monospace,Cascadia Code,SF Mono,Menlo,Consolas,monospace;font-size:12px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.source__stats[data-v-297ee74f]{flex:none;color:var(--muted);font-size:12px}.source--bad .source__stats[data-v-297ee74f]{color:inherit}.source__x[data-v-297ee74f]{display:grid;place-items:center;width:24px;height:24px;flex:none;border:0;border-radius:50%;background:transparent;color:inherit;cursor:pointer}.source__x[data-v-297ee74f]:hover{background:#7f7f7f33}@media(max-width:560px){.source[data-v-297ee74f]{flex-wrap:wrap}.source__stats[data-v-297ee74f]{order:3;width:100%}}.summary[data-v-297ee74f]{padding:10px 14px;border-radius:9px;background:var(--accent-soft)}.summary--warn[data-v-297ee74f]{background:var(--warn-soft);color:var(--warn)}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as V,u as F,w as T,e as U,I as A,m as I,r as C,f as S,g as j,a as D,o as t,c as o,h as i,t as c,i as x,j as v,F as y,b as E,n as M,k as L,v as O,l as b,p as R}from"./index-D8H-zVzo.js";import{F as G}from"./FolderBrowser-Cdzt7edI.js";const H=V({__name:"SourcePicker",props:I({scanUrl:{type:String,required:!0},start:{type:String,required:!0},title:{type:String,required:!1}},{sources:{type:Array,required:!0},sourcesModifiers:{},recursive:{type:Boolean,required:!0},recursiveModifiers:{}}),emits:I(["scanned"],["update:sources","update:recursive"]),setup(k,{expose:n,emit:g}){n();const e=k,a=F(k,"sources"),_=F(k,"recursive"),r=g,h=C(!1),u=C(),f=C(!1);let m,d=0;function w(s,l){return`${s} ${l}${s===1?"":"s"}`}function N(s){return u.value?.sources.find(l=>l.path===s)}function q(s){return s?s.exists?s.kind==="file"?S(s.bytes):s.files===0?"no images":`${w(s.files,"image")} · ${w(s.folders,"folder")} · ${S(s.bytes)}`:"not found":f.value?"…":""}function z(s){a.value=[...new Set([...a.value,...s])],h.value=!1}function P(s){a.value=a.value.filter(l=>l!==s)}function B(){if(clearTimeout(m),a.value.length===0){u.value=void 0,f.value=!1,r("scanned",void 0);return}f.value=!0,m=setTimeout(async()=>{const s=++d;try{const l=await j.post(e.scanUrl,{paths:a.value,recursive:_.value});s===d&&(u.value=l,r("scanned",l))}catch{s===d&&(u.value=void 0,r("scanned",void 0))}finally{s===d&&(f.value=!1)}},200)}T([a,_],B,{deep:!0,immediate:!0}),U(()=>clearTimeout(m));const p={props:e,sources:a,recursive:_,emit:r,browsing:h,scanned:u,scanning:f,get timer(){return m},set timer(s){m=s},get token(){return d},set token(s){d=s},plural:w,statsFor:N,describe:q,add:z,remove:P,schedule:B,get formatBytes(){return S},FolderBrowser:G,Icon:A};return Object.defineProperty(p,"__isScriptSetup",{enumerable:!1,value:!0}),p}}),J={class:"card block"},K={class:"block__head"},Q={key:0,class:"muted"},W={key:1,class:"sources"},X=["title"],Y={class:"source__stats"},Z=["aria-label","onClick"],$={class:"check"},ee={key:0,class:"muted"};function se(k,n,g,e,a,_){return t(),o("section",J,[i("div",K,[i("h2",null,c(g.title??"Images"),1),i("button",{class:"btn",onClick:n[0]||(n[0]=r=>e.browsing=!0)},[x(e.Icon,{name:"plus",size:16}),n[3]||(n[3]=v(" Add folder or images ",-1))])]),e.sources.length===0?(t(),o("p",Q," Add the folders and images to process. Subfolders are included when the box below is ticked. ")):(t(),o("ul",W,[(t(!0),o(y,null,E(e.sources,r=>(t(),o("li",{key:r,class:M(["source",{"source--bad":e.statsFor(r)?.exists===!1}])},[x(e.Icon,{name:e.statsFor(r)?.kind==="file"?"image":"folder",size:16},null,8,["name"]),i("span",{class:"source__path",title:r},c(r),9,X),i("span",Y,c(e.describe(e.statsFor(r))),1),i("button",{class:"source__x","aria-label":`Remove ${r}`,onClick:h=>e.remove(r)},[x(e.Icon,{name:"close",size:14})],8,Z)],2))),128))])),i("label",$,[L(i("input",{"onUpdate:modelValue":n[1]||(n[1]=r=>e.recursive=r),type:"checkbox"},null,512),[[O,e.recursive]]),n[4]||(n[4]=v(" Include subfolders",-1))]),e.sources.length>0?(t(),o("p",{key:2,class:M(["summary",{"summary--warn":e.scanned&&e.scanned.total.files===0}]),role:"status"},[e.scanning&&!e.scanned?(t(),o(y,{key:0},[v("Counting images…")],64)):e.scanned&&e.scanned.total.files===0?(t(),o(y,{key:1},[v(" No images found. Check the paths"+c(e.recursive?"":' or tick "Include subfolders"')+". ",1)],64)):e.scanned?(t(),o(y,{key:2},[i("strong",null,c(e.plural(e.scanned.total.files,"image")),1),v(" in "+c(e.plural(e.scanned.total.folders,"folder"))+" · "+c(e.formatBytes(e.scanned.total.bytes))+" ",1),e.scanning?(t(),o("span",ee,"· updating…")):b("v-if",!0)],64)):b("v-if",!0)],2)):b("v-if",!0),e.browsing?(t(),R(e.FolderBrowser,{key:3,start:e.sources[0]??g.start,onClose:n[2]||(n[2]=r=>e.browsing=!1),onConfirm:e.add},null,8,["start"])):b("v-if",!0)])}const te=D(H,[["render",se],["__scopeId","data-v-297ee74f"],["__file","C:/work/NPM/devtoolz/ui/src/components/SourcePicker.vue"]]);export{te as S};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.seg[data-v-b36a2015]{display:inline-flex;align-self:flex-start;flex-wrap:wrap;padding:3px;border:1px solid var(--border);border-radius:9px;background:var(--surface-2)}.seg__btn[data-v-b36a2015]{padding:5px 12px;border:0;border-radius:6px;background:transparent;color:var(--muted);cursor:pointer}.seg__btn[data-v-b36a2015]:focus-visible{outline:2px solid var(--accent);outline-offset:1px}.seg__btn--on[data-v-b36a2015]{background:var(--surface);color:var(--text);font-weight:600;box-shadow:var(--shadow)}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{d as n,u as d,m as i,a as u,o as l,c as r,F as c,b as _,n as m,t as p}from"./index-D8H-zVzo.js";const b=n({__name:"UiSegmented",props:i({options:{type:Array,required:!0},label:{type:String,required:!1}},{modelValue:{type:null,required:!0},modelModifiers:{}}),emits:["update:modelValue"],setup(o,{expose:s}){s();const e={model:d(o,"modelValue")};return Object.defineProperty(e,"__isScriptSetup",{enumerable:!1,value:!0}),e}}),f=["aria-label"],g=["aria-checked","title","onClick"];function v(o,s,t,e,k,y){return l(),r("div",{class:"seg",role:"radiogroup","aria-label":t.label},[(l(!0),r(c,null,_(t.options,a=>(l(),r("button",{key:a.value,class:m(["seg__btn",{"seg__btn--on":e.model===a.value}]),role:"radio","aria-checked":e.model===a.value,title:a.hint,onClick:S=>e.model=a.value},p(a.label),11,g))),128))],8,f)}const C=u(b,[["render",v],["__scopeId","data-v-b36a2015"],["__file","C:/work/NPM/devtoolz/ui/src/ui-components/UiSegmented.vue"]]);export{C as U};
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/scss-Cw6XMfVs.js","assets/css-Z72CF80r.js","assets/html-BlS82ilI.js","assets/javascript-wDzz0qaB.js","assets/vue-CwSeJimo.js","assets/typescript-BPQ3VLAy.js","assets/json-Cp-IABpG.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{_ as t}from"./index-D8H-zVzo.js";const c={ts:"typescript",js:"javascript",md:"markdown",yml:"yaml"},m=new Set(["typescript","tsx","javascript","jsx","vue","json","css","scss","html","markdown","yaml"]);let n;function d(){return n??=(async()=>{const[{createHighlighterCore:_},{createJavaScriptRegexEngine:i}]=await Promise.all([t(()=>import("./core-DVezgdzc.js"),[]),t(()=>import("./engine-javascript-CNmxVhbB.js"),[])]);return _({themes:[t(()=>import("./github-light-DAi9KRSo.js"),[]),t(()=>import("./github-dark-DHJKELXO.js"),[])],langs:[t(()=>import("./typescript-BPQ3VLAy.js"),[]),t(()=>import("./tsx-COt5Ahok.js"),[]),t(()=>import("./javascript-wDzz0qaB.js"),[]),t(()=>import("./jsx-g9-lgVsj.js"),[]),t(()=>import("./css-Z72CF80r.js"),[]),t(()=>import("./scss-Cw6XMfVs.js"),__vite__mapDeps([0,1])),t(()=>import("./html-BlS82ilI.js"),__vite__mapDeps([2,3,1])),t(()=>import("./json-Cp-IABpG.js"),[]),t(()=>import("./markdown-Cvjx9yec.js"),[]),t(()=>import("./yaml-Buea-lGh.js"),[]),t(()=>import("./vue-CwSeJimo.js"),__vite__mapDeps([4,1,3,5,6,2]))],engine:i()})})(),n}function s(_){return _.split(/\r\n|\r|\n/).map(i=>[{text:i,light:"",dark:"",bold:!1,italic:!1}])}async function v(_,i){const o=c[i]??i;if(!m.has(o))return s(_);try{return(await d()).codeToTokensWithThemes(_,{lang:o,themes:{light:"github-light",dark:"github-dark"}}).map(l=>l.map(r=>{const e=r.variants.light,E=r.variants.dark,a=e?.fontStyle??0;return{text:r.content,light:e?.color??"",dark:E?.color??"",bold:(a&2)!==0,italic:(a&1)!==0}}))}catch{return s(_)}}export{v as h,s as p};
|