@mirage-engine/core 0.0.2 → 0.1.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,154 +1,203 @@
1
- var B = Object.defineProperty;
2
- var z = (r, t, e) => t in r ? B(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
- var c = (r, t, e) => (z(r, typeof t != "symbol" ? t + "" : t, e), e);
4
- import * as h from "three";
5
- const v = 0, R = 1, b = 2, D = 4, C = 8, E = 16;
6
- function F(r, t, e) {
1
+ var k = Object.defineProperty;
2
+ var I = (r, t, e) => t in r ? k(r, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : r[t] = e;
3
+ var l = (r, t, e) => (I(r, typeof t != "symbol" ? t + "" : t, e), e);
4
+ import * as d from "three";
5
+ const T = 0, S = 1, B = 2, A = 4, M = 8, z = 16, D = 0, j = 29, F = 30, _ = [
6
+ "include-tree",
7
+ "exclude-tree",
8
+ "include-self",
9
+ "exclude-self",
10
+ "end"
11
+ ];
12
+ function P(r, t, e) {
7
13
  const i = t.split(`
8
14
  `), s = [];
9
15
  return i.forEach((n) => {
10
16
  const a = n.split(" ");
11
17
  let o = a[0];
12
- for (let l = 1; l < a.length; l++) {
13
- const d = a[l];
14
- r.measureText(o + " " + d).width < e ? o += " " + d : (s.push(o), o = d);
18
+ for (let h = 1; h < a.length; h++) {
19
+ const c = a[h];
20
+ r.measureText(o + " " + c).width < e ? o += " " + c : (s.push(o), o = c);
15
21
  }
16
22
  s.push(o);
17
23
  }), s;
18
24
  }
19
- function S(r, t, e, i, s = 2) {
25
+ function L(r, t, e, i, s = 2) {
20
26
  const n = document.createElement("canvas"), a = n.getContext("2d");
21
27
  if (!a)
22
28
  throw new Error("[Mirage] Failed to create canvas context");
23
- const l = (window.devicePixelRatio || 1) * s;
24
- n.width = e * l, n.height = i * l, a.scale(l, l), a.font = t.font, a.fillStyle = t.color, a.textBaseline = "top", a.globalAlpha = 1;
25
- const d = F(a, r, e), p = t.lineHeight;
26
- d.forEach((m, f) => {
27
- const y = f * p + 2;
28
- let g = 0;
29
- t.textAlign === "center" ? g = e / 2 : t.textAlign === "right" && (g = e), a.textAlign = t.textAlign, a.fillText(m, g, y);
29
+ const h = (window.devicePixelRatio || 1) * s;
30
+ n.width = e * h, n.height = i * h, a.scale(h, h), a.font = t.font, a.fillStyle = t.color, a.textBaseline = "top", a.globalAlpha = 1;
31
+ const c = P(a, r, e), p = t.lineHeight;
32
+ c.forEach((y, w) => {
33
+ const b = w * p + 2;
34
+ let x = 0;
35
+ t.textAlign === "center" ? x = e / 2 : t.textAlign === "right" && (x = e), a.textAlign = t.textAlign, a.fillText(y, x, b);
30
36
  });
31
- const u = new h.CanvasTexture(n);
32
- return u.colorSpace = h.SRGBColorSpace, u.minFilter = h.LinearFilter, u.magFilter = h.LinearFilter, u.needsUpdate = !0, u;
37
+ const f = new d.CanvasTexture(n);
38
+ return f.colorSpace = d.SRGBColorSpace, f.minFilter = d.LinearFilter, f.magFilter = d.LinearFilter, f.needsUpdate = !0, f;
33
39
  }
34
- function x(r) {
40
+ function v(r) {
35
41
  return typeof r == "number" ? r : parseFloat(r) || 0;
36
42
  }
37
- const O = `
43
+ function X(r, t) {
44
+ var o, h, c, p;
45
+ if (!t) {
46
+ r.set(0, 0, 0, 0);
47
+ return;
48
+ }
49
+ const e = t.split("/")[0].trim().split(/\s+/), i = v(e[0]), s = v((o = e[1]) != null ? o : e[0]), n = v((h = e[2]) != null ? h : e[0]), a = v((p = (c = e[3]) != null ? c : e[1]) != null ? p : e[0]);
50
+ r.set(i, s, n, a);
51
+ }
52
+ const Y = (
53
+ /* glsl */
54
+ `
38
55
  varying vec2 vUv;
39
56
  void main() {
40
57
  vUv = uv;
41
58
  gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
42
59
  }
43
- `, A = `
60
+ `
61
+ ), W = (
62
+ /* glsl */
63
+ `
64
+
44
65
  varying vec2 vUv;
45
66
 
46
67
  uniform vec2 uSize;
47
- uniform float uRadius;
68
+ uniform vec4 uRadius;
48
69
  uniform float uBorderWidth;
49
- uniform vec3 uColor;
70
+ uniform vec3 uBgColor;
50
71
  uniform vec3 uBorderColor;
51
72
  uniform float uOpacity;
52
73
  uniform float uBgOpacity;
74
+ uniform float uBorderOpacity;
53
75
 
54
- // SDF 박스 함수
76
+ // SDF box
55
77
  float sdRoundedBox(vec2 p, vec2 b, float r) {
56
78
  vec2 q = abs(p) - b + r;
79
+ // return length(max(q, 0.0)) - r;
57
80
  return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
58
81
  }
59
82
 
60
83
  void main() {
84
+ // uVu: (0.0, 0.0) ~ (1.0, 1.0) / center: (0.5, 0.5)
85
+ // p: (-1.0, -1.0) ~ (1.0, 1.0) / center: (0.0, 0.0)
61
86
  vec2 p = (vUv - 0.5) * uSize;
62
87
  vec2 halfSize = uSize * 0.5;
63
88
 
64
- float d = sdRoundedBox(p, halfSize, uRadius);
65
-
66
- float smoothEdge = 1.0;
89
+ // # border-radius
90
+ vec2 xRadii = mix(uRadius.xw, uRadius.yz, step(0.0, p.x));
91
+ float r = mix(xRadii.y, xRadii.x, step(0.0, p.y));
92
+ float d = sdRoundedBox(p, halfSize, r);
67
93
 
68
- float fillAlpha = 1.0 - smoothstep(-uBorderWidth - smoothEdge, -uBorderWidth, d);
69
-
70
- float borderAlpha = 0.0;
71
-
72
- if (uBorderWidth > 0.01) {
73
- borderAlpha = (1.0 - smoothstep(0.0, smoothEdge, d)) - fillAlpha;
74
- }
94
+ // 1px blur for anti-aliasing
95
+ float aa = 1.0;
75
96
 
76
- vec3 color = uColor;
77
- float totalAlpha = borderAlpha + fillAlpha;
78
-
79
- if (totalAlpha > 0.001) {
80
- color = mix(uColor, uBorderColor, borderAlpha / totalAlpha);
97
+ // x == 0~aa -> 1
98
+ // x < 0 -> 0
99
+ // x > aa -> 1
100
+ float bgMask = 1.0 - smoothstep(0.0, aa, d);
101
+
102
+ // v valley
103
+ // 10px -> 5
104
+ float halfBorder = uBorderWidth * 0.5;
105
+ // 10px :
106
+ // 0 -> 0
107
+ // -10 -> 0
108
+ // -5 -> -5
109
+ float borderD = abs(d + halfBorder) - halfBorder;
110
+ // ^ border 내부는 음수/외부는 양수
111
+
112
+ // [!] 내부가 음수인 곳에서 시작점이 0이면 내부는 안티 얼리어싱 되지 않음.
113
+ // 1에서 빼든 그대로든 상관없이 경계선 밖 1px
114
+
115
+ // 최종 alpha를 위해 border 부분에 해당하는 픽셀 만 1로 반환.
116
+ float borderAlpha = (1.0 - smoothstep(0.0, aa, borderD)) * uBorderOpacity;
117
+
118
+ if (uBorderWidth <= 0.01) {
119
+ borderAlpha = 0.0;
81
120
  }
82
-
83
- float shapeAlpha = borderAlpha + (fillAlpha * uBgOpacity);
84
- float finalOpacity = shapeAlpha * uOpacity;
85
-
121
+
122
+ float aFront = borderAlpha;
123
+ float aBack = uBgOpacity;
124
+ float aOut = aFront + aBack * (1.0 - aFront);
125
+
126
+ float safeAlpha = max(aOut, 0.0001);
127
+ vec3 cOut = (uBorderColor * aFront + uBgColor * aBack * (1.0 - aFront)) / safeAlpha;
128
+
129
+ float finalOpacity = aOut * bgMask * uOpacity;
130
+
86
131
  if (finalOpacity < 0.001) discard;
87
132
 
88
- gl_FragColor = vec4(color, finalOpacity);
133
+ gl_FragColor = vec4(cOut, finalOpacity);
134
+
135
+ #include <colorspace_fragment>
89
136
  }
90
- `;
91
- function w(r) {
137
+ `
138
+ );
139
+ function R(r) {
92
140
  if (!r || r === "transparent")
93
- return { color: new h.Color(16777215), alpha: 0 };
141
+ return { color: new d.Color(16777215), alpha: 0 };
94
142
  const t = r.match(
95
143
  /rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/
96
144
  );
97
145
  if (t) {
98
146
  const e = parseInt(t[1], 10), i = parseInt(t[2], 10), s = parseInt(t[3], 10), n = t[4] !== void 0 ? parseFloat(t[4]) : 1;
99
- return { color: new h.Color(`rgb(${e}, ${i}, ${s})`), alpha: n };
147
+ return { color: new d.Color(`rgb(${e}, ${i}, ${s})`), alpha: n };
100
148
  }
101
- return { color: new h.Color(r), alpha: 1 };
149
+ return { color: new d.Color(r), alpha: 1 };
102
150
  }
103
- function I(r, t, e) {
151
+ function H(r, t, e) {
104
152
  var o;
105
- const i = w(r.backgroundColor), s = w(r.borderColor), n = {
106
- uSize: { value: new h.Vector2(t, e) },
107
- uRadius: { value: x(r.borderRadius) },
108
- uBorderWidth: { value: x(r.borderWidth) },
109
- uColor: { value: i.color },
153
+ const i = R(r.backgroundColor), s = R(r.borderColor), n = {
154
+ uSize: { value: new d.Vector2(t, e) },
155
+ uRadius: { value: new d.Vector4(0, 0, 0, 0) },
156
+ uBorderWidth: { value: v(r.borderWidth) },
157
+ uBgColor: { value: i.color },
110
158
  uBorderColor: { value: s.color },
111
159
  uOpacity: { value: (o = r.opacity) != null ? o : 1 },
112
- uBgOpacity: { value: i.alpha }
160
+ uBgOpacity: { value: i.alpha },
161
+ uBorderOpacity: { value: s.alpha }
113
162
  };
114
- return new h.ShaderMaterial({
163
+ return X(n.uRadius.value, r.borderRadius), new d.ShaderMaterial({
115
164
  uniforms: n,
116
- vertexShader: O,
117
- fragmentShader: A,
165
+ vertexShader: Y,
166
+ fragmentShader: W,
118
167
  transparent: !0,
119
- side: h.FrontSide
168
+ side: d.FrontSide
120
169
  // for better performance
121
170
  });
122
171
  }
123
- function L(r, t, e, i) {
172
+ function U(r, t, e, i) {
124
173
  var a;
125
- const s = w(t.backgroundColor), n = w(t.borderColor);
126
- r.uniforms.uSize.value.set(e, i), r.uniforms.uRadius.value = x(t.borderRadius), r.uniforms.uBorderWidth.value = x(t.borderWidth), r.uniforms.uColor.value.copy(s.color), r.uniforms.uBorderColor.value.copy(n.color), r.uniforms.uOpacity.value = (a = t.opacity) != null ? a : 1, r.uniforms.uBgOpacity.value = s.alpha;
174
+ const s = R(t.backgroundColor), n = R(t.borderColor);
175
+ r.uniforms.uSize.value.set(e, i), X(r.uniforms.uRadius.value, t.borderRadius), r.uniforms.uBorderWidth.value = v(t.borderWidth), r.uniforms.uBgColor.value.copy(s.color), r.uniforms.uBorderColor.value.copy(n.color), r.uniforms.uOpacity.value = (a = t.opacity) != null ? a : 1, r.uniforms.uBgOpacity.value = s.alpha, r.uniforms.uBorderOpacity.value = n.alpha;
127
176
  }
128
- const T = {
177
+ const E = {
129
178
  create(r, t, e, i, s, n = 2) {
130
179
  if (r === "BOX")
131
- return I(t, i, s);
180
+ return H(t, i, s);
132
181
  if (r === "TEXT") {
133
- const a = S(
182
+ const a = L(
134
183
  e || "",
135
184
  t,
136
185
  i,
137
186
  s,
138
187
  n
139
188
  );
140
- return new h.MeshBasicMaterial({
189
+ return new d.MeshBasicMaterial({
141
190
  map: a,
142
191
  transparent: !0,
143
- side: h.FrontSide,
192
+ side: d.FrontSide,
144
193
  color: 16777215
145
194
  });
146
195
  }
147
- return new h.MeshBasicMaterial({ visible: !1 });
196
+ return new d.MeshBasicMaterial({ visible: !1 });
148
197
  },
149
198
  update(r, t, e, i, s, n, a = 2) {
150
199
  if (t === "BOX")
151
- L(
200
+ U(
152
201
  r,
153
202
  e,
154
203
  s,
@@ -157,46 +206,47 @@ const T = {
157
206
  else if (t === "TEXT") {
158
207
  const o = r;
159
208
  o.map && o.map.dispose();
160
- const l = S(
209
+ const h = L(
161
210
  i || "",
162
211
  e,
163
212
  s,
164
213
  n,
165
214
  a
166
215
  );
167
- o.map = l, o.needsUpdate = !0;
216
+ o.map = h, o.needsUpdate = !0;
168
217
  }
169
218
  }
170
219
  };
171
- class X {
220
+ class $ {
172
221
  constructor(t, e, i) {
173
- c(this, "canvas");
174
- c(this, "scene");
175
- c(this, "camera");
176
- c(this, "renderer");
177
- c(this, "renderOrder", 0);
178
- c(this, "textQualityFactor", 2);
179
- c(this, "mode", "overlay");
180
- c(this, "customZIndex", "9999");
181
- c(this, "target");
182
- c(this, "mountContainer");
183
- c(this, "targetRect");
184
- c(this, "meshMap", /* @__PURE__ */ new Map());
185
- var a, o, l;
186
- this.target = t, this.mountContainer = i, this.mode = (a = e.mode) != null ? a : "overlay", (o = e.style) != null && o.zIndex && (this.customZIndex = e.style.zIndex), this.canvas = document.createElement("canvas"), this.scene = new h.Scene(), this.targetRect = this.target.getBoundingClientRect();
222
+ l(this, "canvas");
223
+ l(this, "scene");
224
+ l(this, "camera");
225
+ l(this, "renderer");
226
+ l(this, "renderOrder", 0);
227
+ l(this, "textQualityFactor", 2);
228
+ l(this, "mode", "overlay");
229
+ l(this, "target");
230
+ l(this, "mountContainer");
231
+ l(this, "targetRect");
232
+ l(this, "meshMap", /* @__PURE__ */ new Map());
233
+ var a, o;
234
+ this.target = t, this.mountContainer = i, this.mode = (a = e.mode) != null ? a : "overlay", this.canvas = document.createElement("canvas"), this.scene = new d.Scene(), this.targetRect = this.target.getBoundingClientRect();
187
235
  const s = this.targetRect.width, n = this.targetRect.height;
188
- this.camera = new h.OrthographicCamera(
236
+ this.camera = new d.OrthographicCamera(
189
237
  s / -2,
190
238
  s / 2,
191
239
  n / 2,
192
240
  n / -2,
193
241
  1,
194
242
  1e3
195
- ), this.camera.position.z = 100, this.renderer = new h.WebGLRenderer({
243
+ ), this.camera.position.z = 100, this.renderer = new d.WebGLRenderer({
196
244
  canvas: this.canvas,
197
245
  alpha: !0,
198
246
  antialias: !0
199
- }), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(s, n), this.applyTextQuality((l = e.textQuality) != null ? l : "medium");
247
+ // [new]
248
+ // premultipliedAlpha: true
249
+ }), this.renderer.setPixelRatio(window.devicePixelRatio), this.renderer.setSize(s, n), this.applyTextQuality((o = e.textQuality) != null ? o : "medium");
200
250
  }
201
251
  applyTextQuality(t) {
202
252
  if (typeof t == "number") {
@@ -217,7 +267,7 @@ class X {
217
267
  }
218
268
  }
219
269
  mount() {
220
- this.mountContainer.appendChild(this.canvas), this.canvas.style.zIndex = this.customZIndex, this.canvas.style.pointerEvents = this.mode === "overlay" ? "none" : "auto", this.updateCanvasLayout();
270
+ this.mountContainer.prepend(this.canvas), this.canvas.style.pointerEvents = this.mode === "overlay" ? "none" : "auto", this.updateCanvasLayout();
221
271
  }
222
272
  updateCanvasLayout() {
223
273
  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");
@@ -230,24 +280,24 @@ class X {
230
280
  }
231
281
  syncScene(t) {
232
282
  const e = this.target.getBoundingClientRect(), i = Math.abs(e.width - this.targetRect.width) > 0.1 || Math.abs(e.height - this.targetRect.height) > 0.1, s = this.mode === "overlay" && (Math.abs(e.top - this.targetRect.top) > 0.1 || Math.abs(e.left - this.targetRect.left) > 0.1);
233
- i ? (this.targetRect = e, this.renderer.setSize(this.targetRect.width, this.targetRect.height), this.camera.left = this.targetRect.width / -2, this.camera.right = this.targetRect.width / 2, this.camera.top = this.targetRect.height / 2, this.camera.bottom = this.targetRect.height / -2, this.camera.updateProjectionMatrix(), this.updateCanvasLayout()) : s ? (this.targetRect = e, this.updateCanvasLayout()) : this.targetRect = e, this.renderOrder = 0;
283
+ i ? (this.targetRect = e, this.renderer.setSize(this.targetRect.width, this.targetRect.height), this.camera.left = this.targetRect.width / -2, this.camera.right = this.targetRect.width / 2, this.camera.top = this.targetRect.height / 2, this.camera.bottom = this.targetRect.height / -2, this.camera.layers.set(0), this.camera.updateProjectionMatrix(), this.updateCanvasLayout()) : s ? (this.targetRect = e, this.updateCanvasLayout()) : this.targetRect = e, this.renderOrder = 0;
234
284
  const n = /* @__PURE__ */ new Set();
235
285
  this.reconcileNode(t, n);
236
286
  for (const [a, o] of this.meshMap.entries())
237
- n.has(a) || (this.scene.remove(o), o.geometry.dispose(), o.material instanceof h.Material && o.material.dispose(), this.meshMap.delete(a));
287
+ n.has(a) || (this.scene.remove(o), o.geometry.dispose(), o.material instanceof d.Material && o.material.dispose(), this.meshMap.delete(a));
238
288
  }
239
289
  reconcileNode(t, e) {
240
290
  e.add(t.element);
241
291
  let i = this.meshMap.get(t.element);
242
292
  if (!i) {
243
- const s = new h.PlaneGeometry(1, 1), n = T.create(
293
+ const s = new d.PlaneGeometry(1, 1), n = E.create(
244
294
  "BOX",
245
295
  t.styles,
246
296
  "",
247
297
  t.rect.width,
248
298
  t.rect.height
249
299
  );
250
- i = new h.Mesh(s, n), t.type === "TEXT" && (i.name = "BG_MESH"), this.scene.add(i), this.meshMap.set(t.element, i);
300
+ i = new d.Mesh(s, n), i.layers.set(t.visibility), t.type === "TEXT" && (i.name = "BG_MESH"), this.scene.add(i), this.meshMap.set(t.element, i);
251
301
  }
252
302
  if (i.userData.domRect = t.rect, this.updateMeshProperties(i, t), t.type === "BOX")
253
303
  for (const s of t.children)
@@ -256,39 +306,39 @@ class X {
256
306
  t.type === "TEXT" && this.reconcileTextChild(i, t);
257
307
  }
258
308
  reconcileTextChild(t, e) {
259
- var o, l;
309
+ var o, h;
260
310
  let i = t.children.find(
261
- (d) => d.name === "TEXT_CHILD"
311
+ (c) => c.name === "TEXT_CHILD"
262
312
  );
263
313
  const s = JSON.stringify(e.textStyles), n = (o = i == null ? void 0 : i.userData) == null ? void 0 : o.styleHash;
264
- if (!i || e.dirtyMask & E || s !== n) {
265
- i && ((l = i.material.map) == null || l.dispose(), i.geometry.dispose(), t.remove(i));
266
- const d = T.create(
314
+ if (!i || e.dirtyMask & z || s !== n) {
315
+ i && ((h = i.material.map) == null || h.dispose(), i.geometry.dispose(), t.remove(i));
316
+ const c = E.create(
267
317
  "TEXT",
268
318
  e.textStyles,
269
319
  e.textContent || "",
270
320
  e.rect.width,
271
321
  e.rect.height,
272
322
  this.textQualityFactor
273
- ), p = new h.PlaneGeometry(1, 1);
274
- i = new h.Mesh(p, d), i.name = "TEXT_CHILD", i.userData = { styleHash: s }, i.position.z = 5e-3, t.add(i);
323
+ ), p = new d.PlaneGeometry(1, 1);
324
+ i = new d.Mesh(p, c), i.name = "TEXT_CHILD", i.userData = { styleHash: s }, i.layers.set(e.visibility), i.position.z = 5e-3, t.add(i);
275
325
  }
276
326
  if (i) {
277
- const d = t.userData.domRect, p = d.x + d.width / 2, u = d.y + d.height / 2, m = e.rect.x + e.rect.width / 2, f = e.rect.y + e.rect.height / 2, y = m - p, g = -(f - u);
278
- i.position.set(y, g, 5e-3);
327
+ const c = t.userData.domRect, p = c.x + c.width / 2, f = c.y + c.height / 2, y = e.rect.x + e.rect.width / 2, w = e.rect.y + e.rect.height / 2, b = y - p, x = -(w - f);
328
+ i.position.set(b, x, 5e-3);
279
329
  }
280
330
  }
281
331
  updateMeshProperties(t, e) {
282
332
  const { rect: i, styles: s } = e, n = this.renderer.getPixelRatio(), a = this.renderer.domElement.width / n, o = this.renderer.domElement.height / n;
283
333
  t.scale.set(i.width, i.height, 1);
284
- const l = 1e-3;
334
+ const h = 1e-3;
285
335
  this.renderOrder++;
286
- const d = this.targetRect.left + window.scrollX, p = this.targetRect.top + window.scrollY, u = i.x - d, m = i.y - p;
336
+ const c = this.targetRect.left + window.scrollX, p = this.targetRect.top + window.scrollY, f = i.x - c, y = i.y - p;
287
337
  t.position.set(
288
- u - a / 2 + i.width / 2,
289
- -m + o / 2 - i.height / 2,
290
- s.zIndex + this.renderOrder * l
291
- ), T.update(
338
+ f - a / 2 + i.width / 2,
339
+ -y + o / 2 - i.height / 2,
340
+ s.zIndex + this.renderOrder * h
341
+ ), E.update(
292
342
  t.material,
293
343
  "BOX",
294
344
  e.styles,
@@ -301,7 +351,7 @@ class X {
301
351
  this.renderer.render(this.scene, this.camera);
302
352
  }
303
353
  }
304
- function N(r) {
354
+ function Q(r) {
305
355
  const t = document.createRange();
306
356
  t.selectNodeContents(r);
307
357
  const e = t.getBoundingClientRect();
@@ -312,7 +362,7 @@ function N(r) {
312
362
  height: e.height
313
363
  };
314
364
  }
315
- function k(r) {
365
+ function G(r) {
316
366
  const t = parseFloat(r.fontSize);
317
367
  let e = parseFloat(r.lineHeight);
318
368
  isNaN(e) && (e = t * 1.2);
@@ -327,7 +377,7 @@ function k(r) {
327
377
  letterSpacing: i
328
378
  };
329
379
  }
330
- function M(r, t = R | b | D | E | C) {
380
+ function N(r, t = S | B | A | z | M, e, i) {
331
381
  if (r.nodeType === Node.TEXT_NODE) {
332
382
  const u = r;
333
383
  if (!u.textContent || !u.textContent.trim())
@@ -335,96 +385,129 @@ function M(r, t = R | b | D | E | C) {
335
385
  const m = u.textContent.replace(/\s+/g, " ").trim();
336
386
  if (m.length === 0)
337
387
  return null;
338
- const f = N(u);
339
- if (f.width === 0 || f.height === 0)
388
+ const g = Q(u);
389
+ if (g.width === 0 || g.height === 0)
340
390
  return null;
341
- const y = u.parentElement, g = y ? window.getComputedStyle(y) : null;
342
- return g ? {
391
+ const O = u.parentElement, C = O ? window.getComputedStyle(O) : null;
392
+ return C ? {
343
393
  id: Math.random().toString(36).substring(2, 9),
344
394
  type: "TEXT",
345
395
  element: u,
346
396
  rect: {
347
- x: f.left + window.scrollX,
348
- y: f.top + window.scrollY,
349
- width: f.width,
350
- height: f.height
397
+ x: g.left + window.scrollX,
398
+ y: g.top + window.scrollY,
399
+ width: g.width,
400
+ height: g.height
351
401
  },
352
402
  styles: {
353
403
  backgroundColor: "transparent",
354
- opacity: parseFloat(g.opacity),
404
+ opacity: parseFloat(C.opacity),
355
405
  zIndex: 0,
356
406
  borderRadius: "0px",
357
407
  borderColor: "transparent",
358
408
  borderWidth: "0px"
359
409
  },
360
410
  textContent: m,
361
- textStyles: k(g),
411
+ textStyles: G(C),
362
412
  dirtyMask: t,
413
+ visibility: e,
363
414
  children: []
364
415
  } : null;
365
416
  }
366
- const e = r, i = e.getBoundingClientRect(), s = window.getComputedStyle(e);
367
- if (i.width === 0 || i.height === 0 || s.display === "none")
417
+ const s = r, n = s.dataset.mirageFilter;
418
+ let a = e, o = e;
419
+ if (n) {
420
+ const u = new Set(n.split(/\s+/));
421
+ for (const m of u)
422
+ if (!_.includes(m))
423
+ throw new Error(
424
+ `[MirageEngine] Invalid filter token: '${m}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`
425
+ );
426
+ if (u.has("end"))
427
+ return null;
428
+ if (u.has("include-tree") && u.has("exclude-tree"))
429
+ throw new Error(
430
+ "[MirageEngine] Conflicting filters: 'include-tree' and 'exclude-tree' cannot be used together on the same element."
431
+ );
432
+ if (u.has("include-self") && u.has("exclude-self"))
433
+ throw new Error(
434
+ "[MirageEngine] Conflicting filters: 'include-self' and 'exclude-self' cannot be used together on the same element."
435
+ );
436
+ u.has("include-tree") ? a = D : u.has("exclude-tree") && (a = F), o = a, u.has("include-self") ? o = D : u.has("exclude-self") && (o = F);
437
+ }
438
+ if (i && i.end && i.end.length > 0 && i.end.some(
439
+ (m) => s.classList.contains(m)
440
+ ))
441
+ return null;
442
+ const h = s.getBoundingClientRect(), c = window.getComputedStyle(s);
443
+ if (h.width === 0 || h.height === 0 || c.display === "none")
368
444
  return null;
369
- let n = e.getAttribute("data-mid");
370
- n || (n = Math.random().toString(36).substring(2, 11), e.setAttribute("data-mid", n));
371
- const a = parseInt(s.zIndex), o = {
372
- backgroundColor: s.backgroundColor,
373
- opacity: parseFloat(s.opacity),
374
- zIndex: isNaN(a) ? 0 : a,
375
- borderRadius: s.borderRadius,
376
- borderColor: s.borderColor,
377
- borderWidth: s.borderWidth
445
+ let p = s.getAttribute("data-mid");
446
+ p || (p = Math.random().toString(36).substring(2, 11), s.setAttribute("data-mid", p));
447
+ const f = parseInt(c.zIndex), y = {
448
+ backgroundColor: c.backgroundColor,
449
+ opacity: parseFloat(c.opacity),
450
+ zIndex: isNaN(f) ? 0 : f,
451
+ borderRadius: c.borderRadius,
452
+ borderColor: c.borderColor,
453
+ borderWidth: c.borderWidth
378
454
  };
379
- let l, d;
380
- const p = [];
381
- return Array.from(e.childNodes).forEach((u) => {
382
- const m = M(u, t);
383
- m && p.push(m);
455
+ let w, b;
456
+ const x = [];
457
+ return Array.from(s.childNodes).forEach((u) => {
458
+ const m = u.nodeType === Node.TEXT_NODE ? o : a, g = N(
459
+ u,
460
+ t,
461
+ m,
462
+ i
463
+ );
464
+ g && x.push(g);
384
465
  }), {
385
- id: n,
466
+ id: p,
386
467
  type: "BOX",
387
- element: e,
468
+ element: s,
388
469
  rect: {
389
- x: i.left + window.scrollX,
390
- y: i.top + window.scrollY,
391
- width: i.width,
392
- height: i.height
470
+ x: h.left + window.scrollX,
471
+ y: h.top + window.scrollY,
472
+ width: h.width,
473
+ height: h.height
393
474
  },
394
- styles: o,
395
- textContent: l,
396
- textStyles: d,
475
+ styles: y,
476
+ textContent: w,
477
+ textStyles: b,
397
478
  dirtyMask: t,
398
- children: p
479
+ visibility: o,
480
+ children: x
399
481
  };
400
482
  }
401
- class P {
402
- constructor(t, e) {
403
- c(this, "target");
404
- c(this, "renderer");
405
- c(this, "observer");
406
- c(this, "isDomDirty", !1);
407
- c(this, "isRunning", !1);
408
- c(this, "pendingMask", v);
409
- c(this, "mutationTimer", null);
410
- c(this, "cssTimer", null);
411
- c(this, "onTransitionFinished", (t) => {
412
- this.target.contains(t.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.pendingMask |= R | b, this.cssTimer = window.setTimeout(() => {
483
+ class V {
484
+ constructor(t, e, i) {
485
+ l(this, "target");
486
+ l(this, "renderer");
487
+ l(this, "filter");
488
+ l(this, "observer");
489
+ l(this, "isDomDirty", !1);
490
+ l(this, "isRunning", !1);
491
+ l(this, "pendingMask", T);
492
+ l(this, "mutationTimer", null);
493
+ l(this, "cssTimer", null);
494
+ l(this, "onTransitionFinished", (t) => {
495
+ this.target.contains(t.target) && this.mutationTimer === null && (this.cssTimer && clearTimeout(this.cssTimer), this.pendingMask |= S | B, this.cssTimer = window.setTimeout(() => {
413
496
  this.isDomDirty = !0, this.cssTimer = null;
414
497
  }, 50));
415
498
  });
416
- c(this, "onWindowResize", () => {
499
+ l(this, "onWindowResize", () => {
417
500
  this.renderer.setSize(window.innerWidth, window.innerHeight), this.isDomDirty = !0;
418
501
  });
419
- c(this, "renderLoop", () => {
502
+ l(this, "renderLoop", () => {
420
503
  this.isRunning && (this.isDomDirty && this.forceUpdateScene(), this.renderer.render(), requestAnimationFrame(this.renderLoop));
421
504
  });
422
- this.target = t, this.renderer = e, this.observer = new MutationObserver((i) => {
423
- let s = v;
424
- for (const n of i)
425
- n.type === "childList" ? s |= C : n.type === "attributes" && (n.attributeName === "style" || n.attributeName === "class") && (s |= R | b);
426
- if (s !== v) {
427
- if (this.pendingMask |= s, s & C) {
505
+ this.target = t, this.renderer = e, this.filter = i, this.observer = new MutationObserver((s) => {
506
+ let n = T;
507
+ for (const a of s)
508
+ a.type === "childList" ? n |= M : a.type === "attributes" && (a.attributeName === "style" || a.attributeName === "class") && (n |= S | B);
509
+ if (n !== T) {
510
+ if (this.pendingMask |= n, n & M) {
428
511
  this.clearTimers(), console.log("Structural Change detected"), this.isDomDirty = !0;
429
512
  return;
430
513
  }
@@ -450,21 +533,21 @@ class P {
450
533
  }
451
534
  forceUpdateScene() {
452
535
  this.isDomDirty = !1;
453
- const t = M(this.target, this.pendingMask);
454
- t && this.renderer.syncScene(t), this.pendingMask = v;
536
+ const t = N(this.target, this.pendingMask, D, this.filter);
537
+ t && this.renderer.syncScene(t), this.pendingMask = T;
455
538
  }
456
539
  }
457
- class Y {
540
+ class Z {
458
541
  constructor(t, e) {
459
- c(this, "renderer");
460
- c(this, "syncer");
461
- c(this, "target");
542
+ l(this, "renderer");
543
+ l(this, "syncer");
544
+ l(this, "target");
462
545
  var s, n, a;
463
546
  this.target = t;
464
547
  let i;
465
548
  if (e.mode === "duplicate" ? i = (n = (s = e.container) != null ? s : this.target.parentElement) != null ? n : void 0 : i = (a = this.target.parentElement) != null ? a : void 0, !i)
466
549
  throw new Error("[Mirage] Cannot find a container (parent or option).");
467
- this.renderer = new X(this.target, e, i), this.renderer.mount(), this.syncer = new P(this.target, this.renderer);
550
+ this.renderer = new $(this.target, e, i), this.renderer.mount(), this.syncer = new V(this.target, this.renderer, e.filter);
468
551
  }
469
552
  start() {
470
553
  this.syncer.start();
@@ -477,11 +560,15 @@ class Y {
477
560
  }
478
561
  }
479
562
  export {
480
- E as DIRTY_CONTENT,
481
- v as DIRTY_NONE,
482
- R as DIRTY_RECT,
483
- C as DIRTY_STRUCTURE,
484
- b as DIRTY_STYLE,
485
- D as DIRTY_ZINDEX,
486
- Y as Engine
563
+ _ as ALLOWED_FILTERS,
564
+ z as DIRTY_CONTENT,
565
+ T as DIRTY_NONE,
566
+ S as DIRTY_RECT,
567
+ M as DIRTY_STRUCTURE,
568
+ B as DIRTY_STYLE,
569
+ A as DIRTY_ZINDEX,
570
+ F as EXCLUDED,
571
+ Z as Engine,
572
+ D as INCLUDED,
573
+ j as SYSTEM
487
574
  };