@neo-ui-kit/react 1.3.6 → 1.3.7

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/README.md CHANGED
@@ -25,7 +25,7 @@ import "@neo-ui-kit/react/styles.css";
25
25
  To test repository changes before publishing, run `npm run package` from the repository root and install the resulting archive in a separate application:
26
26
 
27
27
  ```bash
28
- npm install /path/to/adui/release/neo-ui-kit-react-1.3.6.tgz
28
+ npm install /path/to/adui/release/neo-ui-kit-react-1.3.7.tgz
29
29
  ```
30
30
 
31
31
  Maintainers publish new versions from `Pro100Dimka/adui` using the `release.yml` GitHub Actions workflow, a matching `v<version>` tag, and the `npm-publication` environment. npm trusts its OIDC identity; no `NPM_TOKEN` is required. The workflow checks the project and packed consumer before publishing the tested archive. Published `1.0.0` cannot be overwritten: code and README changes in npm require a new package version. See the [repository release instructions](https://github.com/Pro100Dimka/adui#npm-пакет).
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  themes,
3
3
  usePauseOffscreen
4
- } from "./chunk-6VBE5UOI.js";
4
+ } from "./chunk-YVRQTI7B.js";
5
5
  import {
6
6
  assignRef,
7
7
  clamp,
@@ -134,8 +134,8 @@ function startWorker() {
134
134
  }
135
135
  function createBorderWorker(item) {
136
136
  if (unavailable || typeof Worker === "undefined" || typeof OffscreenCanvas === "undefined" || typeof createImageBitmap === "undefined" || typeof HTMLCanvasElement === "undefined" || !HTMLCanvasElement.prototype.transferControlToOffscreen || typeof IntersectionObserver === "undefined" || typeof MutationObserver === "undefined") return null;
137
- const thread = startWorker();
138
- if (!thread) return null;
137
+ const thread2 = startWorker();
138
+ if (!thread2) return null;
139
139
  const id = ++serial, host = item.element;
140
140
  const groups = [...item.overlay.querySelectorAll(".ad-border-aura, .ad-border-core")];
141
141
  const originalVisibility = groups.map((group) => group.style.visibility);
@@ -153,7 +153,7 @@ function createBorderWorker(item) {
153
153
  if (visible && renderer.ready) elapsed += (performance.now() - since) / 1e3;
154
154
  since = performance.now();
155
155
  visible = next;
156
- thread.postMessage({ type: "visible", id, visible });
156
+ thread2.postMessage({ type: "visible", id, visible });
157
157
  };
158
158
  const observer = new IntersectionObserver((entries) => {
159
159
  inView = entries[0].isIntersecting;
@@ -198,7 +198,7 @@ function createBorderWorker(item) {
198
198
  });
199
199
  canvas.remove();
200
200
  clients.delete(id);
201
- if (worker === thread) thread.postMessage({ type: "remove", id });
201
+ if (worker === thread2) thread2.postMessage({ type: "remove", id });
202
202
  if (!clients.size) stopWorker();
203
203
  }
204
204
  function queue() {
@@ -264,7 +264,7 @@ function createBorderWorker(item) {
264
264
  canvas.style.height = `${height}px`;
265
265
  const surface = transferred ? void 0 : canvas.transferControlToOffscreen();
266
266
  transferred = true;
267
- thread.postMessage({
267
+ thread2.postMessage({
268
268
  type: "update",
269
269
  id,
270
270
  revision: current,
@@ -290,6 +290,541 @@ function createBorderWorker(item) {
290
290
  return renderer;
291
291
  }
292
292
 
293
+ // src/components/artwork/NeonWaves/neon-renderer.js
294
+ function createNeonGeometry() {
295
+ const W = 600;
296
+ const H = 120;
297
+ const SKYLINE = [
298
+ [0, 0.93],
299
+ [0.16, 0.86],
300
+ [0.3, 0.82],
301
+ [0.42, 0.72],
302
+ [0.55, 0.64],
303
+ [0.64, 0.7],
304
+ [0.74, 0.52],
305
+ [0.84, 0.1],
306
+ [0.9, 0.56],
307
+ [0.95, 0.46],
308
+ [1, 0.08]
309
+ ];
310
+ const skyline = (x) => {
311
+ const i = Math.max(0, SKYLINE.findIndex(([at]) => at >= x) - 1);
312
+ const [x0, y0] = SKYLINE[i];
313
+ const [x1, y1] = SKYLINE[Math.min(SKYLINE.length - 1, i + 1)];
314
+ const k = x1 === x0 ? 0 : (x - x0) / (x1 - x0);
315
+ return y0 + (y1 - y0) * (1 - Math.cos(k * Math.PI)) / 2;
316
+ };
317
+ const SAMPLES = 36;
318
+ const toPath = (curve) => {
319
+ let d = `M${curve[0].toFixed(2)} ${curve[1].toFixed(2)}`;
320
+ for (let i = 2; i < curve.length; i += 6)
321
+ d += `C${curve.slice(i, i + 6).map((n) => n.toFixed(2)).join(" ")}`;
322
+ return d;
323
+ };
324
+ const smoothTo = (curve, c2x, c2y, x, y) => {
325
+ const n = curve.length;
326
+ curve.push(
327
+ 2 * curve[n - 2] - curve[n - 4],
328
+ 2 * curve[n - 1] - curve[n - 3],
329
+ c2x,
330
+ c2y,
331
+ x,
332
+ y
333
+ );
334
+ };
335
+ const smooth = (xs, ys) => {
336
+ const curve = [xs[0], ys[0]];
337
+ for (let i = 0; i < xs.length - 1; i += 1) {
338
+ const x0 = xs[i - 1] ?? xs[i], y0 = ys[i - 1] ?? ys[i];
339
+ const x1 = xs[i], y1 = ys[i], x2 = xs[i + 1], y2 = ys[i + 1];
340
+ const x3 = xs[i + 2] ?? x2, y3 = ys[i + 2] ?? y2;
341
+ curve.push(
342
+ x1 + (x2 - x0) / 6,
343
+ y1 + (y2 - y0) / 6,
344
+ x2 - (x3 - x1) / 6,
345
+ y2 - (y3 - y1) / 6,
346
+ x2,
347
+ y2
348
+ );
349
+ }
350
+ return curve;
351
+ };
352
+ const ridgeStrand = (t, drift) => {
353
+ const xs = [];
354
+ const ys = [];
355
+ for (let i = 0; i <= SAMPLES; i += 1) {
356
+ const x = i / SAMPLES;
357
+ const base = skyline(x);
358
+ const spread = H * (0.06 + 0.26 * base);
359
+ const ripple = Math.sin(x * 8 + drift + t * 7) * H * (0.03 + 0.05 * base) + Math.sin(x * 21 - drift * 1.3 + t * 11) * H * 0.014;
360
+ xs.push(x * (W + 20) - 10);
361
+ ys.push(base * H + (t - 0.5) * spread + ripple);
362
+ }
363
+ return smooth(xs, ys);
364
+ };
365
+ const twistStrand = (t, drift, main) => {
366
+ const a = Math.sin(drift + t * 1.4) * H * 0.095;
367
+ const b = Math.cos(drift * 0.8 + t * 1.8) * H * 0.08;
368
+ if (!main) {
369
+ const curve2 = [
370
+ -12,
371
+ H * (0.9 + t * 0.12) + b,
372
+ W * 0.21,
373
+ H * 0.98 + a,
374
+ W * 0.33,
375
+ H * 0.24 + t * H * 0.2 + a,
376
+ W * 0.52,
377
+ H * 0.75 + t * H * 0.25 + b
378
+ ];
379
+ smoothTo(
380
+ curve2,
381
+ W * 0.82,
382
+ H * 0.38 + t * H * 0.27 + a,
383
+ W + 8,
384
+ H * (0.48 + t * 0.5) + b
385
+ );
386
+ return curve2;
387
+ }
388
+ const curve = [
389
+ -12,
390
+ H * (0.38 + t * 0.58) + a,
391
+ W * 0.2,
392
+ H * 1.28 - t * H * 0.27 + a,
393
+ W * 0.32,
394
+ H * 0.34 + t * H * 0.21 + b,
395
+ W * 0.46,
396
+ H * 0.62 + t * H * 0.12
397
+ ];
398
+ smoothTo(
399
+ curve,
400
+ W * 0.67,
401
+ H * 1.14 - t * H * 0.09 + a,
402
+ W * 0.8,
403
+ H * 0.69 - t * H * 0.22 + b
404
+ );
405
+ smoothTo(
406
+ curve,
407
+ W * 0.94,
408
+ H * 0.43 - t * H * 0.44 + a,
409
+ W + 8,
410
+ H * 0.21 + t * H * 0.45
411
+ );
412
+ return curve;
413
+ };
414
+ const STEPS = 16;
415
+ const measure = (curve) => {
416
+ const xs = [curve[0]], ys = [curve[1]], lengths = [0];
417
+ for (let i = 2; i < curve.length; i += 6) {
418
+ const x0 = curve[i - 2], y0 = curve[i - 1];
419
+ const [x1, y1, x2, y2, x3, y3] = curve.slice(i, i + 6);
420
+ for (let k = 1; k <= STEPS; k += 1) {
421
+ const u = k / STEPS, v = 1 - u;
422
+ const x = v * v * v * x0 + 3 * v * v * u * x1 + 3 * v * u * u * x2 + u * u * u * x3;
423
+ const y = v * v * v * y0 + 3 * v * v * u * y1 + 3 * v * u * u * y2 + u * u * u * y3;
424
+ lengths.push(
425
+ lengths[lengths.length - 1] + Math.hypot(x - xs[xs.length - 1], y - ys[ys.length - 1])
426
+ );
427
+ xs.push(x);
428
+ ys.push(y);
429
+ }
430
+ }
431
+ return { xs, ys, lengths, total: lengths[lengths.length - 1] };
432
+ };
433
+ const pointAt = (track, fraction) => {
434
+ const distance = Math.min(1, Math.max(0, fraction)) * track.total;
435
+ let low = 0, high = track.lengths.length - 1;
436
+ while (high - low > 1) {
437
+ const middle = low + high >> 1;
438
+ if (track.lengths[middle] < distance) low = middle;
439
+ else high = middle;
440
+ }
441
+ const span = track.lengths[high] - track.lengths[low] || 1;
442
+ const k = (distance - track.lengths[low]) / span;
443
+ return {
444
+ x: track.xs[low] + (track.xs[high] - track.xs[low]) * k,
445
+ y: track.ys[low] + (track.ys[high] - track.ys[low]) * k
446
+ };
447
+ };
448
+ const COMET_LAP = 6;
449
+ const COMET_DASH = 0.016;
450
+ const COMET_WIDTH = 1.6;
451
+ const cometStrand = (i, comets, strands) => Math.min(strands - 1, Math.round((i + 0.5) / comets * (strands - 1)));
452
+ return {
453
+ W,
454
+ H,
455
+ toPath,
456
+ ridgeStrand,
457
+ twistStrand,
458
+ measure,
459
+ pointAt,
460
+ cometStrand,
461
+ COMET_LAP,
462
+ COMET_DASH,
463
+ COMET_WIDTH
464
+ };
465
+ }
466
+ var neonGeometry = createNeonGeometry();
467
+ function renderNeon(createGeometry) {
468
+ const geometry = createGeometry(), scenes = /* @__PURE__ */ new Map();
469
+ let frame = null, fps = 30, last2 = -Infinity;
470
+ function draw(scene) {
471
+ const { ctx, width, height, padX, padY, sx, sy, options, time, gradient } = scene;
472
+ ctx.clearRect(-padX, -padY, width + padX * 2, height + padY * 2);
473
+ ctx.strokeStyle = gradient;
474
+ const tracks = /* @__PURE__ */ new Map();
475
+ const carried = new Set(
476
+ Array.from(
477
+ { length: options.comets },
478
+ (_, i) => geometry.cometStrand(i, options.comets, options.strands)
479
+ )
480
+ );
481
+ for (let i = 0; i < options.strands; i++) {
482
+ const t = i / Math.max(1, options.strands - 1), drift = time * 0.42 + options.phase;
483
+ const curve = options.shape === "ridge" ? geometry.ridgeStrand(t, drift) : geometry.twistStrand(t, drift, i < options.strands * 0.68);
484
+ ctx.beginPath();
485
+ ctx.moveTo(curve[0] * sx, curve[1] * sy);
486
+ for (let j = 2; j < curve.length; j += 6)
487
+ ctx.bezierCurveTo(
488
+ curve[j] * sx,
489
+ curve[j + 1] * sy,
490
+ curve[j + 2] * sx,
491
+ curve[j + 3] * sy,
492
+ curve[j + 4] * sx,
493
+ curve[j + 5] * sy
494
+ );
495
+ ctx.lineWidth = i === 5 ? 1 : 0.55;
496
+ ctx.globalAlpha = i === 5 ? 0.95 : 0.52;
497
+ ctx.stroke();
498
+ if (carried.has(i)) tracks.set(i, geometry.measure(curve));
499
+ }
500
+ for (let i = 0; i < options.comets; i++) {
501
+ const track = tracks.get(
502
+ geometry.cometStrand(i, options.comets, options.strands)
503
+ );
504
+ if (!track) continue;
505
+ const start = (time + i * geometry.COMET_LAP / options.comets + 1.8) / geometry.COMET_LAP % 1;
506
+ const tail = geometry.pointAt(track, start), head = geometry.pointAt(track, start + geometry.COMET_DASH);
507
+ const dx = (head.x - tail.x) * sx, dy = (head.y - tail.y) * sy;
508
+ const length = Math.round(Math.hypot(dx, dy) + geometry.COMET_WIDTH);
509
+ let sprite = scene.sprites.get(length);
510
+ if (!sprite) {
511
+ const padding = Math.ceil(
512
+ Math.max(0, ...scene.shadows.map((shadow) => shadow.blur)) * 2 + 2
513
+ );
514
+ const canvas = new OffscreenCanvas(
515
+ Math.ceil((length + padding * 2) * scene.dpr),
516
+ Math.ceil((geometry.COMET_WIDTH + padding * 2) * scene.dpr)
517
+ );
518
+ const paint = canvas.getContext("2d");
519
+ paint.scale(scene.dpr, scene.dpr);
520
+ paint.fillStyle = scene.color;
521
+ for (const shadow of [...scene.shadows].reverse()) {
522
+ paint.shadowColor = shadow.color;
523
+ paint.shadowBlur = shadow.blur * scene.dpr;
524
+ paint.beginPath();
525
+ paint.roundRect(
526
+ padding,
527
+ padding,
528
+ length,
529
+ geometry.COMET_WIDTH,
530
+ geometry.COMET_WIDTH / 2
531
+ );
532
+ paint.fill();
533
+ }
534
+ sprite = { canvas, padding };
535
+ scene.sprites.set(length, sprite);
536
+ }
537
+ const x = (tail.x + head.x) / 2, y = (tail.y + head.y) / 2;
538
+ ctx.save();
539
+ ctx.translate(x * sx, y * sy);
540
+ ctx.rotate(Math.atan2(dy, dx));
541
+ ctx.globalAlpha = Math.min(
542
+ 1,
543
+ Math.max(0, (x + 20) / ((geometry.W + 40) * 0.35))
544
+ );
545
+ ctx.drawImage(
546
+ sprite.canvas,
547
+ -length / 2 - sprite.padding,
548
+ -geometry.COMET_WIDTH / 2 - sprite.padding,
549
+ sprite.canvas.width / scene.dpr,
550
+ sprite.canvas.height / scene.dpr
551
+ );
552
+ ctx.restore();
553
+ }
554
+ ctx.globalAlpha = 1;
555
+ }
556
+ function schedule2() {
557
+ if (frame === null && [...scenes.values()].some((scene) => scene.visible))
558
+ frame = requestAnimationFrame(tick2);
559
+ }
560
+ function tick2(now) {
561
+ frame = null;
562
+ if (now - last2 >= 1e3 / fps - 0.5) {
563
+ for (const scene of scenes.values()) {
564
+ if (!scene.visible) continue;
565
+ if (scene.previous !== null)
566
+ scene.time += Math.min(
567
+ 0.1,
568
+ Math.max(0, (now - scene.previous) / 1e3)
569
+ );
570
+ scene.previous = now;
571
+ draw(scene);
572
+ }
573
+ last2 = now;
574
+ }
575
+ schedule2();
576
+ }
577
+ onmessage = ({ data }) => {
578
+ const previous = scenes.get(data.id);
579
+ if (data.type === "rate") fps = data.fps;
580
+ else if (data.type === "remove") scenes.delete(data.id);
581
+ else if (data.type === "visible") {
582
+ if (previous) {
583
+ previous.visible = data.visible;
584
+ previous.previous = null;
585
+ }
586
+ } else if (data.type === "update") {
587
+ const scene = {
588
+ ...data,
589
+ canvas: previous?.canvas ?? data.canvas,
590
+ time: previous?.time ?? data.time,
591
+ previous: null,
592
+ sprites: /* @__PURE__ */ new Map()
593
+ };
594
+ scene.canvas.width = Math.ceil((data.width + data.padX * 2) * data.dpr);
595
+ scene.canvas.height = Math.ceil((data.height + data.padY * 2) * data.dpr);
596
+ scene.ctx = scene.canvas.getContext("2d");
597
+ scene.ctx.setTransform(
598
+ data.dpr,
599
+ 0,
600
+ 0,
601
+ data.dpr,
602
+ data.padX * data.dpr,
603
+ data.padY * data.dpr
604
+ );
605
+ scene.sx = data.width / geometry.W;
606
+ scene.sy = data.height / geometry.H;
607
+ const [start, end] = data.options.shape === "ridge" ? [-10, 610] : [-12, 608];
608
+ scene.gradient = scene.ctx.createLinearGradient(
609
+ start * scene.sx,
610
+ 0,
611
+ end * scene.sx,
612
+ 0
613
+ );
614
+ for (const stop of data.stops)
615
+ scene.gradient.addColorStop(stop.at, stop.color);
616
+ scenes.set(data.id, scene);
617
+ draw(scene);
618
+ postMessage({ id: data.id });
619
+ }
620
+ schedule2();
621
+ };
622
+ }
623
+ var thread = null;
624
+ var url = null;
625
+ var serial2 = 0;
626
+ var unavailable2 = false;
627
+ var frameRate2 = 30;
628
+ var clients2 = /* @__PURE__ */ new Map();
629
+ var visibilityChanged2 = () => {
630
+ for (const client of clients2.values()) client.visibility();
631
+ };
632
+ var resized2 = () => {
633
+ for (const client of clients2.values()) client.update();
634
+ };
635
+ function setNeonFrameRate(fps) {
636
+ frameRate2 = fps;
637
+ thread?.postMessage({ type: "rate", fps });
638
+ }
639
+ function stopThread() {
640
+ thread?.terminate();
641
+ if (url) URL.revokeObjectURL(url);
642
+ thread = url = null;
643
+ document.removeEventListener("visibilitychange", visibilityChanged2);
644
+ window.removeEventListener("resize", resized2);
645
+ }
646
+ function createNeonRenderer(root, svg, initial) {
647
+ if (unavailable2 || typeof Worker === "undefined" || typeof OffscreenCanvas === "undefined" || typeof HTMLCanvasElement === "undefined" || !HTMLCanvasElement.prototype.transferControlToOffscreen || typeof IntersectionObserver === "undefined" || typeof MutationObserver === "undefined")
648
+ return null;
649
+ if (!thread) {
650
+ try {
651
+ url = URL.createObjectURL(
652
+ new Blob(
653
+ [`(${renderNeon.toString()})(${createNeonGeometry.toString()})`],
654
+ { type: "text/javascript" }
655
+ )
656
+ );
657
+ thread = new Worker(url);
658
+ } catch {
659
+ unavailable2 = true;
660
+ stopThread();
661
+ return null;
662
+ }
663
+ thread.onmessage = ({ data }) => clients2.get(data.id)?.ready();
664
+ thread.onerror = () => {
665
+ unavailable2 = true;
666
+ const pending = [...clients2.values()];
667
+ stopThread();
668
+ for (const client of pending) client.dispose();
669
+ };
670
+ thread.postMessage({ type: "rate", fps: frameRate2 });
671
+ document.addEventListener("visibilitychange", visibilityChanged2);
672
+ window.addEventListener("resize", resized2);
673
+ }
674
+ const worker2 = thread, id = ++serial2, canvas = document.createElement("canvas");
675
+ canvas.style.cssText = "position:absolute;pointer-events:none;visibility:hidden";
676
+ root.insertBefore(canvas, svg);
677
+ const originalVisibility = svg.style.visibility;
678
+ let options = initial, inView = false, visible = false, disposed = false, transferred = false, queued = false, signature = "";
679
+ let comets = null, cometVisibility = "";
680
+ const renderer = {
681
+ ready: false,
682
+ update(next = options) {
683
+ options = next;
684
+ queue();
685
+ },
686
+ dispose
687
+ };
688
+ const hideOriginal = () => {
689
+ if (!renderer.ready) return;
690
+ svg.style.visibility = "hidden";
691
+ const node = root.querySelector(".ad-neon-waves-comets");
692
+ if (node !== comets) {
693
+ comets = node;
694
+ cometVisibility = node?.style.visibility ?? "";
695
+ }
696
+ if (comets) comets.style.visibility = "hidden";
697
+ };
698
+ const visibility = () => {
699
+ const next = inView && !document.hidden && svg.closest("[data-ad-motion]")?.dataset.adMotion !== "off" && !root.closest("[data-ad-paused], [data-ad-offscreen]");
700
+ if (next !== visible) {
701
+ visible = next;
702
+ worker2.postMessage({ type: "visible", id, visible });
703
+ }
704
+ };
705
+ const intersection = new IntersectionObserver((entries) => {
706
+ inView = entries[0].isIntersecting;
707
+ visibility();
708
+ });
709
+ intersection.observe(root);
710
+ const tokens = new MutationObserver((records) => {
711
+ visibility();
712
+ if (records.some(
713
+ (record) => ["style", "class", "data-ad-theme", "data-ad-color-scheme"].includes(
714
+ record.attributeName
715
+ )
716
+ ))
717
+ queue();
718
+ });
719
+ for (let node = root; node; node = node.parentElement)
720
+ tokens.observe(node, {
721
+ attributes: true,
722
+ attributeFilter: [
723
+ "style",
724
+ "class",
725
+ "data-ad-theme",
726
+ "data-ad-color-scheme",
727
+ "data-ad-paused",
728
+ "data-ad-offscreen",
729
+ "data-ad-motion"
730
+ ]
731
+ });
732
+ tokens.observe(svg, {
733
+ attributes: true,
734
+ attributeFilter: ["data-ad-motion", "data-ad-offscreen"]
735
+ });
736
+ clients2.set(id, {
737
+ visibility,
738
+ update: queue,
739
+ dispose,
740
+ ready() {
741
+ renderer.ready = true;
742
+ hideOriginal();
743
+ canvas.style.visibility = "";
744
+ }
745
+ });
746
+ function dispose() {
747
+ if (disposed) return;
748
+ disposed = true;
749
+ renderer.ready = false;
750
+ intersection.disconnect();
751
+ tokens.disconnect();
752
+ svg.style.visibility = originalVisibility;
753
+ if (comets) comets.style.visibility = cometVisibility;
754
+ canvas.remove();
755
+ clients2.delete(id);
756
+ if (thread === worker2) worker2.postMessage({ type: "remove", id });
757
+ if (!clients2.size) stopThread();
758
+ }
759
+ function queue() {
760
+ if (queued || disposed) return;
761
+ queued = true;
762
+ queueMicrotask(() => {
763
+ queued = false;
764
+ if (!disposed) update();
765
+ });
766
+ }
767
+ function update() {
768
+ try {
769
+ hideOriginal();
770
+ visibility();
771
+ const width = root.clientWidth, height = root.clientHeight, dpr = devicePixelRatio || 1;
772
+ if (!width || !height) return;
773
+ const padX = width / 30 + 2, padY = height / 2 + 2;
774
+ const stops = [...svg.querySelectorAll("stop")].map((stop) => {
775
+ const style2 = getComputedStyle(stop);
776
+ return {
777
+ at: Number(stop.getAttribute("offset") || 0),
778
+ color: `color-mix(in srgb, ${style2.stopColor} ${Number(style2.stopOpacity) * 100}%, transparent)`
779
+ };
780
+ });
781
+ const comet = root.querySelector(".ad-neon-waves-comet"), style = comet && getComputedStyle(comet);
782
+ const shadows = !style ? [] : style.boxShadow.split(/,\s*(?![^()]*\))/).map((shadow) => {
783
+ const values = shadow.match(
784
+ /^(.*?)\s+[-\d.]+px\s+[-\d.]+px\s+([\d.]+)px(?:\s+[-\d.]+px)?$/
785
+ );
786
+ if (!values) throw new Error("Invalid comet shadow");
787
+ return { color: values[1], blur: Number(values[2]) };
788
+ });
789
+ const config = {
790
+ width,
791
+ height,
792
+ dpr,
793
+ padX,
794
+ padY,
795
+ stops,
796
+ shadows,
797
+ color: style?.backgroundColor,
798
+ options: { ...options, comets: comet ? options.comets : 0 }
799
+ };
800
+ const key = JSON.stringify(config);
801
+ if (key === signature) return;
802
+ signature = key;
803
+ canvas.style.left = `${-padX}px`;
804
+ canvas.style.top = `${-padY}px`;
805
+ canvas.style.width = `${width + 2 * padX}px`;
806
+ canvas.style.height = `${height + 2 * padY}px`;
807
+ const surface = transferred ? void 0 : canvas.transferControlToOffscreen();
808
+ transferred = true;
809
+ worker2.postMessage(
810
+ {
811
+ type: "update",
812
+ id,
813
+ canvas: surface,
814
+ ...config,
815
+ visible,
816
+ time: options.time
817
+ },
818
+ surface ? [surface] : []
819
+ );
820
+ } catch {
821
+ dispose();
822
+ }
823
+ }
824
+ queue();
825
+ return renderer;
826
+ }
827
+
293
828
  // src/core/motion-engine.js
294
829
  var uid = 0;
295
830
  var U = {
@@ -309,9 +844,11 @@ var last = 0;
309
844
  var weakDevice = typeof navigator !== "undefined" && ((navigator.hardwareConcurrency || 8) <= 4 || (navigator.deviceMemory || 8) <= 4);
310
845
  var FRAME = 1e3 / (weakDevice ? 20 : 30);
311
846
  setBorderFrameRate(1e3 / FRAME);
847
+ setNeonFrameRate(1e3 / FRAME);
312
848
  U.setMotionFrameRate = (fps) => {
313
849
  FRAME = 1e3 / Math.max(1, Math.min(120, fps));
314
850
  setBorderFrameRate(1e3 / FRAME);
851
+ setNeonFrameRate(1e3 / FRAME);
315
852
  const now = performance.now();
316
853
  for (const animation of looping) {
317
854
  animation.__adStart = now - (animation.currentTime || 0);
@@ -1156,6 +1693,8 @@ var ThemeProvider = ({
1156
1693
  };
1157
1694
 
1158
1695
  export {
1696
+ neonGeometry,
1697
+ createNeonRenderer,
1159
1698
  refreshMotion,
1160
1699
  setMotionFrameRate,
1161
1700
  subscribeTick,
@@ -0,0 +1,60 @@
1
+ export function setNeonFrameRate(fps: any): void;
2
+ export function createNeonRenderer(root: any, svg: any, initial: any): {
3
+ ready: boolean;
4
+ update(next?: any): void;
5
+ dispose: () => void;
6
+ } | null;
7
+ export function createNeonGeometry(): {
8
+ W: number;
9
+ H: number;
10
+ toPath: (curve: any) => string;
11
+ ridgeStrand: (t: any, drift: any) => any[];
12
+ twistStrand: (t: any, drift: any, main: any) => number[];
13
+ measure: (curve: any) => {
14
+ xs: any[];
15
+ ys: any[];
16
+ lengths: number[];
17
+ total: number;
18
+ };
19
+ pointAt: (track: any, fraction: any) => {
20
+ x: any;
21
+ y: any;
22
+ };
23
+ cometStrand: (i: any, comets: any, strands: any) => number;
24
+ COMET_LAP: number;
25
+ COMET_DASH: number;
26
+ COMET_WIDTH: number;
27
+ };
28
+ export namespace neonGeometry {
29
+ export { W };
30
+ export { H };
31
+ export { toPath };
32
+ export { ridgeStrand };
33
+ export { twistStrand };
34
+ export { measure };
35
+ export { pointAt };
36
+ export { cometStrand };
37
+ export { COMET_LAP };
38
+ export { COMET_DASH };
39
+ export { COMET_WIDTH };
40
+ }
41
+ declare const W: 600;
42
+ declare const H: 120;
43
+ declare function toPath(curve: any): string;
44
+ declare function ridgeStrand(t: any, drift: any): any[];
45
+ declare function twistStrand(t: any, drift: any, main: any): number[];
46
+ declare function measure(curve: any): {
47
+ xs: any[];
48
+ ys: any[];
49
+ lengths: number[];
50
+ total: number;
51
+ };
52
+ declare function pointAt(track: any, fraction: any): {
53
+ x: any;
54
+ y: any;
55
+ };
56
+ declare function cometStrand(i: any, comets: any, strands: any): number;
57
+ declare const COMET_LAP: 6;
58
+ declare const COMET_DASH: 0.016;
59
+ declare const COMET_WIDTH: 1.6;
60
+ export {};
package/dist/core.js CHANGED
@@ -11,7 +11,7 @@ import {
11
11
  useSmoothWheel,
12
12
  useTabShape,
13
13
  useTick
14
- } from "./chunks/chunk-6VBE5UOI.js";
14
+ } from "./chunks/chunk-YVRQTI7B.js";
15
15
  import {
16
16
  LocaleProvider,
17
17
  addMessages,
package/dist/forms.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  defaultFieldRegistry,
5
5
  useForm,
6
6
  useFormContext
7
- } from "./chunks/chunk-X7KO7G4S.js";
8
- import "./chunks/chunk-6VBE5UOI.js";
7
+ } from "./chunks/chunk-FRALT7ER.js";
8
+ import "./chunks/chunk-YVRQTI7B.js";
9
9
  import "./chunks/chunk-BJSFN52W.js";
10
10
  import "./chunks/chunk-FCOU3ODR.js";
11
11
  export {
package/dist/index.js CHANGED
@@ -61,10 +61,12 @@ import {
61
61
  useSvgId,
62
62
  variantMaterial,
63
63
  vectorElement
64
- } from "./chunks/chunk-X7KO7G4S.js";
64
+ } from "./chunks/chunk-FRALT7ER.js";
65
65
  import {
66
66
  ThemeProvider,
67
+ createNeonRenderer,
67
68
  getMotionStats,
69
+ neonGeometry,
68
70
  refreshMotion,
69
71
  setMotionFrameRate,
70
72
  subscribeTick,
@@ -76,7 +78,7 @@ import {
76
78
  useTabShape,
77
79
  useThemePalette,
78
80
  useTick
79
- } from "./chunks/chunk-6VBE5UOI.js";
81
+ } from "./chunks/chunk-YVRQTI7B.js";
80
82
  import {
81
83
  LocaleProvider,
82
84
  addMessages,
@@ -3885,99 +3887,19 @@ function Planet({ children, ...p }) {
3885
3887
  // src/components/artwork/NeonWaves/NeonWaves.tsx
3886
3888
  import { useEffect as useEffect7, useMemo as useMemo3, useRef as useRef22 } from "react";
3887
3889
  import { jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
3888
- var W3 = 600;
3889
- var H3 = 120;
3890
- var SKYLINE = [[0, 0.93], [0.16, 0.86], [0.3, 0.82], [0.42, 0.72], [0.55, 0.64], [0.64, 0.7], [0.74, 0.52], [0.84, 0.1], [0.9, 0.56], [0.95, 0.46], [1, 0.08]];
3891
- var skyline = (x) => {
3892
- const i = Math.max(0, SKYLINE.findIndex(([at]) => at >= x) - 1);
3893
- const [x0, y0] = SKYLINE[i];
3894
- const [x1, y1] = SKYLINE[Math.min(SKYLINE.length - 1, i + 1)];
3895
- const k = x1 === x0 ? 0 : (x - x0) / (x1 - x0);
3896
- return y0 + (y1 - y0) * (1 - Math.cos(k * Math.PI)) / 2;
3897
- };
3898
- var SAMPLES = 36;
3899
- var toPath = (curve) => {
3900
- let d = `M${curve[0].toFixed(2)} ${curve[1].toFixed(2)}`;
3901
- for (let i = 2; i < curve.length; i += 6)
3902
- d += `C${curve.slice(i, i + 6).map((n) => n.toFixed(2)).join(" ")}`;
3903
- return d;
3904
- };
3905
- var smoothTo = (curve, c2x, c2y, x, y) => {
3906
- const n = curve.length;
3907
- curve.push(2 * curve[n - 2] - curve[n - 4], 2 * curve[n - 1] - curve[n - 3], c2x, c2y, x, y);
3908
- };
3909
- var smooth = (xs, ys) => {
3910
- const curve = [xs[0], ys[0]];
3911
- for (let i = 0; i < xs.length - 1; i += 1) {
3912
- const x0 = xs[i - 1] ?? xs[i], y0 = ys[i - 1] ?? ys[i];
3913
- const x1 = xs[i], y1 = ys[i], x2 = xs[i + 1], y2 = ys[i + 1];
3914
- const x3 = xs[i + 2] ?? x2, y3 = ys[i + 2] ?? y2;
3915
- curve.push(x1 + (x2 - x0) / 6, y1 + (y2 - y0) / 6, x2 - (x3 - x1) / 6, y2 - (y3 - y1) / 6, x2, y2);
3916
- }
3917
- return curve;
3918
- };
3919
- var ridgeStrand = (t, drift) => {
3920
- const xs = [];
3921
- const ys = [];
3922
- for (let i = 0; i <= SAMPLES; i += 1) {
3923
- const x = i / SAMPLES;
3924
- const base = skyline(x);
3925
- const spread = H3 * (0.06 + 0.26 * base);
3926
- const ripple2 = Math.sin(x * 8 + drift + t * 7) * H3 * (0.03 + 0.05 * base) + Math.sin(x * 21 - drift * 1.3 + t * 11) * H3 * 0.014;
3927
- xs.push(x * (W3 + 20) - 10);
3928
- ys.push(base * H3 + (t - 0.5) * spread + ripple2);
3929
- }
3930
- return smooth(xs, ys);
3931
- };
3932
- var twistStrand = (t, drift, main) => {
3933
- const a = Math.sin(drift + t * 1.4) * H3 * 0.095;
3934
- const b = Math.cos(drift * 0.8 + t * 1.8) * H3 * 0.08;
3935
- if (!main) {
3936
- const curve2 = [-12, H3 * (0.9 + t * 0.12) + b, W3 * 0.21, H3 * 0.98 + a, W3 * 0.33, H3 * 0.24 + t * H3 * 0.2 + a, W3 * 0.52, H3 * 0.75 + t * H3 * 0.25 + b];
3937
- smoothTo(curve2, W3 * 0.82, H3 * 0.38 + t * H3 * 0.27 + a, W3 + 8, H3 * (0.48 + t * 0.5) + b);
3938
- return curve2;
3939
- }
3940
- const curve = [-12, H3 * (0.38 + t * 0.58) + a, W3 * 0.2, H3 * 1.28 - t * H3 * 0.27 + a, W3 * 0.32, H3 * 0.34 + t * H3 * 0.21 + b, W3 * 0.46, H3 * 0.62 + t * H3 * 0.12];
3941
- smoothTo(curve, W3 * 0.67, H3 * 1.14 - t * H3 * 0.09 + a, W3 * 0.8, H3 * 0.69 - t * H3 * 0.22 + b);
3942
- smoothTo(curve, W3 * 0.94, H3 * 0.43 - t * H3 * 0.44 + a, W3 + 8, H3 * 0.21 + t * H3 * 0.45);
3943
- return curve;
3944
- };
3945
- var STEPS = 16;
3946
- var measure = (curve) => {
3947
- const xs = [curve[0]], ys = [curve[1]], lengths = [0];
3948
- for (let i = 2; i < curve.length; i += 6) {
3949
- const x0 = curve[i - 2], y0 = curve[i - 1];
3950
- const [x1, y1, x2, y2, x3, y3] = curve.slice(i, i + 6);
3951
- for (let k = 1; k <= STEPS; k += 1) {
3952
- const u = k / STEPS, v = 1 - u;
3953
- const x = v * v * v * x0 + 3 * v * v * u * x1 + 3 * v * u * u * x2 + u * u * u * x3;
3954
- const y = v * v * v * y0 + 3 * v * v * u * y1 + 3 * v * u * u * y2 + u * u * u * y3;
3955
- lengths.push(lengths[lengths.length - 1] + Math.hypot(x - xs[xs.length - 1], y - ys[ys.length - 1]));
3956
- xs.push(x);
3957
- ys.push(y);
3958
- }
3959
- }
3960
- return { xs, ys, lengths, total: lengths[lengths.length - 1] };
3961
- };
3962
- var pointAt = (track, fraction) => {
3963
- const distance = Math.min(1, Math.max(0, fraction)) * track.total;
3964
- let low = 0, high = track.lengths.length - 1;
3965
- while (high - low > 1) {
3966
- const middle = low + high >> 1;
3967
- if (track.lengths[middle] < distance) low = middle;
3968
- else high = middle;
3969
- }
3970
- const span = track.lengths[high] - track.lengths[low] || 1;
3971
- const k = (distance - track.lengths[low]) / span;
3972
- return {
3973
- x: track.xs[low] + (track.xs[high] - track.xs[low]) * k,
3974
- y: track.ys[low] + (track.ys[high] - track.ys[low]) * k
3975
- };
3976
- };
3977
- var COMET_LAP = 6;
3978
- var COMET_DASH = 0.016;
3979
- var COMET_WIDTH = 1.6;
3980
- var cometStrand = (i, comets, strands) => Math.min(strands - 1, Math.round((i + 0.5) / comets * (strands - 1)));
3890
+ var {
3891
+ W: W3,
3892
+ H: H3,
3893
+ toPath,
3894
+ ridgeStrand,
3895
+ twistStrand,
3896
+ measure,
3897
+ pointAt,
3898
+ cometStrand,
3899
+ COMET_LAP,
3900
+ COMET_DASH,
3901
+ COMET_WIDTH
3902
+ } = neonGeometry;
3981
3903
  function NeonWaves({
3982
3904
  strands = 22,
3983
3905
  stars = true,
@@ -3995,6 +3917,7 @@ function NeonWaves({
3995
3917
  const cometElements = useRef22(null);
3996
3918
  const size = useRef22({ width: 0, height: 0 });
3997
3919
  const lastTime = useRef22(0);
3920
+ const renderer = useRef22(null);
3998
3921
  const motion = useMotion();
3999
3922
  const id = useSvgId();
4000
3923
  const dots = useMemo3(() => {
@@ -4014,14 +3937,27 @@ function NeonWaves({
4014
3937
  const observer = createResizeObserver(([entry]) => {
4015
3938
  if (!entry) return;
4016
3939
  size.current = { width: entry.contentRect.width, height: entry.contentRect.height };
3940
+ renderer.current?.update();
4017
3941
  painter.current(lastTime.current);
4018
3942
  });
4019
3943
  observer.observe(root);
4020
3944
  return () => observer.disconnect();
4021
3945
  }, []);
3946
+ useEffect7(() => {
3947
+ if (!rootRef.current || !ref.current) return;
3948
+ renderer.current = createNeonRenderer(rootRef.current, ref.current, { strands, phase, shape, comets, time: lastTime.current });
3949
+ return () => {
3950
+ renderer.current?.dispose();
3951
+ renderer.current = null;
3952
+ };
3953
+ }, []);
3954
+ useEffect7(() => {
3955
+ renderer.current?.update({ strands, phase, shape, comets, time: lastTime.current });
3956
+ }, [strands, phase, shape, comets, motion]);
4022
3957
  usePauseOffscreen(ref);
4023
3958
  const paint = (time) => {
4024
3959
  lastTime.current = time;
3960
+ if (renderer.current?.ready) return;
4025
3961
  if (lastDraw.current < 0 || time - lastDraw.current >= 1 / 16) {
4026
3962
  lastDraw.current = time;
4027
3963
  const node = ref.current;
@@ -6056,11 +5992,11 @@ function PlaybackTrack({ audio, playing, position: controlledPosition, disabled,
6056
5992
  // src/components/media/LevelMeter/LevelMeter.tsx
6057
5993
  import { useEffect as useEffect13, useRef as useRef28 } from "react";
6058
5994
  import { jsx as jsx48, jsxs as jsxs39 } from "react/jsx-runtime";
6059
- var SAMPLES2 = 64;
5995
+ var SAMPLES = 64;
6060
5996
  var WIDTH = 256;
6061
5997
  var HEIGHT = 24;
6062
5998
  var MID2 = HEIGHT / 2;
6063
- var STEP = WIDTH / (SAMPLES2 - 1);
5999
+ var STEP = WIDTH / (SAMPLES - 1);
6064
6000
  var SAMPLE_MS = 28;
6065
6001
  var wavePath2 = (samples) => {
6066
6002
  const point = (i, level, side) => `${(i * STEP).toFixed(2)} ${(MID2 + side * (1 + level ** 0.68 * (MID2 - 3))).toFixed(2)}`;
@@ -6095,7 +6031,7 @@ function LevelMeter({
6095
6031
  useEffect13(() => {
6096
6032
  const shape = path.current;
6097
6033
  if (!shape) return;
6098
- const samples = Array.from({ length: SAMPLES2 + 1 }, () => 0);
6034
+ const samples = Array.from({ length: SAMPLES + 1 }, () => 0);
6099
6035
  shape.setAttribute("d", wavePath2(samples));
6100
6036
  wake.current = () => void 0;
6101
6037
  if (!active) return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neo-ui-kit/react",
3
- "version": "1.3.6",
3
+ "version": "1.3.7",
4
4
  "description": "NEO UI — React component library",
5
5
  "type": "module",
6
6
  "license": "MIT",