fundus 0.11.0 → 0.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/build/client/_app/immutable/assets/LibraryContextMenu.B6By2-yb.css +1 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.B6By2-yb.css.br +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.B6By2-yb.css.gz +0 -0
- package/build/client/_app/immutable/chunks/B9HdDE5n.js +1 -0
- package/build/client/_app/immutable/chunks/B9HdDE5n.js.br +0 -0
- package/build/client/_app/immutable/chunks/B9HdDE5n.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{DFRlZOKz.js → CAQ5okPf.js} +2 -2
- package/build/client/_app/immutable/chunks/CAQ5okPf.js.br +0 -0
- package/build/client/_app/immutable/chunks/CAQ5okPf.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Ccz62-Hi.js +1 -0
- package/build/client/_app/immutable/chunks/Ccz62-Hi.js.br +0 -0
- package/build/client/_app/immutable/chunks/Ccz62-Hi.js.gz +0 -0
- package/build/client/_app/immutable/chunks/ChVOZl2x.js +1 -0
- package/build/client/_app/immutable/chunks/ChVOZl2x.js.br +0 -0
- package/build/client/_app/immutable/chunks/ChVOZl2x.js.gz +0 -0
- package/build/client/_app/immutable/chunks/CiBv7EZv.js +108 -0
- package/build/client/_app/immutable/chunks/CiBv7EZv.js.br +0 -0
- package/build/client/_app/immutable/chunks/CiBv7EZv.js.gz +0 -0
- package/build/client/_app/immutable/chunks/UFAWUL-4.js +1 -0
- package/build/client/_app/immutable/chunks/UFAWUL-4.js.br +0 -0
- package/build/client/_app/immutable/chunks/UFAWUL-4.js.gz +0 -0
- package/build/client/_app/immutable/chunks/YWIvyYJl.js +1 -0
- package/build/client/_app/immutable/chunks/YWIvyYJl.js.br +0 -0
- package/build/client/_app/immutable/chunks/YWIvyYJl.js.gz +0 -0
- package/build/client/_app/immutable/chunks/{BMORe2Gb.js → YpiA5Xry.js} +1 -1
- package/build/client/_app/immutable/chunks/YpiA5Xry.js.br +0 -0
- package/build/client/_app/immutable/chunks/{BMORe2Gb.js.gz → YpiA5Xry.js.gz} +0 -0
- package/build/client/_app/immutable/chunks/{DpFtnEPx.js → jjXOSnwf.js} +1 -1
- package/build/client/_app/immutable/chunks/jjXOSnwf.js.br +0 -0
- package/build/client/_app/immutable/chunks/jjXOSnwf.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.Rv8f5zSo.js +2 -0
- package/build/client/_app/immutable/entry/app.Rv8f5zSo.js.br +0 -0
- package/build/client/_app/immutable/entry/app.Rv8f5zSo.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.C5jRg_CF.js +1 -0
- package/build/client/_app/immutable/entry/start.C5jRg_CF.js.br +1 -0
- package/build/client/_app/immutable/entry/start.C5jRg_CF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.Gv5d6CcW.js +1 -0
- package/build/client/_app/immutable/nodes/0.Gv5d6CcW.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.Gv5d6CcW.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.8J9y5zyF.js +1 -0
- package/build/client/_app/immutable/nodes/1.8J9y5zyF.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.8J9y5zyF.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.BNvTqsKZ.js +3 -0
- package/build/client/_app/immutable/nodes/2.BNvTqsKZ.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.BNvTqsKZ.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.CmlRI2XA.js +1 -0
- package/build/client/_app/immutable/nodes/3.CmlRI2XA.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.CmlRI2XA.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.CHTKk5QR.js +2 -0
- package/build/client/_app/immutable/nodes/4.CHTKk5QR.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.CHTKk5QR.js.gz +0 -0
- package/build/client/_app/version.json +1 -1
- package/build/client/_app/version.json.br +0 -0
- package/build/client/_app/version.json.gz +0 -0
- package/build/handler.js +7 -7
- package/build/index.js +7 -7
- package/build/server/chunks/chunks/{exports.js-aVVdkXgn.js → exports.js-BcB5q0h5.js} +2 -2
- package/build/server/chunks/chunks/{exports.js-aVVdkXgn.js.map → exports.js-BcB5q0h5.js.map} +1 -1
- package/build/server/chunks/chunks/{internal.js-C6cIfe5d.js → internal.js-B6eePlP4.js} +2 -2
- package/build/server/chunks/chunks/{internal.js-C6cIfe5d.js.map → internal.js-B6eePlP4.js.map} +1 -1
- package/build/server/chunks/chunks/internal2.js-BlXt2rfE.js.map +1 -1
- package/build/server/chunks/chunks/{shared.js-BNd0HSxp.js → shared.js-BO7vJlPc.js} +2 -2
- package/build/server/chunks/chunks/{shared.js-BNd0HSxp.js.map → shared.js-BO7vJlPc.js.map} +1 -1
- package/build/server/chunks/chunks/{utils.js-6HSqnONB.js → utils.js-BTV5xnNv.js} +3 -3
- package/build/server/chunks/chunks/{utils.js-6HSqnONB.js.map → utils.js-BTV5xnNv.js.map} +1 -1
- package/build/server/chunks/{handler-rG16rikT.js → handler-DQdjBhko.js} +5 -5
- package/build/server/chunks/{handler-rG16rikT.js.map → handler-DQdjBhko.js.map} +1 -1
- package/build/server/chunks/{index.js-DYK_SfL5.js → index.js-DtKY5QD2.js} +5 -5
- package/build/server/chunks/{index.js-DYK_SfL5.js.map → index.js-DtKY5QD2.js.map} +1 -1
- package/build/server/chunks/{manifest.js-h2lDpEPs.js → manifest.js-CJMiboeI.js} +7 -7
- package/build/server/chunks/{manifest.js-h2lDpEPs.js.map → manifest.js-CJMiboeI.js.map} +1 -1
- package/build/server/chunks/nodes/{0.js-Db28RwnA.js → 0.js-Ce__dNtc.js} +2 -2
- package/build/server/chunks/nodes/{0.js-Db28RwnA.js.map → 0.js-Ce__dNtc.js.map} +1 -1
- package/build/server/chunks/nodes/1.js-BIwe5V8L.js +7 -0
- package/build/server/chunks/nodes/{1.js-D26Uv3YT.js.map → 1.js-BIwe5V8L.js.map} +1 -1
- package/build/server/chunks/nodes/2.js-Bj7c0eH1.js +7 -0
- package/build/server/chunks/nodes/{2.js-BeRlEFid.js.map → 2.js-Bj7c0eH1.js.map} +1 -1
- package/build/server/chunks/nodes/3.js-BMOf9FTK.js +7 -0
- package/build/server/chunks/nodes/{3.js-BRUNmCyG.js.map → 3.js-BMOf9FTK.js.map} +1 -1
- package/build/server/chunks/nodes/4.js-CNLb7Xc5.js +7 -0
- package/build/server/chunks/nodes/{4.js-CTHWqDf1.js.map → 4.js-CNLb7Xc5.js.map} +1 -1
- package/dist/runtime/chroma-key-video-lifecycle.d.ts +2 -2
- package/dist/runtime/chroma-key-video-lifecycle.js +221 -124
- package/dist/runtime/components/ChromaKeyVideo.svelte +13 -2
- package/dist/runtime/components/Slice.svelte +22 -12
- package/dist/runtime/components/Slice.svelte.d.ts +3 -6
- package/dist/runtime/components/SliceCanvas.svelte +51 -40
- package/dist/runtime/components/SliceCanvas.svelte.d.ts +2 -2
- package/dist/runtime/components/SliceDom.svelte +96 -42
- package/dist/runtime/components/SliceDom.svelte.d.ts +2 -2
- package/dist/runtime/slice-source-lifecycle.d.ts +14 -0
- package/dist/runtime/slice-source-lifecycle.js +70 -0
- package/package.json +4 -1
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css +0 -1
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css.br +0 -0
- package/build/client/_app/immutable/assets/LibraryContextMenu.BSnKt_Is.css.gz +0 -0
- package/build/client/_app/immutable/chunks/BAva9YXm.js +0 -1
- package/build/client/_app/immutable/chunks/BAva9YXm.js.br +0 -0
- package/build/client/_app/immutable/chunks/BAva9YXm.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BGAUmugt.js +0 -1
- package/build/client/_app/immutable/chunks/BGAUmugt.js.br +0 -0
- package/build/client/_app/immutable/chunks/BGAUmugt.js.gz +0 -0
- package/build/client/_app/immutable/chunks/BMORe2Gb.js.br +0 -0
- package/build/client/_app/immutable/chunks/CBygkKLq.js +0 -1
- package/build/client/_app/immutable/chunks/CBygkKLq.js.br +0 -0
- package/build/client/_app/immutable/chunks/CBygkKLq.js.gz +0 -0
- package/build/client/_app/immutable/chunks/Cil0r9BR.js +0 -108
- package/build/client/_app/immutable/chunks/Cil0r9BR.js.br +0 -0
- package/build/client/_app/immutable/chunks/Cil0r9BR.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D-p-QSzz.js +0 -1
- package/build/client/_app/immutable/chunks/D-p-QSzz.js.br +0 -0
- package/build/client/_app/immutable/chunks/D-p-QSzz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/D15yxLq9.js +0 -1
- package/build/client/_app/immutable/chunks/D15yxLq9.js.br +0 -0
- package/build/client/_app/immutable/chunks/D15yxLq9.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DFRlZOKz.js.br +0 -0
- package/build/client/_app/immutable/chunks/DFRlZOKz.js.gz +0 -0
- package/build/client/_app/immutable/chunks/DpFtnEPx.js.br +0 -4
- package/build/client/_app/immutable/chunks/DpFtnEPx.js.gz +0 -0
- package/build/client/_app/immutable/entry/app.BaP08B0_.js +0 -2
- package/build/client/_app/immutable/entry/app.BaP08B0_.js.br +0 -0
- package/build/client/_app/immutable/entry/app.BaP08B0_.js.gz +0 -0
- package/build/client/_app/immutable/entry/start.DntfygIK.js +0 -1
- package/build/client/_app/immutable/entry/start.DntfygIK.js.br +0 -0
- package/build/client/_app/immutable/entry/start.DntfygIK.js.gz +0 -0
- package/build/client/_app/immutable/nodes/0.6A6JK0Xm.js +0 -1
- package/build/client/_app/immutable/nodes/0.6A6JK0Xm.js.br +0 -0
- package/build/client/_app/immutable/nodes/0.6A6JK0Xm.js.gz +0 -0
- package/build/client/_app/immutable/nodes/1.8K7wLW9R.js +0 -1
- package/build/client/_app/immutable/nodes/1.8K7wLW9R.js.br +0 -0
- package/build/client/_app/immutable/nodes/1.8K7wLW9R.js.gz +0 -0
- package/build/client/_app/immutable/nodes/2.CB_PeUBC.js +0 -3
- package/build/client/_app/immutable/nodes/2.CB_PeUBC.js.br +0 -0
- package/build/client/_app/immutable/nodes/2.CB_PeUBC.js.gz +0 -0
- package/build/client/_app/immutable/nodes/3.qIkVQyP6.js +0 -1
- package/build/client/_app/immutable/nodes/3.qIkVQyP6.js.br +0 -0
- package/build/client/_app/immutable/nodes/3.qIkVQyP6.js.gz +0 -0
- package/build/client/_app/immutable/nodes/4.SmoVIy5D.js +0 -2
- package/build/client/_app/immutable/nodes/4.SmoVIy5D.js.br +0 -0
- package/build/client/_app/immutable/nodes/4.SmoVIy5D.js.gz +0 -0
- package/build/server/chunks/nodes/1.js-D26Uv3YT.js +0 -7
- package/build/server/chunks/nodes/2.js-BeRlEFid.js +0 -7
- package/build/server/chunks/nodes/3.js-BRUNmCyG.js +0 -7
- package/build/server/chunks/nodes/4.js-CTHWqDf1.js +0 -7
|
@@ -13,25 +13,28 @@
|
|
|
13
13
|
canvas is enlarged by the overdraw's destination size and offset negatively
|
|
14
14
|
(see `computeCanvasPaintLayout`), so the baked shadow/glow paints outside
|
|
15
15
|
the layout box while the wrapper (and therefore the layout) keeps the box
|
|
16
|
-
size — exactly where the DOM backend positions its
|
|
16
|
+
size — exactly where the DOM backend positions its border-image paint.
|
|
17
17
|
-->
|
|
18
18
|
<script lang="ts">
|
|
19
|
-
import
|
|
20
|
-
|
|
19
|
+
import {
|
|
20
|
+
computeCanvasPaintLayout,
|
|
21
|
+
computeRenderCells,
|
|
22
|
+
type CanvasPaintLayout
|
|
23
|
+
} from '../geometry.js';
|
|
21
24
|
import { observeBorderBoxSize } from '../observe-border-box-size.js';
|
|
25
|
+
import type { LoadedSliceSnapshot } from '../slice-source-lifecycle.js';
|
|
22
26
|
|
|
23
27
|
interface Props {
|
|
24
|
-
|
|
28
|
+
snapshot: LoadedSliceSnapshot | null;
|
|
25
29
|
/** Accessible label for the rendered graphic. */
|
|
26
30
|
alt?: string;
|
|
27
31
|
class?: string;
|
|
28
32
|
}
|
|
29
33
|
|
|
30
|
-
let {
|
|
34
|
+
let { snapshot, alt = '', class: className = '' }: Props = $props();
|
|
31
35
|
|
|
32
36
|
let root = $state<HTMLDivElement>();
|
|
33
37
|
let canvas = $state<HTMLCanvasElement>();
|
|
34
|
-
let image = $state<HTMLImageElement>();
|
|
35
38
|
let boxWidth = $state(0);
|
|
36
39
|
let boxHeight = $state(0);
|
|
37
40
|
let devicePixelRatio = $state(1);
|
|
@@ -39,23 +42,6 @@
|
|
|
39
42
|
// box nor the entry changed (belt and braces alongside the ResizeObserver).
|
|
40
43
|
let redrawTick = $state(0);
|
|
41
44
|
|
|
42
|
-
// Load the source image once per entry `src` — the same plain URL the DOM
|
|
43
|
-
// backend paints (slices are image-backed: the browser cache owns the bytes,
|
|
44
|
-
// preload retains nothing to resolve).
|
|
45
|
-
$effect(() => {
|
|
46
|
-
const sourceUrl = src.src;
|
|
47
|
-
const next = new Image();
|
|
48
|
-
let cancelled = false;
|
|
49
|
-
next.onload = () => {
|
|
50
|
-
if (!cancelled) image = next;
|
|
51
|
-
};
|
|
52
|
-
next.src = sourceUrl;
|
|
53
|
-
return () => {
|
|
54
|
-
cancelled = true;
|
|
55
|
-
next.onload = null;
|
|
56
|
-
};
|
|
57
|
-
});
|
|
58
|
-
|
|
59
45
|
// Track the display's devicePixelRatio: a resolution media query fires
|
|
60
46
|
// exactly when the DPR leaves the tracked value (browser zoom, moving the
|
|
61
47
|
// window to another display). The tracked state must be READ first — a
|
|
@@ -83,40 +69,65 @@
|
|
|
83
69
|
});
|
|
84
70
|
});
|
|
85
71
|
|
|
86
|
-
const
|
|
72
|
+
const emptyLayout: CanvasPaintLayout = {
|
|
73
|
+
cssLeft: 0,
|
|
74
|
+
cssTop: 0,
|
|
75
|
+
cssWidth: 0,
|
|
76
|
+
cssHeight: 0,
|
|
77
|
+
backingWidth: 0,
|
|
78
|
+
backingHeight: 0,
|
|
79
|
+
originX: 0,
|
|
80
|
+
originY: 0
|
|
81
|
+
};
|
|
82
|
+
const layout = $derived.by(() => {
|
|
83
|
+
const current = snapshot;
|
|
84
|
+
return current
|
|
85
|
+
? computeCanvasPaintLayout(current.entry, boxWidth, boxHeight, devicePixelRatio)
|
|
86
|
+
: emptyLayout;
|
|
87
|
+
});
|
|
87
88
|
|
|
88
|
-
// Redraw when
|
|
89
|
+
// Redraw only when a committed snapshot, the box, DPR, or window changes.
|
|
89
90
|
$effect(() => {
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
void layout;
|
|
91
|
+
const current = snapshot;
|
|
92
|
+
const currentLayout = layout;
|
|
93
93
|
void redrawTick;
|
|
94
|
-
draw();
|
|
94
|
+
draw(current, currentLayout);
|
|
95
95
|
});
|
|
96
96
|
|
|
97
|
-
function draw(): void {
|
|
97
|
+
function draw(current: LoadedSliceSnapshot | null, currentLayout: CanvasPaintLayout): void {
|
|
98
98
|
const element = canvas;
|
|
99
|
-
|
|
100
|
-
if (!
|
|
101
|
-
if (boxWidth === 0 || boxHeight === 0) {
|
|
99
|
+
if (!element) return;
|
|
100
|
+
if (!current || boxWidth === 0 || boxHeight === 0) {
|
|
102
101
|
element.width = 0;
|
|
103
102
|
element.height = 0;
|
|
104
103
|
return;
|
|
105
104
|
}
|
|
106
105
|
|
|
107
|
-
element.width =
|
|
108
|
-
element.height =
|
|
106
|
+
element.width = currentLayout.backingWidth;
|
|
107
|
+
element.height = currentLayout.backingHeight;
|
|
109
108
|
|
|
110
109
|
const context = element.getContext('2d');
|
|
111
110
|
if (!context) return;
|
|
112
111
|
// Origin at the layout box's top-left, so the (possibly negative) cell
|
|
113
112
|
// coordinates from computeRenderCells apply directly.
|
|
114
|
-
context.setTransform(
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
113
|
+
context.setTransform(
|
|
114
|
+
devicePixelRatio,
|
|
115
|
+
0,
|
|
116
|
+
0,
|
|
117
|
+
devicePixelRatio,
|
|
118
|
+
currentLayout.originX,
|
|
119
|
+
currentLayout.originY
|
|
120
|
+
);
|
|
121
|
+
context.clearRect(
|
|
122
|
+
currentLayout.cssLeft,
|
|
123
|
+
currentLayout.cssTop,
|
|
124
|
+
currentLayout.cssWidth,
|
|
125
|
+
currentLayout.cssHeight
|
|
126
|
+
);
|
|
127
|
+
|
|
128
|
+
for (const cell of computeRenderCells(current.entry, boxWidth, boxHeight)) {
|
|
118
129
|
context.drawImage(
|
|
119
|
-
|
|
130
|
+
current.image,
|
|
120
131
|
cell.sx,
|
|
121
132
|
cell.sy,
|
|
122
133
|
cell.sw,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoadedSliceSnapshot } from '../slice-source-lifecycle.js';
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
snapshot: LoadedSliceSnapshot | null;
|
|
4
4
|
/** Accessible label for the rendered graphic. */
|
|
5
5
|
alt?: string;
|
|
6
6
|
class?: string;
|
|
@@ -5,33 +5,96 @@
|
|
|
5
5
|
in the entry. Private: hosts render `Slice.svelte`, which dispatches between
|
|
6
6
|
this and the canvas backend.
|
|
7
7
|
|
|
8
|
-
Fills its container and measures it (ResizeObserver), then paints
|
|
9
|
-
slice
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
With overdraw the
|
|
14
|
-
root switches to overflow: visible and the baked shadow/glow draws
|
|
15
|
-
layout box.
|
|
8
|
+
Fills its container and measures it (ResizeObserver), then paints the complete
|
|
9
|
+
slice through one CSS border-image. The browser still stretches the same source
|
|
10
|
+
regions computed by `computeRenderCells`, but rasterizes them as one border
|
|
11
|
+
image instead of separate clipped elements. Shared slice edges therefore cannot
|
|
12
|
+
expose the background under fractional transforms.
|
|
13
|
+
With overdraw the paint element extends past the container (negative offsets),
|
|
14
|
+
so the root switches to overflow: visible and the baked shadow/glow draws
|
|
15
|
+
outside the layout box.
|
|
16
16
|
-->
|
|
17
17
|
<script lang="ts">
|
|
18
|
-
import type { SliceManifestEntry } from '../../core/index.js';
|
|
19
|
-
import { computeRenderCells, effectiveOverdraw } from '../geometry.js';
|
|
18
|
+
import type { SliceInsets, SliceManifestEntry } from '../../core/index.js';
|
|
19
|
+
import { computeRenderCells, effectiveInsets, effectiveOverdraw } from '../geometry.js';
|
|
20
20
|
import { observeBorderBoxSize } from '../observe-border-box-size.js';
|
|
21
|
+
import type { LoadedSliceSnapshot } from '../slice-source-lifecycle.js';
|
|
21
22
|
|
|
22
23
|
interface Props {
|
|
23
|
-
|
|
24
|
+
snapshot: LoadedSliceSnapshot | null;
|
|
24
25
|
/** Accessible label for the rendered graphic. */
|
|
25
26
|
alt?: string;
|
|
26
27
|
class?: string;
|
|
27
28
|
}
|
|
28
29
|
|
|
29
|
-
let {
|
|
30
|
+
let { snapshot, alt = '', class: className = '' }: Props = $props();
|
|
30
31
|
|
|
31
32
|
let root = $state<HTMLDivElement>();
|
|
32
33
|
let boxWidth = $state(0);
|
|
33
34
|
let boxHeight = $state(0);
|
|
34
35
|
|
|
36
|
+
interface BorderImagePaint {
|
|
37
|
+
left: number;
|
|
38
|
+
top: number;
|
|
39
|
+
width: number;
|
|
40
|
+
height: number;
|
|
41
|
+
slices: SliceInsets;
|
|
42
|
+
widths: SliceInsets;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
function clamp(value: number, min: number, max: number): number {
|
|
46
|
+
return Math.max(min, Math.min(max, value));
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
function computeBorderImagePaint(
|
|
50
|
+
entry: SliceManifestEntry,
|
|
51
|
+
width: number,
|
|
52
|
+
height: number
|
|
53
|
+
): BorderImagePaint | null {
|
|
54
|
+
const cells = computeRenderCells(entry, width, height);
|
|
55
|
+
if (cells.length === 0) return null;
|
|
56
|
+
|
|
57
|
+
const effective = effectiveInsets(entry);
|
|
58
|
+
const leftSlice = clamp(effective.left, 0, entry.sourceWidth);
|
|
59
|
+
const rightSlice = clamp(effective.right, 0, entry.sourceWidth - leftSlice);
|
|
60
|
+
const topSlice = clamp(effective.top, 0, entry.sourceHeight);
|
|
61
|
+
const bottomSlice = clamp(effective.bottom, 0, entry.sourceHeight - topSlice);
|
|
62
|
+
const slices = {
|
|
63
|
+
top: topSlice,
|
|
64
|
+
right: rightSlice,
|
|
65
|
+
bottom: bottomSlice,
|
|
66
|
+
left: leftSlice
|
|
67
|
+
};
|
|
68
|
+
const left = Math.min(...cells.map((cell) => cell.dx));
|
|
69
|
+
const top = Math.min(...cells.map((cell) => cell.dy));
|
|
70
|
+
const right = Math.max(...cells.map((cell) => cell.dx + cell.dw));
|
|
71
|
+
const bottom = Math.max(...cells.map((cell) => cell.dy + cell.dh));
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
left,
|
|
75
|
+
top,
|
|
76
|
+
width: right - left,
|
|
77
|
+
height: bottom - top,
|
|
78
|
+
slices,
|
|
79
|
+
widths: {
|
|
80
|
+
top: cells.find((cell) => topSlice > 0 && cell.sy === 0 && cell.sh === topSlice)?.dh ?? 0,
|
|
81
|
+
right:
|
|
82
|
+
cells.find(
|
|
83
|
+
(cell) =>
|
|
84
|
+
rightSlice > 0 && cell.sx === entry.sourceWidth - rightSlice && cell.sw === rightSlice
|
|
85
|
+
)?.dw ?? 0,
|
|
86
|
+
bottom:
|
|
87
|
+
cells.find(
|
|
88
|
+
(cell) =>
|
|
89
|
+
bottomSlice > 0 &&
|
|
90
|
+
cell.sy === entry.sourceHeight - bottomSlice &&
|
|
91
|
+
cell.sh === bottomSlice
|
|
92
|
+
)?.dh ?? 0,
|
|
93
|
+
left: cells.find((cell) => leftSlice > 0 && cell.sx === 0 && cell.sw === leftSlice)?.dw ?? 0
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
|
|
35
98
|
$effect(() => {
|
|
36
99
|
const element = root;
|
|
37
100
|
if (!element) return;
|
|
@@ -41,9 +104,11 @@
|
|
|
41
104
|
});
|
|
42
105
|
});
|
|
43
106
|
|
|
44
|
-
const
|
|
107
|
+
const entry = $derived(snapshot?.entry ?? null);
|
|
108
|
+
const paint = $derived(entry ? computeBorderImagePaint(entry, boxWidth, boxHeight) : null);
|
|
45
109
|
const hasOverdraw = $derived.by(() => {
|
|
46
|
-
|
|
110
|
+
if (!entry) return false;
|
|
111
|
+
const overdraw = effectiveOverdraw(entry);
|
|
47
112
|
return overdraw.top > 0 || overdraw.right > 0 || overdraw.bottom > 0 || overdraw.left > 0;
|
|
48
113
|
});
|
|
49
114
|
</script>
|
|
@@ -55,25 +120,18 @@
|
|
|
55
120
|
role={alt ? 'img' : undefined}
|
|
56
121
|
aria-label={alt || undefined}
|
|
57
122
|
>
|
|
58
|
-
{#
|
|
123
|
+
{#if entry && paint}
|
|
59
124
|
<div
|
|
60
|
-
class="fundus-
|
|
61
|
-
style:left="{
|
|
62
|
-
style:top="{
|
|
63
|
-
style:width="{
|
|
64
|
-
style:height="{
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
style:width="{(src.sourceWidth / cell.sw) * 100}%"
|
|
71
|
-
style:height="{(src.sourceHeight / cell.sh) * 100}%"
|
|
72
|
-
style:left="{(-cell.sx / cell.sw) * 100}%"
|
|
73
|
-
style:top="{(-cell.sy / cell.sh) * 100}%"
|
|
74
|
-
/>
|
|
75
|
-
</div>
|
|
76
|
-
{/each}
|
|
125
|
+
class="fundus-slice__paint"
|
|
126
|
+
style:left="{paint.left}px"
|
|
127
|
+
style:top="{paint.top}px"
|
|
128
|
+
style:width="{paint.width}px"
|
|
129
|
+
style:height="{paint.height}px"
|
|
130
|
+
style:border-image-source={`url(${JSON.stringify(entry.src)})`}
|
|
131
|
+
style:border-image-slice={`${paint.slices.top} ${paint.slices.right} ${paint.slices.bottom} ${paint.slices.left} fill`}
|
|
132
|
+
style:border-image-width={`${paint.widths.top}px ${paint.widths.right}px ${paint.widths.bottom}px ${paint.widths.left}px`}
|
|
133
|
+
></div>
|
|
134
|
+
{/if}
|
|
77
135
|
</div>
|
|
78
136
|
|
|
79
137
|
<style>
|
|
@@ -84,21 +142,17 @@
|
|
|
84
142
|
overflow: hidden;
|
|
85
143
|
}
|
|
86
144
|
|
|
87
|
-
/* Overdraw
|
|
145
|
+
/* Overdraw deliberately extends the paint past the box — don't clip it. */
|
|
88
146
|
.fundus-slice--overdraw {
|
|
89
147
|
overflow: visible;
|
|
90
148
|
}
|
|
91
149
|
|
|
92
|
-
.fundus-
|
|
93
|
-
position: absolute;
|
|
94
|
-
overflow: hidden;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
.fundus-slice__cell img {
|
|
150
|
+
.fundus-slice__paint {
|
|
98
151
|
position: absolute;
|
|
99
|
-
|
|
100
|
-
|
|
152
|
+
box-sizing: border-box;
|
|
153
|
+
border-width: 0;
|
|
154
|
+
border-style: solid;
|
|
155
|
+
border-image-repeat: stretch;
|
|
101
156
|
pointer-events: none;
|
|
102
|
-
user-select: none;
|
|
103
157
|
}
|
|
104
158
|
</style>
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LoadedSliceSnapshot } from '../slice-source-lifecycle.js';
|
|
2
2
|
interface Props {
|
|
3
|
-
|
|
3
|
+
snapshot: LoadedSliceSnapshot | null;
|
|
4
4
|
/** Accessible label for the rendered graphic. */
|
|
5
5
|
alt?: string;
|
|
6
6
|
class?: string;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { SliceManifestEntry } from '../core/index.js';
|
|
2
|
+
export interface LoadedSliceSnapshot {
|
|
3
|
+
entry: SliceManifestEntry;
|
|
4
|
+
image: HTMLImageElement;
|
|
5
|
+
}
|
|
6
|
+
export type SliceImageLoader = (url: string) => Promise<HTMLImageElement>;
|
|
7
|
+
export declare function loadSliceImage(url: string): Promise<HTMLImageElement>;
|
|
8
|
+
/** Coordinates requested slice entries with the last image-ready snapshot. */
|
|
9
|
+
export declare class SliceSourceLifecycle {
|
|
10
|
+
#private;
|
|
11
|
+
constructor(commit: (snapshot: LoadedSliceSnapshot) => void, loadImage?: SliceImageLoader);
|
|
12
|
+
request(entry: SliceManifestEntry): void;
|
|
13
|
+
dispose(): void;
|
|
14
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export function loadSliceImage(url) {
|
|
2
|
+
const image = new Image();
|
|
3
|
+
image.decoding = 'async';
|
|
4
|
+
image.src = url;
|
|
5
|
+
return image.decode().then(() => image);
|
|
6
|
+
}
|
|
7
|
+
/** Coordinates requested slice entries with the last image-ready snapshot. */
|
|
8
|
+
export class SliceSourceLifecycle {
|
|
9
|
+
#loadImage;
|
|
10
|
+
#commit;
|
|
11
|
+
#requestedEntry = null;
|
|
12
|
+
#displayedSnapshot = null;
|
|
13
|
+
#inFlight = new Map();
|
|
14
|
+
#disposed = false;
|
|
15
|
+
constructor(commit, loadImage = loadSliceImage) {
|
|
16
|
+
this.#commit = commit;
|
|
17
|
+
this.#loadImage = loadImage;
|
|
18
|
+
}
|
|
19
|
+
request(entry) {
|
|
20
|
+
if (this.#disposed)
|
|
21
|
+
return;
|
|
22
|
+
this.#requestedEntry = entry;
|
|
23
|
+
const displayed = this.#displayedSnapshot;
|
|
24
|
+
if (displayed?.entry.src === entry.src) {
|
|
25
|
+
this.#commitSnapshot({ entry, image: displayed.image });
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (this.#inFlight.has(entry.src))
|
|
29
|
+
return;
|
|
30
|
+
let promise;
|
|
31
|
+
try {
|
|
32
|
+
promise = Promise.resolve(this.#loadImage(entry.src));
|
|
33
|
+
}
|
|
34
|
+
catch (error) {
|
|
35
|
+
promise = Promise.reject(error);
|
|
36
|
+
}
|
|
37
|
+
const load = { promise };
|
|
38
|
+
this.#inFlight.set(entry.src, load);
|
|
39
|
+
void promise.then((image) => this.#settleSuccess(entry.src, load, image), () => this.#settleFailure(entry.src, load));
|
|
40
|
+
}
|
|
41
|
+
dispose() {
|
|
42
|
+
if (this.#disposed)
|
|
43
|
+
return;
|
|
44
|
+
this.#disposed = true;
|
|
45
|
+
this.#requestedEntry = null;
|
|
46
|
+
this.#displayedSnapshot = null;
|
|
47
|
+
this.#inFlight.clear();
|
|
48
|
+
}
|
|
49
|
+
#settleSuccess(url, load, image) {
|
|
50
|
+
if (this.#inFlight.get(url) !== load)
|
|
51
|
+
return;
|
|
52
|
+
this.#inFlight.delete(url);
|
|
53
|
+
if (this.#disposed)
|
|
54
|
+
return;
|
|
55
|
+
const requested = this.#requestedEntry;
|
|
56
|
+
if (!requested || requested.src !== url)
|
|
57
|
+
return;
|
|
58
|
+
this.#commitSnapshot({ entry: requested, image });
|
|
59
|
+
}
|
|
60
|
+
#settleFailure(url, load) {
|
|
61
|
+
if (this.#inFlight.get(url) === load)
|
|
62
|
+
this.#inFlight.delete(url);
|
|
63
|
+
}
|
|
64
|
+
#commitSnapshot(snapshot) {
|
|
65
|
+
if (this.#disposed)
|
|
66
|
+
return;
|
|
67
|
+
this.#displayedSnapshot = snapshot;
|
|
68
|
+
this.#commit(snapshot);
|
|
69
|
+
}
|
|
70
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "fundus",
|
|
3
|
-
"version": "0.11.
|
|
3
|
+
"version": "0.11.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -67,7 +67,10 @@
|
|
|
67
67
|
"@sveltejs/vite-plugin-svelte": "^7.1.2",
|
|
68
68
|
"@types/ffprobe-static": "^2.0.3",
|
|
69
69
|
"@types/node": "^24.13.3",
|
|
70
|
+
"@vitest/browser": "^3.2.7",
|
|
70
71
|
"fuse.js": "^7.4.2",
|
|
72
|
+
"happy-dom": "^20.11.0",
|
|
73
|
+
"playwright": "^1.61.1",
|
|
71
74
|
"prettier": "^3.8.3",
|
|
72
75
|
"prettier-plugin-svelte": "^4.1.0",
|
|
73
76
|
"publint": "^0.3.21",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
.playback.svelte-nchstv{align-items:center;gap:6px;width:100%;display:flex}.btn.svelte-nchstv{background:var(--panel-raised);border-radius:var(--radius);width:28px;height:28px;color:var(--text);border:1px solid #0000;flex:none;justify-content:center;align-items:center;padding:0;display:inline-flex}.btn.svelte-nchstv:hover:not(:disabled){border-color:var(--border)}.btn.svelte-nchstv:focus-visible{border-color:var(--accent);outline:none}.btn.svelte-nchstv:disabled{opacity:.4;cursor:not-allowed}.btn.active.svelte-nchstv{background:var(--accent-soft);color:var(--accent)}.btn.svelte-nchstv svg:where(.svelte-nchstv){width:16px;height:16px;display:block}.time.svelte-nchstv{color:var(--text-dim);font-variant-numeric:tabular-nums;flex:none;font-size:11px}.volume-group.svelte-nchstv{align-items:center;gap:6px;margin-left:auto;display:inline-flex}.range.svelte-nchstv{appearance:none;background:var(--panel-raised);cursor:pointer;border-radius:999px;height:4px}.range.scrub.svelte-nchstv{flex:1;min-width:0;margin:0 2px}.range.volume.svelte-nchstv{flex:none;width:72px}.range.svelte-nchstv:disabled{opacity:.4;cursor:not-allowed}.range.svelte-nchstv::-webkit-slider-thumb{appearance:none;background:var(--accent);border:none;border-radius:50%;width:12px;height:12px}.range.svelte-nchstv::-moz-range-thumb{background:var(--accent);border:none;border-radius:50%;width:12px;height:12px}.range.svelte-nchstv:focus-visible{outline:none}.range.svelte-nchstv:focus-visible::-webkit-slider-thumb{box-shadow:0 0 0 3px var(--accent-soft)}.range.svelte-nchstv:focus-visible::-moz-range-thumb{box-shadow:0 0 0 3px var(--accent-soft)}.audio-waveform.svelte-1liihyn{flex-direction:column;gap:8px;width:100%;height:100%;min-height:0;display:flex}.wave.svelte-1liihyn{cursor:pointer;touch-action:none;flex:1;width:100%;min-height:0;display:block}.footer.svelte-1liihyn{flex:none;align-items:center;display:flex}.stage.svelte-1ww4cvx{border:1px solid var(--border);border-radius:8px;flex:1;justify-content:center;align-items:center;min-height:0;display:flex;overflow:auto}.audio-frame.svelte-1ww4cvx{width:min(90%,480px);height:128px}p.svelte-1ww4cvx{color:var(--text-dim)}.scrub-number.svelte-nhap92{flex:1;min-width:0;display:flex;position:relative}.input.svelte-nhap92{width:100%;min-width:0;color:var(--text);font-variant-numeric:tabular-nums;appearance:textfield;background:0 0;border:none;outline:none;flex:1;margin:0;padding:0;font-size:11px}.scrub-number.with-suffix.svelte-nhap92 .input:where(.svelte-nhap92){flex:none}.suffix.svelte-nhap92{color:var(--text-dim);font-variant-numeric:tabular-nums;-webkit-user-select:none;user-select:none;flex:none;margin-left:2px;font-size:11px}.scrub-number.right.svelte-nhap92 .input:where(.svelte-nhap92){text-align:right}.input.svelte-nhap92::-webkit-outer-spin-button{appearance:none;margin:0}.input.svelte-nhap92::-webkit-inner-spin-button{appearance:none;margin:0}.scrub-surface.svelte-nhap92{cursor:ew-resize;touch-action:none;position:absolute;inset:0}.number-field.svelte-368zap{flex-direction:column;gap:4px;min-width:0;display:flex}.caption.svelte-368zap{letter-spacing:.27px;color:#ffffffb2;-webkit-user-select:none;user-select:none;font-size:9px;font-weight:500;line-height:14px}.number-input.svelte-368zap{border-radius:4px;align-items:center;gap:4px;min-width:0;height:24px;padding:0 6px 0 0;display:flex;position:relative;overflow:hidden}.number-input.svelte-368zap:focus-within{border-color:var(--accent)}.fill.svelte-368zap{pointer-events:none;z-index:0;background:#4a4a4a;height:100%;position:absolute;top:0;left:0}.icon-slot.svelte-368zap{z-index:1;width:24px;height:24px;color:var(--text-dim);-webkit-user-select:none;user-select:none;flex:none;justify-content:center;align-items:center;font-size:11px;font-weight:500;display:flex;position:relative}.number-input.svelte-368zap .scrub-number{z-index:1}h3.svelte-1ol624f{letter-spacing:0;text-transform:none;color:#fff;margin:0 0 10px;font-size:11px;font-weight:400}.select-field.svelte-bczi6w{flex-direction:column;gap:4px;min-width:0;display:flex}.caption.svelte-bczi6w{letter-spacing:.27px;color:#ffffffb2;-webkit-user-select:none;user-select:none;font-size:9px;font-weight:500;line-height:14px}.select-input.svelte-bczi6w{border-radius:4px;align-items:center;gap:4px;min-width:0;height:24px;padding:0 6px 0 0;display:flex}.select-input.svelte-bczi6w:focus-within{border-color:var(--accent)}.icon-slot.svelte-bczi6w{width:24px;height:24px;color:var(--text-dim);-webkit-user-select:none;user-select:none;flex:none;justify-content:center;align-items:center;font-size:11px;font-weight:500;display:flex}select.svelte-bczi6w{width:100%;min-width:0;height:100%;color:var(--text);background:0 0;border:none;outline:none;flex:1;margin:0;padding:0;font-size:11px}section.svelte-m9vwwu{border-bottom:1px solid var(--border-soft);padding:12px}.hint.svelte-m9vwwu{color:var(--text-faint);margin:4px 0 0;font-size:11px}.info.svelte-m9vwwu{font-variant-numeric:tabular-nums;margin:0}.file.svelte-m9vwwu{color:var(--text-dim);word-break:break-all}section.svelte-1by8n8t{border-bottom:1px solid var(--border-soft);padding:12px}.field.svelte-1by8n8t{margin-bottom:8px}.fundus-slice.svelte-1820t2z{width:100%;height:100%;position:relative;overflow:hidden}.fundus-slice--overdraw.svelte-1820t2z{overflow:visible}.fundus-slice__cell.svelte-1820t2z{position:absolute;overflow:hidden}.fundus-slice__cell.svelte-1820t2z img:where(.svelte-1820t2z){pointer-events:none;-webkit-user-select:none;user-select:none;max-width:none;max-height:none;position:absolute}.fundus-slice-canvas.svelte-xdsbrz{width:100%;height:100%;position:relative}canvas.svelte-xdsbrz{pointer-events:none;display:block;position:absolute}.fundus-chroma-key-video.svelte-r30mxh{width:100%;height:100%;position:relative}canvas.svelte-r30mxh,img.svelte-r30mxh{width:100%;height:100%;display:block}video.svelte-r30mxh{visibility:hidden;pointer-events:none;width:100%;height:100%;position:absolute;inset:0}.stage.svelte-10eps7e{border:1px solid var(--border);border-radius:8px;flex:1;justify-content:center;align-items:center;min-height:0;display:flex;overflow:auto}.stage.svelte-10eps7e img{object-fit:contain;max-width:90%;max-height:90%}img.svelte-gdduef{object-fit:contain;max-width:100%;max-height:100%}section.svelte-1yd7n22{border-bottom:1px solid var(--border-soft);padding:12px}.modes.svelte-1yd7n22{flex-direction:column;gap:4px;display:flex}.modes.svelte-1yd7n22 button:where(.svelte-1yd7n22){text-align:left;background:var(--panel-raised);color:var(--text);border-radius:var(--radius);border:1px solid #0000;padding:6px 10px}.modes.svelte-1yd7n22 button:where(.svelte-1yd7n22):hover{border-color:var(--border)}.modes.svelte-1yd7n22 button.on:where(.svelte-1yd7n22){background:var(--accent-soft);border-color:var(--accent);color:var(--accent);font-weight:600}.insets.svelte-1yd7n22{grid-template-columns:1fr 1fr;gap:8px;min-width:0;display:grid}.insets.single.svelte-1yd7n22{grid-template-columns:1fr}.preview-panel.svelte-1mjaycs{flex-direction:column;height:100%;min-height:0;display:flex}.bar.svelte-1mjaycs{flex:none;align-items:center;gap:10px;padding:8px 0;display:flex}.size.svelte-1mjaycs{color:var(--text-dim);font-variant-numeric:tabular-nums}.backends.svelte-1mjaycs{background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);gap:2px;margin-left:auto;padding:2px;display:inline-flex}.backends.svelte-1mjaycs button:where(.svelte-1mjaycs){color:var(--text-dim);background:0 0;border:none;border-radius:4px;padding:2px 8px}.backends.svelte-1mjaycs button.on:where(.svelte-1mjaycs){background:var(--accent-soft);color:var(--accent);font-weight:600}.reset.svelte-1mjaycs{background:var(--panel-raised);border:1px solid var(--border);color:var(--text);border-radius:var(--radius);padding:4px 10px}.reset.svelte-1mjaycs:hover{border-color:var(--accent)}.stage.svelte-1mjaycs{border:1px solid var(--border);border-radius:var(--radius-large);flex:1;min-height:0;padding:24px;overflow:auto}.box.svelte-1mjaycs{position:relative;box-shadow:0 0 0 1px #ffffff1f}.box.svelte-1mjaycs .fill{position:absolute;inset:0}.handle.svelte-1mjaycs{touch-action:none;background:0 0;position:absolute}.handle.edge-right.svelte-1mjaycs{cursor:ew-resize;width:10px;height:100%;top:0;right:-4px}.handle.edge-bottom.svelte-1mjaycs{cursor:ns-resize;width:100%;height:10px;bottom:-4px;left:0}.handle.corner.svelte-1mjaycs{cursor:nwse-resize;background:var(--accent);width:16px;height:16px;box-shadow:0 0 0 2px var(--canvas);border-radius:3px;bottom:-6px;right:-6px}.canvas.svelte-1jfrg6d{flex-direction:column;height:100%;min-height:0;display:flex}.toolbar.svelte-1jfrg6d{flex:none;align-items:center;gap:8px;padding:8px 0;display:flex}.toolbar.svelte-1jfrg6d button:where(.svelte-1jfrg6d){background:var(--panel-raised);border:1px solid var(--border);color:var(--text);border-radius:var(--radius);padding:4px 10px}.toolbar.svelte-1jfrg6d button:where(.svelte-1jfrg6d):hover{border-color:var(--accent)}.toolbar.svelte-1jfrg6d button.active:where(.svelte-1jfrg6d){background:var(--accent-soft);border-color:var(--accent);color:var(--accent)}.zoom.svelte-1jfrg6d{text-align:center;min-width:44px;color:var(--text-dim);font-variant-numeric:tabular-nums}.dims.svelte-1jfrg6d{color:var(--text-dim);font-variant-numeric:tabular-nums;margin-left:auto}.viewport.svelte-1jfrg6d{touch-action:none;cursor:grab;border:1px solid var(--border);border-radius:var(--radius-large);flex:1;min-height:0;position:relative;overflow:hidden}.viewport.panning.svelte-1jfrg6d{cursor:grabbing}.image-wrap.svelte-1jfrg6d{transform-origin:0 0;position:absolute;top:0;left:0;box-shadow:0 0 0 1px #ffffff14}.image-wrap.svelte-1jfrg6d img:where(.svelte-1jfrg6d){width:100%;height:100%;image-rendering:pixelated;pointer-events:none;-webkit-user-select:none;user-select:none;display:block}.center-rect.svelte-1jfrg6d{pointer-events:none;position:absolute}.center-rect.side-edges.svelte-1jfrg6d{border-left:1px dashed #0d99ff99;border-right:1px dashed #0d99ff99}.center-rect.cap-edges.svelte-1jfrg6d{border-top:1px dashed #0d99ff99;border-bottom:1px dashed #0d99ff99}.overdraw-band.svelte-1jfrg6d{pointer-events:none;background:#38bdf829;position:absolute}.line.svelte-1jfrg6d{background:var(--accent);touch-action:none;position:absolute}.line.overdraw-line.svelte-1jfrg6d{background:#38bdf8 padding-box content-box}.line.overdraw-line.svelte-1jfrg6d .tag:where(.svelte-1jfrg6d){background:#38bdf8}.line.v.svelte-1jfrg6d{cursor:ew-resize;box-sizing:content-box;background-clip:content-box;width:1px;height:100%;margin-left:-.5px;padding:0 7px;top:0;transform:translate(-7px)}.line.h.svelte-1jfrg6d{cursor:ns-resize;box-sizing:content-box;background-clip:content-box;width:100%;height:1px;margin-top:-.5px;padding:7px 0;left:0;transform:translateY(-7px)}.line.active.svelte-1jfrg6d{background-color:var(--text);background-clip:content-box}.tag.svelte-1jfrg6d{background:var(--accent);color:var(--text);font-variant-numeric:tabular-nums;pointer-events:none;border-radius:4px;padding:1px 5px;font-size:11px;font-weight:600;position:absolute}.line.v.svelte-1jfrg6d .tag:where(.svelte-1jfrg6d){top:4px;left:50%;transform:translate(-50%)}.line.h.svelte-1jfrg6d .tag:where(.svelte-1jfrg6d){top:50%;left:4px;transform:translateY(-50%)}.line.v.overdraw-line.svelte-1jfrg6d .tag:where(.svelte-1jfrg6d){top:auto;bottom:4px}.line.h.overdraw-line.svelte-1jfrg6d .tag:where(.svelte-1jfrg6d){left:auto;right:4px}.editor.svelte-1ea2lvt{flex-direction:column;flex:1;min-height:0;display:flex}.tabs.svelte-1ea2lvt{flex:none;gap:4px;margin-bottom:4px;display:inline-flex}.tabs.svelte-1ea2lvt button:where(.svelte-1ea2lvt){border-radius:var(--radius);color:var(--text-dim);background:0 0;border:none;padding:4px 10px}.tabs.svelte-1ea2lvt button.on:where(.svelte-1ea2lvt){background:var(--accent-soft);color:var(--accent)}.pane.svelte-1ea2lvt{flex:1;min-height:0}.empty.svelte-1ea2lvt{color:var(--text-dim);flex:1;justify-content:center;align-items:center;display:flex}section.svelte-ij1927{border-bottom:1px solid var(--border-soft);padding:12px}.field.svelte-ij1927{margin-bottom:8px}.stage.svelte-qls820{border:1px solid var(--border);border-radius:8px;flex:1;justify-content:center;align-items:center;min-height:0;display:flex;overflow:auto}.preview-column.svelte-qls820{flex-direction:column;align-items:center;gap:8px;display:flex}.video-frame.svelte-qls820{width:min(90%,480px)}.video-frame.svelte-qls820 video{width:100%;height:100%}p.svelte-qls820{color:var(--text-dim)}video.svelte-ejgo9x{object-fit:contain;max-width:100%;max-height:100%}.picker.svelte-56kutb{flex-direction:column;gap:4px;min-width:0;margin-bottom:8px;display:flex}.caption.svelte-56kutb{letter-spacing:.27px;color:#ffffffb2;-webkit-user-select:none;user-select:none;font-size:9px;font-weight:500;line-height:14px}.reference-input.svelte-56kutb{border-radius:4px;align-items:center;min-width:0;height:24px;padding:0;display:flex;position:relative}.reference-input.svelte-56kutb:focus-within{border-color:var(--accent)}.current.svelte-56kutb{min-width:0;height:100%;color:var(--text);text-align:left;background:0 0;border:none;outline:none;flex:1;align-items:center;gap:4px;padding:0 6px 0 0;display:flex}.current.empty.svelte-56kutb{color:var(--text-faint)}.preview-slot.svelte-56kutb{box-sizing:border-box;background:#4a4a4a;border-radius:3px 0 0 3px;flex:none;justify-content:center;align-items:center;width:24px;height:24px;margin-left:-1px;padding:2px;display:flex;overflow:hidden}.preview.svelte-56kutb{object-fit:contain;width:100%;height:100%}.missing-preview.svelte-56kutb{color:var(--warning);font-weight:700}.clear.svelte-56kutb{border:none;border-left:1px solid var(--border-soft);width:24px;height:24px;color:var(--text-dim);background:0 0;border-radius:0 3px 3px 0;outline:none;flex:none;padding:0}.clear.svelte-56kutb:hover{color:var(--danger)}.id.svelte-56kutb,.placeholder.svelte-56kutb{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.dangling.svelte-56kutb{color:var(--warning)}.dropdown.svelte-56kutb{z-index:10;background:var(--panel);border:1px solid var(--border);border-radius:var(--radius);max-height:240px;padding:4px;position:absolute;top:calc(100% + 4px);left:0;right:0;overflow-y:auto;box-shadow:0 8px 24px #00000080}.option.svelte-56kutb{border-radius:var(--radius);width:100%;color:var(--text);text-align:left;background:0 0;border:none;align-items:center;gap:6px;padding:4px 6px;display:flex}.option.svelte-56kutb .thumbnail:where(.svelte-56kutb){object-fit:contain;background:var(--canvas);border-radius:3px;flex:none;width:24px;height:24px}.option.svelte-56kutb:hover{background:var(--panel-raised)}.option.selected.svelte-56kutb{background:var(--accent-soft);color:var(--accent)}.hint.svelte-56kutb{color:var(--text-faint);margin:4px;font-size:11px}.color-field.svelte-gjs979{flex-direction:column;gap:4px;min-width:0;display:flex}.caption.svelte-gjs979{letter-spacing:.27px;color:#ffffffb2;-webkit-user-select:none;user-select:none;font-size:9px;font-weight:500;line-height:14px}.color-input.svelte-gjs979{border-radius:4px;align-items:center;gap:4px;min-width:0;height:24px;padding:0 6px 0 0;display:flex}.color-input.svelte-gjs979:focus-within{border-color:var(--accent)}.swatch-slot.svelte-gjs979{flex:none;justify-content:center;align-items:center;width:24px;height:24px;display:flex}.swatch.svelte-gjs979{cursor:pointer;background:0 0;border:1px solid #ffffff3d;border-radius:3px;width:16px;height:16px;margin:0;padding:0;overflow:hidden}.swatch.svelte-gjs979::-webkit-color-swatch-wrapper{padding:0}.swatch.svelte-gjs979::-webkit-color-swatch{border:none}.hex-input.svelte-gjs979{width:100%;min-width:0;color:var(--text);font-variant-numeric:tabular-nums;text-transform:uppercase;background:0 0;border:none;outline:none;flex:1;margin:0;padding:0;font-size:11px}section.svelte-rsjkek{border-bottom:1px solid var(--border-soft);padding:12px}.field.svelte-rsjkek{margin-bottom:8px}.stage.svelte-1y3xro5{border:1px solid var(--border);border-radius:8px;flex:1;justify-content:center;align-items:center;min-height:0;display:flex;overflow:auto}.preview-column.svelte-1y3xro5{flex-direction:column;align-items:center;gap:8px;display:flex}.compare-row.svelte-1y3xro5{justify-content:center;align-items:flex-start;gap:16px;width:100%;max-width:760px;display:flex}figure.svelte-1y3xro5{flex-direction:column;flex:1 1 0;align-items:center;gap:6px;min-width:0;margin:0;display:flex}figcaption.svelte-1y3xro5{text-transform:uppercase;letter-spacing:.06em;color:var(--text-faint);font-size:10px}.video-frame.svelte-1y3xro5{width:100%}.video-frame.svelte-1y3xro5 video{width:100%;height:100%}p.svelte-1y3xro5{color:var(--text-dim)}section.svelte-3jblpy{border-bottom:1px solid var(--border-soft);padding:12px}.field.svelte-3jblpy{margin-bottom:8px}.backdrop.svelte-1f5yh58{z-index:100;background:#0000008c;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.dialog.svelte-1f5yh58{background:var(--panel);border:1px solid var(--border);border-radius:8px;width:360px;padding:16px;box-shadow:0 12px 32px #00000080}h2.svelte-1f5yh58{margin:0 0 4px;font-size:12px}.file-name.svelte-1f5yh58{color:var(--text-dim);font-variant-numeric:tabular-nums;margin:0}.destination.svelte-1f5yh58{color:var(--text-faint);margin:2px 0 16px}.row.svelte-1f5yh58{align-items:center;gap:8px;margin-bottom:8px;display:flex}.label.svelte-1f5yh58{width:64px;color:var(--text-dim);flex:none}.row.svelte-1f5yh58 input:where(.svelte-1f5yh58){flex:1}.row.manifests.svelte-1f5yh58{align-items:flex-start}.row.manifests.svelte-1f5yh58>.label:where(.svelte-1f5yh58){line-height:28px}.manifest-list.svelte-1f5yh58{flex:1;max-height:132px;overflow-y:auto}.empty-manifests.svelte-1f5yh58{color:var(--text-faint);margin:0;font-size:11px}.segmented.svelte-1f5yh58{border:1px solid var(--border);border-radius:var(--radius);display:inline-flex;overflow:hidden}.segmented.svelte-1f5yh58 button:where(.svelte-1f5yh58){background:var(--panel-raised);color:var(--text-dim);border:none;padding:4px 12px}.segmented.svelte-1f5yh58 button.on:where(.svelte-1f5yh58){background:var(--accent);color:var(--text)}.hint.svelte-1f5yh58{color:var(--text-dim);margin:4px 0 0;font-size:11px}.hint.warn.svelte-1f5yh58,.error.svelte-1f5yh58{color:var(--warning)}.actions.svelte-1f5yh58{justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.backdrop.svelte-n5o24b{z-index:100;background:#0000008c;justify-content:center;align-items:center;display:flex;position:fixed;inset:0}.dialog.svelte-n5o24b{border:1px solid var(--border);background:var(--panel);border-radius:8px;width:420px;padding:16px;box-shadow:0 12px 32px #00000080}h2.svelte-n5o24b{margin:0 0 4px;font-size:12px}.destination.svelte-n5o24b{color:var(--text-faint);margin:0 0 16px}.row.svelte-n5o24b{gap:12px;display:flex}.field.svelte-n5o24b{color:var(--text-dim);flex-direction:column;flex:1;gap:4px;margin-bottom:10px;display:flex}.field.wide.svelte-n5o24b{width:100%}.warning.svelte-n5o24b{color:var(--warning);margin:6px 0 0;font-size:11px}.actions.svelte-n5o24b{justify-content:flex-end;gap:8px;margin-top:16px;display:flex}.directory.svelte-ftwms1{background:var(--panel);border-right:1px solid var(--border);flex-direction:column;width:220px;min-width:180px;max-width:320px;min-height:0;display:flex}header.svelte-ftwms1{border-bottom:1px solid var(--border-soft);align-items:center;height:40px;padding:0 8px 0 12px;display:flex}header.svelte-ftwms1 strong:where(.svelte-ftwms1){font-size:11px}.actions.svelte-ftwms1{margin-left:auto;display:flex}.icon-button.svelte-ftwms1{width:24px;height:24px;color:var(--text-dim);border-radius:var(--radius-small);background:0 0;border:0}.icon-button.svelte-ftwms1:hover:not(:disabled){background:var(--panel-raised);color:var(--text)}.icon-button.danger.svelte-ftwms1:hover:not(:disabled){color:var(--danger)}.icon-button.svelte-ftwms1:disabled{opacity:.3;cursor:default}.tree.svelte-ftwms1{padding:6px 4px;overflow:auto}.folder-row.svelte-ftwms1,.asset-row.svelte-ftwms1{padding-left:calc((var(--depth) + 2) * 14px);display:flex}.row.svelte-ftwms1{color:var(--text-dim);border-radius:var(--radius-small);text-align:left;background:0 0;border:0;align-items:center;gap:6px;min-width:0;height:28px;display:flex}.row.special.svelte-ftwms1{width:100%;padding:0 8px}.row.folder.svelte-ftwms1{flex:1;padding:0 8px 0 2px}.row.asset.svelte-ftwms1{cursor:grab;flex:1;padding:0 8px 0 2px}.row.asset.svelte-ftwms1:active{cursor:grabbing}.row.svelte-ftwms1:hover,.row.selected.svelte-ftwms1{background:var(--panel-raised);color:var(--text)}.row.asset.current.svelte-ftwms1,.row.selected.svelte-ftwms1{background:var(--accent-soft);color:var(--accent)}.row.drop-target.svelte-ftwms1{outline:1px solid var(--accent);background:var(--accent-soft)}.glyph.svelte-ftwms1{width:14px;color:var(--text-faint);flex:none;justify-content:center;align-items:center;display:flex}.asset-glyph.svelte-ftwms1{font-size:7px}.asset-warning.svelte-ftwms1{color:var(--warning);flex:none;margin-left:auto}.label.svelte-ftwms1{white-space:nowrap;text-overflow:ellipsis;overflow:hidden}.count.svelte-ftwms1{color:var(--text-faint);margin-left:auto;font-size:10px}.dialog-row.svelte-ftwms1{align-items:center;gap:8px;display:flex}.dialog-row.svelte-ftwms1 span:where(.svelte-ftwms1){width:44px;color:var(--text-dim)}.dialog-row.svelte-ftwms1 input:where(.svelte-ftwms1){flex:1}.dialog-path.svelte-ftwms1,.dialog-text.svelte-ftwms1,.dialog-warning.svelte-ftwms1{margin:8px 0 0}.dialog-path.svelte-ftwms1{color:var(--text-faint)}.dialog-warning.svelte-ftwms1{color:var(--warning)}.context-menu.svelte-10jgqdh{z-index:200;background:var(--panel-raised);border:1px solid var(--border);border-radius:6px;width:168px;padding:4px;position:fixed;box-shadow:0 8px 24px #00000073}button.svelte-10jgqdh{width:100%;color:var(--text);font:inherit;text-align:left;background:0 0;border:0;border-radius:4px;padding:6px 8px}button.svelte-10jgqdh:hover,button.svelte-10jgqdh:focus-visible{background:var(--accent-soft);outline:none}button.danger.svelte-10jgqdh{color:var(--danger)}hr.svelte-10jgqdh{background:var(--border);border:0;height:1px;margin:4px 8px}
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{F as e,H as t,I as n,K as r,O as i,P as a,S as o,Y as s,_ as c,i as l,j as u,k as d,nt as f,q as p,rt as m,st as h,u as g}from"./BMORe2Gb.js";import"./xihTtKlq.js";function _(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} kB`:`${(e/(1024*1024)).toFixed(2)} MB`}function v(e){return`${(e/1e3).toFixed(2)} s`}function y(e,t){let{maxWidth:n,...r}=e;return t===null||!Number.isFinite(t)||t<=0?r:{...r,maxWidth:Math.round(t)}}function b(e,t){return e.defaultPrevented||e.isComposing||t.busy?null:e.key===`Escape`?`cancel`:e.key===`Enter`&&!t.confirmDisabled?`confirm`:null}function x(e){return e instanceof Element&&e.closest(`button, select, textarea, [contenteditable]:not([contenteditable="false"])`)!==null}function S(e,t){let n=b(e,t);n===null||n===`confirm`&&x(e.target)||(e.preventDefault(),e.stopPropagation(),n===`confirm`?t.onConfirm():t.onCancel())}var C=u(`<div class="backdrop svelte-oozc38" role="presentation"><div class="dialog svelte-oozc38" role="dialog" tabindex="-1"><h2 class="svelte-oozc38"> </h2> <!> <div class="actions svelte-oozc38"><button class="control">Cancel</button> <button> </button></div></div></div>`);function w(a,u){m(u,!0);let _=l(u,`danger`,3,!1),v=l(u,`confirmDisabled`,3,!1),y=l(u,`busy`,3,!1);var b=C();n(`keydown`,r,e=>S(e,{busy:y(),confirmDisabled:v(),onConfirm:u.onConfirm,onCancel:u.onCancel}));var x=p(b),w=p(x),T=p(w,!0);h(w);var E=s(w,2);o(E,()=>u.children);var D=s(E,2),O=p(D),k=s(O,2);let A;var j=p(k,!0);h(k),h(D),h(x),h(b),t(()=>{g(x,`aria-label`,u.title),i(T,u.title),O.disabled=y(),A=c(k,1,`control`,null,A,{primary:!_(),danger:_()}),k.disabled=v()||y(),i(j,u.confirmLabel)}),e(`click`,b,e=>{e.target===e.currentTarget&&!y()&&u.onCancel()}),e(`click`,O,function(...e){u.onCancel?.apply(this,e)}),e(`click`,k,function(...e){u.onConfirm?.apply(this,e)}),d(a,b),f()}a([`click`]);export{y as a,v as i,S as n,_ as r,w as t};
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{H as e,O as t,_ as n,i as r,j as i,k as a,q as o,st as s,u as c}from"./BMORe2Gb.js";import"./xihTtKlq.js";var l=i(`<span> </span>`);function u(i,u){let d=r(u,`overlay`,3,!1);var f=l();let p;var m=o(f,!0);s(f),e(()=>{c(f,`title`,u.title),p=n(f,1,`svelte-d2mzbr`,null,p,{edited:u.kind===`edited`,overlay:d()}),t(m,u.kind===`new`?`New`:`Edited`)}),a(i,f)}export{u as t};
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{D as e,H as t,L as n,Q as r,S as i,U as a,Y as o,Z as s,_ as c,a as l,i as u,j as d,k as f,nt as p,q as m,rt as h,st as g,u as _,y as v,z as y}from"./BMORe2Gb.js";import"./xihTtKlq.js";function b({anchor:e,panel:t,viewport:n,align:r,gap:i=6,padding:a=8}){let o=r===`right`?e.right-t.width:e.left,s=Math.max(a,n.width-t.width-a),c=Math.min(Math.max(o,a),s),l=e.bottom+i,u=e.top-i-t.height,d=Math.max(a,n.height-t.height-a),f=l+t.height>n.height-a&&u>=a?u:l;return{left:c,top:Math.min(Math.max(f,a),d)}}var x=d(`<div role="dialog"><!></div>`),S=d(`<div class="popover-anchor svelte-1rznwff"><!> <!></div>`);function C(d,C){h(C,!0);let w=u(C,`open`,15,!1),T=u(C,`align`,3,`left`),E=u(C,`portal`,3,!1),D=r(void 0),O=r(void 0),k=[`button:not([disabled])`,`[href]`,`input:not([disabled])`,`select:not([disabled])`,`textarea:not([disabled])`,`[tabindex]:not([tabindex="-1"])`].join(`,`);function A(){w(!w())}function j(e){if(!E())return{destroy(){}};document.body.append(e);let t=0;function r(){if(!n(D))return;let t=b({anchor:n(D).getBoundingClientRect(),panel:e.getBoundingClientRect(),viewport:{width:window.innerWidth,height:window.innerHeight},align:T()});e.style.left=`${t.left}px`,e.style.top=`${t.top}px`}return t=requestAnimationFrame(r),window.addEventListener(`resize`,r),window.addEventListener(`scroll`,r,!0),{destroy(){cancelAnimationFrame(t),window.removeEventListener(`resize`,r),window.removeEventListener(`scroll`,r,!0),e.remove()}}}a(()=>{if(!w())return;let e=n(D)?.querySelector(k);y().then(()=>{w()&&n(O)?.querySelector(k)?.focus()});function t(e){let t=e.target;!n(D)?.contains(t)&&!n(O)?.contains(t)&&w(!1)}function r(e){e.key===`Escape`&&w(!1)}return window.addEventListener(`pointerdown`,t,!0),window.addEventListener(`keydown`,r),()=>{window.removeEventListener(`pointerdown`,t,!0),window.removeEventListener(`keydown`,r),y().then(()=>{!w()&&e?.isConnected&&e.focus()})}});var M=S(),N=m(M);i(N,()=>C.trigger,()=>({toggle:A,open:w()}));var P=o(N,2),F=e=>{var r=x();let a;i(m(r),()=>C.children),g(r),l(r,e=>s(O,e),()=>n(O)),v(r,e=>j?.(e)),t(()=>{a=c(r,1,`popover svelte-1rznwff`,null,a,{floating:E(),right:T()===`right`}),_(r,`aria-label`,C.label)}),f(e,r)};e(P,e=>{w()&&e(F)}),g(M),l(M,e=>s(D,e),()=>n(D)),f(d,M),p()}export{C as t};
|
|
Binary file
|
|
Binary file
|