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(`
Run0 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(`
`, 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(`
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.
+ {#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 };
+}