@number10/phaserjsx 4.1.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. package/README.md +14 -1
  2. package/dist/clip/index.cjs +7 -695
  3. package/dist/clip/index.js +1 -687
  4. package/dist/clip/stencil-clip-depth.d.ts +10 -0
  5. package/dist/clip/stencil-clip-depth.d.ts.map +1 -0
  6. package/dist/clip/stencil-clip-fbo-bridge.d.ts +7 -0
  7. package/dist/clip/stencil-clip-fbo-bridge.d.ts.map +1 -0
  8. package/dist/clip/stencil-clip-renderer.d.ts +7 -0
  9. package/dist/clip/stencil-clip-renderer.d.ts.map +1 -0
  10. package/dist/clip/stencil-clip-state.d.ts +28 -0
  11. package/dist/clip/stencil-clip-state.d.ts.map +1 -0
  12. package/dist/clip/stencil-clip-types.d.ts +67 -0
  13. package/dist/clip/stencil-clip-types.d.ts.map +1 -0
  14. package/dist/clip/stencil-clip.d.ts +3 -84
  15. package/dist/clip/stencil-clip.d.ts.map +1 -1
  16. package/dist/clip-CHmjztBQ.cjs +705 -0
  17. package/dist/clip-CHmjztBQ.cjs.map +1 -0
  18. package/dist/clip-CPufWCSD.js +668 -0
  19. package/dist/clip-CPufWCSD.js.map +1 -0
  20. package/dist/components/appliers/applyParticles.d.ts.map +1 -1
  21. package/dist/components/custom/Badge.d.ts +73 -0
  22. package/dist/components/custom/Badge.d.ts.map +1 -0
  23. package/dist/components/custom/Checkbox.d.ts +41 -0
  24. package/dist/components/custom/Checkbox.d.ts.map +1 -0
  25. package/dist/components/custom/DebugPanel.d.ts +30 -0
  26. package/dist/components/custom/DebugPanel.d.ts.map +1 -0
  27. package/dist/components/custom/Particles.d.ts +14 -3
  28. package/dist/components/custom/Particles.d.ts.map +1 -1
  29. package/dist/components/custom/Popover.d.ts +89 -0
  30. package/dist/components/custom/Popover.d.ts.map +1 -0
  31. package/dist/components/custom/ProgressBar.d.ts +52 -0
  32. package/dist/components/custom/ProgressBar.d.ts.map +1 -0
  33. package/dist/components/custom/Toggle.d.ts.map +1 -1
  34. package/dist/components/custom/index.cjs +15 -1
  35. package/dist/components/custom/index.d.ts +5 -0
  36. package/dist/components/custom/index.d.ts.map +1 -1
  37. package/dist/components/custom/index.js +2 -2
  38. package/dist/components/index.d.ts +5 -1
  39. package/dist/components/index.d.ts.map +1 -1
  40. package/dist/components/primitives/graphics.d.ts +2 -2
  41. package/dist/components/primitives/particles.d.ts +14 -4
  42. package/dist/components/primitives/particles.d.ts.map +1 -1
  43. package/dist/components/primitives/tilesprite.d.ts +15 -19
  44. package/dist/components/primitives/tilesprite.d.ts.map +1 -1
  45. package/dist/{custom-Dp3yAJdU.cjs → custom-37gL0VZG.cjs} +1578 -264
  46. package/dist/custom-37gL0VZG.cjs.map +1 -0
  47. package/dist/{custom-C_w8D39m.js → custom-DMZASXll.js} +1455 -231
  48. package/dist/custom-DMZASXll.js.map +1 -0
  49. package/dist/gestures/gesture-manager.d.ts +1 -1
  50. package/dist/index.cjs +49 -111
  51. package/dist/index.cjs.map +1 -1
  52. package/dist/index.js +29 -105
  53. package/dist/index.js.map +1 -1
  54. package/dist/particles/emit-zone.d.ts +34 -12
  55. package/dist/particles/emit-zone.d.ts.map +1 -1
  56. package/dist/particles/index.d.ts +1 -1
  57. package/dist/particles/index.d.ts.map +1 -1
  58. package/dist/particles/use-particles.d.ts +6 -2
  59. package/dist/particles/use-particles.d.ts.map +1 -1
  60. package/dist/theme-custom.d.ts +68 -0
  61. package/dist/theme-custom.d.ts.map +1 -1
  62. package/dist/theme-defaults.d.ts.map +1 -1
  63. package/package.json +3 -2
  64. package/dist/clip/index.cjs.map +0 -1
  65. package/dist/clip/index.js.map +0 -1
  66. package/dist/custom-C_w8D39m.js.map +0 -1
  67. package/dist/custom-Dp3yAJdU.cjs.map +0 -1
@@ -570,9 +570,6 @@ var nineSlicePatcher = (node, prev, next) => {
570
570
  };
571
571
  //#endregion
572
572
  //#region src/particles/emit-zone.ts
573
- /**
574
- * Emit zone helpers for particle emitters
575
- */
576
573
  function resolveNumericSize(value) {
577
574
  return typeof value === "number" ? value : void 0;
578
575
  }
@@ -584,18 +581,164 @@ function resolveZoneSize(zone, fallback) {
584
581
  if (height !== void 0) size.height = height;
585
582
  return size;
586
583
  }
584
+ function withPoint(point, x, y) {
585
+ if (point) {
586
+ point.x = x;
587
+ point.y = y;
588
+ return point;
589
+ }
590
+ return {
591
+ x,
592
+ y
593
+ };
594
+ }
595
+ function createRectSource(x, y, width, height) {
596
+ return {
597
+ x,
598
+ y,
599
+ width,
600
+ height,
601
+ contains: (px, py) => px >= x && px <= x + width && py >= y && py <= y + height,
602
+ getRandomPoint: (point) => withPoint(point, x + Math.random() * width, y + Math.random() * height),
603
+ getPoints: (quantity = 1) => {
604
+ const count = Math.max(1, quantity);
605
+ return Array.from({ length: count }, (_, index) => {
606
+ const distance = (count === 1 ? 0 : index / (count - 1)) * (2 * (width + height));
607
+ if (distance <= width) return {
608
+ x: x + distance,
609
+ y
610
+ };
611
+ if (distance <= width + height) return {
612
+ x: x + width,
613
+ y: y + distance - width
614
+ };
615
+ if (distance <= width * 2 + height) return {
616
+ x: x + width - (distance - width - height),
617
+ y: y + height
618
+ };
619
+ return {
620
+ x,
621
+ y: y + height - (distance - width * 2 - height)
622
+ };
623
+ });
624
+ }
625
+ };
626
+ }
627
+ function createCircleSource(x, y, radius) {
628
+ return {
629
+ x,
630
+ y,
631
+ radius,
632
+ contains: (px, py) => {
633
+ const dx = px - x;
634
+ const dy = py - y;
635
+ return dx * dx + dy * dy <= radius * radius;
636
+ },
637
+ getRandomPoint: (point) => {
638
+ const angle = Math.random() * Math.PI * 2;
639
+ const distance = Math.sqrt(Math.random()) * radius;
640
+ return withPoint(point, x + Math.cos(angle) * distance, y + Math.sin(angle) * distance);
641
+ },
642
+ getPoints: (quantity = 1) => {
643
+ const count = Math.max(1, quantity);
644
+ return Array.from({ length: count }, (_, index) => {
645
+ const angle = index / count * Math.PI * 2;
646
+ return {
647
+ x: x + Math.cos(angle) * radius,
648
+ y: y + Math.sin(angle) * radius
649
+ };
650
+ });
651
+ }
652
+ };
653
+ }
654
+ function createEllipseSource(x, y, width, height) {
655
+ const radiusX = width / 2;
656
+ const radiusY = height / 2;
657
+ return {
658
+ x,
659
+ y,
660
+ width,
661
+ height,
662
+ contains: (px, py) => {
663
+ const dx = (px - x) / radiusX;
664
+ const dy = (py - y) / radiusY;
665
+ return dx * dx + dy * dy <= 1;
666
+ },
667
+ getRandomPoint: (point) => {
668
+ const angle = Math.random() * Math.PI * 2;
669
+ const distance = Math.sqrt(Math.random());
670
+ return withPoint(point, x + Math.cos(angle) * radiusX * distance, y + Math.sin(angle) * radiusY * distance);
671
+ },
672
+ getPoints: (quantity = 1) => {
673
+ const count = Math.max(1, quantity);
674
+ return Array.from({ length: count }, (_, index) => {
675
+ const angle = index / count * Math.PI * 2;
676
+ return {
677
+ x: x + Math.cos(angle) * radiusX,
678
+ y: y + Math.sin(angle) * radiusY
679
+ };
680
+ });
681
+ }
682
+ };
683
+ }
684
+ function createLineSource(x, y, endX, endY) {
685
+ return {
686
+ x,
687
+ y,
688
+ contains: (px, py) => {
689
+ const lengthSquared = (endX - x) ** 2 + (endY - y) ** 2;
690
+ if (lengthSquared === 0) return px === x && py === y;
691
+ const progress = Math.max(0, Math.min(1, ((px - x) * (endX - x) + (py - y) * (endY - y)) / lengthSquared));
692
+ const closestX = x + progress * (endX - x);
693
+ const closestY = y + progress * (endY - y);
694
+ return Math.hypot(px - closestX, py - closestY) <= .5;
695
+ },
696
+ getRandomPoint: (point) => {
697
+ const progress = Math.random();
698
+ return withPoint(point, x + (endX - x) * progress, y + (endY - y) * progress);
699
+ },
700
+ getPoints: (quantity = 1) => {
701
+ const count = Math.max(1, quantity);
702
+ return Array.from({ length: count }, (_, index) => {
703
+ const progress = count === 1 ? 0 : index / (count - 1);
704
+ return {
705
+ x: x + (endX - x) * progress,
706
+ y: y + (endY - y) * progress
707
+ };
708
+ });
709
+ }
710
+ };
711
+ }
587
712
  function buildZoneSource(zone, fallbackSize) {
588
713
  const baseX = zone.x ?? 0;
589
714
  const baseY = zone.y ?? 0;
590
715
  const { width, height } = resolveZoneSize(zone, fallbackSize);
591
716
  switch (zone.shape) {
592
- case "rect": return new Phaser.Geom.Rectangle(baseX, baseY, width ?? 1, height ?? 1);
593
- case "circle": return new Phaser.Geom.Circle(baseX, baseY, zone.radius ?? 1);
594
- case "ellipse": return new Phaser.Geom.Ellipse(baseX, baseY, width ?? 1, height ?? 1);
595
- case "line": return new Phaser.Geom.Line(baseX, baseY, zone.endX ?? baseX + (width ?? 1), zone.endY ?? baseY + (height ?? 1));
717
+ case "rect": return createRectSource(baseX, baseY, width ?? 1, height ?? 1);
718
+ case "circle": return createCircleSource(baseX, baseY, zone.radius ?? 1);
719
+ case "ellipse": return createEllipseSource(baseX, baseY, width ?? 1, height ?? 1);
720
+ case "line": return createLineSource(baseX, baseY, zone.endX ?? baseX + (width ?? 1), zone.endY ?? baseY + (height ?? 1));
596
721
  default: return;
597
722
  }
598
723
  }
724
+ function getTransformOwner(value) {
725
+ if (!value || typeof value !== "object") return void 0;
726
+ if (typeof value.getWorldTransformMatrix !== "function") return;
727
+ return value;
728
+ }
729
+ function createLocalDeathZoneSource(source, owner) {
730
+ const transformOwner = getTransformOwner(owner);
731
+ if (!transformOwner) return source;
732
+ return {
733
+ ...source,
734
+ contains: (worldX, worldY) => {
735
+ const matrix = transformOwner.getWorldTransformMatrix?.();
736
+ if (!matrix) return source.contains(worldX, worldY);
737
+ const localPoint = matrix.applyInverse(worldX, worldY);
738
+ return source.contains(localPoint.x, localPoint.y);
739
+ }
740
+ };
741
+ }
599
742
  /**
600
743
  * Build a Phaser emitZone config from a lightweight zone definition
601
744
  */
@@ -620,21 +763,21 @@ function buildEmitZoneFromLayout(zone, width, height) {
620
763
  return buildEmitZone(zone, fallback);
621
764
  }
622
765
  /**
623
- * Build a Phaser deathZone config from a lightweight exclusion definition
766
+ * Build a Phaser deathZone config from a lightweight death zone definition
624
767
  */
625
- function buildDeathZone(zone, fallbackSize = {}) {
768
+ function buildDeathZone(zone, fallbackSize = {}, owner) {
626
769
  const type = zone.mode ?? "onEnter";
627
770
  const source = buildZoneSource(zone, fallbackSize);
628
771
  if (!source) return void 0;
629
772
  return {
630
773
  type,
631
- source
774
+ source: createLocalDeathZoneSource(source, owner)
632
775
  };
633
776
  }
634
777
  /**
635
778
  * Create death zones using layout size as a fallback
636
779
  */
637
- function buildDeathZonesFromLayout(zones, width, height) {
780
+ function buildDeathZonesFromLayout(zones, width, height, owner) {
638
781
  if (!zones) return void 0;
639
782
  const list = Array.isArray(zones) ? zones : [zones];
640
783
  const fallback = {};
@@ -642,7 +785,7 @@ function buildDeathZonesFromLayout(zones, width, height) {
642
785
  const resolvedHeight = resolveNumericSize(height);
643
786
  if (resolvedWidth !== void 0) fallback.width = resolvedWidth;
644
787
  if (resolvedHeight !== void 0) fallback.height = resolvedHeight;
645
- const deathZones = list.map((zone) => buildDeathZone(zone, fallback)).filter((zone) => Boolean(zone));
788
+ const deathZones = list.map((zone) => buildDeathZone(zone, fallback, owner)).filter((zone) => Boolean(zone));
646
789
  return deathZones.length > 0 ? deathZones : void 0;
647
790
  }
648
791
  //#endregion
@@ -833,7 +976,7 @@ function mergeDeathZones(base, extra) {
833
976
  function applyParticlesProps(manager, prev, next) {
834
977
  if (!manager) return;
835
978
  if ((prev.texture !== next.texture || prev.frame !== next.frame) && next.texture && "setTexture" in manager && manager.setTexture) manager.setTexture(next.texture, next.frame);
836
- if (prev.preset !== next.preset || prev.config !== next.config || prev.zone !== next.zone || prev.excludeZones !== next.excludeZones || prev.width !== next.width || prev.height !== next.height) {
979
+ if (prev.preset !== next.preset || prev.config !== next.config || prev.emitZone !== next.emitZone || prev.zone !== next.zone || prev.deathZones !== next.deathZones || prev.excludeZones !== next.excludeZones || prev.width !== next.width || prev.height !== next.height) {
837
980
  const resolvedConfig = resolveParticlePreset(next.preset, next.config);
838
981
  let emitter;
839
982
  if (isParticleEmitter(manager)) emitter = manager;
@@ -845,11 +988,13 @@ function applyParticlesProps(manager, prev, next) {
845
988
  }
846
989
  if (!emitter) return;
847
990
  applyEmitterConfig(emitter, resolvedConfig);
848
- if (next.zone) {
849
- const emitZone = buildEmitZoneFromLayout(next.zone, next.width, next.height);
991
+ const emitZoneProps = next.emitZone ?? next.zone;
992
+ const deathZoneProps = next.deathZones ?? next.excludeZones;
993
+ if (emitZoneProps) {
994
+ const emitZone = buildEmitZoneFromLayout(emitZoneProps, next.width, next.height);
850
995
  if (emitZone) applyEmitZone(emitter, emitZone);
851
996
  }
852
- const deathZones = buildDeathZonesFromLayout(next.excludeZones, next.width, next.height);
997
+ const deathZones = buildDeathZonesFromLayout(deathZoneProps, next.width, next.height, manager);
853
998
  const combined = mergeDeathZones(resolvedConfig.deathZone, deathZones);
854
999
  applyDeathZone(emitter, combined);
855
1000
  }
@@ -885,8 +1030,10 @@ function createParticlesLayout(particles, props) {
885
1030
  */
886
1031
  var particlesCreator = (scene, props) => {
887
1032
  const resolvedConfig = { ...resolveParticlePreset(props.preset, props.config) };
888
- if (props.zone) {
889
- const emitZone = buildEmitZoneFromLayout(props.zone, props.width, props.height);
1033
+ const emitZoneProps = props.emitZone ?? props.zone;
1034
+ const deathZoneProps = props.deathZones ?? props.excludeZones;
1035
+ if (emitZoneProps) {
1036
+ const emitZone = buildEmitZoneFromLayout(emitZoneProps, props.width, props.height);
890
1037
  if (emitZone) {
891
1038
  const configWithZone = resolvedConfig;
892
1039
  configWithZone.emitZone = emitZone;
@@ -904,8 +1051,8 @@ var particlesCreator = (scene, props) => {
904
1051
  createTransform(particles, props);
905
1052
  createPhaser(particles, props);
906
1053
  createParticlesLayout(particles, props);
907
- if (props.excludeZones && emitter) {
908
- const deathZones = buildDeathZonesFromLayout(props.excludeZones, props.width, props.height);
1054
+ if (deathZoneProps && emitter) {
1055
+ const deathZones = buildDeathZonesFromLayout(deathZoneProps, props.width, props.height, particles);
909
1056
  const combinedDeathZones = mergeDeathZones(resolvedConfig.deathZone, deathZones);
910
1057
  if (combinedDeathZones) applyDeathZone(emitter, combinedDeathZones);
911
1058
  }
@@ -16557,18 +16704,54 @@ var textPatcher = (node, prev, next) => {
16557
16704
  //#endregion
16558
16705
  //#region src/components/primitives/tilesprite.ts
16559
16706
  /**
16560
- * TileSprite creator - NOT IMPLEMENTED YET
16561
- * @throws Error indicating component is not implemented
16707
+ * Creates layout infrastructure for TileSprite.
16562
16708
  */
16563
- var tileSpriteCreator = (_scene, _props) => {
16564
- throw new Error("TileSprite component not implemented yet. This is a placeholder for architecture planning.");
16709
+ function createTileSpriteLayout(tileSprite, props) {
16710
+ tileSprite.__layoutProps = props;
16711
+ tileSprite.__getLayoutSize = () => {
16712
+ if (tileSprite.__layoutProps?.headless) return {
16713
+ width: .01,
16714
+ height: .01
16715
+ };
16716
+ return {
16717
+ width: tileSprite.width,
16718
+ height: tileSprite.height
16719
+ };
16720
+ };
16721
+ }
16722
+ function applyTileSpriteProps(tileSprite, prev, next) {
16723
+ if ((prev.texture !== next.texture || prev.frame !== next.frame) && next.texture) tileSprite.setTexture(next.texture, next.frame);
16724
+ if ((prev.width !== next.width || prev.height !== next.height) && typeof next.width === "number" && typeof next.height === "number") tileSprite.setSize(next.width, next.height);
16725
+ if (prev.tilePositionX !== next.tilePositionX && typeof next.tilePositionX === "number") tileSprite.tilePositionX = next.tilePositionX;
16726
+ if (prev.tilePositionY !== next.tilePositionY && typeof next.tilePositionY === "number") tileSprite.tilePositionY = next.tilePositionY;
16727
+ if (prev.tileScaleX !== next.tileScaleX && typeof next.tileScaleX === "number") tileSprite.tileScaleX = next.tileScaleX;
16728
+ if (prev.tileScaleY !== next.tileScaleY && typeof next.tileScaleY === "number") tileSprite.tileScaleY = next.tileScaleY;
16729
+ if (prev.tint !== next.tint) if (typeof next.tint === "number") tileSprite.setTint(next.tint);
16730
+ else tileSprite.clearTint();
16731
+ if (prev.originX !== next.originX || prev.originY !== next.originY) tileSprite.setOrigin(next.originX ?? tileSprite.originX, next.originY ?? tileSprite.originY);
16732
+ }
16733
+ /**
16734
+ * TileSprite creator - creates a Phaser TileSprite object.
16735
+ */
16736
+ var tileSpriteCreator = (scene, props) => {
16737
+ const tileSprite = scene.add.tileSprite(props.x ?? 0, props.y ?? 0, props.width, props.height, props.texture, props.frame);
16738
+ tileSprite.setOrigin(props.originX ?? 0, props.originY ?? 0);
16739
+ createTransform(tileSprite, props);
16740
+ createPhaser(tileSprite, props);
16741
+ applyTileSpriteProps(tileSprite, {}, props);
16742
+ createTileSpriteLayout(tileSprite, props);
16743
+ props.onReady?.(tileSprite);
16744
+ return tileSprite;
16565
16745
  };
16566
16746
  /**
16567
- * TileSprite patcher - NOT IMPLEMENTED YET
16568
- * @throws Error indicating component is not implemented
16747
+ * TileSprite patcher - updates texture, size, tiling and shared display props.
16569
16748
  */
16570
- var tileSpritePatcher = (_node, _prev, _next) => {
16571
- throw new Error("TileSprite component not implemented yet. This is a placeholder for architecture planning.");
16749
+ var tileSpritePatcher = (node, prev, next) => {
16750
+ applyTransformProps(node, prev, next);
16751
+ applyPhaserProps(node, prev, next);
16752
+ applyTileSpriteProps(node, prev, next);
16753
+ const tileSprite = node;
16754
+ if (tileSprite.__layoutProps) tileSprite.__layoutProps = next;
16572
16755
  };
16573
16756
  //#endregion
16574
16757
  //#region src/components/backgroundImage.ts
@@ -16948,7 +17131,7 @@ var GestureManager = class {
16948
17131
  /**
16949
17132
  * Handle global pointer down event
16950
17133
  * Registers all containers that were hit for move event tracking
16951
- * Only the topmost gets touch/longpress callbacks
17134
+ * Only the topmost gets touch/long-press callbacks
16952
17135
  */
16953
17136
  handlePointerDown(pointer) {
16954
17137
  const hitContainers = /* @__PURE__ */ new Set();
@@ -19812,6 +19995,91 @@ function buildDefaultTheme(colors) {
19812
19995
  fontSize: "14px"
19813
19996
  }
19814
19997
  },
19998
+ Checkbox: {
19999
+ checkedColor: colors.primary.DEFAULT.toNumber(),
20000
+ indeterminateColor: colors.primary.medium.toNumber(),
20001
+ color: colors.border.medium.toNumber(),
20002
+ gap: 10,
20003
+ size: 20,
20004
+ disabledAlpha: .5,
20005
+ labelPosition: "right",
20006
+ labelStyle: {
20007
+ color: colors.text.DEFAULT.toString(),
20008
+ fontSize: "14px"
20009
+ }
20010
+ },
20011
+ Badge: {
20012
+ tone: "neutral",
20013
+ variant: "solid",
20014
+ size: "medium",
20015
+ maxCount: 99,
20016
+ disabledAlpha: .5,
20017
+ textStyle: { fontStyle: "bold" }
20018
+ },
20019
+ Tag: {
20020
+ tone: "neutral",
20021
+ variant: "soft",
20022
+ size: "medium",
20023
+ closeSize: 16,
20024
+ disabledAlpha: .5,
20025
+ textStyle: { fontStyle: "bold" }
20026
+ },
20027
+ Popover: {
20028
+ placement: "bottom",
20029
+ offset: 8,
20030
+ depth: 1100,
20031
+ closeOnOutside: true,
20032
+ closeOnEscape: true,
20033
+ viewportPadding: 8,
20034
+ backgroundColor: colors.surface.dark.toNumber(),
20035
+ borderColor: colors.border.medium.toNumber(),
20036
+ borderWidth: 1,
20037
+ cornerRadius: 8,
20038
+ padding: 10,
20039
+ gap: 8
20040
+ },
20041
+ ContextMenu: {
20042
+ width: 220,
20043
+ itemHeight: 34,
20044
+ itemGap: 8,
20045
+ itemPadding: {
20046
+ left: 10,
20047
+ right: 10,
20048
+ top: 6,
20049
+ bottom: 6
20050
+ },
20051
+ itemCornerRadius: 5,
20052
+ backgroundColor: colors.surface.dark.toNumber(),
20053
+ borderColor: colors.border.medium.toNumber(),
20054
+ borderWidth: 1,
20055
+ cornerRadius: 8,
20056
+ padding: 6,
20057
+ gap: 2,
20058
+ textStyle: {
20059
+ ...textStyles.small,
20060
+ color: colors.text.medium.toString()
20061
+ },
20062
+ disabledTextColor: colors.text.lightest.toString(),
20063
+ dangerTextColor: colors.error.darkest.toString(),
20064
+ dangerBackgroundColor: colors.error.dark.toNumber()
20065
+ },
20066
+ ProgressBar: {
20067
+ width: 240,
20068
+ height: 22,
20069
+ orientation: "horizontal",
20070
+ labelPosition: "right",
20071
+ trackColor: colors.surface.dark.toNumber(),
20072
+ fillColor: colors.success.DEFAULT.toNumber(),
20073
+ borderColor: colors.border.medium.toNumber(),
20074
+ borderWidth: 1,
20075
+ cornerRadius: 11,
20076
+ gap: 8,
20077
+ disabledAlpha: .5,
20078
+ labelStyle: {
20079
+ color: colors.text.DEFAULT.toString(),
20080
+ fontSize: "13px"
20081
+ }
20082
+ },
19815
20083
  ScrollSlider: {
19816
20084
  borderColor: colors.border.dark.toNumber(),
19817
20085
  trackColor: colors.surface.dark.toNumber(),
@@ -20624,7 +20892,7 @@ function useViewportSize() {
20624
20892
  * @param container - Phaser container with layout
20625
20893
  * @returns Layout size or undefined if container has no layout
20626
20894
  */
20627
- function getLayoutSize(container) {
20895
+ function getLayoutSize$1(container) {
20628
20896
  if (!container) return void 0;
20629
20897
  return container.__getLayoutSize?.();
20630
20898
  }
@@ -20636,7 +20904,7 @@ function getLayoutSize(container) {
20636
20904
  * @returns Current layout size or undefined
20637
20905
  */
20638
20906
  function useLayoutSize(ref) {
20639
- return getLayoutSize(ref.current);
20907
+ return getLayoutSize$1(ref.current);
20640
20908
  }
20641
20909
  /**
20642
20910
  * Utility function to get layout props from a container
@@ -20677,7 +20945,7 @@ function useBackgroundGraphics(ref) {
20677
20945
  */
20678
20946
  function getLayoutRect(container) {
20679
20947
  if (!container) return void 0;
20680
- const size = getLayoutSize(container);
20948
+ const size = getLayoutSize$1(container);
20681
20949
  if (!size) return void 0;
20682
20950
  return {
20683
20951
  x: container.x,
@@ -20710,7 +20978,7 @@ function useLayoutRect(ref) {
20710
20978
  */
20711
20979
  function getWorldLayoutRect(container) {
20712
20980
  if (!container) return void 0;
20713
- const size = getLayoutSize(container);
20981
+ const size = getLayoutSize$1(container);
20714
20982
  if (!size) return void 0;
20715
20983
  const matrix = container.getWorldTransformMatrix();
20716
20984
  return {
@@ -22766,6 +23034,241 @@ var viewPatcher = (node, prev, next) => {
22766
23034
  applyLayoutProps(container, normalizedPrev, normalizedNext);
22767
23035
  };
22768
23036
  //#endregion
23037
+ //#region src/components/custom/Badge.tsx
23038
+ /** @jsxImportSource ../.. */
23039
+ /**
23040
+ * Badge and Tag components - compact labels for counts, status, filters, and inventory metadata.
23041
+ */
23042
+ var DEFAULT_TONES = {
23043
+ neutral: {
23044
+ backgroundColor: 4674921,
23045
+ softBackgroundColor: 1976635,
23046
+ borderColor: 6583435,
23047
+ textColor: "#ffffff",
23048
+ outlineTextColor: "#cbd5e1"
23049
+ },
23050
+ primary: {
23051
+ backgroundColor: 2450411,
23052
+ softBackgroundColor: 1981066,
23053
+ borderColor: 6333946,
23054
+ textColor: "#ffffff",
23055
+ outlineTextColor: "#93c5fd"
23056
+ },
23057
+ success: {
23058
+ backgroundColor: 1483594,
23059
+ softBackgroundColor: 1332013,
23060
+ borderColor: 4906624,
23061
+ textColor: "#ffffff",
23062
+ outlineTextColor: "#86efac"
23063
+ },
23064
+ warning: {
23065
+ backgroundColor: 16096779,
23066
+ softBackgroundColor: 7877903,
23067
+ borderColor: 16498468,
23068
+ textColor: "#111827",
23069
+ outlineTextColor: "#fde68a"
23070
+ },
23071
+ danger: {
23072
+ backgroundColor: 14427686,
23073
+ softBackgroundColor: 8330525,
23074
+ borderColor: 16281969,
23075
+ textColor: "#ffffff",
23076
+ outlineTextColor: "#fecaca"
23077
+ },
23078
+ info: {
23079
+ backgroundColor: 561586,
23080
+ softBackgroundColor: 1461859,
23081
+ borderColor: 2282478,
23082
+ textColor: "#ffffff",
23083
+ outlineTextColor: "#a5f3fc"
23084
+ }
23085
+ };
23086
+ var DEFAULT_SIZES = {
23087
+ small: {
23088
+ height: 20,
23089
+ padding: {
23090
+ left: 7,
23091
+ right: 7,
23092
+ top: 2,
23093
+ bottom: 2
23094
+ },
23095
+ fontSize: 11,
23096
+ cornerRadius: 10,
23097
+ gap: 5,
23098
+ dotSize: 8
23099
+ },
23100
+ medium: {
23101
+ height: 24,
23102
+ padding: {
23103
+ left: 9,
23104
+ right: 9,
23105
+ top: 3,
23106
+ bottom: 3
23107
+ },
23108
+ fontSize: 13,
23109
+ cornerRadius: 12,
23110
+ gap: 6,
23111
+ dotSize: 10
23112
+ },
23113
+ large: {
23114
+ height: 30,
23115
+ padding: {
23116
+ left: 12,
23117
+ right: 12,
23118
+ top: 4,
23119
+ bottom: 4
23120
+ },
23121
+ fontSize: 18,
23122
+ cornerRadius: 15,
23123
+ gap: 8,
23124
+ dotSize: 12
23125
+ }
23126
+ };
23127
+ function formatBadgeCount({ count, maxCount = 99 }) {
23128
+ if (!Number.isFinite(count)) return "0";
23129
+ const normalizedCount = Math.max(0, Math.floor(count ?? 0));
23130
+ const normalizedMax = Math.max(0, Math.floor(maxCount));
23131
+ return normalizedCount > normalizedMax ? `${normalizedMax}+` : `${normalizedCount}`;
23132
+ }
23133
+ function getBadgeText(props) {
23134
+ if (props.count !== void 0) return formatBadgeCount(props);
23135
+ if (props.label !== void 0) return `${props.label}`;
23136
+ return "";
23137
+ }
23138
+ function resolveBadgeColors(tone, variant) {
23139
+ const toneColors = DEFAULT_TONES[tone];
23140
+ if (variant === "outline") return {
23141
+ backgroundColor: 0,
23142
+ backgroundAlpha: 0,
23143
+ borderColor: toneColors.borderColor,
23144
+ borderWidth: 1,
23145
+ textColor: toneColors.outlineTextColor
23146
+ };
23147
+ if (variant === "soft") return {
23148
+ backgroundColor: toneColors.softBackgroundColor,
23149
+ backgroundAlpha: 1,
23150
+ borderColor: toneColors.borderColor,
23151
+ borderWidth: 1,
23152
+ textColor: toneColors.outlineTextColor
23153
+ };
23154
+ return {
23155
+ backgroundColor: toneColors.backgroundColor,
23156
+ backgroundAlpha: 1,
23157
+ borderColor: toneColors.borderColor,
23158
+ borderWidth: 0,
23159
+ textColor: toneColors.textColor
23160
+ };
23161
+ }
23162
+ function getBadgeSizeConfig(size) {
23163
+ return DEFAULT_SIZES[size];
23164
+ }
23165
+ function resolveBadgeTextStyle(options) {
23166
+ const sizeConfig = getBadgeSizeConfig(options.size);
23167
+ return {
23168
+ color: options.textColor,
23169
+ fontSize: `${sizeConfig.fontSize}px`,
23170
+ ...options.themedTextStyle ?? {},
23171
+ ...options.explicitTextStyle ?? {}
23172
+ };
23173
+ }
23174
+ function Badge(props) {
23175
+ const { children, label, count, maxCount, dot = false, tone: explicitTone, variant: explicitVariant, size: explicitSize, textStyle: explicitTextStyle, disabled = false, disabledAlpha: explicitDisabledAlpha, theme, width, height, padding, gap, cornerRadius, backgroundColor, backgroundAlpha, borderColor, borderWidth, alpha, ...viewProps } = props;
23176
+ const { props: themed, nestedTheme } = getThemedProps("Badge", useTheme(), theme ?? {});
23177
+ const tone = explicitTone ?? themed.tone ?? "neutral";
23178
+ const variant = explicitVariant ?? themed.variant ?? "solid";
23179
+ const size = explicitSize ?? themed.size ?? "medium";
23180
+ const sizeConfig = getBadgeSizeConfig(size);
23181
+ const colors = resolveBadgeColors(tone, variant);
23182
+ const disabledAlpha = explicitDisabledAlpha ?? themed.disabledAlpha ?? .5;
23183
+ const effectiveAlpha = disabled ? disabledAlpha : alpha;
23184
+ const resolvedMaxCount = maxCount ?? themed.maxCount ?? 99;
23185
+ const text = count !== void 0 ? formatBadgeCount({
23186
+ count,
23187
+ maxCount: resolvedMaxCount
23188
+ }) : label !== void 0 ? `${label}` : "";
23189
+ const resolvedTextStyle = resolveBadgeTextStyle({
23190
+ size,
23191
+ textColor: colors.textColor,
23192
+ themedTextStyle: themed.textStyle,
23193
+ explicitTextStyle
23194
+ });
23195
+ const dotSize = themed.dotSize ?? sizeConfig.dotSize;
23196
+ if (dot) return /* @__PURE__ */ jsx(View, {
23197
+ ...viewProps,
23198
+ width: width ?? dotSize,
23199
+ height: height ?? dotSize,
23200
+ backgroundColor: backgroundColor ?? themed.backgroundColor ?? colors.backgroundColor,
23201
+ backgroundAlpha: backgroundAlpha ?? themed.backgroundAlpha ?? colors.backgroundAlpha,
23202
+ borderColor: borderColor ?? themed.borderColor ?? colors.borderColor,
23203
+ borderWidth: borderWidth ?? themed.borderWidth ?? colors.borderWidth,
23204
+ cornerRadius: cornerRadius ?? themed.cornerRadius ?? dotSize / 2,
23205
+ ...effectiveAlpha !== void 0 ? { alpha: effectiveAlpha } : {},
23206
+ theme: nestedTheme
23207
+ });
23208
+ return /* @__PURE__ */ jsx(View, {
23209
+ ...viewProps,
23210
+ width: width ?? themed.width ?? "auto",
23211
+ height: height ?? themed.height ?? sizeConfig.height,
23212
+ direction: "row",
23213
+ alignItems: "center",
23214
+ justifyContent: "center",
23215
+ gap: gap ?? themed.gap ?? sizeConfig.gap,
23216
+ padding: padding ?? themed.padding ?? sizeConfig.padding,
23217
+ backgroundColor: backgroundColor ?? themed.backgroundColor ?? colors.backgroundColor,
23218
+ backgroundAlpha: backgroundAlpha ?? themed.backgroundAlpha ?? colors.backgroundAlpha,
23219
+ borderColor: borderColor ?? themed.borderColor ?? colors.borderColor,
23220
+ borderWidth: borderWidth ?? themed.borderWidth ?? colors.borderWidth,
23221
+ cornerRadius: cornerRadius ?? themed.cornerRadius ?? sizeConfig.cornerRadius,
23222
+ ...effectiveAlpha !== void 0 ? { alpha: effectiveAlpha } : {},
23223
+ theme: nestedTheme,
23224
+ children: children ?? /* @__PURE__ */ jsx(Text, {
23225
+ text,
23226
+ style: resolvedTextStyle
23227
+ })
23228
+ });
23229
+ }
23230
+ function Tag(props) {
23231
+ const { selected = false, onRemove, closeLabel = "x", tone, variant, size, theme, children, label, textStyle, ...badgeProps } = props;
23232
+ const { props: themed, nestedTheme } = getThemedProps("Tag", useTheme(), theme ?? {});
23233
+ const resolvedTone = tone ?? themed.tone ?? (selected ? "primary" : "neutral");
23234
+ const resolvedVariant = variant ?? themed.variant ?? (selected ? "solid" : "soft");
23235
+ const resolvedSize = size ?? themed.size ?? "medium";
23236
+ const resolvedTextStyle = resolveBadgeTextStyle({
23237
+ size: resolvedSize,
23238
+ textColor: resolveBadgeColors(resolvedTone, resolvedVariant).textColor,
23239
+ themedTextStyle: themed.textStyle,
23240
+ explicitTextStyle: textStyle
23241
+ });
23242
+ const text = label !== void 0 ? `${label}` : "";
23243
+ return /* @__PURE__ */ jsxs(Badge, {
23244
+ ...badgeProps,
23245
+ tone: resolvedTone,
23246
+ variant: resolvedVariant,
23247
+ size: resolvedSize,
23248
+ textStyle: resolvedTextStyle,
23249
+ theme: nestedTheme,
23250
+ children: [
23251
+ label !== void 0 && /* @__PURE__ */ jsx(Text, {
23252
+ text,
23253
+ style: resolvedTextStyle
23254
+ }),
23255
+ children,
23256
+ onRemove && /* @__PURE__ */ jsx(Button, {
23257
+ width: themed.closeSize ?? 16,
23258
+ height: themed.closeSize ?? 16,
23259
+ padding: 0,
23260
+ cornerRadius: (themed.closeSize ?? 16) / 2,
23261
+ onClick: onRemove,
23262
+ theme: nestedTheme,
23263
+ children: /* @__PURE__ */ jsx(Text, {
23264
+ text: closeLabel,
23265
+ style: resolvedTextStyle
23266
+ })
23267
+ })
23268
+ ]
23269
+ });
23270
+ }
23271
+ //#endregion
22769
23272
  //#region src/effects/use-effect.ts
22770
23273
  /**
22771
23274
  * Custom hook for Phaser game object effects (shake, pulse, etc.)
@@ -23748,83 +24251,437 @@ function Button(props) {
23748
24251
  });
23749
24252
  }
23750
24253
  //#endregion
23751
- //#region src/components/custom/Graphics.tsx
23752
- /**
23753
- * Graphics component
23754
- * Renders custom vector shapes via imperative drawing API
23755
- *
23756
- * @example
23757
- * ```tsx
23758
- * <Graphics
23759
- * onDraw={(g) => {
23760
- * g.fillStyle(0xff0000, 1)
23761
- * g.fillCircle(50, 50, 50)
23762
- * }}
23763
- * />
23764
- * ```
23765
- */
23766
- function Graphics(props) {
23767
- const { props: themed, nestedTheme } = getThemedProps("Graphics", useTheme(), props);
23768
- return /* @__PURE__ */ jsx("graphics", {
23769
- ...themed,
23770
- theme: nestedTheme
23771
- });
24254
+ //#region src/components/custom/Checkbox.tsx
24255
+ function getNextCheckedState(checked, tristate) {
24256
+ if (!tristate) return checked === true ? false : true;
24257
+ if (checked === false) return true;
24258
+ if (checked === true) return "indeterminate";
24259
+ return false;
23772
24260
  }
23773
- //#endregion
23774
- //#region src/components/custom/RadioButton.tsx
23775
- /** @jsxImportSource ../.. */
23776
- /**
23777
- * RadioButton component - Selectable option with circle indicator and label
23778
- */
23779
- /**
23780
- * RadioButton component - displays a selectable circle with label
23781
- * @param props - RadioButton properties
23782
- * @returns RadioButton JSX element
23783
- */
23784
- function RadioButton(props) {
23785
- const { props: themed, nestedTheme } = getThemedProps("RadioButton", void 0, {});
23786
- const size = themed.size ?? 16;
23787
- const innerSize = themed.innerSize ?? size * .75;
23788
- const innerRadius = innerSize * .5;
23789
- const outerRadius = size * .5;
24261
+ function normalizeCheckedState(checked, tristate) {
24262
+ return checked === "indeterminate" && !tristate ? false : checked;
24263
+ }
24264
+ function drawDefaultIndicator(graphics, indicatorProps) {
24265
+ const { checked, disabled, size, color, checkedColor, indeterminateColor } = indicatorProps;
24266
+ const borderWidth = Math.max(2, Math.round(size * .1));
24267
+ const inset = Math.max(4, Math.round(size * .22));
24268
+ const radius = Math.max(2, Math.round(size * .15));
24269
+ const alpha = disabled ? .45 : 1;
24270
+ graphics.clear();
24271
+ graphics.lineStyle(borderWidth, checked === false ? color : checkedColor, alpha);
24272
+ graphics.strokeRoundedRect(borderWidth / 2, borderWidth / 2, size - borderWidth, size - borderWidth, radius);
24273
+ if (checked === true) {
24274
+ graphics.lineStyle(borderWidth + 1, checkedColor, alpha);
24275
+ graphics.beginPath();
24276
+ graphics.moveTo(inset, size * .52);
24277
+ graphics.lineTo(size * .43, size - inset);
24278
+ graphics.lineTo(size - inset, inset);
24279
+ graphics.strokePath();
24280
+ }
24281
+ if (checked === "indeterminate") {
24282
+ graphics.lineStyle(borderWidth + 1, indeterminateColor, alpha);
24283
+ graphics.beginPath();
24284
+ graphics.moveTo(inset, size / 2);
24285
+ graphics.lineTo(size - inset, size / 2);
24286
+ graphics.strokePath();
24287
+ }
24288
+ }
24289
+ function Checkbox(props) {
24290
+ const { props: themed, nestedTheme } = getThemedProps("Checkbox", useTheme(), props.theme ?? {});
24291
+ const size = themed.size ?? 20;
24292
+ const gap = themed.gap ?? 8;
24293
+ const labelPosition = props.labelPosition ?? themed.labelPosition ?? "right";
24294
+ const disabled = props.disabled ?? false;
24295
+ const disabledAlpha = themed.disabledAlpha ?? .5;
24296
+ const tristate = props.tristate ?? false;
24297
+ const [checked, setChecked] = useState(normalizeCheckedState(props.checked ?? props.defaultChecked ?? false, tristate));
24298
+ useEffect(() => {
24299
+ if (props.checked !== void 0) setChecked(normalizeCheckedState(props.checked, tristate));
24300
+ }, [props.checked, tristate]);
24301
+ const indicatorProps = {
24302
+ checked,
24303
+ disabled,
24304
+ size,
24305
+ color: themed.color ?? 7829367,
24306
+ checkedColor: themed.checkedColor ?? 5025616,
24307
+ indeterminateColor: themed.indeterminateColor ?? themed.checkedColor ?? 5025616
24308
+ };
24309
+ const handleToggle = () => {
24310
+ if (disabled) return;
24311
+ const nextChecked = getNextCheckedState(checked, tristate);
24312
+ if (props.checked === void 0) setChecked(nextChecked);
24313
+ props.onChange?.(nextChecked);
24314
+ };
24315
+ const indicator = props.indicator ?? props.renderIndicator?.(indicatorProps) ?? /* @__PURE__ */ jsx(Graphics, {
24316
+ width: size,
24317
+ height: size,
24318
+ headless: false,
24319
+ dependencies: [
24320
+ indicatorProps.checked,
24321
+ indicatorProps.disabled,
24322
+ indicatorProps.size,
24323
+ indicatorProps.color,
24324
+ indicatorProps.checkedColor,
24325
+ indicatorProps.indeterminateColor
24326
+ ],
24327
+ onDraw: (graphics) => drawDefaultIndicator(graphics, indicatorProps)
24328
+ });
24329
+ const label = props.label && labelPosition !== "none" ? /* @__PURE__ */ jsx(Text, {
24330
+ text: props.label,
24331
+ style: themed.labelStyle,
24332
+ alpha: disabled ? disabledAlpha : 1
24333
+ }) : null;
23790
24334
  return /* @__PURE__ */ jsxs(View, {
23791
24335
  direction: "row",
23792
24336
  alignItems: "center",
23793
- enableGestures: true,
23794
- onTouch: () => props.onClick?.(),
24337
+ enableGestures: !disabled,
24338
+ onTouch: handleToggle,
23795
24339
  theme: nestedTheme,
23796
- gap: themed.gap,
23797
- children: [/* @__PURE__ */ jsx(View, {
23798
- width: size,
23799
- height: size,
23800
- backgroundColor: themed.color,
23801
- alignItems: "center",
23802
- justifyContent: "center",
23803
- backgroundAlpha: 1,
23804
- padding: 0,
23805
- cornerRadius: outerRadius,
23806
- children: /* @__PURE__ */ jsx(View, {
23807
- width: innerSize,
23808
- height: innerSize,
23809
- backgroundColor: themed.selectedColor,
23810
- visible: props.selected ?? false,
23811
- cornerRadius: innerRadius
23812
- })
23813
- }), /* @__PURE__ */ jsx(Text, {
23814
- text: props.label,
23815
- style: themed.labelStyle
23816
- })]
24340
+ gap,
24341
+ alpha: disabled ? disabledAlpha : 1,
24342
+ children: [
24343
+ labelPosition === "left" && label,
24344
+ indicator,
24345
+ labelPosition !== "left" && label
24346
+ ]
23817
24347
  }, props.key);
23818
24348
  }
23819
24349
  //#endregion
23820
- //#region src/components/custom/RadioGroup.tsx
23821
- /** @jsxImportSource ../.. */
24350
+ //#region src/design-tokens/use-theme-tokens.ts
23822
24351
  /**
23823
- * RadioGroup component - Manages a group of radio buttons with single-selection logic
24352
+ * Hook to access complete design token system
24353
+ * Combines colors with text styles, spacing, sizes, and radius tokens
23824
24354
  */
23825
24355
  /**
23826
- * RadioGroup component - displays a group of radio buttons with single-selection
23827
- * @param props - RadioGroup properties
24356
+ * Hook to access complete design token system from theme context
24357
+ * Provides colors, text styles, spacing, sizes, and radius tokens
24358
+ * Automatically updates when color mode or preset changes
24359
+ * @returns Current DesignTokens or undefined
24360
+ * @example
24361
+ * ```typescript
24362
+ * function MyComponent() {
24363
+ * const tokens = useThemeTokens()
24364
+ *
24365
+ * if (!tokens) return null
24366
+ *
24367
+ * return (
24368
+ * <View
24369
+ * backgroundColor={tokens.colors.surface.DEFAULT}
24370
+ * padding={tokens.spacing.lg}
24371
+ * cornerRadius={tokens.radius.md}
24372
+ * >
24373
+ * <Text text="Title" style={tokens.textStyles.title} />
24374
+ * <Text text="Body text" style={tokens.textStyles.DEFAULT} />
24375
+ * </View>
24376
+ * )
24377
+ * }
24378
+ * ```
24379
+ */
24380
+ function useThemeTokens() {
24381
+ const localTheme = useTheme();
24382
+ const getInitialTokens = () => {
24383
+ if (localTheme?.__colorPreset) {
24384
+ const preset = getPresetWithMode(localTheme.__colorPreset.name, localTheme.__colorPreset.mode ?? "light");
24385
+ return {
24386
+ colors: preset.colors,
24387
+ textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),
24388
+ spacing: defaultSpacingTokens,
24389
+ sizes: defaultSizeTokens,
24390
+ radius: defaultRadiusTokens
24391
+ };
24392
+ }
24393
+ const colors = themeRegistry.getColorTokens();
24394
+ if (!colors) return void 0;
24395
+ return {
24396
+ colors,
24397
+ textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),
24398
+ spacing: defaultSpacingTokens,
24399
+ sizes: defaultSizeTokens,
24400
+ radius: defaultRadiusTokens
24401
+ };
24402
+ };
24403
+ const [tokens, setTokens] = useState(getInitialTokens());
24404
+ const [, forceUpdate] = useState(0);
24405
+ useEffect(() => {
24406
+ return themeRegistry.subscribe(() => {
24407
+ if (localTheme?.__colorPreset) {
24408
+ const currentMode = themeRegistry.getColorMode();
24409
+ const preset = getPresetWithMode(localTheme.__colorPreset.name, currentMode);
24410
+ setTokens({
24411
+ colors: preset.colors,
24412
+ textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),
24413
+ spacing: defaultSpacingTokens,
24414
+ sizes: defaultSizeTokens,
24415
+ radius: defaultRadiusTokens
24416
+ });
24417
+ } else {
24418
+ const colors = themeRegistry.getColorTokens();
24419
+ if (colors) setTokens({
24420
+ colors,
24421
+ textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),
24422
+ spacing: defaultSpacingTokens,
24423
+ sizes: defaultSizeTokens,
24424
+ radius: defaultRadiusTokens
24425
+ });
24426
+ }
24427
+ forceUpdate((n) => n + 1);
24428
+ });
24429
+ }, [localTheme]);
24430
+ return tokens;
24431
+ }
24432
+ //#endregion
24433
+ //#region src/components/custom/DebugPanel.tsx
24434
+ /** @jsxImportSource ../.. */
24435
+ /**
24436
+ * DebugPanel component - lightweight runtime diagnostics for Phaser + PhaserJSX
24437
+ * Renders selected metrics as text rows or a compact single-line summary.
24438
+ */
24439
+ var PRESET_METRICS = {
24440
+ fps: ["fps", "frameMs"],
24441
+ perf: [
24442
+ "fps",
24443
+ "frameMs",
24444
+ "renderer",
24445
+ "viewport"
24446
+ ],
24447
+ vdom: [
24448
+ "mountsTotal",
24449
+ "mountsByType",
24450
+ "mountsByParent",
24451
+ "mountsByKey"
24452
+ ],
24453
+ textures: ["textureCount"],
24454
+ full: [
24455
+ "fps",
24456
+ "frameMs",
24457
+ "phaserVersion",
24458
+ "renderer",
24459
+ "viewport",
24460
+ "textureCount",
24461
+ "mountsTotal",
24462
+ "mountsByType",
24463
+ "mountsByParent",
24464
+ "mountsByKey",
24465
+ "debugFlags"
24466
+ ]
24467
+ };
24468
+ var DEFAULT_LABELS = {
24469
+ fps: "FPS",
24470
+ frameMs: "Frame ms",
24471
+ phaserVersion: "Phaser",
24472
+ renderer: "Renderer",
24473
+ viewport: "Viewport",
24474
+ textureCount: "Textures",
24475
+ mountsTotal: "Mounts",
24476
+ mountsByType: "Mounts/type",
24477
+ mountsByParent: "Mounts/parent",
24478
+ mountsByKey: "Mounts/key",
24479
+ debugFlags: "Debug flags"
24480
+ };
24481
+ function resolveRendererName(scene) {
24482
+ const renderer = scene.renderer;
24483
+ const canvasType = Phaser.CANVAS;
24484
+ if (renderer.type === Phaser.WEBGL) return "WebGL";
24485
+ if (canvasType !== void 0 && renderer.type === canvasType) return "Canvas";
24486
+ if (renderer.constructor?.name) return renderer.constructor.name;
24487
+ if (typeof renderer.type === "number") return `Type ${renderer.type}`;
24488
+ return "Unknown";
24489
+ }
24490
+ function resolveTextureCount(scene) {
24491
+ const manager = scene.textures;
24492
+ const keys = typeof manager.getTextureKeys === "function" ? manager.getTextureKeys() : Object.keys(manager.list ?? {});
24493
+ const internalKeys = new Set([
24494
+ "__DEFAULT",
24495
+ "__MISSING",
24496
+ "__NORMAL",
24497
+ "__WHITE"
24498
+ ]);
24499
+ return keys.filter((key) => !internalKeys.has(key.toUpperCase())).length;
24500
+ }
24501
+ function resolveFrameStats(scene) {
24502
+ const loop = scene.game.loop;
24503
+ const rawFps = loop?.actualFps ?? loop?.fps ?? 0;
24504
+ const rawFrameMs = loop?.delta ?? loop?.frameDelta ?? 0;
24505
+ return {
24506
+ fps: Number.isFinite(rawFps) ? Number(rawFps.toFixed(1)) : 0,
24507
+ frameMs: Number.isFinite(rawFrameMs) ? Number(rawFrameMs.toFixed(2)) : 0
24508
+ };
24509
+ }
24510
+ function summarizeMap(map, maxEntries = 3) {
24511
+ return Array.from(map.entries()).sort((a, b) => b[1] - a[1]).slice(0, maxEntries).map(([key, value]) => `${String(key)}:${value}`).join(" | ") || "-";
24512
+ }
24513
+ function resolveDebugFlags() {
24514
+ const debugConfig = DevConfig.debug;
24515
+ if (!debugConfig.enabled) return "off";
24516
+ const enabledFlags = Object.entries(debugConfig).filter(([key, value]) => key !== "enabled" && value).map(([key]) => key);
24517
+ return enabledFlags.length ? enabledFlags.join(",") : "enabled";
24518
+ }
24519
+ function collectSnapshot(scene) {
24520
+ const { fps, frameMs } = resolveFrameStats(scene);
24521
+ const mountStats = getMountStats();
24522
+ return {
24523
+ fps,
24524
+ frameMs,
24525
+ phaserVersion: Phaser.VERSION,
24526
+ renderer: resolveRendererName(scene),
24527
+ viewport: `${scene.scale.width}x${scene.scale.height}`,
24528
+ textureCount: resolveTextureCount(scene),
24529
+ mountsTotal: mountStats.totalMounts,
24530
+ mountsByType: summarizeMap(mountStats.byType),
24531
+ mountsByParent: summarizeMap(mountStats.byParent),
24532
+ mountsByKey: summarizeMap(mountStats.byKey),
24533
+ debugFlags: resolveDebugFlags()
24534
+ };
24535
+ }
24536
+ function formatDefault(value) {
24537
+ return typeof value === "number" ? String(value) : value;
24538
+ }
24539
+ /**
24540
+ * DebugPanel component
24541
+ * Shows selected diagnostics from Phaser + PhaserJSX as overlay-ready content.
24542
+ */
24543
+ function DebugPanel(props) {
24544
+ const scene = useScene();
24545
+ const { preset = "fps", metrics, intervalMs = 250, compact = false, maxRows, labels, formatters, innerProps, ...viewProps } = props;
24546
+ const selectedMetrics = useMemo(() => {
24547
+ const source = metrics && metrics.length > 0 ? metrics : PRESET_METRICS[preset];
24548
+ return Array.from(new Set(source));
24549
+ }, [metrics, preset]);
24550
+ const [snapshot, setSnapshot] = useState(collectSnapshot(scene));
24551
+ useEffect(() => {
24552
+ const delay = Math.max(50, intervalMs);
24553
+ setSnapshot(collectSnapshot(scene));
24554
+ const timer = window.setInterval(() => {
24555
+ setSnapshot(collectSnapshot(scene));
24556
+ }, delay);
24557
+ return () => {
24558
+ window.clearInterval(timer);
24559
+ };
24560
+ }, [
24561
+ scene,
24562
+ intervalMs,
24563
+ selectedMetrics
24564
+ ]);
24565
+ const tokens = useThemeTokens();
24566
+ const rowStyle = tokens?.textStyles.small;
24567
+ const valueStyle = tokens?.textStyles.small;
24568
+ const rows = selectedMetrics.map((metric) => {
24569
+ const rawValue = snapshot[metric];
24570
+ const label = labels?.[metric] ?? DEFAULT_LABELS[metric];
24571
+ const formatter = formatters?.[metric];
24572
+ return {
24573
+ metric,
24574
+ label,
24575
+ value: formatter ? formatter(rawValue) : formatDefault(rawValue)
24576
+ };
24577
+ });
24578
+ const limitedRows = typeof maxRows === "number" ? rows.slice(0, Math.max(1, maxRows)) : rows;
24579
+ if (compact) {
24580
+ const compactText = limitedRows.map((row) => `${row.label} ${row.value}`).join(" | ");
24581
+ return /* @__PURE__ */ jsx(View, {
24582
+ ...viewProps,
24583
+ children: /* @__PURE__ */ jsx(Text, {
24584
+ text: compactText,
24585
+ style: valueStyle
24586
+ })
24587
+ });
24588
+ }
24589
+ return /* @__PURE__ */ jsx(View, {
24590
+ direction: "column",
24591
+ gap: 4,
24592
+ ...viewProps,
24593
+ children: limitedRows.map((row) => /* @__PURE__ */ jsxs(View, {
24594
+ direction: "row",
24595
+ gap: 8,
24596
+ ...innerProps,
24597
+ children: [/* @__PURE__ */ jsx(Text, {
24598
+ text: `${row.label}:`,
24599
+ style: rowStyle
24600
+ }), /* @__PURE__ */ jsx(Text, {
24601
+ text: row.value,
24602
+ style: valueStyle
24603
+ })]
24604
+ }, `debug-${row.metric}`))
24605
+ });
24606
+ }
24607
+ //#endregion
24608
+ //#region src/components/custom/Graphics.tsx
24609
+ /**
24610
+ * Graphics component
24611
+ * Renders custom vector shapes via imperative drawing API
24612
+ *
24613
+ * @example
24614
+ * ```tsx
24615
+ * <Graphics
24616
+ * onDraw={(g) => {
24617
+ * g.fillStyle(0xff0000, 1)
24618
+ * g.fillCircle(50, 50, 50)
24619
+ * }}
24620
+ * />
24621
+ * ```
24622
+ */
24623
+ function Graphics(props) {
24624
+ const { props: themed, nestedTheme } = getThemedProps("Graphics", useTheme(), props);
24625
+ return /* @__PURE__ */ jsx("graphics", {
24626
+ ...themed,
24627
+ theme: nestedTheme
24628
+ });
24629
+ }
24630
+ //#endregion
24631
+ //#region src/components/custom/RadioButton.tsx
24632
+ /** @jsxImportSource ../.. */
24633
+ /**
24634
+ * RadioButton component - Selectable option with circle indicator and label
24635
+ */
24636
+ /**
24637
+ * RadioButton component - displays a selectable circle with label
24638
+ * @param props - RadioButton properties
24639
+ * @returns RadioButton JSX element
24640
+ */
24641
+ function RadioButton(props) {
24642
+ const { props: themed, nestedTheme } = getThemedProps("RadioButton", void 0, {});
24643
+ const size = themed.size ?? 16;
24644
+ const innerSize = themed.innerSize ?? size * .75;
24645
+ const innerRadius = innerSize * .5;
24646
+ const outerRadius = size * .5;
24647
+ return /* @__PURE__ */ jsxs(View, {
24648
+ direction: "row",
24649
+ alignItems: "center",
24650
+ enableGestures: true,
24651
+ onTouch: () => props.onClick?.(),
24652
+ theme: nestedTheme,
24653
+ gap: themed.gap,
24654
+ children: [/* @__PURE__ */ jsx(View, {
24655
+ width: size,
24656
+ height: size,
24657
+ backgroundColor: themed.color,
24658
+ alignItems: "center",
24659
+ justifyContent: "center",
24660
+ backgroundAlpha: 1,
24661
+ padding: 0,
24662
+ cornerRadius: outerRadius,
24663
+ children: /* @__PURE__ */ jsx(View, {
24664
+ width: innerSize,
24665
+ height: innerSize,
24666
+ backgroundColor: themed.selectedColor,
24667
+ visible: props.selected ?? false,
24668
+ cornerRadius: innerRadius
24669
+ })
24670
+ }), /* @__PURE__ */ jsx(Text, {
24671
+ text: props.label,
24672
+ style: themed.labelStyle
24673
+ })]
24674
+ }, props.key);
24675
+ }
24676
+ //#endregion
24677
+ //#region src/components/custom/RadioGroup.tsx
24678
+ /** @jsxImportSource ../.. */
24679
+ /**
24680
+ * RadioGroup component - Manages a group of radio buttons with single-selection logic
24681
+ */
24682
+ /**
24683
+ * RadioGroup component - displays a group of radio buttons with single-selection
24684
+ * @param props - RadioGroup properties
23828
24685
  * @returns RadioGroup JSX element
23829
24686
  */
23830
24687
  function RadioGroup(props) {
@@ -23965,6 +24822,501 @@ function Particles(props) {
23965
24822
  return /* @__PURE__ */ jsx("particles", { ...props });
23966
24823
  }
23967
24824
  //#endregion
24825
+ //#region src/components/custom/Portal.tsx
24826
+ /** @jsxImportSource ../.. */
24827
+ /**
24828
+ * Portal component - renders children into a separate tree at specified depth
24829
+ * Enables overlays, modals, tooltips without affecting parent tree layout
24830
+ */
24831
+ /**
24832
+ * Portal component
24833
+ * Renders child VNode into a separate container tree at specified depth.
24834
+ * Automatically injects event blockers to prevent click-through and scrolling.
24835
+ *
24836
+ * @example
24837
+ * ```tsx
24838
+ * // Basic portal (automatically blocks events in content area)
24839
+ * <Portal depth={1000}>
24840
+ * <View>Overlay content</View>
24841
+ * </Portal>
24842
+ *
24843
+ * // Non-blocking portal (allows click-through)
24844
+ * <Portal depth={500} blockEvents={false}>
24845
+ * <View>Info overlay - clickable background</View>
24846
+ * </Portal>
24847
+ *
24848
+ * // Portal with custom event handling (original handlers are preserved)
24849
+ * <Portal depth={1000}>
24850
+ * <View onTouch={(e) => console.log('clicked')}>
24851
+ * Content
24852
+ * </View>
24853
+ * </Portal>
24854
+ * ```
24855
+ */
24856
+ function Portal(props) {
24857
+ const portalId = useMemo(() => props.id ?? portalRegistry.generateId(), [props.id]);
24858
+ const depth = props.depth ?? 1e3;
24859
+ const scene = useScene();
24860
+ const blockEvents = props.blockEvents ?? true;
24861
+ const mountedNodesRef = useRef([]);
24862
+ const previousChildrenRef = useRef([]);
24863
+ const normalizeChildren = (children) => {
24864
+ if (!children) return [];
24865
+ return (Array.isArray(children) ? children.flat(Infinity) : [children]).filter((child) => !!child && typeof child === "object" && "type" in child);
24866
+ };
24867
+ useEffect(() => {
24868
+ const portalContainer = portalRegistry.register(portalId, depth, scene, {
24869
+ type: "View",
24870
+ props: {},
24871
+ children: []
24872
+ }, scene.add.container(0, 0));
24873
+ let blockerContainer = null;
24874
+ if (blockEvents) {
24875
+ blockerContainer = scene.add.container(0, 0);
24876
+ portalContainer.add(blockerContainer);
24877
+ blockerContainer.setDepth(-1);
24878
+ }
24879
+ const children = normalizeChildren(props.children);
24880
+ const mountedNodes = [];
24881
+ for (const child of children) if (child) {
24882
+ const mountedNode = mount(portalContainer, child);
24883
+ if (mountedNode) {
24884
+ portalContainer.add(mountedNode);
24885
+ mountedNodes.push(mountedNode);
24886
+ }
24887
+ }
24888
+ mountedNodesRef.current = mountedNodes;
24889
+ previousChildrenRef.current = children;
24890
+ const gestureManager = getGestureManager(scene);
24891
+ if (blockEvents && blockerContainer) {
24892
+ const blocker = blockerContainer;
24893
+ DeferredLayoutQueue.defer(() => {
24894
+ const firstChild = portalContainer.getAt(1);
24895
+ if (!firstChild) return;
24896
+ const { width, height } = firstChild.__cachedLayoutSize ? firstChild.__cachedLayoutSize : firstChild.__getLayoutSize ? firstChild.__getLayoutSize() : (() => {
24897
+ const bounds = firstChild.getBounds();
24898
+ return {
24899
+ width: bounds.width,
24900
+ height: bounds.height
24901
+ };
24902
+ })();
24903
+ const x = firstChild.x;
24904
+ const y = firstChild.y;
24905
+ blocker.setPosition(x, y);
24906
+ const hitArea = new Phaser.Geom.Rectangle(0, 0, width, height);
24907
+ gestureManager.registerContainer(blocker, {
24908
+ onTouch: (e) => {
24909
+ e.stopPropagation();
24910
+ },
24911
+ onTouchMove: (e) => {
24912
+ e.stopPropagation();
24913
+ }
24914
+ }, hitArea);
24915
+ });
24916
+ }
24917
+ return () => {
24918
+ if (blockEvents && blockerContainer) gestureManager.unregisterContainer(blockerContainer);
24919
+ portalRegistry.unregister(portalId);
24920
+ };
24921
+ }, [
24922
+ portalId,
24923
+ depth,
24924
+ scene,
24925
+ blockEvents
24926
+ ]);
24927
+ useEffect(() => {
24928
+ const portal = portalRegistry.get(portalId);
24929
+ if (!portal) return;
24930
+ const portalContainer = portal.container;
24931
+ const newChildren = normalizeChildren(props.children);
24932
+ const oldChildren = previousChildrenRef.current;
24933
+ const maxLen = Math.max(oldChildren.length, newChildren.length);
24934
+ for (let i = 0; i < maxLen; i++) {
24935
+ const oldChild = oldChildren[i];
24936
+ const newChild = newChildren[i];
24937
+ if (oldChild && newChild) patchVNode(portalContainer, oldChild, newChild);
24938
+ else if (!oldChild && newChild) {
24939
+ const mountedNode = mount(portalContainer, newChild);
24940
+ if (mountedNode) {
24941
+ portalContainer.add(mountedNode);
24942
+ mountedNodesRef.current.push(mountedNode);
24943
+ }
24944
+ } else if (oldChild && !newChild) unmount(oldChild);
24945
+ }
24946
+ previousChildrenRef.current = newChildren;
24947
+ }, [props.children, portalId]);
24948
+ return null;
24949
+ }
24950
+ //#endregion
24951
+ //#region src/components/custom/Popover.tsx
24952
+ function getMainPlacement(placement) {
24953
+ return placement.split("-")[0];
24954
+ }
24955
+ function getCrossPlacement(placement) {
24956
+ return placement.split("-")[1] ?? "center";
24957
+ }
24958
+ function calculateOverlayPosition(options) {
24959
+ const { anchor, content, placement, offset } = options;
24960
+ const main = getMainPlacement(placement);
24961
+ const cross = getCrossPlacement(placement);
24962
+ let x;
24963
+ let y;
24964
+ if (main === "top" || main === "bottom") {
24965
+ y = main === "top" ? anchor.y - content.height - offset : anchor.y + anchor.height + offset;
24966
+ if (cross === "start") x = anchor.x;
24967
+ else if (cross === "end") x = anchor.x + anchor.width - content.width;
24968
+ else x = anchor.x + (anchor.width - content.width) / 2;
24969
+ } else {
24970
+ x = main === "left" ? anchor.x - content.width - offset : anchor.x + anchor.width + offset;
24971
+ if (cross === "start") y = anchor.y;
24972
+ else if (cross === "end") y = anchor.y + anchor.height - content.height;
24973
+ else y = anchor.y + (anchor.height - content.height) / 2;
24974
+ }
24975
+ const viewport = options.viewport;
24976
+ if (viewport) {
24977
+ const padding = options.viewportPadding ?? 8;
24978
+ x = Math.min(Math.max(padding, x), Math.max(padding, viewport.width - content.width - padding));
24979
+ y = Math.min(Math.max(padding, y), Math.max(padding, viewport.height - content.height - padding));
24980
+ }
24981
+ return {
24982
+ x,
24983
+ y,
24984
+ placement
24985
+ };
24986
+ }
24987
+ function getLayoutSize(container) {
24988
+ const withLayout = container;
24989
+ return withLayout?.__getLayoutSize?.() ?? withLayout?.__cachedLayoutSize ?? {
24990
+ width: 0,
24991
+ height: 0
24992
+ };
24993
+ }
24994
+ function getWorldPosition(container) {
24995
+ const matrix = container.getWorldTransformMatrix?.();
24996
+ if (matrix) return {
24997
+ x: matrix.tx,
24998
+ y: matrix.ty
24999
+ };
25000
+ return {
25001
+ x: container.x ?? 0,
25002
+ y: container.y ?? 0
25003
+ };
25004
+ }
25005
+ function getAnchorRect(container) {
25006
+ if (!container) return {
25007
+ x: 0,
25008
+ y: 0,
25009
+ width: 0,
25010
+ height: 0
25011
+ };
25012
+ const size = getLayoutSize(container);
25013
+ const position = getWorldPosition(container);
25014
+ return {
25015
+ x: position.x,
25016
+ y: position.y,
25017
+ width: size.width,
25018
+ height: size.height
25019
+ };
25020
+ }
25021
+ var FALLBACK_CONTENT_SIZE = {
25022
+ width: 220,
25023
+ height: 120
25024
+ };
25025
+ function assignRef(ref, value) {
25026
+ if (!ref) return;
25027
+ if (typeof ref === "function") {
25028
+ ref(value);
25029
+ return;
25030
+ }
25031
+ ref.current = value;
25032
+ }
25033
+ function Popover(props) {
25034
+ const { props: themed, nestedTheme } = getThemedProps("Popover", useTheme(), props.theme ?? {});
25035
+ const scene = useScene();
25036
+ const triggerRef = useRef(null);
25037
+ const contentRef = useRef(null);
25038
+ const [measuredContentSize, setMeasuredContentSize] = useState(null);
25039
+ const [internalOpen, setInternalOpen] = useState(props.defaultOpen ?? false);
25040
+ const isControlled = props.isOpen !== void 0;
25041
+ const isOpen = isControlled ? props.isOpen === true : internalOpen;
25042
+ const placement = props.placement ?? themed.placement ?? "bottom";
25043
+ const offset = props.offset ?? themed.offset ?? 8;
25044
+ const depth = props.depth ?? themed.depth ?? 1100;
25045
+ const closeOnOutside = props.closeOnOutside ?? themed.closeOnOutside ?? true;
25046
+ const closeOnEscape = props.closeOnEscape ?? themed.closeOnEscape ?? true;
25047
+ const viewportPadding = props.viewportPadding ?? themed.viewportPadding ?? 8;
25048
+ const explicitContentWidth = props.contentWidth ?? themed.contentWidth;
25049
+ const explicitContentHeight = props.contentHeight ?? themed.contentHeight;
25050
+ const viewport = portalRegistry.getViewportSize(scene);
25051
+ const anchor = getAnchorRect(triggerRef.current);
25052
+ const measuredWidth = measuredContentSize?.width ?? FALLBACK_CONTENT_SIZE.width;
25053
+ const measuredHeight = measuredContentSize?.height ?? FALLBACK_CONTENT_SIZE.height;
25054
+ const isPositionReady = !(explicitContentWidth === void 0 || explicitContentHeight === void 0) || measuredContentSize !== null;
25055
+ const contentWidth = props.matchTriggerWidth ? Math.max(anchor.width, explicitContentWidth ?? measuredWidth) : explicitContentWidth ?? measuredWidth;
25056
+ const overlayPosition = calculateOverlayPosition({
25057
+ anchor,
25058
+ content: {
25059
+ width: contentWidth,
25060
+ height: explicitContentHeight ?? measuredHeight
25061
+ },
25062
+ placement,
25063
+ offset,
25064
+ viewport,
25065
+ viewportPadding
25066
+ });
25067
+ const setOpen = (open) => {
25068
+ if (props.disabled && open) return;
25069
+ if (!isControlled) setInternalOpen(open);
25070
+ props.onOpenChange?.(open);
25071
+ };
25072
+ const toggleOpen = (event) => {
25073
+ event.stopPropagation();
25074
+ setOpen(!isOpen);
25075
+ };
25076
+ const close = (event) => {
25077
+ event?.stopPropagation();
25078
+ setOpen(false);
25079
+ };
25080
+ const contentProps = props.contentProps ?? {};
25081
+ const contentPropsRef = contentProps.ref;
25082
+ const contentPropsAlpha = contentProps.alpha;
25083
+ const handleContentRef = (container) => {
25084
+ contentRef.current = container;
25085
+ assignRef(contentPropsRef, container);
25086
+ };
25087
+ useEffect(() => {
25088
+ if (!closeOnEscape || !isOpen) return;
25089
+ const handleKeyDown = (event) => {
25090
+ if (event.key === "Escape") setOpen(false);
25091
+ };
25092
+ window.addEventListener("keydown", handleKeyDown);
25093
+ return () => window.removeEventListener("keydown", handleKeyDown);
25094
+ }, [closeOnEscape, isOpen]);
25095
+ useEffect(() => {
25096
+ if (!isOpen) return;
25097
+ DeferredLayoutQueue.defer(() => {
25098
+ const size = getLayoutSize(contentRef.current);
25099
+ if (size.width <= 0 || size.height <= 0) return;
25100
+ setMeasuredContentSize((current) => {
25101
+ if (current?.width === size.width && current?.height === size.height) return current;
25102
+ return {
25103
+ width: size.width,
25104
+ height: size.height
25105
+ };
25106
+ });
25107
+ });
25108
+ }, [
25109
+ isOpen,
25110
+ props.children,
25111
+ explicitContentWidth,
25112
+ explicitContentHeight
25113
+ ]);
25114
+ return /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx(View, {
25115
+ ...props.triggerProps ?? {},
25116
+ ref: triggerRef,
25117
+ enableGestures: !props.disabled,
25118
+ onTouch: toggleOpen,
25119
+ children: props.trigger
25120
+ }), isOpen && /* @__PURE__ */ jsxs(Portal, {
25121
+ depth,
25122
+ blockEvents: false,
25123
+ children: [closeOnOutside && /* @__PURE__ */ jsx(View, {
25124
+ width: viewport.width,
25125
+ height: viewport.height,
25126
+ backgroundColor: 0,
25127
+ backgroundAlpha: 0,
25128
+ onTouch: close,
25129
+ onTouchMove: (event) => event.stopPropagation()
25130
+ }), /* @__PURE__ */ jsx(View, {
25131
+ ...contentProps,
25132
+ ref: handleContentRef,
25133
+ x: overlayPosition.x,
25134
+ y: overlayPosition.y,
25135
+ ...props.matchTriggerWidth || explicitContentWidth !== void 0 ? { width: contentWidth } : {},
25136
+ direction: "column",
25137
+ backgroundColor: themed.backgroundColor ?? 1120295,
25138
+ borderColor: themed.borderColor ?? 3359061,
25139
+ borderWidth: themed.borderWidth ?? 1,
25140
+ cornerRadius: themed.cornerRadius ?? 8,
25141
+ padding: themed.padding ?? 10,
25142
+ gap: themed.gap ?? 8,
25143
+ ...isPositionReady ? contentPropsAlpha !== void 0 ? { alpha: contentPropsAlpha } : {} : { alpha: 0 },
25144
+ onTouch: (event) => event.stopPropagation(),
25145
+ theme: nestedTheme,
25146
+ children: props.children
25147
+ })]
25148
+ })] });
25149
+ }
25150
+ function ContextMenu(props) {
25151
+ const { items, width: explicitWidth, onSelect, isOpen: explicitOpen, defaultOpen, onOpenChange, ...popoverProps } = props;
25152
+ const { props: themed, nestedTheme } = getThemedProps("ContextMenu", useTheme(), props.theme ?? {});
25153
+ const [internalOpen, setInternalOpen] = useState(defaultOpen ?? false);
25154
+ const isControlled = explicitOpen !== void 0;
25155
+ const isOpen = isControlled ? explicitOpen === true : internalOpen;
25156
+ const width = explicitWidth ?? themed.width ?? 220;
25157
+ const itemHeight = themed.itemHeight ?? 34;
25158
+ const setOpen = (open) => {
25159
+ if (!isControlled) setInternalOpen(open);
25160
+ onOpenChange?.(open);
25161
+ };
25162
+ const handleSelect = (item) => {
25163
+ if (item.disabled) return;
25164
+ item.onSelect?.();
25165
+ onSelect?.(item);
25166
+ setOpen(false);
25167
+ };
25168
+ return /* @__PURE__ */ jsx(Popover, {
25169
+ ...popoverProps,
25170
+ isOpen,
25171
+ onOpenChange: setOpen,
25172
+ contentWidth: width,
25173
+ contentHeight: Math.max(1, items.length) * itemHeight + 20,
25174
+ contentProps: {
25175
+ padding: themed.padding ?? 6,
25176
+ gap: themed.gap ?? 2,
25177
+ backgroundColor: themed.backgroundColor,
25178
+ borderColor: themed.borderColor,
25179
+ borderWidth: themed.borderWidth,
25180
+ cornerRadius: themed.cornerRadius,
25181
+ theme: nestedTheme
25182
+ },
25183
+ children: items.map((item) => {
25184
+ const textColor = item.disabled ? themed.disabledTextColor ?? "#64748b" : item.danger ? themed.dangerTextColor ?? "#fecaca" : themed.textStyle?.color ?? "#f8fafc";
25185
+ return /* @__PURE__ */ jsxs(View, {
25186
+ width: "fill",
25187
+ height: itemHeight,
25188
+ direction: "row",
25189
+ alignItems: "center",
25190
+ gap: themed.itemGap ?? 8,
25191
+ padding: themed.itemPadding ?? {
25192
+ left: 10,
25193
+ right: 10,
25194
+ top: 6,
25195
+ bottom: 6
25196
+ },
25197
+ cornerRadius: themed.itemCornerRadius ?? 5,
25198
+ backgroundColor: item.danger ? themed.dangerBackgroundColor ?? 2042167 : 0,
25199
+ backgroundAlpha: item.danger ? .35 : 0,
25200
+ enableGestures: !item.disabled,
25201
+ onTouch: (event) => {
25202
+ event.stopPropagation();
25203
+ handleSelect(item);
25204
+ },
25205
+ children: [
25206
+ item.prefix,
25207
+ /* @__PURE__ */ jsx(View, {
25208
+ flex: 1,
25209
+ children: /* @__PURE__ */ jsx(Text, {
25210
+ text: item.label,
25211
+ style: {
25212
+ ...themed.textStyle ?? {},
25213
+ color: textColor
25214
+ }
25215
+ })
25216
+ }),
25217
+ item.suffix
25218
+ ]
25219
+ }, item.id);
25220
+ })
25221
+ });
25222
+ }
25223
+ //#endregion
25224
+ //#region src/components/custom/ProgressBar.tsx
25225
+ /** @jsxImportSource ../.. */
25226
+ /**
25227
+ * ProgressBar component - determinate progress indicator for health, loading, cooldowns, and XP.
25228
+ */
25229
+ function clampProgressValue(value, min, max) {
25230
+ if (!Number.isFinite(value)) return min;
25231
+ return Math.min(Math.max(value, min), max);
25232
+ }
25233
+ function getProgressRatio(value, min, max) {
25234
+ if (!Number.isFinite(min) || !Number.isFinite(max) || min === max) return 0;
25235
+ const normalizedMin = Math.min(min, max);
25236
+ const normalizedMax = Math.max(min, max);
25237
+ return (clampProgressValue(value, normalizedMin, normalizedMax) - normalizedMin) / (normalizedMax - normalizedMin);
25238
+ }
25239
+ function formatDefaultValue(props) {
25240
+ return `${Math.round(props.percent)}%`;
25241
+ }
25242
+ function ProgressBar(props) {
25243
+ const { value, min = 0, max = 100, orientation: explicitOrientation, label, showValue, labelPosition: explicitLabelPosition, formatValue, trackColor: explicitTrackColor, fillColor: explicitFillColor, borderColor: explicitBorderColor, borderWidth: explicitBorderWidth, cornerRadius: explicitCornerRadius, labelStyle: explicitLabelStyle, disabled = false, disabledAlpha: explicitDisabledAlpha, theme, width, height, alpha, ...viewProps } = props;
25244
+ const { props: themed, nestedTheme } = getThemedProps("ProgressBar", useTheme(), theme ?? {});
25245
+ const orientation = explicitOrientation ?? themed.orientation ?? "horizontal";
25246
+ const ratio = getProgressRatio(value, min, max);
25247
+ const percent = ratio * 100;
25248
+ const labelPosition = explicitLabelPosition ?? themed.labelPosition ?? (showValue || label ? "right" : "none");
25249
+ const shouldShowText = labelPosition !== "none" && Boolean(showValue || label);
25250
+ const text = shouldShowText ? [label, showValue ? (formatValue ?? themed.formatValue ?? formatDefaultValue)({
25251
+ value,
25252
+ min,
25253
+ max,
25254
+ ratio,
25255
+ percent
25256
+ }) : void 0].filter(Boolean).join(" ") : "";
25257
+ const resolvedWidth = width ?? themed.width ?? (orientation === "horizontal" ? 240 : 24);
25258
+ const resolvedHeight = height ?? themed.height ?? (orientation === "horizontal" ? 22 : 160);
25259
+ const trackColor = explicitTrackColor ?? themed.trackColor ?? 2042167;
25260
+ const fillColor = explicitFillColor ?? themed.fillColor ?? 2278750;
25261
+ const borderColor = explicitBorderColor ?? themed.borderColor ?? 3359061;
25262
+ const borderWidth = explicitBorderWidth ?? themed.borderWidth ?? 1;
25263
+ const cornerRadius = explicitCornerRadius ?? themed.cornerRadius ?? (orientation === "horizontal" ? 11 : 8);
25264
+ const labelStyle = explicitLabelStyle ?? themed.labelStyle ?? {
25265
+ color: "#ffffff",
25266
+ fontSize: "12px"
25267
+ };
25268
+ const disabledAlpha = explicitDisabledAlpha ?? themed.disabledAlpha ?? .5;
25269
+ const effectiveAlpha = disabled ? disabledAlpha : alpha;
25270
+ const rootDirection = labelPosition === "left" || labelPosition === "right" ? "row" : labelPosition === "top" || labelPosition === "bottom" ? "column" : "column";
25271
+ const labelNode = shouldShowText ? /* @__PURE__ */ jsx(Text, {
25272
+ text,
25273
+ style: labelStyle
25274
+ }) : null;
25275
+ const fillProps = orientation === "horizontal" ? {
25276
+ width: `${percent}%`,
25277
+ height: "fill"
25278
+ } : {
25279
+ width: "fill",
25280
+ height: `${percent}%`
25281
+ };
25282
+ const track = /* @__PURE__ */ jsxs(View, {
25283
+ width: resolvedWidth,
25284
+ height: resolvedHeight,
25285
+ direction: orientation === "horizontal" ? "stack" : "column",
25286
+ justifyContent: orientation === "vertical" ? "end" : "start",
25287
+ backgroundColor: trackColor,
25288
+ borderColor,
25289
+ borderWidth,
25290
+ cornerRadius,
25291
+ overflow: "hidden",
25292
+ theme: nestedTheme,
25293
+ children: [/* @__PURE__ */ jsx(View, {
25294
+ ...fillProps,
25295
+ backgroundColor: fillColor,
25296
+ cornerRadius
25297
+ }), labelPosition === "inside" && shouldShowText && /* @__PURE__ */ jsx(View, {
25298
+ width: "fill",
25299
+ height: "fill",
25300
+ justifyContent: "center",
25301
+ alignItems: "center",
25302
+ children: labelNode
25303
+ })]
25304
+ });
25305
+ return /* @__PURE__ */ jsxs(View, {
25306
+ ...viewProps,
25307
+ direction: rootDirection,
25308
+ alignItems: "center",
25309
+ gap: themed.gap ?? 8,
25310
+ ...effectiveAlpha !== void 0 ? { alpha: effectiveAlpha } : {},
25311
+ theme: nestedTheme,
25312
+ children: [
25313
+ labelPosition === "top" || labelPosition === "left" ? labelNode : null,
25314
+ track,
25315
+ labelPosition !== "inside" && (labelPosition === "bottom" || labelPosition === "right") ? labelNode : null
25316
+ ]
25317
+ });
25318
+ }
25319
+ //#endregion
23968
25320
  //#region src/components/index.ts
23969
25321
  /**
23970
25322
  * Built-in component implementations
@@ -23978,7 +25330,6 @@ function Particles(props) {
23978
25330
  /**
23979
25331
  * Registers all built-in components with the host
23980
25332
  * This should be called during library initialization
23981
- * Note: TileSprite is currently dummy (throws on use)
23982
25333
  */
23983
25334
  function registerBuiltins() {
23984
25335
  register("view", {
@@ -24051,7 +25402,7 @@ function registerBuiltins() {
24051
25402
  /**
24052
25403
  * Preprocesses SVG string to ensure tinting works correctly
24053
25404
  * Replaces fill/stroke="currentColor" and other colors with white (#FFFFFF)
24054
- * This allows Phaser's tint to work multiplicatively (white × tint = tint color)
25405
+ * This allows Phaser's tint to work by multiplication (white × tint = tint color)
24055
25406
  * @param svg - Raw SVG string
24056
25407
  * @returns Preprocessed SVG string with white fills/strokes
24057
25408
  */
@@ -25113,132 +26464,6 @@ function Accordion(props) {
25113
26464
  }, props.key);
25114
26465
  }
25115
26466
  //#endregion
25116
- //#region src/components/custom/Portal.tsx
25117
- /** @jsxImportSource ../.. */
25118
- /**
25119
- * Portal component - renders children into a separate tree at specified depth
25120
- * Enables overlays, modals, tooltips without affecting parent tree layout
25121
- */
25122
- /**
25123
- * Portal component
25124
- * Renders child VNode into a separate container tree at specified depth.
25125
- * Automatically injects event blockers to prevent click-through and scrolling.
25126
- *
25127
- * @example
25128
- * ```tsx
25129
- * // Basic portal (automatically blocks events in content area)
25130
- * <Portal depth={1000}>
25131
- * <View>Overlay content</View>
25132
- * </Portal>
25133
- *
25134
- * // Non-blocking portal (allows click-through)
25135
- * <Portal depth={500} blockEvents={false}>
25136
- * <View>Info overlay - clickable background</View>
25137
- * </Portal>
25138
- *
25139
- * // Portal with custom event handling (original handlers are preserved)
25140
- * <Portal depth={1000}>
25141
- * <View onTouch={(e) => console.log('clicked')}>
25142
- * Content
25143
- * </View>
25144
- * </Portal>
25145
- * ```
25146
- */
25147
- function Portal(props) {
25148
- const portalId = useMemo(() => props.id ?? portalRegistry.generateId(), [props.id]);
25149
- const depth = props.depth ?? 1e3;
25150
- const scene = useScene();
25151
- const blockEvents = props.blockEvents ?? true;
25152
- const mountedNodesRef = useRef([]);
25153
- const previousChildrenRef = useRef([]);
25154
- const normalizeChildren = (children) => {
25155
- if (!children) return [];
25156
- return (Array.isArray(children) ? children.flat(Infinity) : [children]).filter((child) => !!child && typeof child === "object" && "type" in child);
25157
- };
25158
- useEffect(() => {
25159
- const portalContainer = portalRegistry.register(portalId, depth, scene, {
25160
- type: "View",
25161
- props: {},
25162
- children: []
25163
- }, scene.add.container(0, 0));
25164
- let blockerContainer = null;
25165
- if (blockEvents) {
25166
- blockerContainer = scene.add.container(0, 0);
25167
- portalContainer.add(blockerContainer);
25168
- blockerContainer.setDepth(-1);
25169
- }
25170
- const children = normalizeChildren(props.children);
25171
- const mountedNodes = [];
25172
- for (const child of children) if (child) {
25173
- const mountedNode = mount(portalContainer, child);
25174
- if (mountedNode) {
25175
- portalContainer.add(mountedNode);
25176
- mountedNodes.push(mountedNode);
25177
- }
25178
- }
25179
- mountedNodesRef.current = mountedNodes;
25180
- previousChildrenRef.current = children;
25181
- const gestureManager = getGestureManager(scene);
25182
- if (blockEvents && blockerContainer) {
25183
- const blocker = blockerContainer;
25184
- DeferredLayoutQueue.defer(() => {
25185
- const firstChild = portalContainer.getAt(1);
25186
- if (!firstChild) return;
25187
- const { width, height } = firstChild.__cachedLayoutSize ? firstChild.__cachedLayoutSize : firstChild.__getLayoutSize ? firstChild.__getLayoutSize() : (() => {
25188
- const bounds = firstChild.getBounds();
25189
- return {
25190
- width: bounds.width,
25191
- height: bounds.height
25192
- };
25193
- })();
25194
- const x = firstChild.x;
25195
- const y = firstChild.y;
25196
- blocker.setPosition(x, y);
25197
- const hitArea = new Phaser.Geom.Rectangle(0, 0, width, height);
25198
- gestureManager.registerContainer(blocker, {
25199
- onTouch: (e) => {
25200
- e.stopPropagation();
25201
- },
25202
- onTouchMove: (e) => {
25203
- e.stopPropagation();
25204
- }
25205
- }, hitArea);
25206
- });
25207
- }
25208
- return () => {
25209
- if (blockEvents && blockerContainer) gestureManager.unregisterContainer(blockerContainer);
25210
- portalRegistry.unregister(portalId);
25211
- };
25212
- }, [
25213
- portalId,
25214
- depth,
25215
- scene,
25216
- blockEvents
25217
- ]);
25218
- useEffect(() => {
25219
- const portal = portalRegistry.get(portalId);
25220
- if (!portal) return;
25221
- const portalContainer = portal.container;
25222
- const newChildren = normalizeChildren(props.children);
25223
- const oldChildren = previousChildrenRef.current;
25224
- const maxLen = Math.max(oldChildren.length, newChildren.length);
25225
- for (let i = 0; i < maxLen; i++) {
25226
- const oldChild = oldChildren[i];
25227
- const newChild = newChildren[i];
25228
- if (oldChild && newChild) patchVNode(portalContainer, oldChild, newChild);
25229
- else if (!oldChild && newChild) {
25230
- const mountedNode = mount(portalContainer, newChild);
25231
- if (mountedNode) {
25232
- portalContainer.add(mountedNode);
25233
- mountedNodesRef.current.push(mountedNode);
25234
- }
25235
- } else if (oldChild && !newChild) unmount(oldChild);
25236
- }
25237
- previousChildrenRef.current = newChildren;
25238
- }, [props.children, portalId]);
25239
- return null;
25240
- }
25241
- //#endregion
25242
26467
  //#region src/components/custom/Modal.tsx
25243
26468
  /** @jsxImportSource ../.. */
25244
26469
  /**
@@ -27996,7 +29221,7 @@ function Joystick(props) {
27996
29221
  y: 0
27997
29222
  });
27998
29223
  useLayoutEffect(() => {
27999
- const size = getLayoutSize(outerRef.current);
29224
+ const size = getLayoutSize$1(outerRef.current);
28000
29225
  if (size != null) {
28001
29226
  const newCenter = {
28002
29227
  x: size.width / 2,
@@ -29087,7 +30312,6 @@ function Toggle(props) {
29087
30312
  setIsAnimating(true);
29088
30313
  const endX = newChecked ? thumbOffsetOn : thumbOffsetOff;
29089
30314
  const startX = thumbX;
29090
- console.log("Duration:", duration.current);
29091
30315
  scene.tweens.addCounter({
29092
30316
  from: 0,
29093
30317
  to: 1,
@@ -29254,6 +30478,6 @@ function TransformOriginView({ originX = .5, originY = .5, width, height, x = 0,
29254
30478
  });
29255
30479
  }
29256
30480
  //#endregion
29257
- export { RadioButton as $, textCreator as $n, shouldComponentUpdate as $t, computed as A, midnightPreset as An, createTheme as At, DOMInputElement as B, hexToNumber as Bn, remountAll as Bt, CharText as C, defaultTextStyleTokens as Cn, graphicsCreator as Cr, createWiggleEffect as Ct, Modal as D, generateColorScale as Dn, register as Dr, useGameObjectEffect as Dt, Dialog as E, forestGreenPreset as En, nodeRegistry as Er, createZoomOutEffect as Et, SpringPhysics as F, darken as Fn, getMountStats as Ft, useSVGTextures as G, rgbToHsl as Gn, disposeCtx as Gt, releaseSVGTexture as H, lightenHex as Hn, unmountJSX as Ht, animatedSignal as I, darkenHex as In, mount as It, Particles as J, normalizeCornerRadius as Jn, getLayoutProps as Jt, svgToTexture as K, rgbToNumber as Kn, getBackgroundGraphics as Kt, isAnimatedSignal as L, ensureContrast as Ln, mountJSX as Lt, useSprings as M, presets as Mn, mergeThemes as Mt, DEFAULT_SPRING_CONFIG as N, alpha as Nn, themeRegistry as Nt, Portal as O, getPreset as On, viewCreator as Ot, SPRING_PRESETS as P, createTextStyle as Pn, createElement as Pt, RadioGroup as Q, tileSpritePatcher as Qn, shallowEqual as Qt, unwrapSignal as R, getContrastRatio as Rn, normalizeVNodeLike as Rt, CharTextInput as S, defaultSpacingTokens as Sn, imagePatcher as Sr, createTadaEffect as St, WrapText as T, applyLightMode as Tn, host as Tr, createZoomInEffect as Tt, releaseSVGTextures as U, numberToHex as Un, portalRegistry as Ut, releaseAllSVGTextures as V, lighten as Vn, unmount as Vt, useSVGTexture as W, numberToRgb as Wn, View as Wt, Text as X, normalizeGap as Xn, getLayoutSize as Xt, TileSprite as Y, normalizeEdgeInsets as Yn, getLayoutRect as Yt, Sprite as Z, tileSpriteCreator as Zn, getWorldLayoutRect as Zt, Dropdown as _, createDefaultTheme as _n, buildEmitZone as _r, createShakeEffect as _t, Tabs as a, useLayoutRect as an, spriteCreator as ar, resolveEffect as at, calculateSliderSize as b, defaultRadiusTokens as bn, nineSlicePatcher as br, createSpinEffect as bt, Sidebar as c, useRedraw as cn, particlesPatcher as cr, createFadeEffect as ct, NineSlice as d, useState as dn, applyEmitterConfig as dr, createFlipOutEffect as dt, useBackgroundGraphics as en, textPatcher as er, Graphics as et, Joystick as f, useTheme as fn, getFirstEmitter as fr, createFloatEffect as ft, Image$1 as g, getRenderContext as gn, buildDeathZonesFromLayout as gr, createPulseEffect as gt, useIconPreload as h, withHooks as hn, resolveParticlePreset as hr, createPressEffect as ht, TabPanel as i, useLayoutEffect as in, DevPresets as ir, applyEffectByName as it, useSpring as j, oceanBluePreset as jn, getThemedProps as jt, Accordion as k, getPresetWithMode as kn, viewPatcher as kt, RefOriginView as l, useRef as ln, applyDeathZone as lr, createFlashEffect as lt, createIconComponent as m, useWorldLayoutRect as mn, PARTICLE_PRESET_REGISTRY as mr, createNoneEffect as mt, Toggle as n, useEffect as nn, DebugLogger as nr, DEFAULT_EFFECT as nt, RangeSlider as o, useLayoutSize as on, spritePatcher as or, createBounceEffect as ot, Icon as p, useViewportSize as pn, isParticleEmitter as pr, createJelloEffect as pt, registerBuiltins as q, HexColor as qn, getCurrent as qt, Tab as r, useForceRedraw as rn, DevConfig as rr, EFFECT_REGISTRY as rt, Slider as s, useMemo as sn, particlesCreator as sr, createBreatheEffect as st, TransformOriginView as t, useCallback as tn, viewportRegistry as tr, Button as tt, NineSliceButton as u, useScene as un, applyEmitZone as ur, createFlipInEffect as ut, ScrollView as v, defaultTheme as vn, buildEmitZoneFromLayout as vr, createSlideInEffect as vt, AlertDialog as w, applyDarkMode as wn, graphicsPatcher as wr, createWobbleEffect as wt, Divider as x, defaultSizeTokens as xn, imageCreator as xr, createSwingEffect as xt, ScrollSlider as y, createTextStyleTokens as yn, nineSliceCreator as yr, createSlideOutEffect as yt, KeyboardInputManager as z, hex as zn, patchVNode as zt };
30481
+ export { Portal as $, getContrastRatio as $n, normalizeVNodeLike as $t, useSpring as A, withHooks as An, resolveParticlePreset as Ar, createSwingEffect as At, releaseAllSVGTextures as B, applyLightMode as Bn, host as Br, getBadgeSizeConfig as Bt, CharText as C, useRedraw as Cn, particlesPatcher as Cr, createNoneEffect as Ct, Modal as D, useTheme as Dn, getFirstEmitter as Dr, createSlideInEffect as Dt, Dialog as E, useState as En, applyEmitterConfig as Er, createShakeEffect as Et, animatedSignal as F, defaultRadiusTokens as Fn, nineSlicePatcher as Fr, createZoomOutEffect as Ft, svgToTexture as G, midnightPreset as Gn, createTheme as Gt, releaseSVGTextures as H, generateColorScale as Hn, register as Hr, resolveBadgeTextStyle as Ht, isAnimatedSignal as I, defaultSizeTokens as In, imageCreator as Ir, useGameObjectEffect as It, clampProgressValue as J, alpha as Jn, themeRegistry as Jt, registerBuiltins as K, oceanBluePreset as Kn, getThemedProps as Kt, unwrapSignal as L, defaultSpacingTokens as Ln, imagePatcher as Lr, Badge as Lt, DEFAULT_SPRING_CONFIG as M, createDefaultTheme as Mn, buildEmitZone as Mr, createWiggleEffect as Mt, SPRING_PRESETS as N, defaultTheme as Nn, buildEmitZoneFromLayout as Nr, createWobbleEffect as Nt, Accordion as O, useViewportSize as On, isParticleEmitter as Or, createSlideOutEffect as Ot, SpringPhysics as P, createTextStyleTokens as Pn, nineSliceCreator as Pr, createZoomInEffect as Pt, calculateOverlayPosition as Q, ensureContrast as Qn, mountJSX as Qt, KeyboardInputManager as R, defaultTextStyleTokens as Rn, graphicsCreator as Rr, Tag as Rt, CharTextInput as S, useMemo as Sn, particlesCreator as Sr, createJelloEffect as St, WrapText as T, useScene as Tn, applyEmitZone as Tr, createPulseEffect as Tt, useSVGTexture as U, getPreset as Un, viewCreator as Ut, releaseSVGTexture as V, forestGreenPreset as Vn, nodeRegistry as Vr, getBadgeText as Vt, useSVGTextures as W, getPresetWithMode as Wn, viewPatcher as Wt, ContextMenu as X, darken as Xn, getMountStats as Xt, getProgressRatio as Y, createTextStyle as Yn, createElement as Yt, Popover as Z, darkenHex as Zn, mount as Zt, Dropdown as _, useEffect as _n, DebugLogger as _r, createFadeEffect as _t, Tabs as a, View as an, numberToRgb as ar, RadioButton as at, calculateSliderSize as b, useLayoutRect as bn, spriteCreator as br, createFlipOutEffect as bt, Sidebar as c, getCurrent as cn, HexColor as cr, useThemeTokens as ct, NineSlice as d, getLayoutSize$1 as dn, normalizeGap as dr, DEFAULT_EFFECT as dt, patchVNode as en, hex as er, Particles as et, Joystick as f, getWorldLayoutRect as fn, tileSpriteCreator as fr, EFFECT_REGISTRY as ft, Image$1 as g, useCallback as gn, viewportRegistry as gr, createBreatheEffect as gt, useIconPreload as h, useBackgroundGraphics as hn, textPatcher as hr, createBounceEffect as ht, TabPanel as i, portalRegistry as in, numberToHex as ir, RadioGroup as it, useSprings as j, getRenderContext as jn, buildDeathZonesFromLayout as jr, createTadaEffect as jt, computed as k, useWorldLayoutRect as kn, PARTICLE_PRESET_REGISTRY as kr, createSpinEffect as kt, RefOriginView as l, getLayoutProps as ln, normalizeCornerRadius as lr, Checkbox as lt, createIconComponent as m, shouldComponentUpdate as mn, textCreator as mr, resolveEffect as mt, Toggle as n, unmount as nn, lighten as nr, Text as nt, RangeSlider as o, disposeCtx as on, rgbToHsl as or, Graphics as ot, Icon as p, shallowEqual as pn, tileSpritePatcher as pr, applyEffectByName as pt, ProgressBar as q, presets as qn, mergeThemes as qt, Tab as r, unmountJSX as rn, lightenHex as rr, Sprite as rt, Slider as s, getBackgroundGraphics as sn, rgbToNumber as sr, DebugPanel as st, TransformOriginView as t, remountAll as tn, hexToNumber as tr, TileSprite as tt, NineSliceButton as u, getLayoutRect as un, normalizeEdgeInsets as ur, Button as ut, ScrollView as v, useForceRedraw as vn, DevConfig as vr, createFlashEffect as vt, AlertDialog as w, useRef as wn, applyDeathZone as wr, createPressEffect as wt, Divider as x, useLayoutSize as xn, spritePatcher as xr, createFloatEffect as xt, ScrollSlider as y, useLayoutEffect as yn, DevPresets as yr, createFlipInEffect as yt, DOMInputElement as z, applyDarkMode as zn, graphicsPatcher as zr, formatBadgeCount as zt };
29258
30482
 
29259
- //# sourceMappingURL=custom-C_w8D39m.js.map
30483
+ //# sourceMappingURL=custom-DMZASXll.js.map