mirage-engine 0.2.17 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,282 +1,840 @@
1
- var k = Object.defineProperty;
2
- var q = (i, e, t) => e in i ? k(i, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : i[e] = t;
3
- var c = (i, e, t) => (q(i, typeof e != "symbol" ? e + "" : e, t), t);
4
- import * as d from "three";
5
- const S = 0, z = 1, L = 2, Y = 4, I = 8, N = 16, x = 1, R = 2, W = [
6
- "include-tree",
7
- "exclude-tree",
8
- "include-self",
9
- "exclude-self",
10
- "end"
11
- ];
12
- function U(i, e, t) {
13
- const r = e.split(`
14
- `), s = [];
15
- return r.forEach((a) => {
16
- const n = a.split(" ");
17
- let o = n[0];
18
- for (let l = 1; l < n.length; l++) {
19
- const h = n[l];
20
- i.measureText(o + " " + h).width < t ? o += " " + h : (s.push(o), o = h);
1
+ var Fe = Object.defineProperty, _e = Object.defineProperties;
2
+ var Xe = Object.getOwnPropertyDescriptors;
3
+ var Ce = Object.getOwnPropertySymbols;
4
+ var ze = Object.prototype.hasOwnProperty, Ne = Object.prototype.propertyIsEnumerable;
5
+ var ge = (s, e, t) => e in s ? Fe(s, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : s[e] = t, G = (s, e) => {
6
+ for (var t in e || (e = {}))
7
+ ze.call(e, t) && ge(s, t, e[t]);
8
+ if (Ce)
9
+ for (var t of Ce(e))
10
+ Ne.call(e, t) && ge(s, t, e[t]);
11
+ return s;
12
+ }, pe = (s, e) => _e(s, Xe(e));
13
+ var h = (s, e, t) => (ge(s, typeof e != "symbol" ? e + "" : e, t), t);
14
+ var we = (s, e, t) => new Promise((i, r) => {
15
+ var c = (o) => {
16
+ try {
17
+ a(t.next(o));
18
+ } catch (l) {
19
+ r(l);
21
20
  }
22
- s.push(o);
23
- }), s;
24
- }
25
- function A(i, e, t, r, s = 2) {
26
- const a = document.createElement("canvas"), n = a.getContext("2d");
27
- if (!n)
28
- throw new Error("[Mirage] Failed to create canvas context");
29
- const l = (window.devicePixelRatio || 1) * s;
30
- a.width = t * l, a.height = r * l, n.scale(l, l), n.font = e.font, n.fillStyle = e.color, n.textBaseline = "top", n.globalAlpha = 1;
31
- const h = U(n, i, t), m = e.lineHeight;
32
- h.forEach((g, p) => {
33
- const y = p * m + 2;
34
- let v = 0;
35
- e.textAlign === "center" ? v = t / 2 : e.textAlign === "right" && (v = t), n.textAlign = e.textAlign, n.fillText(g, v, y);
36
- });
37
- const f = new d.CanvasTexture(a);
38
- return f.colorSpace = d.SRGBColorSpace, f.minFilter = d.LinearFilter, f.magFilter = d.LinearFilter, f.needsUpdate = !0, f;
21
+ }, n = (o) => {
22
+ try {
23
+ a(t.throw(o));
24
+ } catch (l) {
25
+ r(l);
26
+ }
27
+ }, a = (o) => o.done ? i(o.value) : Promise.resolve(o.value).then(c, n);
28
+ a((t = t.apply(s, e)).next());
29
+ });
30
+ import * as b from "three";
31
+ const De = {
32
+ INCLUDE_TREE: "include-tree",
33
+ EXCLUDE_TREE: "exclude-tree",
34
+ INCLUDE_SELF: "include-self",
35
+ EXCLUDE_SELF: "exclude-self",
36
+ END: "end"
37
+ }, $ = {
38
+ NAME: "data-mirage-dom",
39
+ KEY: "mirageDom",
40
+ VALUES: {
41
+ HIDE: "hide"
42
+ }
43
+ }, Te = {
44
+ TRAVELER: "traveler",
45
+ NATIVE: "native",
46
+ CAPTURE_1: "1",
47
+ CAPTURE_2: "2",
48
+ CAPTURE_3: "3",
49
+ CAPTURE_4: "4",
50
+ CAPTURE_5: "5"
51
+ }, U = {
52
+ NAME: "data-mirage-travel",
53
+ KEY: "mirageTravel",
54
+ VALUES: Te,
55
+ MAX_LAYERS: Object.keys(Te).length - 1
56
+ }, N = {
57
+ NAME: "data-mirage-filter",
58
+ KEY: "mirageFilter",
59
+ VALUES: De
60
+ }, Y = {
61
+ NAME: "data-mirage-select",
62
+ KEY: "mirageSelect",
63
+ VALUES: De
64
+ }, Ye = {
65
+ NAME: "data-mirage-shader",
66
+ KEY: "mirageShader"
67
+ }, Se = {
68
+ NAME: "data-mirage-sandwich",
69
+ KEY: "mirageSandwich",
70
+ VALUES: {
71
+ FRONT: "front"
72
+ }
73
+ }, he = 0, j = 1, ae = 2, Ve = 4, ye = 8, be = 16;
74
+ function Pe(s) {
75
+ const e = s.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)/);
76
+ return e ? {
77
+ r: parseInt(e[1]) / 255,
78
+ g: parseInt(e[2]) / 255,
79
+ b: parseInt(e[3]) / 255
80
+ } : { r: 1, g: 1, b: 1 };
39
81
  }
40
- function w(i) {
41
- return typeof i == "number" ? i : parseFloat(i) || 0;
82
+ function We(s) {
83
+ const e = {};
84
+ if (s.opacity && (e.opacity = parseFloat(s.opacity)), s.backgroundColor && s.backgroundColor !== "rgba(0, 0, 0, 0)") {
85
+ const t = Pe(s.backgroundColor);
86
+ e.backgroundColor = [t.r, t.g, t.b];
87
+ }
88
+ if (s.backgroundImage ? e.backgroundImage = s.backgroundImage : s.background && (e.backgroundImage = s.background), s.borderRadius && (e.borderRadius = parseFloat(s.borderRadius)), s.width && (e.width = parseFloat(s.width)), s.height && (e.height = parseFloat(s.height)), s.transform && s.transform !== "none") {
89
+ const t = new DOMMatrix(s.transform);
90
+ e.x = t.m41, e.y = t.m42, e.z = t.m43;
91
+ }
92
+ return e;
42
93
  }
43
- function X(i, e) {
44
- var o, l, h, m;
45
- if (!e) {
46
- i.set(0, 0, 0, 0);
47
- return;
94
+ class Ae {
95
+ constructor(e, t) {
96
+ h(this, "target");
97
+ h(this, "observer");
98
+ h(this, "pendingDeletions", /* @__PURE__ */ new Set());
99
+ h(this, "pendingStyles", /* @__PURE__ */ new Map());
100
+ h(this, "isDomDirty", !1);
101
+ h(this, "isRunning", !1);
102
+ h(this, "pendingMask", he);
103
+ h(this, "mutationTimer", null);
104
+ h(this, "cssTimer", null);
105
+ h(this, "resizeConfig");
106
+ h(this, "resizeTimer", null);
107
+ h(this, "isResizing", !1);
108
+ h(this, "lastScrollX", 0);
109
+ h(this, "lastScrollY", 0);
110
+ h(this, "scrollTimer", null);
111
+ h(this, "onBeforeRender", /* @__PURE__ */ new Set());
112
+ h(this, "onLayoutChange", /* @__PURE__ */ new Set());
113
+ h(this, "onStyleChange", /* @__PURE__ */ new Set());
114
+ h(this, "onScrollChange", /* @__PURE__ */ new Set());
115
+ h(this, "onRender", /* @__PURE__ */ new Set());
116
+ h(this, "onTransitionFinished", (e) => {
117
+ this.target.contains(e.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.pendingStyles.size == 0 && (this.pendingMask |= j | ae, this.cssTimer = window.setTimeout(() => {
118
+ this.isDomDirty = !0, this.cssTimer = null;
119
+ }, 50)));
120
+ });
121
+ h(this, "onWindowResize", () => {
122
+ if (!this.resizeConfig.enabled) {
123
+ this.isDomDirty = !0;
124
+ return;
125
+ }
126
+ this.isResizing || (this.isResizing = !0, this.resizeConfig.onStart && this.resizeConfig.onStart()), this.resizeTimer && clearTimeout(this.resizeTimer), this.resizeTimer = window.setTimeout(() => {
127
+ this.isDomDirty = !0, this.resizeConfig.onEnd && this.resizeConfig.onEnd(), this.isResizing = !1, this.resizeTimer = null;
128
+ }, this.resizeConfig.delay);
129
+ });
130
+ h(this, "renderLoop", () => {
131
+ if (!this.isRunning)
132
+ return;
133
+ this.onBeforeRender.forEach((i) => i()), this.isDomDirty && (this.isDomDirty = !1, this.onLayoutChange.forEach((i) => i(this.pendingMask, this.pendingDeletions)), this.pendingDeletions.clear(), this.pendingMask = he);
134
+ const e = window.scrollX, t = window.scrollY;
135
+ (e !== this.lastScrollX || t !== this.lastScrollY) && (this.onScrollChange.forEach((i) => i(e, t)), this.lastScrollX = e, this.lastScrollY = t, this.scrollTimer && clearTimeout(this.scrollTimer), this.scrollTimer = window.setTimeout(() => {
136
+ this.pendingMask |= j, this.isDomDirty = !0, this.scrollTimer = null;
137
+ }, 150)), this.pendingStyles.size > 0 && (this.onStyleChange.forEach((i) => i(this.pendingStyles)), this.pendingStyles.clear()), this.onRender.forEach((i) => i()), requestAnimationFrame(this.renderLoop);
138
+ });
139
+ var r, c;
140
+ this.target = e;
141
+ const i = (r = t.resizeDebounce) != null ? r : !0;
142
+ i === !1 ? this.resizeConfig = { enabled: !1, delay: 0 } : i === !0 ? this.resizeConfig = { enabled: !0, delay: 150 } : this.resizeConfig = {
143
+ enabled: !0,
144
+ delay: (c = i.delay) != null ? c : 150,
145
+ onStart: i.onStart,
146
+ onEnd: i.onEnd
147
+ }, this.observer = new MutationObserver((n) => {
148
+ let a = he;
149
+ for (const o of n)
150
+ if (o.type === "childList")
151
+ a |= ye, o.removedNodes.length > 0 && o.removedNodes.forEach((l) => {
152
+ l instanceof HTMLElement && this.pendingDeletions.add(l);
153
+ });
154
+ else if (o.type === "attributes")
155
+ if (o.attributeName === "style") {
156
+ a |= j | ae;
157
+ const l = o.target, d = We(l.style);
158
+ this.pendingStyles.set(l, d);
159
+ } else
160
+ (o.attributeName === "class" || o.attributeName && o.attributeName.startsWith("data-")) && (a |= j | ae);
161
+ else
162
+ o.type === "characterData" && (a |= be | j);
163
+ if (a !== he) {
164
+ if (this.pendingMask |= a, a & ye) {
165
+ this.clearTimers(), this.isDomDirty = !0;
166
+ return;
167
+ }
168
+ this.mutationTimer && clearTimeout(this.mutationTimer), this.mutationTimer = window.setTimeout(() => {
169
+ this.mutationTimer = null, this.isDomDirty = !0;
170
+ }, 200);
171
+ }
172
+ });
48
173
  }
49
- const t = e.split("/")[0].trim().split(/\s+/), r = w(t[0]), s = w((o = t[1]) != null ? o : t[0]), a = w((l = t[2]) != null ? l : t[0]), n = w((m = (h = t[3]) != null ? h : t[1]) != null ? m : t[0]);
50
- i.set(r, s, a, n);
51
- }
52
- const H = (
53
- /* glsl */
54
- `
55
- varying vec2 vUv;
56
- varying vec4 vScreenPos;
57
- void main() {
58
- vUv = uv;
59
- gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
60
- vScreenPos = gl_Position;
61
- }
62
- `
63
- ), $ = (
64
- /* glsl */
65
- `
174
+ start() {
175
+ this.isRunning || (this.isRunning = !0, this.observer.observe(this.target, {
176
+ childList: !0,
177
+ subtree: !0,
178
+ attributes: !0,
179
+ characterData: !0
180
+ }), this.target.addEventListener("transitionend", this.onTransitionFinished), this.target.addEventListener("animationend", this.onTransitionFinished), window.addEventListener("resize", this.onWindowResize), this.isDomDirty = !0, this.lastScrollX = window.scrollX, this.lastScrollY = window.scrollY, this.renderLoop());
181
+ }
182
+ stop() {
183
+ this.isRunning = !1, this.observer.disconnect(), this.clearTimers(), this.target.removeEventListener("transitionend", this.onTransitionFinished), this.target.removeEventListener("animationend", this.onTransitionFinished), window.removeEventListener("resize", this.onWindowResize);
184
+ }
185
+ clearTimers() {
186
+ this.mutationTimer && (clearTimeout(this.mutationTimer), this.mutationTimer = null), this.cssTimer && (clearTimeout(this.cssTimer), this.cssTimer = null), this.scrollTimer && (clearTimeout(this.scrollTimer), this.scrollTimer = null);
187
+ }
188
+ }
189
+ const V = 1, Z = 2, A = {
190
+ BASE: 0,
191
+ SELECTED: 1,
192
+ getCaptureLayer: (s) => 31 - s,
193
+ HIDDEN: 31
194
+ }, Le = Object.values(N.VALUES);
195
+ class ke {
196
+ /**
197
+ * Calculates or retrieves the exact alphabetic baseline (in pixels) for the given font.
198
+ * @param font CSS font shorthand string (e.g., "400 16px Inter")
199
+ * @returns Baseline Y offset in pixels
200
+ */
201
+ static getBaseline(e) {
202
+ if (this.cache.has(e))
203
+ return this.cache.get(e);
204
+ const t = this.calculateBaselineFromDOM(e);
205
+ return this.cache.set(e, t), t;
206
+ }
207
+ static calculateBaselineFromDOM(e) {
208
+ if (typeof document == "undefined")
209
+ return 0;
210
+ const t = document.createElement("div"), i = document.createElement("span"), r = document.createElement("img");
211
+ t.style.visibility = "hidden", t.style.position = "absolute", t.style.top = "0px", t.style.left = "0px", t.style.font = e, t.style.margin = "0", t.style.padding = "0", t.style.border = "none", i.style.margin = "0", i.style.padding = "0", i.style.border = "none", i.style.lineHeight = "normal", r.width = 1, r.height = 1, r.style.verticalAlign = "baseline", i.appendChild(document.createTextNode("Hidden Text")), t.appendChild(i), t.appendChild(r), document.body.appendChild(t);
212
+ const c = r.offsetTop - i.offsetTop;
213
+ return document.body.removeChild(t), c;
214
+ }
215
+ }
216
+ h(ke, "cache", /* @__PURE__ */ new Map());
217
+ class He extends b.MeshBasicMaterial {
218
+ constructor(t, i, r, c, n = 2) {
219
+ super({
220
+ transparent: !0,
221
+ side: b.FrontSide,
222
+ color: 16777215
223
+ });
224
+ h(this, "canvas");
225
+ h(this, "ctx");
226
+ h(this, "qualityFactor");
227
+ if (this.canvas = document.createElement("canvas"), this.ctx = this.canvas.getContext("2d"), !this.ctx)
228
+ throw new Error("[Mirage] Failed to create canvas context");
229
+ this.qualityFactor = n, this.map = new b.CanvasTexture(this.canvas), this.map.colorSpace = b.LinearSRGBColorSpace, this.map.minFilter = b.LinearFilter, this.map.magFilter = b.LinearFilter, this.updateText(t, i, r, c);
230
+ }
231
+ wrapText(t, i) {
232
+ const r = t.split(`
233
+ `), c = [];
234
+ return r.forEach((n) => {
235
+ const a = n.match(/[^\s\-]+\-?|\-|\s+/g) || [];
236
+ if (a.length === 0) {
237
+ c.push("");
238
+ return;
239
+ }
240
+ let o = a[0];
241
+ for (let l = 1; l < a.length; l++) {
242
+ const d = a[l];
243
+ this.ctx.measureText(o + d).width <= i + 2 ? o += d : (o && c.push(o), o = d.trimStart());
244
+ }
245
+ o && c.push(o);
246
+ }), c;
247
+ }
248
+ updateText(t, i, r, c, n) {
249
+ n !== void 0 && (this.qualityFactor = n);
250
+ const o = (window.devicePixelRatio || 1) * this.qualityFactor, l = r * o, d = c * o;
251
+ this.canvas.width !== l || this.canvas.height !== d ? (this.canvas.width = l, this.canvas.height = d) : this.ctx.clearRect(0, 0, this.canvas.width, this.canvas.height), this.ctx.setTransform(o, 0, 0, o, 0, 0), this.ctx.font = i.font, this.ctx.fillStyle = i.color, this.ctx.textBaseline = "alphabetic", this.ctx.globalAlpha = 1;
252
+ const f = this.wrapText(t, r), y = i.lineHeight, p = ke.getBaseline(i.font);
253
+ f.forEach((u, g) => {
254
+ const w = g * y + p;
255
+ let R = 0;
256
+ i.textAlign === "center" ? R = r / 2 : i.textAlign === "right" && (R = r), this.ctx.textAlign = i.textAlign, this.ctx.fillText(u, R, w);
257
+ }), this.map && (this.map.needsUpdate = !0);
258
+ }
259
+ dispose() {
260
+ this.map && this.map.dispose(), super.dispose();
261
+ }
262
+ }
263
+ function ee(s) {
264
+ return typeof s == "number" ? s : parseFloat(s) || 0;
265
+ }
266
+ function ce(s) {
267
+ if (!s || s === "transparent")
268
+ return { color: new b.Color(16777215), alpha: 0 };
269
+ const e = s.match(
270
+ /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/
271
+ );
272
+ if (e) {
273
+ const t = parseInt(e[1], 10), i = parseInt(e[2], 10), r = parseInt(e[3], 10), c = e[4] !== void 0 ? parseFloat(e[4]) : 1;
274
+ return { color: new b.Color(`rgb(${t}, ${i}, ${r})`), alpha: c };
275
+ }
276
+ return { color: new b.Color(s), alpha: 1 };
277
+ }
278
+ function Ge(s) {
279
+ const e = [];
280
+ let t = "", i = 0;
281
+ for (let r = 0; r < s.length; r++) {
282
+ const c = s[r];
283
+ if (c === "(")
284
+ i++;
285
+ else if (c === ")")
286
+ i--;
287
+ else if (c === "," && i === 0) {
288
+ e.push(t.trim()), t = "";
289
+ continue;
290
+ }
291
+ t += c;
292
+ }
293
+ return t && e.push(t.trim()), e;
294
+ }
295
+ function $e(s) {
296
+ if (!s || typeof s != "string" || !s.includes("linear-gradient"))
297
+ return null;
298
+ const e = s.match(/linear-gradient\((.*)\)/);
299
+ if (!e)
300
+ return null;
301
+ const t = e[1], i = Ge(t);
302
+ let r = Math.PI, c = 0;
303
+ const n = i[0].trim();
304
+ if (n.startsWith("to "))
305
+ n === "to top" ? r = 0 : n === "to right" ? r = Math.PI / 2 : n === "to bottom" ? r = Math.PI : n === "to left" ? r = Math.PI * 1.5 : n === "to top right" || n === "to right top" ? r = Math.PI / 4 : n === "to bottom right" || n === "to right bottom" ? r = Math.PI * 0.75 : n === "to bottom left" || n === "to left bottom" ? r = Math.PI * 1.25 : (n === "to top left" || n === "to left top") && (r = Math.PI * 1.75), c = 1;
306
+ else if (n.endsWith("deg") || n.endsWith("rad") || n.endsWith("turn")) {
307
+ const o = parseFloat(n);
308
+ n.endsWith("deg") ? r = o * (Math.PI / 180) : n.endsWith("rad") ? r = o : n.endsWith("turn") && (r = o * Math.PI * 2), c = 1;
309
+ }
310
+ const a = [];
311
+ for (let o = c; o < i.length && !(a.length >= 8); o++) {
312
+ const l = i[o].trim(), d = l.lastIndexOf(" ");
313
+ let f = l, y = null;
314
+ if (d !== -1 && !l.endsWith(")")) {
315
+ const u = l.substring(d + 1);
316
+ (u.endsWith("%") || u.endsWith("px") || !isNaN(parseFloat(u))) && (f = l.substring(0, d).trim(), y = u);
317
+ }
318
+ const p = ce(f);
319
+ a.push({
320
+ color: p.color,
321
+ alpha: p.alpha,
322
+ rawStop: y,
323
+ stop: 0
324
+ });
325
+ }
326
+ if (a.length > 0) {
327
+ for (let l = 0; l < a.length; l++)
328
+ a[l].rawStop !== null && (a[l].stop = parseFloat(a[l].rawStop) / 100);
329
+ a[0].rawStop === null && (a[0].stop = 0), a.length > 1 && a[a.length - 1].rawStop === null && (a[a.length - 1].stop = 1);
330
+ let o = 0;
331
+ for (let l = 1; l < a.length; l++)
332
+ if (a[l].rawStop !== null || l === a.length - 1) {
333
+ const d = l - o;
334
+ if (d > 1) {
335
+ const f = a[o].stop, p = (a[l].stop - f) / d;
336
+ for (let u = 1; u < d; u++)
337
+ a[o + u].stop = f + p * u;
338
+ }
339
+ o = l;
340
+ }
341
+ }
342
+ return { angle: r, stops: a };
343
+ }
344
+ const qe = `varying vec2 vUv;
345
+ varying vec4 vScreenPos;
346
+ void main() {
347
+ vUv = uv;
348
+ gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
349
+ vScreenPos = gl_Position;
350
+ }`, je = `varying vec2 vUv;
351
+ uniform vec2 uSize;
352
+ uniform vec4 uBorderRadius;
353
+ uniform float uBorderWidth;
354
+ uniform vec4 uBgColor;
355
+ uniform vec4 uBorderColor;
356
+ uniform float uOpacity;
357
+
358
+ uniform int uGradientCount;
359
+ uniform float uGradientAngle;
360
+ uniform vec4 uGradientColors[8];
361
+ uniform float uGradientStops[8];
362
+
363
+ #INJECT_DECLARATIONS
364
+
365
+ vec3 linearToSrgb(vec3 linearColor) {
366
+ vec3 linearPart = 12.92 * linearColor;
367
+ vec3 curvePart = 1.055 * pow(linearColor, vec3(1.0 / 2.4)) - 0.055;
368
+ vec3 switchCondition = step(vec3(0.0031308), linearColor);
369
+ return mix(linearPart, curvePart, switchCondition);
370
+ }
371
+
372
+ vec3 srgbToLinear(vec3 srgbColor) {
373
+ vec3 linearPart = srgbColor / 12.92;
374
+ vec3 curvePart = pow((srgbColor + vec3(0.055)) / 1.055, vec3(2.4));
375
+ vec3 switchCondition = step(vec3(0.04045), srgbColor);
376
+ return mix(linearPart, curvePart, switchCondition);
377
+ }
378
+
379
+ vec4 blendSrcOverInLinear(vec4 front, vec4 back) {
380
+ front.rgb = srgbToLinear(front.rgb);
381
+ back.rgb = srgbToLinear(back.rgb);
382
+ float aOut = front.a + back.a * (1.0 - front.a);
383
+ float safeAlpha = max(aOut, 0.0001);
384
+ vec3 cOut = (front.rgb * front.a + back.rgb * back.a * (1.0 - front.a)) / safeAlpha;
385
+ return vec4(linearToSrgb(cOut), aOut);
386
+ }
387
+
388
+ vec4 blendSrcOver(vec4 front, vec4 back) {
389
+ float aOut = front.a + back.a * (1.0 - front.a);
390
+ float safeAlpha = max(aOut, 0.0001);
391
+ vec3 cOut = (front.rgb * front.a + back.rgb * back.a * (1.0 - front.a)) / safeAlpha;
392
+ return vec4(cOut, aOut);
393
+ }
394
+
395
+ float sdRoundedBox(vec2 p, vec2 b, float r) {
396
+ vec2 q = abs(p) - b + r;
397
+ return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
398
+ }
66
399
 
67
- varying vec2 vUv;
400
+ float sdVisualBox(vec2 p, vec2 b, float r) {
401
+ vec2 q = abs(p) - b + r;
402
+ float n = 2.01;
403
+ float d = pow(pow(max(q.x, 0.0), n) + pow(max(q.y, 0.0), n), 1.0/n) - r;
404
+ return min(max(q.x, q.y), 0.0) + d;
405
+ }
406
+
407
+ vec4 calculateGradientLayer(vec2 uv) {
408
+ if (uGradientCount < 2) return uGradientColors[0];
409
+
410
+ vec2 dir = vec2(sin(uGradientAngle), cos(uGradientAngle));
411
+ vec2 p = (uv - 0.5) * uSize;
412
+ float proj = dot(p, dir);
413
+ float L = abs(uSize.x * dir.x) + abs(uSize.y * dir.y);
414
+ float t = clamp((proj / L) + 0.5, 0.0, 1.0);
68
415
 
69
- uniform vec2 uSize;
70
- uniform vec4 uBorderRadius;
71
- uniform float uBorderWidth;
72
- uniform vec3 uBgColor;
73
- uniform vec3 uBorderColor;
74
- uniform float uOpacity;
75
- uniform float uBgOpacity;
76
- uniform float uBorderOpacity;
416
+ vec4 color = uGradientColors[0];
417
+ for (int i = 1; i < 8; i++) {
418
+ if (i >= uGradientCount) break;
419
+ float prevStop = uGradientStops[i-1];
420
+ float currStop = uGradientStops[i];
421
+
422
+ float factor = clamp((t - prevStop) / (currStop - prevStop + 0.00001), 0.0, 1.0);
423
+ color = mix(color, uGradientColors[i], factor);
424
+ }
425
+ // return vec4(linearToSrgb(color.rgb), color.a);
426
+ return vec4(color);
427
+ }
428
+
429
+ void main() {
430
+ vec2 p = (vUv - 0.5) * uSize;
431
+ vec2 halfSize = uSize * 0.5;
77
432
 
78
- #INJECT_DECLARATIONS
433
+ #INJECT_UV_MODIFIER
79
434
 
80
- float sdRoundedBox(vec2 p, vec2 b, float r) {
81
- vec2 q = abs(p) - b + r;
435
+ // color decision pipeline
436
+ vec4 baseColor = vec4(uBgColor.rgb, uBgColor.a);
82
437
 
83
- return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
438
+ if (uGradientCount > 0) {
439
+ vec4 gradColor = calculateGradientLayer(vUv);
440
+ baseColor = blendSrcOver(gradColor, baseColor);
84
441
  }
85
442
 
86
- void main() {
87
- vec2 p = (vUv - 0.5) * uSize;
88
- vec2 halfSize = uSize * 0.5;
443
+ #INJECT_BASE_COLOR
89
444
 
90
- #INJECT_UV_MODIFIER
91
-
92
- // color decision pipeline
93
- vec4 baseColor = vec4(uBgColor, uBgOpacity);
445
+ // Hybrid SDF
446
+ vec2 xRadii = mix(uBorderRadius.xw, uBorderRadius.yz, step(0.0, p.x));
447
+ float r = mix(xRadii.y, xRadii.x, step(0.0, p.y));
448
+ r = min(r, min(halfSize.x, halfSize.y));
94
449
 
95
- #INJECT_BASE_COLOR
450
+ float d = sdRoundedBox(p, halfSize, r);
96
451
 
97
- // sdf shape pipeline
98
- vec2 xRadii = mix(uBorderRadius.xw, uBorderRadius.yz, step(0.0, p.x));
99
- float r = mix(xRadii.y, xRadii.x, step(0.0, p.y));
100
- float d = sdRoundedBox(p, halfSize, r);
452
+ float d_smooth = sdVisualBox(p, halfSize, r);
453
+ float d_visual = d_smooth / fwidth(d_smooth);
101
454
 
102
- float aa = 1.0;
103
- float bgMask = 1.0 - smoothstep(0.0, aa, d);
455
+ // rendering pipeline
456
+ float bgMask = 1.0 - smoothstep(-0.5, 0.5, d_visual);
104
457
 
105
- float halfBorder = uBorderWidth * 0.5;
106
- float borderD = abs(d + halfBorder) - halfBorder;
107
- float borderAlpha = (1.0 - smoothstep(0.0, aa, borderD)) * uBorderOpacity;
108
- if (uBorderWidth <= 0.01) {
109
- borderAlpha = 0.0;
110
- }
458
+ float halfBorder = uBorderWidth * 0.5;
459
+ float borderD = abs(d + halfBorder) - halfBorder;
460
+ float borderAlpha = (1.0 - smoothstep(0.0, 1.0, borderD)) * uBorderColor.a;
461
+ if (uBorderWidth <= 0.01) {
462
+ borderAlpha = 0.0;
463
+ }
111
464
 
112
- // final blending (border + background)
113
- float aFront = borderAlpha;
114
- float aBack = baseColor.a;
115
- float aOut = aFront + aBack * (1.0 - aFront);
465
+ // final blending (border + background) using blendSrcOver
466
+ vec4 borderLayer = vec4(uBorderColor.rgb, borderAlpha);
467
+ vec4 finalColor = blendSrcOver(borderLayer, baseColor);
468
+ // final color control (Tint, Noise)
469
+ #INJECT_COLOR_MODIFIER
116
470
 
117
- float safeAlpha = max(aOut, 0.0001);
118
- vec3 cOut = (uBorderColor * aFront + baseColor.rgb * aBack * (1.0 - aFront)) / safeAlpha;
119
- vec4 finalColor = vec4(cOut, aOut);
471
+ float finalOpacity = finalColor.a * bgMask * uOpacity;
472
+ if (finalOpacity < 0.001) discard;
120
473
 
121
- // final color control (Tint, Noise)
122
- #INJECT_COLOR_MODIFIER
474
+ gl_FragColor = vec4(finalColor.rgb, finalOpacity);
123
475
 
124
- float finalOpacity = finalColor.a * bgMask * uOpacity;
125
- if (finalOpacity < 0.001) discard;
126
476
 
127
- gl_FragColor = vec4(finalColor.rgb, finalOpacity);
477
+ // #include <colorspace_fragment>
478
+ }
479
+ `, Ke = `uniform sampler2D uTexture;
480
+ varying vec4 vScreenPos;
481
+ uniform vec2 uTextureRepeat;
482
+ uniform vec2 uTextureOffset;`, Je = `vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
483
+ vec2 resultUv = screenUv;
128
484
 
129
- #include <colorspace_fragment>
130
- }
131
- `
132
- );
133
- function E(i) {
134
- if (!i || i === "transparent")
135
- return { color: new d.Color(16777215), alpha: 0 };
136
- const e = i.match(
137
- /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/
138
- );
139
- if (e) {
140
- const t = parseInt(e[1], 10), r = parseInt(e[2], 10), s = parseInt(e[3], 10), a = e[4] !== void 0 ? parseFloat(e[4]) : 1;
141
- return { color: new d.Color(`rgb(${t}, ${r}, ${s})`), alpha: a };
142
- }
143
- return { color: new d.Color(i), alpha: 1 };
144
- }
145
- function G(i, e, t, r = null, s) {
146
- var v;
147
- const a = r !== null, n = a ? (
148
- /* glsl */
149
- `
150
- uniform sampler2D uTexture;
151
- varying vec4 vScreenPos;
152
- `
153
- ) : "", o = a ? (
154
- /* glsl */
155
- `
156
- vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
157
- vec2 resultUv = screenUv;
158
- ${(s == null ? void 0 : s.uvModifier) || ""}
159
- `
160
- ) : "", l = a ? (
161
- /* glsl */
162
- `
163
- baseColor = texture2D(uTexture, resultUv);
164
- `
165
- ) : "", h = (s == null ? void 0 : s.colorModifier) || "", m = $.replace("#INJECT_DECLARATIONS", n).replace("#INJECT_UV_MODIFIER", o).replace("#INJECT_BASE_COLOR", l).replace("#INJECT_COLOR_MODIFIER", h), f = E(i.backgroundColor), g = E(i.borderColor), p = {
166
- uSize: { value: new d.Vector2(e, t) },
167
- uBorderRadius: { value: new d.Vector4(0, 0, 0, 0) },
168
- uBorderWidth: { value: w(i.borderWidth) },
169
- uBgColor: { value: f.color },
170
- uBorderColor: { value: g.color },
171
- uOpacity: { value: (v = i.opacity) != null ? v : 1 },
172
- uBgOpacity: { value: f.alpha },
173
- uBorderOpacity: { value: g.alpha },
174
- uTexture: { value: null }
485
+ `, Qe = `vec4 texColor = texture2D(uTexture, resultUv);
486
+ baseColor = blendSrcOver(baseColor, texColor);`, Re = {
487
+ vertexShader: qe,
488
+ fragmentShader: je
489
+ }, me = {
490
+ declChunk: Ke,
491
+ uvChunk: Je,
492
+ baseColorChunk: Qe
493
+ };
494
+ function Ze(s, e, t, i = null, r) {
495
+ var L;
496
+ const c = i !== null || !!s.imageSrc;
497
+ let n = "";
498
+ const a = {};
499
+ if (r != null && r.uniforms)
500
+ for (const [E, x] of Object.entries(r.uniforms))
501
+ typeof x == "number" ? (n += `uniform float ${E};
502
+ `, a[E] = { value: x }) : Array.isArray(x) ? x.length === 2 ? (n += `uniform vec2 ${E};
503
+ `, a[E] = { value: new b.Vector2(...x) }) : x.length === 3 ? (n += `uniform vec3 ${E};
504
+ `, a[E] = { value: new b.Vector3(...x) }) : x.length === 4 && (n += `uniform vec4 ${E};
505
+ `, a[E] = { value: new b.Vector4(...x) }) : (n += `uniform float ${E};
506
+ `, a[E] = { value: x });
507
+ const o = (c ? me.declChunk : "") + `
508
+ ` + n, l = s.isTraveler ? me.uvChunk : `vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
509
+ `, d = c ? l + ((r == null ? void 0 : r.uvModifier) || "") : "", f = c ? me.baseColorChunk : "", y = (r == null ? void 0 : r.colorModifier) || "", p = Re.fragmentShader.replace("#INJECT_DECLARATIONS", o).replace("#INJECT_UV_MODIFIER", d).replace("#INJECT_BASE_COLOR", f).replace("#INJECT_COLOR_MODIFIER", y), u = ce(s.backgroundColor), g = ce(s.borderColor), w = {
510
+ uSize: { value: new b.Vector2(e, t) },
511
+ uBgColor: {
512
+ value: new b.Vector4(
513
+ u.color.r,
514
+ u.color.g,
515
+ u.color.b,
516
+ u.alpha
517
+ )
518
+ },
519
+ uBorderColor: {
520
+ value: new b.Vector4(
521
+ g.color.r,
522
+ g.color.g,
523
+ g.color.b,
524
+ g.alpha
525
+ )
526
+ },
527
+ uBorderRadius: { value: new b.Vector4(0, 0, 0, 0) },
528
+ uBorderWidth: { value: ee(s.borderWidth) },
529
+ uOpacity: { value: (L = s.opacity) != null ? L : 1 },
530
+ uTexture: { value: null },
531
+ uTextureRepeat: { value: new b.Vector2(1, 1) },
532
+ uTextureOffset: { value: new b.Vector2(0, 0) },
533
+ uGradientCount: { value: 0 },
534
+ uGradientAngle: { value: 0 },
535
+ uGradientColors: {
536
+ value: Array.from({ length: 8 }, () => new b.Vector4(0, 0, 0, 0))
537
+ },
538
+ uGradientStops: { value: new Float32Array(8) }
175
539
  };
176
- return X(p.uBorderRadius.value, i.borderRadius), a && (p.uTexture.value = r), new d.ShaderMaterial({
177
- uniforms: p,
178
- vertexShader: H,
179
- fragmentShader: m,
540
+ Ie(w.uBorderRadius.value, s.borderRadius), c && (w.uTexture.value = i);
541
+ const R = new b.ShaderMaterial({
542
+ uniforms: G(G({}, w), a),
543
+ vertexShader: Re.vertexShader,
544
+ fragmentShader: p,
180
545
  transparent: !0,
181
- side: d.FrontSide
546
+ side: b.FrontSide
182
547
  // for better performance
183
548
  });
549
+ return s.backgroundImage && ve(R, { backgroundImage: s.backgroundImage }), R;
184
550
  }
185
- function J(i, e, t, r, s) {
186
- var o;
187
- const a = E(e.backgroundColor), n = E(e.borderColor);
188
- i.uniforms.uSize.value.set(t, r), X(i.uniforms.uBorderRadius.value, e.borderRadius), i.uniforms.uBorderWidth.value = w(e.borderWidth), i.uniforms.uBgColor.value.copy(a.color), i.uniforms.uBorderColor.value.copy(n.color), i.uniforms.uOpacity.value = (o = e.opacity) != null ? o : 1, i.uniforms.uBgOpacity.value = a.alpha, i.uniforms.uBorderOpacity.value = n.alpha, i.uniforms.uTexture && s !== void 0 && (i.uniforms.uTexture.value = s);
189
- }
190
- const D = {
191
- create(i, e, t, r, s, a = 2, n = null, o) {
192
- if (i === "BOX")
193
- return G(e, r, s, n, o);
194
- if (i === "TEXT") {
195
- const l = A(
196
- t || "",
197
- e,
198
- r,
199
- s,
200
- a
551
+ function et(s, e, t, i, r) {
552
+ const c = ee(e.borderWidth);
553
+ ve(s, {
554
+ width: t,
555
+ height: i,
556
+ borderRadius: e.borderRadius,
557
+ borderWidth: c,
558
+ backgroundColor: e.backgroundColor,
559
+ borderColor: e.borderColor,
560
+ opacity: e.opacity,
561
+ texture: r,
562
+ backgroundImage: e.backgroundImage
563
+ });
564
+ }
565
+ function ve(s, e) {
566
+ var i, r, c;
567
+ if (e.width !== void 0 && e.height !== void 0 && s.uniforms.uSize.value.set(e.width, e.height), e.borderRadius !== void 0 && Ie(s.uniforms.uBorderRadius.value, e.borderRadius), e.borderWidth !== void 0 && (s.uniforms.uBorderWidth.value = e.borderWidth), e.backgroundColor !== void 0)
568
+ if (Array.isArray(e.backgroundColor)) {
569
+ const n = s.uniforms.uBgColor.value.w;
570
+ s.uniforms.uBgColor.value.set(
571
+ e.backgroundColor[0],
572
+ e.backgroundColor[1],
573
+ e.backgroundColor[2],
574
+ n
575
+ );
576
+ } else if (typeof e.backgroundColor == "string") {
577
+ const n = ce(e.backgroundColor);
578
+ s.uniforms.uBgColor.value.set(
579
+ n.color.r,
580
+ n.color.g,
581
+ n.color.b,
582
+ n.alpha
583
+ );
584
+ } else {
585
+ const n = s.uniforms.uBgColor.value.w;
586
+ s.uniforms.uBgColor.value.set(
587
+ e.backgroundColor.r,
588
+ e.backgroundColor.g,
589
+ e.backgroundColor.b,
590
+ n
201
591
  );
202
- return new d.MeshBasicMaterial({
203
- map: l,
204
- transparent: !0,
205
- side: d.FrontSide,
206
- color: 16777215
207
- });
208
592
  }
209
- return new d.MeshBasicMaterial({ visible: !1 });
210
- },
211
- update(i, e, t, r, s, a, n = 2, o) {
212
- if (e === "BOX")
213
- J(
214
- i,
215
- t,
216
- s,
217
- a,
218
- o
593
+ if (e.borderColor !== void 0)
594
+ if (Array.isArray(e.borderColor)) {
595
+ const n = s.uniforms.uBorderColor.value.w;
596
+ s.uniforms.uBorderColor.value.set(
597
+ e.borderColor[0],
598
+ e.borderColor[1],
599
+ e.borderColor[2],
600
+ n
219
601
  );
220
- else if (e === "TEXT") {
221
- const l = i;
222
- l.map && l.map.dispose();
223
- const h = A(
224
- r || "",
225
- t,
226
- s,
227
- a,
602
+ } else if (typeof e.borderColor == "string") {
603
+ const n = ce(e.borderColor);
604
+ s.uniforms.uBorderColor.value.set(
605
+ n.color.r,
606
+ n.color.g,
607
+ n.color.b,
608
+ n.alpha
609
+ );
610
+ } else {
611
+ const n = s.uniforms.uBorderColor.value.w;
612
+ s.uniforms.uBorderColor.value.set(
613
+ e.borderColor.r,
614
+ e.borderColor.g,
615
+ e.borderColor.b,
228
616
  n
229
617
  );
230
- l.map = h, l.needsUpdate = !0;
231
618
  }
619
+ e.opacity !== void 0 && (s.uniforms.uOpacity.value = e.opacity), e.bgOpacity !== void 0 && (s.uniforms.uBgColor.value.w = e.bgOpacity), e.borderOpacity !== void 0 && (s.uniforms.uBorderColor.value.w = e.borderOpacity), s.uniforms.uTexture && e.texture !== void 0 && (s.uniforms.uTexture.value = e.texture);
620
+ const t = e.texture !== void 0 ? e.texture : (i = s.uniforms.uTexture) == null ? void 0 : i.value;
621
+ if (t && (t.image instanceof ImageBitmap || t.image instanceof HTMLImageElement || t.image instanceof HTMLCanvasElement)) {
622
+ const n = t.image.width, a = t.image.height, o = (r = e.width) != null ? r : s.uniforms.uSize.value.x, l = (c = e.height) != null ? c : s.uniforms.uSize.value.y;
623
+ if (n && a && o && l) {
624
+ const d = n / a, f = o / l;
625
+ if (d > f) {
626
+ const y = f / d;
627
+ s.uniforms.uTextureRepeat.value.set(y, 1), s.uniforms.uTextureOffset.value.set((1 - y) / 2, 0);
628
+ } else {
629
+ const y = d / f;
630
+ s.uniforms.uTextureRepeat.value.set(1, y), s.uniforms.uTextureOffset.value.set(0, (1 - y) / 2);
631
+ }
632
+ }
633
+ } else
634
+ s.uniforms.uTextureRepeat && (s.uniforms.uTextureRepeat.value.set(1, 1), s.uniforms.uTextureOffset.value.set(0, 0));
635
+ if (e.backgroundImage !== void 0) {
636
+ const n = $e(e.backgroundImage);
637
+ if (n) {
638
+ s.uniforms.uGradientCount.value = n.stops.length, s.uniforms.uGradientAngle.value = n.angle;
639
+ for (let a = 0; a < 8; a++)
640
+ if (a < n.stops.length) {
641
+ const o = n.stops[a];
642
+ s.uniforms.uGradientColors.value[a].set(
643
+ o.color.r,
644
+ o.color.g,
645
+ o.color.b,
646
+ o.alpha
647
+ ), s.uniforms.uGradientStops.value[a] = o.stop;
648
+ } else
649
+ s.uniforms.uGradientColors.value[a].set(0, 0, 0, 0), s.uniforms.uGradientStops.value[a] = 1;
650
+ } else
651
+ s.uniforms.uGradientCount.value = 0;
652
+ }
653
+ for (const n of Object.keys(e))
654
+ n !== "width" && n !== "height" && n !== "borderRadius" && n !== "borderWidth" && n !== "backgroundColor" && n !== "borderColor" && n !== "opacity" && n !== "bgOpacity" && n !== "borderOpacity" && n !== "texture" && n !== "backgroundImage" && s.uniforms[n] !== void 0 && (s.uniforms[n].value !== void 0 && s.uniforms[n].value !== null && typeof s.uniforms[n].value.set == "function" ? Array.isArray(e[n]) ? s.uniforms[n].value.set(...e[n]) : e[n] !== void 0 && (e[n].copy ? s.uniforms[n].value.copy(e[n]) : s.uniforms[n].value = e[n]) : s.uniforms[n].value = e[n]);
655
+ }
656
+ function Ie(s, e) {
657
+ var a, o, l, d;
658
+ if (e == null) {
659
+ s.set(0, 0, 0, 0);
660
+ return;
661
+ }
662
+ if (typeof e == "number") {
663
+ s.set(e, e, e, e);
664
+ return;
665
+ }
666
+ if (Array.isArray(e)) {
667
+ s.set(e[0], e[1], e[2], e[3]);
668
+ return;
669
+ }
670
+ const t = e.split("/")[0].trim().split(/\s+/), i = ee(t[0]), r = ee((a = t[1]) != null ? a : t[0]), c = ee((o = t[2]) != null ? o : t[0]), n = ee((d = (l = t[3]) != null ? l : t[1]) != null ? d : t[0]);
671
+ s.set(i, r, c, n);
672
+ }
673
+ const H = {
674
+ create(s, e, t, i, r, c = 2, n = null, a) {
675
+ return s === "BOX" ? Ze(
676
+ e,
677
+ i,
678
+ r,
679
+ n,
680
+ a
681
+ ) : s === "TEXT" ? new He(
682
+ t || "",
683
+ e,
684
+ i,
685
+ r,
686
+ c
687
+ ) : new b.MeshBasicMaterial({ visible: !1 });
688
+ },
689
+ update(s, e, t, i, r, c, n = 2, a) {
690
+ e === "BOX" ? et(
691
+ s,
692
+ t,
693
+ r,
694
+ c,
695
+ a
696
+ ) : e === "TEXT" && s.updateText(
697
+ i || "",
698
+ t,
699
+ r,
700
+ c,
701
+ n
702
+ );
703
+ },
704
+ forceUpdateUniforms(s, e) {
705
+ ve(s, e);
232
706
  }
233
707
  };
234
- class V {
235
- constructor(e, t, r) {
236
- c(this, "canvas");
237
- c(this, "scene");
238
- c(this, "camera");
239
- c(this, "renderer");
240
- c(this, "renderTarget", null);
241
- c(this, "renderOrder", 0);
242
- c(this, "qualityFactor", 2);
243
- c(this, "mode", "overlay");
244
- c(this, "clipArea", 1);
245
- c(this, "target");
246
- c(this, "mountContainer");
247
- c(this, "targetRect");
248
- c(this, "meshMap", /* @__PURE__ */ new Map());
249
- var n, o, l;
250
- this.target = e, this.mountContainer = r, this.mode = (n = t.mode) != null ? n : "overlay", this.clipArea = (o = t.travelerClipArea) != null ? o : 1, this.canvas = document.createElement("canvas"), this.scene = new d.Scene(), this.targetRect = this.target.getBoundingClientRect();
251
- const s = this.targetRect.width, a = this.targetRect.height;
252
- this.camera = new d.OrthographicCamera(
253
- s / -2,
254
- s / 2,
255
- a / 2,
256
- a / -2,
708
+ class tt {
709
+ constructor(e) {
710
+ h(this, "observer");
711
+ h(this, "textures", /* @__PURE__ */ new WeakMap());
712
+ h(this, "loadStatus", /* @__PURE__ */ new WeakMap());
713
+ h(this, "elementUrls", /* @__PURE__ */ new WeakMap());
714
+ h(this, "onUpdate");
715
+ this.onUpdate = e, this.observer = new IntersectionObserver(
716
+ (t) => {
717
+ for (const i of t) {
718
+ const r = i.target;
719
+ i.isIntersecting ? this.loadTexture(r) : this.disposeTexture(r);
720
+ }
721
+ },
722
+ { rootMargin: "300px" }
723
+ );
724
+ }
725
+ register(e, t) {
726
+ if (e.nodeType !== Node.ELEMENT_NODE)
727
+ return;
728
+ this.elementUrls.get(e) !== t && (this.elementUrls.set(e, t), this.observer.unobserve(e), this.observer.observe(e));
729
+ }
730
+ unregister(e) {
731
+ e.nodeType === Node.ELEMENT_NODE && this.observer.unobserve(e), this.disposeTexture(e), this.elementUrls.delete(e), this.loadStatus.delete(e);
732
+ }
733
+ loadTexture(e) {
734
+ return we(this, null, function* () {
735
+ if (this.loadStatus.get(e) || this.textures.has(e))
736
+ return;
737
+ const t = this.elementUrls.get(e);
738
+ if (t) {
739
+ this.loadStatus.set(e, !0);
740
+ try {
741
+ let i;
742
+ if (t.startsWith("data:image/svg+xml"))
743
+ i = yield new Promise((c, n) => {
744
+ const a = new Image();
745
+ a.onload = () => c(a), a.onerror = n, a.src = t;
746
+ });
747
+ else {
748
+ const n = yield (yield fetch(t)).blob();
749
+ i = yield createImageBitmap(n, { imageOrientation: "flipY" });
750
+ }
751
+ if (this.elementUrls.get(e) !== t) {
752
+ "close" in i && i.close();
753
+ return;
754
+ }
755
+ const r = new b.Texture(i);
756
+ i instanceof HTMLImageElement || (r.flipY = !1), r.colorSpace = b.LinearSRGBColorSpace, r.needsUpdate = !0, this.textures.set(e, r), this.onUpdate(e, r);
757
+ } catch (i) {
758
+ console.warn("[MirageEngine] Failed to load texture:", t, i);
759
+ } finally {
760
+ this.elementUrls.has(e) && this.loadStatus.set(e, !1);
761
+ }
762
+ }
763
+ });
764
+ }
765
+ disposeTexture(e) {
766
+ const t = this.textures.get(e);
767
+ t && (t.dispose(), this.textures.delete(e), this.onUpdate(e, null)), this.loadStatus.set(e, !1);
768
+ }
769
+ get(e) {
770
+ return this.textures.get(e);
771
+ }
772
+ disposeAll() {
773
+ this.observer.disconnect();
774
+ }
775
+ }
776
+ class rt {
777
+ constructor(e, t, i, r) {
778
+ h(this, "canvas");
779
+ h(this, "scene");
780
+ h(this, "camera");
781
+ h(this, "renderer");
782
+ h(this, "renderTargets", []);
783
+ h(this, "renderOrder", 0);
784
+ h(this, "qualityFactor", 2);
785
+ h(this, "mode", "overlay");
786
+ h(this, "clipArea", 1);
787
+ h(this, "targetLayer", "base");
788
+ h(this, "target");
789
+ h(this, "mountContainer");
790
+ h(this, "registry");
791
+ h(this, "targetRect");
792
+ h(this, "travelersByLayer", Array.from(
793
+ { length: U.MAX_LAYERS },
794
+ () => /* @__PURE__ */ new Set()
795
+ ));
796
+ h(this, "textureManager");
797
+ // private meshMap: Map<HTMLElement, THREE.Mesh> = new Map();
798
+ h(this, "fixedMeshes", /* @__PURE__ */ new Set());
799
+ var a, o, l, d;
800
+ this.target = e, this.mountContainer = i, this.registry = r, this.textureManager = new tt((f, y) => {
801
+ const p = this.registry.get(f);
802
+ p && p.material instanceof b.ShaderMaterial && H.forceUpdateUniforms(p.material, { texture: y });
803
+ }), this.mode = (a = t.mode) != null ? a : "overlay", this.clipArea = (o = t.travelerClipArea) != null ? o : 1, this.targetLayer = (l = t.layer) != null ? l : "base", this.canvas = document.createElement("canvas"), this.scene = new b.Scene(), this.targetRect = this.target.getBoundingClientRect();
804
+ const c = this.targetRect.width, n = this.targetRect.height;
805
+ this.camera = new b.OrthographicCamera(
806
+ c / -2,
807
+ c / 2,
808
+ n / 2,
809
+ n / -2,
257
810
  1,
258
811
  1e3
259
- ), this.camera.position.z = 100, this.camera.layers.set(0), this.renderer = new d.WebGLRenderer({
812
+ ), this.camera.position.z = 100, this.camera.layers.set(this.getSceneLayer()), this.renderer = new b.WebGLRenderer({
260
813
  canvas: this.canvas,
261
814
  alpha: !0,
262
815
  antialias: !0
263
816
  // [new]
264
817
  // premultipliedAlpha: true
265
- }), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(s, a), this.applyTextQuality((l = t.quality) != null ? l : "medium");
818
+ }), b.ColorManagement.enabled = !1, this.renderer.outputColorSpace = b.LinearSRGBColorSpace, this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(c, n), this.applyTextQuality((d = t.quality) != null ? d : "medium");
819
+ }
820
+ getSceneLayer() {
821
+ return typeof this.targetLayer == "number" ? this.targetLayer : this.targetLayer === "selected" ? A.SELECTED : A.BASE;
266
822
  }
267
823
  createRenderTarget() {
268
- this.renderTarget = new d.WebGLRenderTarget(
269
- this.targetRect.width * this.qualityFactor,
270
- this.targetRect.height * this.qualityFactor,
271
- {
272
- minFilter: d.LinearFilter,
273
- magFilter: d.LinearFilter,
274
- format: d.RGBAFormat,
275
- stencilBuffer: !1,
276
- depthBuffer: !0,
277
- samples: 4
278
- }
279
- );
824
+ for (let e = 0; e < U.MAX_LAYERS; e++)
825
+ this.renderTargets.push(
826
+ new b.WebGLRenderTarget(
827
+ this.targetRect.width * this.qualityFactor,
828
+ this.targetRect.height * this.qualityFactor,
829
+ {
830
+ minFilter: b.LinearFilter,
831
+ magFilter: b.LinearFilter,
832
+ format: b.RGBAFormat,
833
+ stencilBuffer: !1,
834
+ depthBuffer: !0
835
+ }
836
+ )
837
+ );
280
838
  }
281
839
  applyTextQuality(e) {
282
840
  if (typeof e == "number") {
@@ -291,6 +849,8 @@ class V {
291
849
  this.qualityFactor = 4;
292
850
  break;
293
851
  case "medium":
852
+ this.qualityFactor = 2;
853
+ break;
294
854
  default:
295
855
  this.qualityFactor = 2;
296
856
  break;
@@ -302,358 +862,697 @@ class V {
302
862
  updateCanvasLayout() {
303
863
  this.canvas.style.width = `${this.targetRect.width}px`, this.canvas.style.height = `${this.targetRect.height}px`, this.mode === "duplicate" ? (this.canvas.style.position = "", this.canvas.style.top = "", this.canvas.style.left = "", this.canvas.style.display = "block") : (this.canvas.style.position = "absolute", this.canvas.style.top = `${this.target.offsetTop}px`, this.canvas.style.left = `${this.target.offsetLeft}px`, this.canvas.style.display = "block");
304
864
  }
865
+ updateUniforms(e, t) {
866
+ const i = this.registry.get(e);
867
+ i && (i.traverse((r) => {
868
+ r.isMesh && r.material && H.forceUpdateUniforms(
869
+ r.material,
870
+ t
871
+ );
872
+ }), i.userData.nativeMesh && i.userData.nativeMesh.traverse((r) => {
873
+ r.isMesh && r.material && H.forceUpdateUniforms(
874
+ r.material,
875
+ t
876
+ );
877
+ }));
878
+ }
305
879
  dispose() {
306
- this.renderer.dispose(), this.canvas.remove();
880
+ this.renderer.dispose(), this.canvas.remove(), this.textureManager.disposeAll();
307
881
  }
308
882
  setSize(e, t) {
309
- this.renderer.setSize(e, t), this.renderTarget && this.renderTarget.setSize(
310
- e * this.qualityFactor,
311
- t * this.qualityFactor
312
- ), this.camera.left = e / -2, this.camera.right = e / 2, this.camera.top = t / 2, this.camera.bottom = t / -2, this.camera.updateProjectionMatrix();
313
- }
314
- syncScene(e) {
315
- const t = this.target.getBoundingClientRect(), r = Math.abs(t.width - this.targetRect.width) > 0.1 || Math.abs(t.height - this.targetRect.height) > 0.1, s = this.mode === "overlay" && (Math.abs(t.top - this.targetRect.top) > 0.1 || Math.abs(t.left - this.targetRect.left) > 0.1);
316
- r ? (this.targetRect = t, this.setSize(this.targetRect.width, this.targetRect.height), this.updateCanvasLayout()) : s ? (this.targetRect = t, this.updateCanvasLayout()) : this.targetRect = t, this.renderOrder = 0;
317
- const a = /* @__PURE__ */ new Set();
318
- this.reconcileNode(e, a);
319
- for (const [n, o] of this.meshMap.entries())
320
- a.has(n) || (this.scene.remove(o), o.geometry.dispose(), o.material instanceof d.Material && o.material.dispose(), this.meshMap.delete(n));
321
- }
322
- reconcileNode(e, t) {
323
- var s;
324
- t.add(e.element);
325
- let r = this.meshMap.get(e.element);
326
- if (!r) {
327
- const a = new d.PlaneGeometry(1, 1);
328
- let n;
329
- n = D.create(
883
+ this.renderer.setSize(e, t);
884
+ for (const i of this.renderTargets)
885
+ i.setSize(e * this.qualityFactor, t * this.qualityFactor);
886
+ this.camera.left = e / -2, this.camera.right = e / 2, this.camera.top = t / 2, this.camera.bottom = t / -2, this.camera.updateProjectionMatrix();
887
+ }
888
+ syncScene(e, t) {
889
+ const i = this.target.getBoundingClientRect(), r = Math.abs(i.width - this.targetRect.width) > 0.1 || Math.abs(i.height - this.targetRect.height) > 0.1, c = this.mode === "overlay" && (Math.abs(i.top - this.targetRect.top) > 0.1 || Math.abs(i.left - this.targetRect.left) > 0.1);
890
+ r ? (this.targetRect = i, this.setSize(this.targetRect.width, this.targetRect.height), this.updateCanvasLayout()) : c ? (this.targetRect = i, this.updateCanvasLayout()) : this.targetRect = i, this.renderOrder = 0, this.reconcileNode(e), t.size > 0 && t.forEach((n) => {
891
+ const a = this.registry.get(n);
892
+ if (a) {
893
+ this.scene.remove(a);
894
+ for (const o of this.travelersByLayer)
895
+ o.delete(a);
896
+ this.fixedMeshes.delete(a), a.geometry.dispose(), a.userData.nativeMesh && (this.scene.remove(a.userData.nativeMesh), Array.isArray(a.userData.nativeMesh.material) ? a.userData.nativeMesh.material.forEach((o) => o.dispose()) : a.userData.nativeMesh.material.dispose(), a.userData.nativeMesh.geometry.dispose()), a.traverse((o) => {
897
+ o instanceof b.Mesh && (o.geometry && o.geometry.dispose(), o.material && (Array.isArray(o.material) ? o.material.forEach((l) => l.dispose()) : o.material.dispose()));
898
+ }), this.registry.remove(n), this.textureManager.unregister(n);
899
+ }
900
+ });
901
+ }
902
+ // 탐색 후 완성된 Scene node를 이용하여 mesh를 만들거나 조정
903
+ // => 이 과정에서 scene node에 있는 ele를 넣은 hash => activeElements
904
+ // => 이후 activeElements를 이용하여 mesh를 정리!!!+ map에서도 삭제
905
+ // private reconcileNode(node: SceneNode, activeElements: Set<HTMLElement>) {
906
+ reconcileNode(e) {
907
+ var i;
908
+ let t = this.registry.get(e.element);
909
+ if (!t) {
910
+ const r = new b.PlaneGeometry(1, 1), c = e.isTraveler ? (i = this.renderTargets[e.captureLayer - 2]) == null ? void 0 : i.texture : this.textureManager.get(e.element), n = H.create(
330
911
  "BOX",
331
912
  e.styles,
332
913
  "",
333
914
  e.rect.width,
334
915
  e.rect.height,
335
916
  this.qualityFactor,
336
- e.isTraveler ? (s = this.renderTarget) == null ? void 0 : s.texture : void 0,
917
+ c,
337
918
  e.shaderHooks
338
- ), r = new d.Mesh(a, n), e.type === "TEXT" && (r.name = "BG_MESH"), this.scene.add(r), this.meshMap.set(e.element, r);
919
+ );
920
+ t = new b.Mesh(r, n), e.type === "TEXT" && (t.name = "BG_MESH"), this.scene.add(t), this.registry.register(e.element, t), t.userData.baseMaterial = n;
339
921
  }
340
- if (r.userData.domRect = e.rect, this.updateMeshProperties(r, e), this.updateMeshLayers(r, e), e.isTraveler && r.layers.enable(28), e.type === "BOX")
341
- for (const a of e.children)
342
- this.reconcileNode(a, t);
922
+ if (this.updateMeshProperties(t, e), this.updateMeshLayers(t, e), e.isTraveler)
923
+ for (let r = 0; r < U.MAX_LAYERS; r++)
924
+ r === e.captureLayer - 2 ? this.travelersByLayer[r].add(t) : this.travelersByLayer[r].delete(t);
343
925
  else
344
- e.type === "TEXT" && this.reconcileTextChild(r, e);
926
+ for (const r of this.travelersByLayer)
927
+ r.delete(t);
928
+ if (e.isFixed ? this.fixedMeshes.add(t) : this.fixedMeshes.delete(t), e.styles.imageSrc ? this.textureManager.register(e.element, e.styles.imageSrc) : this.textureManager.unregister(e.element), e.type === "BOX")
929
+ for (const r of e.children)
930
+ this.reconcileNode(r);
931
+ else
932
+ e.type === "TEXT" && (this.reconcileTextChild(t, e, !1), t.userData.nativeMesh && e.nativeStyles && this.reconcileTextChild(t.userData.nativeMesh, e, !0));
345
933
  }
346
- reconcileTextChild(e, t) {
347
- var o, l;
348
- let r = e.children.find(
349
- (h) => h.name === "TEXT_CHILD"
350
- );
351
- const s = JSON.stringify(t.textStyles), a = (o = r == null ? void 0 : r.userData) == null ? void 0 : o.styleHash;
352
- if (!r || t.dirtyMask & N || s !== a) {
353
- r && ((l = r.material.map) == null || l.dispose(), r.geometry.dispose(), e.remove(r));
354
- const h = D.create(
355
- "TEXT",
356
- t.textStyles,
357
- t.textContent || "",
358
- t.rect.width,
359
- t.rect.height,
360
- this.qualityFactor
361
- ), m = new d.PlaneGeometry(1, 1);
362
- r = new d.Mesh(m, h), r.name = "TEXT_CHILD", r.userData = { styleHash: s }, this.updateMeshLayers(r, t), r.position.z = 5e-3, e.add(r);
363
- }
364
- if (r) {
365
- const h = e.userData.domRect, m = h.x + h.width / 2, f = h.y + h.height / 2, g = t.rect.x + t.rect.width / 2, p = t.rect.y + t.rect.height / 2, y = g - m, v = -(p - f);
366
- r.position.set(y, v, 5e-3);
934
+ reconcileTextChild(e, t, i) {
935
+ var l;
936
+ const r = t.textLines || [
937
+ { text: t.textContent || "", rect: t.rect }
938
+ ], c = i ? t.nativeStyles : t.textStyles, n = JSON.stringify(c) + t.textContent + r.map((d) => d.text).join("|"), a = (l = e.userData) == null ? void 0 : l.textChildStyleHash;
939
+ if (t.dirtyMask & be || n !== a) {
940
+ e.children.filter(
941
+ (u) => u.name.startsWith("TEXT_CHILD")
942
+ ).forEach((u) => {
943
+ var w;
944
+ const g = u;
945
+ (w = g.material.map) == null || w.dispose(), g.geometry.dispose(), e.remove(g);
946
+ });
947
+ const f = t.rect, y = f.x + f.width / 2, p = f.y + f.height / 2;
948
+ r.forEach((u, g) => {
949
+ const w = H.create(
950
+ "TEXT",
951
+ c,
952
+ u.text,
953
+ u.rect.width,
954
+ u.rect.height,
955
+ this.qualityFactor
956
+ ), R = new b.PlaneGeometry(1, 1), L = new b.Mesh(R, w);
957
+ L.name = `TEXT_CHILD_${g}`;
958
+ const E = t.rect.width === 0 ? 1 : u.rect.width / t.rect.width, x = t.rect.height === 0 ? 1 : u.rect.height / t.rect.height;
959
+ L.scale.set(E, x, 1);
960
+ const B = u.rect.x + u.rect.width / 2, F = u.rect.y + u.rect.height / 2, X = B - y, D = -(F - p);
961
+ L.position.set(
962
+ t.rect.width === 0 ? 0 : X / t.rect.width,
963
+ t.rect.height === 0 ? 0 : D / t.rect.height,
964
+ 5e-3
965
+ ), e.add(L);
966
+ }), e.userData.textChildStyleHash = n;
367
967
  }
968
+ e.children.forEach((d) => {
969
+ if (!d.name.startsWith("TEXT_CHILD"))
970
+ return;
971
+ const f = d, y = t.visibility & V ? A.BASE : A.HIDDEN;
972
+ if (f.layers.set(y), t.visibility & Z && f.layers.enable(A.SELECTED), t.visibility & V)
973
+ if (!i && t.nativeLayer !== void 0 && t.nativeStyles !== void 0)
974
+ for (let p = t.captureLayer; p < t.nativeLayer; p++)
975
+ f.layers.enable(A.getCaptureLayer(p));
976
+ else if (i && t.nativeLayer !== void 0)
977
+ for (let p = Math.max(t.captureLayer, t.nativeLayer); p <= U.MAX_LAYERS + 1; p++)
978
+ f.layers.enable(A.getCaptureLayer(p));
979
+ else
980
+ for (let p = t.captureLayer; p <= U.MAX_LAYERS + 1; p++)
981
+ f.layers.enable(A.getCaptureLayer(p));
982
+ });
368
983
  }
369
984
  updateMeshProperties(e, t) {
370
- var p;
371
- const { rect: r, styles: s } = t, a = this.renderer.getPixelRatio(), n = this.renderer.domElement.width / a, o = this.renderer.domElement.height / a;
372
- e.scale.set(r.width, r.height, 1);
373
- const l = 1e-3;
985
+ var B, F, X;
986
+ const { rect: i, styles: r } = t, c = this.renderer.getPixelRatio(), n = this.renderer.domElement.width / c, a = this.renderer.domElement.height / c;
987
+ e.material = e.userData.baseMaterial, e.scale.set(i.width, i.height, 1), e.userData.domRect = pe(G({}, i), {
988
+ width: i.width,
989
+ height: i.height
990
+ });
991
+ const o = 1e-3;
374
992
  this.renderOrder++;
375
- const h = this.targetRect.left + window.scrollX, m = this.targetRect.top + window.scrollY, f = r.x - h, g = r.y - m;
993
+ const l = this.targetRect.left + window.scrollX, d = this.targetRect.top + window.scrollY, f = i.x - l, y = i.y - d, p = f - n / 2 + i.width / 2, u = -y + a / 2 - i.height / 2;
376
994
  e.position.set(
377
- f - n / 2 + r.width / 2,
378
- -g + o / 2 - r.height / 2,
379
- s.zIndex + this.renderOrder * l
380
- ), D.update(
381
- e.material,
995
+ p,
996
+ u,
997
+ r.zIndex + this.renderOrder * o
998
+ );
999
+ const g = i.x, w = i.y;
1000
+ e.userData.basePosition = { x: p, y: u }, e.userData.originalBasePosition = { x: p, y: u }, e.userData.baseSize = { width: i.width, height: i.height }, e.userData.baseDOM = { x: g, y: w }, e.userData.isFixed = t.isFixed, e.userData.initialScroll = { x: window.scrollX, y: window.scrollY };
1001
+ const R = t.element.nodeType === Node.TEXT_NODE ? t.element.parentElement : t.element, L = window.getComputedStyle(R);
1002
+ let E = 0, x = 0;
1003
+ if (L.transform && L.transform !== "none") {
1004
+ const D = new DOMMatrix(L.transform);
1005
+ E = D.m41, x = D.m42;
1006
+ }
1007
+ if (e.userData.baseTransform = { x: E, y: x }, delete e.userData.originRatioX, delete e.userData.originRatioY, H.update(
1008
+ e.userData.baseMaterial,
382
1009
  "BOX",
383
- t.styles,
1010
+ r,
384
1011
  "",
385
- t.rect.width,
386
- t.rect.height,
1012
+ i.width,
1013
+ i.height,
387
1014
  this.qualityFactor,
388
- t.isTraveler ? (p = this.renderTarget) == null ? void 0 : p.texture : void 0
389
- );
1015
+ t.isTraveler ? (B = this.renderTargets[t.captureLayer - 2]) == null ? void 0 : B.texture : this.textureManager.get(t.element)
1016
+ ), t.nativeStyles && t.nativeRect) {
1017
+ if (!e.userData.nativeMesh) {
1018
+ const q = H.create(
1019
+ "BOX",
1020
+ t.nativeStyles,
1021
+ "",
1022
+ t.nativeRect.width,
1023
+ t.nativeRect.height,
1024
+ this.qualityFactor,
1025
+ t.isTraveler ? (F = this.renderTargets[t.captureLayer - 2]) == null ? void 0 : F.texture : this.textureManager.get(t.element),
1026
+ t.shaderHooks
1027
+ ), P = new b.Mesh(e.geometry, q);
1028
+ t.type === "TEXT" && (P.name = "BG_MESH"), this.scene.add(P), e.userData.nativeMesh = P;
1029
+ }
1030
+ const D = e.userData.nativeMesh, k = t.nativeRect.x - l, K = t.nativeRect.y - d, J = k - n / 2 + t.nativeRect.width / 2, Q = -K + a / 2 - t.nativeRect.height / 2;
1031
+ D.scale.set(t.nativeRect.width, t.nativeRect.height, 1), D.position.set(
1032
+ J,
1033
+ Q,
1034
+ t.nativeStyles.zIndex + this.renderOrder * o
1035
+ ), H.update(
1036
+ D.material,
1037
+ "BOX",
1038
+ t.nativeStyles,
1039
+ "",
1040
+ t.nativeRect.width,
1041
+ t.nativeRect.height,
1042
+ this.qualityFactor,
1043
+ t.isTraveler ? (X = this.renderTargets[t.captureLayer - 2]) == null ? void 0 : X.texture : this.textureManager.get(t.element)
1044
+ );
1045
+ } else
1046
+ e.userData.nativeMesh && (this.scene.remove(e.userData.nativeMesh), e.userData.nativeMesh.material instanceof b.Material && e.userData.nativeMesh.material.dispose(), delete e.userData.nativeMesh);
390
1047
  }
391
1048
  updateMeshLayers(e, t) {
392
- const r = (1 - (t.visibility & x)) * 30;
393
- e.layers.set(r), t.visibility === (x | R) && e.layers.enable(29);
394
- }
395
- captureRenderTarget() {
396
- const e = [];
397
- for (const l of this.meshMap.values())
398
- l.layers.mask & 1 << 28 && e.push(l);
399
- if (e.length === 0)
1049
+ const i = t.visibility & V ? A.BASE : A.HIDDEN;
1050
+ if (e.layers.set(i), t.visibility & Z && e.layers.enable(A.SELECTED), e.userData.nativeMesh && t.nativeLayer !== void 0) {
1051
+ const r = e.userData.nativeMesh;
1052
+ if (r.layers.set(A.HIDDEN), t.visibility & V) {
1053
+ for (let c = t.captureLayer; c < t.nativeLayer; c++)
1054
+ e.layers.enable(A.getCaptureLayer(c));
1055
+ for (let c = Math.max(t.captureLayer, t.nativeLayer); c <= U.MAX_LAYERS + 1; c++)
1056
+ r.layers.enable(A.getCaptureLayer(c));
1057
+ }
1058
+ } else if (t.visibility & V)
1059
+ for (let r = t.captureLayer; r <= U.MAX_LAYERS + 1; r++)
1060
+ e.layers.enable(A.getCaptureLayer(r));
1061
+ }
1062
+ captureRenderTarget(e, t, i) {
1063
+ if (e.size === 0 || !i)
400
1064
  return;
401
- const t = new d.Color(), r = this.renderer.getClearAlpha();
402
- this.renderer.getClearColor(t), this.renderer.setClearColor(0, 0), this.renderer.setRenderTarget(this.renderTarget), this.renderer.clear(), this.renderer.autoClear = !1, this.renderer.setScissorTest(!0), this.camera.layers.set(29);
403
- const s = new d.Vector3(), a = this.targetRect.width, n = this.targetRect.height, o = this.renderer.getPixelRatio();
404
- for (const l of e) {
405
- s.setFromMatrixPosition(l.matrixWorld), s.project(this.camera);
406
- const h = (s.x + 1) / 2 * a, m = (s.y + 1) / 2 * n;
407
- let f = 0, g = 1;
408
- typeof this.clipArea == "number" ? g = this.clipArea : this.clipArea.endsWith("%") ? g = parseFloat(this.clipArea) / 100 : this.clipArea.endsWith("px") && (f = parseFloat(this.clipArea));
409
- const p = l.scale.x * g + 0.5, y = l.scale.y * g + 0.5, v = h - p / 2, B = m - y / 2, M = (v * this.qualityFactor - f) / o, F = (B * this.qualityFactor - f) / o, b = (p * this.qualityFactor + f * 2) / o, u = (y * this.qualityFactor + f * 2) / o;
410
- this.renderer.setScissor(M, F, b, u), this.renderer.render(this.scene, this.camera);
1065
+ const r = new b.Color(), c = this.renderer.getClearAlpha();
1066
+ this.renderer.getClearColor(r), this.renderer.setClearColor(0, 0), this.renderer.setRenderTarget(i), this.renderer.clear(), this.renderer.autoClear = !1, this.renderer.setScissorTest(!0), this.camera.layers.set(t);
1067
+ const n = new b.Vector3(), a = this.targetRect.width, o = this.targetRect.height, l = this.renderer.getPixelRatio();
1068
+ for (const d of e) {
1069
+ n.setFromMatrixPosition(d.matrixWorld), n.project(this.camera);
1070
+ const f = (n.x + 1) / 2 * a, y = (n.y + 1) / 2 * o;
1071
+ let p = 0, u = 1;
1072
+ typeof this.clipArea == "number" ? u = this.clipArea : this.clipArea.endsWith("%") ? u = parseFloat(this.clipArea) / 100 : this.clipArea.endsWith("px") && (p = parseFloat(this.clipArea));
1073
+ const g = d.scale.x * u + 0.5, w = d.scale.y * u + 0.5, R = f - g / 2, L = y - w / 2, E = (R * this.qualityFactor - p) / l, x = (L * this.qualityFactor - p) / l, B = (g * this.qualityFactor + p * 2) / l, F = (w * this.qualityFactor + p * 2) / l;
1074
+ this.renderer.setScissor(E, x, B, F), this.renderer.render(this.scene, this.camera);
411
1075
  }
412
- this.renderer.setScissorTest(!1), this.renderer.autoClear = !0, this.renderer.setRenderTarget(null), this.camera.layers.set(28), this.renderer.setClearColor(t, r);
1076
+ this.renderer.setScissorTest(!1), this.renderer.autoClear = !0, this.renderer.setRenderTarget(null), this.camera.layers.set(this.getSceneLayer()), this.renderer.setClearColor(r, c);
413
1077
  }
414
1078
  render() {
415
- this.renderTarget && this.captureRenderTarget(), this.renderer.render(this.scene, this.camera);
1079
+ for (let e = 0; e < U.MAX_LAYERS; e++) {
1080
+ const t = e + 1;
1081
+ this.captureRenderTarget(
1082
+ this.travelersByLayer[e],
1083
+ A.getCaptureLayer(t),
1084
+ this.renderTargets[e]
1085
+ );
1086
+ }
1087
+ this.renderer.render(this.scene, this.camera);
416
1088
  }
417
- // for debugging
418
- showScissoredRenderTarget() {
419
- if (!this.renderTarget)
420
- return;
421
- const e = this.targetRect.width, t = this.targetRect.height, r = new d.PlaneGeometry(e, t), s = new d.MeshBasicMaterial({
422
- map: this.renderTarget.texture,
423
- side: d.DoubleSide,
424
- transparent: !0,
425
- opacity: 0.8
426
- }), a = new d.Mesh(r, s);
427
- a.position.set(0, 0, 90), a.layers.set(28), this.scene.add(a);
428
- }
429
- }
430
- function j(i) {
431
- const e = document.createRange();
432
- e.selectNodeContents(i);
433
- const t = e.getBoundingClientRect();
434
- return {
435
- left: t.left,
436
- top: t.top,
437
- width: t.width,
438
- height: t.height
439
- };
440
1089
  }
441
- function Q(i) {
442
- const e = parseFloat(i.fontSize);
443
- let t = parseFloat(i.lineHeight);
1090
+ function it(s) {
1091
+ const e = s.textContent || "", t = [];
1092
+ let i = "", r = null, c = -1;
1093
+ const n = (l, d) => {
1094
+ for (let f = 0; f < l.length; f++) {
1095
+ const y = l[f], p = document.createRange();
1096
+ p.setStart(s, d + f), p.setEnd(s, d + f + 1);
1097
+ const u = p.getBoundingClientRect();
1098
+ if (u.width === 0 && u.height === 0) {
1099
+ i += y;
1100
+ continue;
1101
+ }
1102
+ c === -1 || Math.abs(u.top - c) > u.height / 2 ? (i && r && t.push({
1103
+ text: i,
1104
+ rect: {
1105
+ left: r.left,
1106
+ top: r.top,
1107
+ width: r.right - r.left,
1108
+ height: r.bottom - r.top
1109
+ }
1110
+ }), i = y, r = {
1111
+ left: u.left,
1112
+ top: u.top,
1113
+ right: u.right,
1114
+ bottom: u.bottom
1115
+ }, c = u.top) : (i += y, r && (r.left = Math.min(r.left, u.left), r.top = Math.min(r.top, u.top), r.right = Math.max(r.right, u.right), r.bottom = Math.max(
1116
+ r.bottom,
1117
+ u.bottom
1118
+ )));
1119
+ }
1120
+ }, a = e.match(/[^\s\-]+\-?|\-|\s+/g) || [];
1121
+ let o = 0;
1122
+ for (const l of a) {
1123
+ const d = document.createRange();
1124
+ d.setStart(s, o), d.setEnd(s, o + l.length);
1125
+ const f = d.getClientRects();
1126
+ if (f.length > 1)
1127
+ n(l, o);
1128
+ else {
1129
+ const y = f.length === 1 ? f[0] : d.getBoundingClientRect();
1130
+ if (y.width === 0 && y.height === 0) {
1131
+ i += l, o += l.length;
1132
+ continue;
1133
+ }
1134
+ c === -1 || Math.abs(y.top - c) > y.height / 2 ? (i && r && t.push({
1135
+ text: i,
1136
+ rect: {
1137
+ left: r.left,
1138
+ top: r.top,
1139
+ width: r.right - r.left,
1140
+ height: r.bottom - r.top
1141
+ }
1142
+ }), i = l, r = {
1143
+ left: y.left,
1144
+ top: y.top,
1145
+ right: y.right,
1146
+ bottom: y.bottom
1147
+ }, c = y.top) : (i += l, r && (r.left = Math.min(r.left, y.left), r.top = Math.min(r.top, y.top), r.right = Math.max(r.right, y.right), r.bottom = Math.max(
1148
+ r.bottom,
1149
+ y.bottom
1150
+ )));
1151
+ }
1152
+ o += l.length;
1153
+ }
1154
+ return i && r && t.push({
1155
+ text: i,
1156
+ rect: {
1157
+ left: r.left,
1158
+ top: r.top,
1159
+ width: r.right - r.left,
1160
+ height: r.bottom - r.top
1161
+ }
1162
+ }), t.filter(
1163
+ (l) => l.text.trim().length > 0 && l.rect.width > 0 && l.rect.height > 0
1164
+ );
1165
+ }
1166
+ function Me(s) {
1167
+ const e = parseFloat(s.fontSize);
1168
+ let t = parseFloat(s.lineHeight);
444
1169
  isNaN(t) && (t = e * 1.2);
445
- let r = parseFloat(i.letterSpacing);
446
- return isNaN(r) && (r = 0), {
447
- font: `${i.fontStyle} ${i.fontWeight} ${i.fontSize} ${i.fontFamily}`,
448
- color: i.color,
449
- textAlign: i.textAlign || "start",
1170
+ let i = parseFloat(s.letterSpacing);
1171
+ return isNaN(i) && (i = 0), {
1172
+ font: `${s.fontStyle} ${s.fontWeight} ${s.fontSize} ${s.fontFamily}`,
1173
+ fontSize: s.fontSize,
1174
+ color: s.color,
1175
+ textAlign: s.textAlign || "start",
450
1176
  textBaseline: "alphabetic",
451
- direction: i.direction || "inherit",
1177
+ direction: s.direction || "inherit",
452
1178
  lineHeight: t,
453
- letterSpacing: r
1179
+ letterSpacing: i
454
1180
  };
455
1181
  }
456
- function P(i, e = z | L | Y | N | I, t, r) {
457
- if (i.nodeType === Node.TEXT_NODE) {
458
- const u = i;
459
- if (!u.textContent || !u.textContent.trim())
1182
+ function Be(s, e = j | ae | Ve | be | ye, t, i = 1, r = 0, c = 2, n, a) {
1183
+ var P, te, re, ie, se, ne;
1184
+ if (s.nodeType === Node.TEXT_NODE) {
1185
+ const m = s;
1186
+ if (!m.textContent || !m.textContent.trim())
460
1187
  return null;
461
- const C = u.textContent.replace(/\s+/g, " ").trim();
462
- if (C.length === 0)
1188
+ const T = m.textContent.replace(/\s+/g, " ");
1189
+ if (T.length === 0)
463
1190
  return null;
464
- const T = j(u);
465
- if (T.width === 0 || T.height === 0)
1191
+ const M = it(m);
1192
+ if (M.length === 0)
466
1193
  return null;
467
- const _ = u.parentElement, O = _ ? window.getComputedStyle(_) : null;
468
- return O ? {
1194
+ const I = m.parentElement, S = I ? window.getComputedStyle(I) : null;
1195
+ if (!S)
1196
+ return null;
1197
+ const O = Math.min(...M.map((v) => v.rect.left)), C = Math.min(...M.map((v) => v.rect.top)), _ = Math.max(...M.map((v) => v.rect.left + v.rect.width)), W = Math.max(...M.map((v) => v.rect.top + v.rect.height));
1198
+ return {
469
1199
  id: Math.random().toString(36).substring(2, 9),
470
1200
  type: "TEXT",
471
- element: u,
1201
+ element: m,
472
1202
  rect: {
473
- x: T.left + window.scrollX,
474
- y: T.top + window.scrollY,
475
- width: T.width,
476
- height: T.height
1203
+ x: O + window.scrollX,
1204
+ y: C + window.scrollY,
1205
+ width: _ - O,
1206
+ height: W - C
477
1207
  },
478
1208
  styles: {
479
1209
  backgroundColor: "transparent",
480
- opacity: parseFloat(O.opacity),
481
- zIndex: 0,
1210
+ backgroundImage: "",
1211
+ opacity: I && I.dataset[$.KEY] === $.VALUES.HIDE ? 1 : parseFloat(S.opacity),
1212
+ zIndex: (isNaN(parseInt(S.zIndex)) ? 0 : parseInt(S.zIndex)) + r,
482
1213
  borderRadius: "0px",
483
1214
  borderColor: "transparent",
484
- borderWidth: "0px"
1215
+ borderWidth: "0px",
1216
+ isTraveler: !1
485
1217
  },
486
- textContent: C,
487
- textStyles: Q(O),
1218
+ textContent: T,
1219
+ textLines: M.map((v) => ({
1220
+ text: v.text.trim(),
1221
+ rect: {
1222
+ x: v.rect.left + window.scrollX,
1223
+ y: v.rect.top + window.scrollY,
1224
+ width: v.rect.width,
1225
+ height: v.rect.height
1226
+ }
1227
+ })),
1228
+ textStyles: Me(S),
488
1229
  dirtyMask: e,
489
1230
  visibility: t,
490
1231
  isTraveler: !1,
1232
+ captureLayer: i,
1233
+ isFixed: S.position === "fixed",
1234
+ nativeLayer: n,
1235
+ nativeStyles: a ? G(G({
1236
+ backgroundColor: "transparent",
1237
+ backgroundImage: "",
1238
+ opacity: I && I.dataset[$.KEY] === $.VALUES.HIDE ? 1 : parseFloat(S.opacity),
1239
+ zIndex: (isNaN(parseInt(S.zIndex)) ? 0 : parseInt(S.zIndex)) + r,
1240
+ borderRadius: "0px",
1241
+ borderColor: "transparent",
1242
+ borderWidth: "0px",
1243
+ isTraveler: !1
1244
+ }, Me(S)), a) : void 0,
1245
+ nativeRect: a ? {
1246
+ x: O + window.scrollX,
1247
+ y: C + window.scrollY,
1248
+ width: _ - O,
1249
+ height: W - C
1250
+ } : void 0,
491
1251
  children: []
492
- } : null;
493
- }
494
- const s = i, a = s.dataset.mirageFilter;
495
- let n = t, o = t;
496
- if (a) {
497
- const u = new Set(a.split(/\s+/));
498
- for (const C of u)
499
- if (!W.includes(C))
1252
+ };
1253
+ }
1254
+ if (s.nodeType !== Node.ELEMENT_NODE)
1255
+ return null;
1256
+ const o = s, l = o.dataset[N.KEY];
1257
+ let d = t, f = t;
1258
+ if (l) {
1259
+ const m = new Set(l.split(/\s+/));
1260
+ for (const T of m)
1261
+ if (!Le.includes(T))
500
1262
  throw new Error(
501
- `[MirageEngine] Invalid filter token: '${C}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`
1263
+ `[MirageEngine] Invalid filter token: '${T}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`
502
1264
  );
503
- if (u.has("end"))
1265
+ if (m.has(N.VALUES.END))
504
1266
  return null;
505
- if (u.has("include-tree") && u.has("exclude-tree"))
1267
+ if (m.has(N.VALUES.INCLUDE_TREE) && m.has(N.VALUES.EXCLUDE_TREE))
506
1268
  throw new Error(
507
1269
  "[MirageEngine] Conflicting filters: 'include-tree' and 'exclude-tree' cannot be used together on the same element."
508
1270
  );
509
- if (u.has("include-self") && u.has("exclude-self"))
1271
+ if (m.has(N.VALUES.INCLUDE_SELF) && m.has(N.VALUES.EXCLUDE_SELF))
510
1272
  throw new Error(
511
1273
  "[MirageEngine] Conflicting filters: 'include-self' and 'exclude-self' cannot be used together on the same element."
512
1274
  );
513
- u.has("include-tree") ? n = n | x : u.has("exclude-tree") && (n = n & ~x), o = n, u.has("include-self") ? o = o | x : u.has("exclude-self") && (o = o & ~x);
514
- }
515
- o = o | t & R;
516
- const l = s.dataset.mirageTravel;
517
- let h = !1;
518
- l && new Set(l.split(/\s+/)).has("traveler") && (o = o & ~R, n = n & ~R, h = !0);
519
- const m = s.dataset.mirageShader;
520
- let f;
521
- m && (f = JSON.parse(m));
522
- const g = s.getBoundingClientRect(), p = window.getComputedStyle(s);
523
- if (g.width === 0 || g.height === 0 || p.display === "none")
1275
+ m.has(N.VALUES.INCLUDE_TREE) ? d = d | V : m.has(N.VALUES.EXCLUDE_TREE) && (d = d & ~V), f = d, m.has(N.VALUES.INCLUDE_SELF) ? f = f | V : m.has(N.VALUES.EXCLUDE_SELF) && (f = f & ~V);
1276
+ }
1277
+ const y = o.dataset[Y.KEY];
1278
+ if (y) {
1279
+ const m = new Set(y.split(/\s+/));
1280
+ for (const T of m)
1281
+ if (!Le.includes(T))
1282
+ throw new Error(
1283
+ `[MirageEngine] Invalid select token: '${T}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`
1284
+ );
1285
+ if (m.has(Y.VALUES.END))
1286
+ return null;
1287
+ if (m.has(Y.VALUES.INCLUDE_TREE) && m.has(Y.VALUES.EXCLUDE_TREE))
1288
+ throw new Error(
1289
+ "[MirageEngine] Conflicting selects: 'include-tree' and 'exclude-tree' cannot be used together on the same element."
1290
+ );
1291
+ if (m.has(Y.VALUES.INCLUDE_SELF) && m.has(Y.VALUES.EXCLUDE_SELF))
1292
+ throw new Error(
1293
+ "[MirageEngine] Conflicting selects: 'include-self' and 'exclude-self' cannot be used together on the same element."
1294
+ );
1295
+ m.has(Y.VALUES.INCLUDE_TREE) ? d = d | Z : m.has(Y.VALUES.EXCLUDE_TREE) && (d = d & ~Z), f = d, m.has(Y.VALUES.INCLUDE_SELF) ? f = f | Z : m.has(Y.VALUES.EXCLUDE_SELF) && (f = f & ~Z);
1296
+ }
1297
+ const p = o.dataset[U.KEY];
1298
+ let u = !1, g = a ? G({}, a) : {}, w = n;
1299
+ if (p) {
1300
+ let m = 1;
1301
+ const T = p.indexOf("{"), M = p.lastIndexOf("}");
1302
+ let I = p;
1303
+ if (T !== -1 && M !== -1 && M > T) {
1304
+ I = p.substring(0, T).trim();
1305
+ const C = p.substring(T, M + 1);
1306
+ try {
1307
+ g = new Function("return " + C)();
1308
+ } catch (_) {
1309
+ console.warn(
1310
+ `[MirageEngine] Failed to parse travel styles JSON: ${C}`
1311
+ );
1312
+ }
1313
+ }
1314
+ const S = I.split(/\s+/);
1315
+ let O = !1;
1316
+ if (S.includes(U.VALUES.TRAVELER)) {
1317
+ u = !0, O = !0;
1318
+ const C = S.find((_) => !isNaN(parseInt(_, 10)));
1319
+ C && (m = parseInt(C, 10));
1320
+ } else if (S.includes(U.VALUES.NATIVE)) {
1321
+ u = !1;
1322
+ const C = S.find((_) => !isNaN(parseInt(_, 10)));
1323
+ C && (w = parseInt(C, 10));
1324
+ }
1325
+ if (O) {
1326
+ const C = m + 1;
1327
+ if (C < i)
1328
+ throw new Error(
1329
+ `[MirageEngine] Traveler layer (${m}) cannot be smaller than inherited capture layer (${i - 1}).`
1330
+ );
1331
+ i = Math.min(C, U.MAX_LAYERS + 1);
1332
+ }
1333
+ }
1334
+ const R = o.dataset[Ye.KEY];
1335
+ let L;
1336
+ R && (L = JSON.parse(R));
1337
+ const E = o.getBoundingClientRect(), x = window.getComputedStyle(o);
1338
+ if (E.width === 0 || E.height === 0 || x.display === "none")
524
1339
  return null;
525
- let y = s.getAttribute("data-mid");
526
- y || (y = Math.random().toString(36).substring(2, 11), s.setAttribute("data-mid", y));
527
- const v = parseInt(p.zIndex), B = {
528
- backgroundColor: p.backgroundColor,
529
- opacity: parseFloat(p.opacity),
530
- zIndex: isNaN(v) ? 0 : v,
531
- borderRadius: p.borderRadius,
532
- borderColor: p.borderColor,
533
- borderWidth: p.borderWidth
534
- };
535
- let M, F;
536
- const b = [];
537
- return Array.from(s.childNodes).forEach((u) => {
538
- const C = u.nodeType === Node.TEXT_NODE ? o : n, T = P(
539
- u,
1340
+ let B = o.getAttribute("data-mid");
1341
+ B || (B = Math.random().toString(36).substring(2, 11), o.setAttribute("data-mid", B));
1342
+ const F = parseInt(x.zIndex), X = (isNaN(F) ? 0 : F) + r;
1343
+ let D;
1344
+ if (o.tagName === "IMG")
1345
+ D = o.src;
1346
+ else if (o.tagName.toLowerCase() === "svg") {
1347
+ const m = o.cloneNode(!0), T = g == null ? void 0 : g.color, M = g == null ? void 0 : g.fill, I = g == null ? void 0 : g.stroke, S = g == null ? void 0 : g.opacity, O = (v, xe) => {
1348
+ const z = window.getComputedStyle(v), oe = xe, Oe = z.fill === z.color, Ue = z.stroke === z.color, de = M || (Oe ? T : void 0) || z.fill;
1349
+ de && de !== "none" && (oe.style.fill = de);
1350
+ const ue = I || (Ue ? T : void 0) || z.stroke;
1351
+ ue && ue !== "none" && (oe.style.stroke = ue), z.strokeWidth && z.strokeWidth !== "0px" && (oe.style.strokeWidth = z.strokeWidth);
1352
+ const Ee = T || z.color;
1353
+ Ee && (oe.style.color = Ee);
1354
+ const fe = S || z.opacity;
1355
+ fe && fe !== "1" && (oe.style.opacity = fe);
1356
+ for (let le = 0; le < v.children.length; le++)
1357
+ O(v.children[le], xe.children[le]);
1358
+ };
1359
+ O(o, m);
1360
+ const C = o.getBoundingClientRect(), _ = window.devicePixelRatio * c;
1361
+ m.hasAttribute("viewBox") || m.setAttribute("viewBox", `0 0 ${C.width} ${C.height}`), m.setAttribute("width", (C.width * _).toString()), m.setAttribute("height", (C.height * _).toString());
1362
+ let W = new XMLSerializer().serializeToString(m);
1363
+ W.includes("xmlns=") || (W = W.replace(
1364
+ "<svg",
1365
+ '<svg xmlns="http://www.w3.org/2000/svg"'
1366
+ )), D = `data:image/svg+xml;utf8,${encodeURIComponent(W)}`;
1367
+ } else if (x.backgroundImage && x.backgroundImage !== "none") {
1368
+ const m = x.backgroundImage.match(/url\(['"]?(.*?)['"]?\)/);
1369
+ m && (D = m[1]);
1370
+ }
1371
+ const k = {
1372
+ backgroundColor: x.backgroundColor,
1373
+ backgroundImage: x.backgroundImage,
1374
+ opacity: o.dataset[$.KEY] === $.VALUES.HIDE ? 1 : parseFloat(x.opacity),
1375
+ zIndex: X,
1376
+ borderRadius: x.borderRadius,
1377
+ borderColor: x.borderColor,
1378
+ borderWidth: x.borderWidth,
1379
+ imageSrc: D,
1380
+ isTraveler: u
1381
+ }, K = k;
1382
+ let J, Q;
1383
+ const q = [];
1384
+ return o.tagName.toLowerCase() !== "svg" && Array.from(o.childNodes).forEach((m) => {
1385
+ const T = m.nodeType === Node.TEXT_NODE ? f : d, M = Be(
1386
+ m,
540
1387
  e,
541
- C
1388
+ T,
1389
+ i,
1390
+ X,
1391
+ c,
1392
+ w,
1393
+ m.nodeType === Node.TEXT_NODE && Object.keys(g).length > 0 ? g : void 0
542
1394
  );
543
- T && b.push(T);
1395
+ M && q.push(M);
544
1396
  }), {
545
- id: y,
1397
+ id: B,
546
1398
  type: "BOX",
547
- element: s,
1399
+ element: o,
548
1400
  rect: {
549
- x: g.left + window.scrollX,
550
- y: g.top + window.scrollY,
551
- width: g.width,
552
- height: g.height
1401
+ x: E.left + window.scrollX,
1402
+ y: E.top + window.scrollY,
1403
+ width: E.width,
1404
+ height: E.height
553
1405
  },
554
- styles: B,
555
- textContent: M,
556
- textStyles: F,
1406
+ styles: K,
1407
+ textContent: J,
1408
+ textStyles: Q,
557
1409
  dirtyMask: e,
558
- visibility: o,
559
- isTraveler: h,
560
- children: b,
561
- shaderHooks: f
1410
+ visibility: f,
1411
+ isTraveler: u,
1412
+ captureLayer: i,
1413
+ nativeLayer: w,
1414
+ nativeStyles: w !== void 0 ? pe(G({}, k), {
1415
+ backgroundColor: (P = g.backgroundColor) != null ? P : k.backgroundColor,
1416
+ backgroundImage: (te = g.backgroundImage) != null ? te : k.backgroundImage,
1417
+ opacity: (re = g.opacity) != null ? re : k.opacity,
1418
+ zIndex: g.zIndex !== void 0 ? g.zIndex + X : k.zIndex,
1419
+ borderRadius: (ie = g.borderRadius) != null ? ie : k.borderRadius,
1420
+ borderColor: (se = g.borderColor) != null ? se : k.borderColor,
1421
+ borderWidth: (ne = g.borderWidth) != null ? ne : k.borderWidth,
1422
+ isTraveler: k.isTraveler
1423
+ }) : void 0,
1424
+ nativeRect: w !== void 0 ? {
1425
+ x: g.x !== void 0 ? parseFloat(g.x) : E.left + window.scrollX,
1426
+ y: g.y !== void 0 ? parseFloat(g.y) : E.top + window.scrollY,
1427
+ width: g.width !== void 0 ? parseFloat(g.width) : E.width,
1428
+ height: g.height !== void 0 ? parseFloat(g.height) : E.height
1429
+ } : void 0,
1430
+ isFixed: x.position === "fixed",
1431
+ children: q,
1432
+ shaderHooks: L
562
1433
  };
563
1434
  }
564
- class Z {
565
- constructor(e, t, r) {
566
- c(this, "target");
567
- c(this, "renderer");
568
- c(this, "filter");
569
- c(this, "observer");
570
- c(this, "isDomDirty", !1);
571
- c(this, "isRunning", !1);
572
- c(this, "isTravelEnabled", !1);
573
- c(this, "pendingMask", S);
574
- c(this, "mutationTimer", null);
575
- c(this, "cssTimer", null);
576
- c(this, "resizeConfig");
577
- c(this, "resizeTimer", null);
578
- c(this, "isResizing", !1);
579
- c(this, "onTransitionFinished", (e) => {
580
- this.target.contains(e.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.pendingMask |= z | L, this.cssTimer = window.setTimeout(() => {
581
- this.isDomDirty = !0, this.cssTimer = null;
582
- }, 50));
583
- });
584
- c(this, "onWindowResize", () => {
585
- if (!this.resizeConfig.enabled) {
586
- this.isDomDirty = !0;
587
- return;
588
- }
589
- this.isResizing || (this.isResizing = !0, this.resizeConfig.onStart && this.resizeConfig.onStart()), this.resizeTimer && clearTimeout(this.resizeTimer), this.resizeTimer = window.setTimeout(() => {
590
- this.isDomDirty = !0, this.resizeConfig.onEnd && this.resizeConfig.onEnd(), this.isResizing = !1, this.resizeTimer = null;
591
- }, this.resizeConfig.delay);
592
- });
593
- c(this, "renderLoop", () => {
594
- this.isRunning && (this.isDomDirty && this.forceUpdateScene(), this.renderer.render(), requestAnimationFrame(this.renderLoop));
1435
+ function st(s, e) {
1436
+ e.size !== 0 && e.forEach((t, i) => {
1437
+ var B, F, X, D, k, K, J, Q, q, P, te, re, ie, se, ne, m, T, M;
1438
+ const r = s.get(i);
1439
+ if (!r || !r.userData.basePosition)
1440
+ return;
1441
+ let { x: c, y: n } = r.userData.basePosition;
1442
+ const { width: a, height: o } = r.userData.baseSize, l = (B = t.width) != null ? B : a, d = (F = t.height) != null ? F : o, f = l - a, y = d - o;
1443
+ if (t.width !== void 0 && r.userData.originRatioX === void 0 && Math.abs(f) > 0.1) {
1444
+ const I = i.getBoundingClientRect(), S = (X = t.x) != null ? X : 0, O = (k = (D = r.userData.baseTransform) == null ? void 0 : D.x) != null ? k : 0, C = r.userData.isFixed ? 0 : window.scrollX;
1445
+ let v = -(I.left + C - S + O - r.userData.baseDOM.x) / f;
1446
+ Math.abs(v) < 0.05 ? v = 0 : Math.abs(v - 1) < 0.05 ? v = 1 : Math.abs(v - 0.5) < 0.05 && (v = 0.5), r.userData.originRatioX = v;
1447
+ }
1448
+ if (t.height !== void 0 && r.userData.originRatioY === void 0 && Math.abs(y) > 0.1) {
1449
+ const I = i.getBoundingClientRect(), S = (K = t.y) != null ? K : 0, O = (Q = (J = r.userData.baseTransform) == null ? void 0 : J.y) != null ? Q : 0, C = r.userData.isFixed ? 0 : window.scrollY;
1450
+ let v = -(I.top + C - S + O - r.userData.baseDOM.y) / y;
1451
+ Math.abs(v) < 0.05 ? v = 0 : Math.abs(v - 1) < 0.05 ? v = 1 : Math.abs(v - 0.5) < 0.05 && (v = 0.5), r.userData.originRatioY = v;
1452
+ }
1453
+ const p = (q = r.userData.originRatioX) != null ? q : 0.5, u = (P = r.userData.originRatioY) != null ? P : 0.5, g = f * (0.5 - p), w = y * (0.5 - u), R = (re = (te = r.userData.baseTransform) == null ? void 0 : te.x) != null ? re : 0, L = (se = (ie = r.userData.baseTransform) == null ? void 0 : ie.y) != null ? se : 0, E = ((ne = t.x) != null ? ne : R) - R, x = ((m = t.y) != null ? m : L) - L;
1454
+ r.position.setX(c + g + E), r.position.setY(n - (w + x)), r.scale.set(l, d, 1), H.forceUpdateUniforms(r.material, {
1455
+ backgroundColor: t.backgroundColor,
1456
+ backgroundImage: t.backgroundImage,
1457
+ opacity: t.opacity,
1458
+ borderRadius: (M = t.borderRadius) != null ? M : (T = r.userData.baseStyles) == null ? void 0 : T.borderRadius,
1459
+ width: l,
1460
+ height: d
595
1461
  });
596
- var a, n;
597
- this.target = e, this.renderer = t, this.filter = r.filter;
598
- const s = (a = r.resizeDebounce) != null ? a : !0;
599
- s === !1 ? this.resizeConfig = { enabled: !1, delay: 0 } : s === !0 ? this.resizeConfig = { enabled: !0, delay: 150 } : this.resizeConfig = {
600
- enabled: !0,
601
- delay: (n = s.delay) != null ? n : 150,
602
- onStart: s.onStart,
603
- onEnd: s.onEnd
604
- }, this.observer = new MutationObserver((o) => {
605
- let l = S;
606
- for (const h of o)
607
- h.type === "childList" ? l |= I : h.type === "attributes" && (h.attributeName === "style" || h.attributeName === "class") && (l |= z | L);
608
- if (l !== S) {
609
- if (this.pendingMask |= l, l & I) {
610
- this.clearTimers(), console.log("Structural Change detected"), this.isDomDirty = !0;
611
- return;
612
- }
613
- this.mutationTimer && clearTimeout(this.mutationTimer), this.mutationTimer = window.setTimeout(() => {
614
- this.mutationTimer = null, this.isDomDirty = !0;
615
- }, 200);
616
- }
1462
+ });
1463
+ }
1464
+ function nt(s, e, t) {
1465
+ s.forEach((i) => {
1466
+ if (i.userData.isFixed && i.userData.initialScroll && i.userData.originalBasePosition) {
1467
+ const r = e - i.userData.initialScroll.x, c = t - i.userData.initialScroll.y;
1468
+ i.userData.basePosition.x = i.userData.originalBasePosition.x + r, i.userData.basePosition.y = i.userData.originalBasePosition.y - c, i.position.x = i.userData.basePosition.x, i.position.y = i.userData.basePosition.y;
1469
+ }
1470
+ });
1471
+ }
1472
+ class ot {
1473
+ constructor(e, t, i, r) {
1474
+ h(this, "target");
1475
+ h(this, "renderer");
1476
+ h(this, "registry");
1477
+ h(this, "isTravelEnabled", !1);
1478
+ h(this, "tracker");
1479
+ this.target = e, this.renderer = t, this.registry = i, this.tracker = new Ae(e, {
1480
+ resizeDebounce: r.resizeDebounce
1481
+ }), this.tracker.onLayoutChange.add((c, n) => {
1482
+ document.querySelector(`[${U.NAME}~='${U.VALUES.TRAVELER}']`) !== null && !this.isTravelEnabled && (this.isTravelEnabled = !0, this.renderer.createRenderTarget());
1483
+ const o = Be(
1484
+ this.target,
1485
+ c,
1486
+ V,
1487
+ 1,
1488
+ 0,
1489
+ this.renderer.qualityFactor
1490
+ );
1491
+ o && this.renderer.syncScene(o, n);
1492
+ }), this.tracker.onScrollChange.add((c, n) => {
1493
+ nt(this.renderer.fixedMeshes, c, n);
1494
+ }), this.tracker.onStyleChange.add((c) => {
1495
+ st(this.registry, c);
1496
+ }), this.tracker.onRender.add(() => {
1497
+ this.renderer.render();
617
1498
  });
618
1499
  }
619
1500
  start() {
620
- this.isRunning || (this.isRunning = !0, this.observer.observe(this.target, {
621
- childList: !0,
622
- subtree: !0,
623
- attributes: !0,
624
- characterData: !0
625
- }), this.target.addEventListener("transitionend", this.onTransitionFinished), this.target.addEventListener("animationend", this.onTransitionFinished), window.addEventListener("resize", this.onWindowResize), this.forceUpdateScene(), this.renderLoop());
1501
+ this.tracker.start();
626
1502
  }
627
1503
  stop() {
628
- this.isRunning = !1, this.observer.disconnect(), this.clearTimers(), this.target.removeEventListener("transitionend", this.onTransitionFinished), this.target.removeEventListener("animationend", this.onTransitionFinished), window.removeEventListener("resize", this.onWindowResize);
1504
+ this.tracker.stop();
629
1505
  }
630
- clearTimers() {
631
- this.mutationTimer && (clearTimeout(this.mutationTimer), this.mutationTimer = null), this.cssTimer && (clearTimeout(this.cssTimer), this.cssTimer = null);
1506
+ }
1507
+ class at {
1508
+ constructor() {
1509
+ h(this, "store");
1510
+ this.store = /* @__PURE__ */ new WeakMap();
632
1511
  }
633
- forceUpdateScene() {
634
- this.isDomDirty = !1;
635
- const e = document.querySelector("[data-mirage-travel='traveler']") !== null;
636
- e && !this.isTravelEnabled && (this.isTravelEnabled = !0, this.renderer.createRenderTarget());
637
- const t = P(
638
- this.target,
639
- this.pendingMask,
640
- e ? x | R : x,
641
- this.filter
642
- );
643
- t && this.renderer.syncScene(t), this.pendingMask = S;
1512
+ register(e, t) {
1513
+ this.store.set(e, t);
1514
+ }
1515
+ get(e) {
1516
+ return this.store.get(e);
1517
+ }
1518
+ // public register(element: HTMLElement, meshGroup: THREE.Group): void {
1519
+ // this.store.set(element, meshGroup);
1520
+ // }
1521
+ // public get(element: HTMLElement): THREE.Group | undefined {
1522
+ // return this.store.get(element);
1523
+ // }
1524
+ has(e) {
1525
+ return this.store.has(e);
1526
+ }
1527
+ // Optional
1528
+ remove(e) {
1529
+ this.store.delete(e);
644
1530
  }
645
1531
  }
646
- class K {
1532
+ class ct {
647
1533
  constructor(e, t) {
648
- c(this, "renderer");
649
- c(this, "syncer");
650
- c(this, "target");
651
- var s, a, n;
652
- this.target = e;
653
- let r;
654
- if (t.mode === "duplicate" ? r = (a = (s = t.container) != null ? s : this.target.parentElement) != null ? a : void 0 : r = (n = this.target.parentElement) != null ? n : void 0, !r)
1534
+ h(this, "renderer");
1535
+ h(this, "syncer");
1536
+ h(this, "target");
1537
+ h(this, "registry");
1538
+ var r, c, n;
1539
+ if (this.target = e, this.registry = new at(), !document.getElementById("mirage-engine-styles")) {
1540
+ const a = document.createElement("style");
1541
+ a.id = "mirage-engine-styles", a.textContent = `
1542
+ [${$.NAME}="${$.VALUES.HIDE}"] {
1543
+ opacity: 0 !important;
1544
+ }
1545
+ `, document.head.appendChild(a);
1546
+ }
1547
+ let i;
1548
+ if (t.mode === "duplicate" ? i = (c = (r = t.container) != null ? r : this.target.parentElement) != null ? c : void 0 : i = (n = this.target.parentElement) != null ? n : void 0, !i)
655
1549
  throw new Error("[Mirage] Cannot find a container (parent or option).");
656
- this.renderer = new V(this.target, t, r), this.renderer.mount(), this.syncer = new Z(this.target, this.renderer, t);
1550
+ this.renderer = new rt(
1551
+ this.target,
1552
+ t,
1553
+ i,
1554
+ this.registry
1555
+ ), this.renderer.mount(), this.syncer = new ot(this.target, this.renderer, this.registry, t);
657
1556
  }
658
1557
  start() {
659
1558
  this.syncer.start();
@@ -664,16 +1563,124 @@ class K {
664
1563
  dispose() {
665
1564
  this.syncer.stop(), this.renderer.dispose();
666
1565
  }
1566
+ getTracker() {
1567
+ return this.syncer.tracker;
1568
+ }
1569
+ updateUniforms(e, t) {
1570
+ this.renderer.updateUniforms(e, t);
1571
+ }
1572
+ getCanvas() {
1573
+ return this.renderer.canvas;
1574
+ }
1575
+ test() {
1576
+ const e = this.registry.get(
1577
+ document.querySelector("#box2")
1578
+ );
1579
+ if (!e)
1580
+ return;
1581
+ const t = {
1582
+ ArrowRight: !1,
1583
+ ArrowLeft: !1,
1584
+ ArrowUp: !1,
1585
+ ArrowDown: !1
1586
+ };
1587
+ window.addEventListener("keydown", (c) => {
1588
+ t[c.key] !== void 0 && (t[c.key] = !0);
1589
+ }), window.addEventListener("keyup", (c) => {
1590
+ t[c.key] !== void 0 && (t[c.key] = !1);
1591
+ });
1592
+ const i = 2, r = () => {
1593
+ requestAnimationFrame(r), t.ArrowRight && e.position.setX(e.position.x + i), t.ArrowLeft && e.position.setX(e.position.x - i), t.ArrowUp && e.position.setY(e.position.y + i), t.ArrowDown && e.position.setY(e.position.y - i);
1594
+ };
1595
+ r();
1596
+ }
1597
+ }
1598
+ class lt {
1599
+ constructor(e = {}) {
1600
+ h(this, "frontSelector");
1601
+ h(this, "midLayerElement");
1602
+ h(this, "items", []);
1603
+ h(this, "isInitialized", !1);
1604
+ h(this, "midLayer", null);
1605
+ h(this, "frontLayer", null);
1606
+ h(this, "tracker", null);
1607
+ this.frontSelector = e.frontSelector || ".front", this.midLayerElement = e.midLayerElement || null, this.items = [], this.isInitialized = !1, this.tracker = new Ae(document.body, e.trackerConfig || { resizeDebounce: !0 });
1608
+ }
1609
+ init() {
1610
+ var e;
1611
+ this.isInitialized || (this.createLayers(), this.setupMidLayer(), this.hijackFrontElements(), this.setupHooks(), (e = this.tracker) == null || e.start(), this.isInitialized = !0, console.log("🥪 sand-telepochi initialized!"));
1612
+ }
1613
+ // Allow passing an existing tracker (e.g. from mirage-engine/core)
1614
+ useTracker(e) {
1615
+ this.tracker = e, this.setupHooks();
1616
+ }
1617
+ createLayers() {
1618
+ this.midLayer = document.createElement("div"), this.midLayer.id = "sand-layer-mid", Object.assign(this.midLayer.style, {
1619
+ position: "fixed",
1620
+ inset: "0",
1621
+ zIndex: "9998",
1622
+ pointerEvents: "none"
1623
+ }), this.frontLayer = document.createElement("div"), this.frontLayer.id = "sand-layer-front", Object.assign(this.frontLayer.style, {
1624
+ position: "fixed",
1625
+ inset: "0",
1626
+ zIndex: "9999",
1627
+ pointerEvents: "none"
1628
+ }), document.body.appendChild(this.midLayer), document.body.appendChild(this.frontLayer);
1629
+ }
1630
+ setupMidLayer() {
1631
+ this.midLayerElement && this.midLayer && (this.midLayer.appendChild(this.midLayerElement), this.midLayerElement.style.pointerEvents = "auto");
1632
+ }
1633
+ hijackFrontElements() {
1634
+ const e = document.querySelectorAll(this.frontSelector);
1635
+ this.frontLayer && e.forEach((t) => {
1636
+ var n;
1637
+ const i = t.getBoundingClientRect(), r = window.getComputedStyle(t), c = document.createElement("div");
1638
+ c.className = "sand-placeholder", Object.assign(c.style, {
1639
+ display: r.display === "inline" ? "inline-block" : r.display,
1640
+ width: `${i.width}px`,
1641
+ height: `${i.height}px`,
1642
+ boxSizing: "border-box",
1643
+ marginTop: r.marginTop,
1644
+ marginBottom: r.marginBottom,
1645
+ marginLeft: r.marginLeft,
1646
+ marginRight: r.marginRight,
1647
+ visibility: "hidden",
1648
+ pointerEvents: "none"
1649
+ }), (n = t.parentNode) == null || n.insertBefore(c, t), this.frontLayer.appendChild(t), Object.assign(t.style, {
1650
+ position: "fixed",
1651
+ margin: "0",
1652
+ boxSizing: "border-box",
1653
+ width: `${i.width}px`,
1654
+ height: `${i.height}px`,
1655
+ pointerEvents: "auto"
1656
+ }), this.items.push({ placeholder: c, original: t });
1657
+ });
1658
+ }
1659
+ setupHooks() {
1660
+ this.tracker && this.tracker.onBeforeRender.add(() => {
1661
+ const e = this.items.map(({ placeholder: t }) => t.getBoundingClientRect());
1662
+ this.items.forEach(({ original: t }, i) => {
1663
+ const r = e[i];
1664
+ t.style.top = `${r.top}px`, t.style.left = `${r.left}px`, t.style.width = `${r.width}px`, t.style.height = `${r.height}px`;
1665
+ });
1666
+ });
1667
+ }
667
1668
  }
668
- class te {
1669
+ class dt {
669
1670
  constructor(e, t) {
670
- c(this, "_engine");
1671
+ h(this, "_engine");
1672
+ h(this, "_sandwich");
671
1673
  if (!e)
672
1674
  throw new Error("[Mirage] Target element is required.");
673
- this._engine = new K(e, t);
1675
+ if (this._engine = new ct(e, t), t.sandwich !== !1) {
1676
+ const i = typeof t.sandwich == "object" ? t.sandwich : {};
1677
+ this._sandwich = new lt({
1678
+ frontSelector: i.frontSelector || `[${Se.NAME}='${Se.VALUES.FRONT}']`
1679
+ }), this._sandwich.useTracker(this._engine.getTracker());
1680
+ }
674
1681
  }
675
1682
  start() {
676
- this._engine.start();
1683
+ this._engine.start(), this._sandwich && this._sandwich.init();
677
1684
  }
678
1685
  stop() {
679
1686
  this._engine.stop();
@@ -681,7 +1688,19 @@ class te {
681
1688
  destroy() {
682
1689
  this._engine.dispose();
683
1690
  }
1691
+ getTracker() {
1692
+ return this._engine.getTracker();
1693
+ }
1694
+ getCanvas() {
1695
+ return this._engine.getCanvas();
1696
+ }
1697
+ updateUniforms(e, t) {
1698
+ this._engine.updateUniforms(e, t);
1699
+ }
1700
+ test() {
1701
+ this._engine.test();
1702
+ }
684
1703
  }
685
1704
  export {
686
- te as Mirage
1705
+ dt as Mirage
687
1706
  };