From 68cbef51ec3ad082199911dcddf1e519a80c330e Mon Sep 17 00:00:00 2001 From: chrmc40 Date: Thu, 18 Jun 2026 22:06:57 -0700 Subject: [PATCH] Lineage subway tree view + viewer/modal polish - Lineage "subway" lanes: branch columns, spine + S-curve connectors, per-node expand/fold, header expand-all toggle, right-click Copy Path - Lineage fixes: show family when an image is opened by file path; new-gen banner moved off the lineage header to top-center; transparent scrollbar corner; hover-only branch controls; stale-refetch staleness guard + edge-keyed connectors + anomaly instrumentation - Modal-setup persistence: 3D scene, inpaint mask, prompt, upscale dials restore across reopen - Re-pose modal: auto-restore last setup, Re-Apply, pan/zoom + before/after Compare - Upscale modal: before/after Compare wipe - Pose Studio: name-your-file scene export; $name{} block rename mirroring - docs: README wordmark hero --- core/upscale_api.py | 17 + ...l-DSeVjwuq.js => ConfirmModal-BGcVYndw.js} | 6 +- ...7T_RcN.js => GeneratedGallery-Dw0CC3-N.js} | 10 +- ...enubar-PsG9jYP0.js => Menubar-DI-z1NzN.js} | 14 +- ...or-sxqUMRLP.js => PopupAnchor-C6OWGGTI.js} | 6 +- ...Bxw-taga.js => SettingsSlider-CKF_XmgB.js} | 6 +- ...ctions-Ckx5huYg.js => actions-WPfqiWYB.js} | 4 +- ...xt-D3RUFV-0.js => api-context-BFKo1mCD.js} | 4 +- js/lib/svelte/assets/promptchain-svelte.css | 136 +- ...TnIIw0.js => disclose-version-uq4tn5Y6.js} | 63 +- ...t-m0VtlDjX.js => index-client-iMRCrpBY.js} | 4 +- .../{input-Bjai8x-c.js => input-DFQhebEz.js} | 4 +- js/lib/svelte/promptchain-fullscreen.js | 10 +- js/lib/svelte/promptchain-gallery.js | 4 +- js/lib/svelte/promptchain-model-indicator.js | 8 +- js/lib/svelte/promptchain-model-settings.js | 12 +- js/lib/svelte/promptchain-node.js | 16 +- js/lib/svelte/promptchain-sidebar.js | 14 +- js/lib/svelte/promptchain-tag-builder.js | 10 +- js/lib/svelte/promptchain-tag-builder2.js | 10 +- js/lib/svelte/promptchain-viewer.js | 2671 ++++++++++------- ...{select-Dgaht2aI.js => select-Dp4ExMMc.js} | 4 +- .../{style-CbOHK2KU.js => style-Boi27oOu.js} | 4 +- js/pose-studio.js | 11 +- svelte-src/components/ImageViewer.svelte | 621 +++- .../components/LineageContextMenu.svelte | 6 + svelte-src/lib/lineage-lanes.js | 102 + 27 files changed, 2477 insertions(+), 1300 deletions(-) rename js/lib/svelte/{ConfirmModal-DSeVjwuq.js => ConfirmModal-BGcVYndw.js} (95%) rename js/lib/svelte/{GeneratedGallery-D27T_RcN.js => GeneratedGallery-Dw0CC3-N.js} (99%) rename js/lib/svelte/{Menubar-PsG9jYP0.js => Menubar-DI-z1NzN.js} (98%) rename js/lib/svelte/{PopupAnchor-sxqUMRLP.js => PopupAnchor-C6OWGGTI.js} (92%) rename js/lib/svelte/{SettingsSlider-Bxw-taga.js => SettingsSlider-CKF_XmgB.js} (98%) rename js/lib/svelte/{actions-Ckx5huYg.js => actions-WPfqiWYB.js} (79%) rename js/lib/svelte/{api-context-D3RUFV-0.js => api-context-BFKo1mCD.js} (87%) rename js/lib/svelte/{disclose-version-BjTnIIw0.js => disclose-version-uq4tn5Y6.js} (99%) rename js/lib/svelte/{index-client-m0VtlDjX.js => index-client-iMRCrpBY.js} (71%) rename js/lib/svelte/{input-Bjai8x-c.js => input-DFQhebEz.js} (94%) rename js/lib/svelte/{select-Dgaht2aI.js => select-Dp4ExMMc.js} (91%) rename js/lib/svelte/{style-CbOHK2KU.js => style-Boi27oOu.js} (90%) create mode 100644 svelte-src/lib/lineage-lanes.js diff --git a/core/upscale_api.py b/core/upscale_api.py index f78de00..58f3fa5 100644 --- a/core/upscale_api.py +++ b/core/upscale_api.py @@ -204,6 +204,23 @@ async def open_file(request): return web.json_response({"ok": True}) +@routes.get("/promptchain/file-path") +async def file_path(request): + """Return the resolved absolute disk path for an image so the viewer can copy + it to the clipboard. + + Loopback-only: the path is a SERVER-machine filesystem path — meaningless on a + remote client and not worth leaking. The frontend only offers Copy Path to + local clients; this is the backstop. + """ + if request.remote not in ("127.0.0.1", "::1"): + return error_response("file path is only available from the server machine", 403) + path, err = _resolve_request_path(request) + if err: + return error_response(err, 404) + return web.json_response({"path": os.path.normpath(path)}) + + def _show_file_properties_win(path): """Show the native Windows file-properties sheet for `path`. diff --git a/js/lib/svelte/ConfirmModal-DSeVjwuq.js b/js/lib/svelte/ConfirmModal-BGcVYndw.js similarity index 95% rename from js/lib/svelte/ConfirmModal-DSeVjwuq.js rename to js/lib/svelte/ConfirmModal-BGcVYndw.js index dd086e2..31bdd11 100644 --- a/js/lib/svelte/ConfirmModal-DSeVjwuq.js +++ b/js/lib/svelte/ConfirmModal-BGcVYndw.js @@ -1,5 +1,5 @@ -import { d as delegate, p as push, a as prop, u as user_effect, D as comment, v as first_child, i as if_block, k as append, l as pop, g as get, s as state, f as sibling, o as bind_this, e as set, t as template_effect, y as set_text, j as delegated, A as from_html, n as child } from "./disclose-version-BjTnIIw0.js"; -import { a as action } from "./actions-Ckx5huYg.js"; +import { d as delegate, p as push, a as prop, u as user_effect, D as comment, v as first_child, i as if_block, k as append, l as pop, g as get, s as state, f as sibling, o as bind_this, e as set, t as template_effect, y as set_text, j as delegated, A as from_html, n as child } from "./disclose-version-uq4tn5Y6.js"; +import { a as action } from "./actions-WPfqiWYB.js"; function portal(node) { document.body.appendChild(node); return { destroy() { @@ -87,4 +87,4 @@ export { ConfirmModal as C, portal as p }; -//# sourceMappingURL=ConfirmModal-DSeVjwuq.js.map +//# sourceMappingURL=ConfirmModal-BGcVYndw.js.map diff --git a/js/lib/svelte/GeneratedGallery-D27T_RcN.js b/js/lib/svelte/GeneratedGallery-Dw0CC3-N.js similarity index 99% rename from js/lib/svelte/GeneratedGallery-D27T_RcN.js rename to js/lib/svelte/GeneratedGallery-Dw0CC3-N.js index b3d24cd..bd98fdf 100644 --- a/js/lib/svelte/GeneratedGallery-D27T_RcN.js +++ b/js/lib/svelte/GeneratedGallery-Dw0CC3-N.js @@ -1,9 +1,9 @@ -import { d as delegate, p as push, a as prop, u as user_effect, i as if_block, g as get, o as bind_this, t as template_effect, k as append, l as pop, m as user_derived, n as child, v as first_child, f as sibling, j as delegated, r as event, A as from_html, s as state, y as set_text, w as each, h as set_class, z as index, e as set, c as proxy, C as tick, x as set_attribute, D as comment } from "./disclose-version-BjTnIIw0.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; +import { d as delegate, p as push, a as prop, u as user_effect, i as if_block, g as get, o as bind_this, t as template_effect, k as append, l as pop, m as user_derived, n as child, v as first_child, f as sibling, j as delegated, r as event, A as from_html, s as state, y as set_text, w as each, h as set_class, z as index, e as set, c as proxy, C as tick, x as set_attribute, D as comment } from "./disclose-version-uq4tn5Y6.js"; +import { s as set_style } from "./style-Boi27oOu.js"; import { app } from "/scripts/app.js"; import { j as justifiedLayout } from "./justified-layout-cyVM7i96.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { p as portal, C as ConfirmModal } from "./ConfirmModal-DSeVjwuq.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { p as portal, C as ConfirmModal } from "./ConfirmModal-BGcVYndw.js"; const GALLERY_ROW_HEIGHT_MIN = 40; const GALLERY_ROW_HEIGHT_MAX = 400; const ZOOM_FACTOR = 1.15; @@ -782,4 +782,4 @@ export { clampGalleryRowHeight as c, zoomGalleryRowHeight as z }; -//# sourceMappingURL=GeneratedGallery-D27T_RcN.js.map +//# sourceMappingURL=GeneratedGallery-Dw0CC3-N.js.map diff --git a/js/lib/svelte/Menubar-PsG9jYP0.js b/js/lib/svelte/Menubar-DI-z1NzN.js similarity index 98% rename from js/lib/svelte/Menubar-PsG9jYP0.js rename to js/lib/svelte/Menubar-DI-z1NzN.js index f7d318a..fee1a6e 100644 --- a/js/lib/svelte/Menubar-PsG9jYP0.js +++ b/js/lib/svelte/Menubar-DI-z1NzN.js @@ -1,10 +1,10 @@ -import { d as delegate, p as push, a as prop, u as user_effect, g as get, e as set, v as first_child, i as if_block, f as sibling, k as append, l as pop, s as state, m as user_derived, o as bind_this, j as delegated, n as child, D as comment, w as each, z as index, A as from_html, t as template_effect, h as set_class, r as event, y as set_text, x as set_attribute } from "./disclose-version-BjTnIIw0.js"; -import { o as onDestroy } from "./index-client-m0VtlDjX.js"; -import { h as html, P as PopupAnchor } from "./PopupAnchor-sxqUMRLP.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; +import { d as delegate, p as push, a as prop, u as user_effect, g as get, e as set, v as first_child, i as if_block, f as sibling, k as append, l as pop, s as state, m as user_derived, o as bind_this, j as delegated, n as child, D as comment, w as each, z as index, A as from_html, t as template_effect, h as set_class, r as event, y as set_text, x as set_attribute } from "./disclose-version-uq4tn5Y6.js"; +import { o as onDestroy } from "./index-client-iMRCrpBY.js"; +import { h as html, P as PopupAnchor } from "./PopupAnchor-C6OWGGTI.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { s as set_style } from "./style-Boi27oOu.js"; import { app } from "/scripts/app.js"; -import { b as bind_value } from "./input-Bjai8x-c.js"; +import { b as bind_value } from "./input-DFQhebEz.js"; var root_1$2 = from_html(`
`, 1); var root_2$2 = from_html(`
No matching options
`); var root_5$1 = from_html(``); @@ -592,4 +592,4 @@ export { Menubar as M, SearchableList as S }; -//# sourceMappingURL=Menubar-PsG9jYP0.js.map +//# sourceMappingURL=Menubar-DI-z1NzN.js.map diff --git a/js/lib/svelte/PopupAnchor-sxqUMRLP.js b/js/lib/svelte/PopupAnchor-C6OWGGTI.js similarity index 92% rename from js/lib/svelte/PopupAnchor-sxqUMRLP.js rename to js/lib/svelte/PopupAnchor-C6OWGGTI.js index 08bbfd9..6feb55c 100644 --- a/js/lib/svelte/PopupAnchor-sxqUMRLP.js +++ b/js/lib/svelte/PopupAnchor-C6OWGGTI.js @@ -1,5 +1,5 @@ -import { t as template_effect, R as active_effect, S as assign_nodes, T as get_first_child, U as remove_effect_dom, V as create_element, W as NAMESPACE_SVG, X as NAMESPACE_MATHML, b as block, Y as EFFECT_TRANSPARENT, B as BranchManager, c as proxy, d as delegate, p as push, a as prop, u as user_effect, o as bind_this, j as delegated, k as append, l as pop, A as from_html, n as child } from "./disclose-version-BjTnIIw0.js"; -import { a as onMount, o as onDestroy } from "./index-client-m0VtlDjX.js"; +import { t as template_effect, S as active_effect, T as assign_nodes, U as get_first_child, V as remove_effect_dom, W as create_element, X as NAMESPACE_SVG, Y as NAMESPACE_MATHML, b as block, Z as EFFECT_TRANSPARENT, B as BranchManager, c as proxy, d as delegate, p as push, a as prop, u as user_effect, o as bind_this, j as delegated, k as append, l as pop, A as from_html, n as child } from "./disclose-version-uq4tn5Y6.js"; +import { a as onMount, o as onDestroy } from "./index-client-iMRCrpBY.js"; function html(node, get_value, is_controlled = false, svg = false, mathml = false, skip_warning = false) { var anchor = node; var value = ""; @@ -155,4 +155,4 @@ export { PopupAnchor as P, html as h }; -//# sourceMappingURL=PopupAnchor-sxqUMRLP.js.map +//# sourceMappingURL=PopupAnchor-C6OWGGTI.js.map diff --git a/js/lib/svelte/SettingsSlider-Bxw-taga.js b/js/lib/svelte/SettingsSlider-CKF_XmgB.js similarity index 98% rename from js/lib/svelte/SettingsSlider-Bxw-taga.js rename to js/lib/svelte/SettingsSlider-CKF_XmgB.js index c79c0ff..d68903d 100644 --- a/js/lib/svelte/SettingsSlider-Bxw-taga.js +++ b/js/lib/svelte/SettingsSlider-CKF_XmgB.js @@ -1,5 +1,5 @@ -import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, i as if_block, g as get, f as sibling, t as template_effect, x as set_attribute, q as set_value, j as delegated, k as append, l as pop, m as user_derived, n as child, o as bind_this, w as each, h as set_class, y as set_text, z as index, A as from_html } from "./disclose-version-BjTnIIw0.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; +import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, i as if_block, g as get, f as sibling, t as template_effect, x as set_attribute, q as set_value, j as delegated, k as append, l as pop, m as user_derived, n as child, o as bind_this, w as each, h as set_class, y as set_text, z as index, A as from_html } from "./disclose-version-uq4tn5Y6.js"; +import { s as set_style } from "./style-Boi27oOu.js"; var root_2 = from_html(`
`); var root_3 = from_html(`
`); var root_4 = from_html(`
`); @@ -267,4 +267,4 @@ delegate([ export { SettingsSlider as S }; -//# sourceMappingURL=SettingsSlider-Bxw-taga.js.map +//# sourceMappingURL=SettingsSlider-CKF_XmgB.js.map diff --git a/js/lib/svelte/actions-Ckx5huYg.js b/js/lib/svelte/actions-WPfqiWYB.js similarity index 79% rename from js/lib/svelte/actions-Ckx5huYg.js rename to js/lib/svelte/actions-WPfqiWYB.js index 56c94f0..d398fc4 100644 --- a/js/lib/svelte/actions-Ckx5huYg.js +++ b/js/lib/svelte/actions-WPfqiWYB.js @@ -1,4 +1,4 @@ -import { a3 as effect, E as untrack, a8 as render_effect, a9 as deep_read_state, aa as safe_not_equal } from "./disclose-version-BjTnIIw0.js"; +import { a4 as effect, E as untrack, a9 as render_effect, aa as deep_read_state, ab as safe_not_equal } from "./disclose-version-uq4tn5Y6.js"; function action(dom, action2, get_value) { effect(() => { var payload = untrack(() => action2(dom, get_value == null ? void 0 : get_value()) || {}); @@ -29,4 +29,4 @@ function action(dom, action2, get_value) { export { action as a }; -//# sourceMappingURL=actions-Ckx5huYg.js.map +//# sourceMappingURL=actions-WPfqiWYB.js.map diff --git a/js/lib/svelte/api-context-D3RUFV-0.js b/js/lib/svelte/api-context-BFKo1mCD.js similarity index 87% rename from js/lib/svelte/api-context-D3RUFV-0.js rename to js/lib/svelte/api-context-BFKo1mCD.js index 4eec7ef..a652f8a 100644 --- a/js/lib/svelte/api-context-D3RUFV-0.js +++ b/js/lib/svelte/api-context-BFKo1mCD.js @@ -1,4 +1,4 @@ -import { O as setContext, N as getContext } from "./disclose-version-BjTnIIw0.js"; +import { P as setContext, O as getContext } from "./disclose-version-uq4tn5Y6.js"; const API_KEY = "pcr-api"; function provideApi(api) { setContext(API_KEY, api); @@ -41,4 +41,4 @@ export { safeJson as s, useApi as u }; -//# sourceMappingURL=api-context-D3RUFV-0.js.map +//# sourceMappingURL=api-context-BFKo1mCD.js.map diff --git a/js/lib/svelte/assets/promptchain-svelte.css b/js/lib/svelte/assets/promptchain-svelte.css index f35013a..6465b71 100644 --- a/js/lib/svelte/assets/promptchain-svelte.css +++ b/js/lib/svelte/assets/promptchain-svelte.css @@ -1374,12 +1374,16 @@ height: 36px; display: flex; align-items: center; - justify-content: center; + justify-content: space-between; + gap: 6px; + padding: 0 8px; + box-sizing: border-box; font-size: 11px; color: #888; border-bottom: 1px solid #222; flex-shrink: 0; } + .pcr-lin-count.svelte-5cciiw { white-space: nowrap; } .pcr-viewer-lineage-strip.svelte-5cciiw { flex: 1; overflow-y: auto; @@ -1513,6 +1517,129 @@ color: #666; flex-shrink: 0; } + + /* ── subway lanes: the rail grows horizontally into parallel vertical lanes ── */ + .pcr-viewer-lineage-visible.lanes.svelte-5cciiw { + width: auto; + max-width: 62vw; + } + .pcr-lin-lanes.svelte-5cciiw { + position: relative; + flex: 1; + display: flex; + flex-direction: row; + align-items: flex-start; + gap: 22px; + padding: 8px 12px; + overflow: auto; + } + .pcr-lin-lanes.svelte-5cciiw::-webkit-scrollbar { width: 7px; height: 7px; } + .pcr-lin-lanes.svelte-5cciiw::-webkit-scrollbar-track { background: transparent; } + .pcr-lin-lanes.svelte-5cciiw::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; } + /* both axes scroll here, so kill the default white corner where they meet */ + .pcr-lin-lanes.svelte-5cciiw::-webkit-scrollbar-corner { background: transparent; } + .pcr-lin-col.svelte-5cciiw { + display: flex; + flex-direction: column; + align-items: center; + gap: 22px; + flex: 0 0 auto; + } + /* SVG overlay lives inside the scroll content, so it translates with scroll for + free — geometry is only recomputed on expand/fold/resize/img-load. */ + .pcr-lin-connectors.svelte-5cciiw { + position: absolute; + top: 0; + left: 0; + pointer-events: none; + overflow: visible; + } + .pcr-lin-connectors.svelte-5cciiw path:where(.svelte-5cciiw) { + stroke: #4a4a4a; + stroke-width: 2; + fill: none; + } + .pcr-lin-expander.svelte-5cciiw { + position: absolute; + top: 2px; + right: 2px; + min-width: 16px; + height: 16px; + padding: 0 3px; + box-sizing: border-box; + font-size: 10px; + font-weight: 600; + line-height: 1; + border-radius: 4px; + border: 1px solid rgba(120, 120, 120, 0.6); + background: rgba(20, 20, 20, 0.82); + color: #cdd6e0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + z-index: 2; + } + .pcr-lin-expander.svelte-5cciiw:hover { + background: rgba(60, 60, 60, 0.95); + border-color: #888; + } + .pcr-lin-fold.svelte-5cciiw { + position: absolute; + bottom: 2px; + left: 2px; + width: 16px; + height: 16px; + padding: 0; + font-size: 11px; + line-height: 1; + border-radius: 4px; + border: 1px solid rgba(120, 120, 120, 0.6); + background: rgba(20, 20, 20, 0.82); + color: #cdd6e0; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + z-index: 2; + } + .pcr-lin-fold.svelte-5cciiw:hover { + background: rgba(60, 60, 60, 0.95); + border-color: #888; + } + /* ⊞/⊟ are actions, not status — keep them off the thumb until the node is + hovered so the strip isn't cluttered at rest (dot + layers badge stay). */ + .pcr-lin-expander.svelte-5cciiw, + .pcr-lin-fold.svelte-5cciiw { + opacity: 0; + pointer-events: none; + transition: opacity 0.12s; + } + .pcr-viewer-lineage-node.svelte-5cciiw:hover .pcr-lin-expander:where(.svelte-5cciiw), + .pcr-viewer-lineage-node.svelte-5cciiw:hover .pcr-lin-fold:where(.svelte-5cciiw) { + opacity: 1; + pointer-events: auto; + } + .pcr-lin-toggle.svelte-5cciiw { + display: flex; + align-items: center; + justify-content: center; + width: 20px; + height: 20px; + padding: 0; + flex-shrink: 0; + border: 1px solid #333; + border-radius: 4px; + background: #1a1a1a; + color: #9bb4c7; + font-size: 12px; + line-height: 1; + cursor: pointer; + transition: background 0.15s, border-color 0.15s, color 0.15s; + } + .pcr-lin-toggle.svelte-5cciiw:hover { background: #262626; border-color: #555; color: #cfe2f0; } + .pcr-lin-toggle.on.svelte-5cciiw { background: rgba(79, 195, 247, 0.15); border-color: #4fc3f7; color: #4fc3f7; } + /* compare-picking: dropdown open → strip thumbnails are click targets */ .pcr-viewer-lineage-node.compare-candidate.svelte-5cciiw { border-color: rgba(255, 221, 114, 0.6); @@ -1549,7 +1676,8 @@ .pcr-viewer-newgen-banner.svelte-5cciiw { position: absolute; top: 14px; - left: 14px; + left: 50%; + transform: translateX(-50%); z-index: 30; padding: 7px 13px; font-size: 12.5px; @@ -1562,8 +1690,8 @@ pointer-events: none; } @keyframes svelte-5cciiw-pcr-newgen-in { - from { opacity: 0; transform: translateY(-8px); } - to { opacity: 1; transform: translateY(0); } + from { opacity: 0; transform: translate(-50%, -8px); } + to { opacity: 1; transform: translate(-50%, 0); } } @keyframes svelte-5cciiw-pcr-newgen-out { to { opacity: 0; } diff --git a/js/lib/svelte/disclose-version-BjTnIIw0.js b/js/lib/svelte/disclose-version-uq4tn5Y6.js similarity index 99% rename from js/lib/svelte/disclose-version-BjTnIIw0.js rename to js/lib/svelte/disclose-version-uq4tn5Y6.js index 89752a8..05f1fb5 100644 --- a/js/lib/svelte/disclose-version-BjTnIIw0.js +++ b/js/lib/svelte/disclose-version-uq4tn5Y6.js @@ -4285,37 +4285,38 @@ export { autofocus as H, to_array as I, from_svg as J, - mount as K, - unmount as L, - effect_root as M, - getContext as N, - setContext as O, - clsx as P, - text as Q, - active_effect as R, - assign_nodes as S, - get_first_child as T, - remove_effect_dom as U, - create_element as V, - NAMESPACE_SVG as W, - NAMESPACE_MATHML as X, - EFFECT_TRANSPARENT as Y, - component_context as Z, - lifecycle_outside_component as _, + noop as K, + mount as L, + unmount as M, + effect_root as N, + getContext as O, + setContext as P, + clsx as Q, + text as R, + active_effect as S, + assign_nodes as T, + get_first_child as U, + remove_effect_dom as V, + create_element as W, + NAMESPACE_SVG as X, + NAMESPACE_MATHML as Y, + EFFECT_TRANSPARENT as Z, + component_context as _, prop as a, - set_selected as a0, - listen_to_event_and_reset_event as a1, - current_batch as a2, - effect as a3, - is_array as a4, - select_multiple_invalid_value as a5, - is as a6, - teardown as a7, - render_effect as a8, - deep_read_state as a9, - safe_not_equal as aa, - to_style as ab, - queue_micro_task as ac, + lifecycle_outside_component as a0, + set_selected as a1, + listen_to_event_and_reset_event as a2, + current_batch as a3, + effect as a4, + is_array as a5, + select_multiple_invalid_value as a6, + is as a7, + teardown as a8, + render_effect as a9, + deep_read_state as aa, + safe_not_equal as ab, + to_style as ac, + queue_micro_task as ad, block as b, proxy as c, delegate as d, @@ -4342,4 +4343,4 @@ export { set_text as y, index as z }; -//# sourceMappingURL=disclose-version-BjTnIIw0.js.map +//# sourceMappingURL=disclose-version-uq4tn5Y6.js.map diff --git a/js/lib/svelte/index-client-m0VtlDjX.js b/js/lib/svelte/index-client-iMRCrpBY.js similarity index 71% rename from js/lib/svelte/index-client-m0VtlDjX.js rename to js/lib/svelte/index-client-iMRCrpBY.js index c9102fe..7f40ebc 100644 --- a/js/lib/svelte/index-client-m0VtlDjX.js +++ b/js/lib/svelte/index-client-iMRCrpBY.js @@ -1,4 +1,4 @@ -import { Z as component_context, _ as lifecycle_outside_component, u as user_effect, E as untrack } from "./disclose-version-BjTnIIw0.js"; +import { _ as component_context, a0 as lifecycle_outside_component, u as user_effect, E as untrack } from "./disclose-version-uq4tn5Y6.js"; function onMount(fn) { if (component_context === null) { lifecycle_outside_component(); @@ -23,4 +23,4 @@ export { onMount as a, onDestroy as o }; -//# sourceMappingURL=index-client-m0VtlDjX.js.map +//# sourceMappingURL=index-client-iMRCrpBY.js.map diff --git a/js/lib/svelte/input-Bjai8x-c.js b/js/lib/svelte/input-DFQhebEz.js similarity index 94% rename from js/lib/svelte/input-Bjai8x-c.js rename to js/lib/svelte/input-DFQhebEz.js index e1b283e..53cd115 100644 --- a/js/lib/svelte/input-Bjai8x-c.js +++ b/js/lib/svelte/input-DFQhebEz.js @@ -1,4 +1,4 @@ -import { a1 as listen_to_event_and_reset_event, a2 as current_batch, C as tick, E as untrack, a8 as render_effect, a6 as is, a7 as teardown, ac as queue_micro_task } from "./disclose-version-BjTnIIw0.js"; +import { a2 as listen_to_event_and_reset_event, a3 as current_batch, C as tick, E as untrack, a9 as render_effect, a7 as is, a8 as teardown, ad as queue_micro_task } from "./disclose-version-uq4tn5Y6.js"; function bind_value(input, get, set = get) { var batches = /* @__PURE__ */ new WeakSet(); listen_to_event_and_reset_event(input, "input", async (is_reset) => { @@ -150,4 +150,4 @@ export { bind_value as b, bind_group as c }; -//# sourceMappingURL=input-Bjai8x-c.js.map +//# sourceMappingURL=input-DFQhebEz.js.map diff --git a/js/lib/svelte/promptchain-fullscreen.js b/js/lib/svelte/promptchain-fullscreen.js index a7e9729..30ab2d8 100644 --- a/js/lib/svelte/promptchain-fullscreen.js +++ b/js/lib/svelte/promptchain-fullscreen.js @@ -5,11 +5,11 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var _activeNodeId, _treeRoots, _openTabs, _activeWildcardTab, _compiledOutput, _compiledNegOutput, _imageUrl, _previewUrl, _progress, _isGenerating, _sidebarView, _fontSize, _renamingNodeId; -import { d as delegate, p as push, a as prop, i as if_block, f as sibling, t as template_effect, e as set, g as get, j as delegated, k as append, l as pop, s as state, n as child, A as from_html, x as set_attribute, u as user_effect, h as set_class, r as event, m as user_derived, Q as text, y as set_text, o as bind_this, w as each, z as index, D as comment, v as first_child, c as proxy, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { a as onMount, o as onDestroy } from "./index-client-m0VtlDjX.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; -import { b as bind_value } from "./input-Bjai8x-c.js"; -import { M as Menubar, S as SearchableList } from "./Menubar-PsG9jYP0.js"; +import { d as delegate, p as push, a as prop, i as if_block, f as sibling, t as template_effect, e as set, g as get, j as delegated, k as append, l as pop, s as state, n as child, A as from_html, x as set_attribute, u as user_effect, h as set_class, r as event, m as user_derived, R as text, y as set_text, o as bind_this, w as each, z as index, D as comment, v as first_child, c as proxy, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { a as onMount, o as onDestroy } from "./index-client-iMRCrpBY.js"; +import { s as set_style } from "./style-Boi27oOu.js"; +import { b as bind_value } from "./input-DFQhebEz.js"; +import { M as Menubar, S as SearchableList } from "./Menubar-DI-z1NzN.js"; var root_1$4 = from_html(``); var root$5 = from_html(`
Run 0 active
`); function Topbar($$anchor, $$props) { diff --git a/js/lib/svelte/promptchain-gallery.js b/js/lib/svelte/promptchain-gallery.js index 8ca3fe2..bbbfc2e 100644 --- a/js/lib/svelte/promptchain-gallery.js +++ b/js/lib/svelte/promptchain-gallery.js @@ -1,5 +1,5 @@ -import { L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { G as GeneratedGallery } from "./GeneratedGallery-D27T_RcN.js"; +import { M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { G as GeneratedGallery } from "./GeneratedGallery-Dw0CC3-N.js"; function mountGallery(target, props) { return mount(GeneratedGallery, { target, props }); } diff --git a/js/lib/svelte/promptchain-model-indicator.js b/js/lib/svelte/promptchain-model-indicator.js index 84c86a4..a0822ce 100644 --- a/js/lib/svelte/promptchain-model-indicator.js +++ b/js/lib/svelte/promptchain-model-indicator.js @@ -1,9 +1,9 @@ -import { p as push, a as prop, D as comment, v as first_child, i as if_block, g as get, k as append, l as pop, s as state, e as set, f as sibling, t as template_effect, r as event, A as from_html, n as child, y as set_text, x as set_attribute, d as delegate, c as proxy, u as user_effect, E as untrack, o as bind_this, j as delegated, C as tick, m as user_derived, w as each, z as index, h as set_class, F as update, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; -import { b as bind_value } from "./input-Bjai8x-c.js"; +import { p as push, a as prop, D as comment, v as first_child, i as if_block, g as get, k as append, l as pop, s as state, e as set, f as sibling, t as template_effect, r as event, A as from_html, n as child, y as set_text, x as set_attribute, d as delegate, c as proxy, u as user_effect, E as untrack, o as bind_this, j as delegated, C as tick, m as user_derived, w as each, z as index, h as set_class, F as update, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { s as set_style } from "./style-Boi27oOu.js"; +import { b as bind_value } from "./input-DFQhebEz.js"; import { e as extractPrecisions, r as resolveFilesForPrecision } from "./model-constants-WRFJ51jF.js"; import { api } from "/scripts/api.js"; -import { s as safeJson, H as HttpError } from "./api-context-D3RUFV-0.js"; +import { s as safeJson, H as HttpError } from "./api-context-BFKo1mCD.js"; var root_2$4 = from_html(`
`); var root_3$4 = from_html(`
`); var root_4$3 = from_html(`
`); diff --git a/js/lib/svelte/promptchain-model-settings.js b/js/lib/svelte/promptchain-model-settings.js index a21e021..00043dd 100644 --- a/js/lib/svelte/promptchain-model-settings.js +++ b/js/lib/svelte/promptchain-model-settings.js @@ -1,10 +1,10 @@ -import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, f as sibling, o as bind_this, t as template_effect, g as get, x as set_attribute, q as set_value, j as delegated, k as append, l as pop, m as user_derived, n as child, A as from_html, w as each, z as index, i as if_block, G as set_checked, y as set_text, h as set_class, v as first_child, D as comment, I as to_array, a0 as set_selected, Q as text, E as untrack, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; +import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, f as sibling, o as bind_this, t as template_effect, g as get, x as set_attribute, q as set_value, j as delegated, k as append, l as pop, m as user_derived, n as child, A as from_html, w as each, z as index, i as if_block, G as set_checked, y as set_text, h as set_class, v as first_child, D as comment, I as to_array, a1 as set_selected, R as text, E as untrack, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { s as set_style } from "./style-Boi27oOu.js"; import { F as FAMILIES, A as ARCHITECTURES } from "./model-constants-WRFJ51jF.js"; -import { S as SettingsSlider } from "./SettingsSlider-Bxw-taga.js"; -import { b as bind_value } from "./input-Bjai8x-c.js"; -import { b as bind_select_value } from "./select-Dgaht2aI.js"; -import { a as action } from "./actions-Ckx5huYg.js"; +import { S as SettingsSlider } from "./SettingsSlider-CKF_XmgB.js"; +import { b as bind_value } from "./input-DFQhebEz.js"; +import { b as bind_select_value } from "./select-Dp4ExMMc.js"; +import { a as action } from "./actions-WPfqiWYB.js"; var root$7 = from_html(`
–
`); function RangeSlider($$anchor, $$props) { push($$props, true); diff --git a/js/lib/svelte/promptchain-node.js b/js/lib/svelte/promptchain-node.js index 6011c4a..c5e752f 100644 --- a/js/lib/svelte/promptchain-node.js +++ b/js/lib/svelte/promptchain-node.js @@ -5,15 +5,15 @@ var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj)); var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value); var _mode, _switchIndex, _locked, _disabled, _collapsed, _connectedCount, _hasLabels, _switchLabel, _iterateCurrent, _iterateTotal, _iterateCycle, _switchOptions, _outputPanelOpen, _imagePanelVisible, _aiAssistantOpen, _posePanelVisible, _hasPoseStudio, _compiledOutput, _compiledNegOutput, _imageUrl, _previewUrl, _progress, _isGenerating, _rollSelected; -import { p as push, o as bind_this, k as append, l as pop, A as from_html, d as delegate, a as prop, g as get, j as delegated, m as user_derived, s as state, c as proxy, u as user_effect, i as if_block, f as sibling, r as event, e as set, C as tick, n as child, D as comment, v as first_child, w as each, t as template_effect, y as set_text, h as set_class, x as set_attribute, P as clsx, z as index, Q as text, E as untrack, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { u as useApi, p as provideApi } from "./api-context-D3RUFV-0.js"; -import { M as Menubar } from "./Menubar-PsG9jYP0.js"; -import { o as onDestroy, a as onMount } from "./index-client-m0VtlDjX.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; -import { h as html, P as PopupAnchor } from "./PopupAnchor-sxqUMRLP.js"; +import { p as push, o as bind_this, k as append, l as pop, A as from_html, d as delegate, a as prop, g as get, j as delegated, m as user_derived, s as state, c as proxy, u as user_effect, i as if_block, f as sibling, r as event, e as set, C as tick, n as child, D as comment, v as first_child, w as each, t as template_effect, y as set_text, h as set_class, x as set_attribute, Q as clsx, z as index, R as text, E as untrack, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { u as useApi, p as provideApi } from "./api-context-BFKo1mCD.js"; +import { M as Menubar } from "./Menubar-DI-z1NzN.js"; +import { o as onDestroy, a as onMount } from "./index-client-iMRCrpBY.js"; +import { s as set_style } from "./style-Boi27oOu.js"; +import { h as html, P as PopupAnchor } from "./PopupAnchor-C6OWGGTI.js"; import { api } from "/scripts/api.js"; -import { c as clampGalleryRowHeight, z as zoomGalleryRowHeight, G as GeneratedGallery } from "./GeneratedGallery-D27T_RcN.js"; -import { b as bind_value } from "./input-Bjai8x-c.js"; +import { c as clampGalleryRowHeight, z as zoomGalleryRowHeight, G as GeneratedGallery } from "./GeneratedGallery-Dw0CC3-N.js"; +import { b as bind_value } from "./input-DFQhebEz.js"; import { app } from "/scripts/app.js"; import { r as readNodePrompt, c as cryptoId, e as extractNGrams, m as matchCharactersInDb, i as isStandaloneMainPromptChain, a as applyPromptText } from "./ai-patch-helpers-Bayqv0oF.js"; var root$c = from_html(`
`); diff --git a/js/lib/svelte/promptchain-sidebar.js b/js/lib/svelte/promptchain-sidebar.js index 018ed9d..11f7bb4 100644 --- a/js/lib/svelte/promptchain-sidebar.js +++ b/js/lib/svelte/promptchain-sidebar.js @@ -1,11 +1,11 @@ -import { c as proxy, M as effect_root, u as user_effect, d as delegate, p as push, r as event, $ as $window, v as first_child, w as each, f as sibling, i as if_block, g as get, o as bind_this, t as template_effect, j as delegated, k as append, l as pop, s as state, e as set, m as user_derived, n as child, A as from_html, J as from_svg, h as set_class, y as set_text, z as index, q as set_value, x as set_attribute, a as prop, N as getContext, C as tick, D as comment, O as setContext, K as mount, L as unmount } from "./disclose-version-BjTnIIw0.js"; -import { a as onMount } from "./index-client-m0VtlDjX.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; +import { c as proxy, N as effect_root, u as user_effect, d as delegate, p as push, r as event, $ as $window, v as first_child, w as each, f as sibling, i as if_block, g as get, o as bind_this, t as template_effect, j as delegated, k as append, l as pop, s as state, e as set, m as user_derived, n as child, A as from_html, J as from_svg, h as set_class, y as set_text, z as index, q as set_value, x as set_attribute, a as prop, O as getContext, C as tick, D as comment, P as setContext, L as mount, M as unmount } from "./disclose-version-uq4tn5Y6.js"; +import { a as onMount } from "./index-client-iMRCrpBY.js"; +import { s as set_style } from "./style-Boi27oOu.js"; import { j as justifiedLayout } from "./justified-layout-cyVM7i96.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { b as bind_value, c as bind_group } from "./input-Bjai8x-c.js"; -import { p as portal, C as ConfirmModal } from "./ConfirmModal-DSeVjwuq.js"; -import { s as safeJson, H as HttpError } from "./api-context-D3RUFV-0.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { b as bind_value, c as bind_group } from "./input-DFQhebEz.js"; +import { p as portal, C as ConfirmModal } from "./ConfirmModal-BGcVYndw.js"; +import { s as safeJson, H as HttpError } from "./api-context-BFKo1mCD.js"; const VIEW_MODES = [ { id: "grid", label: "Grid" }, { id: "justified", label: "Justified" }, diff --git a/js/lib/svelte/promptchain-tag-builder.js b/js/lib/svelte/promptchain-tag-builder.js index 1d911a1..8467c36 100644 --- a/js/lib/svelte/promptchain-tag-builder.js +++ b/js/lib/svelte/promptchain-tag-builder.js @@ -1,9 +1,9 @@ -import { d as delegate, p as push, a as prop, w as each, z as index, g as get, f as sibling, i as if_block, k as append, l as pop, m as user_derived, n as child, h as set_class, j as delegated, A as from_html, t as template_effect, x as set_attribute, q as set_value, v as first_child, y as set_text, D as comment, s as state, c as proxy, u as user_effect, e as set, I as to_array, E as untrack, o as bind_this, G as set_checked, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { a as onMount, o as onDestroy } from "./index-client-m0VtlDjX.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { a as bind_checked, b as bind_value } from "./input-Bjai8x-c.js"; +import { d as delegate, p as push, a as prop, w as each, z as index, g as get, f as sibling, i as if_block, k as append, l as pop, m as user_derived, n as child, h as set_class, j as delegated, A as from_html, t as template_effect, x as set_attribute, q as set_value, v as first_child, y as set_text, D as comment, s as state, c as proxy, u as user_effect, e as set, I as to_array, E as untrack, o as bind_this, G as set_checked, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { a as onMount, o as onDestroy } from "./index-client-iMRCrpBY.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { a as bind_checked, b as bind_value } from "./input-DFQhebEz.js"; import { b as buildInsertText } from "./tag-builder-utils-ng134QDV.js"; -import { b as bind_select_value } from "./select-Dgaht2aI.js"; +import { b as bind_select_value } from "./select-Dp4ExMMc.js"; const MULTI_SELECT_GROUPS = ["props"]; const CUSTOMIZABLE_CLOTHING_GROUPS = [ "legwear", diff --git a/js/lib/svelte/promptchain-tag-builder2.js b/js/lib/svelte/promptchain-tag-builder2.js index 0fd0f8f..d679572 100644 --- a/js/lib/svelte/promptchain-tag-builder2.js +++ b/js/lib/svelte/promptchain-tag-builder2.js @@ -1,8 +1,8 @@ -import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, f as sibling, n as child, i as if_block, g as get, t as template_effect, j as delegated, k as append, l as pop, v as first_child, h as set_class, y as set_text, A as from_html, m as user_derived, w as each, z as index, I as to_array, C as tick, o as bind_this, D as comment, x as set_attribute, q as set_value, Q as text, L as unmount, K as mount } from "./disclose-version-BjTnIIw0.js"; -import { a as onMount } from "./index-client-m0VtlDjX.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; -import { a as bind_checked, b as bind_value } from "./input-Bjai8x-c.js"; +import { d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, e as set, f as sibling, n as child, i as if_block, g as get, t as template_effect, j as delegated, k as append, l as pop, v as first_child, h as set_class, y as set_text, A as from_html, m as user_derived, w as each, z as index, I as to_array, C as tick, o as bind_this, D as comment, x as set_attribute, q as set_value, R as text, M as unmount, L as mount } from "./disclose-version-uq4tn5Y6.js"; +import { a as onMount } from "./index-client-iMRCrpBY.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { s as set_style } from "./style-Boi27oOu.js"; +import { a as bind_checked, b as bind_value } from "./input-DFQhebEz.js"; import { b as isStructuralLine, d as isInNegativeBlock } from "./ai-patch-helpers-Bayqv0oF.js"; import { f as formatTagsForModel } from "./tag-builder-utils-ng134QDV.js"; var root_1$3 = from_html(`
Loading…
`); diff --git a/js/lib/svelte/promptchain-viewer.js b/js/lib/svelte/promptchain-viewer.js index 4c06f31..8ddc34e 100644 --- a/js/lib/svelte/promptchain-viewer.js +++ b/js/lib/svelte/promptchain-viewer.js @@ -1,12 +1,12 @@ -import { b as block, B as BranchManager, d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, g as get, e as set, i as if_block, f as sibling, t as template_effect, h as set_class, j as delegated, k as append, l as pop, m as user_derived, n as child, o as bind_this, q as set_value, r as event, v as first_child, w as each, x as set_attribute, y as set_text, z as index, A as from_html, C as tick, D as comment, E as untrack, F as update, G as set_checked, H as autofocus, I as to_array, J as from_svg, $ as $window, K as mount, L as unmount } from "./disclose-version-BjTnIIw0.js"; -import { o as onDestroy } from "./index-client-m0VtlDjX.js"; -import { s as set_style } from "./style-CbOHK2KU.js"; -import { a as action } from "./actions-Ckx5huYg.js"; -import { b as bind_value, a as bind_checked } from "./input-Bjai8x-c.js"; -import { i as init_select, s as select_option, b as bind_select_value } from "./select-Dgaht2aI.js"; -import { p as portal, C as ConfirmModal } from "./ConfirmModal-DSeVjwuq.js"; -import { S as SettingsSlider } from "./SettingsSlider-Bxw-taga.js"; -import { P as PopupAnchor, h as html } from "./PopupAnchor-sxqUMRLP.js"; +import { b as block, B as BranchManager, d as delegate, p as push, a as prop, s as state, c as proxy, u as user_effect, g as get, e as set, i as if_block, f as sibling, t as template_effect, h as set_class, j as delegated, k as append, l as pop, m as user_derived, n as child, o as bind_this, q as set_value, r as event, v as first_child, w as each, x as set_attribute, y as set_text, z as index, A as from_html, C as tick, D as comment, E as untrack, F as update, G as set_checked, H as autofocus, I as to_array, J as from_svg, $ as $window, K as noop, L as mount, M as unmount } from "./disclose-version-uq4tn5Y6.js"; +import { o as onDestroy } from "./index-client-iMRCrpBY.js"; +import { s as set_style } from "./style-Boi27oOu.js"; +import { a as action } from "./actions-WPfqiWYB.js"; +import { b as bind_value, a as bind_checked } from "./input-DFQhebEz.js"; +import { i as init_select, s as select_option, b as bind_select_value } from "./select-Dp4ExMMc.js"; +import { p as portal, C as ConfirmModal } from "./ConfirmModal-BGcVYndw.js"; +import { S as SettingsSlider } from "./SettingsSlider-CKF_XmgB.js"; +import { P as PopupAnchor, h as html } from "./PopupAnchor-C6OWGGTI.js"; const NAN = Symbol("NaN"); function key(node, get_key, render_fn) { var branches = new BranchManager(node); @@ -76,11 +76,11 @@ async function saveModalSetup(fetchApi, hash, kind, data, dims = null, planes = } } var root_1$7 = from_html(``); -var root_3$7 = from_html(` /`, 1); +var root_3$8 = from_html(` /`, 1); var root_2$8 = from_html(` `, 1); var root_5$7 = from_html(`
`); var root_4$7 = from_html(`
`); -var root$3 = from_html(`
`); +var root$2 = from_html(`
`); function SavePathInput($$anchor, $$props) { push($$props, true); let value = prop($$props, "value", 3, ""), onChange = prop($$props, "onChange", 3, () => { @@ -231,7 +231,7 @@ function SavePathInput($$anchor, $$props) { fetchApi()(`/promptchain/reveal-file?scope=output&path=${encodeURIComponent(rel)}`).catch(() => { }); } - var div = root$3(); + var div = root$2(); let classes; var div_1 = child(div); var node = child(div_1); @@ -283,7 +283,7 @@ function SavePathInput($$anchor, $$props) { var fragment = root_2$8(); var node_1 = first_child(fragment); each(node_1, 17, () => get(chips), index, ($$anchor3, chip, i) => { - var fragment_1 = root_3$7(); + var fragment_1 = root_3$8(); var button = first_child(fragment_1); let classes_1; var text_1 = child(button); @@ -358,13 +358,13 @@ function SavePathInput($$anchor, $$props) { pop(); } delegate(["click", "input", "keydown", "mousedown"]); -var root_3$6 = from_html(`
No matching models
`); -var root_6$5 = from_html(`
`); +var root_3$7 = from_html(`
No matching models
`); +var root_6$6 = from_html(`
`); var root_8$5 = from_html(``); -var root_7$5 = from_html(`
`); +var root_7$6 = from_html(`
`); var root_5$6 = from_html(` `, 1); var root_2$7 = from_html(`
`, 1); -var root$2 = from_html(` `, 1); +var root$1 = from_html(` `, 1); function SearchableSelect($$anchor, $$props) { push($$props, true); let id = prop($$props, "id", 3, ""), value = prop($$props, "value", 3, ""), groups = prop($$props, "groups", 19, () => []), disabled = prop($$props, "disabled", 3, false), popupKey = prop($$props, "popupKey", 3, "searchable-select"), placeholder = prop($$props, "placeholder", 3, "Search models..."), onpick = prop($$props, "onpick", 3, () => { @@ -454,7 +454,7 @@ function SearchableSelect($$anchor, $$props) { } return result; } - var fragment = root$2(); + var fragment = root$1(); var button = first_child(fragment); var span = child(button); var text_1 = child(span); @@ -486,7 +486,7 @@ function SearchableSelect($$anchor, $$props) { var node_1 = child(div_1); { var consequent = ($$anchor4) => { - var div_2 = root_3$6(); + var div_2 = root_3$7(); append($$anchor4, div_2); }; var alternate = ($$anchor4) => { @@ -497,7 +497,7 @@ function SearchableSelect($$anchor, $$props) { var node_3 = first_child(fragment_4); { var consequent_1 = ($$anchor6) => { - var div_3 = root_6$5(); + var div_3 = root_6$6(); var text_2 = child(div_3); template_effect(() => set_text(text_2, get(g).label)); append($$anchor6, div_3); @@ -509,7 +509,7 @@ function SearchableSelect($$anchor, $$props) { var node_4 = sibling(node_3, 2); each(node_4, 17, () => get(g).options, index, ($$anchor6, opt) => { const i = user_derived(() => get(flat).indexOf(get(opt))); - var div_4 = root_7$5(); + var div_4 = root_7$6(); let classes; var span_2 = child(div_4); html(span_2, () => highlightText(get(opt).label), true); @@ -569,17 +569,17 @@ function SearchableSelect($$anchor, $$props) { } delegate(["click", "keydown"]); var root_2$6 = from_html(``); -var root_3$5 = from_html(``); +var root_3$6 = from_html(``); var root_5$5 = from_html(`
Before
After
`, 1); -var root_7$4 = from_html(``); -var root_6$4 = from_html(`
`); +var root_7$5 = from_html(``); +var root_6$5 = from_html(`
`); var root_4$6 = from_html(`
`, 1); var root_9$4 = from_html(`
`); var root_10$4 = from_html(`
`); var root_12$4 = from_html(`
`); -var root_11$3 = from_html(`
`, 1); +var root_11$2 = from_html(`
`, 1); var root_8$4 = from_html(`
`); -var root_13$4 = from_html(``); +var root_13$3 = from_html(``); var root_14$4 = from_html(`

This image has no usable prompt metadata — a plain model upscale (ESRGAN) will be used.

`); var root_16$4 = from_html(` `); var root_17$4 = from_html(`re-renders the whole frame at ~2MP from your instruction — composition can shift slightly; the climb model below pushes to the target size`); @@ -603,8 +603,8 @@ var root_34$3 = from_html(`
`); var root_37$3 = from_html(``); var root_35$3 = from_html(`
`); -var root_39$2 = from_html(``); -var root_40$2 = from_html(``); +var root_39$3 = from_html(``); +var root_40$3 = from_html(``); var root_38$3 = from_html(`
`); var root_42$3 = from_html(` `); var root_44$3 = from_html(``); @@ -614,10 +614,10 @@ var root_48$2 = from_html(`
`); var root_41$3 = from_html(`
▶ Advanced
`, 1); var root_49$2 = from_html(`
Save to
`); -var root_51$2 = from_html(``); +var root_51$1 = from_html(``); var root_53$2 = from_html(``); var root_54$2 = from_html(``); -var root_52$2 = from_html(` `, 1); +var root_52$1 = from_html(` `, 1); var root_56$2 = from_html(``); var root_55$2 = from_html(` `, 1); var root_1$6 = from_html(`
`); @@ -1404,7 +1404,7 @@ function UpscaleOptionsModal($$anchor, $$props) { var node_3 = child(div_5); { var consequent_1 = ($$anchor3) => { - var img = root_3$5(); + var img = root_3$6(); template_effect(() => set_attribute(img, "src", get(liveTile))); append($$anchor3, img); }; @@ -1441,13 +1441,13 @@ function UpscaleOptionsModal($$anchor, $$props) { var node_5 = sibling(node_4, 2); { var consequent_4 = ($$anchor4) => { - var div_10 = root_6$4(); + var div_10 = root_6$5(); var span_1 = child(div_10); var text_2 = child(span_1); var node_6 = sibling(span_1, 2); { var consequent_3 = ($$anchor5) => { - var button_1 = root_7$4(); + var button_1 = root_7$5(); let classes_1; template_effect(() => classes_1 = set_class(button_1, 1, "pcr-up-fit-btn svelte-xw7bpl", null, classes_1, { on: get(compareSplit) })); delegated("click", button_1, toggleCompare); @@ -1498,7 +1498,7 @@ function UpscaleOptionsModal($$anchor, $$props) { append($$anchor4, div_13); }; var alternate = ($$anchor4) => { - var fragment_3 = root_11$3(); + var fragment_3 = root_11$2(); var div_14 = first_child(fragment_3); var text_5 = child(div_14); var div_15 = sibling(div_14, 2); @@ -1540,7 +1540,7 @@ function UpscaleOptionsModal($$anchor, $$props) { var node_10 = child(div_18); { var consequent_10 = ($$anchor3) => { - var button_3 = root_13$4(); + var button_3 = root_13$3(); delegated("click", button_3, applySavedSetup); append($$anchor3, button_3); }; @@ -2014,7 +2014,7 @@ function UpscaleOptionsModal($$anchor, $$props) { var select_5 = sibling(child(div_51), 2); let classes_12; each(select_5, 21, () => caps().samplerOptions, index, ($$anchor4, opt) => { - var option_9 = root_39$2(); + var option_9 = root_39$3(); let styles_6; var text_22 = child(option_9); var option_9_value = {}; @@ -2041,7 +2041,7 @@ function UpscaleOptionsModal($$anchor, $$props) { var select_6 = sibling(child(div_52), 2); let classes_13; each(select_6, 21, () => caps().schedulerOptions, index, ($$anchor4, opt) => { - var option_10 = root_40$2(); + var option_10 = root_40$3(); let styles_7; var text_23 = child(option_10); var option_10_value = {}; @@ -2243,7 +2243,7 @@ function UpscaleOptionsModal($$anchor, $$props) { var node_45 = first_child(fragment_8); { var consequent_38 = ($$anchor4) => { - var button_4 = root_51$2(); + var button_4 = root_51$1(); delegated("click", button_4, function(...$$args) { var _a; (_a = onCancelRun()) == null ? void 0 : _a.apply(this, $$args); @@ -2251,7 +2251,7 @@ function UpscaleOptionsModal($$anchor, $$props) { append($$anchor4, button_4); }; var alternate_2 = ($$anchor4) => { - var fragment_9 = root_52$2(); + var fragment_9 = root_52$1(); var button_5 = first_child(fragment_9); var button_6 = sibling(button_5, 2); var text_28 = child(button_6); @@ -2354,17 +2354,17 @@ delegate([ "change" ]); var root_2$5 = from_html(``); -var root_3$4 = from_html(`
`, 1); +var root_3$5 = from_html(`
`, 1); var root_4$5 = from_html(`
`); var root_5$4 = from_html(`
`); -var root_7$3 = from_html(`
`); +var root_7$4 = from_html(`
`); var root_9$3 = from_html(`
Before
After
`, 1); var root_8$3 = from_html(`
`, 1); var root_10$3 = from_html(`
`); var root_12$3 = from_html(` `); -var root_11$2 = from_html(`
`); -var root_6$3 = from_html(` `, 1); -var root_13$3 = from_html(``); +var root_11$1 = from_html(`
`); +var root_6$4 = from_html(` `, 1); +var root_13$2 = from_html(``); var root_15$3 = from_html(`
renders the painted region with this checkpoint — no render metadata needed, and PuLID / Style Reference work on any source
`); var root_16$3 = from_html(`
re-renders the painted region with this FLUX.1 model at the denoise below — describe the content, strong on faces and eyes
`); var root_17$3 = from_html(`
follows your instruction inside the mask only — unmasked pixels stay untouched; the region renders at full model resolution
`); @@ -2387,9 +2387,9 @@ var root_34$2 = from_html(``, 1); var root_36$2 = from_html(`
Denoise
`); var root_38$2 = from_html(``); -var root_39$1 = from_html(``); +var root_39$2 = from_html(``); var root_37$2 = from_html(`
`); -var root_40$1 = from_html(`
Grow
Feather
`, 1); +var root_40$2 = from_html(`
Grow
Feather
`, 1); var root_41$2 = from_html(`Save to `, 1); var root_42$2 = from_html(`
`); var root_43$2 = from_html(``); @@ -3344,7 +3344,7 @@ function InpaintModal($$anchor, $$props) { var node_3 = sibling(div_6, 2); { var consequent_1 = ($$anchor3) => { - var fragment_1 = root_3$4(); + var fragment_1 = root_3$5(); var label = first_child(fragment_1); var input = sibling(child(label)); var div_9 = sibling(label, 2); @@ -3417,11 +3417,11 @@ function InpaintModal($$anchor, $$props) { var node_5 = sibling(node_4, 2); { var consequent_8 = ($$anchor3) => { - var fragment_2 = root_6$3(); + var fragment_2 = root_6$4(); var node_6 = first_child(fragment_2); { var consequent_3 = ($$anchor4) => { - var div_15 = root_7$3(); + var div_15 = root_7$4(); var img_2 = child(div_15); template_effect(() => set_attribute(img_2, "src", get(progress).previewUrl)); append($$anchor4, div_15); @@ -3481,7 +3481,7 @@ function InpaintModal($$anchor, $$props) { var node_8 = sibling(node_6, 2); { var consequent_7 = ($$anchor4) => { - var div_22 = root_11$2(); + var div_22 = root_11$1(); var div_23 = child(div_22); var div_24 = child(div_23); let classes_7; @@ -3518,7 +3518,7 @@ function InpaintModal($$anchor, $$props) { var node_10 = child(div_25); { var consequent_9 = ($$anchor3) => { - var button_7 = root_13$3(); + var button_7 = root_13$2(); delegated("click", button_7, applySavedSetup); append($$anchor3, button_7); }; @@ -3981,7 +3981,7 @@ function InpaintModal($$anchor, $$props) { var select_4 = sibling(child(div_50), 2); let classes_10; each(select_4, 21, () => caps().schedulerOptions, index, ($$anchor4, opt) => { - var option_6 = root_39$1(); + var option_6 = root_39$2(); let styles_4; var text_12 = child(option_6); var option_6_value = {}; @@ -4022,7 +4022,7 @@ function InpaintModal($$anchor, $$props) { var node_34 = sibling(div_51, 2); { var consequent_27 = ($$anchor3) => { - var fragment_13 = root_40$1(); + var fragment_13 = root_40$2(); var div_52 = first_child(fragment_13); var node_35 = sibling(child(div_52), 2); SettingsSlider(node_35, { @@ -4204,7 +4204,7 @@ delegate([ "change" ]); var root_4$4 = from_html(`
`); -var root_3$3 = from_html(`
`); +var root_3$4 = from_html(`
`); var root_2$4 = from_html(`
`); var root_1$4 = from_html(`
`); function AdjustModal($$anchor, $$props) { @@ -4890,7 +4890,7 @@ function AdjustModal($$anchor, $$props) { var node_1 = sibling(div_8, 2); { var consequent = ($$anchor4) => { - var div_9 = root_3$3(); + var div_9 = root_3$4(); each(div_9, 21, () => get(g).sliders, index, ($$anchor5, sl) => { var div_10 = root_4$4(); var span_4 = child(div_10); @@ -4987,16 +4987,16 @@ delegate([ "dblclick" ]); var root_2$3 = from_html(` `); -var root_3$2 = from_svg(``); +var root_3$3 = from_svg(``); var root_4$3 = from_svg(``); var root_5$3 = from_html(`
`); -var root_6$2 = from_html(`Transform drag a corner to scale · the knob above rotates (Shift = 15° steps) · drag inside to move · Shift on a corner keeps proportions · Enter applies · Esc cancels`, 1); -var root_7$2 = from_html(`
Tolerance
click to flood-fill with the foreground color · constrained to the selection · Alt/Ctrl+Backspace fills`, 1); +var root_6$3 = from_html(`Transform drag a corner to scale · the knob above rotates (Shift = 15° steps) · drag inside to move · Shift on a corner keeps proportions · Enter applies · Esc cancels`, 1); +var root_7$3 = from_html(`
Tolerance
click to flood-fill with the foreground color · constrained to the selection · Alt/Ctrl+Backspace fills`, 1); var root_8$2 = from_html(`
Blur
Feather
lasso a region — it blurs and feather-blends on release`, 1); var root_9$2 = from_html(`
Size
Hardness
Opacity
Flow
`, 1); -var root_11$1 = from_html(`
Opacity
Flow
`, 1); +var root_11 = from_html(`
Opacity
Flow
`, 1); var root_12$2 = from_html(`paint over a blemish — it heals from the surroundings on release`); -var root_13$2 = from_html(` `); +var root_13$1 = from_html(` `); var root_14$2 = from_html(` `); var root_10$2 = from_html(`
Size
Hardness
`, 1); var root_16$2 = from_html(``); @@ -5022,9 +5022,9 @@ var root_35$1 = from_svg(`
`, 1); var root_38$1 = from_html(`
`); var root_36$1 = from_html(`
`, 1); -var root_40 = from_html(`
`); +var root_40$1 = from_html(`
`); var root_41$1 = from_html(`
`, 1); -var root_39 = from_html(`
`); +var root_39$1 = from_html(`
`); var root_42$1 = from_html(`
`); var root_43$1 = from_html(`
`); var root_44$1 = from_html(`
`); @@ -5033,9 +5033,9 @@ var root_46$1 = from_html(`
drag / var root_47$1 = from_html(`
`); var root_49$1 = from_html(``); var root_50$1 = from_html(``); -var root_51$1 = from_html(`
`); +var root_51 = from_html(`
`); var root_48$1 = from_html(`
`); -var root_52$1 = from_html(` `); +var root_52 = from_html(` `); var root_54$1 = from_html(``); var root_56$1 = from_html(``); var root_58$1 = from_html(`▦`); @@ -5047,18 +5047,18 @@ var root_61$1 = from_html(`
`); var root_60$1 = from_html(`
`); var root_63$1 = from_html(``); var root_64$1 = from_html(``); -var root_66 = from_html(``); -var root_67 = from_html(` `, 1); -var root_68 = from_html(``); -var root_69 = from_html(``); +var root_66$1 = from_html(``); +var root_67$1 = from_html(` `, 1); +var root_68$1 = from_html(``); +var root_69$1 = from_html(``); var root_62$1 = from_html(`
`); -var root_71 = from_html(` `, 1); -var root_72 = from_html(` `, 1); -var root_70 = from_html(`
`); -var root_73 = from_html(`
`); -var root_74 = from_html(`
`); -var root_75 = from_html(`
⏳ Selecting subject…
`); -var root_76 = from_html(`
Alt-click a clean area of the image to define a source point, then paint.
`); +var root_71$1 = from_html(` `, 1); +var root_72$1 = from_html(` `, 1); +var root_70$1 = from_html(`
`); +var root_73$1 = from_html(`
`); +var root_74$1 = from_html(`
`); +var root_75$1 = from_html(`
⏳ Selecting subject…
`); +var root_76$1 = from_html(`
Alt-click a clean area of the image to define a source point, then paint.
`); var root_77 = from_html(`
`); var root_78 = from_html(`✓ Edits saved`); var root_1$3 = from_html(`
Editing:
Navigator
`); @@ -9652,7 +9652,7 @@ function EditModal($$anchor, $$props) { var node_2 = child(button); { var consequent_1 = ($$anchor3) => { - var svg_1 = root_3$2(); + var svg_1 = root_3$3(); append($$anchor3, svg_1); }; var alternate = ($$anchor3) => { @@ -9684,7 +9684,7 @@ function EditModal($$anchor, $$props) { var node_4 = child(div_7); { var consequent_3 = ($$anchor3) => { - var fragment_1 = root_6$2(); + var fragment_1 = root_6$3(); var button_2 = sibling(first_child(fragment_1), 2); var button_3 = sibling(button_2, 2); var span_4 = sibling(button_3, 2); @@ -9701,7 +9701,7 @@ function EditModal($$anchor, $$props) { append($$anchor3, fragment_1); }; var consequent_4 = ($$anchor3) => { - var fragment_2 = root_7$2(); + var fragment_2 = root_7$3(); var div_8 = first_child(fragment_2); var node_5 = sibling(child(div_8), 2); SettingsSlider(node_5, { @@ -9855,7 +9855,7 @@ function EditModal($$anchor, $$props) { var node_14 = sibling(div_16, 2); { var consequent_7 = ($$anchor4) => { - var fragment_6 = root_11$1(); + var fragment_6 = root_11(); var div_17 = first_child(fragment_6); var node_15 = sibling(child(div_17), 2); SettingsSlider(node_15, { @@ -9897,7 +9897,7 @@ function EditModal($$anchor, $$props) { append($$anchor4, span_5); }; var consequent_9 = ($$anchor4) => { - var span_6 = root_13$2(); + var span_6 = root_13$1(); var text_4 = child(span_6); template_effect(() => set_text(text_4, get(healSource) ? "paint over the flaw — texture from the source, lighting from the spot · Alt-click to re-sample" : "Alt-click a clean area to set the sample source")); append($$anchor4, span_6); @@ -10427,13 +10427,13 @@ function EditModal($$anchor, $$props) { { var consequent_28 = ($$anchor3) => { const hs = user_derived(() => 11 / get(zoom)); - var div_50 = root_39(); + var div_50 = root_39$1(); var canvas_3 = child(div_50); bind_this(canvas_3, ($$value) => set(patchEl, $$value), () => get(patchEl)); var div_51 = sibling(canvas_3, 2); var node_42 = sibling(div_51, 2); each(node_42, 17, () => HANDLES, index, ($$anchor4, dir) => { - var div_52 = root_40(); + var div_52 = root_40$1(); template_effect(($0) => set_style(div_52, $0), [() => tHandleStyle(get(dir), get(patch), get(zoom))]); delegated("pointerdown", div_52, (e) => patchPointerDown(e, get(dir))); delegated("pointermove", div_52, patchPointerMove); @@ -10599,7 +10599,7 @@ function EditModal($$anchor, $$props) { var node_53 = sibling(div_67, 2); { var consequent_37 = ($$anchor4) => { - var div_68 = root_51$1(); + var div_68 = root_51(); var button_29 = child(div_68); template_effect(() => button_29.disabled = !!get(handoffBusy)); delegated("click", button_29, openReposeHandoff); @@ -10626,7 +10626,7 @@ function EditModal($$anchor, $$props) { var node_54 = sibling(span_15, 2); { var consequent_39 = ($$anchor3) => { - var span_16 = root_52$1(); + var span_16 = root_52(); var button_32 = child(span_16); var button_33 = sibling(button_32, 2); var button_34 = sibling(button_33, 2); @@ -10866,7 +10866,7 @@ function EditModal($$anchor, $$props) { var node_62 = first_child(fragment_17); { var consequent_46 = ($$anchor5) => { - var button_40 = root_66(); + var button_40 = root_66$1(); var text_24 = child(button_40); template_effect(() => set_text(text_24, `Add Layer Mask${get(selActive) ? " (Reveal Selection)" : ""}`)); delegated("click", button_40, () => { @@ -10876,7 +10876,7 @@ function EditModal($$anchor, $$props) { append($$anchor5, button_40); }; var alternate_5 = ($$anchor5) => { - var fragment_18 = root_67(); + var fragment_18 = root_67$1(); var button_41 = first_child(fragment_18); var button_42 = sibling(button_41, 2); delegated("click", button_41, () => { @@ -10905,7 +10905,7 @@ function EditModal($$anchor, $$props) { var node_63 = sibling(node_61, 2); { var consequent_48 = ($$anchor4) => { - var button_43 = root_68(); + var button_43 = root_68$1(); delegated("click", button_43, () => { const i = get(layerMenu).i; set(layerMenu, null); @@ -10924,7 +10924,7 @@ function EditModal($$anchor, $$props) { var node_64 = sibling(button_44, 2); { var consequent_49 = ($$anchor4) => { - var button_45 = root_69(); + var button_45 = root_69$1(); var text_25 = child(button_45); template_effect(() => set_text(text_25, get(selectedIds).length > 1 ? "Delete Layers" : "Delete Layer")); delegated("click", button_45, () => { @@ -10960,11 +10960,11 @@ function EditModal($$anchor, $$props) { var node_65 = sibling(node_59, 2); { var consequent_53 = ($$anchor3) => { - var div_76 = root_70(); + var div_76 = root_70$1(); var node_66 = child(div_76); { var consequent_51 = ($$anchor4) => { - var fragment_19 = root_71(); + var fragment_19 = root_71$1(); var button_46 = first_child(fragment_19); var button_47 = sibling(button_46, 2); delegated("click", button_46, () => { @@ -10989,7 +10989,7 @@ function EditModal($$anchor, $$props) { var node_67 = sibling(button_50, 2); { var consequent_52 = ($$anchor4) => { - var fragment_20 = root_72(); + var fragment_20 = root_72$1(); var button_51 = first_child(fragment_20); var button_52 = sibling(button_51, 2); delegated("click", button_51, () => { @@ -11033,7 +11033,7 @@ function EditModal($$anchor, $$props) { var node_68 = sibling(div_6, 2); { var consequent_54 = ($$anchor3) => { - var div_77 = root_73(); + var div_77 = root_73$1(); var text_28 = child(div_77); template_effect(() => set_text(text_28, `⚠ ${get(errorMsg) ?? ""}`)); append($$anchor3, div_77); @@ -11045,13 +11045,13 @@ function EditModal($$anchor, $$props) { var node_69 = sibling(node_68, 2); { var consequent_55 = ($$anchor3) => { - var div_78 = root_74(); + var div_78 = root_74$1(); var text_29 = child(div_78); template_effect(() => set_text(text_29, `⏳ ${get(selSetupMsg) ?? ""}`)); append($$anchor3, div_78); }; var consequent_56 = ($$anchor3) => { - var div_79 = root_75(); + var div_79 = root_75$1(); append($$anchor3, div_79); }; if_block(node_69, ($$render) => { @@ -11079,7 +11079,7 @@ function EditModal($$anchor, $$props) { var node_71 = sibling(node_70, 2); { var consequent_57 = ($$anchor3) => { - var div_80 = root_76(); + var div_80 = root_76$1(); var div_81 = child(div_80); var div_82 = child(div_81); var text_30 = child(div_82); @@ -11284,17 +11284,17 @@ delegate([ "input", "keydown" ]); -var root_3$1 = from_html(``); +var root_3$2 = from_html(``); var root_2$2 = from_html(`
`); var root_4$2 = from_html(`preview`); -var root_6$1 = from_html(`
Before
After
`, 1); +var root_6$2 = from_html(`
Before
After
`, 1); var root_5$2 = from_html(`
`, 1); -var root_7$1 = from_html(`
`); +var root_7$2 = from_html(`
`); var root_8$1 = from_html(``); var root_9$1 = from_html(`
`); var root_10$1 = from_html(``); var root_12$1 = from_html(`
`); -var root_13$1 = from_html(``); +var root_13 = from_html(``); var root_14$1 = from_html(``); var root_15$1 = from_html(``); var root_16$1 = from_html(`
Depth-locked: the poser outputs a depth map; output follows the pose frame.
`); @@ -11752,7 +11752,7 @@ function RePoseModal($$anchor, $$props) { var node_3 = child(div_8); { var consequent = ($$anchor4) => { - var button_1 = root_3$1(); + var button_1 = root_3$2(); let classes; template_effect(() => classes = set_class(button_1, 1, "pcr-rp-fit-btn svelte-1elgmyq", null, classes, { on: get(compareSplit) })); delegated("click", button_1, toggleCompare); @@ -11786,7 +11786,7 @@ function RePoseModal($$anchor, $$props) { var node_5 = sibling(div_10, 2); { var consequent_3 = ($$anchor4) => { - var fragment_2 = root_6$1(); + var fragment_2 = root_6$2(); var div_11 = first_child(fragment_2); var div_12 = child(div_11); var img_2 = child(div_12); @@ -11825,7 +11825,7 @@ function RePoseModal($$anchor, $$props) { var node_6 = sibling(div_9, 2); { var consequent_5 = ($$anchor3) => { - var div_14 = root_7$1(); + var div_14 = root_7$2(); var div_15 = child(div_14); var div_16 = child(div_15); let styles; @@ -11906,7 +11906,7 @@ function RePoseModal($$anchor, $$props) { append($$anchor4, div_22); }; var alternate = ($$anchor4) => { - var textarea = root_13$1(); + var textarea = root_13(); bind_value(textarea, () => get(promptDoc), ($$value) => set(promptDoc, $$value)); append($$anchor4, textarea); }; @@ -12062,15 +12062,17 @@ delegate([ "contextmenu", "change" ]); -var root_1$1 = from_html(``); -var root_2$1 = from_html(``); -var root_4$1 = from_html(`
`); -var root_5$1 = from_html(``); -var root_3 = from_html(` `, 1); -var root$1 = from_html(`
`); +var root_2$1 = from_html(`
`); +var root_1$1 = from_html(` `, 1); +var root_3$1 = from_html(``); +var root_4$1 = from_html(``); +var root_6$1 = from_html(`
`); +var root_7$1 = from_html(``); +var root_5$1 = from_html(` `, 1); +var root = from_html(`
`); function LineageContextMenu($$anchor, $$props) { push($$props, true); - let canEdit = prop($$props, "canEdit", 3, false), canDelete = prop($$props, "canDelete", 3, false), isLocal = prop($$props, "isLocal", 3, false), isWindows = prop($$props, "isWindows", 3, false), orphaned = prop($$props, "orphaned", 3, false); + let canExpand = prop($$props, "canExpand", 3, false), canEdit = prop($$props, "canEdit", 3, false), canDelete = prop($$props, "canDelete", 3, false), isLocal = prop($$props, "isLocal", 3, false), isWindows = prop($$props, "isWindows", 3, false), orphaned = prop($$props, "orphaned", 3, false); let menuEl; function act(action2) { var _a, _b; @@ -12101,67 +12103,92 @@ function LineageContextMenu($$anchor, $$props) { window.removeEventListener("keydown", onKey); }; }); - var div = root$1(); + var div = root(); var node = child(div); - { - var consequent = ($$anchor2) => { - var button = root_1$1(); - delegated("click", button, () => act("edit")); - append($$anchor2, button); - }; - if_block(node, ($$render) => { - if (canEdit()) $$render(consequent); - }); - } - var node_1 = sibling(node, 2); { var consequent_1 = ($$anchor2) => { - var button_1 = root_2$1(); - delegated("click", button_1, () => act("delete")); - append($$anchor2, button_1); - }; - if_block(node_1, ($$render) => { - if (canDelete()) $$render(consequent_1); - }); - } - var node_2 = sibling(node_1, 2); - { - var consequent_4 = ($$anchor2) => { - var fragment = root_3(); - var node_3 = first_child(fragment); + var fragment = root_1$1(); + var button = first_child(fragment); + var node_1 = sibling(button, 2); { - var consequent_2 = ($$anchor3) => { - var div_1 = root_4$1(); + var consequent = ($$anchor3) => { + var div_1 = root_2$1(); append($$anchor3, div_1); }; - if_block(node_3, ($$render) => { - if (canEdit() || canDelete()) $$render(consequent_2); + if_block(node_1, ($$render) => { + if (canEdit() || canDelete() || isLocal()) $$render(consequent); }); } - var button_2 = sibling(node_3, 2); - var button_3 = sibling(button_2, 2); - var node_4 = sibling(button_3, 2); + delegated("click", button, () => act("expand-branches")); + append($$anchor2, fragment); + }; + if_block(node, ($$render) => { + if (canExpand()) $$render(consequent_1); + }); + } + var node_2 = sibling(node, 2); + { + var consequent_2 = ($$anchor2) => { + var button_1 = root_3$1(); + delegated("click", button_1, () => act("edit")); + append($$anchor2, button_1); + }; + if_block(node_2, ($$render) => { + if (canEdit()) $$render(consequent_2); + }); + } + var node_3 = sibling(node_2, 2); + { + var consequent_3 = ($$anchor2) => { + var button_2 = root_4$1(); + delegated("click", button_2, () => act("delete")); + append($$anchor2, button_2); + }; + if_block(node_3, ($$render) => { + if (canDelete()) $$render(consequent_3); + }); + } + var node_4 = sibling(node_3, 2); + { + var consequent_6 = ($$anchor2) => { + var fragment_1 = root_5$1(); + var node_5 = first_child(fragment_1); { - var consequent_3 = ($$anchor3) => { - var button_4 = root_5$1(); - template_effect(() => button_4.disabled = orphaned()); - delegated("click", button_4, () => act("properties")); - append($$anchor3, button_4); + var consequent_4 = ($$anchor3) => { + var div_2 = root_6$1(); + append($$anchor3, div_2); }; - if_block(node_4, ($$render) => { - if (isWindows()) $$render(consequent_3); + if_block(node_5, ($$render) => { + if (canEdit() || canDelete()) $$render(consequent_4); + }); + } + var button_3 = sibling(node_5, 2); + var button_4 = sibling(button_3, 2); + var button_5 = sibling(button_4, 2); + var node_6 = sibling(button_5, 2); + { + var consequent_5 = ($$anchor3) => { + var button_6 = root_7$1(); + template_effect(() => button_6.disabled = orphaned()); + delegated("click", button_6, () => act("properties")); + append($$anchor3, button_6); + }; + if_block(node_6, ($$render) => { + if (isWindows()) $$render(consequent_5); }); } template_effect(() => { - button_2.disabled = orphaned(); button_3.disabled = orphaned(); + button_4.disabled = orphaned(); + button_5.disabled = orphaned(); }); - delegated("click", button_2, () => act("open-file")); - delegated("click", button_3, () => act("open-folder")); - append($$anchor2, fragment); + delegated("click", button_3, () => act("copy-path")); + delegated("click", button_4, () => act("open-file")); + delegated("click", button_5, () => act("open-folder")); + append($$anchor2, fragment_1); }; - if_block(node_2, ($$render) => { - if (isLocal()) $$render(consequent_4); + if_block(node_4, ($$render) => { + if (isLocal()) $$render(consequent_6); }); } action(div, ($$node) => { @@ -12174,6 +12201,73 @@ function LineageContextMenu($$anchor, $$props) { pop(); } delegate(["click"]); +function ancestry(tree, hash) { + const { byHash } = tree; + const set2 = /* @__PURE__ */ new Set(); + let cur = hash; + let root2 = hash; + while (cur && byHash.has(cur) && !set2.has(cur)) { + set2.add(cur); + root2 = cur; + cur = byHash.get(cur).parent_hash; + } + return { root: root2, set: set2 }; +} +function buildLane(tree, startHash, spineSet) { + const { byHash, childrenOf } = tree; + const nodes = []; + const junctions = []; + const guard = /* @__PURE__ */ new Set(); + let cur = startHash; + while (cur && byHash.has(cur) && !guard.has(cur)) { + guard.add(cur); + nodes.push(byHash.get(cur)); + const kids = childrenOf.get(cur) || []; + let primary = spineSet ? kids.find((k) => spineSet.has(k.hash)) : null; + if (!primary) primary = kids[0] || null; + const offPrimary = kids.filter((k) => k !== primary).map((k) => k.hash); + if (offPrimary.length) junctions.push({ atHash: cur, childRoots: offPrimary }); + cur = primary ? primary.hash : null; + } + return { startHash, nodes, junctions }; +} +function buildRender(tree, anchorHash, brokenOut) { + const a = ancestry(tree, anchorHash); + const col0 = buildLane(tree, a.root, a.set); + const columns = []; + const edges = []; + const started = /* @__PURE__ */ new Set(); + const junctionsByNode = /* @__PURE__ */ new Map(); + const visit = (lane, topRow) => { + lane.topRow = topRow; + columns.push(lane); + for (let i = 0; i + 1 < lane.nodes.length; i++) { + edges.push({ from: lane.nodes[i].hash, to: lane.nodes[i + 1].hash }); + } + for (const j of lane.junctions) { + const forkRow = lane.nodes.findIndex((n) => n.hash === j.atHash); + let rec = junctionsByNode.get(j.atHash); + if (!rec) { + rec = { shown: [], hidden: [] }; + junctionsByNode.set(j.atHash, rec); + } + for (const childRoot of j.childRoots) { + if (brokenOut.has(childRoot)) { + rec.shown.push(childRoot); + if (!started.has(childRoot)) { + started.add(childRoot); + edges.push({ from: j.atHash, to: childRoot }); + visit(buildLane(tree, childRoot), topRow + forkRow + 1); + } + } else { + rec.hidden.push(childRoot); + } + } + } + }; + visit(col0, 0); + return { columns, edges, junctionsByNode, rootHash: col0.nodes.length ? col0.nodes[0].hash : null }; +} function regionFigureIndices(regionList, poseJson) { let names = []; let numFigures = null; @@ -12266,73 +12360,83 @@ function buildFigureRegions({ workflow, regionsRaw, poseFilesOk, apiURL }) { return []; } } -var root_1 = from_html(`
`); -var root_5 = from_html(`
`); -var root_4 = from_html(`
`); -var root_8 = from_html(``); -var root_7 = from_html(`
`, 1); -var root_9 = from_html(`▴`); -var root_6 = from_html(`
`); -var root_10 = from_html(`
`); -var root_2 = from_html(`
`); -var root_11 = from_html(`
`); -var root_13 = from_html(`
`); -var root_14 = from_html(`
`); -var root_15 = from_html(`
`); -var root_12 = from_html(`
`); -var root_17 = from_html(`
`); -var root_18 = from_html(`Compare`); -var root_21 = from_html(`
`); -var root_20 = from_html( +var root_3 = from_html(`
`); +var root_4 = from_html(``); +var root_5 = from_html(``); +var root_2 = from_html(`
`); +var root_7 = from_html(``); +var root_9 = from_svg(``); +var root_10 = from_html(`
`); +var root_8 = from_html(`
`); +var root_15 = from_html(`
`); +var root_14 = from_html(`
`); +var root_18 = from_html(``); +var root_17 = from_html(`
`, 1); +var root_19 = from_html(`▴`); +var root_16 = from_html(`
`); +var root_20 = from_html(`
`); +var root_12 = from_html(`
`, 1); +var root_6 = from_html(`
`); +var root_21 = from_html(`
`); +var root_23 = from_html(`
`); +var root_24 = from_html(`
`); +var root_25 = from_html(`
`); +var root_22 = from_html(`
`); +var root_26 = from_html(`
`); +var root_27 = from_html(`
📋 Path copied to clipboard
`); +var root_29 = from_html(`
`); +var root_30 = from_html(`Compare`); +var root_33 = from_html(`
`); +var root_32 = from_html( `
This image's record points to a file that no longer exists. If the file was moved or renamed, locate it — it's verified against the image's content hash, so the wrong file can't be attached.
`, 1 ); -var root_19 = from_html(`
`); -var root_23 = from_html(`
`); -var root_24 = from_html(`
`); -var root_22 = from_html(`
`, 1); -var root_16 = from_html(` `, 1); -var root_25 = from_html(`
`); -var root_26 = from_html(`
`); -var root_28 = from_html(`
`); -var root_29 = from_svg(``); -var root_30 = from_svg(``); -var root_32 = from_html(`
`); -var root_31 = from_html(`
`); -var root_27 = from_html(`
`); -var root_34 = from_html(`
`); -var root_33 = from_html(`
`); -var root_37 = from_html(`
`); -var root_38 = from_html(`
Clear
`, 1); -var root_36 = from_html(`
`); -var root_35 = from_html(`
Compare
`); -var root_42 = from_html(` `); -var root_41 = from_html(`
`); -var root_43 = from_html(`
`); -var root_44 = from_html(`
Open Folder
`); -var root_46 = from_html(`
Dimensions
`); -var root_47 = from_html(`
Size
`); -var root_48 = from_html(`
Generated
`); -var root_49 = from_html(`
Filename
`); -var root_50 = from_html(`
Status Source deleted
`); -var root_53 = from_html(`

`); -var root_54 = from_html(`
Global:

`); -var root_52 = from_html(` `, 1); -var root_55 = from_html(`
Positive Prompt:

`); -var root_56 = from_html(`
Negative Prompt:

`); -var root_51 = from_html(`
Prompt
`, 1); -var root_58 = from_html(`
Model
`); -var root_59 = from_html(`
Seed
`); -var root_60 = from_html(`
Steps
`); -var root_61 = from_html(`
CFG
`); -var root_62 = from_html(`
Sampler
`); -var root_63 = from_html(`
Denoise
`); -var root_57 = from_html(`
Generation Settings
`, 1); -var root_45 = from_html(`
Image Info
`, 1); -var root_64 = from_html(`
Loading metadata...
`); -var root = from_html(`
`, 1); +var root_31 = from_html(`
`); +var root_35 = from_html(`
`); +var root_36 = from_html(`
`); +var root_34 = from_html(`
`, 1); +var root_28 = from_html(` `, 1); +var root_37 = from_html(`
`); +var root_38 = from_html(`
`); +var root_40 = from_html(`
`); +var root_41 = from_svg(``); +var root_42 = from_svg(``); +var root_44 = from_html(`
`); +var root_43 = from_html(`
`); +var root_39 = from_html(`
`); +var root_46 = from_html(`
`); +var root_45 = from_html(`
`); +var root_49 = from_html(`
`); +var root_50 = from_html(`
Clear
`, 1); +var root_48 = from_html(`
`); +var root_47 = from_html(`
Compare
`); +var root_54 = from_html(` `); +var root_53 = from_html(`
`); +var root_55 = from_html(`
`); +var root_56 = from_html(`
Open Folder
`); +var root_58 = from_html(`
Dimensions
`); +var root_59 = from_html(`
Size
`); +var root_60 = from_html(`
Generated
`); +var root_61 = from_html(`
Filename
`); +var root_62 = from_html(`
Status Source deleted
`); +var root_65 = from_html(`

`); +var root_66 = from_html(`
Global:

`); +var root_64 = from_html(` `, 1); +var root_67 = from_html(`
Positive Prompt:

`); +var root_68 = from_html(`
Negative Prompt:

`); +var root_63 = from_html(`
Prompt
`, 1); +var root_70 = from_html(`
Model
`); +var root_71 = from_html(`
Seed
`); +var root_72 = from_html(`
Steps
`); +var root_73 = from_html(`
CFG
`); +var root_74 = from_html(`
Sampler
`); +var root_75 = from_html(`
Denoise
`); +var root_69 = from_html(`
Generation Settings
`, 1); +var root_57 = from_html(`
Image Info
`, 1); +var root_76 = from_html(`
Loading metadata...
`); +var root_1 = from_html(`
`, 1); function ImageViewer($$anchor, $$props) { var _a; push($$props, true); @@ -12516,13 +12620,11 @@ function ImageViewer($$anchor, $$props) { keepLineageFocusFor = hash; set(displayedHash, hash, true); } - let lineageDisplay = user_derived(() => (() => { - const asNodes = (list) => list.map((item) => ({ kind: "node", item })); - if (get(lineageList).length < 2) return asNodes(get(lineageList)); - const byHash = new Map(get(lineageList).map((f) => [f.hash, f])); - if (!byHash.has(get(displayedHash))) return asNodes(get(lineageList)); + let lineageTree = user_derived(() => (() => { + const list = get(lineageList); + const byHash = new Map(list.map((f) => [f.hash, f])); const childrenOf = /* @__PURE__ */ new Map(); - for (const f of get(lineageList)) { + for (const f of list) { if (!f.parent_hash || !byHash.has(f.parent_hash)) continue; if (!childrenOf.has(f.parent_hash)) childrenOf.set(f.parent_hash, []); childrenOf.get(f.parent_hash).push(f); @@ -12530,6 +12632,14 @@ function ImageViewer($$anchor, $$props) { for (const kids of childrenOf.values()) { kids.sort((a, b) => (a.created_at || 0) - (b.created_at || 0)); } + const roots = list.filter((f) => !f.parent_hash || !byHash.has(f.parent_hash)).map((f) => f.hash); + return { byHash, childrenOf, roots }; + })()); + let lineageDisplay = user_derived(() => (() => { + const asNodes = (list) => list.map((item) => ({ kind: "node", item })); + if (get(lineageList).length < 2) return asNodes(get(lineageList)); + const { byHash, childrenOf } = get(lineageTree); + if (!byHash.has(get(displayedHash))) return asNodes(get(lineageList)); const subtreeNodes = (rootHash) => { const out = []; const seen = /* @__PURE__ */ new Set(); @@ -12603,6 +12713,138 @@ function ImageViewer($$anchor, $$props) { let lineageVisible = user_derived(() => get(lineageDisplay).filter((d) => d.kind === "node").map((d) => d.item)); let lineageDisplayCurrentIdx = user_derived(() => get(lineageDisplay).findIndex((d) => d.kind === "node" && d.item.hash === get(displayedHash))); let lineageHiddenCount = user_derived(() => get(lineageList).length - get(lineageVisible).length); + let brokenOut = state(proxy(/* @__PURE__ */ new Set())); + let subwayAnchor = user_derived(() => get(lineageFocusHash) && get(lineageTree).byHash.has(get(lineageFocusHash)) ? get(lineageFocusHash) : get(displayedHash)); + let laneRender = user_derived(() => buildRender(get(lineageTree), get(subwayAnchor), get(brokenOut))); + let lanesActive = user_derived(() => get(brokenOut).size > 0 && get(lineageList).length > 1); + function primaryChildHash(item) { + const kids = get(lineageTree).childrenOf.get(item == null ? void 0 : item.hash) || []; + if (!kids.length) return null; + const a = ancestry(get(lineageTree), get(subwayAnchor)); + return (kids.find((k) => a.set.has(k.hash)) || kids[0]).hash; + } + function canExpand(item) { + const primary = primaryChildHash(item); + return (get(lineageTree).childrenOf.get(item == null ? void 0 : item.hash) || []).some((k) => k.hash !== primary && !get(brokenOut).has(k.hash)); + } + function expandBranches(item) { + const primary = primaryChildHash(item); + const next = new Set(get(brokenOut)); + for (const k of get(lineageTree).childrenOf.get(item == null ? void 0 : item.hash) || []) if (k.hash !== primary) next.add(k.hash); + set(brokenOut, next, true); + } + function foldLane(childRoot) { + const next = new Set(get(brokenOut)); + const stack = [childRoot]; + while (stack.length) { + const h = stack.pop(); + next.delete(h); + for (const k of get(lineageTree).childrenOf.get(h) || []) stack.push(k.hash); + } + set(brokenOut, next, true); + } + function collapseAllLanes() { + set(brokenOut, /* @__PURE__ */ new Set(), true); + } + let hasBranches = user_derived(() => (() => { + for (const kids of get(lineageTree).childrenOf.values()) if (kids.length > 1) return true; + return false; + })()); + function expandAll() { + const a = ancestry(get(lineageTree), get(subwayAnchor)); + const next = new Set(get(brokenOut)); + for (const kids of get(lineageTree).childrenOf.values()) { + if (kids.length < 2) continue; + const primary = (kids.find((k) => a.set.has(k.hash)) || kids[0]).hash; + for (const k of kids) if (k.hash !== primary) next.add(k.hash); + } + set(brokenOut, next, true); + } + user_effect(() => { + var _a2; + if (!get(lanesActive)) return; + if (get(laneRender).columns.some((c) => c.nodes.some((n) => n.hash === get(displayedHash)))) return; + const { byHash, childrenOf } = get(lineageTree); + const a = ancestry(get(lineageTree), get(subwayAnchor)); + const toBreak = []; + let cur = get(displayedHash); + const guard = /* @__PURE__ */ new Set(); + while (cur && byHash.has(cur) && !guard.has(cur) && !a.set.has(cur)) { + guard.add(cur); + const parent = byHash.get(cur).parent_hash; + if (!parent || !byHash.has(parent)) break; + const kids = childrenOf.get(parent) || []; + const primary = (_a2 = kids.find((k) => a.set.has(k.hash)) || kids[0]) == null ? void 0 : _a2.hash; + if (cur !== primary) toBreak.push(cur); + cur = parent; + } + const additions = toBreak.filter((h) => !get(brokenOut).has(h)); + if (additions.length) { + const next = new Set(get(brokenOut)); + for (const h of additions) next.add(h); + set(brokenOut, next, true); + } + }); + let lanesWrapEl = state(null); + let connectorGeom = state(proxy([])); + let connectorBox = state(proxy({ w: 0, h: 0 })); + let measureScheduled = false; + const LANE_ROW_H = 86; + function contentXY(el, root2) { + let x = 0, y = 0; + for (let n = el; n && n !== root2; n = n.offsetParent) { + x += n.offsetLeft; + y += n.offsetTop; + } + return { x, y, w: el.offsetWidth, h: el.offsetHeight }; + } + function measureConnectors() { + const wrap = get(lanesWrapEl); + if (!wrap) return; + const geom = []; + for (const e of get(laneRender).edges) { + const a = wrap.querySelector(`[data-hash="${e.from}"]`); + const b = wrap.querySelector(`[data-hash="${e.to}"]`); + if (!a || !b) continue; + const ra = contentXY(a, wrap), rb = contentXY(b, wrap); + const px = ra.x + ra.w / 2, pb = ra.y + ra.h; + const cx = rb.x + rb.w / 2, ct = rb.y; + const key2 = `${e.from}>${e.to}`; + if (Math.abs(px - cx) < 1) { + geom.push({ key: key2, d: `M ${px} ${pb} L ${cx} ${ct}` }); + } else { + const my = (pb + ct) / 2; + geom.push({ + key: key2, + d: `M ${px} ${pb} C ${px} ${my}, ${cx} ${my}, ${cx} ${ct}` + }); + } + } + set(connectorGeom, geom, true); + set(connectorBox, { w: wrap.scrollWidth, h: wrap.scrollHeight }, true); + } + function scheduleMeasure() { + if (measureScheduled) return; + measureScheduled = true; + requestAnimationFrame(() => { + measureScheduled = false; + measureConnectors(); + }); + } + user_effect(() => { + if (!get(lanesActive)) return; + const cols = get( + laneRender + // read → track expand/fold/family changes + ).columns; + if (cols) scheduleMeasure(); + }); + user_effect(() => { + if (!get(lanesWrapEl)) return; + const ro = new ResizeObserver(() => scheduleMeasure()); + ro.observe(get(lanesWrapEl)); + return () => ro.disconnect(); + }); let compareTargets = user_derived(() => get(lineageList).filter((item) => (item == null ? void 0 : item.hash) !== get(displayedHash))); let hasCompareTargets = user_derived(() => get(compareTargets).length > 0); let compareImageUrl = user_derived(() => get(compareTargetHash) ? imageUrl(get(compareTargetHash)) : null); @@ -12642,11 +12884,18 @@ function ImageViewer($$anchor, $$props) { fetchApi()(`/promptchain/image-meta/${get(displayedHash)}`).then((r) => r.ok ? r.json() : null).then((data) => { set(imageInfo, data, true); }).catch(onMetaError("image meta")); - fetchApi()(`/promptchain/lineage/${get(displayedHash)}`).then((r) => r.ok ? r.json() : null).then((data) => { + const reqHash = get(displayedHash); + fetchApi()(`/promptchain/lineage/${reqHash}`).then((r) => r.ok ? r.json() : null).then((data) => { + if (get( + displayedHash + // stale response — a newer hash is shown + ) !== reqHash) return; set(lineageData, data, true); + reportLineageAnomaly(reqHash, data); }).catch((e) => { + if (get(displayedHash) !== reqHash) return; set(lineageData, null); - console.error(`[PromptChain] lineage fetch failed for ${get(displayedHash)}:`, e); + console.error(`[PromptChain] lineage fetch failed for ${reqHash}:`, e); }); } }); @@ -13253,6 +13502,15 @@ ${negative}` : "")); } catch { } } + function reportLineageAnomaly(reqHash, data) { + const fam = data == null ? void 0 : data.family; + if (!Array.isArray(fam) || fam.length === 0) return; + const me = fam.find((f) => (f == null ? void 0 : f.hash) === reqHash); + const parentOrphaned = !!((me == null ? void 0 : me.parent_hash) && !fam.some((f) => (f == null ? void 0 : f.hash) === me.parent_hash)); + if (me && !parentOrphaned) return; + const fams = fam.map((f) => ((f == null ? void 0 : f.hash) || "").slice(0, 8)).join(","); + reportHandback("lineage-tree-anomaly", `node ${(reqHash || "").slice(0, 8)} ${me ? "orphaned: parent " + (me.parent_hash || "").slice(0, 8) + " absent" : "ABSENT"} from its own family [${fams}]`); + } async function handleUpscaleToEdit(doneState) { var _a2, _b, _c; const ctx = get(upscaleEditCtx); @@ -13471,11 +13729,58 @@ ${negative}` : "")); e.stopPropagation(); set(lineageMenu, { x: e.clientX, y: e.clientY, item }, true); } + let copyPathTimer = null; + let copyPathToast = state(false); + async function copyTextToClipboard(text) { + try { + await navigator.clipboard.writeText(text); + return true; + } catch { + } + try { + const ta = document.createElement("textarea"); + ta.value = text; + ta.style.position = "fixed"; + ta.style.top = "-1000px"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.focus(); + ta.select(); + const ok = document.execCommand("copy"); + document.body.removeChild(ta); + return ok; + } catch { + return false; + } + } + async function copyPath(hash) { + var _a2; + try { + const r = await ((_a2 = fetchApi()) == null ? void 0 : _a2(`/promptchain/file-path?hash=${encodeURIComponent(hash)}`)); + const d = r && r.ok ? await r.json() : null; + if (!(d == null ? void 0 : d.path)) return; + if (await copyTextToClipboard(d.path)) { + set(copyPathToast, true); + clearTimeout(copyPathTimer); + copyPathTimer = setTimeout( + () => { + set(copyPathToast, false); + }, + 1800 + ); + } + } catch { + } + } function lineageMenuAction(action2, item) { var _a2, _b, _c; const hash = item == null ? void 0 : item.hash; if (!hash) return; - if (action2 === "edit") { + if (action2 === "expand-branches") { + expandBranches(item); + } else if (action2 === "copy-path") { + copyPath(hash); + } else if (action2 === "edit") { lineageJump(hash); openEdit(hash); } else if (action2 === "delete") { @@ -13584,7 +13889,7 @@ ${negative}` : "")); }); } } - var fragment = root(); + var fragment = root_1(); event("keydown", $window, handleKeydown); event("mousemove", $window, handleWindowMouseMove); event("mouseup", $window, handleWindowMouseUp); @@ -13593,873 +13898,1061 @@ ${negative}` : "")); if (get(zoomDropdownOpen) && !e.target.closest(".pcr-viewer-zoom-control")) set(zoomDropdownOpen, false); }); var div = first_child(fragment); - var node = child(div); { - var consequent = ($$anchor2) => { - var div_1 = root_1(); - var text = child(div_1); - template_effect(() => set_text(text, `✨ ${get(newGenBanner) ?? ""}`)); + const lineageNode = ($$anchor2, item = noop, lane = noop) => { + var div_1 = root_2(); + let classes; + var img_1 = child(div_1); + var div_2 = sibling(img_1, 2); + let classes_1; + var node = sibling(div_2, 2); + { + var consequent = ($$anchor3) => { + var div_3 = root_3(); + append($$anchor3, div_3); + }; + if_block(node, ($$render) => { + if (get(editDocLayers)[item().hash]) $$render(consequent); + }); + } + var node_1 = sibling(node, 2); + { + var consequent_1 = ($$anchor3) => { + var button = root_4(); + var text_1 = child(button); + template_effect( + ($0, $1) => { + set_attribute(button, "title", `Break this node's ${$0 ?? ""} other branch(es) into their own columns`); + set_text(text_1, `⊞${$1 ?? ""}`); + }, + [ + () => get(laneRender).junctionsByNode.get(item().hash).hidden.length, + () => get(laneRender).junctionsByNode.get(item().hash).hidden.length + ] + ); + delegated("click", button, (e) => { + e.stopPropagation(); + expandBranches(item()); + }); + append($$anchor3, button); + }; + var d_1 = user_derived(() => { + var _a2; + return (_a2 = get(laneRender).junctionsByNode.get(item().hash)) == null ? void 0 : _a2.hidden.length; + }); + if_block(node_1, ($$render) => { + if (get(d_1)) $$render(consequent_1); + }); + } + var node_2 = sibling(node_1, 2); + { + var consequent_2 = ($$anchor3) => { + var button_1 = root_5(); + delegated("click", button_1, (e) => { + e.stopPropagation(); + foldLane(lane().startHash); + }); + append($$anchor3, button_1); + }; + var d_2 = user_derived(() => get(brokenOut).has(lane().startHash) && item().hash === lane().startHash); + if_block(node_2, ($$render) => { + if (get(d_2)) $$render(consequent_2); + }); + } + template_effect( + ($0) => { + classes = set_class(div_1, 1, "pcr-viewer-lineage-node svelte-5cciiw", null, classes, { + current: item().hash === get(displayedHash), + orphaned: item().orphaned === 1, + "compare-candidate": get(compareDropdownOpen) && item().hash !== get(displayedHash), + "compare-left": get(compareMode) && item().hash === get(displayedHash), + "compare-right": get(compareMode) && item().hash === get(compareTargetHash) + }); + set_attribute(div_1, "data-hash", item().hash); + set_attribute(img_1, "src", $0); + classes_1 = set_class(div_2, 1, "pcr-viewer-lineage-dot svelte-5cciiw", null, classes_1, { + "dot-root": item().hash === get(laneRender).rootHash, + "dot-current": item().hash === get(displayedHash), + "dot-tip": item().hash === lane().nodes[lane().nodes.length - 1].hash && item().hash !== get(displayedHash) + }); + }, + [() => thumbUrl(item().hash)] + ); + delegated("click", div_1, () => { + if (get(compareDropdownOpen)) { + if (item().hash !== get(displayedHash)) enterCompareWith(item().hash, item().filename || item().hash.slice(0, 8)); + return; + } + lineageJump(item().hash); + exitCompare(); + }); + event("mouseenter", div_1, (e) => showTip(e, item())); + event("mouseleave", div_1, hideTip); + delegated("contextmenu", div_1, (e) => { + hideTip(); + openLineageMenu(e, item()); + }); + event("load", img_1, scheduleMeasure); append($$anchor2, div_1); }; - if_block(node, ($$render) => { - if (get(newGenBanner)) $$render(consequent); - }); - } - var node_1 = sibling(node, 2); - { - var consequent_5 = ($$anchor2) => { - var div_2 = root_2(); - var div_3 = child(div_2); - var text_1 = child(div_3); - var div_4 = sibling(div_3, 2); - each(div_4, 23, () => get(lineageDisplay), (d) => d.kind === "node" ? d.item.hash : `${d.kind}:${d.at}`, ($$anchor3, d, i) => { - var fragment_1 = comment(); - var node_2 = first_child(fragment_1); + var node_3 = child(div); + { + var consequent_9 = ($$anchor2) => { + var div_4 = root_6(); + let classes_2; + var div_5 = child(div_4); + var span = child(div_5); + var text_2 = child(span); + var node_4 = sibling(span, 2); { - var consequent_2 = ($$anchor4) => { - const item = user_derived(() => get(d).item); - var div_5 = root_4(); - let classes; - var img_1 = child(div_5); - var div_6 = sibling(img_1, 2); - let classes_1; - var node_3 = sibling(div_6, 2); + var consequent_3 = ($$anchor3) => { + var button_2 = root_7(); + let classes_3; + var text_3 = child(button_2); + template_effect(() => { + classes_3 = set_class(button_2, 1, "pcr-lin-toggle svelte-5cciiw", null, classes_3, { on: get(lanesActive) }); + set_attribute(button_2, "title", get(lanesActive) ? "Collapse the subway back to the strip" : "Expand every branch into a subway map"); + set_text(text_3, get(lanesActive) ? "⊟" : "⊞"); + }); + delegated("click", button_2, () => get(lanesActive) ? collapseAllLanes() : expandAll()); + append($$anchor3, button_2); + }; + if_block(node_4, ($$render) => { + if (get(hasBranches)) $$render(consequent_3); + }); + } + var node_5 = sibling(div_5, 2); + { + var consequent_4 = ($$anchor3) => { + var div_6 = root_8(); + var svg = child(div_6); + each(svg, 21, () => get(connectorGeom), (g) => g.key, ($$anchor4, g) => { + var path_1 = root_9(); + template_effect(() => set_attribute(path_1, "d", get(g).d)); + append($$anchor4, path_1); + }); + var node_6 = sibling(svg, 2); + each(node_6, 17, () => get(laneRender).columns, (lane) => lane.startHash, ($$anchor4, lane) => { + var div_7 = root_10(); + each(div_7, 21, () => get(lane).nodes, (item) => item.hash, ($$anchor5, item) => { + lineageNode($$anchor5, () => get(item), () => get(lane)); + }); + template_effect(() => set_style(div_7, `margin-top: ${get(lane).topRow * LANE_ROW_H}px`)); + append($$anchor4, div_7); + }); + bind_this(div_6, ($$value) => set(lanesWrapEl, $$value), () => get(lanesWrapEl)); + template_effect(() => { + set_attribute(svg, "width", get(connectorBox).w); + set_attribute(svg, "height", get(connectorBox).h); + }); + append($$anchor3, div_6); + }; + var alternate_2 = ($$anchor3) => { + var fragment_2 = root_12(); + var div_8 = first_child(fragment_2); + each(div_8, 23, () => get(lineageDisplay), (d) => d.kind === "node" ? d.item.hash : `${d.kind}:${d.at}`, ($$anchor4, d, i) => { + var fragment_3 = comment(); + var node_7 = first_child(fragment_3); + { + var consequent_6 = ($$anchor5) => { + const item = user_derived(() => get(d).item); + var div_9 = root_14(); + let classes_4; + var img_2 = child(div_9); + var div_10 = sibling(img_2, 2); + let classes_5; + var node_8 = sibling(div_10, 2); + { + var consequent_5 = ($$anchor6) => { + var div_11 = root_15(); + append($$anchor6, div_11); + }; + if_block(node_8, ($$render) => { + if (get(editDocLayers)[get(item).hash]) $$render(consequent_5); + }); + } + template_effect( + ($0) => { + var _a2; + classes_4 = set_class(div_9, 1, "pcr-viewer-lineage-node svelte-5cciiw", null, classes_4, { + current: get(i) === get(lineageDisplayCurrentIdx), + ancestor: get(i) < get(lineageDisplayCurrentIdx), + descendant: get(i) > get(lineageDisplayCurrentIdx), + branch: get(d).branch, + orphaned: get(item).orphaned === 1, + "compare-candidate": get(compareDropdownOpen) && get(item).hash !== get(displayedHash), + "compare-left": get(compareMode) && get(item).hash === get(displayedHash), + "compare-right": get(compareMode) && get(item).hash === get(compareTargetHash) + }); + set_attribute(img_2, "src", $0); + classes_5 = set_class(div_10, 1, "pcr-viewer-lineage-dot svelte-5cciiw", null, classes_5, { + "dot-root": get(item).hash === ((_a2 = get(lineageList)[0]) == null ? void 0 : _a2.hash), + "dot-current": get(i) === get(lineageDisplayCurrentIdx), + "dot-tip": get(i) === get(lineageDisplay).length - 1 && get(i) !== get(lineageDisplayCurrentIdx) + }); + }, + [() => thumbUrl(get(item).hash)] + ); + delegated("click", div_9, () => { + if (get(compareDropdownOpen)) { + if (get(item).hash !== get(displayedHash)) enterCompareWith(get(item).hash, get(item).filename || get(item).hash.slice(0, 8)); + return; + } + lineageJump(get(item).hash); + exitCompare(); + }); + event("mouseenter", div_9, (e) => showTip(e, get(item))); + event("mouseleave", div_9, hideTip); + delegated("contextmenu", div_9, (e) => { + hideTip(); + openLineageMenu(e, get(item)); + }); + append($$anchor5, div_9); + }; + var alternate_1 = ($$anchor5) => { + var div_12 = root_16(); + let classes_6; + var node_9 = child(div_12); + { + var consequent_7 = ($$anchor6) => { + var fragment_4 = root_17(); + var div_13 = first_child(fragment_4); + each(div_13, 21, () => get(d).preview, (p) => p.hash, ($$anchor7, p) => { + var img_3 = root_18(); + template_effect(($0) => set_attribute(img_3, "src", $0), [() => thumbUrl(get(p).hash)]); + append($$anchor7, img_3); + }); + var span_1 = sibling(div_13, 2); + var text_4 = child(span_1); + template_effect(() => set_text(text_4, `+${get(d).count ?? ""}`)); + append($$anchor6, fragment_4); + }; + var alternate = ($$anchor6) => { + var span_2 = root_19(); + append($$anchor6, span_2); + }; + if_block(node_9, ($$render) => { + if (get(d).kind === "bundle") $$render(consequent_7); + else $$render(alternate, -1); + }); + } + template_effect(() => { + classes_6 = set_class(div_12, 1, "pcr-viewer-lineage-bundle svelte-5cciiw", null, classes_6, { expanded: get(d).kind === "collapse" }); + set_attribute(div_12, "title", get(d).kind === "collapse" ? "Collapse this branch" : `${get(d).count} other generation${get(d).count > 1 ? "s" : ""} branch off here — click to expand`); + }); + delegated("click", div_12, () => toggleBundle(get(d).at)); + append($$anchor5, div_12); + }; + if_block(node_7, ($$render) => { + if (get(d).kind === "node") $$render(consequent_6); + else $$render(alternate_1, -1); + }); + } + append($$anchor4, fragment_3); + }); + var node_10 = sibling(div_8, 2); { - var consequent_1 = ($$anchor5) => { - var div_7 = root_5(); - append($$anchor5, div_7); + var consequent_8 = ($$anchor4) => { + var div_14 = root_20(); + var text_5 = child(div_14); + template_effect(() => set_text(text_5, `${get(lineageHiddenCount) ?? ""} hidden`)); + append($$anchor4, div_14); }; - if_block(node_3, ($$render) => { - if (get(editDocLayers)[get(item).hash]) $$render(consequent_1); + if_block(node_10, ($$render) => { + if (get(lineageHiddenCount) > 0) $$render(consequent_8); }); } - template_effect( - ($0) => { - var _a2; - classes = set_class(div_5, 1, "pcr-viewer-lineage-node svelte-5cciiw", null, classes, { - current: get(i) === get(lineageDisplayCurrentIdx), - ancestor: get(i) < get(lineageDisplayCurrentIdx), - descendant: get(i) > get(lineageDisplayCurrentIdx), - branch: get(d).branch, - orphaned: get(item).orphaned === 1, - "compare-candidate": get(compareDropdownOpen) && get(item).hash !== get(displayedHash), - "compare-left": get(compareMode) && get(item).hash === get(displayedHash), - "compare-right": get(compareMode) && get(item).hash === get(compareTargetHash) - }); - set_attribute(img_1, "src", $0); - classes_1 = set_class(div_6, 1, "pcr-viewer-lineage-dot svelte-5cciiw", null, classes_1, { - "dot-root": get(item).hash === ((_a2 = get(lineageList)[0]) == null ? void 0 : _a2.hash), - "dot-current": get(i) === get(lineageDisplayCurrentIdx), - "dot-tip": get(i) === get(lineageDisplay).length - 1 && get(i) !== get(lineageDisplayCurrentIdx) - }); - }, - [() => thumbUrl(get(item).hash)] - ); - delegated("click", div_5, () => { - if (get(compareDropdownOpen)) { - if (get(item).hash !== get(displayedHash)) enterCompareWith(get(item).hash, get(item).filename || get(item).hash.slice(0, 8)); - return; - } - lineageJump(get(item).hash); - exitCompare(); - }); - event("mouseenter", div_5, (e) => showTip(e, get(item))); - event("mouseleave", div_5, hideTip); - delegated("contextmenu", div_5, (e) => { - hideTip(); - openLineageMenu(e, get(item)); - }); - append($$anchor4, div_5); + append($$anchor3, fragment_2); }; - var alternate_1 = ($$anchor4) => { - var div_8 = root_6(); - let classes_2; - var node_4 = child(div_8); + if_block(node_5, ($$render) => { + if (get(lanesActive)) $$render(consequent_4); + else $$render(alternate_2, -1); + }); + } + template_effect(() => { + classes_2 = set_class(div_4, 1, "pcr-viewer-lineage pcr-viewer-lineage-visible svelte-5cciiw", null, classes_2, { lanes: get(lanesActive) }); + set_text(text_2, `${get(lineageCurrentIdx) + 1} / ${get(lineageList).length ?? ""}`); + }); + append($$anchor2, div_4); + }; + var alternate_3 = ($$anchor2) => { + var div_15 = root_21(); + append($$anchor2, div_15); + }; + if_block(node_3, ($$render) => { + if (get(lineageList).length > 1) $$render(consequent_9); + else $$render(alternate_3, -1); + }); + } + var node_11 = sibling(node_3, 2); + { + var consequent_13 = ($$anchor2) => { + var div_16 = root_22(); + var div_17 = child(div_16); + var text_6 = child(div_17); + var node_12 = sibling(div_17, 2); + { + var consequent_10 = ($$anchor3) => { + var div_18 = root_23(); + var text_7 = child(div_18); + template_effect(($0) => set_text(text_7, $0), [() => timeAgo(get(hoverTip).item.created_at)]); + append($$anchor3, div_18); + }; + if_block(node_12, ($$render) => { + if (get(hoverTip).item.created_at) $$render(consequent_10); + }); + } + var node_13 = sibling(node_12, 2); + { + var consequent_11 = ($$anchor3) => { + var div_19 = root_24(); + var text_8 = child(div_19); + template_effect(() => set_text(text_8, `${get(hoverTip).item.width ?? ""}×${get(hoverTip).item.height ?? ""}`)); + append($$anchor3, div_19); + }; + if_block(node_13, ($$render) => { + if (get(hoverTip).item.width && get(hoverTip).item.height) $$render(consequent_11); + }); + } + var node_14 = sibling(node_13, 2); + { + var consequent_12 = ($$anchor3) => { + var div_20 = root_25(); + var text_9 = child(div_20); + template_effect(() => set_text(text_9, `▦ ${get(editDocLayers)[get(hoverTip).item.hash] ?? ""} layers — opens layered in Edit`)); + append($$anchor3, div_20); + }; + if_block(node_14, ($$render) => { + if (get(editDocLayers)[get(hoverTip).item.hash]) $$render(consequent_12); + }); + } + template_effect( + ($0) => { + set_style(div_16, `top:${get(hoverTip).top ?? ""}px; left:${get(hoverTip).left ?? ""}px;`); + set_text(text_6, $0); + }, + [ + () => { + var _a2; + return get(hoverTip).item.filename || ((_a2 = get(hoverTip).item.hash) == null ? void 0 : _a2.slice(0, 12)); + } + ] + ); + append($$anchor2, div_16); + }; + if_block(node_11, ($$render) => { + if (get(hoverTip)) $$render(consequent_13); + }); + } + var div_21 = sibling(node_11, 2); + var node_15 = child(div_21); + { + var consequent_14 = ($$anchor2) => { + var div_22 = root_26(); + var text_10 = child(div_22); + template_effect(() => set_text(text_10, `✨ ${get(newGenBanner) ?? ""}`)); + append($$anchor2, div_22); + }; + if_block(node_15, ($$render) => { + if (get(newGenBanner)) $$render(consequent_14); + }); + } + var node_16 = sibling(node_15, 2); + { + var consequent_15 = ($$anchor2) => { + var div_23 = root_27(); + append($$anchor2, div_23); + }; + if_block(node_16, ($$render) => { + if (get(copyPathToast)) $$render(consequent_15); + }); + } + var node_17 = sibling(node_16, 2); + { + var consequent_24 = ($$anchor2) => { + var fragment_5 = root_28(); + var node_18 = first_child(fragment_5); + { + var consequent_16 = ($$anchor3) => { + var div_24 = root_29(); + append($$anchor3, div_24); + }; + if_block(node_18, ($$render) => { + if (!get(imageLoaded) && !get(imageError)) $$render(consequent_16); + }); + } + var img_4 = sibling(node_18, 2); + let classes_7; + bind_this(img_4, ($$value) => set(mainImageEl, $$value), () => get(mainImageEl)); + var node_19 = sibling(img_4, 2); + { + var consequent_17 = ($$anchor3) => { + var img_5 = root_30(); + template_effect(() => { + set_attribute(img_5, "src", get(compareImageUrl)); + set_style(img_5, `transform: translate(${get(panX) ?? ""}px, ${get(panY) ?? ""}px) scale(${get(zoom) ?? ""}); clip-path: inset(0 0 0 ${get(compareClipPercent) ?? ""}%);`); + }); + append($$anchor3, img_5); + }; + if_block(node_19, ($$render) => { + if (get(compareMode) && get(compareImageUrl)) $$render(consequent_17); + }); + } + var node_20 = sibling(node_19, 2); + { + var consequent_20 = ($$anchor3) => { + var div_25 = root_31(); + var div_26 = child(div_25); + var text_11 = child(div_26); + var node_21 = sibling(div_26, 2); { - var consequent_3 = ($$anchor5) => { - var fragment_2 = root_7(); - var div_9 = first_child(fragment_2); - each(div_9, 21, () => get(d).preview, (p) => p.hash, ($$anchor6, p) => { - var img_2 = root_8(); - template_effect(($0) => set_attribute(img_2, "src", $0), [() => thumbUrl(get(p).hash)]); - append($$anchor6, img_2); + var consequent_19 = ($$anchor4) => { + var fragment_6 = root_32(); + var button_3 = sibling(first_child(fragment_6), 2); + var text_12 = child(button_3); + var node_22 = sibling(button_3, 2); + { + var consequent_18 = ($$anchor5) => { + var div_27 = root_33(); + var text_13 = child(div_27); + template_effect(() => set_text(text_13, get(reattachMsg))); + append($$anchor5, div_27); + }; + if_block(node_22, ($$render) => { + if (get(reattachMsg)) $$render(consequent_18); + }); + } + var input = sibling(node_22, 2); + bind_this(input, ($$value) => set(reattachInputEl, $$value), () => get(reattachInputEl)); + template_effect(() => { + button_3.disabled = get(reattaching); + set_text(text_12, get(reattaching) ? "Verifying…" : "Locate file…"); }); - var span = sibling(div_9, 2); - var text_2 = child(span); - template_effect(() => set_text(text_2, `+${get(d).count ?? ""}`)); - append($$anchor5, fragment_2); + delegated("click", button_3, () => { + var _a2; + return (_a2 = get(reattachInputEl)) == null ? void 0 : _a2.click(); + }); + delegated("change", input, handleReattachPick); + append($$anchor4, fragment_6); }; - var alternate = ($$anchor5) => { - var span_1 = root_9(); - append($$anchor5, span_1); + if_block(node_21, ($$render) => { + if (get(canReattach)) $$render(consequent_19); + }); + } + template_effect(() => set_text(text_11, get(isOrphaned) ? "Source file deleted" : "Image not found")); + append($$anchor3, div_25); + }; + if_block(node_20, ($$render) => { + if (get(imageError)) $$render(consequent_20); + }); + } + var node_23 = sibling(node_20, 2); + { + var consequent_23 = ($$anchor3) => { + var fragment_7 = root_34(); + var div_28 = first_child(fragment_7); + var div_29 = sibling(div_28, 2); + var text_14 = child(div_29); + var node_24 = sibling(text_14); + { + var consequent_21 = ($$anchor4) => { + var div_30 = root_35(); + var text_15 = child(div_30); + template_effect(($0) => set_text(text_15, $0), [() => timeAgo(get(imageInfo).created_at)]); + append($$anchor4, div_30); }; - if_block(node_4, ($$render) => { - if (get(d).kind === "bundle") $$render(consequent_3); - else $$render(alternate, -1); + if_block(node_24, ($$render) => { + var _a2; + if ((_a2 = get(imageInfo)) == null ? void 0 : _a2.created_at) $$render(consequent_21); + }); + } + var div_31 = sibling(div_29, 2); + var text_16 = child(div_31); + var node_25 = sibling(text_16); + { + var consequent_22 = ($$anchor4) => { + var div_32 = root_36(); + var text_17 = child(div_32); + template_effect(($0) => set_text(text_17, $0), [() => timeAgo(get(compareTargetItem).created_at)]); + append($$anchor4, div_32); + }; + if_block(node_25, ($$render) => { + var _a2; + if ((_a2 = get(compareTargetItem)) == null ? void 0 : _a2.created_at) $$render(consequent_22); }); } template_effect(() => { - classes_2 = set_class(div_8, 1, "pcr-viewer-lineage-bundle svelte-5cciiw", null, classes_2, { expanded: get(d).kind === "collapse" }); - set_attribute(div_8, "title", get(d).kind === "collapse" ? "Collapse this branch" : `${get(d).count} other generation${get(d).count > 1 ? "s" : ""} branch off here — click to expand`); + var _a2; + set_style(div_28, `left: ${get(compareSliderPos) ?? ""}%;`); + set_text(text_14, `${(((_a2 = get(imageInfo)) == null ? void 0 : _a2.filename) || "Current") ?? ""} `); + set_text(text_16, `${(get(compareTargetLabel) || "Compare") ?? ""} `); }); - delegated("click", div_8, () => toggleBundle(get(d).at)); - append($$anchor4, div_8); + delegated("mousedown", div_28, handleSliderDown); + append($$anchor3, fragment_7); }; - if_block(node_2, ($$render) => { - if (get(d).kind === "node") $$render(consequent_2); - else $$render(alternate_1, -1); + if_block(node_23, ($$render) => { + if (get(compareMode)) $$render(consequent_23); }); } - append($$anchor3, fragment_1); - }); - var node_5 = sibling(div_4, 2); - { - var consequent_4 = ($$anchor3) => { - var div_10 = root_10(); - var text_3 = child(div_10); - template_effect(() => set_text(text_3, `${get(lineageHiddenCount) ?? ""} hidden`)); - append($$anchor3, div_10); - }; - if_block(node_5, ($$render) => { - if (get(lineageHiddenCount) > 0) $$render(consequent_4); - }); - } - template_effect(() => set_text(text_1, `${get(lineageCurrentIdx) + 1} / ${get(lineageList).length ?? ""}`)); - append($$anchor2, div_2); - }; - var alternate_2 = ($$anchor2) => { - var div_11 = root_11(); - append($$anchor2, div_11); - }; - if_block(node_1, ($$render) => { - if (get(lineageList).length > 1) $$render(consequent_5); - else $$render(alternate_2, -1); - }); - } - var node_6 = sibling(node_1, 2); - { - var consequent_9 = ($$anchor2) => { - var div_12 = root_12(); - var div_13 = child(div_12); - var text_4 = child(div_13); - var node_7 = sibling(div_13, 2); - { - var consequent_6 = ($$anchor3) => { - var div_14 = root_13(); - var text_5 = child(div_14); - template_effect(($0) => set_text(text_5, $0), [() => timeAgo(get(hoverTip).item.created_at)]); - append($$anchor3, div_14); - }; - if_block(node_7, ($$render) => { - if (get(hoverTip).item.created_at) $$render(consequent_6); - }); - } - var node_8 = sibling(node_7, 2); - { - var consequent_7 = ($$anchor3) => { - var div_15 = root_14(); - var text_6 = child(div_15); - template_effect(() => set_text(text_6, `${get(hoverTip).item.width ?? ""}×${get(hoverTip).item.height ?? ""}`)); - append($$anchor3, div_15); - }; - if_block(node_8, ($$render) => { - if (get(hoverTip).item.width && get(hoverTip).item.height) $$render(consequent_7); - }); - } - var node_9 = sibling(node_8, 2); - { - var consequent_8 = ($$anchor3) => { - var div_16 = root_15(); - var text_7 = child(div_16); - template_effect(() => set_text(text_7, `▦ ${get(editDocLayers)[get(hoverTip).item.hash] ?? ""} layers — opens layered in Edit`)); - append($$anchor3, div_16); - }; - if_block(node_9, ($$render) => { - if (get(editDocLayers)[get(hoverTip).item.hash]) $$render(consequent_8); - }); - } - template_effect( - ($0) => { - set_style(div_12, `top:${get(hoverTip).top ?? ""}px; left:${get(hoverTip).left ?? ""}px;`); - set_text(text_4, $0); - }, - [ - () => { - var _a2; - return get(hoverTip).item.filename || ((_a2 = get(hoverTip).item.hash) == null ? void 0 : _a2.slice(0, 12)); - } - ] - ); - append($$anchor2, div_12); - }; - if_block(node_6, ($$render) => { - if (get(hoverTip)) $$render(consequent_9); - }); - } - var div_17 = sibling(node_6, 2); - var node_10 = child(div_17); - { - var consequent_18 = ($$anchor2) => { - var fragment_3 = root_16(); - var node_11 = first_child(fragment_3); - { - var consequent_10 = ($$anchor3) => { - var div_18 = root_17(); - append($$anchor3, div_18); - }; - if_block(node_11, ($$render) => { - if (!get(imageLoaded) && !get(imageError)) $$render(consequent_10); - }); - } - var img_3 = sibling(node_11, 2); - let classes_3; - bind_this(img_3, ($$value) => set(mainImageEl, $$value), () => get(mainImageEl)); - var node_12 = sibling(img_3, 2); - { - var consequent_11 = ($$anchor3) => { - var img_4 = root_18(); - template_effect(() => { - set_attribute(img_4, "src", get(compareImageUrl)); - set_style(img_4, `transform: translate(${get(panX) ?? ""}px, ${get(panY) ?? ""}px) scale(${get(zoom) ?? ""}); clip-path: inset(0 0 0 ${get(compareClipPercent) ?? ""}%);`); - }); - append($$anchor3, img_4); - }; - if_block(node_12, ($$render) => { - if (get(compareMode) && get(compareImageUrl)) $$render(consequent_11); - }); - } - var node_13 = sibling(node_12, 2); - { - var consequent_14 = ($$anchor3) => { - var div_19 = root_19(); - var div_20 = child(div_19); - var text_8 = child(div_20); - var node_14 = sibling(div_20, 2); - { - var consequent_13 = ($$anchor4) => { - var fragment_4 = root_20(); - var button = sibling(first_child(fragment_4), 2); - var text_9 = child(button); - var node_15 = sibling(button, 2); - { - var consequent_12 = ($$anchor5) => { - var div_21 = root_21(); - var text_10 = child(div_21); - template_effect(() => set_text(text_10, get(reattachMsg))); - append($$anchor5, div_21); - }; - if_block(node_15, ($$render) => { - if (get(reattachMsg)) $$render(consequent_12); - }); - } - var input = sibling(node_15, 2); - bind_this(input, ($$value) => set(reattachInputEl, $$value), () => get(reattachInputEl)); - template_effect(() => { - button.disabled = get(reattaching); - set_text(text_9, get(reattaching) ? "Verifying…" : "Locate file…"); - }); - delegated("click", button, () => { - var _a2; - return (_a2 = get(reattachInputEl)) == null ? void 0 : _a2.click(); - }); - delegated("change", input, handleReattachPick); - append($$anchor4, fragment_4); - }; - if_block(node_14, ($$render) => { - if (get(canReattach)) $$render(consequent_13); - }); - } - template_effect(() => set_text(text_8, get(isOrphaned) ? "Source file deleted" : "Image not found")); - append($$anchor3, div_19); - }; - if_block(node_13, ($$render) => { - if (get(imageError)) $$render(consequent_14); - }); - } - var node_16 = sibling(node_13, 2); - { - var consequent_17 = ($$anchor3) => { - var fragment_5 = root_22(); - var div_22 = first_child(fragment_5); - var div_23 = sibling(div_22, 2); - var text_11 = child(div_23); - var node_17 = sibling(text_11); - { - var consequent_15 = ($$anchor4) => { - var div_24 = root_23(); - var text_12 = child(div_24); - template_effect(($0) => set_text(text_12, $0), [() => timeAgo(get(imageInfo).created_at)]); - append($$anchor4, div_24); - }; - if_block(node_17, ($$render) => { - var _a2; - if ((_a2 = get(imageInfo)) == null ? void 0 : _a2.created_at) $$render(consequent_15); - }); - } - var div_25 = sibling(div_23, 2); - var text_13 = child(div_25); - var node_18 = sibling(text_13); - { - var consequent_16 = ($$anchor4) => { - var div_26 = root_24(); - var text_14 = child(div_26); - template_effect(($0) => set_text(text_14, $0), [() => timeAgo(get(compareTargetItem).created_at)]); - append($$anchor4, div_26); - }; - if_block(node_18, ($$render) => { - var _a2; - if ((_a2 = get(compareTargetItem)) == null ? void 0 : _a2.created_at) $$render(consequent_16); - }); - } - template_effect(() => { - var _a2; - set_style(div_22, `left: ${get(compareSliderPos) ?? ""}%;`); - set_text(text_11, `${(((_a2 = get(imageInfo)) == null ? void 0 : _a2.filename) || "Current") ?? ""} `); - set_text(text_13, `${(get(compareTargetLabel) || "Compare") ?? ""} `); - }); - delegated("mousedown", div_22, handleSliderDown); - append($$anchor3, fragment_5); - }; - if_block(node_16, ($$render) => { - if (get(compareMode)) $$render(consequent_17); - }); - } - template_effect( - ($0) => { - set_attribute(img_3, "src", $0); - classes_3 = set_class(img_3, 1, "pcr-viewer-image svelte-5cciiw", null, classes_3, { hidden: !get(imageLoaded) }); - set_style(img_3, `transform: translate(${get(panX) ?? ""}px, ${get(panY) ?? ""}px) scale(${get(zoom) ?? ""})`); - }, - [() => mainImageSrc(get(displayedHash))] - ); - event("load", img_3, () => { - set(imageLoaded, true); - }); - event("error", img_3, () => { - set(imageError, true); - set(imageLoaded, false); - }); - append($$anchor2, fragment_3); - }; - if_block(node_10, ($$render) => { - if (get(displayedHash)) $$render(consequent_18); - }); - } - var node_19 = sibling(node_10, 2); - { - var consequent_19 = ($$anchor2) => { - var div_27 = root_25(); - delegated("pointerdown", div_27, (e) => e.stopPropagation()); - delegated("click", div_27, (e) => { - e.stopPropagation(); - navigate(-1); - }); - append($$anchor2, div_27); - }; - if_block(node_19, ($$render) => { - if (get(currentIndex) > 0) $$render(consequent_19); - }); - } - var node_20 = sibling(node_19, 2); - { - var consequent_20 = ($$anchor2) => { - var div_28 = root_26(); - delegated("pointerdown", div_28, (e) => e.stopPropagation()); - delegated("click", div_28, (e) => { - e.stopPropagation(); - navigate(1); - }); - append($$anchor2, div_28); - }; - if_block(node_20, ($$render) => { - if (get(currentIndex) < images().length - 1) $$render(consequent_20); - }); - } - bind_this(div_17, ($$value) => containerEl = $$value, () => containerEl); - var div_29 = sibling(div_17, 2); - var div_30 = child(div_29); - var span_2 = child(div_30); - var text_15 = child(span_2); - var div_31 = sibling(span_2, 2); - var node_21 = sibling(div_30, 2); - { - var consequent_23 = ($$anchor2) => { - var div_32 = root_27(); - let classes_4; - var div_33 = child(div_32); - var div_34 = child(div_33); - var node_22 = child(div_34); - each(node_22, 17, () => get(visibleThumbs), (thumb) => thumb.hash, ($$anchor3, thumb) => { - var div_35 = root_28(); - let classes_5; - var img_5 = child(div_35); template_effect( ($0) => { - classes_5 = set_class(div_35, 1, "pcr-viewer-history-thumb svelte-5cciiw", null, classes_5, { current: get(thumb).globalIndex === get(currentIndex) }); - set_attribute(img_5, "src", $0); + set_attribute(img_4, "src", $0); + classes_7 = set_class(img_4, 1, "pcr-viewer-image svelte-5cciiw", null, classes_7, { hidden: !get(imageLoaded) }); + set_style(img_4, `transform: translate(${get(panX) ?? ""}px, ${get(panY) ?? ""}px) scale(${get(zoom) ?? ""})`); }, - [() => thumbUrl(get(thumb).hash)] + [() => mainImageSrc(get(displayedHash))] ); - delegated("click", div_35, () => jumpTo(get(thumb).globalIndex)); - append($$anchor3, div_35); - }); - var div_36 = sibling(div_34, 2); - var svg = child(div_36); - var node_23 = child(svg); - { - var consequent_21 = ($$anchor3) => { - var path_1 = root_29(); - append($$anchor3, path_1); - }; - var alternate_3 = ($$anchor3) => { - var path_2 = root_30(); - append($$anchor3, path_2); - }; - if_block(node_23, ($$render) => { - if (get(historyExpanded)) $$render(consequent_21); - else $$render(alternate_3, -1); + event("load", img_4, () => { + set(imageLoaded, true); }); - } - var div_37 = sibling(div_33, 2); - var div_38 = child(div_37); - var div_39 = sibling(div_38, 2); - var node_24 = sibling(div_37, 2); - { - var consequent_22 = ($$anchor3) => { - var div_40 = root_31(); - each(div_40, 23, images, (img) => img.hash, ($$anchor4, img, idx) => { - var div_41 = root_32(); - let classes_6; - var img_6 = child(div_41); - template_effect( - ($0) => { - classes_6 = set_class(div_41, 1, "pcr-viewer-grid-thumb svelte-5cciiw", null, classes_6, { current: get(idx) === get(currentIndex) }); - set_attribute(img_6, "src", $0); - }, - [() => thumbUrl(get(img).hash)] - ); - delegated("click", div_41, () => jumpTo(get(idx))); - append($$anchor4, div_41); - }); - bind_this(div_40, ($$value) => set(historyGridEl, $$value), () => get(historyGridEl)); - append($$anchor3, div_40); - }; - if_block(node_24, ($$render) => { - if (get(historyExpanded)) $$render(consequent_22); + event("error", img_4, () => { + set(imageError, true); + set(imageLoaded, false); }); - } - template_effect(() => { - classes_4 = set_class(div_32, 1, "pcr-viewer-history svelte-5cciiw", null, classes_4, { expanded: get(historyExpanded) }); - set_attribute(div_36, "title", get(historyExpanded) ? "Collapse" : "Expand"); - set_style(div_38, `width: ${get(scrubberPercent) ?? ""}%`); - set_style(div_39, `left: ${get(scrubberPercent) ?? ""}%`); + append($$anchor2, fragment_5); + }; + if_block(node_17, ($$render) => { + if (get(displayedHash)) $$render(consequent_24); }); - delegated("click", div_36, toggleGrid); - delegated("mousedown", div_37, handleScrubberTrackDown); - delegated("mousedown", div_39, handleScrubberHandleDown); - append($$anchor2, div_32); - }; - if_block(node_21, ($$render) => { - if (images().length > 1) $$render(consequent_23); - }); - } - var div_42 = sibling(node_21, 2); - var div_43 = child(div_42); - var div_44 = child(div_43); - var div_45 = child(div_44); - var span_3 = sibling(child(div_45), 2); - var text_16 = child(span_3); - var node_25 = sibling(div_45, 2); - { - var consequent_24 = ($$anchor2) => { - var div_46 = root_33(); - each(div_46, 21, () => ZOOM_PRESETS, index, ($$anchor3, level) => { - var div_47 = root_34(); - var text_17 = child(div_47); - template_effect(() => set_text(text_17, `${get(level) ?? ""}%`)); - delegated("click", div_47, () => setZoomLevel(get(level))); - append($$anchor3, div_47); + } + var node_26 = sibling(node_17, 2); + { + var consequent_25 = ($$anchor2) => { + var div_33 = root_37(); + delegated("pointerdown", div_33, (e) => e.stopPropagation()); + delegated("click", div_33, (e) => { + e.stopPropagation(); + navigate(-1); + }); + append($$anchor2, div_33); + }; + if_block(node_26, ($$render) => { + if (get(currentIndex) > 0) $$render(consequent_25); }); - append($$anchor2, div_46); - }; - if_block(node_25, ($$render) => { - if (get(zoomDropdownOpen)) $$render(consequent_24); - }); - } - var input_1 = sibling(div_44, 2); - var node_26 = sibling(div_43, 2); - { - var consequent_27 = ($$anchor2) => { - var div_48 = root_35(); - var div_49 = child(div_48); - let classes_7; - var node_27 = sibling(div_49, 2); - { - var consequent_26 = ($$anchor3) => { - var div_50 = root_36(); - var node_28 = child(div_50); - each(node_28, 17, () => get(compareTargets), index, ($$anchor4, target) => { - var div_51 = root_37(); - let classes_8; - var text_18 = child(div_51); - template_effect( - ($0) => { - classes_8 = set_class(div_51, 1, "pcr-viewer-compare-dropdown-item svelte-5cciiw", null, classes_8, { active: get(compareTargetHash) === get(target).hash }); - set_text(text_18, $0); - }, - [ - () => get(target).filename || get(target).hash.slice(0, 8) - ] - ); - delegated("click", div_51, () => enterCompareWith(get(target).hash, get(target).filename || get(target).hash.slice(0, 8))); - append($$anchor4, div_51); + } + var node_27 = sibling(node_26, 2); + { + var consequent_26 = ($$anchor2) => { + var div_34 = root_38(); + delegated("pointerdown", div_34, (e) => e.stopPropagation()); + delegated("click", div_34, (e) => { + e.stopPropagation(); + navigate(1); + }); + append($$anchor2, div_34); + }; + if_block(node_27, ($$render) => { + if (get(currentIndex) < images().length - 1) $$render(consequent_26); + }); + } + bind_this(div_21, ($$value) => containerEl = $$value, () => containerEl); + var div_35 = sibling(div_21, 2); + var div_36 = child(div_35); + var span_3 = child(div_36); + var text_18 = child(span_3); + var div_37 = sibling(span_3, 2); + var node_28 = sibling(div_36, 2); + { + var consequent_29 = ($$anchor2) => { + var div_38 = root_39(); + let classes_8; + var div_39 = child(div_38); + var div_40 = child(div_39); + var node_29 = child(div_40); + each(node_29, 17, () => get(visibleThumbs), (thumb) => thumb.hash, ($$anchor3, thumb) => { + var div_41 = root_40(); + let classes_9; + var img_6 = child(div_41); + template_effect( + ($0) => { + classes_9 = set_class(div_41, 1, "pcr-viewer-history-thumb svelte-5cciiw", null, classes_9, { current: get(thumb).globalIndex === get(currentIndex) }); + set_attribute(img_6, "src", $0); + }, + [() => thumbUrl(get(thumb).hash)] + ); + delegated("click", div_41, () => jumpTo(get(thumb).globalIndex)); + append($$anchor3, div_41); + }); + var div_42 = sibling(div_40, 2); + var svg_1 = child(div_42); + var node_30 = child(svg_1); + { + var consequent_27 = ($$anchor3) => { + var path_2 = root_41(); + append($$anchor3, path_2); + }; + var alternate_4 = ($$anchor3) => { + var path_3 = root_42(); + append($$anchor3, path_3); + }; + if_block(node_30, ($$render) => { + if (get(historyExpanded)) $$render(consequent_27); + else $$render(alternate_4, -1); }); - var node_29 = sibling(node_28, 2); - { - var consequent_25 = ($$anchor4) => { - var fragment_6 = root_38(); - var div_52 = sibling(first_child(fragment_6), 2); - delegated("click", div_52, exitCompare); - append($$anchor4, fragment_6); - }; - if_block(node_29, ($$render) => { - if (get(compareMode)) $$render(consequent_25); + } + var div_43 = sibling(div_39, 2); + var div_44 = child(div_43); + var div_45 = sibling(div_44, 2); + var node_31 = sibling(div_43, 2); + { + var consequent_28 = ($$anchor3) => { + var div_46 = root_43(); + each(div_46, 23, images, (img) => img.hash, ($$anchor4, img, idx) => { + var div_47 = root_44(); + let classes_10; + var img_7 = child(div_47); + template_effect( + ($0) => { + classes_10 = set_class(div_47, 1, "pcr-viewer-grid-thumb svelte-5cciiw", null, classes_10, { current: get(idx) === get(currentIndex) }); + set_attribute(img_7, "src", $0); + }, + [() => thumbUrl(get(img).hash)] + ); + delegated("click", div_47, () => jumpTo(get(idx))); + append($$anchor4, div_47); }); - } - append($$anchor3, div_50); - }; - if_block(node_27, ($$render) => { - if (get(compareDropdownOpen)) $$render(consequent_26); - }); - } - template_effect(() => classes_7 = set_class(div_49, 1, "pcr-viewer-toolbar-btn svelte-5cciiw", null, classes_7, { active: get(compareMode) || get(compareDropdownOpen) })); - delegated("click", div_49, () => { - set(compareDropdownOpen, !get(compareDropdownOpen)); - }); - append($$anchor2, div_48); - }; - if_block(node_26, ($$render) => { - if (get(hasCompareTargets)) $$render(consequent_27); - }); - } - var node_30 = sibling(node_26, 2); - { - if_block(node_30, ($$render) => { - }); - } - var node_31 = sibling(node_30, 2); - { - if_block(node_31, ($$render) => { - }); - } - var node_32 = sibling(node_31, 2); - { - var consequent_31 = ($$anchor2) => { - var div_57 = root_41(); - var div_58 = child(div_57); - var span_6 = sibling(child(div_58), 2); - var text_21 = child(span_6); - var node_33 = sibling(span_6, 2); - { - var consequent_30 = ($$anchor3) => { - var span_7 = root_42(); - var text_22 = sibling(child(span_7)); - template_effect(() => { - set_attribute(span_7, "title", `This image has ${get(editDocLayers)[get(displayedHash)] ?? ""} saved layers — Edit opens it layered, un-flattened`); - set_text(text_22, ` ${get(editDocLayers)[get(displayedHash)] ?? ""}`); + bind_this(div_46, ($$value) => set(historyGridEl, $$value), () => get(historyGridEl)); + append($$anchor3, div_46); + }; + if_block(node_31, ($$render) => { + if (get(historyExpanded)) $$render(consequent_28); }); - append($$anchor3, span_7); - }; - if_block(node_33, ($$render) => { - if (get(editDocLayers)[get(displayedHash)]) $$render(consequent_30); + } + template_effect(() => { + classes_8 = set_class(div_38, 1, "pcr-viewer-history svelte-5cciiw", null, classes_8, { expanded: get(historyExpanded) }); + set_attribute(div_42, "title", get(historyExpanded) ? "Collapse" : "Expand"); + set_style(div_44, `width: ${get(scrubberPercent) ?? ""}%`); + set_style(div_45, `left: ${get(scrubberPercent) ?? ""}%`); }); - } - template_effect(() => set_text(text_21, get(editPreparing) ? "Reading..." : "Edit")); - delegated("click", div_58, () => { - if (!get(editPreparing)) openEdit(); + delegated("click", div_42, toggleGrid); + delegated("mousedown", div_43, handleScrubberTrackDown); + delegated("mousedown", div_45, handleScrubberHandleDown); + append($$anchor2, div_38); + }; + if_block(node_28, ($$render) => { + if (images().length > 1) $$render(consequent_29); }); - append($$anchor2, div_57); - }; - if_block(node_32, ($$render) => { - if (onEditSave()) $$render(consequent_31); - }); - } - var div_59 = sibling(node_32, 2); - var node_34 = child(div_59); - { - var consequent_32 = ($$anchor2) => { - var div_60 = root_43(); - var span_8 = sibling(child(div_60), 2); - var text_23 = child(span_8); - template_effect(() => set_text(text_23, get(deleting) ? "Deleting..." : "Delete")); - delegated("click", div_60, requestDelete); - append($$anchor2, div_60); - }; - if_block(node_34, ($$render) => { - if (onDelete()) $$render(consequent_32); - }); - } - var node_35 = sibling(node_34, 2); - { - var consequent_33 = ($$anchor2) => { - var div_61 = root_44(); - delegated("click", div_61, openFolder); - append($$anchor2, div_61); - }; - if_block(node_35, ($$render) => { - if (isLocalClient) $$render(consequent_33); - }); - } - var div_62 = sibling(node_35, 2); - let classes_9; - var span_9 = sibling(child(div_62), 2); - var text_24 = child(span_9); - var div_63 = sibling(div_42, 2); - var node_36 = child(div_63); - { - var consequent_51 = ($$anchor2) => { - var fragment_7 = root_45(); - var div_64 = sibling(first_child(fragment_7), 2); - var div_65 = child(div_64); - var node_37 = child(div_65); - { - var consequent_34 = ($$anchor3) => { - var div_66 = root_46(); - var span_10 = sibling(child(div_66), 2); - var text_25 = child(span_10); - template_effect(() => set_text(text_25, `${get(imageInfo).width ?? ""} × ${get(imageInfo).height ?? ""}`)); - append($$anchor3, div_66); - }; - if_block(node_37, ($$render) => { - if (get(imageInfo).width && get(imageInfo).height) $$render(consequent_34); + } + var div_48 = sibling(node_28, 2); + var div_49 = child(div_48); + var div_50 = child(div_49); + var div_51 = child(div_50); + var span_4 = sibling(child(div_51), 2); + var text_19 = child(span_4); + var node_32 = sibling(div_51, 2); + { + var consequent_30 = ($$anchor2) => { + var div_52 = root_45(); + each(div_52, 21, () => ZOOM_PRESETS, index, ($$anchor3, level) => { + var div_53 = root_46(); + var text_20 = child(div_53); + template_effect(() => set_text(text_20, `${get(level) ?? ""}%`)); + delegated("click", div_53, () => setZoomLevel(get(level))); + append($$anchor3, div_53); }); - } - var node_38 = sibling(node_37, 2); - { - var consequent_35 = ($$anchor3) => { - var div_67 = root_47(); - var span_11 = sibling(child(div_67), 2); - var text_26 = child(span_11); - template_effect(($0) => set_text(text_26, $0), [ - () => get(imageInfo).file_size > 1048576 ? (get(imageInfo).file_size / 1048576).toFixed(1) + " MB" : Math.round(get(imageInfo).file_size / 1024) + " KB" - ]); - append($$anchor3, div_67); - }; - if_block(node_38, ($$render) => { - if (get(imageInfo).file_size) $$render(consequent_35); - }); - } - var node_39 = sibling(div_65, 2); - { - var consequent_36 = ($$anchor3) => { - var div_68 = root_48(); - var span_12 = sibling(child(div_68), 2); - var text_27 = child(span_12); - template_effect(($0) => set_text(text_27, $0), [ - () => new Date(get(imageInfo).created_at * 1e3).toLocaleDateString() - ]); - append($$anchor3, div_68); - }; - if_block(node_39, ($$render) => { - if (get(imageInfo).created_at) $$render(consequent_36); - }); - } - var node_40 = sibling(node_39, 2); - { - var consequent_37 = ($$anchor3) => { - var div_69 = root_49(); - var span_13 = sibling(child(div_69), 2); - var text_28 = child(span_13); - template_effect(() => set_text(text_28, get(imageInfo).filename)); - append($$anchor3, div_69); - }; - if_block(node_40, ($$render) => { - if (get(imageInfo).filename) $$render(consequent_37); - }); - } - var node_41 = sibling(node_40, 2); - { - var consequent_38 = ($$anchor3) => { - var div_70 = root_50(); - append($$anchor3, div_70); - }; - if_block(node_41, ($$render) => { - if (get(isOrphaned)) $$render(consequent_38); - }); - } - var node_42 = sibling(div_64, 2); - { - var consequent_43 = ($$anchor3) => { - const regionData = user_derived(() => parseRegions(get(imageInfo).regions)); - var fragment_8 = root_51(); - var div_71 = sibling(first_child(fragment_8), 2); - var node_43 = child(div_71); - { - var consequent_40 = ($$anchor4) => { - var fragment_9 = root_52(); - var node_44 = first_child(fragment_9); - each(node_44, 17, () => get(regionData).regions, (region) => region.id, ($$anchor5, region) => { - var div_72 = root_53(); - var span_14 = child(div_72); - var text_29 = child(span_14); - var p_1 = sibling(span_14, 2); - var text_30 = child(p_1); - template_effect(() => { - set_text(text_29, `$${get(region).name ?? ""}`); - set_text(text_30, get(region).text); - }); - append($$anchor5, div_72); + append($$anchor2, div_52); + }; + if_block(node_32, ($$render) => { + if (get(zoomDropdownOpen)) $$render(consequent_30); + }); + } + var input_1 = sibling(div_50, 2); + var node_33 = sibling(div_49, 2); + { + var consequent_33 = ($$anchor2) => { + var div_54 = root_47(); + var div_55 = child(div_54); + let classes_11; + var node_34 = sibling(div_55, 2); + { + var consequent_32 = ($$anchor3) => { + var div_56 = root_48(); + var node_35 = child(div_56); + each(node_35, 17, () => get(compareTargets), index, ($$anchor4, target) => { + var div_57 = root_49(); + let classes_12; + var text_21 = child(div_57); + template_effect( + ($0) => { + classes_12 = set_class(div_57, 1, "pcr-viewer-compare-dropdown-item svelte-5cciiw", null, classes_12, { active: get(compareTargetHash) === get(target).hash }); + set_text(text_21, $0); + }, + [ + () => get(target).filename || get(target).hash.slice(0, 8) + ] + ); + delegated("click", div_57, () => enterCompareWith(get(target).hash, get(target).filename || get(target).hash.slice(0, 8))); + append($$anchor4, div_57); + }); + var node_36 = sibling(node_35, 2); + { + var consequent_31 = ($$anchor4) => { + var fragment_8 = root_50(); + var div_58 = sibling(first_child(fragment_8), 2); + delegated("click", div_58, exitCompare); + append($$anchor4, fragment_8); + }; + if_block(node_36, ($$render) => { + if (get(compareMode)) $$render(consequent_31); }); - var node_45 = sibling(node_44, 2); - { - var consequent_39 = ($$anchor5) => { - var div_73 = root_54(); - var p_2 = sibling(child(div_73), 2); - var text_31 = child(p_2); - template_effect(() => set_text(text_31, get(regionData).global)); - append($$anchor5, div_73); - }; - if_block(node_45, ($$render) => { - if (get(regionData).global) $$render(consequent_39); + } + append($$anchor3, div_56); + }; + if_block(node_34, ($$render) => { + if (get(compareDropdownOpen)) $$render(consequent_32); + }); + } + template_effect(() => classes_11 = set_class(div_55, 1, "pcr-viewer-toolbar-btn svelte-5cciiw", null, classes_11, { active: get(compareMode) || get(compareDropdownOpen) })); + delegated("click", div_55, () => { + set(compareDropdownOpen, !get(compareDropdownOpen)); + }); + append($$anchor2, div_54); + }; + if_block(node_33, ($$render) => { + if (get(hasCompareTargets)) $$render(consequent_33); + }); + } + var node_37 = sibling(node_33, 2); + { + if_block(node_37, ($$render) => { + }); + } + var node_38 = sibling(node_37, 2); + { + if_block(node_38, ($$render) => { + }); + } + var node_39 = sibling(node_38, 2); + { + var consequent_37 = ($$anchor2) => { + var div_63 = root_53(); + var div_64 = child(div_63); + var span_7 = sibling(child(div_64), 2); + var text_24 = child(span_7); + var node_40 = sibling(span_7, 2); + { + var consequent_36 = ($$anchor3) => { + var span_8 = root_54(); + var text_25 = sibling(child(span_8)); + template_effect(() => { + set_attribute(span_8, "title", `This image has ${get(editDocLayers)[get(displayedHash)] ?? ""} saved layers — Edit opens it layered, un-flattened`); + set_text(text_25, ` ${get(editDocLayers)[get(displayedHash)] ?? ""}`); + }); + append($$anchor3, span_8); + }; + if_block(node_40, ($$render) => { + if (get(editDocLayers)[get(displayedHash)]) $$render(consequent_36); + }); + } + template_effect(() => set_text(text_24, get(editPreparing) ? "Reading..." : "Edit")); + delegated("click", div_64, () => { + if (!get(editPreparing)) openEdit(); + }); + append($$anchor2, div_63); + }; + if_block(node_39, ($$render) => { + if (onEditSave()) $$render(consequent_37); + }); + } + var div_65 = sibling(node_39, 2); + var node_41 = child(div_65); + { + var consequent_38 = ($$anchor2) => { + var div_66 = root_55(); + var span_9 = sibling(child(div_66), 2); + var text_26 = child(span_9); + template_effect(() => set_text(text_26, get(deleting) ? "Deleting..." : "Delete")); + delegated("click", div_66, requestDelete); + append($$anchor2, div_66); + }; + if_block(node_41, ($$render) => { + if (onDelete()) $$render(consequent_38); + }); + } + var node_42 = sibling(node_41, 2); + { + var consequent_39 = ($$anchor2) => { + var div_67 = root_56(); + delegated("click", div_67, openFolder); + append($$anchor2, div_67); + }; + if_block(node_42, ($$render) => { + if (isLocalClient) $$render(consequent_39); + }); + } + var div_68 = sibling(node_42, 2); + let classes_13; + var span_10 = sibling(child(div_68), 2); + var text_27 = child(span_10); + var div_69 = sibling(div_48, 2); + var node_43 = child(div_69); + { + var consequent_57 = ($$anchor2) => { + var fragment_9 = root_57(); + var div_70 = sibling(first_child(fragment_9), 2); + var div_71 = child(div_70); + var node_44 = child(div_71); + { + var consequent_40 = ($$anchor3) => { + var div_72 = root_58(); + var span_11 = sibling(child(div_72), 2); + var text_28 = child(span_11); + template_effect(() => set_text(text_28, `${get(imageInfo).width ?? ""} × ${get(imageInfo).height ?? ""}`)); + append($$anchor3, div_72); + }; + if_block(node_44, ($$render) => { + if (get(imageInfo).width && get(imageInfo).height) $$render(consequent_40); + }); + } + var node_45 = sibling(node_44, 2); + { + var consequent_41 = ($$anchor3) => { + var div_73 = root_59(); + var span_12 = sibling(child(div_73), 2); + var text_29 = child(span_12); + template_effect(($0) => set_text(text_29, $0), [ + () => get(imageInfo).file_size > 1048576 ? (get(imageInfo).file_size / 1048576).toFixed(1) + " MB" : Math.round(get(imageInfo).file_size / 1024) + " KB" + ]); + append($$anchor3, div_73); + }; + if_block(node_45, ($$render) => { + if (get(imageInfo).file_size) $$render(consequent_41); + }); + } + var node_46 = sibling(div_71, 2); + { + var consequent_42 = ($$anchor3) => { + var div_74 = root_60(); + var span_13 = sibling(child(div_74), 2); + var text_30 = child(span_13); + template_effect(($0) => set_text(text_30, $0), [ + () => new Date(get(imageInfo).created_at * 1e3).toLocaleDateString() + ]); + append($$anchor3, div_74); + }; + if_block(node_46, ($$render) => { + if (get(imageInfo).created_at) $$render(consequent_42); + }); + } + var node_47 = sibling(node_46, 2); + { + var consequent_43 = ($$anchor3) => { + var div_75 = root_61(); + var span_14 = sibling(child(div_75), 2); + var text_31 = child(span_14); + template_effect(() => set_text(text_31, get(imageInfo).filename)); + append($$anchor3, div_75); + }; + if_block(node_47, ($$render) => { + if (get(imageInfo).filename) $$render(consequent_43); + }); + } + var node_48 = sibling(node_47, 2); + { + var consequent_44 = ($$anchor3) => { + var div_76 = root_62(); + append($$anchor3, div_76); + }; + if_block(node_48, ($$render) => { + if (get(isOrphaned)) $$render(consequent_44); + }); + } + var node_49 = sibling(div_70, 2); + { + var consequent_49 = ($$anchor3) => { + const regionData = user_derived(() => parseRegions(get(imageInfo).regions)); + var fragment_10 = root_63(); + var div_77 = sibling(first_child(fragment_10), 2); + var node_50 = child(div_77); + { + var consequent_46 = ($$anchor4) => { + var fragment_11 = root_64(); + var node_51 = first_child(fragment_11); + each(node_51, 17, () => get(regionData).regions, (region) => region.id, ($$anchor5, region) => { + var div_78 = root_65(); + var span_15 = child(div_78); + var text_32 = child(span_15); + var p_1 = sibling(span_15, 2); + var text_33 = child(p_1); + template_effect(() => { + set_text(text_32, `$${get(region).name ?? ""}`); + set_text(text_33, get(region).text); + }); + append($$anchor5, div_78); }); - } - append($$anchor4, fragment_9); - }; - var consequent_41 = ($$anchor4) => { - var div_74 = root_55(); - var p_3 = sibling(child(div_74), 2); - var text_32 = child(p_3); - template_effect(() => set_text(text_32, get(imageInfo).prompt)); - append($$anchor4, div_74); - }; - if_block(node_43, ($$render) => { - if (get(regionData)) $$render(consequent_40); - else if (get(imageInfo).prompt) $$render(consequent_41, 1); - }); - } - var node_46 = sibling(node_43, 2); - { - var consequent_42 = ($$anchor4) => { - var div_75 = root_56(); - var p_4 = sibling(child(div_75), 2); - var text_33 = child(p_4); - template_effect(() => set_text(text_33, get(imageInfo).negative)); - append($$anchor4, div_75); - }; - if_block(node_46, ($$render) => { - if (get(imageInfo).negative) $$render(consequent_42); - }); - } - append($$anchor3, fragment_8); - }; - if_block(node_42, ($$render) => { - if (get(imageInfo).prompt || get(imageInfo).negative) $$render(consequent_43); - }); - } - var node_47 = sibling(node_42, 2); - { - var consequent_50 = ($$anchor3) => { - var fragment_10 = root_57(); - var div_76 = sibling(first_child(fragment_10), 2); - var node_48 = child(div_76); - { - var consequent_44 = ($$anchor4) => { - var div_77 = root_58(); - var span_15 = sibling(child(div_77), 2); - var text_34 = child(span_15); - template_effect(() => set_text(text_34, get(imageInfo).model)); - append($$anchor4, div_77); - }; - if_block(node_48, ($$render) => { - if (get(imageInfo).model) $$render(consequent_44); - }); - } - var node_49 = sibling(node_48, 2); - { - var consequent_45 = ($$anchor4) => { - var div_78 = root_59(); - var span_16 = sibling(child(div_78), 2); - var text_35 = child(span_16); - template_effect(($0) => set_text(text_35, $0), [() => formatSeed(get(imageInfo).seed)]); - delegated("click", div_78, copySeed); - append($$anchor4, div_78); - }; - if_block(node_49, ($$render) => { - if (get(imageInfo).seed != null) $$render(consequent_45); - }); - } - var div_79 = sibling(node_49, 2); - var node_50 = child(div_79); - { - var consequent_46 = ($$anchor4) => { - var div_80 = root_60(); - var span_17 = sibling(child(div_80), 2); - var text_36 = child(span_17); - template_effect(() => set_text(text_36, get(imageInfo).steps)); - append($$anchor4, div_80); - }; - if_block(node_50, ($$render) => { - if (get(imageInfo).steps) $$render(consequent_46); - }); - } - var node_51 = sibling(node_50, 2); - { - var consequent_47 = ($$anchor4) => { - var div_81 = root_61(); - var span_18 = sibling(child(div_81), 2); - var text_37 = child(span_18); - template_effect(() => set_text(text_37, get(imageInfo).cfg)); - append($$anchor4, div_81); - }; - if_block(node_51, ($$render) => { - if (get(imageInfo).cfg) $$render(consequent_47); - }); - } - var node_52 = sibling(node_51, 2); - { - var consequent_48 = ($$anchor4) => { - var div_82 = root_62(); - var span_19 = sibling(child(div_82), 2); - var text_38 = child(span_19); - template_effect(() => set_text(text_38, get(imageInfo).sampler)); - append($$anchor4, div_82); - }; - if_block(node_52, ($$render) => { - if (get(imageInfo).sampler) $$render(consequent_48); - }); - } - var node_53 = sibling(node_52, 2); - { - var consequent_49 = ($$anchor4) => { - var div_83 = root_63(); - var span_20 = sibling(child(div_83), 2); - var text_39 = child(span_20); - template_effect(() => set_text(text_39, get(imageInfo).denoise)); - append($$anchor4, div_83); - }; - if_block(node_53, ($$render) => { - if (get(imageInfo).denoise != null) $$render(consequent_49); - }); - } - append($$anchor3, fragment_10); - }; - if_block(node_47, ($$render) => { - if (get(imageInfo).model || get(imageInfo).seed != null || get(imageInfo).steps) $$render(consequent_50); - }); - } - append($$anchor2, fragment_7); - }; - var consequent_52 = ($$anchor2) => { - var div_84 = root_64(); - append($$anchor2, div_84); - }; - if_block(node_36, ($$render) => { - if (get(imageInfo)) $$render(consequent_51); - else if (get(currentImage)) $$render(consequent_52, 1); + var node_52 = sibling(node_51, 2); + { + var consequent_45 = ($$anchor5) => { + var div_79 = root_66(); + var p_2 = sibling(child(div_79), 2); + var text_34 = child(p_2); + template_effect(() => set_text(text_34, get(regionData).global)); + append($$anchor5, div_79); + }; + if_block(node_52, ($$render) => { + if (get(regionData).global) $$render(consequent_45); + }); + } + append($$anchor4, fragment_11); + }; + var consequent_47 = ($$anchor4) => { + var div_80 = root_67(); + var p_3 = sibling(child(div_80), 2); + var text_35 = child(p_3); + template_effect(() => set_text(text_35, get(imageInfo).prompt)); + append($$anchor4, div_80); + }; + if_block(node_50, ($$render) => { + if (get(regionData)) $$render(consequent_46); + else if (get(imageInfo).prompt) $$render(consequent_47, 1); + }); + } + var node_53 = sibling(node_50, 2); + { + var consequent_48 = ($$anchor4) => { + var div_81 = root_68(); + var p_4 = sibling(child(div_81), 2); + var text_36 = child(p_4); + template_effect(() => set_text(text_36, get(imageInfo).negative)); + append($$anchor4, div_81); + }; + if_block(node_53, ($$render) => { + if (get(imageInfo).negative) $$render(consequent_48); + }); + } + append($$anchor3, fragment_10); + }; + if_block(node_49, ($$render) => { + if (get(imageInfo).prompt || get(imageInfo).negative) $$render(consequent_49); + }); + } + var node_54 = sibling(node_49, 2); + { + var consequent_56 = ($$anchor3) => { + var fragment_12 = root_69(); + var div_82 = sibling(first_child(fragment_12), 2); + var node_55 = child(div_82); + { + var consequent_50 = ($$anchor4) => { + var div_83 = root_70(); + var span_16 = sibling(child(div_83), 2); + var text_37 = child(span_16); + template_effect(() => set_text(text_37, get(imageInfo).model)); + append($$anchor4, div_83); + }; + if_block(node_55, ($$render) => { + if (get(imageInfo).model) $$render(consequent_50); + }); + } + var node_56 = sibling(node_55, 2); + { + var consequent_51 = ($$anchor4) => { + var div_84 = root_71(); + var span_17 = sibling(child(div_84), 2); + var text_38 = child(span_17); + template_effect(($0) => set_text(text_38, $0), [() => formatSeed(get(imageInfo).seed)]); + delegated("click", div_84, copySeed); + append($$anchor4, div_84); + }; + if_block(node_56, ($$render) => { + if (get(imageInfo).seed != null) $$render(consequent_51); + }); + } + var div_85 = sibling(node_56, 2); + var node_57 = child(div_85); + { + var consequent_52 = ($$anchor4) => { + var div_86 = root_72(); + var span_18 = sibling(child(div_86), 2); + var text_39 = child(span_18); + template_effect(() => set_text(text_39, get(imageInfo).steps)); + append($$anchor4, div_86); + }; + if_block(node_57, ($$render) => { + if (get(imageInfo).steps) $$render(consequent_52); + }); + } + var node_58 = sibling(node_57, 2); + { + var consequent_53 = ($$anchor4) => { + var div_87 = root_73(); + var span_19 = sibling(child(div_87), 2); + var text_40 = child(span_19); + template_effect(() => set_text(text_40, get(imageInfo).cfg)); + append($$anchor4, div_87); + }; + if_block(node_58, ($$render) => { + if (get(imageInfo).cfg) $$render(consequent_53); + }); + } + var node_59 = sibling(node_58, 2); + { + var consequent_54 = ($$anchor4) => { + var div_88 = root_74(); + var span_20 = sibling(child(div_88), 2); + var text_41 = child(span_20); + template_effect(() => set_text(text_41, get(imageInfo).sampler)); + append($$anchor4, div_88); + }; + if_block(node_59, ($$render) => { + if (get(imageInfo).sampler) $$render(consequent_54); + }); + } + var node_60 = sibling(node_59, 2); + { + var consequent_55 = ($$anchor4) => { + var div_89 = root_75(); + var span_21 = sibling(child(div_89), 2); + var text_42 = child(span_21); + template_effect(() => set_text(text_42, get(imageInfo).denoise)); + append($$anchor4, div_89); + }; + if_block(node_60, ($$render) => { + if (get(imageInfo).denoise != null) $$render(consequent_55); + }); + } + append($$anchor3, fragment_12); + }; + if_block(node_54, ($$render) => { + if (get(imageInfo).model || get(imageInfo).seed != null || get(imageInfo).steps) $$render(consequent_56); + }); + } + append($$anchor2, fragment_9); + }; + var consequent_58 = ($$anchor2) => { + var div_90 = root_76(); + append($$anchor2, div_90); + }; + if_block(node_43, ($$render) => { + if (get(imageInfo)) $$render(consequent_57); + else if (get(currentImage)) $$render(consequent_58, 1); + }); + } + bind_this(div, ($$value) => viewerEl = $$value, () => viewerEl); + template_effect(() => { + set_style(div_21, `cursor: ${get(isPanning) ? "grabbing" : "grab"}`); + set_text(text_18, `${get(currentIndex) + 1} / ${images().length ?? ""}`); + set_text(text_19, get(zoomDisplayText)); + set_value(input_1, get(zoomSliderValue)); + classes_13 = set_class(div_68, 1, "pcr-viewer-toolbar-btn svelte-5cciiw", null, classes_13, { active: get(linkCopied) }); + set_text(text_27, get(linkCopied) ? "Copied!" : "Copy Link"); }); + event("wheel", div_21, handleWheel); + delegated("pointerdown", div_21, handlePointerDown); + delegated("pointermove", div_21, handlePointerMove); + delegated("pointerup", div_21, handlePointerUp); + delegated("dblclick", div_21, handleDblClick); + delegated("click", div_37, function(...$$args) { + var _a2; + (_a2 = onClose()) == null ? void 0 : _a2.apply(this, $$args); + }); + delegated("click", div_51, () => { + set(zoomDropdownOpen, !get(zoomDropdownOpen)); + }); + delegated("input", input_1, handleZoomSlider); + delegated("click", div_68, copyLink); } - bind_this(div, ($$value) => viewerEl = $$value, () => viewerEl); - var node_54 = sibling(div, 2); + var node_61 = sibling(div, 2); { let $0 = user_derived(() => get(displayedHash) || ""); let $1 = user_derived(() => { @@ -14487,7 +14980,7 @@ ${negative}` : "")); var _a2; return get(upscaleFromEdit) ? ((_a2 = get(upscaleEditCtx)) == null ? void 0 : _a2.docHeight) || 0 : 0; }); - UpscaleOptionsModal(node_54, { + UpscaleOptionsModal(node_61, { get open() { return get(upscaleModalOpen); }, @@ -14539,7 +15032,7 @@ ${negative}` : "")); } }); } - var node_55 = sibling(node_54, 2); + var node_62 = sibling(node_61, 2); { let $0 = user_derived(() => get(displayedHash) || ""); let $1 = user_derived(() => { @@ -14580,7 +15073,7 @@ ${get(imageInfo).negative}` : "") : ""); let $9 = user_derived(() => get(inpaintFromEdit) ? get(inpaintMovedContent) : false); let $10 = user_derived(() => get(inpaintFromEdit) ? get(inpaintEditMask) : null); let $11 = user_derived(() => get(inpaintFromEdit) ? handleInpaintToEdit : null); - InpaintModal(node_55, { + InpaintModal(node_62, { get open() { return get(inpaintModalOpen); }, @@ -14659,7 +15152,7 @@ ${get(imageInfo).negative}` : "") : ""); } }); } - var node_56 = sibling(node_55, 2); + var node_63 = sibling(node_62, 2); { let $0 = user_derived(() => { var _a2; @@ -14687,7 +15180,7 @@ ${get(imageInfo).negative}` : "") : ""); let $8 = user_derived(() => onReposeCaps() && onReposeRun() && onMountPoser() && onInpaintUploadReference() ? openReposeFromEdit : null); let $9 = user_derived(() => get(inpaintFromEdit) && get(inpaintModalOpen) || get(upscaleFromEdit) && get(upscaleModalOpen) || get(reposeModalOpen)); bind_this( - EditModal(node_56, { + EditModal(node_63, { get open() { return get(editModalOpen); }, @@ -14742,7 +15235,7 @@ ${get(imageInfo).negative}` : "") : ""); () => get(editModalRef) ); } - var node_57 = sibling(node_56, 2); + var node_64 = sibling(node_63, 2); { let $0 = user_derived(() => get(displayedHash) || ""); let $1 = user_derived(() => { @@ -14761,7 +15254,7 @@ ${get(imageInfo).negative}` : "") : ""); var _a2; return (_a2 = get(reposePrepared)) == null ? void 0 : _a2.caps; }); - RePoseModal(node_57, { + RePoseModal(node_64, { get open() { return get(reposeModalOpen); }, @@ -14804,8 +15297,8 @@ ${get(imageInfo).negative}` : "") : ""); } }); } - var node_58 = sibling(node_57, 2); - ConfirmModal(node_58, { + var node_65 = sibling(node_64, 2); + ConfirmModal(node_65, { get open() { return get(confirmDeleteOpen); }, @@ -14815,13 +15308,14 @@ ${get(imageInfo).negative}` : "") : ""); onConfirm: handleDelete, onCancel: cancelDelete }); - var node_59 = sibling(node_58, 2); + var node_66 = sibling(node_65, 2); { - var consequent_53 = ($$anchor2) => { + var consequent_59 = ($$anchor2) => { { - let $0 = user_derived(() => !!onEditSave()); - let $1 = user_derived(() => !!onDelete()); - let $2 = user_derived(() => { + let $0 = user_derived(() => get(lineageMenu).item ? canExpand(get(lineageMenu).item) : false); + let $1 = user_derived(() => !!onEditSave()); + let $2 = user_derived(() => !!onDelete()); + let $3 = user_derived(() => { var _a2; return ((_a2 = get(lineageMenu).item) == null ? void 0 : _a2.orphaned) === 1; }); @@ -14832,12 +15326,15 @@ ${get(imageInfo).negative}` : "") : ""); get y() { return get(lineageMenu).y; }, - get canEdit() { + get canExpand() { return get($0); }, - get canDelete() { + get canEdit() { return get($1); }, + get canDelete() { + return get($2); + }, get isLocal() { return isLocalClient; }, @@ -14845,7 +15342,7 @@ ${get(imageInfo).negative}` : "") : ""); return isWindows; }, get orphaned() { - return get($2); + return get($3); }, onAction: (action2) => lineageMenuAction(action2, get(lineageMenu).item), onClose: () => { @@ -14854,33 +15351,11 @@ ${get(imageInfo).negative}` : "") : ""); }); } }; - if_block(node_59, ($$render) => { - if (get(lineageMenu)) $$render(consequent_53); + if_block(node_66, ($$render) => { + if (get(lineageMenu)) $$render(consequent_59); }); } - template_effect(() => { - set_style(div, `transform: translateY(${get(viewerTransformY) ?? ""}px); opacity: ${get(viewerOpacity) ?? ""}`); - set_style(div_17, `cursor: ${get(isPanning) ? "grabbing" : "grab"}`); - set_text(text_15, `${get(currentIndex) + 1} / ${images().length ?? ""}`); - set_text(text_16, get(zoomDisplayText)); - set_value(input_1, get(zoomSliderValue)); - classes_9 = set_class(div_62, 1, "pcr-viewer-toolbar-btn svelte-5cciiw", null, classes_9, { active: get(linkCopied) }); - set_text(text_24, get(linkCopied) ? "Copied!" : "Copy Link"); - }); - event("wheel", div_17, handleWheel); - delegated("pointerdown", div_17, handlePointerDown); - delegated("pointermove", div_17, handlePointerMove); - delegated("pointerup", div_17, handlePointerUp); - delegated("dblclick", div_17, handleDblClick); - delegated("click", div_31, function(...$$args) { - var _a2; - (_a2 = onClose()) == null ? void 0 : _a2.apply(this, $$args); - }); - delegated("click", div_45, () => { - set(zoomDropdownOpen, !get(zoomDropdownOpen)); - }); - delegated("input", input_1, handleZoomSlider); - delegated("click", div_62, copyLink); + template_effect(() => set_style(div, `transform: translateY(${get(viewerTransformY) ?? ""}px); opacity: ${get(viewerOpacity) ?? ""}`)); append($$anchor, fragment); pop(); } diff --git a/js/lib/svelte/select-Dgaht2aI.js b/js/lib/svelte/select-Dp4ExMMc.js similarity index 91% rename from js/lib/svelte/select-Dgaht2aI.js rename to js/lib/svelte/select-Dp4ExMMc.js index a21de0c..9b587f8 100644 --- a/js/lib/svelte/select-Dgaht2aI.js +++ b/js/lib/svelte/select-Dp4ExMMc.js @@ -1,4 +1,4 @@ -import { a1 as listen_to_event_and_reset_event, a2 as current_batch, a3 as effect, a4 as is_array, a5 as select_multiple_invalid_value, a6 as is, a7 as teardown } from "./disclose-version-BjTnIIw0.js"; +import { a2 as listen_to_event_and_reset_event, a3 as current_batch, a4 as effect, a5 as is_array, a6 as select_multiple_invalid_value, a7 as is, a8 as teardown } from "./disclose-version-uq4tn5Y6.js"; function select_option(select, value, mounting = false) { if (select.multiple) { if (value == void 0) { @@ -97,4 +97,4 @@ export { init_select as i, select_option as s }; -//# sourceMappingURL=select-Dgaht2aI.js.map +//# sourceMappingURL=select-Dp4ExMMc.js.map diff --git a/js/lib/svelte/style-CbOHK2KU.js b/js/lib/svelte/style-Boi27oOu.js similarity index 90% rename from js/lib/svelte/style-CbOHK2KU.js rename to js/lib/svelte/style-Boi27oOu.js index 8056e12..7c0e249 100644 --- a/js/lib/svelte/style-CbOHK2KU.js +++ b/js/lib/svelte/style-Boi27oOu.js @@ -1,4 +1,4 @@ -import { ab as to_style } from "./disclose-version-BjTnIIw0.js"; +import { ac as to_style } from "./disclose-version-uq4tn5Y6.js"; function update_styles(dom, prev = {}, next, priority) { for (var key in next) { var value = next[key]; @@ -36,4 +36,4 @@ function set_style(dom, value, prev_styles, next_styles) { export { set_style as s }; -//# sourceMappingURL=style-CbOHK2KU.js.map +//# sourceMappingURL=style-Boi27oOu.js.map diff --git a/js/pose-studio.js b/js/pose-studio.js index 7bc8d04..68007a9 100644 --- a/js/pose-studio.js +++ b/js/pose-studio.js @@ -8240,11 +8240,17 @@ async function mountViewport(node, container) { // Svelte bundle's CSS isn't present. let exportModal = null; // built lazily on first export (after the teardown chain is in place) const closeExport = () => { if (exportModal) exportModal.backdrop.style.display = "none"; }; + // Remember the last name the author exported as (device-local), so the next + // export defaults to it instead of the generic placeholder. The browser still + // auto-suffixes " (1)" etc. on its own if that file already exists on disk. + const EXPORT_NAME_KEY = "pcr.pose-export-name"; const attemptExport = () => { const raw = exportModal.input.value.trim(); if (!raw) return; // confirm is disabled while empty; guard the Enter path too closeExport(); - downloadScene(sanitizeSceneFilename(raw)); + const name = sanitizeSceneFilename(raw); + try { localStorage.setItem(EXPORT_NAME_KEY, name); } catch { /* localStorage blocked */ } + downloadScene(name); }; const buildExportModal = () => { const backdrop = document.createElement("div"); @@ -8328,7 +8334,8 @@ async function mountViewport(node, container) { const openExportScene = () => { if (!exportModal) buildExportModal(); exportModal.backdrop.style.zIndex = String((node.properties?.pcrFullscreenZ || 10001) + 10); // above this poser's flyout menus - const defaultName = "promptchain-pose-scene.json"; + let defaultName = "promptchain-pose-scene.json"; + try { const saved = localStorage.getItem(EXPORT_NAME_KEY); if (saved) defaultName = saved; } catch { /* localStorage blocked */ } exportModal.input.value = defaultName; exportModal.refreshConfirm(); exportModal.backdrop.style.display = "flex"; diff --git a/svelte-src/components/ImageViewer.svelte b/svelte-src/components/ImageViewer.svelte index 9e70c8b..b1c0c72 100644 --- a/svelte-src/components/ImageViewer.svelte +++ b/svelte-src/components/ImageViewer.svelte @@ -6,6 +6,7 @@ import RePoseModal from "./RePoseModal.svelte"; import ConfirmModal from "./sidebar/ConfirmModal.svelte"; import LineageContextMenu from "./LineageContextMenu.svelte"; + import { buildRender, ancestry } from "../lib/lineage-lanes.js"; import { buildFigureRegions, matchRegionByOverlap } from "../lib/region-binding.js"; let { @@ -247,14 +248,17 @@ displayedHash = hash; } - let lineageDisplay = $derived((() => { - const asNodes = (list) => list.map(item => ({ kind: "node", item })); - if (lineageList.length < 2) return asNodes(lineageList); - const byHash = new Map(lineageList.map(f => [f.hash, f])); - if (!byHash.has(displayedHash)) return asNodes(lineageList); - + // Topology primitives for the family tree, hoisted out of lineageDisplay so the + // strip, the context-menu "expand branches" gate, and the subway lane builder + // all read ONE source. byHash/childrenOf rebuild parent→children edges from each + // node's parent_hash (a content sha256, so acyclic by construction). roots is the + // true root plus any node orphaned by a deleted-and-absent parent, so the lane + // builder can surface it as its own root rather than dropping it. + let lineageTree = $derived((() => { + const list = lineageList; + const byHash = new Map(list.map(f => [f.hash, f])); const childrenOf = new Map(); - for (const f of lineageList) { + for (const f of list) { if (!f.parent_hash || !byHash.has(f.parent_hash)) continue; if (!childrenOf.has(f.parent_hash)) childrenOf.set(f.parent_hash, []); childrenOf.get(f.parent_hash).push(f); @@ -262,6 +266,15 @@ for (const kids of childrenOf.values()) { kids.sort((a, b) => (a.created_at || 0) - (b.created_at || 0)); } + const roots = list.filter(f => !f.parent_hash || !byHash.has(f.parent_hash)).map(f => f.hash); + return { byHash, childrenOf, roots }; + })()); + + let lineageDisplay = $derived((() => { + const asNodes = (list) => list.map(item => ({ kind: "node", item })); + if (lineageList.length < 2) return asNodes(lineageList); + const { byHash, childrenOf } = lineageTree; + if (!byHash.has(displayedHash)) return asNodes(lineageList); // parent_hash is a content sha256, so the family is acyclic by // construction — the visited set is cheap defense against malformed data @@ -341,6 +354,159 @@ ); let lineageHiddenCount = $derived(lineageList.length - lineageVisible.length); + // ── subway lanes (right-click "Expand branches") ── + // brokenOut holds CHILD-SUBTREE ROOT hashes the user has peeled into their own + // vertical column. The rail switches from the compact strip to the lane view + // whenever anything is broken out. subwayAnchor reuses the stable lineageFocusHash + // so navigating between nodes never re-partitions the lanes, and the displayed + // image is always on column 0 (anchored on the anchor's root→tip spine). + let brokenOut = $state(new Set()); + let subwayAnchor = $derived( + lineageFocusHash && lineageTree.byHash.has(lineageFocusHash) ? lineageFocusHash : displayedHash + ); + let laneRender = $derived(buildRender(lineageTree, subwayAnchor, brokenOut)); + let lanesActive = $derived(brokenOut.size > 0 && lineageList.length > 1); + + // The child that CONTINUES a node's lane — "expand branches" peels the SIBLINGS, + // never this. Matches buildLane's primary rule (spine-ward child, else oldest). + function primaryChildHash(item) { + const kids = lineageTree.childrenOf.get(item?.hash) || []; + if (!kids.length) return null; + const a = ancestry(lineageTree, subwayAnchor); + return (kids.find(k => a.set.has(k.hash)) || kids[0]).hash; + } + function canExpand(item) { + const primary = primaryChildHash(item); + return (lineageTree.childrenOf.get(item?.hash) || []) + .some(k => k.hash !== primary && !brokenOut.has(k.hash)); + } + function expandBranches(item) { + const primary = primaryChildHash(item); + const next = new Set(brokenOut); + for (const k of lineageTree.childrenOf.get(item?.hash) || []) + if (k.hash !== primary) next.add(k.hash); + brokenOut = next; + } + function foldLane(childRoot) { + // folding a column folds its whole broken-out subtree with it + const next = new Set(brokenOut); + const stack = [childRoot]; + while (stack.length) { + const h = stack.pop(); + next.delete(h); + for (const k of lineageTree.childrenOf.get(h) || []) stack.push(k.hash); + } + brokenOut = next; + } + function collapseAllLanes() { brokenOut = new Set(); } + // the family has at least one fork worth fanning out + let hasBranches = $derived((() => { + for (const kids of lineageTree.childrenOf.values()) if (kids.length > 1) return true; + return false; + })()); + // header "expand" affordance — fan EVERY branch out at once (the full subway): + // add every off-primary child across the whole family to brokenOut. + function expandAll() { + const a = ancestry(lineageTree, subwayAnchor); + const next = new Set(brokenOut); + for (const kids of lineageTree.childrenOf.values()) { + if (kids.length < 2) continue; + const primary = (kids.find(k => a.set.has(k.hash)) || kids[0]).hash; + for (const k of kids) if (k.hash !== primary) next.add(k.hash); + } + brokenOut = next; + } + + // Keep the displayed image materialized if it sits inside a folded branch: peel + // the chain of off-primary roots from the anchor spine down to it. Guarded so it + // only ever ADDS new roots (never loops). + $effect(() => { + if (!lanesActive) return; + if (laneRender.columns.some(c => c.nodes.some(n => n.hash === displayedHash))) return; + const { byHash, childrenOf } = lineageTree; + const a = ancestry(lineageTree, subwayAnchor); + const toBreak = []; + let cur = displayedHash; + const guard = new Set(); + while (cur && byHash.has(cur) && !guard.has(cur) && !a.set.has(cur)) { + guard.add(cur); + const parent = byHash.get(cur).parent_hash; + if (!parent || !byHash.has(parent)) break; + const kids = childrenOf.get(parent) || []; + const primary = (kids.find(k => a.set.has(k.hash)) || kids[0])?.hash; + if (cur !== primary) toBreak.push(cur); + cur = parent; + } + const additions = toBreak.filter(h => !brokenOut.has(h)); + if (additions.length) { + const next = new Set(brokenOut); + for (const h of additions) next.add(h); + brokenOut = next; + } + }); + + // SVG connector geometry — edges are DATA from laneRender; the rAF only MEASURES + // pixel positions of known nodes (never infers topology from the DOM). The SVG + // lives inside the scrolling wrapper so it translates with scroll for free; we + // recompute only on expand/fold/resize/thumbnail-load — never on scroll, never on + // a timer (event/observer-driven per CLAUDE.md). + let lanesWrapEl = $state(null); + let connectorGeom = $state([]); + let connectorBox = $state({ w: 0, h: 0 }); + let measureScheduled = false; + // Row pitch for vertically offsetting broken-out columns so children sit one + // generation below their parent. MUST match .pcr-viewer-lineage-node height (64px) + // + .pcr-lin-col gap (22px). + const LANE_ROW_H = 86; + // Layout coords relative to a content root — independent of scroll AND of CSS + // transform, so the same measurement serves the P3 zoom panel unchanged. + function contentXY(el, root) { + let x = 0, y = 0; + for (let n = el; n && n !== root; n = n.offsetParent) { x += n.offsetLeft; y += n.offsetTop; } + return { x, y, w: el.offsetWidth, h: el.offsetHeight }; + } + function measureConnectors() { + const wrap = lanesWrapEl; + if (!wrap) return; + const geom = []; + for (const e of laneRender.edges) { + const a = wrap.querySelector(`[data-hash="${e.from}"]`); + const b = wrap.querySelector(`[data-hash="${e.to}"]`); + if (!a || !b) continue; + const ra = contentXY(a, wrap), rb = contentXY(b, wrap); + const px = ra.x + ra.w / 2, pb = ra.y + ra.h; // parent bottom-center + const cx = rb.x + rb.w / 2, ct = rb.y; // child top-center + // key by edge identity, not array index — when the edge set changes, a + // keyed {#each} won't reuse a stale path d-string under a shifted index + // (that was the one-frame connector "points at the old node" jitter). + const key = `${e.from}>${e.to}`; + if (Math.abs(px - cx) < 1) { + geom.push({ key, d: `M ${px} ${pb} L ${cx} ${ct}` }); // spine: straight down + } else { + const my = (pb + ct) / 2; // branch: smooth S-curve + geom.push({ key, d: `M ${px} ${pb} C ${px} ${my}, ${cx} ${my}, ${cx} ${ct}` }); + } + } + connectorGeom = geom; + connectorBox = { w: wrap.scrollWidth, h: wrap.scrollHeight }; + } + function scheduleMeasure() { + if (measureScheduled) return; + measureScheduled = true; + requestAnimationFrame(() => { measureScheduled = false; measureConnectors(); }); + } + $effect(() => { + if (!lanesActive) return; + const cols = laneRender.columns; // read → track expand/fold/family changes + if (cols) scheduleMeasure(); + }); + $effect(() => { + if (!lanesWrapEl) return; + const ro = new ResizeObserver(() => scheduleMeasure()); + ro.observe(lanesWrapEl); + return () => ro.disconnect(); + }); + let compareTargets = $derived( lineageList.filter(item => item?.hash !== displayedHash) ); @@ -408,12 +574,24 @@ .then(r => r.ok ? r.json() : null) .then(data => { imageInfo = data; }) .catch(onMetaError("image meta")); - fetchApi(`/promptchain/lineage/${displayedHash}`) + // Capture the hash this fetch was issued for: displayedHash can change + // (fast navigation / save-then-navigate) before the response lands, and a + // late loser must NOT overwrite the current family — same staleness guard + // the browse branch above uses. Deliberately not nulling lineageData first: + // in-family navigation keeps the same family, so blanking it would flicker + // the tree on every step. + const reqHash = displayedHash; + fetchApi(`/promptchain/lineage/${reqHash}`) .then(r => r.ok ? r.json() : null) - .then(data => { lineageData = data; }) + .then(data => { + if (displayedHash !== reqHash) return; // stale response — a newer hash is shown + lineageData = data; + reportLineageAnomaly(reqHash, data); + }) .catch((e) => { + if (displayedHash !== reqHash) return; lineageData = null; - console.error(`[PromptChain] lineage fetch failed for ${displayedHash}:`, e); + console.error(`[PromptChain] lineage fetch failed for ${reqHash}:`, e); }); } }); @@ -1068,6 +1246,26 @@ } catch { /* diagnostics must never break the handback */ } } + // A healthy lineage response contains the queried node WITH its parent present + // in the same family. If the node is absent, or its parent_hash points outside + // the returned family (so the tree renders it as a stray root), log it via + // comfyui.log — that is the data signature behind a node appearing + // "mis-attributed" until a refresh. Event-driven (fires only on a landed + // response), no timers. We couldn't capture the live case, so this catches the + // next one. A true root (parent_hash null) is healthy and never logs. + function reportLineageAnomaly(reqHash, data) { + const fam = data?.family; + if (!Array.isArray(fam) || fam.length === 0) return; + const me = fam.find(f => f?.hash === reqHash); + const parentOrphaned = !!(me?.parent_hash && !fam.some(f => f?.hash === me.parent_hash)); + if (me && !parentOrphaned) return; // healthy + const fams = fam.map(f => (f?.hash || "").slice(0, 8)).join(","); + reportHandback( + "lineage-tree-anomaly", + `node ${(reqHash || "").slice(0, 8)} ${me ? "orphaned: parent " + (me.parent_hash || "").slice(0, 8) + " absent" : "ABSENT"} from its own family [${fams}]` + ); + } + async function handleUpscaleToEdit(doneState) { const ctx = upscaleEditCtx; const viewUrl = (img) => apiURL(`/view?filename=${encodeURIComponent(img.filename)}&subfolder=${encodeURIComponent(img.subfolder || "")}&type=${img.type || "output"}&rand=${Math.random()}`); @@ -1270,10 +1468,47 @@ lineageMenu = { x: e.clientX, y: e.clientY, item }; } + let copyPathTimer = null; + let copyPathToast = $state(false); + async function copyTextToClipboard(text) { + try { await navigator.clipboard.writeText(text); return true; } catch {} + // The async clipboard API can refuse after an awaited fetch (transient + // activation expires); a hidden textarea + execCommand still copies. + try { + const ta = document.createElement("textarea"); + ta.value = text; + ta.style.position = "fixed"; + ta.style.top = "-1000px"; + ta.style.opacity = "0"; + document.body.appendChild(ta); + ta.focus(); + ta.select(); + const ok = document.execCommand("copy"); + document.body.removeChild(ta); + return ok; + } catch { return false; } + } + async function copyPath(hash) { + try { + const r = await fetchApi?.(`/promptchain/file-path?hash=${encodeURIComponent(hash)}`); + const d = r && r.ok ? await r.json() : null; + if (!d?.path) return; + if (await copyTextToClipboard(d.path)) { + copyPathToast = true; + clearTimeout(copyPathTimer); + copyPathTimer = setTimeout(() => { copyPathToast = false; }, 1800); + } + } catch {} + } + function lineageMenuAction(action, item) { const hash = item?.hash; if (!hash) return; - if (action === "edit") { + if (action === "expand-branches") { + expandBranches(item); + } else if (action === "copy-path") { + copyPath(hash); + } else if (action === "edit") { lineageJump(hash); // bring it on screen so editDocHash matches what we edit openEdit(hash); } else if (action === "delete") { @@ -1404,86 +1639,154 @@
- {#if newGenBanner} -
✨ {newGenBanner}
- {/if} + {#snippet lineageNode(item, lane)} + + +
{ + if (compareDropdownOpen) { + if (item.hash !== displayedHash) enterCompareWith(item.hash, item.filename || item.hash.slice(0, 8)); + return; + } + lineageJump(item.hash); exitCompare(); + }} + onmouseenter={(e) => showTip(e, item)} + onmouseleave={hideTip} + oncontextmenu={(e) => { hideTip(); openLineageMenu(e, item); }} + > + +
+ {#if editDocLayers[item.hash]} +
+ + + +
+ {/if} + {#if laneRender.junctionsByNode.get(item.hash)?.hidden.length} + + {/if} + {#if brokenOut.has(lane.startHash) && item.hash === lane.startHash} + + {/if} +
+ {/snippet} + {#if lineageList.length > 1} -
+
- {lineageCurrentIdx + 1} / {lineageList.length} + {lineageCurrentIdx + 1} / {lineageList.length} + {#if hasBranches} + + {/if}
-
- {#each lineageDisplay as d, i (d.kind === "node" ? d.item.hash : `${d.kind}:${d.at}`)} - {#if d.kind === "node"} - {@const item = d.item} - - -
lineageDisplayCurrentIdx} - class:branch={d.branch} - class:orphaned={item.orphaned === 1} - class:compare-candidate={compareDropdownOpen && item.hash !== displayedHash} - class:compare-left={compareMode && item.hash === displayedHash} - class:compare-right={compareMode && item.hash === compareTargetHash} - onclick={() => { - // With the compare dropdown open, the strip doubles as the - // target picker — clicking a thumbnail compares against it - // instead of navigating away. - if (compareDropdownOpen) { - if (item.hash !== displayedHash) enterCompareWith(item.hash, item.filename || item.hash.slice(0, 8)); - return; - } - lineageJump(item.hash); exitCompare(); - }} - onmouseenter={(e) => showTip(e, item)} - onmouseleave={hideTip} - oncontextmenu={(e) => { hideTip(); openLineageMenu(e, item); }} - > - -
- {#if editDocLayers[item.hash]} -
- - - -
- {/if} + {#if lanesActive} +
+ + {#each laneRender.columns as lane (lane.startHash)} +
+ {#each lane.nodes as item (item.hash)} + {@render lineageNode(item, lane)} + {/each}
- {:else} - - -
toggleBundle(d.at)} - title={d.kind === "collapse" - ? "Collapse this branch" - : `${d.count} other generation${d.count > 1 ? "s" : ""} branch off here — click to expand`} - > - {#if d.kind === "bundle"} -
- {#each d.preview as p (p.hash)} - - {/each} -
- +{d.count} - {:else} - ▴ - {/if} -
- {/if} - {/each} -
- {#if lineageHiddenCount > 0} -
{lineageHiddenCount} hidden
+ {/each} +
+ {:else} +
+ {#each lineageDisplay as d, i (d.kind === "node" ? d.item.hash : `${d.kind}:${d.at}`)} + {#if d.kind === "node"} + {@const item = d.item} + + +
lineageDisplayCurrentIdx} + class:branch={d.branch} + class:orphaned={item.orphaned === 1} + class:compare-candidate={compareDropdownOpen && item.hash !== displayedHash} + class:compare-left={compareMode && item.hash === displayedHash} + class:compare-right={compareMode && item.hash === compareTargetHash} + onclick={() => { + // With the compare dropdown open, the strip doubles as the + // target picker — clicking a thumbnail compares against it + // instead of navigating away. + if (compareDropdownOpen) { + if (item.hash !== displayedHash) enterCompareWith(item.hash, item.filename || item.hash.slice(0, 8)); + return; + } + lineageJump(item.hash); exitCompare(); + }} + onmouseenter={(e) => showTip(e, item)} + onmouseleave={hideTip} + oncontextmenu={(e) => { hideTip(); openLineageMenu(e, item); }} + > + +
+ {#if editDocLayers[item.hash]} +
+ + + +
+ {/if} +
+ {:else} + + +
toggleBundle(d.at)} + title={d.kind === "collapse" + ? "Collapse this branch" + : `${d.count} other generation${d.count > 1 ? "s" : ""} branch off here — click to expand`} + > + {#if d.kind === "bundle"} +
+ {#each d.preview as p (p.hash)} + + {/each} +
+ +{d.count} + {:else} + ▴ + {/if} +
+ {/if} + {/each} +
+ {#if lineageHiddenCount > 0} +
{lineageHiddenCount} hidden
+ {/if} {/if}
{:else} @@ -1511,6 +1814,15 @@ ondblclick={handleDblClick} style="cursor: {isPanning ? 'grabbing' : 'grab'}" > + + {#if newGenBanner} +
✨ {newGenBanner}
+ {/if} + {#if copyPathToast} +
📋 Path copied to clipboard
+ {/if} {#if displayedHash} {#if !imageLoaded && !imageError}
@@ -2061,6 +2373,7 @@
+ {#if canExpand} + + {#if canEdit || canDelete || isLocal}
{/if} + {/if} {#if canEdit} {/if} @@ -52,6 +57,7 @@ {/if} {#if isLocal} {#if canEdit || canDelete}
{/if} + {#if isWindows} diff --git a/svelte-src/lib/lineage-lanes.js b/svelte-src/lib/lineage-lanes.js new file mode 100644 index 0000000..8c94e84 --- /dev/null +++ b/svelte-src/lib/lineage-lanes.js @@ -0,0 +1,102 @@ +// Lineage "subway" lane builder — pure topology, no Svelte. Shared by the in-rail +// lane view (ImageViewer) and the pop-out full-graph panel. Consumes the hoisted +// `lineageTree` ({ byHash, childrenOf, roots }) and a `brokenOut` Set of +// child-subtree ROOT hashes (the nodes the user has peeled into their own columns). +// +// Mental model: the family is a pure tree (single parent_hash, acyclic by +// content-sha256, never merges). A LANE is one vertical run following a primary +// path; at each node the OTHER children are "junctions" that can break out into +// their own lane. A column is the same recursive shape as column 0, so nested +// sub-junctions have somewhere to attach. + +// Climb parent_hash from `hash` to its root. Returns { root, set } where `set` +// holds every node on the path (used as column 0's primary-path preference so the +// displayed image always sits on the leftmost lane). +export function ancestry(tree, hash) { + const { byHash } = tree; + const set = new Set(); + let cur = hash; + let root = hash; + while (cur && byHash.has(cur) && !set.has(cur)) { + set.add(cur); + root = cur; + cur = byHash.get(cur).parent_hash; + } + return { root, set }; +} + +// Build one lane from `startHash`: start → primary child → … → tip, recording each +// off-primary fork as a junction. `spineSet` (optional) pulls the lane through a +// preferred path — on column 0 it's the displayed image's ancestry, so the lane +// flows root → displayed → tip; broken-out lanes pass no spineSet and follow the +// oldest child (childrenOf is pre-sorted ascending by created_at). +export function buildLane(tree, startHash, spineSet) { + const { byHash, childrenOf } = tree; + const nodes = []; + const junctions = []; + const guard = new Set(); + let cur = startHash; + while (cur && byHash.has(cur) && !guard.has(cur)) { + guard.add(cur); + nodes.push(byHash.get(cur)); + const kids = childrenOf.get(cur) || []; + let primary = spineSet ? kids.find(k => spineSet.has(k.hash)) : null; + if (!primary) primary = kids[0] || null; + const offPrimary = kids.filter(k => k !== primary).map(k => k.hash); + if (offPrimary.length) junctions.push({ atHash: cur, childRoots: offPrimary }); + cur = primary ? primary.hash : null; + } + return { startHash, nodes, junctions }; +} + +// Full render: column 0 anchored on `anchorHash`'s spine, then DFS the broken-out +// lanes (each appears just right of the junction it forks from). Returns: +// columns — lanes in left-to-right DFS order (column 0 first) +// edges — { from: forkHash, to: childRootHash } per broken-out lane, +// consumed as DATA by the SVG connector layer (geometry is +// measured from the DOM; topology is never inferred from it) +// junctionsByNode — Map powering the ⊞ expander +// badge and the context-menu "Expand branches" gate +// rootHash — column 0's first node (for the dot-root badge) +// topRow is the column's vertical offset measured in ROWS from the top of the +// whole lane area. A broken-out child column starts one generation BELOW its fork +// (topRow = parentTopRow + forkRowInParent + 1), i.e. the SAME row as the sibling +// that stayed inline in the parent column. So a parent sits a row above all its +// children, children of children another row down — a proper top-down hierarchy +// instead of every column top-aligned (which made parents look like peers). +export function buildRender(tree, anchorHash, brokenOut) { + const a = ancestry(tree, anchorHash); + const col0 = buildLane(tree, a.root, a.set); + const columns = []; + const edges = []; + const started = new Set(); + const junctionsByNode = new Map(); + const visit = (lane, topRow) => { + lane.topRow = topRow; + columns.push(lane); + // spine edges: every consecutive pair in a column is a parent→primary-child + // link, drawn as a straight vertical connector (same column = same x). + for (let i = 0; i + 1 < lane.nodes.length; i++) { + edges.push({ from: lane.nodes[i].hash, to: lane.nodes[i + 1].hash }); + } + for (const j of lane.junctions) { + const forkRow = lane.nodes.findIndex(n => n.hash === j.atHash); + let rec = junctionsByNode.get(j.atHash); + if (!rec) { rec = { shown: [], hidden: [] }; junctionsByNode.set(j.atHash, rec); } + for (const childRoot of j.childRoots) { + if (brokenOut.has(childRoot)) { + rec.shown.push(childRoot); + if (!started.has(childRoot)) { + started.add(childRoot); + edges.push({ from: j.atHash, to: childRoot }); + visit(buildLane(tree, childRoot), topRow + forkRow + 1); + } + } else { + rec.hidden.push(childRoot); + } + } + } + }; + visit(col0, 0); + return { columns, edges, junctionsByNode, rootHash: col0.nodes.length ? col0.nodes[0].hash : null }; +}