@number10/phaserjsx 4.4.0 → 4.5.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.
- package/README.md +7 -2
- package/dist/colors/color-presets.d.ts +1 -1
- package/dist/colors/color-presets.d.ts.map +1 -1
- package/dist/colors/color-types.d.ts +20 -8
- package/dist/colors/color-types.d.ts.map +1 -1
- package/dist/colors/color-utils.d.ts +29 -27
- package/dist/colors/color-utils.d.ts.map +1 -1
- package/dist/colors/index.d.ts +3 -3
- package/dist/colors/index.d.ts.map +1 -1
- package/dist/colors/preset-manager.d.ts.map +1 -1
- package/dist/colors/use-colors.d.ts +0 -4
- package/dist/colors/use-colors.d.ts.map +1 -1
- package/dist/components/custom/ActivityIndicator.d.ts +43 -0
- package/dist/components/custom/ActivityIndicator.d.ts.map +1 -0
- package/dist/components/custom/BottomSheet.d.ts +86 -0
- package/dist/components/custom/BottomSheet.d.ts.map +1 -0
- package/dist/components/custom/Button.d.ts +2 -0
- package/dist/components/custom/Button.d.ts.map +1 -1
- package/dist/components/custom/ColorPicker.d.ts +72 -0
- package/dist/components/custom/ColorPicker.d.ts.map +1 -0
- package/dist/components/custom/Icon.d.ts.map +1 -1
- package/dist/components/custom/Icon.test.d.ts +2 -0
- package/dist/components/custom/Icon.test.d.ts.map +1 -0
- package/dist/components/custom/ListBox.d.ts +77 -0
- package/dist/components/custom/ListBox.d.ts.map +1 -0
- package/dist/components/custom/MenuButton.d.ts +40 -0
- package/dist/components/custom/MenuButton.d.ts.map +1 -0
- package/dist/components/custom/NumberInput.d.ts +143 -0
- package/dist/components/custom/NumberInput.d.ts.map +1 -0
- package/dist/components/custom/PalettePicker.d.ts +96 -0
- package/dist/components/custom/PalettePicker.d.ts.map +1 -0
- package/dist/components/custom/ProgressView.d.ts +47 -0
- package/dist/components/custom/ProgressView.d.ts.map +1 -0
- package/dist/components/custom/RatingBar.d.ts +48 -0
- package/dist/components/custom/RatingBar.d.ts.map +1 -0
- package/dist/components/custom/ScrollView.d.ts.map +1 -1
- package/dist/components/custom/SegmentedControl.d.ts +99 -0
- package/dist/components/custom/SegmentedControl.d.ts.map +1 -0
- package/dist/components/custom/Toast.d.ts +89 -0
- package/dist/components/custom/Toast.d.ts.map +1 -0
- package/dist/components/custom/Toolbar.d.ts +134 -0
- package/dist/components/custom/Toolbar.d.ts.map +1 -0
- package/dist/components/custom/WheelPicker.d.ts +63 -0
- package/dist/components/custom/WheelPicker.d.ts.map +1 -0
- package/dist/components/custom/index.cjs +39 -1
- package/dist/components/custom/index.d.ts +18 -5
- package/dist/components/custom/index.d.ts.map +1 -1
- package/dist/components/custom/index.js +2 -2
- package/dist/components/index.d.ts +16 -5
- package/dist/components/index.d.ts.map +1 -1
- package/dist/{custom-BPY0TbuS.js → custom-pRNJ0_kS.js} +16820 -28213
- package/dist/custom-pRNJ0_kS.js.map +1 -0
- package/dist/{custom-Bnit70lx.cjs → custom-rkdLsk0U.cjs} +10167 -21201
- package/dist/custom-rkdLsk0U.cjs.map +1 -0
- package/dist/design-tokens/component-size-presets.d.ts +52 -0
- package/dist/design-tokens/component-size-presets.d.ts.map +1 -0
- package/dist/design-tokens/index.d.ts +2 -0
- package/dist/design-tokens/index.d.ts.map +1 -1
- package/dist/dev-config.d.ts.map +1 -1
- package/dist/index.cjs +61 -256
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -244
- package/dist/index.js.map +1 -1
- package/dist/scripts/generate-icon-loaders.js +27 -1
- package/dist/scripts/generate-icons.d.ts.map +1 -1
- package/dist/scripts/generate-icons.js +27 -1
- package/dist/theme-custom.d.ts +238 -0
- package/dist/theme-custom.d.ts.map +1 -1
- package/dist/theme-defaults.d.ts.map +1 -1
- package/dist/theme.d.ts +9 -0
- package/dist/theme.d.ts.map +1 -1
- package/package.json +1 -3
- package/dist/custom-BPY0TbuS.js.map +0 -1
- package/dist/custom-Bnit70lx.cjs.map +0 -1
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../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/scene-backgrounds.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/index.ts"],"sourcesContent":["/**\n * Hook and creators for Phaser camera effects\n */\nimport * as 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 (internal vs external filter context)\n */\nexport type FXType = 'internal' | 'external'\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.Filters.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.Filters.Controller>>(new Set())\n\n // Pre-initialize the Phaser 4 filter pipeline at mount time.\n // Calling enableFilters() lazily (on first FX application) causes the game object\n // to resize to 1/4 of its original size. Initializing it eagerly during mount\n // (before layout settles) prevents this resize behavior.\n useEffect(() => {\n const obj = ref.current\n if (obj && typeof (obj as { enableFilters?: () => void }).enableFilters === 'function') {\n ;(obj as { enableFilters: () => void }).enableFilters()\n }\n }, [])\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 = 'internal'\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 filters\n const obj = ref.current\n if (obj?.filters) {\n obj.filters.internal.clear()\n obj.filters.external.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 = 'internal') => {\n const { quality = 0, x = 2, y = 2, strength = 1, color = 0xffffff, steps = 4 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createBlurFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal'\n) => {\n const { effect = 'grayscale', amount = 1 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createColorMatrixFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\n if (!pipeline) {\n console.warn('[createColorMatrixFX] FX pipeline not available on this GameObject')\n return null\n }\n\n const colorMatrixFilter = pipeline.addColorMatrix()\n const cm = colorMatrixFilter.colorMatrix\n\n // Apply the selected effect\n switch (effect) {\n case 'grayscale':\n cm.grayscale(amount)\n break\n case 'sepia':\n cm.sepia()\n break\n case 'negative':\n cm.negative()\n break\n case 'blackWhite':\n cm.blackWhite()\n break\n case 'brown':\n cm.brown()\n break\n case 'kodachrome':\n cm.kodachrome()\n break\n case 'technicolor':\n cm.technicolor()\n break\n case 'polaroid':\n cm.polaroid()\n break\n }\n\n return colorMatrixFilter\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 = 'internal') => {\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 obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createGlowFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\n if (!pipeline) {\n console.warn('[createGlowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser 4 API: addGlow(color, outerStrength, innerStrength, scale, knockout, quality, distance)\n const glow = pipeline.addGlow(color, outerStrength, innerStrength, 1, 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 = 'internal') => {\n const { amount = 1 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createPixelateFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal') => {\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 obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createShadowFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal') => {\n const { strength = 0.5, radius = 0.5, x = 0.5, y = 0.5 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createVignetteFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 ParticleDeathZoneConfig,\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 setDeathZones: (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\n width?: number,\n height?: number\n ) => void\n /**\n * @deprecated Use setDeathZones.\n */\n setExcludeZones: (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\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 setDeathZones = useCallback(\n (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\n width?: number,\n height?: number\n ) => {\n const emitter = getEmitter()\n const manager = getManager()\n const deathZones = buildDeathZonesFromLayout(zones, width, height, manager ?? undefined)\n applyDeathZone(emitter, deathZones)\n },\n [getEmitter, getManager]\n )\n\n return {\n getManager,\n getEmitter,\n start,\n stop,\n explode,\n setConfig,\n setEmitZone,\n setDeathZones,\n setExcludeZones: setDeathZones,\n }\n}\n","import * as Phaser from 'phaser'\n\n/**\n * Built-in decorative background variants that can be attached to a Phaser scene.\n */\nexport type SceneBackgroundType = 'grid' | 'logo' | 'gradient' | 'particles' | 'none'\n\n/**\n * Optional animation applied to a scene background after it is created.\n */\nexport type BackgroundAnimation = 'lemniscate' | 'wave' | 'pulse' | 'rotate' | 'static'\n\n/**\n * Configuration for {@link addSceneBackground}.\n */\nexport interface BackgroundConfig {\n /** Background variant to create. Use `'none'` to disable background creation. */\n type: SceneBackgroundType\n\n /** Animation preset applied to the created background. Defaults depend on caller config. */\n animation?: BackgroundAnimation\n\n /** Background opacity, usually between `0` and `1`. */\n opacity?: number\n\n /** Primary color as a Phaser numeric color, for example `0x4a9eff`. */\n color?: number\n\n /** Secondary color used by gradient backgrounds. */\n colorSecondary?: number\n\n /** Texture key used by the logo background. Defaults to the built-in logo key. */\n logoKey?: string\n}\n\n/**\n * Handle returned by {@link addSceneBackground}.\n */\nexport interface SceneBackgroundHandle {\n /** Root game object created for the background. */\n background: BackgroundTarget\n\n /** Stops animations, destroys game objects, removes generated textures, and detaches listeners. */\n destroy: () => void\n\n /** Manually resize the background to match an external viewport size. */\n resize: (width: number, height: number) => void\n}\n\nconst DEFAULT_LOGO_KEY = 'phaser-jsx-logo'\n\n/**\n * Default scene background used when no explicit config is provided.\n */\nexport const DEFAULT_BACKGROUND: BackgroundConfig = {\n type: 'grid',\n animation: 'lemniscate',\n opacity: 0.15,\n color: 0x4a9eff,\n}\n\ntype BackgroundTarget =\n | Phaser.GameObjects.Container\n | Phaser.GameObjects.Image\n | Phaser.GameObjects.TileSprite\ntype RedrawableTarget = BackgroundTarget & { __redrawFn?: (x: number, y: number) => void }\n\nlet sceneBackgroundTextureId = 0\n\nfunction colorToCss(color: number): string {\n return `#${color.toString(16).padStart(6, '0')}`\n}\n\nfunction createCanvasTexture(\n scene: Phaser.Scene,\n width: number,\n height: number,\n draw: (ctx: CanvasRenderingContext2D, width: number, height: number) => void\n): string {\n const textureKey = `__phaserjsx_scene_bg_${sceneBackgroundTextureId++}`\n const textureWidth = Math.max(1, Math.ceil(width))\n const textureHeight = Math.max(1, Math.ceil(height))\n const texture = scene.textures.createCanvas(textureKey, textureWidth, textureHeight)\n\n if (!texture) {\n throw new Error('Unable to create scene background texture')\n }\n\n const canvas = texture.getSourceImage() as HTMLCanvasElement\n const ctx = canvas.getContext('2d')\n\n if (!ctx) {\n throw new Error('Unable to create scene background canvas texture')\n }\n\n ctx.clearRect(0, 0, textureWidth, textureHeight)\n draw(ctx, textureWidth, textureHeight)\n texture.refresh()\n\n return textureKey\n}\n\nfunction removeTexture(scene: Phaser.Scene, textureKey: string | undefined): void {\n if (textureKey && scene.textures.exists(textureKey)) {\n scene.textures.remove(textureKey)\n }\n}\n\n/**\n * Adds a decorative background object to a Phaser scene.\n *\n * The helper owns all game objects, tweens, resize listeners, and generated textures it creates.\n * It automatically cleans up on scene shutdown or destroy. Call `handle.destroy()` when removing\n * the background earlier.\n *\n * @param scene - Phaser scene that receives the background.\n * @param config - Background type, colors, opacity, animation, and optional logo texture key.\n * @returns A handle for manual resize and cleanup, or `null` when `config.type` is `'none'`.\n *\n * @example\n * ```ts\n * const handle = addSceneBackground(scene, {\n * type: 'grid',\n * animation: 'wave',\n * color: 0x4a9eff,\n * opacity: 0.12,\n * })\n *\n * // Later, if the background should be removed before scene shutdown:\n * handle?.destroy()\n * ```\n */\nexport function addSceneBackground(\n scene: Phaser.Scene,\n config: BackgroundConfig = DEFAULT_BACKGROUND\n): SceneBackgroundHandle | null {\n const bgConfig = config ?? DEFAULT_BACKGROUND\n if (bgConfig.type === 'none') return null\n\n let background: BackgroundTarget | undefined\n let backgroundTween: Phaser.Tweens.Tween | undefined\n const particleTweens: Phaser.Tweens.Tween[] = []\n const textureKeys = new Set<string>()\n let resizeFn: ((width: number, height: number) => void) | undefined\n let destroyed = false\n\n const createGridBackground = () => {\n const gridSize = 40\n const color = bgConfig.color ?? 0x4a9eff\n const opacity = bgConfig.opacity ?? 0.15\n const textureKey = createCanvasTexture(scene, gridSize, gridSize, (ctx, width, height) => {\n ctx.globalAlpha = opacity\n ctx.strokeStyle = colorToCss(color)\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(0.5, 0)\n ctx.lineTo(0.5, height)\n ctx.moveTo(0, 0.5)\n ctx.lineTo(width, 0.5)\n ctx.stroke()\n })\n textureKeys.add(textureKey)\n\n const tile = scene.add.tileSprite(0, 0, scene.scale.width, scene.scale.height, textureKey)\n tile.setOrigin(0, 0)\n\n const moveGrid = (offsetX: number, offsetY: number) => {\n tile.tilePositionX = -offsetX\n tile.tilePositionY = -offsetY\n }\n\n ;(tile as RedrawableTarget).__redrawFn = moveGrid\n background = tile\n resizeFn = (width, height) => {\n tile.setSize(width, height)\n }\n }\n\n const createLogoBackground = () => {\n const container = scene.add.container(scene.scale.width / 2, scene.scale.height / 2)\n const opacity = bgConfig.opacity ?? 0.1\n const logoKey = bgConfig.logoKey ?? DEFAULT_LOGO_KEY\n\n const logo = scene.add.image(0, 0, logoKey)\n logo.setAlpha(opacity)\n logo.setScale(0.5)\n\n container.add(logo)\n background = container\n resizeFn = (width, height) => {\n container.setPosition(width / 2, height / 2)\n }\n }\n\n const createGradientBackground = () => {\n const color1 = bgConfig.color ?? 0x4a9eff\n const color2 = bgConfig.colorSecondary ?? 0x6b4aff\n const opacity = bgConfig.opacity ?? 0.2\n\n const createGradientTexture = (width: number, height: number) =>\n createCanvasTexture(scene, width, height, (ctx, textureWidth, textureHeight) => {\n const gradient = ctx.createLinearGradient(0, 0, 0, textureHeight)\n gradient.addColorStop(0, colorToCss(color1))\n gradient.addColorStop(1, colorToCss(color2))\n\n ctx.globalAlpha = opacity\n ctx.fillStyle = gradient\n ctx.fillRect(0, 0, textureWidth, textureHeight)\n })\n\n let textureKey = createGradientTexture(scene.scale.width, scene.scale.height)\n textureKeys.add(textureKey)\n\n const image = scene.add.image(0, 0, textureKey)\n image.setOrigin(0, 0)\n\n resizeFn = (width, height) => {\n const previousTextureKey = textureKey\n textureKey = createGradientTexture(width, height)\n textureKeys.add(textureKey)\n image.setTexture(textureKey)\n image.setDisplaySize(width, height)\n textureKeys.delete(previousTextureKey)\n removeTexture(scene, previousTextureKey)\n }\n\n background = image\n }\n\n const createParticlesBackground = () => {\n const container = scene.add.container(0, 0)\n const particleCount = 20\n const color = bgConfig.color ?? 0x4a9eff\n const opacity = bgConfig.opacity ?? 0.1\n const particles: Phaser.GameObjects.Arc[] = []\n\n for (let i = 0; i < particleCount; i += 1) {\n const size = Phaser.Math.Between(2, 6)\n const x = Phaser.Math.Between(0, scene.scale.width)\n const y = Phaser.Math.Between(0, scene.scale.height)\n\n const particle = scene.add.circle(x, y, size, color, opacity)\n container.add(particle)\n particles.push(particle)\n\n particleTweens.push(\n scene.tweens.add({\n targets: particle,\n y: particle.y + Phaser.Math.Between(-50, 50),\n x: particle.x + Phaser.Math.Between(-50, 50),\n alpha: opacity * 1.5,\n duration: Phaser.Math.Between(2000, 4000),\n yoyo: true,\n repeat: -1,\n ease: 'Sine.easeInOut',\n })\n )\n }\n\n background = container\n resizeFn = (width, height) => {\n for (const particle of particles) {\n particle.setPosition(Phaser.Math.Between(0, width), Phaser.Math.Between(0, height))\n }\n }\n }\n\n switch (bgConfig.type) {\n case 'grid':\n createGridBackground()\n break\n case 'logo':\n createLogoBackground()\n break\n case 'gradient':\n createGradientBackground()\n break\n case 'particles':\n createParticlesBackground()\n break\n }\n\n if (!background) return null\n\n if (bgConfig.animation && bgConfig.animation !== 'static') {\n backgroundTween = applyAnimation(scene, background, bgConfig.animation)\n }\n\n const onResize = () => {\n if (resizeFn) resizeFn(scene.scale.width, scene.scale.height)\n }\n\n const cleanup = () => {\n if (destroyed) return\n destroyed = true\n\n backgroundTween?.stop()\n for (const tween of particleTweens) {\n tween.stop()\n }\n\n background?.destroy()\n background = undefined\n for (const textureKey of textureKeys) {\n removeTexture(scene, textureKey)\n }\n textureKeys.clear()\n\n scene.scale.off(Phaser.Scale.Events.RESIZE, onResize)\n scene.events.off(Phaser.Scenes.Events.SHUTDOWN, cleanup)\n scene.events.off(Phaser.Scenes.Events.DESTROY, cleanup)\n }\n\n scene.scale.on(Phaser.Scale.Events.RESIZE, onResize)\n scene.events.once(Phaser.Scenes.Events.SHUTDOWN, cleanup)\n scene.events.once(Phaser.Scenes.Events.DESTROY, cleanup)\n\n return {\n background,\n destroy: cleanup,\n resize: (width, height) => {\n if (resizeFn) resizeFn(width, height)\n },\n }\n}\n\nfunction applyAnimation(\n scene: Phaser.Scene,\n target: BackgroundTarget,\n animation: BackgroundAnimation\n): Phaser.Tweens.Tween | undefined {\n const redrawFn = (target as RedrawableTarget).__redrawFn\n\n switch (animation) {\n case 'lemniscate':\n return redrawFn ? animateLemniscate(scene, redrawFn) : animatePulse(scene, target)\n case 'wave':\n return redrawFn ? animateWave(scene, redrawFn) : animatePulse(scene, target)\n case 'pulse':\n return animatePulse(scene, target)\n case 'rotate':\n return animateRotate(scene, target)\n case 'static':\n default:\n return undefined\n }\n}\n\nfunction animateLemniscate(\n scene: Phaser.Scene,\n drawFn: (x: number, y: number) => void\n): Phaser.Tweens.Tween {\n const amplitude = 30\n const duration = 8000\n\n return scene.tweens.addCounter({\n from: 0,\n to: Math.PI * 2,\n duration,\n repeat: -1,\n onUpdate: (tween) => {\n const t = tween.getValue()\n if (t !== null) {\n const offsetX = amplitude * Math.cos(t)\n const offsetY = (amplitude * Math.sin(2 * t)) / 2\n drawFn(offsetX, offsetY)\n }\n },\n })\n}\n\nfunction animateWave(\n scene: Phaser.Scene,\n drawFn: (x: number, y: number) => void\n): Phaser.Tweens.Tween {\n return scene.tweens.addCounter({\n from: 0,\n to: 40,\n duration: 3000,\n yoyo: true,\n repeat: -1,\n onUpdate: (tween) => {\n const offset = tween.getValue()\n if (offset !== null) {\n drawFn(offset, 0)\n }\n },\n })\n}\n\nfunction animatePulse(scene: Phaser.Scene, target: BackgroundTarget): Phaser.Tweens.Tween {\n return scene.tweens.add({\n targets: target,\n scaleX: 1.1,\n scaleY: 1.1,\n duration: 2000,\n yoyo: true,\n repeat: -1,\n ease: 'Sine.easeInOut',\n })\n}\n\nfunction animateRotate(scene: Phaser.Scene, target: BackgroundTarget): Phaser.Tweens.Tween {\n return scene.tweens.add({\n targets: target,\n angle: 360,\n duration: 20000,\n repeat: -1,\n ease: 'Linear',\n })\n}\n","/**\n * PhaserJSX Plugin for automatic JSX mounting\n * Enables declarative initialization via Phaser game config\n */\nimport * as 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: unknown) => 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 { createDefaultTheme } from '../theme-defaults'\nimport { remountAll } from '../vdom'\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.setGlobalTheme(createDefaultTheme(presetName, targetMode))\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 remountAll()\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 * PhaserJSX UI Library\n * Provides JSX + hooks + VDOM for Phaser 4 game UI development\n */\nimport { registerBuiltins } from './components'\nimport './clip'\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 './clip'\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'\nexport * from './scene-backgrounds'\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"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../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/scene-backgrounds.ts","../src/plugin.ts","../src/index.ts"],"sourcesContent":["/**\n * Hook and creators for Phaser camera effects\n */\nimport * as 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 (internal vs external filter context)\n */\nexport type FXType = 'internal' | 'external'\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.Filters.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.Filters.Controller>>(new Set())\n\n // Pre-initialize the Phaser 4 filter pipeline at mount time.\n // Calling enableFilters() lazily (on first FX application) causes the game object\n // to resize to 1/4 of its original size. Initializing it eagerly during mount\n // (before layout settles) prevents this resize behavior.\n useEffect(() => {\n const obj = ref.current\n if (obj && typeof (obj as { enableFilters?: () => void }).enableFilters === 'function') {\n ;(obj as { enableFilters: () => void }).enableFilters()\n }\n }, [])\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 = 'internal'\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 filters\n const obj = ref.current\n if (obj?.filters) {\n obj.filters.internal.clear()\n obj.filters.external.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 = 'internal') => {\n const { quality = 0, x = 2, y = 2, strength = 1, color = 0xffffff, steps = 4 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createBlurFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal'\n) => {\n const { effect = 'grayscale', amount = 1 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createColorMatrixFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\n if (!pipeline) {\n console.warn('[createColorMatrixFX] FX pipeline not available on this GameObject')\n return null\n }\n\n const colorMatrixFilter = pipeline.addColorMatrix()\n const cm = colorMatrixFilter.colorMatrix\n\n // Apply the selected effect\n switch (effect) {\n case 'grayscale':\n cm.grayscale(amount)\n break\n case 'sepia':\n cm.sepia()\n break\n case 'negative':\n cm.negative()\n break\n case 'blackWhite':\n cm.blackWhite()\n break\n case 'brown':\n cm.brown()\n break\n case 'kodachrome':\n cm.kodachrome()\n break\n case 'technicolor':\n cm.technicolor()\n break\n case 'polaroid':\n cm.polaroid()\n break\n }\n\n return colorMatrixFilter\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 = 'internal') => {\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 obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createGlowFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\n if (!pipeline) {\n console.warn('[createGlowFX] FX pipeline not available on this GameObject')\n return null\n }\n\n // Phaser 4 API: addGlow(color, outerStrength, innerStrength, scale, knockout, quality, distance)\n const glow = pipeline.addGlow(color, outerStrength, innerStrength, 1, 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 = 'internal') => {\n const { amount = 1 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createPixelateFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal') => {\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 obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createShadowFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 = 'internal') => {\n const { strength = 0.5, radius = 0.5, x = 0.5, y = 0.5 } = config\n\n obj.enableFilters()\n const filters = obj.filters\n if (!filters) {\n console.warn('[createVignetteFX] Filters not available on this GameObject')\n return null\n }\n\n const pipeline = type === 'internal' ? filters.internal : filters.external\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 ParticleDeathZoneConfig,\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 setDeathZones: (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\n width?: number,\n height?: number\n ) => void\n /**\n * @deprecated Use setDeathZones.\n */\n setExcludeZones: (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\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 setDeathZones = useCallback(\n (\n zones: ParticleDeathZoneConfig | ParticleDeathZoneConfig[],\n width?: number,\n height?: number\n ) => {\n const emitter = getEmitter()\n const manager = getManager()\n const deathZones = buildDeathZonesFromLayout(zones, width, height, manager ?? undefined)\n applyDeathZone(emitter, deathZones)\n },\n [getEmitter, getManager]\n )\n\n return {\n getManager,\n getEmitter,\n start,\n stop,\n explode,\n setConfig,\n setEmitZone,\n setDeathZones,\n setExcludeZones: setDeathZones,\n }\n}\n","import * as Phaser from 'phaser'\n\n/**\n * Built-in decorative background variants that can be attached to a Phaser scene.\n */\nexport type SceneBackgroundType = 'grid' | 'logo' | 'gradient' | 'particles' | 'none'\n\n/**\n * Optional animation applied to a scene background after it is created.\n */\nexport type BackgroundAnimation = 'lemniscate' | 'wave' | 'pulse' | 'rotate' | 'static'\n\n/**\n * Configuration for {@link addSceneBackground}.\n */\nexport interface BackgroundConfig {\n /** Background variant to create. Use `'none'` to disable background creation. */\n type: SceneBackgroundType\n\n /** Animation preset applied to the created background. Defaults depend on caller config. */\n animation?: BackgroundAnimation\n\n /** Background opacity, usually between `0` and `1`. */\n opacity?: number\n\n /** Primary color as a Phaser numeric color, for example `0x4a9eff`. */\n color?: number\n\n /** Secondary color used by gradient backgrounds. */\n colorSecondary?: number\n\n /** Texture key used by the logo background. Defaults to the built-in logo key. */\n logoKey?: string\n}\n\n/**\n * Handle returned by {@link addSceneBackground}.\n */\nexport interface SceneBackgroundHandle {\n /** Root game object created for the background. */\n background: BackgroundTarget\n\n /** Stops animations, destroys game objects, removes generated textures, and detaches listeners. */\n destroy: () => void\n\n /** Manually resize the background to match an external viewport size. */\n resize: (width: number, height: number) => void\n}\n\nconst DEFAULT_LOGO_KEY = 'phaser-jsx-logo'\n\n/**\n * Default scene background used when no explicit config is provided.\n */\nexport const DEFAULT_BACKGROUND: BackgroundConfig = {\n type: 'grid',\n animation: 'lemniscate',\n opacity: 0.15,\n color: 0x4a9eff,\n}\n\ntype BackgroundTarget =\n | Phaser.GameObjects.Container\n | Phaser.GameObjects.Image\n | Phaser.GameObjects.TileSprite\ntype RedrawableTarget = BackgroundTarget & { __redrawFn?: (x: number, y: number) => void }\n\nlet sceneBackgroundTextureId = 0\n\nfunction colorToCss(color: number): string {\n return `#${color.toString(16).padStart(6, '0')}`\n}\n\nfunction createCanvasTexture(\n scene: Phaser.Scene,\n width: number,\n height: number,\n draw: (ctx: CanvasRenderingContext2D, width: number, height: number) => void\n): string {\n const textureKey = `__phaserjsx_scene_bg_${sceneBackgroundTextureId++}`\n const textureWidth = Math.max(1, Math.ceil(width))\n const textureHeight = Math.max(1, Math.ceil(height))\n const texture = scene.textures.createCanvas(textureKey, textureWidth, textureHeight)\n\n if (!texture) {\n throw new Error('Unable to create scene background texture')\n }\n\n const canvas = texture.getSourceImage() as HTMLCanvasElement\n const ctx = canvas.getContext('2d')\n\n if (!ctx) {\n throw new Error('Unable to create scene background canvas texture')\n }\n\n ctx.clearRect(0, 0, textureWidth, textureHeight)\n draw(ctx, textureWidth, textureHeight)\n texture.refresh()\n\n return textureKey\n}\n\nfunction removeTexture(scene: Phaser.Scene, textureKey: string | undefined): void {\n if (textureKey && scene.textures.exists(textureKey)) {\n scene.textures.remove(textureKey)\n }\n}\n\n/**\n * Adds a decorative background object to a Phaser scene.\n *\n * The helper owns all game objects, tweens, resize listeners, and generated textures it creates.\n * It automatically cleans up on scene shutdown or destroy. Call `handle.destroy()` when removing\n * the background earlier.\n *\n * @param scene - Phaser scene that receives the background.\n * @param config - Background type, colors, opacity, animation, and optional logo texture key.\n * @returns A handle for manual resize and cleanup, or `null` when `config.type` is `'none'`.\n *\n * @example\n * ```ts\n * const handle = addSceneBackground(scene, {\n * type: 'grid',\n * animation: 'wave',\n * color: 0x4a9eff,\n * opacity: 0.12,\n * })\n *\n * // Later, if the background should be removed before scene shutdown:\n * handle?.destroy()\n * ```\n */\nexport function addSceneBackground(\n scene: Phaser.Scene,\n config: BackgroundConfig = DEFAULT_BACKGROUND\n): SceneBackgroundHandle | null {\n const bgConfig = config ?? DEFAULT_BACKGROUND\n if (bgConfig.type === 'none') return null\n\n let background: BackgroundTarget | undefined\n let backgroundTween: Phaser.Tweens.Tween | undefined\n const particleTweens: Phaser.Tweens.Tween[] = []\n const textureKeys = new Set<string>()\n let resizeFn: ((width: number, height: number) => void) | undefined\n let destroyed = false\n\n const createGridBackground = () => {\n const gridSize = 40\n const color = bgConfig.color ?? 0x4a9eff\n const opacity = bgConfig.opacity ?? 0.15\n const textureKey = createCanvasTexture(scene, gridSize, gridSize, (ctx, width, height) => {\n ctx.globalAlpha = opacity\n ctx.strokeStyle = colorToCss(color)\n ctx.lineWidth = 1\n ctx.beginPath()\n ctx.moveTo(0.5, 0)\n ctx.lineTo(0.5, height)\n ctx.moveTo(0, 0.5)\n ctx.lineTo(width, 0.5)\n ctx.stroke()\n })\n textureKeys.add(textureKey)\n\n const tile = scene.add.tileSprite(0, 0, scene.scale.width, scene.scale.height, textureKey)\n tile.setOrigin(0, 0)\n\n const moveGrid = (offsetX: number, offsetY: number) => {\n tile.tilePositionX = -offsetX\n tile.tilePositionY = -offsetY\n }\n\n ;(tile as RedrawableTarget).__redrawFn = moveGrid\n background = tile\n resizeFn = (width, height) => {\n tile.setSize(width, height)\n }\n }\n\n const createLogoBackground = () => {\n const container = scene.add.container(scene.scale.width / 2, scene.scale.height / 2)\n const opacity = bgConfig.opacity ?? 0.1\n const logoKey = bgConfig.logoKey ?? DEFAULT_LOGO_KEY\n\n const logo = scene.add.image(0, 0, logoKey)\n logo.setAlpha(opacity)\n logo.setScale(0.5)\n\n container.add(logo)\n background = container\n resizeFn = (width, height) => {\n container.setPosition(width / 2, height / 2)\n }\n }\n\n const createGradientBackground = () => {\n const color1 = bgConfig.color ?? 0x4a9eff\n const color2 = bgConfig.colorSecondary ?? 0x6b4aff\n const opacity = bgConfig.opacity ?? 0.2\n\n const createGradientTexture = (width: number, height: number) =>\n createCanvasTexture(scene, width, height, (ctx, textureWidth, textureHeight) => {\n const gradient = ctx.createLinearGradient(0, 0, 0, textureHeight)\n gradient.addColorStop(0, colorToCss(color1))\n gradient.addColorStop(1, colorToCss(color2))\n\n ctx.globalAlpha = opacity\n ctx.fillStyle = gradient\n ctx.fillRect(0, 0, textureWidth, textureHeight)\n })\n\n let textureKey = createGradientTexture(scene.scale.width, scene.scale.height)\n textureKeys.add(textureKey)\n\n const image = scene.add.image(0, 0, textureKey)\n image.setOrigin(0, 0)\n\n resizeFn = (width, height) => {\n const previousTextureKey = textureKey\n textureKey = createGradientTexture(width, height)\n textureKeys.add(textureKey)\n image.setTexture(textureKey)\n image.setDisplaySize(width, height)\n textureKeys.delete(previousTextureKey)\n removeTexture(scene, previousTextureKey)\n }\n\n background = image\n }\n\n const createParticlesBackground = () => {\n const container = scene.add.container(0, 0)\n const particleCount = 20\n const color = bgConfig.color ?? 0x4a9eff\n const opacity = bgConfig.opacity ?? 0.1\n const particles: Phaser.GameObjects.Arc[] = []\n\n for (let i = 0; i < particleCount; i += 1) {\n const size = Phaser.Math.Between(2, 6)\n const x = Phaser.Math.Between(0, scene.scale.width)\n const y = Phaser.Math.Between(0, scene.scale.height)\n\n const particle = scene.add.circle(x, y, size, color, opacity)\n container.add(particle)\n particles.push(particle)\n\n particleTweens.push(\n scene.tweens.add({\n targets: particle,\n y: particle.y + Phaser.Math.Between(-50, 50),\n x: particle.x + Phaser.Math.Between(-50, 50),\n alpha: opacity * 1.5,\n duration: Phaser.Math.Between(2000, 4000),\n yoyo: true,\n repeat: -1,\n ease: 'Sine.easeInOut',\n })\n )\n }\n\n background = container\n resizeFn = (width, height) => {\n for (const particle of particles) {\n particle.setPosition(Phaser.Math.Between(0, width), Phaser.Math.Between(0, height))\n }\n }\n }\n\n switch (bgConfig.type) {\n case 'grid':\n createGridBackground()\n break\n case 'logo':\n createLogoBackground()\n break\n case 'gradient':\n createGradientBackground()\n break\n case 'particles':\n createParticlesBackground()\n break\n }\n\n if (!background) return null\n\n if (bgConfig.animation && bgConfig.animation !== 'static') {\n backgroundTween = applyAnimation(scene, background, bgConfig.animation)\n }\n\n const onResize = () => {\n if (resizeFn) resizeFn(scene.scale.width, scene.scale.height)\n }\n\n const cleanup = () => {\n if (destroyed) return\n destroyed = true\n\n backgroundTween?.stop()\n for (const tween of particleTweens) {\n tween.stop()\n }\n\n background?.destroy()\n background = undefined\n for (const textureKey of textureKeys) {\n removeTexture(scene, textureKey)\n }\n textureKeys.clear()\n\n scene.scale.off(Phaser.Scale.Events.RESIZE, onResize)\n scene.events.off(Phaser.Scenes.Events.SHUTDOWN, cleanup)\n scene.events.off(Phaser.Scenes.Events.DESTROY, cleanup)\n }\n\n scene.scale.on(Phaser.Scale.Events.RESIZE, onResize)\n scene.events.once(Phaser.Scenes.Events.SHUTDOWN, cleanup)\n scene.events.once(Phaser.Scenes.Events.DESTROY, cleanup)\n\n return {\n background,\n destroy: cleanup,\n resize: (width, height) => {\n if (resizeFn) resizeFn(width, height)\n },\n }\n}\n\nfunction applyAnimation(\n scene: Phaser.Scene,\n target: BackgroundTarget,\n animation: BackgroundAnimation\n): Phaser.Tweens.Tween | undefined {\n const redrawFn = (target as RedrawableTarget).__redrawFn\n\n switch (animation) {\n case 'lemniscate':\n return redrawFn ? animateLemniscate(scene, redrawFn) : animatePulse(scene, target)\n case 'wave':\n return redrawFn ? animateWave(scene, redrawFn) : animatePulse(scene, target)\n case 'pulse':\n return animatePulse(scene, target)\n case 'rotate':\n return animateRotate(scene, target)\n case 'static':\n default:\n return undefined\n }\n}\n\nfunction animateLemniscate(\n scene: Phaser.Scene,\n drawFn: (x: number, y: number) => void\n): Phaser.Tweens.Tween {\n const amplitude = 30\n const duration = 8000\n\n return scene.tweens.addCounter({\n from: 0,\n to: Math.PI * 2,\n duration,\n repeat: -1,\n onUpdate: (tween) => {\n const t = tween.getValue()\n if (t !== null) {\n const offsetX = amplitude * Math.cos(t)\n const offsetY = (amplitude * Math.sin(2 * t)) / 2\n drawFn(offsetX, offsetY)\n }\n },\n })\n}\n\nfunction animateWave(\n scene: Phaser.Scene,\n drawFn: (x: number, y: number) => void\n): Phaser.Tweens.Tween {\n return scene.tweens.addCounter({\n from: 0,\n to: 40,\n duration: 3000,\n yoyo: true,\n repeat: -1,\n onUpdate: (tween) => {\n const offset = tween.getValue()\n if (offset !== null) {\n drawFn(offset, 0)\n }\n },\n })\n}\n\nfunction animatePulse(scene: Phaser.Scene, target: BackgroundTarget): Phaser.Tweens.Tween {\n return scene.tweens.add({\n targets: target,\n scaleX: 1.1,\n scaleY: 1.1,\n duration: 2000,\n yoyo: true,\n repeat: -1,\n ease: 'Sine.easeInOut',\n })\n}\n\nfunction animateRotate(scene: Phaser.Scene, target: BackgroundTarget): Phaser.Tweens.Tween {\n return scene.tweens.add({\n targets: target,\n angle: 360,\n duration: 20000,\n repeat: -1,\n ease: 'Linear',\n })\n}\n","/**\n * PhaserJSX Plugin for automatic JSX mounting\n * Enables declarative initialization via Phaser game config\n */\nimport * as 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: unknown) => 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 * PhaserJSX UI Library\n * Provides JSX + hooks + VDOM for Phaser 4 game UI development\n */\nimport { registerBuiltins } from './components'\nimport './clip'\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 './clip'\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'\nexport * from './scene-backgrounds'\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"],"mappings":"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"}
|
|
@@ -28,16 +28,42 @@ async function findTsFiles(dir) {
|
|
|
28
28
|
/**
|
|
29
29
|
* Extract icon names from file content
|
|
30
30
|
*/
|
|
31
|
+
function escapeRegExp(value) {
|
|
32
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
33
|
+
}
|
|
34
|
+
function addStringLiteralIcons(expression, iconNames) {
|
|
35
|
+
const stringLiteralPattern = /(["'])([^"'\r\n]+)\1/g;
|
|
36
|
+
let match;
|
|
37
|
+
while ((match = stringLiteralPattern.exec(expression)) !== null) {
|
|
38
|
+
const iconName = match[2];
|
|
39
|
+
if (iconName) iconNames.add(iconName);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function addIconTypeDeclarationIcons(content, iconNames) {
|
|
43
|
+
const iconTypeLiteralDeclarationPattern = /\b(?:const|let|var)\s+\w+\s*:\s*[^=;\r\n]*\bIconType\b[^=;\r\n]*=\s*(["'])([^"']+)\1/g;
|
|
44
|
+
let match;
|
|
45
|
+
while ((match = iconTypeLiteralDeclarationPattern.exec(content)) !== null) {
|
|
46
|
+
const iconName = match[2];
|
|
47
|
+
if (iconName) iconNames.add(iconName);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
31
50
|
function extractIconNames(content, componentNames) {
|
|
32
51
|
const iconNames = /* @__PURE__ */ new Set();
|
|
33
52
|
let match;
|
|
34
53
|
for (const componentName of componentNames) {
|
|
35
|
-
const
|
|
54
|
+
const escapedComponentName = escapeRegExp(componentName);
|
|
55
|
+
const typePattern = new RegExp(`<${escapedComponentName}\\s+[^>]*\\btype=(?:["']([^"']+)["']|\\{['"]([^"']+)["']\\})`, "g");
|
|
36
56
|
while ((match = typePattern.exec(content)) !== null) {
|
|
37
57
|
const iconName = match[1] || match[2];
|
|
38
58
|
if (iconName) iconNames.add(iconName);
|
|
39
59
|
}
|
|
60
|
+
const typeExpressionPattern = new RegExp(`<${escapedComponentName}\\s+[^>]*\\btype=\\{([^}]*)\\}`, "g");
|
|
61
|
+
while ((match = typeExpressionPattern.exec(content)) !== null) {
|
|
62
|
+
const expression = match[1];
|
|
63
|
+
if (expression) addStringLiteralIcons(expression, iconNames);
|
|
64
|
+
}
|
|
40
65
|
}
|
|
66
|
+
addIconTypeDeclarationIcons(content, iconNames);
|
|
41
67
|
const themedPattern = /themed\.(\w*[Ii]con)\s*\?\?\s*["']([^"']+)["']/g;
|
|
42
68
|
while ((match = themedPattern.exec(content)) !== null) if (match[2]) iconNames.add(match[2]);
|
|
43
69
|
const iconPropPattern = /(?:icon|iconType):\s*["']([^"']+)["']/g;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generate-icons.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-icons.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;
|
|
1
|
+
{"version":3,"file":"generate-icons.d.ts","sourceRoot":"","sources":["../../src/scripts/generate-icons.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAA;AA0LlE;;;GAGG;AACH,wBAAsB,aAAa,CACjC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAAG,IAAI,CAAC,CA+EnF;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC,CAgC5E;AAED;;;GAGG;AACH,wBAAsB,eAAe,CACnC,MAAM,EAAE,mBAAmB,EAC3B,GAAG,EAAE,MAAM,EACX,WAAW,CAAC,EAAE;IAAE,SAAS,EAAE,MAAM,EAAE,CAAC;IAAC,cAAc,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;CAAE,GAC9E,OAAO,CAAC,IAAI,CAAC,CAgLf;AAED;;GAEG;AACH;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,UAAU,EAAE,MAAM,EAClB,GAAG,SAAgB,GAClB,OAAO,CAAC,mBAAmB,CAAC,CA8B9B"}
|
|
@@ -57,16 +57,42 @@ async function findTsFiles(dir, exclude = []) {
|
|
|
57
57
|
/**
|
|
58
58
|
* Extract icon names from file content
|
|
59
59
|
*/
|
|
60
|
+
function escapeRegExp(value) {
|
|
61
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
62
|
+
}
|
|
63
|
+
function addStringLiteralIcons(expression, iconNames) {
|
|
64
|
+
const stringLiteralPattern = /(["'])([^"'\r\n]+)\1/g;
|
|
65
|
+
let match;
|
|
66
|
+
while ((match = stringLiteralPattern.exec(expression)) !== null) {
|
|
67
|
+
const iconName = match[2];
|
|
68
|
+
if (iconName) iconNames.add(iconName);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
function addIconTypeDeclarationIcons(content, iconNames) {
|
|
72
|
+
const iconTypeLiteralDeclarationPattern = /\b(?:const|let|var)\s+\w+\s*:\s*[^=;\r\n]*\bIconType\b[^=;\r\n]*=\s*(["'])([^"']+)\1/g;
|
|
73
|
+
let match;
|
|
74
|
+
while ((match = iconTypeLiteralDeclarationPattern.exec(content)) !== null) {
|
|
75
|
+
const iconName = match[2];
|
|
76
|
+
if (iconName) iconNames.add(iconName);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
60
79
|
function extractIconNames(content, componentNames, customPatterns) {
|
|
61
80
|
const iconNames = /* @__PURE__ */ new Set();
|
|
62
81
|
let match;
|
|
63
82
|
for (const componentName of componentNames) {
|
|
64
|
-
const
|
|
83
|
+
const escapedComponentName = escapeRegExp(componentName);
|
|
84
|
+
const typePattern = new RegExp(`<${escapedComponentName}\\s+[^>]*\\btype=(?:["']([^"']+)["']|\\{["']([^"']+)["']\\})`, "g");
|
|
65
85
|
while ((match = typePattern.exec(content)) !== null) {
|
|
66
86
|
const iconName = match[1] || match[2];
|
|
67
87
|
if (iconName) iconNames.add(iconName);
|
|
68
88
|
}
|
|
89
|
+
const typeExpressionPattern = new RegExp(`<${escapedComponentName}\\s+[^>]*\\btype=\\{([^}]*)\\}`, "g");
|
|
90
|
+
while ((match = typeExpressionPattern.exec(content)) !== null) {
|
|
91
|
+
const expression = match[1];
|
|
92
|
+
if (expression) addStringLiteralIcons(expression, iconNames);
|
|
93
|
+
}
|
|
69
94
|
}
|
|
95
|
+
addIconTypeDeclarationIcons(content, iconNames);
|
|
70
96
|
const themedPattern = /themed\.(\w*[Ii]con)\s*\?\?\s*["']([^"']+)["']/g;
|
|
71
97
|
while ((match = themedPattern.exec(content)) !== null) if (match[2]) iconNames.add(match[2]);
|
|
72
98
|
const iconPropPattern = /(?:icon|iconType):\s*["']([^"']+)["']/g;
|