@caperjs/core 0.1.0 → 0.1.1

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/lib/caper.mjs CHANGED
@@ -202,7 +202,7 @@ function B(e, t) {
202
202
  }
203
203
  //#endregion
204
204
  //#region src/version.ts
205
- var V = "0.1.0", H = "8.19.0", Dn = " ........ ..... ............ ............. ........... \n ............. ....... ................ ............. .............. \n .............. ......... ............... ............. .............. \n ..... ........... .............. ............ .............. \n ..... ...... ...... .............. ............. ............. \n .............. ...... ..... ............ ............. ..... ...... \n ................... ..... ..... ............. ..... ....... \n ................ .......... ............. ..... ..... ";
205
+ var V = "0.1.1", H = "8.19.0", Dn = " ........ ..... ............ ............. ........... \n ............. ....... ................ ............. .............. \n .............. ......... ............... ............. .............. \n ..... ........... .............. ............ .............. \n ..... ...... ...... .............. ............. ............. \n .............. ...... ..... ............ ............. ..... ...... \n ................... ..... ..... ............. ..... ....... \n ................ .......... ............. ..... ..... ";
206
206
  function U() {
207
207
  let e = `\n${Dn}\n\n v${V} | %cPixi.js v${H} %c| %chttps://github.com/anthonysapp/caper\n\n`;
208
208
  console.log(e, "color: #E91E63; font-weight: 600;", "color: inherit;", "color: #00BCD4; text-decoration: underline;");
package/lib/caper.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"caper.mjs","names":[],"sources":["../src/utils/array.ts","../src/utils/canvas.ts","../src/utils/color.ts","../src/utils/define.ts","../src/utils/pixi.ts","../src/utils/platform.ts","../src/utils/rect.ts","../src/utils/set.ts","../src/utils/text.ts","../src/version.ts","../src/hello.ts","../src/webgl-check.ts","../src/display/Entity.ts","../src/display/Scene.ts","../src/display/SceneTransition.ts","../src/display/Camera.ts","../src/ui/Input.ts","../src/plugins/actions/methods.ts","../src/plugins/breakpoints/methods.ts","../src/plugins/input/touch/constants.ts","../src/plugins/input/methods.ts","../src/ui/Joystick.ts","../src/ui/Popup.ts","../src/mixins/factory/props.ts","../src/core/globals.ts","../src/core/create.ts"],"sourcesContent":["import { intBetween } from './random';\n\n/**\n * Shuffle an array.\n * @param array\n */\nexport function shuffle<T>(array: T[]): void {\n let temp: T;\n let index: number;\n for (let i = 0; i < array.length; ++i) {\n index = intBetween(0, array.length);\n temp = array[i];\n array[i] = array[index];\n array[index] = temp;\n }\n}\n\n/**\n * Get a random array element.\n * @param array\n */\nexport function getRandomElement<T>(array: T[]): T {\n return array[intBetween(0, array.length)];\n}\n","export function destroyCanvas(canvas: HTMLCanvasElement | OffscreenCanvas) {\n const gl = canvas.getContext('webgl');\n if (gl) {\n const extension = gl.getExtension('WEBGL_lose_context');\n if (extension) {\n extension.loseContext();\n }\n }\n // If you are using a 2D context, there's no direct resource release method,\n // but you should ensure all operations are complete before nullifying the canvas\n const ctx = canvas.getContext('2d');\n if (ctx) {\n // Perform any necessary cleanup tasks for 2D context\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n if (!(canvas instanceof OffscreenCanvas)) {\n if (canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n }\n canvas.width = 0;\n canvas.height = 0;\n\n // @ts-expect-error canvas can't be null;\n canvas = null;\n}\n","export function toHex(color: number): string {\n return `#${color.toString(16)}`;\n}\n\n// return a uint color from a hex string\nexport function toRgb(hex: string): number {\n return parseInt(hex.replace(/^#/, ''), 16);\n}\n\nexport class Color {\n public static readonly WHITE: Color = new Color(255, 255, 255);\n public static readonly BLACK: Color = new Color(0, 0, 0);\n public static readonly GREY: Color = new Color(127, 127, 127);\n public static readonly RED: Color = new Color(255, 0, 0);\n public static readonly GREEN: Color = new Color(0, 255, 0);\n public static readonly BLUE: Color = new Color(0, 0, 255);\n public static readonly YELLOW: Color = new Color(255, 255, 0);\n public static readonly MAGENTA: Color = new Color(255, 0, 255);\n public static readonly CYAN: Color = new Color(0, 255, 255);\n\n public r: number;\n public g: number;\n public b: number;\n\n /**\n * A Color reresented by a red, green and blue component.\n * @param r The red component of the Color OR the full Color in HEX.\n * @param g The green component of the Color.\n * @param b The blue component of the Color.\n */\n constructor(r?: number, g?: number, b?: number) {\n if (r !== undefined && g === undefined) {\n // tslint:disable-next-line no-bitwise\n this.r = (r & (255 << 16)) >> 16;\n // tslint:disable-next-line no-bitwise\n this.g = (r & (255 << 8)) >> 8;\n // tslint:disable-next-line no-bitwise\n this.b = r & 255;\n } else {\n this.r = r || 0;\n this.g = g || 0;\n this.b = b || 0;\n }\n }\n\n /**\n * Creates a random Color.\n * @returns The new Color.\n */\n public static random(): Color {\n return new Color(Math.random() * 255, Math.random() * 255, Math.random() * 255);\n }\n\n /**\n * Converts the rgb values passed in to hex.\n * @param r The red component to convert.\n * @param g The green component to convert.\n * @param b The blue component to convert.\n * @returns The hex value.\n */\n public static rgbToHex(r: number, g: number, b: number): number {\n // tslint:disable-next-line no-bitwise\n return (r << 16) | (g << 8) | b;\n }\n\n public static rgbToHexString(pNumber: number): string {\n let hex = Number(pNumber).toString(16);\n if (hex.length < 2) {\n hex = '0' + hex;\n }\n\n return hex;\n }\n\n public static rgbToFullHexString(r: number, g: number, b: number): string {\n const rStr: string = Color.rgbToHexString(r);\n const gStr: string = Color.rgbToHexString(g);\n const bStr: string = Color.rgbToHexString(b);\n\n return rStr + gStr + bStr;\n }\n\n /**\n * Creates a new Color that is linearly interpolated from pA to b .\n * @param pA The start Color.\n * @param b The end Color.\n * @param pPerc The percentage on the path from pA to b .\n * @returns The new Color.\n */\n public static lerp(pA: Color, b: Color, pPerc: number): Color {\n return new Color(pA.r + pPerc * (b.r - pA.r), pA.g + pPerc * (b.g - pA.g), pA.b + pPerc * (b.b - pA.b));\n }\n\n /**\n * Creates a new hex Color that is linearly interpolated from pA to b .\n * @param pA The first Color hex.\n * @param b The second Color hex.\n * @param pPerc The percentage along the path from pA to b .\n * @returns The new hex Color.\n */\n public static lerpHex(pA: number, b: number, pPerc: number): number {\n const colorA: Color = new Color(pA);\n const colorB: Color = new Color(b);\n return Color.lerp(colorA, colorB, pPerc).toHex();\n }\n\n /**\n * Convert this Color to hex.\n * @returns The Color in hex format.\n */\n public toHex(): number {\n return Color.rgbToHex(this.r, this.g, this.b);\n }\n\n public toHexString(): string {\n return Color.rgbToFullHexString(this.r, this.g, this.b);\n }\n\n /**\n * Converts the Color components to the 0...1 range.\n * @returns The new Color.\n */\n public toWebGL(): number[] {\n return [this.r / 255, this.g / 255, this.b / 255];\n }\n}\n","import type { SceneAssets, SceneDebug, ScenePlugins } from '../display/Scene';\nimport type { AppTypeOverrides } from './types';\n\ntype AppPluginId = AppTypeOverrides['Plugins'];\n\n/**\n * Runtime-free helpers that give scene/plugin/popup/entity config files\n * strong type inference without forcing users to extend base classes or\n * hand-type every file-level export.\n *\n * They are all typed identity functions (`(config) => config`), following\n * the Vite / Rollup / Playwright `defineConfig` pattern. No runtime cost:\n * the vite-plugin-caper-config scanner reads the call's object\n * argument via AST just like it reads individual `export const` forms.\n *\n * Example:\n *\n * // src/scenes/MenuScene.ts\n * import { defineScene, Scene } from '@caperjs/core';\n * export const scene = defineScene({\n * id: 'menu',\n * assets: { preload: { bundles: ['menu'] } },\n * plugins: ['google-analytics'],\n * });\n * export default class MenuScene extends Scene { ... }\n */\n\n/**\n * Scene metadata accepted by `defineScene`. Mirrors the runtime\n * `SceneConfig` in `display/Scene.ts` — reuses the canonical `SceneAssets`\n * / `ScenePlugins` / `SceneDebug` types so there's one source of truth.\n *\n * `id` is required here (unlike the runtime `SceneConfig` where it's\n * optional, because the scene class itself may carry the id).\n */\nexport interface SceneConfigInput {\n /** Unique scene ID used in `app.scenes.loadScene()`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `true` (code-split). Set `false` to force a static import. */\n dynamic?: boolean;\n /**\n * Asset load configuration. Uses the canonical `SceneAssets` shape:\n *\n * { preload: { bundles: [...] }, background: { bundles: [...] }, autoUnload: true }\n */\n assets?: SceneAssets;\n /** Plugin IDs this scene requires. Loaded lazily on scene load. */\n plugins?: ScenePlugins;\n /** Labels used by the debug UI scene picker. */\n debug?: SceneDebug;\n}\n\nexport interface PluginConfigInput {\n /** Unique plugin ID used in `app.getPlugin(id)`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `true` (code-split). Set `false` to force a static import. */\n dynamic?: boolean;\n /**\n * Plugin IDs that must be initialized before this one. The framework\n * topologically sorts plugins by `requires` at bootstrap, so the order\n * in `caper.config.ts` doesn't matter — required deps will always\n * `initialize()` (and `postInitialize()`) before any plugin that\n * requires them.\n *\n * Bootstrap fails loudly if a required plugin id isn't registered in\n * `caper.config.ts plugins[]`, or if there's a dependency cycle. The\n * error message includes the fix.\n *\n * Build-time validation also checks `requires` against discovered\n * plugin IDs and warns on typos before you ever run the app.\n */\n requires?: AppPluginId[];\n}\n\nexport interface PopupConfigInput {\n /** Unique popup ID used in `app.popups.show(id)`. */\n id: string;\n active?: boolean;\n dynamic?: boolean;\n}\n\nexport interface EntityConfigInput {\n /** Unique entity ID used in `app.entities.create(id)`. */\n id: string;\n active?: boolean;\n dynamic?: boolean;\n}\n\nexport interface UIConfigInput {\n /** Unique UI element ID used in `this.add.ui(id)`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `false` (static import). Set `true` to code-split. */\n dynamic?: boolean;\n}\n\nexport function defineScene<T extends SceneConfigInput>(config: T): T {\n return config;\n}\n\nexport function definePlugin<T extends PluginConfigInput>(config: T): T {\n return config;\n}\n\nexport function definePopup<T extends PopupConfigInput>(config: T): T {\n return config;\n}\n\nexport function defineEntity<T extends EntityConfigInput>(config: T): T {\n return config;\n}\n\nexport function defineUI<T extends UIConfigInput>(config: T): T {\n return config;\n}\n","import { Circle, Container, ContainerChild, Ellipse, Point, Polygon, Rectangle, RoundedRectangle } from 'pixi.js';\nimport { PointLike, Size } from './types';\nimport { resolvePointLike } from './point';\n\nexport type PixiSimpleShape = Rectangle | Circle | Ellipse | RoundedRectangle;\nexport type PixiShape = PixiSimpleShape | Polygon;\n\n/**\n * Reassigns the displays object parent while maintaing it's world position\n * @param pChild\n * @param pParent\n */\nexport function reParent(pChild: ContainerChild, pParent: Container): void {\n if (pChild.parent) {\n pChild.parent.worldTransform.apply(pChild.position as Point, pChild.position as Point);\n }\n pParent.worldTransform.applyInverse(pChild.position as Point, pChild.position as Point);\n pChild.parent?.removeChild(pChild);\n pParent.addChild(pChild);\n}\n\n/**\n *\n * @param pObject\n */\nexport function objectDiagonal(pObject: Container): number {\n return Math.sqrt(pObject.width * pObject.width + pObject.height * pObject.height);\n}\n\n/**\n * Removes provided object from its parent and re-adds it.\n * @param pObject The object to send to the back.\n */\nexport function sendToFront(pObject: Container): void {\n const parent = pObject.parent;\n if (!parent) return;\n parent.removeChild(pObject);\n parent.addChild(pObject);\n}\n\n/**\n * Removes provided object from its parent and re-adds it at index 0.\n * @param pObject The object to send to the back.\n */\nexport function sendToBack(pObject: Container): void {\n const parent = pObject.parent;\n if (!parent) return;\n parent.removeChild(pObject);\n parent.addChildAt(pObject, 0);\n}\n\n/**\n *\n * @param pShape\n * @param pDelta\n */\nexport function offsetShape(pShape: PixiShape, pDelta: Point): PixiShape {\n if (pShape instanceof Polygon) {\n for (let i = 0; i < pShape.points.length; i += 2) {\n pShape.points[i] += pDelta.x;\n pShape.points[i + 1] += pDelta.y;\n }\n return pShape;\n } else {\n pShape.x += pDelta.x;\n pShape.y += pDelta.y;\n return pShape;\n }\n}\n\n/**\n *\n * @param pShape\n * @param pDelta\n */\nexport function offsetSimpleShape(pShape: PixiSimpleShape, pDelta: Point): PixiSimpleShape {\n pShape.x += pDelta.x;\n pShape.y += pDelta.y;\n return pShape;\n}\n\nexport function scaleUniform(obj: any, scaleNum: number, scaleProp: 'width' | 'height' = 'width') {\n const scaleVal: 'x' | 'y' = scaleProp === 'width' ? 'y' : 'x';\n const otherScaleVal: 'x' | 'y' = scaleProp === 'width' ? 'x' : 'y';\n obj[scaleProp] = scaleNum;\n obj.scale[scaleVal] = obj.scale[otherScaleVal];\n}\n\nexport function scaleToWidth(obj: Container, width: number) {\n scaleUniform(obj, width, 'width');\n}\n\nexport function scaleToHeight(obj: Container, height: number) {\n scaleUniform(obj, height, 'height');\n}\n\nexport function scaleToSize(obj: Container, size: PointLike | Size, firstProp: 'width' | 'height' = 'width') {\n let resolvedSize;\n if ((size as Size)?.width && (size as Size)?.height) {\n resolvedSize = { x: (size as Size).width, y: (size as Size).height };\n } else {\n resolvedSize = resolvePointLike(size as PointLike);\n }\n\n if (firstProp === 'width') {\n scaleToWidth(obj, resolvedSize.x);\n if (obj.height < resolvedSize.y) {\n scaleToHeight(obj, resolvedSize.y);\n }\n } else {\n scaleToHeight(obj, resolvedSize.y);\n if (obj.width < resolvedSize.x) {\n scaleToWidth(obj, resolvedSize.x);\n }\n }\n}\n","import { isMobile as PIXIUtilsIsMobile } from 'pixi.js';\n\n/**\n * Checks if the device has a retina display.\n * A device is considered to have a retina display if its device pixel ratio is greater than 1,\n * or if it matches the media query for high resolution displays.\n * @type {boolean}\n */\nexport const isRetina =\n typeof window !== 'undefined'\n ? window.devicePixelRatio > 1 ||\n (window.matchMedia &&\n window.matchMedia(\n '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)',\n ).matches)\n : false;\n\n/**\n * Check if we're on a touch device\n */\nexport const isTouch: boolean =\n typeof window !== 'undefined'\n ? 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator?.maxTouchPoints > 0\n : false;\n\n/**\n * Checks if the device is a mobile device.\n * This uses the `isMobile` function from the `@pixi/utils` package.\n * @type {boolean}\n */\nexport const isMobile = PIXIUtilsIsMobile.any;\nexport const isAndroid = PIXIUtilsIsMobile.android.device;\nexport const isIos = PIXIUtilsIsMobile.apple.device;\n","import { Point, PointLike, Rectangle } from 'pixi.js';\n/**\n *\n * @param rect\n * @param delta\n */\nexport function offset(rect: Rectangle, delta: Point): Rectangle {\n rect.x += delta.x;\n rect.y += delta.y;\n return rect;\n}\n\n/**\n *\n * @param rect\n * @param output\n */\nexport function center(rect: Rectangle, output?: Point): Point {\n if (output === undefined) {\n output = new Point();\n }\n output.set(rect.x + rect.width * 0.5, rect.y + rect.height * 0.5);\n return output;\n}\n\n/**\n * Scale a rectangle by a provided value\n * @param rect\n * @param scale\n */\nexport function scale(rect: Rectangle, scale: number): Rectangle {\n rect.x *= scale;\n rect.y *= scale;\n rect.width *= scale;\n rect.height *= scale;\n return rect;\n}\n\n/**\n * Returns a `Point` representing the width and height of the input Rectangle\n * @param rect\n * @param output\n */\nexport function size(rect: Rectangle, output?: Point): PointLike {\n if (output === undefined) {\n output = new Point();\n }\n output.set(rect.width, rect.height);\n return output;\n}\n","/**\n * Filters a Set based on the provided filter function.\n * @param set The original Set to filter.\n * @param filterFunction The function used to filter the Set.\n * @returns A new Set containing only the elements that satisfy the filter function.\n */\nexport function filterSet<T>(set: Set<T>, filterFunction: (item: T) => boolean): Set<T> {\n const filteredSet = new Set<T>();\n for (const item of set) {\n if (filterFunction(item)) {\n filteredSet.add(item);\n }\n }\n return filteredSet;\n}\n\nexport function firstFromSet<T = any>(set: Set<T>): T | undefined {\n return set?.values().next().value;\n}\n\n/**\n * Gets the last element of a Set.\n * @param set The Set from which to retrieve the last element.\n * @returns The last element of the Set, or undefined if the Set is empty.\n */\nexport function lastFromSet<T>(set: Set<T>): T | undefined {\n let lastElement: T | undefined = undefined;\n for (const item of set) {\n lastElement = item;\n }\n return lastElement;\n}\n","import { CanvasTextMetrics, FederatedEvent, Point, Text } from 'pixi.js';\n\nexport function getNearestCharacterIndex(text: Text, e: FederatedEvent): number {\n const metrics = CanvasTextMetrics.measureText(text.text, text.style);\n const lines = metrics.lines;\n const lineHeight = metrics.lineHeight;\n const position = text.toLocal(new Point(e.pageX, e.pageY));\n\n let closestIndex = 0;\n let minDistance = Infinity;\n\n let currentIndex = 0;\n for (let i = 0; i < lines.length; i++) {\n const lineText = lines[i];\n for (let j = 0; j <= lineText.length; j++) {\n const subText = lineText.substring(0, j);\n const lineMetrics = CanvasTextMetrics.measureText(subText, text.style);\n const charX = lineMetrics.width;\n const charY = i * lineHeight;\n const distance = Math.hypot(charX - position.x, charY - position.y);\n if (distance < minDistance) {\n minDistance = distance;\n closestIndex = currentIndex + j;\n }\n }\n currentIndex += lineText.length;\n }\n\n return closestIndex;\n}\n","// This file is auto-generated during the build process.\nexport const version: string = '0.1.0';\nexport const pixiVersion: string = '8.19.0';\n","import { pixiVersion, version } from './version';\n// https://www.asciiart.eu/image-to-ascii\nconst ascii = ` ........ ..... ............ ............. ........... \n ............. ....... ................ ............. .............. \n .............. ......... ............... ............. .............. \n ..... ........... .............. ............ .............. \n ..... ...... ...... .............. ............. ............. \n .............. ...... ..... ............ ............. ..... ...... \n ................... ..... ..... ............. ..... ....... \n ................ .......... ............. ..... ..... `;\n\nexport function sayHello() {\n const hello = `\\n${ascii}\\n\\n v${version} | %cPixi.js v${pixiVersion} %c| %chttps://github.com/anthonysapp/caper\\n\\n`;\n console.log(\n hello,\n 'color: #E91E63; font-weight: 600;',\n 'color: inherit;',\n 'color: #00BCD4; text-decoration: underline;',\n );\n}\n","export function checkWebGL() {\n if (typeof document === 'undefined') {\n return;\n }\n\n const checkerCanvas = document.createElement('canvas');\n const gl = checkerCanvas.getContext('webgl') || checkerCanvas.getContext('experimental-webgl');\n\n if (!gl) {\n console.error('Your browser does not support WebGL.');\n }\n}\n","import { Container } from './Container';\n\n/**\n * Optional convenience base class for entities discovered from\n * `src/entities/`. The factory system (`this.add.entity(id, props)`) does\n * **not** require entities to extend this class — any class with a\n * single-options-object constructor works. `Entity<Props>` just gives you\n * typed prop storage and a conventional lifecycle for free.\n *\n * **Lifecycle** (inherited from Container):\n *\n * 1. `constructor(props)` — props are stashed on `this.props` before\n * Container's constructor runs. Don't reference `this.app` yet.\n * 2. **addChild** — the factory auto-adds the instance to the calling\n * Container; Pixi emits an `added` event.\n * 3. `added()` — override this to build the display tree using\n * `this.props`. Safe to use `this.app`, `this.add.*`, and any asset.\n * Runs after construction, after stage attachment.\n *\n * @example\n * ```ts\n * import { defineEntity, Entity } from '@caperjs/core';\n *\n * type ActorProps = { color?: number; x?: number; y?: number };\n *\n * export const entity = defineEntity({ id: 'actor' });\n *\n * export default class Actor extends Entity<ActorProps> {\n * added() {\n * this.x = this.props.x ?? 0;\n * this.y = this.props.y ?? 0;\n * this.add.graphics().circle(0, 0, 50).fill(this.props.color ?? 0xffffff);\n * }\n * }\n * ```\n *\n * Then from a scene:\n * ```ts\n * this.add.entity('actor', { color: 0xff0000, x: 50, y: 100 });\n * ```\n */\nexport class Entity<Props = void> extends Container {\n /** Props passed into the factory call. Populated before `added()` fires. */\n public readonly props: Props;\n\n constructor(props?: Props) {\n super();\n this.props = (props ?? ({} as Props)) as Props;\n }\n}\n","import { Ticker } from 'pixi.js';\nimport { PauseConfig } from '../core';\nimport { type AppTypeOverrides, type AssetTypeOverrides, Size } from '../utils';\nimport type { IContainer } from './Container';\nimport { Container } from './Container';\n\ntype AppScenes = AppTypeOverrides['Scenes'];\n\ntype SceneAssetsToLoad = {\n assets?: (string | { alias: string; src: string | string[] })[];\n bundles?: AssetTypeOverrides['Bundles'] | AssetTypeOverrides['Bundles'][];\n};\n\nexport type SceneAssets = {\n preload?: SceneAssetsToLoad;\n background?: SceneAssetsToLoad;\n autoUnload?: boolean;\n};\n\nexport type ScenePlugins = AppTypeOverrides['Plugins'][];\n\nexport type SceneDebug = {\n label?: string;\n group?: string;\n order?: number;\n};\n\nexport type SceneConfig = {\n id?: string;\n dynamic?: boolean;\n active?: boolean;\n assets?: SceneAssets;\n plugins?: ScenePlugins;\n debug?: SceneDebug;\n};\n\nexport interface IScene extends IContainer {\n id: AppScenes;\n label?: string;\n assets?: SceneAssets;\n autoUnloadAssets?: boolean;\n\n enter(): Promise<any>;\n\n exit(): Promise<any>;\n\n initialize(): Promise<void> | void;\n\n start(): Promise<void> | void;\n\n onPause(config: PauseConfig): void;\n\n onResume(config: PauseConfig): void;\n}\n\nexport interface SceneListItem {\n id: string;\n path: string;\n scene: () => Promise<new () => IScene> | IScene;\n debug?: {\n label?: string;\n group?: string;\n };\n assets?: SceneAssets;\n plugins?: ScenePlugins;\n autoUnloadAssets: boolean;\n}\n\n/**\n * Base class for all scenes in a Caper app. A scene is a self-contained\n * unit of game state and display — start screen, level, menu, etc.\n *\n * **Lifecycle order** (per scene load):\n *\n * 1. `constructor` — instantiated by the SceneManager. Don't reference\n * `this.app` here; it's not yet attached to the stage.\n * 2. **Assets load** — anything declared in `assets.preload.bundles` is\n * fetched before `initialize` runs. Background bundles are kicked\n * off in parallel and may complete after.\n * 3. `initialize()` — build the display tree. The scene is on the stage\n * but not yet animated in. Safe to use `this.app`, `this.add.*`,\n * and any preloaded asset.\n * 4. `enter()` — animate the scene in. Override to return a promise /\n * tween / timeline; the manager awaits it before calling `start`.\n * 5. `start()` — fired after `enter` resolves. Begin per-frame work,\n * timers, signal connections, gameplay loops.\n * 6. `update(ticker)` — called every frame while the scene is active.\n * Read `ticker.deltaMS` for frame timing.\n * 7. `resize(size)` — called on viewport resize. Re-layout here.\n * 8. `onPause(config)` / `onResume(config)` — called when the app pauses\n * or resumes. Use to halt/restart non-display work (audio, network).\n * 9. `exit()` — animate the scene out. Awaited before `destroy`.\n * 10. `destroy()` — tear down. The base implementation removes the\n * ticker callback and destroys all children — call `super.destroy()`.\n *\n * Scenes are **discovered automatically** by the Vite plugin walking\n * `src/scenes/`. Annotate the file with `defineScene({ id, assets })`\n * (or individual `export const id` / `export const assets`) to give the\n * scene a stable id and declare its asset bundles.\n *\n * @example\n * ```ts\n * import { defineScene, Scene } from '@caperjs/core';\n *\n * export const scene = defineScene({\n * id: 'menu',\n * assets: { preload: { bundles: ['ui'] } },\n * });\n *\n * export default class MenuScene extends Scene {\n * initialize() {\n * this.add.text({ text: 'Play', anchor: 0.5 });\n * }\n * start() {\n * // begin gameplay loop\n * }\n * destroy() {\n * super.destroy();\n * }\n * }\n * ```\n */\nexport class Scene<Props = void> extends Container implements IScene {\n public readonly id: string;\n public autoUnloadAssets: boolean = false;\n\n /**\n * Runtime props passed via `app.scenes.load(id, props)`. Populated by\n * `SceneManagerPlugin._createCurrentScene` after construction and before\n * `initialize()` runs, so scene authors can read them safely from any\n * lifecycle hook.\n *\n * Subclasses declare the shape via the generic parameter:\n *\n * @example\n * ```ts\n * class LevelScene extends Scene<{ levelId: number; difficulty: 'easy' | 'hard' }> {\n * async start() {\n * const { levelId } = this.props;\n * }\n * }\n * ```\n *\n * For scenes that don't need props, use the default `Scene<void>` (no\n * generic parameter) — `app.scenes.load('menu')` takes no second arg.\n */\n public props!: Props;\n\n protected _animationContext: string;\n public get animationContext(): string {\n return this._animationContext ?? `__scene_${this.id}`;\n }\n public set animationContext(value: string) {\n this._animationContext = value;\n }\n\n constructor() {\n super({ autoResize: true, autoUpdate: true, priority: 'highest' });\n }\n\n /**\n * The assets to load for the scene\n * @private\n * @type {AssetLoadingOptions}\n * @example\n * ```ts\n * assets: {\n * preload: {\n * assets: ['path/to/asset.png'],\n * bundles: ['bundle1', 'bundle2'],\n * },\n * background: {\n * assets: ['path/to/asset.png'],\n * bundles: ['bundle1', 'bundle2'],\n * },\n * }\n * ```\n */\n private _assets: SceneAssets;\n\n get assets(): SceneAssets {\n return this._assets;\n }\n\n set assets(value: SceneAssets) {\n this._assets = value;\n }\n\n /**\n * Build the scene's display tree. Called once after preload assets\n * have loaded and the scene has been added to the stage, but **before**\n * `enter()` animates it in. Safe to use `this.app`, `this.add.*`, and\n * any asset declared in `assets.preload`.\n *\n * Override to construct sprites, text, containers, layouts. Don't put\n * gameplay loops here — that's `start()`.\n *\n * Can be sync or async; the manager awaits the return value before\n * calling `enter`.\n */\n public initialize(): Promise<void> | void;\n\n public async initialize(): Promise<void> {}\n\n /**\n * Animate the scene in. Called after `initialize()` resolves. The\n * manager awaits the returned promise before calling `start()`, so\n * return a tween / timeline / promise to gate the entry on it.\n *\n * Default implementation resolves immediately (no animation).\n *\n * @returns A promise that resolves when the entry animation completes.\n */\n public enter(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Animate the scene out. Called when the SceneManager is unloading\n * this scene. Awaited before `destroy()` runs.\n *\n * Default implementation resolves immediately (no animation).\n *\n * @returns A promise that resolves when the exit animation completes.\n */\n public exit(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Begin per-frame work. Called once after `enter()` resolves; this is\n * where gameplay loops, timers, signal connections, and any work that\n * shouldn't start until the scene is fully visible should live.\n *\n * Override to start tickers, subscribe to input, kick off gameplay.\n * Don't build the display tree here — that's `initialize()`.\n *\n * Can be sync or async.\n */\n public start(): Promise<void> | void;\n\n public async start(): Promise<void> {}\n\n /**\n * Per-frame update hook. Called every tick while the scene is active,\n * after `start()` has resolved. Use `ticker.deltaMS` for time-based\n * motion that's framerate-independent.\n *\n * The base implementation is a no-op; override to drive game logic.\n * The base `destroy()` removes this from the ticker — call\n * `super.destroy()` if you override destroy.\n *\n * @param ticker The Pixi ticker; provides `deltaMS`, `deltaTime`, etc.\n */\n public update(ticker?: Ticker) {\n void ticker;\n }\n\n /**\n * Re-layout on viewport resize. Called whenever the host element /\n * window size changes. Use to reposition or rescale display elements\n * relative to the new viewport size.\n *\n * @param size New viewport dimensions.\n * @override\n */\n public resize(size?: Size): void {\n void size;\n }\n\n /**\n * Tear down the scene. The base implementation removes this scene\n * from the ticker (so `update` stops firing) and destroys all child\n * display objects. **Always call `super.destroy()`** if you override\n * — otherwise the ticker callback leaks.\n *\n * Override to clean up listeners, signal connections, timers, network\n * subscriptions, or anything else not handled by Pixi's destroy.\n */\n public destroy() {\n this.app.ticker.remove(this.update);\n super.destroy({ children: true });\n }\n\n /**\n * Called when the application is paused. Use to halt non-display\n * work — audio, network polling, gameplay timers. Display state\n * stays on screen; only logic should pause.\n *\n * @param config Pause options (e.g. which subsystems to pause).\n */\n public onPause(config: PauseConfig): void {\n void config;\n }\n\n /**\n * Called when the application resumes from a pause. Use to restart\n * whatever was halted in `onPause`.\n *\n * @param config Resume options.\n */\n public onResume(config: PauseConfig): void {\n void config;\n }\n}\n","import { Sprite, Ticker } from 'pixi.js';\nimport { type Size } from '../utils';\nimport { Container } from './Container';\n\nexport interface ISceneTransition extends Container {\n initialized: boolean;\n progress: number;\n active: boolean;\n destroy(): void;\n enter(): Promise<any> | void;\n exit(): Promise<any> | void;\n initialize(): void;\n}\n\nexport class SceneTransition extends Container {\n public initialized: boolean = false;\n protected __background: Sprite;\n\n private _active: boolean = false;\n\n get active(): boolean {\n return this._active;\n }\n\n set active(value: boolean) {\n this._active = value;\n }\n\n private _progress: number;\n\n get progress(): number {\n return this._progress;\n }\n\n set progress(value: number) {\n this._progress = value;\n }\n\n constructor(autoUpdate: boolean = false) {\n super({ autoResize: true, autoUpdate: false, priority: -9999 });\n\n if (autoUpdate) {\n this.app.ticker.add(this._update);\n }\n\n this.addSignalConnection(\n this.app.assets.onLoadStart.connect(this.handleLoadStart),\n this.app.assets.onLoadProgress.connect(this.handleLoadProgress),\n this.app.assets.onLoadProgress.connect(this.handleLoadComplete),\n );\n }\n\n public initialize(): void;\n public async initialize(): Promise<void> {\n return Promise.resolve();\n }\n\n public resize(size: Size): void {\n void size;\n }\n\n public destroy(): void {\n this.app.ticker.remove(this._update);\n this.initialized = false;\n this._active = false;\n this._progress = 0;\n super.destroy();\n }\n\n /**\n * Called to animate the scene in\n * @returns {Promise<void>}\n */\n public enter(): void;\n public async enter(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Called to animate the scene out\n * @returns {Promise<void>}\n */\n public exit(): void;\n public async exit(): Promise<any> {\n return Promise.resolve();\n }\n\n protected handleLoadStart() {\n // signifies the preloading phase has started for the new scene\n }\n\n protected handleLoadProgress(progress: number) {\n // the preloading progress for the loading scene\n this._progress = progress;\n }\n\n protected handleLoadComplete() {\n // signifies the preloading phase is complete for the new scene\n }\n\n // check if initialized and active before calling update\n // this way we're sure in the case of a Splash sccreen, all the assets are loaded and the scene is initialized\n private _update(ticker: Ticker) {\n if (this.active && this.initialized) {\n this.update(ticker);\n }\n }\n}\n","import { Container, Point } from 'pixi.js';\nimport { IApplication } from '../core';\nimport { Application } from '../core/Application';\nimport type { KeyboardEventDetail } from '../plugins';\nimport { Signal } from '../signals';\nimport type { ContainerLike, PointLike } from '../utils';\nimport { bindAllMethods, resolvePointLike } from '../utils';\n\ntype CameraConfig = {\n container: Container;\n minX: number;\n maxX: number;\n minY: number;\n maxY: number;\n viewportWidth: number;\n viewportHeight: number;\n worldWidth: number;\n worldHeight: number;\n target: ContainerLike | null;\n targetPivot: Point;\n lerp: number;\n};\n\n// require container to be set\ntype OptionalCameraConfig = Partial<CameraConfig>;\ntype RequiredCameraConfig = Required<Pick<CameraConfig, 'container'>>;\ntype CustomCameraConfig = OptionalCameraConfig & RequiredCameraConfig;\n\nexport interface ICamera {\n onZoom: Signal<(camera?: ICamera) => void>;\n onZoomComplete: Signal<(camera?: ICamera) => void>;\n container: Container;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n viewportWidth: number;\n viewportHeight: number;\n worldWidth: number;\n worldHeight: number;\n readonly targetPivot: Point;\n readonly targetScale: Point;\n readonly zooming: boolean;\n readonly zoomLerp: number;\n readonly lerp: number;\n readonly target: ContainerLike | null;\n readonly followOffset: Point;\n app: IApplication;\n\n follow(target: ContainerLike, offset: PointLike): void;\n\n pan(deltaX: number, deltaY: number): void;\n\n zoom(scale: number, lerp?: number): void;\n\n update(): void;\n}\n\nexport class Camera extends Container implements ICamera {\n public onZoom = new Signal<(camera?: ICamera) => void>();\n public onZoomComplete = new Signal<(camera?: ICamera) => void>();\n public container: Container;\n public minX: number = 0;\n public minY: number = 0;\n public maxX: number;\n public maxY: number;\n public viewportWidth: number;\n public viewportHeight: number;\n public worldWidth: number;\n public worldHeight: number;\n\n constructor(public config: CustomCameraConfig) {\n super({ isRenderGroup: true });\n bindAllMethods(this);\n if (config) {\n this.container = config.container;\n this.addChild(this.container);\n if (config.minX) {\n this.minX = config.minX;\n }\n if (config.maxX) {\n this.maxX = config.maxX;\n }\n if (config.minY) {\n this.minY = config.minY;\n }\n this.viewportWidth = config.viewportWidth ?? this.app.size.width;\n this.viewportHeight = config.viewportHeight ?? this.app.size.width;\n this.worldWidth = config.worldWidth ?? this.viewportWidth;\n this.worldHeight = config.worldHeight ?? this.viewportHeight;\n this.maxX = config.maxX ?? this.worldWidth - this.viewportWidth;\n this.maxY = config.maxY ?? this.worldHeight - this.viewportHeight;\n }\n\n this._targetPivot.set(this.viewportWidth * 0.5, this.viewportHeight * 0.5);\n if (config.target) {\n this.target = config.target;\n }\n this._lerp = 1;\n this.update();\n if (config.lerp) {\n this.lerp = config.lerp;\n }\n return this;\n }\n\n protected _zooming: boolean = false;\n\n get zooming(): boolean {\n return this._zooming;\n }\n\n protected _zoomLerp: number = 0.1;\n\n get zoomLerp(): number {\n return this._zoomLerp;\n }\n\n protected _targetPivot: Point = new Point(0, 0);\n\n get targetPivot(): Point {\n return this._targetPivot;\n }\n\n protected _targetScale: Point = new Point(1, 1);\n\n get targetScale(): Point {\n return this._targetPivot;\n }\n\n private _lerp: number = 0;\n\n get lerp(): number {\n return this._lerp;\n }\n\n set lerp(value: number) {\n // if the value is less than 0 or greater than 1, clamp it to the range [0, 1], and log an error\n if (value < 0 || value > 1) {\n throw new Error('Camera lerp value must be in the range [0, 1]');\n }\n this._lerp = Math.max(0, Math.min(value, 1));\n }\n\n protected _target: ContainerLike | null = null;\n\n get target(): ContainerLike | null {\n return this._target;\n }\n\n set target(value: ContainerLike | null) {\n this._target = value;\n if (this._target) {\n this.focusOn(this._target);\n }\n }\n\n protected _followOffset: Point = new Point(0, 0);\n get followOffset(): Point {\n return this._followOffset;\n }\n\n set followOffset(value: PointLike) {\n this._followOffset = resolvePointLike(value, true);\n }\n\n get app(): IApplication {\n return Application.getInstance();\n }\n\n follow(target: ContainerLike, offset?: PointLike) {\n if (!offset) {\n offset = { x: 0, y: 0 };\n }\n this.followOffset = offset;\n this.target = target;\n }\n\n pan(deltaX: number, deltaY: number) {\n let newPivotX = this.pivot.x + deltaX;\n let newPivotY = this.pivot.y + deltaY;\n\n // Clamp pivot to min and max values\n newPivotX = Math.max(this.minX, Math.min(newPivotX, this.maxX));\n newPivotY = Math.max(this.minY, Math.min(newPivotY, this.maxY));\n\n this._targetPivot.set(newPivotX, newPivotY);\n }\n\n zoom(scale: number, lerp: number = 0.1) {\n this._zoomLerp = lerp;\n this._zooming = true;\n this._targetScale.set(scale, scale);\n }\n\n update() {\n this.updateZoom();\n if (this._target) {\n this.focusOn(this._target);\n }\n this.updatePosition(this._zooming);\n if (\n this._zooming &&\n Math.abs(this.scale.x - this._targetScale.x) < 0.001 &&\n Math.abs(this.scale.y - this._targetScale.y) < 0.001\n ) {\n this.onZoom.emit(this);\n this._zooming = false;\n this.scale.set(this._targetScale.x, this._targetScale.y);\n this.onZoomComplete.emit(this);\n } else if (this._zooming) {\n this.onZoom.emit(this);\n }\n }\n\n private focusOn(entity: ContainerLike) {\n // Get the global position of the entity and convert it to the local position within the container.\n const globalPosition = entity.getGlobalPosition();\n const spritePosition = this.toLocal(globalPosition);\n\n const posXModifier = this.position.x / this.scale.x - this.viewportWidth / 2;\n const posYModifier = this.position.y / this.scale.y - this.viewportHeight / 2;\n\n const offsetX = this.followOffset.x / this.scale.x;\n const offsetY = this.followOffset.y / this.scale.y;\n\n this._targetPivot.x = (spritePosition.x * this.scale.x + this.viewportWidth / 2) * (1 / this.scale.x) + offsetX;\n\n const tMinX = this.viewportWidth / this.scale.x / 2 + posXModifier + this.minX - offsetX;\n const tMaxX = this.worldWidth - this.viewportWidth / this.scale.x / 2 + posXModifier + this.maxX + offsetX;\n\n if (this._targetPivot.x < tMinX) {\n this._targetPivot.x = tMinX;\n } else if (this._targetPivot.x > tMaxX) {\n this._targetPivot.x = tMaxX;\n }\n\n this._targetPivot.y = (spritePosition.y * this.scale.y + this.viewportHeight / 2) * (1 / this.scale.y) + offsetY;\n\n const tMinY = this.viewportHeight / this.scale.y / 2 + posYModifier + this.minY - offsetY;\n const tMaxY = this.worldHeight - this.viewportHeight / this.scale.y / 2 + posYModifier + this.maxY - offsetY;\n\n if (this._targetPivot.y < tMinY) {\n this._targetPivot.y = tMinY;\n } else if (this._targetPivot.y > tMaxY) {\n this._targetPivot.y = tMaxY;\n }\n }\n\n private updateZoom() {\n const currentScaleX = this.scale.x;\n const currentScaleY = this.scale.y;\n\n const interpolatedScaleX = currentScaleX + this._zoomLerp * (this._targetScale.x - currentScaleX);\n const interpolatedScaleY = currentScaleY + this._zoomLerp * (this._targetScale.y - currentScaleY);\n\n this.scale.set(Math.max(0, interpolatedScaleX), Math.max(0, interpolatedScaleY));\n }\n\n private updatePosition(skipLerp: boolean = false) {\n if (this.lerp > 0 && !skipLerp) {\n // Current pivot positions\n const currentPivotX = this.pivot.x;\n const currentPivotY = this.pivot.y;\n\n // Calculate interpolated pivot positions\n const interpolatedPivotX = currentPivotX + this.lerp * (this._targetPivot.x - currentPivotX);\n const interpolatedPivotY = currentPivotY + this.lerp * (this._targetPivot.y - currentPivotY);\n\n // Set the pivot to the interpolated position to smooth out the camera movement\n this.pivot.set(interpolatedPivotX, interpolatedPivotY);\n } else {\n this.pivot.set(this._targetPivot.x, this._targetPivot.y);\n }\n\n this.position.set(this.viewportWidth / 2, this.viewportHeight / 2);\n }\n}\n\nexport class CameraController {\n private dragging: boolean = false;\n private previousPointerPosition: Point | null = null;\n\n constructor(\n public camera: Camera,\n public interactiveArea: Container,\n ) {\n bindAllMethods(this);\n this.camera = camera;\n this.interactiveArea = interactiveArea;\n this.app.keyboard.onKeyDown().connect(this.handleKeyDown);\n // Keyboard events\n\n // Mouse and touch events\n this.interactiveArea.on('pointerdown', this.onPointerDown.bind(this));\n this.interactiveArea.on('pointermove', this.onPointerMove.bind(this));\n this.app.stage.on('pointerup', this.onPointerUp.bind(this));\n this.app.stage.on('pointerupoutside', this.onPointerUp.bind(this));\n\n // Touch events equivalent\n this.interactiveArea.on('touchstart', this.onPointerDown.bind(this));\n this.interactiveArea.on('touchmove', this.onPointerMove.bind(this));\n this.interactiveArea.on('touchend', this.onPointerUp.bind(this));\n }\n\n get app(): IApplication {\n return Application.getInstance();\n }\n\n destroy() {\n // Mouse and touch events\n this.interactiveArea.removeAllListeners();\n this.app.stage.off('pointerup', this.onPointerUp.bind(this));\n this.app.stage.off('pointerupoutside', this.onPointerUp.bind(this));\n }\n\n private handleKeyDown(detail: KeyboardEventDetail) {\n const panSpeed = 10; // Adjust pan speed as necessary\n const zoomFactor = 1.1; // Adjust zoom factor as necessary\n\n switch (detail.event.key) {\n case 'ArrowUp':\n this.camera.pan(0, -panSpeed);\n break;\n case 'ArrowDown':\n this.camera.pan(0, panSpeed);\n break;\n case 'ArrowLeft':\n this.camera.pan(-panSpeed, 0);\n break;\n case 'ArrowRight':\n this.camera.pan(panSpeed, 0);\n break;\n case '+':\n this.camera.zoom(zoomFactor);\n break;\n case '-':\n this.camera.zoom(1 / zoomFactor);\n break;\n }\n }\n\n private onPointerDown(event: MouseEvent | TouchEvent) {\n this.dragging = true;\n this.previousPointerPosition = this.getEventPosition(event);\n }\n\n private onPointerMove(event: MouseEvent | TouchEvent) {\n if (!this.dragging || !this.previousPointerPosition) return;\n\n const currentPosition = this.getEventPosition(event);\n const deltaX = currentPosition.x - this.previousPointerPosition.x;\n const deltaY = currentPosition.y - this.previousPointerPosition.y;\n\n this.camera.pan(deltaX, deltaY);\n this.previousPointerPosition = currentPosition;\n }\n\n private onPointerUp() {\n this.dragging = false;\n this.previousPointerPosition = null;\n }\n\n private getEventPosition(event: MouseEvent | TouchEvent): Point {\n if (event instanceof TouchEvent) {\n return new Point(event.touches[0].clientX, event.touches[0].clientY);\n } else {\n return new Point(event.clientX, event.clientY);\n }\n }\n}\n","import {\n Bounds,\n CanvasTextMetrics,\n FederatedEvent,\n FederatedPointerEvent,\n Graphics,\n Container as PIXIContainer,\n Rectangle,\n Sprite,\n Text,\n Texture,\n} from 'pixi.js';\n\nimport { Focusable, Interactive, TextProps, WithSignals } from '../mixins';\n\nimport {\n EaseString,\n ensurePadding,\n getNearestCharacterIndex,\n isAndroid,\n isMobile,\n isTouch,\n Logger,\n Padding,\n PointLike,\n resolvePointLike,\n} from '../utils';\n\nimport { gsap } from 'gsap';\nimport { Container } from '../display';\nimport { Signal } from '../signals';\n\n/**\n * Options for styling the input background\n * @interface BgStyleOptions\n */\nexport type BgStyleOptions = {\n /** Border radius of the input background */\n radius: number;\n /** Fill style for the background */\n fill: { color?: number; alpha?: number };\n /** Stroke style for the background border */\n stroke: { width?: number; color?: number; alpha?: number };\n};\n\n/**\n * Color configuration options\n * @interface ColorOptions\n */\nexport type ColorOptions = {\n /** Color in hexadecimal format */\n color: number;\n /** Alpha transparency value (0-1) */\n alpha: number;\n};\n\n/**\n * Placeholder text configuration\n * @interface PlaceholderOptions\n */\nexport type PlaceholderOptions = {\n /** Text to display as placeholder */\n text: string;\n};\n\n/**\n * Focus overlay configuration for mobile/touch interactions\n * @interface FocusOverlayOptions\n * @example\n * ```typescript\n * const overlaySettings = {\n * activeFilter: ['mobile', 'touch'],\n * marginTop: 60,\n * scale: 2.5,\n * backing: { active: true, color: 0x0 }\n * };\n * ```\n */\nexport type FocusOverlayOptions = {\n /** Enable overlay for specific platforms */\n mobile: boolean;\n touch: boolean;\n desktop: boolean;\n /** Custom filter for when to show overlay */\n activeFilter?: boolean | (() => boolean) | ('mobile' | 'touch' | 'desktop')[];\n /** Scale factor for the overlay */\n scale: number;\n /** Top margin for the overlay */\n marginTop: number;\n /** Backing configuration */\n backing: {\n active: boolean;\n options: Partial<ColorOptions>;\n };\n};\n\n/**\n * Extended placeholder options with animation and positioning\n * @interface ExtraPlaceholderOptions\n * @example\n * ```typescript\n * const placeholderConfig = {\n * positionOnType: 'top',\n * offsetOnType: { x: 0, y: -20 },\n * scaleOnType: { x: 0.8, y: 0.8 },\n * animationOnType: {\n * duration: 0.3,\n * ease: 'sine.out',\n * tint: 0x666666,\n * alpha: 0.5\n * }\n * };\n * ```\n */\ntype ExtraPlaceholderOptions = {\n /** Position of placeholder when typing */\n positionOnType: 'top' | 'bottom';\n /** Offset from original position when typing */\n offsetOnType: PointLike;\n /** Scale factor when typing */\n scaleOnType: PointLike;\n /** Animation configuration when typing */\n animationOnType: {\n duration: number;\n ease: EaseString;\n tint: number;\n alpha: number;\n };\n};\n\n/**\n * Main configuration options for the Input component\n * @interface InputOptions\n * @example\n * ```typescript\n * const input = new Input({\n * value: 'Initial value',\n * type: 'text',\n * minWidth: 400,\n * padding: [12, 15],\n * placeholder: {\n * text: 'Enter text...',\n * color: 0x666666\n * },\n * bg: {\n * radius: 10,\n * stroke: { width: 2, color: 0x000000 }\n * },\n * focusOverlay: {\n * activeFilter: ['mobile', 'touch'],\n * scale: 2.5\n * }\n * });\n * ```\n */\nexport interface InputOptions extends Partial<TextProps> {\n /** Initial value of the input */\n value: string;\n /** Input type (text, password, number, etc.) */\n type: 'text' | 'password' | 'number' | 'email' | 'tel' | 'url';\n /** Whether the input width is fixed */\n fixed: boolean;\n /** Pattern for input validation */\n pattern: string;\n /** Enable debug mode */\n debug: boolean;\n /** Minimum width of the input */\n minWidth: number;\n /** Padding configuration */\n padding: Padding;\n /** Maximum length of input */\n maxLength?: number;\n /** Whether to blur on Enter key */\n blurOnEnter: boolean;\n /** Custom regex for validation */\n regex?: RegExp;\n /** Background style configuration */\n bg: Partial<BgStyleOptions>;\n /** Placeholder configuration */\n placeholder: Partial<PlaceholderOptions & ColorOptions & ExtraPlaceholderOptions>;\n /** Selection highlight configuration */\n selection: Partial<ColorOptions>;\n /** Caret configuration */\n caret: Partial<ColorOptions>;\n /** Error state styling */\n error?: {\n input?: {\n fill?: number;\n };\n bg?: Partial<Omit<BgStyleOptions, 'stroke'>>;\n };\n /** Focus overlay configuration */\n focusOverlay: Partial<FocusOverlayOptions>;\n}\n\nexport interface InputProps extends Omit<InputOptions, 'padding'> {\n padding: PointLike | Padding | number[] | number;\n}\n\nexport type InputDetail = {\n value: string;\n input: Input;\n domElement: HTMLInputElement;\n};\n\nconst defaultOptions: InputOptions = {\n value: '',\n type: 'text',\n fixed: true,\n pattern: '',\n debug: false,\n minWidth: 200,\n padding: { top: 0, left: 0, bottom: 0, right: 0 },\n blurOnEnter: true,\n style: {\n fontFamily: 'Arial',\n fill: '#000000',\n fontSize: 20,\n fontWeight: 'bold',\n },\n bg: {\n radius: 5,\n fill: { color: 0xffffff },\n stroke: { width: 1, color: 0x0 },\n },\n placeholder: {},\n selection: { color: 0x00ff00 },\n caret: {\n color: 0x0,\n alpha: 0.8,\n },\n focusOverlay: {\n activeFilter: false,\n scale: 1,\n marginTop: 60,\n },\n};\n\nconst AVAILABLE_TYPES = ['text', 'password', 'number', 'email', 'tel', 'url'];\n\n/**\n * A highly customizable input component with mobile/touch support\n * @class Input\n * @extends Focusable(Interactive(WithSignals(Container)))\n *\n * @example\n * ```typescript\n * // Basic text input\n * const basicInput = new Input({\n * minWidth: 400,\n * placeholder: { text: 'Enter text' },\n * padding: [12, 15]\n * });\n *\n * // Password input with validation\n * const passwordInput = new Input({\n * type: 'password',\n * minWidth: 400,\n * placeholder: { text: 'Enter password' },\n * maxLength: 20,\n * regex: /^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$/\n * });\n *\n * // Phone number input with validation\n * const phoneInput = new Input({\n * type: 'tel',\n * regex: /^1?-?\\(?([2-9][0-9]{2})\\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/,\n * error: {\n * input: { fill: 0xff0000 },\n * bg: { fill: 0xf5e0df }\n * }\n * });\n * ```\n */\nexport class Input extends Focusable(Interactive(WithSignals(Container))) {\n /**\n * Emitted when the Enter key is pressed\n * @event onEnter\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onEnter: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Emitted when the input value changes\n * @event onChange\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onChange: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Emitted when validation fails\n * @event onError\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onError: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Input configuration options\n * @type {InputOptions}\n */\n public options: InputOptions;\n\n /**\n * Background graphics container\n * @type {Graphics}\n */\n public bg: Graphics;\n\n /**\n * Caret (cursor) container\n * @type {PIXIContainer}\n */\n public caret: PIXIContainer;\n\n /**\n * Text input container\n * @type {Text}\n */\n public input: Text;\n\n /**\n * Placeholder text container\n * @type {Text}\n */\n public placeholder: Text;\n\n /**\n * Current error state\n * @type {boolean}\n */\n public error: boolean;\n\n // Protected properties\n protected cursorAnimation: gsap.core.Tween;\n protected domElement: HTMLInputElement;\n protected selectionGraphics: Graphics;\n protected cloneOverlay: Input;\n protected overlayBacking: Sprite;\n\n // Private properties\n private _focusTimer: any;\n private _pointerDownTimer: any;\n private _inner: Container;\n private _inputContainer: Container;\n private _placeholderContainer: Container;\n private _mask: Graphics;\n private _lastWidth: number = 0;\n private _lastHeight: number = 0;\n private _placeholderPositioned: boolean = false;\n private _placeholderAnimating: boolean = false;\n private _caretPosition: number = -1;\n private _selectionRect: Rectangle | null;\n private _regex: RegExp;\n private _value: string = '';\n\n constructor(\n options: Partial<InputProps>,\n public isClone: boolean = false,\n public clone: Input | null = null,\n ) {\n super({ autoUpdate: true, autoResize: !isClone });\n\n this.options = {\n ...defaultOptions,\n ...options,\n style: {\n ...defaultOptions.style,\n ...(options?.style ?? {}),\n },\n padding: ensurePadding(options.padding ?? defaultOptions.padding),\n bg: {\n ...defaultOptions.bg,\n ...(options.bg ?? {}),\n },\n focusOverlay: {\n ...defaultOptions.focusOverlay,\n ...(options.focusOverlay ?? {}),\n },\n };\n\n if (this.options.layout && typeof this.options.layout === 'object') {\n this.layout = { ...this.options.layout };\n } else {\n this.layout = { transformOrigin: 'top left' };\n }\n\n if (!this.options.placeholder) {\n this.options.placeholder = {\n color: Number(this.options.style?.fill) ?? 0x666666,\n };\n }\n\n this._inner = this.add.container({\n layout: { position: 'relative', top: 0, left: 0, width: '100%', height: '100%' },\n });\n this.addBg();\n\n this._inputContainer = this._inner.add.container({\n y: -2,\n layout: {\n position: 'absolute',\n transformOrigin: 'top left',\n inset: 0,\n width: '100%',\n height: '100%',\n },\n });\n this._placeholderContainer = this._inner.add.container({\n y: -2,\n layout: {\n position: 'absolute',\n inset: 0,\n transformOrigin: 'top left',\n width: '100%',\n height: '100%',\n },\n });\n this._placeholderContainer.eventMode = 'none';\n this.addSelection();\n this.addCaret();\n this.addInput();\n this.addPlaceholder();\n\n this.placeholder.text = this.options.placeholder.text || `Enter ${this.options.type}`;\n\n this.input.eventMode = this.placeholder.eventMode = 'none';\n\n if (isTouch) {\n this.addSignalConnection(this.onInteraction('pointertap').connect(this.handleClick, -1));\n }\n this.addSignalConnection(this.onInteraction('click').connect(this.handleClick, -1));\n\n if (this.options.fixed) {\n const scale = this.isClone ? (this.clone?.options?.focusOverlay?.scale ?? 1) : 1;\n this._mask = this._inner.add\n .graphics()\n .rect(\n 0,\n 0,\n this.bg.width * scale - this.options.padding.left - this.options.padding.right,\n this.bg.height * scale - this.options.padding.top - this.options.padding.bottom,\n )\n .fill({ color: 0x0 });\n this._inputContainer.mask = this._mask;\n }\n }\n\n /**\n * Gets the current caret (cursor) position\n * @readonly\n * @returns {number} The caret position in pixels from the left\n */\n get caretPosition() {\n return this._caretPosition;\n }\n\n /**\n * Gets the current selection rectangle\n * @readonly\n * @returns {Rectangle | null} The selection rectangle or null if no selection\n */\n get selectionRect() {\n return this._selectionRect;\n }\n\n /**\n * Sets the validation regex\n * @param {RegExp} value - The regular expression to use for validation\n */\n set regex(value: RegExp) {\n this._regex = value;\n }\n\n /**\n * Gets whether the current input value is valid\n * @readonly\n * @returns {boolean} True if the input is valid\n */\n get isValid(): boolean {\n let result = false;\n if (this.domElement) {\n if (this._regex) {\n result = this._regex.test(this._value);\n } else {\n if (this.options.type === 'text') {\n return true;\n }\n this.domElement.required = true;\n result = this.domElement.checkValidity();\n this.domElement.required = false;\n }\n }\n return result;\n }\n\n /**\n * Gets the current input value\n * @returns {string} The current value\n */\n public get value() {\n return this._value?.trim() ?? '';\n }\n\n /**\n * Sets the input value\n * @param {string} value - The value to set\n */\n public set value(value: string) {\n if (this.domElement) {\n this.domElement.value = value;\n const event = new Event('input', {\n bubbles: true,\n cancelable: true,\n });\n this.domElement.dispatchEvent(event);\n } else {\n this._value = value;\n this.input.text = value;\n }\n }\n\n /**\n * Resizes the input component\n * Updates the clone overlay position if it exists\n */\n resize() {\n super.resize();\n if (this.cloneOverlay) {\n this._positionCloneOverlay();\n }\n }\n\n /**\n * Redraws the background graphics\n */\n resetBg() {\n this.drawBg();\n }\n\n /**\n * Called when the component is added to the display list\n * Shows the cursor if this is a clone\n */\n added() {\n super.added();\n if (this.isClone) {\n this.showCursor();\n }\n }\n\n /**\n * Handles click/tap events on the input\n * Creates the DOM element and positions the caret\n * @param {FederatedEvent} [e] - The pointer event\n */\n handleClick(e?: FederatedEvent) {\n // check if this was a triggered event from the FocusMnagerPlugin\n if ((e?.originalEvent as unknown as KeyboardEvent)?.key) {\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n const nearestCharacterIndex = e ? getNearestCharacterIndex(this.input, e) : (this.input.text?.length ?? 0);\n this.createDomElement(nearestCharacterIndex);\n // this._focusDomElement(nearestCharacterIndex);\n }\n\n /**\n * Focuses the input\n * Creates the DOM element and shows the cursor\n */\n focusIn() {\n this.handleClick();\n }\n\n _focusDomElement(selection?: number) {\n this._focusTimer = setTimeout(() => {\n this._triggerFocusAndSelection(selection);\n }, 100);\n }\n\n _triggerFocusAndSelection(selection?: number) {\n if (this.domElement) {\n try {\n this.domElement.focus();\n this.domElement.click();\n if (selection === undefined) {\n this.domElement.selectionStart = this.domElement?.value?.length;\n } else {\n this.domElement.setSelectionRange(selection, selection, 'none');\n }\n } catch (e) {\n // nothing\n }\n this._updateCaretAndSelection();\n }\n }\n\n _checkPointerDownOutside(e: FederatedPointerEvent) {\n const pos = this.toLocal(e.data.global);\n if (this.getBounds().rectangle.contains(pos.x, pos.y)) {\n this.focusIn();\n } else {\n this.focusOut();\n }\n }\n\n /**\n * Blurs (unfocuses) the input\n * Removes the DOM element and hides the cursor\n */\n focusOut() {\n this.domElement?.blur();\n }\n\n update() {\n this.bg.x = 0;\n this.bg.y = 0;\n\n // size background\n const bgHeight =\n this.input.getLocalBounds().y +\n this.input.style.fontSize +\n this.options.padding.top +\n this.options.padding.bottom;\n\n const bgWidth = this.options.fixed\n ? this.options.minWidth\n : Math.max(this.options.minWidth, this.input.width) + this.options.padding.left + this.options.padding.right;\n\n // position inputs\n // the 'align' property doesn't affect single line text,\n // so we need to do this manually\n const diff = this.options.minWidth - bgWidth + this.options.padding.left + this.options.padding.right;\n const inputAvailableWidth = bgWidth - this.options.padding.left - this.options.padding.right;\n\n switch (this.input.style.align) {\n case 'center':\n this.input.x = bgWidth / 2 - this.input.width / 2;\n if (!this._placeholderPositioned) {\n this.placeholder.x = bgWidth / 2 - this.placeholder.width / 2;\n }\n this._inner.x = diff >= 0 ? 0 : diff / 2;\n if (this.options.fixed) {\n const inputDiff = this.input.width - inputAvailableWidth;\n if (inputDiff > 0) {\n this.input.x -= inputDiff / 2;\n }\n }\n break;\n case 'right':\n this.input.x = bgWidth - this.options.padding.right - this.input.width;\n if (!this._placeholderPositioned) {\n this.placeholder.x = bgWidth - this.options.padding.right - this.placeholder.width;\n }\n this._inner.x = diff >= 0 ? 0 : diff;\n break;\n default:\n this.input.x = this.options.padding.left;\n if (!this._placeholderPositioned) {\n this.placeholder.x = this.options.padding.left;\n }\n this._inner.x = 0;\n if (this.options.fixed) {\n const inputDiff = this.input.width - inputAvailableWidth;\n if (inputDiff > 0) {\n this.input.x -= inputDiff;\n }\n }\n break;\n }\n\n this.input.y = this.options.padding.top;\n if (!this._placeholderPositioned) {\n this.placeholder.y = this.input.y;\n }\n\n if (this.isClone && this.clone) {\n const cloneScale = this.clone.options?.focusOverlay?.scale ?? 1;\n this.error = this.clone.error;\n this._value = this.clone.input.text;\n this.input.text = this._value;\n this._selectionRect = this.clone.selectionRect!.clone();\n this._selectionRect.x *= cloneScale;\n this._selectionRect.y *= cloneScale;\n this._selectionRect.width *= cloneScale;\n this._selectionRect.height *= cloneScale;\n this._caretPosition = this.clone.caretPosition * cloneScale;\n }\n // position caret\n this.caret.x = this._caretPosition >= 0 ? this.input.x + this._caretPosition : this.input.x + this.input.width + 1;\n this.caret.y = this.input.y - 2;\n this.caret.height = this.input.style.fontSize * 1.15;\n\n // check if value is empty\n if (this.value === '') {\n this.placeholder.visible = true;\n if (!this.isClone && this._placeholderPositioned && !this._placeholderAnimating) {\n this._placeholderAnimating = true;\n const tx = this.input.x;\n const ty = this.input.y;\n if (this.options.placeholder.animationOnType) {\n this.addAnimation([\n gsap.to(this.placeholder, {\n x: tx,\n y: ty,\n tint: 0xffffff,\n alpha: this.options.placeholder.alpha ?? 1,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'sine.in',\n overwrite: true,\n onComplete: () => {\n this._placeholderPositioned = false;\n this._placeholderAnimating = false;\n },\n }),\n gsap.to(this.placeholder.scale, {\n x: 1,\n y: 1,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'sine.out',\n overwrite: true,\n }),\n ]);\n } else {\n this.placeholder.x = tx;\n this.placeholder.y = ty;\n this.placeholder.scale.set(1, 1);\n this._placeholderPositioned = false;\n this._placeholderAnimating = false;\n }\n }\n } else {\n if (!this.isClone && this.options.placeholder.positionOnType) {\n this.placeholder.visible = true;\n if (!this._placeholderPositioned) {\n this._placeholderPositioned = true;\n let tx = this.placeholder.x;\n let ty = this.placeholder.y;\n switch (this.options.placeholder.positionOnType) {\n case 'top':\n ty = this.input.y - this.placeholder.height - this.options.padding.top;\n break;\n case 'bottom':\n ty = this.input.y + this.input.height + this.options.padding.bottom;\n break;\n }\n\n if (this.options.placeholder.offsetOnType) {\n const offset = resolvePointLike(this.options.placeholder.offsetOnType);\n tx += offset.x;\n ty += offset.y;\n }\n\n if (this.options.placeholder.animationOnType) {\n this.addAnimation(\n gsap.to(this.placeholder, {\n x: tx,\n y: ty,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'none',\n tint: this.options.placeholder.animationOnType.tint ?? null,\n alpha: this.options.placeholder.animationOnType.alpha ?? this.options.placeholder.alpha ?? 1,\n overwrite: true,\n }),\n );\n\n if (this.options.placeholder.scaleOnType) {\n const scale = resolvePointLike(this.options.placeholder.scaleOnType);\n this.addAnimation(\n gsap.to(this.placeholder.scale, {\n x: scale.x,\n y: scale.y,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'none',\n overwrite: true,\n }),\n );\n }\n } else {\n this.placeholder.x = tx;\n this.placeholder.y = ty;\n }\n }\n } else {\n this.placeholder.visible = false;\n }\n }\n\n if (this.options.fixed) {\n const scale = this.isClone ? (this.options?.focusOverlay?.scale ?? 1) : 1;\n if (this._mask) {\n this._mask\n .clear()\n .rect(0, 0, (bgWidth - this.options.padding.left - this.options.padding.right) * scale, bgHeight * scale)\n .fill({ color: 0x0 });\n this._mask.position.set(this.options.padding.left * scale, 0);\n }\n }\n\n if (bgWidth !== this._lastWidth) {\n this.drawBg(bgWidth, bgHeight);\n }\n\n if (this._selectionRect) {\n this.drawSelection();\n } else {\n this.selectionGraphics?.clear();\n }\n\n if (this.cloneOverlay) {\n this._positionCloneOverlay();\n }\n }\n\n drawSelection() {\n const rect = this._selectionRect;\n if (!rect) {\n this.selectionGraphics?.clear();\n return;\n }\n this.selectionGraphics?.clear();\n this.selectionGraphics\n .rect(rect.left + this.input.x, this.caret.y, rect.width, this.caret.height)\n .fill({ color: this.options.selection.color });\n }\n\n drawBg(width: number = this._lastWidth, height: number = this._lastHeight) {\n const opts =\n (this.error || (this.isClone && this.clone?.error)) && this.options?.error?.bg\n ? { ...this.options.bg, ...this.options.error.bg }\n : this.options.bg;\n\n this.bg\n .clear()\n .roundRect(0, 0, width, height, opts?.radius ?? 0)\n .fill(opts.fill)\n .stroke({ ...(opts?.stroke || {}), alignment: 0 });\n\n this._lastWidth = width;\n this._lastHeight = height;\n }\n\n destroy() {\n console.log('input destroy', this);\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n\n this.app.stage.off('pointerdown', this._checkPointerDownOutside);\n\n this.hideCursor();\n this.destroyDomElement();\n\n super.destroy();\n }\n\n protected addBg() {\n this.bg = this._inner.add\n .graphics()\n .roundRect(0, 0, 100, 50, this.options?.bg?.radius ?? 0)\n .fill(this.options.bg.fill);\n }\n\n protected addSelection() {\n this.selectionGraphics = this._inputContainer.add.graphics();\n }\n\n protected addCaret() {\n this.caret = this._inputContainer.add.sprite({\n asset: Texture.WHITE,\n width: 3,\n height: 10,\n tint: this.options.caret.color ?? 0x0,\n alpha: 0,\n visible: false,\n });\n }\n\n protected addInput() {\n // Seed the backing value alongside the display text — otherwise an input\n // constructed with `value` reports `''` until the first edit, and\n // update() keeps the placeholder visible over the rendered text.\n this._value = this.options.value ?? '';\n this.input = this._inputContainer.add.text({\n ...this.options,\n style: { ...(this.options?.style || {}), padding: 2 },\n text: this.options.value ?? '',\n label: 'input',\n resolution: 2,\n roundPixels: true,\n layout: false,\n });\n }\n\n protected addPlaceholder() {\n this.placeholder = this._placeholderContainer.add.text({\n ...this.options,\n ...this.options.placeholder,\n style: {\n ...this.options.style,\n fill: this.options.placeholder?.color ?? 0x666666,\n },\n resolution: 2,\n label: 'placeholder',\n roundPixels: true,\n layout: true,\n });\n\n this.placeholder.style.align = this.input.style.align;\n }\n\n protected createDomElement(selection?: number) {\n if (this.isClone && this.clone?.domElement) {\n this.domElement = this.clone.domElement;\n this._addDomElementListeners();\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n\n this.domElement = document.createElement('input');\n this.domElement.type = 'text';\n if (this.options.type && AVAILABLE_TYPES.includes(this.options.type)) {\n this.domElement.type = this.options.type;\n }\n\n if (this.options.pattern) {\n this.domElement.pattern = this.options.pattern;\n }\n if (this.options.regex) {\n this._regex = this.options.regex;\n }\n\n const pos = this.getGlobalPosition();\n const bounds = this.getBounds();\n bounds.x = pos.x;\n bounds.y = pos.y;\n bounds.width = this.width - this.options.padding.left;\n\n /**\n * Overlays an HTMLInputElement\n * allows the keyboard to be used on mobile devices\n * mostly taken from @pixi/ui\n * @see https://github.com/pixijs/ui/blob/main/src/Input.ts\n */\n\n this.domElement.style.position = 'fixed';\n this.domElement.style.border = 'none';\n this.domElement.style.outline = 'none';\n this.domElement.style.left = isAndroid ? `0` : `${bounds.left}px`;\n this.domElement.style.top = isAndroid ? `0` : `${bounds.top}px`;\n this.domElement.style.width = `${bounds.width}px`;\n this.domElement.style.height = `${bounds.height}px`;\n this.domElement.style.padding = '0';\n\n if (this.options.debug) {\n this.domElement.style.opacity = '0.8';\n } else {\n this.domElement.style.opacity = '0.0000001';\n }\n this.app.canvas.parentElement?.appendChild(this.domElement);\n this.domElement.value = this.value;\n this.domElement.setAttribute('placeholder', this.options?.placeholder?.text ?? '');\n if (this.options?.maxLength) {\n this.domElement.setAttribute('maxLength', this.options.maxLength.toString());\n }\n\n this._addDomElementListeners();\n this._focusDomElement(selection);\n }\n\n protected destroyDomElement() {\n if (this.isClone) {\n return;\n }\n if (this.domElement) {\n this._removeDomElementListeners();\n this.domElement.remove();\n\n if (this.domElement.parentNode) {\n this.domElement.parentNode.removeChild(this.domElement);\n }\n // @ts-expect-error domelement can't be null\n this.domElement = null;\n }\n }\n\n protected showCursor() {\n this.caret.visible = true;\n this.blinkCaret();\n }\n\n protected hideCursor() {\n this.cursorAnimation?.kill();\n this.caret.visible = false;\n }\n\n protected blinkCaret() {\n if (this.cursorAnimation) {\n this.cursorAnimation.kill();\n }\n this.cursorAnimation = gsap.fromTo(\n this.caret,\n { alpha: 0 },\n {\n duration: 0.5,\n alpha: 1,\n yoyo: true,\n repeat: -1,\n overwrite: true,\n },\n );\n this.addAnimation(this.cursorAnimation);\n }\n\n protected validate() {\n const hasError = this.error;\n if (this.isClone) {\n this.error = this.clone?.error || false;\n } else {\n this.error = !this.isValid;\n if (this.error && this.error !== hasError) {\n this.onError.emit({ input: this, domElement: this.domElement, value: this._value });\n }\n }\n if (this.error !== hasError) {\n if (this.error && this.error !== hasError) {\n this.input.style.fill = this.options?.error?.input?.fill || 0x0;\n } else {\n this.input.style.fill = this.options.input?.style?.fill || 0x0;\n }\n this.drawBg();\n }\n\n if (this.cloneOverlay) {\n this.cloneOverlay.validate();\n }\n }\n\n private _removeDomElementListeners() {\n this.domElement.removeEventListener('focus', this._handleDomElementFocus, false);\n this.domElement.removeEventListener('blur', this._handleDomElementBlur, false);\n this.domElement.removeEventListener('input', this._handleDomElementChange, false);\n this.domElement.removeEventListener('keyup', this._handleDomElementKeyup, false);\n this.domElement.removeEventListener('keydown', this._handleDomElementKeydown, false);\n }\n\n private _addDomElementListeners() {\n if (this.isClone) {\n return;\n }\n this._removeDomElementListeners();\n this.domElement.addEventListener('focus', this._handleDomElementFocus, false);\n this.domElement.addEventListener('blur', this._handleDomElementBlur, false);\n this.domElement.addEventListener('input', this._handleDomElementChange, false);\n this.domElement.addEventListener('keyup', this._handleDomElementKeyup, false);\n this.domElement.addEventListener('keydown', this._handleDomElementKeydown, false);\n }\n\n private _handleFocus() {\n this._caretPosition = -1;\n this.showCursor();\n\n clearTimeout(this._pointerDownTimer);\n\n if (!this.isClone) {\n this._pointerDownTimer = setTimeout(() => {\n this.app.stage.on('pointerdown', this._checkPointerDownOutside);\n }, 250);\n\n const hasOverlay = Boolean(this.options.focusOverlay.activeFilter);\n if (hasOverlay) {\n // decide if we should show an overlay\n if (this.cloneOverlay) {\n this._removeCloneOverlay();\n }\n const isList = Array.isArray(this.options.focusOverlay.activeFilter);\n let shouldShow = false;\n if (isList) {\n const filterList = this.options.focusOverlay.activeFilter as ('mobile' | 'touch' | 'desktop')[];\n if (\n (isMobile && filterList.includes('mobile')) ||\n (isTouch && filterList.includes('touch')) ||\n (!isMobile && !isTouch && filterList.includes('desktop'))\n ) {\n shouldShow = true;\n }\n } else if (typeof this.options.focusOverlay.activeFilter === 'function') {\n shouldShow = this.options.focusOverlay.activeFilter();\n } else {\n shouldShow = hasOverlay;\n }\n\n if (shouldShow) {\n const opts = structuredClone(this.options);\n const scale = this.options.focusOverlay?.scale || 1;\n opts.focusOverlay = { activeFilter: false };\n const fontSize = Number(opts.style?.fontSize || defaultOptions.style?.fontSize || 20) * scale;\n if (!opts.style) {\n opts.style = {};\n }\n\n opts.style.fontSize = fontSize;\n if (opts.padding) {\n opts.padding.left *= scale;\n opts.padding.top *= scale;\n opts.padding.right *= scale;\n opts.padding.bottom *= scale;\n }\n if (opts.bg?.radius) {\n opts.bg.radius *= scale;\n }\n if (opts.bg?.stroke?.width) {\n opts.bg.stroke.width *= scale;\n }\n if (opts.minWidth) {\n opts.minWidth *= scale;\n if (opts.minWidth > this.app.size.width) {\n opts.minWidth = this.app.size.width - (opts.bg?.stroke?.width ? opts.bg.stroke.width * 2 + 20 : 20);\n }\n }\n\n // should we show backing?\n if (this.options.focusOverlay?.backing?.active) {\n const backing = this.make.sprite({\n asset: Texture.WHITE,\n tint: this.options.focusOverlay.backing.options?.color ?? 0x0,\n alpha: this.options.focusOverlay.backing.options?.alpha ?? 0.8,\n width: this.app.size.width,\n height: this.app.size.height,\n eventMode: 'static',\n });\n this.overlayBacking = this.app.stage.addChild(backing);\n }\n\n this.cloneOverlay = new Input(opts, true, this);\n this.cloneOverlay.label = `${this.label} -- clone`;\n this.cloneOverlay.alpha = 0;\n this.cloneOverlay.input.text = this.value;\n this.cloneOverlay.validate();\n this.app.stage.addChild(this.cloneOverlay);\n this._positionCloneOverlay();\n this._showCloneOverlay();\n }\n }\n }\n }\n\n private _showCloneOverlay() {\n this.cloneOverlay.pivot.y = -20;\n this.addAnimation(gsap.to(this.cloneOverlay, { duration: 0.5, alpha: 0.8, ease: 'sine.out', delay: 0.1 }));\n this.addAnimation(gsap.to(this.cloneOverlay.pivot, { duration: 0.5, y: 0, ease: 'sine.out', delay: 0.1 }));\n }\n\n private _positionCloneOverlay() {\n if (!this.cloneOverlay) {\n return;\n }\n const w = this.cloneOverlay.options.minWidth;\n this.cloneOverlay.x = this.app.size.width * 0.5 - w * 0.5;\n this.cloneOverlay.y = this.options.focusOverlay?.marginTop || 20;\n if (this.overlayBacking) {\n this.overlayBacking.width = this.app.size.width;\n this.overlayBacking.height = this.app.size.height;\n }\n }\n\n private _removeCloneOverlay() {\n this.overlayBacking?.destroy();\n this.overlayBacking?.parent?.removeChild(this.overlayBacking);\n // @ts-expect-error cloneOverlay can't be null\n this.overlayBacking = null;\n this.cloneOverlay?.destroy();\n this.cloneOverlay?.parent?.removeChild(this.cloneOverlay);\n // @ts-expect-error cloneOverlay can't be null\n this.cloneOverlay = null;\n }\n\n private _handleDomElementFocus() {\n this.app.stage.off('pointerdown', this._checkPointerDownOutside);\n this._handleFocus();\n }\n\n private _handleDomElementBlur() {\n if (this.isClone) {\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n this.hideCursor();\n this._removeCloneOverlay();\n this.destroyDomElement();\n }\n\n private _handleDomElementKeyup() {\n this._updateCaretAndSelection();\n }\n\n private _handleDomElementKeydown(e: KeyboardEvent) {\n this._updateCaretAndSelection();\n if (!this.isClone && e.key === 'Enter') {\n if (this.options.blurOnEnter) {\n this.domElement.blur();\n }\n this.onEnter.emit({ input: this, value: this._value, domElement: this.domElement });\n }\n }\n\n private _updateCaretAndSelection() {\n if (!this.domElement) {\n Logger.warn(this.label, 'No dom element');\n return;\n }\n const start = this.domElement.selectionStart || 0;\n const end = this.domElement.selectionEnd || -1;\n const direction = this.domElement.selectionDirection;\n let text = '';\n const value = this.options.type === 'password' ? this.input.text : this._value;\n if (end === undefined) {\n text = value.substring(0, start);\n const metrics = CanvasTextMetrics.measureText(text, this.input.style);\n this._caretPosition = metrics.width;\n this._selectionRect = null;\n } else {\n text = value.substring(start > end ? end : start, start > end ? start : end);\n const toStart = value.substring(0, start > end ? end : start);\n const leftMetrics = CanvasTextMetrics.measureText(toStart, this.input.style);\n const textMetrics = CanvasTextMetrics.measureText(text, this.input.style);\n this._selectionRect = new Rectangle(leftMetrics.width, 0, textMetrics.width, this.input.height);\n this._caretPosition =\n direction === 'backward' ? this._selectionRect.left : this._selectionRect.left + this._selectionRect.width;\n }\n }\n\n private _handleDomElementChange(e: Event) {\n const target = e.target as HTMLInputElement;\n if (target && !this.domElement) {\n this.domElement = target;\n }\n if (this.options.pattern !== '') {\n const filteredValue = target.value.replace(new RegExp(this.options.pattern, 'g'), '');\n target.value = filteredValue;\n this._value = filteredValue;\n } else {\n this._value = target.value;\n }\n\n this.input.text =\n this.options.type === 'password'\n ? this._value\n ?.split('')\n .map(() => '*')\n .join('')\n : this._value;\n\n this._updateCaretAndSelection();\n\n if (!this.isClone) {\n this.onChange.emit({ input: this, domElement: this.domElement, value: this._value });\n this.validate();\n }\n }\n\n /**\n * Gets the focusable area bounds\n * @returns {Bounds} The bounds of the input container\n */\n getFocusArea(): Bounds {\n const bounds = this._inputContainer.getBounds();\n bounds.width = this._lastWidth;\n bounds.height = this._lastHeight;\n return bounds;\n }\n}\n","import { DefaultActionContextsArray, defaultActionsList } from './constants';\nimport { type UserActions, type UserButtons, type UserContexts } from './types';\n\n/**\n * Define the contexts for the actions.\n * @param contexts - The contexts to define.\n * @default ['default', 'game', 'menu', 'pause', 'popup', 'default']\n * @returns {ActionContext[]}\n */\n\nexport function defineContexts<C extends UserContexts = UserContexts>(contexts?: C): C {\n return contexts ?? (DefaultActionContextsArray as unknown as C);\n}\n\nexport function defineActions<C extends UserContexts = UserContexts, U extends UserActions = UserActions<C>>(\n contexts: C,\n actions: U,\n useDefaultActions: boolean = true,\n): U {\n if (useDefaultActions) {\n actions = { ...defaultActionsList, ...actions };\n }\n return actions;\n}\n\nexport function defineButtons<B extends UserButtons = UserButtons>(buttons?: B): B {\n return buttons || ([] as unknown as B);\n}\n","import type { BreakpointMode } from './types';\n\n/**\n * Declare an app's tier ladder and modes in `caper.config.ts`. Returns the\n * config unchanged — its value is the inferred literal key types, which the\n * Vite plugin re-exports into `caper-app.d.ts` so tier and mode names\n * autocomplete everywhere.\n *\n * @example\n * ```ts\n * export const breakpoints = defineBreakpoints({\n * tiers: { mobile: 0, tablet: 768, desktop: 1024 },\n * modes: { stacked: { below: 880 } },\n * });\n * ```\n */\nexport function defineBreakpoints<\n const T extends Record<string, number>,\n const M extends Record<string, BreakpointMode<keyof T & string>> = {},\n>(config: { tiers: T; modes?: M }): { tiers: T; modes: M } {\n return { tiers: config.tiers, modes: (config.modes ?? {}) as M };\n}\n","export enum JoystickDirection {\n None = 'none',\n Left = 'left',\n Top = 'top',\n Bottom = 'bottom',\n Right = 'right',\n TopLeft = 'top_left',\n TopRight = 'top_right',\n BottomLeft = 'bottom_left',\n BottomRight = 'bottom_right',\n}\nexport type JoystickDirectionType =\n | JoystickDirection.None\n | JoystickDirection.Left\n | JoystickDirection.Top\n | JoystickDirection.Bottom\n | JoystickDirection.Right\n | JoystickDirection.TopLeft\n | JoystickDirection.TopRight\n | JoystickDirection.BottomLeft\n | JoystickDirection.BottomRight;\n\n// export a type of all the JoystickDirections\nexport const JOYSTICK_DIRECTIONS: JoystickDirectionType[] = [\n JoystickDirection.None,\n JoystickDirection.Left,\n JoystickDirection.Top,\n JoystickDirection.Bottom,\n JoystickDirection.Right,\n JoystickDirection.TopLeft,\n JoystickDirection.TopRight,\n JoystickDirection.BottomLeft,\n JoystickDirection.BottomRight,\n];\n","import { UserActions, UserButtons } from '../actions';\nimport { UserControls } from './interfaces';\nexport function defineControls<U extends UserActions = UserActions, B extends UserButtons = UserButtons>(\n actions: U,\n buttons: B,\n controls?: UserControls<U, B>,\n): UserControls<U, B> {\n return controls || ([] as unknown as UserControls<U, B>);\n}\n","/**\n * Joystick UI component\n * based on https://github.com/endel/pixi-virtual-joystick\n * ported to TypeScript and adapted for Caper\n */\nimport { DestroyOptions, FederatedPointerEvent, Graphics, Point, Sprite } from 'pixi.js';\nimport { Container } from '../display';\nimport { JoystickDirection } from '../plugins';\nimport { Signal } from '../signals';\n\nexport interface IJoystick {\n onChange: Signal<(detail: JoystickSignalDetail) => void>;\n onStart: Signal<() => void>;\n onEnd: Signal<() => void>;\n onDestroy: Signal<() => void>;\n settings: JoystickSettings;\n outerRadius: number;\n innerRadius: number;\n outer: Sprite | Graphics;\n inner: Sprite | Graphics;\n dragging: boolean;\n pointData: Point;\n power: number;\n startPosition: Point;\n direction: JoystickDirection;\n}\n\nexport interface JoystickSignalDetail {\n angle: number;\n direction: JoystickDirection;\n power: number;\n}\n\nexport interface JoystickSettings {\n outer?: Sprite | Graphics;\n inner?: Sprite | Graphics;\n outerScale?: number;\n innerScale?: number;\n threshold?: number;\n}\n\nexport class Joystick extends Container implements IJoystick {\n onChange = new Signal<(detail: JoystickSignalDetail) => void>();\n onStart = new Signal<() => void>();\n onEnd = new Signal<() => void>();\n onDestroy = new Signal<() => void>();\n settings: JoystickSettings;\n outerRadius: number = 0;\n innerRadius: number = 0;\n\n outer!: Sprite | Graphics;\n inner!: Sprite | Graphics;\n\n innerAlphaStandby = 0.5;\n\n dragging: boolean = false;\n pointData: Point = new Point();\n power: number;\n startPosition: Point;\n direction: JoystickDirection = JoystickDirection.None;\n threshold: number;\n\n private _pointerId?: number;\n\n constructor(opts: Partial<JoystickSettings>) {\n super();\n\n this.settings = Object.assign(\n {\n outerScale: 1,\n innerScale: 1,\n },\n opts,\n );\n\n if (!this.settings.outer) {\n const outer = new Graphics();\n outer.circle(0, 0, 60).fill({ color: 0x0 });\n outer.alpha = 0.5;\n this.settings.outer = outer;\n }\n\n if (!this.settings.inner) {\n const inner = new Graphics();\n inner.circle(0, 0, 35).fill({ color: 0x0 });\n inner.alpha = this.innerAlphaStandby;\n this.settings.inner = inner;\n }\n\n this.threshold = this.settings.threshold ?? 0.01;\n\n this.initialize();\n }\n\n initialize() {\n this.outer = this.settings.outer!;\n this.inner = this.settings.inner!;\n\n this.outer.scale.set(this.settings.outerScale, this.settings.outerScale);\n this.inner.scale.set(this.settings.innerScale, this.settings.innerScale);\n\n if ('anchor' in this.outer) {\n this.outer.anchor.set(0.5);\n }\n if ('anchor' in this.inner) {\n this.inner.anchor.set(0.5);\n }\n\n this.add.existing(this.outer);\n this.add.existing(this.inner);\n\n // this.outerRadius = this.containerJoystick.width / 2;\n this.outerRadius = this.width / 2.5;\n this.innerRadius = this.inner.width / 2;\n\n this.bindEvents();\n }\n\n handleDragMove(e: FederatedPointerEvent) {\n if (!this.dragging || e.pointerId !== this._pointerId) {\n return;\n }\n const newPosition = this.toLocal(e.global);\n const sideX = newPosition.x - this.startPosition.x;\n const sideY = newPosition.y - this.startPosition.y;\n\n const centerPoint = new Point(0, 0);\n let angle = 0;\n let direction = JoystickDirection.None;\n if (sideX == 0 && sideY == 0) {\n this.direction = direction;\n return;\n }\n\n if (sideX === 0) {\n if (sideY > 0) {\n centerPoint.set(0, sideY > this.outerRadius ? this.outerRadius : sideY);\n angle = 270;\n direction = JoystickDirection.Bottom;\n } else {\n centerPoint.set(0, -(Math.abs(sideY) > this.outerRadius ? this.outerRadius : Math.abs(sideY)));\n angle = 90;\n direction = JoystickDirection.Top;\n }\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n this.direction = direction;\n this.onChange.emit({ angle, direction, power: this.power });\n return;\n }\n }\n\n if (sideY === 0) {\n if (sideX > 0) {\n centerPoint.set(Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX), 0);\n angle = 0;\n direction = JoystickDirection.Right;\n } else {\n centerPoint.set(-(Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX)), 0);\n angle = 180;\n direction = JoystickDirection.Left;\n }\n\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n this.direction = direction;\n this.onChange.emit({ angle, direction, power: this.power });\n return;\n }\n }\n\n const tanVal = Math.abs(sideY / sideX);\n const radian = Math.atan(tanVal);\n angle = (radian * 180) / Math.PI;\n\n let centerX = 0;\n let centerY = 0;\n\n if (sideX * sideX + sideY * sideY >= this.outerRadius * this.outerRadius) {\n centerX = this.outerRadius * Math.cos(radian);\n centerY = this.outerRadius * Math.sin(radian);\n } else {\n centerX = Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX);\n centerY = Math.abs(sideY) > this.outerRadius ? this.outerRadius : Math.abs(sideY);\n }\n\n if (sideY < 0) {\n centerY = -Math.abs(centerY);\n }\n\n if (sideX < 0) {\n centerX = -Math.abs(centerX);\n }\n\n if (sideX > 0 && sideY < 0) {\n // < 90\n } else if (sideX < 0 && sideY < 0) {\n // 90 ~ 180\n angle = 180 - angle;\n } else if (sideX < 0 && sideY > 0) {\n // 180 ~ 270\n angle = angle + 180;\n } else if (sideX > 0 && sideY > 0) {\n // 270 ~ 369\n angle = 360 - angle;\n }\n centerPoint.set(centerX, centerY);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n direction = this.getDirection(centerPoint);\n this.direction = direction;\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.onChange.emit({ angle, direction, power: this.power });\n }\n }\n\n destroy(options?: DestroyOptions) {\n this.off('pointerdown', this.handleDragStart)\n .off('pointerup', this.handleDragEnd)\n .off('pointerupoutside', this.handleDragEnd)\n .off('pointermove', this.handleDragMove);\n window.removeEventListener('pointerup', this.handleDragEnd);\n this.onDestroy.emit();\n super.destroy(options);\n }\n\n protected handleDragStart(e: FederatedPointerEvent) {\n if (this._pointerId !== undefined) {\n return;\n }\n this._pointerId = e.pointerId;\n this.startPosition = this.toLocal(e.global);\n this.dragging = true;\n this.inner.alpha = 1;\n this.onStart.emit();\n }\n\n protected handleDragEnd(e: FederatedPointerEvent | PointerEvent) {\n if (this._pointerId !== e.pointerId) {\n return;\n }\n this.direction = JoystickDirection.None;\n this.inner.position.set(0, 0);\n this.dragging = false;\n this.inner.alpha = this.innerAlphaStandby;\n this.onEnd.emit();\n this._pointerId = undefined;\n }\n\n protected bindEvents() {\n this.eventMode = 'static';\n this.on('pointerdown', this.handleDragStart)\n .on('pointerup', this.handleDragEnd)\n .on('pointerupoutside', this.handleDragEnd)\n .on('pointermove', this.handleDragMove);\n\n window.addEventListener('pointerup', this.handleDragEnd);\n }\n\n protected getPower(centerPoint: Point) {\n const a = centerPoint.x;\n const b = centerPoint.y;\n return Math.min(1, Math.sqrt(a * a + b * b) / this.outerRadius);\n }\n\n protected getDirection(center: Point) {\n const rad = Math.atan2(center.y, center.x); // [-PI, PI]\n if ((rad >= -Math.PI / 8 && rad < 0) || (rad >= 0 && rad < Math.PI / 8)) {\n return JoystickDirection.Right;\n } else if (rad >= Math.PI / 8 && rad < (3 * Math.PI) / 8) {\n return JoystickDirection.BottomRight;\n } else if (rad >= (3 * Math.PI) / 8 && rad < (5 * Math.PI) / 8) {\n return JoystickDirection.Bottom;\n } else if (rad >= (5 * Math.PI) / 8 && rad < (7 * Math.PI) / 8) {\n return JoystickDirection.BottomLeft;\n } else if ((rad >= (7 * Math.PI) / 8 && rad < Math.PI) || (rad >= -Math.PI && rad < (-7 * Math.PI) / 8)) {\n return JoystickDirection.Left;\n } else if (rad >= (-7 * Math.PI) / 8 && rad < (-5 * Math.PI) / 8) {\n return JoystickDirection.TopLeft;\n } else if (rad >= (-5 * Math.PI) / 8 && rad < (-3 * Math.PI) / 8) {\n return JoystickDirection.Top;\n } else {\n return JoystickDirection.TopRight;\n }\n }\n}\n","import { ColorSource, DestroyOptions, Container as PIXIContainer, Sprite, Texture } from 'pixi.js';\n\nimport type { IContainer } from '../display/Container';\nimport { Container } from '../display/Container';\nimport type { ActionContext, IFocusable } from '../plugins';\nimport { Logger, type Size } from '../utils';\n\n/**\n * Interface for Popup\n */\nexport interface IPopup<T = any> extends IContainer {\n readonly id: string | number; // Unique identifier for the popup\n config: PopupConfig<T>; // Configuration for the popup\n view: Container; // The view of the popup\n backing?: PIXIContainer; // The backing of the popup\n isShowing: boolean; // Whether the popup is currently showing\n firstFocusableEntity?: IFocusable; // The first focusable entity in the popup\n data: T;\n\n readonly actionContext: ActionContext | undefined; // The action context of the popup\n\n close(): void;\n\n initialize(): void; // Initialize the popup\n\n beforeShow(): void; // Show the popup\n\n show(): void | Promise<any>; // Show the popup\n\n afterShow(): void; // Show the popup\n\n beforeHide(): void; // Hide the popup\n\n hide(): void | Promise<any>; // Hide the popup\n\n start(): void | Promise<any>; // Start the popup\n\n end(): void; // End the popup\n\n restoreActionContext(): void; // Restore the action context\n}\n\nexport type PopupConstructor<T = any> = new (id: string | number, config?: Partial<PopupConfig<T>>) => IPopup<T>;\n\n/**\n * Configuration for the backing of the popup\n */\nexport type BackingConfig = {\n color: ColorSource;\n alpha: number;\n};\n\nconst defaultBackingConfig = {\n color: 0x0,\n alpha: 0.75,\n};\n\n/**\n * Configuration for the popup\n */\nexport type PopupConfig<T = any> = {\n id: string | number;\n closeOnEscape: boolean;\n closeOnPointerDownOutside: boolean;\n backing: boolean | Partial<BackingConfig>;\n data?: T;\n actionContext?: ActionContext;\n};\n\nconst defaultPopupConfig = {\n backing: true,\n closeOnEscape: true,\n closeOnPointerDownOutside: true,\n actionContext: 'popup',\n};\n\n/**\n * Class representing a Popup\n */\nexport class Popup<T = any> extends Container implements IPopup<T> {\n public isShowing: boolean = false;\n public firstFocusableEntity: IFocusable;\n public view: Container;\n public backing?: Sprite;\n public config: PopupConfig<T>;\n\n protected _storedActionContext: ActionContext | undefined = undefined;\n\n get actionContext(): ActionContext | undefined {\n return this.config.actionContext;\n }\n\n /**\n * Create a new Popup\n * @param id - The unique identifier for the popup\n * @param config - The configuration for the popup. The `data` field is\n * narrowed to `T` when the subclass declares its generic parameter\n * (e.g. `class MyPopup extends Popup<MyData>`), which flows through to\n * the typed `app.popups.show('id', { data })` call site.\n */\n constructor(\n public readonly id: string | number,\n config: Partial<PopupConfig<T>> = {},\n ) {\n super();\n this.config = Object.assign({ id, ...defaultPopupConfig }, config) as PopupConfig<T>;\n\n this._initialize();\n }\n\n get data(): T {\n return this.config.data as T;\n }\n /**\n * Create a backing for the popup\n * @param config - The configuration for the backing\n * @param size - The size of the backing\n * @returns The backing container\n */\n private static makeBacking(config: boolean | Partial<BackingConfig>, size: Size): Sprite {\n let finalConfig = {};\n if (typeof config === 'object') {\n finalConfig = config;\n }\n const backingConfig: BackingConfig = Object.assign({ ...defaultBackingConfig }, finalConfig);\n const backing = new Sprite(Texture.WHITE);\n backing.anchor.set(0.5);\n backing.alpha = backingConfig.alpha;\n backing.tint = backingConfig.color;\n backing.width = size.width;\n backing.height = size.height;\n return backing;\n }\n\n initialize() {}\n\n public beforeShow() {\n this.storeActionContext();\n this.setActionContext();\n }\n\n public beforeHide() {\n this.app.focus.removeFocusLayer(this.id);\n }\n\n destroy(options?: boolean | DestroyOptions): void {\n this.app.focus.removeFocusLayer(this.id);\n this._storedActionContext = undefined;\n super.destroy(options);\n }\n\n /**\n * Hide the popup\n * @returns A promise that resolves when the popup is hidden\n */\n hide(): void | any | Promise<any>;\n\n async hide(): Promise<void> {\n this.visible = false;\n return Promise.resolve();\n }\n\n /**\n * Show the popup\n * @returns A promise that resolves when the popup is shown\n */\n show(): void | Promise<any>;\n\n async show(): Promise<void> {\n this.resize();\n this.visible = true;\n return Promise.resolve();\n }\n\n /**\n * Start the popup\n */\n start(): void | Promise<any>;\n async start() {}\n\n afterShow() {\n if (this.firstFocusableEntity) {\n this.app.focus.add(this.firstFocusableEntity, this.id, true);\n this.app.focus.setFocus(this.firstFocusableEntity);\n }\n }\n /**\n * End the popup\n */\n end() {}\n\n close(): void | Promise<void>;\n async close(): Promise<void> {\n void this.app.popups.hidePopup(this.id, this.config.data);\n }\n\n resize() {\n this.backing?.setSize(this.app.size.width, this.app.size.height);\n }\n\n /**\n * Initialize the popup\n * @private\n */\n private _initialize() {\n this.app.focus.addFocusLayer(this.id, false);\n\n if (this.config.backing) {\n this.backing = this.add.existing(Popup.makeBacking(this.config.backing, this.app.size));\n this.backing.eventMode = 'static';\n\n if (this.config.closeOnPointerDownOutside) {\n this.backing.once('click', this.close);\n this.backing.once('tap', this.close);\n }\n }\n\n this.view = this.add.container();\n this.view.eventMode = 'static';\n }\n\n // store and restore the action context\n protected setActionContext() {\n if (this.actionContext) {\n this.app.actionContext = this.actionContext;\n Logger.log('Popup', 'Setting action context', this.app.actionContext);\n }\n }\n\n protected storeActionContext() {\n this._storedActionContext = this.app.actionContext;\n Logger.log('Popup', 'Storing action context', this._storedActionContext);\n }\n\n public restoreActionContext() {\n if (this._storedActionContext) {\n Logger.log('Popup', 'Restoring action context', this._storedActionContext);\n this.app.actionContext = this._storedActionContext;\n }\n this._storedActionContext = undefined;\n }\n}\n","import type { LayoutOptions } from '@pixi/layout';\nimport { GraphicsContext, HTMLTextStyleOptions, TextStyleOptions } from 'pixi.js';\nimport { ContainerConfig } from '../../display';\nimport { ParticleContainerConfig } from '../../display/ParticleContainer';\nimport { ButtonConfig, FlexContainerConfig, UICanvasProps } from '../../ui';\nimport type {\n BitmapFontFamilyAsset,\n FontFamilyAsset,\n PointLike,\n SpineAsset,\n SpritesheetAsset,\n TextureAsset,\n WithRequiredProps,\n} from '../../utils';\n\nexport interface AbstractProps {\n [key: string]: any;\n}\n\nexport interface TextureProps {\n asset: TextureAsset;\n sheet: SpritesheetAsset;\n}\n\nexport interface PositionProps {\n x: number;\n y: number;\n position: PointLike;\n}\n\nexport interface ScaleProps {\n scaleX: number;\n scaleY: number;\n scale: PointLike;\n}\n\nexport interface PivotProps {\n pivot: PointLike;\n}\n\nexport interface VisibilityProps {\n alpha: number;\n visible: boolean;\n}\n\nexport interface LayoutProps {\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n}\n\nexport interface ExistingProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {}\n\n/**\n * Layout-ish props the `this.add.entity(id, props)` factory applies after\n * construction — intentionally narrow (no `AbstractProps` index signature)\n * so TypeScript can still narrow entity-specific props at the call site.\n */\nexport interface EntityFactoryProps\n extends Partial<PositionProps>,\n Partial<ScaleProps>,\n Partial<PivotProps>,\n Partial<VisibilityProps> {}\n\nexport interface GraphicsProps extends AbstractProps, PositionProps, ScaleProps, PivotProps, VisibilityProps {}\n\nexport interface SvgProps extends GraphicsProps {\n ctx: string | GraphicsContext;\n}\n\nexport interface SpriteProps\n extends AbstractProps,\n TextureProps,\n ScaleProps,\n PositionProps,\n VisibilityProps,\n LayoutProps {\n anchor: PointLike;\n}\n\nexport interface TilingSpriteProps extends SpriteProps {\n tilePosition?: PointLike;\n /**\n * Scaling of the image that is being tiled.\n * @default {x: 1, y: 1}\n */\n tileScale?: PointLike;\n /**\n * The rotation of the image that is being tiled.\n * @default 0\n */\n tileRotation?: number;\n /**\n * The texture to use for the sprite.\n * @default Texture.WHITE\n */\n /**\n * The width of the tiling sprite. #\n * @default 256\n */\n width?: number;\n /**\n * The height of the tiling sprite.\n * @default 256\n */\n height?: number;\n /**\n * @default false\n */\n applyAnchorToTexture?: boolean;\n /** Whether or not to round the x/y position. */\n roundPixels?: boolean;\n}\n\nexport interface AnimatedSpriteAnimationProps\n extends AbstractProps,\n ScaleProps,\n PositionProps,\n VisibilityProps,\n LayoutProps {\n texturePrefix: string;\n sheet: SpritesheetAsset;\n startIndex: number;\n numFrames: number;\n zeroPad: number;\n autoUpdate: boolean;\n updateAnchor: boolean;\n loop: boolean;\n animationSpeed: number;\n}\n\nexport interface AnimatedSpriteProps extends AbstractProps, ScaleProps, PositionProps, VisibilityProps, LayoutProps {\n sheet: SpritesheetAsset;\n texturePrefix: string;\n zeroPad: number;\n animations: { [animationName: string]: Partial<AnimatedSpriteAnimationProps> };\n autoPlay: boolean;\n autoUpdate: boolean;\n defaultAnimation: string;\n reversible: boolean;\n animationSpeed: number;\n startIndex: number;\n}\n\nexport type TextStyle = Partial<Omit<TextStyleOptions, 'fontFamily'> & { fontFamily: FontFamilyAsset }>;\n\nexport interface TextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: TextStyle;\n}\n\nexport interface BitmapTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: Partial<Omit<TextStyleOptions, 'fontFamily'> & { fontFamily: BitmapFontFamilyAsset }>;\n}\n\nexport interface HTMLTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: Partial<Omit<HTMLTextStyleOptions, 'fontFamily'> & { fontFamily: FontFamilyAsset }>;\n}\n\nexport interface OmittedTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps {}\n\nexport const TextPropsKeys: (keyof TextProps)[] = ['text', 'anchor', 'roundPixels', 'style', 'pivot'];\n\nexport interface ContainerProps\n extends AbstractProps,\n PositionProps,\n ScaleProps,\n PivotProps,\n VisibilityProps,\n LayoutProps,\n ContainerConfig {}\n\nexport interface ParticleContainerProps extends AbstractProps, ParticleContainerConfig {}\n\nexport interface FlexContainerProps extends ContainerProps, FlexContainerConfig {}\n\nexport interface UICanvasFactoryProps extends ContainerProps, UICanvasProps {}\n\n// spine\nexport interface SpineProps extends AbstractProps, ScaleProps, PositionProps, VisibilityProps, LayoutProps {\n data: SpineAsset;\n autoUpdate: boolean;\n animationName: string;\n trackIndex: number;\n loop: boolean;\n paused: boolean;\n}\n\ninterface _ButtonProps\n extends AbstractProps,\n ScaleProps,\n PositionProps,\n PivotProps,\n VisibilityProps,\n ButtonConfig,\n LayoutProps {}\n\nexport type ButtonProps = WithRequiredProps<_ButtonProps, 'textures'>;\n","import type { IActionsPlugin } from '../plugins/actions';\nimport type { Application } from './Application';\nimport type { IApplication } from './interfaces';\n\n/**\n * A single entry in an app's automation log ring buffer.\n */\nexport interface AutomationLogEntry {\n t: number;\n kind: 'action' | 'state' | 'context';\n name?: string;\n data?: unknown;\n}\n\n/**\n * The automation facade exposed on `window.Caper.automation[appId]` for\n * Playwright / agent drivers. Only present when automation is enabled (see the\n * gating rules in {@link registerCaperApp}).\n */\nexport interface ICaperAutomation {\n readonly appId: string;\n readonly log: readonly AutomationLogEntry[];\n action(name: string, data?: unknown): void;\n getContext(): string;\n getState(): unknown;\n registerStateGetter(fn: () => unknown): void;\n notifyStateChanged(state: unknown): void;\n waitFor(predicate: (state: unknown) => boolean, opts?: { timeoutMs?: number }): Promise<unknown>;\n}\n\nconst LOG_CAP = 200;\nconst FALLBACK_APP_ID = 'CaperApplication';\n\ninterface CaperReadyResolver {\n resolve: (app: IApplication) => void;\n promise: Promise<IApplication>;\n}\n\ninterface CaperGlobalInternal {\n apps: Map<string, IApplication>;\n app?: IApplication;\n automation: Record<string, ICaperAutomation>;\n ready: (id?: string) => Promise<IApplication>;\n __runtimeManaged?: boolean;\n /** set by the caper-runtime virtual module from the app's import.meta.env.DEV */\n __dev?: boolean;\n /** internal: keyed ready resolvers */\n __readyResolvers?: Map<string, CaperReadyResolver>;\n /** internal: ids of apps that have fully finished booting (signalCaperReady) */\n __readyApps?: Set<string>;\n [key: string]: unknown;\n}\n\n/**\n * Guarded dev-env check. The caper-runtime virtual module sets `Caper.__dev`\n * from the consumer app's `import.meta.env.DEV` (the reliable signal — inside\n * this pre-built lib, import.meta.env has been compiled away at build time).\n * The direct import.meta check remains as a fallback for source-linked\n * consumers. Access to browser/env globals must stay inside a function (never\n * at module top level) so the built entry can be evaluated in plain Node\n * during SSR config loading.\n */\nfunction isDevEnv(): boolean {\n try {\n if ((globalThis as any).Caper?.__dev === true) {\n return true;\n }\n return typeof import.meta !== 'undefined' && (import.meta as any).env?.DEV === true;\n } catch {\n return false;\n }\n}\n\nfunction automationEnvFlag(): boolean {\n try {\n return typeof import.meta !== 'undefined' && (import.meta as any).env?.VITE_CAPER_AUTOMATION === 'true';\n } catch {\n return false;\n }\n}\n\nconst FIRST_APP_KEY = '__first__';\n\n/**\n * Lazily create/return the `globalThis.Caper` object with the automation +\n * discovery surface installed. No browser globals are touched at module load\n * time — everything happens inside this function.\n */\nfunction ensureCaperGlobal(): CaperGlobalInternal {\n const g = globalThis as any;\n const caper: CaperGlobalInternal = (g.Caper ||= {} as CaperGlobalInternal);\n\n if (!(caper.apps instanceof Map)) {\n caper.apps = new Map<string, IApplication>();\n }\n if (typeof caper.automation !== 'object' || caper.automation === null) {\n caper.automation = {};\n }\n if (!(caper.__readyResolvers instanceof Map)) {\n caper.__readyResolvers = new Map<string, CaperReadyResolver>();\n }\n if (!(caper.__readyApps instanceof Set)) {\n caper.__readyApps = new Set<string>();\n }\n\n if (typeof caper.ready !== 'function') {\n caper.ready = (id?: string): Promise<IApplication> => {\n const resolvers = caper.__readyResolvers as Map<string, CaperReadyResolver>;\n const readyApps = caper.__readyApps as Set<string>;\n // Only resolve immediately for apps that have FINISHED booting\n // (signalCaperReady) — registration alone happens earlier, in create(),\n // before main.ts has run.\n if (id && readyApps.has(id)) {\n return Promise.resolve(caper.apps.get(id)!);\n }\n // No id: resolve with the first fully-booted app if one exists.\n if (!id && readyApps.size > 0) {\n const firstReadyId = readyApps.values().next().value as string;\n return Promise.resolve(caper.apps.get(firstReadyId)!);\n }\n const key = id ?? FIRST_APP_KEY;\n let entry = resolvers.get(key);\n if (!entry) {\n let resolve!: (app: IApplication) => void;\n const promise = new Promise<IApplication>((res) => {\n resolve = res;\n });\n entry = { resolve, promise };\n resolvers.set(key, entry);\n }\n return entry.promise;\n };\n }\n\n return caper;\n}\n\n/**\n * Install the `Caper` discovery surface (`apps`, `automation`, `ready()`) on\n * `globalThis` immediately. The caper-runtime virtual module calls this before\n * bootstrap so automation drivers (Playwright etc.) can `await Caper.ready()`\n * from the very first moment the page scripts run, instead of polling for the\n * function to appear at the end of boot.\n */\nexport function installCaperGlobal(): void {\n ensureCaperGlobal();\n}\n\nfunction appIdOf(app: IApplication): string {\n return (app.config?.id as string) || FALLBACK_APP_ID;\n}\n\nfunction buildAutomation(app: IApplication): ICaperAutomation {\n const appId = appIdOf(app);\n const log: AutomationLogEntry[] = [];\n let stateGetter: (() => unknown) | undefined;\n const pending: Array<{ predicate: (state: unknown) => boolean; resolve: (v: unknown) => void }> = [];\n\n const push = (entry: AutomationLogEntry) => {\n log.push(entry);\n if (log.length > LOG_CAP) {\n log.splice(0, log.length - LOG_CAP);\n }\n };\n\n const getState = (): unknown => (stateGetter ? stateGetter() : undefined);\n\n const checkPending = (state: unknown) => {\n if (pending.length === 0) {\n return;\n }\n for (let i = pending.length - 1; i >= 0; i--) {\n let matched = false;\n try {\n matched = pending[i].predicate(state);\n } catch {\n matched = false;\n }\n if (matched) {\n const [entry] = pending.splice(i, 1);\n entry.resolve(state);\n }\n }\n };\n\n const facade: ICaperAutomation = {\n appId,\n get log() {\n return log as readonly AutomationLogEntry[];\n },\n action(name: string, data?: unknown) {\n app.sendAction(name as any, data);\n },\n getContext() {\n return String(app.actionContext);\n },\n getState,\n registerStateGetter(fn: () => unknown) {\n stateGetter = fn;\n },\n notifyStateChanged(state: unknown) {\n push({ t: Date.now(), kind: 'state', data: state });\n checkPending(state);\n },\n waitFor(predicate: (state: unknown) => boolean, opts?: { timeoutMs?: number }) {\n // Check immediately against current state.\n const current = getState();\n try {\n if (predicate(current)) {\n return Promise.resolve(current);\n }\n } catch {\n // ignore predicate errors on the immediate check\n }\n return new Promise<unknown>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const entry = {\n predicate,\n resolve: (v: unknown) => {\n if (timer) {\n clearTimeout(timer);\n }\n resolve(v);\n },\n };\n pending.push(entry);\n if (opts?.timeoutMs != null) {\n timer = setTimeout(() => {\n const idx = pending.indexOf(entry);\n if (idx >= 0) {\n pending.splice(idx, 1);\n }\n reject(new Error(`waitFor timed out after ${opts.timeoutMs}ms`));\n }, opts.timeoutMs);\n }\n });\n },\n };\n\n // Subscribe to action dispatches + context changes for the log, and re-check\n // pending waitFor predicates after each dispatched action.\n const actions = app.getPlugin<IActionsPlugin>('actions');\n if (actions) {\n actions.onActionDispatched?.connect((detail) => {\n push({ t: Date.now(), kind: 'action', name: String(detail.id), data: detail.data });\n checkPending(getState());\n });\n actions.onActionContextChanged.connect((context) => {\n push({ t: Date.now(), kind: 'context', name: String(context) });\n });\n }\n\n return facade;\n}\n\n/**\n * Register an app with the global `Caper` discovery surface. Adds it to\n * `Caper.apps` under its config id, sets `Caper.app` to the most-recently\n * created app, and — when automation is enabled — builds the automation facade\n * and stores it at `Caper.automation[id]` (and on the app instance).\n *\n * Automation is enabled when any of: dev env, `config.automation === true`, or\n * `VITE_CAPER_AUTOMATION === 'true'`.\n */\nexport function registerCaperApp(app: IApplication): void {\n const caper = ensureCaperGlobal();\n const id = appIdOf(app);\n caper.apps.set(id, app);\n caper.app = app;\n\n const automationEnabled = isDevEnv() || app.config?.automation === true || automationEnvFlag();\n if (automationEnabled) {\n const facade = buildAutomation(app);\n caper.automation[id] = facade;\n (app as Application).automation = facade;\n }\n}\n\n/**\n * Resolve any pending `Caper.ready()` promises for this app — both the\n * id-keyed resolver and the first-app resolver.\n */\nexport function signalCaperReady(app: IApplication): void {\n const caper = ensureCaperGlobal();\n const id = appIdOf(app);\n (caper.__readyApps as Set<string>).add(id);\n const resolvers = caper.__readyResolvers as Map<string, CaperReadyResolver>;\n\n const idEntry = resolvers.get(id);\n if (idEntry) {\n idEntry.resolve(app);\n resolvers.delete(id);\n }\n const firstEntry = resolvers.get(FIRST_APP_KEY);\n if (firstEntry) {\n firstEntry.resolve(app);\n resolvers.delete(FIRST_APP_KEY);\n }\n}\n","import { type RegisterSWOptions } from 'vite-plugin-pwa/types';\nimport { sayHello } from '../hello';\nimport type { PluginListItem } from '../plugins';\nimport type { AppTypeOverrides, SceneImportListItem } from '../utils';\nimport { triggerViteError } from '../utils/vite';\nimport { checkWebGL } from '../webgl-check';\nimport { Application } from './Application';\nimport { registerCaperApp, signalCaperReady, type ICaperAutomation } from './globals';\nimport type { IApplication } from './interfaces';\nimport { AppConfig } from './types';\n\ntype App = AppTypeOverrides['App'];\n\ninterface CaperPWA {\n readonly info: any;\n register: () => void;\n onRegisteredSW: (swScriptUrl: string) => void;\n offlineReady: () => void;\n onNeedRefresh?: () => void;\n onRegisterError?: (error: any) => void;\n}\ninterface CaperGlobal {\n APP_NAME: string;\n APP_VERSION: string | number;\n\n readonly sceneList: SceneImportListItem<any>[];\n readonly pluginsList: PluginListItem[];\n\n get: (key?: string) => any;\n // pwa\n pwa: CaperPWA;\n\n // app discovery + automation\n apps: Map<string, IApplication>;\n app?: IApplication;\n ready(id?: string): Promise<IApplication>;\n automation: Record<string, ICaperAutomation>;\n __runtimeManaged?: boolean;\n}\n\ndeclare global {\n const Caper: CaperGlobal;\n const registerSW: (options: RegisterSWOptions) => void;\n interface Window {\n Caper: CaperGlobal;\n }\n}\n\nexport const DEFAULT_GAME_CONTAINER_ID = 'caper-game-container';\n\nexport function createContainer(id: string) {\n const container = document.createElement('div');\n container.setAttribute('id', id);\n document.body.appendChild(container);\n return container;\n}\n\nexport async function documentReady() {\n return new Promise((resolve) => {\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n resolve(true);\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n resolve(true);\n });\n }\n });\n}\n\nfunction addErrorHandler() {\n // This guard ensures these listeners only run during development\n if (import.meta.env.DEV) {\n /**\n * Listen for standard runtime errors that are not caught.\n */\n window.addEventListener('error', (event) => {\n // Prevent the default browser console error log\n event.preventDefault();\n\n triggerViteError({\n message: event.message,\n // The error object might contain a more detailed stack trace\n stack: event.error?.stack,\n id: event.filename,\n line: event.lineno,\n column: event.colno,\n });\n });\n\n /**\n * Listen for unhandled promise rejections (e.g., from async functions).\n */\n window.addEventListener('unhandledrejection', (event) => {\n // Prevent the default browser console error log\n event.preventDefault();\n\n const error = event.reason;\n\n // The 'reason' can be any value, so we handle Error objects specifically\n if (error instanceof Error) {\n triggerViteError({\n message: error.message,\n stack: error.stack,\n // Note: stack parsing would be needed to get file/line for promise rejections\n });\n } else {\n // Handle cases where a non-error value is rejected\n triggerViteError({\n message: `Unhandled promise rejection: ${String(event.reason)}`,\n });\n }\n });\n }\n}\n\nexport async function create(\n config: Partial<AppConfig> = { id: 'CaperApplication' },\n domElement: string | Window | HTMLElement = DEFAULT_GAME_CONTAINER_ID,\n speak: boolean = true,\n): Promise<App> {\n await documentReady();\n checkWebGL();\n if (speak) {\n sayHello();\n }\n addErrorHandler();\n let el: HTMLElement | null = null;\n if (typeof domElement === 'string') {\n el = document.getElementById(domElement);\n if (!el) {\n el = createContainer(domElement);\n }\n } else if (domElement instanceof HTMLElement) {\n el = domElement;\n } else if (domElement === window) {\n el = document.body;\n }\n if (!el) {\n // no element to use\n throw new Error(\n 'You passed in a DOM Element, but none was found. If you instead pass in a string, a container will be created for you, using the string for its id.',\n );\n }\n if (config.resizeToContainer) {\n config.resizeTo = el;\n }\n\n if (config.useLayout) {\n config.layout = {\n // @ts-expect-error some config stuff isn't typed right in @pixi/layout\n autoUpdate: false,\n enableDebug: false,\n debugModificationCount: 0,\n throttle: 100,\n };\n }\n\n config.container = el;\n const ApplicationClass = config.application || Application;\n const instance = new ApplicationClass();\n await instance.initialize(config, el);\n\n if (config.useLayout) {\n instance.stage.layout = {\n position: 'absolute',\n width: '100%',\n height: '100%',\n };\n }\n\n // ensure all plugins are initialized\n // run framework post-init: the plugin loop + core wiring, then the user hook\n await instance._postInitialize();\n\n // register with the global Caper discovery/automation surface\n registerCaperApp(instance as unknown as IApplication);\n // when not driven by the vite runtime (which signals readiness itself after\n // main.ts), signal readiness here so direct create() usage still resolves\n // Caper.ready()\n if (!(globalThis as any).Caper?.__runtimeManaged) {\n signalCaperReady(instance as unknown as IApplication);\n }\n\n // return the app instance\n return instance as App;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"caper.mjs","names":[],"sources":["../src/utils/array.ts","../src/utils/canvas.ts","../src/utils/color.ts","../src/utils/define.ts","../src/utils/pixi.ts","../src/utils/platform.ts","../src/utils/rect.ts","../src/utils/set.ts","../src/utils/text.ts","../src/version.ts","../src/hello.ts","../src/webgl-check.ts","../src/display/Entity.ts","../src/display/Scene.ts","../src/display/SceneTransition.ts","../src/display/Camera.ts","../src/ui/Input.ts","../src/plugins/actions/methods.ts","../src/plugins/breakpoints/methods.ts","../src/plugins/input/touch/constants.ts","../src/plugins/input/methods.ts","../src/ui/Joystick.ts","../src/ui/Popup.ts","../src/mixins/factory/props.ts","../src/core/globals.ts","../src/core/create.ts"],"sourcesContent":["import { intBetween } from './random';\n\n/**\n * Shuffle an array.\n * @param array\n */\nexport function shuffle<T>(array: T[]): void {\n let temp: T;\n let index: number;\n for (let i = 0; i < array.length; ++i) {\n index = intBetween(0, array.length);\n temp = array[i];\n array[i] = array[index];\n array[index] = temp;\n }\n}\n\n/**\n * Get a random array element.\n * @param array\n */\nexport function getRandomElement<T>(array: T[]): T {\n return array[intBetween(0, array.length)];\n}\n","export function destroyCanvas(canvas: HTMLCanvasElement | OffscreenCanvas) {\n const gl = canvas.getContext('webgl');\n if (gl) {\n const extension = gl.getExtension('WEBGL_lose_context');\n if (extension) {\n extension.loseContext();\n }\n }\n // If you are using a 2D context, there's no direct resource release method,\n // but you should ensure all operations are complete before nullifying the canvas\n const ctx = canvas.getContext('2d');\n if (ctx) {\n // Perform any necessary cleanup tasks for 2D context\n ctx.clearRect(0, 0, canvas.width, canvas.height);\n }\n if (!(canvas instanceof OffscreenCanvas)) {\n if (canvas.parentNode) {\n canvas.parentNode.removeChild(canvas);\n }\n }\n canvas.width = 0;\n canvas.height = 0;\n\n // @ts-expect-error canvas can't be null;\n canvas = null;\n}\n","export function toHex(color: number): string {\n return `#${color.toString(16)}`;\n}\n\n// return a uint color from a hex string\nexport function toRgb(hex: string): number {\n return parseInt(hex.replace(/^#/, ''), 16);\n}\n\nexport class Color {\n public static readonly WHITE: Color = new Color(255, 255, 255);\n public static readonly BLACK: Color = new Color(0, 0, 0);\n public static readonly GREY: Color = new Color(127, 127, 127);\n public static readonly RED: Color = new Color(255, 0, 0);\n public static readonly GREEN: Color = new Color(0, 255, 0);\n public static readonly BLUE: Color = new Color(0, 0, 255);\n public static readonly YELLOW: Color = new Color(255, 255, 0);\n public static readonly MAGENTA: Color = new Color(255, 0, 255);\n public static readonly CYAN: Color = new Color(0, 255, 255);\n\n public r: number;\n public g: number;\n public b: number;\n\n /**\n * A Color reresented by a red, green and blue component.\n * @param r The red component of the Color OR the full Color in HEX.\n * @param g The green component of the Color.\n * @param b The blue component of the Color.\n */\n constructor(r?: number, g?: number, b?: number) {\n if (r !== undefined && g === undefined) {\n // tslint:disable-next-line no-bitwise\n this.r = (r & (255 << 16)) >> 16;\n // tslint:disable-next-line no-bitwise\n this.g = (r & (255 << 8)) >> 8;\n // tslint:disable-next-line no-bitwise\n this.b = r & 255;\n } else {\n this.r = r || 0;\n this.g = g || 0;\n this.b = b || 0;\n }\n }\n\n /**\n * Creates a random Color.\n * @returns The new Color.\n */\n public static random(): Color {\n return new Color(Math.random() * 255, Math.random() * 255, Math.random() * 255);\n }\n\n /**\n * Converts the rgb values passed in to hex.\n * @param r The red component to convert.\n * @param g The green component to convert.\n * @param b The blue component to convert.\n * @returns The hex value.\n */\n public static rgbToHex(r: number, g: number, b: number): number {\n // tslint:disable-next-line no-bitwise\n return (r << 16) | (g << 8) | b;\n }\n\n public static rgbToHexString(pNumber: number): string {\n let hex = Number(pNumber).toString(16);\n if (hex.length < 2) {\n hex = '0' + hex;\n }\n\n return hex;\n }\n\n public static rgbToFullHexString(r: number, g: number, b: number): string {\n const rStr: string = Color.rgbToHexString(r);\n const gStr: string = Color.rgbToHexString(g);\n const bStr: string = Color.rgbToHexString(b);\n\n return rStr + gStr + bStr;\n }\n\n /**\n * Creates a new Color that is linearly interpolated from pA to b .\n * @param pA The start Color.\n * @param b The end Color.\n * @param pPerc The percentage on the path from pA to b .\n * @returns The new Color.\n */\n public static lerp(pA: Color, b: Color, pPerc: number): Color {\n return new Color(pA.r + pPerc * (b.r - pA.r), pA.g + pPerc * (b.g - pA.g), pA.b + pPerc * (b.b - pA.b));\n }\n\n /**\n * Creates a new hex Color that is linearly interpolated from pA to b .\n * @param pA The first Color hex.\n * @param b The second Color hex.\n * @param pPerc The percentage along the path from pA to b .\n * @returns The new hex Color.\n */\n public static lerpHex(pA: number, b: number, pPerc: number): number {\n const colorA: Color = new Color(pA);\n const colorB: Color = new Color(b);\n return Color.lerp(colorA, colorB, pPerc).toHex();\n }\n\n /**\n * Convert this Color to hex.\n * @returns The Color in hex format.\n */\n public toHex(): number {\n return Color.rgbToHex(this.r, this.g, this.b);\n }\n\n public toHexString(): string {\n return Color.rgbToFullHexString(this.r, this.g, this.b);\n }\n\n /**\n * Converts the Color components to the 0...1 range.\n * @returns The new Color.\n */\n public toWebGL(): number[] {\n return [this.r / 255, this.g / 255, this.b / 255];\n }\n}\n","import type { SceneAssets, SceneDebug, ScenePlugins } from '../display/Scene';\nimport type { AppTypeOverrides } from './types';\n\ntype AppPluginId = AppTypeOverrides['Plugins'];\n\n/**\n * Runtime-free helpers that give scene/plugin/popup/entity config files\n * strong type inference without forcing users to extend base classes or\n * hand-type every file-level export.\n *\n * They are all typed identity functions (`(config) => config`), following\n * the Vite / Rollup / Playwright `defineConfig` pattern. No runtime cost:\n * the vite-plugin-caper-config scanner reads the call's object\n * argument via AST just like it reads individual `export const` forms.\n *\n * Example:\n *\n * // src/scenes/MenuScene.ts\n * import { defineScene, Scene } from '@caperjs/core';\n * export const scene = defineScene({\n * id: 'menu',\n * assets: { preload: { bundles: ['menu'] } },\n * plugins: ['google-analytics'],\n * });\n * export default class MenuScene extends Scene { ... }\n */\n\n/**\n * Scene metadata accepted by `defineScene`. Mirrors the runtime\n * `SceneConfig` in `display/Scene.ts` — reuses the canonical `SceneAssets`\n * / `ScenePlugins` / `SceneDebug` types so there's one source of truth.\n *\n * `id` is required here (unlike the runtime `SceneConfig` where it's\n * optional, because the scene class itself may carry the id).\n */\nexport interface SceneConfigInput {\n /** Unique scene ID used in `app.scenes.loadScene()`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `true` (code-split). Set `false` to force a static import. */\n dynamic?: boolean;\n /**\n * Asset load configuration. Uses the canonical `SceneAssets` shape:\n *\n * { preload: { bundles: [...] }, background: { bundles: [...] }, autoUnload: true }\n */\n assets?: SceneAssets;\n /** Plugin IDs this scene requires. Loaded lazily on scene load. */\n plugins?: ScenePlugins;\n /** Labels used by the debug UI scene picker. */\n debug?: SceneDebug;\n}\n\nexport interface PluginConfigInput {\n /** Unique plugin ID used in `app.getPlugin(id)`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `true` (code-split). Set `false` to force a static import. */\n dynamic?: boolean;\n /**\n * Plugin IDs that must be initialized before this one. The framework\n * topologically sorts plugins by `requires` at bootstrap, so the order\n * in `caper.config.ts` doesn't matter — required deps will always\n * `initialize()` (and `postInitialize()`) before any plugin that\n * requires them.\n *\n * Bootstrap fails loudly if a required plugin id isn't registered in\n * `caper.config.ts plugins[]`, or if there's a dependency cycle. The\n * error message includes the fix.\n *\n * Build-time validation also checks `requires` against discovered\n * plugin IDs and warns on typos before you ever run the app.\n */\n requires?: AppPluginId[];\n}\n\nexport interface PopupConfigInput {\n /** Unique popup ID used in `app.popups.show(id)`. */\n id: string;\n active?: boolean;\n dynamic?: boolean;\n}\n\nexport interface EntityConfigInput {\n /** Unique entity ID used in `app.entities.create(id)`. */\n id: string;\n active?: boolean;\n dynamic?: boolean;\n}\n\nexport interface UIConfigInput {\n /** Unique UI element ID used in `this.add.ui(id)`. */\n id: string;\n /** Defaults to `true`. Set `false` to hide from discovery without deleting the file. */\n active?: boolean;\n /** Defaults to `false` (static import). Set `true` to code-split. */\n dynamic?: boolean;\n}\n\nexport function defineScene<T extends SceneConfigInput>(config: T): T {\n return config;\n}\n\nexport function definePlugin<T extends PluginConfigInput>(config: T): T {\n return config;\n}\n\nexport function definePopup<T extends PopupConfigInput>(config: T): T {\n return config;\n}\n\nexport function defineEntity<T extends EntityConfigInput>(config: T): T {\n return config;\n}\n\nexport function defineUI<T extends UIConfigInput>(config: T): T {\n return config;\n}\n","import { Circle, Container, ContainerChild, Ellipse, Point, Polygon, Rectangle, RoundedRectangle } from 'pixi.js';\nimport { PointLike, Size } from './types';\nimport { resolvePointLike } from './point';\n\nexport type PixiSimpleShape = Rectangle | Circle | Ellipse | RoundedRectangle;\nexport type PixiShape = PixiSimpleShape | Polygon;\n\n/**\n * Reassigns the displays object parent while maintaing it's world position\n * @param pChild\n * @param pParent\n */\nexport function reParent(pChild: ContainerChild, pParent: Container): void {\n if (pChild.parent) {\n pChild.parent.worldTransform.apply(pChild.position as Point, pChild.position as Point);\n }\n pParent.worldTransform.applyInverse(pChild.position as Point, pChild.position as Point);\n pChild.parent?.removeChild(pChild);\n pParent.addChild(pChild);\n}\n\n/**\n *\n * @param pObject\n */\nexport function objectDiagonal(pObject: Container): number {\n return Math.sqrt(pObject.width * pObject.width + pObject.height * pObject.height);\n}\n\n/**\n * Removes provided object from its parent and re-adds it.\n * @param pObject The object to send to the back.\n */\nexport function sendToFront(pObject: Container): void {\n const parent = pObject.parent;\n if (!parent) return;\n parent.removeChild(pObject);\n parent.addChild(pObject);\n}\n\n/**\n * Removes provided object from its parent and re-adds it at index 0.\n * @param pObject The object to send to the back.\n */\nexport function sendToBack(pObject: Container): void {\n const parent = pObject.parent;\n if (!parent) return;\n parent.removeChild(pObject);\n parent.addChildAt(pObject, 0);\n}\n\n/**\n *\n * @param pShape\n * @param pDelta\n */\nexport function offsetShape(pShape: PixiShape, pDelta: Point): PixiShape {\n if (pShape instanceof Polygon) {\n for (let i = 0; i < pShape.points.length; i += 2) {\n pShape.points[i] += pDelta.x;\n pShape.points[i + 1] += pDelta.y;\n }\n return pShape;\n } else {\n pShape.x += pDelta.x;\n pShape.y += pDelta.y;\n return pShape;\n }\n}\n\n/**\n *\n * @param pShape\n * @param pDelta\n */\nexport function offsetSimpleShape(pShape: PixiSimpleShape, pDelta: Point): PixiSimpleShape {\n pShape.x += pDelta.x;\n pShape.y += pDelta.y;\n return pShape;\n}\n\nexport function scaleUniform(obj: any, scaleNum: number, scaleProp: 'width' | 'height' = 'width') {\n const scaleVal: 'x' | 'y' = scaleProp === 'width' ? 'y' : 'x';\n const otherScaleVal: 'x' | 'y' = scaleProp === 'width' ? 'x' : 'y';\n obj[scaleProp] = scaleNum;\n obj.scale[scaleVal] = obj.scale[otherScaleVal];\n}\n\nexport function scaleToWidth(obj: Container, width: number) {\n scaleUniform(obj, width, 'width');\n}\n\nexport function scaleToHeight(obj: Container, height: number) {\n scaleUniform(obj, height, 'height');\n}\n\nexport function scaleToSize(obj: Container, size: PointLike | Size, firstProp: 'width' | 'height' = 'width') {\n let resolvedSize;\n if ((size as Size)?.width && (size as Size)?.height) {\n resolvedSize = { x: (size as Size).width, y: (size as Size).height };\n } else {\n resolvedSize = resolvePointLike(size as PointLike);\n }\n\n if (firstProp === 'width') {\n scaleToWidth(obj, resolvedSize.x);\n if (obj.height < resolvedSize.y) {\n scaleToHeight(obj, resolvedSize.y);\n }\n } else {\n scaleToHeight(obj, resolvedSize.y);\n if (obj.width < resolvedSize.x) {\n scaleToWidth(obj, resolvedSize.x);\n }\n }\n}\n","import { isMobile as PIXIUtilsIsMobile } from 'pixi.js';\n\n/**\n * Checks if the device has a retina display.\n * A device is considered to have a retina display if its device pixel ratio is greater than 1,\n * or if it matches the media query for high resolution displays.\n * @type {boolean}\n */\nexport const isRetina =\n typeof window !== 'undefined'\n ? window.devicePixelRatio > 1 ||\n (window.matchMedia &&\n window.matchMedia(\n '(-webkit-min-device-pixel-ratio: 1.5), (min--moz-device-pixel-ratio: 1.5), (-o-min-device-pixel-ratio: 3/2), (min-resolution: 1.5dppx)',\n ).matches)\n : false;\n\n/**\n * Check if we're on a touch device\n */\nexport const isTouch: boolean =\n typeof window !== 'undefined'\n ? 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator?.maxTouchPoints > 0\n : false;\n\n/**\n * Checks if the device is a mobile device.\n * This uses the `isMobile` function from the `@pixi/utils` package.\n * @type {boolean}\n */\nexport const isMobile = PIXIUtilsIsMobile.any;\nexport const isAndroid = PIXIUtilsIsMobile.android.device;\nexport const isIos = PIXIUtilsIsMobile.apple.device;\n","import { Point, PointLike, Rectangle } from 'pixi.js';\n/**\n *\n * @param rect\n * @param delta\n */\nexport function offset(rect: Rectangle, delta: Point): Rectangle {\n rect.x += delta.x;\n rect.y += delta.y;\n return rect;\n}\n\n/**\n *\n * @param rect\n * @param output\n */\nexport function center(rect: Rectangle, output?: Point): Point {\n if (output === undefined) {\n output = new Point();\n }\n output.set(rect.x + rect.width * 0.5, rect.y + rect.height * 0.5);\n return output;\n}\n\n/**\n * Scale a rectangle by a provided value\n * @param rect\n * @param scale\n */\nexport function scale(rect: Rectangle, scale: number): Rectangle {\n rect.x *= scale;\n rect.y *= scale;\n rect.width *= scale;\n rect.height *= scale;\n return rect;\n}\n\n/**\n * Returns a `Point` representing the width and height of the input Rectangle\n * @param rect\n * @param output\n */\nexport function size(rect: Rectangle, output?: Point): PointLike {\n if (output === undefined) {\n output = new Point();\n }\n output.set(rect.width, rect.height);\n return output;\n}\n","/**\n * Filters a Set based on the provided filter function.\n * @param set The original Set to filter.\n * @param filterFunction The function used to filter the Set.\n * @returns A new Set containing only the elements that satisfy the filter function.\n */\nexport function filterSet<T>(set: Set<T>, filterFunction: (item: T) => boolean): Set<T> {\n const filteredSet = new Set<T>();\n for (const item of set) {\n if (filterFunction(item)) {\n filteredSet.add(item);\n }\n }\n return filteredSet;\n}\n\nexport function firstFromSet<T = any>(set: Set<T>): T | undefined {\n return set?.values().next().value;\n}\n\n/**\n * Gets the last element of a Set.\n * @param set The Set from which to retrieve the last element.\n * @returns The last element of the Set, or undefined if the Set is empty.\n */\nexport function lastFromSet<T>(set: Set<T>): T | undefined {\n let lastElement: T | undefined = undefined;\n for (const item of set) {\n lastElement = item;\n }\n return lastElement;\n}\n","import { CanvasTextMetrics, FederatedEvent, Point, Text } from 'pixi.js';\n\nexport function getNearestCharacterIndex(text: Text, e: FederatedEvent): number {\n const metrics = CanvasTextMetrics.measureText(text.text, text.style);\n const lines = metrics.lines;\n const lineHeight = metrics.lineHeight;\n const position = text.toLocal(new Point(e.pageX, e.pageY));\n\n let closestIndex = 0;\n let minDistance = Infinity;\n\n let currentIndex = 0;\n for (let i = 0; i < lines.length; i++) {\n const lineText = lines[i];\n for (let j = 0; j <= lineText.length; j++) {\n const subText = lineText.substring(0, j);\n const lineMetrics = CanvasTextMetrics.measureText(subText, text.style);\n const charX = lineMetrics.width;\n const charY = i * lineHeight;\n const distance = Math.hypot(charX - position.x, charY - position.y);\n if (distance < minDistance) {\n minDistance = distance;\n closestIndex = currentIndex + j;\n }\n }\n currentIndex += lineText.length;\n }\n\n return closestIndex;\n}\n","// This file is auto-generated during the build process.\nexport const version: string = '0.1.1';\nexport const pixiVersion: string = '8.19.0';\n","import { pixiVersion, version } from './version';\n// https://www.asciiart.eu/image-to-ascii\nconst ascii = ` ........ ..... ............ ............. ........... \n ............. ....... ................ ............. .............. \n .............. ......... ............... ............. .............. \n ..... ........... .............. ............ .............. \n ..... ...... ...... .............. ............. ............. \n .............. ...... ..... ............ ............. ..... ...... \n ................... ..... ..... ............. ..... ....... \n ................ .......... ............. ..... ..... `;\n\nexport function sayHello() {\n const hello = `\\n${ascii}\\n\\n v${version} | %cPixi.js v${pixiVersion} %c| %chttps://github.com/anthonysapp/caper\\n\\n`;\n console.log(\n hello,\n 'color: #E91E63; font-weight: 600;',\n 'color: inherit;',\n 'color: #00BCD4; text-decoration: underline;',\n );\n}\n","export function checkWebGL() {\n if (typeof document === 'undefined') {\n return;\n }\n\n const checkerCanvas = document.createElement('canvas');\n const gl = checkerCanvas.getContext('webgl') || checkerCanvas.getContext('experimental-webgl');\n\n if (!gl) {\n console.error('Your browser does not support WebGL.');\n }\n}\n","import { Container } from './Container';\n\n/**\n * Optional convenience base class for entities discovered from\n * `src/entities/`. The factory system (`this.add.entity(id, props)`) does\n * **not** require entities to extend this class — any class with a\n * single-options-object constructor works. `Entity<Props>` just gives you\n * typed prop storage and a conventional lifecycle for free.\n *\n * **Lifecycle** (inherited from Container):\n *\n * 1. `constructor(props)` — props are stashed on `this.props` before\n * Container's constructor runs. Don't reference `this.app` yet.\n * 2. **addChild** — the factory auto-adds the instance to the calling\n * Container; Pixi emits an `added` event.\n * 3. `added()` — override this to build the display tree using\n * `this.props`. Safe to use `this.app`, `this.add.*`, and any asset.\n * Runs after construction, after stage attachment.\n *\n * @example\n * ```ts\n * import { defineEntity, Entity } from '@caperjs/core';\n *\n * type ActorProps = { color?: number; x?: number; y?: number };\n *\n * export const entity = defineEntity({ id: 'actor' });\n *\n * export default class Actor extends Entity<ActorProps> {\n * added() {\n * this.x = this.props.x ?? 0;\n * this.y = this.props.y ?? 0;\n * this.add.graphics().circle(0, 0, 50).fill(this.props.color ?? 0xffffff);\n * }\n * }\n * ```\n *\n * Then from a scene:\n * ```ts\n * this.add.entity('actor', { color: 0xff0000, x: 50, y: 100 });\n * ```\n */\nexport class Entity<Props = void> extends Container {\n /** Props passed into the factory call. Populated before `added()` fires. */\n public readonly props: Props;\n\n constructor(props?: Props) {\n super();\n this.props = (props ?? ({} as Props)) as Props;\n }\n}\n","import { Ticker } from 'pixi.js';\nimport { PauseConfig } from '../core';\nimport { type AppTypeOverrides, type AssetTypeOverrides, Size } from '../utils';\nimport type { IContainer } from './Container';\nimport { Container } from './Container';\n\ntype AppScenes = AppTypeOverrides['Scenes'];\n\ntype SceneAssetsToLoad = {\n assets?: (string | { alias: string; src: string | string[] })[];\n bundles?: AssetTypeOverrides['Bundles'] | AssetTypeOverrides['Bundles'][];\n};\n\nexport type SceneAssets = {\n preload?: SceneAssetsToLoad;\n background?: SceneAssetsToLoad;\n autoUnload?: boolean;\n};\n\nexport type ScenePlugins = AppTypeOverrides['Plugins'][];\n\nexport type SceneDebug = {\n label?: string;\n group?: string;\n order?: number;\n};\n\nexport type SceneConfig = {\n id?: string;\n dynamic?: boolean;\n active?: boolean;\n assets?: SceneAssets;\n plugins?: ScenePlugins;\n debug?: SceneDebug;\n};\n\nexport interface IScene extends IContainer {\n id: AppScenes;\n label?: string;\n assets?: SceneAssets;\n autoUnloadAssets?: boolean;\n\n enter(): Promise<any>;\n\n exit(): Promise<any>;\n\n initialize(): Promise<void> | void;\n\n start(): Promise<void> | void;\n\n onPause(config: PauseConfig): void;\n\n onResume(config: PauseConfig): void;\n}\n\nexport interface SceneListItem {\n id: string;\n path: string;\n scene: () => Promise<new () => IScene> | IScene;\n debug?: {\n label?: string;\n group?: string;\n };\n assets?: SceneAssets;\n plugins?: ScenePlugins;\n autoUnloadAssets: boolean;\n}\n\n/**\n * Base class for all scenes in a Caper app. A scene is a self-contained\n * unit of game state and display — start screen, level, menu, etc.\n *\n * **Lifecycle order** (per scene load):\n *\n * 1. `constructor` — instantiated by the SceneManager. Don't reference\n * `this.app` here; it's not yet attached to the stage.\n * 2. **Assets load** — anything declared in `assets.preload.bundles` is\n * fetched before `initialize` runs. Background bundles are kicked\n * off in parallel and may complete after.\n * 3. `initialize()` — build the display tree. The scene is on the stage\n * but not yet animated in. Safe to use `this.app`, `this.add.*`,\n * and any preloaded asset.\n * 4. `enter()` — animate the scene in. Override to return a promise /\n * tween / timeline; the manager awaits it before calling `start`.\n * 5. `start()` — fired after `enter` resolves. Begin per-frame work,\n * timers, signal connections, gameplay loops.\n * 6. `update(ticker)` — called every frame while the scene is active.\n * Read `ticker.deltaMS` for frame timing.\n * 7. `resize(size)` — called on viewport resize. Re-layout here.\n * 8. `onPause(config)` / `onResume(config)` — called when the app pauses\n * or resumes. Use to halt/restart non-display work (audio, network).\n * 9. `exit()` — animate the scene out. Awaited before `destroy`.\n * 10. `destroy()` — tear down. The base implementation removes the\n * ticker callback and destroys all children — call `super.destroy()`.\n *\n * Scenes are **discovered automatically** by the Vite plugin walking\n * `src/scenes/`. Annotate the file with `defineScene({ id, assets })`\n * (or individual `export const id` / `export const assets`) to give the\n * scene a stable id and declare its asset bundles.\n *\n * @example\n * ```ts\n * import { defineScene, Scene } from '@caperjs/core';\n *\n * export const scene = defineScene({\n * id: 'menu',\n * assets: { preload: { bundles: ['ui'] } },\n * });\n *\n * export default class MenuScene extends Scene {\n * initialize() {\n * this.add.text({ text: 'Play', anchor: 0.5 });\n * }\n * start() {\n * // begin gameplay loop\n * }\n * destroy() {\n * super.destroy();\n * }\n * }\n * ```\n */\nexport class Scene<Props = void> extends Container implements IScene {\n public readonly id: string;\n public autoUnloadAssets: boolean = false;\n\n /**\n * Runtime props passed via `app.scenes.load(id, props)`. Populated by\n * `SceneManagerPlugin._createCurrentScene` after construction and before\n * `initialize()` runs, so scene authors can read them safely from any\n * lifecycle hook.\n *\n * Subclasses declare the shape via the generic parameter:\n *\n * @example\n * ```ts\n * class LevelScene extends Scene<{ levelId: number; difficulty: 'easy' | 'hard' }> {\n * async start() {\n * const { levelId } = this.props;\n * }\n * }\n * ```\n *\n * For scenes that don't need props, use the default `Scene<void>` (no\n * generic parameter) — `app.scenes.load('menu')` takes no second arg.\n */\n public props!: Props;\n\n protected _animationContext: string;\n public get animationContext(): string {\n return this._animationContext ?? `__scene_${this.id}`;\n }\n public set animationContext(value: string) {\n this._animationContext = value;\n }\n\n constructor() {\n super({ autoResize: true, autoUpdate: true, priority: 'highest' });\n }\n\n /**\n * The assets to load for the scene\n * @private\n * @type {AssetLoadingOptions}\n * @example\n * ```ts\n * assets: {\n * preload: {\n * assets: ['path/to/asset.png'],\n * bundles: ['bundle1', 'bundle2'],\n * },\n * background: {\n * assets: ['path/to/asset.png'],\n * bundles: ['bundle1', 'bundle2'],\n * },\n * }\n * ```\n */\n private _assets: SceneAssets;\n\n get assets(): SceneAssets {\n return this._assets;\n }\n\n set assets(value: SceneAssets) {\n this._assets = value;\n }\n\n /**\n * Build the scene's display tree. Called once after preload assets\n * have loaded and the scene has been added to the stage, but **before**\n * `enter()` animates it in. Safe to use `this.app`, `this.add.*`, and\n * any asset declared in `assets.preload`.\n *\n * Override to construct sprites, text, containers, layouts. Don't put\n * gameplay loops here — that's `start()`.\n *\n * Can be sync or async; the manager awaits the return value before\n * calling `enter`.\n */\n public initialize(): Promise<void> | void;\n\n public async initialize(): Promise<void> {}\n\n /**\n * Animate the scene in. Called after `initialize()` resolves. The\n * manager awaits the returned promise before calling `start()`, so\n * return a tween / timeline / promise to gate the entry on it.\n *\n * Default implementation resolves immediately (no animation).\n *\n * @returns A promise that resolves when the entry animation completes.\n */\n public enter(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Animate the scene out. Called when the SceneManager is unloading\n * this scene. Awaited before `destroy()` runs.\n *\n * Default implementation resolves immediately (no animation).\n *\n * @returns A promise that resolves when the exit animation completes.\n */\n public exit(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Begin per-frame work. Called once after `enter()` resolves; this is\n * where gameplay loops, timers, signal connections, and any work that\n * shouldn't start until the scene is fully visible should live.\n *\n * Override to start tickers, subscribe to input, kick off gameplay.\n * Don't build the display tree here — that's `initialize()`.\n *\n * Can be sync or async.\n */\n public start(): Promise<void> | void;\n\n public async start(): Promise<void> {}\n\n /**\n * Per-frame update hook. Called every tick while the scene is active,\n * after `start()` has resolved. Use `ticker.deltaMS` for time-based\n * motion that's framerate-independent.\n *\n * The base implementation is a no-op; override to drive game logic.\n * The base `destroy()` removes this from the ticker — call\n * `super.destroy()` if you override destroy.\n *\n * @param ticker The Pixi ticker; provides `deltaMS`, `deltaTime`, etc.\n */\n public update(ticker?: Ticker) {\n void ticker;\n }\n\n /**\n * Re-layout on viewport resize. Called whenever the host element /\n * window size changes. Use to reposition or rescale display elements\n * relative to the new viewport size.\n *\n * @param size New viewport dimensions.\n * @override\n */\n public resize(size?: Size): void {\n void size;\n }\n\n /**\n * Tear down the scene. The base implementation removes this scene\n * from the ticker (so `update` stops firing) and destroys all child\n * display objects. **Always call `super.destroy()`** if you override\n * — otherwise the ticker callback leaks.\n *\n * Override to clean up listeners, signal connections, timers, network\n * subscriptions, or anything else not handled by Pixi's destroy.\n */\n public destroy() {\n this.app.ticker.remove(this.update);\n super.destroy({ children: true });\n }\n\n /**\n * Called when the application is paused. Use to halt non-display\n * work — audio, network polling, gameplay timers. Display state\n * stays on screen; only logic should pause.\n *\n * @param config Pause options (e.g. which subsystems to pause).\n */\n public onPause(config: PauseConfig): void {\n void config;\n }\n\n /**\n * Called when the application resumes from a pause. Use to restart\n * whatever was halted in `onPause`.\n *\n * @param config Resume options.\n */\n public onResume(config: PauseConfig): void {\n void config;\n }\n}\n","import { Sprite, Ticker } from 'pixi.js';\nimport { type Size } from '../utils';\nimport { Container } from './Container';\n\nexport interface ISceneTransition extends Container {\n initialized: boolean;\n progress: number;\n active: boolean;\n destroy(): void;\n enter(): Promise<any> | void;\n exit(): Promise<any> | void;\n initialize(): void;\n}\n\nexport class SceneTransition extends Container {\n public initialized: boolean = false;\n protected __background: Sprite;\n\n private _active: boolean = false;\n\n get active(): boolean {\n return this._active;\n }\n\n set active(value: boolean) {\n this._active = value;\n }\n\n private _progress: number;\n\n get progress(): number {\n return this._progress;\n }\n\n set progress(value: number) {\n this._progress = value;\n }\n\n constructor(autoUpdate: boolean = false) {\n super({ autoResize: true, autoUpdate: false, priority: -9999 });\n\n if (autoUpdate) {\n this.app.ticker.add(this._update);\n }\n\n this.addSignalConnection(\n this.app.assets.onLoadStart.connect(this.handleLoadStart),\n this.app.assets.onLoadProgress.connect(this.handleLoadProgress),\n this.app.assets.onLoadProgress.connect(this.handleLoadComplete),\n );\n }\n\n public initialize(): void;\n public async initialize(): Promise<void> {\n return Promise.resolve();\n }\n\n public resize(size: Size): void {\n void size;\n }\n\n public destroy(): void {\n this.app.ticker.remove(this._update);\n this.initialized = false;\n this._active = false;\n this._progress = 0;\n super.destroy();\n }\n\n /**\n * Called to animate the scene in\n * @returns {Promise<void>}\n */\n public enter(): void;\n public async enter(): Promise<any> {\n return Promise.resolve();\n }\n\n /**\n * Called to animate the scene out\n * @returns {Promise<void>}\n */\n public exit(): void;\n public async exit(): Promise<any> {\n return Promise.resolve();\n }\n\n protected handleLoadStart() {\n // signifies the preloading phase has started for the new scene\n }\n\n protected handleLoadProgress(progress: number) {\n // the preloading progress for the loading scene\n this._progress = progress;\n }\n\n protected handleLoadComplete() {\n // signifies the preloading phase is complete for the new scene\n }\n\n // check if initialized and active before calling update\n // this way we're sure in the case of a Splash sccreen, all the assets are loaded and the scene is initialized\n private _update(ticker: Ticker) {\n if (this.active && this.initialized) {\n this.update(ticker);\n }\n }\n}\n","import { Container, Point } from 'pixi.js';\nimport { IApplication } from '../core';\nimport { Application } from '../core/Application';\nimport type { KeyboardEventDetail } from '../plugins';\nimport { Signal } from '../signals';\nimport type { ContainerLike, PointLike } from '../utils';\nimport { bindAllMethods, resolvePointLike } from '../utils';\n\ntype CameraConfig = {\n container: Container;\n minX: number;\n maxX: number;\n minY: number;\n maxY: number;\n viewportWidth: number;\n viewportHeight: number;\n worldWidth: number;\n worldHeight: number;\n target: ContainerLike | null;\n targetPivot: Point;\n lerp: number;\n};\n\n// require container to be set\ntype OptionalCameraConfig = Partial<CameraConfig>;\ntype RequiredCameraConfig = Required<Pick<CameraConfig, 'container'>>;\ntype CustomCameraConfig = OptionalCameraConfig & RequiredCameraConfig;\n\nexport interface ICamera {\n onZoom: Signal<(camera?: ICamera) => void>;\n onZoomComplete: Signal<(camera?: ICamera) => void>;\n container: Container;\n minX: number;\n minY: number;\n maxX: number;\n maxY: number;\n viewportWidth: number;\n viewportHeight: number;\n worldWidth: number;\n worldHeight: number;\n readonly targetPivot: Point;\n readonly targetScale: Point;\n readonly zooming: boolean;\n readonly zoomLerp: number;\n readonly lerp: number;\n readonly target: ContainerLike | null;\n readonly followOffset: Point;\n app: IApplication;\n\n follow(target: ContainerLike, offset: PointLike): void;\n\n pan(deltaX: number, deltaY: number): void;\n\n zoom(scale: number, lerp?: number): void;\n\n update(): void;\n}\n\nexport class Camera extends Container implements ICamera {\n public onZoom = new Signal<(camera?: ICamera) => void>();\n public onZoomComplete = new Signal<(camera?: ICamera) => void>();\n public container: Container;\n public minX: number = 0;\n public minY: number = 0;\n public maxX: number;\n public maxY: number;\n public viewportWidth: number;\n public viewportHeight: number;\n public worldWidth: number;\n public worldHeight: number;\n\n constructor(public config: CustomCameraConfig) {\n super({ isRenderGroup: true });\n bindAllMethods(this);\n if (config) {\n this.container = config.container;\n this.addChild(this.container);\n if (config.minX) {\n this.minX = config.minX;\n }\n if (config.maxX) {\n this.maxX = config.maxX;\n }\n if (config.minY) {\n this.minY = config.minY;\n }\n this.viewportWidth = config.viewportWidth ?? this.app.size.width;\n this.viewportHeight = config.viewportHeight ?? this.app.size.width;\n this.worldWidth = config.worldWidth ?? this.viewportWidth;\n this.worldHeight = config.worldHeight ?? this.viewportHeight;\n this.maxX = config.maxX ?? this.worldWidth - this.viewportWidth;\n this.maxY = config.maxY ?? this.worldHeight - this.viewportHeight;\n }\n\n this._targetPivot.set(this.viewportWidth * 0.5, this.viewportHeight * 0.5);\n if (config.target) {\n this.target = config.target;\n }\n this._lerp = 1;\n this.update();\n if (config.lerp) {\n this.lerp = config.lerp;\n }\n return this;\n }\n\n protected _zooming: boolean = false;\n\n get zooming(): boolean {\n return this._zooming;\n }\n\n protected _zoomLerp: number = 0.1;\n\n get zoomLerp(): number {\n return this._zoomLerp;\n }\n\n protected _targetPivot: Point = new Point(0, 0);\n\n get targetPivot(): Point {\n return this._targetPivot;\n }\n\n protected _targetScale: Point = new Point(1, 1);\n\n get targetScale(): Point {\n return this._targetPivot;\n }\n\n private _lerp: number = 0;\n\n get lerp(): number {\n return this._lerp;\n }\n\n set lerp(value: number) {\n // if the value is less than 0 or greater than 1, clamp it to the range [0, 1], and log an error\n if (value < 0 || value > 1) {\n throw new Error('Camera lerp value must be in the range [0, 1]');\n }\n this._lerp = Math.max(0, Math.min(value, 1));\n }\n\n protected _target: ContainerLike | null = null;\n\n get target(): ContainerLike | null {\n return this._target;\n }\n\n set target(value: ContainerLike | null) {\n this._target = value;\n if (this._target) {\n this.focusOn(this._target);\n }\n }\n\n protected _followOffset: Point = new Point(0, 0);\n get followOffset(): Point {\n return this._followOffset;\n }\n\n set followOffset(value: PointLike) {\n this._followOffset = resolvePointLike(value, true);\n }\n\n get app(): IApplication {\n return Application.getInstance();\n }\n\n follow(target: ContainerLike, offset?: PointLike) {\n if (!offset) {\n offset = { x: 0, y: 0 };\n }\n this.followOffset = offset;\n this.target = target;\n }\n\n pan(deltaX: number, deltaY: number) {\n let newPivotX = this.pivot.x + deltaX;\n let newPivotY = this.pivot.y + deltaY;\n\n // Clamp pivot to min and max values\n newPivotX = Math.max(this.minX, Math.min(newPivotX, this.maxX));\n newPivotY = Math.max(this.minY, Math.min(newPivotY, this.maxY));\n\n this._targetPivot.set(newPivotX, newPivotY);\n }\n\n zoom(scale: number, lerp: number = 0.1) {\n this._zoomLerp = lerp;\n this._zooming = true;\n this._targetScale.set(scale, scale);\n }\n\n update() {\n this.updateZoom();\n if (this._target) {\n this.focusOn(this._target);\n }\n this.updatePosition(this._zooming);\n if (\n this._zooming &&\n Math.abs(this.scale.x - this._targetScale.x) < 0.001 &&\n Math.abs(this.scale.y - this._targetScale.y) < 0.001\n ) {\n this.onZoom.emit(this);\n this._zooming = false;\n this.scale.set(this._targetScale.x, this._targetScale.y);\n this.onZoomComplete.emit(this);\n } else if (this._zooming) {\n this.onZoom.emit(this);\n }\n }\n\n private focusOn(entity: ContainerLike) {\n // Get the global position of the entity and convert it to the local position within the container.\n const globalPosition = entity.getGlobalPosition();\n const spritePosition = this.toLocal(globalPosition);\n\n const posXModifier = this.position.x / this.scale.x - this.viewportWidth / 2;\n const posYModifier = this.position.y / this.scale.y - this.viewportHeight / 2;\n\n const offsetX = this.followOffset.x / this.scale.x;\n const offsetY = this.followOffset.y / this.scale.y;\n\n this._targetPivot.x = (spritePosition.x * this.scale.x + this.viewportWidth / 2) * (1 / this.scale.x) + offsetX;\n\n const tMinX = this.viewportWidth / this.scale.x / 2 + posXModifier + this.minX - offsetX;\n const tMaxX = this.worldWidth - this.viewportWidth / this.scale.x / 2 + posXModifier + this.maxX + offsetX;\n\n if (this._targetPivot.x < tMinX) {\n this._targetPivot.x = tMinX;\n } else if (this._targetPivot.x > tMaxX) {\n this._targetPivot.x = tMaxX;\n }\n\n this._targetPivot.y = (spritePosition.y * this.scale.y + this.viewportHeight / 2) * (1 / this.scale.y) + offsetY;\n\n const tMinY = this.viewportHeight / this.scale.y / 2 + posYModifier + this.minY - offsetY;\n const tMaxY = this.worldHeight - this.viewportHeight / this.scale.y / 2 + posYModifier + this.maxY - offsetY;\n\n if (this._targetPivot.y < tMinY) {\n this._targetPivot.y = tMinY;\n } else if (this._targetPivot.y > tMaxY) {\n this._targetPivot.y = tMaxY;\n }\n }\n\n private updateZoom() {\n const currentScaleX = this.scale.x;\n const currentScaleY = this.scale.y;\n\n const interpolatedScaleX = currentScaleX + this._zoomLerp * (this._targetScale.x - currentScaleX);\n const interpolatedScaleY = currentScaleY + this._zoomLerp * (this._targetScale.y - currentScaleY);\n\n this.scale.set(Math.max(0, interpolatedScaleX), Math.max(0, interpolatedScaleY));\n }\n\n private updatePosition(skipLerp: boolean = false) {\n if (this.lerp > 0 && !skipLerp) {\n // Current pivot positions\n const currentPivotX = this.pivot.x;\n const currentPivotY = this.pivot.y;\n\n // Calculate interpolated pivot positions\n const interpolatedPivotX = currentPivotX + this.lerp * (this._targetPivot.x - currentPivotX);\n const interpolatedPivotY = currentPivotY + this.lerp * (this._targetPivot.y - currentPivotY);\n\n // Set the pivot to the interpolated position to smooth out the camera movement\n this.pivot.set(interpolatedPivotX, interpolatedPivotY);\n } else {\n this.pivot.set(this._targetPivot.x, this._targetPivot.y);\n }\n\n this.position.set(this.viewportWidth / 2, this.viewportHeight / 2);\n }\n}\n\nexport class CameraController {\n private dragging: boolean = false;\n private previousPointerPosition: Point | null = null;\n\n constructor(\n public camera: Camera,\n public interactiveArea: Container,\n ) {\n bindAllMethods(this);\n this.camera = camera;\n this.interactiveArea = interactiveArea;\n this.app.keyboard.onKeyDown().connect(this.handleKeyDown);\n // Keyboard events\n\n // Mouse and touch events\n this.interactiveArea.on('pointerdown', this.onPointerDown.bind(this));\n this.interactiveArea.on('pointermove', this.onPointerMove.bind(this));\n this.app.stage.on('pointerup', this.onPointerUp.bind(this));\n this.app.stage.on('pointerupoutside', this.onPointerUp.bind(this));\n\n // Touch events equivalent\n this.interactiveArea.on('touchstart', this.onPointerDown.bind(this));\n this.interactiveArea.on('touchmove', this.onPointerMove.bind(this));\n this.interactiveArea.on('touchend', this.onPointerUp.bind(this));\n }\n\n get app(): IApplication {\n return Application.getInstance();\n }\n\n destroy() {\n // Mouse and touch events\n this.interactiveArea.removeAllListeners();\n this.app.stage.off('pointerup', this.onPointerUp.bind(this));\n this.app.stage.off('pointerupoutside', this.onPointerUp.bind(this));\n }\n\n private handleKeyDown(detail: KeyboardEventDetail) {\n const panSpeed = 10; // Adjust pan speed as necessary\n const zoomFactor = 1.1; // Adjust zoom factor as necessary\n\n switch (detail.event.key) {\n case 'ArrowUp':\n this.camera.pan(0, -panSpeed);\n break;\n case 'ArrowDown':\n this.camera.pan(0, panSpeed);\n break;\n case 'ArrowLeft':\n this.camera.pan(-panSpeed, 0);\n break;\n case 'ArrowRight':\n this.camera.pan(panSpeed, 0);\n break;\n case '+':\n this.camera.zoom(zoomFactor);\n break;\n case '-':\n this.camera.zoom(1 / zoomFactor);\n break;\n }\n }\n\n private onPointerDown(event: MouseEvent | TouchEvent) {\n this.dragging = true;\n this.previousPointerPosition = this.getEventPosition(event);\n }\n\n private onPointerMove(event: MouseEvent | TouchEvent) {\n if (!this.dragging || !this.previousPointerPosition) return;\n\n const currentPosition = this.getEventPosition(event);\n const deltaX = currentPosition.x - this.previousPointerPosition.x;\n const deltaY = currentPosition.y - this.previousPointerPosition.y;\n\n this.camera.pan(deltaX, deltaY);\n this.previousPointerPosition = currentPosition;\n }\n\n private onPointerUp() {\n this.dragging = false;\n this.previousPointerPosition = null;\n }\n\n private getEventPosition(event: MouseEvent | TouchEvent): Point {\n if (event instanceof TouchEvent) {\n return new Point(event.touches[0].clientX, event.touches[0].clientY);\n } else {\n return new Point(event.clientX, event.clientY);\n }\n }\n}\n","import {\n Bounds,\n CanvasTextMetrics,\n FederatedEvent,\n FederatedPointerEvent,\n Graphics,\n Container as PIXIContainer,\n Rectangle,\n Sprite,\n Text,\n Texture,\n} from 'pixi.js';\n\nimport { Focusable, Interactive, TextProps, WithSignals } from '../mixins';\n\nimport {\n EaseString,\n ensurePadding,\n getNearestCharacterIndex,\n isAndroid,\n isMobile,\n isTouch,\n Logger,\n Padding,\n PointLike,\n resolvePointLike,\n} from '../utils';\n\nimport { gsap } from 'gsap';\nimport { Container } from '../display';\nimport { Signal } from '../signals';\n\n/**\n * Options for styling the input background\n * @interface BgStyleOptions\n */\nexport type BgStyleOptions = {\n /** Border radius of the input background */\n radius: number;\n /** Fill style for the background */\n fill: { color?: number; alpha?: number };\n /** Stroke style for the background border */\n stroke: { width?: number; color?: number; alpha?: number };\n};\n\n/**\n * Color configuration options\n * @interface ColorOptions\n */\nexport type ColorOptions = {\n /** Color in hexadecimal format */\n color: number;\n /** Alpha transparency value (0-1) */\n alpha: number;\n};\n\n/**\n * Placeholder text configuration\n * @interface PlaceholderOptions\n */\nexport type PlaceholderOptions = {\n /** Text to display as placeholder */\n text: string;\n};\n\n/**\n * Focus overlay configuration for mobile/touch interactions\n * @interface FocusOverlayOptions\n * @example\n * ```typescript\n * const overlaySettings = {\n * activeFilter: ['mobile', 'touch'],\n * marginTop: 60,\n * scale: 2.5,\n * backing: { active: true, color: 0x0 }\n * };\n * ```\n */\nexport type FocusOverlayOptions = {\n /** Enable overlay for specific platforms */\n mobile: boolean;\n touch: boolean;\n desktop: boolean;\n /** Custom filter for when to show overlay */\n activeFilter?: boolean | (() => boolean) | ('mobile' | 'touch' | 'desktop')[];\n /** Scale factor for the overlay */\n scale: number;\n /** Top margin for the overlay */\n marginTop: number;\n /** Backing configuration */\n backing: {\n active: boolean;\n options: Partial<ColorOptions>;\n };\n};\n\n/**\n * Extended placeholder options with animation and positioning\n * @interface ExtraPlaceholderOptions\n * @example\n * ```typescript\n * const placeholderConfig = {\n * positionOnType: 'top',\n * offsetOnType: { x: 0, y: -20 },\n * scaleOnType: { x: 0.8, y: 0.8 },\n * animationOnType: {\n * duration: 0.3,\n * ease: 'sine.out',\n * tint: 0x666666,\n * alpha: 0.5\n * }\n * };\n * ```\n */\ntype ExtraPlaceholderOptions = {\n /** Position of placeholder when typing */\n positionOnType: 'top' | 'bottom';\n /** Offset from original position when typing */\n offsetOnType: PointLike;\n /** Scale factor when typing */\n scaleOnType: PointLike;\n /** Animation configuration when typing */\n animationOnType: {\n duration: number;\n ease: EaseString;\n tint: number;\n alpha: number;\n };\n};\n\n/**\n * Main configuration options for the Input component\n * @interface InputOptions\n * @example\n * ```typescript\n * const input = new Input({\n * value: 'Initial value',\n * type: 'text',\n * minWidth: 400,\n * padding: [12, 15],\n * placeholder: {\n * text: 'Enter text...',\n * color: 0x666666\n * },\n * bg: {\n * radius: 10,\n * stroke: { width: 2, color: 0x000000 }\n * },\n * focusOverlay: {\n * activeFilter: ['mobile', 'touch'],\n * scale: 2.5\n * }\n * });\n * ```\n */\nexport interface InputOptions extends Partial<TextProps> {\n /** Initial value of the input */\n value: string;\n /** Input type (text, password, number, etc.) */\n type: 'text' | 'password' | 'number' | 'email' | 'tel' | 'url';\n /** Whether the input width is fixed */\n fixed: boolean;\n /** Pattern for input validation */\n pattern: string;\n /** Enable debug mode */\n debug: boolean;\n /** Minimum width of the input */\n minWidth: number;\n /** Padding configuration */\n padding: Padding;\n /** Maximum length of input */\n maxLength?: number;\n /** Whether to blur on Enter key */\n blurOnEnter: boolean;\n /** Custom regex for validation */\n regex?: RegExp;\n /** Background style configuration */\n bg: Partial<BgStyleOptions>;\n /** Placeholder configuration */\n placeholder: Partial<PlaceholderOptions & ColorOptions & ExtraPlaceholderOptions>;\n /** Selection highlight configuration */\n selection: Partial<ColorOptions>;\n /** Caret configuration */\n caret: Partial<ColorOptions>;\n /** Error state styling */\n error?: {\n input?: {\n fill?: number;\n };\n bg?: Partial<Omit<BgStyleOptions, 'stroke'>>;\n };\n /** Focus overlay configuration */\n focusOverlay: Partial<FocusOverlayOptions>;\n}\n\nexport interface InputProps extends Omit<InputOptions, 'padding'> {\n padding: PointLike | Padding | number[] | number;\n}\n\nexport type InputDetail = {\n value: string;\n input: Input;\n domElement: HTMLInputElement;\n};\n\nconst defaultOptions: InputOptions = {\n value: '',\n type: 'text',\n fixed: true,\n pattern: '',\n debug: false,\n minWidth: 200,\n padding: { top: 0, left: 0, bottom: 0, right: 0 },\n blurOnEnter: true,\n style: {\n fontFamily: 'Arial',\n fill: '#000000',\n fontSize: 20,\n fontWeight: 'bold',\n },\n bg: {\n radius: 5,\n fill: { color: 0xffffff },\n stroke: { width: 1, color: 0x0 },\n },\n placeholder: {},\n selection: { color: 0x00ff00 },\n caret: {\n color: 0x0,\n alpha: 0.8,\n },\n focusOverlay: {\n activeFilter: false,\n scale: 1,\n marginTop: 60,\n },\n};\n\nconst AVAILABLE_TYPES = ['text', 'password', 'number', 'email', 'tel', 'url'];\n\n/**\n * A highly customizable input component with mobile/touch support\n * @class Input\n * @extends Focusable(Interactive(WithSignals(Container)))\n *\n * @example\n * ```typescript\n * // Basic text input\n * const basicInput = new Input({\n * minWidth: 400,\n * placeholder: { text: 'Enter text' },\n * padding: [12, 15]\n * });\n *\n * // Password input with validation\n * const passwordInput = new Input({\n * type: 'password',\n * minWidth: 400,\n * placeholder: { text: 'Enter password' },\n * maxLength: 20,\n * regex: /^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d]{8,}$/\n * });\n *\n * // Phone number input with validation\n * const phoneInput = new Input({\n * type: 'tel',\n * regex: /^1?-?\\(?([2-9][0-9]{2})\\)?[-. ]?([2-9][0-9]{2})[-. ]?([0-9]{4})$/,\n * error: {\n * input: { fill: 0xff0000 },\n * bg: { fill: 0xf5e0df }\n * }\n * });\n * ```\n */\nexport class Input extends Focusable(Interactive(WithSignals(Container))) {\n /**\n * Emitted when the Enter key is pressed\n * @event onEnter\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onEnter: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Emitted when the input value changes\n * @event onChange\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onChange: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Emitted when validation fails\n * @event onError\n * @type {Signal<(detail: InputDetail) => void>}\n */\n public onError: Signal<(detail: InputDetail) => void> = new Signal<(detail: InputDetail) => void>();\n\n /**\n * Input configuration options\n * @type {InputOptions}\n */\n public options: InputOptions;\n\n /**\n * Background graphics container\n * @type {Graphics}\n */\n public bg: Graphics;\n\n /**\n * Caret (cursor) container\n * @type {PIXIContainer}\n */\n public caret: PIXIContainer;\n\n /**\n * Text input container\n * @type {Text}\n */\n public input: Text;\n\n /**\n * Placeholder text container\n * @type {Text}\n */\n public placeholder: Text;\n\n /**\n * Current error state\n * @type {boolean}\n */\n public error: boolean;\n\n // Protected properties\n protected cursorAnimation: gsap.core.Tween;\n protected domElement: HTMLInputElement;\n protected selectionGraphics: Graphics;\n protected cloneOverlay: Input;\n protected overlayBacking: Sprite;\n\n // Private properties\n private _focusTimer: any;\n private _pointerDownTimer: any;\n private _inner: Container;\n private _inputContainer: Container;\n private _placeholderContainer: Container;\n private _mask: Graphics;\n private _lastWidth: number = 0;\n private _lastHeight: number = 0;\n private _placeholderPositioned: boolean = false;\n private _placeholderAnimating: boolean = false;\n private _caretPosition: number = -1;\n private _selectionRect: Rectangle | null;\n private _regex: RegExp;\n private _value: string = '';\n\n constructor(\n options: Partial<InputProps>,\n public isClone: boolean = false,\n public clone: Input | null = null,\n ) {\n super({ autoUpdate: true, autoResize: !isClone });\n\n this.options = {\n ...defaultOptions,\n ...options,\n style: {\n ...defaultOptions.style,\n ...(options?.style ?? {}),\n },\n padding: ensurePadding(options.padding ?? defaultOptions.padding),\n bg: {\n ...defaultOptions.bg,\n ...(options.bg ?? {}),\n },\n focusOverlay: {\n ...defaultOptions.focusOverlay,\n ...(options.focusOverlay ?? {}),\n },\n };\n\n if (this.options.layout && typeof this.options.layout === 'object') {\n this.layout = { ...this.options.layout };\n } else {\n this.layout = { transformOrigin: 'top left' };\n }\n\n if (!this.options.placeholder) {\n this.options.placeholder = {\n color: Number(this.options.style?.fill) ?? 0x666666,\n };\n }\n\n this._inner = this.add.container({\n layout: { position: 'relative', top: 0, left: 0, width: '100%', height: '100%' },\n });\n this.addBg();\n\n this._inputContainer = this._inner.add.container({\n y: -2,\n layout: {\n position: 'absolute',\n transformOrigin: 'top left',\n inset: 0,\n width: '100%',\n height: '100%',\n },\n });\n this._placeholderContainer = this._inner.add.container({\n y: -2,\n layout: {\n position: 'absolute',\n inset: 0,\n transformOrigin: 'top left',\n width: '100%',\n height: '100%',\n },\n });\n this._placeholderContainer.eventMode = 'none';\n this.addSelection();\n this.addCaret();\n this.addInput();\n this.addPlaceholder();\n\n this.placeholder.text = this.options.placeholder.text || `Enter ${this.options.type}`;\n\n this.input.eventMode = this.placeholder.eventMode = 'none';\n\n if (isTouch) {\n this.addSignalConnection(this.onInteraction('pointertap').connect(this.handleClick, -1));\n }\n this.addSignalConnection(this.onInteraction('click').connect(this.handleClick, -1));\n\n if (this.options.fixed) {\n const scale = this.isClone ? (this.clone?.options?.focusOverlay?.scale ?? 1) : 1;\n this._mask = this._inner.add\n .graphics()\n .rect(\n 0,\n 0,\n this.bg.width * scale - this.options.padding.left - this.options.padding.right,\n this.bg.height * scale - this.options.padding.top - this.options.padding.bottom,\n )\n .fill({ color: 0x0 });\n this._inputContainer.mask = this._mask;\n }\n }\n\n /**\n * Gets the current caret (cursor) position\n * @readonly\n * @returns {number} The caret position in pixels from the left\n */\n get caretPosition() {\n return this._caretPosition;\n }\n\n /**\n * Gets the current selection rectangle\n * @readonly\n * @returns {Rectangle | null} The selection rectangle or null if no selection\n */\n get selectionRect() {\n return this._selectionRect;\n }\n\n /**\n * Sets the validation regex\n * @param {RegExp} value - The regular expression to use for validation\n */\n set regex(value: RegExp) {\n this._regex = value;\n }\n\n /**\n * Gets whether the current input value is valid\n * @readonly\n * @returns {boolean} True if the input is valid\n */\n get isValid(): boolean {\n let result = false;\n if (this.domElement) {\n if (this._regex) {\n result = this._regex.test(this._value);\n } else {\n if (this.options.type === 'text') {\n return true;\n }\n this.domElement.required = true;\n result = this.domElement.checkValidity();\n this.domElement.required = false;\n }\n }\n return result;\n }\n\n /**\n * Gets the current input value\n * @returns {string} The current value\n */\n public get value() {\n return this._value?.trim() ?? '';\n }\n\n /**\n * Sets the input value\n * @param {string} value - The value to set\n */\n public set value(value: string) {\n if (this.domElement) {\n this.domElement.value = value;\n const event = new Event('input', {\n bubbles: true,\n cancelable: true,\n });\n this.domElement.dispatchEvent(event);\n } else {\n this._value = value;\n this.input.text = value;\n }\n }\n\n /**\n * Resizes the input component\n * Updates the clone overlay position if it exists\n */\n resize() {\n super.resize();\n if (this.cloneOverlay) {\n this._positionCloneOverlay();\n }\n }\n\n /**\n * Redraws the background graphics\n */\n resetBg() {\n this.drawBg();\n }\n\n /**\n * Called when the component is added to the display list\n * Shows the cursor if this is a clone\n */\n added() {\n super.added();\n if (this.isClone) {\n this.showCursor();\n }\n }\n\n /**\n * Handles click/tap events on the input\n * Creates the DOM element and positions the caret\n * @param {FederatedEvent} [e] - The pointer event\n */\n handleClick(e?: FederatedEvent) {\n // check if this was a triggered event from the FocusMnagerPlugin\n if ((e?.originalEvent as unknown as KeyboardEvent)?.key) {\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n const nearestCharacterIndex = e ? getNearestCharacterIndex(this.input, e) : (this.input.text?.length ?? 0);\n this.createDomElement(nearestCharacterIndex);\n // this._focusDomElement(nearestCharacterIndex);\n }\n\n /**\n * Focuses the input\n * Creates the DOM element and shows the cursor\n */\n focusIn() {\n this.handleClick();\n }\n\n _focusDomElement(selection?: number) {\n this._focusTimer = setTimeout(() => {\n this._triggerFocusAndSelection(selection);\n }, 100);\n }\n\n _triggerFocusAndSelection(selection?: number) {\n if (this.domElement) {\n try {\n this.domElement.focus();\n this.domElement.click();\n if (selection === undefined) {\n this.domElement.selectionStart = this.domElement?.value?.length;\n } else {\n this.domElement.setSelectionRange(selection, selection, 'none');\n }\n } catch (e) {\n // nothing\n }\n this._updateCaretAndSelection();\n }\n }\n\n _checkPointerDownOutside(e: FederatedPointerEvent) {\n const pos = this.toLocal(e.data.global);\n if (this.getBounds().rectangle.contains(pos.x, pos.y)) {\n this.focusIn();\n } else {\n this.focusOut();\n }\n }\n\n /**\n * Blurs (unfocuses) the input\n * Removes the DOM element and hides the cursor\n */\n focusOut() {\n this.domElement?.blur();\n }\n\n update() {\n this.bg.x = 0;\n this.bg.y = 0;\n\n // size background\n const bgHeight =\n this.input.getLocalBounds().y +\n this.input.style.fontSize +\n this.options.padding.top +\n this.options.padding.bottom;\n\n const bgWidth = this.options.fixed\n ? this.options.minWidth\n : Math.max(this.options.minWidth, this.input.width) + this.options.padding.left + this.options.padding.right;\n\n // position inputs\n // the 'align' property doesn't affect single line text,\n // so we need to do this manually\n const diff = this.options.minWidth - bgWidth + this.options.padding.left + this.options.padding.right;\n const inputAvailableWidth = bgWidth - this.options.padding.left - this.options.padding.right;\n\n switch (this.input.style.align) {\n case 'center':\n this.input.x = bgWidth / 2 - this.input.width / 2;\n if (!this._placeholderPositioned) {\n this.placeholder.x = bgWidth / 2 - this.placeholder.width / 2;\n }\n this._inner.x = diff >= 0 ? 0 : diff / 2;\n if (this.options.fixed) {\n const inputDiff = this.input.width - inputAvailableWidth;\n if (inputDiff > 0) {\n this.input.x -= inputDiff / 2;\n }\n }\n break;\n case 'right':\n this.input.x = bgWidth - this.options.padding.right - this.input.width;\n if (!this._placeholderPositioned) {\n this.placeholder.x = bgWidth - this.options.padding.right - this.placeholder.width;\n }\n this._inner.x = diff >= 0 ? 0 : diff;\n break;\n default:\n this.input.x = this.options.padding.left;\n if (!this._placeholderPositioned) {\n this.placeholder.x = this.options.padding.left;\n }\n this._inner.x = 0;\n if (this.options.fixed) {\n const inputDiff = this.input.width - inputAvailableWidth;\n if (inputDiff > 0) {\n this.input.x -= inputDiff;\n }\n }\n break;\n }\n\n this.input.y = this.options.padding.top;\n if (!this._placeholderPositioned) {\n this.placeholder.y = this.input.y;\n }\n\n if (this.isClone && this.clone) {\n const cloneScale = this.clone.options?.focusOverlay?.scale ?? 1;\n this.error = this.clone.error;\n this._value = this.clone.input.text;\n this.input.text = this._value;\n this._selectionRect = this.clone.selectionRect!.clone();\n this._selectionRect.x *= cloneScale;\n this._selectionRect.y *= cloneScale;\n this._selectionRect.width *= cloneScale;\n this._selectionRect.height *= cloneScale;\n this._caretPosition = this.clone.caretPosition * cloneScale;\n }\n // position caret\n this.caret.x = this._caretPosition >= 0 ? this.input.x + this._caretPosition : this.input.x + this.input.width + 1;\n this.caret.y = this.input.y - 2;\n this.caret.height = this.input.style.fontSize * 1.15;\n\n // check if value is empty\n if (this.value === '') {\n this.placeholder.visible = true;\n if (!this.isClone && this._placeholderPositioned && !this._placeholderAnimating) {\n this._placeholderAnimating = true;\n const tx = this.input.x;\n const ty = this.input.y;\n if (this.options.placeholder.animationOnType) {\n this.addAnimation([\n gsap.to(this.placeholder, {\n x: tx,\n y: ty,\n tint: 0xffffff,\n alpha: this.options.placeholder.alpha ?? 1,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'sine.in',\n overwrite: true,\n onComplete: () => {\n this._placeholderPositioned = false;\n this._placeholderAnimating = false;\n },\n }),\n gsap.to(this.placeholder.scale, {\n x: 1,\n y: 1,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'sine.out',\n overwrite: true,\n }),\n ]);\n } else {\n this.placeholder.x = tx;\n this.placeholder.y = ty;\n this.placeholder.scale.set(1, 1);\n this._placeholderPositioned = false;\n this._placeholderAnimating = false;\n }\n }\n } else {\n if (!this.isClone && this.options.placeholder.positionOnType) {\n this.placeholder.visible = true;\n if (!this._placeholderPositioned) {\n this._placeholderPositioned = true;\n let tx = this.placeholder.x;\n let ty = this.placeholder.y;\n switch (this.options.placeholder.positionOnType) {\n case 'top':\n ty = this.input.y - this.placeholder.height - this.options.padding.top;\n break;\n case 'bottom':\n ty = this.input.y + this.input.height + this.options.padding.bottom;\n break;\n }\n\n if (this.options.placeholder.offsetOnType) {\n const offset = resolvePointLike(this.options.placeholder.offsetOnType);\n tx += offset.x;\n ty += offset.y;\n }\n\n if (this.options.placeholder.animationOnType) {\n this.addAnimation(\n gsap.to(this.placeholder, {\n x: tx,\n y: ty,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'none',\n tint: this.options.placeholder.animationOnType.tint ?? null,\n alpha: this.options.placeholder.animationOnType.alpha ?? this.options.placeholder.alpha ?? 1,\n overwrite: true,\n }),\n );\n\n if (this.options.placeholder.scaleOnType) {\n const scale = resolvePointLike(this.options.placeholder.scaleOnType);\n this.addAnimation(\n gsap.to(this.placeholder.scale, {\n x: scale.x,\n y: scale.y,\n duration: this.options.placeholder.animationOnType.duration || 0.4,\n ease: this.options.placeholder.animationOnType.ease || 'none',\n overwrite: true,\n }),\n );\n }\n } else {\n this.placeholder.x = tx;\n this.placeholder.y = ty;\n }\n }\n } else {\n this.placeholder.visible = false;\n }\n }\n\n if (this.options.fixed) {\n const scale = this.isClone ? (this.options?.focusOverlay?.scale ?? 1) : 1;\n if (this._mask) {\n this._mask\n .clear()\n .rect(0, 0, (bgWidth - this.options.padding.left - this.options.padding.right) * scale, bgHeight * scale)\n .fill({ color: 0x0 });\n this._mask.position.set(this.options.padding.left * scale, 0);\n }\n }\n\n if (bgWidth !== this._lastWidth) {\n this.drawBg(bgWidth, bgHeight);\n }\n\n if (this._selectionRect) {\n this.drawSelection();\n } else {\n this.selectionGraphics?.clear();\n }\n\n if (this.cloneOverlay) {\n this._positionCloneOverlay();\n }\n }\n\n drawSelection() {\n const rect = this._selectionRect;\n if (!rect) {\n this.selectionGraphics?.clear();\n return;\n }\n this.selectionGraphics?.clear();\n this.selectionGraphics\n .rect(rect.left + this.input.x, this.caret.y, rect.width, this.caret.height)\n .fill({ color: this.options.selection.color });\n }\n\n drawBg(width: number = this._lastWidth, height: number = this._lastHeight) {\n const opts =\n (this.error || (this.isClone && this.clone?.error)) && this.options?.error?.bg\n ? { ...this.options.bg, ...this.options.error.bg }\n : this.options.bg;\n\n this.bg\n .clear()\n .roundRect(0, 0, width, height, opts?.radius ?? 0)\n .fill(opts.fill)\n .stroke({ ...(opts?.stroke || {}), alignment: 0 });\n\n this._lastWidth = width;\n this._lastHeight = height;\n }\n\n destroy() {\n console.log('input destroy', this);\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n\n this.app.stage.off('pointerdown', this._checkPointerDownOutside);\n\n this.hideCursor();\n this.destroyDomElement();\n\n super.destroy();\n }\n\n protected addBg() {\n this.bg = this._inner.add\n .graphics()\n .roundRect(0, 0, 100, 50, this.options?.bg?.radius ?? 0)\n .fill(this.options.bg.fill);\n }\n\n protected addSelection() {\n this.selectionGraphics = this._inputContainer.add.graphics();\n }\n\n protected addCaret() {\n this.caret = this._inputContainer.add.sprite({\n asset: Texture.WHITE,\n width: 3,\n height: 10,\n tint: this.options.caret.color ?? 0x0,\n alpha: 0,\n visible: false,\n });\n }\n\n protected addInput() {\n // Seed the backing value alongside the display text — otherwise an input\n // constructed with `value` reports `''` until the first edit, and\n // update() keeps the placeholder visible over the rendered text.\n this._value = this.options.value ?? '';\n this.input = this._inputContainer.add.text({\n ...this.options,\n style: { ...(this.options?.style || {}), padding: 2 },\n text: this.options.value ?? '',\n label: 'input',\n resolution: 2,\n roundPixels: true,\n layout: false,\n });\n }\n\n protected addPlaceholder() {\n this.placeholder = this._placeholderContainer.add.text({\n ...this.options,\n ...this.options.placeholder,\n style: {\n ...this.options.style,\n fill: this.options.placeholder?.color ?? 0x666666,\n },\n resolution: 2,\n label: 'placeholder',\n roundPixels: true,\n layout: true,\n });\n\n this.placeholder.style.align = this.input.style.align;\n }\n\n protected createDomElement(selection?: number) {\n if (this.isClone && this.clone?.domElement) {\n this.domElement = this.clone.domElement;\n this._addDomElementListeners();\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n\n this.domElement = document.createElement('input');\n this.domElement.type = 'text';\n if (this.options.type && AVAILABLE_TYPES.includes(this.options.type)) {\n this.domElement.type = this.options.type;\n }\n\n if (this.options.pattern) {\n this.domElement.pattern = this.options.pattern;\n }\n if (this.options.regex) {\n this._regex = this.options.regex;\n }\n\n const pos = this.getGlobalPosition();\n const bounds = this.getBounds();\n bounds.x = pos.x;\n bounds.y = pos.y;\n bounds.width = this.width - this.options.padding.left;\n\n /**\n * Overlays an HTMLInputElement\n * allows the keyboard to be used on mobile devices\n * mostly taken from @pixi/ui\n * @see https://github.com/pixijs/ui/blob/main/src/Input.ts\n */\n\n this.domElement.style.position = 'fixed';\n this.domElement.style.border = 'none';\n this.domElement.style.outline = 'none';\n this.domElement.style.left = isAndroid ? `0` : `${bounds.left}px`;\n this.domElement.style.top = isAndroid ? `0` : `${bounds.top}px`;\n this.domElement.style.width = `${bounds.width}px`;\n this.domElement.style.height = `${bounds.height}px`;\n this.domElement.style.padding = '0';\n\n if (this.options.debug) {\n this.domElement.style.opacity = '0.8';\n } else {\n this.domElement.style.opacity = '0.0000001';\n }\n this.app.canvas.parentElement?.appendChild(this.domElement);\n this.domElement.value = this.value;\n this.domElement.setAttribute('placeholder', this.options?.placeholder?.text ?? '');\n if (this.options?.maxLength) {\n this.domElement.setAttribute('maxLength', this.options.maxLength.toString());\n }\n\n this._addDomElementListeners();\n this._focusDomElement(selection);\n }\n\n protected destroyDomElement() {\n if (this.isClone) {\n return;\n }\n if (this.domElement) {\n this._removeDomElementListeners();\n this.domElement.remove();\n\n if (this.domElement.parentNode) {\n this.domElement.parentNode.removeChild(this.domElement);\n }\n // @ts-expect-error domelement can't be null\n this.domElement = null;\n }\n }\n\n protected showCursor() {\n this.caret.visible = true;\n this.blinkCaret();\n }\n\n protected hideCursor() {\n this.cursorAnimation?.kill();\n this.caret.visible = false;\n }\n\n protected blinkCaret() {\n if (this.cursorAnimation) {\n this.cursorAnimation.kill();\n }\n this.cursorAnimation = gsap.fromTo(\n this.caret,\n { alpha: 0 },\n {\n duration: 0.5,\n alpha: 1,\n yoyo: true,\n repeat: -1,\n overwrite: true,\n },\n );\n this.addAnimation(this.cursorAnimation);\n }\n\n protected validate() {\n const hasError = this.error;\n if (this.isClone) {\n this.error = this.clone?.error || false;\n } else {\n this.error = !this.isValid;\n if (this.error && this.error !== hasError) {\n this.onError.emit({ input: this, domElement: this.domElement, value: this._value });\n }\n }\n if (this.error !== hasError) {\n if (this.error && this.error !== hasError) {\n this.input.style.fill = this.options?.error?.input?.fill || 0x0;\n } else {\n this.input.style.fill = this.options.input?.style?.fill || 0x0;\n }\n this.drawBg();\n }\n\n if (this.cloneOverlay) {\n this.cloneOverlay.validate();\n }\n }\n\n private _removeDomElementListeners() {\n this.domElement.removeEventListener('focus', this._handleDomElementFocus, false);\n this.domElement.removeEventListener('blur', this._handleDomElementBlur, false);\n this.domElement.removeEventListener('input', this._handleDomElementChange, false);\n this.domElement.removeEventListener('keyup', this._handleDomElementKeyup, false);\n this.domElement.removeEventListener('keydown', this._handleDomElementKeydown, false);\n }\n\n private _addDomElementListeners() {\n if (this.isClone) {\n return;\n }\n this._removeDomElementListeners();\n this.domElement.addEventListener('focus', this._handleDomElementFocus, false);\n this.domElement.addEventListener('blur', this._handleDomElementBlur, false);\n this.domElement.addEventListener('input', this._handleDomElementChange, false);\n this.domElement.addEventListener('keyup', this._handleDomElementKeyup, false);\n this.domElement.addEventListener('keydown', this._handleDomElementKeydown, false);\n }\n\n private _handleFocus() {\n this._caretPosition = -1;\n this.showCursor();\n\n clearTimeout(this._pointerDownTimer);\n\n if (!this.isClone) {\n this._pointerDownTimer = setTimeout(() => {\n this.app.stage.on('pointerdown', this._checkPointerDownOutside);\n }, 250);\n\n const hasOverlay = Boolean(this.options.focusOverlay.activeFilter);\n if (hasOverlay) {\n // decide if we should show an overlay\n if (this.cloneOverlay) {\n this._removeCloneOverlay();\n }\n const isList = Array.isArray(this.options.focusOverlay.activeFilter);\n let shouldShow = false;\n if (isList) {\n const filterList = this.options.focusOverlay.activeFilter as ('mobile' | 'touch' | 'desktop')[];\n if (\n (isMobile && filterList.includes('mobile')) ||\n (isTouch && filterList.includes('touch')) ||\n (!isMobile && !isTouch && filterList.includes('desktop'))\n ) {\n shouldShow = true;\n }\n } else if (typeof this.options.focusOverlay.activeFilter === 'function') {\n shouldShow = this.options.focusOverlay.activeFilter();\n } else {\n shouldShow = hasOverlay;\n }\n\n if (shouldShow) {\n const opts = structuredClone(this.options);\n const scale = this.options.focusOverlay?.scale || 1;\n opts.focusOverlay = { activeFilter: false };\n const fontSize = Number(opts.style?.fontSize || defaultOptions.style?.fontSize || 20) * scale;\n if (!opts.style) {\n opts.style = {};\n }\n\n opts.style.fontSize = fontSize;\n if (opts.padding) {\n opts.padding.left *= scale;\n opts.padding.top *= scale;\n opts.padding.right *= scale;\n opts.padding.bottom *= scale;\n }\n if (opts.bg?.radius) {\n opts.bg.radius *= scale;\n }\n if (opts.bg?.stroke?.width) {\n opts.bg.stroke.width *= scale;\n }\n if (opts.minWidth) {\n opts.minWidth *= scale;\n if (opts.minWidth > this.app.size.width) {\n opts.minWidth = this.app.size.width - (opts.bg?.stroke?.width ? opts.bg.stroke.width * 2 + 20 : 20);\n }\n }\n\n // should we show backing?\n if (this.options.focusOverlay?.backing?.active) {\n const backing = this.make.sprite({\n asset: Texture.WHITE,\n tint: this.options.focusOverlay.backing.options?.color ?? 0x0,\n alpha: this.options.focusOverlay.backing.options?.alpha ?? 0.8,\n width: this.app.size.width,\n height: this.app.size.height,\n eventMode: 'static',\n });\n this.overlayBacking = this.app.stage.addChild(backing);\n }\n\n this.cloneOverlay = new Input(opts, true, this);\n this.cloneOverlay.label = `${this.label} -- clone`;\n this.cloneOverlay.alpha = 0;\n this.cloneOverlay.input.text = this.value;\n this.cloneOverlay.validate();\n this.app.stage.addChild(this.cloneOverlay);\n this._positionCloneOverlay();\n this._showCloneOverlay();\n }\n }\n }\n }\n\n private _showCloneOverlay() {\n this.cloneOverlay.pivot.y = -20;\n this.addAnimation(gsap.to(this.cloneOverlay, { duration: 0.5, alpha: 0.8, ease: 'sine.out', delay: 0.1 }));\n this.addAnimation(gsap.to(this.cloneOverlay.pivot, { duration: 0.5, y: 0, ease: 'sine.out', delay: 0.1 }));\n }\n\n private _positionCloneOverlay() {\n if (!this.cloneOverlay) {\n return;\n }\n const w = this.cloneOverlay.options.minWidth;\n this.cloneOverlay.x = this.app.size.width * 0.5 - w * 0.5;\n this.cloneOverlay.y = this.options.focusOverlay?.marginTop || 20;\n if (this.overlayBacking) {\n this.overlayBacking.width = this.app.size.width;\n this.overlayBacking.height = this.app.size.height;\n }\n }\n\n private _removeCloneOverlay() {\n this.overlayBacking?.destroy();\n this.overlayBacking?.parent?.removeChild(this.overlayBacking);\n // @ts-expect-error cloneOverlay can't be null\n this.overlayBacking = null;\n this.cloneOverlay?.destroy();\n this.cloneOverlay?.parent?.removeChild(this.cloneOverlay);\n // @ts-expect-error cloneOverlay can't be null\n this.cloneOverlay = null;\n }\n\n private _handleDomElementFocus() {\n this.app.stage.off('pointerdown', this._checkPointerDownOutside);\n this._handleFocus();\n }\n\n private _handleDomElementBlur() {\n if (this.isClone) {\n return;\n }\n clearTimeout(this._focusTimer);\n clearTimeout(this._pointerDownTimer);\n this.hideCursor();\n this._removeCloneOverlay();\n this.destroyDomElement();\n }\n\n private _handleDomElementKeyup() {\n this._updateCaretAndSelection();\n }\n\n private _handleDomElementKeydown(e: KeyboardEvent) {\n this._updateCaretAndSelection();\n if (!this.isClone && e.key === 'Enter') {\n if (this.options.blurOnEnter) {\n this.domElement.blur();\n }\n this.onEnter.emit({ input: this, value: this._value, domElement: this.domElement });\n }\n }\n\n private _updateCaretAndSelection() {\n if (!this.domElement) {\n Logger.warn(this.label, 'No dom element');\n return;\n }\n const start = this.domElement.selectionStart || 0;\n const end = this.domElement.selectionEnd || -1;\n const direction = this.domElement.selectionDirection;\n let text = '';\n const value = this.options.type === 'password' ? this.input.text : this._value;\n if (end === undefined) {\n text = value.substring(0, start);\n const metrics = CanvasTextMetrics.measureText(text, this.input.style);\n this._caretPosition = metrics.width;\n this._selectionRect = null;\n } else {\n text = value.substring(start > end ? end : start, start > end ? start : end);\n const toStart = value.substring(0, start > end ? end : start);\n const leftMetrics = CanvasTextMetrics.measureText(toStart, this.input.style);\n const textMetrics = CanvasTextMetrics.measureText(text, this.input.style);\n this._selectionRect = new Rectangle(leftMetrics.width, 0, textMetrics.width, this.input.height);\n this._caretPosition =\n direction === 'backward' ? this._selectionRect.left : this._selectionRect.left + this._selectionRect.width;\n }\n }\n\n private _handleDomElementChange(e: Event) {\n const target = e.target as HTMLInputElement;\n if (target && !this.domElement) {\n this.domElement = target;\n }\n if (this.options.pattern !== '') {\n const filteredValue = target.value.replace(new RegExp(this.options.pattern, 'g'), '');\n target.value = filteredValue;\n this._value = filteredValue;\n } else {\n this._value = target.value;\n }\n\n this.input.text =\n this.options.type === 'password'\n ? this._value\n ?.split('')\n .map(() => '*')\n .join('')\n : this._value;\n\n this._updateCaretAndSelection();\n\n if (!this.isClone) {\n this.onChange.emit({ input: this, domElement: this.domElement, value: this._value });\n this.validate();\n }\n }\n\n /**\n * Gets the focusable area bounds\n * @returns {Bounds} The bounds of the input container\n */\n getFocusArea(): Bounds {\n const bounds = this._inputContainer.getBounds();\n bounds.width = this._lastWidth;\n bounds.height = this._lastHeight;\n return bounds;\n }\n}\n","import { DefaultActionContextsArray, defaultActionsList } from './constants';\nimport { type UserActions, type UserButtons, type UserContexts } from './types';\n\n/**\n * Define the contexts for the actions.\n * @param contexts - The contexts to define.\n * @default ['default', 'game', 'menu', 'pause', 'popup', 'default']\n * @returns {ActionContext[]}\n */\n\nexport function defineContexts<C extends UserContexts = UserContexts>(contexts?: C): C {\n return contexts ?? (DefaultActionContextsArray as unknown as C);\n}\n\nexport function defineActions<C extends UserContexts = UserContexts, U extends UserActions = UserActions<C>>(\n contexts: C,\n actions: U,\n useDefaultActions: boolean = true,\n): U {\n if (useDefaultActions) {\n actions = { ...defaultActionsList, ...actions };\n }\n return actions;\n}\n\nexport function defineButtons<B extends UserButtons = UserButtons>(buttons?: B): B {\n return buttons || ([] as unknown as B);\n}\n","import type { BreakpointMode } from './types';\n\n/**\n * Declare an app's tier ladder and modes in `caper.config.ts`. Returns the\n * config unchanged — its value is the inferred literal key types, which the\n * Vite plugin re-exports into `caper-app.d.ts` so tier and mode names\n * autocomplete everywhere.\n *\n * @example\n * ```ts\n * export const breakpoints = defineBreakpoints({\n * tiers: { mobile: 0, tablet: 768, desktop: 1024 },\n * modes: { stacked: { below: 880 } },\n * });\n * ```\n */\nexport function defineBreakpoints<\n const T extends Record<string, number>,\n const M extends Record<string, BreakpointMode<keyof T & string>> = {},\n>(config: { tiers: T; modes?: M }): { tiers: T; modes: M } {\n return { tiers: config.tiers, modes: (config.modes ?? {}) as M };\n}\n","export enum JoystickDirection {\n None = 'none',\n Left = 'left',\n Top = 'top',\n Bottom = 'bottom',\n Right = 'right',\n TopLeft = 'top_left',\n TopRight = 'top_right',\n BottomLeft = 'bottom_left',\n BottomRight = 'bottom_right',\n}\nexport type JoystickDirectionType =\n | JoystickDirection.None\n | JoystickDirection.Left\n | JoystickDirection.Top\n | JoystickDirection.Bottom\n | JoystickDirection.Right\n | JoystickDirection.TopLeft\n | JoystickDirection.TopRight\n | JoystickDirection.BottomLeft\n | JoystickDirection.BottomRight;\n\n// export a type of all the JoystickDirections\nexport const JOYSTICK_DIRECTIONS: JoystickDirectionType[] = [\n JoystickDirection.None,\n JoystickDirection.Left,\n JoystickDirection.Top,\n JoystickDirection.Bottom,\n JoystickDirection.Right,\n JoystickDirection.TopLeft,\n JoystickDirection.TopRight,\n JoystickDirection.BottomLeft,\n JoystickDirection.BottomRight,\n];\n","import { UserActions, UserButtons } from '../actions';\nimport { UserControls } from './interfaces';\nexport function defineControls<U extends UserActions = UserActions, B extends UserButtons = UserButtons>(\n actions: U,\n buttons: B,\n controls?: UserControls<U, B>,\n): UserControls<U, B> {\n return controls || ([] as unknown as UserControls<U, B>);\n}\n","/**\n * Joystick UI component\n * based on https://github.com/endel/pixi-virtual-joystick\n * ported to TypeScript and adapted for Caper\n */\nimport { DestroyOptions, FederatedPointerEvent, Graphics, Point, Sprite } from 'pixi.js';\nimport { Container } from '../display';\nimport { JoystickDirection } from '../plugins';\nimport { Signal } from '../signals';\n\nexport interface IJoystick {\n onChange: Signal<(detail: JoystickSignalDetail) => void>;\n onStart: Signal<() => void>;\n onEnd: Signal<() => void>;\n onDestroy: Signal<() => void>;\n settings: JoystickSettings;\n outerRadius: number;\n innerRadius: number;\n outer: Sprite | Graphics;\n inner: Sprite | Graphics;\n dragging: boolean;\n pointData: Point;\n power: number;\n startPosition: Point;\n direction: JoystickDirection;\n}\n\nexport interface JoystickSignalDetail {\n angle: number;\n direction: JoystickDirection;\n power: number;\n}\n\nexport interface JoystickSettings {\n outer?: Sprite | Graphics;\n inner?: Sprite | Graphics;\n outerScale?: number;\n innerScale?: number;\n threshold?: number;\n}\n\nexport class Joystick extends Container implements IJoystick {\n onChange = new Signal<(detail: JoystickSignalDetail) => void>();\n onStart = new Signal<() => void>();\n onEnd = new Signal<() => void>();\n onDestroy = new Signal<() => void>();\n settings: JoystickSettings;\n outerRadius: number = 0;\n innerRadius: number = 0;\n\n outer!: Sprite | Graphics;\n inner!: Sprite | Graphics;\n\n innerAlphaStandby = 0.5;\n\n dragging: boolean = false;\n pointData: Point = new Point();\n power: number;\n startPosition: Point;\n direction: JoystickDirection = JoystickDirection.None;\n threshold: number;\n\n private _pointerId?: number;\n\n constructor(opts: Partial<JoystickSettings>) {\n super();\n\n this.settings = Object.assign(\n {\n outerScale: 1,\n innerScale: 1,\n },\n opts,\n );\n\n if (!this.settings.outer) {\n const outer = new Graphics();\n outer.circle(0, 0, 60).fill({ color: 0x0 });\n outer.alpha = 0.5;\n this.settings.outer = outer;\n }\n\n if (!this.settings.inner) {\n const inner = new Graphics();\n inner.circle(0, 0, 35).fill({ color: 0x0 });\n inner.alpha = this.innerAlphaStandby;\n this.settings.inner = inner;\n }\n\n this.threshold = this.settings.threshold ?? 0.01;\n\n this.initialize();\n }\n\n initialize() {\n this.outer = this.settings.outer!;\n this.inner = this.settings.inner!;\n\n this.outer.scale.set(this.settings.outerScale, this.settings.outerScale);\n this.inner.scale.set(this.settings.innerScale, this.settings.innerScale);\n\n if ('anchor' in this.outer) {\n this.outer.anchor.set(0.5);\n }\n if ('anchor' in this.inner) {\n this.inner.anchor.set(0.5);\n }\n\n this.add.existing(this.outer);\n this.add.existing(this.inner);\n\n // this.outerRadius = this.containerJoystick.width / 2;\n this.outerRadius = this.width / 2.5;\n this.innerRadius = this.inner.width / 2;\n\n this.bindEvents();\n }\n\n handleDragMove(e: FederatedPointerEvent) {\n if (!this.dragging || e.pointerId !== this._pointerId) {\n return;\n }\n const newPosition = this.toLocal(e.global);\n const sideX = newPosition.x - this.startPosition.x;\n const sideY = newPosition.y - this.startPosition.y;\n\n const centerPoint = new Point(0, 0);\n let angle = 0;\n let direction = JoystickDirection.None;\n if (sideX == 0 && sideY == 0) {\n this.direction = direction;\n return;\n }\n\n if (sideX === 0) {\n if (sideY > 0) {\n centerPoint.set(0, sideY > this.outerRadius ? this.outerRadius : sideY);\n angle = 270;\n direction = JoystickDirection.Bottom;\n } else {\n centerPoint.set(0, -(Math.abs(sideY) > this.outerRadius ? this.outerRadius : Math.abs(sideY)));\n angle = 90;\n direction = JoystickDirection.Top;\n }\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n this.direction = direction;\n this.onChange.emit({ angle, direction, power: this.power });\n return;\n }\n }\n\n if (sideY === 0) {\n if (sideX > 0) {\n centerPoint.set(Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX), 0);\n angle = 0;\n direction = JoystickDirection.Right;\n } else {\n centerPoint.set(-(Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX)), 0);\n angle = 180;\n direction = JoystickDirection.Left;\n }\n\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n this.direction = direction;\n this.onChange.emit({ angle, direction, power: this.power });\n return;\n }\n }\n\n const tanVal = Math.abs(sideY / sideX);\n const radian = Math.atan(tanVal);\n angle = (radian * 180) / Math.PI;\n\n let centerX = 0;\n let centerY = 0;\n\n if (sideX * sideX + sideY * sideY >= this.outerRadius * this.outerRadius) {\n centerX = this.outerRadius * Math.cos(radian);\n centerY = this.outerRadius * Math.sin(radian);\n } else {\n centerX = Math.abs(sideX) > this.outerRadius ? this.outerRadius : Math.abs(sideX);\n centerY = Math.abs(sideY) > this.outerRadius ? this.outerRadius : Math.abs(sideY);\n }\n\n if (sideY < 0) {\n centerY = -Math.abs(centerY);\n }\n\n if (sideX < 0) {\n centerX = -Math.abs(centerX);\n }\n\n if (sideX > 0 && sideY < 0) {\n // < 90\n } else if (sideX < 0 && sideY < 0) {\n // 90 ~ 180\n angle = 180 - angle;\n } else if (sideX < 0 && sideY > 0) {\n // 180 ~ 270\n angle = angle + 180;\n } else if (sideX > 0 && sideY > 0) {\n // 270 ~ 369\n angle = 360 - angle;\n }\n centerPoint.set(centerX, centerY);\n this.power = this.getPower(centerPoint);\n if (this.power >= this.threshold) {\n direction = this.getDirection(centerPoint);\n this.direction = direction;\n this.inner.position.set(centerPoint.x, centerPoint.y);\n this.onChange.emit({ angle, direction, power: this.power });\n }\n }\n\n destroy(options?: DestroyOptions) {\n this.off('pointerdown', this.handleDragStart)\n .off('pointerup', this.handleDragEnd)\n .off('pointerupoutside', this.handleDragEnd)\n .off('pointermove', this.handleDragMove);\n window.removeEventListener('pointerup', this.handleDragEnd);\n this.onDestroy.emit();\n super.destroy(options);\n }\n\n protected handleDragStart(e: FederatedPointerEvent) {\n if (this._pointerId !== undefined) {\n return;\n }\n this._pointerId = e.pointerId;\n this.startPosition = this.toLocal(e.global);\n this.dragging = true;\n this.inner.alpha = 1;\n this.onStart.emit();\n }\n\n protected handleDragEnd(e: FederatedPointerEvent | PointerEvent) {\n if (this._pointerId !== e.pointerId) {\n return;\n }\n this.direction = JoystickDirection.None;\n this.inner.position.set(0, 0);\n this.dragging = false;\n this.inner.alpha = this.innerAlphaStandby;\n this.onEnd.emit();\n this._pointerId = undefined;\n }\n\n protected bindEvents() {\n this.eventMode = 'static';\n this.on('pointerdown', this.handleDragStart)\n .on('pointerup', this.handleDragEnd)\n .on('pointerupoutside', this.handleDragEnd)\n .on('pointermove', this.handleDragMove);\n\n window.addEventListener('pointerup', this.handleDragEnd);\n }\n\n protected getPower(centerPoint: Point) {\n const a = centerPoint.x;\n const b = centerPoint.y;\n return Math.min(1, Math.sqrt(a * a + b * b) / this.outerRadius);\n }\n\n protected getDirection(center: Point) {\n const rad = Math.atan2(center.y, center.x); // [-PI, PI]\n if ((rad >= -Math.PI / 8 && rad < 0) || (rad >= 0 && rad < Math.PI / 8)) {\n return JoystickDirection.Right;\n } else if (rad >= Math.PI / 8 && rad < (3 * Math.PI) / 8) {\n return JoystickDirection.BottomRight;\n } else if (rad >= (3 * Math.PI) / 8 && rad < (5 * Math.PI) / 8) {\n return JoystickDirection.Bottom;\n } else if (rad >= (5 * Math.PI) / 8 && rad < (7 * Math.PI) / 8) {\n return JoystickDirection.BottomLeft;\n } else if ((rad >= (7 * Math.PI) / 8 && rad < Math.PI) || (rad >= -Math.PI && rad < (-7 * Math.PI) / 8)) {\n return JoystickDirection.Left;\n } else if (rad >= (-7 * Math.PI) / 8 && rad < (-5 * Math.PI) / 8) {\n return JoystickDirection.TopLeft;\n } else if (rad >= (-5 * Math.PI) / 8 && rad < (-3 * Math.PI) / 8) {\n return JoystickDirection.Top;\n } else {\n return JoystickDirection.TopRight;\n }\n }\n}\n","import { ColorSource, DestroyOptions, Container as PIXIContainer, Sprite, Texture } from 'pixi.js';\n\nimport type { IContainer } from '../display/Container';\nimport { Container } from '../display/Container';\nimport type { ActionContext, IFocusable } from '../plugins';\nimport { Logger, type Size } from '../utils';\n\n/**\n * Interface for Popup\n */\nexport interface IPopup<T = any> extends IContainer {\n readonly id: string | number; // Unique identifier for the popup\n config: PopupConfig<T>; // Configuration for the popup\n view: Container; // The view of the popup\n backing?: PIXIContainer; // The backing of the popup\n isShowing: boolean; // Whether the popup is currently showing\n firstFocusableEntity?: IFocusable; // The first focusable entity in the popup\n data: T;\n\n readonly actionContext: ActionContext | undefined; // The action context of the popup\n\n close(): void;\n\n initialize(): void; // Initialize the popup\n\n beforeShow(): void; // Show the popup\n\n show(): void | Promise<any>; // Show the popup\n\n afterShow(): void; // Show the popup\n\n beforeHide(): void; // Hide the popup\n\n hide(): void | Promise<any>; // Hide the popup\n\n start(): void | Promise<any>; // Start the popup\n\n end(): void; // End the popup\n\n restoreActionContext(): void; // Restore the action context\n}\n\nexport type PopupConstructor<T = any> = new (id: string | number, config?: Partial<PopupConfig<T>>) => IPopup<T>;\n\n/**\n * Configuration for the backing of the popup\n */\nexport type BackingConfig = {\n color: ColorSource;\n alpha: number;\n};\n\nconst defaultBackingConfig = {\n color: 0x0,\n alpha: 0.75,\n};\n\n/**\n * Configuration for the popup\n */\nexport type PopupConfig<T = any> = {\n id: string | number;\n closeOnEscape: boolean;\n closeOnPointerDownOutside: boolean;\n backing: boolean | Partial<BackingConfig>;\n data?: T;\n actionContext?: ActionContext;\n};\n\nconst defaultPopupConfig = {\n backing: true,\n closeOnEscape: true,\n closeOnPointerDownOutside: true,\n actionContext: 'popup',\n};\n\n/**\n * Class representing a Popup\n */\nexport class Popup<T = any> extends Container implements IPopup<T> {\n public isShowing: boolean = false;\n public firstFocusableEntity: IFocusable;\n public view: Container;\n public backing?: Sprite;\n public config: PopupConfig<T>;\n\n protected _storedActionContext: ActionContext | undefined = undefined;\n\n get actionContext(): ActionContext | undefined {\n return this.config.actionContext;\n }\n\n /**\n * Create a new Popup\n * @param id - The unique identifier for the popup\n * @param config - The configuration for the popup. The `data` field is\n * narrowed to `T` when the subclass declares its generic parameter\n * (e.g. `class MyPopup extends Popup<MyData>`), which flows through to\n * the typed `app.popups.show('id', { data })` call site.\n */\n constructor(\n public readonly id: string | number,\n config: Partial<PopupConfig<T>> = {},\n ) {\n super();\n this.config = Object.assign({ id, ...defaultPopupConfig }, config) as PopupConfig<T>;\n\n this._initialize();\n }\n\n get data(): T {\n return this.config.data as T;\n }\n /**\n * Create a backing for the popup\n * @param config - The configuration for the backing\n * @param size - The size of the backing\n * @returns The backing container\n */\n private static makeBacking(config: boolean | Partial<BackingConfig>, size: Size): Sprite {\n let finalConfig = {};\n if (typeof config === 'object') {\n finalConfig = config;\n }\n const backingConfig: BackingConfig = Object.assign({ ...defaultBackingConfig }, finalConfig);\n const backing = new Sprite(Texture.WHITE);\n backing.anchor.set(0.5);\n backing.alpha = backingConfig.alpha;\n backing.tint = backingConfig.color;\n backing.width = size.width;\n backing.height = size.height;\n return backing;\n }\n\n initialize() {}\n\n public beforeShow() {\n this.storeActionContext();\n this.setActionContext();\n }\n\n public beforeHide() {\n this.app.focus.removeFocusLayer(this.id);\n }\n\n destroy(options?: boolean | DestroyOptions): void {\n this.app.focus.removeFocusLayer(this.id);\n this._storedActionContext = undefined;\n super.destroy(options);\n }\n\n /**\n * Hide the popup\n * @returns A promise that resolves when the popup is hidden\n */\n hide(): void | any | Promise<any>;\n\n async hide(): Promise<void> {\n this.visible = false;\n return Promise.resolve();\n }\n\n /**\n * Show the popup\n * @returns A promise that resolves when the popup is shown\n */\n show(): void | Promise<any>;\n\n async show(): Promise<void> {\n this.resize();\n this.visible = true;\n return Promise.resolve();\n }\n\n /**\n * Start the popup\n */\n start(): void | Promise<any>;\n async start() {}\n\n afterShow() {\n if (this.firstFocusableEntity) {\n this.app.focus.add(this.firstFocusableEntity, this.id, true);\n this.app.focus.setFocus(this.firstFocusableEntity);\n }\n }\n /**\n * End the popup\n */\n end() {}\n\n close(): void | Promise<void>;\n async close(): Promise<void> {\n void this.app.popups.hidePopup(this.id, this.config.data);\n }\n\n resize() {\n this.backing?.setSize(this.app.size.width, this.app.size.height);\n }\n\n /**\n * Initialize the popup\n * @private\n */\n private _initialize() {\n this.app.focus.addFocusLayer(this.id, false);\n\n if (this.config.backing) {\n this.backing = this.add.existing(Popup.makeBacking(this.config.backing, this.app.size));\n this.backing.eventMode = 'static';\n\n if (this.config.closeOnPointerDownOutside) {\n this.backing.once('click', this.close);\n this.backing.once('tap', this.close);\n }\n }\n\n this.view = this.add.container();\n this.view.eventMode = 'static';\n }\n\n // store and restore the action context\n protected setActionContext() {\n if (this.actionContext) {\n this.app.actionContext = this.actionContext;\n Logger.log('Popup', 'Setting action context', this.app.actionContext);\n }\n }\n\n protected storeActionContext() {\n this._storedActionContext = this.app.actionContext;\n Logger.log('Popup', 'Storing action context', this._storedActionContext);\n }\n\n public restoreActionContext() {\n if (this._storedActionContext) {\n Logger.log('Popup', 'Restoring action context', this._storedActionContext);\n this.app.actionContext = this._storedActionContext;\n }\n this._storedActionContext = undefined;\n }\n}\n","import type { LayoutOptions } from '@pixi/layout';\nimport { GraphicsContext, HTMLTextStyleOptions, TextStyleOptions } from 'pixi.js';\nimport { ContainerConfig } from '../../display';\nimport { ParticleContainerConfig } from '../../display/ParticleContainer';\nimport { ButtonConfig, FlexContainerConfig, UICanvasProps } from '../../ui';\nimport type {\n BitmapFontFamilyAsset,\n FontFamilyAsset,\n PointLike,\n SpineAsset,\n SpritesheetAsset,\n TextureAsset,\n WithRequiredProps,\n} from '../../utils';\n\nexport interface AbstractProps {\n [key: string]: any;\n}\n\nexport interface TextureProps {\n asset: TextureAsset;\n sheet: SpritesheetAsset;\n}\n\nexport interface PositionProps {\n x: number;\n y: number;\n position: PointLike;\n}\n\nexport interface ScaleProps {\n scaleX: number;\n scaleY: number;\n scale: PointLike;\n}\n\nexport interface PivotProps {\n pivot: PointLike;\n}\n\nexport interface VisibilityProps {\n alpha: number;\n visible: boolean;\n}\n\nexport interface LayoutProps {\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n}\n\nexport interface ExistingProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {}\n\n/**\n * Layout-ish props the `this.add.entity(id, props)` factory applies after\n * construction — intentionally narrow (no `AbstractProps` index signature)\n * so TypeScript can still narrow entity-specific props at the call site.\n */\nexport interface EntityFactoryProps\n extends Partial<PositionProps>,\n Partial<ScaleProps>,\n Partial<PivotProps>,\n Partial<VisibilityProps> {}\n\nexport interface GraphicsProps extends AbstractProps, PositionProps, ScaleProps, PivotProps, VisibilityProps {}\n\nexport interface SvgProps extends GraphicsProps {\n ctx: string | GraphicsContext;\n}\n\nexport interface SpriteProps\n extends AbstractProps,\n TextureProps,\n ScaleProps,\n PositionProps,\n VisibilityProps,\n LayoutProps {\n anchor: PointLike;\n}\n\nexport interface TilingSpriteProps extends SpriteProps {\n tilePosition?: PointLike;\n /**\n * Scaling of the image that is being tiled.\n * @default {x: 1, y: 1}\n */\n tileScale?: PointLike;\n /**\n * The rotation of the image that is being tiled.\n * @default 0\n */\n tileRotation?: number;\n /**\n * The texture to use for the sprite.\n * @default Texture.WHITE\n */\n /**\n * The width of the tiling sprite. #\n * @default 256\n */\n width?: number;\n /**\n * The height of the tiling sprite.\n * @default 256\n */\n height?: number;\n /**\n * @default false\n */\n applyAnchorToTexture?: boolean;\n /** Whether or not to round the x/y position. */\n roundPixels?: boolean;\n}\n\nexport interface AnimatedSpriteAnimationProps\n extends AbstractProps,\n ScaleProps,\n PositionProps,\n VisibilityProps,\n LayoutProps {\n texturePrefix: string;\n sheet: SpritesheetAsset;\n startIndex: number;\n numFrames: number;\n zeroPad: number;\n autoUpdate: boolean;\n updateAnchor: boolean;\n loop: boolean;\n animationSpeed: number;\n}\n\nexport interface AnimatedSpriteProps extends AbstractProps, ScaleProps, PositionProps, VisibilityProps, LayoutProps {\n sheet: SpritesheetAsset;\n texturePrefix: string;\n zeroPad: number;\n animations: { [animationName: string]: Partial<AnimatedSpriteAnimationProps> };\n autoPlay: boolean;\n autoUpdate: boolean;\n defaultAnimation: string;\n reversible: boolean;\n animationSpeed: number;\n startIndex: number;\n}\n\nexport type TextStyle = Partial<Omit<TextStyleOptions, 'fontFamily'> & { fontFamily: FontFamilyAsset }>;\n\nexport interface TextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: TextStyle;\n}\n\nexport interface BitmapTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: Partial<Omit<TextStyleOptions, 'fontFamily'> & { fontFamily: BitmapFontFamilyAsset }>;\n}\n\nexport interface HTMLTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps, LayoutProps {\n text: string;\n anchor: PointLike;\n resolution: number;\n roundPixels: boolean;\n style: Partial<Omit<HTMLTextStyleOptions, 'fontFamily'> & { fontFamily: FontFamilyAsset }>;\n}\n\nexport interface OmittedTextProps extends AbstractProps, PositionProps, ScaleProps, VisibilityProps {}\n\nexport const TextPropsKeys: (keyof TextProps)[] = ['text', 'anchor', 'roundPixels', 'style', 'pivot'];\n\nexport interface ContainerProps\n extends AbstractProps,\n PositionProps,\n ScaleProps,\n PivotProps,\n VisibilityProps,\n LayoutProps,\n ContainerConfig {}\n\nexport interface ParticleContainerProps extends AbstractProps, ParticleContainerConfig {}\n\nexport interface FlexContainerProps extends ContainerProps, FlexContainerConfig {}\n\nexport interface UICanvasFactoryProps extends ContainerProps, UICanvasProps {}\n\n// spine\nexport interface SpineProps extends AbstractProps, ScaleProps, PositionProps, VisibilityProps, LayoutProps {\n data: SpineAsset;\n autoUpdate: boolean;\n animationName: string;\n trackIndex: number;\n loop: boolean;\n paused: boolean;\n}\n\ninterface _ButtonProps\n extends AbstractProps,\n ScaleProps,\n PositionProps,\n PivotProps,\n VisibilityProps,\n ButtonConfig,\n LayoutProps {}\n\nexport type ButtonProps = WithRequiredProps<_ButtonProps, 'textures'>;\n","import type { IActionsPlugin } from '../plugins/actions';\nimport type { Application } from './Application';\nimport type { IApplication } from './interfaces';\n\n/**\n * A single entry in an app's automation log ring buffer.\n */\nexport interface AutomationLogEntry {\n t: number;\n kind: 'action' | 'state' | 'context';\n name?: string;\n data?: unknown;\n}\n\n/**\n * The automation facade exposed on `window.Caper.automation[appId]` for\n * Playwright / agent drivers. Only present when automation is enabled (see the\n * gating rules in {@link registerCaperApp}).\n */\nexport interface ICaperAutomation {\n readonly appId: string;\n readonly log: readonly AutomationLogEntry[];\n action(name: string, data?: unknown): void;\n getContext(): string;\n getState(): unknown;\n registerStateGetter(fn: () => unknown): void;\n notifyStateChanged(state: unknown): void;\n waitFor(predicate: (state: unknown) => boolean, opts?: { timeoutMs?: number }): Promise<unknown>;\n}\n\nconst LOG_CAP = 200;\nconst FALLBACK_APP_ID = 'CaperApplication';\n\ninterface CaperReadyResolver {\n resolve: (app: IApplication) => void;\n promise: Promise<IApplication>;\n}\n\ninterface CaperGlobalInternal {\n apps: Map<string, IApplication>;\n app?: IApplication;\n automation: Record<string, ICaperAutomation>;\n ready: (id?: string) => Promise<IApplication>;\n __runtimeManaged?: boolean;\n /** set by the caper-runtime virtual module from the app's import.meta.env.DEV */\n __dev?: boolean;\n /** internal: keyed ready resolvers */\n __readyResolvers?: Map<string, CaperReadyResolver>;\n /** internal: ids of apps that have fully finished booting (signalCaperReady) */\n __readyApps?: Set<string>;\n [key: string]: unknown;\n}\n\n/**\n * Guarded dev-env check. The caper-runtime virtual module sets `Caper.__dev`\n * from the consumer app's `import.meta.env.DEV` (the reliable signal — inside\n * this pre-built lib, import.meta.env has been compiled away at build time).\n * The direct import.meta check remains as a fallback for source-linked\n * consumers. Access to browser/env globals must stay inside a function (never\n * at module top level) so the built entry can be evaluated in plain Node\n * during SSR config loading.\n */\nfunction isDevEnv(): boolean {\n try {\n if ((globalThis as any).Caper?.__dev === true) {\n return true;\n }\n return typeof import.meta !== 'undefined' && (import.meta as any).env?.DEV === true;\n } catch {\n return false;\n }\n}\n\nfunction automationEnvFlag(): boolean {\n try {\n return typeof import.meta !== 'undefined' && (import.meta as any).env?.VITE_CAPER_AUTOMATION === 'true';\n } catch {\n return false;\n }\n}\n\nconst FIRST_APP_KEY = '__first__';\n\n/**\n * Lazily create/return the `globalThis.Caper` object with the automation +\n * discovery surface installed. No browser globals are touched at module load\n * time — everything happens inside this function.\n */\nfunction ensureCaperGlobal(): CaperGlobalInternal {\n const g = globalThis as any;\n const caper: CaperGlobalInternal = (g.Caper ||= {} as CaperGlobalInternal);\n\n if (!(caper.apps instanceof Map)) {\n caper.apps = new Map<string, IApplication>();\n }\n if (typeof caper.automation !== 'object' || caper.automation === null) {\n caper.automation = {};\n }\n if (!(caper.__readyResolvers instanceof Map)) {\n caper.__readyResolvers = new Map<string, CaperReadyResolver>();\n }\n if (!(caper.__readyApps instanceof Set)) {\n caper.__readyApps = new Set<string>();\n }\n\n if (typeof caper.ready !== 'function') {\n caper.ready = (id?: string): Promise<IApplication> => {\n const resolvers = caper.__readyResolvers as Map<string, CaperReadyResolver>;\n const readyApps = caper.__readyApps as Set<string>;\n // Only resolve immediately for apps that have FINISHED booting\n // (signalCaperReady) — registration alone happens earlier, in create(),\n // before main.ts has run.\n if (id && readyApps.has(id)) {\n return Promise.resolve(caper.apps.get(id)!);\n }\n // No id: resolve with the first fully-booted app if one exists.\n if (!id && readyApps.size > 0) {\n const firstReadyId = readyApps.values().next().value as string;\n return Promise.resolve(caper.apps.get(firstReadyId)!);\n }\n const key = id ?? FIRST_APP_KEY;\n let entry = resolvers.get(key);\n if (!entry) {\n let resolve!: (app: IApplication) => void;\n const promise = new Promise<IApplication>((res) => {\n resolve = res;\n });\n entry = { resolve, promise };\n resolvers.set(key, entry);\n }\n return entry.promise;\n };\n }\n\n return caper;\n}\n\n/**\n * Install the `Caper` discovery surface (`apps`, `automation`, `ready()`) on\n * `globalThis` immediately. The caper-runtime virtual module calls this before\n * bootstrap so automation drivers (Playwright etc.) can `await Caper.ready()`\n * from the very first moment the page scripts run, instead of polling for the\n * function to appear at the end of boot.\n */\nexport function installCaperGlobal(): void {\n ensureCaperGlobal();\n}\n\nfunction appIdOf(app: IApplication): string {\n return (app.config?.id as string) || FALLBACK_APP_ID;\n}\n\nfunction buildAutomation(app: IApplication): ICaperAutomation {\n const appId = appIdOf(app);\n const log: AutomationLogEntry[] = [];\n let stateGetter: (() => unknown) | undefined;\n const pending: Array<{ predicate: (state: unknown) => boolean; resolve: (v: unknown) => void }> = [];\n\n const push = (entry: AutomationLogEntry) => {\n log.push(entry);\n if (log.length > LOG_CAP) {\n log.splice(0, log.length - LOG_CAP);\n }\n };\n\n const getState = (): unknown => (stateGetter ? stateGetter() : undefined);\n\n const checkPending = (state: unknown) => {\n if (pending.length === 0) {\n return;\n }\n for (let i = pending.length - 1; i >= 0; i--) {\n let matched = false;\n try {\n matched = pending[i].predicate(state);\n } catch {\n matched = false;\n }\n if (matched) {\n const [entry] = pending.splice(i, 1);\n entry.resolve(state);\n }\n }\n };\n\n const facade: ICaperAutomation = {\n appId,\n get log() {\n return log as readonly AutomationLogEntry[];\n },\n action(name: string, data?: unknown) {\n app.sendAction(name as any, data);\n },\n getContext() {\n return String(app.actionContext);\n },\n getState,\n registerStateGetter(fn: () => unknown) {\n stateGetter = fn;\n },\n notifyStateChanged(state: unknown) {\n push({ t: Date.now(), kind: 'state', data: state });\n checkPending(state);\n },\n waitFor(predicate: (state: unknown) => boolean, opts?: { timeoutMs?: number }) {\n // Check immediately against current state.\n const current = getState();\n try {\n if (predicate(current)) {\n return Promise.resolve(current);\n }\n } catch {\n // ignore predicate errors on the immediate check\n }\n return new Promise<unknown>((resolve, reject) => {\n let timer: ReturnType<typeof setTimeout> | undefined;\n const entry = {\n predicate,\n resolve: (v: unknown) => {\n if (timer) {\n clearTimeout(timer);\n }\n resolve(v);\n },\n };\n pending.push(entry);\n if (opts?.timeoutMs != null) {\n timer = setTimeout(() => {\n const idx = pending.indexOf(entry);\n if (idx >= 0) {\n pending.splice(idx, 1);\n }\n reject(new Error(`waitFor timed out after ${opts.timeoutMs}ms`));\n }, opts.timeoutMs);\n }\n });\n },\n };\n\n // Subscribe to action dispatches + context changes for the log, and re-check\n // pending waitFor predicates after each dispatched action.\n const actions = app.getPlugin<IActionsPlugin>('actions');\n if (actions) {\n actions.onActionDispatched?.connect((detail) => {\n push({ t: Date.now(), kind: 'action', name: String(detail.id), data: detail.data });\n checkPending(getState());\n });\n actions.onActionContextChanged.connect((context) => {\n push({ t: Date.now(), kind: 'context', name: String(context) });\n });\n }\n\n return facade;\n}\n\n/**\n * Register an app with the global `Caper` discovery surface. Adds it to\n * `Caper.apps` under its config id, sets `Caper.app` to the most-recently\n * created app, and — when automation is enabled — builds the automation facade\n * and stores it at `Caper.automation[id]` (and on the app instance).\n *\n * Automation is enabled when any of: dev env, `config.automation === true`, or\n * `VITE_CAPER_AUTOMATION === 'true'`.\n */\nexport function registerCaperApp(app: IApplication): void {\n const caper = ensureCaperGlobal();\n const id = appIdOf(app);\n caper.apps.set(id, app);\n caper.app = app;\n\n const automationEnabled = isDevEnv() || app.config?.automation === true || automationEnvFlag();\n if (automationEnabled) {\n const facade = buildAutomation(app);\n caper.automation[id] = facade;\n (app as Application).automation = facade;\n }\n}\n\n/**\n * Resolve any pending `Caper.ready()` promises for this app — both the\n * id-keyed resolver and the first-app resolver.\n */\nexport function signalCaperReady(app: IApplication): void {\n const caper = ensureCaperGlobal();\n const id = appIdOf(app);\n (caper.__readyApps as Set<string>).add(id);\n const resolvers = caper.__readyResolvers as Map<string, CaperReadyResolver>;\n\n const idEntry = resolvers.get(id);\n if (idEntry) {\n idEntry.resolve(app);\n resolvers.delete(id);\n }\n const firstEntry = resolvers.get(FIRST_APP_KEY);\n if (firstEntry) {\n firstEntry.resolve(app);\n resolvers.delete(FIRST_APP_KEY);\n }\n}\n","import { type RegisterSWOptions } from 'vite-plugin-pwa/types';\nimport { sayHello } from '../hello';\nimport type { PluginListItem } from '../plugins';\nimport type { AppTypeOverrides, SceneImportListItem } from '../utils';\nimport { triggerViteError } from '../utils/vite';\nimport { checkWebGL } from '../webgl-check';\nimport { Application } from './Application';\nimport { registerCaperApp, signalCaperReady, type ICaperAutomation } from './globals';\nimport type { IApplication } from './interfaces';\nimport { AppConfig } from './types';\n\ntype App = AppTypeOverrides['App'];\n\ninterface CaperPWA {\n readonly info: any;\n register: () => void;\n onRegisteredSW: (swScriptUrl: string) => void;\n offlineReady: () => void;\n onNeedRefresh?: () => void;\n onRegisterError?: (error: any) => void;\n}\ninterface CaperGlobal {\n APP_NAME: string;\n APP_VERSION: string | number;\n\n readonly sceneList: SceneImportListItem<any>[];\n readonly pluginsList: PluginListItem[];\n\n get: (key?: string) => any;\n // pwa\n pwa: CaperPWA;\n\n // app discovery + automation\n apps: Map<string, IApplication>;\n app?: IApplication;\n ready(id?: string): Promise<IApplication>;\n automation: Record<string, ICaperAutomation>;\n __runtimeManaged?: boolean;\n}\n\ndeclare global {\n const Caper: CaperGlobal;\n const registerSW: (options: RegisterSWOptions) => void;\n interface Window {\n Caper: CaperGlobal;\n }\n}\n\nexport const DEFAULT_GAME_CONTAINER_ID = 'caper-game-container';\n\nexport function createContainer(id: string) {\n const container = document.createElement('div');\n container.setAttribute('id', id);\n document.body.appendChild(container);\n return container;\n}\n\nexport async function documentReady() {\n return new Promise((resolve) => {\n if (document.readyState === 'complete' || document.readyState === 'interactive') {\n resolve(true);\n } else {\n document.addEventListener('DOMContentLoaded', () => {\n resolve(true);\n });\n }\n });\n}\n\nfunction addErrorHandler() {\n // This guard ensures these listeners only run during development\n if (import.meta.env.DEV) {\n /**\n * Listen for standard runtime errors that are not caught.\n */\n window.addEventListener('error', (event) => {\n // Prevent the default browser console error log\n event.preventDefault();\n\n triggerViteError({\n message: event.message,\n // The error object might contain a more detailed stack trace\n stack: event.error?.stack,\n id: event.filename,\n line: event.lineno,\n column: event.colno,\n });\n });\n\n /**\n * Listen for unhandled promise rejections (e.g., from async functions).\n */\n window.addEventListener('unhandledrejection', (event) => {\n // Prevent the default browser console error log\n event.preventDefault();\n\n const error = event.reason;\n\n // The 'reason' can be any value, so we handle Error objects specifically\n if (error instanceof Error) {\n triggerViteError({\n message: error.message,\n stack: error.stack,\n // Note: stack parsing would be needed to get file/line for promise rejections\n });\n } else {\n // Handle cases where a non-error value is rejected\n triggerViteError({\n message: `Unhandled promise rejection: ${String(event.reason)}`,\n });\n }\n });\n }\n}\n\nexport async function create(\n config: Partial<AppConfig> = { id: 'CaperApplication' },\n domElement: string | Window | HTMLElement = DEFAULT_GAME_CONTAINER_ID,\n speak: boolean = true,\n): Promise<App> {\n await documentReady();\n checkWebGL();\n if (speak) {\n sayHello();\n }\n addErrorHandler();\n let el: HTMLElement | null = null;\n if (typeof domElement === 'string') {\n el = document.getElementById(domElement);\n if (!el) {\n el = createContainer(domElement);\n }\n } else if (domElement instanceof HTMLElement) {\n el = domElement;\n } else if (domElement === window) {\n el = document.body;\n }\n if (!el) {\n // no element to use\n throw new Error(\n 'You passed in a DOM Element, but none was found. If you instead pass in a string, a container will be created for you, using the string for its id.',\n );\n }\n if (config.resizeToContainer) {\n config.resizeTo = el;\n }\n\n if (config.useLayout) {\n config.layout = {\n // @ts-expect-error some config stuff isn't typed right in @pixi/layout\n autoUpdate: false,\n enableDebug: false,\n debugModificationCount: 0,\n throttle: 100,\n };\n }\n\n config.container = el;\n const ApplicationClass = config.application || Application;\n const instance = new ApplicationClass();\n await instance.initialize(config, el);\n\n if (config.useLayout) {\n instance.stage.layout = {\n position: 'absolute',\n width: '100%',\n height: '100%',\n };\n }\n\n // ensure all plugins are initialized\n // run framework post-init: the plugin loop + core wiring, then the user hook\n await instance._postInitialize();\n\n // register with the global Caper discovery/automation surface\n registerCaperApp(instance as unknown as IApplication);\n // when not driven by the vite runtime (which signals readiness itself after\n // main.ts), signal readiness here so direct create() usage still resolves\n // Caper.ready()\n if (!(globalThis as any).Caper?.__runtimeManaged) {\n signalCaperReady(instance as unknown as IApplication);\n }\n\n // return the app instance\n return instance as App;\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caperjs/core",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "title": "Caper",
5
5
  "description": "An opinionated HTML game framework built on PixiJS v8",
6
6
  "bin": {
@@ -74,8 +74,7 @@
74
74
  "turbo": "^2.0.3",
75
75
  "typedoc": "^0.28.1",
76
76
  "vite-plugin-dts": "^4.5.3",
77
- "vitest": "^3",
78
- "zod": "^4.3.6"
77
+ "vitest": "^3"
79
78
  },
80
79
  "peerDependencies": {
81
80
  "@pixi/sound": "^6.0.1",
@@ -115,7 +114,8 @@
115
114
  "workbox-expiration": "^7.4.0",
116
115
  "workbox-routing": "^7.4.0",
117
116
  "workbox-strategies": "^7.4.0",
118
- "workbox-window": "^7.4.0"
117
+ "workbox-window": "^7.4.0",
118
+ "zod": "^4.3.6"
119
119
  },
120
120
  "scripts": {
121
121
  "dev": "cd ./examples && pnpm dev",
package/src/version.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  // This file is auto-generated during the build process.
2
- export const version: string = '0.1.0';
2
+ export const version: string = '0.1.1';
3
3
  export const pixiVersion: string = '8.19.0';