@mirage-engine/core 0.2.0 → 0.2.2
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 +16 -0
- package/dist/mirage-engine.js +1016 -418
- package/dist/mirage-engine.umd.js +136 -72
- package/dist/src/animation/Animator.d.ts +11 -0
- package/dist/src/core/Engine.d.ts +2 -0
- package/dist/src/core/Syncer.d.ts +8 -1
- package/dist/src/renderer/Renderer.d.ts +9 -4
- package/dist/src/store/MeshRegistry.d.ts +9 -0
- package/dist/src/store/TextureLifecycleManager.d.ts +16 -0
- package/dist/src/types/animate.d.ts +19 -0
- package/dist/src/types/common.d.ts +7 -1
- package/dist/src/types/config.d.ts +4 -0
- package/dist/src/types/index.d.ts +1 -0
- package/package.json +2 -2
- package/src/animation/Animator.ts +163 -0
- package/src/core/Engine.ts +56 -4
- package/src/core/Syncer.ts +71 -16
- package/src/dom/Extractor.ts +176 -21
- package/src/env.d.ts +4 -0
- package/src/renderer/Renderer.ts +206 -80
- package/src/store/MeshRegistry.ts +32 -0
- package/src/store/TextureLifecycleManager.ts +111 -0
- package/src/types/animate.ts +26 -0
- package/src/types/common.ts +4 -1
- package/src/types/config.ts +4 -0
- package/src/types/index.ts +2 -1
|
@@ -1,85 +1,149 @@
|
|
|
1
|
-
(function(
|
|
2
|
-
`),
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
(function(v,T){typeof exports=="object"&&typeof module!="undefined"?T(exports,require("three")):typeof define=="function"&&define.amd?define(["exports","three"],T):(v=typeof globalThis!="undefined"?globalThis:v||self,T(v.MirageEngine={},v.THREE))})(this,function(v,T){"use strict";var Xe=Object.defineProperty;var Ye=(v,T,M)=>T in v?Xe(v,T,{enumerable:!0,configurable:!0,writable:!0,value:M}):v[T]=M;var u=(v,T,M)=>(Ye(v,typeof T!="symbol"?T+"":T,M),M);var fe=(v,T,M)=>new Promise((p,L)=>{var I=E=>{try{P(M.next(E))}catch(A){L(A)}},z=E=>{try{P(M.throw(E))}catch(A){L(A)}},P=E=>E.done?p(E.value):Promise.resolve(E.value).then(I,z);P((M=M.apply(v,T)).next())});function M(n){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const t in n)if(t!=="default"){const i=Object.getOwnPropertyDescriptor(n,t);Object.defineProperty(e,t,i.get?i:{enumerable:!0,get:()=>n[t]})}}return e.default=n,Object.freeze(e)}const p=M(T),L=0,I=1,z=2,P=4,E=8,A=16,B=1,_=2,ge=0,ee=["include-tree","exclude-tree","include-self","exclude-self","end"];class te{static getBaseline(e){if(this.cache.has(e))return this.cache.get(e);const t=this.calculateBaselineFromDOM(e);return this.cache.set(e,t),t}static calculateBaselineFromDOM(e){if(typeof document=="undefined")return 0;const t=document.createElement("div"),i=document.createElement("span"),r=document.createElement("img");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);const a=r.offsetTop-i.offsetTop;return document.body.removeChild(t),a}}u(te,"cache",new Map);class pe extends p.MeshBasicMaterial{constructor(t,i,r,a,o=2){super({transparent:!0,side:p.FrontSide,color:16777215});u(this,"canvas");u(this,"ctx");u(this,"qualityFactor");if(this.canvas=document.createElement("canvas"),this.ctx=this.canvas.getContext("2d"),!this.ctx)throw new Error("[Mirage] Failed to create canvas context");this.qualityFactor=o,this.map=new p.CanvasTexture(this.canvas),this.map.colorSpace=p.LinearSRGBColorSpace,this.map.minFilter=p.LinearFilter,this.map.magFilter=p.LinearFilter,this.updateText(t,i,r,a)}wrapText(t,i){const r=t.split(`
|
|
2
|
+
`),a=[];return r.forEach(o=>{const s=o.match(/[^\s\-]+\-?|\-|\s+/g)||[];if(s.length===0){a.push("");return}let l=s[0];for(let c=1;c<s.length;c++){const d=s[c];this.ctx.measureText(l+d).width<=i+2?l+=d:(l&&a.push(l),l=d.trimStart())}l&&a.push(l)}),a}updateText(t,i,r,a,o){o!==void 0&&(this.qualityFactor=o);const l=(window.devicePixelRatio||1)*this.qualityFactor,c=r*l,d=a*l;this.canvas.width!==c||this.canvas.height!==d?(this.canvas.width=c,this.canvas.height=d):this.ctx.clearRect(0,0,this.canvas.width,this.canvas.height),this.ctx.setTransform(l,0,0,l,0,0),this.ctx.font=i.font,this.ctx.fillStyle=i.color,this.ctx.textBaseline="alphabetic",this.ctx.globalAlpha=1;const f=this.wrapText(t,r),h=i.lineHeight,m=te.getBaseline(i.font);f.forEach((g,C)=>{const x=C*h+m;let R=0;i.textAlign==="center"?R=r/2:i.textAlign==="right"&&(R=r),this.ctx.textAlign=i.textAlign,this.ctx.fillText(g,R,x)}),this.map&&(this.map.needsUpdate=!0)}dispose(){this.map&&this.map.dispose(),super.dispose()}}function N(n){return typeof n=="number"?n:parseFloat(n)||0}function U(n){if(!n||n==="transparent")return{color:new p.Color(16777215),alpha:0};const e=n.match(/rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*([\d.]+))?\)/);if(e){const t=parseInt(e[1],10),i=parseInt(e[2],10),r=parseInt(e[3],10),a=e[4]!==void 0?parseFloat(e[4]):1;return{color:new p.Color(`rgb(${t}, ${i}, ${r})`),alpha:a}}return{color:new p.Color(n),alpha:1}}function me(n){const e=[];let t="",i=0;for(let r=0;r<n.length;r++){const a=n[r];if(a==="(")i++;else if(a===")")i--;else if(a===","&&i===0){e.push(t.trim()),t="";continue}t+=a}return t&&e.push(t.trim()),e}function be(n){if(!n||typeof n!="string"||!n.includes("linear-gradient"))return null;const e=n.match(/linear-gradient\((.*)\)/);if(!e)return null;const t=e[1],i=me(t);let r=Math.PI,a=0;const o=i[0].trim();if(o.startsWith("to "))o==="to top"?r=0:o==="to right"?r=Math.PI/2:o==="to bottom"?r=Math.PI:o==="to left"?r=Math.PI*1.5:o==="to top right"||o==="to right top"?r=Math.PI/4:o==="to bottom right"||o==="to right bottom"?r=Math.PI*.75:o==="to bottom left"||o==="to left bottom"?r=Math.PI*1.25:(o==="to top left"||o==="to left top")&&(r=Math.PI*1.75),a=1;else if(o.endsWith("deg")||o.endsWith("rad")||o.endsWith("turn")){const l=parseFloat(o);o.endsWith("deg")?r=l*(Math.PI/180):o.endsWith("rad")?r=l:o.endsWith("turn")&&(r=l*Math.PI*2),a=1}const s=[];for(let l=a;l<i.length&&!(s.length>=8);l++){const c=i[l].trim(),d=c.lastIndexOf(" ");let f=c,h=null;if(d!==-1&&!c.endsWith(")")){const g=c.substring(d+1);(g.endsWith("%")||g.endsWith("px")||!isNaN(parseFloat(g)))&&(f=c.substring(0,d).trim(),h=g)}const m=U(f);s.push({color:m.color,alpha:m.alpha,rawStop:h,stop:0})}if(s.length>0){for(let c=0;c<s.length;c++)s[c].rawStop!==null&&(s[c].stop=parseFloat(s[c].rawStop)/100);s[0].rawStop===null&&(s[0].stop=0),s.length>1&&s[s.length-1].rawStop===null&&(s[s.length-1].stop=1);let l=0;for(let c=1;c<s.length;c++)if(s[c].rawStop!==null||c===s.length-1){const d=c-l;if(d>1){const f=s[l].stop,m=(s[c].stop-f)/d;for(let g=1;g<d;g++)s[l+g].stop=f+m*g}l=c}}return{angle:r,stops:s}}const ve=`varying vec2 vUv;
|
|
3
|
+
varying vec4 vScreenPos;
|
|
4
|
+
void main() {
|
|
5
|
+
vUv = uv;
|
|
6
|
+
gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);
|
|
7
|
+
vScreenPos = gl_Position;
|
|
8
|
+
}`,xe=`varying vec2 vUv;
|
|
9
|
+
uniform vec2 uSize;
|
|
10
|
+
uniform vec4 uBorderRadius;
|
|
11
|
+
uniform float uBorderWidth;
|
|
12
|
+
uniform vec4 uBgColor;
|
|
13
|
+
uniform vec4 uBorderColor;
|
|
14
|
+
uniform float uOpacity;
|
|
15
|
+
|
|
16
|
+
uniform int uGradientCount;
|
|
17
|
+
uniform float uGradientAngle;
|
|
18
|
+
uniform vec4 uGradientColors[8];
|
|
19
|
+
uniform float uGradientStops[8];
|
|
20
|
+
|
|
21
|
+
#INJECT_DECLARATIONS
|
|
22
|
+
|
|
23
|
+
vec3 linearToSrgb(vec3 linearColor) {
|
|
24
|
+
vec3 linearPart = 12.92 * linearColor;
|
|
25
|
+
vec3 curvePart = 1.055 * pow(linearColor, vec3(1.0 / 2.4)) - 0.055;
|
|
26
|
+
vec3 switchCondition = step(vec3(0.0031308), linearColor);
|
|
27
|
+
return mix(linearPart, curvePart, switchCondition);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
vec3 srgbToLinear(vec3 srgbColor) {
|
|
31
|
+
vec3 linearPart = srgbColor / 12.92;
|
|
32
|
+
vec3 curvePart = pow((srgbColor + vec3(0.055)) / 1.055, vec3(2.4));
|
|
33
|
+
vec3 switchCondition = step(vec3(0.04045), srgbColor);
|
|
34
|
+
return mix(linearPart, curvePart, switchCondition);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
vec4 blendSrcOverInLinear(vec4 front, vec4 back) {
|
|
38
|
+
front.rgb = srgbToLinear(front.rgb);
|
|
39
|
+
back.rgb = srgbToLinear(back.rgb);
|
|
40
|
+
float aOut = front.a + back.a * (1.0 - front.a);
|
|
41
|
+
float safeAlpha = max(aOut, 0.0001);
|
|
42
|
+
vec3 cOut = (front.rgb * front.a + back.rgb * back.a * (1.0 - front.a)) / safeAlpha;
|
|
43
|
+
return vec4(linearToSrgb(cOut), aOut);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
vec4 blendSrcOver(vec4 front, vec4 back) {
|
|
47
|
+
float aOut = front.a + back.a * (1.0 - front.a);
|
|
48
|
+
float safeAlpha = max(aOut, 0.0001);
|
|
49
|
+
vec3 cOut = (front.rgb * front.a + back.rgb * back.a * (1.0 - front.a)) / safeAlpha;
|
|
50
|
+
return vec4(cOut, aOut);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
float sdRoundedBox(vec2 p, vec2 b, float r) {
|
|
54
|
+
vec2 q = abs(p) - b + r;
|
|
55
|
+
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
float sdVisualBox(vec2 p, vec2 b, float r) {
|
|
59
|
+
vec2 q = abs(p) - b + r;
|
|
60
|
+
float n = 2.01;
|
|
61
|
+
float d = pow(pow(max(q.x, 0.0), n) + pow(max(q.y, 0.0), n), 1.0/n) - r;
|
|
62
|
+
return min(max(q.x, q.y), 0.0) + d;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
vec4 calculateGradientLayer(vec2 uv) {
|
|
66
|
+
if (uGradientCount < 2) return uGradientColors[0];
|
|
67
|
+
|
|
68
|
+
vec2 dir = vec2(sin(uGradientAngle), cos(uGradientAngle));
|
|
69
|
+
vec2 p = (uv - 0.5) * uSize;
|
|
70
|
+
float proj = dot(p, dir);
|
|
71
|
+
float L = abs(uSize.x * dir.x) + abs(uSize.y * dir.y);
|
|
72
|
+
float t = clamp((proj / L) + 0.5, 0.0, 1.0);
|
|
13
73
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
uniform float uOpacity;
|
|
20
|
-
uniform float uBgOpacity;
|
|
21
|
-
uniform float uBorderOpacity;
|
|
22
|
-
|
|
23
|
-
#INJECT_DECLARATIONS
|
|
24
|
-
|
|
25
|
-
float sdRoundedBox(vec2 p, vec2 b, float r) {
|
|
26
|
-
vec2 q = abs(p) - b + r;
|
|
27
|
-
|
|
28
|
-
return min(max(q.x, q.y), 0.0) + length(max(q, 0.0)) - r;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
void main() {
|
|
32
|
-
vec2 p = (vUv - 0.5) * uSize;
|
|
33
|
-
vec2 halfSize = uSize * 0.5;
|
|
34
|
-
|
|
35
|
-
#INJECT_UV_MODIFIER
|
|
74
|
+
vec4 color = uGradientColors[0];
|
|
75
|
+
for (int i = 1; i < 8; i++) {
|
|
76
|
+
if (i >= uGradientCount) break;
|
|
77
|
+
float prevStop = uGradientStops[i-1];
|
|
78
|
+
float currStop = uGradientStops[i];
|
|
36
79
|
|
|
37
|
-
|
|
38
|
-
|
|
80
|
+
float factor = clamp((t - prevStop) / (currStop - prevStop + 0.00001), 0.0, 1.0);
|
|
81
|
+
color = mix(color, uGradientColors[i], factor);
|
|
82
|
+
}
|
|
83
|
+
// return vec4(linearToSrgb(color.rgb), color.a);
|
|
84
|
+
return vec4(color);
|
|
85
|
+
}
|
|
39
86
|
|
|
40
|
-
|
|
87
|
+
void main() {
|
|
88
|
+
vec2 p = (vUv - 0.5) * uSize;
|
|
89
|
+
vec2 halfSize = uSize * 0.5;
|
|
41
90
|
|
|
42
|
-
|
|
43
|
-
vec2 xRadii = mix(uBorderRadius.xw, uBorderRadius.yz, step(0.0, p.x));
|
|
44
|
-
float r = mix(xRadii.y, xRadii.x, step(0.0, p.y));
|
|
45
|
-
float d = sdRoundedBox(p, halfSize, r);
|
|
91
|
+
#INJECT_UV_MODIFIER
|
|
46
92
|
|
|
47
|
-
|
|
48
|
-
|
|
93
|
+
// color decision pipeline
|
|
94
|
+
vec4 baseColor = vec4(uBgColor.rgb, uBgColor.a);
|
|
49
95
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
borderAlpha = 0.0;
|
|
55
|
-
}
|
|
96
|
+
if (uGradientCount > 0) {
|
|
97
|
+
vec4 gradColor = calculateGradientLayer(vUv);
|
|
98
|
+
baseColor = blendSrcOver(gradColor, baseColor);
|
|
99
|
+
}
|
|
56
100
|
|
|
57
|
-
|
|
58
|
-
float aFront = borderAlpha;
|
|
59
|
-
float aBack = baseColor.a;
|
|
60
|
-
float aOut = aFront + aBack * (1.0 - aFront);
|
|
101
|
+
#INJECT_BASE_COLOR
|
|
61
102
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
103
|
+
// Hybrid SDF
|
|
104
|
+
vec2 xRadii = mix(uBorderRadius.xw, uBorderRadius.yz, step(0.0, p.x));
|
|
105
|
+
float r = mix(xRadii.y, xRadii.x, step(0.0, p.y));
|
|
106
|
+
r = min(r, min(halfSize.x, halfSize.y));
|
|
65
107
|
|
|
66
|
-
|
|
67
|
-
#INJECT_COLOR_MODIFIER
|
|
108
|
+
float d = sdRoundedBox(p, halfSize, r);
|
|
68
109
|
|
|
69
|
-
|
|
70
|
-
|
|
110
|
+
float d_smooth = sdVisualBox(p, halfSize, r);
|
|
111
|
+
float d_visual = d_smooth / fwidth(d_smooth);
|
|
71
112
|
|
|
72
|
-
|
|
113
|
+
// rendering pipeline
|
|
114
|
+
float bgMask = 1.0 - smoothstep(-0.5, 0.5, d_visual);
|
|
73
115
|
|
|
74
|
-
|
|
116
|
+
float halfBorder = uBorderWidth * 0.5;
|
|
117
|
+
float borderD = abs(d + halfBorder) - halfBorder;
|
|
118
|
+
float borderAlpha = (1.0 - smoothstep(0.0, 1.0, borderD)) * uBorderColor.a;
|
|
119
|
+
if (uBorderWidth <= 0.01) {
|
|
120
|
+
borderAlpha = 0.0;
|
|
75
121
|
}
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
`:"",c=(s==null?void 0:s.colorModifier)||"",p=$.replace("#INJECT_DECLARATIONS",a).replace("#INJECT_UV_MODIFIER",o).replace("#INJECT_BASE_COLOR",l).replace("#INJECT_COLOR_MODIFIER",c),f=F(i.backgroundColor),m=F(i.borderColor),v={uSize:{value:new h.Vector2(e,t)},uBorderRadius:{value:new h.Vector4(0,0,0,0)},uBorderWidth:{value:S(i.borderWidth)},uBgColor:{value:f.color},uBorderColor:{value:m.color},uOpacity:{value:(y=i.opacity)!=null?y:1},uBgOpacity:{value:f.alpha},uBorderOpacity:{value:m.alpha},uTexture:{value:null}};return P(v.uBorderRadius.value,i.borderRadius),n&&(v.uTexture.value=r),new h.ShaderMaterial({uniforms:v,vertexShader:H,fragmentShader:p,transparent:!0,side:h.FrontSide})}function j(i,e,t,r,s){var o;const n=F(e.backgroundColor),a=F(e.borderColor);i.uniforms.uSize.value.set(t,r),P(i.uniforms.uBorderRadius.value,e.borderRadius),i.uniforms.uBorderWidth.value=S(e.borderWidth),i.uniforms.uBgColor.value.copy(n.color),i.uniforms.uBorderColor.value.copy(a.color),i.uniforms.uOpacity.value=(o=e.opacity)!=null?o:1,i.uniforms.uBgOpacity.value=n.alpha,i.uniforms.uBorderOpacity.value=a.alpha,i.uniforms.uTexture&&s!==void 0&&(i.uniforms.uTexture.value=s)}const I={create(i,e,t,r,s,n=2,a=null){if(i==="BOX")return G(e,r,s,a);if(i==="TEXT"){const o=Y(t||"",e,r,s,n);return new h.MeshBasicMaterial({map:o,transparent:!0,side:h.FrontSide,color:16777215})}return new h.MeshBasicMaterial({visible:!1})},update(i,e,t,r,s,n,a=2,o){if(e==="BOX")j(i,t,s,n,o);else if(e==="TEXT"){const l=i;l.map&&l.map.dispose();const c=Y(r||"",t,s,n,a);l.map=c,l.needsUpdate=!0}}};class J{constructor(e,t,r){d(this,"canvas");d(this,"scene");d(this,"camera");d(this,"renderer");d(this,"renderTarget",null);d(this,"renderOrder",0);d(this,"qualityFactor",2);d(this,"mode","overlay");d(this,"target");d(this,"mountContainer");d(this,"targetRect");d(this,"meshMap",new Map);var a,o;this.target=e,this.mountContainer=r,this.mode=(a=t.mode)!=null?a:"overlay",this.canvas=document.createElement("canvas"),this.scene=new h.Scene,this.targetRect=this.target.getBoundingClientRect();const s=this.targetRect.width,n=this.targetRect.height;this.camera=new h.OrthographicCamera(s/-2,s/2,n/2,n/-2,1,1e3),this.camera.position.z=100,this.camera.layers.set(0),this.renderer=new h.WebGLRenderer({canvas:this.canvas,alpha:!0,antialias:!0}),this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(s,n),this.applyTextQuality((o=t.quality)!=null?o:"medium")}createRenderTarget(){this.renderTarget=new h.WebGLRenderTarget(this.targetRect.width*this.qualityFactor,this.targetRect.height*this.qualityFactor,{minFilter:h.LinearFilter,magFilter:h.LinearFilter,format:h.RGBAFormat,stencilBuffer:!1,depthBuffer:!0,samples:4})}applyTextQuality(e){if(typeof e=="number"){this.qualityFactor=Math.max(.1,e);return}switch(e){case"low":this.qualityFactor=1;break;case"high":this.qualityFactor=4;break;case"medium":default:this.qualityFactor=2;break}}mount(){this.mountContainer.prepend(this.canvas),this.canvas.style.pointerEvents=this.mode==="overlay"?"none":"auto",this.updateCanvasLayout()}updateCanvasLayout(){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")}dispose(){this.renderer.dispose(),this.canvas.remove()}setSize(e,t){this.renderer.setSize(e,t),this.renderTarget&&this.renderTarget.setSize(e*this.qualityFactor,t*this.qualityFactor),this.camera.left=e/-2,this.camera.right=e/2,this.camera.top=t/2,this.camera.bottom=t/-2,this.camera.updateProjectionMatrix()}syncScene(e){const t=this.target.getBoundingClientRect(),r=Math.abs(t.width-this.targetRect.width)>.1||Math.abs(t.height-this.targetRect.height)>.1,s=this.mode==="overlay"&&(Math.abs(t.top-this.targetRect.top)>.1||Math.abs(t.left-this.targetRect.left)>.1);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;const n=new Set;this.reconcileNode(e,n);for(const[a,o]of this.meshMap.entries())n.has(a)||(this.scene.remove(o),o.geometry.dispose(),o.material instanceof h.Material&&o.material.dispose(),this.meshMap.delete(a))}reconcileNode(e,t){var s;t.add(e.element);let r=this.meshMap.get(e.element);if(!r){const n=new h.PlaneGeometry(1,1);let a;a=I.create("BOX",e.styles,"",e.rect.width,e.rect.height,this.qualityFactor,e.isTraveler?(s=this.renderTarget)==null?void 0:s.texture:void 0),r=new h.Mesh(n,a),e.type==="TEXT"&&(r.name="BG_MESH"),this.scene.add(r),this.meshMap.set(e.element,r)}if(r.userData.domRect=e.rect,this.updateMeshProperties(r,e),this.updateMeshLayers(r,e),e.isTraveler&&r.layers.enable(28),e.type==="BOX")for(const n of e.children)this.reconcileNode(n,t);else e.type==="TEXT"&&this.reconcileTextChild(r,e)}reconcileTextChild(e,t){var o,l;let r=e.children.find(c=>c.name==="TEXT_CHILD");const s=JSON.stringify(t.textStyles),n=(o=r==null?void 0:r.userData)==null?void 0:o.styleHash;if(!r||t.dirtyMask&L||s!==n){r&&((l=r.material.map)==null||l.dispose(),r.geometry.dispose(),e.remove(r));const c=I.create("TEXT",t.textStyles,t.textContent||"",t.rect.width,t.rect.height,this.qualityFactor),p=new h.PlaneGeometry(1,1);r=new h.Mesh(p,c),r.name="TEXT_CHILD",r.userData={styleHash:s},this.updateMeshLayers(r,t),r.position.z=.005,e.add(r)}if(r){const c=e.userData.domRect,p=c.x+c.width/2,f=c.y+c.height/2,m=t.rect.x+t.rect.width/2,v=t.rect.y+t.rect.height/2,b=m-p,y=-(v-f);r.position.set(b,y,.005)}}updateMeshProperties(e,t){var v;const{rect:r,styles:s}=t,n=this.renderer.getPixelRatio(),a=this.renderer.domElement.width/n,o=this.renderer.domElement.height/n;e.scale.set(r.width,r.height,1);const l=.001;this.renderOrder++;const c=this.targetRect.left+window.scrollX,p=this.targetRect.top+window.scrollY,f=r.x-c,m=r.y-p;e.position.set(f-a/2+r.width/2,-m+o/2-r.height/2,s.zIndex+this.renderOrder*l),I.update(e.material,"BOX",t.styles,"",t.rect.width,t.rect.height,this.qualityFactor,t.isTraveler?(v=this.renderTarget)==null?void 0:v.texture:void 0)}updateMeshLayers(e,t){const r=(1-(t.visibility&R))*30;e.layers.set(r),t.visibility===(R|E)&&e.layers.enable(29)}captureRenderTarget(){const e=[];for(const l of this.meshMap.values())l.layers.mask&1<<28&&e.push(l);if(e.length===0)return;const t=new h.Color,r=this.renderer.getClearAlpha();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);const s=new h.Vector3,n=this.targetRect.width,a=this.targetRect.height,o=this.renderer.getPixelRatio();for(const l of e){s.setFromMatrixPosition(l.matrixWorld),s.project(this.camera);const c=(s.x+1)/2*n,p=(s.y+1)/2*a,f=l.scale.x,m=l.scale.y,v=c-f/2,b=p-m/2,y=v*this.qualityFactor/o,_=b*this.qualityFactor/o,z=f*this.qualityFactor/o,g=m*this.qualityFactor/o;this.renderer.setScissor(y,_,z,g),this.renderer.render(this.scene,this.camera)}this.renderer.setScissorTest(!1),this.renderer.autoClear=!0,this.renderer.setRenderTarget(null),this.camera.layers.set(28),this.renderer.setClearColor(t,r)}render(){this.renderTarget&&this.captureRenderTarget(),this.renderer.render(this.scene,this.camera)}showScissoredRenderTarget(){if(!this.renderTarget)return;const e=this.targetRect.width,t=this.targetRect.height,r=new h.PlaneGeometry(e,t),s=new h.MeshBasicMaterial({map:this.renderTarget.texture,side:h.DoubleSide,transparent:!0,opacity:.8}),n=new h.Mesh(r,s);n.position.set(0,0,90),n.layers.set(28),this.scene.add(n)}}function V(i){const e=document.createRange();e.selectNodeContents(i);const t=e.getBoundingClientRect();return{left:t.left,top:t.top,width:t.width,height:t.height}}function Z(i){const e=parseFloat(i.fontSize);let t=parseFloat(i.lineHeight);isNaN(t)&&(t=e*1.2);let r=parseFloat(i.letterSpacing);return isNaN(r)&&(r=0),{font:`${i.fontStyle} ${i.fontWeight} ${i.fontSize} ${i.fontFamily}`,color:i.color,textAlign:i.textAlign||"start",textBaseline:"alphabetic",direction:i.direction||"inherit",lineHeight:t,letterSpacing:r}}function U(i,e=B|O|A|L|D,t,r){if(i.nodeType===Node.TEXT_NODE){const g=i;if(!g.textContent||!g.textContent.trim())return null;const x=g.textContent.replace(/\s+/g," ").trim();if(x.length===0)return null;const C=V(g);if(C.width===0||C.height===0)return null;const k=g.parentElement,N=k?window.getComputedStyle(k):null;return N?{id:Math.random().toString(36).substring(2,9),type:"TEXT",element:g,rect:{x:C.left+window.scrollX,y:C.top+window.scrollY,width:C.width,height:C.height},styles:{backgroundColor:"transparent",opacity:parseFloat(N.opacity),zIndex:0,borderRadius:"0px",borderColor:"transparent",borderWidth:"0px"},textContent:x,textStyles:Z(N),dirtyMask:e,visibility:t,isTraveler:!1,children:[]}:null}const s=i,n=s.dataset.mirageFilter;let a=t,o=t;if(n){const g=new Set(n.split(/\s+/));for(const x of g)if(!X.includes(x))throw new Error(`[MirageEngine] Invalid filter token: '${x}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`);if(g.has("end"))return null;if(g.has("include-tree")&&g.has("exclude-tree"))throw new Error("[MirageEngine] Conflicting filters: 'include-tree' and 'exclude-tree' cannot be used together on the same element.");if(g.has("include-self")&&g.has("exclude-self"))throw new Error("[MirageEngine] Conflicting filters: 'include-self' and 'exclude-self' cannot be used together on the same element.");g.has("include-tree")?a=a|R:g.has("exclude-tree")&&(a=a&~R),o=a,g.has("include-self")?o=o|R:g.has("exclude-self")&&(o=o&~R)}o=o|t&E;const l=s.dataset.mirageTravel;let c=!1;l&&new Set(l.split(/\s+/)).has("traveler")&&(o=o&~E,a=a&~E,c=!0);const p=s.getBoundingClientRect(),f=window.getComputedStyle(s);if(p.width===0||p.height===0||f.display==="none")return null;let m=s.getAttribute("data-mid");m||(m=Math.random().toString(36).substring(2,11),s.setAttribute("data-mid",m));const v=parseInt(f.zIndex),b={backgroundColor:f.backgroundColor,opacity:parseFloat(f.opacity),zIndex:isNaN(v)?0:v,borderRadius:f.borderRadius,borderColor:f.borderColor,borderWidth:f.borderWidth};let y,_;const z=[];return Array.from(s.childNodes).forEach(g=>{const x=g.nodeType===Node.TEXT_NODE?o:a,C=U(g,e,x);C&&z.push(C)}),{id:m,type:"BOX",element:s,rect:{x:p.left+window.scrollX,y:p.top+window.scrollY,width:p.width,height:p.height},styles:b,textContent:y,textStyles:_,dirtyMask:e,visibility:o,isTraveler:c,children:z}}class Q{constructor(e,t,r){d(this,"target");d(this,"renderer");d(this,"filter");d(this,"observer");d(this,"isDomDirty",!1);d(this,"isRunning",!1);d(this,"isTravelEnabled",!1);d(this,"pendingMask",M);d(this,"mutationTimer",null);d(this,"cssTimer",null);d(this,"resizeConfig");d(this,"resizeTimer",null);d(this,"isResizing",!1);d(this,"onTransitionFinished",e=>{this.target.contains(e.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.pendingMask|=B|O,this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50))});d(this,"onWindowResize",()=>{if(!this.resizeConfig.enabled){this.isDomDirty=!0;return}this.isResizing||(this.isResizing=!0,this.resizeConfig.onStart&&this.resizeConfig.onStart()),this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.resizeConfig.onEnd&&this.resizeConfig.onEnd(),this.isResizing=!1,this.resizeTimer=null},this.resizeConfig.delay)});d(this,"renderLoop",()=>{this.isRunning&&(this.isDomDirty&&this.forceUpdateScene(),this.renderer.render(),requestAnimationFrame(this.renderLoop))});var n,a;this.target=e,this.renderer=t,this.filter=r.filter;const s=(n=r.resizeDebounce)!=null?n:!0;s===!1?this.resizeConfig={enabled:!1,delay:0}:s===!0?this.resizeConfig={enabled:!0,delay:150}:this.resizeConfig={enabled:!0,delay:(a=s.delay)!=null?a:150,onStart:s.onStart,onEnd:s.onEnd},this.observer=new MutationObserver(o=>{let l=M;for(const c of o)c.type==="childList"?l|=D:c.type==="attributes"&&(c.attributeName==="style"||c.attributeName==="class")&&(l|=B|O);if(l!==M){if(this.pendingMask|=l,l&D){this.clearTimers(),console.log("Structural Change detected"),this.isDomDirty=!0;return}this.mutationTimer&&clearTimeout(this.mutationTimer),this.mutationTimer=window.setTimeout(()=>{this.mutationTimer=null,this.isDomDirty=!0},200)}})}start(){this.isRunning||(this.isRunning=!0,this.observer.observe(this.target,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),this.target.addEventListener("transitionend",this.onTransitionFinished),this.target.addEventListener("animationend",this.onTransitionFinished),window.addEventListener("resize",this.onWindowResize),this.forceUpdateScene(),this.renderLoop())}stop(){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)}clearTimers(){this.mutationTimer&&(clearTimeout(this.mutationTimer),this.mutationTimer=null),this.cssTimer&&(clearTimeout(this.cssTimer),this.cssTimer=null)}forceUpdateScene(){this.isDomDirty=!1;const e=document.querySelector("[data-mirage-travel='traveler']")!==null;e&&!this.isTravelEnabled&&(this.isTravelEnabled=!0,this.renderer.createRenderTarget());const t=U(this.target,this.pendingMask,e?R|E:R,this.filter);t&&this.renderer.syncScene(t),this.pendingMask=M}}class K{constructor(e,t){d(this,"renderer");d(this,"syncer");d(this,"target");var s,n,a;this.target=e;let r;if(t.mode==="duplicate"?r=(n=(s=t.container)!=null?s:this.target.parentElement)!=null?n:void 0:r=(a=this.target.parentElement)!=null?a:void 0,!r)throw new Error("[Mirage] Cannot find a container (parent or option).");this.renderer=new J(this.target,t,r),this.renderer.mount(),this.syncer=new Q(this.target,this.renderer,t)}start(){this.syncer.start()}stop(){this.syncer.stop()}dispose(){this.syncer.stop(),this.renderer.dispose()}}u.ALLOWED_FILTERS=X,u.DIRTY_CONTENT=L,u.DIRTY_NONE=M,u.DIRTY_RECT=B,u.DIRTY_STRUCTURE=D,u.DIRTY_STYLE=O,u.DIRTY_ZINDEX=A,u.EXCLUDED=q,u.Engine=K,u.SYSTEM_LAYER=E,u.USER_LAYER=R,Object.defineProperty(u,Symbol.toStringTag,{value:"Module"})});
|
|
122
|
+
|
|
123
|
+
// final blending (border + background) using blendSrcOver
|
|
124
|
+
vec4 borderLayer = vec4(uBorderColor.rgb, borderAlpha);
|
|
125
|
+
vec4 finalColor = blendSrcOver(borderLayer, baseColor);
|
|
126
|
+
// final color control (Tint, Noise)
|
|
127
|
+
#INJECT_COLOR_MODIFIER
|
|
128
|
+
|
|
129
|
+
float finalOpacity = finalColor.a * bgMask * uOpacity;
|
|
130
|
+
if (finalOpacity < 0.001) discard;
|
|
131
|
+
|
|
132
|
+
gl_FragColor = vec4(finalColor.rgb, finalOpacity);
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
// #include <colorspace_fragment>
|
|
136
|
+
}
|
|
137
|
+
`,ye=`uniform sampler2D uTexture;
|
|
138
|
+
varying vec4 vScreenPos;
|
|
139
|
+
uniform vec2 uTextureRepeat;
|
|
140
|
+
uniform vec2 uTextureOffset;`,Te=`vec2 screenUv = (vScreenPos.xy / vScreenPos.w) * 0.5 + 0.5;
|
|
141
|
+
vec2 resultUv = screenUv;
|
|
142
|
+
|
|
143
|
+
`,Ce=`vec4 texColor = texture2D(uTexture, resultUv);
|
|
144
|
+
baseColor = blendSrcOver(baseColor, texColor);`,re={vertexShader:ve,fragmentShader:xe},j={declChunk:ye,uvChunk:Te,baseColorChunk:Ce};function we(n,e,t,i=null,r){var x;const a=i!==null||!!n.imageSrc,o=a?j.declChunk:"",s=n.isTraveler?j.uvChunk:`vec2 resultUv = vUv * uTextureRepeat + uTextureOffset;
|
|
145
|
+
`,l=a?s+((r==null?void 0:r.uvModifier)||""):"",c=a?j.baseColorChunk:"",d=(r==null?void 0:r.colorModifier)||"",f=re.fragmentShader.replace("#INJECT_DECLARATIONS",o).replace("#INJECT_UV_MODIFIER",l).replace("#INJECT_BASE_COLOR",c).replace("#INJECT_COLOR_MODIFIER",d),h=U(n.backgroundColor),m=U(n.borderColor),g={uSize:{value:new p.Vector2(e,t)},uBgColor:{value:new p.Vector4(h.color.r,h.color.g,h.color.b,h.alpha)},uBorderColor:{value:new p.Vector4(m.color.r,m.color.g,m.color.b,m.alpha)},uBorderRadius:{value:new p.Vector4(0,0,0,0)},uBorderWidth:{value:N(n.borderWidth)},uOpacity:{value:(x=n.opacity)!=null?x:1},uTexture:{value:null},uTextureRepeat:{value:new p.Vector2(1,1)},uTextureOffset:{value:new p.Vector2(0,0)},uGradientCount:{value:0},uGradientAngle:{value:0},uGradientColors:{value:Array.from({length:8},()=>new p.Vector4(0,0,0,0))},uGradientStops:{value:new Float32Array(8)}};ie(g.uBorderRadius.value,n.borderRadius),a&&(g.uTexture.value=i);const C=new p.ShaderMaterial({uniforms:g,vertexShader:re.vertexShader,fragmentShader:f,transparent:!0,side:p.FrontSide});return n.backgroundImage&&$(C,{backgroundImage:n.backgroundImage}),C}function Se(n,e,t,i,r){const a=N(e.borderWidth);$(n,{width:t,height:i,borderRadius:e.borderRadius,borderWidth:a,backgroundColor:e.backgroundColor,borderColor:e.borderColor,opacity:e.opacity,texture:r,backgroundImage:e.backgroundImage})}function $(n,e){var i,r,a;if(e.width!==void 0&&e.height!==void 0&&n.uniforms.uSize.value.set(e.width,e.height),e.borderRadius!==void 0&&ie(n.uniforms.uBorderRadius.value,e.borderRadius),e.borderWidth!==void 0&&(n.uniforms.uBorderWidth.value=e.borderWidth),e.backgroundColor!==void 0)if(Array.isArray(e.backgroundColor)){const o=n.uniforms.uBgColor.value.w;n.uniforms.uBgColor.value.set(e.backgroundColor[0],e.backgroundColor[1],e.backgroundColor[2],o)}else if(typeof e.backgroundColor=="string"){const o=U(e.backgroundColor);n.uniforms.uBgColor.value.set(o.color.r,o.color.g,o.color.b,o.alpha)}else{const o=n.uniforms.uBgColor.value.w;n.uniforms.uBgColor.value.set(e.backgroundColor.r,e.backgroundColor.g,e.backgroundColor.b,o)}if(e.borderColor!==void 0)if(Array.isArray(e.borderColor)){const o=n.uniforms.uBorderColor.value.w;n.uniforms.uBorderColor.value.set(e.borderColor[0],e.borderColor[1],e.borderColor[2],o)}else if(typeof e.borderColor=="string"){const o=U(e.borderColor);n.uniforms.uBorderColor.value.set(o.color.r,o.color.g,o.color.b,o.alpha)}else{const o=n.uniforms.uBorderColor.value.w;n.uniforms.uBorderColor.value.set(e.borderColor.r,e.borderColor.g,e.borderColor.b,o)}e.opacity!==void 0&&(n.uniforms.uOpacity.value=e.opacity),e.bgOpacity!==void 0&&(n.uniforms.uBgColor.value.w=e.bgOpacity),e.borderOpacity!==void 0&&(n.uniforms.uBorderColor.value.w=e.borderOpacity),n.uniforms.uTexture&&e.texture!==void 0&&(n.uniforms.uTexture.value=e.texture);const t=e.texture!==void 0?e.texture:(i=n.uniforms.uTexture)==null?void 0:i.value;if(t&&(t.image instanceof ImageBitmap||t.image instanceof HTMLImageElement||t.image instanceof HTMLCanvasElement)){const o=t.image.width,s=t.image.height,l=(r=e.width)!=null?r:n.uniforms.uSize.value.x,c=(a=e.height)!=null?a:n.uniforms.uSize.value.y;if(o&&s&&l&&c){const d=o/s,f=l/c;if(d>f){const h=f/d;n.uniforms.uTextureRepeat.value.set(h,1),n.uniforms.uTextureOffset.value.set((1-h)/2,0)}else{const h=d/f;n.uniforms.uTextureRepeat.value.set(1,h),n.uniforms.uTextureOffset.value.set(0,(1-h)/2)}}}else n.uniforms.uTextureRepeat&&(n.uniforms.uTextureRepeat.value.set(1,1),n.uniforms.uTextureOffset.value.set(0,0));if(e.backgroundImage!==void 0){const o=be(e.backgroundImage);if(o){n.uniforms.uGradientCount.value=o.stops.length,n.uniforms.uGradientAngle.value=o.angle;for(let s=0;s<8;s++)if(s<o.stops.length){const l=o.stops[s];n.uniforms.uGradientColors.value[s].set(l.color.r,l.color.g,l.color.b,l.alpha),console.log(l.color.r,l.color.g,l.color.b),n.uniforms.uGradientStops.value[s]=l.stop}else n.uniforms.uGradientColors.value[s].set(0,0,0,0),n.uniforms.uGradientStops.value[s]=1}else n.uniforms.uGradientCount.value=0}}function ie(n,e){var s,l,c,d;if(e==null){n.set(0,0,0,0);return}if(typeof e=="number"){n.set(e,e,e,e);return}if(Array.isArray(e)){n.set(e[0],e[1],e[2],e[3]);return}const t=e.split("/")[0].trim().split(/\s+/),i=N(t[0]),r=N((s=t[1])!=null?s:t[0]),a=N((l=t[2])!=null?l:t[0]),o=N((d=(c=t[3])!=null?c:t[1])!=null?d:t[0]);n.set(i,r,a,o)}const W={create(n,e,t,i,r,a=2,o=null,s){return n==="BOX"?we(e,i,r,o,s):n==="TEXT"?new pe(t||"",e,i,r,a):new p.MeshBasicMaterial({visible:!1})},update(n,e,t,i,r,a,o=2,s){e==="BOX"?Se(n,t,r,a,s):e==="TEXT"&&n.updateText(i||"",t,r,a,o)},forceUpdateUniforms(n,e){$(n,e)}};class Re{constructor(e){u(this,"observer");u(this,"textures",new WeakMap);u(this,"loadStatus",new WeakMap);u(this,"elementUrls",new WeakMap);u(this,"onUpdate");this.onUpdate=e,this.observer=new IntersectionObserver(t=>{for(const i of t){const r=i.target;i.isIntersecting?this.loadTexture(r):this.disposeTexture(r)}},{rootMargin:"300px"})}register(e,t){if(e.nodeType!==Node.ELEMENT_NODE)return;this.elementUrls.get(e)!==t&&(this.elementUrls.set(e,t),this.observer.unobserve(e),this.observer.observe(e))}unregister(e){e.nodeType===Node.ELEMENT_NODE&&this.observer.unobserve(e),this.disposeTexture(e),this.elementUrls.delete(e),this.loadStatus.delete(e)}loadTexture(e){return fe(this,null,function*(){if(this.loadStatus.get(e)||this.textures.has(e))return;const t=this.elementUrls.get(e);if(t){this.loadStatus.set(e,!0);try{const r=yield(yield fetch(t)).blob(),a=yield createImageBitmap(r,{imageOrientation:"flipY"});if(this.elementUrls.get(e)!==t){a.close();return}const o=new p.CanvasTexture(a);o.needsUpdate=!0,this.textures.set(e,o),this.onUpdate(e,o)}catch(i){console.warn("[MirageEngine] Failed to load texture:",t,i)}finally{this.elementUrls.has(e)&&this.loadStatus.set(e,!1)}}})}disposeTexture(e){const t=this.textures.get(e);t&&(t.dispose(),this.textures.delete(e),this.onUpdate(e,null)),this.loadStatus.set(e,!1)}get(e){return this.textures.get(e)}disposeAll(){this.observer.disconnect()}}class Me{constructor(e,t,i,r){u(this,"canvas");u(this,"scene");u(this,"camera");u(this,"renderer");u(this,"renderTarget",null);u(this,"renderOrder",0);u(this,"qualityFactor",2);u(this,"mode","overlay");u(this,"clipArea",1);u(this,"target");u(this,"mountContainer");u(this,"registry");u(this,"targetRect");u(this,"travelers",new Set);u(this,"textureManager");u(this,"fixedMeshes",new Set);var s,l,c;this.target=e,this.mountContainer=i,this.registry=r,this.textureManager=new Re((d,f)=>{const h=this.registry.get(d);h&&h.material instanceof p.ShaderMaterial&&W.forceUpdateUniforms(h.material,{texture:f})}),this.mode=(s=t.mode)!=null?s:"overlay",this.clipArea=(l=t.travelerClipArea)!=null?l:1,this.canvas=document.createElement("canvas"),this.scene=new p.Scene,this.targetRect=this.target.getBoundingClientRect();const a=this.targetRect.width,o=this.targetRect.height;this.camera=new p.OrthographicCamera(a/-2,a/2,o/2,o/-2,1,1e3),this.camera.position.z=100,this.camera.layers.set(0),this.renderer=new p.WebGLRenderer({canvas:this.canvas,alpha:!0,antialias:!0}),p.ColorManagement.enabled=!1,this.renderer.outputColorSpace=p.LinearSRGBColorSpace,this.renderer.setPixelRatio(window.devicePixelRatio),this.renderer.setSize(a,o),this.applyTextQuality((c=t.quality)!=null?c:"medium")}createRenderTarget(){this.renderTarget=new p.WebGLRenderTarget(this.targetRect.width*this.qualityFactor,this.targetRect.height*this.qualityFactor,{minFilter:p.LinearFilter,magFilter:p.LinearFilter,format:p.RGBAFormat,stencilBuffer:!1,depthBuffer:!0})}applyTextQuality(e){if(typeof e=="number"){this.qualityFactor=Math.max(.1,e);return}switch(e){case"low":this.qualityFactor=1;break;case"high":this.qualityFactor=4;break;case"medium":default:this.qualityFactor=2;break}}mount(){this.mountContainer.prepend(this.canvas),this.canvas.style.pointerEvents=this.mode==="overlay"?"none":"auto",this.updateCanvasLayout()}updateCanvasLayout(){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")}dispose(){this.renderer.dispose(),this.canvas.remove(),this.textureManager.disposeAll()}setSize(e,t){this.renderer.setSize(e,t),this.renderTarget&&this.renderTarget.setSize(e*this.qualityFactor,t*this.qualityFactor),this.camera.left=e/-2,this.camera.right=e/2,this.camera.top=t/2,this.camera.bottom=t/-2,this.camera.updateProjectionMatrix()}syncScene(e,t){const i=this.target.getBoundingClientRect(),r=Math.abs(i.width-this.targetRect.width)>.1||Math.abs(i.height-this.targetRect.height)>.1,a=this.mode==="overlay"&&(Math.abs(i.top-this.targetRect.top)>.1||Math.abs(i.left-this.targetRect.left)>.1);r?(this.targetRect=i,this.setSize(this.targetRect.width,this.targetRect.height),this.updateCanvasLayout()):a?(this.targetRect=i,this.updateCanvasLayout()):this.targetRect=i,this.renderOrder=0,this.reconcileNode(e),t.size>0&&t.forEach(o=>{const s=this.registry.get(o);s&&(this.scene.remove(s),this.travelers.delete(s),this.fixedMeshes.delete(s),s.geometry.dispose(),s.traverse(l=>{l instanceof p.Mesh&&(l.geometry&&l.geometry.dispose(),l.material&&(Array.isArray(l.material)?l.material.forEach(c=>c.dispose()):l.material.dispose()))}),this.registry.remove(o),this.textureManager.unregister(o))})}reconcileNode(e){var i;let t=this.registry.get(e.element);if(!t){const r=new p.PlaneGeometry(1,1);let a;const o=e.isTraveler?(i=this.renderTarget)==null?void 0:i.texture:this.textureManager.get(e.element);a=W.create("BOX",e.styles,"",e.rect.width,e.rect.height,this.qualityFactor,o,e.shaderHooks),t=new p.Mesh(r,a),e.type==="TEXT"&&(t.name="BG_MESH"),this.scene.add(t),this.registry.register(e.element,t)}if(t.userData.domRect=e.rect,this.updateMeshProperties(t,e),this.updateMeshLayers(t,e),e.isTraveler?(t.layers.enable(28),this.travelers.add(t)):(t.layers.disable(28),this.travelers.delete(t)),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")for(const r of e.children)this.reconcileNode(r);else e.type==="TEXT"&&this.reconcileTextChild(t,e)}reconcileTextChild(e,t){var s;const i=t.textLines||[{text:t.textContent||"",rect:t.rect}],r=JSON.stringify(t.textStyles)+t.textContent+i.map(l=>l.text).join("|"),a=(s=e.userData)==null?void 0:s.textChildStyleHash;if(t.dirtyMask&A||r!==a){e.children.filter(h=>h.name.startsWith("TEXT_CHILD")).forEach(h=>{var g;const m=h;(g=m.material.map)==null||g.dispose(),m.geometry.dispose(),e.remove(m)});const c=t.rect,d=c.x+c.width/2,f=c.y+c.height/2;i.forEach((h,m)=>{const g=W.create("TEXT",t.textStyles,h.text,h.rect.width,h.rect.height,this.qualityFactor),C=new p.PlaneGeometry(1,1),x=new p.Mesh(C,g);x.name=`TEXT_CHILD_${m}`,this.updateMeshLayers(x,t);const R=t.rect.width===0?1:h.rect.width/t.rect.width,D=t.rect.height===0?1:h.rect.height/t.rect.height;x.scale.set(R,D,1);const k=h.rect.x+h.rect.width/2,F=h.rect.y+h.rect.height/2,b=k-d,w=-(F-f);x.position.set(t.rect.width===0?0:b/t.rect.width,t.rect.height===0?0:w/t.rect.height,.005),e.add(x)}),e.userData.textChildStyleHash=r}}updateMeshProperties(e,t){var b;const{rect:i,styles:r}=t,a=this.renderer.getPixelRatio(),o=this.renderer.domElement.width/a,s=this.renderer.domElement.height/a;e.scale.set(i.width,i.height,1);const l=.001;this.renderOrder++;const c=this.targetRect.left+window.scrollX,d=this.targetRect.top+window.scrollY,f=i.x-c,h=i.y-d,m=f-o/2+i.width/2,g=-h+s/2-i.height/2;e.position.set(m,g,r.zIndex+this.renderOrder*l);const C=i.x,x=i.y;e.userData.basePosition={x:m,y:g},e.userData.originalBasePosition={x:m,y:g},e.userData.baseSize={width:i.width,height:i.height},e.userData.baseDOM={x:C,y:x},e.userData.isFixed=t.isFixed,e.userData.initialScroll={x:window.scrollX,y:window.scrollY};const R=t.element.nodeType===Node.TEXT_NODE?t.element.parentElement:t.element,D=window.getComputedStyle(R);let k=0,F=0;if(D.transform&&D.transform!=="none"){const w=new DOMMatrix(D.transform);k=w.m41,F=w.m42}e.userData.baseTransform={x:k,y:F},delete e.userData.originRatioX,delete e.userData.originRatioY,W.update(e.material,"BOX",t.styles,"",t.rect.width,t.rect.height,this.qualityFactor,t.isTraveler?(b=this.renderTarget)==null?void 0:b.texture:this.textureManager.get(t.element))}updateMeshLayers(e,t){const i=(1-(t.visibility&B))*30;e.layers.set(i),t.visibility===(B|_)&&e.layers.enable(29)}captureRenderTarget(){if(this.travelers.size===0)return;const e=new p.Color,t=this.renderer.getClearAlpha();this.renderer.getClearColor(e),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);const i=new p.Vector3,r=this.targetRect.width,a=this.targetRect.height,o=this.renderer.getPixelRatio();for(const s of this.travelers){i.setFromMatrixPosition(s.matrixWorld),i.project(this.camera);const l=(i.x+1)/2*r,c=(i.y+1)/2*a;let d=0,f=1;typeof this.clipArea=="number"?f=this.clipArea:this.clipArea.endsWith("%")?f=parseFloat(this.clipArea)/100:this.clipArea.endsWith("px")&&(d=parseFloat(this.clipArea));const h=s.scale.x*f+.5,m=s.scale.y*f+.5,g=l-h/2,C=c-m/2,x=(g*this.qualityFactor-d)/o,R=(C*this.qualityFactor-d)/o,D=(h*this.qualityFactor+d*2)/o,k=(m*this.qualityFactor+d*2)/o;this.renderer.setScissor(x,R,D,k),this.renderer.render(this.scene,this.camera)}this.renderer.setScissorTest(!1),this.renderer.autoClear=!0,this.renderer.setRenderTarget(null),this.camera.layers.set(0),this.renderer.setClearColor(e,t)}render(){this.renderTarget&&this.captureRenderTarget(),this.renderer.render(this.scene,this.camera)}showScissoredRenderTarget(){if(!this.renderTarget)return;const e=this.targetRect.width,t=this.targetRect.height,i=new p.PlaneGeometry(e,t),r=new p.MeshBasicMaterial({map:this.renderTarget.texture,side:p.DoubleSide,transparent:!0,opacity:.8}),a=new p.Mesh(i,r);a.position.set(0,0,90),a.layers.set(28),this.scene.add(a)}}function Ee(n){const e=n.textContent||"",t=[];let i="",r=null,a=-1;const o=(c,d)=>{for(let f=0;f<c.length;f++){const h=c[f],m=document.createRange();m.setStart(n,d+f),m.setEnd(n,d+f+1);const g=m.getBoundingClientRect();if(g.width===0&&g.height===0){i+=h;continue}a===-1||Math.abs(g.top-a)>g.height/2?(i&&r&&t.push({text:i,rect:{left:r.left,top:r.top,width:r.right-r.left,height:r.bottom-r.top}}),i=h,r={left:g.left,top:g.top,right:g.right,bottom:g.bottom},a=g.top):(i+=h,r&&(r.left=Math.min(r.left,g.left),r.top=Math.min(r.top,g.top),r.right=Math.max(r.right,g.right),r.bottom=Math.max(r.bottom,g.bottom)))}},s=e.match(/[^\s\-]+\-?|\-|\s+/g)||[];let l=0;for(const c of s){const d=document.createRange();d.setStart(n,l),d.setEnd(n,l+c.length);const f=d.getClientRects();if(f.length>1)o(c,l);else{const h=f.length===1?f[0]:d.getBoundingClientRect();if(h.width===0&&h.height===0){i+=c,l+=c.length;continue}a===-1||Math.abs(h.top-a)>h.height/2?(i&&r&&t.push({text:i,rect:{left:r.left,top:r.top,width:r.right-r.left,height:r.bottom-r.top}}),i=c,r={left:h.left,top:h.top,right:h.right,bottom:h.bottom},a=h.top):(i+=c,r&&(r.left=Math.min(r.left,h.left),r.top=Math.min(r.top,h.top),r.right=Math.max(r.right,h.right),r.bottom=Math.max(r.bottom,h.bottom)))}l+=c.length}return i&&r&&t.push({text:i,rect:{left:r.left,top:r.top,width:r.right-r.left,height:r.bottom-r.top}}),t.filter(c=>c.text.trim().length>0&&c.rect.width>0&&c.rect.height>0)}function De(n){const e=parseFloat(n.fontSize);let t=parseFloat(n.lineHeight);isNaN(t)&&(t=e*1.2);let i=parseFloat(n.letterSpacing);return isNaN(i)&&(i=0),{font:`${n.fontStyle} ${n.fontWeight} ${n.fontSize} ${n.fontFamily}`,fontSize:n.fontSize,color:n.color,textAlign:n.textAlign||"start",textBaseline:"alphabetic",direction:n.direction||"inherit",lineHeight:t,letterSpacing:i}}function ne(n,e=I|z|P|A|E,t,i){if(n.nodeType===Node.TEXT_NODE){const b=n;if(!b.textContent||!b.textContent.trim())return null;const w=b.textContent.replace(/\s+/g," ");if(w.length===0)return null;const O=Ee(b);if(O.length===0)return null;const X=b.parentElement,Y=X?window.getComputedStyle(X):null;if(!Y)return null;const G=Math.min(...O.map(y=>y.rect.left)),q=Math.min(...O.map(y=>y.rect.top)),H=Math.max(...O.map(y=>y.rect.left+y.rect.width)),V=Math.max(...O.map(y=>y.rect.top+y.rect.height));return{id:Math.random().toString(36).substring(2,9),type:"TEXT",element:b,rect:{x:G+window.scrollX,y:q+window.scrollY,width:H-G,height:V-q},styles:{backgroundColor:"transparent",backgroundImage:"",opacity:X&&X.dataset.mirageDom==="hide"?1:parseFloat(Y.opacity),zIndex:0,borderRadius:"0px",borderColor:"transparent",borderWidth:"0px",isTraveler:!1},textContent:w,textLines:O.map(y=>({text:y.text.trim(),rect:{x:y.rect.left+window.scrollX,y:y.rect.top+window.scrollY,width:y.rect.width,height:y.rect.height}})),textStyles:De(Y),dirtyMask:e,visibility:t,isTraveler:!1,isFixed:Y.position==="fixed",children:[]}}if(n.nodeType!==Node.ELEMENT_NODE)return null;const r=n,a=r.dataset.mirageFilter;let o=t,s=t;if(a){const b=new Set(a.split(/\s+/));for(const w of b)if(!ee.includes(w))throw new Error(`[MirageEngine] Invalid filter token: '${w}'. Expected one of: 'include-tree', 'exclude-tree', 'include-self', 'exclude-self', 'end'.`);if(b.has("end"))return null;if(b.has("include-tree")&&b.has("exclude-tree"))throw new Error("[MirageEngine] Conflicting filters: 'include-tree' and 'exclude-tree' cannot be used together on the same element.");if(b.has("include-self")&&b.has("exclude-self"))throw new Error("[MirageEngine] Conflicting filters: 'include-self' and 'exclude-self' cannot be used together on the same element.");b.has("include-tree")?o=o|B:b.has("exclude-tree")&&(o=o&~B),s=o,b.has("include-self")?s=s|B:b.has("exclude-self")&&(s=s&~B)}s=s|t&_;const l=r.dataset.mirageTravel;let c=!1;l&&new Set(l.split(/\s+/)).has("traveler")&&(s=s&~_,o=o&~_,c=!0);const d=r.dataset.mirageShader;let f;d&&(f=JSON.parse(d));const h=r.getBoundingClientRect(),m=window.getComputedStyle(r);if(h.width===0||h.height===0||m.display==="none")return null;let g=r.getAttribute("data-mid");g||(g=Math.random().toString(36).substring(2,11),r.setAttribute("data-mid",g));const C=parseInt(m.zIndex);let x;if(r.tagName==="IMG")x=r.src;else if(m.backgroundImage&&m.backgroundImage!=="none"){const b=m.backgroundImage.match(/url\(['"]?(.*?)['"]?\)/);b&&(x=b[1])}const R={backgroundColor:m.backgroundColor,backgroundImage:m.backgroundImage,opacity:r.dataset.mirageDom==="hide"?1:parseFloat(m.opacity),zIndex:isNaN(C)?0:C,borderRadius:m.borderRadius,borderColor:m.borderColor,borderWidth:m.borderWidth,imageSrc:x,isTraveler:c};let D,k;const F=[];return Array.from(r.childNodes).forEach(b=>{const w=b.nodeType===Node.TEXT_NODE?s:o,O=ne(b,e,w);O&&F.push(O)}),{id:g,type:"BOX",element:r,rect:{x:h.left+window.scrollX,y:h.top+window.scrollY,width:h.width,height:h.height},styles:R,textContent:D,textStyles:k,dirtyMask:e,visibility:s,isTraveler:c,isFixed:m.position==="fixed",children:F,shaderHooks:f}}function Oe(n,e){e.size!==0&&e.forEach((t,i)=>{var b,w,O,X,Y,G,q,H,V,y,oe,se,ae,ce,le,he,de,ue;const r=n.get(i);if(!r||!r.userData.basePosition)return;let{x:a,y:o}=r.userData.basePosition;const{width:s,height:l}=r.userData.baseSize,c=(b=t.width)!=null?b:s,d=(w=t.height)!=null?w:l,f=c-s,h=d-l;if(t.width!==void 0&&r.userData.originRatioX===void 0&&Math.abs(f)>.1){const J=i.getBoundingClientRect(),Z=(O=t.x)!=null?O:0,Q=(Y=(X=r.userData.baseTransform)==null?void 0:X.x)!=null?Y:0,K=r.userData.isFixed?0:window.scrollX;let S=-(J.left+K-Z+Q-r.userData.baseDOM.x)/f;Math.abs(S)<.05?S=0:Math.abs(S-1)<.05?S=1:Math.abs(S-.5)<.05&&(S=.5),r.userData.originRatioX=S}if(t.height!==void 0&&r.userData.originRatioY===void 0&&Math.abs(h)>.1){const J=i.getBoundingClientRect(),Z=(G=t.y)!=null?G:0,Q=(H=(q=r.userData.baseTransform)==null?void 0:q.y)!=null?H:0,K=r.userData.isFixed?0:window.scrollY;let S=-(J.top+K-Z+Q-r.userData.baseDOM.y)/h;Math.abs(S)<.05?S=0:Math.abs(S-1)<.05?S=1:Math.abs(S-.5)<.05&&(S=.5),r.userData.originRatioY=S}const m=(V=r.userData.originRatioX)!=null?V:.5,g=(y=r.userData.originRatioY)!=null?y:.5,C=f*(.5-m),x=h*(.5-g),R=(se=(oe=r.userData.baseTransform)==null?void 0:oe.x)!=null?se:0,D=(ce=(ae=r.userData.baseTransform)==null?void 0:ae.y)!=null?ce:0,k=((le=t.x)!=null?le:R)-R,F=((he=t.y)!=null?he:D)-D;r.position.setX(a+C+k),r.position.setY(o-(x+F)),r.scale.set(c,d,1),W.forceUpdateUniforms(r.material,{backgroundColor:t.backgroundColor,backgroundImage:t.backgroundImage,opacity:t.opacity,borderRadius:(ue=t.borderRadius)!=null?ue:(de=r.userData.baseStyles)==null?void 0:de.borderRadius,width:c,height:d})})}function ke(n,e,t){n.forEach(i=>{if(i.userData.isFixed&&i.userData.initialScroll&&i.userData.originalBasePosition){const r=e-i.userData.initialScroll.x,a=t-i.userData.initialScroll.y;i.userData.basePosition.x=i.userData.originalBasePosition.x+r,i.userData.basePosition.y=i.userData.originalBasePosition.y-a,i.position.x=i.userData.basePosition.x,i.position.y=i.userData.basePosition.y}})}function Ie(n){const e={};if(n.opacity&&(e.opacity=parseFloat(n.opacity)),n.backgroundColor&&n.backgroundColor!=="rgba(0, 0, 0, 0)"){const t=U(n.backgroundColor);e.backgroundColor=[t.color.r,t.color.g,t.color.b]}if(n.backgroundImage?e.backgroundImage=n.backgroundImage:n.background&&(e.backgroundImage=n.background),n.borderRadius&&(e.borderRadius=parseFloat(n.borderRadius)),n.width&&(e.width=parseFloat(n.width)),n.height&&(e.height=parseFloat(n.height)),n.transform&&n.transform!=="none"){const t=new DOMMatrix(n.transform);e.x=t.m41,e.y=t.m42,e.z=t.m43}return e}class Be{constructor(e,t,i,r){u(this,"target");u(this,"renderer");u(this,"registry");u(this,"filter");u(this,"observer");u(this,"pendingDeletions",new Set);u(this,"pendingStyles",new Map);u(this,"isDomDirty",!1);u(this,"isRunning",!1);u(this,"isTravelEnabled",!1);u(this,"pendingMask",L);u(this,"mutationTimer",null);u(this,"cssTimer",null);u(this,"resizeConfig");u(this,"resizeTimer",null);u(this,"isResizing",!1);u(this,"lastScrollX",0);u(this,"lastScrollY",0);u(this,"scrollTimer",null);u(this,"onTransitionFinished",e=>{this.target.contains(e.target)&&this.mutationTimer===null&&(this.cssTimer&&clearTimeout(this.cssTimer),this.pendingStyles.size==0&&(this.pendingMask|=I|z,this.cssTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.cssTimer=null},50)))});u(this,"onWindowResize",()=>{if(!this.resizeConfig.enabled){this.isDomDirty=!0;return}this.isResizing||(this.isResizing=!0,this.resizeConfig.onStart&&this.resizeConfig.onStart()),this.resizeTimer&&clearTimeout(this.resizeTimer),this.resizeTimer=window.setTimeout(()=>{this.isDomDirty=!0,this.resizeConfig.onEnd&&this.resizeConfig.onEnd(),this.isResizing=!1,this.resizeTimer=null},this.resizeConfig.delay)});u(this,"renderLoop",()=>{if(!this.isRunning)return;this.isDomDirty&&this.forceUpdateScene();const e=window.scrollX,t=window.scrollY;(e!==this.lastScrollX||t!==this.lastScrollY)&&(ke(this.renderer.fixedMeshes,e,t),this.lastScrollX=e,this.lastScrollY=t,this.scrollTimer&&clearTimeout(this.scrollTimer),this.scrollTimer=window.setTimeout(()=>{this.pendingMask|=I,this.isDomDirty=!0,this.scrollTimer=null},150)),this.pendingStyles.size>0&&(Oe(this.registry,this.pendingStyles),this.pendingStyles.clear()),this.renderer.render(),requestAnimationFrame(this.renderLoop)});var o,s;this.target=e,this.renderer=t,this.registry=i,this.filter=r.filter;const a=(o=r.resizeDebounce)!=null?o:!0;a===!1?this.resizeConfig={enabled:!1,delay:0}:a===!0?this.resizeConfig={enabled:!0,delay:150}:this.resizeConfig={enabled:!0,delay:(s=a.delay)!=null?s:150,onStart:a.onStart,onEnd:a.onEnd},this.observer=new MutationObserver(l=>{let c=L;for(const d of l)if(d.type==="childList")c|=E,d.removedNodes.length>0&&d.removedNodes.forEach(f=>{f instanceof HTMLElement&&this.pendingDeletions.add(f)});else if(d.type==="attributes")if(d.attributeName==="style"){c|=I|z;const f=d.target,h=Ie(f.style);this.pendingStyles.set(f,h)}else d.attributeName==="class"&&(c|=I|z);else d.type==="characterData"&&(c|=A|I);if(c!==L){if(this.pendingMask|=c,c&E){this.clearTimers(),this.isDomDirty=!0;return}this.mutationTimer&&clearTimeout(this.mutationTimer),this.mutationTimer=window.setTimeout(()=>{this.mutationTimer=null,this.isDomDirty=!0},200)}})}start(){this.isRunning||(this.isRunning=!0,this.observer.observe(this.target,{childList:!0,subtree:!0,attributes:!0,characterData:!0}),this.target.addEventListener("transitionend",this.onTransitionFinished),this.target.addEventListener("animationend",this.onTransitionFinished),window.addEventListener("resize",this.onWindowResize),this.forceUpdateScene(),this.renderLoop())}stop(){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)}clearTimers(){this.mutationTimer&&(clearTimeout(this.mutationTimer),this.mutationTimer=null),this.cssTimer&&(clearTimeout(this.cssTimer),this.cssTimer=null),this.scrollTimer&&(clearTimeout(this.scrollTimer),this.scrollTimer=null)}forceUpdateScene(){this.isDomDirty=!1,this.lastScrollX=window.scrollX,this.lastScrollY=window.scrollY;const e=document.querySelector("[data-mirage-travel='traveler']")!==null;e&&!this.isTravelEnabled&&(this.isTravelEnabled=!0,this.renderer.createRenderTarget());const t=ne(this.target,this.pendingMask,e?B|_:B,this.filter);t&&(this.renderer.syncScene(t,this.pendingDeletions),this.pendingDeletions.clear()),this.pendingMask=L}}class Fe{constructor(){u(this,"store");this.store=new WeakMap}register(e,t){this.store.set(e,t)}get(e){return this.store.get(e)}has(e){return this.store.has(e)}remove(e){this.store.delete(e)}}class Le{constructor(e,t){u(this,"renderer");u(this,"syncer");u(this,"target");u(this,"registry");var r,a,o;if(this.target=e,this.registry=new Fe,!document.getElementById("mirage-engine-styles")){const s=document.createElement("style");s.id="mirage-engine-styles",s.textContent=`
|
|
146
|
+
[data-mirage-dom="hide"] {
|
|
147
|
+
opacity: 0 !important;
|
|
148
|
+
}
|
|
149
|
+
`,document.head.appendChild(s)}let i;if(t.mode==="duplicate"?i=(a=(r=t.container)!=null?r:this.target.parentElement)!=null?a:void 0:i=(o=this.target.parentElement)!=null?o:void 0,!i)throw new Error("[Mirage] Cannot find a container (parent or option).");this.renderer=new Me(this.target,t,i,this.registry),this.renderer.mount(),this.syncer=new Be(this.target,this.renderer,this.registry,t)}start(){this.syncer.start()}stop(){this.syncer.stop()}dispose(){this.syncer.stop(),this.renderer.dispose()}test(){const e=this.registry.get(document.querySelector("#box2"));if(!e)return;const t={ArrowRight:!1,ArrowLeft:!1,ArrowUp:!1,ArrowDown:!1};window.addEventListener("keydown",a=>{t[a.key]!==void 0&&(t[a.key]=!0)}),window.addEventListener("keyup",a=>{t[a.key]!==void 0&&(t[a.key]=!1)});const i=2,r=()=>{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)};r()}}v.ALLOWED_FILTERS=ee,v.DIRTY_CONTENT=A,v.DIRTY_NONE=L,v.DIRTY_RECT=I,v.DIRTY_STRUCTURE=E,v.DIRTY_STYLE=z,v.DIRTY_ZINDEX=P,v.EXCLUDED=ge,v.Engine=Le,v.SYSTEM_LAYER=_,v.USER_LAYER=B,Object.defineProperty(v,Symbol.toStringTag,{value:"Module"})});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { StyleData } from '../types';
|
|
2
|
+
import { MeshRegistry } from '../store/MeshRegistry';
|
|
3
|
+
|
|
4
|
+
import * as THREE from "three";
|
|
5
|
+
export declare function animateMeshByData(registry: MeshRegistry, data: Map<HTMLElement, StyleData>): void;
|
|
6
|
+
export declare function animateMeshByAttribute(_target: HTMLElement, _options: {
|
|
7
|
+
duration: number;
|
|
8
|
+
easing?: string;
|
|
9
|
+
}): void;
|
|
10
|
+
export declare function updateFixedMeshesScroll(fixedMeshes: Set<THREE.Mesh>, currentScrollX: number, currentScrollY: number): void;
|
|
11
|
+
export declare function extractFromStyle(style: CSSStyleDeclaration): StyleData;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { CoreConfig } from '../types/config';
|
|
2
2
|
import { Renderer } from '../renderer/Renderer';
|
|
3
|
+
import { MeshRegistry } from '../store/MeshRegistry';
|
|
3
4
|
|
|
4
5
|
export declare class Syncer {
|
|
5
6
|
private target;
|
|
6
7
|
private renderer;
|
|
8
|
+
private registry;
|
|
7
9
|
private filter;
|
|
8
10
|
private observer;
|
|
11
|
+
private pendingDeletions;
|
|
12
|
+
private pendingStyles;
|
|
9
13
|
private isDomDirty;
|
|
10
14
|
private isRunning;
|
|
11
15
|
private isTravelEnabled;
|
|
@@ -15,7 +19,10 @@ export declare class Syncer {
|
|
|
15
19
|
private resizeConfig;
|
|
16
20
|
private resizeTimer;
|
|
17
21
|
private isResizing;
|
|
18
|
-
|
|
22
|
+
private lastScrollX;
|
|
23
|
+
private lastScrollY;
|
|
24
|
+
private scrollTimer;
|
|
25
|
+
constructor(target: HTMLElement, renderer: Renderer, registry: MeshRegistry, config: CoreConfig);
|
|
19
26
|
start(): void;
|
|
20
27
|
stop(): void;
|
|
21
28
|
private clearTimers;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { SceneNode, CoreConfig } from '../types';
|
|
2
|
-
|
|
2
|
+
import { MeshRegistry } from '../store/MeshRegistry';
|
|
3
|
+
import * as THREE from "three";
|
|
3
4
|
export declare class Renderer {
|
|
4
5
|
readonly canvas: HTMLCanvasElement;
|
|
5
6
|
private readonly scene;
|
|
@@ -9,18 +10,22 @@ export declare class Renderer {
|
|
|
9
10
|
private renderOrder;
|
|
10
11
|
private qualityFactor;
|
|
11
12
|
private mode;
|
|
13
|
+
private clipArea;
|
|
12
14
|
private target;
|
|
13
15
|
private mountContainer;
|
|
16
|
+
private registry;
|
|
14
17
|
private targetRect;
|
|
15
|
-
private
|
|
16
|
-
|
|
18
|
+
private travelers;
|
|
19
|
+
private textureManager;
|
|
20
|
+
readonly fixedMeshes: Set<THREE.Mesh>;
|
|
21
|
+
constructor(target: HTMLElement, config: CoreConfig, mountContainer: HTMLElement, registry: MeshRegistry);
|
|
17
22
|
createRenderTarget(): void;
|
|
18
23
|
private applyTextQuality;
|
|
19
24
|
mount(): void;
|
|
20
25
|
private updateCanvasLayout;
|
|
21
26
|
dispose(): void;
|
|
22
27
|
setSize(width: number, height: number): void;
|
|
23
|
-
syncScene(graphNode: SceneNode): void;
|
|
28
|
+
syncScene(graphNode: SceneNode, pendingDeletions: Set<HTMLElement>): void;
|
|
24
29
|
private reconcileNode;
|
|
25
30
|
private reconcileTextChild;
|
|
26
31
|
private updateMeshProperties;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
export declare class MeshRegistry {
|
|
3
|
+
private store;
|
|
4
|
+
constructor();
|
|
5
|
+
register(element: HTMLElement, mesh: THREE.Mesh): void;
|
|
6
|
+
get(element: HTMLElement): THREE.Mesh | undefined;
|
|
7
|
+
has(element: HTMLElement): boolean;
|
|
8
|
+
remove(element: HTMLElement): void;
|
|
9
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as THREE from "three";
|
|
2
|
+
export type TextureReadyCallback = (element: HTMLElement, texture: THREE.Texture | null) => void;
|
|
3
|
+
export declare class TextureLifecycleManager {
|
|
4
|
+
private observer;
|
|
5
|
+
private textures;
|
|
6
|
+
private loadStatus;
|
|
7
|
+
private elementUrls;
|
|
8
|
+
private onUpdate;
|
|
9
|
+
constructor(onUpdate: TextureReadyCallback);
|
|
10
|
+
register(element: HTMLElement, url: string): void;
|
|
11
|
+
unregister(element: HTMLElement): void;
|
|
12
|
+
private loadTexture;
|
|
13
|
+
private disposeTexture;
|
|
14
|
+
get(element: HTMLElement): THREE.Texture<unknown> | undefined;
|
|
15
|
+
disposeAll(): void;
|
|
16
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface StyleData {
|
|
2
|
+
x?: number;
|
|
3
|
+
y?: number;
|
|
4
|
+
z?: number;
|
|
5
|
+
scaleX?: number;
|
|
6
|
+
scaleY?: number;
|
|
7
|
+
scaleZ?: number;
|
|
8
|
+
rotateX?: number;
|
|
9
|
+
rotateY?: number;
|
|
10
|
+
rotateZ?: number;
|
|
11
|
+
matrix?: Float32Array;
|
|
12
|
+
opacity?: number;
|
|
13
|
+
backgroundColor?: [number, number, number];
|
|
14
|
+
backgroundImage?: string;
|
|
15
|
+
borderRadius?: number | [number, number, number, number];
|
|
16
|
+
width?: number;
|
|
17
|
+
height?: number;
|
|
18
|
+
zIndex?: number;
|
|
19
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { TextStyles, BoxStyles } from '../../packages/painter/src/index.ts';
|
|
1
|
+
import { TextStyles, BoxStyles, ShaderHooks } from '../../packages/painter/src/index.ts';
|
|
2
2
|
import { Visibility } from './flags';
|
|
3
3
|
|
|
4
4
|
export type NodeType = "BOX" | "TEXT";
|
|
@@ -16,8 +16,14 @@ export interface SceneNode {
|
|
|
16
16
|
styles: BoxStyles;
|
|
17
17
|
textContent?: string;
|
|
18
18
|
textStyles?: TextStyles;
|
|
19
|
+
textLines?: {
|
|
20
|
+
text: string;
|
|
21
|
+
rect: NodeRect;
|
|
22
|
+
}[];
|
|
19
23
|
dirtyMask: number;
|
|
20
24
|
visibility: Visibility;
|
|
21
25
|
isTraveler: boolean;
|
|
26
|
+
isFixed: boolean;
|
|
27
|
+
shaderHooks?: ShaderHooks;
|
|
22
28
|
children: SceneNode[];
|
|
23
29
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export type Quality = "low" | "medium" | "high" | number;
|
|
2
2
|
export type MirageMode = "overlay" | "duplicate";
|
|
3
|
+
export type PxUnit = `${number}px`;
|
|
4
|
+
export type PercentUnit = `${number}%`;
|
|
5
|
+
export type travelerClipArea = PxUnit | PercentUnit | number;
|
|
3
6
|
export interface FilterConfig {
|
|
4
7
|
includeTree?: string[];
|
|
5
8
|
excludeTree?: string[];
|
|
@@ -20,6 +23,7 @@ interface BaseConfig {
|
|
|
20
23
|
};
|
|
21
24
|
filter?: FilterConfig;
|
|
22
25
|
resizeDebounce?: boolean | ResizeConfig;
|
|
26
|
+
travelerClipArea?: travelerClipArea;
|
|
23
27
|
}
|
|
24
28
|
export interface OverlayConfig extends BaseConfig {
|
|
25
29
|
mode?: "overlay";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mirage-engine/core",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2",
|
|
4
4
|
"main": "src/index.ts",
|
|
5
5
|
"types": "src/index.ts",
|
|
6
6
|
"peerDependencies": {
|
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
},
|
|
14
14
|
"dependencies": {
|
|
15
15
|
"@types/three": "^0.181.0",
|
|
16
|
-
"@mirage-engine/painter": "0.
|
|
16
|
+
"@mirage-engine/painter": "1.0.0"
|
|
17
17
|
},
|
|
18
18
|
"private": false,
|
|
19
19
|
"publishConfig": {
|