@toriistudio/shader-ui 0.0.2 → 0.0.4

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/dist/index.js CHANGED
@@ -30,10 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var src_exports = {};
32
32
  __export(src_exports, {
33
+ AnimatedDrawingSVG: () => AnimatedDrawingSVG,
34
+ EFECTO_ASCII_COMPONENT_DEFAULTS: () => EFECTO_ASCII_COMPONENT_DEFAULTS,
35
+ EFECTO_ASCII_POST_PROCESSING_DEFAULTS: () => EFECTO_ASCII_POST_PROCESSING_DEFAULTS,
36
+ Efecto: () => Efecto,
33
37
  FractalFlower: () => FractalFlower,
34
38
  MenuGlitch: () => MenuGlitch,
35
39
  OranoParticles: () => OranoParticles,
36
- ShaderArt: () => ShaderArt
40
+ ShaderArt: () => ShaderArt,
41
+ Snow: () => Snow
37
42
  });
38
43
  module.exports = __toCommonJS(src_exports);
39
44
 
@@ -52,7 +57,8 @@ function useScene({
52
57
  onCreate,
53
58
  onRender,
54
59
  onResize,
55
- deps
60
+ deps,
61
+ manualRender = false
56
62
  } = {}) {
57
63
  const containerRef = (0, import_react.useRef)(null);
58
64
  const contextRef = (0, import_react.useRef)(null);
@@ -82,6 +88,10 @@ function useScene({
82
88
  antialias: true,
83
89
  ...rendererOptions
84
90
  });
91
+ renderer.autoClear = false;
92
+ renderer.autoClearColor = true;
93
+ renderer.autoClearDepth = true;
94
+ renderer.autoClearStencil = true;
85
95
  renderer.setPixelRatio(resolvedPixelRatio);
86
96
  renderer.setSize(initialWidth, initialHeight, false);
87
97
  renderer.setClearColor(0, 0);
@@ -132,7 +142,9 @@ function useScene({
132
142
  elapsedTime += delta;
133
143
  context.size = { ...sizeRef.current };
134
144
  onRenderRef.current?.(context, delta, elapsedTime);
135
- renderer.render(scene, camera);
145
+ if (!manualRender) {
146
+ renderer.render(scene, camera);
147
+ }
136
148
  animationFrameId = requestAnimationFrame(renderLoop);
137
149
  };
138
150
  animationFrameId = requestAnimationFrame(renderLoop);
@@ -143,13 +155,14 @@ function useScene({
143
155
  sizeRef.current = { width, height };
144
156
  if (camera instanceof THREE.PerspectiveCamera) {
145
157
  camera.aspect = width / Math.max(1, height);
158
+ camera.updateProjectionMatrix();
146
159
  } else if (camera instanceof THREE.OrthographicCamera) {
147
160
  camera.left = -width / 2;
148
161
  camera.right = width / 2;
149
162
  camera.top = height / 2;
150
163
  camera.bottom = -height / 2;
164
+ camera.updateProjectionMatrix();
151
165
  }
152
- camera.updateProjectionMatrix();
153
166
  context.size = { ...sizeRef.current };
154
167
  onResizeRef.current?.(context, { width, height });
155
168
  });
@@ -1074,10 +1087,1587 @@ function createDiffuseTexture() {
1074
1087
  texture.generateMipmaps = true;
1075
1088
  return texture;
1076
1089
  }
1090
+
1091
+ // src/components/EfectoAsciiEffect.tsx
1092
+ var import_react6 = require("react");
1093
+ var import_postprocessing = require("postprocessing");
1094
+ var THREE6 = __toESM(require("three"));
1095
+ var import_three = require("three");
1096
+
1097
+ // src/utils/efectoMediaAdjustments.ts
1098
+ var EFECTO_MEDIA_ADJUSTMENT_DEFAULTS = {
1099
+ brightness: 1,
1100
+ contrast: 1,
1101
+ saturation: 1
1102
+ };
1103
+ var resolveEfectoMediaAdjustments = (adjustments) => ({
1104
+ brightness: typeof adjustments?.brightness === "number" ? adjustments.brightness : EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.brightness,
1105
+ contrast: typeof adjustments?.contrast === "number" ? adjustments.contrast : EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.contrast,
1106
+ saturation: typeof adjustments?.saturation === "number" ? adjustments.saturation : EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.saturation
1107
+ });
1108
+
1109
+ // src/shaders/efecto-ascii-effect/fragment.ts
1110
+ var fragment_default5 = `
1111
+ uniform float cellSize;
1112
+ uniform bool invert;
1113
+ uniform bool colorMode;
1114
+ uniform int asciiStyle;
1115
+
1116
+ // PostFX uniforms
1117
+ uniform float time;
1118
+ uniform vec2 resolution;
1119
+ uniform vec2 mousePos;
1120
+
1121
+ // Tier 1 uniforms
1122
+ uniform float scanlineIntensity;
1123
+ uniform float scanlineCount;
1124
+ uniform float targetFPS;
1125
+ uniform float jitterIntensity;
1126
+ uniform float jitterSpeed;
1127
+ uniform bool mouseGlowEnabled;
1128
+ uniform float mouseGlowRadius;
1129
+ uniform float mouseGlowIntensity;
1130
+ uniform float vignetteIntensity;
1131
+ uniform float vignetteRadius;
1132
+ uniform int colorPalette;
1133
+
1134
+ // Tier 2 uniforms
1135
+ uniform float curvature;
1136
+ uniform float aberrationStrength;
1137
+ uniform float noiseIntensity;
1138
+ uniform float noiseScale;
1139
+ uniform float noiseSpeed;
1140
+ uniform float waveAmplitude;
1141
+ uniform float waveFrequency;
1142
+ uniform float waveSpeed;
1143
+ uniform float glitchIntensity;
1144
+ uniform float glitchFrequency;
1145
+ uniform float brightnessAdjust;
1146
+ uniform float contrastAdjust;
1147
+
1148
+ // =======================
1149
+ // HELPER FUNCTIONS
1150
+ // =======================
1151
+
1152
+ // Pseudo-random function
1153
+ float random(vec2 st) {
1154
+ return fract(sin(dot(st, vec2(12.9898, 78.233))) * 43758.5453);
1155
+ }
1156
+
1157
+ // 2D Noise function
1158
+ float noise(vec2 st) {
1159
+ vec2 i = floor(st);
1160
+ vec2 f = fract(st);
1161
+ float a = random(i);
1162
+ float b = random(i + vec2(1.0, 0.0));
1163
+ float c = random(i + vec2(0.0, 1.0));
1164
+ float d = random(i + vec2(1.0, 1.0));
1165
+ vec2 u = f * f * (3.0 - 2.0 * f);
1166
+ return mix(a, b, u.x) + (c - a) * u.y * (1.0 - u.x) + (d - b) * u.x * u.y;
1167
+ }
1168
+
1169
+ // RGB to HSL conversion
1170
+ vec3 rgb2hsl(vec3 rgb) {
1171
+ float maxVal = max(max(rgb.r, rgb.g), rgb.b);
1172
+ float minVal = min(min(rgb.r, rgb.g), rgb.b);
1173
+ float delta = maxVal - minVal;
1174
+
1175
+ float h = 0.0;
1176
+ float s = 0.0;
1177
+ float l = (maxVal + minVal) * 0.5;
1178
+
1179
+ if (delta > 0.0001) {
1180
+ s = delta / (1.0 - abs(2.0 * l - 1.0));
1181
+
1182
+ if (maxVal == rgb.r) {
1183
+ h = mod((rgb.g - rgb.b) / delta, 6.0);
1184
+ } else if (maxVal == rgb.g) {
1185
+ h = (rgb.b - rgb.r) / delta + 2.0;
1186
+ } else {
1187
+ h = (rgb.r - rgb.g) / delta + 4.0;
1188
+ }
1189
+ h = h / 6.0;
1190
+ }
1191
+
1192
+ return vec3(h, s, l);
1193
+ }
1194
+
1195
+ // HSL to RGB conversion
1196
+ vec3 hsl2rgb(vec3 hsl) {
1197
+ float h = hsl.x;
1198
+ float s = hsl.y;
1199
+ float l = hsl.z;
1200
+
1201
+ float c = (1.0 - abs(2.0 * l - 1.0)) * s;
1202
+ float x = c * (1.0 - abs(mod(h * 6.0, 2.0) - 1.0));
1203
+ float m = l - c * 0.5;
1204
+
1205
+ vec3 rgb = vec3(0.0);
1206
+
1207
+ if (h < 1.0/6.0) {
1208
+ rgb = vec3(c, x, 0.0);
1209
+ } else if (h < 2.0/6.0) {
1210
+ rgb = vec3(x, c, 0.0);
1211
+ } else if (h < 3.0/6.0) {
1212
+ rgb = vec3(0.0, c, x);
1213
+ } else if (h < 4.0/6.0) {
1214
+ rgb = vec3(0.0, x, c);
1215
+ } else if (h < 5.0/6.0) {
1216
+ rgb = vec3(x, 0.0, c);
1217
+ } else {
1218
+ rgb = vec3(c, 0.0, x);
1219
+ }
1220
+
1221
+ return rgb + m;
1222
+ }
1223
+
1224
+ // Apply color palette
1225
+ vec3 applyColorPalette(vec3 color, float brightness, int palette) {
1226
+ if (palette == 0) return color; // Original
1227
+
1228
+ vec3 paletteColor = color;
1229
+
1230
+ if (palette == 1) { // Green phosphor
1231
+ paletteColor = vec3(0.0, brightness, 0.0) * 1.5;
1232
+ } else if (palette == 2) { // Amber
1233
+ paletteColor = vec3(brightness * 1.2, brightness * 0.7, 0.0);
1234
+ } else if (palette == 3) { // Cyan
1235
+ paletteColor = vec3(0.0, brightness * 0.9, brightness);
1236
+ } else if (palette == 4) { // Blue
1237
+ paletteColor = vec3(0.0, 0.0, brightness);
1238
+ }
1239
+
1240
+ return paletteColor;
1241
+ }
1242
+
1243
+ // Different character patterns based on style
1244
+ float getChar(float brightness, vec2 p, int style) {
1245
+ vec2 grid = floor(p * 4.0);
1246
+ float val = 0.0;
1247
+
1248
+ if (style == 0) {
1249
+ // Standard ASCII style
1250
+ if (brightness < 0.2) {
1251
+ val = (grid.x == 1.0 && grid.y == 1.0) ? 0.3 : 0.0;
1252
+ } else if (brightness < 0.35) {
1253
+ val = (grid.x == 1.0 || grid.x == 2.0) && (grid.y == 1.0 || grid.y == 2.0) ? 1.0 : 0.0;
1254
+ } else if (brightness < 0.5) {
1255
+ val = (grid.y == 1.0 || grid.y == 2.0) ? 1.0 : 0.0;
1256
+ } else if (brightness < 0.65) {
1257
+ val = (grid.y == 0.0 || grid.y == 3.0) ? 1.0 : (grid.y == 1.0 || grid.y == 2.0) ? 0.5 : 0.0;
1258
+ } else if (brightness < 0.8) {
1259
+ val = (grid.x == 0.0 || grid.x == 2.0 || grid.y == 0.0 || grid.y == 2.0) ? 1.0 : 0.3;
1260
+ } else {
1261
+ val = 1.0;
1262
+ }
1263
+ } else if (style == 1) {
1264
+ // Dense style
1265
+ if (brightness < 0.15) {
1266
+ val = 0.0;
1267
+ } else if (brightness < 0.3) {
1268
+ val = (grid.x >= 1.0 && grid.x <= 2.0 && grid.y >= 1.0 && grid.y <= 2.0) ? 0.6 : 0.0;
1269
+ } else if (brightness < 0.5) {
1270
+ val = (grid.y == 1.0 || grid.y == 2.0) ? 1.0 : 0.3;
1271
+ } else if (brightness < 0.7) {
1272
+ val = (grid.x == 0.0 || grid.x == 3.0 || grid.y == 0.0 || grid.y == 3.0) ? 1.0 : 0.6;
1273
+ } else {
1274
+ val = 1.0;
1275
+ }
1276
+ } else if (style == 2) {
1277
+ // Minimal style
1278
+ if (brightness < 0.25) {
1279
+ val = 0.0;
1280
+ } else if (brightness < 0.4) {
1281
+ val = (grid.x == 2.0 && grid.y == 2.0) ? 1.0 : 0.0;
1282
+ } else if (brightness < 0.6) {
1283
+ val = (grid.x == 1.0 || grid.x == 2.0) && grid.y == 2.0 ? 1.0 : 0.0;
1284
+ } else if (brightness < 0.8) {
1285
+ val = (grid.y == 1.0 || grid.y == 2.0) ? 1.0 : 0.0;
1286
+ } else {
1287
+ val = (grid.x <= 2.0 && grid.y <= 2.0) ? 1.0 : 0.3;
1288
+ }
1289
+ } else if (style == 3) {
1290
+ // Blocks style
1291
+ if (brightness < 0.2) {
1292
+ val = 0.0;
1293
+ } else if (brightness < 0.4) {
1294
+ val = (grid.x >= 1.0 && grid.x <= 2.0 && grid.y >= 1.0 && grid.y <= 2.0) ? 0.8 : 0.0;
1295
+ } else if (brightness < 0.6) {
1296
+ val = (grid.y <= 2.0) ? 0.9 : 0.0;
1297
+ } else if (brightness < 0.8) {
1298
+ val = (grid.x <= 2.0 || grid.y <= 2.0) ? 1.0 : 0.2;
1299
+ } else {
1300
+ val = 1.0;
1301
+ }
1302
+ }
1303
+
1304
+ return val;
1305
+ }
1306
+
1307
+ void mainImage(const in vec4 inputColor, const in vec2 uv, out vec4 outputColor) {
1308
+ vec2 workingUV = uv;
1309
+
1310
+ // ===========================
1311
+ // TIER 2: PRE-PROCESSING
1312
+ // ===========================
1313
+
1314
+ // Screen curvature
1315
+ if (curvature > 0.0) {
1316
+ vec2 centered = workingUV * 2.0 - 1.0;
1317
+ float dist = dot(centered, centered);
1318
+ centered *= 1.0 + curvature * dist;
1319
+ workingUV = centered * 0.5 + 0.5;
1320
+
1321
+ // Make out-of-bounds transparent so parent background shows through
1322
+ if (workingUV.x < 0.0 || workingUV.x > 1.0 || workingUV.y < 0.0 || workingUV.y > 1.0) {
1323
+ outputColor = vec4(0.0, 0.0, 0.0, 0.0);
1324
+ return;
1325
+ }
1326
+ }
1327
+
1328
+ // Wave distortion
1329
+ if (waveAmplitude > 0.0) {
1330
+ workingUV.x += sin(workingUV.y * waveFrequency + time * waveSpeed) * waveAmplitude;
1331
+ workingUV.y += cos(workingUV.x * waveFrequency + time * waveSpeed) * waveAmplitude * 0.5;
1332
+ }
1333
+
1334
+ // ===========================
1335
+ // CORE ASCII RENDERING
1336
+ // ===========================
1337
+
1338
+ vec2 res = resolution;
1339
+ vec2 cellCount = res / cellSize;
1340
+ vec2 cellCoord = floor(workingUV * cellCount);
1341
+
1342
+ // Frame rate control
1343
+ if (targetFPS > 0.0) {
1344
+ float frameTime = 1.0 / targetFPS;
1345
+ float frameIndex = floor(time / frameTime);
1346
+ cellCoord = floor(workingUV * cellCount) + vec2(random(vec2(frameIndex)) * 0.5);
1347
+ }
1348
+
1349
+ vec2 cellUV = (cellCoord + 0.5) / cellCount;
1350
+
1351
+ // Chromatic aberration
1352
+ vec4 cellColor;
1353
+ if (aberrationStrength > 0.0) {
1354
+ float r = texture(inputBuffer, cellUV + vec2(aberrationStrength, 0.0)).r;
1355
+ float g = texture(inputBuffer, cellUV).g;
1356
+ float b = texture(inputBuffer, cellUV - vec2(aberrationStrength, 0.0)).b;
1357
+ cellColor = vec4(r, g, b, 1.0);
1358
+ } else {
1359
+ cellColor = texture(inputBuffer, cellUV);
1360
+ }
1361
+
1362
+ // Calculate brightness
1363
+ float brightness = dot(cellColor.rgb, vec3(0.299, 0.587, 0.114));
1364
+
1365
+ // Contrast and brightness adjustment
1366
+ brightness = (brightness - 0.5) * contrastAdjust + 0.5 + brightnessAdjust;
1367
+ brightness = clamp(brightness, 0.0, 1.0);
1368
+
1369
+ // Time-based noise
1370
+ if (noiseIntensity > 0.0) {
1371
+ float noiseVal = noise(workingUV * noiseScale * 100.0 + time * noiseSpeed);
1372
+ brightness = mix(brightness, noiseVal, noiseIntensity);
1373
+ }
1374
+
1375
+ // Jitter/fuzzy effect
1376
+ if (jitterIntensity > 0.0) {
1377
+ float jitter = random(cellCoord + floor(time * jitterSpeed) * 0.1) - 0.5;
1378
+ brightness += jitter * jitterIntensity;
1379
+ brightness = clamp(brightness, 0.0, 1.0);
1380
+ }
1381
+
1382
+ // RGB Glitch
1383
+ if (glitchIntensity > 0.0 && glitchFrequency > 0.0) {
1384
+ float glitchTrigger = random(vec2(time * glitchFrequency));
1385
+ if (glitchTrigger > 0.9) {
1386
+ float glitchOffset = (random(cellCoord + time) - 0.5) * glitchIntensity;
1387
+ cellColor.r = texture(inputBuffer, cellUV + vec2(glitchOffset, 0.0)).r;
1388
+ cellColor.b = texture(inputBuffer, cellUV - vec2(glitchOffset, 0.0)).b;
1389
+ }
1390
+ }
1391
+
1392
+ if (invert) {
1393
+ brightness = 1.0 - brightness;
1394
+ }
1395
+
1396
+ // Get local UV within the cell
1397
+ vec2 localUV = fract(workingUV * cellCount);
1398
+ float charValue = getChar(brightness, localUV, asciiStyle);
1399
+
1400
+ // ===========================
1401
+ // TIER 1: POST-PROCESSING
1402
+ // ===========================
1403
+
1404
+ vec3 finalColor;
1405
+
1406
+ if (colorMode) {
1407
+ finalColor = cellColor.rgb * charValue;
1408
+ } else {
1409
+ finalColor = vec3(brightness * charValue);
1410
+ }
1411
+
1412
+ // Color palette
1413
+ finalColor = applyColorPalette(finalColor, brightness, colorPalette);
1414
+
1415
+ // Mouse glow
1416
+ if (mouseGlowEnabled && mouseGlowRadius > 0.0) {
1417
+ vec2 pixelPos = workingUV * res;
1418
+ float dist = distance(pixelPos, mousePos);
1419
+ float glow = 1.0 - smoothstep(0.0, mouseGlowRadius, dist);
1420
+ glow = pow(glow, 2.0);
1421
+ finalColor *= 1.0 + glow * mouseGlowIntensity;
1422
+ }
1423
+
1424
+ // Scanlines
1425
+ if (scanlineIntensity > 0.0) {
1426
+ float scanline = sin(workingUV.y * scanlineCount * 3.14159) * 0.5 + 0.5;
1427
+ finalColor *= 1.0 - scanlineIntensity * (1.0 - scanline);
1428
+ }
1429
+
1430
+ // Vignette
1431
+ if (vignetteIntensity > 0.0) {
1432
+ vec2 centered = workingUV - 0.5;
1433
+ float dist = length(centered) / 0.707; // Normalize to corner distance
1434
+ float vignette = smoothstep(vignetteRadius, vignetteRadius - 0.5, dist);
1435
+ finalColor *= mix(1.0, vignette, vignetteIntensity);
1436
+ }
1437
+
1438
+ outputColor = vec4(finalColor, cellColor.a);
1439
+ }
1440
+ `;
1441
+
1442
+ // src/shaders/efecto-media-image/vertex.glsl
1443
+ var vertex_default5 = "uniform vec2 uvScale;\nuniform vec2 uvOffset;\nvarying vec2 vUv;\n\nvoid main() {\n // Apply texture scale and offset for cover-fill effect\n vUv = uv * uvScale + uvOffset;\n gl_Position = projectionMatrix * modelViewMatrix * vec4(position, 1.0);\n}";
1444
+
1445
+ // src/shaders/efecto-media-image/fragment.glsl
1446
+ var fragment_default6 = "uniform sampler2D map;\nuniform float brightness;\nuniform float contrast;\nuniform float saturation;\nvarying vec2 vUv;\n\nvec3 adjustContrast(vec3 color, float contrastAmount) {\n return (color - 0.5) * contrastAmount + 0.5;\n}\n\nvec3 adjustSaturation(vec3 color, float saturationAmount) {\n float gray = dot(color, vec3(0.299, 0.587, 0.114));\n return mix(vec3(gray), color, saturationAmount);\n}\n\nvoid main() {\n vec4 texel = texture2D(map, vUv);\n vec3 color = texel.rgb;\n\n // Apply brightness\n color *= brightness;\n\n // Apply contrast\n color = adjustContrast(color, contrast);\n\n // Apply saturation\n color = adjustSaturation(color, saturation);\n\n gl_FragColor = vec4(color, texel.a);\n}";
1447
+
1448
+ // src/components/EfectoAsciiEffect.tsx
1449
+ var import_jsx_runtime5 = require("react/jsx-runtime");
1450
+ var DEFAULT_RESOLUTION = new import_three.Vector2(1920, 1080);
1451
+ var DEFAULT_MOUSE_POSITION = new import_three.Vector2(0, 0);
1452
+ var PARALLAX_LERP = 0.12;
1453
+ var STYLE_MAP = {
1454
+ standard: 0,
1455
+ dense: 1,
1456
+ minimal: 2,
1457
+ blocks: 3
1458
+ };
1459
+ var COLOR_PALETTE_MAP = {
1460
+ original: 0,
1461
+ green: 1,
1462
+ amber: 2,
1463
+ cyan: 3,
1464
+ blue: 4
1465
+ };
1466
+ var EFECTO_ASCII_COMPONENT_DEFAULTS = {
1467
+ cellSize: 8,
1468
+ invert: false,
1469
+ colorMode: true,
1470
+ asciiStyle: "standard"
1471
+ };
1472
+ var EFECTO_ASCII_POST_PROCESSING_DEFAULTS = {
1473
+ scanlineIntensity: 0,
1474
+ scanlineCount: 200,
1475
+ targetFPS: 0,
1476
+ jitterIntensity: 0,
1477
+ jitterSpeed: 0,
1478
+ mouseGlowEnabled: false,
1479
+ mouseGlowRadius: 200,
1480
+ mouseGlowIntensity: 1.5,
1481
+ vignetteIntensity: 0,
1482
+ vignetteRadius: 0.8,
1483
+ colorPalette: COLOR_PALETTE_MAP.original,
1484
+ curvature: 0,
1485
+ aberrationStrength: 0,
1486
+ noiseIntensity: 0,
1487
+ noiseScale: 0.1,
1488
+ noiseSpeed: 0,
1489
+ waveAmplitude: 0,
1490
+ waveFrequency: 3,
1491
+ waveSpeed: 0.2,
1492
+ glitchIntensity: 0,
1493
+ glitchFrequency: 0,
1494
+ brightnessAdjust: 0,
1495
+ contrastAdjust: 1
1496
+ };
1497
+ var normalizePostProcessing = (overrides) => {
1498
+ const { colorPalette: overridePalette, ...otherOverrides } = overrides ?? {};
1499
+ const merged = {
1500
+ ...EFECTO_ASCII_POST_PROCESSING_DEFAULTS,
1501
+ ...otherOverrides
1502
+ };
1503
+ const paletteValue = overridePalette === void 0 ? merged.colorPalette : typeof overridePalette === "string" ? COLOR_PALETTE_MAP[overridePalette.toLowerCase()] ?? COLOR_PALETTE_MAP.original : overridePalette;
1504
+ return { ...merged, colorPalette: paletteValue };
1505
+ };
1506
+ var AsciiEffectImpl = class extends import_postprocessing.Effect {
1507
+ constructor(initialProps) {
1508
+ const uniformEntries = [
1509
+ ["cellSize", new import_three.Uniform(initialProps.cellSize)],
1510
+ ["invert", new import_three.Uniform(initialProps.invert)],
1511
+ ["colorMode", new import_three.Uniform(initialProps.colorMode)],
1512
+ ["asciiStyle", new import_three.Uniform(initialProps.asciiStyle)],
1513
+ ["time", new import_three.Uniform(0)],
1514
+ ["resolution", new import_three.Uniform(initialProps.resolution.clone())],
1515
+ ["mousePos", new import_three.Uniform(initialProps.mousePos.clone())],
1516
+ ["scanlineIntensity", new import_three.Uniform(initialProps.scanlineIntensity)],
1517
+ ["scanlineCount", new import_three.Uniform(initialProps.scanlineCount)],
1518
+ ["targetFPS", new import_three.Uniform(initialProps.targetFPS)],
1519
+ ["jitterIntensity", new import_three.Uniform(initialProps.jitterIntensity)],
1520
+ ["jitterSpeed", new import_three.Uniform(initialProps.jitterSpeed)],
1521
+ ["mouseGlowEnabled", new import_three.Uniform(initialProps.mouseGlowEnabled)],
1522
+ ["mouseGlowRadius", new import_three.Uniform(initialProps.mouseGlowRadius)],
1523
+ ["mouseGlowIntensity", new import_three.Uniform(initialProps.mouseGlowIntensity)],
1524
+ ["vignetteIntensity", new import_three.Uniform(initialProps.vignetteIntensity)],
1525
+ ["vignetteRadius", new import_three.Uniform(initialProps.vignetteRadius)],
1526
+ ["colorPalette", new import_three.Uniform(initialProps.colorPalette)],
1527
+ ["curvature", new import_three.Uniform(initialProps.curvature)],
1528
+ ["aberrationStrength", new import_three.Uniform(initialProps.aberrationStrength)],
1529
+ ["noiseIntensity", new import_three.Uniform(initialProps.noiseIntensity)],
1530
+ ["noiseScale", new import_three.Uniform(initialProps.noiseScale)],
1531
+ ["noiseSpeed", new import_three.Uniform(initialProps.noiseSpeed)],
1532
+ ["waveAmplitude", new import_three.Uniform(initialProps.waveAmplitude)],
1533
+ ["waveFrequency", new import_three.Uniform(initialProps.waveFrequency)],
1534
+ ["waveSpeed", new import_three.Uniform(initialProps.waveSpeed)],
1535
+ ["glitchIntensity", new import_three.Uniform(initialProps.glitchIntensity)],
1536
+ ["glitchFrequency", new import_three.Uniform(initialProps.glitchFrequency)],
1537
+ ["brightnessAdjust", new import_three.Uniform(initialProps.brightnessAdjust)],
1538
+ ["contrastAdjust", new import_three.Uniform(initialProps.contrastAdjust)]
1539
+ ];
1540
+ super("AsciiEffect", fragment_default5, {
1541
+ blendFunction: import_postprocessing.BlendFunction.SRC,
1542
+ uniforms: new Map(uniformEntries)
1543
+ });
1544
+ this.time = 0;
1545
+ this.deltaAccumulator = 0;
1546
+ }
1547
+ updateUniforms(nextProps) {
1548
+ if (nextProps.cellSize !== void 0) {
1549
+ this.uniforms.get("cellSize").value = nextProps.cellSize;
1550
+ }
1551
+ if (nextProps.invert !== void 0) {
1552
+ this.uniforms.get("invert").value = nextProps.invert;
1553
+ }
1554
+ if (nextProps.colorMode !== void 0) {
1555
+ this.uniforms.get("colorMode").value = nextProps.colorMode;
1556
+ }
1557
+ if (nextProps.asciiStyle !== void 0) {
1558
+ this.uniforms.get("asciiStyle").value = nextProps.asciiStyle;
1559
+ }
1560
+ if (nextProps.resolution) {
1561
+ this.setVector2Uniform("resolution", nextProps.resolution);
1562
+ }
1563
+ if (nextProps.mousePos) {
1564
+ this.setVector2Uniform("mousePos", nextProps.mousePos);
1565
+ }
1566
+ const uniformKeys = Object.keys(
1567
+ EFECTO_ASCII_POST_PROCESSING_DEFAULTS
1568
+ );
1569
+ for (const key of uniformKeys) {
1570
+ if (nextProps[key] !== void 0) {
1571
+ this.uniforms.get(key).value = nextProps[key];
1572
+ }
1573
+ }
1574
+ }
1575
+ setVector2Uniform(key, nextValue) {
1576
+ const uniform = this.uniforms.get(key);
1577
+ if (!uniform) {
1578
+ return;
1579
+ }
1580
+ if (uniform.value instanceof import_three.Vector2) {
1581
+ uniform.value.copy(nextValue);
1582
+ return;
1583
+ }
1584
+ uniform.value = nextValue.clone();
1585
+ }
1586
+ update(_renderer, _inputBuffer, deltaTime) {
1587
+ const targetFPS = this.uniforms.get("targetFPS").value;
1588
+ if (targetFPS > 0) {
1589
+ const frameDuration = 1 / targetFPS;
1590
+ this.deltaAccumulator += deltaTime;
1591
+ if (this.deltaAccumulator >= frameDuration) {
1592
+ this.time += frameDuration;
1593
+ this.deltaAccumulator = this.deltaAccumulator % frameDuration;
1594
+ }
1595
+ } else {
1596
+ this.time += deltaTime;
1597
+ }
1598
+ this.uniforms.get("time").value = this.time;
1599
+ }
1600
+ };
1601
+ function AsciiEffect({
1602
+ cellSize = EFECTO_ASCII_COMPONENT_DEFAULTS.cellSize,
1603
+ invert = EFECTO_ASCII_COMPONENT_DEFAULTS.invert,
1604
+ colorMode = EFECTO_ASCII_COMPONENT_DEFAULTS.colorMode,
1605
+ asciiStyle: asciiStyleProp = EFECTO_ASCII_COMPONENT_DEFAULTS.asciiStyle,
1606
+ imageUrl,
1607
+ resolution,
1608
+ mousePosition,
1609
+ postProcessing = {},
1610
+ mediaAdjustments,
1611
+ mouseParallax = false,
1612
+ parallaxIntensity = 0.5,
1613
+ className,
1614
+ style,
1615
+ width,
1616
+ height,
1617
+ ...divProps
1618
+ }) {
1619
+ const composerRef = (0, import_react6.useRef)(null);
1620
+ const effectRef = (0, import_react6.useRef)(null);
1621
+ const assetsRef = (0, import_react6.useRef)(null);
1622
+ const loadedTextureRef = (0, import_react6.useRef)(null);
1623
+ const cameraRef = (0, import_react6.useRef)(null);
1624
+ const mediaUniformsRef = (0, import_react6.useRef)({
1625
+ map: { value: null },
1626
+ brightness: { value: EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.brightness },
1627
+ contrast: { value: EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.contrast },
1628
+ saturation: { value: EFECTO_MEDIA_ADJUSTMENT_DEFAULTS.saturation },
1629
+ uvScale: { value: new import_three.Vector2(1, 1) },
1630
+ uvOffset: { value: new import_three.Vector2(0, 0) }
1631
+ });
1632
+ const pointerBoundsRef = (0, import_react6.useRef)({
1633
+ left: 0,
1634
+ top: 0,
1635
+ width: 1,
1636
+ height: 1
1637
+ });
1638
+ const manualResolutionRef = (0, import_react6.useRef)(
1639
+ resolution ? resolution.clone() : null
1640
+ );
1641
+ manualResolutionRef.current = resolution ? resolution.clone() : null;
1642
+ const resolutionRef = (0, import_react6.useRef)(
1643
+ manualResolutionRef.current ? manualResolutionRef.current.clone() : DEFAULT_RESOLUTION.clone()
1644
+ );
1645
+ const autoMouseRef = (0, import_react6.useRef)(DEFAULT_MOUSE_POSITION.clone());
1646
+ const usesExternalMouseRef = (0, import_react6.useRef)(Boolean(mousePosition));
1647
+ usesExternalMouseRef.current = Boolean(mousePosition);
1648
+ const viewportSizeRef = (0, import_react6.useRef)({ width: 1, height: 1 });
1649
+ const meshDisplaySizeRef = (0, import_react6.useRef)({ width: 1, height: 1 });
1650
+ const parallaxStateRef = (0, import_react6.useRef)({
1651
+ targetX: 0,
1652
+ targetY: 0,
1653
+ rotationX: 0,
1654
+ rotationY: 0
1655
+ });
1656
+ const parallaxIntensityRef = (0, import_react6.useRef)(
1657
+ THREE6.MathUtils.clamp(parallaxIntensity ?? 0, 0, 1)
1658
+ );
1659
+ parallaxIntensityRef.current = THREE6.MathUtils.clamp(
1660
+ parallaxIntensity ?? 0,
1661
+ 0,
1662
+ 1
1663
+ );
1664
+ const normalizedStyle = typeof asciiStyleProp === "string" ? asciiStyleProp.toLowerCase() ?? EFECTO_ASCII_COMPONENT_DEFAULTS.asciiStyle : EFECTO_ASCII_COMPONENT_DEFAULTS.asciiStyle;
1665
+ const asciiStyle = STYLE_MAP[normalizedStyle] ?? STYLE_MAP.standard;
1666
+ const resolvedPostProcessing = (0, import_react6.useMemo)(
1667
+ () => normalizePostProcessing(postProcessing),
1668
+ [postProcessing]
1669
+ );
1670
+ const resolvedMediaAdjustments = (0, import_react6.useMemo)(
1671
+ () => resolveEfectoMediaAdjustments(mediaAdjustments),
1672
+ [mediaAdjustments]
1673
+ );
1674
+ const initialEffectPropsRef = (0, import_react6.useRef)(null);
1675
+ if (!initialEffectPropsRef.current) {
1676
+ initialEffectPropsRef.current = {
1677
+ cellSize,
1678
+ invert,
1679
+ colorMode,
1680
+ asciiStyle,
1681
+ resolution: resolutionRef.current.clone(),
1682
+ mousePos: (mousePosition ?? DEFAULT_MOUSE_POSITION).clone(),
1683
+ ...resolvedPostProcessing
1684
+ };
1685
+ }
1686
+ const updateTextureUVTransform = (0, import_react6.useCallback)(() => {
1687
+ const texture = loadedTextureRef.current;
1688
+ if (!texture || !texture.image) {
1689
+ return;
1690
+ }
1691
+ const { width: planeWidth, height: planeHeight } = meshDisplaySizeRef.current;
1692
+ if (planeWidth <= 0 || planeHeight <= 0) {
1693
+ return;
1694
+ }
1695
+ const image = texture.image;
1696
+ if (!image.width || !image.height) {
1697
+ return;
1698
+ }
1699
+ const imageAspect = image.width / image.height;
1700
+ const planeAspect = planeWidth / planeHeight;
1701
+ let scaleX = 1;
1702
+ let scaleY = 1;
1703
+ if (imageAspect > planeAspect) {
1704
+ scaleX = imageAspect / planeAspect;
1705
+ } else {
1706
+ scaleY = planeAspect / imageAspect;
1707
+ }
1708
+ const uvScaleX = 1 / scaleX;
1709
+ const uvScaleY = 1 / scaleY;
1710
+ const offsetX = (1 - uvScaleX) * 0.5;
1711
+ const offsetY = (1 - uvScaleY) * 0.5;
1712
+ mediaUniformsRef.current.uvScale.value.set(uvScaleX, uvScaleY);
1713
+ mediaUniformsRef.current.uvOffset.value.set(offsetX, offsetY);
1714
+ const assets = assetsRef.current;
1715
+ if (assets) {
1716
+ assets.material.uniforms.uvScale.value.set(
1717
+ uvScaleX,
1718
+ uvScaleY
1719
+ );
1720
+ assets.material.uniforms.uvOffset.value.set(
1721
+ offsetX,
1722
+ offsetY
1723
+ );
1724
+ }
1725
+ }, []);
1726
+ const updateMeshScale = (0, import_react6.useCallback)(() => {
1727
+ const assets = assetsRef.current;
1728
+ if (!assets) return;
1729
+ const { width: width2, height: height2 } = viewportSizeRef.current;
1730
+ const camera = cameraRef.current;
1731
+ let viewWidth = width2;
1732
+ let viewHeight = height2;
1733
+ if (camera instanceof THREE6.PerspectiveCamera) {
1734
+ const distance = Math.abs(camera.position.z - assets.mesh.position.z);
1735
+ const verticalFov = THREE6.MathUtils.degToRad(camera.fov);
1736
+ viewHeight = 2 * Math.tan(verticalFov / 2) * distance;
1737
+ viewWidth = viewHeight * camera.aspect;
1738
+ }
1739
+ const texture = loadedTextureRef.current;
1740
+ if (!texture || !texture.image) {
1741
+ assets.mesh.scale.set(viewWidth, viewHeight, 1);
1742
+ meshDisplaySizeRef.current = { width: viewWidth, height: viewHeight };
1743
+ return;
1744
+ }
1745
+ const image = texture.image;
1746
+ const imageAspect = image.width && image.height ? image.width / Math.max(1, image.height) : 1;
1747
+ const viewportAspect = viewWidth / Math.max(1, viewHeight);
1748
+ let meshWidth = viewWidth;
1749
+ let meshHeight = viewHeight;
1750
+ if (imageAspect > viewportAspect) {
1751
+ meshHeight = viewHeight;
1752
+ meshWidth = viewHeight * imageAspect;
1753
+ } else {
1754
+ meshWidth = viewWidth;
1755
+ meshHeight = viewWidth / Math.max(1e-4, imageAspect);
1756
+ }
1757
+ assets.mesh.scale.set(meshWidth, meshHeight, 1);
1758
+ meshDisplaySizeRef.current = { width: meshWidth, height: meshHeight };
1759
+ updateTextureUVTransform();
1760
+ }, [updateTextureUVTransform]);
1761
+ const updatePointerBounds = (0, import_react6.useCallback)(
1762
+ (container = containerRef.current) => {
1763
+ if (!container) return;
1764
+ const bounds = container.getBoundingClientRect();
1765
+ pointerBoundsRef.current = {
1766
+ left: bounds.left,
1767
+ top: bounds.top,
1768
+ width: bounds.width || 1,
1769
+ height: bounds.height || 1
1770
+ };
1771
+ },
1772
+ []
1773
+ );
1774
+ const resetParallax = (0, import_react6.useCallback)(() => {
1775
+ parallaxStateRef.current.targetX = 0;
1776
+ parallaxStateRef.current.targetY = 0;
1777
+ parallaxStateRef.current.rotationX = 0;
1778
+ parallaxStateRef.current.rotationY = 0;
1779
+ const mesh = assetsRef.current?.mesh;
1780
+ if (mesh) {
1781
+ mesh.rotation.x = 0;
1782
+ mesh.rotation.y = 0;
1783
+ }
1784
+ }, []);
1785
+ const handleCreate = (0, import_react6.useCallback)(
1786
+ ({ scene, camera, renderer, size }) => {
1787
+ renderer.outputColorSpace = THREE6.SRGBColorSpace;
1788
+ renderer.toneMapping = THREE6.NoToneMapping;
1789
+ if (!manualResolutionRef.current) {
1790
+ resolutionRef.current.set(size.width, size.height);
1791
+ }
1792
+ viewportSizeRef.current = { width: size.width, height: size.height };
1793
+ const geometry = new THREE6.PlaneGeometry(1, 1);
1794
+ const material = new THREE6.ShaderMaterial({
1795
+ vertexShader: vertex_default5,
1796
+ fragmentShader: fragment_default6,
1797
+ uniforms: mediaUniformsRef.current,
1798
+ transparent: true,
1799
+ depthTest: false
1800
+ });
1801
+ material.toneMapped = false;
1802
+ const mesh = new THREE6.Mesh(geometry, material);
1803
+ scene.add(mesh);
1804
+ if (loadedTextureRef.current) {
1805
+ mediaUniformsRef.current.map.value = loadedTextureRef.current;
1806
+ material.uniforms.map.value = loadedTextureRef.current;
1807
+ }
1808
+ assetsRef.current = { mesh, geometry, material };
1809
+ cameraRef.current = camera;
1810
+ updateMeshScale();
1811
+ const composer = new import_postprocessing.EffectComposer(renderer);
1812
+ const renderPass = new import_postprocessing.RenderPass(scene, camera);
1813
+ const effect = new AsciiEffectImpl({
1814
+ ...initialEffectPropsRef.current,
1815
+ resolution: resolutionRef.current.clone()
1816
+ });
1817
+ const effectPass = new import_postprocessing.EffectPass(camera, effect);
1818
+ effectPass.renderToScreen = true;
1819
+ composer.addPass(renderPass);
1820
+ composer.addPass(effectPass);
1821
+ composer.setSize(size.width, size.height);
1822
+ composerRef.current = composer;
1823
+ effectRef.current = effect;
1824
+ return () => {
1825
+ composer.dispose();
1826
+ if (assetsRef.current) {
1827
+ scene.remove(assetsRef.current.mesh);
1828
+ assetsRef.current.geometry.dispose();
1829
+ assetsRef.current.material.dispose();
1830
+ assetsRef.current = null;
1831
+ }
1832
+ cameraRef.current = null;
1833
+ loadedTextureRef.current?.dispose();
1834
+ loadedTextureRef.current = null;
1835
+ composerRef.current = null;
1836
+ effectRef.current = null;
1837
+ };
1838
+ },
1839
+ [updateMeshScale]
1840
+ );
1841
+ const handleRender = (0, import_react6.useCallback)(
1842
+ (_context, delta, _elapsed) => {
1843
+ const assets = assetsRef.current;
1844
+ if (assets) {
1845
+ const enabled = mouseParallax && parallaxIntensityRef.current > 0 && assets.mesh;
1846
+ if (enabled) {
1847
+ parallaxStateRef.current.rotationX += (parallaxStateRef.current.targetX - parallaxStateRef.current.rotationX) * PARALLAX_LERP;
1848
+ parallaxStateRef.current.rotationY += (parallaxStateRef.current.targetY - parallaxStateRef.current.rotationY) * PARALLAX_LERP;
1849
+ assets.mesh.rotation.x = parallaxStateRef.current.rotationX;
1850
+ assets.mesh.rotation.y = parallaxStateRef.current.rotationY;
1851
+ } else if (Math.abs(assets.mesh.rotation.x) > 1e-3 || Math.abs(assets.mesh.rotation.y) > 1e-3) {
1852
+ assets.mesh.rotation.x *= 0.9;
1853
+ assets.mesh.rotation.y *= 0.9;
1854
+ }
1855
+ }
1856
+ composerRef.current?.render(delta);
1857
+ },
1858
+ [mouseParallax]
1859
+ );
1860
+ const handleResize = (0, import_react6.useCallback)(
1861
+ (_context, size) => {
1862
+ const composer = composerRef.current;
1863
+ composer?.setSize(size.width, size.height);
1864
+ viewportSizeRef.current = { width: size.width, height: size.height };
1865
+ updateMeshScale();
1866
+ updatePointerBounds(containerRef.current);
1867
+ if (manualResolutionRef.current) {
1868
+ resolutionRef.current.copy(manualResolutionRef.current);
1869
+ } else {
1870
+ resolutionRef.current.set(size.width, size.height);
1871
+ }
1872
+ effectRef.current?.updateUniforms({
1873
+ resolution: resolutionRef.current
1874
+ });
1875
+ if (!usesExternalMouseRef.current) {
1876
+ autoMouseRef.current.set(size.width / 2, size.height / 2);
1877
+ effectRef.current?.updateUniforms({ mousePos: autoMouseRef.current });
1878
+ }
1879
+ },
1880
+ [updateMeshScale, updatePointerBounds]
1881
+ );
1882
+ const { containerRef, contextRef } = useScene({
1883
+ camera: {
1884
+ type: "perspective",
1885
+ near: 0.1,
1886
+ far: 100,
1887
+ position: [0, 0, 10],
1888
+ fov: 50
1889
+ },
1890
+ onCreate: handleCreate,
1891
+ onRender: handleRender,
1892
+ onResize: handleResize,
1893
+ manualRender: true
1894
+ });
1895
+ (0, import_react6.useEffect)(() => {
1896
+ if (!mouseParallax) {
1897
+ resetParallax();
1898
+ }
1899
+ }, [mouseParallax, resetParallax]);
1900
+ (0, import_react6.useEffect)(() => {
1901
+ if (!imageUrl) return;
1902
+ let disposed = false;
1903
+ const loader = new THREE6.TextureLoader();
1904
+ loader.load(
1905
+ imageUrl,
1906
+ (texture) => {
1907
+ if (disposed) {
1908
+ texture.dispose();
1909
+ return;
1910
+ }
1911
+ texture.colorSpace = THREE6.SRGBColorSpace;
1912
+ texture.wrapS = THREE6.ClampToEdgeWrapping;
1913
+ texture.wrapT = THREE6.ClampToEdgeWrapping;
1914
+ texture.minFilter = THREE6.LinearFilter;
1915
+ texture.magFilter = THREE6.LinearFilter;
1916
+ loadedTextureRef.current?.dispose();
1917
+ loadedTextureRef.current = texture;
1918
+ mediaUniformsRef.current.map.value = texture;
1919
+ const assets = assetsRef.current;
1920
+ if (assets) {
1921
+ assets.material.uniforms.map.value = texture;
1922
+ }
1923
+ updateMeshScale();
1924
+ updateTextureUVTransform();
1925
+ },
1926
+ void 0,
1927
+ () => {
1928
+ if (disposed) return;
1929
+ loadedTextureRef.current?.dispose();
1930
+ loadedTextureRef.current = null;
1931
+ }
1932
+ );
1933
+ return () => {
1934
+ disposed = true;
1935
+ };
1936
+ }, [imageUrl, updateMeshScale, updateTextureUVTransform]);
1937
+ (0, import_react6.useEffect)(() => {
1938
+ const effect = effectRef.current;
1939
+ if (!effect) return;
1940
+ effect.updateUniforms({
1941
+ cellSize,
1942
+ invert,
1943
+ colorMode,
1944
+ asciiStyle
1945
+ });
1946
+ }, [asciiStyle, cellSize, colorMode, invert]);
1947
+ (0, import_react6.useEffect)(() => {
1948
+ if (!effectRef.current) return;
1949
+ effectRef.current.updateUniforms(resolvedPostProcessing);
1950
+ }, [resolvedPostProcessing]);
1951
+ (0, import_react6.useEffect)(() => {
1952
+ mediaUniformsRef.current.brightness.value = resolvedMediaAdjustments.brightness;
1953
+ mediaUniformsRef.current.contrast.value = resolvedMediaAdjustments.contrast;
1954
+ mediaUniformsRef.current.saturation.value = resolvedMediaAdjustments.saturation;
1955
+ const material = assetsRef.current?.material;
1956
+ if (material) {
1957
+ material.uniforms.brightness.value = resolvedMediaAdjustments.brightness;
1958
+ material.uniforms.contrast.value = resolvedMediaAdjustments.contrast;
1959
+ material.uniforms.saturation.value = resolvedMediaAdjustments.saturation;
1960
+ }
1961
+ }, [resolvedMediaAdjustments]);
1962
+ (0, import_react6.useEffect)(() => {
1963
+ if (!mousePosition || !effectRef.current) return;
1964
+ effectRef.current.updateUniforms({ mousePos: mousePosition });
1965
+ }, [mousePosition]);
1966
+ (0, import_react6.useEffect)(() => {
1967
+ if (!resolution || !effectRef.current) return;
1968
+ resolutionRef.current.copy(resolution);
1969
+ manualResolutionRef.current = resolution.clone();
1970
+ effectRef.current.updateUniforms({ resolution });
1971
+ }, [resolution]);
1972
+ (0, import_react6.useEffect)(() => {
1973
+ if (mousePosition) return;
1974
+ const container = containerRef.current;
1975
+ if (!container) return;
1976
+ updatePointerBounds(container);
1977
+ const updateFromEvent = (event) => {
1978
+ const bounds = pointerBoundsRef.current;
1979
+ autoMouseRef.current.set(
1980
+ event.clientX - bounds.left,
1981
+ bounds.height - (event.clientY - bounds.top)
1982
+ );
1983
+ effectRef.current?.updateUniforms({ mousePos: autoMouseRef.current });
1984
+ if (mouseParallax && bounds.width > 0 && bounds.height > 0) {
1985
+ const normalizedX = ((event.clientX - bounds.left) / bounds.width - 0.5) * 2;
1986
+ const normalizedY = ((event.clientY - bounds.top) / bounds.height - 0.5) * 2;
1987
+ const intensity = parallaxIntensityRef.current;
1988
+ parallaxStateRef.current.targetY = 0.3 * normalizedX * intensity;
1989
+ parallaxStateRef.current.targetX = -0.2 * normalizedY * intensity;
1990
+ }
1991
+ };
1992
+ const handlePointerEnter = () => {
1993
+ updatePointerBounds();
1994
+ };
1995
+ const resetToCenter = () => {
1996
+ const size = contextRef.current?.size ?? {
1997
+ width: container.clientWidth || 1,
1998
+ height: container.clientHeight || 1
1999
+ };
2000
+ autoMouseRef.current.set(size.width / 2, size.height / 2);
2001
+ effectRef.current?.updateUniforms({ mousePos: autoMouseRef.current });
2002
+ if (mouseParallax) {
2003
+ resetParallax();
2004
+ }
2005
+ };
2006
+ resetToCenter();
2007
+ container.addEventListener("pointermove", updateFromEvent);
2008
+ container.addEventListener("pointerenter", handlePointerEnter);
2009
+ container.addEventListener("pointerleave", resetToCenter);
2010
+ return () => {
2011
+ container.removeEventListener("pointermove", updateFromEvent);
2012
+ container.removeEventListener("pointerenter", handlePointerEnter);
2013
+ container.removeEventListener("pointerleave", resetToCenter);
2014
+ };
2015
+ }, [
2016
+ containerRef,
2017
+ contextRef,
2018
+ mouseParallax,
2019
+ mousePosition,
2020
+ resetParallax,
2021
+ updatePointerBounds
2022
+ ]);
2023
+ (0, import_react6.useEffect)(() => {
2024
+ parallaxIntensityRef.current = THREE6.MathUtils.clamp(
2025
+ parallaxIntensity ?? 0,
2026
+ 0,
2027
+ 1
2028
+ );
2029
+ }, [parallaxIntensity]);
2030
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2031
+ "div",
2032
+ {
2033
+ ref: containerRef,
2034
+ className,
2035
+ style: {
2036
+ width: width ?? "100%",
2037
+ height: height ?? "100%",
2038
+ ...style
2039
+ },
2040
+ ...divProps
2041
+ }
2042
+ );
2043
+ }
2044
+
2045
+ // src/components/EfectoAsciiWrapper.tsx
2046
+ var import_jsx_runtime6 = require("react/jsx-runtime");
2047
+ function EfectoAsciiWrapper({
2048
+ settings,
2049
+ imageUrl,
2050
+ mediaAdjustments,
2051
+ mouseParallax,
2052
+ parallaxIntensity,
2053
+ ...passThrough
2054
+ }) {
2055
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2056
+ AsciiEffect,
2057
+ {
2058
+ asciiStyle: settings.asciiStyle,
2059
+ cellSize: settings.cellSize,
2060
+ invert: settings.invert,
2061
+ colorMode: settings.colorMode,
2062
+ postProcessing: settings.postProcessing,
2063
+ imageUrl,
2064
+ mediaAdjustments,
2065
+ mouseParallax,
2066
+ parallaxIntensity,
2067
+ ...passThrough
2068
+ }
2069
+ );
2070
+ }
2071
+
2072
+ // src/components/Efecto.tsx
2073
+ var import_jsx_runtime7 = require("react/jsx-runtime");
2074
+ var ASCII_BASE_DEFAULTS = {
2075
+ cellSize: EFECTO_ASCII_COMPONENT_DEFAULTS.cellSize,
2076
+ invert: EFECTO_ASCII_COMPONENT_DEFAULTS.invert,
2077
+ colorMode: EFECTO_ASCII_COMPONENT_DEFAULTS.colorMode,
2078
+ asciiStyle: EFECTO_ASCII_COMPONENT_DEFAULTS.asciiStyle
2079
+ };
2080
+ function Efecto({
2081
+ postProcessing,
2082
+ src,
2083
+ mouseParallax = false,
2084
+ parallaxIntensity = 0.5,
2085
+ mediaAdjustments,
2086
+ cellSize,
2087
+ invert,
2088
+ colorMode,
2089
+ style,
2090
+ asciiStyle,
2091
+ ...wrapperProps
2092
+ }) {
2093
+ const resolvedStyle = style ?? asciiStyle ?? ASCII_BASE_DEFAULTS.asciiStyle;
2094
+ const baseAsciiProps = {
2095
+ cellSize: cellSize ?? ASCII_BASE_DEFAULTS.cellSize,
2096
+ invert: invert ?? ASCII_BASE_DEFAULTS.invert,
2097
+ colorMode: colorMode ?? ASCII_BASE_DEFAULTS.colorMode,
2098
+ asciiStyle: resolvedStyle
2099
+ };
2100
+ const asciiSettings = {
2101
+ ...baseAsciiProps,
2102
+ postProcessing
2103
+ };
2104
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2105
+ EfectoAsciiWrapper,
2106
+ {
2107
+ settings: asciiSettings,
2108
+ imageUrl: src,
2109
+ mediaAdjustments,
2110
+ mouseParallax,
2111
+ parallaxIntensity,
2112
+ ...wrapperProps
2113
+ }
2114
+ );
2115
+ }
2116
+
2117
+ // src/components/Snow.tsx
2118
+ var import_react7 = require("react");
2119
+ var THREE7 = __toESM(require("three"));
2120
+
2121
+ // src/shaders/snow/fragment.glsl
2122
+ var fragment_default7 = "precision mediump float;\n\nuniform vec3 uColor;\n\nvarying float vAlpha;\n\nvoid main() {\n vec2 uv = gl_PointCoord - 0.5;\n float dist = length(uv);\n float mask = smoothstep(0.5, 0.0, dist);\n if (mask <= 0.01) {\n discard;\n }\n\n float centerGlow = smoothstep(0.22, 0.0, dist);\n vec3 color = mix(uColor * 1.2, uColor, centerGlow);\n\n gl_FragColor = vec4(color, mask * vAlpha);\n}\n";
2123
+
2124
+ // src/shaders/snow/vertex.glsl
2125
+ var vertex_default6 = "uniform float uTime;\nuniform float uFallSpeed;\nuniform float uWindStrength;\nuniform float uTurbulence;\nuniform float uSize;\nuniform float uTwinkleStrength;\nuniform vec3 uArea;\n\nattribute float aSpeed;\nattribute float aSize;\nattribute float aSeed;\n\nvarying float vAlpha;\n\nfloat wrap(float value, float size) {\n return mod(value + size * 0.5, size) - size * 0.5;\n}\n\nvoid main() {\n float height = uArea.y;\n float width = uArea.x;\n float depth = uArea.z;\n\n float fall = uFallSpeed * (0.3 + aSpeed);\n float droppedY = position.y - uTime * fall;\n float wrappedY = wrap(droppedY, height);\n\n float sway =\n sin((wrappedY + aSeed) * 0.45 + uTime * 0.8) * uTurbulence +\n cos(uTime * 0.35 + aSeed) * 0.15;\n float wind = uWindStrength * (0.4 + aSpeed);\n float displacedX = wrap(position.x + sway + wind, width);\n\n float driftZ =\n sin(uTime * 0.25 + aSeed * 1.7) * 0.5 +\n cos((wrappedY + aSeed) * 0.2) * 0.4;\n float displacedZ = wrap(position.z + driftZ, depth);\n\n vec4 modelPosition =\n modelMatrix * vec4(displacedX, wrappedY, displacedZ, 1.0);\n vec4 viewPosition = viewMatrix * modelPosition;\n\n float baseSize = mix(0.45, 1.0, aSize) * uSize;\n float twinkle =\n 1.0 + sin(uTime * (0.6 + aSpeed) + aSeed) * uTwinkleStrength;\n float perspective = clamp(15.0 / max(1.0, -viewPosition.z), 0.5, 3.0);\n gl_PointSize = baseSize * twinkle * perspective;\n gl_Position = projectionMatrix * viewPosition;\n\n vAlpha = mix(0.35, 1.0, aSize);\n}\n";
2126
+
2127
+ // src/components/Snow.tsx
2128
+ var import_jsx_runtime8 = require("react/jsx-runtime");
2129
+ var AREA_BOUNDS = {
2130
+ width: 36,
2131
+ height: 44,
2132
+ depth: 26
2133
+ };
2134
+ function createSnowGeometry(count) {
2135
+ const geometry = new THREE7.BufferGeometry();
2136
+ const positions = new Float32Array(count * 3);
2137
+ const speeds = new Float32Array(count);
2138
+ const sizes = new Float32Array(count);
2139
+ const seeds = new Float32Array(count);
2140
+ for (let i = 0; i < count; i += 1) {
2141
+ const x = (Math.random() - 0.5) * AREA_BOUNDS.width;
2142
+ const y = (Math.random() - 0.5) * AREA_BOUNDS.height;
2143
+ const z = (Math.random() - 0.5) * AREA_BOUNDS.depth;
2144
+ positions[i * 3] = x;
2145
+ positions[i * 3 + 1] = y;
2146
+ positions[i * 3 + 2] = z;
2147
+ speeds[i] = Math.random();
2148
+ sizes[i] = Math.random();
2149
+ seeds[i] = Math.random() * 100;
2150
+ }
2151
+ geometry.setAttribute("position", new THREE7.BufferAttribute(positions, 3));
2152
+ geometry.setAttribute("aSpeed", new THREE7.BufferAttribute(speeds, 1));
2153
+ geometry.setAttribute("aSize", new THREE7.BufferAttribute(sizes, 1));
2154
+ geometry.setAttribute("aSeed", new THREE7.BufferAttribute(seeds, 1));
2155
+ geometry.computeBoundingSphere();
2156
+ return geometry;
2157
+ }
2158
+ function buildUniforms2({
2159
+ color,
2160
+ fallSpeed,
2161
+ windStrength,
2162
+ turbulence,
2163
+ flakeSize,
2164
+ twinkleStrength
2165
+ }) {
2166
+ return {
2167
+ uTime: { value: 0 },
2168
+ uFallSpeed: { value: fallSpeed },
2169
+ uWindStrength: { value: windStrength },
2170
+ uTurbulence: { value: turbulence },
2171
+ uSize: { value: flakeSize },
2172
+ uTwinkleStrength: { value: twinkleStrength },
2173
+ uColor: { value: new THREE7.Color(color) },
2174
+ uArea: {
2175
+ value: new THREE7.Vector3(
2176
+ AREA_BOUNDS.width,
2177
+ AREA_BOUNDS.height,
2178
+ AREA_BOUNDS.depth
2179
+ )
2180
+ }
2181
+ };
2182
+ }
2183
+ function Snow({
2184
+ className,
2185
+ style,
2186
+ width,
2187
+ height,
2188
+ color,
2189
+ fallSpeed,
2190
+ windStrength,
2191
+ turbulence,
2192
+ flakeSize,
2193
+ twinkleStrength,
2194
+ flakeCount,
2195
+ mouseWindInteraction = false,
2196
+ ...divProps
2197
+ }) {
2198
+ const snowRef = (0, import_react7.useRef)(null);
2199
+ const uniformsRef = (0, import_react7.useRef)({
2200
+ color,
2201
+ fallSpeed,
2202
+ windStrength,
2203
+ turbulence,
2204
+ flakeSize,
2205
+ twinkleStrength,
2206
+ flakeCount
2207
+ });
2208
+ uniformsRef.current = {
2209
+ color,
2210
+ fallSpeed,
2211
+ windStrength,
2212
+ turbulence,
2213
+ flakeSize,
2214
+ twinkleStrength,
2215
+ flakeCount
2216
+ };
2217
+ const pointerWindOffsetRef = (0, import_react7.useRef)(0);
2218
+ const pointerWindTargetRef = (0, import_react7.useRef)(0);
2219
+ const pointerStateRef = (0, import_react7.useRef)({
2220
+ lastX: 0,
2221
+ lastTime: 0,
2222
+ timeoutId: null
2223
+ });
2224
+ const pointerActiveRef = (0, import_react7.useRef)(false);
2225
+ const baseWindRef = (0, import_react7.useRef)(windStrength);
2226
+ (0, import_react7.useEffect)(() => {
2227
+ baseWindRef.current = windStrength;
2228
+ }, [windStrength]);
2229
+ const handleCreate = (0, import_react7.useCallback)(({ scene }) => {
2230
+ const uniforms = buildUniforms2(uniformsRef.current);
2231
+ const geometry = createSnowGeometry(
2232
+ Math.max(1, Math.floor(uniformsRef.current.flakeCount))
2233
+ );
2234
+ const material = new THREE7.ShaderMaterial({
2235
+ fragmentShader: fragment_default7,
2236
+ vertexShader: vertex_default6,
2237
+ uniforms,
2238
+ transparent: true,
2239
+ depthWrite: false,
2240
+ blending: THREE7.AdditiveBlending
2241
+ });
2242
+ const points = new THREE7.Points(geometry, material);
2243
+ points.frustumCulled = false;
2244
+ scene.add(points);
2245
+ snowRef.current = { points, geometry, material, uniforms };
2246
+ return () => {
2247
+ scene.remove(points);
2248
+ geometry.dispose();
2249
+ material.dispose();
2250
+ snowRef.current = null;
2251
+ };
2252
+ }, []);
2253
+ const handleRender = (0, import_react7.useCallback)(
2254
+ (_context, delta, elapsedTime) => {
2255
+ const assets = snowRef.current;
2256
+ if (!assets) return;
2257
+ assets.uniforms.uTime.value = elapsedTime;
2258
+ const currentOffset = pointerWindOffsetRef.current;
2259
+ const targetOffset = pointerWindTargetRef.current;
2260
+ const nextOffset = THREE7.MathUtils.damp(
2261
+ currentOffset,
2262
+ targetOffset,
2263
+ 3.5,
2264
+ delta
2265
+ );
2266
+ if (Math.abs(nextOffset - currentOffset) > 5e-5) {
2267
+ pointerWindOffsetRef.current = nextOffset;
2268
+ assets.uniforms.uWindStrength.value = baseWindRef.current + nextOffset;
2269
+ }
2270
+ },
2271
+ []
2272
+ );
2273
+ const { containerRef } = useScene({
2274
+ camera: {
2275
+ position: [0, 0, 18]
2276
+ },
2277
+ onCreate: handleCreate,
2278
+ onRender: handleRender
2279
+ });
2280
+ (0, import_react7.useEffect)(() => {
2281
+ const assets = snowRef.current;
2282
+ if (!assets) return;
2283
+ assets.uniforms.uColor.value.set(color);
2284
+ }, [color]);
2285
+ (0, import_react7.useEffect)(() => {
2286
+ const assets = snowRef.current;
2287
+ if (!assets) return;
2288
+ assets.uniforms.uFallSpeed.value = fallSpeed;
2289
+ }, [fallSpeed]);
2290
+ (0, import_react7.useEffect)(() => {
2291
+ const assets = snowRef.current;
2292
+ if (!assets) return;
2293
+ assets.uniforms.uWindStrength.value = windStrength + pointerWindOffsetRef.current;
2294
+ }, [windStrength]);
2295
+ (0, import_react7.useEffect)(() => {
2296
+ const assets = snowRef.current;
2297
+ if (!assets) return;
2298
+ assets.uniforms.uTurbulence.value = turbulence;
2299
+ }, [turbulence]);
2300
+ (0, import_react7.useEffect)(() => {
2301
+ const assets = snowRef.current;
2302
+ if (!assets) return;
2303
+ assets.uniforms.uSize.value = flakeSize;
2304
+ }, [flakeSize]);
2305
+ (0, import_react7.useEffect)(() => {
2306
+ const assets = snowRef.current;
2307
+ if (!assets) return;
2308
+ assets.uniforms.uTwinkleStrength.value = twinkleStrength;
2309
+ }, [twinkleStrength]);
2310
+ (0, import_react7.useEffect)(() => {
2311
+ const assets = snowRef.current;
2312
+ if (!assets) return;
2313
+ const geometry = createSnowGeometry(Math.max(1, Math.floor(flakeCount)));
2314
+ assets.points.geometry.dispose();
2315
+ assets.points.geometry = geometry;
2316
+ assets.geometry = geometry;
2317
+ }, [flakeCount]);
2318
+ (0, import_react7.useEffect)(() => {
2319
+ const pointerState = pointerStateRef.current;
2320
+ const clearTimeoutIfNeeded = () => {
2321
+ if (pointerState.timeoutId !== null) {
2322
+ window.clearTimeout(pointerState.timeoutId);
2323
+ pointerState.timeoutId = null;
2324
+ }
2325
+ };
2326
+ if (!mouseWindInteraction) {
2327
+ clearTimeoutIfNeeded();
2328
+ pointerWindOffsetRef.current = 0;
2329
+ pointerWindTargetRef.current = 0;
2330
+ pointerState.lastTime = 0;
2331
+ pointerActiveRef.current = false;
2332
+ const assets = snowRef.current;
2333
+ if (assets) {
2334
+ assets.uniforms.uWindStrength.value = windStrength;
2335
+ }
2336
+ return;
2337
+ }
2338
+ const container = containerRef.current;
2339
+ if (!container) return;
2340
+ const scheduleReset = () => {
2341
+ clearTimeoutIfNeeded();
2342
+ pointerState.timeoutId = window.setTimeout(() => {
2343
+ pointerWindTargetRef.current = 0;
2344
+ pointerState.timeoutId = null;
2345
+ }, 220);
2346
+ };
2347
+ const handlePointerMove = (event) => {
2348
+ const isMouse = event.pointerType === "mouse";
2349
+ if (!isMouse && !pointerActiveRef.current) return;
2350
+ const now = performance.now();
2351
+ if (pointerState.lastTime === 0) {
2352
+ pointerState.lastX = event.clientX;
2353
+ pointerState.lastTime = now;
2354
+ return;
2355
+ }
2356
+ const dx = event.clientX - pointerState.lastX;
2357
+ const dt = Math.max(1, now - pointerState.lastTime);
2358
+ const velocity = dx / dt;
2359
+ const offset = THREE7.MathUtils.clamp(velocity * 0.9, -1.6, 1.6);
2360
+ pointerWindTargetRef.current = offset;
2361
+ pointerState.lastX = event.clientX;
2362
+ pointerState.lastTime = now;
2363
+ scheduleReset();
2364
+ };
2365
+ const handlePointerDown = (event) => {
2366
+ pointerActiveRef.current = true;
2367
+ pointerState.lastX = event.clientX;
2368
+ pointerState.lastTime = performance.now();
2369
+ scheduleReset();
2370
+ };
2371
+ const handlePointerUp = () => {
2372
+ pointerActiveRef.current = false;
2373
+ pointerState.lastTime = 0;
2374
+ pointerWindTargetRef.current = 0;
2375
+ scheduleReset();
2376
+ };
2377
+ const handlePointerLeave = () => {
2378
+ pointerActiveRef.current = false;
2379
+ pointerState.lastTime = 0;
2380
+ pointerWindTargetRef.current = 0;
2381
+ clearTimeoutIfNeeded();
2382
+ };
2383
+ container.addEventListener("pointermove", handlePointerMove);
2384
+ container.addEventListener("pointerdown", handlePointerDown);
2385
+ container.addEventListener("pointerup", handlePointerUp);
2386
+ container.addEventListener("pointercancel", handlePointerUp);
2387
+ container.addEventListener("pointerout", handlePointerLeave);
2388
+ container.addEventListener("pointerleave", handlePointerLeave);
2389
+ return () => {
2390
+ container.removeEventListener("pointermove", handlePointerMove);
2391
+ container.removeEventListener("pointerdown", handlePointerDown);
2392
+ container.removeEventListener("pointerup", handlePointerUp);
2393
+ container.removeEventListener("pointercancel", handlePointerUp);
2394
+ container.removeEventListener("pointerout", handlePointerLeave);
2395
+ container.removeEventListener("pointerleave", handlePointerLeave);
2396
+ pointerState.lastTime = 0;
2397
+ pointerWindOffsetRef.current = 0;
2398
+ pointerWindTargetRef.current = 0;
2399
+ pointerActiveRef.current = false;
2400
+ clearTimeoutIfNeeded();
2401
+ const assets = snowRef.current;
2402
+ if (assets) {
2403
+ assets.uniforms.uWindStrength.value = windStrength;
2404
+ }
2405
+ };
2406
+ }, [containerRef, mouseWindInteraction, windStrength]);
2407
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2408
+ "div",
2409
+ {
2410
+ ref: containerRef,
2411
+ className,
2412
+ style: {
2413
+ width: width ?? "100%",
2414
+ height: height ?? "100%",
2415
+ ...style
2416
+ },
2417
+ ...divProps
2418
+ }
2419
+ );
2420
+ }
2421
+
2422
+ // src/components/AnimatedDrawingSVG.tsx
2423
+ var import_clsx = __toESM(require("clsx"));
2424
+ var import_react8 = require("react");
2425
+ var import_jsx_runtime9 = require("react/jsx-runtime");
2426
+ var PATH_SELECTOR = "path, line, polyline, polygon, circle, ellipse";
2427
+ function AnimatedDrawingSVG({
2428
+ svgMarkup,
2429
+ animated = true,
2430
+ size,
2431
+ onAnimated,
2432
+ delay,
2433
+ className,
2434
+ style,
2435
+ ...divProps
2436
+ }) {
2437
+ const containerRef = (0, import_react8.useRef)(null);
2438
+ const animationsRef = (0, import_react8.useRef)([]);
2439
+ const parserRef = (0, import_react8.useRef)(null);
2440
+ const onAnimatedRef = (0, import_react8.useRef)(onAnimated);
2441
+ const animationRunIdRef = (0, import_react8.useRef)(0);
2442
+ const onAnimationCompleteRef = (0, import_react8.useRef)(false);
2443
+ const timeoutRef = (0, import_react8.useRef)([]);
2444
+ const monitorRafRef = (0, import_react8.useRef)(null);
2445
+ const sanitizedMarkup = (svgMarkup ?? "").toString().trim();
2446
+ const normalizedDelay = typeof delay === "number" && delay > 0 ? delay : 0;
2447
+ (0, import_react8.useEffect)(() => {
2448
+ onAnimatedRef.current = onAnimated;
2449
+ }, [onAnimated]);
2450
+ (0, import_react8.useEffect)(() => {
2451
+ return () => {
2452
+ animationsRef.current.forEach((animation) => animation.cancel());
2453
+ animationsRef.current = [];
2454
+ timeoutRef.current.forEach((id) => window.clearTimeout(id));
2455
+ timeoutRef.current = [];
2456
+ if (monitorRafRef.current !== null) {
2457
+ cancelAnimationFrame(monitorRafRef.current);
2458
+ monitorRafRef.current = null;
2459
+ }
2460
+ };
2461
+ }, []);
2462
+ (0, import_react8.useLayoutEffect)(() => {
2463
+ const container = containerRef.current;
2464
+ if (!container) return;
2465
+ let rafId = null;
2466
+ let delayId = null;
2467
+ let started = false;
2468
+ if (normalizedDelay > 0) {
2469
+ container.style.visibility = "hidden";
2470
+ } else {
2471
+ container.style.removeProperty("visibility");
2472
+ }
2473
+ animationRunIdRef.current += 1;
2474
+ const currentRunId = animationRunIdRef.current;
2475
+ onAnimationCompleteRef.current = false;
2476
+ timeoutRef.current.forEach((id) => window.clearTimeout(id));
2477
+ timeoutRef.current = [];
2478
+ const markComplete = () => {
2479
+ if (animationRunIdRef.current === currentRunId && !onAnimationCompleteRef.current) {
2480
+ onAnimationCompleteRef.current = true;
2481
+ onAnimatedRef.current?.();
2482
+ }
2483
+ };
2484
+ animationsRef.current.forEach((animation) => animation.cancel());
2485
+ animationsRef.current = [];
2486
+ if (monitorRafRef.current !== null) {
2487
+ cancelAnimationFrame(monitorRafRef.current);
2488
+ monitorRafRef.current = null;
2489
+ }
2490
+ if (!sanitizedMarkup) {
2491
+ container.replaceChildren();
2492
+ markComplete();
2493
+ return;
2494
+ }
2495
+ const parser = parserRef.current ?? new DOMParser();
2496
+ parserRef.current = parser;
2497
+ let parsed;
2498
+ try {
2499
+ parsed = parser.parseFromString(sanitizedMarkup, "image/svg+xml");
2500
+ } catch {
2501
+ return;
2502
+ }
2503
+ if (parsed.querySelector("parsererror")) {
2504
+ return;
2505
+ }
2506
+ const parsedSvg = parsed.querySelector("svg");
2507
+ if (!parsedSvg) {
2508
+ container.replaceChildren();
2509
+ onAnimatedRef.current?.();
2510
+ return;
2511
+ }
2512
+ const svgElement = document.importNode(parsedSvg, true);
2513
+ svgElement.setAttribute("preserveAspectRatio", "xMidYMid meet");
2514
+ if (size !== void 0) {
2515
+ svgElement.removeAttribute("width");
2516
+ svgElement.removeAttribute("height");
2517
+ const sizeValue = typeof size === "number" ? `${Math.max(0, size)}px` : `${size}`;
2518
+ svgElement.style.width = sizeValue;
2519
+ svgElement.style.height = "auto";
2520
+ } else {
2521
+ svgElement.style.width = "100%";
2522
+ svgElement.style.height = "100%";
2523
+ svgElement.style.maxWidth = "100%";
2524
+ svgElement.style.maxHeight = "100%";
2525
+ }
2526
+ svgElement.style.display = "block";
2527
+ container.replaceChildren(svgElement);
2528
+ const runAnimations = () => {
2529
+ const drawTargets = Array.from(
2530
+ svgElement.querySelectorAll(PATH_SELECTOR)
2531
+ );
2532
+ const scheduleFallback = (delay2) => {
2533
+ const fallbackId = window.setTimeout(markComplete, delay2);
2534
+ timeoutRef.current.push(fallbackId);
2535
+ };
2536
+ if (!drawTargets.length) {
2537
+ if (!animated) {
2538
+ markComplete();
2539
+ } else {
2540
+ Promise.resolve().then(() => {
2541
+ markComplete();
2542
+ });
2543
+ }
2544
+ return;
2545
+ }
2546
+ let maxDuration = 0;
2547
+ const resolveTimingValue = (value, fallback) => {
2548
+ if (typeof value === "number") {
2549
+ return value;
2550
+ }
2551
+ if (typeof value === "string") {
2552
+ const parsed2 = Number.parseFloat(value);
2553
+ return Number.isFinite(parsed2) ? parsed2 : fallback;
2554
+ }
2555
+ if (typeof value === "object" && value !== null) {
2556
+ const parsed2 = Number.parseFloat(value.toString());
2557
+ return Number.isFinite(parsed2) ? parsed2 : fallback;
2558
+ }
2559
+ return fallback;
2560
+ };
2561
+ drawTargets.forEach((element, index) => {
2562
+ const length = typeof element.getTotalLength === "function" ? element.getTotalLength() : null;
2563
+ if (!length || Number.isNaN(length)) {
2564
+ element.style.removeProperty("stroke-dasharray");
2565
+ element.style.removeProperty("stroke-dashoffset");
2566
+ return;
2567
+ }
2568
+ const dashValue = `${length}`;
2569
+ element.style.strokeDasharray = dashValue;
2570
+ element.style.strokeDashoffset = animated ? dashValue : "0";
2571
+ if (!element.style.strokeLinecap) {
2572
+ element.style.strokeLinecap = "round";
2573
+ }
2574
+ if (!animated) {
2575
+ return;
2576
+ }
2577
+ const animation = element.animate(
2578
+ [{ strokeDashoffset: dashValue }, { strokeDashoffset: "0" }],
2579
+ {
2580
+ duration: Math.min(6500, Math.max(1200, length * 12)),
2581
+ delay: index * 120,
2582
+ easing: "ease-in-out",
2583
+ fill: "forwards"
2584
+ }
2585
+ );
2586
+ const timing = animation.effect?.getTiming();
2587
+ const baseDuration = Math.min(6500, Math.max(1200, length * 12));
2588
+ const total = resolveTimingValue(timing?.delay, index * 120) + resolveTimingValue(timing?.duration, baseDuration);
2589
+ if (total > maxDuration) {
2590
+ maxDuration = total;
2591
+ }
2592
+ animationsRef.current.push(animation);
2593
+ });
2594
+ if (!animated) {
2595
+ markComplete();
2596
+ return;
2597
+ }
2598
+ const startMonitor = () => {
2599
+ const monitor = () => {
2600
+ if (animationRunIdRef.current !== currentRunId) {
2601
+ return;
2602
+ }
2603
+ const allFinished = animationsRef.current.every((animation) => {
2604
+ const state = animation.playState;
2605
+ return state === "finished" || state === "idle";
2606
+ });
2607
+ if (allFinished) {
2608
+ if (monitorRafRef.current !== null) {
2609
+ cancelAnimationFrame(monitorRafRef.current);
2610
+ monitorRafRef.current = null;
2611
+ }
2612
+ markComplete();
2613
+ return;
2614
+ }
2615
+ monitorRafRef.current = requestAnimationFrame(monitor);
2616
+ };
2617
+ if (monitorRafRef.current !== null) {
2618
+ cancelAnimationFrame(monitorRafRef.current);
2619
+ }
2620
+ monitorRafRef.current = requestAnimationFrame(monitor);
2621
+ };
2622
+ startMonitor();
2623
+ if (animated && maxDuration > 0) {
2624
+ scheduleFallback(maxDuration + 50);
2625
+ }
2626
+ };
2627
+ const triggerStart = () => {
2628
+ if (started) return;
2629
+ started = true;
2630
+ container.style.removeProperty("visibility");
2631
+ rafId = requestAnimationFrame(runAnimations);
2632
+ };
2633
+ if (normalizedDelay > 0) {
2634
+ delayId = window.setTimeout(triggerStart, normalizedDelay);
2635
+ } else {
2636
+ triggerStart();
2637
+ }
2638
+ return () => {
2639
+ if (delayId !== null) {
2640
+ window.clearTimeout(delayId);
2641
+ }
2642
+ if (rafId !== null) {
2643
+ cancelAnimationFrame(rafId);
2644
+ }
2645
+ };
2646
+ }, [sanitizedMarkup, animated, size, normalizedDelay]);
2647
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2648
+ "div",
2649
+ {
2650
+ ref: containerRef,
2651
+ className: (0, import_clsx.default)(
2652
+ "flex items-center justify-center [&_svg]:block",
2653
+ className
2654
+ ),
2655
+ style: {
2656
+ ...style
2657
+ },
2658
+ ...divProps
2659
+ }
2660
+ );
2661
+ }
1077
2662
  // Annotate the CommonJS export names for ESM import in node:
1078
2663
  0 && (module.exports = {
2664
+ AnimatedDrawingSVG,
2665
+ EFECTO_ASCII_COMPONENT_DEFAULTS,
2666
+ EFECTO_ASCII_POST_PROCESSING_DEFAULTS,
2667
+ Efecto,
1079
2668
  FractalFlower,
1080
2669
  MenuGlitch,
1081
2670
  OranoParticles,
1082
- ShaderArt
2671
+ ShaderArt,
2672
+ Snow
1083
2673
  });