@number10/phaserjsx 0.3.1 → 0.4.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 (137) hide show
  1. package/dist/{TransformOriginView-KcTgaYRi.cjs → TransformOriginView-Bx81YEUU.cjs} +1077 -1500
  2. package/dist/TransformOriginView-Bx81YEUU.cjs.map +1 -0
  3. package/dist/{TransformOriginView-CzVjS16F.js → TransformOriginView-DCvId72M.js} +1200 -1623
  4. package/dist/TransformOriginView-DCvId72M.js.map +1 -0
  5. package/dist/camera/camera-fx-registry.d.ts +47 -0
  6. package/dist/camera/camera-fx-registry.d.ts.map +1 -0
  7. package/dist/camera/index.d.ts +6 -0
  8. package/dist/camera/index.d.ts.map +1 -0
  9. package/dist/camera/use-camera-fx.d.ts +59 -0
  10. package/dist/camera/use-camera-fx.d.ts.map +1 -0
  11. package/dist/components/appliers/applyBackground.d.ts +4 -0
  12. package/dist/components/appliers/applyBackground.d.ts.map +1 -1
  13. package/dist/components/appliers/applyParticles.d.ts +7 -0
  14. package/dist/components/appliers/applyParticles.d.ts.map +1 -0
  15. package/dist/components/appliers/applyParticlesLayout.d.ts +11 -0
  16. package/dist/components/appliers/applyParticlesLayout.d.ts.map +1 -0
  17. package/dist/components/creators/createParticlesLayout.d.ts +14 -0
  18. package/dist/components/creators/createParticlesLayout.d.ts.map +1 -0
  19. package/dist/components/custom/Accordion.d.ts +3 -2
  20. package/dist/components/custom/Accordion.d.ts.map +1 -1
  21. package/dist/components/custom/AlertDialog.d.ts +2 -1
  22. package/dist/components/custom/AlertDialog.d.ts.map +1 -1
  23. package/dist/components/custom/Button.d.ts +2 -1
  24. package/dist/components/custom/Button.d.ts.map +1 -1
  25. package/dist/components/custom/CharText/CharText.d.ts +2 -1
  26. package/dist/components/custom/CharText/CharText.d.ts.map +1 -1
  27. package/dist/components/custom/CharTextInput.d.ts +2 -1
  28. package/dist/components/custom/CharTextInput.d.ts.map +1 -1
  29. package/dist/components/custom/Dialog.d.ts +2 -1
  30. package/dist/components/custom/Dialog.d.ts.map +1 -1
  31. package/dist/components/custom/Divider.d.ts +2 -1
  32. package/dist/components/custom/Divider.d.ts.map +1 -1
  33. package/dist/components/custom/Dropdown.d.ts +2 -1
  34. package/dist/components/custom/Dropdown.d.ts.map +1 -1
  35. package/dist/components/custom/Graphics.d.ts +45 -0
  36. package/dist/components/custom/Graphics.d.ts.map +1 -0
  37. package/dist/components/custom/Icon.d.ts +3 -2
  38. package/dist/components/custom/Icon.d.ts.map +1 -1
  39. package/dist/components/custom/Image.d.ts +2 -1
  40. package/dist/components/custom/Image.d.ts.map +1 -1
  41. package/dist/components/custom/Joystick.d.ts +42 -0
  42. package/dist/components/custom/Joystick.d.ts.map +1 -0
  43. package/dist/components/custom/Modal.d.ts +2 -1
  44. package/dist/components/custom/Modal.d.ts.map +1 -1
  45. package/dist/components/custom/NineSlice.d.ts +2 -1
  46. package/dist/components/custom/NineSlice.d.ts.map +1 -1
  47. package/dist/components/custom/NineSliceButton.d.ts +2 -1
  48. package/dist/components/custom/NineSliceButton.d.ts.map +1 -1
  49. package/dist/components/custom/Particles.d.ts +17 -0
  50. package/dist/components/custom/Particles.d.ts.map +1 -0
  51. package/dist/components/custom/Portal.d.ts +2 -1
  52. package/dist/components/custom/Portal.d.ts.map +1 -1
  53. package/dist/components/custom/RadioButton.d.ts +2 -1
  54. package/dist/components/custom/RadioButton.d.ts.map +1 -1
  55. package/dist/components/custom/RadioGroup.d.ts +2 -5
  56. package/dist/components/custom/RadioGroup.d.ts.map +1 -1
  57. package/dist/components/custom/RefOriginView.d.ts +2 -1
  58. package/dist/components/custom/RefOriginView.d.ts.map +1 -1
  59. package/dist/components/custom/ScrollSlider.d.ts +3 -2
  60. package/dist/components/custom/ScrollSlider.d.ts.map +1 -1
  61. package/dist/components/custom/ScrollView.d.ts +13 -4
  62. package/dist/components/custom/ScrollView.d.ts.map +1 -1
  63. package/dist/components/custom/Sidebar.d.ts +2 -1
  64. package/dist/components/custom/Sidebar.d.ts.map +1 -1
  65. package/dist/components/custom/Slider.d.ts +4 -3
  66. package/dist/components/custom/Slider.d.ts.map +1 -1
  67. package/dist/components/custom/Sprite.d.ts +74 -0
  68. package/dist/components/custom/Sprite.d.ts.map +1 -0
  69. package/dist/components/custom/Tabs.d.ts +50 -0
  70. package/dist/components/custom/Tabs.d.ts.map +1 -0
  71. package/dist/components/custom/Text.d.ts +2 -1
  72. package/dist/components/custom/Text.d.ts.map +1 -1
  73. package/dist/components/custom/TileSprite.d.ts +60 -0
  74. package/dist/components/custom/TileSprite.d.ts.map +1 -0
  75. package/dist/components/custom/Toggle.d.ts +2 -1
  76. package/dist/components/custom/Toggle.d.ts.map +1 -1
  77. package/dist/components/custom/TransformOriginView.d.ts +3 -2
  78. package/dist/components/custom/TransformOriginView.d.ts.map +1 -1
  79. package/dist/components/custom/View.d.ts +2 -1
  80. package/dist/components/custom/View.d.ts.map +1 -1
  81. package/dist/components/custom/WrapText.d.ts +2 -1
  82. package/dist/components/custom/WrapText.d.ts.map +1 -1
  83. package/dist/components/custom/index.cjs +6 -1
  84. package/dist/components/custom/index.cjs.map +1 -1
  85. package/dist/components/custom/index.d.ts +3 -0
  86. package/dist/components/custom/index.d.ts.map +1 -1
  87. package/dist/components/custom/index.js +16 -11
  88. package/dist/components/index.d.ts +10 -8
  89. package/dist/components/index.d.ts.map +1 -1
  90. package/dist/components/internal/SceneWrapper.d.ts +1 -1
  91. package/dist/components/internal/SceneWrapper.d.ts.map +1 -1
  92. package/dist/components/primitives/particles.d.ts +37 -0
  93. package/dist/components/primitives/particles.d.ts.map +1 -0
  94. package/dist/core-types.d.ts +5 -0
  95. package/dist/core-types.d.ts.map +1 -1
  96. package/dist/gestures/gesture-manager.d.ts.map +1 -1
  97. package/dist/hooks.d.ts +124 -3
  98. package/dist/hooks.d.ts.map +1 -1
  99. package/dist/index.cjs +2152 -20
  100. package/dist/index.cjs.map +1 -1
  101. package/dist/index.d.ts +4 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +2265 -132
  104. package/dist/index.js.map +1 -1
  105. package/dist/jsx-runtime.cjs.map +1 -1
  106. package/dist/jsx-runtime.d.ts +2 -3
  107. package/dist/jsx-runtime.d.ts.map +1 -1
  108. package/dist/jsx-runtime.js.map +1 -1
  109. package/dist/jsx-types.d.ts +8 -0
  110. package/dist/jsx-types.d.ts.map +1 -1
  111. package/dist/layout/layout-engine.d.ts.map +1 -1
  112. package/dist/particles/emit-zone.d.ts +67 -0
  113. package/dist/particles/emit-zone.d.ts.map +1 -0
  114. package/dist/particles/index.d.ts +8 -0
  115. package/dist/particles/index.d.ts.map +1 -0
  116. package/dist/particles/particle-types.d.ts +20 -0
  117. package/dist/particles/particle-types.d.ts.map +1 -0
  118. package/dist/particles/preset-registry.d.ts +46 -0
  119. package/dist/particles/preset-registry.d.ts.map +1 -0
  120. package/dist/particles/use-particles.d.ts +15 -0
  121. package/dist/particles/use-particles.d.ts.map +1 -0
  122. package/dist/particles/utils.d.ts +10 -0
  123. package/dist/particles/utils.d.ts.map +1 -0
  124. package/dist/plugin.d.ts +157 -0
  125. package/dist/plugin.d.ts.map +1 -0
  126. package/dist/theme-base.d.ts +10 -1
  127. package/dist/theme-base.d.ts.map +1 -1
  128. package/dist/theme-custom.d.ts +7 -0
  129. package/dist/theme-custom.d.ts.map +1 -1
  130. package/dist/theme-defaults.d.ts.map +1 -1
  131. package/dist/types.d.ts +18 -1
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/vdom.d.ts +28 -3
  134. package/dist/vdom.d.ts.map +1 -1
  135. package/package.json +1 -1
  136. package/dist/TransformOriginView-CzVjS16F.js.map +0 -1
  137. package/dist/TransformOriginView-KcTgaYRi.cjs.map +0 -1
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../src/fx/use-fx.ts","../src/fx/fx-creators/blur.ts","../src/fx/fx-creators/color-matrix.ts","../src/fx/fx-creators/glow.ts","../src/fx/fx-creators/pixelate.ts","../src/fx/fx-creators/shadow.ts","../src/fx/fx-creators/vignette.ts","../src/fx/fx-registry.ts","../src/fx/convenience-hooks/use-blur.ts","../src/fx/convenience-hooks/use-glow.ts","../src/fx/convenience-hooks/use-shadow.ts","../src/memo.ts","../src/colors/use-color-mode.ts","../src/colors/use-colors.ts","../src/colors/color-theme-helpers.ts","../src/colors/preset-manager.ts","../src/design-tokens/use-theme-tokens.ts","../src/index.ts"],"sourcesContent":["/**\n * Hook for applying Phaser PostFX/PreFX pipeline effects\n * Manages FX lifecycle with proper cleanup\n */\nimport { useEffect, useRef } from '../hooks'\n\n/**\n * Ref object type\n */\ntype RefObject<T> = { current: T | null }\n\n/**\n * FX configuration base type\n */\nexport interface FXConfig {\n intensity?: number\n quality?: number\n onComplete?: () => void\n}\n\n/**\n * FX type discriminator (postFX vs preFX)\n */\nexport type FXType = 'post' | 'pre'\n\n/**\n * GameObject with FX pipeline support\n */\nexport type FXCapableGameObject =\n | Phaser.GameObjects.Image\n | Phaser.GameObjects.Sprite\n | Phaser.GameObjects.Container\n | Phaser.GameObjects.Text\n | Phaser.GameObjects.TileSprite\n | Phaser.GameObjects.NineSlice\n | Phaser.GameObjects.RenderTexture\n | Phaser.GameObjects.Video\n\n/**\n * FX creator function signature\n * @param obj - GameObject with FX pipeline\n * @param config - Effect-specific configuration\n * @param type - 'post' or 'pre' FX pipeline\n * @returns Cleanup function or FX controller (or any Phaser.FX effect)\n */\nexport type FXCreatorFn<TConfig extends FXConfig = FXConfig> = (\n obj: FXCapableGameObject,\n config: TConfig,\n type?: FXType\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n) => (() => void) | Phaser.FX.Controller | any | null\n\n/**\n * Hook for applying FX to GameObject\n * @param ref - Ref to GameObject\n * @returns Object with applyFX and clearFX methods\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * const { applyFX, clearFX } = useFX(ref)\n *\n * const handleClick = () => {\n * applyFX(createShadowFX, { offsetX: 4, offsetY: 4, blur: 8 })\n * }\n *\n * return <View ref={ref} onClick={handleClick}>Click me</View>\n * ```\n */\nexport function useFX<T extends FXCapableGameObject>(ref: RefObject<T>) {\n const activeEffectsRef = useRef<Set<(() => void) | Phaser.FX.Controller>>(new Set())\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n activeEffectsRef.current.forEach((cleanup) => {\n if (typeof cleanup === 'function') {\n cleanup()\n } else if (cleanup?.destroy) {\n cleanup.destroy()\n }\n })\n activeEffectsRef.current.clear()\n }\n }, [])\n\n const applyFX = <TConfig extends FXConfig>(\n fxCreator: FXCreatorFn<TConfig>,\n config: TConfig,\n type: FXType = 'post'\n ) => {\n const obj = ref.current\n if (!obj) {\n console.warn('[useFX] No object found in ref')\n return\n }\n\n const cleanupOrController = fxCreator(obj, config, type)\n if (cleanupOrController) {\n activeEffectsRef.current.add(cleanupOrController)\n }\n }\n\n const clearFX = () => {\n activeEffectsRef.current.forEach((cleanup) => {\n if (typeof cleanup === 'function') {\n cleanup()\n } else if (cleanup?.destroy) {\n cleanup.destroy()\n }\n })\n activeEffectsRef.current.clear()\n\n // Clear FX pipeline\n const obj = ref.current\n if (obj && 'postFX' in obj && obj.postFX) {\n obj.postFX.clear()\n }\n if (obj && 'preFX' in obj && obj.preFX) {\n obj.preFX.clear()\n }\n }\n\n return { applyFX, clearFX }\n}\n","/**\n * Blur FX creator (Box & Gaussian Blur)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Blur FX configuration\n */\nexport interface BlurFXConfig extends FXConfig {\n /** The quality of the blur effect. Can be either 0 for Low Quality, 1 for Medium Quality or 2 for High Quality */\n quality?: number\n /** The horizontal offset of the blur effect */\n x?: number\n /** The vertical offset of the blur effect */\n y?: number\n /** The strength of the blur effect */\n strength?: number\n /** The color of the blur, as a hex value */\n color?: number\n /** The number of steps to run the blur effect for. This value should always be an integer */\n steps?: number\n}\n\n/**\n * Create blur FX\n * @param obj - GameObject\n * @param config - Blur configuration\n * @param type - 'post' or 'pre' FX\n * @returns Blur controller\n *\n * @example\n * ```tsx\n * applyFX(createBlurFX, {\n * quality: 1,\n * x: 4,\n * y: 4,\n * strength: 2\n * })\n * ```\n */\nexport const createBlurFX: FXCreatorFn<BlurFXConfig> = (obj, config, type = 'post') => {\n const { quality = 0, x = 2, y = 2, strength = 1, color = 0xffffff, steps = 4 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createBlurFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addBlur(quality, x, y, strength, color, steps)\n const blur = pipeline.addBlur(quality, x, y, strength, color, steps)\n\n return blur\n}\n","/**\n * Color Matrix FX creator (Grayscale, Sepia, Negative, etc.)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Color Matrix effect types\n */\nexport type ColorMatrixEffect =\n | 'grayscale'\n | 'sepia'\n | 'negative'\n | 'blackWhite'\n | 'brown'\n | 'kodachrome'\n | 'technicolor'\n | 'polaroid'\n\n/**\n * Color Matrix FX configuration\n */\nexport interface ColorMatrixFXConfig extends FXConfig {\n /** Effect type */\n effect?: ColorMatrixEffect\n /** Effect amount (0-1, for effects that support it like grayscale) */\n amount?: number\n}\n\n/**\n * Create color matrix FX\n * @param obj - GameObject\n * @param config - Color matrix configuration\n * @param type - 'post' or 'pre' FX\n * @returns Color matrix controller\n *\n * @example\n * ```tsx\n * applyFX(createColorMatrixFX, {\n * effect: 'grayscale',\n * amount: 1\n * })\n * ```\n */\nexport const createColorMatrixFX: FXCreatorFn<ColorMatrixFXConfig> = (\n obj,\n config,\n type = 'post'\n) => {\n const { effect = 'grayscale', amount = 1 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createColorMatrixFX] FX pipeline not available on this GameObject')\n return null\n }\n\n const colorMatrix = pipeline.addColorMatrix()\n\n // Apply the selected effect\n switch (effect) {\n case 'grayscale':\n colorMatrix.grayscale(amount)\n break\n case 'sepia':\n colorMatrix.sepia()\n break\n case 'negative':\n colorMatrix.negative()\n break\n case 'blackWhite':\n colorMatrix.blackWhite()\n break\n case 'brown':\n colorMatrix.brown()\n break\n case 'kodachrome':\n colorMatrix.kodachrome()\n break\n case 'technicolor':\n colorMatrix.technicolor()\n break\n case 'polaroid':\n colorMatrix.polaroid()\n break\n }\n\n return colorMatrix\n}\n","/**\n * Glow FX creator (Outer Glow)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Glow FX configuration\n */\nexport interface GlowFXConfig extends FXConfig {\n /** Glow color (hex number) */\n color?: number\n /** The strength of the glow outward from the edge */\n outerStrength?: number\n /** The strength of the glow inward from the edge */\n innerStrength?: number\n /** If true, only the glow is drawn, not the texture itself */\n knockout?: boolean\n /** Sets the quality of this Glow effect (PostFX only, cannot be changed post-creation) */\n quality?: number\n /** Sets the distance of this Glow effect (PostFX only, cannot be changed post-creation) */\n distance?: number\n}\n\n/**\n * Create glow FX\n * @param obj - GameObject\n * @param config - Glow configuration\n * @param type - 'post' or 'pre' FX\n * @returns Glow controller\n *\n * @example\n * ```tsx\n * applyFX(createGlowFX, {\n * color: 0xff6600,\n * outerStrength: 6,\n * innerStrength: 2\n * })\n * ```\n */\nexport const createGlowFX: FXCreatorFn<GlowFXConfig> = (obj, config, type = 'post') => {\n const {\n color = 0xffffff,\n outerStrength = 4,\n innerStrength = 0,\n knockout = false,\n quality = 0.1,\n distance = 10,\n } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createGlowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addGlow(color, outerStrength, innerStrength, knockout, quality, distance)\n const glow = pipeline.addGlow(color, outerStrength, innerStrength, knockout, quality, distance)\n\n return glow\n}\n","/**\n * Pixelate FX creator\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Pixelate FX configuration\n */\nexport interface PixelateFXConfig extends FXConfig {\n /** The amount of pixelation to apply */\n amount?: number\n}\n\n/**\n * Create pixelate FX\n * @param obj - GameObject\n * @param config - Pixelate configuration\n * @param type - 'post' or 'pre' FX\n * @returns Pixelate controller\n *\n * @example\n * ```tsx\n * applyFX(createPixelateFX, {\n * amount: 8\n * })\n * ```\n */\nexport const createPixelateFX: FXCreatorFn<PixelateFXConfig> = (obj, config, type = 'post') => {\n const { amount = 1 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createPixelateFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addPixelate(amount)\n const pixelate = pipeline.addPixelate(amount)\n\n return pixelate\n}\n","/**\n * Shadow FX creator\n *\n * The shadow effect creates the illusion of depth by adding darker, offset silhouettes\n * beneath game objects, enhancing visual appeal and immersion.\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Shadow FX configuration\n * Maps to Phaser's addShadow(x, y, decay, power, color, samples, intensity)\n */\nexport interface ShadowFXConfig extends FXConfig {\n /** Horizontal offset of the shadow effect (default: 0) */\n x?: number\n /** Vertical offset of the shadow effect (default: 0) */\n y?: number\n /** Amount of decay for shadow effect (default: 0.1) */\n decay?: number\n /** Power of the shadow effect (default: 1) */\n power?: number\n /** Color of the shadow (default: 0x000000) */\n color?: number\n /** Number of samples (1-12, higher = better quality, default: 6) */\n samples?: number\n /** Intensity of the shadow effect (default: 1) */\n intensity?: number\n}\n\n/**\n * Create shadow FX\n * @param obj - GameObject\n * @param config - Shadow configuration\n * @param type - 'post' or 'pre' FX\n * @returns Shadow controller\n *\n * @example\n * ```tsx\n * applyFX(createShadowFX, {\n * x: 0,\n * y: 0,\n * decay: 0.1,\n * power: 1,\n * color: 0x000000,\n * samples: 6,\n * intensity: 1\n * })\n * ```\n */\nexport const createShadowFX: FXCreatorFn<ShadowFXConfig> = (obj, config, type = 'post') => {\n const {\n x = 0,\n y = 1,\n decay = 0.05,\n power = 1,\n color = 0x000000,\n samples = 6,\n intensity = 1,\n } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createShadowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addShadow(x, y, decay, power, color, samples, intensity)\n const shadow = pipeline.addShadow(x, y, decay, power, color, samples, intensity)\n\n return shadow\n}\n","/**\n * Vignette FX creator\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Vignette FX configuration\n */\nexport interface VignetteFXConfig extends FXConfig {\n /** The horizontal offset of the vignette effect. This value is normalized to the range 0 to 1 */\n x?: number\n /** The vertical offset of the vignette effect. This value is normalized to the range 0 to 1 */\n y?: number\n /** The radius of the vignette effect. This value is normalized to the range 0 to 1 */\n radius?: number\n /** The strength of the vignette effect */\n strength?: number\n}\n\n/**\n * Create vignette FX\n * @param obj - GameObject\n * @param config - Vignette configuration\n * @param type - 'post' or 'pre' FX\n * @returns Vignette controller\n *\n * @example\n * ```tsx\n * applyFX(createVignetteFX, {\n * x: 0.5,\n * y: 0.5,\n * radius: 0.5,\n * strength: 0.7\n * })\n * ```\n */\nexport const createVignetteFX: FXCreatorFn<VignetteFXConfig> = (obj, config, type = 'post') => {\n const { strength = 0.5, radius = 0.5, x = 0.5, y = 0.5 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createVignetteFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser Vignette: addVignette(x, y, radius, strength)\n const vignette = pipeline.addVignette(x, y, radius, strength)\n\n return vignette\n}\n","/**\n * FX Registry - string-based FX lookup\n * Similar to effect-registry.ts for animation effects\n */\nimport {\n createBlurFX,\n createColorMatrixFX,\n createGlowFX,\n createPixelateFX,\n createShadowFX,\n createVignetteFX,\n type BlurFXConfig,\n type ColorMatrixFXConfig,\n type GlowFXConfig,\n type PixelateFXConfig,\n type ShadowFXConfig,\n type VignetteFXConfig,\n} from './fx-creators'\nimport type { FXConfig, FXCreatorFn } from './use-fx'\n\n/**\n * Built-in FX names\n */\nexport type BuiltInFXName =\n | 'shadow'\n | 'glow'\n | 'blur'\n | 'pixelate'\n | 'vignette'\n | 'grayscale'\n | 'sepia'\n | 'negative'\n | 'blackWhite'\n | 'brown'\n | 'kodachrome'\n | 'technicolor'\n | 'polaroid'\n\n/**\n * Extension point for custom FX (declaration merging)\n * @example\n * ```typescript\n * declare module '@number10/phaserjsx/fx' {\n * interface FXNameExtensions {\n * myCustomFX: 'myCustomFX'\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface FXNameExtensions {}\n\n/**\n * All available FX names (built-in + extensions)\n */\nexport type FXName =\n | BuiltInFXName\n | (keyof FXNameExtensions extends never ? never : keyof FXNameExtensions)\n\n/**\n * FX definition with name and config\n */\nexport interface FXDefinition {\n name: FXName\n config?: FXConfig\n}\n\n/**\n * FX Registry mapping names to creator functions\n */\nexport const FX_REGISTRY: Record<BuiltInFXName, FXCreatorFn> = {\n shadow: createShadowFX,\n glow: createGlowFX,\n blur: createBlurFX,\n pixelate: createPixelateFX,\n vignette: createVignetteFX,\n grayscale: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'grayscale' }, type),\n sepia: (obj, config, type) => createColorMatrixFX(obj, { ...config, effect: 'sepia' }, type),\n negative: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'negative' }, type),\n blackWhite: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'blackWhite' }, type),\n brown: (obj, config, type) => createColorMatrixFX(obj, { ...config, effect: 'brown' }, type),\n kodachrome: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'kodachrome' }, type),\n technicolor: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'technicolor' }, type),\n polaroid: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'polaroid' }, type),\n}\n\n/**\n * Default FX (none)\n */\nexport const DEFAULT_FX: FXName = 'grayscale'\n\n/**\n * Resolve FX by name or function\n * @param fxOrName - FX name string or creator function\n * @returns FX creator function or null\n */\nexport function resolveFX(fxOrName: FXName | FXCreatorFn): FXCreatorFn | null {\n if (typeof fxOrName === 'function') {\n return fxOrName\n }\n return FX_REGISTRY[fxOrName as BuiltInFXName] ?? null\n}\n\n/**\n * Apply FX by name (helper function)\n * @param applyFXFn - applyFX function from useFX hook\n * @param fxName - FX name\n * @param config - FX config\n *\n * @example\n * ```tsx\n * const { applyFX } = useFX(ref)\n * applyFXByName(applyFX, 'shadow', { offsetX: 4, offsetY: 4, blur: 8 })\n * ```\n */\nexport function applyFXByName(\n applyFXFn: ReturnType<typeof import('./use-fx').useFX>['applyFX'],\n fxName: FXName,\n config: FXConfig = {}\n) {\n const creator = resolveFX(fxName)\n if (creator) {\n applyFXFn(creator, config)\n } else {\n console.warn(`[applyFXByName] FX \"${fxName}\" not found in registry`)\n }\n}\n\n// Re-export config types for convenience\nexport type {\n BlurFXConfig,\n ColorMatrixFXConfig,\n GlowFXConfig,\n PixelateFXConfig,\n ShadowFXConfig,\n VignetteFXConfig,\n}\n","/**\n * Convenience hook for automatic blur FX\n * Applies blur on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createBlurFX, type BlurFXConfig } from '../fx-creators/blur'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic blur FX\n * @param ref - GameObject ref\n * @param config - Blur config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useBlur(ref, { strength: 8, steps: 4 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useBlur(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: BlurFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new blur\n applyFX(createBlurFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Convenience hook for automatic glow FX\n * Applies glow on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createGlowFX, type GlowFXConfig } from '../fx-creators/glow'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic glow FX\n * @param ref - GameObject ref\n * @param config - Glow config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useGlow(ref, { color: 0xff6600, outerStrength: 6, innerStrength: 2 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useGlow(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: GlowFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new glow\n applyFX(createGlowFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Convenience hook for automatic shadow FX\n * Applies shadow on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createShadowFX, type ShadowFXConfig } from '../fx-creators/shadow'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic shadow FX\n * @param ref - GameObject ref\n * @param config - Shadow config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useShadow(ref, { x: 4, y: 4, decay: 0.1 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useShadow(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: ShadowFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new shadow\n applyFX(createShadowFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Component memoization utilities\n * Similar to React.memo() - prevents re-renders when props haven't changed\n */\nimport type { VNode } from './hooks'\n\n/**\n * Safely sets __memo on a VNode, handling frozen/sealed objects from bundlers\n * @param vnode - VNode to set __memo on\n * @param value - Memoization value\n * @returns Original VNode if extensible, or shallow copy with __memo\n */\nfunction setMemoSafe<T extends VNode>(vnode: T, value: boolean): T {\n if (Object.isExtensible(vnode)) {\n vnode.__memo = value\n return vnode\n }\n // VNode is frozen - create shallow copy\n return { ...vnode, __memo: value } as T\n}\n\n/**\n * Marks a component to skip memoization (always re-render on prop changes)\n * Use when component has side effects or needs to re-render every time\n *\n * @example\n * ```tsx\n * function AlwaysUpdate({ value }) {\n * console.log('Rendering with:', value)\n * return <Text text={value} />\n * }\n *\n * // Disable memoization\n * <AlwaysUpdate value={counter} __memo={false} />\n * ```\n *\n * @param vnode - VNode to mark\n * @returns Same VNode with memoization disabled (may be a copy if frozen)\n */\nexport function noMemo<T extends VNode>(vnode: T): T {\n return setMemoSafe(vnode, false)\n}\n\n/**\n * Explicitly enable memoization for a component (default behavior)\n * This is the default - you don't need to call this unless you want to be explicit\n *\n * @param vnode - VNode to mark\n * @returns Same VNode with memoization enabled (may be a copy if frozen)\n */\nexport function memo<T extends VNode>(vnode: T): T {\n return setMemoSafe(vnode, true)\n}\n","/**\n * Color mode management for dynamic theme switching\n */\nimport { useEffect, useState } from '../hooks'\nimport { themeRegistry } from '../theme'\n\n/**\n * Hook to manage color mode (light/dark) dynamically\n * @returns Object with current mode, toggle function, and setter\n * @example\n * ```typescript\n * function ThemeToggle() {\n * const { colorMode, toggleColorMode } = useColorMode()\n *\n * return (\n * <Button onClick={toggleColorMode}>\n * {colorMode === 'light' ? 'Dark' : 'Light'} Mode\n * </Button>\n * )\n * }\n * ```\n */\nexport function useColorMode(): {\n colorMode: 'light' | 'dark'\n setColorMode: (mode: 'light' | 'dark') => void\n toggleColorMode: () => void\n} {\n const [colorMode, setColorModeState] = useState<'light' | 'dark'>(themeRegistry.getColorMode())\n\n useEffect(() => {\n // Subscribe to theme registry changes\n const unsubscribe = themeRegistry.subscribe(() => {\n setColorModeState(themeRegistry.getColorMode())\n })\n\n return unsubscribe\n }, [])\n\n const setColorMode = (mode: 'light' | 'dark') => {\n themeRegistry.setColorMode(mode)\n }\n\n const toggleColorMode = () => {\n const newMode = colorMode === 'light' ? 'dark' : 'light'\n setColorMode(newMode)\n }\n\n return {\n colorMode,\n setColorMode,\n toggleColorMode,\n }\n}\n","/**\n * Color system hooks for component usage\n */\nimport { useEffect, useState, useTheme } from '../hooks'\nimport { themeRegistry } from '../theme'\nimport { getPresetWithMode } from './color-presets'\nimport type { ColorTokens } from './color-types'\n\n/**\n * Hook to access color tokens from theme context\n * Automatically updates when color mode or preset changes\n * @returns Current ColorTokens or undefined\n * @deprecated Use `useThemeTokens()` instead for access to colors, text styles, spacing, and more\n * @example\n * ```typescript\n * // Old way (deprecated):\n * const colors = useColors()\n *\n * // New way:\n * const tokens = useThemeTokens()\n * const colors = tokens?.colors\n *\n * // Access text styles, spacing, etc.:\n * <Text style={tokens.textStyles.DEFAULT} />\n * <View padding={tokens.spacing.lg} />\n * ```\n */\nexport function useColors(): ColorTokens | undefined {\n const localTheme = useTheme()\n\n // Initialize colors state\n const getInitialColors = (): ColorTokens | undefined => {\n // Check if local theme has color preset info\n if (localTheme?.__colorPreset) {\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n localTheme.__colorPreset.mode ?? 'light'\n )\n return preset.colors\n }\n\n // Fall back to global color tokens\n return themeRegistry.getColorTokens()\n }\n\n const [colors, setColors] = useState<ColorTokens | undefined>(getInitialColors())\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // Subscribe to theme changes (mode/preset switches)\n const unsubscribe = themeRegistry.subscribe(() => {\n // Check if local theme has preset\n if (localTheme?.__colorPreset) {\n const currentMode = themeRegistry.getColorMode()\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n currentMode\n )\n setColors(preset.colors)\n } else {\n // Use global tokens\n setColors(themeRegistry.getColorTokens())\n }\n // Force re-render when theme changes\n forceUpdate((n) => n + 1)\n })\n\n return unsubscribe\n }, [localTheme])\n\n return colors\n}\n\n/**\n * Hook to subscribe to theme changes without accessing colors\n * Use this in parent components that don't need colors themselves\n * but want to ensure children re-render when theme changes\n *\n * Note: Since useColors() now triggers re-renders automatically,\n * this hook is mainly useful if you don't need the colors themselves\n * but still want to react to theme changes.\n *\n * @example\n * ```typescript\n * function ParentComponent() {\n * useThemeSubscription() // Children will re-render on theme changes\n * return <ChildThatUsesColors />\n * }\n * ```\n */\nexport function useThemeSubscription(): void {\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n const unsubscribe = themeRegistry.subscribe(() => {\n forceUpdate((n) => n + 1)\n })\n return unsubscribe\n }, [])\n}\n","/**\n * Helper functions for color system integration with theme\n */\nimport type { ColorTokens } from './color-types'\nimport { alpha } from './color-utils'\n\n/**\n * Convert ColorTokens to a theme-compatible object\n * Maps semantic color names to Phaser number format for View/Button components\n * @param colors - ColorTokens to convert\n * @returns Object with backgroundColor, borderColor, etc.\n * @example\n * ```typescript\n * const colors = getPreset('oceanBlue').colors\n * const buttonTheme = {\n * ...colorsToTheme(colors, 'primary'),\n * padding: 8,\n * }\n * // Returns: { backgroundColor: 0x2196f3, borderColor: 0x... }\n * ```\n */\nexport function colorsToTheme(\n colors: ColorTokens,\n colorKey: keyof Pick<\n ColorTokens,\n 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'error' | 'info'\n >,\n options: {\n /** Which shade to use for background (default: 'DEFAULT') */\n backgroundShade?: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT'\n /** Which shade to use for border (default: 'dark') */\n borderShade?: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT'\n /** Include border color (default: true) */\n includeBorder?: boolean\n } = {}\n): {\n backgroundColor: number\n borderColor?: number\n} {\n const { backgroundShade = 'DEFAULT', borderShade = 'dark', includeBorder = true } = options\n\n const result: { backgroundColor: number; borderColor?: number } = {\n backgroundColor: colors[colorKey][backgroundShade].toNumber(),\n }\n\n if (includeBorder) {\n result.borderColor = colors[colorKey][borderShade].toNumber()\n }\n\n return result\n}\n\n/**\n * Get text color from ColorTokens as hex string for Phaser Text style\n * @param colors - ColorTokens to use\n * @param shade - Which text shade to use (default: 'DEFAULT')\n * @param alphaValue - Optional alpha value (0-1)\n * @returns Hex string or rgba string for Text style\n * @example\n * ```typescript\n * const colors = getPreset('oceanBlue').colors\n * const textStyle = {\n * color: getTextColor(colors),\n * fontSize: '18px'\n * }\n * ```\n */\nexport function getTextColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT',\n alphaValue?: number\n): string {\n const color = colors.text[shade]\n return alphaValue !== undefined ? alpha(color.toNumber(), alphaValue) : color.toString()\n}\n\n/**\n * Get background color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getBackgroundColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.background[shade].toNumber()\n}\n\n/**\n * Get surface color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getSurfaceColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.surface[shade].toNumber()\n}\n\n/**\n * Get border color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getBorderColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.border[shade].toNumber()\n}\n","/**\n * Dynamic color preset management\n */\nimport { themeRegistry } from '../theme'\nimport type { PresetName } from './color-presets'\nimport { getPresetWithMode } from './color-presets'\n\n/**\n * Set the active color preset globally\n * Applies the preset with the current color mode and updates all components\n * Triggers complete remount of all active mountJSX instances\n * @param presetName - Name of the preset to apply\n * @param colorMode - Optional color mode to apply together with the preset\n * @example\n * ```typescript\n * // Switch to forest green theme\n * setColorPreset('forestGreen')\n *\n * // Apply preset and force dark mode in one go\n * setColorPreset('midnight', 'dark')\n *\n * // Current mode (light/dark) is preserved\n * ```\n */\nexport function setColorPreset(presetName: PresetName, colorMode?: 'light' | 'dark'): void {\n const targetMode = colorMode ?? themeRegistry.getColorMode()\n const preset = getPresetWithMode(presetName, targetMode)\n\n // Update color tokens WITHOUT notifying listeners\n // We skip listener notifications to prevent unnecessary re-renders\n themeRegistry.setColorTokens(preset.colors)\n themeRegistry.setCurrentPresetName(presetName, true) // true = skip notify\n\n // If caller asked for a specific mode, update it here so we only remount once\n if (colorMode && themeRegistry.getColorMode() !== colorMode) {\n themeRegistry.setColorMode(colorMode)\n return\n }\n\n // Trigger complete remount of all VDOM trees to apply new preset\n // Using setTimeout(0) to ensure all synchronous state updates complete first\n setTimeout(() => {\n // Import remountAll lazily to avoid circular dependency\n import('../vdom').then(({ remountAll }) => {\n remountAll()\n })\n }, 0)\n}\n\n/**\n * Get the currently active preset name\n * @returns Current preset name or undefined\n */\nexport function getCurrentPreset(): string | undefined {\n return themeRegistry.getCurrentPresetName()\n}\n\n/**\n * Set the active color mode globally (without changing the preset)\n * @param mode - Color mode to apply\n */\nexport function setColorMode(mode: 'light' | 'dark'): void {\n themeRegistry.setColorMode(mode)\n}\n\n/**\n * Get all available preset names\n * @returns Array of preset names\n * @example\n * ```typescript\n * const presets = getAvailablePresets() // ['oceanBlue', 'forestGreen', 'midnight']\n * ```\n */\nexport function getAvailablePresets(): PresetName[] {\n return ['oceanBlue', 'forestGreen', 'midnight']\n}\n","/**\n * Hook to access complete design token system\n * Combines colors with text styles, spacing, sizes, and radius tokens\n */\nimport { getPresetWithMode } from '../colors/color-presets'\nimport { useEffect, useState, useTheme } from '../hooks'\nimport { themeRegistry } from '../theme'\nimport {\n createTextStyleTokens,\n defaultRadiusTokens,\n defaultSizeTokens,\n defaultSpacingTokens,\n} from './design-token-presets'\nimport type { DesignTokens } from './design-token-types'\n\n/**\n * Hook to access complete design token system from theme context\n * Provides colors, text styles, spacing, sizes, and radius tokens\n * Automatically updates when color mode or preset changes\n * @returns Current DesignTokens or undefined\n * @example\n * ```typescript\n * function MyComponent() {\n * const tokens = useThemeTokens()\n *\n * if (!tokens) return null\n *\n * return (\n * <View\n * backgroundColor={tokens.colors.surface.DEFAULT}\n * padding={tokens.spacing.lg}\n * cornerRadius={tokens.radius.md}\n * >\n * <Text text=\"Title\" style={tokens.textStyles.title} />\n * <Text text=\"Body text\" style={tokens.textStyles.DEFAULT} />\n * </View>\n * )\n * }\n * ```\n */\nexport function useThemeTokens(): DesignTokens | undefined {\n const localTheme = useTheme()\n\n // Initialize design tokens state\n const getInitialTokens = (): DesignTokens | undefined => {\n // Check if local theme has color preset info\n if (localTheme?.__colorPreset) {\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n localTheme.__colorPreset.mode ?? 'light'\n )\n return {\n colors: preset.colors,\n textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n }\n }\n\n // Fall back to global tokens\n const colors = themeRegistry.getColorTokens()\n if (!colors) return undefined\n\n return {\n colors,\n textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n }\n }\n\n const [tokens, setTokens] = useState<DesignTokens | undefined>(getInitialTokens())\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // Subscribe to theme changes (mode/preset switches)\n const unsubscribe = themeRegistry.subscribe(() => {\n // Check if local theme has preset\n if (localTheme?.__colorPreset) {\n const currentMode = themeRegistry.getColorMode()\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n currentMode\n )\n setTokens({\n colors: preset.colors,\n textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n })\n } else {\n // Use global tokens\n const colors = themeRegistry.getColorTokens()\n if (colors) {\n setTokens({\n colors,\n textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n })\n }\n }\n // Force re-render when theme changes\n forceUpdate((n) => n + 1)\n })\n\n return unsubscribe\n }, [localTheme])\n\n return tokens\n}\n","/**\n * PhaserJSX UI Library\n * Provides JSX + hooks + VDOM for Phaser 3 game development\n */\nimport { registerBuiltins } from './components'\nimport './jsx-types' // Import JSX type declarations\n\n// Register built-in components (View, Text) on module load\nregisterBuiltins()\n\nexport * from './core-types'\nexport * from './effects'\nexport * from './fx'\nexport * from './hooks'\nexport * from './hooks-svg'\nexport * from './host'\nexport * from './memo'\nexport * from './theme'\nexport * from './types'\nexport * from './vdom'\n\n// Export core prop utilities\nexport {\n normalizeCornerRadius,\n normalizeEdgeInsets,\n normalizeGap,\n type CornerRadiusInsets,\n type EdgeInsets,\n type GapInsets,\n} from './core-props'\n\n// Export gesture types explicitly for better IDE support\nexport type {\n Display,\n FlexBasisValue,\n FocusEventData,\n GestureEventData,\n GestureProps,\n InputEventData,\n KeyboardEventData,\n SizeValue,\n TouchMoveState,\n} from './core-props'\n\n// Export DOM input manager utility\nexport { DOMInputElement, type DOMInputConfig } from './utils/dom-input-manager'\nexport { KeyboardInputManager, type KeyboardInputManagerConfig } from './utils/KeyboardInputManager'\n\n// Explicit export for convenience functions\nexport { mountJSX as mountComponent, type MountComponentProps, type MountProps } from './vdom'\n\n// Re-export component creators/patchers for advanced usage\nexport * from './components'\n\n// Re-export custom components for convenience\nexport * from './components/custom'\n\n// Re-export portal system\nexport * from './portal'\n\n// Animation utilities for spring-based transitions\nexport * from './animation'\n\n// Explicitly export AnimationConfig for component themes\nexport type { AnimationConfig } from './animation/spring-physics'\n\n// Color system utilities and presets\nexport * from './colors'\n\n// Design token system - semantic tokens for colors, text styles, spacing, etc.\nexport * from './design-tokens'\n\n// Tooltip system - onTooltip property types\nexport type {\n TooltipCallback,\n TooltipConfig,\n TooltipNativeAnimation,\n TooltipPosition,\n} from './tooltip/tooltip-types'\n\n// Viewport context - provides screen dimensions for vw/vh units\nexport { viewportRegistry, type ViewportSize } from './viewport-context'\n\n// Render context - isolates global state per mount point (advanced usage)\nexport { getRenderContext, type RenderContext } from './render-context'\n\n/**\n * Consumers can import JSX runtime from here:\n * import { jsx, jsxs, Fragment } from \"@number10/phaserjsx/jsx-runtime\";\n */\nexport { Fragment, jsx, jsxs } from './jsx-runtime'\n\n// Development configuration and debugging utilities\nexport { DebugLogger, DevConfig, DevPresets } from './dev-config'\n\n// SVG to texture utilities\nexport type { SVGTextureConfig } from './hooks-svg'\nexport { svgToTexture } from './utils/svg-texture'\n"],"names":["setColorMode","n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","sources":["../src/components/appliers/applyGraphics.ts","../src/components/appliers/applyGraphicsLayout.ts","../src/components/appliers/applyPhaser.ts","../src/components/appliers/applyTransform.ts","../src/components/creators/createGraphicsLayout.ts","../src/components/creators/createPhaser.ts","../src/components/creators/createTransform.ts","../src/components/primitives/graphics.ts","../src/components/appliers/applyImage.ts","../src/components/appliers/applyImageLayout.ts","../src/components/creators/createImageLayout.ts","../src/components/primitives/image.ts","../src/components/appliers/applyNineSlice.ts","../src/components/appliers/applyNineSliceLayout.ts","../src/components/creators/createNineSliceLayout.ts","../src/components/primitives/nineslice.ts","../src/particles/emit-zone.ts","../src/particles/preset-registry.ts","../src/particles/utils.ts","../src/components/appliers/applyParticles.ts","../src/components/appliers/applyParticlesLayout.ts","../src/components/creators/createParticlesLayout.ts","../src/components/primitives/particles.ts","../src/components/appliers/applySprite.ts","../src/components/appliers/applySpriteLayout.ts","../src/components/creators/createSpriteLayout.ts","../src/components/primitives/sprite.ts","../src/components/appliers/applyText.ts","../src/components/appliers/applyTextLayout.ts","../src/components/creators/createTextLayout.ts","../src/components/primitives/text.ts","../src/components/primitives/tilesprite.ts","../src/components/appliers/applyBackground.ts","../src/components/appliers/applyGestures.ts","../src/components/appliers/applyLayout.ts","../src/components/appliers/applyTooltip.ts","../src/components/creators/createBackground.ts","../src/components/creators/createGestures.ts","../src/components/creators/createLayout.ts","../src/components/primitives/view.ts","../src/components/custom/Sprite.tsx","../src/components/custom/TileSprite.tsx","../src/components/index.ts","../src/camera/use-camera-fx.ts","../src/camera/camera-fx-registry.ts","../src/fx/use-fx.ts","../src/fx/fx-creators/blur.ts","../src/fx/fx-creators/color-matrix.ts","../src/fx/fx-creators/glow.ts","../src/fx/fx-creators/pixelate.ts","../src/fx/fx-creators/shadow.ts","../src/fx/fx-creators/vignette.ts","../src/fx/fx-registry.ts","../src/fx/convenience-hooks/use-blur.ts","../src/fx/convenience-hooks/use-glow.ts","../src/fx/convenience-hooks/use-shadow.ts","../src/memo.ts","../src/particles/use-particles.ts","../src/plugin.ts","../src/colors/use-color-mode.ts","../src/colors/use-colors.ts","../src/colors/color-theme-helpers.ts","../src/colors/preset-manager.ts","../src/design-tokens/use-theme-tokens.ts","../src/index.ts"],"sourcesContent":["/**\n * Graphics-specific property appliers\n */\nimport type Phaser from 'phaser'\nimport type { GameObjectWithLayout } from '../../layout/types'\nimport type { GraphicsBaseProps } from '../primitives/graphics'\n\n/**\n * Graphics node with draw dependencies tracking\n */\ntype GraphicsWithDrawDeps = Phaser.GameObjects.Graphics &\n GameObjectWithLayout & {\n __drawDependencies?: unknown[] | undefined\n }\n\n/**\n * Shallow comparison of dependency arrays\n * @param a - First array\n * @param b - Second array\n * @returns True if arrays are equal\n */\nfunction shallowEqual(a?: unknown[], b?: unknown[]): boolean {\n if (!a || !b) return a === b\n if (a.length !== b.length) return false\n return a.every((val, i) => val === b[i])\n}\n\n/**\n * Apply Graphics-specific props (onDraw, autoClear, dependencies)\n * @param node - Graphics node\n * @param _prev - Previous props (unused, dependencies stored on node)\n * @param next - New props\n */\nexport function applyGraphicsProps(\n node: Phaser.GameObjects.Graphics,\n _prev: Partial<GraphicsBaseProps>,\n next: Partial<GraphicsBaseProps>\n): void {\n // Check if dependencies changed (shallow compare)\n const prevDeps = (node as GraphicsWithDrawDeps).__drawDependencies\n const nextDeps = next.dependencies\n const depsChanged = !shallowEqual(prevDeps, nextDeps)\n\n // Redraw if dependencies changed and onDraw callback exists\n if (depsChanged && next.onDraw) {\n // Clear graphics if autoClear is enabled (default: true)\n if (next.autoClear !== false) {\n node.clear()\n }\n\n // Execute draw callback\n next.onDraw(node, next)\n\n // Update stored dependencies\n ;(node as GraphicsWithDrawDeps).__drawDependencies = nextDeps\n }\n}\n","/**\n * Graphics layout property appliers\n */\nimport type Phaser from 'phaser'\nimport type { GameObjectWithLayout } from '../../layout/types'\nimport type { GraphicsBaseProps } from '../primitives/graphics'\n\n/**\n * Apply layout updates for Graphics (width/height changes)\n * @param node - Graphics node\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyGraphicsLayout(\n node: Phaser.GameObjects.Graphics,\n prev: Partial<GraphicsBaseProps>,\n next: Partial<GraphicsBaseProps>\n): void {\n // Update layout props to trigger parent layout recalculation (like Text does)\n ;(node as GameObjectWithLayout).__layoutProps = next as GraphicsBaseProps\n\n // Update size provider if dimensions or headless changed\n if (prev.width !== next.width || prev.height !== next.height || prev.headless !== next.headless) {\n ;(node as GameObjectWithLayout).__getLayoutSize = () => {\n if (next.headless ?? true) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: typeof next.width === 'number' ? next.width : 0,\n height: typeof next.height === 'number' ? next.height : 0,\n }\n }\n }\n}\n","/**\n * Applier for Phaser GameObject display properties\n */\nimport type { Display, PhaserProps } from '../../core-props'\n\n/**\n * Generic node type with Phaser GameObject display capabilities\n */\ntype PhaserNode = {\n visible: boolean\n setAlpha: (alpha: number) => void\n setDepth: (depth: number) => void\n}\n\n/**\n * Normalize visible prop to boolean for Phaser GameObject\n * - true / 'visible' → true (rendered)\n * - false / 'invisible' → false (not rendered, but takes space)\n * - 'none' → false (not rendered, no space)\n * @param visible - Visible prop value\n * @returns Boolean for Phaser GameObject.visible\n */\nfunction normalizeVisible(visible: boolean | Display | undefined): boolean {\n if (visible === undefined) return true // default: visible\n if (typeof visible === 'boolean') return visible\n // String values\n if (visible === 'visible') return true\n if (visible === 'invisible' || visible === 'none') return false\n return true\n}\n\n/**\n * Applies Phaser display properties (alpha, depth, visibility)\n * @param node - Node with Phaser GameObject properties\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyPhaserProps<T extends Partial<PhaserNode>>(\n node: T,\n prev: Partial<PhaserProps & { visible?: boolean | Display }>,\n next: Partial<PhaserProps & { visible?: boolean | Display }>\n): void {\n // Alpha\n if (prev.alpha !== next.alpha && typeof next.alpha === 'number') {\n node.setAlpha?.(next.alpha)\n }\n\n // Depth\n if (prev.depth !== next.depth && typeof next.depth === 'number') {\n node.setDepth?.(next.depth)\n }\n\n // Visibility - supports boolean and Display type (from LayoutProps)\n if (prev.visible !== next.visible) {\n const visibleValue = normalizeVisible(next.visible)\n node.visible = visibleValue\n }\n}\n","/**\n * Shared property appliers for component patching\n * These functions avoid code duplication when updating node properties\n */\nimport type { TransformProps } from '../../core-props'\n\n/**\n * Generic node type with transform capabilities\n */\ntype TransformNode = {\n x: number\n y: number\n rotation: number\n scaleX: number\n scaleY: number\n setScale: (x: number, y: number) => void\n}\n\n/**\n * Applies transform properties (position, rotation, scale)\n * @param node - Node with transform properties\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyTransformProps<T extends Partial<TransformNode>>(\n node: T,\n prev: Partial<TransformProps>,\n next: Partial<TransformProps>\n): void {\n // Position\n if (prev.x !== next.x && typeof next.x === 'number') {\n node.x = next.x\n }\n if (prev.y !== next.y && typeof next.y === 'number') {\n node.y = next.y\n }\n\n // Rotation\n if (prev.rotation !== next.rotation && typeof next.rotation === 'number') {\n node.rotation = next.rotation\n }\n\n // Scale - handle both unified scale and separate scaleX/scaleY\n const nextScale = next.scale as number | undefined\n const nextScaleX = next.scaleX as number | undefined\n const nextScaleY = next.scaleY as number | undefined\n const prevScale = prev.scale as number | undefined\n const prevScaleX = prev.scaleX as number | undefined\n const prevScaleY = prev.scaleY as number | undefined\n\n if (nextScale !== undefined && nextScale !== prevScale) {\n node.setScale?.(nextScale, nextScale)\n } else if (nextScaleX !== prevScaleX || nextScaleY !== prevScaleY) {\n const currentScaleX = node.scaleX ?? 1\n const currentScaleY = node.scaleY ?? 1\n const sx = nextScaleX ?? currentScaleX\n const sy = nextScaleY ?? currentScaleY\n node.setScale?.(sx, sy)\n }\n}\n","/**\n * Layout system initialization for Graphics component\n */\nimport type Phaser from 'phaser'\nimport type { GraphicsBaseProps } from '../primitives/graphics'\n\n/**\n * Setup layout system for Graphics component\n * @param graphics - Phaser Graphics instance\n * @param props - Initial props\n */\nexport function createGraphicsLayout(\n graphics: Phaser.GameObjects.Graphics,\n props: Partial<GraphicsBaseProps>\n): void {\n // Validation: headless=false requires explicit width/height\n if (props.headless === false) {\n if (typeof props.width !== 'number' || typeof props.height !== 'number') {\n throw new Error(\n 'Graphics component requires explicit width and height props when headless=false'\n )\n }\n }\n\n // Setup layout props (for layout system) - store ALL props like Text does\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(graphics as any).__layoutProps = props as GraphicsBaseProps\n\n // Setup layout size provider (returns explicit dimensions)\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(graphics as any).__getLayoutSize = () => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n if ((graphics as any).__layoutProps?.headless ?? true) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: props.width ?? 0,\n height: props.height ?? 0,\n }\n }\n\n // Store dependencies for comparison in patcher\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ;(graphics as any).__drawDependencies = props.dependencies\n}\n","/**\n * Creator for Phaser GameObject display properties\n */\nimport type { Display, PhaserProps } from '../../core-props'\n\n/**\n * Normalize visible prop to boolean for Phaser GameObject\n * - true / 'visible' → true (rendered)\n * - false / 'invisible' → false (not rendered, but takes space)\n * - 'none' → false (not rendered, no space)\n * @param visible - Visible prop value\n * @returns Boolean for Phaser GameObject.visible\n */\nfunction normalizeVisible(visible: boolean | Display | undefined): boolean {\n if (visible === undefined) return true // default: visible\n if (typeof visible === 'boolean') return visible\n // String values\n if (visible === 'visible') return true\n if (visible === 'invisible' || visible === 'none') return false\n return true\n}\n\n/**\n * Apply Phaser display properties during node creation\n * @param node - Node with Phaser GameObject capabilities\n * @param props - Initial props\n */\nexport function createPhaser<\n T extends {\n visible: boolean\n setDepth: (depth: number) => void\n setAlpha: (alpha: number) => void\n },\n>(node: T, props: Partial<PhaserProps & { visible?: boolean | Display }>): void {\n // Visibility - supports boolean and Display type (from LayoutProps)\n if (props.visible !== undefined) {\n node.visible = normalizeVisible(props.visible)\n }\n if (props.depth !== undefined) {\n node.setDepth(props.depth)\n }\n if (props.alpha !== undefined) {\n node.setAlpha(props.alpha)\n }\n}\n","/**\n * Shared property creators for component initialization\n * These functions avoid code duplication when creating nodes with initial properties\n */\nimport type { TransformProps } from '../../core-props'\n\n/**\n * Apply transform properties during node creation (geometric transformations only)\n * @param node - Node with transform capabilities\n * @param props - Initial props\n */\nexport function createTransform<\n T extends {\n setScale: (x: number, y: number) => void\n setRotation: (rotation: number) => void\n },\n>(node: T, props: Partial<TransformProps>): void {\n if (props.scaleX !== undefined || props.scaleY !== undefined) {\n node.setScale(\n (props.scaleX as number | undefined) ?? 1,\n (props.scaleY as number | undefined) ?? 1\n )\n }\n if (props.rotation !== undefined) {\n node.setRotation(props.rotation as number)\n }\n}\n","/**\n * Graphics component - Phaser Graphics GameObject (custom shapes)\n * Status: IMPLEMENTED ✅\n *\n * Design Decisions & Answers:\n * ===========================\n *\n * 1. Headless Default: TRUE ✅\n * Rationale: Graphics are typically decorative (custom shapes, effects).\n * They should NOT affect layout unless explicitly configured.\n * Use Cases:\n * - ✅ Headless (default): Debug visualizations, particle trails, decorative effects\n * - ❌ Layout-aware: Custom UI shapes (via headless=false + explicit width/height)\n *\n * 2. View Background vs. Graphics Component: CLEAR SEPARATION ✅\n * View Background (internal):\n * - Special role: Defines container dimensions\n * - Automatically managed by View component\n * - Marked with __isBackground flag\n * - Always excluded from layout calculations\n * Graphics Component (user-facing):\n * - Custom shapes for any purpose\n * - User controls drawing via onDraw callback\n * - Can be headless OR layout-aware (explicit)\n * - Independent GameObject, not tied to View\n *\n * 3. Layout Size Provider: EXPLICIT DIMENSIONS REQUIRED ✅\n * Decision: Option A - Require explicit width/height props for layout participation\n * Reasoning:\n * - Graphics have no inherent dimensions until drawn\n * - Calculating bounds dynamically is expensive (getBounds() forces geometry calc)\n * - Bounds change with every draw call (unstable for layout)\n * - Explicit dimensions = predictable layout behavior\n * Implementation:\n * - If headless=false: Require width/height props (throw error if missing)\n * - __getLayoutSize = () => ({ width: props.width!, height: props.height! })\n *\n * 4. Drawing API: IMPERATIVE CALLBACK ✅\n * Decision: Option A - onDraw callback (imperative)\n * Reasoning:\n * - Simplest API, full Phaser Graphics power\n * - No abstraction overhead\n * - Familiar to Phaser developers\n * - Flexible for complex shapes\n * Interface:\n * onDraw?: (graphics: Phaser.GameObjects.Graphics, props: GraphicsBaseProps) => void\n * Example:\n * <Graphics onDraw={(g) => {\n * g.fillStyle(0xff0000, 1)\n * g.fillCircle(50, 50, 50)\n * }} />\n * Future: Consider declarative shape components if demand is high\n *\n * 5. Redraw Strategy: DEPENDENCY-BASED ✅\n * Decision: Redraw when dependencies array changes (React useEffect style)\n * Behavior:\n * - autoClear=true (default): Clear graphics before each onDraw call\n * - dependencies=[...]: Only redraw when dependencies change (shallow compare)\n * - No dependencies: Redraw on every patch (expensive!)\n * Implementation:\n * - Store previous dependencies on graphics object\n * - Compare with current dependencies in patcher\n * - Call onDraw only if changed\n *\n * 6. Performance Optimization: GENERATETEXTURE PATH 🆕\n * Strategy for static graphics:\n * - Static graphics (no redraw) → Consider generateTexture() optimization\n * - Converts geometry to texture (faster rendering, loses vector quality)\n * - Trade-off: Memory (texture) vs. CPU (redraw)\n * Props:\n * - static?: boolean (if true, generate texture after first draw)\n * - textureKey?: string (cache key for generated texture)\n * Recommendation: Advanced feature, implement later if needed\n *\n * 7. Common Use Cases & Alternatives: DOCUMENTED ✅\n * Use Graphics For:\n * - ✅ Custom complex shapes (polygons, stars, bezier curves)\n * - ✅ Dynamic visualizations (graphs, charts)\n * - ✅ Progress bars with custom shapes\n * - ✅ Debug overlays (hitboxes, grids)\n * Use Alternatives For:\n * - ❌ Simple rectangles → Use View with backgroundColor\n * - ❌ Borders → Use View with borderColor/borderWidth\n * - ❌ Static shapes → Consider Image with pre-rendered texture\n * - ❌ Repeated patterns → Use TileSprite\n *\n * 8. Clear Behavior: CONFIGURABLE ✅\n * Decision: autoClear=true by default\n * Reasoning:\n * - Most use cases: Single shape per Graphics object\n * - Prevents accumulation of draw calls\n * - Override with autoClear=false for additive drawing\n * Edge Case: Multiple draw calls in onDraw → All executed, then cleared on next redraw\n *\n * Implementation Status:\n * ======================\n * [✅] Create graphics with scene.add.graphics()\n * [✅] Apply transform props via applyTransformProps\n * [✅] Setup onDraw callback invocation\n * [✅] Implement dependency-based redraw logic\n * [✅] Handle autoClear flag\n * [✅] Setup layout size provider (explicit width/height)\n * [✅] Validate width/height if headless=false\n * [✅] Example component with interactive demos\n * [❌] generateTexture optimization (future enhancement)\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyGraphicsProps } from '../appliers/applyGraphics'\nimport { applyGraphicsLayout } from '../appliers/applyGraphicsLayout'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createGraphicsLayout } from '../creators/createGraphicsLayout'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Base props for Graphics component\n */\nexport interface GraphicsBaseProps extends TransformProps, PhaserProps, LayoutProps {\n /**\n * Drawing callback - receives Graphics instance for custom drawing\n * Called on mount and when dependencies change\n * @param graphics - Phaser Graphics instance\n * @param props - Current props (for accessing dynamic values)\n */\n onDraw?: (graphics: Phaser.GameObjects.Graphics, props: GraphicsBaseProps) => void\n\n /**\n * If true, graphics is cleared before onDraw is called\n * Default: true (usually what you want)\n */\n autoClear?: boolean\n\n /**\n * Dependencies array - if any value changes, onDraw is re-executed\n * Similar to React useEffect dependencies\n */\n dependencies?: unknown[]\n}\n\n/**\n * Props for Graphics component\n */\nexport interface GraphicsProps\n extends GraphicsBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.Graphics> {}\n\n/**\n * Graphics creator - creates a Phaser Graphics object\n */\nexport const graphicsCreator: HostCreator<'Graphics'> = (scene, props) => {\n // Create graphics (position set via setPosition below)\n const graphics = scene.add.graphics()\n\n // Set initial position explicitly (Graphics doesn't take x/y in constructor like Text does)\n graphics.setPosition(props.x ?? 0, props.y ?? 0)\n\n // Apply transform props (scale, rotation)\n createTransform(graphics, props)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(graphics, props)\n\n // Setup layout system (props and size provider)\n createGraphicsLayout(graphics, props)\n\n // Execute initial draw if onDraw callback provided\n if (props.onDraw) {\n props.onDraw(graphics, props)\n }\n return graphics\n}\n\n/**\n * Graphics patcher - updates Graphics properties\n */\nexport const graphicsPatcher: HostPatcher<'Graphics'> = (node, prev, next) => {\n // Apply transform props (position, rotation, scale)\n applyTransformProps(node, prev, next)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, prev, next)\n\n // Apply Graphics-specific props (onDraw, autoClear, dependencies)\n applyGraphicsProps(node, prev, next)\n\n // Apply layout props and update size provider if needed\n applyGraphicsLayout(node, prev, next)\n}\n","/**\n * Applier for Image-specific properties\n */\nimport type Phaser from 'phaser'\nimport type { ImageBaseProps } from '../primitives/image'\n\n/**\n * Calculates scale factors for fit modes\n * @param image - Phaser Image object\n * @param targetWidth - Desired width\n * @param targetHeight - Desired height\n * @param fit - Fit mode\n * @returns Scale factors for x and y\n */\nfunction calculateFitScale(\n image: Phaser.GameObjects.Image,\n targetWidth: number,\n targetHeight: number,\n fit: 'fill' | 'contain' | 'cover' = 'fill'\n): { scaleX: number; scaleY: number } {\n const textureWidth = image.width\n const textureHeight = image.height\n\n if (textureWidth === 0 || textureHeight === 0) {\n return { scaleX: 1, scaleY: 1 }\n }\n\n if (fit === 'fill') {\n // Stretch to fill (may distort aspect ratio)\n return {\n scaleX: targetWidth / textureWidth,\n scaleY: targetHeight / textureHeight,\n }\n }\n\n const targetAspect = targetWidth / targetHeight\n const textureAspect = textureWidth / textureHeight\n\n if (fit === 'contain') {\n // Scale to fit within bounds, preserve aspect ratio\n const scale =\n targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth\n return { scaleX: scale, scaleY: scale }\n }\n\n if (fit === 'cover') {\n // Scale to cover bounds, preserve aspect ratio (may crop)\n const scale =\n targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth\n return { scaleX: scale, scaleY: scale }\n }\n\n return { scaleX: 1, scaleY: 1 }\n}\n\n/**\n * Applies Image-specific properties (texture, frame, tint, displaySize, fit)\n * @param image - Phaser Image object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyImageProps(\n image: Phaser.GameObjects.Image,\n prev: Partial<ImageBaseProps>,\n next: Partial<ImageBaseProps>\n): void {\n // Check if texture or frame changed\n const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame\n if (textureChanged && next.texture) {\n image.setTexture(next.texture, next.frame)\n }\n\n // Apply tint\n if (prev.tint !== next.tint) {\n if (typeof next.tint === 'number') {\n image.setTint(next.tint)\n } else {\n image.clearTint()\n }\n }\n\n // Apply origin if specified\n if (prev.originX !== next.originX || prev.originY !== next.originY) {\n const originX = next.originX ?? image.originX\n const originY = next.originY ?? image.originY\n image.setOrigin(originX, originY)\n }\n\n // Apply displayWidth/displayHeight with fit mode\n const displayWidthChanged = prev.displayWidth !== next.displayWidth\n const displayHeightChanged = prev.displayHeight !== next.displayHeight\n const fitChanged = prev.fit !== next.fit\n\n if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {\n if (typeof next.displayWidth === 'number' && typeof next.displayHeight === 'number') {\n const { scaleX, scaleY } = calculateFitScale(\n image,\n next.displayWidth,\n next.displayHeight,\n next.fit\n )\n image.setScale(scaleX, scaleY)\n } else if (typeof next.displayWidth === 'number') {\n // Only width specified - preserve aspect ratio\n const scale = next.displayWidth / image.width\n image.setScale(scale)\n } else if (typeof next.displayHeight === 'number') {\n // Only height specified - preserve aspect ratio\n const scale = next.displayHeight / image.height\n image.setScale(scale, scale)\n }\n }\n}\n","/**\n * Layout applier for Image components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps } from '../../core-props'\nimport type { LayoutSize } from '../../layout/index'\nimport type { ImageBaseProps } from '../primitives/image'\n\n/**\n * Applies layout props and updates layout size provider\n * @param image - Phaser Image object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyImageLayout(\n image: Phaser.GameObjects.Image & {\n __layoutProps?: ImageBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n prev: Partial<ImageBaseProps & LayoutProps>,\n next: Partial<ImageBaseProps & LayoutProps>\n): void {\n // Update layout props reference\n image.__layoutProps = next as ImageBaseProps\n\n // Update size provider if headless flag changed\n if (prev.headless !== next.headless) {\n image.__getLayoutSize = () => {\n if (image.__layoutProps?.headless) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: image.displayWidth,\n height: image.displayHeight,\n }\n }\n }\n}\n","/**\n * Layout creator for Image components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { ImageBaseProps } from '../primitives/image'\n\n/**\n * Creates layout infrastructure for an Image component\n * Attaches layout props and dynamic size provider\n * @param image - Phaser Image object\n * @param props - Image props including layout\n */\nexport function createImageLayout(\n image: Phaser.GameObjects.Image & {\n __layoutProps?: ImageBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n props: Partial<ImageBaseProps>\n): void {\n // Attach layout props for layout calculations\n image.__layoutProps = props as ImageBaseProps\n\n // Attach dynamic size provider\n // Headless images return minimal size 0.01x0.01 (participates in alignment, not spacing)\n // Layout-aware images return actual display dimensions\n image.__getLayoutSize = () => {\n if (image.__layoutProps?.headless) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: image.displayWidth,\n height: image.displayHeight,\n }\n }\n}\n","/**\n * Image component - Phaser Image GameObject (static texture)\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n *\n * 1. Component Role: TEXTURE RENDERING\n * Purpose: Display static textures in UI layouts (icons, avatars, illustrations)\n * Phaser Type: Phaser.GameObjects.Image (texture-based rendering)\n * Characteristics:\n * - Layout-aware by default (participates in parent layout)\n * - Auto-sizing based on texture dimensions (like HTML <img>)\n * - Supports Phaser texture system (atlases, frames)\n *\n * 2. Headless Default: FALSE ✅\n * Decision: Image participates in layout by default\n * Reasoning:\n * - Images are UI elements (icons, avatars, illustrations)\n * - Should affect parent container dimensions\n * - Similar to Text component behavior\n * Use Cases:\n * - ✅ Layout-aware (default): Icons, avatars, logos, UI illustrations\n * - ❌ Headless (optional): Decorative backgrounds, overlays, parallax layers\n * Usage:\n * <Image texture=\"icon\" /> // Layout-aware\n * <Image texture=\"bg\" headless={true} /> // Decorative (no layout impact)\n *\n * 3. Layout Size Provider: DISPLAY DIMENSIONS ✅\n * Implementation: Uses image.displayWidth and image.displayHeight\n * Behavior:\n * - Returns scaled display dimensions\n * - Rotation is IGNORED for layout-aware images (headless=false)\n * - Rotation only works with headless=true (no layout impact)\n * Reasoning:\n * - Flow layout is incompatible with rotation (causes positioning issues)\n * - Rotated images would overlap siblings in flow layout\n * - Matches Text component behavior\n * Example:\n * <Image texture=\"icon\" /> // ✅ Layout size: 64x64\n * <Image texture=\"icon\" rotation={Math.PI/4} /> // ⚠️ Rotation IGNORED, size: 64x64\n * <Image texture=\"icon\" rotation={Math.PI/4} headless={true} /> // ✅ Rotated, no layout\n * Recommendation: Use rotation only with headless=true or absolute positioning\n *\n * 4. Sizing Strategy: HYBRID APPROACH ✅\n * Auto-Size (default):\n * - No displayWidth/displayHeight → Use texture dimensions\n * - Like HTML <img> natural size\n * Explicit Size:\n * - displayWidth + displayHeight → Scale to fit\n * - fit prop controls aspect ratio handling\n * Example:\n * <Image texture=\"icon\" /> // Auto-size\n * <Image texture=\"icon\" displayWidth={64} displayHeight={64} fit=\"contain\" />\n *\n * 5. Fit Modes: CSS-LIKE BEHAVIOR ✅\n * Decision: Implement CSS object-fit equivalent\n * Modes:\n * - 'fill' (default): Stretch to fill bounds (may distort aspect ratio)\n * - 'contain': Scale to fit within bounds, preserve aspect ratio (letterbox)\n * - 'cover': Scale to cover bounds, preserve aspect ratio (crop)\n * Implementation: Calculate scale in applier based on fit mode\n *\n * 6. Origin Behavior: HEADLESS-AWARE ✅\n * Current: Like Text component\n * - Layout-aware (headless=false): Origin (0, 0) - top-left, UI-friendly\n * - Headless (headless=true): Origin (0.5, 0.5) - centered, game object semantics\n * Reasoning:\n * - UI elements align naturally with top-left origin\n * - Game objects (headless) work better centered\n * - Consistent with Text component behavior\n *\n * 7. Rotation Behavior: LIKE TEXT ✅\n * Decision: Rotation only supported with headless=true\n * Reasoning:\n * - Flow layout is incompatible with rotation\n * - Matches Text component constraints\n * - Props normalized: rotation removed if headless=false\n *\n * 8. Common Patterns:\n * Icon:\n * <View direction=\"row\" gap={10}>\n * <Image texture=\"icon-user\" />\n * <Text text=\"Username\" />\n * </View>\n * Avatar:\n * <Image texture=\"avatar\" displayWidth={64} displayHeight={64} fit=\"cover\" />\n * Background (headless):\n * <Image texture=\"bg\" headless={true} alpha={0.5} />\n *\n * 9. Performance Considerations:\n * - Texture atlases recommended (reduce texture switches)\n * - Static images are efficient (single draw call)\n * - Texture changes trigger re-render\n * - Scaling via displayWidth/displayHeight is GPU-accelerated\n *\n * 10. Known Limitations:\n * - Rotation only supported with headless=true (ignored for layout-aware)\n * - Missing textures show Phaser default (white square)\n * - No built-in loading states\n * - Texture must be preloaded before use\n *\n * Implementation Status:\n * ======================\n * [✅] Phaser Image creation with texture/frame support\n * [✅] Transform props (position, scale, alpha)\n * [✅] Layout system integration (__layoutProps, __getLayoutSize)\n * [✅] Origin handling (headless-aware: 0,0 vs 0.5,0.5)\n * [✅] Display size with fit modes (contain/cover/fill)\n * [✅] Tint support\n * [✅] Texture and frame patching\n * [⚠️] Rotation - Only with headless=true (ignored for layout-aware)\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyImageProps } from '../appliers/applyImage'\nimport { applyImageLayout } from '../appliers/applyImageLayout'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createImageLayout } from '../creators/createImageLayout'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Base props for Image component\n */\nexport interface ImageBaseProps extends TransformProps, PhaserProps, LayoutProps {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas */\n frame?: string | number\n\n /** Tint color applied to image (0xRRGGBB) */\n tint?: number | undefined\n\n /** Display width (scales image to fit) */\n displayWidth?: number | undefined\n\n /** Display height (scales image to fit) */\n displayHeight?: number | undefined\n\n /**\n * How image should fit within bounds (if displayWidth/displayHeight set)\n * - 'fill': Stretch to fill (default, may distort aspect ratio)\n * - 'contain': Scale to fit within bounds, preserve aspect ratio\n * - 'cover': Scale to cover bounds, preserve aspect ratio (may crop)\n */\n fit?: 'fill' | 'contain' | 'cover'\n\n /** Origin X (0-1, default 0.5) */\n originX?: number\n\n /** Origin Y (0-1, default 0.5) */\n originY?: number\n}\n\n/**\n * Props for primitive image component (internal use only)\n * For public API, use ImageProps from custom/Image.tsx\n */\nexport interface ImagePrimitiveProps\n extends ImageBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.Image> {}\n\n/**\n * Image creator - creates a Phaser Image object\n */\nexport const imageCreator: HostCreator<'Image'> = (scene, props) => {\n const image = scene.add.image(props.x ?? 0, props.y ?? 0, props.texture, props.frame)\n\n // Set origin based on headless flag\n // Headless: (0.5, 0.5) - centered, works naturally with rotation/scale\n // Layout-aware: (0, 0) - top-left, aligns with layout flow\n if (props.headless) {\n image.setOrigin(0.5, 0.5)\n } else {\n image.setOrigin(0, 0)\n }\n\n // Apply custom origin if specified\n if (props.originX !== undefined || props.originY !== undefined) {\n image.setOrigin(props.originX ?? image.originX, props.originY ?? image.originY)\n }\n\n // Normalize props for headless objects\n // Headless objects are positioned as points - no spacing or rotation constraints\n const normalizedProps = { ...props } as Record<string, unknown>\n if (props.headless) {\n // Remove spacing props (headless = positioned as point)\n delete normalizedProps.padding\n delete normalizedProps.margin\n delete normalizedProps.gap\n } else {\n // Remove rotation (only supported with headless=true)\n if (normalizedProps.rotation !== undefined) {\n delete normalizedProps.rotation\n }\n }\n\n // Apply transform props (scale, rotation if headless)\n createTransform(image, normalizedProps)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(image, normalizedProps)\n\n // Apply image-specific props (tint, displaySize, fit)\n if (props.tint !== undefined) {\n image.setTint(props.tint)\n }\n\n // Apply displayWidth/displayHeight if specified\n if (props.displayWidth !== undefined || props.displayHeight !== undefined) {\n if (props.displayWidth !== undefined && props.displayHeight !== undefined) {\n // Both specified - use fit mode\n const fit = props.fit ?? 'fill'\n const textureWidth = image.width\n const textureHeight = image.height\n\n if (textureWidth > 0 && textureHeight > 0) {\n if (fit === 'fill') {\n image.setDisplaySize(props.displayWidth, props.displayHeight)\n } else if (fit === 'contain') {\n const targetAspect = props.displayWidth / props.displayHeight\n const textureAspect = textureWidth / textureHeight\n const scale =\n targetAspect > textureAspect\n ? props.displayHeight / textureHeight\n : props.displayWidth / textureWidth\n image.setScale(scale)\n } else if (fit === 'cover') {\n const targetAspect = props.displayWidth / props.displayHeight\n const textureAspect = textureWidth / textureHeight\n const scale =\n targetAspect < textureAspect\n ? props.displayHeight / textureHeight\n : props.displayWidth / textureWidth\n image.setScale(scale)\n }\n }\n } else if (props.displayWidth !== undefined) {\n // Only width - preserve aspect ratio\n const scale = props.displayWidth / image.width\n image.setScale(scale)\n } else if (props.displayHeight !== undefined) {\n // Only height - preserve aspect ratio\n const scale = props.displayHeight / image.height\n image.setScale(scale)\n }\n }\n\n // Setup layout system (props and size provider)\n createImageLayout(image, normalizedProps)\n\n // Call onReady callback if provided\n if (props.onReady) {\n props.onReady(image)\n }\n\n return image\n}\n\n/**\n * Image patcher - updates Image properties\n */\nexport const imagePatcher: HostPatcher<'Image'> = (node, prev, next) => {\n // Update origin if headless flag changed\n if (prev.headless !== next.headless) {\n if (next.headless) {\n node.setOrigin(0.5, 0.5) // Headless: centered\n } else {\n node.setOrigin(0, 0) // Layout-aware: top-left\n }\n }\n\n // Normalize props for headless objects\n const normalizedPrev = { ...prev } as Record<string, unknown>\n const normalizedNext = { ...next } as Record<string, unknown>\n\n if (next.headless) {\n // Remove spacing props (headless = positioned as point)\n delete normalizedNext.padding\n delete normalizedNext.margin\n delete normalizedNext.gap\n } else {\n // Remove rotation (only supported with headless=true)\n if (normalizedNext.rotation !== undefined) {\n delete normalizedNext.rotation\n }\n }\n\n if (prev.headless) {\n delete normalizedPrev.padding\n delete normalizedPrev.margin\n delete normalizedPrev.gap\n } else {\n if (normalizedPrev.rotation !== undefined) {\n delete normalizedPrev.rotation\n }\n }\n\n // Apply transform props (position, rotation only if headless, scale)\n applyTransformProps(node, normalizedPrev, normalizedNext)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, normalizedPrev, normalizedNext)\n\n // Apply image-specific props (texture, frame, tint, displaySize, fit)\n applyImageProps(node, normalizedPrev, normalizedNext)\n\n // Apply layout props and update size provider if needed\n applyImageLayout(node, normalizedPrev, normalizedNext)\n}\n","/**\n * Applier for NineSlice-specific properties\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps } from '../../core-props'\nimport type { NineSliceSpecificProps } from '../primitives/nineslice'\n\n/**\n * Applies NineSlice-specific properties (texture, frame, slice dimensions)\n * @param nineSlice - Phaser NineSlice object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyNineSliceProps(\n nineSlice: Phaser.GameObjects.NineSlice,\n prev: Partial<NineSliceSpecificProps & LayoutProps>,\n next: Partial<NineSliceSpecificProps & LayoutProps>\n): void {\n // Check if texture or frame changed\n const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame\n if (textureChanged && next.texture) {\n nineSlice.setTexture(next.texture, next.frame)\n }\n\n // Check if slice dimensions changed\n const sliceChanged =\n prev.leftWidth !== next.leftWidth ||\n prev.rightWidth !== next.rightWidth ||\n prev.topHeight !== next.topHeight ||\n prev.bottomHeight !== next.bottomHeight\n\n if (sliceChanged) {\n const width = typeof next.width === 'number' ? next.width : nineSlice.width\n const height = typeof next.height === 'number' ? next.height : nineSlice.height\n\n nineSlice.setSlices(\n width,\n height,\n next.leftWidth ?? prev.leftWidth ?? 0,\n next.rightWidth ?? prev.rightWidth ?? 0,\n next.topHeight ?? prev.topHeight,\n next.bottomHeight ?? prev.bottomHeight\n )\n }\n\n // Check if size changed (independent of slice changes)\n const prevWidth = typeof prev.width === 'number' ? prev.width : nineSlice.width\n const nextWidth = typeof next.width === 'number' ? next.width : nineSlice.width\n const prevHeight = typeof prev.height === 'number' ? prev.height : nineSlice.height\n const nextHeight = typeof next.height === 'number' ? next.height : nineSlice.height\n\n if (prevWidth !== nextWidth || prevHeight !== nextHeight) {\n nineSlice.setSize(nextWidth, nextHeight)\n }\n\n // Check if tint changed\n if (prev.tint !== next.tint) {\n if (next.tint !== undefined) {\n nineSlice.setTint(next.tint)\n } else {\n nineSlice.clearTint()\n }\n }\n}\n","/**\n * Layout applier for NineSlice components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { NineSliceBaseProps } from '../primitives/nineslice'\n\n/**\n * Applies layout properties for NineSlice components\n * Updates layout props when properties change\n * @param nineSlice - Phaser NineSlice object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyNineSliceLayout(\n nineSlice: Phaser.GameObjects.NineSlice & {\n __layoutProps?: NineSliceBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n prev: Partial<NineSliceBaseProps>,\n next: Partial<NineSliceBaseProps>\n): void {\n // Update layout props to trigger parent layout recalculation\n nineSlice.__layoutProps = next as NineSliceBaseProps\n\n // Update size provider if dimensions changed\n if (prev.width !== next.width || prev.height !== next.height) {\n nineSlice.__getLayoutSize = () => {\n return {\n width: nineSlice.width,\n height: nineSlice.height,\n }\n }\n }\n}\n","/**\n * Layout creator for NineSlice components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { NineSliceBaseProps } from '../primitives/nineslice'\n\n/**\n * Creates layout infrastructure for a NineSlice component\n * Attaches layout props and dynamic size provider\n * @param nineSlice - Phaser NineSlice object\n * @param props - NineSlice props including layout\n */\nexport function createNineSliceLayout(\n nineSlice: Phaser.GameObjects.NineSlice & {\n __layoutProps?: NineSliceBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n props: Partial<NineSliceBaseProps>\n): void {\n // Attach layout props for layout calculations\n nineSlice.__layoutProps = props as NineSliceBaseProps\n\n // Attach dynamic size provider using NineSlice dimensions\n nineSlice.__getLayoutSize = () => {\n return {\n width: nineSlice.width,\n height: nineSlice.height,\n }\n }\n}\n","/**\n * NineSlice component - Phaser NineSlice GameObject for scalable UI panels\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n *\n * 1. Component Role: SCALABLE UI PANELS\n * Purpose: Create resizable UI elements that preserve border/corner integrity\n * Phaser Type: Phaser.GameObjects.NineSlice (9-slice scaling)\n * Use Cases:\n * - Buttons with fixed corner radius\n * - Dialog boxes with preserved borders\n * - Progress bars with capped ends\n * - Panels that scale without distorting decorative edges\n *\n * 2. Nine-Slice Scaling Concept:\n * Texture divided into 9 regions:\n * ┌─────┬─────────┬─────┐\n * │ TL │ Top │ TR │ (corners + edges)\n * ├─────┼─────────┼─────┤\n * │Left │ Center │Right│ (center scales, edges stretch)\n * ├─────┼─────────┼─────┤\n * │ BL │ Bottom │ BR │ (corners stay fixed)\n * └─────┴─────────┴─────┘\n * Behavior:\n * - Corners: Never scale (preserve pixel-perfect)\n * - Edges: Stretch along one axis (top/bottom: horizontal, left/right: vertical)\n * - Center: Scales in both directions\n * Benefit: UI elements scale to any size without visual distortion\n *\n * 3. Three-Slice Mode (Optional):\n * Feature: Omit topHeight/bottomHeight for horizontal-only slicing\n * Use Case: Horizontal buttons, progress bars\n * Layout:\n * ┌─────┬─────────────────┬─────┐\n * │Left │ Center │Right│\n * └─────┴─────────────────┴─────┘\n * Props: Only leftWidth + rightWidth required\n *\n * 4. Headless Default: FALSE ✅\n * Decision: NineSlice participates in layout by default\n * Reasoning:\n * - NineSlice is a UI element (buttons, panels, containers)\n * - Should affect parent container dimensions\n * - Similar to View component (container semantics)\n * Use Cases:\n * - ✅ Layout-aware (default): Buttons, panels, dialogs, cards\n * - ❌ Headless (optional): Background overlays, decorative frames\n * Usage:\n * <NineSlice texture=\"panel\" leftWidth={16} rightWidth={16} width={200} height={100} />\n * <NineSlice texture=\"frame\" headless={true} /> // Decorative\n *\n * 5. Layout Size Provider:\n * Implementation: Uses explicit width/height (required props)\n * Reasoning:\n * - NineSlice requires explicit dimensions (Phaser constructor param)\n * - No auto-sizing (unlike Text)\n * - Dimensions always known and stable\n * __getLayoutSize:\n * return { width: nineSlice.width, height: nineSlice.height }\n * Note: getBounds() not needed (no rotation typically applied)\n *\n * 6. Slice Configuration:\n * Required Props:\n * - texture: string (texture key)\n * - leftWidth: number (pixels)\n * - rightWidth: number (pixels)\n * - width: number (total width)\n * - height: number (total height)\n * Optional Props:\n * - topHeight: number (9-slice mode, default: 0 for 3-slice)\n * - bottomHeight: number (9-slice mode, default: 0 for 3-slice)\n * - frame: string | number (texture atlas frame)\n * Validation:\n * - Width must be >= leftWidth + rightWidth\n * - Height must be >= topHeight + bottomHeight\n * - Slice widths/heights define source texture regions\n *\n * 7. Inner Bounds Feature:\n * Purpose: Calculate content area excluding slices\n * Use Case: Position children inside panel borders\n * Calculation:\n * innerBounds = {\n * x: leftWidth,\n * y: topHeight,\n * width: totalWidth - leftWidth - rightWidth,\n * height: totalHeight - topHeight - bottomHeight\n * }\n * Access:\n * const ref = useRef<NineSliceRef>(null)\n * <NineSlice ref={ref} ... />\n * console.log(ref.current?.innerBounds) // { x, y, width, height }\n * Pattern: Useful for padding-aware content positioning\n *\n * 8. Ref Extension:\n * Feature: NineSliceRef provides slice metadata\n * Properties:\n * - node: Phaser.GameObjects.NineSlice (the GameObject)\n * - leftWidth, rightWidth, topHeight, bottomHeight: Slice dimensions\n * - innerBounds: Content area calculation\n * Usage:\n * const panelRef = useRef<NineSliceRef>(null)\n * // Access slice info for child positioning\n * const { innerBounds } = panelRef.current\n *\n * 9. Common Patterns:\n * Button:\n * <NineSlice\n * texture=\"button\"\n * leftWidth={16} rightWidth={16}\n * topHeight={16} bottomHeight={16}\n * width={200} height={60}\n * >\n * <Text text=\"Click Me\" />\n * </NineSlice>\n * Dialog Box:\n * <NineSlice\n * texture=\"panel\"\n * leftWidth={32} rightWidth={32}\n * topHeight={32} bottomHeight={32}\n * width={400} height={300}\n * >\n * <View padding={32}> {/* Padding matches slice sizes * }\n * <Text text=\"Dialog Content\" />\n * </View>\n * </NineSlice>\n * Progress Bar (3-slice):\n * <NineSlice\n * texture=\"progressbar\"\n * leftWidth={8} rightWidth={8}\n * width={progress * 200} height={20}\n * />\n *\n * 10. Performance Considerations:\n * - Efficient rendering (single draw call per NineSlice)\n * - Texture atlases recommended (reduce texture switches)\n * - Scaling performance: No geometry regeneration needed\n * - Slice configuration: Calculated once on creation\n * - Dynamic resizing: Efficiently handled by Phaser\n *\n * 11. Known Limitations:\n * - Requires pre-designed 9-slice texture\n * - Slice dimensions must match source texture layout exactly\n * - Rotation not recommended (distorts slice alignment)\n * - Can't animate slice dimensions (only width/height)\n * - No rounded corner support (must be in texture)\n *\n * Implementation Status:\n * ======================\n * [✅] Phaser NineSlice creation with slice configuration\n * [✅] Transform props (position, scale, alpha, depth)\n * [✅] Layout system integration (__layoutProps, __getLayoutSize)\n * [✅] Width/height as layout props (explicit sizing)\n * [✅] Three-slice mode support (optional topHeight/bottomHeight)\n * [✅] NineSliceRef with innerBounds calculation\n * [✅] Slice dimension validation\n * [✅] Theme system integration\n * [✅] Dynamic resizing support (width/height patching)\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyNineSliceProps } from '../appliers/applyNineSlice'\nimport { applyNineSliceLayout } from '../appliers/applyNineSliceLayout'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createNineSliceLayout } from '../creators/createNineSliceLayout'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Inner bounds of a NineSlice - the content area excluding slices\n */\nexport interface NineSliceInnerBounds {\n /**\n * X offset from left edge (equals leftWidth)\n */\n x: number\n /**\n * Y offset from top edge (equals topHeight)\n */\n y: number\n /**\n * Width of inner content area (totalWidth - leftWidth - rightWidth)\n */\n width: number\n /**\n * Height of inner content area (totalHeight - topHeight - bottomHeight)\n */\n height: number\n}\n\n/**\n * Extended NineSlice reference with slice information and inner bounds\n */\nexport interface NineSliceRef {\n /**\n * The underlying Phaser NineSlice GameObject\n */\n node: Phaser.GameObjects.NineSlice | null\n /**\n * Width of the left slice in pixels\n */\n leftWidth: number\n /**\n * Width of the right slice in pixels\n */\n rightWidth: number\n /**\n * Height of the top slice in pixels (0 for 3-slice mode)\n */\n topHeight: number\n /**\n * Height of the bottom slice in pixels (0 for 3-slice mode)\n */\n bottomHeight: number\n /**\n * Inner content bounds excluding slices\n * Useful for positioning content within the NineSlice\n */\n innerBounds: NineSliceInnerBounds\n}\n\n/**\n * NineSlice-specific properties for texture and slice configuration\n */\nexport interface NineSliceSpecificProps {\n /**\n * Texture key to use for the NineSlice\n */\n texture: string\n\n /**\n * Optional tint to apply to the NineSlice\n */\n tint?: number | undefined\n\n /**\n * Optional frame within the texture atlas\n */\n frame?: string | number\n\n /**\n * Width of the left slice (in pixels of source texture)\n */\n leftWidth: number\n\n /**\n * Width of the right slice (in pixels of source texture)\n */\n rightWidth: number\n\n /**\n * Height of the top slice (in pixels of source texture)\n * Optional - omit for 3-slice mode (horizontal only)\n */\n topHeight?: number\n\n /**\n * Height of the bottom slice (in pixels of source texture)\n * Optional - omit for 3-slice mode (horizontal only)\n */\n bottomHeight?: number\n}\n\n/**\n * Base props for NineSlice - composing shared prop groups\n * Note: No InteractionProps - interaction should be handled by parent View container\n */\nexport interface NineSliceBaseProps\n extends TransformProps,\n PhaserProps,\n LayoutProps,\n NineSliceSpecificProps {}\n\n/**\n * Props for NineSlice primitive - extends base props with JSX-specific props\n * Renamed to avoid conflict with custom NineSlice wrapper\n */\nexport interface NineSlicePrimitiveProps\n extends NineSliceBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.NineSlice> {}\n\n/**\n * NineSlice creator - creates a Phaser NineSlice object\n */\nexport const nineSliceCreator: HostCreator<'NineSlice'> = (scene, props) => {\n // For width/height, use a small default that will be overridden by layout system\n // This prevents the NineSlice from being created with huge dimensions\n const initialWidth = typeof props.width === 'number' ? props.width : 64\n const initialHeight = typeof props.height === 'number' ? props.height : 64\n\n const nineSlice = scene.add.nineslice(\n props.x ?? 0,\n props.y ?? 0,\n props.texture,\n props.frame,\n initialWidth,\n initialHeight,\n props.leftWidth,\n props.rightWidth,\n props.topHeight,\n props.bottomHeight\n )\n nineSlice.setOrigin(0, 0) // Top-left origin for easier layout handling as it is in UI\n\n // Apply tint if provided\n if (props.tint !== undefined) {\n nineSlice.setTint(props.tint)\n }\n\n // Apply transform props (scale, rotation)\n createTransform(nineSlice, props)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(nineSlice, props)\n\n // Setup layout system (props and size provider)\n createNineSliceLayout(nineSlice, props)\n\n return nineSlice\n}\n\n/**\n * NineSlice patcher - updates NineSlice properties\n */\nexport const nineSlicePatcher: HostPatcher<'NineSlice'> = (node, prev, next) => {\n // Apply transform props (position, rotation, scale)\n applyTransformProps(node, prev, next)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, prev, next)\n\n // Apply NineSlice-specific props (texture, frame, slice dimensions)\n applyNineSliceProps(node, prev, next)\n\n // Apply layout props and update size provider if needed\n applyNineSliceLayout(node, prev, next)\n}\n","/**\n * Emit zone helpers for particle emitters\n */\nimport Phaser from 'phaser'\nimport type { SizeValue } from '../core-props'\n\n/**\n * Supported zone shapes\n */\nexport type ParticleZoneShape = 'rect' | 'circle' | 'ellipse' | 'line'\n\n/**\n * Supported death zone modes\n */\nexport type ParticleDeathZoneMode = 'onEnter' | 'onLeave'\n\ntype ZoneConfigBase = {\n shape: ParticleZoneShape\n width?: number\n height?: number\n radius?: number\n x?: number\n y?: number\n endX?: number\n endY?: number\n}\n\n/**\n * Emit zone config\n */\nexport interface ParticleZoneConfig extends ZoneConfigBase {\n type?: 'random' | 'edge'\n}\n\n/**\n * Exclusion zone config\n * Death zones use particle world positions for evaluation,\n * but coordinates should be specified relative to the emitter position\n */\nexport interface ParticleExclusionZoneConfig extends ZoneConfigBase {\n /**\n * Death zone mode - evaluated using particle world positions\n */\n mode?: ParticleDeathZoneMode\n}\n\nexport type EmitZoneConfig = {\n type: 'random' | 'edge'\n source: Phaser.Geom.Rectangle | Phaser.Geom.Circle | Phaser.Geom.Ellipse | Phaser.Geom.Line\n}\n\nexport type DeathZoneConfig = {\n type: ParticleDeathZoneMode\n source: Phaser.Geom.Rectangle | Phaser.Geom.Circle | Phaser.Geom.Ellipse | Phaser.Geom.Line\n}\n\ntype ZoneSize = { width?: number; height?: number }\n\nfunction resolveNumericSize(value?: SizeValue): number | undefined {\n return typeof value === 'number' ? value : undefined\n}\n\nfunction resolveZoneSize(zone: ZoneConfigBase, fallback: ZoneSize): ZoneSize {\n const size: ZoneSize = {}\n const width = zone.width ?? fallback.width\n const height = zone.height ?? fallback.height\n if (width !== undefined) size.width = width\n if (height !== undefined) size.height = height\n return size\n}\n\nfunction buildZoneSource(\n zone: ZoneConfigBase,\n fallbackSize: ZoneSize\n): Phaser.Geom.Rectangle | Phaser.Geom.Circle | Phaser.Geom.Ellipse | Phaser.Geom.Line | undefined {\n const baseX = zone.x ?? 0\n const baseY = zone.y ?? 0\n const { width, height } = resolveZoneSize(zone, fallbackSize)\n\n switch (zone.shape) {\n case 'rect':\n return new Phaser.Geom.Rectangle(baseX, baseY, width ?? 1, height ?? 1)\n case 'circle':\n return new Phaser.Geom.Circle(baseX, baseY, zone.radius ?? 1)\n case 'ellipse':\n return new Phaser.Geom.Ellipse(baseX, baseY, width ?? 1, height ?? 1)\n case 'line':\n return new Phaser.Geom.Line(\n baseX,\n baseY,\n zone.endX ?? baseX + (width ?? 1),\n zone.endY ?? baseY + (height ?? 1)\n )\n default:\n return undefined\n }\n}\n\n/**\n * Build a Phaser emitZone config from a lightweight zone definition\n */\nexport function buildEmitZone(\n zone: ParticleZoneConfig,\n fallbackSize: ZoneSize = {}\n): EmitZoneConfig | undefined {\n const type = zone.type ?? 'random'\n const source = buildZoneSource(zone, fallbackSize)\n\n if (!source) return undefined\n\n return { type, source }\n}\n\n/**\n * Create an emit zone using layout size as a fallback\n */\nexport function buildEmitZoneFromLayout(\n zone: ParticleZoneConfig,\n width?: SizeValue,\n height?: SizeValue\n): EmitZoneConfig | undefined {\n const fallback: ZoneSize = {}\n const resolvedWidth = resolveNumericSize(width)\n const resolvedHeight = resolveNumericSize(height)\n if (resolvedWidth !== undefined) fallback.width = resolvedWidth\n if (resolvedHeight !== undefined) fallback.height = resolvedHeight\n return buildEmitZone(zone, fallback)\n}\n\n/**\n * Build a Phaser deathZone config from a lightweight exclusion definition\n */\nexport function buildDeathZone(\n zone: ParticleExclusionZoneConfig,\n fallbackSize: ZoneSize = {}\n): DeathZoneConfig | undefined {\n const type = zone.mode ?? 'onEnter'\n\n // Zones are in container-relative coordinates\n // No need to adjust since emitter is at container origin (0,0) with origin(0,0)\n const source = buildZoneSource(zone, fallbackSize)\n\n if (!source) return undefined\n\n return { type, source }\n}\n\n/**\n * Create death zones using layout size as a fallback\n */\nexport function buildDeathZonesFromLayout(\n zones: ParticleExclusionZoneConfig | ParticleExclusionZoneConfig[] | undefined,\n width?: SizeValue,\n height?: SizeValue\n): DeathZoneConfig[] | undefined {\n if (!zones) return undefined\n const list = Array.isArray(zones) ? zones : [zones]\n const fallback: ZoneSize = {}\n const resolvedWidth = resolveNumericSize(width)\n const resolvedHeight = resolveNumericSize(height)\n if (resolvedWidth !== undefined) fallback.width = resolvedWidth\n if (resolvedHeight !== undefined) fallback.height = resolvedHeight\n\n const deathZones = list\n .map((zone) => buildDeathZone(zone, fallback))\n .filter((zone): zone is DeathZoneConfig => Boolean(zone))\n\n return deathZones.length > 0 ? deathZones : undefined\n}\n","/**\n * Particle preset registry - typed presets with extension support\n */\nimport type Phaser from 'phaser'\n\n/**\n * Built-in particle preset names\n */\nexport type BuiltInParticlePresetName = 'explosion' | 'trail' | 'rain' | 'snow' | 'sparkle'\n\n/**\n * Extension point for custom particle preset names\n * Use declaration merging to add custom presets:\n * @example\n * ```typescript\n * declare module '@number10/phaserjsx' {\n * interface ParticlePresetExtensions {\n * myPreset: 'myPreset'\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ParticlePresetExtensions {}\n\n/**\n * Available particle preset names (built-in + extensions)\n */\nexport type ParticlePresetName =\n | BuiltInParticlePresetName\n | (keyof ParticlePresetExtensions extends never ? never : keyof ParticlePresetExtensions)\n\n/**\n * Phaser emitter config alias\n */\nexport type ParticleEmitterConfig = Phaser.Types.GameObjects.Particles.ParticleEmitterConfig\n\n/**\n * Preset definition for component/theme props\n */\nexport interface ParticlePresetDefinition {\n preset?: ParticlePresetName\n config?: ParticleEmitterConfig\n}\n\n/**\n * Map of built-in particle presets to emitter configs\n */\nexport const PARTICLE_PRESET_REGISTRY: Record<BuiltInParticlePresetName, ParticleEmitterConfig> = {\n explosion: {\n speed: { min: 120, max: 320 },\n scale: { start: 1, end: 0 },\n alpha: { start: 1, end: 0 },\n lifespan: 600,\n quantity: 24,\n blendMode: 'ADD',\n },\n trail: {\n speed: { min: 30, max: 80 },\n scale: { start: 0.6, end: 0 },\n alpha: { start: 0.8, end: 0 },\n lifespan: 700,\n frequency: 40,\n },\n rain: {\n speed: { min: 320, max: 520 },\n angle: { min: 80, max: 100 },\n scale: { start: 0.5, end: 0.2 },\n alpha: { start: 0.6, end: 0.1 },\n lifespan: 1000,\n frequency: 20,\n },\n snow: {\n speed: { min: 40, max: 120 },\n angle: { min: 80, max: 100 },\n gravityY: 8,\n scale: { start: 0.6, end: 0.6 },\n alpha: { start: 0.8, end: 0.3 },\n lifespan: 2600,\n frequency: 80,\n },\n sparkle: {\n speed: { min: 20, max: 60 },\n scale: { start: 0.4, end: 0 },\n alpha: { start: 1, end: 0 },\n lifespan: 500,\n frequency: 60,\n blendMode: 'ADD',\n },\n}\n\n/**\n * Resolve a preset name with optional overrides\n * @param preset - Preset name (built-in or extension)\n * @param config - Optional overrides applied last\n * @returns Resolved emitter config\n */\nexport function resolveParticlePreset(\n preset?: ParticlePresetName,\n config: ParticleEmitterConfig = {}\n): ParticleEmitterConfig {\n const base = preset ? PARTICLE_PRESET_REGISTRY[preset as BuiltInParticlePresetName] : undefined\n\n if (preset && !base) {\n console.warn(`[Particles] Preset \"${String(preset)}\" not found in registry`)\n }\n\n return {\n ...(base ?? {}),\n ...config,\n }\n}\n","/**\n * Particle utilities shared across hooks/components\n */\nimport type Phaser from 'phaser'\nimport type { DeathZoneConfig, EmitZoneConfig } from './emit-zone'\nimport type { ParticleEmitter, ParticleEmitterManagerLike, ParticlesHandle } from './particle-types'\nimport type { ParticleEmitterConfig } from './preset-registry'\n\nexport function isParticleEmitter(target: ParticlesHandle | null): target is ParticleEmitter {\n return !!target && typeof (target as ParticleEmitter).explode === 'function'\n}\n\nexport function getFirstEmitter(\n manager: ParticleEmitterManagerLike | null\n): ParticleEmitter | null {\n if (!manager) return null\n if (manager.__emitter) return manager.__emitter\n const emitters = (manager as unknown as { emitters?: { list?: unknown[] } | unknown[] }).emitters\n if (Array.isArray(emitters)) {\n return (emitters[0] as ParticleEmitter) ?? null\n }\n if (emitters && 'list' in emitters && Array.isArray(emitters.list)) {\n return (emitters.list[0] as ParticleEmitter) ?? null\n }\n return null\n}\n\nexport function applyEmitterConfig(\n emitter: ParticleEmitter | null,\n config: ParticleEmitterConfig\n): void {\n if (!emitter) return\n const withConfig = emitter as Phaser.GameObjects.Particles.ParticleEmitter & {\n setConfig?: (config: ParticleEmitterConfig) => void\n fromJSON?: (config: ParticleEmitterConfig) => void\n }\n\n if (withConfig.setConfig) {\n withConfig.setConfig(config)\n return\n }\n\n if (withConfig.fromJSON) {\n withConfig.fromJSON(config)\n return\n }\n\n Object.assign(emitter, config)\n}\n\nexport function applyEmitZone(\n emitter: ParticleEmitter | null,\n emitZone: EmitZoneConfig | undefined\n): void {\n if (!emitter || !emitZone) return\n const withZone = emitter as Phaser.GameObjects.Particles.ParticleEmitter & {\n setEmitZone?: (config: EmitZoneConfig) => void\n }\n\n if (withZone.setEmitZone) {\n withZone.setEmitZone(emitZone)\n return\n }\n}\n\nexport function applyDeathZone(\n emitter: ParticleEmitter | null,\n deathZone: DeathZoneConfig | DeathZoneConfig[] | undefined\n): void {\n if (!emitter) return\n const withZone = emitter as Phaser.GameObjects.Particles.ParticleEmitter & {\n setDeathZone?: (config: DeathZoneConfig | DeathZoneConfig[]) => void\n addDeathZone?: (config: DeathZoneConfig | DeathZoneConfig[]) => void\n clearDeathZones?: () => void\n deathZones?: unknown[]\n }\n\n const isDefined = <T>(value: T | null | undefined): value is T =>\n value !== null && value !== undefined\n const normalized = Array.isArray(deathZone)\n ? deathZone.filter(isDefined)\n : deathZone\n ? [deathZone]\n : []\n const hasZone = normalized.length > 0\n\n if (hasZone && withZone.setDeathZone) {\n withZone.setDeathZone(normalized)\n return\n }\n\n if (!hasZone) {\n if (withZone.clearDeathZones) {\n withZone.clearDeathZones()\n return\n }\n if (withZone.deathZones) {\n withZone.deathZones = []\n }\n return\n }\n\n if (withZone.clearDeathZones) {\n withZone.clearDeathZones()\n }\n if (withZone.addDeathZone) {\n withZone.addDeathZone(normalized)\n return\n }\n if (withZone.deathZones) {\n ;(withZone as unknown as { deathZones?: unknown[] }).deathZones = normalized\n }\n}\n\nexport function mergeDeathZones(\n base: unknown | unknown[] | undefined,\n extra: unknown[] | undefined\n): unknown[] | undefined {\n const baseList = Array.isArray(base) ? base : base ? [base] : []\n const extraList = extra ?? []\n const merged = [...baseList, ...extraList]\n return merged.length > 0 ? merged : undefined\n}\n","/**\n * Applier for Particles-specific properties\n */\nimport { buildDeathZonesFromLayout, buildEmitZoneFromLayout } from '../../particles/emit-zone'\nimport type {\n ParticleEmitter,\n ParticleEmitterManagerLike,\n ParticlesHandle,\n} from '../../particles/particle-types'\nimport { resolveParticlePreset } from '../../particles/preset-registry'\nimport {\n applyDeathZone,\n applyEmitZone,\n applyEmitterConfig,\n getFirstEmitter,\n isParticleEmitter,\n mergeDeathZones,\n} from '../../particles/utils'\nimport type { ParticlesBaseProps } from '../primitives/particles'\n\n/**\n * Applies particle props updates (texture, emitter config, emit zone)\n */\nexport function applyParticlesProps(\n manager: ParticlesHandle,\n prev: Partial<ParticlesBaseProps>,\n next: Partial<ParticlesBaseProps>\n): void {\n if (!manager) return\n\n const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame\n if (textureChanged && next.texture && 'setTexture' in manager && manager.setTexture) {\n manager.setTexture(next.texture, next.frame)\n }\n\n const configChanged =\n prev.preset !== next.preset ||\n prev.config !== next.config ||\n prev.zone !== next.zone ||\n prev.excludeZones !== next.excludeZones ||\n prev.width !== next.width ||\n prev.height !== next.height\n\n if (configChanged) {\n const resolvedConfig = resolveParticlePreset(next.preset, next.config)\n let emitter: ParticleEmitter | null = null\n\n if (isParticleEmitter(manager)) {\n emitter = manager\n } else {\n const managerLike = manager as ParticleEmitterManagerLike\n emitter = managerLike.__emitter ?? getFirstEmitter(managerLike)\n if (!emitter && managerLike.createEmitter) {\n const created = managerLike.createEmitter(resolvedConfig)\n emitter = (created as ParticleEmitter | void) ?? null\n }\n managerLike.__emitter = emitter\n }\n\n if (!emitter) return\n\n applyEmitterConfig(emitter, resolvedConfig)\n\n if (next.zone) {\n const emitZone = buildEmitZoneFromLayout(next.zone, next.width, next.height)\n if (emitZone) {\n applyEmitZone(emitter, emitZone)\n }\n }\n\n const deathZones = buildDeathZonesFromLayout(next.excludeZones, next.width, next.height)\n const combined = mergeDeathZones(\n (resolvedConfig as unknown as { deathZone?: unknown }).deathZone,\n deathZones\n ) as Parameters<typeof applyDeathZone>[1]\n applyDeathZone(emitter, combined)\n }\n}\n","/**\n * Layout applier for Particles components\n */\nimport type { LayoutProps } from '../../core-props'\nimport type { ParticlesHandle } from '../../particles/particle-types'\nimport type { ParticlesBaseProps } from '../primitives/particles'\n\n/**\n * Applies layout props for Particles\n * Particles are always headless (minimal size)\n */\nexport function applyParticlesLayout(\n particles: ParticlesHandle & {\n __layoutProps?: ParticlesBaseProps\n },\n _prev: Partial<ParticlesBaseProps & LayoutProps>,\n next: Partial<ParticlesBaseProps & LayoutProps>\n): void {\n particles.__layoutProps = next as ParticlesBaseProps\n}\n","/**\n * Layout creator for Particles components\n */\nimport type { LayoutSize } from '../../layout/index'\nimport type { ParticlesHandle } from '../../particles/particle-types'\nimport type { ParticlesBaseProps } from '../primitives/particles'\n\n/**\n * Creates layout infrastructure for a Particles component\n * Particles are always headless (minimal size)\n * @param particles - Phaser ParticleEmitterManager\n * @param props - Particle props\n */\nexport function createParticlesLayout(\n particles: ParticlesHandle & {\n __layoutProps?: ParticlesBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n props: Partial<ParticlesBaseProps>\n): void {\n particles.__layoutProps = props as ParticlesBaseProps\n particles.__getLayoutSize = () => ({ width: 0.01, height: 0.01 })\n}\n","/**\n * Particles component - Phaser ParticleEmitterManager wrapper\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n * - Always headless (does not affect layout)\n * - Emits particles via a single emitter (configurable)\n * - Optional emit zone support (rect, circle, ellipse, line)\n */\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { ParticleExclusionZoneConfig, ParticleZoneConfig } from '../../particles/emit-zone'\nimport { buildDeathZonesFromLayout, buildEmitZoneFromLayout } from '../../particles/emit-zone'\nimport type { ParticleEmitterManagerLike, ParticlesHandle } from '../../particles/particle-types'\nimport type { ParticleEmitterConfig, ParticlePresetName } from '../../particles/preset-registry'\nimport { resolveParticlePreset } from '../../particles/preset-registry'\nimport {\n applyDeathZone,\n getFirstEmitter,\n isParticleEmitter,\n mergeDeathZones,\n} from '../../particles/utils'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyParticlesProps } from '../appliers/applyParticles'\nimport { applyParticlesLayout } from '../appliers/applyParticlesLayout'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createParticlesLayout } from '../creators/createParticlesLayout'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Base props for Particles component\n */\nexport interface ParticlesBaseProps extends TransformProps, PhaserProps, LayoutProps {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas or spritesheet */\n frame?: string | number\n\n /** Built-in preset name */\n preset?: ParticlePresetName\n\n /** Optional emitter config overrides */\n config?: ParticleEmitterConfig\n\n /** Optional emit zone */\n zone?: ParticleZoneConfig\n\n /** Optional exclusion zones (coordinates relative to particle emitter) */\n excludeZones?: ParticleExclusionZoneConfig | ParticleExclusionZoneConfig[] | undefined\n}\n\n/**\n * Props for primitive Particles component (internal use only)\n */\nexport interface ParticlesPrimitiveProps\n extends ParticlesBaseProps,\n PropsDefaultExtension<ParticlesHandle> {}\n\n/**\n * Particles creator - creates a Phaser ParticleEmitterManager with a single emitter\n */\nexport const particlesCreator: HostCreator<'Particles'> = (scene, props) => {\n const resolvedConfig = {\n ...resolveParticlePreset(props.preset, props.config),\n } as ParticleEmitterConfig\n\n if (props.zone) {\n const emitZone = buildEmitZoneFromLayout(props.zone, props.width, props.height)\n if (emitZone) {\n const configWithZone = resolvedConfig as unknown as { emitZone?: unknown }\n configWithZone.emitZone = emitZone\n }\n }\n\n // Don't set death zones yet - will be applied after transform\n\n const particles = scene.add.particles(\n props.x ?? 0,\n props.y ?? 0,\n props.texture,\n resolvedConfig\n ) as unknown as ParticlesHandle\n if (props.frame !== undefined) {\n const configWithFrame = resolvedConfig as unknown as { frame?: string | number }\n configWithFrame.frame = props.frame\n if ('setTexture' in particles && particles.setTexture) {\n particles.setTexture(props.texture, props.frame)\n }\n }\n\n const emitter = isParticleEmitter(particles)\n ? particles\n : getFirstEmitter(particles as ParticleEmitterManagerLike)\n\n if (!isParticleEmitter(particles)) {\n ;(particles as ParticleEmitterManagerLike).__emitter = emitter\n }\n\n // Set origin to (0, 0) for consistent coordinate system (top-left)\n if ('setOrigin' in particles && typeof particles.setOrigin === 'function') {\n particles.setOrigin(0, 0)\n }\n\n // Apply transform props\n createTransform(particles, props)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(particles, props)\n\n // Setup layout system (headless)\n createParticlesLayout(particles, props)\n\n // Now apply death zones with container-relative coordinates\n if (props.excludeZones && emitter) {\n const deathZones = buildDeathZonesFromLayout(props.excludeZones, props.width, props.height)\n const combinedDeathZones = mergeDeathZones(\n (resolvedConfig as unknown as { deathZone?: unknown }).deathZone,\n deathZones\n )\n if (combinedDeathZones) {\n applyDeathZone(emitter, combinedDeathZones as Parameters<typeof applyDeathZone>[1])\n }\n }\n\n // Call onReady callback if provided\n if (props.onReady) {\n props.onReady(particles)\n }\n\n return particles\n}\n\n/**\n * Particles patcher - updates ParticleEmitterManager properties\n */\nexport const particlesPatcher: HostPatcher<'Particles'> = (node, prev, next) => {\n // Apply transform props\n applyTransformProps(node, prev, next)\n\n // Apply Phaser display props\n applyPhaserProps(node, prev, next)\n\n // Apply particle-specific props\n applyParticlesProps(node, prev, next)\n\n // Apply layout props\n applyParticlesLayout(node, prev, next)\n}\n","/**\n * Applier for Sprite-specific properties\n */\nimport type Phaser from 'phaser'\nimport type { SpriteBaseProps } from '../primitives/sprite'\n\n/**\n * Gets original texture dimensions (unscaled)\n * @param sprite - Phaser Sprite object\n * @returns Original width and height\n */\nfunction getOriginalTextureDimensions(sprite: Phaser.GameObjects.Sprite): {\n width: number\n height: number\n} {\n const frame = sprite.frame\n return {\n width: frame.width,\n height: frame.height,\n }\n}\n\n/**\n * Calculates scale factors for fit modes\n * @param sprite - Phaser Sprite object\n * @param targetWidth - Desired width\n * @param targetHeight - Desired height\n * @param fit - Fit mode\n * @returns Scale factors for x and y\n */\nfunction calculateFitScale(\n sprite: Phaser.GameObjects.Sprite,\n targetWidth: number,\n targetHeight: number,\n fit: 'fill' | 'contain' | 'cover' = 'fill'\n): { scaleX: number; scaleY: number } {\n const { width: textureWidth, height: textureHeight } = getOriginalTextureDimensions(sprite)\n\n if (textureWidth === 0 || textureHeight === 0) {\n return { scaleX: 1, scaleY: 1 }\n }\n\n if (fit === 'fill') {\n return {\n scaleX: targetWidth / textureWidth,\n scaleY: targetHeight / textureHeight,\n }\n }\n\n const targetAspect = targetWidth / targetHeight\n const textureAspect = textureWidth / textureHeight\n\n if (fit === 'contain') {\n const scale =\n targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth\n return { scaleX: scale, scaleY: scale }\n }\n\n if (fit === 'cover') {\n const scale =\n targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth\n return { scaleX: scale, scaleY: scale }\n }\n\n return { scaleX: 1, scaleY: 1 }\n}\n\n/**\n * Applies Sprite-specific properties (texture, frame, tint, displaySize, fit, animations)\n * @param sprite - Phaser Sprite object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applySpriteProps(\n sprite: Phaser.GameObjects.Sprite,\n prev: Partial<SpriteBaseProps>,\n next: Partial<SpriteBaseProps>\n): void {\n // Check if texture or frame changed\n const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame\n if (textureChanged && next.texture) {\n sprite.setTexture(next.texture, next.frame)\n }\n\n // Apply tint\n if (prev.tint !== next.tint) {\n if (typeof next.tint === 'number') {\n sprite.setTint(next.tint)\n } else {\n sprite.clearTint()\n }\n }\n\n // Apply origin if specified\n if (prev.originX !== next.originX || prev.originY !== next.originY) {\n const originX = next.originX ?? sprite.originX\n const originY = next.originY ?? sprite.originY\n sprite.setOrigin(originX, originY)\n }\n\n // Apply displayWidth/displayHeight with fit mode\n const displayWidthChanged = prev.displayWidth !== next.displayWidth\n const displayHeightChanged = prev.displayHeight !== next.displayHeight\n const fitChanged = prev.fit !== next.fit\n\n if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {\n if (typeof next.displayWidth === 'number' && typeof next.displayHeight === 'number') {\n // Both specified - use fit mode\n const fit = next.fit ?? 'fill'\n\n if (fit === 'fill') {\n // Use setDisplaySize for fill mode (non-uniform scaling)\n sprite.setDisplaySize(next.displayWidth, next.displayHeight)\n } else {\n // Use setScale for contain/cover (uniform scaling)\n const { scaleX, scaleY } = calculateFitScale(\n sprite,\n next.displayWidth,\n next.displayHeight,\n fit\n )\n sprite.setScale(scaleX, scaleY)\n }\n } else if (typeof next.displayWidth === 'number') {\n // Only width - preserve aspect ratio (use original texture width)\n const { width: origWidth } = getOriginalTextureDimensions(sprite)\n const scale = next.displayWidth / origWidth\n sprite.setScale(scale)\n } else if (typeof next.displayHeight === 'number') {\n // Only height - preserve aspect ratio (use original texture height)\n const { height: origHeight } = getOriginalTextureDimensions(sprite)\n const scale = next.displayHeight / origHeight\n sprite.setScale(scale, scale)\n } else {\n // No display size specified - reset to default scale\n sprite.setScale(1)\n }\n }\n\n // Handle animation changes\n const animationChanged =\n prev.animationKey !== next.animationKey ||\n prev.loop !== next.loop ||\n prev.repeatDelay !== next.repeatDelay\n\n if (animationChanged) {\n // Stop previous animation if playing\n if (sprite.anims.isPlaying) {\n sprite.anims.stop()\n }\n\n // Play new animation if specified\n if (next.animationKey) {\n sprite.anims.play({\n key: next.animationKey,\n repeat: next.loop ? -1 : 0,\n repeatDelay: next.repeatDelay ?? 0,\n })\n }\n }\n\n // Update animation callbacks\n const callbacksChanged =\n prev.onAnimationStart !== next.onAnimationStart ||\n prev.onAnimationComplete !== next.onAnimationComplete ||\n prev.onAnimationRepeat !== next.onAnimationRepeat ||\n prev.onAnimationUpdate !== next.onAnimationUpdate\n\n if (callbacksChanged) {\n // Remove old listeners\n sprite.off('animationstart')\n sprite.off('animationcomplete')\n sprite.off('animationrepeat')\n sprite.off('animationupdate')\n\n // Add new listeners\n if (next.onAnimationStart) {\n sprite.on('animationstart', (anim: Phaser.Animations.Animation) => {\n next.onAnimationStart?.(anim.key)\n })\n }\n\n if (next.onAnimationComplete) {\n sprite.on('animationcomplete', (anim: Phaser.Animations.Animation) => {\n next.onAnimationComplete?.(anim.key)\n })\n }\n\n if (next.onAnimationRepeat) {\n sprite.on('animationrepeat', (anim: Phaser.Animations.Animation) => {\n next.onAnimationRepeat?.(anim.key)\n })\n }\n\n if (next.onAnimationUpdate) {\n sprite.on(\n 'animationupdate',\n (anim: Phaser.Animations.Animation, frame: Phaser.Animations.AnimationFrame) => {\n next.onAnimationUpdate?.(anim.key, frame)\n }\n )\n }\n }\n}\n","/**\n * Layout applier for Sprite components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps } from '../../core-props'\nimport type { SpriteBaseProps } from '../primitives/sprite'\n\n/**\n * Applies layout props and updates layout size provider\n * Sprites are always headless (return minimal size)\n * @param sprite - Phaser Sprite object\n * @param _prev - Previous props (unused)\n * @param next - New props\n */\nexport function applySpriteLayout(\n sprite: Phaser.GameObjects.Sprite & {\n __layoutProps?: SpriteBaseProps\n },\n _prev: Partial<SpriteBaseProps & LayoutProps>,\n next: Partial<SpriteBaseProps & LayoutProps>\n): void {\n // Update layout props reference\n sprite.__layoutProps = next as SpriteBaseProps\n\n // Note: __getLayoutSize is set once in creator and never changes\n // Sprites are always headless (0.01x0.01)\n}\n","/**\n * Layout creator for Sprite components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { SpriteBaseProps } from '../primitives/sprite'\n\n/**\n * Creates layout infrastructure for a Sprite component\n * Attaches layout props and size provider\n * Sprites are always headless (minimal size)\n * @param sprite - Phaser Sprite object\n * @param props - Sprite props including layout\n */\nexport function createSpriteLayout(\n sprite: Phaser.GameObjects.Sprite & {\n __layoutProps?: SpriteBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n props: Partial<SpriteBaseProps>\n): void {\n // Attach layout props for layout calculations\n sprite.__layoutProps = props as SpriteBaseProps\n\n // Attach size provider\n // Sprites are always headless - return minimal size (0.01x0.01)\n // This allows them to participate in alignment but not affect layout dimensions\n sprite.__getLayoutSize = () => {\n return { width: 0.01, height: 0.01 }\n }\n}\n","/**\n * Sprite component - Phaser Sprite GameObject (animated texture)\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n *\n * 1. Component Role: ANIMATED GAME OBJECTS\n * Purpose: Display animated sprites in game scenes (characters, effects, particles)\n * Phaser Type: Phaser.GameObjects.Sprite (animation-capable texture rendering)\n * Characteristics:\n * - Always headless (does not affect parent layout)\n * - Supports Phaser Animation system\n * - Free positioning with rotation/scale\n *\n * 2. Headless Behavior: MANDATORY ✅\n * Decision: Sprites are ALWAYS headless (not configurable)\n * Reasoning:\n * - Sprites are game objects, not UI elements\n * - Should NOT affect parent layout dimensions\n * - Free positioning with full transform support (rotation, scale)\n * Layout Impact: Returns minimal size (0.01x0.01) - participates in alignment only\n * Use Cases:\n * - ✅ Game characters, particles, effects, free-floating objects\n * - ✅ Animated decorations, background elements\n * - ❌ NOT for layout-based UIs (use Image component instead)\n *\n * 3. Layout Size Provider: MINIMAL SIZE ✅\n * Implementation: Always returns { width: 0.01, height: 0.01 }\n * Reasoning:\n * - Sprites don't affect layout spacing\n * - Minimal size allows alignment but no spacing impact\n * - Simpler than getBounds() with same result\n *\n * 4. Animation System: PHASER ANIMATIONS ✅\n * Features:\n * - animationKey: Play pre-registered animation\n * - loop: Repeat animation indefinitely\n * - repeatDelay: Delay between animation repeats (ms)\n * Callbacks:\n * - onAnimationStart: Triggered when animation begins\n * - onAnimationComplete: Triggered when animation ends\n * - onAnimationRepeat: Triggered on each repeat\n * - onAnimationUpdate: Triggered on each frame update\n * Note: Animations must be pre-registered in Phaser AnimationManager\n *\n * 5. Texture & Sizing: LIKE IMAGE ✅\n * Props:\n * - texture: Texture key (required)\n * - frame: Frame from atlas/spritesheet\n * - tint: Color tint (0xRRGGBB)\n * - displayWidth/displayHeight: Scale sprite to fit\n * - fit: 'fill' | 'contain' | 'cover' (aspect ratio handling)\n * Error Handling: Missing texture → Phaser default (white square)\n *\n * 6. Origin Behavior: CENTERED (0.5, 0.5) ✅\n * Decision: Default origin (0.5, 0.5) - centered\n * Reasoning:\n * - Phaser sprite default\n * - Natural for rotation/scale pivot\n * - Game object semantics\n * Override: Use originX/originY props for custom origin\n *\n * 7. Performance: SPRITE BATCHING ✅\n * Strategy:\n * - Leverages Phaser's sprite batching (WebGL)\n * - Props that preserve batching: tint, alpha, scale, position\n * - Props that break batching: custom shaders, blend modes (use sparingly)\n * - Texture atlases strongly recommended for multiple sprites\n *\n * 8. Common Patterns:\n * Character:\n * <Sprite texture=\"player\" animationKey=\"walk\" loop={true} />\n * Particle Effect:\n * <Sprite texture=\"explosion\" animationKey=\"explode\" onAnimationComplete={destroy} />\n * Scaled Sprite:\n * <Sprite texture=\"coin\" displayWidth={32} displayHeight={32} fit=\"contain\" />\n *\n * Implementation Status:\n * ======================\n * [✅] Phaser Sprite creation with texture/frame support\n * [✅] Transform props (position, rotation, scale, alpha)\n * [✅] Layout system integration (always headless)\n * [✅] Origin handling (0.5, 0.5 default)\n * [✅] Display size with fit modes (contain/cover/fill)\n * [✅] Tint support\n * [✅] Animation system (play, loop, callbacks)\n * [✅] Texture and frame patching\n */\nimport type Phaser from 'phaser'\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applySpriteProps } from '../appliers/applySprite'\nimport { applySpriteLayout } from '../appliers/applySpriteLayout'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createSpriteLayout } from '../creators/createSpriteLayout'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Base props for Sprite component\n */\nexport interface SpriteBaseProps extends TransformProps, PhaserProps, LayoutProps {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas or spritesheet */\n frame?: string | number\n\n /** Tint color applied to sprite (0xRRGGBB) */\n tint?: number\n\n /** Display width (scales sprite to fit) */\n displayWidth?: number\n\n /** Display height (scales sprite to fit) */\n displayHeight?: number\n\n /**\n * How sprite should fit within bounds (if displayWidth/displayHeight set)\n * - 'fill': Stretch to fill (default, may distort aspect ratio)\n * - 'contain': Scale to fit within bounds, preserve aspect ratio\n * - 'cover': Scale to cover bounds, preserve aspect ratio (may crop)\n */\n fit?: 'fill' | 'contain' | 'cover'\n\n /** Animation key to play (pre-registered in Phaser AnimationManager) */\n animationKey?: string\n\n /** Loop animation (default: false) */\n loop?: boolean\n\n /** Delay between animation repeats in ms (default: 0) */\n repeatDelay?: number\n\n /** Callback when animation starts */\n onAnimationStart?: (key: string) => void\n\n /** Callback when animation completes */\n onAnimationComplete?: (key: string) => void\n\n /** Callback when animation repeats */\n onAnimationRepeat?: (key: string) => void\n\n /** Callback on each animation frame update */\n onAnimationUpdate?: (key: string, frame: Phaser.Animations.AnimationFrame) => void\n\n /** Origin X (0-1, default 0.5) */\n originX?: number\n\n /** Origin Y (0-1, default 0.5) */\n originY?: number\n}\n\n/**\n * Props for Sprite component\n */\nexport interface SpriteProps\n extends SpriteBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.Sprite> {}\n\n/**\n * Sprite creator - creates a Phaser Sprite object with animations\n */\nexport const spriteCreator: HostCreator<'Sprite'> = (scene, props) => {\n const sprite = scene.add.sprite(props.x ?? 0, props.y ?? 0, props.texture, props.frame)\n\n // Set origin - always centered (0.5, 0.5) for sprites\n sprite.setOrigin(0.5, 0.5)\n\n // Apply custom origin if specified\n if (props.originX !== undefined || props.originY !== undefined) {\n sprite.setOrigin(props.originX ?? sprite.originX, props.originY ?? sprite.originY)\n }\n\n // Apply transform props (scale, rotation)\n createTransform(sprite, props)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(sprite, props)\n\n // Apply sprite-specific props (tint, displaySize, fit)\n if (props.tint !== undefined) {\n sprite.setTint(props.tint)\n }\n\n // Apply displayWidth/displayHeight if specified\n if (props.displayWidth !== undefined || props.displayHeight !== undefined) {\n if (props.displayWidth !== undefined && props.displayHeight !== undefined) {\n // Both specified - use fit mode\n const fit = props.fit ?? 'fill'\n const textureWidth = sprite.width\n const textureHeight = sprite.height\n\n if (textureWidth > 0 && textureHeight > 0) {\n if (fit === 'fill') {\n sprite.setDisplaySize(props.displayWidth, props.displayHeight)\n } else if (fit === 'contain') {\n const targetAspect = props.displayWidth / props.displayHeight\n const textureAspect = textureWidth / textureHeight\n const scale =\n targetAspect > textureAspect\n ? props.displayHeight / textureHeight\n : props.displayWidth / textureWidth\n sprite.setScale(scale)\n } else if (fit === 'cover') {\n const targetAspect = props.displayWidth / props.displayHeight\n const textureAspect = textureWidth / textureHeight\n const scale =\n targetAspect < textureAspect\n ? props.displayHeight / textureHeight\n : props.displayWidth / textureWidth\n sprite.setScale(scale)\n }\n }\n } else if (props.displayWidth !== undefined) {\n const scale = props.displayWidth / sprite.width\n sprite.setScale(scale)\n } else if (props.displayHeight !== undefined) {\n const scale = props.displayHeight / sprite.height\n sprite.setScale(scale)\n }\n }\n\n // Setup animation system\n // Only play if the animation is already registered in the AnimationManager.\n // Calling `sprite.anims.play` with a missing key causes Phaser to log\n // \"Missing animation: <key>\". Many examples register animations in a\n // separate effect that may run after the Sprite is created, so avoid\n // attempting to play until the animation actually exists.\n if (props.animationKey) {\n if (sprite.scene && sprite.scene.anims.exists(props.animationKey)) {\n sprite.anims.play({\n key: props.animationKey,\n repeat: props.loop ? -1 : 0,\n repeatDelay: props.repeatDelay ?? 0,\n })\n }\n }\n\n // Setup animation callbacks\n if (props.onAnimationStart) {\n sprite.on('animationstart', (anim: Phaser.Animations.Animation) => {\n props.onAnimationStart?.(anim.key)\n })\n }\n\n if (props.onAnimationComplete) {\n sprite.on('animationcomplete', (anim: Phaser.Animations.Animation) => {\n props.onAnimationComplete?.(anim.key)\n })\n }\n\n if (props.onAnimationRepeat) {\n sprite.on('animationrepeat', (anim: Phaser.Animations.Animation) => {\n props.onAnimationRepeat?.(anim.key)\n })\n }\n\n if (props.onAnimationUpdate) {\n sprite.on(\n 'animationupdate',\n (anim: Phaser.Animations.Animation, frame: Phaser.Animations.AnimationFrame) => {\n props.onAnimationUpdate?.(anim.key, frame)\n }\n )\n }\n\n // Setup layout system (props and size provider)\n createSpriteLayout(sprite, props)\n\n // Call onReady callback if provided\n if (props.onReady) {\n props.onReady(sprite)\n }\n\n return sprite\n}\n\n/**\n * Sprite patcher - updates Sprite properties\n */\nexport const spritePatcher: HostPatcher<'Sprite'> = (node, prev, next) => {\n // Apply transform props (position, rotation, scale)\n applyTransformProps(node, prev, next)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, prev, next)\n\n // Apply sprite-specific props (texture, frame, tint, displaySize, fit, animations)\n applySpriteProps(node, prev, next)\n\n // Apply layout props and update size provider if needed\n applySpriteLayout(node, prev, next)\n}\n","/**\n * Shared property appliers for component patching\n * These functions avoid code duplication when updating node properties\n */\nimport equal from 'fast-deep-equal'\nimport type { TextSpecificProps } from '../../core-props'\nimport { parseSize, resolveSize } from '../../layout/utils/size-resolver'\nimport { viewportRegistry } from '../../viewport-context'\n\n/**\n * Generic node type with text capabilities\n */\ntype TextNode = {\n setText: (text: string) => void\n setStyle: (style: object) => void\n setWordWrapWidth: (width: number, useAdvancedWrap: boolean) => void\n updateText?: () => void // Force Phaser to recalculate text metrics immediately\n active?: boolean // Check if GameObject is still active\n scene?: Phaser.Scene // Access to scene for texture checks\n}\n\n/**\n * Applies text-specific properties (text content, color, font, alignment)\n * @param node - Phaser Text GameObject\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyTextProps<T extends TextNode>(\n node: T,\n prev: Partial<\n TextSpecificProps & { style?: Phaser.Types.GameObjects.Text.TextStyle | undefined }\n >,\n next: Partial<TextSpecificProps & { style?: Phaser.Types.GameObjects.Text.TextStyle | undefined }>\n): void {\n // Safety check: Ensure node is still active and scene is available\n if (node.active === false || (node.scene && !node.scene.sys.game)) {\n return\n }\n\n let needsUpdate = false\n\n // Text content\n if (prev.text !== next.text && typeof next.text === 'string') {\n node.setText(next.text)\n needsUpdate = true\n }\n\n // Apply style changes if the style object changed\n if (next.style !== undefined && !equal(next.style, prev.style || {})) {\n // Guard against Phaser canvas context errors during theme updates\n try {\n node.setStyle(next.style)\n needsUpdate = true\n } catch (error) {\n console.warn('Failed to apply text style (scene may be transitioning):', error)\n }\n }\n\n // Word wrap width - resolve SizeValue to pixels\n if (next.maxWidth !== prev.maxWidth && next.maxWidth !== undefined) {\n const viewport = viewportRegistry.getViewport()\n const parsedMaxWidth = parseSize(next.maxWidth)\n const resolvedMaxWidth = resolveSize(parsedMaxWidth, viewport?.width, undefined, undefined)\n node.setWordWrapWidth(resolvedMaxWidth, true)\n needsUpdate = true\n }\n\n // Legacy: Support direct Phaser style object\n if (prev.style !== next.style && next.style !== undefined) {\n try {\n node.setStyle(next.style)\n needsUpdate = true\n } catch (error) {\n console.warn('Failed to apply text style (scene may be transitioning):', error)\n }\n }\n\n // Force Phaser to recalculate text metrics immediately\n // This ensures getBounds() returns updated dimensions for layout calculations\n if (needsUpdate && node.updateText) {\n node.updateText()\n }\n}\n","/**\n * Layout applier for text components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { TextBaseProps } from '../primitives/text'\n\n/**\n * Applies layout properties for text components\n * Updates layout props and size provider when text or style changes\n * @param text - Phaser text object\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyTextLayout(\n text: Phaser.GameObjects.Text & {\n __layoutProps?: TextBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n _prev: Partial<TextBaseProps>,\n next: Partial<TextBaseProps>\n): void {\n // Update layout props to trigger parent layout recalculation\n text.__layoutProps = next as TextBaseProps\n\n // ALWAYS recreate size provider to ensure VDOM detects size changes\n // Even if function reference changes, VDOM needs to know dimensions might have changed\n // Previously: Only updated if text/style changed - this caused layout not to recalculate\n // when text dimensions changed (e.g., \"9 times\" -> \"10 times\")\n text.__getLayoutSize = () => {\n if (text.__layoutProps?.headless) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: text.width,\n height: text.height,\n }\n }\n}\n","/**\n * Layout creator for text components\n */\nimport type Phaser from 'phaser'\nimport type { LayoutSize } from '../../layout/index'\nimport type { TextBaseProps } from '../primitives/text'\n\n/**\n * Creates layout infrastructure for a text component\n * Attaches layout props and dynamic size provider\n * @param text - Phaser text object\n * @param props - Text props including layout\n */\nexport function createTextLayout(\n text: Phaser.GameObjects.Text & {\n __layoutProps?: TextBaseProps\n __getLayoutSize?: () => LayoutSize\n },\n props: Partial<TextBaseProps>\n): void {\n // Attach layout props for layout calculations\n text.__layoutProps = props as TextBaseProps\n\n // Attach dynamic size provider\n // Headless text returns minimal size 1x1 (participates in alignment, not spacing)\n // Note: 0x0 causes issues with Phaser internals or layout optimizations\n // Layout-aware text returns actual dimensions (rotation ignored for layout)\n text.__getLayoutSize = () => {\n if (text.__layoutProps?.headless) {\n return { width: 0.01, height: 0.01 }\n }\n return {\n width: text.width,\n height: text.height,\n }\n }\n}\n","/**\n * Text component - Phaser Text GameObject for rendering text\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n *\n * 1. Component Role: TEXT RENDERING\n * Purpose: Display styled text in UI layouts\n * Phaser Type: Phaser.GameObjects.Text (bitmap-based text rendering)\n * Characteristics:\n * - Layout-aware by default (participates in parent layout)\n * - Auto-sizing based on text content + font metrics\n * - Supports Phaser text styling (color, font, alignment, etc.)\n *\n * 2. Headless Default: FALSE ✅\n * Decision: Text participates in layout by default\n * Reasoning:\n * - Text is a UI element (labels, paragraphs, buttons)\n * - Should affect parent container dimensions\n * - Similar to HTML text nodes\n * Use Cases:\n * - ✅ Layout-aware (default): Labels, buttons, paragraphs, UI text\n * - ❌ Headless (optional): Floating damage numbers, debug text, tooltips\n * Usage:\n * <Text text=\"Label\" /> // Layout-aware\n * <Text text=\"+100\" headless={true} /> // Floating (no layout impact)\n *\n * 3. Layout Size Provider: UN-ROTATED DIMENSIONS ✅\n * Implementation: Uses text.width and text.height (un-rotated)\n * Behavior:\n * - Returns un-rotated text dimensions\n * - Rotation is IGNORED for layout-aware text (headless=false)\n * - Rotation only works with headless=true (no layout impact)\n * Reasoning:\n * - Flow layout is incompatible with rotation (causes positioning issues)\n * - Rotated text would overlap siblings in flow layout\n * - getBounds() position compensation is complex and error-prone\n * Example:\n * <Text text=\"Hello\" /> // ✅ Layout size: 100x20\n * <Text text=\"World\" rotation={Math.PI/4} /> // ⚠️ Rotation IGNORED, size: 100x20\n * <Text text=\"World\" rotation={Math.PI/4} headless={true} /> // ✅ Rotated, no layout\n * Recommendation: Use rotation only with headless=true or absolute positioning\n *\n * 4. Text Content & Styling:\n * Props:\n * - text: string (required, the text to display)\n * - style: Phaser.Types.GameObjects.Text.TextStyle (font, color, etc.)\n * - fontStyle, align, maxWidth: Convenience props (legacy)\n * Styling Priority:\n * 1. Inline style prop (highest)\n * 2. Individual props (fontStyle, align)\n * 3. Theme defaults (lowest)\n * Example:\n * <Text\n * text=\"Hello\"\n * style={{ fontSize: '24px', color: '#ffffff', fontFamily: 'Arial' }}\n * />\n *\n * 5. Margin Support:\n * Feature: Text supports margin prop (unique among primitives)\n * Reasoning:\n * - Text often needs spacing from siblings (inline elements)\n * - Margin affects layout calculations (added to text dimensions)\n * - Similar to CSS inline element margin\n * Usage:\n * <Text text=\"Label\" margin={{ left: 10, right: 10 }} />\n * <Text text=\"Spaced\" margin={8} /> // All sides\n *\n * 6. Layout Behavior:\n * Sizing:\n * - Auto-size: Text dimensions = rendered text bounds (default)\n * - No explicit width/height props (text size determined by content)\n * - maxWidth prop wraps text (Phaser feature)\n * Positioning:\n * - Positioned by parent layout engine (flexbox-style)\n * - x/y props override layout position (absolute positioning)\n *\n * 7. Origin Behavior:\n * Current: Phaser default origin (0, 0) - top-left\n * Reasoning:\n * - Text aligns naturally with layout flow\n * - Top-left origin simplifies position calculations\n * - Consistent with HTML text rendering\n * Note: Origin affects rotation pivot (if rotation applied)\n *\n * 8. Common Patterns:\n * Label:\n * <View direction=\"row\" gap={10}>\n * <Text text=\"Name:\" />\n * <Text text={userName} />\n * </View>\n * Styled Text:\n * <Text\n * text=\"Title\"\n * style={{ fontSize: '32px', fontWeight: 'bold', color: '#ff0000' }}\n * />\n * Wrapped Text:\n * <Text text={longParagraph} maxWidth={300} />\n * Floating Damage:\n * <Text text=\"-50 HP\" headless={true} alpha={0.8} />\n *\n * 9. Performance Considerations:\n * - Text rendering is relatively expensive (canvas-based)\n * - Frequent text changes trigger re-render\n * - Long text with maxWidth: word-wrap calculation cost\n * - Consider BitmapText for better performance (future component)\n * - Text batching: Multiple Text objects don't batch (separate draw calls)\n *\n * 10. Known Limitations:\n * - Rotation only supported with headless=true (ignored for layout-aware text)\n * → Flow layout is incompatible with rotation\n * - No rich text support (HTML tags, colors within text)\n * - Limited text effects (no shadows, outlines in base component)\n * - WordWrap with maxWidth: Can't specify ellipsis truncation\n * - Changing text frequently: Performance impact\n *\n * Implementation Status:\n * ======================\n * [✅] Phaser Text creation with style support\n * [✅] Transform props (position, scale, alpha)\n * [✅] Layout system integration (__layoutProps, __getLayoutSize)\n * [✅] Margin support (unique feature)\n * [✅] Text content and style patching\n * [✅] Theme system integration\n * [⚠️] Rotation - Only with headless=true (ignored for layout-aware text)\n * [❌] Rich text support - Future feature\n * [❌] Text effects (shadow, outline) - Future feature\n */\nimport type Phaser from 'phaser'\nimport type {\n EdgeInsets,\n LayoutProps,\n PhaserProps,\n TextSpecificProps,\n TransformProps,\n} from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTextProps } from '../appliers/applyText'\nimport { applyTextLayout } from '../appliers/applyTextLayout'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTextLayout } from '../creators/createTextLayout'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Base props for Text - composing shared prop groups\n * Includes optional margin for layout engine use\n */\nexport interface TextBaseProps\n extends TransformProps,\n PhaserProps,\n Pick<LayoutProps, 'headless'>,\n TextSpecificProps {\n margin?: EdgeInsets\n // Legacy: support Phaser's style object directly\n style?: Phaser.Types.GameObjects.Text.TextStyle | undefined\n}\n\n/**\n * Props for Text component - extends base props with JSX-specific props\n */\nexport interface TextProps extends TextBaseProps, PropsDefaultExtension<Phaser.GameObjects.Text> {}\n\n/**\n * Text creator - creates a Phaser Text object\n */\nexport const textCreator: HostCreator<'Text'> = (scene, props) => {\n const text = scene.add.text(props.x ?? 0, props.y ?? 0, props.text ?? '', props.style)\n\n // Set origin based on headless flag\n // Headless: (0.5, 0.5) - centered, works naturally with rotation/scale\n // Layout-aware: (0, 0) - top-left, aligns with layout flow\n if (props.headless) {\n text.setOrigin(0.5, 0.5)\n } else {\n text.setOrigin(0, 0)\n }\n\n // Normalize props for headless objects\n // Headless objects are positioned as points - no spacing or rotation constraints\n const normalizedProps = { ...props } as Record<string, unknown>\n if (props.headless) {\n // Remove spacing props (headless = positioned as point)\n delete normalizedProps.padding\n delete normalizedProps.margin\n delete normalizedProps.gap\n } else {\n // Remove rotation (only supported with headless=true)\n if (normalizedProps.rotation !== undefined) {\n delete normalizedProps.rotation\n }\n }\n\n // Apply transform props (scale, rotation if headless)\n createTransform(text, normalizedProps)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(text, normalizedProps)\n\n // Setup layout system (props and size provider)\n createTextLayout(text, normalizedProps)\n\n return text\n}\n\n/**\n * Text patcher - updates Text properties\n */\nexport const textPatcher: HostPatcher<'Text'> = (node, prev, next) => {\n // Update origin if headless flag changed\n if (prev.headless !== next.headless) {\n if (next.headless) {\n node.setOrigin(0.5, 0.5) // Headless: centered\n } else {\n node.setOrigin(0, 0) // Layout-aware: top-left\n }\n }\n\n // Normalize props for headless objects\n const normalizedPrev = { ...prev } as Record<string, unknown>\n const normalizedNext = { ...next } as Record<string, unknown>\n\n if (next.headless) {\n // Remove spacing props (headless = positioned as point)\n delete normalizedNext.padding\n delete normalizedNext.margin\n delete normalizedNext.gap\n } else {\n // Remove rotation (only supported with headless=true)\n if (normalizedNext.rotation !== undefined) {\n delete normalizedNext.rotation\n }\n }\n\n if (prev.headless) {\n delete normalizedPrev.padding\n delete normalizedPrev.margin\n delete normalizedPrev.gap\n } else {\n if (normalizedPrev.rotation !== undefined) {\n delete normalizedPrev.rotation\n }\n }\n\n // Apply transform props (position, rotation only if headless, scale)\n applyTransformProps(node, normalizedPrev, normalizedNext)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, normalizedPrev, normalizedNext)\n\n // Apply text-specific props (text content, color, font, etc.)\n applyTextProps(node, normalizedPrev, normalizedNext)\n\n // Apply layout props and update size provider if needed\n applyTextLayout(node, normalizedPrev, normalizedNext)\n}\n","/**\n * TileSprite component - Phaser TileSprite GameObject (repeating texture pattern)\n * Status: DUMMY - Not implemented yet\n *\n * Design Decisions & Answers:\n * ===========================\n *\n * 1. Headless Default: TRUE ✅\n * Rationale: TileSprites are typically backgrounds/patterns (decorative).\n * They fill available space and shouldn't affect parent dimensions.\n * Use Cases:\n * - ✅ Headless (default): Scrolling backgrounds, parallax layers, repeating patterns\n * - ❌ Layout-aware: Rare - textured progress bars, pattern-filled UI blocks\n *\n * 2. Layout Size Provider: SIMPLE DIMENSIONS ✅\n * Decision: Use width/height directly (not getBounds)\n * Reasoning:\n * - TileSprite requires explicit width/height (Phaser constructor param)\n * - Dimensions are always known and stable\n * - getBounds() adds unnecessary overhead\n * - Rotation affects visual but not logical dimensions (pattern stays in rect)\n * Implementation: __getLayoutSize = () => ({ width, height })\n *\n * 3. Tiling Props: DIRECT PHASER MAPPING ✅\n * Decision: Expose Phaser's tilePosition/tileScale props directly\n * Props:\n * - tilePositionX/Y: Offset for scrolling effect (default: 0)\n * - tileScaleX/Y: Tile size multiplier (default: 1)\n * Example:\n * <TileSprite\n * texture=\"clouds\"\n * width={800} height={200}\n * tilePositionX={scrollOffset}\n * tileScaleX={2} // Tiles 2x larger\n * />\n * Note: tilePosition updates are cheap (WebGL texture wrapping, no redraw)\n *\n * 4. Sizing Strategy: HYBRID LAYOUT SUPPORT ✅\n * Decision: Support both explicit and layout-aware sizing\n * Behavior:\n * - Explicit pixels: width={800} height={200} → Fixed size\n * - Layout string: width=\"100%\" height=\"50%\" → Resolved from parent\n * - Layout fill: width={undefined} → Auto-fill parent (if parent sized)\n * Implementation:\n * - Resolve layout size in creator using existing size-resolver\n * - Create TileSprite with resolved pixel dimensions\n * - Update dimensions in patcher if layout props change\n * Phaser Limitation: TileSprite dimensions can't change after creation\n * → Workaround: Recreate TileSprite if dimensions change (expensive!)\n *\n * 5. Performance Characteristics: OPTIMAL FOR PATTERNS ✅\n * Advantages:\n * - WebGL texture wrapping (hardware-accelerated, no CPU cost)\n * - tilePosition updates are free (just shader uniform)\n * - Good for large repeating areas (better than multiple sprites)\n * - No geometry regeneration on scroll\n * Limitations:\n * - Texture must support wrapping (power-of-2 dimensions recommended)\n * - Rotation/scale affects entire area (not individual tiles)\n * - Can't change dimensions dynamically (requires recreation)\n *\n * 6. Animation Support: USER CODE ✅\n * Decision: No built-in animation helpers\n * Reasoning:\n * - Scrolling patterns vary widely (linear, sine wave, parallax)\n * - Simple to implement in user code:\n * const [scroll, setScroll] = useState(0)\n * useEffect(() => {\n * const timer = setInterval(() => setScroll(s => s + 1), 16)\n * return () => clearInterval(timer)\n * }, [])\n * <TileSprite tilePositionX={scroll} />\n * - No need for framework abstraction\n * Future: Consider useScrollingPattern hook if demand is high\n *\n * 7. Common Use Cases & Patterns: DOCUMENTED ✅\n * Best For:\n * - ✅ Scrolling backgrounds (clouds, stars, terrain)\n * - ✅ Infinite repeating patterns (tiles, grids)\n * - ✅ Parallax layers (different scroll speeds)\n * - ✅ Textured fills (progress bars, health bars)\n * Avoid For:\n * - ❌ Static backgrounds → Use Image (simpler)\n * - ❌ Complex patterns → Use Graphics or multiple Sprites\n * - ❌ Animated tiles → Use Sprite with animation\n *\n * 8. Origin Behavior: UI-FRIENDLY DEFAULT 🆕\n * Decision: Default origin (0, 0) like Image (differs from Sprite!)\n * Reasoning:\n * - TileSprites typically used as backgrounds/fills (top-left alignment)\n * - Matches Image component behavior (UI semantics)\n * - Easier layout calculations\n * - Allow override via originX/originY for special cases\n *\n * 9. Rotation & Tiling: DOCUMENTED BEHAVIOR 🆕\n * Behavior:\n * - Rotation rotates entire TileSprite area (not individual tiles)\n * - Tile pattern remains axis-aligned in texture space\n * - Useful for rotated pattern fills, but limited flexibility\n * - For rotated individual tiles, use multiple Sprite instances\n *\n * Implementation Checklist:\n * ========================\n * [ ] Create TileSprite with scene.add.tileSprite(x, y, width, height, texture, frame)\n * [ ] Set origin to (0, 0) by default (UI-friendly)\n * [ ] Apply transform props via applyTransformProps\n * [ ] Setup tilePosition/tileScale props\n * [ ] Implement layout size resolver (support %, fill)\n * [ ] Setup layout size provider (width/height)\n * [ ] Handle dimension changes (recreate if needed)\n * [ ] Support tint, origin props\n * [ ] Test with scrolling, scaling, rotation\n * [ ] Document power-of-2 texture recommendation\n */\nimport type Phaser from 'phaser'\nimport type { TransformProps } from '../../core-props'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsDefaultExtension } from '../../types'\n\n/**\n * Base props for TileSprite component\n */\nexport interface TileSpriteBaseProps extends TransformProps {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas */\n frame?: string | number\n\n /** Width of the tile sprite area */\n width: number\n\n /** Height of the tile sprite area */\n height: number\n\n /** Horizontal tile position offset (for scrolling effect) */\n tilePositionX?: number\n\n /** Vertical tile position offset (for scrolling effect) */\n tilePositionY?: number\n\n /** Horizontal tile scale factor */\n tileScaleX?: number\n\n /** Vertical tile scale factor */\n tileScaleY?: number\n\n /** Tint color applied to tiles (0xRRGGBB) */\n tint?: number\n\n /** Origin X (0-1, default 0.5) */\n originX?: number\n\n /** Origin Y (0-1, default 0.5) */\n originY?: number\n}\n\n/**\n * Props for TileSprite component\n */\nexport interface TileSpriteProps\n extends TileSpriteBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.TileSprite> {}\n\n/**\n * TileSprite creator - NOT IMPLEMENTED YET\n * @throws Error indicating component is not implemented\n */\nexport const tileSpriteCreator: HostCreator<'TileSprite'> = (_scene, _props) => {\n throw new Error(\n 'TileSprite component not implemented yet. This is a placeholder for architecture planning.'\n )\n}\n\n/**\n * TileSprite patcher - NOT IMPLEMENTED YET\n * @throws Error indicating component is not implemented\n */\nexport const tileSpritePatcher: HostPatcher<'TileSprite'> = (_node, _prev, _next) => {\n throw new Error(\n 'TileSprite component not implemented yet. This is a placeholder for architecture planning.'\n )\n}\n","/**\n * Shared property appliers for component patching\n * These functions avoid code duplication when updating node properties\n */\nimport Phaser from 'phaser'\nimport type { BackgroundProps, LayoutProps } from '../../core-props'\n\n/**\n * Applies background properties (color, alpha, corner radius, border)\n * Handles adding, removing, and updating background graphics on containers\n * @param container - Phaser Container with potential background\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyBackgroundProps(\n container: Phaser.GameObjects.Container & {\n __background?: Phaser.GameObjects.Graphics\n __getLayoutSize?: () => { width: number; height: number }\n },\n prev: Partial<BackgroundProps & LayoutProps>,\n next: Partial<BackgroundProps & LayoutProps>\n): void {\n const prevBgColor = prev.backgroundColor\n const nextBgColor = next.backgroundColor\n const prevBgAlpha = prev.backgroundAlpha ?? 1\n const nextBgAlpha = next.backgroundAlpha ?? 1\n\n // Get actual layout size if available, fall back to props\n let prevWidth = typeof prev.width === 'number' ? prev.width : 100\n let prevHeight = typeof prev.height === 'number' ? prev.height : 100\n let nextWidth = typeof next.width === 'number' ? next.width : 100\n let nextHeight = typeof next.height === 'number' ? next.height : 100\n\n // Use actual layout size if available (for auto-sized or calculated dimensions)\n if (container.__getLayoutSize) {\n const layoutSize = container.__getLayoutSize()\n prevWidth = layoutSize.width\n prevHeight = layoutSize.height\n nextWidth = layoutSize.width\n nextHeight = layoutSize.height\n }\n\n const prevCornerRadius = prev.cornerRadius ?? 0\n const nextCornerRadius = next.cornerRadius ?? 0\n const prevBorderColor = prev.borderColor\n const nextBorderColor = next.borderColor\n const prevBorderWidth = prev.borderWidth ?? 0\n const nextBorderWidth = next.borderWidth ?? 0\n const prevBorderAlpha = prev.borderAlpha ?? 1\n const nextBorderAlpha = next.borderAlpha ?? 1\n\n const prevHasBorder = prevBorderWidth > 0 && prevBorderColor !== undefined\n const nextHasBorder = nextBorderWidth > 0 && nextBorderColor !== undefined\n const prevHasGraphics = prevBgColor !== undefined || prevHasBorder\n const nextHasGraphics = nextBgColor !== undefined || nextHasBorder\n\n if (prevHasGraphics && !nextHasGraphics) {\n // Remove background/border graphics entirely\n if (container.__background) {\n container.__background.destroy()\n delete container.__background\n }\n } else if (!prevHasGraphics && nextHasGraphics) {\n // Add background/border graphics\n if (container.scene) {\n const background = container.scene.add.graphics()\n\n if (nextBgColor !== undefined) {\n background.fillStyle(nextBgColor, nextBgAlpha)\n }\n\n if (nextHasBorder) {\n background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha)\n }\n\n if (nextCornerRadius !== 0) {\n if (nextBgColor !== undefined) {\n background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius)\n }\n if (nextHasBorder) {\n background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius)\n }\n } else {\n if (nextBgColor !== undefined) {\n background.fillRect(0, 0, nextWidth, nextHeight)\n }\n if (nextHasBorder) {\n background.strokeRect(0, 0, nextWidth, nextHeight)\n }\n }\n\n container.addAt(background, 0)\n container.__background = background\n ;(background as Phaser.GameObjects.Graphics & { __isBackground?: boolean }).__isBackground =\n true\n }\n } else if (container.__background && nextHasGraphics) {\n // Update existing background - Graphics requires clear and redraw\n const needsRedraw =\n prevBgColor !== nextBgColor ||\n prevBgAlpha !== nextBgAlpha ||\n prevWidth !== nextWidth ||\n prevHeight !== nextHeight ||\n prevCornerRadius !== nextCornerRadius ||\n prevBorderWidth !== nextBorderWidth ||\n prevBorderColor !== nextBorderColor ||\n prevBorderAlpha !== nextBorderAlpha\n\n if (needsRedraw) {\n container.__background.clear()\n\n if (nextBgColor !== undefined) {\n container.__background.fillStyle(nextBgColor, nextBgAlpha)\n }\n\n if (nextHasBorder) {\n container.__background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha)\n }\n\n if (nextCornerRadius !== 0) {\n if (nextBgColor !== undefined) {\n container.__background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius)\n }\n if (nextHasBorder) {\n container.__background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius)\n }\n } else {\n if (nextBgColor !== undefined) {\n container.__background.fillRect(0, 0, nextWidth, nextHeight)\n }\n if (nextHasBorder) {\n container.__background.strokeRect(0, 0, nextWidth, nextHeight)\n }\n }\n }\n }\n}\n","/**\n * Gesture property appliers for component patching\n * Updates gesture registration when props change\n */\nimport type { LayoutSize } from '@number10/phaserjsx/layout'\nimport Phaser from 'phaser'\nimport type { GestureProps, LayoutProps } from '../../core-props'\nimport { getGestureManager } from '../../gestures/gesture-manager'\nimport type { GestureCallbacks } from '../../gestures/gesture-types'\n\n/**\n * Applies gesture properties when props change\n * Handles enabling/disabling gestures, updating callbacks, and hit area changes\n * @param scene - Scene containing the gesture manager\n * @param container - Phaser Container to update gestures on\n * @param prev - Previous props\n * @param next - New props\n */\nexport function applyGesturesProps(\n scene: Phaser.Scene,\n container: Phaser.GameObjects.Container,\n prev: Partial<GestureProps & LayoutProps>,\n next: Partial<GestureProps & LayoutProps>\n): void {\n // Safety check: ensure scene is valid and booted\n if (!scene || !scene.sys || !scene.data) {\n console.warn('applyGesturesProps: Invalid scene or scene not initialized')\n return\n }\n\n // Check if scene is still active (not shutting down/destroyed)\n if (!scene.sys.isActive() || scene.sys.game === null) {\n console.warn('applyGesturesProps: Scene is not active or game is null')\n return\n }\n\n const hasAnyGesture = !!(\n next.onTouch ||\n next.onTouchOutside ||\n next.onTouchMove ||\n next.onDoubleTap ||\n next.onLongPress ||\n next.onHoverStart ||\n next.onHoverEnd ||\n next.onWheel\n )\n const hadAnyGesture = !!(\n prev.onTouch ||\n prev.onTouchOutside ||\n prev.onTouchMove ||\n prev.onDoubleTap ||\n prev.onLongPress ||\n prev.onHoverStart ||\n prev.onHoverEnd ||\n prev.onWheel\n )\n\n // Auto-enable if callbacks present, unless explicitly disabled\n const prevEnabled = hadAnyGesture && prev.enableGestures !== false\n const nextEnabled = hasAnyGesture && next.enableGestures !== false\n\n const manager = getGestureManager(scene)\n\n // Case 1: Gestures newly enabled\n if (!prevEnabled && nextEnabled && hasAnyGesture) {\n // Register for the first time\n // Use __getLayoutSize for actual calculated dimensions\n const containerWithLayout = container as typeof container & {\n __getLayoutSize?: () => LayoutSize\n }\n\n let width = 100\n let height = 100\n\n if (containerWithLayout.__getLayoutSize) {\n const size = containerWithLayout.__getLayoutSize()\n width = size.width\n height = size.height\n } else {\n const bounds = container.getBounds()\n width = bounds.width || 100\n height = bounds.height || 100\n }\n\n const hitArea = new Phaser.Geom.Rectangle(0, 0, width, height)\n\n const callbacks: GestureCallbacks = {}\n if (next.onTouch) callbacks.onTouch = next.onTouch\n if (next.onTouchOutside) callbacks.onTouchOutside = next.onTouchOutside\n if (next.onTouchMove) callbacks.onTouchMove = next.onTouchMove\n if (next.onDoubleTap) callbacks.onDoubleTap = next.onDoubleTap\n if (next.onLongPress) callbacks.onLongPress = next.onLongPress\n if (next.onHoverStart) callbacks.onHoverStart = next.onHoverStart\n if (next.onHoverEnd) callbacks.onHoverEnd = next.onHoverEnd\n if (next.onWheel) callbacks.onWheel = next.onWheel\n\n const config: { longPressDuration?: number; doubleTapDelay?: number } = {}\n if (next.longPressDuration !== undefined) config.longPressDuration = next.longPressDuration\n if (next.doubleTapDelay !== undefined) config.doubleTapDelay = next.doubleTapDelay\n\n manager.registerContainer(container, callbacks, hitArea, config)\n return\n }\n\n // Case 2: Gestures disabled or no callbacks\n if (prevEnabled && (!nextEnabled || !hasAnyGesture)) {\n manager.unregisterContainer(container)\n return\n }\n\n // Case 3: Gestures still enabled, update callbacks/hit area\n if (nextEnabled && hasAnyGesture) {\n // Update callbacks if any changed\n const callbacksChanged =\n prev.onTouch !== next.onTouch ||\n prev.onTouchOutside !== next.onTouchOutside ||\n prev.onTouchMove !== next.onTouchMove ||\n prev.onDoubleTap !== next.onDoubleTap ||\n prev.onLongPress !== next.onLongPress ||\n prev.onHoverStart !== next.onHoverStart ||\n prev.onHoverEnd !== next.onHoverEnd ||\n prev.onWheel !== next.onWheel\n\n if (callbacksChanged) {\n const callbacks: GestureCallbacks = {}\n if (next.onTouch) callbacks.onTouch = next.onTouch\n if (next.onTouchOutside) callbacks.onTouchOutside = next.onTouchOutside\n if (next.onTouchMove) callbacks.onTouchMove = next.onTouchMove\n if (next.onDoubleTap) callbacks.onDoubleTap = next.onDoubleTap\n if (next.onLongPress) callbacks.onLongPress = next.onLongPress\n if (next.onHoverStart) callbacks.onHoverStart = next.onHoverStart\n if (next.onHoverEnd) callbacks.onHoverEnd = next.onHoverEnd\n if (next.onWheel) callbacks.onWheel = next.onWheel\n\n manager.updateCallbacks(container, callbacks)\n }\n\n // Always update hit area when gestures are enabled\n // This ensures animated size changes (overlayHeight.value) are reflected\n // Use __getLayoutSize for actual calculated dimensions\n const containerWithLayout = container as typeof container & {\n __getLayoutSize?: () => LayoutSize\n }\n\n let width = 100\n let height = 100\n\n if (containerWithLayout.__getLayoutSize) {\n const size = containerWithLayout.__getLayoutSize()\n width = size.width\n height = size.height\n } else {\n const bounds = container.getBounds()\n width = bounds.width || 100\n height = bounds.height || 100\n }\n\n const hitArea = new Phaser.Geom.Rectangle(0, 0, width, height)\n\n manager.updateHitArea(container, hitArea)\n }\n}\n","/**\n * Layout property applier for updating container layout configuration\n */\nimport equal from 'fast-deep-equal'\nimport type { BackgroundProps, LayoutProps } from '../../core-props'\nimport { getGestureManager } from '../../gestures/gesture-manager'\nimport { calculateLayout, type LayoutSize } from '../../layout/index'\n\n/**\n * Updates gesture hit area based on current layout size\n * Called after layout recalculation to sync hit area with actual container size\n * @param node - Container with potential gesture registration\n */\nfunction updateGestureHitAreaIfNeeded(node: Phaser.GameObjects.Container): void {\n const containerWithLayout = node as typeof node & {\n __getLayoutSize?: () => LayoutSize\n scene: Phaser.Scene\n }\n\n // Only update if container has gesture system enabled and layout size available\n if (!containerWithLayout.__getLayoutSize) return\n\n try {\n const manager = getGestureManager(containerWithLayout.scene)\n const size = containerWithLayout.__getLayoutSize()\n const hitArea = new Phaser.Geom.Rectangle(0, 0, size.width, size.height)\n manager.updateHitArea(node, hitArea)\n } catch {\n // Gesture manager or container not registered, ignore\n }\n}\n\n/**\n * Layout-relevant props that trigger layout recalculation when changed\n */\nconst LAYOUT_RELEVANT_PROPS: (keyof LayoutProps)[] = [\n 'width',\n 'height',\n 'minWidth',\n 'maxWidth',\n 'minHeight',\n 'maxHeight',\n 'flex',\n 'margin',\n 'padding',\n 'gap',\n 'direction',\n 'justifyContent',\n 'alignItems',\n 'overflow',\n]\n\n/**\n * Object props that need deep comparison\n */\nconst DEEP_COMPARE_PROPS = new Set(['margin', 'padding'])\n\n/**\n * Check if any layout-relevant prop changed\n * Uses shallow equality for primitives and deep equality for objects\n * @param prev - Previous props\n * @param next - New props\n * @returns True if any layout prop changed\n */\nfunction hasLayoutPropsChanged(\n prev: Partial<LayoutProps & BackgroundProps>,\n next: Partial<LayoutProps & BackgroundProps>\n): boolean {\n for (const prop of LAYOUT_RELEVANT_PROPS) {\n const oldVal = prev[prop]\n const newVal = next[prop]\n\n // Use deep comparison for object props (margin, padding)\n if (DEEP_COMPARE_PROPS.has(prop as string)) {\n if (!equal(oldVal, newVal)) {\n return true\n }\n } else {\n // Shallow comparison for primitives\n if (oldVal !== newVal) {\n return true\n }\n }\n }\n return false\n}\n\n/**\n * Calculates parent size and padding from parent container's layout\n * Falls back to viewport size for root containers without a parent\n * @param node - Container node to get parent info for\n * @returns Parent size and padding if parent is a layout container\n */\nfunction getParentLayoutContext(node: Phaser.GameObjects.Container): {\n parentSize?: { width: number; height: number }\n parentPadding?: { horizontal: number; vertical: number }\n} {\n const parent = node.parentContainer as\n | (Phaser.GameObjects.Container & {\n __layoutProps?: LayoutProps\n __getLayoutSize?: () => LayoutSize\n })\n | undefined\n\n // If has layout parent, use its content-area\n if (parent && parent.__layoutProps && parent.__getLayoutSize) {\n const parentSize = parent.__getLayoutSize()\n const padding = parent.__layoutProps.padding ?? 0\n const normPadding =\n typeof padding === 'number'\n ? { left: padding, right: padding, top: padding, bottom: padding }\n : {\n left: padding.left ?? 0,\n right: padding.right ?? 0,\n top: padding.top ?? 0,\n bottom: padding.bottom ?? 0,\n }\n\n return {\n parentSize: {\n width: parentSize.width - normPadding.left - normPadding.right,\n height: parentSize.height - normPadding.top - normPadding.bottom,\n },\n // Parent already provides content-area, no padding offset needed\n }\n }\n\n // Fallback: Root container without layout parent - use viewport as parent size\n // This allows percentage-based sizing/constraints to work on root containers\n if (node.scene) {\n return {\n parentSize: {\n width: node.scene.scale.width,\n height: node.scene.scale.height,\n },\n }\n }\n\n return {}\n}\n\n/**\n * Applies layout property changes to a container\n * Handles width, height, direction, padding, margin updates\n * Triggers layout recalculation when:\n * 1. Layout-relevant props changed, OR\n * 2. This is being called from host.patch (which means VDOM will handle child changes)\n * @param node - Phaser container node\n * @param prev - Previous layout props\n * @param next - New layout props\n */\nexport function applyLayoutProps(\n node: Phaser.GameObjects.Container & { __layoutProps?: LayoutProps & BackgroundProps },\n prev: Partial<LayoutProps & BackgroundProps>,\n next: Partial<LayoutProps & BackgroundProps>\n): void {\n // Update stored layout props (includes visible for display control)\n node.__layoutProps = next as LayoutProps & BackgroundProps\n\n // IMPORTANT: We only recalculate if container's own props changed\n // Children changes are handled by VDOM patchVNode() which has smarter detection\n // This prevents double-calculation while still catching container prop changes\n if (hasLayoutPropsChanged(prev, next)) {\n // Get parent layout context for percentage/fill resolution\n const { parentSize, parentPadding } = getParentLayoutContext(node)\n calculateLayout(node, next, parentSize, parentPadding)\n // Update gesture hit area after layout recalculation\n // This ensures hit area matches actual container size (important for auto-sized containers)\n updateGestureHitAreaIfNeeded(node)\n }\n // Note: If children changed (text content, child added/removed, etc.),\n // the VDOM layer will detect that and call calculateLayout separately\n}\n","/**\n * Tooltip applier for component patching\n * Manages native Phaser text tooltip rendering with animations\n */\nimport Phaser from 'phaser'\nimport type { HoverEventData } from '../../gestures/gesture-types'\nimport { themeRegistry } from '../../theme'\nimport type { TooltipCallback, TooltipConfig } from '../../tooltip/tooltip-types'\n\n/**\n * Internal state for tooltip management per container\n */\ninterface TooltipState {\n isVisible: boolean\n tooltip: Phaser.GameObjects.Container | null\n activeTweens: Phaser.Tweens.Tween[]\n showTimer: NodeJS.Timeout | null\n hideTimer: NodeJS.Timeout | null\n autoDismissTimer: NodeJS.Timeout | null\n currentConfig: TooltipConfig | null\n}\n\n// Map to store tooltip state for each container\nconst tooltipStates = new Map<Phaser.GameObjects.Container, TooltipState>()\n\n/**\n * Calculate tooltip position based on target bounds and preferred position\n * Auto-adjusts if tooltip would go out of viewport bounds\n */\nfunction calculateTooltipPosition(\n targetBounds: Phaser.Geom.Rectangle,\n position: 'top' | 'bottom' | 'left' | 'right',\n offset: number,\n tooltipWidth: number,\n tooltipHeight: number\n): { x: number; y: number } {\n const viewport = {\n width: window.innerWidth,\n height: window.innerHeight,\n }\n\n let x = 0\n let y = 0\n\n switch (position) {\n case 'top':\n x = targetBounds.centerX - tooltipWidth / 2\n y = targetBounds.top - tooltipHeight - offset\n break\n case 'bottom':\n x = targetBounds.centerX - tooltipWidth / 2\n y = targetBounds.bottom + offset\n break\n case 'left':\n x = targetBounds.left - tooltipWidth - offset\n y = targetBounds.centerY - tooltipHeight / 2\n break\n case 'right':\n x = targetBounds.right + offset\n y = targetBounds.centerY - tooltipHeight / 2\n break\n }\n\n // Clamp to viewport bounds (with small padding)\n x = Math.max(8, Math.min(x, viewport.width - tooltipWidth - 8))\n y = Math.max(8, Math.min(y, viewport.height - tooltipHeight - 8))\n\n return { x, y }\n}\n\n/**\n * Show native Phaser text tooltip with animations\n */\nfunction showTooltip(\n scene: Phaser.Scene,\n container: Phaser.GameObjects.Container,\n config: TooltipConfig\n): void {\n const state = tooltipStates.get(container)\n if (!state || state.isVisible) return\n\n state.isVisible = true\n state.currentConfig = config\n\n const theme = themeRegistry.getGlobalTheme()\n const tooltipTheme = theme.Tooltip || {}\n\n const position = config.position ?? tooltipTheme.position ?? 'top'\n const offset = config.offset ?? tooltipTheme.offset ?? 8\n\n const content = config.content\n\n // Get target bounds\n const targetBounds = container.getBounds()\n\n // Create text without background first to measure\n const textStyle: Phaser.Types.GameObjects.Text.TextStyle = tooltipTheme.textStyle ?? {\n fontSize: '14px',\n fontFamily: 'Arial',\n color: '#ffffff',\n padding: { x: 8, y: 4 },\n }\n\n // Remove backgroundColor from textStyle, we'll draw it manually\n const { backgroundColor: bgColor, ...styleWithoutBg } = textStyle\n\n const text = scene.add.text(0, 0, content, styleWithoutBg)\n text.setOrigin(0.5)\n\n // Measure text with padding\n const padding = textStyle.padding ?? { x: 8, y: 4 }\n const paddingX = typeof padding === 'number' ? padding : (padding.x ?? 8)\n const paddingY = typeof padding === 'number' ? padding : (padding.y ?? 4)\n const textWidth = text.width\n const textHeight = text.height\n const bgWidth = textWidth + paddingX * 2\n const bgHeight = textHeight + paddingY * 2\n\n // Create rounded background\n const cornerRadius = tooltipTheme.cornerRadius ?? 6\n const graphics = scene.add.graphics()\n\n // Parse background color\n const bg = bgColor ?? '#000000dd'\n let fillColor = 0x000000\n let fillAlpha = 0.87\n\n if (typeof bg === 'string') {\n if (bg.startsWith('#')) {\n // Handle hex with optional alpha\n const hex = bg.slice(1)\n if (hex.length === 8) {\n fillColor = parseInt(hex.slice(0, 6), 16)\n fillAlpha = parseInt(hex.slice(6, 8), 16) / 255\n } else if (hex.length === 6) {\n fillColor = parseInt(hex, 16)\n fillAlpha = 1\n }\n }\n }\n\n graphics.fillStyle(fillColor, fillAlpha)\n graphics.fillRoundedRect(-bgWidth / 2, -bgHeight / 2, bgWidth, bgHeight, cornerRadius)\n\n // Create container for background + text\n const tooltipContainer = scene.add.container(0, 0, [graphics, text])\n tooltipContainer.setDepth(10000)\n\n // Measure container bounds\n const textBounds = tooltipContainer.getBounds()\n\n // Calculate position\n const pos = calculateTooltipPosition(\n targetBounds,\n position,\n offset,\n textBounds.width,\n textBounds.height\n )\n\n // Animation config - merge config with theme defaults\n const themeAnim = tooltipTheme.animation || {}\n const anim = config.animation || {}\n const fadeInDuration = anim.fadeIn ?? themeAnim.fadeIn ?? 200\n const moveOffset = {\n dx: anim.move?.dx ?? themeAnim.move?.dx ?? 0,\n dy: anim.move?.dy ?? themeAnim.move?.dy ?? 0,\n }\n const pulse = anim.pulse ?? themeAnim.pulse ?? false\n const pulseScale = anim.pulseScale ?? [0.75, 1.25]\n\n // Set initial position (with move offset if enabled)\n tooltipContainer.setPosition(\n pos.x + textBounds.width / 2 - moveOffset.dx,\n pos.y + textBounds.height / 2 - moveOffset.dy\n )\n tooltipContainer.setAlpha(0)\n\n state.tooltip = tooltipContainer\n\n // Fade in animation\n const fadeTween = scene.tweens.add({\n targets: tooltipContainer,\n alpha: 1,\n x: pos.x + textBounds.width / 2,\n y: pos.y + textBounds.height / 2,\n duration: fadeInDuration,\n ease: 'Cubic.Out',\n })\n state.activeTweens.push(fadeTween)\n\n // Pulse animation\n if (pulse) {\n const pulseTween = scene.tweens.add({\n targets: tooltipContainer,\n scale: { from: pulseScale[0], to: pulseScale[1] },\n duration: 600,\n yoyo: true,\n repeat: -1,\n ease: 'Sine.InOut',\n })\n state.activeTweens.push(pulseTween)\n }\n\n // Auto-dismiss timer if configured\n if (config.autoDismiss && config.autoDismiss > 0) {\n state.autoDismissTimer = setTimeout(() => {\n hideTooltip(container)\n }, config.autoDismiss)\n }\n}\n\n/**\n * Hide tooltip for a container\n */\nfunction hideTooltip(container: Phaser.GameObjects.Container): void {\n const state = tooltipStates.get(container)\n if (!state || !state.isVisible) return\n\n state.isVisible = false\n const config = state.currentConfig\n state.currentConfig = null\n\n // Clear auto-dismiss timer\n if (state.autoDismissTimer) {\n clearTimeout(state.autoDismissTimer)\n state.autoDismissTimer = null\n }\n\n if (!state.tooltip) return\n\n const tooltip = state.tooltip\n const scene = tooltip.scene\n\n // Get theme defaults for fade out\n const theme = themeRegistry.getGlobalTheme()\n const tooltipTheme = theme.Tooltip || {}\n const themeAnim = tooltipTheme.animation || {}\n const anim = config?.animation || {}\n const fadeOutDuration = anim.fadeOut ?? themeAnim.fadeOut ?? 200\n\n // Stop all existing tweens\n state.activeTweens.forEach((tween) => tween.stop())\n state.activeTweens = []\n\n // Fade out animation\n scene.tweens.add({\n targets: tooltip,\n alpha: 0,\n duration: fadeOutDuration,\n ease: 'Cubic.In',\n onComplete: () => {\n tooltip.destroy()\n },\n })\n\n state.tooltip = null\n}\n\n/**\n * Apply tooltip functionality to a container\n * Sets up hover handlers and manages tooltip lifecycle\n */\nexport function applyTooltip(\n scene: Phaser.Scene,\n container: Phaser.GameObjects.Container,\n nextCallback: TooltipCallback | undefined,\n existingOnHoverStart?: (data: HoverEventData) => void,\n existingOnHoverEnd?: (data: HoverEventData) => void\n): {\n onHoverStart: (data: HoverEventData) => void\n onHoverEnd: (data: HoverEventData) => void\n} {\n // Initialize state if needed\n if (!tooltipStates.has(container)) {\n tooltipStates.set(container, {\n isVisible: false,\n tooltip: null,\n activeTweens: [],\n showTimer: null,\n hideTimer: null,\n autoDismissTimer: null,\n currentConfig: null,\n })\n\n // Cleanup on container destroy\n container.once('destroy', () => {\n const state = tooltipStates.get(container)\n if (state) {\n if (state.showTimer) clearTimeout(state.showTimer)\n if (state.hideTimer) clearTimeout(state.hideTimer)\n if (state.autoDismissTimer) clearTimeout(state.autoDismissTimer)\n state.activeTweens.forEach((tween) => tween.stop())\n hideTooltip(container)\n tooltipStates.delete(container)\n }\n })\n }\n\n const state = tooltipStates.get(container)\n if (!state) {\n throw new Error('applyTooltip: state not initialized')\n }\n\n const theme = themeRegistry.getGlobalTheme()\n const tooltipTheme = theme.Tooltip || {}\n\n // Create hover handlers\n const onHoverStart = (data: HoverEventData) => {\n // Call existing handler if present\n if (existingOnHoverStart) existingOnHoverStart(data)\n\n // Get tooltip config\n if (!nextCallback) return\n\n const result = nextCallback()\n if (!result) return // null/undefined = no tooltip\n\n const config: TooltipConfig = typeof result === 'string' ? { content: result } : result\n\n if (config.disabled) return\n\n // Clear any pending hide/auto-dismiss timers\n if (state.hideTimer) {\n clearTimeout(state.hideTimer)\n state.hideTimer = null\n }\n if (state.autoDismissTimer) {\n clearTimeout(state.autoDismissTimer)\n state.autoDismissTimer = null\n }\n\n // Start show timer\n const showDelay = config.showDelay ?? tooltipTheme.showDelay ?? 500\n state.showTimer = setTimeout(() => {\n showTooltip(scene, container, config)\n }, showDelay)\n }\n\n const onHoverEnd = (data: HoverEventData) => {\n // Call existing handler if present\n if (existingOnHoverEnd) existingOnHoverEnd(data)\n\n // Clear any pending show timer\n if (state.showTimer) {\n clearTimeout(state.showTimer)\n state.showTimer = null\n }\n\n // Start hide timer\n const hideDelay = state.currentConfig?.hideDelay ?? tooltipTheme.hideDelay ?? 0\n if (hideDelay > 0) {\n state.hideTimer = setTimeout(() => {\n hideTooltip(container)\n }, hideDelay)\n } else {\n hideTooltip(container)\n }\n }\n\n return { onHoverStart, onHoverEnd }\n}\n","/**\n * Shared property creators for component initialization\n * These functions avoid code duplication when creating nodes with initial properties\n */\nimport type Phaser from 'phaser'\nimport type { BackgroundProps } from '../../core-props'\n\n/**\n * Create background graphics for container-based components\n * @param scene - Phaser scene\n * @param container - Container to add background to\n * @param props - Props with background settings\n */\nexport function createBackground(\n scene: Phaser.Scene,\n container: Phaser.GameObjects.Container & { __background?: Phaser.GameObjects.Graphics },\n props: Partial<\n BackgroundProps & { width?: number | string | undefined; height?: number | string | undefined }\n >\n): void {\n const hasBackground = props.backgroundColor !== undefined\n const hasBorder = props.borderColor !== undefined\n\n // Create graphics if either background or border is specified\n if (hasBackground || hasBorder) {\n const width = typeof props.width === 'number' ? props.width : 100\n const height = typeof props.height === 'number' ? props.height : 100\n const bgColor = props.backgroundColor as number | undefined\n const bgAlpha = props.backgroundAlpha ?? 1\n const cornerRadius = props.cornerRadius ?? 0\n const borderColor = props.borderColor\n const borderWidth = props.borderWidth ?? 0\n const borderAlpha = props.borderAlpha ?? 1\n\n const background = scene.add.graphics()\n\n // Fill style (only if background color is specified)\n if (bgColor !== undefined) {\n background.fillStyle(bgColor, bgAlpha)\n }\n\n // Border style (if specified)\n if (borderWidth > 0 && borderColor !== undefined) {\n background.lineStyle(borderWidth, borderColor, borderAlpha)\n }\n\n // Draw shape\n if (cornerRadius !== 0) {\n if (bgColor !== undefined) {\n background.fillRoundedRect(0, 0, width, height, cornerRadius)\n }\n if (borderWidth > 0 && borderColor !== undefined) {\n background.strokeRoundedRect(0, 0, width, height, cornerRadius)\n }\n } else {\n if (bgColor !== undefined) {\n background.fillRect(0, 0, width, height)\n }\n if (borderWidth > 0 && borderColor !== undefined) {\n background.strokeRect(0, 0, width, height)\n }\n }\n\n container.addAt(background, 0)\n container.__background = background\n // Mark as background so layout system can skip it\n ;(background as Phaser.GameObjects.Graphics & { __isBackground?: boolean }).__isBackground =\n true\n }\n}\n","/**\n * Gesture setup for component initialization\n * Registers containers with the GestureManager for high-level gesture detection\n */\nimport type { LayoutSize } from '@number10/phaserjsx/layout/types'\nimport Phaser from 'phaser'\nimport type { GestureProps, LayoutProps } from '../../core-props'\nimport { getGestureManager } from '../../gestures/gesture-manager'\nimport type { GestureCallbacks } from '../../gestures/gesture-types'\n\n/**\n * Setup gesture tracking for container-based components\n * Only registers if enableGestures is true and at least one gesture callback exists\n * @param scene - Scene containing the gesture manager\n * @param container - Container to make gesture-aware\n * @param props - Props with gesture settings\n */\nexport function createGestures(\n scene: Phaser.Scene,\n container: Phaser.GameObjects.Container,\n props: Partial<GestureProps & LayoutProps>\n): void {\n // Check if any gesture callback is defined\n const hasAnyGesture = !!(\n props.onTouch ||\n props.onTouchOutside ||\n props.onTouchMove ||\n props.onDoubleTap ||\n props.onLongPress ||\n props.onHoverStart ||\n props.onHoverEnd ||\n props.onWheel\n )\n\n // Auto-enable gestures if callbacks are provided, unless explicitly disabled\n const shouldEnable = hasAnyGesture && props.enableGestures !== false\n\n if (!shouldEnable) {\n return\n }\n\n // Get scene's gesture manager\n const manager = getGestureManager(scene)\n\n // Get actual calculated container size from layout system\n // Use __getLayoutSize if available (set by createLayout), otherwise fallback to getBounds\n const containerWithLayout = container as typeof container & {\n __getLayoutSize?: () => LayoutSize\n }\n\n let width = 100\n let height = 100\n\n if (containerWithLayout.__getLayoutSize) {\n const size = containerWithLayout.__getLayoutSize()\n width = size.width\n height = size.height\n } else {\n // Fallback to getBounds if __getLayoutSize not available yet\n const bounds = container.getBounds()\n width = bounds.width || 100\n height = bounds.height || 100\n }\n\n // Create hit area with origin at (0,0) - matches our component system\n const hitArea = new Phaser.Geom.Rectangle(0, 0, width, height)\n\n // Build callbacks object\n const callbacks: GestureCallbacks = {}\n if (props.onTouch) callbacks.onTouch = props.onTouch\n if (props.onTouchOutside) callbacks.onTouchOutside = props.onTouchOutside\n if (props.onTouchMove) callbacks.onTouchMove = props.onTouchMove\n if (props.onDoubleTap) callbacks.onDoubleTap = props.onDoubleTap\n if (props.onLongPress) callbacks.onLongPress = props.onLongPress\n if (props.onHoverStart) callbacks.onHoverStart = props.onHoverStart\n if (props.onHoverEnd) callbacks.onHoverEnd = props.onHoverEnd\n if (props.onWheel) callbacks.onWheel = props.onWheel\n\n // Build config (only include defined values)\n const config: { longPressDuration?: number; doubleTapDelay?: number; maxTouchDuration?: number } =\n {}\n if (props.longPressDuration !== undefined) config.longPressDuration = props.longPressDuration\n if (props.doubleTapDelay !== undefined) config.doubleTapDelay = props.doubleTapDelay\n if (props.maxTouchDuration !== undefined) config.maxTouchDuration = props.maxTouchDuration\n\n // Register with manager\n manager.registerContainer(container, callbacks, hitArea, config)\n}\n","/**\n * Layout creator for initializing container layout system\n */\nimport type { BackgroundProps, LayoutProps, TransformProps } from '../../core-props'\nimport { normalizeGap } from '../../core-props'\nimport {\n getChildSize,\n parseSize,\n resolveSize,\n type GameObjectWithLayout,\n type LayoutSize,\n} from '../../layout/index'\n\n/**\n * Creates layout infrastructure for a container\n * Attaches layout props and dynamic size provider\n * @param container - Phaser container\n * @param props - Layout props\n */\nexport function createLayout(\n container: Phaser.GameObjects.Container & {\n __layoutProps?: LayoutProps & BackgroundProps & TransformProps\n __getLayoutSize?: () => LayoutSize\n width?: number | string\n height?: number | string\n },\n props: Partial<LayoutProps & BackgroundProps & TransformProps>\n): void {\n // Attach layout props for layout calculations (includes visible for display control)\n container.__layoutProps = props as LayoutProps & BackgroundProps & TransformProps\n\n // Attach dynamic size provider\n // This returns the calculated dimensions after layout\n container.__getLayoutSize = () => {\n const children = container.list as GameObjectWithLayout[]\n\n const direction = props.direction ?? 'column'\n const paddingRaw = props.padding ?? {}\n const padding =\n typeof paddingRaw === 'number'\n ? { left: paddingRaw, top: paddingRaw, right: paddingRaw, bottom: paddingRaw }\n : paddingRaw\n const paddingLeft = padding.left ?? 0\n const paddingTop = padding.top ?? 0\n const paddingRight = padding.right ?? 0\n const paddingBottom = padding.bottom ?? 0\n const gapNormalized = normalizeGap(props.gap)\n\n let maxWidth = 0\n let maxHeight = 0\n let totalMainSize = 0\n\n // Count non-background children\n let childCount = 0\n\n for (const child of children) {\n if (child.__isBackground) {\n continue\n }\n\n childCount++\n\n const marginRaw = child.__layoutProps?.margin ?? {}\n const margin =\n typeof marginRaw === 'number'\n ? { top: marginRaw, right: marginRaw, bottom: marginRaw, left: marginRaw }\n : marginRaw\n const marginTop = margin.top ?? 0\n const marginBottom = margin.bottom ?? 0\n const marginLeft = margin.left ?? 0\n const marginRight = margin.right ?? 0\n\n const childSize = getChildSize(child)\n\n if (direction === 'row') {\n // Horizontal layout\n totalMainSize += marginLeft + childSize.width + marginRight\n const childTotalHeight = marginTop + childSize.height + marginBottom\n maxHeight = Math.max(maxHeight, childTotalHeight)\n } else {\n // Vertical layout (column)\n const childTotalWidth = marginLeft + childSize.width + marginRight\n maxWidth = Math.max(maxWidth, childTotalWidth)\n totalMainSize += marginTop + childSize.height + marginBottom\n }\n }\n\n // Add gaps to total main size\n if (childCount > 1) {\n const gapValue = direction === 'row' ? gapNormalized.horizontal : gapNormalized.vertical\n totalMainSize += gapValue * (childCount - 1)\n }\n\n const defaultWidth =\n direction === 'row'\n ? totalMainSize + paddingLeft + paddingRight\n : maxWidth + paddingLeft + paddingRight\n const defaultHeight =\n direction === 'row'\n ? maxHeight + paddingTop + paddingBottom\n : totalMainSize + paddingTop + paddingBottom\n\n // Resolve width (handle percentage and auto)\n const parsedWidth = parseSize(props.width)\n const finalWidth = resolveSize(parsedWidth, undefined, defaultWidth)\n\n // Resolve height (handle percentage and auto)\n const parsedHeight = parseSize(props.height)\n const finalHeight = resolveSize(parsedHeight, undefined, defaultHeight)\n\n return {\n width: finalWidth,\n height: finalHeight,\n }\n }\n}\n","/**\n * View component - Phaser Container with background Graphics and layout system\n * Status: IMPLEMENTED ✅\n *\n * Design Overview:\n * ================\n *\n * 1. Component Role: LAYOUT CONTAINER\n * Purpose: Primary layout primitive for UI composition\n * Composition: Phaser.Container + Background Graphics (optional)\n * Responsibilities:\n * - Layout orchestration (flexbox-style positioning of children)\n * - Visual styling (background color, borders, corner radius)\n * - Gesture handling (touch/mouse interaction)\n * - Dimension management (defines its own size + provides context for children)\n *\n * 2. Headless Behavior: NEVER HEADLESS ⚠️\n * Decision: View cannot be headless (always participates in layout)\n * Reasoning:\n * - View IS the layout system - it defines layout context for children\n * - Background Graphics has special role (__isBackground flag)\n * - Graphics is internal to View, excluded from child layout calculations\n * - If you need non-layout container, use raw Phaser.Container directly\n *\n * 3. Layout System Architecture:\n * Two-part system:\n * A) Background Graphics (special role):\n * - Defines View dimensions (not a layout child!)\n * - Marked with __isBackground = true\n * - Filtered out in layout calculations (see isLayoutChild helper)\n * - Automatically resized to match container dimensions\n * B) Layout Engine:\n * - Processes children (Views, Text, Images, etc.)\n * - Applies flexbox-style layout (row/column/stack)\n * - Respects headless flag on children\n * - Updates child positions/sizes based on layout props\n *\n * 4. Background Graphics vs. Graphics Component:\n * Distinction:\n * - View Background: Internal, auto-managed, defines dimensions, __isBackground=true\n * - Graphics Component: User-facing, custom shapes, typically headless=true\n * - Both use Phaser.Graphics but completely different purposes\n *\n * 5. Layout Size Provider:\n * Implementation: __getLayoutSize returns explicit or calculated dimensions\n * Behavior:\n * - Explicit width/height: Use those values\n * - Auto-size (undefined): Calculate from children + padding\n * - Percentage/fill: Resolve from parent context\n * - Critical: Background Graphics updates to match final size\n *\n * 6. Gesture System Integration:\n * Features:\n * - enableGestures: true enables touch/mouse interaction\n * - Hit area automatically sized to container dimensions\n * - Updated after layout recalculation (deferred queue)\n * - Supports: onTouch, onTouchMove, onDoubleTap, onLongPress\n * - Cross-platform (transparent mouse/touch support)\n *\n * 7. Styling Props:\n * Background:\n * - backgroundColor/backgroundAlpha: Fill color\n * - cornerRadius: Rounded corners (number or per-corner object)\n * - borderColor/borderWidth/borderAlpha: Stroke\n * Auto-defaults:\n * - backgroundAlpha defaults to 1 if backgroundColor set\n * - borderWidth defaults to 1 if borderColor set\n *\n * 8. Common Patterns:\n * Layout Container:\n * <View direction=\"row\" gap={10} padding={20}>\n * <View flex={1}>Left</View>\n * <View flex={2}>Right</View>\n * </View>\n * Styled Box:\n * <View backgroundColor={0x3498db} cornerRadius={8} padding={16}>\n * <Text text=\"Card Content\" />\n * </View>\n * Interactive Area:\n * <View enableGestures={true} onTouch={() => console.log('clicked')}>\n * <Text text=\"Button\" />\n * </View>\n *\n * 9. Performance Considerations:\n * - Background Graphics redrawn only when visual props change\n * - Layout calculations batched (LayoutBatchQueue)\n * - Gesture hit areas updated in deferred queue (post-layout)\n * - Overflow masking (overflow=\"hidden\") adds Phaser mask overhead\n *\n * 10. Known Limitations:\n * - Background Graphics cannot be independently positioned/rotated\n * - Nested View layout recalculations can be expensive (use sparingly)\n * - Gesture system requires scene pointer plugin (auto-enabled)\n *\n * Implementation Status:\n * ======================\n * [✅] Phaser Container creation\n * [✅] Background Graphics with styling (color, border, radius)\n * [✅] Layout system integration (__layoutProps, __getLayoutSize)\n * [✅] Transform props (position, rotation, scale, alpha)\n * [✅] Gesture system (enableGestures, interaction callbacks)\n * [✅] Auto-defaults for background/border alpha\n * [✅] Overflow masking support\n * [✅] Theme system integration\n * [✅] Deferred layout queue for gesture updates\n */\nimport Phaser from 'phaser'\nimport type {\n BackgroundProps,\n GestureProps,\n LayoutProps,\n PhaserProps,\n TransformProps,\n} from '../../core-props'\nimport { DebugLogger } from '../../dev-config'\nimport type { HostCreator, HostPatcher } from '../../host'\nimport type { PropsContainerExtension, PropsDefaultExtension } from '../../types'\nimport { applyBackgroundProps } from '../appliers/applyBackground'\nimport { applyGesturesProps } from '../appliers/applyGestures'\nimport { applyLayoutProps } from '../appliers/applyLayout'\nimport { applyPhaserProps } from '../appliers/applyPhaser'\nimport { applyTooltip } from '../appliers/applyTooltip'\nimport { applyTransformProps } from '../appliers/applyTransform'\nimport { createBackground } from '../creators/createBackground'\nimport { createGestures } from '../creators/createGestures'\nimport { createLayout } from '../creators/createLayout'\nimport { createPhaser } from '../creators/createPhaser'\nimport { createTransform } from '../creators/createTransform'\n\n/**\n * Normalize background props - apply auto-defaults for alpha and border width\n * @param props - Original props\n * @returns Normalized props with auto-defaults applied\n */\nfunction normalizeBackgroundProps<T>(props: T): T {\n // Only process if props contain background/border properties\n const bgProps = props as unknown as Partial<BackgroundProps>\n const hasBackground = bgProps.backgroundColor !== undefined\n const hasBorder = bgProps.borderColor !== undefined\n\n // If no background/border props, return as-is\n if (!hasBackground && !hasBorder) {\n return props\n }\n\n // Only apply defaults if the prop is explicitly undefined or 0 (theme default)\n // This allows users to override with explicit values\n const normalized = { ...props } as T & Partial<BackgroundProps>\n\n if (hasBackground && bgProps.backgroundAlpha === undefined) {\n normalized.backgroundAlpha = 1\n }\n\n if (hasBorder) {\n if (bgProps.borderWidth === undefined || bgProps.borderWidth === 0) {\n normalized.borderWidth = 1\n }\n if (bgProps.borderAlpha === undefined || bgProps.borderAlpha === 0) {\n normalized.borderAlpha = 1\n }\n }\n\n return normalized as T\n}\n\n/**\n * Base props for View - composing shared prop groups\n */\nexport interface ViewBaseProps\n extends TransformProps,\n PhaserProps,\n LayoutProps,\n BackgroundProps,\n GestureProps {}\n\n/**\n * Props for View (Container) component - extends base props with JSX-specific props\n */\nexport interface ViewProps\n extends ViewBaseProps,\n PropsDefaultExtension<Phaser.GameObjects.Container>,\n PropsContainerExtension {}\n\n/**\n * View creator - creates a Phaser Container with optional background and interaction\n */\nexport const viewCreator: HostCreator<'View'> = (scene, props) => {\n // Debug: Log props to verify theme values\n if (props.backgroundColor !== undefined || props.cornerRadius !== undefined) {\n DebugLogger.log('theme', 'View Creator - Props received:', {\n backgroundColor: props.backgroundColor,\n cornerRadius: props.cornerRadius,\n width: props.width,\n height: props.height,\n })\n }\n\n // Normalize props early - apply auto-defaults for background/border\n const normalizedProps = normalizeBackgroundProps(props)\n\n const container = scene.add.container(normalizedProps.x ?? 0, normalizedProps.y ?? 0)\n\n // Apply transform props (scale, rotation)\n createTransform(container, normalizedProps)\n\n // Apply Phaser display props (alpha, depth, visible)\n createPhaser(container, normalizedProps)\n\n // Add background if backgroundColor is provided\n createBackground(\n scene,\n container as typeof container & { __background?: Phaser.GameObjects.Graphics },\n normalizedProps\n )\n\n // Setup layout system (props and size provider)\n // Must be before createGestures so __getLayoutSize is available\n createLayout(container, normalizedProps)\n\n // Tooltip support - inject hover handlers if onTooltip is present\n if (normalizedProps.onTooltip) {\n const handlers = applyTooltip(\n scene,\n container,\n normalizedProps.onTooltip,\n normalizedProps.onHoverStart,\n normalizedProps.onHoverEnd\n )\n normalizedProps.onHoverStart = handlers.onHoverStart\n normalizedProps.onHoverEnd = handlers.onHoverEnd\n }\n\n // Setup gesture system (high-level touch/mouse gestures)\n createGestures(scene, container, normalizedProps)\n\n // Debug: Log layout props storage\n DebugLogger.log(\n 'layout',\n 'View creator storing __layoutProps with padding:',\n normalizedProps.padding\n )\n\n return container\n}\n\n/**\n * View patcher - updates View properties\n */\nexport const viewPatcher: HostPatcher<'View'> = (node, prev, next) => {\n // Normalize props early - apply auto-defaults for background/border\n const normalizedPrev = normalizeBackgroundProps(prev)\n const normalizedNext = normalizeBackgroundProps(next)\n\n // Apply transform props (position, rotation, scale)\n applyTransformProps(node, normalizedPrev, normalizedNext)\n\n // Apply Phaser display props (alpha, depth, visible)\n applyPhaserProps(node, normalizedPrev, normalizedNext)\n\n // Background updates\n const container = node as Phaser.GameObjects.Container & {\n __background?: Phaser.GameObjects.Graphics\n }\n\n applyBackgroundProps(container, normalizedPrev, normalizedNext)\n\n // Tooltip support (integrates with gesture system)\n // Apply before gestures so hover handlers can be injected\n if (container.scene && container.scene.data) {\n if (normalizedNext.onTooltip) {\n const handlers = applyTooltip(\n container.scene,\n container,\n normalizedNext.onTooltip,\n normalizedNext.onHoverStart,\n normalizedNext.onHoverEnd\n )\n // Inject hover handlers for tooltip\n normalizedNext.onHoverStart = handlers.onHoverStart\n normalizedNext.onHoverEnd = handlers.onHoverEnd\n }\n }\n\n // Gesture event handlers (high-level touch/mouse gestures)\n // Safety check: ensure container has valid scene before applying gestures\n if (container.scene && container.scene.data) {\n applyGesturesProps(container.scene, container, normalizedPrev, normalizedNext)\n }\n\n // Apply layout props and recalculate if needed\n applyLayoutProps(container, normalizedPrev, normalizedNext)\n}\n","/** @jsxImportSource ../.. */\n/**\n * Sprite component wrapper - strict type-safe wrapper around primitive sprite\n * This component is the public API for Sprite, with controlled prop interface\n */\nimport type { VNodeLike } from '@number10/phaserjsx/vdom'\nimport type Phaser from 'phaser'\nimport type { LayoutProps, PhaserProps, TransformProps } from '../../core-props'\nimport { useTheme } from '../../hooks'\nimport { getThemedProps } from '../../theme'\nimport type { ChildrenType, PropsDefaultExtension } from '../../types'\n\n/**\n * Props for Sprite component\n * Explicitly defined to ensure type safety in JSX usage\n */\nexport interface SpriteProps\n extends TransformProps,\n PhaserProps,\n Omit<LayoutProps, 'direction' | 'justifyContent' | 'alignItems' | 'gap' | 'flexWrap'>,\n PropsDefaultExtension<Phaser.GameObjects.Sprite> {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas or spritesheet */\n frame?: string | number\n\n /** Tint color applied to sprite (0xRRGGBB) */\n tint?: number\n\n /** Display width (scales sprite to fit) */\n displayWidth?: number\n\n /** Display height (scales sprite to fit) */\n displayHeight?: number\n\n /**\n * How sprite should fit within bounds (if displayWidth/displayHeight set)\n * - 'fill': Stretch to fill (default, may distort aspect ratio)\n * - 'contain': Scale to fit within bounds, preserve aspect ratio\n * - 'cover': Scale to cover bounds, preserve aspect ratio (may crop)\n */\n fit?: 'fill' | 'contain' | 'cover'\n\n /** Animation key to play (pre-registered in Phaser AnimationManager) */\n animationKey?: string\n\n /** Loop animation (default: false) */\n loop?: boolean\n\n /** Delay between animation repeats in ms (default: 0) */\n repeatDelay?: number\n\n /** Callback when animation starts */\n onAnimationStart?: (key: string) => void\n\n /** Callback when animation completes */\n onAnimationComplete?: (key: string) => void\n\n /** Callback when animation repeats */\n onAnimationRepeat?: (key: string) => void\n\n /** Callback on each animation frame update */\n onAnimationUpdate?: (key: string, frame: Phaser.Animations.AnimationFrame) => void\n\n /** Origin X (0-1, default 0.5) */\n originX?: number\n\n /** Origin Y (0-1, default 0.5) */\n originY?: number\n\n /** Children are not supported for Sprite component */\n children?: ChildrenType\n}\n\n/**\n * Sprite component\n * Displays animated sprites with Phaser animation system\n *\n * @example\n * ```tsx\n * // Basic sprite\n * <Sprite texture=\"player\" frame=\"idle\" />\n *\n * // Animated sprite\n * <Sprite\n * texture=\"player\"\n * animationKey=\"walk\"\n * loop={true}\n * />\n *\n * // Scaled sprite with fit\n * <Sprite\n * texture=\"coin\"\n * displayWidth={32}\n * displayHeight={32}\n * fit=\"contain\"\n * />\n * ```\n */\nexport function Sprite(props: SpriteProps): VNodeLike {\n const localTheme = useTheme()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { props: themed, nestedTheme } = getThemedProps('Sprite', localTheme, props as any)\n\n // Cast to any to bypass type checking - the props are correct at runtime\n return <sprite {...themed} theme={nestedTheme} />\n}\n","/** @jsxImportSource ../.. */\n/**\n * TileSprite component wrapper - strict type-safe wrapper around primitive tilesprite\n * This component is the public API for TileSprite, with controlled prop interface\n */\nimport type { VNodeLike } from '@number10/phaserjsx/vdom'\nimport type Phaser from 'phaser'\nimport type { PhaserProps, TransformProps } from '../../core-props'\nimport { useTheme } from '../../hooks'\nimport { getThemedProps } from '../../theme'\nimport type { ChildrenType, PropsDefaultExtension } from '../../types'\n\n/**\n * Props for TileSprite component\n * Explicitly defined to ensure type safety in JSX usage\n */\nexport interface TileSpriteProps\n extends TransformProps,\n PhaserProps,\n PropsDefaultExtension<Phaser.GameObjects.TileSprite> {\n /** Texture key (loaded via Phaser's texture manager) */\n texture: string\n\n /** Optional frame from texture atlas */\n frame?: string | number\n\n /** Width of the tile sprite area */\n width: number\n\n /** Height of the tile sprite area */\n height: number\n\n /** Horizontal tile position offset (for scrolling effect) */\n tilePositionX?: number\n\n /** Vertical tile position offset (for scrolling effect) */\n tilePositionY?: number\n\n /** Horizontal tile scale factor */\n tileScaleX?: number\n\n /** Vertical tile scale factor */\n tileScaleY?: number\n\n /** Tint color applied to tiles (0xRRGGBB) */\n tint?: number\n\n /** Origin X (0-1, default 0) */\n originX?: number\n\n /** Origin Y (0-1, default 0) */\n originY?: number\n\n /** Children are not supported for TileSprite component */\n children?: ChildrenType\n}\n\n/**\n * TileSprite component\n * Displays repeating texture patterns for backgrounds and effects\n *\n * @example\n * ```tsx\n * // Scrolling background\n * <TileSprite\n * texture=\"clouds\"\n * width={800}\n * height={200}\n * tilePositionX={scrollOffset}\n * />\n *\n * // Scaled tiles\n * <TileSprite\n * texture=\"pattern\"\n * width={400}\n * height={400}\n * tileScaleX={2}\n * tileScaleY={2}\n * />\n * ```\n */\nexport function TileSprite(props: TileSpriteProps): VNodeLike {\n const localTheme = useTheme()\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const { props: themed, nestedTheme } = getThemedProps('TileSprite', localTheme, props as any)\n\n // Cast to any to bypass type checking - the props are correct at runtime\n return <tilesprite {...themed} theme={nestedTheme} />\n}\n","/**\n * Built-in component implementations\n * Exports creators, patchers, props and registration function for all components\n */\nimport { register } from '../host'\nimport { graphicsCreator, graphicsPatcher } from './primitives/graphics'\nimport { imageCreator, imagePatcher } from './primitives/image'\nimport { nineSliceCreator, nineSlicePatcher } from './primitives/nineslice'\nimport { particlesCreator, particlesPatcher } from './primitives/particles'\nimport { spriteCreator, spritePatcher } from './primitives/sprite'\nimport { textCreator, textPatcher } from './primitives/text'\nimport { tileSpriteCreator, tileSpritePatcher } from './primitives/tilesprite'\nimport { viewCreator, viewPatcher } from './primitives/view'\n\n/**\n * Component type constants for JSX usage (legacy primitives)\n * Note: All primitive components now have custom wrappers\n * Use lowercase primitives internally or import wrappers from custom\n */\n\n/**\n * Registers all built-in components with the host\n * This should be called during library initialization\n * Note: TileSprite is currently dummy (throws on use)\n */\nexport function registerBuiltins() {\n // Register primitives (lowercase) - internal use\n register('view' as 'View', { create: viewCreator, patch: viewPatcher })\n register('text' as 'Text', { create: textCreator, patch: textPatcher })\n register('nineslice' as 'NineSlice', { create: nineSliceCreator, patch: nineSlicePatcher })\n register('particles' as 'Particles', { create: particlesCreator, patch: particlesPatcher })\n register('sprite' as 'Sprite', { create: spriteCreator, patch: spritePatcher })\n register('image' as 'Image', { create: imageCreator, patch: imagePatcher })\n register('graphics' as 'Graphics', { create: graphicsCreator, patch: graphicsPatcher })\n register('tilesprite' as 'TileSprite', { create: tileSpriteCreator, patch: tileSpritePatcher })\n\n // Register uppercase variants for backward compatibility\n register('View', { create: viewCreator, patch: viewPatcher })\n register('Text', { create: textCreator, patch: textPatcher })\n register('NineSlice', { create: nineSliceCreator, patch: nineSlicePatcher })\n register('Particles', { create: particlesCreator, patch: particlesPatcher })\n register('Sprite', { create: spriteCreator, patch: spritePatcher })\n register('Image', { create: imageCreator, patch: imagePatcher })\n register('Graphics', { create: graphicsCreator, patch: graphicsPatcher })\n register('TileSprite', { create: tileSpriteCreator, patch: tileSpritePatcher })\n\n // Register internal SceneWrapper component (for mountJSX auto-sizing)\n // SceneWrapper is a function component, not a primitive, so it doesn't need creators\n // It will be handled by the function component path in mount()\n}\n\n// Re-export layout types\nexport { type LayoutSize } from './../layout/types'\n\n// Re-export custom components (public API)\nexport { Button, type ButtonProps } from './custom/Button'\nexport { Graphics, type GraphicsProps } from './custom/Graphics'\nexport { RadioButton, type RadioButtonProps } from './custom/RadioButton'\nexport { RadioGroup, type RadioGroupOption, type RadioGroupProps } from './custom/RadioGroup'\nexport { Sprite, type SpriteProps } from './custom/Sprite'\nexport { Text, type TextProps } from './custom/Text'\nexport { TileSprite, type TileSpriteProps } from './custom/TileSprite'\nexport { View, type ViewProps } from './custom/View'\nexport { Particles, type ParticlesProps } from './custom/Particles'\n\n// Re-export primitive creators/patchers for advanced use cases\nexport { textCreator, textPatcher, type TextBaseProps } from './primitives/text'\nexport { viewCreator, viewPatcher, type ViewBaseProps } from './primitives/view'\n\n// Re-export NineSlice primitive (internal use only - prefer custom wrapper)\nexport {\n nineSliceCreator,\n nineSlicePatcher,\n type NineSliceBaseProps,\n type NineSliceInnerBounds,\n type NineSlicePrimitiveProps,\n type NineSliceRef,\n} from './primitives/nineslice'\n\n// Re-export Sprite primitive (internal use only - prefer custom wrapper)\nexport { spriteCreator, spritePatcher, type SpriteBaseProps } from './primitives/sprite'\nexport { particlesCreator, particlesPatcher, type ParticlesBaseProps } from './primitives/particles'\n\n// Re-export Image component (dummy, no wrapper yet)\nexport {\n imageCreator,\n imagePatcher,\n type ImageBaseProps,\n type ImagePrimitiveProps,\n} from './primitives/image'\n\n// Re-export Graphics primitive (internal use only - prefer custom wrapper)\nexport { graphicsCreator, graphicsPatcher, type GraphicsBaseProps } from './primitives/graphics'\n\n// Re-export TileSprite primitive (internal use only - prefer custom wrapper)\nexport {\n tileSpriteCreator,\n tileSpritePatcher,\n type TileSpriteBaseProps,\n} from './primitives/tilesprite'\n","/**\n * Hook and creators for Phaser camera effects\n */\nimport Phaser from 'phaser'\nimport { useCallback, useEffect, useRef, useScene } from '../hooks'\nimport type { RefObject } from '../types'\n\n/**\n * Base camera FX config\n */\nexport interface CameraFXConfig {\n duration?: number\n force?: boolean\n onComplete?: () => void\n}\n\nexport interface CameraShakeConfig extends CameraFXConfig {\n intensity?: number | { x: number; y: number }\n}\n\nexport interface CameraFlashConfig extends CameraFXConfig {\n red?: number\n green?: number\n blue?: number\n}\n\nexport interface CameraFadeConfig extends CameraFXConfig {\n red?: number\n green?: number\n blue?: number\n direction?: 'in' | 'out'\n}\n\nexport interface CameraZoomConfig extends CameraFXConfig {\n zoom?: number\n ease?: string\n}\n\n/**\n * Camera FX creator function signature\n */\nexport type CameraFXFn<TConfig extends CameraFXConfig = CameraFXConfig> = (\n camera: Phaser.Cameras.Scene2D.Camera,\n config: TConfig\n) => (() => void) | void\n\nexport const createCameraShakeFX: CameraFXFn<CameraShakeConfig> = (camera, config) => {\n const duration = config.duration ?? 250\n const intensity =\n typeof config.intensity === 'object'\n ? new Phaser.Math.Vector2(config.intensity.x, config.intensity.y)\n : (config.intensity ?? 0.01)\n camera.shake(duration, intensity, config.force ?? false, config.onComplete)\n}\n\nexport const createCameraFlashFX: CameraFXFn<CameraFlashConfig> = (camera, config) => {\n const duration = config.duration ?? 200\n const red = config.red ?? 255\n const green = config.green ?? 255\n const blue = config.blue ?? 255\n camera.flash(duration, red, green, blue, config.force ?? false, config.onComplete)\n}\n\nexport const createCameraFadeInFX: CameraFXFn<CameraFadeConfig> = (camera, config) => {\n const duration = config.duration ?? 300\n const red = config.red ?? 0\n const green = config.green ?? 0\n const blue = config.blue ?? 0\n camera.fadeIn(duration, red, green, blue, config.onComplete)\n}\n\nexport const createCameraFadeOutFX: CameraFXFn<CameraFadeConfig> = (camera, config) => {\n const duration = config.duration ?? 300\n const red = config.red ?? 0\n const green = config.green ?? 0\n const blue = config.blue ?? 0\n camera.fadeOut(duration, red, green, blue, config.onComplete)\n}\n\nexport const createCameraZoomFX: CameraFXFn<CameraZoomConfig> = (camera, config) => {\n const duration = config.duration ?? 250\n const targetZoom = config.zoom ?? camera.zoom * 1.1\n camera.zoomTo(targetZoom, duration, config.ease, config.force ?? false, config.onComplete)\n}\n\nexport function useCameraFX(\n cameraRef?: RefObject<Phaser.Cameras.Scene2D.Camera | null>,\n options: { resetZoomOnClear?: boolean } = {}\n): {\n applyCameraFX: <TConfig extends CameraFXConfig>(fx: CameraFXFn<TConfig>, config: TConfig) => void\n clearCameraFX: () => void\n} {\n const scene = useScene()\n const activeFxRef = useRef<Set<() => void>>(new Set())\n const baseZoomRef = useRef<number | null>(null)\n\n const getCamera = useCallback(() => {\n return cameraRef?.current ?? scene.cameras.main\n }, [cameraRef, scene])\n\n const applyCameraFX = useCallback(\n <TConfig extends CameraFXConfig>(fx: CameraFXFn<TConfig>, config: TConfig) => {\n const camera = getCamera()\n if (!camera) {\n console.warn('[useCameraFX] No camera available')\n return\n }\n\n if (baseZoomRef.current === null) {\n baseZoomRef.current = camera.zoom\n }\n\n const cleanup = fx(camera, config)\n if (typeof cleanup === 'function') {\n activeFxRef.current.add(cleanup)\n }\n },\n [getCamera]\n )\n\n const clearCameraFX = useCallback(() => {\n const camera = getCamera()\n activeFxRef.current.forEach((cleanup) => cleanup())\n activeFxRef.current.clear()\n\n if (!camera) return\n const cameraWithStops = camera as unknown as {\n stopShake?: () => void\n stopFlash?: () => void\n stopFade?: () => void\n }\n if (typeof cameraWithStops.stopShake === 'function') cameraWithStops.stopShake()\n if (typeof cameraWithStops.stopFlash === 'function') cameraWithStops.stopFlash()\n if (typeof cameraWithStops.stopFade === 'function') cameraWithStops.stopFade()\n\n if (options.resetZoomOnClear !== false && baseZoomRef.current !== null) {\n camera.setZoom(baseZoomRef.current)\n }\n }, [getCamera, options.resetZoomOnClear])\n\n useEffect(() => {\n return () => clearCameraFX()\n }, [clearCameraFX])\n\n return { applyCameraFX, clearCameraFX }\n}\n\nexport function useScreenShake(\n config: CameraShakeConfig = {},\n cameraRef?: RefObject<Phaser.Cameras.Scene2D.Camera | null>\n): { clearCameraFX: () => void } {\n const { applyCameraFX, clearCameraFX } = useCameraFX(cameraRef)\n\n useEffect(() => {\n applyCameraFX(createCameraShakeFX, config)\n return () => clearCameraFX()\n }, [applyCameraFX, clearCameraFX, config])\n\n return { clearCameraFX }\n}\n\nexport function useCameraFlash(\n config: CameraFlashConfig = {},\n cameraRef?: RefObject<Phaser.Cameras.Scene2D.Camera | null>\n): { clearCameraFX: () => void } {\n const { applyCameraFX, clearCameraFX } = useCameraFX(cameraRef)\n\n useEffect(() => {\n applyCameraFX(createCameraFlashFX, config)\n return () => clearCameraFX()\n }, [applyCameraFX, clearCameraFX, config])\n\n return { clearCameraFX }\n}\n\nexport function useCameraFade(\n config: CameraFadeConfig = {},\n cameraRef?: RefObject<Phaser.Cameras.Scene2D.Camera | null>\n): { clearCameraFX: () => void } {\n const { applyCameraFX, clearCameraFX } = useCameraFX(cameraRef)\n\n useEffect(() => {\n const fx = config.direction === 'in' ? createCameraFadeInFX : createCameraFadeOutFX\n applyCameraFX(fx, config)\n return () => clearCameraFX()\n }, [applyCameraFX, clearCameraFX, config])\n\n return { clearCameraFX }\n}\n\nexport function useCameraZoom(\n config: CameraZoomConfig = {},\n cameraRef?: RefObject<Phaser.Cameras.Scene2D.Camera | null>\n): { clearCameraFX: () => void } {\n const { applyCameraFX, clearCameraFX } = useCameraFX(cameraRef)\n\n useEffect(() => {\n applyCameraFX(createCameraZoomFX, config)\n return () => clearCameraFX()\n }, [applyCameraFX, clearCameraFX, config])\n\n return { clearCameraFX }\n}\n","/**\n * Camera FX registry - string-based lookup with extension support\n */\nimport {\n createCameraFadeInFX,\n createCameraFadeOutFX,\n createCameraFlashFX,\n createCameraShakeFX,\n createCameraZoomFX,\n type CameraFXConfig,\n type CameraFXFn,\n} from './use-camera-fx'\n\n/**\n * Built-in camera FX names\n */\nexport type BuiltInCameraFXName = 'shake' | 'flash' | 'fadeIn' | 'fadeOut' | 'zoom'\n\n/**\n * Extension point for custom camera FX names\n * Use declaration merging to add custom camera FX:\n * @example\n * ```typescript\n * declare module '@number10/phaserjsx' {\n * interface CameraFXNameExtensions {\n * myCameraFX: 'myCameraFX'\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface CameraFXNameExtensions {}\n\n/**\n * Available camera FX names (built-in + extensions)\n */\nexport type CameraFXName =\n | BuiltInCameraFXName\n | (keyof CameraFXNameExtensions extends never ? never : keyof CameraFXNameExtensions)\n\n/**\n * Camera FX definition for props/theme usage\n */\nexport interface CameraFXDefinition {\n fx?: CameraFXName\n fxConfig?: CameraFXConfig\n}\n\n/**\n * Camera FX registry mapping names to FX creators\n */\nexport const CAMERA_FX_REGISTRY: Record<BuiltInCameraFXName, CameraFXFn> = {\n shake: createCameraShakeFX,\n flash: createCameraFlashFX,\n fadeIn: createCameraFadeInFX,\n fadeOut: createCameraFadeOutFX,\n zoom: createCameraZoomFX,\n}\n\n/**\n * Default camera FX definition\n */\nexport const DEFAULT_CAMERA_FX: Required<CameraFXDefinition> = {\n fx: 'shake',\n fxConfig: { duration: 200, force: false },\n}\n\n/**\n * Apply a camera FX by name\n */\nexport function applyCameraFXByName(\n applyCameraFX: (fx: CameraFXFn, config: CameraFXConfig) => void,\n fxName?: CameraFXName,\n fxConfig?: CameraFXConfig\n): boolean {\n const name = fxName ?? DEFAULT_CAMERA_FX.fx\n const config = fxConfig ?? DEFAULT_CAMERA_FX.fxConfig\n const fx = CAMERA_FX_REGISTRY[name as BuiltInCameraFXName]\n\n if (fx) {\n applyCameraFX(fx, config)\n return true\n }\n\n return false\n}\n\n/**\n * Resolve camera FX definition with priority: props > default\n */\nexport function resolveCameraFX(props?: CameraFXDefinition): Required<CameraFXDefinition> {\n return {\n fx: props?.fx ?? DEFAULT_CAMERA_FX.fx,\n fxConfig: props?.fxConfig ?? DEFAULT_CAMERA_FX.fxConfig,\n }\n}\n","/**\n * Hook for applying Phaser PostFX/PreFX pipeline effects\n * Manages FX lifecycle with proper cleanup\n */\nimport { useEffect, useRef } from '../hooks'\n\n/**\n * Ref object type\n */\ntype RefObject<T> = { current: T | null }\n\n/**\n * FX configuration base type\n */\nexport interface FXConfig {\n intensity?: number\n quality?: number\n onComplete?: () => void\n}\n\n/**\n * FX type discriminator (postFX vs preFX)\n */\nexport type FXType = 'post' | 'pre'\n\n/**\n * GameObject with FX pipeline support\n */\nexport type FXCapableGameObject =\n | Phaser.GameObjects.Image\n | Phaser.GameObjects.Sprite\n | Phaser.GameObjects.Container\n | Phaser.GameObjects.Text\n | Phaser.GameObjects.TileSprite\n | Phaser.GameObjects.NineSlice\n | Phaser.GameObjects.RenderTexture\n | Phaser.GameObjects.Video\n\n/**\n * FX creator function signature\n * @param obj - GameObject with FX pipeline\n * @param config - Effect-specific configuration\n * @param type - 'post' or 'pre' FX pipeline\n * @returns Cleanup function or FX controller (or any Phaser.FX effect)\n */\nexport type FXCreatorFn<TConfig extends FXConfig = FXConfig> = (\n obj: FXCapableGameObject,\n config: TConfig,\n type?: FXType\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n) => (() => void) | Phaser.FX.Controller | any | null\n\n/**\n * Hook for applying FX to GameObject\n * @param ref - Ref to GameObject\n * @returns Object with applyFX and clearFX methods\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * const { applyFX, clearFX } = useFX(ref)\n *\n * const handleClick = () => {\n * applyFX(createShadowFX, { offsetX: 4, offsetY: 4, blur: 8 })\n * }\n *\n * return <View ref={ref} onClick={handleClick}>Click me</View>\n * ```\n */\nexport function useFX<T extends FXCapableGameObject>(ref: RefObject<T>) {\n const activeEffectsRef = useRef<Set<(() => void) | Phaser.FX.Controller>>(new Set())\n\n // Cleanup on unmount\n useEffect(() => {\n return () => {\n activeEffectsRef.current.forEach((cleanup) => {\n if (typeof cleanup === 'function') {\n cleanup()\n } else if (cleanup?.destroy) {\n cleanup.destroy()\n }\n })\n activeEffectsRef.current.clear()\n }\n }, [])\n\n const applyFX = <TConfig extends FXConfig>(\n fxCreator: FXCreatorFn<TConfig>,\n config: TConfig,\n type: FXType = 'post'\n ) => {\n const obj = ref.current\n if (!obj) {\n console.warn('[useFX] No object found in ref')\n return\n }\n\n const cleanupOrController = fxCreator(obj, config, type)\n if (cleanupOrController) {\n activeEffectsRef.current.add(cleanupOrController)\n }\n }\n\n const clearFX = () => {\n activeEffectsRef.current.forEach((cleanup) => {\n if (typeof cleanup === 'function') {\n cleanup()\n } else if (cleanup?.destroy) {\n cleanup.destroy()\n }\n })\n activeEffectsRef.current.clear()\n\n // Clear FX pipeline\n const obj = ref.current\n if (obj && 'postFX' in obj && obj.postFX) {\n obj.postFX.clear()\n }\n if (obj && 'preFX' in obj && obj.preFX) {\n obj.preFX.clear()\n }\n }\n\n return { applyFX, clearFX }\n}\n","/**\n * Blur FX creator (Box & Gaussian Blur)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Blur FX configuration\n */\nexport interface BlurFXConfig extends FXConfig {\n /** The quality of the blur effect. Can be either 0 for Low Quality, 1 for Medium Quality or 2 for High Quality */\n quality?: number\n /** The horizontal offset of the blur effect */\n x?: number\n /** The vertical offset of the blur effect */\n y?: number\n /** The strength of the blur effect */\n strength?: number\n /** The color of the blur, as a hex value */\n color?: number\n /** The number of steps to run the blur effect for. This value should always be an integer */\n steps?: number\n}\n\n/**\n * Create blur FX\n * @param obj - GameObject\n * @param config - Blur configuration\n * @param type - 'post' or 'pre' FX\n * @returns Blur controller\n *\n * @example\n * ```tsx\n * applyFX(createBlurFX, {\n * quality: 1,\n * x: 4,\n * y: 4,\n * strength: 2\n * })\n * ```\n */\nexport const createBlurFX: FXCreatorFn<BlurFXConfig> = (obj, config, type = 'post') => {\n const { quality = 0, x = 2, y = 2, strength = 1, color = 0xffffff, steps = 4 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createBlurFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addBlur(quality, x, y, strength, color, steps)\n const blur = pipeline.addBlur(quality, x, y, strength, color, steps)\n\n return blur\n}\n","/**\n * Color Matrix FX creator (Grayscale, Sepia, Negative, etc.)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Color Matrix effect types\n */\nexport type ColorMatrixEffect =\n | 'grayscale'\n | 'sepia'\n | 'negative'\n | 'blackWhite'\n | 'brown'\n | 'kodachrome'\n | 'technicolor'\n | 'polaroid'\n\n/**\n * Color Matrix FX configuration\n */\nexport interface ColorMatrixFXConfig extends FXConfig {\n /** Effect type */\n effect?: ColorMatrixEffect\n /** Effect amount (0-1, for effects that support it like grayscale) */\n amount?: number\n}\n\n/**\n * Create color matrix FX\n * @param obj - GameObject\n * @param config - Color matrix configuration\n * @param type - 'post' or 'pre' FX\n * @returns Color matrix controller\n *\n * @example\n * ```tsx\n * applyFX(createColorMatrixFX, {\n * effect: 'grayscale',\n * amount: 1\n * })\n * ```\n */\nexport const createColorMatrixFX: FXCreatorFn<ColorMatrixFXConfig> = (\n obj,\n config,\n type = 'post'\n) => {\n const { effect = 'grayscale', amount = 1 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createColorMatrixFX] FX pipeline not available on this GameObject')\n return null\n }\n\n const colorMatrix = pipeline.addColorMatrix()\n\n // Apply the selected effect\n switch (effect) {\n case 'grayscale':\n colorMatrix.grayscale(amount)\n break\n case 'sepia':\n colorMatrix.sepia()\n break\n case 'negative':\n colorMatrix.negative()\n break\n case 'blackWhite':\n colorMatrix.blackWhite()\n break\n case 'brown':\n colorMatrix.brown()\n break\n case 'kodachrome':\n colorMatrix.kodachrome()\n break\n case 'technicolor':\n colorMatrix.technicolor()\n break\n case 'polaroid':\n colorMatrix.polaroid()\n break\n }\n\n return colorMatrix\n}\n","/**\n * Glow FX creator (Outer Glow)\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Glow FX configuration\n */\nexport interface GlowFXConfig extends FXConfig {\n /** Glow color (hex number) */\n color?: number\n /** The strength of the glow outward from the edge */\n outerStrength?: number\n /** The strength of the glow inward from the edge */\n innerStrength?: number\n /** If true, only the glow is drawn, not the texture itself */\n knockout?: boolean\n /** Sets the quality of this Glow effect (PostFX only, cannot be changed post-creation) */\n quality?: number\n /** Sets the distance of this Glow effect (PostFX only, cannot be changed post-creation) */\n distance?: number\n}\n\n/**\n * Create glow FX\n * @param obj - GameObject\n * @param config - Glow configuration\n * @param type - 'post' or 'pre' FX\n * @returns Glow controller\n *\n * @example\n * ```tsx\n * applyFX(createGlowFX, {\n * color: 0xff6600,\n * outerStrength: 6,\n * innerStrength: 2\n * })\n * ```\n */\nexport const createGlowFX: FXCreatorFn<GlowFXConfig> = (obj, config, type = 'post') => {\n const {\n color = 0xffffff,\n outerStrength = 4,\n innerStrength = 0,\n knockout = false,\n quality = 0.1,\n distance = 10,\n } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createGlowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addGlow(color, outerStrength, innerStrength, knockout, quality, distance)\n const glow = pipeline.addGlow(color, outerStrength, innerStrength, knockout, quality, distance)\n\n return glow\n}\n","/**\n * Pixelate FX creator\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Pixelate FX configuration\n */\nexport interface PixelateFXConfig extends FXConfig {\n /** The amount of pixelation to apply */\n amount?: number\n}\n\n/**\n * Create pixelate FX\n * @param obj - GameObject\n * @param config - Pixelate configuration\n * @param type - 'post' or 'pre' FX\n * @returns Pixelate controller\n *\n * @example\n * ```tsx\n * applyFX(createPixelateFX, {\n * amount: 8\n * })\n * ```\n */\nexport const createPixelateFX: FXCreatorFn<PixelateFXConfig> = (obj, config, type = 'post') => {\n const { amount = 1 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createPixelateFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addPixelate(amount)\n const pixelate = pipeline.addPixelate(amount)\n\n return pixelate\n}\n","/**\n * Shadow FX creator\n *\n * The shadow effect creates the illusion of depth by adding darker, offset silhouettes\n * beneath game objects, enhancing visual appeal and immersion.\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Shadow FX configuration\n * Maps to Phaser's addShadow(x, y, decay, power, color, samples, intensity)\n */\nexport interface ShadowFXConfig extends FXConfig {\n /** Horizontal offset of the shadow effect (default: 0) */\n x?: number\n /** Vertical offset of the shadow effect (default: 0) */\n y?: number\n /** Amount of decay for shadow effect (default: 0.1) */\n decay?: number\n /** Power of the shadow effect (default: 1) */\n power?: number\n /** Color of the shadow (default: 0x000000) */\n color?: number\n /** Number of samples (1-12, higher = better quality, default: 6) */\n samples?: number\n /** Intensity of the shadow effect (default: 1) */\n intensity?: number\n}\n\n/**\n * Create shadow FX\n * @param obj - GameObject\n * @param config - Shadow configuration\n * @param type - 'post' or 'pre' FX\n * @returns Shadow controller\n *\n * @example\n * ```tsx\n * applyFX(createShadowFX, {\n * x: 0,\n * y: 0,\n * decay: 0.1,\n * power: 1,\n * color: 0x000000,\n * samples: 6,\n * intensity: 1\n * })\n * ```\n */\nexport const createShadowFX: FXCreatorFn<ShadowFXConfig> = (obj, config, type = 'post') => {\n const {\n x = 0,\n y = 1,\n decay = 0.05,\n power = 1,\n color = 0x000000,\n samples = 6,\n intensity = 1,\n } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createShadowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser API: addShadow(x, y, decay, power, color, samples, intensity)\n const shadow = pipeline.addShadow(x, y, decay, power, color, samples, intensity)\n\n return shadow\n}\n","/**\n * Vignette FX creator\n */\nimport type { FXConfig, FXCreatorFn } from '../use-fx'\n\n/**\n * Vignette FX configuration\n */\nexport interface VignetteFXConfig extends FXConfig {\n /** The horizontal offset of the vignette effect. This value is normalized to the range 0 to 1 */\n x?: number\n /** The vertical offset of the vignette effect. This value is normalized to the range 0 to 1 */\n y?: number\n /** The radius of the vignette effect. This value is normalized to the range 0 to 1 */\n radius?: number\n /** The strength of the vignette effect */\n strength?: number\n}\n\n/**\n * Create vignette FX\n * @param obj - GameObject\n * @param config - Vignette configuration\n * @param type - 'post' or 'pre' FX\n * @returns Vignette controller\n *\n * @example\n * ```tsx\n * applyFX(createVignetteFX, {\n * x: 0.5,\n * y: 0.5,\n * radius: 0.5,\n * strength: 0.7\n * })\n * ```\n */\nexport const createVignetteFX: FXCreatorFn<VignetteFXConfig> = (obj, config, type = 'post') => {\n const { strength = 0.5, radius = 0.5, x = 0.5, y = 0.5 } = config\n\n const pipeline = type === 'post' ? obj.postFX : obj.preFX\n if (!pipeline) {\n console.warn('[createVignetteFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser Vignette: addVignette(x, y, radius, strength)\n const vignette = pipeline.addVignette(x, y, radius, strength)\n\n return vignette\n}\n","/**\n * FX Registry - string-based FX lookup\n * Similar to effect-registry.ts for animation effects\n */\nimport {\n createBlurFX,\n createColorMatrixFX,\n createGlowFX,\n createPixelateFX,\n createShadowFX,\n createVignetteFX,\n type BlurFXConfig,\n type ColorMatrixFXConfig,\n type GlowFXConfig,\n type PixelateFXConfig,\n type ShadowFXConfig,\n type VignetteFXConfig,\n} from './fx-creators'\nimport type { FXConfig, FXCreatorFn } from './use-fx'\n\n/**\n * Built-in FX names\n */\nexport type BuiltInFXName =\n | 'shadow'\n | 'glow'\n | 'blur'\n | 'pixelate'\n | 'vignette'\n | 'grayscale'\n | 'sepia'\n | 'negative'\n | 'blackWhite'\n | 'brown'\n | 'kodachrome'\n | 'technicolor'\n | 'polaroid'\n\n/**\n * Extension point for custom FX (declaration merging)\n * @example\n * ```typescript\n * declare module '@number10/phaserjsx/fx' {\n * interface FXNameExtensions {\n * myCustomFX: 'myCustomFX'\n * }\n * }\n * ```\n */\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface FXNameExtensions {}\n\n/**\n * All available FX names (built-in + extensions)\n */\nexport type FXName =\n | BuiltInFXName\n | (keyof FXNameExtensions extends never ? never : keyof FXNameExtensions)\n\n/**\n * FX definition with name and config\n */\nexport interface FXDefinition {\n name: FXName\n config?: FXConfig\n}\n\n/**\n * FX Registry mapping names to creator functions\n */\nexport const FX_REGISTRY: Record<BuiltInFXName, FXCreatorFn> = {\n shadow: createShadowFX,\n glow: createGlowFX,\n blur: createBlurFX,\n pixelate: createPixelateFX,\n vignette: createVignetteFX,\n grayscale: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'grayscale' }, type),\n sepia: (obj, config, type) => createColorMatrixFX(obj, { ...config, effect: 'sepia' }, type),\n negative: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'negative' }, type),\n blackWhite: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'blackWhite' }, type),\n brown: (obj, config, type) => createColorMatrixFX(obj, { ...config, effect: 'brown' }, type),\n kodachrome: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'kodachrome' }, type),\n technicolor: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'technicolor' }, type),\n polaroid: (obj, config, type) =>\n createColorMatrixFX(obj, { ...config, effect: 'polaroid' }, type),\n}\n\n/**\n * Default FX (none)\n */\nexport const DEFAULT_FX: FXName = 'grayscale'\n\n/**\n * Resolve FX by name or function\n * @param fxOrName - FX name string or creator function\n * @returns FX creator function or null\n */\nexport function resolveFX(fxOrName: FXName | FXCreatorFn): FXCreatorFn | null {\n if (typeof fxOrName === 'function') {\n return fxOrName\n }\n return FX_REGISTRY[fxOrName as BuiltInFXName] ?? null\n}\n\n/**\n * Apply FX by name (helper function)\n * @param applyFXFn - applyFX function from useFX hook\n * @param fxName - FX name\n * @param config - FX config\n *\n * @example\n * ```tsx\n * const { applyFX } = useFX(ref)\n * applyFXByName(applyFX, 'shadow', { offsetX: 4, offsetY: 4, blur: 8 })\n * ```\n */\nexport function applyFXByName(\n applyFXFn: ReturnType<typeof import('./use-fx').useFX>['applyFX'],\n fxName: FXName,\n config: FXConfig = {}\n) {\n const creator = resolveFX(fxName)\n if (creator) {\n applyFXFn(creator, config)\n } else {\n console.warn(`[applyFXByName] FX \"${fxName}\" not found in registry`)\n }\n}\n\n// Re-export config types for convenience\nexport type {\n BlurFXConfig,\n ColorMatrixFXConfig,\n GlowFXConfig,\n PixelateFXConfig,\n ShadowFXConfig,\n VignetteFXConfig,\n}\n","/**\n * Convenience hook for automatic blur FX\n * Applies blur on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createBlurFX, type BlurFXConfig } from '../fx-creators/blur'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic blur FX\n * @param ref - GameObject ref\n * @param config - Blur config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useBlur(ref, { strength: 8, steps: 4 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useBlur(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: BlurFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new blur\n applyFX(createBlurFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Convenience hook for automatic glow FX\n * Applies glow on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createGlowFX, type GlowFXConfig } from '../fx-creators/glow'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic glow FX\n * @param ref - GameObject ref\n * @param config - Glow config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useGlow(ref, { color: 0xff6600, outerStrength: 6, innerStrength: 2 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useGlow(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: GlowFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new glow\n applyFX(createGlowFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Convenience hook for automatic shadow FX\n * Applies shadow on mount and updates on config changes\n */\nimport { useEffect } from '../../hooks'\nimport { createShadowFX, type ShadowFXConfig } from '../fx-creators/shadow'\nimport { useFX } from '../use-fx'\n\n/**\n * Hook for automatic shadow FX\n * @param ref - GameObject ref\n * @param config - Shadow config (updates reactively)\n * @returns FX controls\n *\n * @example\n * ```tsx\n * const ref = useRef(null)\n * useShadow(ref, { x: 4, y: 4, decay: 0.1 })\n *\n * return <View ref={ref}>Content</View>\n * ```\n */\nexport function useShadow(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n ref: { current: any },\n config: ShadowFXConfig = {}\n): { clearFX: () => void } {\n const { applyFX, clearFX } = useFX(ref)\n\n useEffect(() => {\n if (!ref.current) return\n\n // Clear previous FX\n clearFX()\n\n // Apply new shadow\n applyFX(createShadowFX, config)\n\n return () => clearFX()\n }, [ref, config, applyFX, clearFX])\n\n return { clearFX }\n}\n","/**\n * Component memoization utilities\n * Similar to React.memo() - prevents re-renders when props haven't changed\n */\nimport type { VNode } from './hooks'\n\n/**\n * Safely sets __memo on a VNode, handling frozen/sealed objects from bundlers\n * @param vnode - VNode to set __memo on\n * @param value - Memoization value\n * @returns Original VNode if extensible, or shallow copy with __memo\n */\nfunction setMemoSafe<T extends VNode>(vnode: T, value: boolean): T {\n if (Object.isExtensible(vnode)) {\n vnode.__memo = value\n return vnode\n }\n // VNode is frozen - create shallow copy\n return { ...vnode, __memo: value } as T\n}\n\n/**\n * Marks a component to skip memoization (always re-render on prop changes)\n * Use when component has side effects or needs to re-render every time\n *\n * @example\n * ```tsx\n * function AlwaysUpdate({ value }) {\n * console.log('Rendering with:', value)\n * return <Text text={value} />\n * }\n *\n * // Disable memoization\n * <AlwaysUpdate value={counter} __memo={false} />\n * ```\n *\n * @param vnode - VNode to mark\n * @returns Same VNode with memoization disabled (may be a copy if frozen)\n */\nexport function noMemo<T extends VNode>(vnode: T): T {\n return setMemoSafe(vnode, false)\n}\n\n/**\n * Explicitly enable memoization for a component (default behavior)\n * This is the default - you don't need to call this unless you want to be explicit\n *\n * @param vnode - VNode to mark\n * @returns Same VNode with memoization enabled (may be a copy if frozen)\n */\nexport function memo<T extends VNode>(vnode: T): T {\n return setMemoSafe(vnode, true)\n}\n","/**\n * Hook for imperative particle control\n */\nimport { useCallback } from '../hooks'\nimport type { RefObject } from '../types'\nimport {\n buildDeathZonesFromLayout,\n buildEmitZoneFromLayout,\n type ParticleExclusionZoneConfig,\n type ParticleZoneConfig,\n} from './emit-zone'\nimport type { ParticleEmitter, ParticleEmitterManagerLike, ParticlesHandle } from './particle-types'\nimport type { ParticleEmitterConfig } from './preset-registry'\nimport {\n applyDeathZone,\n applyEmitZone,\n applyEmitterConfig,\n getFirstEmitter,\n isParticleEmitter,\n} from './utils'\n\nexport function useParticles(ref: RefObject<ParticlesHandle | null>): {\n getManager: () => ParticlesHandle | null\n getEmitter: () => ParticleEmitter | null\n start: () => void\n stop: () => void\n explode: (count: number, x?: number, y?: number) => void\n setConfig: (config: ParticleEmitterConfig) => void\n setEmitZone: (zone: ParticleZoneConfig, width?: number, height?: number) => void\n setExcludeZones: (\n zones: ParticleExclusionZoneConfig | ParticleExclusionZoneConfig[],\n width?: number,\n height?: number\n ) => void\n} {\n const getManager = useCallback(() => ref.current ?? null, [ref])\n const getEmitter = useCallback(() => {\n const current = ref.current\n if (!current) return null\n if (isParticleEmitter(current)) return current\n return getFirstEmitter(current as ParticleEmitterManagerLike)\n }, [ref])\n\n const start = useCallback(() => {\n const emitter = getEmitter()\n emitter?.start()\n }, [getEmitter])\n\n const stop = useCallback(() => {\n const emitter = getEmitter()\n emitter?.stop()\n }, [getEmitter])\n\n const explode = useCallback(\n (count: number, x?: number, y?: number) => {\n const emitter = getEmitter()\n emitter?.explode(count, x, y)\n },\n [getEmitter]\n )\n\n const setConfig = useCallback(\n (config: ParticleEmitterConfig) => {\n const emitter = getEmitter()\n applyEmitterConfig(emitter, config)\n },\n [getEmitter]\n )\n\n const setEmitZone = useCallback(\n (zone: ParticleZoneConfig, width?: number, height?: number) => {\n const emitter = getEmitter()\n const emitZone = buildEmitZoneFromLayout(zone, width, height)\n applyEmitZone(emitter, emitZone)\n },\n [getEmitter]\n )\n\n const setExcludeZones = useCallback(\n (\n zones: ParticleExclusionZoneConfig | ParticleExclusionZoneConfig[],\n width?: number,\n height?: number\n ) => {\n const emitter = getEmitter()\n const deathZones = buildDeathZonesFromLayout(zones, width, height)\n applyDeathZone(emitter, deathZones)\n },\n [getEmitter]\n )\n\n return {\n getManager,\n getEmitter,\n start,\n stop,\n explode,\n setConfig,\n setEmitZone,\n setExcludeZones,\n }\n}\n","/**\n * PhaserJSX Plugin for automatic JSX mounting\n * Enables declarative initialization via Phaser game config\n */\nimport Phaser from 'phaser'\nimport type { VNodeLike } from './types'\nimport { mountJSX, type MountHandle, type MountProps } from './vdom'\n\n/**\n * Plugin configuration\n */\nexport interface PhaserJSXPluginConfig<P = Record<string, unknown>> {\n /** Component to mount */\n component?: ((props: P & MountProps) => VNodeLike) | string\n /** Props for component (width and height are auto-injected from game size) */\n props?: P\n /** Container configuration */\n container?: {\n x?: number\n y?: number\n depth?: number\n }\n /** Auto-mount on scene create (default: true) */\n autoMount?: boolean\n /** Auto-resize on scale events (default: true) */\n autoResize?: boolean\n}\n\n/**\n * Extracts custom props from component function (excluding MountProps)\n */\ntype InferCustomProps<C> = C extends (props: infer P) => VNodeLike\n ? Omit<P, keyof MountProps>\n : never\n\n/**\n * Type-safe plugin entry for PhaserJSX Plugin\n * Use this in game config for proper TypeScript support\n *\n * @example\n * ```typescript\n * const config: Phaser.Types.Core.GameConfig = {\n * plugins: {\n * global: [\n * createPhaserJSXPlugin({\n * component: App,\n * props: { title: 'My App' },\n * autoResize: true\n * })\n * ]\n * }\n * }\n * ```\n */\nexport interface PhaserJSXPluginEntry<P = Record<string, unknown>> {\n key: string\n plugin: typeof PhaserJSXPlugin\n start: boolean\n data: PhaserJSXPluginConfig<P>\n}\n\n/**\n * Creates a type-safe PhaserJSX plugin entry for game config\n * Provides full IDE autocomplete and type checking for plugin configuration\n * Automatically infers component props for full type safety\n *\n * @param config - Plugin configuration with component and props\n * @returns Type-safe plugin entry for Phaser game config\n *\n * @example\n * ```typescript\n * // Full type safety - TypeScript infers AppProps from component\n * createPhaserJSXPlugin({\n * component: App,\n * props: { title: 'My App' }, // Only valid AppProps allowed!\n * autoResize: true\n * })\n * ```\n */\nexport function createPhaserJSXPlugin<C extends (props: any) => VNodeLike>(config: {\n component: C\n props?: InferCustomProps<C>\n autoMount?: boolean\n autoResize?: boolean\n container?: { x?: number; y?: number; depth?: number }\n}): PhaserJSXPluginEntry<InferCustomProps<C>>\n\n/**\n * Creates a PhaserJSX plugin entry (string component variant)\n */\nexport function createPhaserJSXPlugin<P = Record<string, unknown>>(\n config: PhaserJSXPluginConfig<P>\n): PhaserJSXPluginEntry<P>\n\n/**\n * Implementation\n */\nexport function createPhaserJSXPlugin<P = Record<string, unknown>>(\n config: PhaserJSXPluginConfig<P>\n): PhaserJSXPluginEntry<P> {\n return {\n key: 'PhaserJSX',\n plugin: PhaserJSXPlugin,\n start: true,\n data: config,\n }\n}\n\n/**\n * PhaserJSX Plugin\n * Provides automatic JSX mounting through Phaser plugin system\n *\n * @example\n * ```typescript\n * // In game config\n * plugins: {\n * global: [{\n * key: 'PhaserJSX',\n * plugin: PhaserJSXPlugin,\n * start: true,\n * data: {\n * component: App,\n * props: { width: '100%', height: '100%' }\n * }\n * }]\n * }\n * ```\n */\nexport class PhaserJSXPlugin extends Phaser.Plugins.BasePlugin {\n private config: PhaserJSXPluginConfig | undefined\n private mountHandle: MountHandle | undefined\n private container: Phaser.GameObjects.Container | undefined\n private targetScene: Phaser.Scene | undefined\n\n /**\n * Constructor - receives plugin manager and optional mapping\n */\n constructor(pluginManager: Phaser.Plugins.PluginManager) {\n super(pluginManager)\n }\n\n /**\n * Init lifecycle - called first with config data\n */\n override init(data?: PhaserJSXPluginConfig): void {\n if (data) {\n this.config = { ...data }\n }\n }\n\n /**\n * Start lifecycle - called when plugin should start\n */\n override start(): void {\n // Listen for scene being added to the scene manager\n this.game.events.on('ready', this.onGameReady, this)\n }\n\n /**\n * Game ready handler - scene system is now initialized\n */\n private onGameReady(): void {\n // Get first scene\n const scenes = this.game.scene.scenes\n\n if (scenes.length > 0) {\n const targetScene = scenes[0]\n if (!targetScene) return\n\n this.targetScene = targetScene\n\n // Listen to scene events\n targetScene.events.once('create', this.onSceneCreate, this)\n\n // If scene is already created, mount immediately\n if (targetScene.scene.isActive()) {\n this.onSceneCreate()\n }\n } else {\n console.warn('[PhaserJSX Plugin] No scenes found to mount JSX')\n }\n }\n\n /**\n * Scene create handler - auto-mount JSX\n */\n private onSceneCreate(): void {\n // Auto-mount if enabled and component is configured\n const shouldAutoMount = this.config?.autoMount !== false\n if (shouldAutoMount && this.config?.component) {\n this.mount()\n // Setup resize handler if auto-resize is enabled (default: true)\n if (this.config?.autoResize !== false) {\n this.setupResizeHandler()\n }\n } else {\n console.warn('[PhaserJSX Plugin] Auto-mount disabled or no component configured')\n }\n }\n\n /**\n * Setup resize event handler\n */\n private setupResizeHandler(): void {\n if (!this.targetScene) return\n\n // Listen to scale resize events\n this.targetScene.scale.on('resize', this.onResize, this)\n }\n\n /**\n * Handle scene resize - update component props\n */\n private onResize(gameSize: Phaser.Structs.Size): void {\n if (!this.mountHandle || !this.config?.component || !this.container) return\n\n // Get current props\n const props = this.config.props || {}\n const width = (props as { width?: unknown }).width ?? gameSize.width\n const height = (props as { height?: unknown }).height ?? gameSize.height\n\n // Call mountJSX again with same container and component\n // This will trigger a patch since mount already exists for this container\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.mountHandle = mountJSX(this.container, this.config.component as any, {\n ...props,\n width,\n height,\n })\n }\n\n /**\n * Configure plugin\n * Can be called from scene to set up component dynamically\n */\n configure(\n component: ((props: unknown) => VNodeLike) | string,\n props?: MountProps & Record<string, unknown>\n ): void {\n const newConfig: PhaserJSXPluginConfig = {\n component,\n }\n if (props !== undefined) {\n newConfig.props = props\n }\n this.config = {\n ...this.config,\n ...newConfig,\n }\n }\n\n /**\n * Mount JSX component\n */\n mount(): void {\n if (!this.targetScene) {\n console.warn('[PhaserJSX Plugin] No scene available for mounting')\n return\n }\n\n if (!this.config?.component) {\n console.warn('[PhaserJSX Plugin] No component configured for mounting')\n return\n }\n\n // Create container if not exists\n if (!this.container) {\n const containerConfig = this.config.container || {}\n this.container = this.targetScene.add.container(\n containerConfig.x ?? 0,\n containerConfig.y ?? 0\n )\n this.container.setDepth(containerConfig.depth ?? 100)\n }\n\n // Get dimensions from config or use scene dimensions\n const props = this.config.props || {}\n const width = (props as { width?: unknown }).width ?? this.targetScene.scale.width\n const height = (props as { height?: unknown }).height ?? this.targetScene.scale.height\n\n // Mount JSX\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n this.mountHandle = mountJSX(this.container, this.config.component as any, {\n ...props,\n width,\n height,\n })\n }\n\n /**\n * Unmount JSX component\n */\n unmount(): void {\n if (this.mountHandle) {\n this.mountHandle.unmount()\n this.mountHandle = undefined\n }\n }\n\n /**\n * Destroy lifecycle - cleanup\n */\n override destroy(): void {\n // Unmount JSX\n this.unmount()\n\n // Remove container\n if (this.container) {\n this.container.destroy()\n this.container = undefined\n }\n\n // Remove listeners\n this.game.events.off('ready', this.onGameReady, this)\n if (this.targetScene) {\n this.targetScene.events.off('create', this.onSceneCreate, this)\n this.targetScene.scale.off('resize', this.onResize, this)\n }\n\n // Clear references\n this.targetScene = undefined\n this.config = undefined\n\n super.destroy()\n }\n}\n","/**\n * Color mode management for dynamic theme switching\n */\nimport { useEffect, useState } from '../hooks'\nimport { themeRegistry } from '../theme'\n\n/**\n * Hook to manage color mode (light/dark) dynamically\n * @returns Object with current mode, toggle function, and setter\n * @example\n * ```typescript\n * function ThemeToggle() {\n * const { colorMode, toggleColorMode } = useColorMode()\n *\n * return (\n * <Button onClick={toggleColorMode}>\n * {colorMode === 'light' ? 'Dark' : 'Light'} Mode\n * </Button>\n * )\n * }\n * ```\n */\nexport function useColorMode(): {\n colorMode: 'light' | 'dark'\n setColorMode: (mode: 'light' | 'dark') => void\n toggleColorMode: () => void\n} {\n const [colorMode, setColorModeState] = useState<'light' | 'dark'>(themeRegistry.getColorMode())\n\n useEffect(() => {\n // Subscribe to theme registry changes\n const unsubscribe = themeRegistry.subscribe(() => {\n setColorModeState(themeRegistry.getColorMode())\n })\n\n return unsubscribe\n }, [])\n\n const setColorMode = (mode: 'light' | 'dark') => {\n themeRegistry.setColorMode(mode)\n }\n\n const toggleColorMode = () => {\n const newMode = colorMode === 'light' ? 'dark' : 'light'\n setColorMode(newMode)\n }\n\n return {\n colorMode,\n setColorMode,\n toggleColorMode,\n }\n}\n","/**\n * Color system hooks for component usage\n */\nimport { useEffect, useState, useTheme } from '../hooks'\nimport { themeRegistry } from '../theme'\nimport { getPresetWithMode } from './color-presets'\nimport type { ColorTokens } from './color-types'\n\n/**\n * Hook to access color tokens from theme context\n * Automatically updates when color mode or preset changes\n * @returns Current ColorTokens or undefined\n * @deprecated Use `useThemeTokens()` instead for access to colors, text styles, spacing, and more\n * @example\n * ```typescript\n * // Old way (deprecated):\n * const colors = useColors()\n *\n * // New way:\n * const tokens = useThemeTokens()\n * const colors = tokens?.colors\n *\n * // Access text styles, spacing, etc.:\n * <Text style={tokens.textStyles.DEFAULT} />\n * <View padding={tokens.spacing.lg} />\n * ```\n */\nexport function useColors(): ColorTokens | undefined {\n const localTheme = useTheme()\n\n // Initialize colors state\n const getInitialColors = (): ColorTokens | undefined => {\n // Check if local theme has color preset info\n if (localTheme?.__colorPreset) {\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n localTheme.__colorPreset.mode ?? 'light'\n )\n return preset.colors\n }\n\n // Fall back to global color tokens\n return themeRegistry.getColorTokens()\n }\n\n const [colors, setColors] = useState<ColorTokens | undefined>(getInitialColors())\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // Subscribe to theme changes (mode/preset switches)\n const unsubscribe = themeRegistry.subscribe(() => {\n // Check if local theme has preset\n if (localTheme?.__colorPreset) {\n const currentMode = themeRegistry.getColorMode()\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n currentMode\n )\n setColors(preset.colors)\n } else {\n // Use global tokens\n setColors(themeRegistry.getColorTokens())\n }\n // Force re-render when theme changes\n forceUpdate((n) => n + 1)\n })\n\n return unsubscribe\n }, [localTheme])\n\n return colors\n}\n\n/**\n * Hook to subscribe to theme changes without accessing colors\n * Use this in parent components that don't need colors themselves\n * but want to ensure children re-render when theme changes\n *\n * Note: Since useColors() now triggers re-renders automatically,\n * this hook is mainly useful if you don't need the colors themselves\n * but still want to react to theme changes.\n *\n * @example\n * ```typescript\n * function ParentComponent() {\n * useThemeSubscription() // Children will re-render on theme changes\n * return <ChildThatUsesColors />\n * }\n * ```\n */\nexport function useThemeSubscription(): void {\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n const unsubscribe = themeRegistry.subscribe(() => {\n forceUpdate((n) => n + 1)\n })\n return unsubscribe\n }, [])\n}\n","/**\n * Helper functions for color system integration with theme\n */\nimport type { ColorTokens } from './color-types'\nimport { alpha } from './color-utils'\n\n/**\n * Convert ColorTokens to a theme-compatible object\n * Maps semantic color names to Phaser number format for View/Button components\n * @param colors - ColorTokens to convert\n * @returns Object with backgroundColor, borderColor, etc.\n * @example\n * ```typescript\n * const colors = getPreset('oceanBlue').colors\n * const buttonTheme = {\n * ...colorsToTheme(colors, 'primary'),\n * padding: 8,\n * }\n * // Returns: { backgroundColor: 0x2196f3, borderColor: 0x... }\n * ```\n */\nexport function colorsToTheme(\n colors: ColorTokens,\n colorKey: keyof Pick<\n ColorTokens,\n 'primary' | 'secondary' | 'accent' | 'success' | 'warning' | 'error' | 'info'\n >,\n options: {\n /** Which shade to use for background (default: 'DEFAULT') */\n backgroundShade?: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT'\n /** Which shade to use for border (default: 'dark') */\n borderShade?: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT'\n /** Include border color (default: true) */\n includeBorder?: boolean\n } = {}\n): {\n backgroundColor: number\n borderColor?: number\n} {\n const { backgroundShade = 'DEFAULT', borderShade = 'dark', includeBorder = true } = options\n\n const result: { backgroundColor: number; borderColor?: number } = {\n backgroundColor: colors[colorKey][backgroundShade].toNumber(),\n }\n\n if (includeBorder) {\n result.borderColor = colors[colorKey][borderShade].toNumber()\n }\n\n return result\n}\n\n/**\n * Get text color from ColorTokens as hex string for Phaser Text style\n * @param colors - ColorTokens to use\n * @param shade - Which text shade to use (default: 'DEFAULT')\n * @param alphaValue - Optional alpha value (0-1)\n * @returns Hex string or rgba string for Text style\n * @example\n * ```typescript\n * const colors = getPreset('oceanBlue').colors\n * const textStyle = {\n * color: getTextColor(colors),\n * fontSize: '18px'\n * }\n * ```\n */\nexport function getTextColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT',\n alphaValue?: number\n): string {\n const color = colors.text[shade]\n return alphaValue !== undefined ? alpha(color.toNumber(), alphaValue) : color.toString()\n}\n\n/**\n * Get background color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getBackgroundColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.background[shade].toNumber()\n}\n\n/**\n * Get surface color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getSurfaceColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.surface[shade].toNumber()\n}\n\n/**\n * Get border color from ColorTokens\n * @param colors - ColorTokens to use\n * @param shade - Which shade to use (default: 'DEFAULT')\n * @returns Phaser color number\n */\nexport function getBorderColor(\n colors: ColorTokens,\n shade: 'lightest' | 'light' | 'medium' | 'dark' | 'darkest' | 'DEFAULT' = 'DEFAULT'\n): number {\n return colors.border[shade].toNumber()\n}\n","/**\n * Dynamic color preset management\n */\nimport { themeRegistry } from '../theme'\nimport type { PresetName } from './color-presets'\nimport { getPresetWithMode } from './color-presets'\n\n/**\n * Set the active color preset globally\n * Applies the preset with the current color mode and updates all components\n * Triggers complete remount of all active mountJSX instances\n * @param presetName - Name of the preset to apply\n * @param colorMode - Optional color mode to apply together with the preset\n * @example\n * ```typescript\n * // Switch to forest green theme\n * setColorPreset('forestGreen')\n *\n * // Apply preset and force dark mode in one go\n * setColorPreset('midnight', 'dark')\n *\n * // Current mode (light/dark) is preserved\n * ```\n */\nexport function setColorPreset(presetName: PresetName, colorMode?: 'light' | 'dark'): void {\n const targetMode = colorMode ?? themeRegistry.getColorMode()\n const preset = getPresetWithMode(presetName, targetMode)\n\n // Update color tokens WITHOUT notifying listeners\n // We skip listener notifications to prevent unnecessary re-renders\n themeRegistry.setColorTokens(preset.colors)\n themeRegistry.setCurrentPresetName(presetName, true) // true = skip notify\n\n // If caller asked for a specific mode, update it here so we only remount once\n if (colorMode && themeRegistry.getColorMode() !== colorMode) {\n themeRegistry.setColorMode(colorMode)\n return\n }\n\n // Trigger complete remount of all VDOM trees to apply new preset\n // Using setTimeout(0) to ensure all synchronous state updates complete first\n setTimeout(() => {\n // Import remountAll lazily to avoid circular dependency\n import('../vdom').then(({ remountAll }) => {\n remountAll()\n })\n }, 0)\n}\n\n/**\n * Get the currently active preset name\n * @returns Current preset name or undefined\n */\nexport function getCurrentPreset(): string | undefined {\n return themeRegistry.getCurrentPresetName()\n}\n\n/**\n * Set the active color mode globally (without changing the preset)\n * @param mode - Color mode to apply\n */\nexport function setColorMode(mode: 'light' | 'dark'): void {\n themeRegistry.setColorMode(mode)\n}\n\n/**\n * Get all available preset names\n * @returns Array of preset names\n * @example\n * ```typescript\n * const presets = getAvailablePresets() // ['oceanBlue', 'forestGreen', 'midnight']\n * ```\n */\nexport function getAvailablePresets(): PresetName[] {\n return ['oceanBlue', 'forestGreen', 'midnight']\n}\n","/**\n * Hook to access complete design token system\n * Combines colors with text styles, spacing, sizes, and radius tokens\n */\nimport { getPresetWithMode } from '../colors/color-presets'\nimport { useEffect, useState, useTheme } from '../hooks'\nimport { themeRegistry } from '../theme'\nimport {\n createTextStyleTokens,\n defaultRadiusTokens,\n defaultSizeTokens,\n defaultSpacingTokens,\n} from './design-token-presets'\nimport type { DesignTokens } from './design-token-types'\n\n/**\n * Hook to access complete design token system from theme context\n * Provides colors, text styles, spacing, sizes, and radius tokens\n * Automatically updates when color mode or preset changes\n * @returns Current DesignTokens or undefined\n * @example\n * ```typescript\n * function MyComponent() {\n * const tokens = useThemeTokens()\n *\n * if (!tokens) return null\n *\n * return (\n * <View\n * backgroundColor={tokens.colors.surface.DEFAULT}\n * padding={tokens.spacing.lg}\n * cornerRadius={tokens.radius.md}\n * >\n * <Text text=\"Title\" style={tokens.textStyles.title} />\n * <Text text=\"Body text\" style={tokens.textStyles.DEFAULT} />\n * </View>\n * )\n * }\n * ```\n */\nexport function useThemeTokens(): DesignTokens | undefined {\n const localTheme = useTheme()\n\n // Initialize design tokens state\n const getInitialTokens = (): DesignTokens | undefined => {\n // Check if local theme has color preset info\n if (localTheme?.__colorPreset) {\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n localTheme.__colorPreset.mode ?? 'light'\n )\n return {\n colors: preset.colors,\n textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n }\n }\n\n // Fall back to global tokens\n const colors = themeRegistry.getColorTokens()\n if (!colors) return undefined\n\n return {\n colors,\n textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n }\n }\n\n const [tokens, setTokens] = useState<DesignTokens | undefined>(getInitialTokens())\n const [, forceUpdate] = useState(0)\n\n useEffect(() => {\n // Subscribe to theme changes (mode/preset switches)\n const unsubscribe = themeRegistry.subscribe(() => {\n // Check if local theme has preset\n if (localTheme?.__colorPreset) {\n const currentMode = themeRegistry.getColorMode()\n const preset = getPresetWithMode(\n localTheme.__colorPreset.name as Parameters<typeof getPresetWithMode>[0],\n currentMode\n )\n setTokens({\n colors: preset.colors,\n textStyles: createTextStyleTokens(preset.colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n })\n } else {\n // Use global tokens\n const colors = themeRegistry.getColorTokens()\n if (colors) {\n setTokens({\n colors,\n textStyles: createTextStyleTokens(colors.text.DEFAULT.toString()),\n spacing: defaultSpacingTokens,\n sizes: defaultSizeTokens,\n radius: defaultRadiusTokens,\n })\n }\n }\n // Force re-render when theme changes\n forceUpdate((n) => n + 1)\n })\n\n return unsubscribe\n }, [localTheme])\n\n return tokens\n}\n","/**\n * PhaserJSX UI Library\n * Provides JSX + hooks + VDOM for Phaser 3 game development\n */\nimport { registerBuiltins } from './components'\nimport './jsx-types' // Import JSX type declarations\n\n// Register built-in components (View, Text) on module load\nregisterBuiltins()\n\nexport * from './core-types'\nexport * from './camera'\nexport * from './effects'\nexport * from './fx'\nexport * from './hooks'\nexport * from './hooks-svg'\nexport * from './host'\nexport * from './memo'\nexport * from './theme'\nexport * from './types'\nexport * from './vdom'\nexport * from './particles'\n\n// Export core prop utilities\nexport {\n normalizeCornerRadius,\n normalizeEdgeInsets,\n normalizeGap,\n type CornerRadiusInsets,\n type EdgeInsets,\n type GapInsets,\n} from './core-props'\n\n// Export gesture types explicitly for better IDE support\nexport type {\n Display,\n FlexBasisValue,\n FocusEventData,\n GestureEventData,\n GestureProps,\n InputEventData,\n KeyboardEventData,\n SizeValue,\n TouchMoveState,\n} from './core-props'\n\n// Export DOM input manager utility\nexport { DOMInputElement, type DOMInputConfig } from './utils/dom-input-manager'\nexport { KeyboardInputManager, type KeyboardInputManagerConfig } from './utils/KeyboardInputManager'\n\n// Export PhaserJSX Plugin for automatic mounting\nexport {\n createPhaserJSXPlugin,\n PhaserJSXPlugin,\n type PhaserJSXPluginConfig,\n type PhaserJSXPluginEntry,\n} from './plugin'\n\n// Explicit export for convenience functions\nexport {\n getMountStats,\n mountJSX as mountComponent,\n type MountComponentProps,\n type MountProps,\n} from './vdom'\n\n// Re-export component creators/patchers for advanced usage\nexport * from './components'\n\n// Re-export custom components for convenience\nexport * from './components/custom'\n\n// Re-export portal system\nexport * from './portal'\n\n// Animation utilities for spring-based transitions\nexport * from './animation'\n\n// Explicitly export AnimationConfig for component themes\nexport type { AnimationConfig } from './animation/spring-physics'\n\n// Color system utilities and presets\nexport * from './colors'\n\n// Design token system - semantic tokens for colors, text styles, spacing, etc.\nexport * from './design-tokens'\n\n// Tooltip system - onTooltip property types\nexport type {\n TooltipCallback,\n TooltipConfig,\n TooltipNativeAnimation,\n TooltipPosition,\n} from './tooltip/tooltip-types'\n\n// Viewport context - provides screen dimensions for vw/vh units\nexport { viewportRegistry, type ViewportSize } from './viewport-context'\n\n// Render context - isolates global state per mount point (advanced usage)\nexport { getRenderContext, type RenderContext } from './render-context'\n\n/**\n * Consumers can import JSX runtime from here:\n * import { jsx, jsxs, Fragment } from \"@number10/phaserjsx/jsx-runtime\";\n */\nexport { Fragment, jsx, jsxs } from './jsx-runtime'\n\n// Development configuration and debugging utilities\nexport { DebugLogger, DevConfig, DevPresets } from './dev-config'\n\n// SVG to texture utilities\nexport type { SVGTextureConfig } from './hooks-svg'\nexport { svgToTexture } from './utils/svg-texture'\n"],"names":["a","b","i","normalizeVisible","calculateFitScale","Phaser","bg","state","setColorMode","n"],"mappings":"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"}