@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.
- package/CHANGELOG.md +6 -0
- package/dist/mirage-engine.js +271 -184
- package/dist/mirage-engine.umd.js +54 -27
- package/dist/src/core/Syncer.d.ts +3 -1
- package/dist/src/dom/Extractor.d.ts +3 -2
- package/dist/src/renderer/Renderer.d.ts +0 -1
- package/dist/src/types/common.d.ts +2 -0
- package/dist/src/types/config.d.ts +8 -0
- package/dist/src/types/flags.d.ts +5 -0
- package/package.json +1 -1
- package/src/core/Engine.ts +1 -1
- package/src/core/Syncer.ts +7 -2
- package/src/dom/Extractor.ts +72 -4
- package/src/renderer/Renderer.ts +9 -11
- package/src/types/common.ts +5 -2
- package/src/types/config.ts +13 -4
- package/src/types/flags.ts +17 -1
package/dist/mirage-engine.js
CHANGED
|
@@ -1,154 +1,203 @@
|
|
|
1
|
-
var
|
|
2
|
-
var
|
|
3
|
-
var
|
|
4
|
-
import * as
|
|
5
|
-
const
|
|
6
|
-
|
|
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
|
|
13
|
-
const
|
|
14
|
-
r.measureText(o + " " +
|
|
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
|
|
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
|
|
24
|
-
n.width = e *
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
const
|
|
28
|
-
let
|
|
29
|
-
t.textAlign === "center" ?
|
|
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
|
|
32
|
-
return
|
|
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
|
|
40
|
+
function v(r) {
|
|
35
41
|
return typeof r == "number" ? r : parseFloat(r) || 0;
|
|
36
42
|
}
|
|
37
|
-
|
|
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
|
-
|
|
60
|
+
`
|
|
61
|
+
), W = (
|
|
62
|
+
/* glsl */
|
|
63
|
+
`
|
|
64
|
+
|
|
44
65
|
varying vec2 vUv;
|
|
45
66
|
|
|
46
67
|
uniform vec2 uSize;
|
|
47
|
-
uniform
|
|
68
|
+
uniform vec4 uRadius;
|
|
48
69
|
uniform float uBorderWidth;
|
|
49
|
-
uniform vec3
|
|
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
|
-
|
|
65
|
-
|
|
66
|
-
float
|
|
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
|
-
|
|
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
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
84
|
-
float
|
|
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(
|
|
133
|
+
gl_FragColor = vec4(cOut, finalOpacity);
|
|
134
|
+
|
|
135
|
+
#include <colorspace_fragment>
|
|
89
136
|
}
|
|
90
|
-
|
|
91
|
-
|
|
137
|
+
`
|
|
138
|
+
);
|
|
139
|
+
function R(r) {
|
|
92
140
|
if (!r || r === "transparent")
|
|
93
|
-
return { color: new
|
|
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
|
|
147
|
+
return { color: new d.Color(`rgb(${e}, ${i}, ${s})`), alpha: n };
|
|
100
148
|
}
|
|
101
|
-
return { color: new
|
|
149
|
+
return { color: new d.Color(r), alpha: 1 };
|
|
102
150
|
}
|
|
103
|
-
function
|
|
151
|
+
function H(r, t, e) {
|
|
104
152
|
var o;
|
|
105
|
-
const i =
|
|
106
|
-
uSize: { value: new
|
|
107
|
-
uRadius: { value:
|
|
108
|
-
uBorderWidth: { value:
|
|
109
|
-
|
|
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
|
|
163
|
+
return X(n.uRadius.value, r.borderRadius), new d.ShaderMaterial({
|
|
115
164
|
uniforms: n,
|
|
116
|
-
vertexShader:
|
|
117
|
-
fragmentShader:
|
|
165
|
+
vertexShader: Y,
|
|
166
|
+
fragmentShader: W,
|
|
118
167
|
transparent: !0,
|
|
119
|
-
side:
|
|
168
|
+
side: d.FrontSide
|
|
120
169
|
// for better performance
|
|
121
170
|
});
|
|
122
171
|
}
|
|
123
|
-
function
|
|
172
|
+
function U(r, t, e, i) {
|
|
124
173
|
var a;
|
|
125
|
-
const s =
|
|
126
|
-
r.uniforms.uSize.value.set(e, i), r.uniforms.uRadius.value
|
|
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
|
|
177
|
+
const E = {
|
|
129
178
|
create(r, t, e, i, s, n = 2) {
|
|
130
179
|
if (r === "BOX")
|
|
131
|
-
return
|
|
180
|
+
return H(t, i, s);
|
|
132
181
|
if (r === "TEXT") {
|
|
133
|
-
const a =
|
|
182
|
+
const a = L(
|
|
134
183
|
e || "",
|
|
135
184
|
t,
|
|
136
185
|
i,
|
|
137
186
|
s,
|
|
138
187
|
n
|
|
139
188
|
);
|
|
140
|
-
return new
|
|
189
|
+
return new d.MeshBasicMaterial({
|
|
141
190
|
map: a,
|
|
142
191
|
transparent: !0,
|
|
143
|
-
side:
|
|
192
|
+
side: d.FrontSide,
|
|
144
193
|
color: 16777215
|
|
145
194
|
});
|
|
146
195
|
}
|
|
147
|
-
return new
|
|
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
|
-
|
|
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
|
|
209
|
+
const h = L(
|
|
161
210
|
i || "",
|
|
162
211
|
e,
|
|
163
212
|
s,
|
|
164
213
|
n,
|
|
165
214
|
a
|
|
166
215
|
);
|
|
167
|
-
o.map =
|
|
216
|
+
o.map = h, o.needsUpdate = !0;
|
|
168
217
|
}
|
|
169
218
|
}
|
|
170
219
|
};
|
|
171
|
-
class
|
|
220
|
+
class $ {
|
|
172
221
|
constructor(t, e, i) {
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
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
|
|
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
|
|
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
|
-
|
|
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.
|
|
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
|
|
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
|
|
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
|
|
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,
|
|
309
|
+
var o, h;
|
|
260
310
|
let i = t.children.find(
|
|
261
|
-
(
|
|
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 &
|
|
265
|
-
i && ((
|
|
266
|
-
const
|
|
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
|
|
274
|
-
i = new
|
|
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
|
|
278
|
-
i.position.set(
|
|
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
|
|
334
|
+
const h = 1e-3;
|
|
285
335
|
this.renderOrder++;
|
|
286
|
-
const
|
|
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
|
-
|
|
289
|
-
-
|
|
290
|
-
s.zIndex + this.renderOrder *
|
|
291
|
-
),
|
|
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
|
|
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
|
|
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
|
|
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
|
|
339
|
-
if (
|
|
388
|
+
const g = Q(u);
|
|
389
|
+
if (g.width === 0 || g.height === 0)
|
|
340
390
|
return null;
|
|
341
|
-
const
|
|
342
|
-
return
|
|
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:
|
|
348
|
-
y:
|
|
349
|
-
width:
|
|
350
|
-
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(
|
|
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:
|
|
411
|
+
textStyles: G(C),
|
|
362
412
|
dirtyMask: t,
|
|
413
|
+
visibility: e,
|
|
363
414
|
children: []
|
|
364
415
|
} : null;
|
|
365
416
|
}
|
|
366
|
-
const
|
|
367
|
-
|
|
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
|
|
370
|
-
|
|
371
|
-
const
|
|
372
|
-
backgroundColor:
|
|
373
|
-
opacity: parseFloat(
|
|
374
|
-
zIndex: isNaN(
|
|
375
|
-
borderRadius:
|
|
376
|
-
borderColor:
|
|
377
|
-
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
|
|
380
|
-
const
|
|
381
|
-
return Array.from(
|
|
382
|
-
const m =
|
|
383
|
-
|
|
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:
|
|
466
|
+
id: p,
|
|
386
467
|
type: "BOX",
|
|
387
|
-
element:
|
|
468
|
+
element: s,
|
|
388
469
|
rect: {
|
|
389
|
-
x:
|
|
390
|
-
y:
|
|
391
|
-
width:
|
|
392
|
-
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:
|
|
395
|
-
textContent:
|
|
396
|
-
textStyles:
|
|
475
|
+
styles: y,
|
|
476
|
+
textContent: w,
|
|
477
|
+
textStyles: b,
|
|
397
478
|
dirtyMask: t,
|
|
398
|
-
|
|
479
|
+
visibility: o,
|
|
480
|
+
children: x
|
|
399
481
|
};
|
|
400
482
|
}
|
|
401
|
-
class
|
|
402
|
-
constructor(t, e) {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
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
|
-
|
|
499
|
+
l(this, "onWindowResize", () => {
|
|
417
500
|
this.renderer.setSize(window.innerWidth, window.innerHeight), this.isDomDirty = !0;
|
|
418
501
|
});
|
|
419
|
-
|
|
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((
|
|
423
|
-
let
|
|
424
|
-
for (const
|
|
425
|
-
|
|
426
|
-
if (
|
|
427
|
-
if (this.pendingMask |=
|
|
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 =
|
|
454
|
-
t && this.renderer.syncScene(t), this.pendingMask =
|
|
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
|
|
540
|
+
class Z {
|
|
458
541
|
constructor(t, e) {
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
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
|
|
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
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
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
|
};
|