@caperjs/core 0.2.2 → 0.2.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/build/index.mjs +2 -0
  2. package/build/plugins/viewport.mjs +52 -0
  3. package/lib/{CaptionsPlugin-DeGyPecB.js → CaptionsPlugin-WPAcfAkx.js} +13 -12
  4. package/lib/CaptionsPlugin-WPAcfAkx.js.map +1 -0
  5. package/lib/{DataAdapter-DeI2kIxC.js → DataAdapter-DS-twowe.js} +11 -11
  6. package/lib/{DataAdapter-DeI2kIxC.js.map → DataAdapter-DS-twowe.js.map} +1 -1
  7. package/lib/{DebugRenderer-wjV0tMwL.js → DebugRenderer-D1ryrRYx.js} +2 -2
  8. package/lib/{DebugRenderer-wjV0tMwL.js.map → DebugRenderer-D1ryrRYx.js.map} +1 -1
  9. package/lib/{DevToolsPlugin-D4iWQwkO.js → DevToolsPlugin-DH7zX7HU.js} +2 -2
  10. package/lib/{DevToolsPlugin-D4iWQwkO.js.map → DevToolsPlugin-DH7zX7HU.js.map} +1 -1
  11. package/lib/{GSAPPlugin-DQTyIwcC.js → GSAPPlugin-BBtRjUqe.js} +2 -2
  12. package/lib/{GSAPPlugin-DQTyIwcC.js.map → GSAPPlugin-BBtRjUqe.js.map} +1 -1
  13. package/lib/{LayoutPlugin-vR_h-BaG.js → LayoutPlugin-Co6vcoV4.js} +4 -4
  14. package/lib/{LayoutPlugin-vR_h-BaG.js.map → LayoutPlugin-Co6vcoV4.js.map} +1 -1
  15. package/lib/{SpinePlugin-DJ-PpxFj.js → SpinePlugin-uN641Hmk.js} +2 -2
  16. package/lib/{SpinePlugin-DJ-PpxFj.js.map → SpinePlugin-uN641Hmk.js.map} +1 -1
  17. package/lib/{StatsPlugin-BYNnKYOm.js → StatsPlugin-vZQRm6wh.js} +4 -4
  18. package/lib/{StatsPlugin-BYNnKYOm.js.map → StatsPlugin-vZQRm6wh.js.map} +1 -1
  19. package/lib/{VoiceOverPlugin-BLSbq3DU.js → VoiceOverPlugin-KlZdGj1G.js} +32 -32
  20. package/lib/{VoiceOverPlugin-BLSbq3DU.js.map → VoiceOverPlugin-KlZdGj1G.js.map} +1 -1
  21. package/lib/caper.mjs +2107 -353
  22. package/lib/caper.mjs.map +1 -1
  23. package/lib/core/Application.d.ts +7 -1
  24. package/lib/core/Application.d.ts.map +1 -1
  25. package/lib/core/interfaces/IApplicationOptions.d.ts +1 -1
  26. package/lib/core/interfaces/IApplicationOptions.d.ts.map +1 -1
  27. package/lib/core/interfaces/ICoreFunctions.d.ts +1 -0
  28. package/lib/core/interfaces/ICoreFunctions.d.ts.map +1 -1
  29. package/lib/display/AnimatedSprite.d.ts +1 -1
  30. package/lib/display/AnimatedSprite.d.ts.map +1 -1
  31. package/lib/display/Container.d.ts.map +1 -1
  32. package/lib/display/SpineAnimation.d.ts +1 -1
  33. package/lib/display/SpineAnimation.d.ts.map +1 -1
  34. package/lib/importOrder.containerFirst.test.d.ts +2 -0
  35. package/lib/importOrder.containerFirst.test.d.ts.map +1 -0
  36. package/lib/importOrder.displayFirst.test.d.ts +2 -0
  37. package/lib/importOrder.displayFirst.test.d.ts.map +1 -0
  38. package/lib/importOrder.mixinsFirst.test.d.ts +2 -0
  39. package/lib/importOrder.mixinsFirst.test.d.ts.map +1 -0
  40. package/lib/importOrder.sceneFirst.test.d.ts +2 -0
  41. package/lib/importOrder.sceneFirst.test.d.ts.map +1 -0
  42. package/lib/importOrder.toastFirst.test.d.ts +2 -0
  43. package/lib/importOrder.toastFirst.test.d.ts.map +1 -0
  44. package/lib/importOrder.uiFirst.test.d.ts +2 -0
  45. package/lib/importOrder.uiFirst.test.d.ts.map +1 -0
  46. package/lib/mixins/factory/Factory.d.ts +1 -1
  47. package/lib/mixins/factory/Factory.d.ts.map +1 -1
  48. package/lib/mixins/factory/Factory.test.d.ts +1 -0
  49. package/lib/mixins/factory/Factory.test.d.ts.map +1 -0
  50. package/lib/mixins/factory/const.d.ts +9 -2
  51. package/lib/mixins/factory/const.d.ts.map +1 -1
  52. package/lib/mixins/factory/defaults.d.ts +5 -0
  53. package/lib/mixins/factory/defaults.d.ts.map +1 -0
  54. package/lib/mixins/factory/methods.d.ts +1 -1
  55. package/lib/mixins/factory/methods.d.ts.map +1 -1
  56. package/lib/mixins/factory/props.d.ts +4 -2
  57. package/lib/mixins/factory/props.d.ts.map +1 -1
  58. package/lib/plugins/PopupManagerPlugin.d.ts +1 -1
  59. package/lib/plugins/PopupManagerPlugin.d.ts.map +1 -1
  60. package/lib/plugins/ResizerPlugin.d.ts +29 -0
  61. package/lib/plugins/ResizerPlugin.d.ts.map +1 -1
  62. package/lib/plugins/ResizerPlugin.test.d.ts +2 -0
  63. package/lib/plugins/ResizerPlugin.test.d.ts.map +1 -0
  64. package/lib/plugins/WebEventsPlugin.d.ts +5 -0
  65. package/lib/plugins/WebEventsPlugin.d.ts.map +1 -1
  66. package/lib/plugins/WebEventsPlugin.test.d.ts +2 -0
  67. package/lib/plugins/WebEventsPlugin.test.d.ts.map +1 -0
  68. package/lib/plugins/captions/CaptionsRenderer.d.ts +1 -1
  69. package/lib/plugins/captions/CaptionsRenderer.d.ts.map +1 -1
  70. package/lib/plugins/i18nPlugin.d.ts +29 -3
  71. package/lib/plugins/i18nPlugin.d.ts.map +1 -1
  72. package/lib/plugins/i18nPlugin.test.d.ts +2 -0
  73. package/lib/plugins/i18nPlugin.test.d.ts.map +1 -0
  74. package/lib/plugins/input/touch/VirtualControls.d.ts.map +1 -1
  75. package/lib/plugins/spine/pixi-spine/require-shim.d.ts +0 -1
  76. package/lib/plugins/spine/pixi-spine/require-shim.d.ts.map +1 -1
  77. package/lib/{registries-aN0y0Xha.js → registries-BLrxALZ0.js} +1124 -2801
  78. package/lib/registries-BLrxALZ0.js.map +1 -0
  79. package/lib/ui/Button.d.ts +1 -1
  80. package/lib/ui/Button.d.ts.map +1 -1
  81. package/lib/ui/FlexContainer.d.ts +1 -1
  82. package/lib/ui/FlexContainer.d.ts.map +1 -1
  83. package/lib/ui/Input.d.ts +2 -2
  84. package/lib/ui/Input.d.ts.map +1 -1
  85. package/lib/ui/Joystick.d.ts +1 -1
  86. package/lib/ui/Joystick.d.ts.map +1 -1
  87. package/lib/ui/Toast.d.ts +1 -1
  88. package/lib/ui/Toast.d.ts.map +1 -1
  89. package/lib/ui/UICanvas.d.ts +11 -1
  90. package/lib/ui/UICanvas.d.ts.map +1 -1
  91. package/lib/ui/UICanvas.test.d.ts +2 -0
  92. package/lib/ui/UICanvas.test.d.ts.map +1 -0
  93. package/lib/utils/types.d.ts +1 -2
  94. package/lib/utils/types.d.ts.map +1 -1
  95. package/package.json +1 -1
  96. package/src/core/Application.ts +15 -2
  97. package/src/core/interfaces/IApplicationOptions.ts +1 -1
  98. package/src/core/interfaces/ICoreFunctions.ts +1 -0
  99. package/src/display/AnimatedSprite.ts +2 -1
  100. package/src/display/Container.ts +3 -1
  101. package/src/display/SpineAnimation.ts +3 -2
  102. package/src/importOrder.containerFirst.test.ts +32 -0
  103. package/src/importOrder.displayFirst.test.ts +19 -0
  104. package/src/importOrder.mixinsFirst.test.ts +18 -0
  105. package/src/importOrder.sceneFirst.test.ts +21 -0
  106. package/src/importOrder.toastFirst.test.ts +20 -0
  107. package/src/importOrder.uiFirst.test.ts +24 -0
  108. package/src/mixins/factory/Factory.test.ts +22 -0
  109. package/src/mixins/factory/Factory.ts +9 -2
  110. package/src/mixins/factory/const.ts +18 -11
  111. package/src/mixins/factory/defaults.ts +28 -0
  112. package/src/mixins/factory/methods.ts +1 -1
  113. package/src/mixins/factory/props.ts +5 -3
  114. package/src/plugins/LookupPlugin.ts +1 -1
  115. package/src/plugins/PopupManagerPlugin.ts +1 -1
  116. package/src/plugins/ResizerPlugin.test.ts +84 -0
  117. package/src/plugins/ResizerPlugin.ts +59 -1
  118. package/src/plugins/WebEventsPlugin.test.ts +75 -0
  119. package/src/plugins/WebEventsPlugin.ts +15 -0
  120. package/src/plugins/captions/CaptionsRenderer.ts +1 -1
  121. package/src/plugins/i18nPlugin.test.ts +124 -0
  122. package/src/plugins/i18nPlugin.ts +57 -18
  123. package/src/plugins/input/keyboard/KeyboardContols.ts +1 -1
  124. package/src/plugins/input/touch/VirtualControls.ts +2 -2
  125. package/src/plugins/spine/pixi-spine/require-shim.ts +3 -1
  126. package/src/ui/Button.ts +5 -1
  127. package/src/ui/FlexContainer.ts +3 -2
  128. package/src/ui/Input.ts +5 -2
  129. package/src/ui/Joystick.ts +1 -1
  130. package/src/ui/Toast.ts +2 -1
  131. package/src/ui/Toaster.ts +1 -1
  132. package/src/ui/UICanvas.test.ts +35 -0
  133. package/src/ui/UICanvas.ts +46 -8
  134. package/src/utils/types.ts +1 -1
  135. package/src/version.ts +1 -1
  136. package/lib/CaptionsPlugin-DeGyPecB.js.map +0 -1
  137. package/lib/registries-aN0y0Xha.js.map +0 -1
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.2.2';\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\n/**\n * The `Caper.pwa` facade installed by the vite preset's runtime snippet. Reachable\n * from game code as `app.pwa`, which is `undefined` when the app was built without\n * the `pwa` option.\n *\n * Two timing rules matter:\n *\n * - `beforeinstallprompt` often fires before any scene exists, and signals do not\n * replay. UI that offers an install button must check `app.pwa?.canInstall` when\n * it mounts AND connect to `app.onPwaInstallAvailable` for the later case.\n * - Browsers only honour {@link CaperPWA.promptInstall} from inside a user gesture.\n * Call it from a click/tap handler — an overlay with an Install button. Calling it\n * from a timer, a scene transition, or a game-over event is silently ignored.\n */\nexport interface CaperPWA {\n readonly info: any;\n register: () => void;\n onRegisteredSW: (swScriptUrl: string) => void;\n offlineReady: () => void;\n /** Called when a new build is waiting. Defaults to caper's update banner; assign to replace it. */\n onNeedRefresh?: () => void;\n onRegisterError?: (error: any) => void;\n\n /** True once a new build is waiting to take over. */\n updateAvailable: boolean;\n /** Activate the waiting worker; the page reloads once it takes control. */\n applyUpdate: () => void;\n\n /** True once the browser has offered an install prompt to stash. */\n canInstall: boolean;\n /** Called when the browser offers the install prompt. */\n onCanInstall?: () => void;\n /** Called after the app is installed. */\n onInstalled?: () => void;\n /** Show the stashed install prompt. Resolves null when there is nothing to show. */\n promptInstall: () => Promise<'accepted' | 'dismissed' | null>;\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/debug.ts","../src/utils/define.ts","../src/utils/number.ts","../src/utils/padding.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/plugins/actions/methods.ts","../src/plugins/breakpoints/methods.ts","../src/plugins/input/touch/constants.ts","../src/plugins/input/methods.ts","../src/core/globals.ts","../src/core/create.ts","../src/display/Entity.ts","../src/display/ParticleContainer.ts","../src/display/Scene.ts","../src/display/SceneTransition.ts","../src/display/Svg.ts","../src/mixins/factory/utils.ts","../src/display/AnimatedSprite.ts","../src/display/Camera.ts","../src/display/SpineAnimation.ts","../src/mixins/focus.ts","../src/mixins/interaction.ts","../src/ui/Button.ts","../src/ui/FlexContainer.ts","../src/ui/Toast.ts","../src/ui/Toaster.ts","../src/ui/UICanvas.ts","../src/mixins/factory/registry.ts","../src/mixins/factory/ui-registry.ts","../src/mixins/factory/schema.ts","../src/mixins/factory/const.ts","../src/mixins/factory/props.ts","../src/ui/Input.ts","../src/ui/Joystick.ts","../src/ui/Popup.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 { Graphics, Text } from 'pixi.js';\n\n// --- Color palette ---\nexport const DebugColors = {\n bounds: 0x00ffff, // cyan — container bounds\n innerBounds: 0x00ff00, // green — content/child bounds\n outerBounds: 0xff0000, // red — outer/padding bounds\n direction: 0xffff00, // yellow — flow direction indicators\n gap: 0xff00ff, // magenta — gap/spacing fills\n region: 0x0078ff, // blue — grid regions\n} as const;\n\nexport const DebugAlpha = {\n stroke: 0.6,\n fill: 0.1,\n fillActive: 0.2,\n crosshair: 0.5,\n} as const;\n\n/**\n * Creates a Graphics object pre-configured for debug overlays.\n * Non-interactive, excluded from layout, labeled for identification.\n */\nexport function createDebugGraphics(label?: string): Graphics {\n const g = new Graphics();\n g.eventMode = 'none';\n g.interactiveChildren = false;\n g.layout = false;\n g.label = label ?? 'DebugGraphics';\n return g;\n}\n\n/**\n * Creates a small monospace Text label for debug overlays.\n * Dark stroke ensures readability over any background.\n */\nexport function createDebugLabel(text: string, color: number = DebugColors.bounds): Text {\n const label = new Text({\n text,\n style: {\n fontFamily: 'monospace',\n fontSize: 10,\n fill: color,\n stroke: { color: 0x000000, width: 2 },\n },\n });\n label.eventMode = 'none';\n label.layout = false;\n label.label = 'DebugLabel';\n return label;\n}\n\n// --- Registry ---\n// Tracks active debug items. A future DebugPanel can iterate\n// getDebugRegistry() to render a color → label legend.\ntype DebugEntry = { label: string; color: number };\nconst _registry = new Map<string, DebugEntry>();\n\nexport function registerDebug(id: string, label: string, color: number): void {\n _registry.set(id, { label, color });\n}\n\nexport function unregisterDebug(id: string): void {\n _registry.delete(id);\n}\n\nexport function getDebugRegistry(): ReadonlyMap<string, DebugEntry> {\n return _registry;\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","export function getZeroPaddedNumber(num: number, zeroPad: number = 0): string {\n return num.toString().padStart(zeroPad, '0');\n}\n","import type { Padding, PointLike } from './types';\n\nexport function resolvePadding(paddingNum: number, size: number) {\n // check of the paddingNum is a decimal between 0 and 1\n // if it is, return a number that is the percentage of the size\n if (paddingNum >= 0 && paddingNum <= 1) {\n return paddingNum * size;\n }\n return paddingNum;\n}\n\nexport function ensurePadding(padding: Partial<Padding> | PointLike): Padding {\n if (Array.isArray(padding)) {\n return {\n top: padding[0],\n right: padding?.[1] ?? padding[0],\n bottom: padding?.[2] ?? padding[0],\n left: padding?.[3] ?? padding?.[1] ?? padding[0] ?? 0,\n };\n }\n if (typeof padding === 'number') {\n return { top: padding, right: padding, bottom: padding, left: padding };\n } else if (typeof padding === 'object') {\n const paddingAsPointLike = padding as { x?: number; y?: number };\n if (paddingAsPointLike.x !== undefined && paddingAsPointLike.y !== undefined) {\n return {\n top: paddingAsPointLike.y,\n right: paddingAsPointLike.x,\n bottom: paddingAsPointLike.y,\n left: paddingAsPointLike.x,\n };\n } else {\n return {\n top: (padding as Padding).top ?? 0,\n right: (padding as Padding).right ?? 0,\n bottom: (padding as Padding).bottom ?? 0,\n left: (padding as Padding).left ?? 0,\n };\n }\n } else {\n return { top: 0, right: 0, bottom: 0, left: 0 };\n }\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.2.3';\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 { 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","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\n/**\n * The `Caper.pwa` facade installed by the vite preset's runtime snippet. Reachable\n * from game code as `app.pwa`, which is `undefined` when the app was built without\n * the `pwa` option.\n *\n * Two timing rules matter:\n *\n * - `beforeinstallprompt` often fires before any scene exists, and signals do not\n * replay. UI that offers an install button must check `app.pwa?.canInstall` when\n * it mounts AND connect to `app.onPwaInstallAvailable` for the later case.\n * - Browsers only honour {@link CaperPWA.promptInstall} from inside a user gesture.\n * Call it from a click/tap handler — an overlay with an Install button. Calling it\n * from a timer, a scene transition, or a game-over event is silently ignored.\n */\nexport interface CaperPWA {\n readonly info: any;\n register: () => void;\n onRegisteredSW: (swScriptUrl: string) => void;\n offlineReady: () => void;\n /** Called when a new build is waiting. Defaults to caper's update banner; assign to replace it. */\n onNeedRefresh?: () => void;\n onRegisterError?: (error: any) => void;\n\n /** True once a new build is waiting to take over. */\n updateAvailable: boolean;\n /** Activate the waiting worker; the page reloads once it takes control. */\n applyUpdate: () => void;\n\n /** True once the browser has offered an install prompt to stash. */\n canInstall: boolean;\n /** Called when the browser offers the install prompt. */\n onCanInstall?: () => void;\n /** Called after the app is installed. */\n onInstalled?: () => void;\n /** Show the stashed install prompt. Resolves null when there is nothing to show. */\n promptInstall: () => Promise<'accepted' | 'dismissed' | null>;\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","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 { DestroyOptions, ParticleContainerOptions, ParticleContainer as PIXIParticleContainer, Ticker } from 'pixi.js';\n\nimport { Application } from '../core/Application';\nimport { Signal } from '../signals';\nimport type { AppTypeOverrides, Size } from '../utils';\nimport { bindAllMethods } from '../utils';\n\n/**\n * Configuration for the Container class.\n */\nexport interface ParticleContainerConfig extends ParticleContainerOptions {\n autoUpdate: boolean;\n priority: number;\n}\n\nexport const ParticleContainerConfigKeys: (keyof ParticleContainerConfig)[] = ['autoUpdate', 'priority'];\n\nconst defaultConfig: ParticleContainerConfig = { autoUpdate: true, priority: 0 };\n\nexport interface IParticleContainer {\n app: AppTypeOverrides['App'];\n\n onDestroy: Signal<() => void>;\n\n destroy(options?: DestroyOptions): void;\n\n added(): Promise<void> | void;\n\n update(ticker?: Ticker | number): void;\n}\n\n/**\n * The Container class extends the _Container class (which includes the Animated and Factory mixins) and implements the IContainer interface.\n * It represents a container for PIXI.js display objects.\n */\nexport class ParticleContainer extends PIXIParticleContainer implements IParticleContainer {\n onDestroy: Signal<() => void> = new Signal();\n static __caper_method_binding_root = true;\n private __config: ParticleContainerConfig;\n\n /**\n * The constructor for the Container class.\n * @param config - The configuration for the container.\n */\n constructor(config: Partial<ParticleContainerConfig> = {}) {\n super(config);\n this.__config = { ...defaultConfig, ...config };\n // Bind all methods of this class to the current instance.\n bindAllMethods(this);\n // Add an event listener for the 'added' event.\n this.on('added', this._added);\n this.on('removed', this._removed);\n }\n\n /**\n * Get the application instance.\n */\n public get app(): AppTypeOverrides['App'] {\n return Application.getInstance() as AppTypeOverrides['App'];\n }\n /**\n * Update the container. This method is meant to be overridden by subclasses.\n * @param ticker\n */\n public update(ticker?: Ticker | number) {\n void ticker;\n }\n\n /**\n * Resize the container. This method is meant to be overridden by subclasses.\n * @param size\n */\n public resize(size?: Size) {\n void size;\n }\n\n /**\n * This method is called when the container is added to the stage. It is meant to be overridden by subclasses.\n */\n public added() {}\n\n destroy(options?: DestroyOptions): void {\n if (this.__config.autoUpdate) {\n this.app.ticker.remove(this.update, this);\n }\n this.onDestroy.emit();\n super.destroy(options);\n }\n\n public removed() {}\n /**\n * This method is called when the container is added to the stage. It sets up auto-resizing and auto-updating if enabled.\n */\n private _added() {\n if (this.__config.autoUpdate) {\n this.app.ticker.add(this.update, this, this.__config.priority);\n }\n this.added();\n }\n\n private _removed() {\n if (this.__config.autoUpdate) {\n this.app.ticker.remove(this.update, this);\n }\n this.removed();\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 { Assets, Graphics, GraphicsContext } from 'pixi.js';\n\nexport class Svg extends Graphics {\n constructor(ctx: string | GraphicsContext) {\n super(typeof ctx === 'string' ? Assets.get(ctx) : ctx);\n const bounds = this.getLocalBounds();\n this.pivot.set((bounds.x + bounds.width) / 2, (bounds.y + bounds.height) / 2);\n }\n}\n","import { Assets, Graphics, Sprite, Spritesheet, Texture } from 'pixi.js';\nimport { Logger, PointLike, resolvePointLike } from '../../utils';\n\nimport { Application } from '../../core/Application';\nimport { PositionProps, ScaleProps, TextureProps } from './props';\n\nlet errorTexture: Texture | undefined;\n\nexport function resolveUnknownKeys(props: any, entity: any) {\n for (const key in props) {\n try {\n (entity as any)[key] = props[key];\n } catch (e) {\n Logger.warn(`Error setting property ${key}`, e);\n }\n }\n}\n\nexport function getErrorTexture() {\n if (!errorTexture) {\n const gfx = new Graphics();\n gfx.rect(0, 0, 100, 100);\n gfx.fill({ color: 0xff0000 });\n gfx.stroke({ color: 0xffffff, width: 1, alignment: 0 });\n // draw an X across the rectangle\n gfx.moveTo(0, 0);\n gfx.lineTo(100, 100);\n gfx.moveTo(100, 0);\n gfx.lineTo(0, 100);\n gfx.stroke({ color: 0xffffff, width: 2, alignment: 0.5 });\n errorTexture = Application.getInstance().renderer.generateTexture(gfx);\n gfx.destroy();\n }\n return errorTexture;\n}\n\nexport function resolveTexture(props?: Partial<TextureProps>): Texture {\n let texture: Texture | undefined;\n const asset = props?.asset;\n const assetAsString = asset as string;\n const sheet = props?.sheet;\n if (asset instanceof Texture) {\n texture = asset;\n } else if (!sheet || sheet?.length === 0) {\n if (Assets.cache.has(assetAsString)) {\n texture = Assets.get(assetAsString)!;\n } else if (Assets.get(assetAsString)) {\n texture = Assets.get(assetAsString).texture!;\n } else {\n Logger.error('Asset \"' + asset + '\" not loaded into Pixi cache');\n texture = getErrorTexture();\n //throw new Error('Asset \"' + asset + '\" not loaded into Pixi cache');\n }\n } else {\n if (!Assets.get(sheet)) {\n // throw new Error('Spritesheet \"' + sheet + '\" not loaded into Pixi cache');\n Logger.error('Spritesheet \"' + sheet + '\" not loaded into Pixi cache');\n return getErrorTexture();\n } else {\n const spriteSheet: Spritesheet = Assets.get(sheet) as Spritesheet;\n const textures = spriteSheet.textures;\n if (textures !== undefined) {\n // eslint-disable-next-line no-prototype-builtins\n if (textures.hasOwnProperty(assetAsString)) {\n texture = textures[assetAsString];\n } else if (spriteSheet.linkedSheets !== undefined && spriteSheet.linkedSheets.length > 0) {\n for (const linkedSheet of spriteSheet.linkedSheets) {\n // eslint-disable-next-line no-prototype-builtins\n if (linkedSheet.textures !== undefined && linkedSheet.textures.hasOwnProperty(assetAsString)) {\n texture = linkedSheet.textures[assetAsString];\n break;\n }\n }\n if (texture === undefined) {\n Logger.error(\n 'Asset \"' + asset + '\" not found inside spritesheet \"' + asset + \"' or any of its linked sheets\",\n );\n texture = getErrorTexture();\n }\n } else {\n Logger.error('Asset \"' + asset + '\" not found inside spritesheet \"' + sheet + \"'\");\n texture = getErrorTexture();\n }\n } else {\n Logger.error('Spritesheet \"' + sheet + '\" loaded but textures arent?!');\n texture = getErrorTexture();\n }\n }\n }\n return texture || new Sprite().texture;\n}\n\nexport function resolvePosition(props: Partial<PositionProps>, entity: any) {\n const pos = resolvePointLike(props.position, false, props.x, props.y);\n entity.x = pos.x;\n entity.y = pos.y;\n}\n\nexport function resolveScale(props: Partial<ScaleProps>, entity: any) {\n if (!props) {\n return;\n }\n if (props.scale === undefined) {\n if (props.scaleX === undefined && props.scaleY === undefined) {\n return;\n }\n if (props.scaleX === undefined) {\n props.scaleX = 1;\n }\n if (props.scaleY === undefined) {\n props.scaleY = 1;\n }\n }\n const scale = resolvePointLike(props.scale, false, props.scaleX, props.scaleY);\n entity.scale.set(scale.x, scale.y);\n}\n\nexport function resolveAnchor(anchor: PointLike | undefined, entity: any) {\n if (anchor !== undefined) {\n const anchorPoint = resolvePointLike(anchor);\n entity.anchor.set(anchorPoint.x, anchorPoint.y);\n }\n}\n\nexport function resolvePivot(pivot: PointLike | undefined, entity: any) {\n if (pivot !== undefined) {\n const pivotPoint = resolvePointLike(pivot);\n entity.pivot.set(pivotPoint.x, pivotPoint.y);\n }\n}\n","import { AnimatedSprite as PIXIAnimatedSprite, Texture, Ticker } from 'pixi.js';\nimport type { AnimatedSpriteProps } from '../mixins/factory/props';\nimport { resolveTexture } from '../mixins/factory/utils';\nimport { Signal } from '../signals';\nimport {\n bindAllMethods,\n getFirstMapEntry,\n getLastMapEntry,\n getNextMapEntry,\n getPreviousMapEntry,\n getZeroPaddedNumber,\n type SpritesheetAsset,\n} from '../utils';\n\nexport class AnimatedSprite extends PIXIAnimatedSprite {\n onAnimationChange: Signal<(currentAnimation: string) => void> = new Signal();\n onAnimationStart: Signal<() => void> = new Signal();\n onAnimationStop: Signal<() => void> = new Signal();\n onAnimationLoop: Signal<() => void> = new Signal();\n onAnimationComplete: Signal<() => void> = new Signal();\n onAnimationFrameChange: Signal<() => void> = new Signal();\n public defaultTexturePrefix: string = '';\n public defaultSheet: string | undefined;\n public defaultAnimation: string;\n public defaultAnimationSpeed: number;\n public defaultZeroPad: number | undefined;\n public autoPlay: boolean;\n public currentAnimation: string;\n protected _animations: Map<string, Texture[]>;\n\n constructor(protected config?: Partial<AnimatedSpriteProps>) {\n // get default animation\n const animations = config?.animations ?? {};\n const defaultAnimationName = config?.animation ?? Object.keys(animations)[0];\n const defaultAnimation = animations[defaultAnimationName as string];\n const defaultSheet = config?.sheet;\n const defaultTexturePrefix = config?.texturePrefix || '';\n const defaultZeroPad = config?.zeroPad;\n const defaultStartIndex = config?.startIndex ?? 0;\n\n super(\n AnimatedSprite.generateTexturesFromProps(\n defaultAnimationName,\n defaultAnimation,\n defaultTexturePrefix,\n defaultSheet,\n defaultZeroPad,\n defaultStartIndex,\n ),\n config?.autoUpdate !== false,\n );\n bindAllMethods(this);\n this.defaultSheet = defaultSheet;\n this.defaultTexturePrefix = defaultTexturePrefix;\n this.defaultZeroPad = defaultZeroPad;\n this._generateAnimations();\n this.currentAnimation = this.defaultAnimation = defaultAnimationName;\n this.autoPlay = config?.autoPlay ?? true;\n this.loop = config?.loop ?? true;\n this.updateAnchor = config?.updateAnchor ?? false;\n this.animationSpeed = this.defaultAnimationSpeed = config?.animationSpeed ?? 1;\n this.on('added', this._added);\n }\n\n protected _paused: boolean = false;\n\n get paused(): boolean {\n return this._paused;\n }\n\n set paused(value: boolean) {\n this._paused = value;\n }\n\n get speed(): number {\n return this.animationSpeed;\n }\n\n set speed(value: number) {\n this.animationSpeed = this.defaultAnimationSpeed = value;\n }\n\n protected _isReversed: boolean = false;\n\n get isReversed(): boolean {\n return this._isReversed;\n }\n\n static generateTexturesFromProps(\n animationName: string,\n props?: Partial<AnimatedSpriteProps>,\n defaultTexturePrefix = '',\n defaultSheet: SpritesheetAsset | undefined = undefined,\n defaultZeroPad?: number,\n defaultStartIndex?: number,\n ): Texture[] {\n const textures: Texture[] = [];\n let asset = '';\n const sheet = props?.sheet ?? defaultSheet;\n if (props?.numFrames > 1) {\n const idx = props?.startIndex ?? defaultStartIndex ?? 0;\n for (let i = idx; i < idx + props?.numFrames; i++) {\n asset = `${defaultTexturePrefix}${props?.texturePrefix ?? animationName}${getZeroPaddedNumber(i, props?.zeroPad ?? defaultZeroPad)}`;\n textures.push(\n resolveTexture({\n asset,\n sheet,\n }),\n );\n }\n } else {\n asset = `${defaultTexturePrefix}${props?.texturePrefix ?? animationName}`;\n textures.push(\n resolveTexture({\n asset,\n sheet,\n }),\n );\n }\n return textures;\n }\n\n reverse() {\n this._isReversed = !this._isReversed;\n if (this._isReversed) {\n this.setAnimation(`${this.currentAnimation}_reverse`);\n } else {\n this.setAnimation(this.currentAnimation.split('_reverse')[0]);\n }\n }\n\n setAnimation(animationName: string, autoPlay: boolean = true) {\n if (!this._animations.has(animationName)) {\n throw new Error(`Animation ${animationName} does not exist`);\n }\n this.textures = this._animations.get(animationName) as Texture[];\n this.currentAnimation = animationName;\n const animSpeed = this.config?.animations?.[animationName.split('_reverse')[0]]?.animationSpeed;\n if (animSpeed) {\n this.animationSpeed = animSpeed;\n } else {\n this.animationSpeed = this.defaultAnimationSpeed;\n }\n this.onAnimationChange.emit(animationName);\n if (autoPlay) {\n this.play();\n }\n }\n\n play() {\n super.play();\n this.onAnimationStart?.emit();\n }\n\n stop() {\n super.stop();\n this.onAnimationStop?.emit();\n }\n\n nextAnimation() {\n const entry = getNextMapEntry(this._animations, this.currentAnimation) ?? getFirstMapEntry(this._animations);\n if (entry) {\n this.setAnimation(entry[0]);\n }\n }\n\n previousAnimation() {\n const entry = getPreviousMapEntry(this._animations, this.currentAnimation) ?? getLastMapEntry(this._animations);\n if (entry) {\n this.setAnimation(entry[0]);\n }\n }\n\n update(ticker: Ticker) {\n if (this._paused) {\n return;\n }\n super.update(ticker);\n }\n\n private _generateAnimations() {\n this._animations = new Map();\n const animations = this.config?.animations ?? {};\n if (animations) {\n for (const [key, value] of Object.entries(animations)) {\n this._animations.set(\n key,\n AnimatedSprite.generateTexturesFromProps(\n key,\n value,\n this.defaultTexturePrefix,\n this.defaultSheet,\n this.defaultZeroPad,\n ),\n );\n }\n if (this.config?.reversible) {\n for (const [key, value] of Object.entries(animations)) {\n const textures = AnimatedSprite.generateTexturesFromProps(\n key,\n value,\n this.defaultTexturePrefix,\n this.defaultSheet,\n this.defaultZeroPad,\n );\n textures.reverse();\n this._animations.set(`${key}_reverse`, textures);\n }\n }\n }\n }\n\n private _added() {\n this.onLoop = () => {\n this.onAnimationLoop.emit();\n };\n this.onComplete = () => {\n this.onAnimationComplete.emit();\n };\n this.onFrameChange = () => {\n this.onAnimationFrameChange.emit();\n };\n\n if (this.autoPlay) {\n this.play();\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 { type AnimationStateListener, type Event, type TrackEntry } from '@esotericsoftware/spine-core';\nimport { Application } from '../core/Application';\nimport type { SpineProps } from '../mixins/factory/props';\nimport { Factory } from '../mixins/factory/Factory';\nimport { WithSignals } from '../mixins/signals';\nimport { Signal } from '../signals';\nimport { type AppTypeOverrides, bindAllMethods, Spine } from '../utils';\n\nconst _SpineAnimation = WithSignals(Factory());\n\nexport interface ISpineAnimation<ANames extends string = string> extends InstanceType<typeof _SpineAnimation> {\n readonly spine: Spine;\n readonly animationNames: ANames[];\n readonly app: AppTypeOverrides['App'];\n readonly onAnimationComplete: Signal<(entry: TrackEntry) => void>;\n readonly onAnimationStart: Signal<(entry: TrackEntry) => void>;\n readonly onAnimationInterrupt: Signal<(entry: TrackEntry) => void>;\n readonly onAnimationDispose: Signal<(entry: TrackEntry) => void>;\n readonly onAnimationEnd: Signal<(entry: TrackEntry) => void>;\n readonly onAnimationEvent: Signal<(entry: TrackEntry, event: Event) => void>;\n readonly onPaused: Signal<(entry: TrackEntry | null) => void>;\n readonly onResumed: Signal<(entry: TrackEntry | null) => void>;\n setAnimation(name: ANames, loop?: boolean, tracklndex?: number): void;\n getCurrentAnimation(tracklndex?: number): ANames;\n pause(): void;\n resume(): void;\n togglePause(): void;\n}\n\nexport class SpineAnimation<ANames extends string = string> extends _SpineAnimation {\n spine: Spine;\n paused: boolean;\n\n onAnimationComplete: Signal<(entry: TrackEntry) => void> = new Signal();\n onAnimationStart: Signal<(entry: TrackEntry) => void> = new Signal();\n onAnimationInterrupt: Signal<(entry: TrackEntry) => void> = new Signal();\n onAnimationDispose: Signal<(entry: TrackEntry) => void> = new Signal();\n onAnimationEnd: Signal<(entry: TrackEntry) => void> = new Signal();\n onAnimationEvent: Signal<(entry: TrackEntry, event: Event) => void> = new Signal();\n\n onPaused: Signal<(entry: TrackEntry | null) => void> = new Signal();\n onResumed: Signal<(entry: TrackEntry | null) => void> = new Signal();\n\n protected _stateListener: AnimationStateListener;\n\n get app(): AppTypeOverrides['App'] {\n return Application.getInstance();\n }\n\n get animationNames(): ANames[] {\n return this.spine.state.data.skeletonData.animations.map((a) => a.name) as ANames[];\n }\n\n get currentEntry() {\n return this.spine.state.getCurrent(0);\n }\n\n get elapsedAnimationTime() {\n if (this.currentEntry) {\n return this.currentEntry.trackTime;\n }\n return -1;\n }\n\n public constructor(props?: Partial<SpineProps>) {\n super();\n bindAllMethods(this);\n let data = props?.data;\n let spineData: { skeleton: string; atlas: string } | string = '';\n if (typeof data === 'string') {\n // get the spine data from cache\n // check if '.json' is the last part of the asset string, and add it if not\n let ext = data.slice(-5);\n if (ext !== '.json' && ext !== '.skel') {\n ext = '.json';\n } else {\n data = data.substring(0, data.length - 5);\n }\n spineData = { skeleton: data + ext, atlas: data + '.atlas' };\n }\n this.spine = (window as any).Spine.from(spineData);\n this.add.existing(this.spine);\n\n if (props) {\n if (props.autoUpdate !== undefined) this.spine.autoUpdate = props.autoUpdate;\n if (props.animationName) this.setAnimation(props.animationName as ANames, props.loop, props.trackIndex ?? 0);\n }\n\n this.addSignalConnection(this.app.actions('toggle_pause').connect(this.togglePause));\n\n if (props?.paused) {\n this.pause();\n }\n\n this._stateListener = {\n start: this._handleAnimationStart,\n interrupt: this._handleAnimationInterrupt,\n dispose: this._handleAnimationDispose,\n end: this._handleAnimationEnd,\n event: this._handleAnimationEvent,\n complete: this._handleAnimationComplete,\n };\n\n this.spine.state.addListener(this._stateListener);\n }\n\n destroy() {\n this.spine.state.removeListener(this._stateListener);\n super.destroy();\n }\n\n getCurrentAnimation(trackIndex: number = 0): ANames {\n return (this.spine.state.getCurrent(trackIndex)?.animation?.name as ANames) || ('' as ANames);\n }\n\n setAnimation(name: ANames, loop = false, tracklndex: number = 0) {\n this.spine.state.setAnimation(tracklndex, name, loop);\n }\n\n pause() {\n this.paused = true;\n this.spine.autoUpdate = false;\n\n if (this.currentEntry) {\n this.currentEntry.timeScale = 0;\n }\n this.onPaused.emit(this.currentEntry);\n }\n\n resume() {\n this.paused = false;\n this.spine.autoUpdate = true;\n if (this.currentEntry) {\n this.currentEntry.timeScale = 1;\n }\n this.onResumed.emit(this.currentEntry);\n }\n\n togglePause() {\n if (this.paused) {\n this.resume();\n } else {\n this.pause();\n }\n }\n\n // protected methods\n protected _handleAnimationComplete(entry: TrackEntry) {\n this.onAnimationComplete.emit(entry);\n }\n\n protected _handleAnimationStart(entry: TrackEntry) {\n this.onAnimationStart.emit(entry);\n }\n\n protected _handleAnimationInterrupt(entry: TrackEntry) {\n this.onAnimationInterrupt.emit(entry);\n }\n\n protected _handleAnimationDispose(entry: TrackEntry) {\n this.onAnimationDispose.emit(entry);\n }\n\n protected _handleAnimationEnd(entry: TrackEntry) {\n this.onAnimationEnd.emit(entry);\n }\n\n protected _handleAnimationEvent(entry: TrackEntry, event: Event) {\n this.onAnimationEvent.emit(entry, event);\n }\n}\n","import type { DestroyOptions, PointerEvents } from 'pixi.js';\nimport { Container, FederatedEvent } from 'pixi.js';\nimport type { Constructor, PointLike } from '../utils';\n\nimport { Application } from '../core/Application';\nimport type { IFocusable } from '../plugins';\nimport { Signal } from '../signals';\n\n/**\n * The Focusable function is a higher-order function that adds focus-related functionality to a given class.\n *\n * @param {TBase extends Constructor<Container>} Base - The base class to add focus functionality to.\n *\n * @returns {TBase & Constructor<IFocusable>} The modified class with focus functionality.\n */\nexport function Focusable<TBase extends Constructor<Container>>(Base: TBase): TBase & Constructor<IFocusable> {\n return class extends Base implements IFocusable {\n _accessibleDiv: HTMLElement;\n isFocused = false;\n isKeyDown = false;\n focusEnabled = true;\n tabIndex = 0;\n // pixi accessibility options\n accessible = false;\n accessibleType: keyof HTMLElementTagNameMap | undefined = 'button';\n accessibleTitle = 'Focusable';\n accessibleHint = 'Press enter to focus';\n accessiblePointerEvents: PointerEvents = 'auto';\n accessibleChildren = true;\n // signals\n onFocus = new Signal<(focusable: IFocusable) => void>();\n onFocusIn = new Signal<(focusable: IFocusable) => void>();\n onFocusOut = new Signal<(focusable: IFocusable) => void>();\n onBlur = new Signal<(focusable: IFocusable) => void>();\n\n private _eventsDisabled: boolean = false;\n\n constructor(...args: any[]) {\n super(...args);\n this.eventMode = 'static';\n this.on('mouseover', this._onMouseOver);\n this.on('mousedown', this._onMouseDown);\n this.on('click', this._handleClick);\n this.on('tap', this._handleClick);\n }\n\n get app() {\n return Application.getInstance();\n }\n\n public destroy(options?: DestroyOptions): void {\n this.off('mouseover', this._onMouseOver);\n this.off('mousedown', this._onMouseDown);\n this.off('click', this._handleClick);\n this.off('tap', this._handleClick);\n super.destroy(options);\n }\n\n public focusIn() {\n if (this.app.focus.active) {\n // @ts-expect-error Argument of type { type: string; } is not assignable to parameter of type FederatedPointerEvent\n this.emit('pointerover', { type: 'pointerover' });\n }\n }\n\n public blur() {\n if (!this.isKeyDown) {\n window.removeEventListener('keyup', this._handleKeyUp.bind(this));\n }\n }\n\n public focusOut() {\n if (!this.isKeyDown) {\n window.removeEventListener('keyup', this._handleKeyUp.bind(this));\n }\n if (this.app.focus.active) {\n // @ts-expect-error Argument of type { type: string; } is not assignable to parameter of type FederatedPointerEvent\n this.emit('pointerout', { type: 'pointerout' });\n }\n }\n\n public click() {}\n\n public getFocusPosition() {\n return null;\n }\n\n public getFocusArea() {\n return this.getBounds();\n }\n\n public getFocusSize(): PointLike | null {\n return [this.getFocusArea().width, this.getFocusArea().height];\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _onMouseOver(_e: MouseEvent) {\n this.app.focus.setFocus(this);\n }\n\n protected _onMouseDown(e: FederatedEvent) {\n this._maybeEmit('pointerdown', e);\n }\n\n protected _handleClick(e: FederatedEvent) {\n this._maybeEmit('click', e);\n this.click();\n }\n\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n protected _handleKeyUp(_e: KeyboardEvent) {}\n\n private _maybeEmit(type: string, e: FederatedEvent) {\n if (this._eventsDisabled || e.type) {\n return;\n }\n this._eventsDisabled = true;\n this.emit(type, { type });\n this._eventsDisabled = false;\n }\n } as unknown as TBase & Constructor<IFocusable>;\n}\n\nFocusable.INITTED = false;\n","import type { AllFederatedEventMap, DestroyOptions } from 'pixi.js';\nimport { Container, FederatedEvent } from 'pixi.js';\nimport { Signal } from '../signals';\n\nimport { type Constructor } from '../utils';\n\n// gets all the event names from the PIXI event map\ntype InteractionEventName = keyof AllFederatedEventMap;\n\nexport type InteractionSignal = Signal<(event: FederatedEvent) => void>;\n\n/**\n * Represents an interactive element.\n */\nexport interface IInteractive {\n onInteraction: (eventName: InteractionEventName) => InteractionSignal;\n}\n\n/**\n * Adds interactive functionality to a container.\n *\n * @param {Constructor<Container>} Base - The base container class.\n * @returns {Constructor<IInteractive>} - The extended container class with interactive functionality.\n */\nexport function Interactive<TBase extends Constructor<Container>>(Base: TBase): TBase & Constructor<IInteractive> {\n return class extends Base implements IInteractive {\n private _signals: Map<InteractionEventName, InteractionSignal> = new Map();\n\n constructor(...args: any[]) {\n super(...args);\n this._emitSignal = this._emitSignal.bind(this);\n this.eventMode = 'static';\n }\n\n /**\n * Handles interaction events and returns the corresponding signal.\n *\n * @param {InteractionEventName} eventName - The name of the interaction event.\n * @return {InteractionSignal} The signal associated with the interaction event.\n */\n public onInteraction(eventName: InteractionEventName) {\n if (!this._signals.has(eventName)) {\n const signal = new Signal<(event: FederatedEvent) => void>();\n this._signals.set(eventName, signal);\n this.on(eventName, this._emitSignal);\n }\n return this._signals.get(eventName) as InteractionSignal;\n }\n\n public destroy(options: DestroyOptions): void {\n for (const eventName of this._signals.keys()) {\n this.off(eventName, this._emitSignal);\n }\n this._signals.clear();\n super.destroy(options);\n }\n\n /**\n * Emits a signal with the given event.\n *\n * @param {FederatedEvent} event - The event to emit.\n *\n * @return {void}\n */\n private _emitSignal(event: FederatedEvent) {\n const signalName = event.type as InteractionEventName;\n const signal = this._signals.get(signalName);\n\n if (signal) {\n signal.emit(event);\n }\n }\n } as unknown as TBase & Constructor<IInteractive>;\n}\n","import {\n BitmapText,\n Cursor,\n DestroyOptions,\n FederatedEvent,\n FederatedPointerEvent,\n HTMLText,\n Sprite,\n Text,\n} from 'pixi.js';\n\nimport { type LayoutOptions } from '@pixi/layout';\nimport type { IApplication } from '../core';\nimport { Application } from '../core/Application';\nimport { Factory } from '../mixins/factory/Factory';\nimport type { HTMLTextProps, TextProps } from '../mixins/factory/props';\nimport { Focusable } from '../mixins/focus';\nimport { Interactive } from '../mixins/interaction';\nimport { WithSignals } from '../mixins/signals';\nimport { Signal } from '../signals';\nimport { AudioAsset, bindAllMethods, type SpritesheetAsset, type TextureAsset } from '../utils';\n\nexport type ButtonCallback = (() => void) | (() => Promise<void>);\nexport type ButtonAction = { id: string | number; data?: any };\n\nexport type ButtonActionOrCallback = ButtonAction | ButtonCallback;\n\ntype ButtonTextureId = 'default' | 'hover' | 'active' | 'disabled';\n\nexport interface IButton {\n // signals\n onDown: Signal<() => void>;\n onUp: Signal<() => void>;\n onUpOutside: Signal<() => void>;\n onOut: Signal<() => void>;\n onOver: Signal<() => void>;\n onClick: Signal<() => void>;\n onEnabled: Signal<() => void>;\n onDisabled: Signal<() => void>;\n onDestroy: Signal<() => void>;\n onKeyboardEvent: Signal<(key: string) => void>;\n // visual\n view: Sprite;\n // whether the button is down\n isDown: boolean;\n isOver: boolean;\n //\n id: string;\n}\n\nexport type ButtonConfig = {\n id: string;\n textures: {\n default: TextureAsset;\n hover?: TextureAsset;\n active?: TextureAsset;\n disabled?: TextureAsset;\n };\n sounds?: {\n hover?: AudioAsset;\n out?: AudioAsset;\n down?: AudioAsset;\n click?: AudioAsset;\n };\n actions?: {\n hover?: ButtonActionOrCallback;\n out?: ButtonActionOrCallback;\n down?: ButtonActionOrCallback;\n click?: ButtonActionOrCallback;\n };\n textLabel?: Partial<TextProps | HTMLTextProps> & { type?: 'text' | 'html' | 'bitmap' };\n cursor: Cursor;\n disabledCursor: Cursor;\n sheet: SpritesheetAsset;\n enabled: boolean;\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n};\n\nexport const ButtonConfigKeys: (keyof ButtonConfig)[] = [\n 'textures',\n 'sounds',\n 'actions',\n 'cursor',\n 'disabledCursor',\n 'sheet',\n 'enabled',\n 'layout',\n 'textLabel',\n];\n\n// Create a new class that extends Container and includes the Interactive and Focusable mixins.\nconst _Button = Focusable(Interactive(WithSignals(Factory())));\n\n/**\n * @class\n * @extends {Container}\n * A class representing a button.\n */\nexport class Button extends _Button implements IButton {\n // signals\n public onDown = new Signal<() => void>();\n public onUp = new Signal<() => void>();\n public onUpOutside = new Signal<() => void>();\n public onOut = new Signal<() => void>();\n public onOver = new Signal<() => void>();\n public onClick = new Signal<() => void>();\n public onEnabled = new Signal<() => void>();\n public onDisabled = new Signal<() => void>();\n public onKeyboardEvent = new Signal<(key: string) => void>();\n public onDestroy = new Signal<() => void>();\n public id: string;\n // visual\n public view: Sprite;\n // whether the button is down\n public isDown: boolean;\n public isOver: boolean;\n // config\n protected config: ButtonConfig;\n // a set of unique callbacks for when the button is down\n protected _isDownCallbacks: Map<string, () => void> = new Map();\n private _isDownListenerAdded: boolean = false;\n private _pointerId?: number;\n private _textLabel?: Text | HTMLText | BitmapText;\n\n /**\n * The text label of the button.\n * @returns {Text | HTMLText | BitmapText | undefined} The text label instance.\n */\n get textLabel() {\n return this._textLabel;\n }\n\n /**\n * @constructor\n * @param {Partial<ButtonConfig>} config - The configuration for the button.\n */\n constructor(config: Partial<ButtonConfig>) {\n super();\n\n bindAllMethods(this);\n\n this.config = Object.assign(\n {\n id: 'button',\n textures: { default: '' },\n sheet: undefined,\n enabled: true,\n cursor: 'default',\n disabledCursor: 'not-allowed',\n },\n config,\n ) as ButtonConfig;\n\n this.id = this.config.id;\n\n // Allow layout to be set via config, but default to false\n if (config.layout !== undefined) {\n this.layout = config.layout;\n } else {\n this.layout = false;\n }\n\n // Create a sprite with the default texture and add it to the container.\n this.view = this.add.sprite({\n asset: this.config.textures.default,\n sheet: this.config.sheet ?? undefined,\n });\n\n this.cursor = this.config.cursor;\n this.enabled = config.enabled !== false;\n\n if (this.layout?.style.transformOrigin !== 'top left') {\n this.layout = { transformOrigin: 'top left' };\n if (this.app.renderer.layout) {\n this.app.renderer.layout.update(this);\n }\n }\n\n if (this.config.textLabel) {\n this.addLabel(this.config.textLabel);\n }\n\n // Set up interaction handlers.\n // make them high priority so they run before any other interaction handlers\n this.addSignalConnection(\n this.onInteraction('pointerover').connect(this.handlePointerOver, -1),\n this.onInteraction('pointerout').connect(this.handlePointerOut, -1),\n this.onInteraction('pointerup').connect(this.handlePointerUp, -1),\n this.onInteraction('click').connect(this.handleClick, -1),\n this.onInteraction('tap').connect(this.handleClick, -1),\n this.onInteraction('pointerdown').connect(this.handlePointerDown, -1),\n );\n }\n\n // enabled state\n protected _enabled: boolean;\n\n /**\n * Sets the enabled state of the button.\n * @param {boolean} enabled - Whether the button is enabled.\n */\n public set enabled(enabled: boolean) {\n if (this._enabled === enabled) {\n return;\n }\n this._enabled = enabled;\n this.cursor = this._enabled ? this.config.cursor : this.config.disabledCursor;\n this.focusEnabled = enabled;\n if (this._enabled) {\n this.view.texture = this.make.texture({\n asset: this.config.textures.default,\n sheet: this.config.sheet ?? undefined,\n });\n this.onEnabled.emit();\n } else {\n this.view.texture = this.make.texture({\n asset: this.config.textures.disabled || this.config.textures.default,\n sheet: this.config.sheet ?? undefined,\n });\n this.onDisabled.emit();\n }\n }\n\n public addLabel<T extends Text | HTMLText | BitmapText>(\n config: (Partial<TextProps | HTMLTextProps> & { type?: 'text' | 'html' | 'bitmap' }) | T,\n ): T {\n if (config instanceof Text || config instanceof HTMLText || config instanceof BitmapText) {\n config.anchor.set(0.5, 0.5);\n this._textLabel = this.add.existing(config) as T;\n this._textLabel.layout = false;\n } else {\n config.anchor = 0.5;\n switch (config.type) {\n case 'bitmap':\n this._textLabel = this.add.bitmapText({ ...config, layout: false }) as BitmapText;\n break;\n case 'html':\n this._textLabel = this.add.htmlText({ ...config, layout: false }) as HTMLText;\n break;\n default:\n this._textLabel = this.add.text({ ...config, layout: false }) as Text;\n break;\n }\n }\n\n this.positionLabel();\n\n return this._textLabel as T;\n }\n\n public positionLabel() {\n if (this._textLabel) {\n this._textLabel.position.set(this.view.width * 0.5, this.view.height * 0.5);\n }\n }\n\n public get enabled() {\n return this._enabled;\n }\n\n get app(): IApplication {\n return Application.getInstance();\n }\n\n destroy(options?: DestroyOptions) {\n this.onDestroy.emit();\n super.destroy(options);\n }\n\n focusOut() {\n super.focusOut();\n this.isDown = false;\n this.isOver = false;\n }\n\n blur() {\n super.blur();\n this.isDown = false;\n this.isOver = false;\n }\n\n public getFocusArea() {\n return this.view.getBounds().clone();\n }\n\n addIsDownCallback(callbackId: string, callback: () => void) {\n this._isDownCallbacks.set(callbackId, callback);\n this._checkIsDownCallbacks();\n }\n\n removeIsDownCallback(callbackId: string) {\n this._isDownCallbacks.delete(callbackId);\n }\n\n setTexture(textureId: ButtonTextureId, texture: TextureAsset) {\n this.config.textures[textureId] = texture;\n if (textureId === 'default') {\n this.view.texture = this.make.texture({\n asset: this.config.textures.default,\n sheet: this.config.sheet,\n });\n }\n\n this.positionLabel();\n }\n\n /**\n * Sets the texture of the button to the hover texture and emits the onOver event.\n */\n protected handlePointerOver() {\n if (!this._enabled) {\n return;\n }\n if (!this.isOver) {\n this.isOver = true;\n }\n if (this.isDown) {\n return;\n }\n this.view.texture = this.make.texture({\n asset: this.config.textures.hover || this.config.textures.default,\n sheet: this.config.sheet,\n });\n this.onOver.emit();\n if (this.config.sounds?.hover) {\n void this.app.audio.play(this.config.sounds.hover, 'sfx');\n }\n if (this.config.actions?.hover) {\n this._doAction(this.config.actions.hover);\n }\n }\n\n /**\n * Sets the texture of the button to the default texture and emits the onOut event.\n */\n protected handlePointerOut() {\n this.isOver = false;\n if (!this._enabled) {\n return;\n }\n if (this.isDown) {\n return;\n }\n this.view.texture = this.make.texture({ asset: this.config.textures.default, sheet: this.config.sheet });\n\n if (this.config.sounds?.out) {\n void this.app.audio.play(this.config.sounds.out, 'sfx');\n }\n this.onOut.emit();\n }\n\n /**\n * Sets the isDown property to true and changes the texture of the button.\n */\n protected handlePointerDown(e: FederatedEvent) {\n if (!this._enabled && !this.isKeyDown) {\n return;\n }\n if (!this.isDown && this._pointerId === undefined) {\n this._pointerId = (e as FederatedPointerEvent).pointerId;\n\n window.removeEventListener('pointerup', this.handlePointerUpOutside);\n this.off('pointerupoutside', this.handlePointerUpOutside);\n\n window.addEventListener('pointerup', this.handlePointerUpOutside);\n this.on('pointerupoutside', this.handlePointerUpOutside);\n\n this.isDown = true;\n this.view.texture = this.make.texture({\n asset: this.config.textures.active || this.config.textures.hover || this.config.textures.default,\n sheet: this.config.sheet,\n });\n this.onDown.emit();\n if (this.config.sounds?.down) {\n void this.app.audio.play(this.config.sounds.down, 'sfx');\n }\n if (this.config.actions?.down) {\n this._doAction(this.config.actions.down);\n }\n }\n }\n\n /**\n * Removes the keyup event listener and emits the onPress and onUp events.\n */\n protected handlePointerUp(e: FederatedEvent) {\n if (!this._enabled || !this.isOver || (e as FederatedPointerEvent).pointerId !== this._pointerId) {\n return;\n }\n window.removeEventListener('pointerup', this.handlePointerUpOutside);\n\n this.view.texture = this.make.texture({ asset: this.config.textures.default, sheet: this.config.sheet });\n this.onUp.emit();\n\n this._pointerId = undefined;\n }\n\n protected handleClick() {\n if (!this._enabled) {\n return;\n }\n this.isDown = false;\n this.onClick.emit();\n if (this.config.sounds?.click) {\n void this.app.audio.play(this.config.sounds.click, 'sfx');\n }\n if (this.config.actions?.click) {\n this._doAction(this.config.actions.click);\n }\n }\n\n /**\n * Handles the pointer up event.\n */\n protected handlePointerUpOutside(e: PointerEvent | FederatedPointerEvent) {\n if (!this._enabled || e.pointerId !== this._pointerId) {\n return;\n }\n window.removeEventListener('pointerup', this.handlePointerUpOutside);\n this.off('pointerupoutside', this.handlePointerUpOutside);\n this.view.texture = this.make.texture({ asset: this.config.textures.default, sheet: this.config.sheet });\n this.isDown = false;\n this.isOver = false;\n this.onUpOutside.emit();\n\n this._pointerId = undefined;\n }\n\n private _doAction(action: ButtonActionOrCallback) {\n if (typeof action === 'function') {\n void action();\n } else {\n if (!action.data.button) {\n action.data.button = this;\n }\n this.app.action(action.id, action.data);\n }\n }\n\n private _checkIsDownCallbacks() {\n // check if there are any callbacks, if there are, add the ticker listener\n if (!this._isDownListenerAdded && this._isDownCallbacks.size > 0) {\n this._isDownListenerAdded = true;\n this.app.ticker.add(this._handleIsDownCallbacks);\n } else {\n this.app.ticker.remove(this._handleIsDownCallbacks);\n this._isDownListenerAdded = false;\n }\n }\n\n private _handleIsDownCallbacks() {\n if (this.isDown) {\n this._isDownCallbacks.forEach((callback) => {\n callback();\n });\n }\n }\n}\n","import type { LayoutOptions, NumberValue } from '@pixi/layout';\nimport { BitmapText, Graphics, Container as PIXIContainer, Text } from 'pixi.js';\nimport { Application } from '../core/Application';\nimport { Container } from '../display/Container';\nimport { Factory } from '../mixins/factory/Factory';\nimport { WithSignals } from '../mixins/signals';\nimport { Signal } from '../signals';\nimport {\n AppTypeOverrides,\n bindAllMethods,\n type ContainerLike,\n createDebugGraphics,\n createDebugLabel,\n DebugAlpha,\n DebugColors,\n registerDebug,\n unregisterDebug,\n} from '../utils';\n\nconst _FlexContainer = WithSignals(Factory());\n\nexport function isText(child: PIXIContainer): child is Text | BitmapText {\n return child instanceof Text || child instanceof BitmapText;\n}\n\nexport interface FlexContainerConfig {\n bindTo?: ContainerLike;\n bindToAppSize?: boolean;\n autoLayoutChildren?: boolean;\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n debug?: boolean;\n}\n\nexport const FlexContainerConfigKeys: (keyof FlexContainerConfig)[] = [\n 'bindTo',\n 'bindToAppSize',\n 'autoLayoutChildren',\n 'debug',\n];\n\nexport type FlexWrap = 'wrap' | 'nowrap' | 'wrap-reverse' | undefined;\nexport type FlexDirection = 'row' | 'column' | 'row-reverse' | 'column-reverse' | undefined;\nexport type AlignItems = 'center' | 'flex-start' | 'flex-end' | 'stretch' | 'baseline' | undefined;\nexport type JustifyContent =\n | 'center'\n | 'space-between'\n | 'space-around'\n | 'space-evenly'\n | 'flex-start'\n | 'flex-end'\n | undefined;\n\nexport type SizeNumber = NumberValue | 'auto' | 'intrinsic';\n\nexport class FlexContainer extends _FlexContainer {\n public onLayoutComplete = new Signal<() => void>();\n public config: Partial<FlexContainerConfig>;\n private _debugGraphics: Graphics | null = null;\n private _debugLabel: Text | null = null;\n\n constructor(config: Partial<FlexContainerConfig> = {}) {\n super();\n\n if (!this.app.config.useLayout) {\n throw new Error('You must set useLayout to true in your app config to use FlexContainer');\n }\n\n bindAllMethods(this);\n\n this.config = {\n autoLayoutChildren: true,\n ...config,\n };\n\n // Set up layout\n this.layout = this.createLayout(config);\n\n // Set up event listeners\n this.on('added', this.handleAdded);\n this.on('childAdded', this.handleChildAdded);\n this.on('childRemoved', this.handleChildRemoved);\n\n if (this.config.bindToAppSize) {\n this.app.onResize.connect(this.handleResize);\n }\n\n if (this.config.bindTo && 'on' in this.config.bindTo) {\n (this.config.bindTo as PIXIContainer).on('layout', this.handleBindToResize);\n }\n }\n\n private createLayout(config: Partial<FlexContainerConfig>): Omit<LayoutOptions, 'target'> | null | boolean {\n if (config?.layout === true) {\n config.layout = {};\n }\n const layout: Omit<LayoutOptions, 'target'> | null | boolean = { ...(config?.layout ?? {}) };\n\n if (this.config.bindToAppSize) {\n layout.width = this.app.size.width;\n layout.height = this.app.size.height;\n } else if (this.config.bindTo) {\n layout.width = this.config.bindTo.width;\n layout.height = this.config.bindTo.height;\n }\n\n return layout;\n }\n\n private handleAdded() {\n this.updateLayout();\n }\n\n private _updateLayout() {\n this.app.ticker.addOnce(this.updateLayout);\n }\n\n private handleChildAdded(child: PIXIContainer) {\n if (this.config.autoLayoutChildren) {\n if (!(child.layout as unknown as boolean)) {\n // No layout yet — set isLeaf (original behavior)\n child.layout = { isLeaf: true };\n } else if (isText(child) && !child.layout?.style?.isLeaf) {\n // Text/BitmapText with existing layout props (e.g. marginTop) but missing isLeaf.\n // Without isLeaf, Yoga won't measure the text's intrinsic bounds.\n // The layout setter merges, so existing props are preserved.\n child.layout = { isLeaf: true };\n }\n }\n\n Container.childAdded(child);\n child.on('layout', this._updateLayout);\n this._updateLayout();\n }\n\n private handleChildRemoved(child: PIXIContainer) {\n child.off('layout', this._updateLayout);\n Container.childRemoved(child);\n this._updateLayout();\n }\n\n private handleResize() {\n if (this.config.bindToAppSize) {\n this.layout = {\n width: this.app.size.width,\n height: this.app.size.height,\n };\n }\n this._updateLayout();\n }\n\n private handleBindToResize() {\n if (!this.config.bindTo) return;\n this.layout = {\n width: this.config.bindTo.width,\n height: this.config.bindTo.height,\n };\n this._updateLayout();\n }\n\n public updateLayout() {\n if (this.destroyed || !this.layout || !this.app?.renderer.layout) return;\n this.app.renderer.layout.update(this);\n this.onLayoutComplete.emit();\n if (this.config.debug) {\n this.drawDebug();\n }\n }\n\n public get app(): AppTypeOverrides['App'] {\n return Application.getInstance();\n }\n\n /**\n * Set multiple layout properties at once, triggering a single deferred layout update.\n */\n public configure(styles: Partial<Omit<LayoutOptions, 'target'>>): void {\n this.layout = styles;\n this._updateLayout();\n }\n\n // Convenience getters/setters for common layout properties\n get gap(): number {\n return (this.layout?.style?.gap as number) ?? 0;\n }\n\n set gap(value: number) {\n this.layout = { gap: value };\n this._updateLayout();\n }\n\n get flexWrap(): FlexWrap {\n return this.layout?.style?.flexWrap as FlexWrap;\n }\n\n set flexWrap(value: FlexWrap) {\n this.layout = { flexWrap: value };\n this._updateLayout();\n }\n\n get flexDirection(): FlexDirection {\n return this.layout?.style?.flexDirection as FlexDirection;\n }\n\n set flexDirection(value: FlexDirection) {\n this.layout = { flexDirection: value };\n this._updateLayout();\n }\n\n get alignItems(): AlignItems {\n return this.layout?.style?.alignItems as AlignItems;\n }\n\n set alignItems(value: AlignItems) {\n this.layout = { alignItems: value };\n this._updateLayout();\n }\n\n get justifyContent(): JustifyContent {\n return this.layout?.style?.justifyContent as JustifyContent;\n }\n\n set justifyContent(value: JustifyContent) {\n this.layout = { justifyContent: value };\n this._updateLayout();\n }\n\n get size(): { width: SizeNumber; height: SizeNumber } {\n return {\n width: this.layout?.style?.width as SizeNumber,\n height: this.layout?.style?.height as SizeNumber,\n };\n }\n\n set size(size: { width: SizeNumber; height: SizeNumber } | [SizeNumber, SizeNumber] | SizeNumber) {\n if (Array.isArray(size)) {\n size = { width: size[0], height: size[1] };\n }\n if (typeof size === 'number' || typeof size === 'string') {\n size = { width: size, height: size };\n }\n this.layout = { ...size };\n this._updateLayout();\n }\n\n get layoutWidth(): SizeNumber {\n return this.layout?.style?.width as SizeNumber;\n }\n\n set layoutWidth(width: SizeNumber) {\n this.layout = { width };\n this._updateLayout();\n }\n\n get layoutHeight(): SizeNumber {\n return this.layout?.style?.height as SizeNumber;\n }\n\n set layoutHeight(height: SizeNumber) {\n this.layout = { height };\n this._updateLayout();\n }\n\n // Padding convenience\n get padding(): NumberValue | undefined {\n return this.layout?.style?.padding as NumberValue | undefined;\n }\n\n set padding(value: NumberValue) {\n this.layout = { padding: value };\n this._updateLayout();\n }\n\n get paddingTop(): NumberValue | undefined {\n return this.layout?.style?.paddingTop as NumberValue | undefined;\n }\n\n set paddingTop(value: NumberValue) {\n this.layout = { paddingTop: value };\n this._updateLayout();\n }\n\n get paddingRight(): NumberValue | undefined {\n return this.layout?.style?.paddingRight as NumberValue | undefined;\n }\n\n set paddingRight(value: NumberValue) {\n this.layout = { paddingRight: value };\n this._updateLayout();\n }\n\n get paddingBottom(): NumberValue | undefined {\n return this.layout?.style?.paddingBottom as NumberValue | undefined;\n }\n\n set paddingBottom(value: NumberValue) {\n this.layout = { paddingBottom: value };\n this._updateLayout();\n }\n\n get paddingLeft(): NumberValue | undefined {\n return this.layout?.style?.paddingLeft as NumberValue | undefined;\n }\n\n set paddingLeft(value: NumberValue) {\n this.layout = { paddingLeft: value };\n this._updateLayout();\n }\n\n // Margin convenience\n get margin(): NumberValue | undefined {\n return this.layout?.style?.margin as NumberValue | undefined;\n }\n\n set margin(value: NumberValue) {\n this.layout = { margin: value };\n this._updateLayout();\n }\n\n get marginTop(): NumberValue | undefined {\n return this.layout?.style?.marginTop as NumberValue | undefined;\n }\n\n set marginTop(value: NumberValue) {\n this.layout = { marginTop: value };\n this._updateLayout();\n }\n\n get marginRight(): NumberValue | undefined {\n return this.layout?.style?.marginRight as NumberValue | undefined;\n }\n\n set marginRight(value: NumberValue) {\n this.layout = { marginRight: value };\n this._updateLayout();\n }\n\n get marginBottom(): NumberValue | undefined {\n return this.layout?.style?.marginBottom as NumberValue | undefined;\n }\n\n set marginBottom(value: NumberValue) {\n this.layout = { marginBottom: value };\n this._updateLayout();\n }\n\n get marginLeft(): NumberValue | undefined {\n return this.layout?.style?.marginLeft as NumberValue | undefined;\n }\n\n set marginLeft(value: NumberValue) {\n this.layout = { marginLeft: value };\n this._updateLayout();\n }\n\n // --- Debug visualization ---\n get debug(): boolean {\n return this.config.debug ?? false;\n }\n\n set debug(value: boolean) {\n this.config.debug = value;\n if (value) {\n const uid = `FlexContainer:${this.uid}`;\n registerDebug(uid, this.label || 'FlexContainer', DebugColors.bounds);\n this.drawDebug();\n } else {\n unregisterDebug(`FlexContainer:${this.uid}`);\n if (this._debugGraphics) {\n this._debugGraphics.clear();\n }\n if (this._debugLabel) {\n this._debugLabel.visible = false;\n }\n }\n }\n\n private drawDebug() {\n // Create or re-add debug graphics if orphaned by removeChildren()\n if (!this._debugGraphics || this._debugGraphics.parent !== this) {\n if (!this._debugGraphics) {\n this._debugGraphics = createDebugGraphics(`${this.label ?? 'FlexContainer'}:debug`);\n }\n this.addChild(this._debugGraphics);\n this._debugGraphics.layout = false; // override auto-isLeaf from handleChildAdded\n }\n if (!this._debugLabel || this._debugLabel.parent !== this) {\n if (!this._debugLabel) {\n this._debugLabel = createDebugLabel(this.label || 'FlexContainer', DebugColors.bounds);\n }\n this.addChild(this._debugLabel);\n this._debugLabel.layout = false;\n }\n\n // Update label text in case label changed\n this._debugLabel.text = this.label || 'FlexContainer';\n this._debugLabel.visible = true;\n\n // Ensure debug graphics render on top\n this.setChildIndex(this._debugGraphics, this.children.length - 1);\n this.setChildIndex(this._debugLabel, this.children.length - 1);\n\n this._debugGraphics.clear();\n\n const computedLayout = this.layout?.computedLayout;\n if (!computedLayout) return;\n\n const w = computedLayout.width;\n const h = computedLayout.height;\n const direction = (this.layout?.style?.flexDirection as string) ?? 'row';\n const gap = (this.layout?.style?.gap as number) ?? 0;\n\n // 1. Container bounds (cyan)\n this._debugGraphics\n .rect(0, 0, w, h)\n .stroke({ width: 1, color: DebugColors.bounds, alpha: DebugAlpha.stroke, pixelLine: true });\n\n // 2. Padding visualization (red subtle fill)\n const pt = (this.layout?.style?.paddingTop as number) ?? 0;\n const pr = (this.layout?.style?.paddingRight as number) ?? 0;\n const pb = (this.layout?.style?.paddingBottom as number) ?? 0;\n const pl = (this.layout?.style?.paddingLeft as number) ?? 0;\n if (pt > 0) {\n this._debugGraphics.rect(0, 0, w, pt).fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pb > 0) {\n this._debugGraphics.rect(0, h - pb, w, pb).fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pl > 0) {\n this._debugGraphics.rect(0, pt, pl, h - pt - pb).fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pr > 0) {\n this._debugGraphics\n .rect(w - pr, pt, pr, h - pt - pb)\n .fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n\n // 3. Flex direction arrow (yellow)\n const arrowLen = Math.min(w, h, 40);\n const cx = w / 2;\n const cy = h / 2;\n const isRow = direction === 'row' || direction === 'row-reverse';\n if (isRow) {\n const dir = direction === 'row' ? 1 : -1;\n const startX = cx - (dir * arrowLen) / 2;\n const endX = cx + (dir * arrowLen) / 2;\n this._debugGraphics\n .moveTo(startX, cy)\n .lineTo(endX, cy)\n .moveTo(endX, cy)\n .lineTo(endX - dir * 6, cy - 4)\n .moveTo(endX, cy)\n .lineTo(endX - dir * 6, cy + 4)\n .stroke({ width: 1, color: DebugColors.direction, alpha: 0.8, pixelLine: true });\n } else {\n const dir = direction === 'column' ? 1 : -1;\n const startY = cy - (dir * arrowLen) / 2;\n const endY = cy + (dir * arrowLen) / 2;\n this._debugGraphics\n .moveTo(cx, startY)\n .lineTo(cx, endY)\n .moveTo(cx, endY)\n .lineTo(cx - 4, endY - dir * 6)\n .moveTo(cx, endY)\n .lineTo(cx + 4, endY - dir * 6)\n .stroke({ width: 1, color: DebugColors.direction, alpha: 0.8, pixelLine: true });\n }\n\n // 4. Gap indicators between children (magenta fills)\n if (gap > 0) {\n for (let i = 0; i < this.children.length - 1; i++) {\n const child = this.children[i];\n if (child === this._debugGraphics || child === this._debugLabel) continue;\n if (!child.layout?.computedLayout) continue;\n const cl = child.layout.computedLayout;\n if (isRow) {\n const gapX = cl.left + cl.width;\n this._debugGraphics.rect(gapX, 0, gap, h).fill({ color: DebugColors.gap, alpha: DebugAlpha.fill });\n } else {\n const gapY = cl.top + cl.height;\n this._debugGraphics.rect(0, gapY, w, gap).fill({ color: DebugColors.gap, alpha: DebugAlpha.fill });\n }\n }\n }\n\n // 5. Child bounding boxes (green outlines)\n for (const child of this.children) {\n if (child === this._debugGraphics || child === this._debugLabel) continue;\n if (!child.layout?.computedLayout) continue;\n const cl = child.layout.computedLayout;\n this._debugGraphics\n .rect(cl.left, cl.top, cl.width, cl.height)\n .stroke({ width: 1, color: DebugColors.innerBounds, alpha: 0.4, pixelLine: true });\n }\n\n // Position label at top-left with slight offset\n this._debugLabel.position.set(2, 2);\n }\n\n destroy() {\n // Clean up debug\n if (this.config.debug) {\n unregisterDebug(`FlexContainer:${this.uid}`);\n }\n if (this._debugGraphics) {\n this._debugGraphics.destroy();\n this._debugGraphics = null;\n }\n if (this._debugLabel) {\n this._debugLabel.destroy();\n this._debugLabel = null;\n }\n\n this.off('added', this.handleAdded);\n this.off('childAdded', this.handleChildAdded);\n this.off('childRemoved', this.handleChildRemoved);\n\n if (this.config.bindToAppSize) {\n this.app.onResize.disconnect(this.handleResize);\n }\n\n if (this.config.bindTo && 'off' in this.config.bindTo) {\n (this.config.bindTo as PIXIContainer).off('layout', this.handleBindToResize);\n }\n\n super.destroy();\n }\n}\n","import { gsap } from 'gsap';\nimport { Graphics, Text } from 'pixi.js';\nimport { Container } from '../display/Container';\nimport type { TextStyle } from '../mixins/factory/props';\nimport { WithSignals } from '../mixins/signals';\nimport { Signal } from '../signals';\nimport { Button } from './Button';\nimport { Toaster } from './Toaster';\n\n/**\n * Types of toasts that can be displayed, each with its own color indicator.\n */\nexport type ToastType = 'info' | 'success' | 'warning' | 'error';\n\n/**\n * Position options for the close button within a toast.\n */\nexport type CloseButtonPosition = 'top right' | 'top left';\n\n/**\n * Configuration interface for creating a Toast notification.\n *\n * @example\n * ```typescript\n * // Basic toast with default settings\n * const config: ToastConfig = {\n * message: \"Operation successful!\",\n * type: \"success\"\n * };\n *\n * // Custom styled toast with shadow and close button\n * const config: ToastConfig = {\n * message: \"Custom notification\",\n * backgroundColor: 0x9b59b6,\n * backgroundAlpha: 1,\n * cornerRadius: 8,\n * shadow: {\n * color: 0x000000,\n * alpha: 0.2,\n * offset: { x: 4, y: 4 }\n * },\n * closeButton: {\n * show: true,\n * position: 'top right'\n * }\n * };\n * ```\n */\nexport interface ToastConfig {\n /** Optional custom Toast class to use instead of the default */\n class?: typeof Toast;\n /** The message to display in the toast */\n message: string;\n /** Type of toast, determines the color indicator */\n type?: ToastType;\n /** Duration in milliseconds before auto-closing (if autoClose is true) */\n duration?: number;\n /** Custom text style options */\n style?: TextStyle;\n /** Width of the toast in pixels */\n width?: number;\n /** Height of the toast in pixels */\n height?: number;\n /** Background color in hex format */\n backgroundColor?: number;\n /** Background opacity (0-1) */\n backgroundAlpha?: number;\n /** Corner radius for rounded corners */\n cornerRadius?: number;\n /** Padding around the content */\n padding?: number;\n /** Whether the toast should automatically close after duration */\n autoClose?: boolean;\n /** Custom colors for each toast type's indicator */\n textColors?: Record<ToastType, number>;\n /** Horizontal text alignment */\n textAlign?: 'left' | 'center' | 'right';\n /** Vertical text alignment */\n verticalAlign?: 'top' | 'middle' | 'bottom';\n /** Width of the colored type indicator bar */\n colorBarWidth?: number;\n /** Shadow configuration for depth effect */\n shadow?: {\n /** Shadow color in hex format */\n color?: number;\n /** Shadow opacity (0-1) */\n alpha?: number;\n /** Shadow offset from the toast */\n offset?: { x: number; y: number };\n };\n /** Close button configuration */\n closeButton?: {\n /** Whether to show the close button */\n show?: boolean;\n /** Position of the close button */\n position?: CloseButtonPosition;\n /** Custom button class to use */\n class?: typeof Button;\n /** Size of the close button */\n size?: number;\n /** Offset from the edges */\n offset?: number;\n };\n}\n\nexport const defaultToastConfig: Partial<ToastConfig> = {\n type: 'info',\n duration: 3000,\n width: 300,\n height: 80,\n backgroundColor: 0x000000,\n backgroundAlpha: 0.8,\n cornerRadius: 0,\n padding: 10,\n autoClose: true,\n textAlign: 'center',\n verticalAlign: 'middle',\n colorBarWidth: 6,\n shadow: {\n color: 0x000000,\n alpha: 0.2,\n offset: { x: 1, y: 3 },\n },\n closeButton: {\n show: false,\n position: 'top right',\n size: 12,\n offset: 4,\n },\n style: {\n fill: 0xffffff,\n fontSize: 16,\n wordWrap: true,\n },\n textColors: {\n info: 0x3498db,\n success: 0x2ecc71,\n warning: 0xf1c40f,\n error: 0xe74c3c,\n },\n};\n\nexport class Toast extends WithSignals(Container) {\n public readonly onToastClosed = new Signal<() => void>();\n protected background: Graphics;\n protected shadow: Graphics;\n protected textDisplay: Text;\n protected closeButton?: Button;\n protected config: ToastConfig;\n protected timeline?: gsap.core.Timeline;\n protected closeTimeout?: any;\n protected isHiding: boolean = false;\n\n protected view: Container;\n\n private _toaster: Toaster;\n\n set toaster(value: Toaster) {\n this._toaster = value;\n }\n\n get toaster(): Toaster {\n return this._toaster;\n }\n\n set text(value: string) {\n this.textDisplay.text = value;\n this.alignText();\n }\n\n constructor(config: Partial<ToastConfig> = {}) {\n super();\n this.config = { ...defaultToastConfig, ...config } as ToastConfig;\n this.initialize();\n }\n\n protected initialize(): void {\n this.view = this.add.container();\n // Create shadow first so it's behind everything\n if (this.config.shadow) {\n this.shadow = this.view.add\n .graphics()\n .roundRect(\n this.config.shadow.offset?.x ?? 4,\n this.config.shadow.offset?.y ?? 4,\n this.config.width!,\n this.config.height!,\n this.config.cornerRadius!,\n )\n .fill({\n color: this.config.shadow.color ?? 0x000000,\n alpha: this.config.shadow.alpha ?? 0.2,\n });\n }\n\n // Create background\n this.background = this.view.add\n .graphics()\n .roundRect(0, 0, this.config.width!, this.config.height!, this.config.cornerRadius!)\n .fill({\n color: this.config.backgroundColor!,\n alpha: this.config.backgroundAlpha!,\n });\n\n // Create a container for the colored indicator with mask\n if (this.config.type) {\n // Create a mask with the same rounded rectangle as the background\n const mask = new Graphics()\n .roundRect(0, 0, this.config.width!, this.config.height!, this.config.cornerRadius!)\n .fill({ color: 0xffffff });\n\n // Create the colored indicator\n const indicator = this.view.add\n .graphics()\n .rect(0, 0, this.config.colorBarWidth!, this.config.height!)\n .fill({ color: this.config.textColors![this.config.type] });\n\n // Apply the mask to the indicator\n indicator.mask = mask;\n\n // Add both the mask and indicator to the container\n this.view.addChild(mask);\n this.view.addChild(indicator);\n }\n\n // Add close button if enabled\n if (this.config.closeButton?.show) {\n this.addCloseButton();\n }\n\n // Create text with adjusted padding to account for color bar and close button\n const leftPadding = this.config.type ? this.config.colorBarWidth! + this.config.padding! : this.config.padding!;\n const rightPadding =\n this.config.closeButton?.show && this.config.closeButton.position === 'top right'\n ? this.config.closeButton.size! + this.config.closeButton.offset! * 2\n : this.config.padding!;\n\n this.textDisplay = this.view.add.text({\n text: this.config.message,\n style: {\n ...defaultToastConfig.style,\n ...this.config.style,\n wordWrapWidth: this.config.style?.wordWrapWidth ?? this.config.width! - leftPadding - rightPadding,\n },\n x: leftPadding,\n y: this.config.padding!,\n });\n\n this.alignText();\n\n this.view.pivot.set(this.config.width! * 0.5, this.config.height! * 0.5);\n\n this.view.position.set(this.config.width! * 0.5, this.config.height! * 0.5);\n // Set initial state\n this.alpha = 0;\n\n this.addChild(this.view);\n }\n\n protected addCloseButton(): void {\n const ButtonClass = this.config.closeButton?.class || Button;\n const size = this.config.closeButton?.size ?? 12;\n const offset = this.config.closeButton?.offset ?? 4;\n const position = this.config.closeButton?.position ?? 'top right';\n\n this.closeButton = this.view.add.existing(\n new ButtonClass({\n cursor: 'pointer',\n }),\n );\n\n // Position the close button\n const x = position === 'top right' ? this.config.width! - size * 0.5 - offset : size * 0.5 + offset;\n const y = size * 0.5 + offset;\n\n this.closeButton.position.set(x, y);\n\n // Connect close button to hide\n this.closeButton.onClick.connect(() => {\n void this.hide();\n });\n }\n\n public alignText(): void {\n switch (this.config.textAlign) {\n case 'left':\n this.textDisplay.anchor.set(0, 0.5);\n break;\n case 'center':\n this.textDisplay.anchor.set(0.5, 0.5);\n this.textDisplay.x = this.config.width! / 2;\n break;\n case 'right':\n this.textDisplay.anchor.set(1, 0.5);\n break;\n }\n\n switch (this.config.verticalAlign) {\n case 'top':\n this.textDisplay.y = this.config.padding!;\n break;\n case 'middle':\n this.textDisplay.y = this.config.height! * 0.5;\n break;\n case 'bottom':\n this.textDisplay.y = this.config.height! - this.textDisplay.height - this.config.padding!;\n break;\n }\n }\n\n public getShowAnimation(): gsap.core.Timeline {\n const tl = gsap.timeline({ paused: true });\n tl.to(this, {\n alpha: 1,\n duration: 0.4,\n ease: 'power2.out',\n });\n\n return tl;\n }\n\n public getHideAnimation(): gsap.core.Timeline {\n const tl = gsap.timeline({ paused: true });\n tl.to(this, {\n alpha: 0,\n duration: 0.25,\n ease: 'power2.in',\n });\n\n return tl;\n }\n\n public async show(): Promise<Toast> {\n this.timeline = this.getShowAnimation();\n await this.timeline.play();\n\n if (this.config.autoClose) {\n this.closeTimeout = setTimeout(() => {\n void this.hide();\n }, this.config.duration);\n }\n return this;\n }\n\n public async hide(): Promise<Toast> {\n // Prevent multiple hide calls\n if (this.isHiding || this.destroyed) {\n return this;\n }\n this.isHiding = true;\n\n if (this.closeTimeout) {\n clearTimeout(this.closeTimeout);\n this.closeTimeout = undefined;\n }\n\n try {\n // Create a new timeline for hiding\n const tl = this.getHideAnimation();\n await tl.play();\n // Only emit if we haven't been destroyed during animation\n if (!this.destroyed) {\n this.onToastClosed.emit();\n }\n } catch (error) {\n // Handle any animation errors gracefully\n console.warn('Toast hide animation error:', error);\n if (!this.destroyed) {\n this.onToastClosed.emit();\n }\n }\n\n return this;\n }\n\n public destroy(): void {\n // Prevent any ongoing animations or timeouts\n this.isHiding = true;\n\n if (this.closeTimeout) {\n clearTimeout(this.closeTimeout);\n this.closeTimeout = undefined;\n }\n\n // Kill any active GSAP animations immediately\n gsap.killTweensOf(this);\n\n if (this.timeline) {\n this.timeline.kill();\n this.timeline = undefined;\n }\n\n // Emit close if we're being destroyed without hiding\n if (!this.destroyed && !this.isHiding) {\n this.onToastClosed.emit();\n }\n\n super.destroy({ children: true });\n }\n}\n","import { gsap } from 'gsap';\nimport { Container } from '../display/Container';\nimport { WithSignals } from '../mixins/signals';\nimport { Signal } from '../signals';\nimport { defaultToastConfig, Toast, ToastConfig } from './Toast';\nimport { UICanvasEdge } from './UICanvas';\n\n/**\n * Configuration interface for the Toaster component, which manages toast notifications.\n *\n * @example\n * ```typescript\n * // Basic toaster in top-right corner\n * const config: ToasterConfig = {\n * position: 'top right',\n * maxToasts: 3\n * };\n *\n * // Custom toaster with specific spacing and offset\n * const config: ToasterConfig = {\n * position: 'bottom center',\n * maxToasts: 5,\n * spacing: 15,\n * offset: { x: 20, y: 30 },\n * stackDirection: 'up'\n * };\n * ```\n */\nexport interface ToasterConfig {\n /** Position of toasts relative to the screen edges */\n position?: UICanvasEdge;\n /** Maximum number of toasts to show at once */\n maxToasts?: number;\n /** Vertical spacing between toasts */\n spacing?: number;\n /** Distance from screen edges, can be a number for equal x/y or an object for different values */\n offset?: { x: number; y: number } | number;\n /** Direction in which new toasts should stack */\n stackDirection?: 'up' | 'down';\n\n animationSpeed: number;\n}\n\nconst defaultConfig: ToasterConfig = {\n position: 'bottom right',\n maxToasts: 5,\n spacing: 10,\n offset: { x: 20, y: 20 },\n stackDirection: 'up',\n animationSpeed: 1,\n};\n\n/**\n * Toaster component that manages the display and positioning of toast notifications.\n *\n * @example\n * ```typescript\n * // Create a toaster\n * const toaster = new Toaster({\n * position: 'top right',\n * maxToasts: 3\n * });\n *\n * // Show a basic toast\n * toaster.show({\n * message: \"Operation successful!\",\n * type: \"success\"\n * });\n *\n * // Show a custom toast\n * toaster.show({\n * message: \"Custom notification\",\n * backgroundColor: 0x9b59b6,\n * shadow: {\n * color: 0x000000,\n * alpha: 0.2,\n * offset: { x: 4, y: 4 }\n * }\n * });\n *\n * // Hide all toasts\n * toaster.hideAll();\n * ```\n */\nexport class Toaster extends WithSignals(Container) {\n /** Emitted when a new toast is added */\n public readonly onToastAdded = new Signal<(toast: Toast) => void>();\n /** Emitted when a toast is removed */\n public readonly onToastRemoved = new Signal<(toast: Toast) => void>();\n /** Emitted when all toasts are removed */\n public readonly onAllToastsRemoved = new Signal<() => void>();\n\n public config: ToasterConfig;\n public defaultToastConfig: Partial<ToastConfig>;\n private toasts: Toast[] = [];\n private container: Container;\n\n /**\n * Get the current number of visible toasts\n */\n public get size(): number {\n return this.toasts.length;\n }\n\n get toastPosition(): UICanvasEdge {\n return this.config.position ?? 'top right';\n }\n\n get stackDirection(): 'up' | 'down' {\n return this.config.stackDirection ?? 'up';\n }\n\n get spacing(): number {\n return this.config.spacing ?? 10;\n }\n\n get offset(): { x: number; y: number } | number {\n return this.config.offset ?? { x: 20, y: 20 };\n }\n\n get maxToasts(): number {\n return this.config.maxToasts ?? 5;\n }\n\n get toastConfig(): Partial<ToastConfig> {\n return this.defaultToastConfig ?? {};\n }\n\n /**\n * Create a new Toaster instance to manage toast notifications.\n *\n * @param config - Configuration for the Toaster's position, spacing, and behavior\n * @param defaultToastConfig - Default configuration applied to all toasts shown by this Toaster\n *\n * @example\n * ```typescript\n * // Basic toaster with default settings\n * const toaster = new Toaster();\n *\n * // Toaster with custom position and behavior\n * const toaster = new Toaster({\n * position: 'bottom center',\n * maxToasts: 3,\n * spacing: 15,\n * offset: { x: 20, y: 30 },\n * stackDirection: 'up'\n * });\n *\n * // Toaster with custom defaults for all toasts\n * const toaster = new Toaster(\n * {\n * position: 'top right',\n * maxToasts: 5\n * },\n * {\n * backgroundColor: 0x000000,\n * backgroundAlpha: 0.8,\n * cornerRadius: 8,\n * shadow: {\n * color: 0x000000,\n * alpha: 0.2,\n * offset: { x: 4, y: 4 }\n * },\n * closeButton: {\n * show: true,\n * position: 'top right'\n * }\n * }\n * );\n *\n * // The defaultToastConfig will be applied to all toasts,\n * // but can be overridden per toast:\n * toaster.show({ message: \"Uses default config\" });\n * toaster.show({\n * message: \"Custom config\",\n * backgroundColor: 0x9b59b6 // Overrides default\n * });\n * ```\n */\n constructor(config: Partial<ToasterConfig> = {}, defaultToastConfig: Partial<ToastConfig> = {}) {\n super({ autoResize: true });\n this.config = { ...defaultConfig, ...config } as ToasterConfig;\n this.defaultToastConfig = { ...defaultToastConfig } as Partial<ToastConfig>;\n this.initialize();\n this.resize();\n }\n\n protected initialize(): void {\n this.container = this.add.container();\n }\n\n /**\n * Display a new toast notification\n * @param config Configuration for the toast to display\n * @returns Promise that resolves with the created toast\n */\n public async show(\n config: Partial<ToastConfig> = this.defaultToastConfig,\n overrideDefaults: boolean = false,\n ): Promise<Toast> {\n // Remove oldest toast if we exceed max before creating new one\n if (this.size >= this.config.maxToasts!) {\n const oldestToast = this.toasts[0];\n // Wait for the hide animation to complete\n await oldestToast.hide();\n // Wait for removal to complete\n await this.removeToast(oldestToast);\n }\n\n if (!overrideDefaults && this.defaultToastConfig) {\n config = {\n ...this.defaultToastConfig,\n ...config,\n style:\n this.defaultToastConfig.style || config.style\n ? { ...(this.defaultToastConfig.style ?? {}), ...(config.style ?? {}) }\n : this.defaultToastConfig.style,\n textColors:\n this.defaultToastConfig.textColors || config.textColors\n ? { ...(this.defaultToastConfig.textColors ?? {}), ...(config.textColors ?? {}) }\n : defaultToastConfig.textColors,\n shadow:\n this.defaultToastConfig.shadow || config.shadow\n ? { ...(this.defaultToastConfig.shadow ?? {}), ...(config.shadow ?? {}) }\n : this.defaultToastConfig.shadow,\n closeButton:\n this.defaultToastConfig.closeButton || config.closeButton\n ? { ...(this.defaultToastConfig.closeButton ?? {}), ...(config.closeButton ?? {}) }\n : defaultToastConfig.closeButton,\n } as ToastConfig;\n }\n // Create new toast\n const ToastClass = config.class ?? Toast;\n const toast = new ToastClass(config);\n\n toast.toaster = this;\n\n // Add to container and array first\n this.container.addChild(toast);\n this.toasts.push(toast);\n this.positionToast(toast, this.toasts.length - 1, false);\n\n // Connect to close signal\n toast.onToastClosed.connectOnce(() => this.removeToast(toast));\n\n // Position all toasts including the new one\n this.positionToasts();\n\n // Emit signal\n this.onToastAdded.emit(toast);\n\n // Show the toast and return it\n return toast.show();\n }\n\n /**\n * Hide all currently visible toasts with animation\n * @returns Promise that resolves when all toasts are hidden\n */\n public async hideAll(): Promise<void> {\n // Create a copy of the array to avoid modification during iteration\n const toastsToHide = [...this.toasts];\n\n // Hide all toasts simultaneously\n await Promise.all(toastsToHide.map((toast) => toast.hide()));\n\n this.onAllToastsRemoved.emit();\n }\n\n /**\n * Remove all toasts (alias for hideAll)\n */\n public async removeAll(): Promise<void> {\n return this.hideAll();\n }\n\n protected async removeToast(toast: Toast): Promise<void> {\n const index = this.toasts.indexOf(toast);\n if (index === -1 || toast.destroyed) {\n return;\n }\n\n // Remove from array first\n this.toasts.splice(index, 1);\n\n // Position remaining toasts\n this.positionToasts();\n\n // Remove from container and destroy\n if (!toast.destroyed) {\n this.container.removeChild(toast);\n toast.destroy();\n }\n\n // Emit signal\n this.onToastRemoved.emit(toast);\n }\n\n /**\n * Update positions of all toasts\n * @param animate Whether to animate the position changes\n * @param skipLast Whether to skip positioning the last toast\n */\n public positionToasts(animate: boolean = true, skipLast: boolean = false): void {\n // Create a copy of the array to avoid modification during iteration\n const validToasts = this.toasts.filter(\n (toast, index) => toast && !toast.destroyed && (skipLast ? index !== this.toasts.length - 1 : true),\n );\n\n validToasts.forEach((toast, index) => {\n this.positionToast(toast, index, animate);\n });\n }\n\n /**\n * Position a single toast\n * @param toast The toast to position\n * @param index The index of the toast in the toasts array\n * @param animate Whether to animate the position changes\n */\n protected positionToast(toast: Toast, index: number, animate: boolean = true): void {\n // Early return if toast is destroyed or invalid\n if (!toast?.parent || toast.destroyed) {\n return;\n }\n\n const { position, spacing, offset, stackDirection } = this.config;\n const offsetX = typeof offset === 'number' ? offset : offset!.x;\n const offsetY = typeof offset === 'number' ? offset : offset!.y;\n let x = this.app.size.width * 0.5;\n let y = this.app.size.height * 0.5;\n\n // Calculate base position\n switch (position) {\n case 'top right':\n case 'right top':\n x += this.app.size.width * 0.5 - toast.width - offsetX;\n y -= this.app.size.height * 0.5 - offsetY;\n break;\n case 'top left':\n case 'left top':\n x -= this.app.size.width * 0.5 - offsetX;\n y -= this.app.size.height * 0.5 - offsetY;\n break;\n case 'bottom right':\n case 'right bottom':\n x += this.app.size.width * 0.5 - toast.width - offsetX;\n y += this.app.size.height * 0.5 - toast.height - offsetY;\n break;\n case 'bottom left':\n case 'left bottom':\n x -= this.app.size.width * 0.5 - offsetX;\n y += this.app.size.height * 0.5 - toast.height - offsetY;\n break;\n case 'top':\n case 'top center':\n x += -toast.width * 0.5;\n y -= this.app.size.height * 0.5 - offsetY;\n break;\n case 'bottom':\n case 'bottom center':\n x += -toast.width * 0.5;\n y += this.app.size.height * 0.5 - toast.height - offsetY;\n break;\n }\n\n // Apply stacking offset\n if (stackDirection === 'down') {\n y += index * (toast.height + spacing!);\n } else {\n y -= index * (toast.height + spacing!);\n }\n\n try {\n // Animate to position\n if (animate) {\n gsap.to(toast, {\n x,\n y,\n duration: 0.3 / this.config.animationSpeed,\n ease: 'power2.out',\n });\n } else {\n toast.position.set(x, y);\n }\n } catch (error) {\n console.warn('Error positioning toast:', error);\n }\n }\n\n /**\n * Handle window resize events\n */\n public resize(): void {\n this.position.set(-this.app.size.width * 0.5, -this.app.size.height * 0.5);\n this.positionToasts(false); // Don't animate on resize\n }\n\n public destroy(): void {\n // Kill any active GSAP animations\n this.toasts.forEach((toast) => {\n gsap.killTweensOf(toast);\n });\n\n this.hideAll();\n this.toasts = [];\n super.destroy({ children: true });\n }\n}\n","import type { LayoutOptions } from '@pixi/layout';\nimport { ContainerChild, Graphics, RenderLayer, Container as PIXIContainer, Text } from 'pixi.js';\nimport { Application } from '../core/Application';\nimport { Container } from '../display/Container';\nimport { Factory } from '../mixins/factory/Factory';\nimport { WithSignals } from '../mixins/signals';\nimport type { AppTypeOverrides, Padding, PointLike, Size, SizeLike } from '../utils';\nimport {\n bindAllMethods,\n createDebugGraphics,\n createDebugLabel,\n DebugAlpha,\n DebugColors,\n ensurePadding,\n Logger,\n registerDebug,\n resolveSizeLike,\n unregisterDebug,\n} from '../utils';\nimport { FlexContainer } from './FlexContainer';\n\nexport type UICanvasEdge =\n | 'top right'\n | 'top left'\n | 'top center'\n | 'top'\n | 'bottom right'\n | 'bottom left'\n | 'bottom center'\n | 'bottom'\n | 'left top'\n | 'left bottom'\n | 'left center'\n | 'left'\n | 'right top'\n | 'right bottom'\n | 'right center'\n | 'right'\n | 'center';\n\nexport interface UICanvasChildSettings {\n align: UICanvasEdge;\n padding: Padding;\n}\n\n/** Anchor box handed to a binding's placement callback, in canvas-local space\n * (origin = canvas top-left), derived from the anchor's computed layout so it\n * never lags the render transform. */\nexport interface UICanvasBindRect {\n left: number;\n top: number;\n width: number;\n height: number;\n}\n\n/** Places a bound (free-floating) element from its anchor's rect. Both the\n * rect and the element's `position` are in canvas-local space. */\nexport type UICanvasBindFn = (rect: UICanvasBindRect, child: PIXIContainer) => void;\n\ninterface UICanvasBinding {\n child: PIXIContainer;\n anchor: PIXIContainer;\n place: UICanvasBindFn;\n}\n\nexport interface UICanvasChildProps {\n align: UICanvasEdge;\n padding: Partial<Padding> | PointLike;\n}\n\nexport type UICanvasConfig = {\n debug: boolean;\n padding: Padding;\n size: Size;\n useAppSize: boolean;\n useSafeArea: boolean;\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n autoLayoutChildren?: boolean;\n};\n\nexport const UICanvasConfigKeys: (keyof UICanvasConfig)[] = [\n 'debug',\n 'padding',\n 'size',\n 'useAppSize',\n 'useSafeArea',\n 'layout',\n];\n\nexport type UICanvasProps = {\n debug: boolean;\n padding: Partial<Padding> | PointLike;\n size?: SizeLike;\n useAppSize?: boolean;\n useSafeArea?: boolean;\n layout?: Omit<LayoutOptions, 'target'> | null | boolean;\n autoLayoutChildren?: boolean;\n};\n\nconst zeroPadding: Padding = { top: 0, right: 0, bottom: 0, left: 0 };\n\n/**\n * The padding the canvas actually lays out with: the configured padding plus the\n * device's safe-area insets. Kept separate from `config.padding` so it can be\n * re-derived on every resize without compounding.\n */\nexport function computeEffectivePadding(padding: Padding, safeArea: Padding): Padding {\n return {\n top: padding.top + safeArea.top,\n right: padding.right + safeArea.right,\n bottom: padding.bottom + safeArea.bottom,\n left: padding.left + safeArea.left,\n };\n}\n\nconst defaultLayout = {\n flexGrow: 0,\n flexShrink: 0,\n autoLayoutChildren: true,\n};\n\nconst _UICanvas = WithSignals(Factory());\n\nexport class UICanvas extends _UICanvas {\n public config: UICanvasConfig;\n protected settingsMap = new Map<PIXIContainer, UICanvasChildSettings>();\n protected _childMap = new Map<PIXIContainer, PIXIContainer>();\n protected _debugGraphics: Graphics | null = null;\n protected _debugLabel: Text | null = null;\n protected _regionLabels: Text[] = [];\n private _disableAddChildError: boolean = false;\n private _positionContainers: Map<UICanvasEdge, Container>;\n private _bindings: UICanvasBinding[] = [];\n\n public topRow: FlexContainer;\n public middleRow: FlexContainer;\n public bottomRow: FlexContainer;\n\n constructor(config: Partial<UICanvasProps>) {\n super();\n\n if (!this.app.config.useLayout) {\n throw new Error('You must set useLayout to true in your app config to use UICanvas');\n }\n\n bindAllMethods(this);\n this._positionContainers = new Map();\n this.config = {\n debug: config.debug === true,\n padding: ensurePadding(config?.padding ?? 0),\n size: config.size !== undefined ? resolveSizeLike(config.size) : { width: 0, height: 0 },\n useAppSize: config.useAppSize === true,\n useSafeArea: config.useSafeArea ?? true,\n autoLayoutChildren: config.autoLayoutChildren ?? true,\n };\n\n if (config.layout) {\n if (typeof config.layout === 'boolean') {\n this.config.layout = config.layout;\n } else {\n this.config.layout = { ...defaultLayout, ...config.layout };\n }\n } else {\n this.config.layout = { ...defaultLayout };\n }\n\n if (this.config.useAppSize) {\n this.config.size = this.app.size;\n }\n this.layout = {\n width: this.config.size.width,\n height: this.config.size.height,\n flexDirection: 'column',\n justifyContent: 'space-between',\n ...(typeof this.config.layout === 'object' ? this.config.layout : {}),\n };\n\n this.on('childRemoved', this._childRemoved);\n this.once('added', this._added);\n\n this.addSignalConnection(this.app.onResize.connect(this.resize));\n\n this._initializeLayout();\n this._updateLayout();\n\n if (this.config.debug) {\n registerDebug(`UICanvas:${this.uid}`, this.label || 'UICanvas', DebugColors.outerBounds);\n }\n }\n\n private _updateLayout() {\n this.app.ticker.addOnce(this.updateLayout);\n }\n\n private _initializeLayout() {\n this._disableAddChildError = true;\n // Create top row\n this.topRow = this.add.flexContainer({\n label: 'Top',\n layout: {\n width: '100%',\n height: 'auto',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'flex-start',\n },\n });\n\n // Create middle row\n this.middleRow = this.add.flexContainer({\n label: 'Middle',\n layout: {\n width: '100%',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'center',\n },\n });\n\n // Create bottom row\n this.bottomRow = this.add.flexContainer({\n label: 'Bottom',\n layout: {\n width: '100%',\n height: 'auto',\n flexDirection: 'row',\n justifyContent: 'space-between',\n alignItems: 'flex-end',\n },\n });\n\n this._disableAddChildError = false;\n\n // Create the 9 actual position containers\n const topLeft = this._createPositionContainer(\n this.topRow,\n {\n justifyContent: 'flex-start',\n alignItems: 'flex-start',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Left',\n );\n const topCenter = this._createPositionContainer(\n this.topRow,\n {\n justifyContent: 'center',\n alignItems: 'flex-start',\n flexGrow: 1,\n flexShrink: 0,\n },\n 'Center',\n );\n const topRight = this._createPositionContainer(\n this.topRow,\n {\n justifyContent: 'flex-end',\n alignItems: 'flex-start',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Right',\n );\n\n const middleLeft = this._createPositionContainer(\n this.middleRow,\n {\n justifyContent: 'flex-start',\n alignItems: 'center',\n flexDirection: 'row',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Left',\n );\n const center = this._createPositionContainer(\n this.middleRow,\n {\n justifyContent: 'center',\n alignItems: 'center',\n flexDirection: 'row',\n flexGrow: 1,\n flexShrink: 0,\n },\n 'Center',\n );\n const middleRight = this._createPositionContainer(\n this.middleRow,\n {\n justifyContent: 'flex-end',\n alignItems: 'center',\n flexDirection: 'row',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Right',\n );\n\n const bottomLeft = this._createPositionContainer(\n this.bottomRow,\n {\n justifyContent: 'flex-start',\n alignItems: 'flex-end',\n flexDirection: 'row',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Left',\n );\n const bottomCenter = this._createPositionContainer(\n this.bottomRow,\n {\n justifyContent: 'center',\n alignItems: 'flex-end',\n flexGrow: 1,\n flexShrink: 0,\n flexDirection: 'row',\n },\n 'Center',\n );\n const bottomRight = this._createPositionContainer(\n this.bottomRow,\n {\n justifyContent: 'flex-end',\n alignItems: 'flex-end',\n flexDirection: 'row',\n flexGrow: 0,\n flexShrink: 0,\n },\n 'Right',\n );\n\n // Map all edge variants to the appropriate containers\n this._positionContainers.set('top left', topLeft);\n this._positionContainers.set('left top', topLeft);\n\n this._positionContainers.set('top center', topCenter);\n this._positionContainers.set('top', topCenter);\n\n this._positionContainers.set('top right', topRight);\n this._positionContainers.set('right top', topRight);\n\n this._positionContainers.set('left center', middleLeft);\n this._positionContainers.set('left', middleLeft);\n this._positionContainers.set('left bottom', bottomLeft);\n\n this._positionContainers.set('center', center);\n\n this._positionContainers.set('right center', middleRight);\n this._positionContainers.set('right', middleRight);\n this._positionContainers.set('right bottom', bottomRight);\n\n this._positionContainers.set('bottom left', bottomLeft);\n\n this._positionContainers.set('bottom center', bottomCenter);\n this._positionContainers.set('bottom', bottomCenter);\n\n this._positionContainers.set('bottom right', bottomRight);\n }\n\n private _createPositionContainer(parent: FlexContainer, layout: Partial<LayoutOptions>, label: string): Container {\n const container = parent.add.container({\n layout: {\n width: 'auto',\n height: 'auto',\n ...layout,\n },\n });\n container.label = label;\n container.on('childAdded', this._updateLayout);\n container.on('childRemoved', this._updateLayout);\n container.on('layout', this._updateLayout);\n return container;\n }\n\n protected _canvasChildren: PIXIContainer[] = [];\n\n public get canvasChildren(): PIXIContainer[] {\n return this._canvasChildren;\n }\n\n /**\n * Get the application instance.\n */\n public get app(): AppTypeOverrides['App'] {\n return Application.getInstance();\n }\n\n destroy() {\n // Must be set before any child.destroy() call — PixiJS's destroy cascade\n // calls child.removeFromParent() → parent.removeChild() internally.\n this._disableAddChildError = true;\n\n // Clean up debug\n if (this.config.debug) {\n unregisterDebug(`UICanvas:${this.uid}`);\n }\n if (this._debugGraphics) {\n this._debugGraphics.destroy();\n this._debugGraphics = null;\n }\n if (this._debugLabel) {\n this._debugLabel.destroy();\n this._debugLabel = null;\n }\n for (const rl of this._regionLabels) {\n rl.destroy();\n }\n this._regionLabels = [];\n\n this.canvasChildren?.forEach((child) => {\n child.off('layout', this._updateLayout);\n });\n\n this.children.forEach((child) => {\n child.off('layout', this._updateLayout);\n });\n\n this.off('childAdded', this._updateLayout);\n this.off('childRemoved', this._updateLayout);\n\n this._positionContainers.forEach((container) => {\n container.off('childAdded', this._updateLayout);\n container.off('childRemoved', this._updateLayout);\n });\n\n this._bindings = [];\n\n super.destroy();\n }\n\n set size(value: SizeLike) {\n this.config.size = value === undefined ? { width: 0, height: 0 } : resolveSizeLike(value);\n\n this.layout = { width: this.config.size.width, height: this.config.size.height };\n\n this.updateLayout();\n }\n\n set padding(value: Partial<Padding> | PointLike) {\n this.config.padding = ensurePadding(value);\n // Update position to account for padding\n this._applyPadding();\n this._updateLayout();\n }\n\n /** Writes the effective padding (configured padding + safe-area insets) into the layout. */\n private _applyPadding() {\n const padding = computeEffectivePadding(\n this.config.padding,\n this.config.useSafeArea ? this.app.safeArea : zeroPadding,\n );\n this.layout = {\n paddingLeft: padding.left,\n paddingTop: padding.top,\n paddingRight: padding.right,\n paddingBottom: padding.bottom,\n };\n }\n\n private static isFlexContainer(child: PIXIContainer): boolean {\n return child instanceof FlexContainer;\n }\n\n /**\n * Removes all the children from the container\n */\n public removeChildren = (beginIndex?: number, endIndex?: number): PIXIContainer[] => {\n return super.removeChildren(beginIndex, endIndex) as PIXIContainer[];\n };\n\n /**\n * Removes a child from the container at the specified index\n */\n public removeChildAt = <U extends PIXIContainer | RenderLayer>(index: number): U => {\n return super.removeChildAt(index) as U;\n };\n\n /**\n * Adds a child to the container at the specified index\n */\n public addChildAt = <U extends PIXIContainer | RenderLayer>(_child: U, _index: number): U => {\n throw new Error(\n `UICanvas: Do not call addChildAt() directly. Use addElement(child, { align }) instead.\\n` +\n `Example: uiCanvas.addElement(myChild, { align: 'top right' })`,\n );\n };\n\n /**\n * Sets the index of the child in the container\n */\n public setChildIndex = <U extends PIXIContainer>(child: U, index: number): void => {\n super.setChildIndex(child, index);\n this._updateLayout();\n };\n\n /**\n * Gets the index of a child in the container\n */\n public getChildIndex = <U extends PIXIContainer>(child: U): number => {\n return super.getChildIndex(child);\n };\n\n /**\n * Gets the child at the specified index\n */\n public getChildAt = <U extends PIXIContainer | RenderLayer>(index: number): U => {\n return super.getChildAt(index) as U;\n };\n\n public addChild<U extends (ContainerChild | RenderLayer)[]>(...children: U): U[0] {\n if (this._disableAddChildError) {\n return super.addChild(...children);\n }\n throw new Error(\n `UICanvas: Do not call addChild() directly. Use addElement(child, { align }) instead.\\n` +\n `Example: uiCanvas.addElement(myChild, { align: 'top right' })`,\n );\n }\n\n /**\n * Removes one or more children from the container\n */\n public removeChild(..._children: (PIXIContainer | RenderLayer)[]): PIXIContainer {\n if (this._disableAddChildError) {\n return super.removeChild(...(_children as PIXIContainer[]));\n }\n throw new Error(`UICanvas: Do not call removeChild() directly. Use removeElement(child) instead.`);\n }\n\n public resize() {\n // Re-derived rather than cached: the safe area changes with the viewport.\n this._applyPadding();\n if (this.config.useAppSize) {\n this.size = { width: this.app.size.width, height: this.app.size.height };\n this.position.set(-this.app.size.width * 0.5, -this.app.size.height * 0.5);\n } else {\n this._updateLayout();\n }\n }\n\n public updateLayout() {\n if (this.destroyed || !this.layout || !this.app?.renderer.layout) return;\n this.app.renderer.layout.update(this);\n\n this._positionContainers.forEach((container) => {\n this.app.renderer.layout.update(container);\n });\n\n if (this.config.useAppSize) {\n this.position.set(-this.config.size.width * 0.5, -this.config.size.height * 0.5);\n }\n\n this._updateBindings();\n\n if (this.config.debug) {\n this.app.ticker.addOnce(this.drawDebug);\n }\n }\n\n /**\n * Bind a free-floating element to a UICanvas-managed anchor without adding it\n * to the flex flow. The element is parented to the canvas as a `layout: false`\n * child (so it never re-measures a region — it can't \"shift everything left\"),\n * and `place` re-runs on every layout pass with the anchor's current box in\n * canvas-local space. Use it for popovers, tooltips, and dropdowns anchored to\n * laid-out chrome. Idempotent per child — binding the same child again replaces\n * the previous binding.\n *\n * The bound element must NOT be a `@pixi/layout` node: re-enabling `.layout` on\n * it (a layout-enabled direct child of the canvas joins the column flow and\n * bottom-docks + reflows the canvas). Position its own subtree manually.\n */\n public bindElement(child: PIXIContainer, anchor: PIXIContainer, place: UICanvasBindFn): void {\n if (child.parent !== this) {\n this._disableAddChildError = true;\n super.addChild(child);\n this._disableAddChildError = false;\n }\n child.layout = false;\n this._bindings = this._bindings.filter((b) => b.child !== child);\n this._bindings.push({ child, anchor, place });\n this._updateLayout();\n }\n\n /** Remove a binding created by `bindElement` and detach the element. */\n public unbindElement(child: PIXIContainer): void {\n const had = this._bindings.some((b) => b.child === child);\n this._bindings = this._bindings.filter((b) => b.child !== child);\n if (had && child.parent === this) {\n this._disableAddChildError = true;\n super.removeChild(child);\n this._disableAddChildError = false;\n }\n }\n\n private _updateBindings(): void {\n for (const { child, anchor, place } of this._bindings) {\n const rect = this._anchorRect(anchor);\n if (rect) place(rect, child);\n }\n }\n\n /** The anchor's box in canvas-local space, summed from the computed-layout\n * offsets up to this canvas — deterministic and free of render-transform lag\n * (the same source the debug overlay uses to draw regions). */\n private _anchorRect(anchor: PIXIContainer): UICanvasBindRect | null {\n const own = anchor.layout?.computedLayout;\n if (!own) return null;\n let left = 0;\n let top = 0;\n for (let node: PIXIContainer | null = anchor; node && node !== this; node = node.parent) {\n const cl = node.layout?.computedLayout;\n if (cl) {\n left += cl.left;\n top += cl.top;\n }\n }\n return { left, top, width: own.width, height: own.height };\n }\n\n public addElement<U extends PIXIContainer = PIXIContainer>(\n child: PIXIContainer,\n settings?: Partial<UICanvasChildProps>,\n ): U {\n const position = settings?.align ?? 'top left';\n const container = this._positionContainers.get(position);\n\n if (!container) {\n Logger.error(`UICanvas:: Invalid position \"${position}\" for element`);\n return child as U;\n }\n\n if (UICanvas.isFlexContainer(child as PIXIContainer)) {\n this.addSignalConnection((child as unknown as FlexContainer).onLayoutComplete.connect(this._updateLayout));\n }\n\n this.settingsMap.set(child, {\n align: position,\n padding: settings?.padding ? ensurePadding(settings.padding) : { top: 0, left: 0, bottom: 0, right: 0 },\n });\n\n this._childMap.set(child, container);\n this._canvasChildren = Array.from(this._childMap.keys());\n\n container.add.existing(child);\n this._childAdded(child);\n\n return child as U;\n }\n\n public removeElement(child: PIXIContainer): PIXIContainer {\n const container = this._childMap.get(child);\n if (!container) {\n throw new Error(\n `UICanvas: Cannot remove element — it was not added via addElement().\\n` +\n `Child label: \"${child.label ?? '(unlabeled)'}\"`,\n );\n }\n\n container.removeChild(child);\n child.off('layout', this._updateLayout);\n this.settingsMap.delete(child);\n this._childMap.delete(child);\n this._canvasChildren = Array.from(this._childMap.keys());\n this._updateLayout();\n return child;\n }\n\n private _childAdded(child: PIXIContainer) {\n if (this.config.autoLayoutChildren) {\n if (!child.layout) {\n child.layout = true;\n }\n if (!child.layout?.style?.width) {\n child.layout = { width: 'auto' };\n }\n if (!child.layout?.style?.height) {\n child.layout = { height: 'auto' };\n }\n }\n child.on('layout', this._updateLayout);\n Container.childAdded(child);\n this._updateLayout();\n }\n\n private _childRemoved(child: any) {\n this.settingsMap.delete(child);\n this._childMap.delete(child as PIXIContainer);\n this._canvasChildren = Array.from(this._childMap.keys());\n Container.childRemoved(child);\n }\n\n private _added() {\n this._updateLayout();\n }\n\n // --- Debug visualization ---\n get debug(): boolean {\n return this.config.debug;\n }\n\n set debug(value: boolean) {\n this.config.debug = value;\n if (value) {\n const uid = `UICanvas:${this.uid}`;\n registerDebug(uid, this.label || 'UICanvas', DebugColors.outerBounds);\n this.drawDebug();\n } else {\n unregisterDebug(`UICanvas:${this.uid}`);\n if (this._debugGraphics) {\n this._debugGraphics.clear();\n }\n if (this._debugLabel) {\n this._debugLabel.visible = false;\n }\n for (const rl of this._regionLabels) {\n rl.visible = false;\n }\n }\n }\n\n private drawDebug() {\n // Lazily create debug graphics as a child of this canvas\n if (!this._debugGraphics) {\n this._disableAddChildError = true;\n this._debugGraphics = createDebugGraphics(`${this.label ?? 'UICanvas'}:debug`);\n super.addChild(this._debugGraphics);\n this._debugGraphics.layout = false;\n this._disableAddChildError = false;\n }\n\n if (!this._debugLabel) {\n this._disableAddChildError = true;\n this._debugLabel = createDebugLabel(this.label || 'UICanvas', DebugColors.outerBounds);\n super.addChild(this._debugLabel);\n this._debugLabel.layout = false;\n this._disableAddChildError = false;\n }\n\n this._debugLabel.text = this.label || 'UICanvas';\n this._debugLabel.visible = true;\n this._debugLabel.position.set(2, 2);\n\n this._debugGraphics.clear();\n\n const w = this.config.size.width;\n const h = this.config.size.height;\n const pad = this.config.padding;\n\n // 1. Outer bounds (red)\n this._debugGraphics\n .rect(0, 0, w, h)\n .stroke({ width: 1, color: DebugColors.outerBounds, alpha: DebugAlpha.stroke, pixelLine: true });\n\n // 2. Padding areas (red subtle fill)\n if (pad.top > 0) {\n this._debugGraphics.rect(0, 0, w, pad.top).fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pad.bottom > 0) {\n this._debugGraphics\n .rect(0, h - pad.bottom, w, pad.bottom)\n .fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pad.left > 0) {\n this._debugGraphics\n .rect(0, pad.top, pad.left, h - pad.top - pad.bottom)\n .fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n if (pad.right > 0) {\n this._debugGraphics\n .rect(w - pad.right, pad.top, pad.right, h - pad.top - pad.bottom)\n .fill({ color: DebugColors.outerBounds, alpha: DebugAlpha.fill });\n }\n\n // 3. Inner bounds (green)\n const innerX = pad.left;\n const innerY = pad.top;\n const innerW = w - pad.left - pad.right;\n const innerH = h - pad.top - pad.bottom;\n this._debugGraphics\n .rect(innerX, innerY, innerW, innerH)\n .stroke({ width: 1, color: DebugColors.innerBounds, alpha: DebugAlpha.stroke, pixelLine: true });\n\n // 4. 9-grid region visualization\n // Build a name map from edge → container for labeling\n const edgeNames = new Map<Container, string>();\n this._positionContainers.forEach((container, edge) => {\n // Use the shortest edge name for each unique container\n if (!edgeNames.has(container) || edge.length < edgeNames.get(container)!.length) {\n edgeNames.set(container, edge);\n }\n });\n\n const uniqueContainers = [...new Set(this._positionContainers.values())];\n\n // Ensure we have enough region labels\n while (this._regionLabels.length < uniqueContainers.length) {\n this._disableAddChildError = true;\n const rl = createDebugLabel('', DebugColors.region);\n super.addChild(rl);\n rl.layout = false;\n this._regionLabels.push(rl);\n this._disableAddChildError = false;\n }\n\n uniqueContainers.forEach((container, i) => {\n if (!container.layout?.computedLayout) return;\n const cl = container.layout.computedLayout;\n const parent = container.parent;\n if (!parent?.layout?.computedLayout) return;\n const parentCL = parent.layout.computedLayout;\n\n const rx = parentCL.left + cl.left;\n const ry = parentCL.top + cl.top;\n const rw = cl.width;\n const rh = cl.height;\n const hasChildren = container.children.length > 0;\n\n // Region fill (different alpha for occupied vs empty)\n this._debugGraphics!\n .rect(rx, ry, rw, rh)\n .fill({ color: DebugColors.region, alpha: hasChildren ? DebugAlpha.fillActive : DebugAlpha.fill })\n .stroke({ width: 1, color: DebugColors.region, alpha: 0.3, pixelLine: true });\n\n // Region label\n const rl = this._regionLabels[i];\n rl.text = edgeNames.get(container) ?? '';\n rl.visible = true;\n rl.position.set(rx + 2, ry + 2);\n });\n\n // Hide unused region labels\n for (let i = uniqueContainers.length; i < this._regionLabels.length; i++) {\n this._regionLabels[i].visible = false;\n }\n\n // 5. Center crosshairs\n const centerX = w / 2;\n const centerY = h / 2;\n this._debugGraphics\n .moveTo(centerX, centerY - 10)\n .lineTo(centerX, centerY + 10)\n .stroke({ width: 1, color: DebugColors.outerBounds, alpha: DebugAlpha.crosshair, pixelLine: true })\n .moveTo(centerX - 10, centerY)\n .lineTo(centerX + 10, centerY)\n .stroke({ width: 1, color: DebugColors.outerBounds, alpha: DebugAlpha.crosshair, pixelLine: true });\n }\n}\n","/**\n * Runtime registry for `this.add.entity(id, props)` lookups.\n *\n * The Vite plugin's entity discovery emits a `virtual:caper-entities` module\n * with static imports by default (`defaultDynamic: false` in\n * `discoverLocalClassFiles`). The `caper-runtime` virtual module pulls that\n * list onto `globalThis.Caper.entityList` before the Application starts, so\n * by the time any scene fires `initialize()` and calls `this.add.entity`,\n * the list is in place.\n *\n * This registry is populated lazily on first lookup — no explicit bootstrap\n * step needed. Entities declared with `defineEntity({ dynamic: true })` have\n * an async `module` function and are skipped: the sync factory API can't\n * wait for them. That's an intentional tradeoff — if a project needs code-\n * split entities, they use `add.existing(new Foo(...), props)` with a\n * manual lazy import instead.\n */\n\ntype EntityConstructor = new (props?: unknown) => unknown;\n\ntype EntityListItem = {\n id: string;\n active?: boolean;\n module?: EntityConstructor | (() => Promise<unknown>);\n};\n\nlet registry: Map<string, EntityConstructor> | null = null;\n\nfunction ensureRegistry(): Map<string, EntityConstructor> {\n if (registry) return registry;\n registry = new Map();\n const list: EntityListItem[] =\n (globalThis as unknown as { Caper?: { get?: (key: string) => unknown } }).Caper?.get?.(\n 'entityList',\n ) as EntityListItem[] | undefined ?? [];\n for (const item of list) {\n if (item.active === false) continue;\n if (typeof item.module === 'function' && item.module.prototype) {\n registry.set(item.id, item.module as EntityConstructor);\n }\n // Dynamic (arrow-function) modules have no prototype — skipped, since\n // `this.add.entity` is sync and can't await a dynamic import.\n }\n return registry;\n}\n\nexport function getEntityCtor(id: string): EntityConstructor | undefined {\n return ensureRegistry().get(id);\n}\n\nexport function getRegisteredEntityIds(): string[] {\n return [...ensureRegistry().keys()];\n}\n\n/**\n * Reset the registry. Test-only — production code should rely on the lazy\n * initialization from `globalThis.Caper.entityList`.\n */\nexport function _resetEntityRegistry(): void {\n registry = null;\n}\n","/**\n * Runtime registry for `this.add.ui(id, props)` lookups.\n *\n * Mirrors the entity registry pattern exactly. The Vite plugin's UI\n * discovery emits a `virtual:caper-uis` module with static imports by\n * default (`defaultDynamic: false`). The `caper-runtime` virtual module\n * pulls that list onto `globalThis.Caper.uiList` before the Application\n * starts.\n *\n * Populated lazily on first lookup — no explicit bootstrap step needed.\n */\n\ntype UIConstructor = new (props?: unknown) => unknown;\n\ntype UIListItem = {\n id: string;\n active?: boolean;\n module?: UIConstructor | (() => Promise<unknown>);\n};\n\nlet registry: Map<string, UIConstructor> | null = null;\n\nfunction ensureRegistry(): Map<string, UIConstructor> {\n if (registry) return registry;\n registry = new Map();\n const list: UIListItem[] =\n (globalThis as unknown as { Caper?: { get?: (key: string) => unknown } }).Caper?.get?.(\n 'uiList',\n ) as UIListItem[] | undefined ?? [];\n for (const item of list) {\n if (item.active === false) continue;\n if (typeof item.module === 'function' && item.module.prototype) {\n registry.set(item.id, item.module as UIConstructor);\n }\n // Dynamic (arrow-function) modules have no prototype — skipped, since\n // `this.add.ui` is sync and can't await a dynamic import.\n }\n return registry;\n}\n\nexport function getUICtor(id: string): UIConstructor | undefined {\n return ensureRegistry().get(id);\n}\n\nexport function getRegisteredUIIds(): string[] {\n return [...ensureRegistry().keys()];\n}\n\n/**\n * Reset the registry. Test-only.\n */\nexport function _resetUIRegistry(): void {\n registry = null;\n}\n","// Import from source files directly (not via the `../../utils` barrel) so\n// the test runtime doesn't transitively pull in display/Container → the\n// Factory mixin chain → const.ts. That cycle is fine for bundled builds\n// but breaks vitest module evaluation when the test imports from here.\nimport { omitKeys } from '../../utils/object';\nimport {\n resolveAnchor,\n resolvePivot,\n resolvePosition,\n resolveScale,\n resolveUnknownKeys,\n} from './utils';\n\n/**\n * Common prop resolvers the schema helper can apply after constructing an\n * instance. Each entry corresponds to one of the `resolveXxx` utilities and\n * reads its inputs from the raw props object — so `'position'` consumes\n * `{ position, x, y }`, `'scale'` consumes `{ scale, scaleX, scaleY }`,\n * etc.\n */\nexport type FactoryApply = 'position' | 'scale' | 'pivot' | 'anchor';\n\n/**\n * Schema describing a single factory method. Owned by the method's entry in\n * `defaultFactoryMethods`; `buildFactoryMethod` consumes it to produce a\n * typed `(props?: Props) => Instance` function with the standard\n * resolve-position / resolve-scale / resolve-pivot / resolve-anchor\n * post-construct pipeline and an automatic unknown-keys passthrough.\n *\n * The point of pushing every method through this shape is to collapse the\n * copy-paste construction boilerplate in [const.ts](./const.ts): each\n * method becomes (a) `build` — the bespoke constructor call that may\n * reshape the props before handing them to Pixi — and (b) a list of which\n * common resolvers to run. Everything else (unknowns passthrough, optional\n * props guard, etc.) is centralized.\n */\nexport interface FactorySchema<Props, Instance> {\n /**\n * Bespoke construction. Receives the raw Caper-shaped props (possibly\n * undefined) and returns a new instance. Any reshaping Caper does for DX\n * — Sprite's `{asset, sheet}` → texture resolution, Text's top-level\n * style flattening, Container's config/extras split — lives here.\n */\n build: (props: Props | undefined) => Instance;\n\n /**\n * Which common resolvers to run on the instance after `build` returns.\n * Defaults to `['position', 'scale', 'pivot']` when omitted — the lowest\n * common denominator that every display object supports. Classes with an\n * `anchor` field (Sprite, Text, AnimatedSprite, Spine) opt in to\n * `'anchor'` explicitly.\n */\n applies?: readonly FactoryApply[];\n\n /**\n * Keys the `build` callback already consumed — excluded from the\n * unknown-keys passthrough so Caper doesn't try to set them on the\n * instance a second time. For example, Sprite's schema excludes `asset`\n * and `sheet` (consumed by `resolveTexture`), Text's schema excludes\n * `text`, `roundPixels`, `resolution`, `style`, `anchor`, and `pivot`.\n */\n exclude?: readonly string[];\n}\n\nconst DEFAULT_APPLIES: readonly FactoryApply[] = ['position', 'scale', 'pivot'];\n\n/**\n * Keys automatically excluded from the unknown-keys passthrough because\n * they're either consumed by a resolver listed in `applies` or are a\n * shorthand alias for one that is. Listed here so individual schemas don't\n * have to re-declare them.\n */\nconst RESOLVER_KEYS: readonly string[] = [\n 'position',\n 'x',\n 'y',\n 'scale',\n 'scaleX',\n 'scaleY',\n 'pivot',\n 'anchor',\n];\n\n/**\n * Build a typed factory method from a schema. The return type preserves\n * the `(props?: Props) => Instance` shape TypeScript uses to drive\n * autocomplete on `this.add.*({...})` call sites.\n *\n * Behavior mirrors the hand-written factory method pattern:\n * 1. Call `schema.build(props)` to get the instance.\n * 2. If props were passed, apply each resolver in `schema.applies`\n * (position / scale / pivot / anchor).\n * 3. Forward any remaining keys to `resolveUnknownKeys` for the common\n * pass-through surface (`alpha`, `visible`, `label`, `eventMode`, etc.)\n * minus any keys the `build` callback already consumed.\n *\n * @example\n * ```ts\n * sprite: buildFactoryMethod<Partial<SpriteProps>, Sprite>({\n * build: (props) => new Sprite(props ? resolveTexture(props) : undefined),\n * applies: ['position', 'scale', 'pivot', 'anchor'],\n * exclude: ['asset', 'sheet'],\n * }),\n * ```\n */\nexport function buildFactoryMethod<Props, Instance>(\n schema: FactorySchema<Props, Instance>,\n): (props?: Props) => Instance {\n const applies = schema.applies ?? DEFAULT_APPLIES;\n const applyPosition = applies.includes('position');\n const applyScale = applies.includes('scale');\n const applyPivot = applies.includes('pivot');\n const applyAnchor = applies.includes('anchor');\n const excludeKeys = [...RESOLVER_KEYS, ...(schema.exclude ?? [])];\n\n return (props?: Props): Instance => {\n const instance = schema.build(props);\n if (props === undefined || props === null) return instance;\n\n // Post-construct resolvers. Each reads from the raw props object so the\n // schema doesn't have to pre-extract them.\n const rawProps = props as unknown as Record<string, unknown>;\n if (applyPosition) {\n resolvePosition(\n { position: rawProps.position as never, x: rawProps.x as never, y: rawProps.y as never },\n instance as unknown as object,\n );\n }\n if (applyScale) {\n resolveScale(\n {\n scale: rawProps.scale as never,\n scaleX: rawProps.scaleX as never,\n scaleY: rawProps.scaleY as never,\n },\n instance as unknown as object,\n );\n }\n if (applyPivot) {\n resolvePivot(rawProps.pivot as never, instance as unknown as object);\n }\n if (applyAnchor) {\n resolveAnchor(rawProps.anchor as never, instance as unknown as object);\n }\n\n // Forward any remaining keys via the passthrough. Excludes the keys\n // already handled by the resolvers above plus anything the schema's\n // `build` callback consumed.\n const rest = omitKeys(excludeKeys, rawProps);\n resolveUnknownKeys(rest, instance);\n return instance;\n };\n}\n","import { BitmapText, Graphics, HTMLText, Sprite, Text, TilingSprite } from 'pixi.js';\n\nimport { AnimatedSprite } from '../../display/AnimatedSprite';\nimport { Container, ContainerConfigKeys } from '../../display/Container';\nimport { ParticleContainer, ParticleContainerConfigKeys } from '../../display/ParticleContainer';\nimport { SpineAnimation } from '../../display/SpineAnimation';\nimport { Svg } from '../../display/Svg';\nimport type { ButtonConfig } from '../../ui/Button';\nimport { Button, ButtonConfigKeys } from '../../ui/Button';\nimport type { FlexContainerConfig } from '../../ui/FlexContainer';\nimport { FlexContainer, FlexContainerConfigKeys } from '../../ui/FlexContainer';\nimport type { ToastConfig } from '../../ui/Toast';\nimport type { ToasterConfig } from '../../ui/Toaster';\nimport { Toaster } from '../../ui/Toaster';\nimport type { UICanvasProps } from '../../ui/UICanvas';\nimport { UICanvas, UICanvasConfigKeys } from '../../ui/UICanvas';\nimport type { EntityId, EntityInstance, EntityProps, UIId, UIInstance, UIProps } from '../../utils';\nimport { pluck, resolvePointLike, Spine, WithRequiredProps } from '../../utils';\n\nimport { setDefaultFactoryMethods } from './defaults';\nimport type { EntityFactoryProps } from './props';\nimport {\n AnimatedSpriteProps,\n BitmapTextProps,\n ButtonProps,\n ContainerProps,\n ExistingProps,\n FlexContainerProps,\n GraphicsProps,\n HTMLTextProps,\n ParticleContainerProps,\n SpineProps,\n SpriteProps,\n SvgProps,\n TextProps,\n TilingSpriteProps,\n UICanvasFactoryProps,\n} from './props';\nimport { getEntityCtor, getRegisteredEntityIds } from './registry';\nimport { getUICtor, getRegisteredUIIds } from './ui-registry';\nimport { buildFactoryMethod } from './schema';\nimport {\n resolveAnchor,\n resolvePivot,\n resolvePosition,\n resolveScale,\n resolveTexture,\n resolveUnknownKeys,\n} from './utils';\n\n/**\n * Keys consumed by text-family factory builds (`text`, `htmlText`,\n * `bitmapText`). Shared here so the three schemas don't drift — each one\n * flattens `{text, style, roundPixels, resolution, anchor, pivot}` into\n * the Pixi constructor options in `build`, so all those keys must be\n * excluded from the schema's unknown-keys passthrough.\n */\nconst TEXT_CONSUMED_KEYS = ['text', 'roundPixels', 'resolution', 'style', 'anchor', 'pivot'] as const;\n\n/**\n * Factory method table consumed by the `Factory()` mixin. Almost every\n * entry is built via `buildFactoryMethod({ build, applies, exclude })`:\n * the `build` callback owns the bespoke constructor call (including any\n * DX reshaping Caper applies — asset-name resolution, text style\n * flattening, config-vs-extras splits), and the helper centralizes\n * position/scale/pivot/anchor + unknown-keys passthrough.\n *\n * The five bespoke entries (`existing`, `texture`, `svg`, `toaster`,\n * `entity`) don't fit the `(props?) → instance` shape — `existing` takes\n * `(entity, props)`, `texture` is a plain resolver re-bind, `svg` takes\n * a required `ctx` field, `toaster` takes two config objects, and\n * `entity` takes `(id, props)` with a generic narrowed to discovered\n * entity ids — so they stay hand-written.\n */\nexport const defaultFactoryMethods = {\n existing: <TEntity>(entity: TEntity, props?: Partial<ExistingProps>): TEntity => {\n if (!props) return entity;\n const { position, x, y, pivot, scale, scaleX, scaleY, ...rest } = props;\n resolvePosition({ position, x, y }, entity);\n resolveScale({ scale, scaleX, scaleY }, entity);\n resolvePivot(pivot, entity);\n resolveUnknownKeys(rest, entity);\n return entity;\n },\n\n container: buildFactoryMethod({\n build: (props?: Partial<ContainerProps>): Container =>\n new Container(props ? pluck(props, ContainerConfigKeys) : undefined),\n applies: ['position', 'scale', 'pivot'],\n exclude: ContainerConfigKeys as readonly string[],\n }),\n\n particleContainer: buildFactoryMethod({\n build: (props?: Partial<ParticleContainerProps>): ParticleContainer =>\n new ParticleContainer(props ? pluck(props, ParticleContainerConfigKeys) : undefined),\n applies: ['position', 'scale', 'pivot'],\n exclude: ParticleContainerConfigKeys as readonly string[],\n }),\n\n texture: resolveTexture,\n\n sprite: buildFactoryMethod({\n build: (props?: Partial<SpriteProps>) =>\n new Sprite(props ? resolveTexture(props) : undefined),\n applies: ['position', 'scale', 'pivot', 'anchor'],\n exclude: ['asset', 'sheet'],\n }),\n\n tilingSprite: buildFactoryMethod({\n build: (props?: Partial<TilingSpriteProps>) =>\n new TilingSprite(props ? resolveTexture(props) : undefined),\n applies: ['position', 'scale', 'pivot', 'anchor'],\n exclude: ['asset', 'sheet'],\n }),\n\n animatedSprite: buildFactoryMethod({\n // AnimatedSprite's Caper-side constructor consumes the full props bag\n // (animations, autoPlay, autoUpdate, sheet, texturePrefix, etc.), so\n // the schema's `build` just forwards them. Position/scale/pivot are\n // applied by the helper from the same object.\n build: (props?: Partial<AnimatedSpriteProps>): AnimatedSprite => new AnimatedSprite(props),\n applies: ['position', 'scale', 'pivot'],\n exclude: [\n 'sheet',\n 'texturePrefix',\n 'zeroPad',\n 'animations',\n 'autoPlay',\n 'autoUpdate',\n 'defaultAnimation',\n 'reversible',\n 'animationSpeed',\n 'startIndex',\n 'animation',\n ],\n }),\n\n graphics: buildFactoryMethod({\n build: (_props?: Partial<GraphicsProps>) => new Graphics(),\n applies: ['position', 'scale', 'pivot'],\n }),\n\n svg(props: WithRequiredProps<SvgProps, 'ctx'>) {\n const entity = new Svg(props.ctx);\n const { position, x, y, pivot, scale, scaleX, scaleY, ctx: _ctx, ...rest } = props;\n resolvePosition({ position, x, y }, entity);\n resolveScale({ scale, scaleX, scaleY }, entity);\n resolvePivot(pivot, entity);\n resolveUnknownKeys(rest, entity);\n return entity;\n },\n\n text: buildFactoryMethod({\n // Text flattens Pixi's nested `style: {...}` into top-level props for\n // DX (e.g. `{fontFamily, fontSize, fill}` without the `style:` wrapper\n // — see TextStyle type in props.ts). The build callback rebuilds the\n // Pixi-shape options object, including `anchor`/`pivot` pre-resolved\n // via `resolvePointLike(..., true)` the way the hand-written method\n // did. Post-construct resolvers handle position/scale/pivot.\n build: (props?: Partial<TextProps>) =>\n new Text(\n props\n ? {\n text: props.text,\n roundPixels: props.roundPixels,\n resolution: props.resolution,\n style: props.style,\n anchor: props.anchor ? resolvePointLike(props.anchor, true) : undefined,\n pivot: props.pivot ? resolvePointLike(props.pivot, true) : undefined,\n }\n : {},\n ),\n applies: ['position', 'scale', 'pivot'],\n exclude: [...TEXT_CONSUMED_KEYS],\n }),\n\n htmlText: buildFactoryMethod({\n build: (props?: Partial<HTMLTextProps>) =>\n new HTMLText(\n props\n ? {\n text: props.text,\n roundPixels: props.roundPixels,\n resolution: props.resolution,\n style: props.style,\n anchor: props.anchor ? resolvePointLike(props.anchor, true) : undefined,\n pivot: props.pivot ? resolvePointLike(props.pivot, true) : undefined,\n }\n : {},\n ),\n applies: ['position', 'scale', 'pivot'],\n exclude: [...TEXT_CONSUMED_KEYS],\n }),\n\n bitmapText: buildFactoryMethod({\n // BitmapText's ctor doesn't take `resolution` — that's the only field\n // that differs from Text/HTMLText here.\n build: (props?: Partial<BitmapTextProps>) =>\n new BitmapText(\n props\n ? {\n text: props.text,\n roundPixels: props.roundPixels,\n style: props.style,\n anchor: props.anchor ? resolvePointLike(props.anchor, true) : undefined,\n pivot: props.pivot ? resolvePointLike(props.pivot, true) : undefined,\n }\n : {},\n ),\n applies: ['position', 'scale', 'pivot'],\n exclude: [...TEXT_CONSUMED_KEYS],\n }),\n\n button: buildFactoryMethod({\n build: (props?: Partial<ButtonProps>): Button =>\n new Button((props ? pluck(props, ButtonConfigKeys) : undefined) as Partial<ButtonConfig>),\n applies: ['position', 'scale', 'pivot'],\n exclude: ButtonConfigKeys as readonly string[],\n }),\n\n flexContainer: buildFactoryMethod({\n // FlexContainer takes the full props bag (minus position/scale/pivot)\n // as its constructor config — historical: the hand-written method\n // passed `props as Partial<FlexContainerConfig>` directly rather than\n // plucking FlexContainerConfigKeys. Preserving that shape.\n build: (props?: Partial<FlexContainerProps>): FlexContainer =>\n new FlexContainer(props as Partial<FlexContainerConfig>),\n applies: ['position', 'scale', 'pivot'],\n exclude: FlexContainerConfigKeys as readonly string[],\n }),\n\n uiCanvas: buildFactoryMethod({\n build: (props?: Partial<UICanvasFactoryProps>): UICanvas =>\n // UICanvas's ctor takes Partial<UICanvasProps>, which is a superset\n // of UICanvasConfig — the pluck narrows, so cast back.\n new UICanvas(props ? (pluck(props, UICanvasConfigKeys) as Partial<UICanvasProps>) : ({} as Partial<UICanvasProps>)),\n applies: ['position', 'scale', 'pivot'],\n exclude: UICanvasConfigKeys as readonly string[],\n }),\n\n spine: buildFactoryMethod({\n build: (props?: Partial<SpineProps>): Spine => {\n // Resolve Caper's `{data: 'spine/foo'}` shorthand into the Pixi\n // `{skeleton, atlas}` pair expected by Spine.from().\n let spineData: { skeleton: string; atlas: string } | string = '';\n const data = props?.data;\n if (typeof data === 'string') {\n // If the asset name is missing an extension, default to .json. If\n // it has one, strip it so we can re-append both skeleton + atlas\n // paths from the base name.\n let ext = data.slice(-5);\n if (ext !== '.json' && ext !== '.skel') {\n ext = '.json';\n } else {\n spineData = data.substring(0, data.length - 5);\n }\n spineData = { skeleton: data + ext, atlas: data + '.atlas' };\n }\n const entity: Spine = (window as unknown as { Spine: { from: (d: unknown) => Spine } }).Spine.from(\n spineData,\n );\n // Spine-specific post-construct setup. Has to happen here (not in\n // `applies`) because the helper doesn't know about spine state.\n if (props?.autoUpdate !== undefined) entity.autoUpdate = props.autoUpdate;\n if (props?.animationName) {\n entity.state.setAnimation(props.trackIndex ?? 0, props.animationName, props.loop);\n }\n return entity;\n },\n applies: ['position', 'scale', 'pivot', 'anchor'],\n exclude: ['data', 'autoUpdate', 'animationName', 'trackIndex', 'loop'],\n }),\n\n spineAnimation: <ANames extends string = string>(\n props?: Partial<SpineProps>,\n ): SpineAnimation<ANames> => {\n // Hand-written rather than schema-driven because `buildFactoryMethod`\n // can't carry the `<ANames>` generic through to the call site —\n // kitchen-sink's SpineScene narrows the animation-name union via\n // `this.add.spineAnimation<CharacterAnimations>({...})`, which\n // requires the method itself to declare the generic.\n const entity = new SpineAnimation<ANames>(props);\n if (!props) return entity;\n const { position, x, y, anchor, pivot, scale, scaleX, scaleY, ...rest } = props;\n resolvePosition({ position, x, y }, entity);\n resolveScale({ scale, scaleX, scaleY }, entity);\n resolveAnchor(anchor, entity);\n resolvePivot(pivot, entity);\n resolveUnknownKeys(rest, entity);\n return entity;\n },\n\n toaster: (toasterConfig?: Partial<ToasterConfig>, defaultToastConfig: Partial<ToastConfig> = {}): Toaster => {\n return new Toaster(toasterConfig, defaultToastConfig);\n },\n\n /**\n * Construct an entity from the auto-discovered registry. `id` is narrowed\n * to the union of entity ids declared under `src/entities/` (see the\n * generated `caper-app.d.ts`), and `props` is typed from the entity's\n * constructor signature via `ConstructorParameters<typeof Entity>[0]`.\n *\n * Throws if `id` isn't registered. Discovery runs at build time, so the\n * only way to hit this at runtime is a stale virtual module — fail loud\n * and list the known ids so the user can see what's wrong.\n *\n * @example\n * this.add.entity('actor', { color: 0xff0000, x: 50, y: 100 });\n */\n entity: <K extends EntityId>(\n id: K,\n props?: EntityProps<K> & EntityFactoryProps,\n ): EntityInstance<K> => {\n const Ctor = getEntityCtor(id as string);\n if (!Ctor) {\n const known = getRegisteredEntityIds();\n throw new Error(\n `[caper] Unknown entity id '${String(id)}'. ` +\n `Known: ${known.length > 0 ? known.map((k) => `'${k}'`).join(', ') : '(none — discovery may have failed)'}`,\n );\n }\n const instance = new (Ctor as new (props?: EntityProps<K>) => EntityInstance<K>)(props);\n if (props) {\n const { position, x, y, pivot, scale, scaleX, scaleY, alpha, visible } = props as EntityFactoryProps;\n resolvePosition({ position, x, y }, instance);\n resolveScale({ scale, scaleX, scaleY }, instance);\n resolvePivot(pivot, instance);\n if (alpha !== undefined) (instance as unknown as { alpha: number }).alpha = alpha;\n if (visible !== undefined) (instance as unknown as { visible: boolean }).visible = visible;\n }\n return instance;\n },\n\n /**\n * Construct a UI element from the auto-discovered registry. `id` is\n * narrowed to the union of UI ids declared under `src/ui/` (see the\n * generated `caper-app.d.ts`), and `props` is typed from the UI\n * element's constructor signature via `ConstructorParameters<...>[0]`.\n *\n * @example\n * this.add.ui('close-button', { x: 100, y: 50 });\n */\n ui: <K extends UIId>(\n id: K,\n props?: UIProps<K> & EntityFactoryProps,\n ): UIInstance<K> => {\n const Ctor = getUICtor(id as string);\n if (!Ctor) {\n const known = getRegisteredUIIds();\n throw new Error(\n `[caper] Unknown ui id '${String(id)}'. ` +\n `Known: ${known.length > 0 ? known.map((k) => `'${k}'`).join(', ') : '(none — discovery may have failed)'}`,\n );\n }\n const instance = new (Ctor as new (props?: UIProps<K>) => UIInstance<K>)(props);\n if (props) {\n const { position, x, y, pivot, scale, scaleX, scaleY, alpha, visible } = props as EntityFactoryProps;\n resolvePosition({ position, x, y }, instance);\n resolveScale({ scale, scaleX, scaleY }, instance);\n resolvePivot(pivot, instance);\n if (alpha !== undefined) (instance as unknown as { alpha: number }).alpha = alpha;\n if (visible !== undefined) (instance as unknown as { visible: boolean }).visible = visible;\n }\n return instance;\n },\n};\n\n// Hand the table to the import-free registration slot the moment it exists, so\n// `Factory()` can read it without importing this module. See ./defaults.ts.\nsetDefaultFactoryMethods(defaultFactoryMethods);\n","import type { LayoutOptions } from '@pixi/layout';\nimport { GraphicsContext, HTMLTextStyleOptions, TextStyleOptions } from 'pixi.js';\nimport type { ContainerConfig } from '../../display/Container';\nimport type { ParticleContainerConfig } from '../../display/ParticleContainer';\nimport type { ButtonConfig } from '../../ui/Button';\nimport type { FlexContainerConfig } from '../../ui/FlexContainer';\nimport type { UICanvasProps } from '../../ui/UICanvas';\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 {\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 type { TextProps } from '../mixins/factory/props';\nimport { Focusable } from '../mixins/focus';\nimport { Interactive } from '../mixins/interaction';\nimport { WithSignals } from '../mixins/signals';\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/Container';\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","/**\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/Container';\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"],"mappings":";;;;;AAMA,SAAgB,GAAW,GAAkB;CAC3C,IAAI,GACA;AACJ,MAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,EAAE,EAIlC,CAHA,IAAQ,GAAW,GAAG,EAAM,OAAO,EACnC,IAAO,EAAM,IACb,EAAM,KAAK,EAAM,IACjB,EAAM,KAAS;;AAQnB,SAAgB,GAAoB,GAAe;AACjD,QAAO,EAAM,GAAW,GAAG,EAAM,OAAO;;;;ACtB1C,SAAgB,GAAc,GAA6C;CACzE,IAAM,IAAK,EAAO,WAAW,QAAQ;AACrC,KAAI,GAAI;EACN,IAAM,IAAY,EAAG,aAAa,qBAAqB;AACvD,EAAI,KACF,EAAU,aAAa;;CAK3B,IAAM,IAAM,EAAO,WAAW,KAAK;AAcnC,CAbI,KAEF,EAAI,UAAU,GAAG,GAAG,EAAO,OAAO,EAAO,OAAO,EAE5C,aAAkB,mBAClB,EAAO,cACT,EAAO,WAAW,YAAY,EAAO,EAGzC,EAAO,QAAQ,GACf,EAAO,SAAS,GAGhB,IAAS;;;;ACxBX,SAAgB,GAAM,GAAuB;AAC3C,QAAO,IAAI,EAAM,SAAS,GAAG;;AAI/B,SAAgB,GAAM,GAAqB;AACzC,QAAO,SAAS,EAAI,QAAQ,MAAM,GAAG,EAAE,GAAG;;AAG5C,IAAa,KAAb,MAAa,EAAM;;eACqB,IAAI,EAAM,KAAK,KAAK,IAAI;;;eACxB,IAAI,EAAM,GAAG,GAAG,EAAE;;;cACnB,IAAI,EAAM,KAAK,KAAK,IAAI;;;aACzB,IAAI,EAAM,KAAK,GAAG,EAAE;;;eAClB,IAAI,EAAM,GAAG,KAAK,EAAE;;;cACrB,IAAI,EAAM,GAAG,GAAG,IAAI;;;gBAClB,IAAI,EAAM,KAAK,KAAK,EAAE;;;iBACrB,IAAI,EAAM,KAAK,GAAG,IAAI;;;cACzB,IAAI,EAAM,GAAG,KAAK,IAAI;;CAY3D,YAAY,GAAY,GAAY,GAAY;AAC9C,EAAI,MAAM,KAAA,KAAa,MAAM,KAAA,KAE3B,KAAK,KAAK,IAAK,OAAO,OAAQ,IAE9B,KAAK,KAAK,IAAK,UAAc,GAE7B,KAAK,IAAI,IAAI,QAEb,KAAK,IAAI,KAAK,GACd,KAAK,IAAI,KAAK,GACd,KAAK,IAAI,KAAK;;CAQlB,OAAc,SAAgB;AAC5B,SAAO,IAAI,EAAM,KAAK,QAAQ,GAAG,KAAK,KAAK,QAAQ,GAAG,KAAK,KAAK,QAAQ,GAAG,IAAI;;CAUjF,OAAc,SAAS,GAAW,GAAW,GAAmB;AAE9D,SAAQ,KAAK,KAAO,KAAK,IAAK;;CAGhC,OAAc,eAAe,GAAyB;EACpD,IAAI,IAAM,OAAO,EAAQ,CAAC,SAAS,GAAG;AAKtC,SAJI,EAAI,SAAS,MACf,IAAM,MAAM,IAGP;;CAGT,OAAc,mBAAmB,GAAW,GAAW,GAAmB;EACxE,IAAM,IAAe,EAAM,eAAe,EAAE,EACtC,IAAe,EAAM,eAAe,EAAE,EACtC,IAAe,EAAM,eAAe,EAAE;AAE5C,SAAO,IAAO,IAAO;;CAUvB,OAAc,KAAK,GAAW,GAAU,GAAsB;AAC5D,SAAO,IAAI,EAAM,EAAG,IAAI,KAAS,EAAE,IAAI,EAAG,IAAI,EAAG,IAAI,KAAS,EAAE,IAAI,EAAG,IAAI,EAAG,IAAI,KAAS,EAAE,IAAI,EAAG,GAAG;;CAUzG,OAAc,QAAQ,GAAY,GAAW,GAAuB;EAClE,IAAM,IAAgB,IAAI,EAAM,EAAG,EAC7B,IAAgB,IAAI,EAAM,EAAE;AAClC,SAAO,EAAM,KAAK,GAAQ,GAAQ,EAAM,CAAC,OAAO;;CAOlD,QAAuB;AACrB,SAAO,EAAM,SAAS,KAAK,GAAG,KAAK,GAAG,KAAK,EAAE;;CAG/C,cAA6B;AAC3B,SAAO,EAAM,mBAAmB,KAAK,GAAG,KAAK,GAAG,KAAK,EAAE;;CAOzD,UAA2B;AACzB,SAAO;GAAC,KAAK,IAAI;GAAK,KAAK,IAAI;GAAK,KAAK,IAAI;GAAI;;GCxHxC,IAAc;CACzB,QAAQ;CACR,aAAa;CACb,aAAa;CACb,WAAW;CACX,KAAK;CACL,QAAQ;CACT,EAEY,IAAa;CACxB,QAAQ;CACR,MAAM;CACN,YAAY;CACZ,WAAW;CACZ;AAMD,SAAgB,GAAoB,GAA0B;CAC5D,IAAM,IAAI,IAAI,GAAU;AAKxB,QAJA,EAAE,YAAY,QACd,EAAE,sBAAsB,IACxB,EAAE,SAAS,IACX,EAAE,QAAQ,KAAS,iBACZ;;AAOT,SAAgB,EAAiB,GAAc,IAAgB,EAAY,QAAc;CACvF,IAAM,IAAQ,IAAI,EAAK;EACrB;EACA,OAAO;GACL,YAAY;GACZ,UAAU;GACV,MAAM;GACN,QAAQ;IAAE,OAAO;IAAU,OAAO;IAAG;GACtC;EACF,CAAC;AAIF,QAHA,EAAM,YAAY,QAClB,EAAM,SAAS,IACf,EAAM,QAAQ,cACP;;AAOT,IAAM,qBAAY,IAAI,KAAyB;AAE/C,SAAgB,EAAc,GAAY,GAAe,GAAqB;AAC5E,IAAU,IAAI,GAAI;EAAE;EAAO;EAAO,CAAC;;AAGrC,SAAgB,EAAgB,GAAkB;AAChD,IAAU,OAAO,EAAG;;AAGtB,SAAgB,KAAoD;AAClE,QAAO;;;;ACkCT,SAAgB,GAAwC,GAAc;AACpE,QAAO;;AAGT,SAAgB,GAA0C,GAAc;AACtE,QAAO;;AAGT,SAAgB,GAAwC,GAAc;AACpE,QAAO;;AAGT,SAAgB,GAA0C,GAAc;AACtE,QAAO;;AAGT,SAAgB,GAAkC,GAAc;AAC9D,QAAO;;;;ACtHT,SAAgB,GAAoB,GAAa,IAAkB,GAAW;AAC5E,QAAO,EAAI,UAAU,CAAC,SAAS,GAAS,IAAI;;;;ACC9C,SAAgB,GAAe,GAAoB,GAAc;AAM/D,QAHI,KAAc,KAAK,KAAc,IAC5B,IAAa,IAEf;;AAGT,SAAgB,EAAc,GAAgD;AAC5E,KAAI,MAAM,QAAQ,EAAQ,CACxB,QAAO;EACL,KAAK,EAAQ;EACb,OAAO,IAAU,MAAM,EAAQ;EAC/B,QAAQ,IAAU,MAAM,EAAQ;EAChC,MAAM,IAAU,MAAM,IAAU,MAAM,EAAQ,MAAM;EACrD;AAEH,KAAI,OAAO,KAAY,SACrB,QAAO;EAAE,KAAK;EAAS,OAAO;EAAS,QAAQ;EAAS,MAAM;EAAS;KAC9D,OAAO,KAAY,UAAU;EACtC,IAAM,IAAqB;AASzB,SARE,EAAmB,MAAM,KAAA,KAAa,EAAmB,MAAM,KAAA,IAC1D;GACL,KAAK,EAAmB;GACxB,OAAO,EAAmB;GAC1B,QAAQ,EAAmB;GAC3B,MAAM,EAAmB;GAC1B,GAEM;GACL,KAAM,EAAoB,OAAO;GACjC,OAAQ,EAAoB,SAAS;GACrC,QAAS,EAAoB,UAAU;GACvC,MAAO,EAAoB,QAAQ;GACpC;OAGH,QAAO;EAAE,KAAK;EAAG,OAAO;EAAG,QAAQ;EAAG,MAAM;EAAG;;;;AC5BnD,SAAgB,GAAS,GAAwB,GAA0B;AAMzE,CALI,EAAO,UACT,EAAO,OAAO,eAAe,MAAM,EAAO,UAAmB,EAAO,SAAkB,EAExF,EAAQ,eAAe,aAAa,EAAO,UAAmB,EAAO,SAAkB,EACvF,EAAO,QAAQ,YAAY,EAAO,EAClC,EAAQ,SAAS,EAAO;;AAO1B,SAAgB,GAAe,GAA4B;AACzD,QAAO,KAAK,KAAK,EAAQ,QAAQ,EAAQ,QAAQ,EAAQ,SAAS,EAAQ,OAAO;;AAOnF,SAAgB,GAAY,GAA0B;CACpD,IAAM,IAAS,EAAQ;AAClB,OACL,EAAO,YAAY,EAAQ,EAC3B,EAAO,SAAS,EAAQ;;AAO1B,SAAgB,GAAW,GAA0B;CACnD,IAAM,IAAS,EAAQ;AAClB,OACL,EAAO,YAAY,EAAQ,EAC3B,EAAO,WAAW,GAAS,EAAE;;AAQ/B,SAAgB,GAAY,GAAmB,GAA0B;AACvE,KAAI,aAAkB,IAAS;AAC7B,OAAK,IAAI,IAAI,GAAG,IAAI,EAAO,OAAO,QAAQ,KAAK,EAE7C,CADA,EAAO,OAAO,MAAM,EAAO,GAC3B,EAAO,OAAO,IAAI,MAAM,EAAO;AAEjC,SAAO;OAIP,QAFA,EAAO,KAAK,EAAO,GACnB,EAAO,KAAK,EAAO,GACZ;;AASX,SAAgB,GAAkB,GAAyB,GAAgC;AAGzF,QAFA,EAAO,KAAK,EAAO,GACnB,EAAO,KAAK,EAAO,GACZ;;AAGT,SAAgB,EAAa,GAAU,GAAkB,IAAgC,SAAS;CAChG,IAAM,IAAsB,MAAc,UAAU,MAAM,KACpD,IAA2B,MAAc,UAAU,MAAM;AAE/D,CADA,EAAI,KAAa,GACjB,EAAI,MAAM,KAAY,EAAI,MAAM;;AAGlC,SAAgB,EAAa,GAAgB,GAAe;AAC1D,GAAa,GAAK,GAAO,QAAQ;;AAGnC,SAAgB,EAAc,GAAgB,GAAgB;AAC5D,GAAa,GAAK,GAAQ,SAAS;;AAGrC,SAAgB,GAAY,GAAgB,GAAwB,IAAgC,SAAS;CAC3G,IAAI;AAOJ,CANA,AAGE,IAHG,GAAe,SAAU,GAAe,SAC5B;EAAE,GAAI,EAAc;EAAO,GAAI,EAAc;EAAQ,GAErD,EAAiB,EAAkB,EAGhD,MAAc,WAChB,EAAa,GAAK,EAAa,EAAE,EAC7B,EAAI,SAAS,EAAa,KAC5B,EAAc,GAAK,EAAa,EAAE,KAGpC,EAAc,GAAK,EAAa,EAAE,EAC9B,EAAI,QAAQ,EAAa,KAC3B,EAAa,GAAK,EAAa,EAAE;;;;ACxGvC,IAAa,KACX,OAAO,SAAW,MACd,OAAO,mBAAmB,KACzB,OAAO,cACN,OAAO,WACL,yIACD,CAAC,UACJ,IAKO,IACX,OAAO,SAAW,MACd,kBAAkB,UAAU,UAAU,iBAAiB,KAAK,WAAW,iBAAiB,IACxF,IAOO,KAAW,GAAkB,KAC7B,KAAY,GAAkB,QAAQ,QACtC,KAAQ,GAAkB,MAAM;;;AC1B7C,SAAgB,GAAO,GAAiB,GAAyB;AAG/D,QAFA,EAAK,KAAK,EAAM,GAChB,EAAK,KAAK,EAAM,GACT;;AAQT,SAAgB,GAAO,GAAiB,GAAuB;AAK7D,QAJI,MAAW,KAAA,MACb,IAAS,IAAI,GAAO,GAEtB,EAAO,IAAI,EAAK,IAAI,EAAK,QAAQ,IAAK,EAAK,IAAI,EAAK,SAAS,GAAI,EAC1D;;AAQT,SAAgB,GAAM,GAAiB,GAA0B;AAK/D,QAJA,EAAK,KAAK,GACV,EAAK,KAAK,GACV,EAAK,SAAS,GACd,EAAK,UAAU,GACR;;AAQT,SAAgB,GAAK,GAAiB,GAA2B;AAK/D,QAJI,MAAW,KAAA,MACb,IAAS,IAAI,GAAO,GAEtB,EAAO,IAAI,EAAK,OAAO,EAAK,OAAO,EAC5B;;;;AC1CT,SAAgB,GAAa,GAAa,GAA8C;CACtF,IAAM,oBAAc,IAAI,KAAQ;AAChC,MAAK,IAAM,KAAQ,EACjB,CAAI,EAAe,EAAK,IACtB,EAAY,IAAI,EAAK;AAGzB,QAAO;;AAGT,SAAgB,GAAsB,GAA4B;AAChE,QAAO,GAAK,QAAQ,CAAC,MAAM,CAAC;;AAQ9B,SAAgB,GAAe,GAA4B;CACzD,IAAI;AACJ,MAAK,IAAM,KAAQ,EACjB,KAAc;AAEhB,QAAO;;;;AC5BT,SAAgB,GAAyB,GAAY,GAA2B;CAC9E,IAAM,IAAU,EAAkB,YAAY,EAAK,MAAM,EAAK,MAAM,EAC9D,IAAQ,EAAQ,OAChB,IAAa,EAAQ,YACrB,IAAW,EAAK,QAAQ,IAAI,EAAM,EAAE,OAAO,EAAE,MAAM,CAAC,EAEtD,IAAe,GACf,IAAc,UAEd,IAAe;AACnB,MAAK,IAAI,IAAI,GAAG,IAAI,EAAM,QAAQ,KAAK;EACrC,IAAM,IAAW,EAAM;AACvB,OAAK,IAAI,IAAI,GAAG,KAAK,EAAS,QAAQ,KAAK;GACzC,IAAM,IAAU,EAAS,UAAU,GAAG,EAAE,EAElC,IADc,EAAkB,YAAY,GAAS,EAAK,MAAM,CAC5C,OACpB,IAAQ,IAAI,GACZ,IAAW,KAAK,MAAM,IAAQ,EAAS,GAAG,IAAQ,EAAS,EAAE;AACnE,GAAI,IAAW,MACb,IAAc,GACd,IAAe,IAAe;;AAGlC,OAAgB,EAAS;;AAG3B,QAAO;;;;AC3BT,IAAa,KAAkB,SAClB,KAAsB,UCA7B,KAAQ;AASd,SAAgB,KAAW;CACzB,IAAM,IAAQ,KAAK,GAAM,QAAQ,GAAQ,gBAAgB,GAAY;AACrE,SAAQ,IACN,GACA,qCACA,mBACA,8CACD;;;;AClBH,SAAgB,KAAa;AAC3B,KAAI,OAAO,WAAa,IACtB;CAGF,IAAM,IAAgB,SAAS,cAAc,SAAS;AAGtD,CAFW,EAAc,WAAW,QAAQ,IAAI,EAAc,WAAW,qBAAqB,IAG5F,QAAQ,MAAM,uCAAuC;;;;ACCzD,SAAgB,GAAsD,GAAiB;AACrF,QAAO,KAAa;;AAGtB,SAAgB,GACd,GACA,GACA,IAA6B,IAC1B;AAIH,QAHI,MACF,IAAU;EAAE,GAAG;EAAoB,GAAG;EAAS,GAE1C;;AAGT,SAAgB,GAAmD,GAAgB;AACjF,QAAO,KAAY,EAAE;;;;ACVvB,SAAgB,GAGd,GAAyD;AACzD,QAAO;EAAE,OAAO,EAAO;EAAO,OAAQ,EAAO,SAAS,EAAE;EAAQ;;;;ACpBlE,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,OAAA,QACA,EAAA,OAAA,QACA,EAAA,MAAA,OACA,EAAA,SAAA,UACA,EAAA,QAAA,SACA,EAAA,UAAA,YACA,EAAA,WAAA,aACA,EAAA,aAAA,eACA,EAAA,cAAA;KACD,EAaY,KAA+C;CAC1D,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CAClB,EAAkB;CACnB;;;AC/BD,SAAgB,GACd,GACA,GACA,GACoB;AACpB,QAAO,KAAa,EAAE;;;;ACuBxB,IAAM,KAAU,KACV,KAAkB;AA+BxB,SAAS,KAAoB;AAC3B,KAAI;AAIF,SAHK,WAAmB,OAAO,UAAU;SAInC;AACN,SAAO;;;AAIX,SAAS,KAA6B;AACpC,KAAI;AACF,SAA8C;SACxC;AACN,SAAO;;;AAIX,IAAM,KAAgB;AAOtB,SAAS,KAAyC;CAChD,IAAM,IAAI,YACJ,IAA8B,EAAE,UAAU,EAAE;AA4ClD,QA1CM,EAAM,gBAAgB,QAC1B,EAAM,uBAAO,IAAI,KAA2B,IAE1C,OAAO,EAAM,cAAe,YAAY,EAAM,eAAe,UAC/D,EAAM,aAAa,EAAE,GAEjB,EAAM,4BAA4B,QACtC,EAAM,mCAAmB,IAAI,KAAiC,GAE1D,EAAM,uBAAuB,QACjC,EAAM,8BAAc,IAAI,KAAa,GAGnC,OAAO,EAAM,SAAU,eACzB,EAAM,SAAS,MAAuC;EACpD,IAAM,IAAY,EAAM,kBAClB,IAAY,EAAM;AAIxB,MAAI,KAAM,EAAU,IAAI,EAAG,CACzB,QAAO,QAAQ,QAAQ,EAAM,KAAK,IAAI,EAAG,CAAE;AAG7C,MAAI,CAAC,KAAM,EAAU,OAAO,GAAG;GAC7B,IAAM,IAAe,EAAU,QAAQ,CAAC,MAAM,CAAC;AAC/C,UAAO,QAAQ,QAAQ,EAAM,KAAK,IAAI,EAAa,CAAE;;EAEvD,IAAM,IAAM,KAAM,IACd,IAAQ,EAAU,IAAI,EAAI;AAC9B,MAAI,CAAC,GAAO;GACV,IAAI,GACE,IAAU,IAAI,SAAuB,MAAQ;AACjD,QAAU;KACV;AAEF,GADA,IAAQ;IAAE;IAAS;IAAS,EAC5B,EAAU,IAAI,GAAK,EAAM;;AAE3B,SAAO,EAAM;KAIV;;AAUT,SAAgB,KAA2B;AACzC,KAAmB;;AAGrB,SAAS,GAAQ,GAA2B;AAC1C,QAAQ,EAAI,QAAQ,MAAiB;;AAGvC,SAAS,GAAgB,GAAqC;CAC5D,IAAM,IAAQ,GAAQ,EAAI,EACpB,IAA4B,EAAE,EAChC,GACE,IAA4F,EAAE,EAE9F,KAAQ,MAA8B;AAE1C,EADA,EAAI,KAAK,EAAM,EACX,EAAI,SAAS,MACf,EAAI,OAAO,GAAG,EAAI,SAAS,GAAQ;IAIjC,UAA2B,IAAc,GAAa,GAAG,KAAA,GAEzD,KAAgB,MAAmB;AACnC,QAAQ,WAAW,EAGvB,MAAK,IAAI,IAAI,EAAQ,SAAS,GAAG,KAAK,GAAG,KAAK;GAC5C,IAAI,IAAU;AACd,OAAI;AACF,QAAU,EAAQ,GAAG,UAAU,EAAM;WAC/B;AACN,QAAU;;AAEZ,OAAI,GAAS;IACX,IAAM,CAAC,KAAS,EAAQ,OAAO,GAAG,EAAE;AACpC,MAAM,QAAQ,EAAM;;;IAKpB,IAA2B;EAC/B;EACA,IAAI,MAAM;AACR,UAAO;;EAET,OAAO,GAAc,GAAgB;AACnC,KAAI,WAAW,GAAa,EAAK;;EAEnC,aAAa;AACX,UAAO,OAAO,EAAI,cAAc;;EAElC;EACA,oBAAoB,GAAmB;AACrC,OAAc;;EAEhB,mBAAmB,GAAgB;AAEjC,GADA,EAAK;IAAE,GAAG,KAAK,KAAK;IAAE,MAAM;IAAS,MAAM;IAAO,CAAC,EACnD,EAAa,EAAM;;EAErB,QAAQ,GAAwC,GAA+B;GAE7E,IAAM,IAAU,GAAU;AAC1B,OAAI;AACF,QAAI,EAAU,EAAQ,CACpB,QAAO,QAAQ,QAAQ,EAAQ;WAE3B;AAGR,UAAO,IAAI,SAAkB,GAAS,MAAW;IAC/C,IAAI,GACE,IAAQ;KACZ;KACA,UAAU,MAAe;AAIvB,MAHI,KACF,aAAa,EAAM,EAErB,EAAQ,EAAE;;KAEb;AAED,IADA,EAAQ,KAAK,EAAM,EACf,GAAM,aAAa,SACrB,IAAQ,iBAAiB;KACvB,IAAM,IAAM,EAAQ,QAAQ,EAAM;AAIlC,KAHI,KAAO,KACT,EAAQ,OAAO,GAAK,EAAE,EAExB,EAAO,gBAAI,MAAM,2BAA2B,EAAK,UAAU,IAAI,CAAC;OAC/D,EAAK,UAAU;KAEpB;;EAEL,EAIK,IAAU,EAAI,UAA0B,UAAU;AAWxD,QAVI,MACF,EAAQ,oBAAoB,SAAS,MAAW;AAE9C,EADA,EAAK;GAAE,GAAG,KAAK,KAAK;GAAE,MAAM;GAAU,MAAM,OAAO,EAAO,GAAG;GAAE,MAAM,EAAO;GAAM,CAAC,EACnF,EAAa,GAAU,CAAC;GACxB,EACF,EAAQ,uBAAuB,SAAS,MAAY;AAClD,IAAK;GAAE,GAAG,KAAK,KAAK;GAAE,MAAM;GAAW,MAAM,OAAO,EAAQ;GAAE,CAAC;GAC/D,GAGG;;AAYT,SAAgB,GAAiB,GAAyB;CACxD,IAAM,IAAQ,IAAmB,EAC3B,IAAK,GAAQ,EAAI;AAKvB,KAJA,EAAM,KAAK,IAAI,GAAI,EAAI,EACvB,EAAM,MAAM,GAEc,IAAU,IAAI,EAAI,QAAQ,eAAe,MAAQ,IAAmB,EACvE;EACrB,IAAM,IAAS,GAAgB,EAAI;AAElC,EADD,EAAM,WAAW,KAAM,GACtB,EAAoB,aAAa;;;AAQtC,SAAgB,GAAiB,GAAyB;CACxD,IAAM,IAAQ,IAAmB,EAC3B,IAAK,GAAQ,EAAI;AACtB,GAAM,YAA4B,IAAI,EAAG;CAC1C,IAAM,IAAY,EAAM,kBAElB,IAAU,EAAU,IAAI,EAAG;AACjC,CAAI,MACF,EAAQ,QAAQ,EAAI,EACpB,EAAU,OAAO,EAAG;CAEtB,IAAM,IAAa,EAAU,IAAI,GAAc;AAC/C,CAAI,MACF,EAAW,QAAQ,EAAI,EACvB,EAAU,OAAO,GAAc;;;;AC3NnC,IAAa,KAA4B;AAEzC,SAAgB,GAAgB,GAAY;CAC1C,IAAM,IAAY,SAAS,cAAc,MAAM;AAG/C,QAFA,EAAU,aAAa,MAAM,EAAG,EAChC,SAAS,KAAK,YAAY,EAAU,EAC7B;;AAGT,eAAsB,KAAgB;AACpC,QAAO,IAAI,SAAS,MAAY;AAC9B,EAAI,SAAS,eAAe,cAAc,SAAS,eAAe,gBAChE,EAAQ,GAAK,GAEb,SAAS,iBAAiB,0BAA0B;AAClD,KAAQ,GAAK;IACb;GAEJ;;AAiDJ,eAAsB,GACpB,IAA6B,EAAE,IAAI,oBAAoB,EACvD,IAA4C,IAC5C,IAAiB,IACH;AAGd,CAFA,MAAM,IAAe,EACrB,IAAY,EACR,KACF,IAAU;CAGZ,IAAI,IAAyB;AAW7B,KAVI,OAAO,KAAe,YACxB,IAAK,SAAS,eAAe,EAAW,EACxC,AACE,MAAK,GAAgB,EAAW,IAEzB,aAAsB,cAC/B,IAAK,IACI,MAAe,WACxB,IAAK,SAAS,OAEZ,CAAC,EAEH,OAAU,MACR,sJACD;AAgBH,CAdI,EAAO,sBACT,EAAO,WAAW,IAGhB,EAAO,cACT,EAAO,SAAS;EAEd,YAAY;EACZ,aAAa;EACb,wBAAwB;EACxB,UAAU;EACX,GAGH,EAAO,YAAY;CAEnB,IAAM,IAAW,KADQ,EAAO,eAAe,IACR;AAyBvC,QAxBA,MAAM,EAAS,WAAW,GAAQ,EAAG,EAEjC,EAAO,cACT,EAAS,MAAM,SAAS;EACtB,UAAU;EACV,OAAO;EACP,QAAQ;EACT,GAKH,MAAM,EAAS,iBAAiB,EAGhC,GAAiB,EAAoC,EAI/C,WAAmB,OAAO,oBAC9B,GAAiB,EAAoC,EAIhD;;;;AC5KT,IAAa,KAAb,cAA0C,EAAU;CAIlD,YAAY,GAAe;AAEzB,EADA,OAAO,EACP,KAAK,QAAS,KAAU,EAAE;;GChCjB,KAAiE,CAAC,cAAc,WAAW,EAElG,KAAyC;CAAE,YAAY;CAAM,UAAU;CAAG,EAkBnE,KAAb,cAAuC,GAAoD;;qCAEpD;;CAOrC,YAAY,IAA2C,EAAE,EAAE;AAOzD,EANA,MAAM,EAAO,mBATiB,IAAI,GAAQ,EAU1C,KAAK,WAAW;GAAE,GAAG;GAAe,GAAG;GAAQ,EAE/C,EAAe,KAAK,EAEpB,KAAK,GAAG,SAAS,KAAK,OAAO,EAC7B,KAAK,GAAG,WAAW,KAAK,SAAS;;CAMnC,IAAW,MAA+B;AACxC,SAAO,EAAY,aAAa;;CAMlC,OAAc,GAA0B;CAQxC,OAAc,GAAa;CAO3B,QAAe;CAEf,QAAQ,GAAgC;AAKtC,EAJI,KAAK,SAAS,cAChB,KAAK,IAAI,OAAO,OAAO,KAAK,QAAQ,KAAK,EAE3C,KAAK,UAAU,MAAM,EACrB,MAAM,QAAQ,EAAQ;;CAGxB,UAAiB;CAIjB,SAAiB;AAIf,EAHI,KAAK,SAAS,cAChB,KAAK,IAAI,OAAO,IAAI,KAAK,QAAQ,MAAM,KAAK,SAAS,SAAS,EAEhE,KAAK,OAAO;;CAGd,WAAmB;AAIjB,EAHI,KAAK,SAAS,cAChB,KAAK,IAAI,OAAO,OAAO,KAAK,QAAQ,KAAK,EAE3C,KAAK,SAAS;;GCkBL,KAAb,cAAyC,EAA4B;CA2BnE,IAAW,mBAA2B;AACpC,SAAO,KAAK,qBAAqB,WAAW,KAAK;;CAEnD,IAAW,iBAAiB,GAAe;AACzC,OAAK,oBAAoB;;CAG3B,cAAc;EACZ,MAAM;GAAE,YAAY;GAAM,YAAY;GAAM,UAAU;GAAW,CAAC,0BAjCjC;;CAwDnC,IAAI,SAAsB;AACxB,SAAO,KAAK;;CAGd,IAAI,OAAO,GAAoB;AAC7B,OAAK,UAAU;;CAiBjB,MAAa,aAA4B;CAWzC,QAA6B;AAC3B,SAAO,QAAQ,SAAS;;CAW1B,OAA4B;AAC1B,SAAO,QAAQ,SAAS;;CAe1B,MAAa,QAAuB;CAapC,OAAc,GAAiB;CAY/B,OAAc,GAAmB;CAajC,UAAiB;AAEf,EADA,KAAK,IAAI,OAAO,OAAO,KAAK,OAAO,EACnC,MAAM,QAAQ,EAAE,UAAU,IAAM,CAAC;;CAUnC,QAAe,GAA2B;CAU1C,SAAgB,GAA2B;GC/RhC,KAAb,cAAqC,EAAU;CAM7C,IAAI,SAAkB;AACpB,SAAO,KAAK;;CAGd,IAAI,OAAO,GAAgB;AACzB,OAAK,UAAU;;CAKjB,IAAI,WAAmB;AACrB,SAAO,KAAK;;CAGd,IAAI,SAAS,GAAe;AAC1B,OAAK,YAAY;;CAGnB,YAAY,IAAsB,IAAO;AAOvC,EANA,MAAM;GAAE,YAAY;GAAM,YAAY;GAAO,UAAU;GAAO,CAAC,qBAxBnC,mBAGH,IAuBrB,KACF,KAAK,IAAI,OAAO,IAAI,KAAK,QAAQ,EAGnC,KAAK,oBACH,KAAK,IAAI,OAAO,YAAY,QAAQ,KAAK,gBAAgB,EACzD,KAAK,IAAI,OAAO,eAAe,QAAQ,KAAK,mBAAmB,EAC/D,KAAK,IAAI,OAAO,eAAe,QAAQ,KAAK,mBAAmB,CAChE;;CAIH,MAAa,aAA4B;AACvC,SAAO,QAAQ,SAAS;;CAG1B,OAAc,GAAkB;CAIhC,UAAuB;AAKrB,EAJA,KAAK,IAAI,OAAO,OAAO,KAAK,QAAQ,EACpC,KAAK,cAAc,IACnB,KAAK,UAAU,IACf,KAAK,YAAY,GACjB,MAAM,SAAS;;CAQjB,MAAa,QAAsB;AACjC,SAAO,QAAQ,SAAS;;CAQ1B,MAAa,OAAqB;AAChC,SAAO,QAAQ,SAAS;;CAG1B,kBAA4B;CAI5B,mBAA6B,GAAkB;AAE7C,OAAK,YAAY;;CAGnB,qBAA+B;CAM/B,QAAgB,GAAgB;AAC9B,EAAI,KAAK,UAAU,KAAK,eACtB,KAAK,OAAO,EAAO;;GCtGZ,KAAb,cAAyB,EAAS;CAChC,YAAY,GAA+B;AACzC,QAAM,OAAO,KAAQ,WAAW,EAAO,IAAI,EAAI,GAAG,EAAI;EACtD,IAAM,IAAS,KAAK,gBAAgB;AACpC,OAAK,MAAM,KAAK,EAAO,IAAI,EAAO,SAAS,IAAI,EAAO,IAAI,EAAO,UAAU,EAAE;;GCA7E;AAEJ,SAAgB,EAAmB,GAAY,GAAa;AAC1D,MAAK,IAAM,KAAO,EAChB,KAAI;AACD,IAAe,KAAO,EAAM;UACtB,GAAG;AACV,IAAO,KAAK,0BAA0B,KAAO,EAAE;;;AAKrD,SAAgB,IAAkB;AAChC,KAAI,CAAC,IAAc;EACjB,IAAM,IAAM,IAAI,GAAU;AAW1B,EAVA,EAAI,KAAK,GAAG,GAAG,KAAK,IAAI,EACxB,EAAI,KAAK,EAAE,OAAO,UAAU,CAAC,EAC7B,EAAI,OAAO;GAAE,OAAO;GAAU,OAAO;GAAG,WAAW;GAAG,CAAC,EAEvD,EAAI,OAAO,GAAG,EAAE,EAChB,EAAI,OAAO,KAAK,IAAI,EACpB,EAAI,OAAO,KAAK,EAAE,EAClB,EAAI,OAAO,GAAG,IAAI,EAClB,EAAI,OAAO;GAAE,OAAO;GAAU,OAAO;GAAG,WAAW;GAAK,CAAC,EACzD,KAAe,EAAY,aAAa,CAAC,SAAS,gBAAgB,EAAI,EACtE,EAAI,SAAS;;AAEf,QAAO;;AAGT,SAAgB,EAAe,GAAwC;CACrE,IAAI,GACE,IAAQ,GAAO,OACf,IAAgB,GAChB,IAAQ,GAAO;AACrB,KAAI,aAAiB,EACnB,KAAU;UACD,CAAC,KAAS,GAAO,WAAW,EACrC,CAAI,EAAO,MAAM,IAAI,EAAc,GACjC,IAAU,EAAO,IAAI,EAAc,GAC1B,EAAO,IAAI,EAAc,GAClC,IAAU,EAAO,IAAI,EAAc,CAAC,WAEpC,EAAO,MAAM,aAAY,IAAQ,gCAA+B,EAChE,IAAU,GAAiB;UAIxB,EAAO,IAAI,EAAM,EAIf;EACL,IAAM,IAA2B,EAAO,IAAI,EAAM,EAC5C,IAAW,EAAY;AAC7B,MAAI,MAAa,KAAA,EAEf,KAAI,EAAS,eAAe,EAAc,CACxC,KAAU,EAAS;WACV,EAAY,iBAAiB,KAAA,KAAa,EAAY,aAAa,SAAS,GAAG;AACxF,QAAK,IAAM,KAAe,EAAY,aAEpC,KAAI,EAAY,aAAa,KAAA,KAAa,EAAY,SAAS,eAAe,EAAc,EAAE;AAC5F,QAAU,EAAY,SAAS;AAC/B;;AAGJ,GAAI,MAAY,KAAA,MACd,EAAO,MACL,aAAY,IAAQ,uCAAqC,IAAQ,gCAClE,EACD,IAAU,GAAiB;QAI7B,CADA,EAAO,MAAM,aAAY,IAAQ,uCAAqC,IAAQ,IAAI,EAClF,IAAU,GAAiB;MAI7B,CADA,EAAO,MAAM,mBAAkB,IAAQ,iCAAgC,EACvE,IAAU,GAAiB;OA5B7B,QADA,EAAO,MAAM,mBAAkB,IAAQ,gCAA+B,EAC/D,GAAiB;AAgC5B,QAAO,KAAW,IAAI,IAAQ,CAAC;;AAGjC,SAAgB,EAAgB,GAA+B,GAAa;CAC1E,IAAM,IAAM,EAAiB,EAAM,UAAU,IAAO,EAAM,GAAG,EAAM,EAAE;AAErE,CADA,EAAO,IAAI,EAAI,GACf,EAAO,IAAI,EAAI;;AAGjB,SAAgB,EAAa,GAA4B,GAAa;AACpE,KAAI,CAAC,EACH;AAEF,KAAI,EAAM,UAAU,KAAA,GAAW;AAC7B,MAAI,EAAM,WAAW,KAAA,KAAa,EAAM,WAAW,KAAA,EACjD;AAKF,EAHI,EAAM,WAAW,KAAA,MACnB,EAAM,SAAS,IAEb,EAAM,WAAW,KAAA,MACnB,EAAM,SAAS;;CAGnB,IAAM,IAAQ,EAAiB,EAAM,OAAO,IAAO,EAAM,QAAQ,EAAM,OAAO;AAC9E,GAAO,MAAM,IAAI,EAAM,GAAG,EAAM,EAAE;;AAGpC,SAAgB,GAAc,GAA+B,GAAa;AACxE,KAAI,MAAW,KAAA,GAAW;EACxB,IAAM,IAAc,EAAiB,EAAO;AAC5C,IAAO,OAAO,IAAI,EAAY,GAAG,EAAY,EAAE;;;AAInD,SAAgB,EAAa,GAA8B,GAAa;AACtE,KAAI,MAAU,KAAA,GAAW;EACvB,IAAM,IAAa,EAAiB,EAAM;AAC1C,IAAO,MAAM,IAAI,EAAW,GAAG,EAAW,EAAE;;;;;ACjHhD,IAAa,KAAb,MAAa,UAAuB,GAAmB;CAgBrD,YAAY,GAAiD;EAE3D,IAAM,IAAa,GAAQ,cAAc,EAAE,EACrC,IAAuB,GAAQ,aAAa,OAAO,KAAK,EAAW,CAAC,IACpE,IAAmB,EAAW,IAC9B,IAAe,GAAQ,OACvB,IAAuB,GAAQ,iBAAiB,IAChD,IAAiB,GAAQ,SACzB,IAAoB,GAAQ,cAAc;AAuBhD,EArBA,MACE,EAAe,0BACb,GACA,GACA,GACA,GACA,GACA,EACD,EACD,GAAQ,eAAe,GACxB,EApBmB,KAAA,SAAA,4BAf0C,IAAI,GAAQ,0BACrC,IAAI,GAAQ,yBACb,IAAI,GAAQ,yBACZ,IAAI,GAAQ,6BACR,IAAI,GAAQ,gCACT,IAAI,GAAQ,8BACnB,mBA2CT,uBAkBI,IA/B/B,EAAe,KAAK,EACpB,KAAK,eAAe,GACpB,KAAK,uBAAuB,GAC5B,KAAK,iBAAiB,GACtB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB,KAAK,mBAAmB,GAChD,KAAK,WAAW,GAAQ,YAAY,IACpC,KAAK,OAAO,GAAQ,QAAQ,IAC5B,KAAK,eAAe,GAAQ,gBAAgB,IAC5C,KAAK,iBAAiB,KAAK,wBAAwB,GAAQ,kBAAkB,GAC7E,KAAK,GAAG,SAAS,KAAK,OAAO;;CAK/B,IAAI,SAAkB;AACpB,SAAO,KAAK;;CAGd,IAAI,OAAO,GAAgB;AACzB,OAAK,UAAU;;CAGjB,IAAI,QAAgB;AAClB,SAAO,KAAK;;CAGd,IAAI,MAAM,GAAe;AACvB,OAAK,iBAAiB,KAAK,wBAAwB;;CAKrD,IAAI,aAAsB;AACxB,SAAO,KAAK;;CAGd,OAAO,0BACL,GACA,GACA,IAAuB,IACvB,IAA6C,KAAA,GAC7C,GACA,GACW;EACX,IAAM,IAAsB,EAAE,EAC1B,IAAQ,IACN,IAAQ,GAAO,SAAS;AAC9B,MAAI,GAAO,YAAY,GAAG;GACxB,IAAM,IAAM,GAAO,cAAc,KAAqB;AACtD,QAAK,IAAI,IAAI,GAAK,IAAI,IAAM,GAAO,WAAW,IAE5C,CADA,IAAQ,GAAG,IAAuB,GAAO,iBAAiB,IAAgB,GAAoB,GAAG,GAAO,WAAW,EAAe,IAClI,EAAS,KACP,EAAe;IACb;IACA;IACD,CAAC,CACH;QAIH,CADA,IAAQ,GAAG,IAAuB,GAAO,iBAAiB,KAC1D,EAAS,KACP,EAAe;GACb;GACA;GACD,CAAC,CACH;AAEH,SAAO;;CAGT,UAAU;AAER,EADA,KAAK,cAAc,CAAC,KAAK,aACrB,KAAK,cACP,KAAK,aAAa,GAAG,KAAK,iBAAiB,UAAU,GAErD,KAAK,aAAa,KAAK,iBAAiB,MAAM,WAAW,CAAC,GAAG;;CAIjE,aAAa,GAAuB,IAAoB,IAAM;AAC5D,MAAI,CAAC,KAAK,YAAY,IAAI,EAAc,CACtC,OAAU,MAAM,aAAa,EAAc,iBAAiB;AAG9D,EADA,KAAK,WAAW,KAAK,YAAY,IAAI,EAAc,EACnD,KAAK,mBAAmB;EACxB,IAAM,IAAY,KAAK,QAAQ,aAAa,EAAc,MAAM,WAAW,CAAC,KAAK;AAOjF,EANI,IACF,KAAK,iBAAiB,IAEtB,KAAK,iBAAiB,KAAK,uBAE7B,KAAK,kBAAkB,KAAK,EAAc,EACtC,KACF,KAAK,MAAM;;CAIf,OAAO;AAEL,EADA,MAAM,MAAM,EACZ,KAAK,kBAAkB,MAAM;;CAG/B,OAAO;AAEL,EADA,MAAM,MAAM,EACZ,KAAK,iBAAiB,MAAM;;CAG9B,gBAAgB;EACd,IAAM,IAAQ,GAAgB,KAAK,aAAa,KAAK,iBAAiB,IAAI,GAAiB,KAAK,YAAY;AAC5G,EAAI,KACF,KAAK,aAAa,EAAM,GAAG;;CAI/B,oBAAoB;EAClB,IAAM,IAAQ,GAAoB,KAAK,aAAa,KAAK,iBAAiB,IAAI,GAAgB,KAAK,YAAY;AAC/G,EAAI,KACF,KAAK,aAAa,EAAM,GAAG;;CAI/B,OAAO,GAAgB;AACjB,OAAK,WAGT,MAAM,OAAO,EAAO;;CAGtB,sBAA8B;AAC5B,OAAK,8BAAc,IAAI,KAAK;EAC5B,IAAM,IAAa,KAAK,QAAQ,cAAc,EAAE;AAChD,MAAI,GAAY;AACd,QAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,EAAW,CACnD,MAAK,YAAY,IACf,GACA,EAAe,0BACb,GACA,GACA,KAAK,sBACL,KAAK,cACL,KAAK,eACN,CACF;AAEH,OAAI,KAAK,QAAQ,WACf,MAAK,IAAM,CAAC,GAAK,MAAU,OAAO,QAAQ,EAAW,EAAE;IACrD,IAAM,IAAW,EAAe,0BAC9B,GACA,GACA,KAAK,sBACL,KAAK,cACL,KAAK,eACN;AAED,IADA,EAAS,SAAS,EAClB,KAAK,YAAY,IAAI,GAAG,EAAI,WAAW,EAAS;;;;CAMxD,SAAiB;AAWf,EAVA,KAAK,eAAe;AAClB,QAAK,gBAAgB,MAAM;KAE7B,KAAK,mBAAmB;AACtB,QAAK,oBAAoB,MAAM;KAEjC,KAAK,sBAAsB;AACzB,QAAK,uBAAuB,MAAM;KAGhC,KAAK,YACP,KAAK,MAAM;;GCtKJ,KAAb,cAA4B,GAA6B;CAavD,YAAY,GAAmC;AAgC7C,SA/BA,MAAM,EAAE,eAAe,IAAM,CAAC,EADb,KAAA,SAAA,iBAZH,IAAI,GAAoC,wBAChC,IAAI,GAAoC,cAE1C,eACA,mBA2CQ,qBAMA,wBAME,IAAI,EAAM,GAAG,EAAE,sBAMf,IAAI,EAAM,GAAG,EAAE,eAMvB,kBAckB,2BAaT,IAAI,EAAM,GAAG,EAAE,EApF9C,EAAe,KAAK,EAChB,MACF,KAAK,YAAY,EAAO,WACxB,KAAK,SAAS,KAAK,UAAU,EACzB,EAAO,SACT,KAAK,OAAO,EAAO,OAEjB,EAAO,SACT,KAAK,OAAO,EAAO,OAEjB,EAAO,SACT,KAAK,OAAO,EAAO,OAErB,KAAK,gBAAgB,EAAO,iBAAiB,KAAK,IAAI,KAAK,OAC3D,KAAK,iBAAiB,EAAO,kBAAkB,KAAK,IAAI,KAAK,OAC7D,KAAK,aAAa,EAAO,cAAc,KAAK,eAC5C,KAAK,cAAc,EAAO,eAAe,KAAK,gBAC9C,KAAK,OAAO,EAAO,QAAQ,KAAK,aAAa,KAAK,eAClD,KAAK,OAAO,EAAO,QAAQ,KAAK,cAAc,KAAK,iBAGrD,KAAK,aAAa,IAAI,KAAK,gBAAgB,IAAK,KAAK,iBAAiB,GAAI,EACtE,EAAO,WACT,KAAK,SAAS,EAAO,SAEvB,KAAK,QAAQ,GACb,KAAK,QAAQ,EACT,EAAO,SACT,KAAK,OAAO,EAAO,OAEd;;CAKT,IAAI,UAAmB;AACrB,SAAO,KAAK;;CAKd,IAAI,WAAmB;AACrB,SAAO,KAAK;;CAKd,IAAI,cAAqB;AACvB,SAAO,KAAK;;CAKd,IAAI,cAAqB;AACvB,SAAO,KAAK;;CAKd,IAAI,OAAe;AACjB,SAAO,KAAK;;CAGd,IAAI,KAAK,GAAe;AAEtB,MAAI,IAAQ,KAAK,IAAQ,EACvB,OAAU,MAAM,gDAAgD;AAElE,OAAK,QAAQ,KAAK,IAAI,GAAG,KAAK,IAAI,GAAO,EAAE,CAAC;;CAK9C,IAAI,SAA+B;AACjC,SAAO,KAAK;;CAGd,IAAI,OAAO,GAA6B;AAEtC,EADA,KAAK,UAAU,GACX,KAAK,WACP,KAAK,QAAQ,KAAK,QAAQ;;CAK9B,IAAI,eAAsB;AACxB,SAAO,KAAK;;CAGd,IAAI,aAAa,GAAkB;AACjC,OAAK,gBAAgB,EAAiB,GAAO,GAAK;;CAGpD,IAAI,MAAoB;AACtB,SAAO,EAAY,aAAa;;CAGlC,OAAO,GAAuB,GAAoB;AAKhD,EAJA,AACE,MAAS;GAAE,GAAG;GAAG,GAAG;GAAG,EAEzB,KAAK,eAAe,GACpB,KAAK,SAAS;;CAGhB,IAAI,GAAgB,GAAgB;EAClC,IAAI,IAAY,KAAK,MAAM,IAAI,GAC3B,IAAY,KAAK,MAAM,IAAI;AAM/B,EAHA,IAAY,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,GAAW,KAAK,KAAK,CAAC,EAC/D,IAAY,KAAK,IAAI,KAAK,MAAM,KAAK,IAAI,GAAW,KAAK,KAAK,CAAC,EAE/D,KAAK,aAAa,IAAI,GAAW,EAAU;;CAG7C,KAAK,GAAe,IAAe,IAAK;AAGtC,EAFA,KAAK,YAAY,GACjB,KAAK,WAAW,IAChB,KAAK,aAAa,IAAI,GAAO,EAAM;;CAGrC,SAAS;AAMP,EALA,KAAK,YAAY,EACb,KAAK,WACP,KAAK,QAAQ,KAAK,QAAQ,EAE5B,KAAK,eAAe,KAAK,SAAS,EAEhC,KAAK,YACL,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,aAAa,EAAE,GAAG,QAC/C,KAAK,IAAI,KAAK,MAAM,IAAI,KAAK,aAAa,EAAE,GAAG,QAE/C,KAAK,OAAO,KAAK,KAAK,EACtB,KAAK,WAAW,IAChB,KAAK,MAAM,IAAI,KAAK,aAAa,GAAG,KAAK,aAAa,EAAE,EACxD,KAAK,eAAe,KAAK,KAAK,IACrB,KAAK,YACd,KAAK,OAAO,KAAK,KAAK;;CAI1B,QAAgB,GAAuB;EAErC,IAAM,IAAiB,EAAO,mBAAmB,EAC3C,IAAiB,KAAK,QAAQ,EAAe,EAE7C,IAAe,KAAK,SAAS,IAAI,KAAK,MAAM,IAAI,KAAK,gBAAgB,GACrE,IAAe,KAAK,SAAS,IAAI,KAAK,MAAM,IAAI,KAAK,iBAAiB,GAEtE,IAAU,KAAK,aAAa,IAAI,KAAK,MAAM,GAC3C,IAAU,KAAK,aAAa,IAAI,KAAK,MAAM;AAEjD,OAAK,aAAa,KAAK,EAAe,IAAI,KAAK,MAAM,IAAI,KAAK,gBAAgB,MAAM,IAAI,KAAK,MAAM,KAAK;EAExG,IAAM,IAAQ,KAAK,gBAAgB,KAAK,MAAM,IAAI,IAAI,IAAe,KAAK,OAAO,GAC3E,IAAQ,KAAK,aAAa,KAAK,gBAAgB,KAAK,MAAM,IAAI,IAAI,IAAe,KAAK,OAAO;AAQnG,EANI,KAAK,aAAa,IAAI,IACxB,KAAK,aAAa,IAAI,IACb,KAAK,aAAa,IAAI,MAC/B,KAAK,aAAa,IAAI,IAGxB,KAAK,aAAa,KAAK,EAAe,IAAI,KAAK,MAAM,IAAI,KAAK,iBAAiB,MAAM,IAAI,KAAK,MAAM,KAAK;EAEzG,IAAM,IAAQ,KAAK,iBAAiB,KAAK,MAAM,IAAI,IAAI,IAAe,KAAK,OAAO,GAC5E,IAAQ,KAAK,cAAc,KAAK,iBAAiB,KAAK,MAAM,IAAI,IAAI,IAAe,KAAK,OAAO;AAErG,EAAI,KAAK,aAAa,IAAI,IACxB,KAAK,aAAa,IAAI,IACb,KAAK,aAAa,IAAI,MAC/B,KAAK,aAAa,IAAI;;CAI1B,aAAqB;EACnB,IAAM,IAAgB,KAAK,MAAM,GAC3B,IAAgB,KAAK,MAAM,GAE3B,IAAqB,IAAgB,KAAK,aAAa,KAAK,aAAa,IAAI,IAC7E,IAAqB,IAAgB,KAAK,aAAa,KAAK,aAAa,IAAI;AAEnF,OAAK,MAAM,IAAI,KAAK,IAAI,GAAG,EAAmB,EAAE,KAAK,IAAI,GAAG,EAAmB,CAAC;;CAGlF,eAAuB,IAAoB,IAAO;AAChD,MAAI,KAAK,OAAO,KAAK,CAAC,GAAU;GAE9B,IAAM,IAAgB,KAAK,MAAM,GAC3B,IAAgB,KAAK,MAAM,GAG3B,IAAqB,IAAgB,KAAK,QAAQ,KAAK,aAAa,IAAI,IACxE,IAAqB,IAAgB,KAAK,QAAQ,KAAK,aAAa,IAAI;AAG9E,QAAK,MAAM,IAAI,GAAoB,EAAmB;QAEtD,MAAK,MAAM,IAAI,KAAK,aAAa,GAAG,KAAK,aAAa,EAAE;AAG1D,OAAK,SAAS,IAAI,KAAK,gBAAgB,GAAG,KAAK,iBAAiB,EAAE;;GAIzD,KAAb,MAA8B;CAI5B,YACE,GACA,GACA;AAgBA,EAlBO,KAAA,SAAA,GACA,KAAA,kBAAA,mBALmB,mCACoB,MAM9C,EAAe,KAAK,EACpB,KAAK,SAAS,GACd,KAAK,kBAAkB,GACvB,KAAK,IAAI,SAAS,WAAW,CAAC,QAAQ,KAAK,cAAc,EAIzD,KAAK,gBAAgB,GAAG,eAAe,KAAK,cAAc,KAAK,KAAK,CAAC,EACrE,KAAK,gBAAgB,GAAG,eAAe,KAAK,cAAc,KAAK,KAAK,CAAC,EACrE,KAAK,IAAI,MAAM,GAAG,aAAa,KAAK,YAAY,KAAK,KAAK,CAAC,EAC3D,KAAK,IAAI,MAAM,GAAG,oBAAoB,KAAK,YAAY,KAAK,KAAK,CAAC,EAGlE,KAAK,gBAAgB,GAAG,cAAc,KAAK,cAAc,KAAK,KAAK,CAAC,EACpE,KAAK,gBAAgB,GAAG,aAAa,KAAK,cAAc,KAAK,KAAK,CAAC,EACnE,KAAK,gBAAgB,GAAG,YAAY,KAAK,YAAY,KAAK,KAAK,CAAC;;CAGlE,IAAI,MAAoB;AACtB,SAAO,EAAY,aAAa;;CAGlC,UAAU;AAIR,EAFA,KAAK,gBAAgB,oBAAoB,EACzC,KAAK,IAAI,MAAM,IAAI,aAAa,KAAK,YAAY,KAAK,KAAK,CAAC,EAC5D,KAAK,IAAI,MAAM,IAAI,oBAAoB,KAAK,YAAY,KAAK,KAAK,CAAC;;CAGrE,cAAsB,GAA6B;EACjD,IACM,IAAa;AAEnB,UAAQ,EAAO,MAAM,KAArB;GACE,KAAK;AACH,SAAK,OAAO,IAAI,GAAG,IAAU;AAC7B;GACF,KAAK;AACH,SAAK,OAAO,IAAI,GAAG,GAAS;AAC5B;GACF,KAAK;AACH,SAAK,OAAO,IAAI,KAAW,EAAE;AAC7B;GACF,KAAK;AACH,SAAK,OAAO,IAAI,IAAU,EAAE;AAC5B;GACF,KAAK;AACH,SAAK,OAAO,KAAK,EAAW;AAC5B;GACF,KAAK;AACH,SAAK,OAAO,KAAK,IAAI,EAAW;AAChC;;;CAIN,cAAsB,GAAgC;AAEpD,EADA,KAAK,WAAW,IAChB,KAAK,0BAA0B,KAAK,iBAAiB,EAAM;;CAG7D,cAAsB,GAAgC;AACpD,MAAI,CAAC,KAAK,YAAY,CAAC,KAAK,wBAAyB;EAErD,IAAM,IAAkB,KAAK,iBAAiB,EAAM,EAC9C,IAAS,EAAgB,IAAI,KAAK,wBAAwB,GAC1D,IAAS,EAAgB,IAAI,KAAK,wBAAwB;AAGhE,EADA,KAAK,OAAO,IAAI,GAAQ,EAAO,EAC/B,KAAK,0BAA0B;;CAGjC,cAAsB;AAEpB,EADA,KAAK,WAAW,IAChB,KAAK,0BAA0B;;CAGjC,iBAAyB,GAAuC;AAI5D,SAHE,aAAiB,aACZ,IAAI,EAAM,EAAM,QAAQ,GAAG,SAAS,EAAM,QAAQ,GAAG,QAAQ,GAE7D,IAAI,EAAM,EAAM,SAAS,EAAM,QAAQ;;GCvW9C,KAAkB,EAAY,GAAS,CAAC,EAqBjC,KAAb,cAAoE,GAAgB;CAgBlF,IAAI,MAA+B;AACjC,SAAO,EAAY,aAAa;;CAGlC,IAAI,iBAA2B;AAC7B,SAAO,KAAK,MAAM,MAAM,KAAK,aAAa,WAAW,KAAK,MAAM,EAAE,KAAK;;CAGzE,IAAI,eAAe;AACjB,SAAO,KAAK,MAAM,MAAM,WAAW,EAAE;;CAGvC,IAAI,uBAAuB;AAIzB,SAHI,KAAK,eACA,KAAK,aAAa,YAEpB;;CAGT,YAAmB,GAA6B;AAE9C,EADA,OAAO,6BAhCkD,IAAI,GAAQ,0BACf,IAAI,GAAQ,8BACR,IAAI,GAAQ,4BACd,IAAI,GAAQ,wBAChB,IAAI,GAAQ,0BACI,IAAI,GAAQ,kBAE3B,IAAI,GAAQ,mBACX,IAAI,GAAQ,EAyBlE,EAAe,KAAK;EACpB,IAAI,IAAO,GAAO,MACd,IAA0D;AAC9D,MAAI,OAAO,KAAS,UAAU;GAG5B,IAAI,IAAM,EAAK,MAAM,GAAG;AAMxB,GALI,MAAQ,WAAW,MAAQ,UAC7B,IAAM,UAEN,IAAO,EAAK,UAAU,GAAG,EAAK,SAAS,EAAE,EAE3C,IAAY;IAAE,UAAU,IAAO;IAAK,OAAO,IAAO;IAAU;;AAyB9D,EAvBA,KAAK,QAAS,OAAe,MAAM,KAAK,EAAU,EAClD,KAAK,IAAI,SAAS,KAAK,MAAM,EAEzB,MACE,EAAM,eAAe,KAAA,MAAW,KAAK,MAAM,aAAa,EAAM,aAC9D,EAAM,iBAAe,KAAK,aAAa,EAAM,eAAyB,EAAM,MAAM,EAAM,cAAc,EAAE,GAG9G,KAAK,oBAAoB,KAAK,IAAI,QAAQ,eAAe,CAAC,QAAQ,KAAK,YAAY,CAAC,EAEhF,GAAO,UACT,KAAK,OAAO,EAGd,KAAK,iBAAiB;GACpB,OAAO,KAAK;GACZ,WAAW,KAAK;GAChB,SAAS,KAAK;GACd,KAAK,KAAK;GACV,OAAO,KAAK;GACZ,UAAU,KAAK;GAChB,EAED,KAAK,MAAM,MAAM,YAAY,KAAK,eAAe;;CAGnD,UAAU;AAER,EADA,KAAK,MAAM,MAAM,eAAe,KAAK,eAAe,EACpD,MAAM,SAAS;;CAGjB,oBAAoB,IAAqB,GAAW;AAClD,SAAQ,KAAK,MAAM,MAAM,WAAW,EAAW,EAAE,WAAW,QAAoB;;CAGlF,aAAa,GAAc,IAAO,IAAO,IAAqB,GAAG;AAC/D,OAAK,MAAM,MAAM,aAAa,GAAY,GAAM,EAAK;;CAGvD,QAAQ;AAON,EANA,KAAK,SAAS,IACd,KAAK,MAAM,aAAa,IAEpB,KAAK,iBACP,KAAK,aAAa,YAAY,IAEhC,KAAK,SAAS,KAAK,KAAK,aAAa;;CAGvC,SAAS;AAMP,EALA,KAAK,SAAS,IACd,KAAK,MAAM,aAAa,IACpB,KAAK,iBACP,KAAK,aAAa,YAAY,IAEhC,KAAK,UAAU,KAAK,KAAK,aAAa;;CAGxC,cAAc;AACZ,EAAI,KAAK,SACP,KAAK,QAAQ,GAEb,KAAK,OAAO;;CAKhB,yBAAmC,GAAmB;AACpD,OAAK,oBAAoB,KAAK,EAAM;;CAGtC,sBAAgC,GAAmB;AACjD,OAAK,iBAAiB,KAAK,EAAM;;CAGnC,0BAAoC,GAAmB;AACrD,OAAK,qBAAqB,KAAK,EAAM;;CAGvC,wBAAkC,GAAmB;AACnD,OAAK,mBAAmB,KAAK,EAAM;;CAGrC,oBAA8B,GAAmB;AAC/C,OAAK,eAAe,KAAK,EAAM;;CAGjC,sBAAgC,GAAmB,GAAc;AAC/D,OAAK,iBAAiB,KAAK,GAAO,EAAM;;;;;ACzJ5C,SAAgB,EAAgD,GAA8C;AAC5G,QAAO,cAAc,EAA2B;EAqB9C,YAAY,GAAG,GAAa;AAM1B,GALA,MAAM,GAAG,EAAK,mBApBJ,qBACA,wBACG,oBACJ,qBAEE,0BAC6C,iCACxC,mCACD,uDACwB,kCACpB,mBAEX,IAAI,GAAyC,mBAC3C,IAAI,GAAyC,oBAC5C,IAAI,GAAyC,gBACjD,IAAI,GAAyC,yBAEnB,IAIjC,KAAK,YAAY,UACjB,KAAK,GAAG,aAAa,KAAK,aAAa,EACvC,KAAK,GAAG,aAAa,KAAK,aAAa,EACvC,KAAK,GAAG,SAAS,KAAK,aAAa,EACnC,KAAK,GAAG,OAAO,KAAK,aAAa;;EAGnC,IAAI,MAAM;AACR,UAAO,EAAY,aAAa;;EAGlC,QAAe,GAAgC;AAK7C,GAJA,KAAK,IAAI,aAAa,KAAK,aAAa,EACxC,KAAK,IAAI,aAAa,KAAK,aAAa,EACxC,KAAK,IAAI,SAAS,KAAK,aAAa,EACpC,KAAK,IAAI,OAAO,KAAK,aAAa,EAClC,MAAM,QAAQ,EAAQ;;EAGxB,UAAiB;AACf,GAAI,KAAK,IAAI,MAAM,UAEjB,KAAK,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC;;EAIrD,OAAc;AACZ,GAAK,KAAK,aACR,OAAO,oBAAoB,SAAS,KAAK,aAAa,KAAK,KAAK,CAAC;;EAIrE,WAAkB;AAIhB,GAHK,KAAK,aACR,OAAO,oBAAoB,SAAS,KAAK,aAAa,KAAK,KAAK,CAAC,EAE/D,KAAK,IAAI,MAAM,UAEjB,KAAK,KAAK,cAAc,EAAE,MAAM,cAAc,CAAC;;EAInD,QAAe;EAEf,mBAA0B;AACxB,UAAO;;EAGT,eAAsB;AACpB,UAAO,KAAK,WAAW;;EAGzB,eAAwC;AACtC,UAAO,CAAC,KAAK,cAAc,CAAC,OAAO,KAAK,cAAc,CAAC,OAAO;;EAIhE,aAAuB,GAAgB;AACrC,QAAK,IAAI,MAAM,SAAS,KAAK;;EAG/B,aAAuB,GAAmB;AACxC,QAAK,WAAW,eAAe,EAAE;;EAGnC,aAAuB,GAAmB;AAExC,GADA,KAAK,WAAW,SAAS,EAAE,EAC3B,KAAK,OAAO;;EAId,aAAuB,GAAmB;EAE1C,WAAmB,GAAc,GAAmB;AAC9C,QAAK,mBAAmB,EAAE,SAG9B,KAAK,kBAAkB,IACvB,KAAK,KAAK,GAAM,EAAE,SAAM,CAAC,EACzB,KAAK,kBAAkB;;;;AAK7B,EAAU,UAAU;;;ACnGpB,SAAgB,GAAkD,GAAgD;AAChH,QAAO,cAAc,EAA6B;EAGhD,YAAY,GAAG,GAAa;AAG1B,GAFA,MAAM,GAAG,EAAK,kCAHiD,IAAI,KAAK,EAIxE,KAAK,cAAc,KAAK,YAAY,KAAK,KAAK,EAC9C,KAAK,YAAY;;EASnB,cAAqB,GAAiC;AACpD,OAAI,CAAC,KAAK,SAAS,IAAI,EAAU,EAAE;IACjC,IAAM,IAAS,IAAI,GAAyC;AAE5D,IADA,KAAK,SAAS,IAAI,GAAW,EAAO,EACpC,KAAK,GAAG,GAAW,KAAK,YAAY;;AAEtC,UAAO,KAAK,SAAS,IAAI,EAAU;;EAGrC,QAAe,GAA+B;AAC5C,QAAK,IAAM,KAAa,KAAK,SAAS,MAAM,CAC1C,MAAK,IAAI,GAAW,KAAK,YAAY;AAGvC,GADA,KAAK,SAAS,OAAO,EACrB,MAAM,QAAQ,EAAQ;;EAUxB,YAAoB,GAAuB;GACzC,IAAM,IAAa,EAAM,MACnB,IAAS,KAAK,SAAS,IAAI,EAAW;AAE5C,GAAI,KACF,EAAO,KAAK,EAAM;;;;;;ACS1B,IAAa,KAA2C;CACtD;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD,EAGK,KAAU,EAAU,GAAY,EAAY,GAAS,CAAC,CAAC,CAAC,EAOjD,KAAb,cAA4B,GAA2B;CA8BrD,IAAI,YAAY;AACd,SAAO,KAAK;;CAOd,YAAY,GAA+B;AAgDzC,EA/CA,OAAO,gBArCO,IAAI,GAAoB,cAC1B,IAAI,GAAoB,qBACjB,IAAI,GAAoB,eAC9B,IAAI,GAAoB,gBACvB,IAAI,GAAoB,iBACvB,IAAI,GAAoB,mBACtB,IAAI,GAAoB,oBACvB,IAAI,GAAoB,yBACnB,IAAI,GAA+B,mBACzC,IAAI,GAAoB,0CAUW,IAAI,KAAK,8BACvB,IAmBtC,EAAe,KAAK,EAEpB,KAAK,SAAS,OAAO,OACnB;GACE,IAAI;GACJ,UAAU,EAAE,SAAS,IAAI;GACzB,OAAO,KAAA;GACP,SAAS;GACT,QAAQ;GACR,gBAAgB;GACjB,EACD,EACD,EAED,KAAK,KAAK,KAAK,OAAO,IAGlB,EAAO,WAAW,KAAA,IAGpB,KAAK,SAAS,KAFd,KAAK,SAAS,EAAO,QAMvB,KAAK,OAAO,KAAK,IAAI,OAAO;GAC1B,OAAO,KAAK,OAAO,SAAS;GAC5B,OAAO,KAAK,OAAO,SAAS,KAAA;GAC7B,CAAC,EAEF,KAAK,SAAS,KAAK,OAAO,QAC1B,KAAK,UAAU,EAAO,YAAY,IAE9B,KAAK,QAAQ,MAAM,oBAAoB,eACzC,KAAK,SAAS,EAAE,iBAAiB,YAAY,EACzC,KAAK,IAAI,SAAS,UACpB,KAAK,IAAI,SAAS,OAAO,OAAO,KAAK,GAIrC,KAAK,OAAO,aACd,KAAK,SAAS,KAAK,OAAO,UAAU,EAKtC,KAAK,oBACH,KAAK,cAAc,cAAc,CAAC,QAAQ,KAAK,mBAAmB,GAAG,EACrE,KAAK,cAAc,aAAa,CAAC,QAAQ,KAAK,kBAAkB,GAAG,EACnE,KAAK,cAAc,YAAY,CAAC,QAAQ,KAAK,iBAAiB,GAAG,EACjE,KAAK,cAAc,QAAQ,CAAC,QAAQ,KAAK,aAAa,GAAG,EACzD,KAAK,cAAc,MAAM,CAAC,QAAQ,KAAK,aAAa,GAAG,EACvD,KAAK,cAAc,cAAc,CAAC,QAAQ,KAAK,mBAAmB,GAAG,CACtE;;CAUH,IAAW,QAAQ,GAAkB;AAC/B,OAAK,aAAa,MAGtB,KAAK,WAAW,GAChB,KAAK,SAAS,KAAK,WAAW,KAAK,OAAO,SAAS,KAAK,OAAO,gBAC/D,KAAK,eAAe,GAChB,KAAK,YACP,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GACpC,OAAO,KAAK,OAAO,SAAS;GAC5B,OAAO,KAAK,OAAO,SAAS,KAAA;GAC7B,CAAC,EACF,KAAK,UAAU,MAAM,KAErB,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GACpC,OAAO,KAAK,OAAO,SAAS,YAAY,KAAK,OAAO,SAAS;GAC7D,OAAO,KAAK,OAAO,SAAS,KAAA;GAC7B,CAAC,EACF,KAAK,WAAW,MAAM;;CAI1B,SACE,GACG;AACH,MAAI,aAAkB,KAAQ,aAAkB,MAAY,aAAkB,EAG5E,CAFA,EAAO,OAAO,IAAI,IAAK,GAAI,EAC3B,KAAK,aAAa,KAAK,IAAI,SAAS,EAAO,EAC3C,KAAK,WAAW,SAAS;MAGzB,SADA,EAAO,SAAS,IACR,EAAO,MAAf;GACE,KAAK;AACH,SAAK,aAAa,KAAK,IAAI,WAAW;KAAE,GAAG;KAAQ,QAAQ;KAAO,CAAC;AACnE;GACF,KAAK;AACH,SAAK,aAAa,KAAK,IAAI,SAAS;KAAE,GAAG;KAAQ,QAAQ;KAAO,CAAC;AACjE;GACF;AACE,SAAK,aAAa,KAAK,IAAI,KAAK;KAAE,GAAG;KAAQ,QAAQ;KAAO,CAAC;AAC7D;;AAMN,SAFA,KAAK,eAAe,EAEb,KAAK;;CAGd,gBAAuB;AACrB,EAAI,KAAK,cACP,KAAK,WAAW,SAAS,IAAI,KAAK,KAAK,QAAQ,IAAK,KAAK,KAAK,SAAS,GAAI;;CAI/E,IAAW,UAAU;AACnB,SAAO,KAAK;;CAGd,IAAI,MAAoB;AACtB,SAAO,EAAY,aAAa;;CAGlC,QAAQ,GAA0B;AAEhC,EADA,KAAK,UAAU,MAAM,EACrB,MAAM,QAAQ,EAAQ;;CAGxB,WAAW;AAGT,EAFA,MAAM,UAAU,EAChB,KAAK,SAAS,IACd,KAAK,SAAS;;CAGhB,OAAO;AAGL,EAFA,MAAM,MAAM,EACZ,KAAK,SAAS,IACd,KAAK,SAAS;;CAGhB,eAAsB;AACpB,SAAO,KAAK,KAAK,WAAW,CAAC,OAAO;;CAGtC,kBAAkB,GAAoB,GAAsB;AAE1D,EADA,KAAK,iBAAiB,IAAI,GAAY,EAAS,EAC/C,KAAK,uBAAuB;;CAG9B,qBAAqB,GAAoB;AACvC,OAAK,iBAAiB,OAAO,EAAW;;CAG1C,WAAW,GAA4B,GAAuB;AAS5D,EARA,KAAK,OAAO,SAAS,KAAa,GAC9B,MAAc,cAChB,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GACpC,OAAO,KAAK,OAAO,SAAS;GAC5B,OAAO,KAAK,OAAO;GACpB,CAAC,GAGJ,KAAK,eAAe;;CAMtB,oBAA8B;AACvB,OAAK,aAGV,AACE,KAAK,WAAS,IAEZ,MAAK,WAGT,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GACpC,OAAO,KAAK,OAAO,SAAS,SAAS,KAAK,OAAO,SAAS;GAC1D,OAAO,KAAK,OAAO;GACpB,CAAC,EACF,KAAK,OAAO,MAAM,EACd,KAAK,OAAO,QAAQ,SACjB,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,OAAO,OAAO,MAAM,EAEvD,KAAK,OAAO,SAAS,SACvB,KAAK,UAAU,KAAK,OAAO,QAAQ,MAAM;;CAO7C,mBAA6B;AAC3B,OAAK,SAAS,IACT,KAAK,aAGN,KAAK,WAGT,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GAAE,OAAO,KAAK,OAAO,SAAS;GAAS,OAAO,KAAK,OAAO;GAAO,CAAC,EAEpG,KAAK,OAAO,QAAQ,OACjB,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,OAAO,KAAK,MAAM,EAEzD,KAAK,MAAM,MAAM;;CAMnB,kBAA4B,GAAmB;AACzC,GAAC,KAAK,YAAY,CAAC,KAAK,aAGxB,CAAC,KAAK,UAAU,KAAK,eAAe,KAAA,MACtC,KAAK,aAAc,EAA4B,WAE/C,OAAO,oBAAoB,aAAa,KAAK,uBAAuB,EACpE,KAAK,IAAI,oBAAoB,KAAK,uBAAuB,EAEzD,OAAO,iBAAiB,aAAa,KAAK,uBAAuB,EACjE,KAAK,GAAG,oBAAoB,KAAK,uBAAuB,EAExD,KAAK,SAAS,IACd,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GACpC,OAAO,KAAK,OAAO,SAAS,UAAU,KAAK,OAAO,SAAS,SAAS,KAAK,OAAO,SAAS;GACzF,OAAO,KAAK,OAAO;GACpB,CAAC,EACF,KAAK,OAAO,MAAM,EACd,KAAK,OAAO,QAAQ,QACjB,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,OAAO,MAAM,MAAM,EAEtD,KAAK,OAAO,SAAS,QACvB,KAAK,UAAU,KAAK,OAAO,QAAQ,KAAK;;CAQ9C,gBAA0B,GAAmB;AACvC,GAAC,KAAK,YAAY,CAAC,KAAK,UAAW,EAA4B,cAAc,KAAK,eAGtF,OAAO,oBAAoB,aAAa,KAAK,uBAAuB,EAEpE,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GAAE,OAAO,KAAK,OAAO,SAAS;GAAS,OAAO,KAAK,OAAO;GAAO,CAAC,EACxG,KAAK,KAAK,MAAM,EAEhB,KAAK,aAAa,KAAA;;CAGpB,cAAwB;AACjB,OAAK,aAGV,KAAK,SAAS,IACd,KAAK,QAAQ,MAAM,EACf,KAAK,OAAO,QAAQ,SACjB,KAAK,IAAI,MAAM,KAAK,KAAK,OAAO,OAAO,OAAO,MAAM,EAEvD,KAAK,OAAO,SAAS,SACvB,KAAK,UAAU,KAAK,OAAO,QAAQ,MAAM;;CAO7C,uBAAiC,GAAyC;AACpE,GAAC,KAAK,YAAY,EAAE,cAAc,KAAK,eAG3C,OAAO,oBAAoB,aAAa,KAAK,uBAAuB,EACpE,KAAK,IAAI,oBAAoB,KAAK,uBAAuB,EACzD,KAAK,KAAK,UAAU,KAAK,KAAK,QAAQ;GAAE,OAAO,KAAK,OAAO,SAAS;GAAS,OAAO,KAAK,OAAO;GAAO,CAAC,EACxG,KAAK,SAAS,IACd,KAAK,SAAS,IACd,KAAK,YAAY,MAAM,EAEvB,KAAK,aAAa,KAAA;;CAGpB,UAAkB,GAAgC;AAChD,EAAI,OAAO,KAAW,aACf,GAAQ,IAER,EAAO,KAAK,WACf,EAAO,KAAK,SAAS,OAEvB,KAAK,IAAI,OAAO,EAAO,IAAI,EAAO,KAAK;;CAI3C,wBAAgC;AAE9B,EAAI,CAAC,KAAK,wBAAwB,KAAK,iBAAiB,OAAO,KAC7D,KAAK,uBAAuB,IAC5B,KAAK,IAAI,OAAO,IAAI,KAAK,uBAAuB,KAEhD,KAAK,IAAI,OAAO,OAAO,KAAK,uBAAuB,EACnD,KAAK,uBAAuB;;CAIhC,yBAAiC;AAC/B,EAAI,KAAK,UACP,KAAK,iBAAiB,SAAS,MAAa;AAC1C,MAAU;IACV;;GCnbF,KAAiB,EAAY,GAAS,CAAC;AAE7C,SAAgB,GAAO,GAAkD;AACvE,QAAO,aAAiB,KAAQ,aAAiB;;AAWnD,IAAa,KAAyD;CACpE;CACA;CACA;CACA;CACD,EAgBY,KAAb,cAAmC,GAAe;CAMhD,YAAY,IAAuC,EAAE,EAAE;AAGrD,MAFA,OAAO,0BANiB,IAAI,GAAoB,wBAER,yBACP,MAK7B,CAAC,KAAK,IAAI,OAAO,UACnB,OAAU,MAAM,yEAAyE;AAsB3F,EAnBA,EAAe,KAAK,EAEpB,KAAK,SAAS;GACZ,oBAAoB;GACpB,GAAG;GACJ,EAGD,KAAK,SAAS,KAAK,aAAa,EAAO,EAGvC,KAAK,GAAG,SAAS,KAAK,YAAY,EAClC,KAAK,GAAG,cAAc,KAAK,iBAAiB,EAC5C,KAAK,GAAG,gBAAgB,KAAK,mBAAmB,EAE5C,KAAK,OAAO,iBACd,KAAK,IAAI,SAAS,QAAQ,KAAK,aAAa,EAG1C,KAAK,OAAO,UAAU,QAAQ,KAAK,OAAO,UAC3C,KAAK,OAAO,OAAyB,GAAG,UAAU,KAAK,mBAAmB;;CAI/E,aAAqB,GAAsF;AACzG,EAAI,GAAQ,WAAW,OACrB,EAAO,SAAS,EAAE;EAEpB,IAAM,IAAyD,EAAE,GAAI,GAAQ,UAAU,EAAE,EAAG;AAU5F,SARI,KAAK,OAAO,iBACd,EAAO,QAAQ,KAAK,IAAI,KAAK,OAC7B,EAAO,SAAS,KAAK,IAAI,KAAK,UACrB,KAAK,OAAO,WACrB,EAAO,QAAQ,KAAK,OAAO,OAAO,OAClC,EAAO,SAAS,KAAK,OAAO,OAAO,SAG9B;;CAGT,cAAsB;AACpB,OAAK,cAAc;;CAGrB,gBAAwB;AACtB,OAAK,IAAI,OAAO,QAAQ,KAAK,aAAa;;CAG5C,iBAAyB,GAAsB;AAe7C,EAdI,KAAK,OAAO,uBACR,EAAM,SAGD,GAAO,EAAM,IAAI,CAAC,EAAM,QAAQ,OAAO,WAIhD,EAAM,SAAS,EAAE,QAAQ,IAAM,IAL/B,EAAM,SAAS,EAAE,QAAQ,IAAM,GASnC,EAAU,WAAW,EAAM,EAC3B,EAAM,GAAG,UAAU,KAAK,cAAc,EACtC,KAAK,eAAe;;CAGtB,mBAA2B,GAAsB;AAG/C,EAFA,EAAM,IAAI,UAAU,KAAK,cAAc,EACvC,EAAU,aAAa,EAAM,EAC7B,KAAK,eAAe;;CAGtB,eAAuB;AAOrB,EANI,KAAK,OAAO,kBACd,KAAK,SAAS;GACZ,OAAO,KAAK,IAAI,KAAK;GACrB,QAAQ,KAAK,IAAI,KAAK;GACvB,GAEH,KAAK,eAAe;;CAGtB,qBAA6B;AACtB,OAAK,OAAO,WACjB,KAAK,SAAS;GACZ,OAAO,KAAK,OAAO,OAAO;GAC1B,QAAQ,KAAK,OAAO,OAAO;GAC5B,EACD,KAAK,eAAe;;CAGtB,eAAsB;AAChB,OAAK,aAAa,CAAC,KAAK,UAAU,CAAC,KAAK,KAAK,SAAS,WAC1D,KAAK,IAAI,SAAS,OAAO,OAAO,KAAK,EACrC,KAAK,iBAAiB,MAAM,EACxB,KAAK,OAAO,SACd,KAAK,WAAW;;CAIpB,IAAW,MAA+B;AACxC,SAAO,EAAY,aAAa;;CAMlC,UAAiB,GAAsD;AAErE,EADA,KAAK,SAAS,GACd,KAAK,eAAe;;CAItB,IAAI,MAAc;AAChB,SAAQ,KAAK,QAAQ,OAAO,OAAkB;;CAGhD,IAAI,IAAI,GAAe;AAErB,EADA,KAAK,SAAS,EAAE,KAAK,GAAO,EAC5B,KAAK,eAAe;;CAGtB,IAAI,WAAqB;AACvB,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,SAAS,GAAiB;AAE5B,EADA,KAAK,SAAS,EAAE,UAAU,GAAO,EACjC,KAAK,eAAe;;CAGtB,IAAI,gBAA+B;AACjC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,cAAc,GAAsB;AAEtC,EADA,KAAK,SAAS,EAAE,eAAe,GAAO,EACtC,KAAK,eAAe;;CAGtB,IAAI,aAAyB;AAC3B,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,WAAW,GAAmB;AAEhC,EADA,KAAK,SAAS,EAAE,YAAY,GAAO,EACnC,KAAK,eAAe;;CAGtB,IAAI,iBAAiC;AACnC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,eAAe,GAAuB;AAExC,EADA,KAAK,SAAS,EAAE,gBAAgB,GAAO,EACvC,KAAK,eAAe;;CAGtB,IAAI,OAAkD;AACpD,SAAO;GACL,OAAO,KAAK,QAAQ,OAAO;GAC3B,QAAQ,KAAK,QAAQ,OAAO;GAC7B;;CAGH,IAAI,KAAK,GAAyF;AAQhG,EAPI,MAAM,QAAQ,EAAK,KACrB,IAAO;GAAE,OAAO,EAAK;GAAI,QAAQ,EAAK;GAAI,IAExC,OAAO,KAAS,YAAY,OAAO,KAAS,cAC9C,IAAO;GAAE,OAAO;GAAM,QAAQ;GAAM,GAEtC,KAAK,SAAS,EAAE,GAAG,GAAM,EACzB,KAAK,eAAe;;CAGtB,IAAI,cAA0B;AAC5B,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,YAAY,GAAmB;AAEjC,EADA,KAAK,SAAS,EAAE,UAAO,EACvB,KAAK,eAAe;;CAGtB,IAAI,eAA2B;AAC7B,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,aAAa,GAAoB;AAEnC,EADA,KAAK,SAAS,EAAE,WAAQ,EACxB,KAAK,eAAe;;CAItB,IAAI,UAAmC;AACrC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,QAAQ,GAAoB;AAE9B,EADA,KAAK,SAAS,EAAE,SAAS,GAAO,EAChC,KAAK,eAAe;;CAGtB,IAAI,aAAsC;AACxC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,WAAW,GAAoB;AAEjC,EADA,KAAK,SAAS,EAAE,YAAY,GAAO,EACnC,KAAK,eAAe;;CAGtB,IAAI,eAAwC;AAC1C,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,aAAa,GAAoB;AAEnC,EADA,KAAK,SAAS,EAAE,cAAc,GAAO,EACrC,KAAK,eAAe;;CAGtB,IAAI,gBAAyC;AAC3C,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,cAAc,GAAoB;AAEpC,EADA,KAAK,SAAS,EAAE,eAAe,GAAO,EACtC,KAAK,eAAe;;CAGtB,IAAI,cAAuC;AACzC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,YAAY,GAAoB;AAElC,EADA,KAAK,SAAS,EAAE,aAAa,GAAO,EACpC,KAAK,eAAe;;CAItB,IAAI,SAAkC;AACpC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,OAAO,GAAoB;AAE7B,EADA,KAAK,SAAS,EAAE,QAAQ,GAAO,EAC/B,KAAK,eAAe;;CAGtB,IAAI,YAAqC;AACvC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,UAAU,GAAoB;AAEhC,EADA,KAAK,SAAS,EAAE,WAAW,GAAO,EAClC,KAAK,eAAe;;CAGtB,IAAI,cAAuC;AACzC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,YAAY,GAAoB;AAElC,EADA,KAAK,SAAS,EAAE,aAAa,GAAO,EACpC,KAAK,eAAe;;CAGtB,IAAI,eAAwC;AAC1C,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,aAAa,GAAoB;AAEnC,EADA,KAAK,SAAS,EAAE,cAAc,GAAO,EACrC,KAAK,eAAe;;CAGtB,IAAI,aAAsC;AACxC,SAAO,KAAK,QAAQ,OAAO;;CAG7B,IAAI,WAAW,GAAoB;AAEjC,EADA,KAAK,SAAS,EAAE,YAAY,GAAO,EACnC,KAAK,eAAe;;CAItB,IAAI,QAAiB;AACnB,SAAO,KAAK,OAAO,SAAS;;CAG9B,IAAI,MAAM,GAAgB;AAExB,EADA,KAAK,OAAO,QAAQ,GAChB,KAEF,EADY,iBAAiB,KAAK,OACf,KAAK,SAAS,iBAAiB,EAAY,OAAO,EACrE,KAAK,WAAW,KAEhB,EAAgB,iBAAiB,KAAK,MAAM,EACxC,KAAK,kBACP,KAAK,eAAe,OAAO,EAEzB,KAAK,gBACP,KAAK,YAAY,UAAU;;CAKjC,YAAoB;AAyBlB,GAvBI,CAAC,KAAK,kBAAkB,KAAK,eAAe,WAAW,UACzD,AACE,KAAK,mBAAiB,GAAoB,GAAG,KAAK,SAAS,gBAAgB,QAAQ,EAErF,KAAK,SAAS,KAAK,eAAe,EAClC,KAAK,eAAe,SAAS,MAE3B,CAAC,KAAK,eAAe,KAAK,YAAY,WAAW,UACnD,AACE,KAAK,gBAAc,EAAiB,KAAK,SAAS,iBAAiB,EAAY,OAAO,EAExF,KAAK,SAAS,KAAK,YAAY,EAC/B,KAAK,YAAY,SAAS,KAI5B,KAAK,YAAY,OAAO,KAAK,SAAS,iBACtC,KAAK,YAAY,UAAU,IAG3B,KAAK,cAAc,KAAK,gBAAgB,KAAK,SAAS,SAAS,EAAE,EACjE,KAAK,cAAc,KAAK,aAAa,KAAK,SAAS,SAAS,EAAE,EAE9D,KAAK,eAAe,OAAO;EAE3B,IAAM,IAAiB,KAAK,QAAQ;AACpC,MAAI,CAAC,EAAgB;EAErB,IAAM,IAAI,EAAe,OACnB,IAAI,EAAe,QACnB,IAAa,KAAK,QAAQ,OAAO,iBAA4B,OAC7D,IAAO,KAAK,QAAQ,OAAO,OAAkB;AAGnD,OAAK,eACF,KAAK,GAAG,GAAG,GAAG,EAAE,CAChB,OAAO;GAAE,OAAO;GAAG,OAAO,EAAY;GAAQ,OAAO,EAAW;GAAQ,WAAW;GAAM,CAAC;EAG7F,IAAM,IAAM,KAAK,QAAQ,OAAO,cAAyB,GACnD,IAAM,KAAK,QAAQ,OAAO,gBAA2B,GACrD,IAAM,KAAK,QAAQ,OAAO,iBAA4B,GACtD,IAAM,KAAK,QAAQ,OAAO,eAA0B;AAU1D,EATI,IAAK,KACP,KAAK,eAAe,KAAK,GAAG,GAAG,GAAG,EAAG,CAAC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAEpG,IAAK,KACP,KAAK,eAAe,KAAK,GAAG,IAAI,GAAI,GAAG,EAAG,CAAC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAEzG,IAAK,KACP,KAAK,eAAe,KAAK,GAAG,GAAI,GAAI,IAAI,IAAK,EAAG,CAAC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAE/G,IAAK,KACP,KAAK,eACF,KAAK,IAAI,GAAI,GAAI,GAAI,IAAI,IAAK,EAAG,CACjC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC;EAIrE,IAAM,IAAW,KAAK,IAAI,GAAG,GAAG,GAAG,EAC7B,IAAK,IAAI,GACT,IAAK,IAAI,GACT,IAAQ,MAAc,SAAS,MAAc;AACnD,MAAI,GAAO;GACT,IAAM,IAAM,MAAc,QAAQ,IAAI,IAChC,IAAS,IAAM,IAAM,IAAY,GACjC,IAAO,IAAM,IAAM,IAAY;AACrC,QAAK,eACF,OAAO,GAAQ,EAAG,CAClB,OAAO,GAAM,EAAG,CAChB,OAAO,GAAM,EAAG,CAChB,OAAO,IAAO,IAAM,GAAG,IAAK,EAAE,CAC9B,OAAO,GAAM,EAAG,CAChB,OAAO,IAAO,IAAM,GAAG,IAAK,EAAE,CAC9B,OAAO;IAAE,OAAO;IAAG,OAAO,EAAY;IAAW,OAAO;IAAK,WAAW;IAAM,CAAC;SAC7E;GACL,IAAM,IAAM,MAAc,WAAW,IAAI,IACnC,IAAS,IAAM,IAAM,IAAY,GACjC,IAAO,IAAM,IAAM,IAAY;AACrC,QAAK,eACF,OAAO,GAAI,EAAO,CAClB,OAAO,GAAI,EAAK,CAChB,OAAO,GAAI,EAAK,CAChB,OAAO,IAAK,GAAG,IAAO,IAAM,EAAE,CAC9B,OAAO,GAAI,EAAK,CAChB,OAAO,IAAK,GAAG,IAAO,IAAM,EAAE,CAC9B,OAAO;IAAE,OAAO;IAAG,OAAO,EAAY;IAAW,OAAO;IAAK,WAAW;IAAM,CAAC;;AAIpF,MAAI,IAAM,EACR,MAAK,IAAI,IAAI,GAAG,IAAI,KAAK,SAAS,SAAS,GAAG,KAAK;GACjD,IAAM,IAAQ,KAAK,SAAS;AAE5B,OADI,MAAU,KAAK,kBAAkB,MAAU,KAAK,eAChD,CAAC,EAAM,QAAQ,eAAgB;GACnC,IAAM,IAAK,EAAM,OAAO;AACxB,OAAI,GAAO;IACT,IAAM,IAAO,EAAG,OAAO,EAAG;AAC1B,SAAK,eAAe,KAAK,GAAM,GAAG,GAAK,EAAE,CAAC,KAAK;KAAE,OAAO,EAAY;KAAK,OAAO,EAAW;KAAM,CAAC;UAC7F;IACL,IAAM,IAAO,EAAG,MAAM,EAAG;AACzB,SAAK,eAAe,KAAK,GAAG,GAAM,GAAG,EAAI,CAAC,KAAK;KAAE,OAAO,EAAY;KAAK,OAAO,EAAW;KAAM,CAAC;;;AAMxG,OAAK,IAAM,KAAS,KAAK,UAAU;AAEjC,OADI,MAAU,KAAK,kBAAkB,MAAU,KAAK,eAChD,CAAC,EAAM,QAAQ,eAAgB;GACnC,IAAM,IAAK,EAAM,OAAO;AACxB,QAAK,eACF,KAAK,EAAG,MAAM,EAAG,KAAK,EAAG,OAAO,EAAG,OAAO,CAC1C,OAAO;IAAE,OAAO;IAAG,OAAO,EAAY;IAAa,OAAO;IAAK,WAAW;IAAM,CAAC;;AAItF,OAAK,YAAY,SAAS,IAAI,GAAG,EAAE;;CAGrC,UAAU;AA0BR,EAxBI,KAAK,OAAO,SACd,EAAgB,iBAAiB,KAAK,MAAM,EAE9C,AAEE,KAAK,oBADL,KAAK,eAAe,SAAS,EACP,OAExB,AAEE,KAAK,iBADL,KAAK,YAAY,SAAS,EACP,OAGrB,KAAK,IAAI,SAAS,KAAK,YAAY,EACnC,KAAK,IAAI,cAAc,KAAK,iBAAiB,EAC7C,KAAK,IAAI,gBAAgB,KAAK,mBAAmB,EAE7C,KAAK,OAAO,iBACd,KAAK,IAAI,SAAS,WAAW,KAAK,aAAa,EAG7C,KAAK,OAAO,UAAU,SAAS,KAAK,OAAO,UAC5C,KAAK,OAAO,OAAyB,IAAI,UAAU,KAAK,mBAAmB,EAG9E,MAAM,SAAS;;GCnaN,IAA2C;CACtD,MAAM;CACN,UAAU;CACV,OAAO;CACP,QAAQ;CACR,iBAAiB;CACjB,iBAAiB;CACjB,cAAc;CACd,SAAS;CACT,WAAW;CACX,WAAW;CACX,eAAe;CACf,eAAe;CACf,QAAQ;EACN,OAAO;EACP,OAAO;EACP,QAAQ;GAAE,GAAG;GAAG,GAAG;GAAG;EACvB;CACD,aAAa;EACX,MAAM;EACN,UAAU;EACV,MAAM;EACN,QAAQ;EACT;CACD,OAAO;EACL,MAAM;EACN,UAAU;EACV,UAAU;EACX;CACD,YAAY;EACV,MAAM;EACN,SAAS;EACT,SAAS;EACT,OAAO;EACR;CACF,EAEY,KAAb,cAA2B,EAAY,EAAU,CAAC;CAehD,IAAI,QAAQ,GAAgB;AAC1B,OAAK,WAAW;;CAGlB,IAAI,UAAmB;AACrB,SAAO,KAAK;;CAGd,IAAI,KAAK,GAAe;AAEtB,EADA,KAAK,YAAY,OAAO,GACxB,KAAK,WAAW;;CAGlB,YAAY,IAA+B,EAAE,EAAE;AAG7C,EAFA,OAAO,uBA5BuB,IAAI,GAAoB,kBAQ1B,IAqB5B,KAAK,SAAS;GAAE,GAAG;GAAoB,GAAG;GAAQ,EAClD,KAAK,YAAY;;CAGnB,aAA6B;AA6B3B,MA5BA,KAAK,OAAO,KAAK,IAAI,WAAW,EAE5B,KAAK,OAAO,WACd,KAAK,SAAS,KAAK,KAAK,IACrB,UAAU,CACV,UACC,KAAK,OAAO,OAAO,QAAQ,KAAK,GAChC,KAAK,OAAO,OAAO,QAAQ,KAAK,GAChC,KAAK,OAAO,OACZ,KAAK,OAAO,QACZ,KAAK,OAAO,aACb,CACA,KAAK;GACJ,OAAO,KAAK,OAAO,OAAO,SAAS;GACnC,OAAO,KAAK,OAAO,OAAO,SAAS;GACpC,CAAC,GAIN,KAAK,aAAa,KAAK,KAAK,IACzB,UAAU,CACV,UAAU,GAAG,GAAG,KAAK,OAAO,OAAQ,KAAK,OAAO,QAAS,KAAK,OAAO,aAAc,CACnF,KAAK;GACJ,OAAO,KAAK,OAAO;GACnB,OAAO,KAAK,OAAO;GACpB,CAAC,EAGA,KAAK,OAAO,MAAM;GAEpB,IAAM,IAAO,IAAI,GAAU,CACxB,UAAU,GAAG,GAAG,KAAK,OAAO,OAAQ,KAAK,OAAO,QAAS,KAAK,OAAO,aAAc,CACnF,KAAK,EAAE,OAAO,UAAU,CAAC,EAGtB,IAAY,KAAK,KAAK,IACzB,UAAU,CACV,KAAK,GAAG,GAAG,KAAK,OAAO,eAAgB,KAAK,OAAO,OAAQ,CAC3D,KAAK,EAAE,OAAO,KAAK,OAAO,WAAY,KAAK,OAAO,OAAO,CAAC;AAO7D,GAJA,EAAU,OAAO,GAGjB,KAAK,KAAK,SAAS,EAAK,EACxB,KAAK,KAAK,SAAS,EAAU;;AAI/B,EAAI,KAAK,OAAO,aAAa,QAC3B,KAAK,gBAAgB;EAIvB,IAAM,IAAc,KAAK,OAAO,OAAO,KAAK,OAAO,gBAAiB,KAAK,OAAO,UAAW,KAAK,OAAO,SACjG,IACJ,KAAK,OAAO,aAAa,QAAQ,KAAK,OAAO,YAAY,aAAa,cAClE,KAAK,OAAO,YAAY,OAAQ,KAAK,OAAO,YAAY,SAAU,IAClE,KAAK,OAAO;AAqBlB,EAnBA,KAAK,cAAc,KAAK,KAAK,IAAI,KAAK;GACpC,MAAM,KAAK,OAAO;GAClB,OAAO;IACL,GAAG,EAAmB;IACtB,GAAG,KAAK,OAAO;IACf,eAAe,KAAK,OAAO,OAAO,iBAAiB,KAAK,OAAO,QAAS,IAAc;IACvF;GACD,GAAG;GACH,GAAG,KAAK,OAAO;GAChB,CAAC,EAEF,KAAK,WAAW,EAEhB,KAAK,KAAK,MAAM,IAAI,KAAK,OAAO,QAAS,IAAK,KAAK,OAAO,SAAU,GAAI,EAExE,KAAK,KAAK,SAAS,IAAI,KAAK,OAAO,QAAS,IAAK,KAAK,OAAO,SAAU,GAAI,EAE3E,KAAK,QAAQ,GAEb,KAAK,SAAS,KAAK,KAAK;;CAG1B,iBAAiC;EAC/B,IAAM,IAAc,KAAK,OAAO,aAAa,SAAS,IAChD,IAAO,KAAK,OAAO,aAAa,QAAQ,IACxC,IAAS,KAAK,OAAO,aAAa,UAAU,GAC5C,IAAW,KAAK,OAAO,aAAa,YAAY;AAEtD,OAAK,cAAc,KAAK,KAAK,IAAI,SAC/B,IAAI,EAAY,EACd,QAAQ,WACT,CAAC,CACH;EAGD,IAAM,IAAI,MAAa,cAAc,KAAK,OAAO,QAAS,IAAO,KAAM,IAAS,IAAO,KAAM,GACvF,IAAI,IAAO,KAAM;AAKvB,EAHA,KAAK,YAAY,SAAS,IAAI,GAAG,EAAE,EAGnC,KAAK,YAAY,QAAQ,cAAc;AAChC,QAAK,MAAM;IAChB;;CAGJ,YAAyB;AACvB,UAAQ,KAAK,OAAO,WAApB;GACE,KAAK;AACH,SAAK,YAAY,OAAO,IAAI,GAAG,GAAI;AACnC;GACF,KAAK;AAEH,IADA,KAAK,YAAY,OAAO,IAAI,IAAK,GAAI,EACrC,KAAK,YAAY,IAAI,KAAK,OAAO,QAAS;AAC1C;GACF,KAAK;AACH,SAAK,YAAY,OAAO,IAAI,GAAG,GAAI;AACnC;;AAGJ,UAAQ,KAAK,OAAO,eAApB;GACE,KAAK;AACH,SAAK,YAAY,IAAI,KAAK,OAAO;AACjC;GACF,KAAK;AACH,SAAK,YAAY,IAAI,KAAK,OAAO,SAAU;AAC3C;GACF,KAAK;AACH,SAAK,YAAY,IAAI,KAAK,OAAO,SAAU,KAAK,YAAY,SAAS,KAAK,OAAO;AACjF;;;CAIN,mBAA8C;EAC5C,IAAM,IAAK,EAAK,SAAS,EAAE,QAAQ,IAAM,CAAC;AAO1C,SANA,EAAG,GAAG,MAAM;GACV,OAAO;GACP,UAAU;GACV,MAAM;GACP,CAAC,EAEK;;CAGT,mBAA8C;EAC5C,IAAM,IAAK,EAAK,SAAS,EAAE,QAAQ,IAAM,CAAC;AAO1C,SANA,EAAG,GAAG,MAAM;GACV,OAAO;GACP,UAAU;GACV,MAAM;GACP,CAAC,EAEK;;CAGT,MAAa,OAAuB;AASlC,SARA,KAAK,WAAW,KAAK,kBAAkB,EACvC,MAAM,KAAK,SAAS,MAAM,EAEtB,KAAK,OAAO,cACd,KAAK,eAAe,iBAAiB;AAC9B,QAAK,MAAM;KACf,KAAK,OAAO,SAAS,GAEnB;;CAGT,MAAa,OAAuB;AAElC,MAAI,KAAK,YAAY,KAAK,UACxB,QAAO;AAIT,EAFA,KAAK,WAAW,IAEhB,AAEE,KAAK,kBADL,aAAa,KAAK,aAAa,EACX,KAAA;AAGtB,MAAI;AAKF,GAFA,MADW,KAAK,kBAAkB,CACzB,MAAM,EAEV,KAAK,aACR,KAAK,cAAc,MAAM;WAEpB,GAAO;AAGd,GADA,QAAQ,KAAK,+BAA+B,EAAM,EAC7C,KAAK,aACR,KAAK,cAAc,MAAM;;AAI7B,SAAO;;CAGT,UAAuB;AAsBrB,EApBA,KAAK,WAAW,IAEhB,AAEE,KAAK,kBADL,aAAa,KAAK,aAAa,EACX,KAAA,IAItB,EAAK,aAAa,KAAK,EAEvB,AAEE,KAAK,cADL,KAAK,SAAS,MAAM,EACJ,KAAA,IAId,CAAC,KAAK,aAAa,CAAC,KAAK,YAC3B,KAAK,cAAc,MAAM,EAG3B,MAAM,QAAQ,EAAE,UAAU,IAAM,CAAC;;GClW/B,KAA+B;CACnC,UAAU;CACV,WAAW;CACX,SAAS;CACT,QAAQ;EAAE,GAAG;EAAI,GAAG;EAAI;CACxB,gBAAgB;CAChB,gBAAgB;CACjB,EAkCY,KAAb,cAA6B,EAAY,EAAU,CAAC;CAgBlD,IAAW,OAAe;AACxB,SAAO,KAAK,OAAO;;CAGrB,IAAI,gBAA8B;AAChC,SAAO,KAAK,OAAO,YAAY;;CAGjC,IAAI,iBAAgC;AAClC,SAAO,KAAK,OAAO,kBAAkB;;CAGvC,IAAI,UAAkB;AACpB,SAAO,KAAK,OAAO,WAAW;;CAGhC,IAAI,SAA4C;AAC9C,SAAO,KAAK,OAAO,UAAU;GAAE,GAAG;GAAI,GAAG;GAAI;;CAG/C,IAAI,YAAoB;AACtB,SAAO,KAAK,OAAO,aAAa;;CAGlC,IAAI,cAAoC;AACtC,SAAO,KAAK,sBAAsB,EAAE;;CAsDtC,YAAY,IAAiC,EAAE,EAAE,IAA2C,EAAE,EAAE;AAK9F,EAJA,MAAM,EAAE,YAAY,IAAM,CAAC,sBA9FE,IAAI,GAAgC,wBAElC,IAAI,GAAgC,4BAEhC,IAAI,GAAoB,gBAInC,EAAE,EAuF1B,KAAK,SAAS;GAAE,GAAG;GAAe,GAAG;GAAQ,EAC7C,KAAK,qBAAqB,EAAE,GAAG,GAAoB,EACnD,KAAK,YAAY,EACjB,KAAK,QAAQ;;CAGf,aAA6B;AAC3B,OAAK,YAAY,KAAK,IAAI,WAAW;;CAQvC,MAAa,KACX,IAA+B,KAAK,oBACpC,IAA4B,IACZ;AAEhB,MAAI,KAAK,QAAQ,KAAK,OAAO,WAAY;GACvC,IAAM,IAAc,KAAK,OAAO;AAIhC,GAFA,MAAM,EAAY,MAAM,EAExB,MAAM,KAAK,YAAY,EAAY;;AAGrC,EAAI,CAAC,KAAoB,KAAK,uBAC5B,IAAS;GACP,GAAG,KAAK;GACR,GAAG;GACH,OACE,KAAK,mBAAmB,SAAS,EAAO,QACpC;IAAE,GAAI,KAAK,mBAAmB,SAAS,EAAE;IAAG,GAAI,EAAO,SAAS,EAAE;IAAG,GACrE,KAAK,mBAAmB;GAC9B,YACE,KAAK,mBAAmB,cAAc,EAAO,aACzC;IAAE,GAAI,KAAK,mBAAmB,cAAc,EAAE;IAAG,GAAI,EAAO,cAAc,EAAE;IAAG,GAC/E,EAAmB;GACzB,QACE,KAAK,mBAAmB,UAAU,EAAO,SACrC;IAAE,GAAI,KAAK,mBAAmB,UAAU,EAAE;IAAG,GAAI,EAAO,UAAU,EAAE;IAAG,GACvE,KAAK,mBAAmB;GAC9B,aACE,KAAK,mBAAmB,eAAe,EAAO,cAC1C;IAAE,GAAI,KAAK,mBAAmB,eAAe,EAAE;IAAG,GAAI,EAAO,eAAe,EAAE;IAAG,GACjF,EAAmB;GAC1B;EAIH,IAAM,IAAQ,KADK,EAAO,SAAS,IACN,EAAO;AAmBpC,SAjBA,EAAM,UAAU,MAGhB,KAAK,UAAU,SAAS,EAAM,EAC9B,KAAK,OAAO,KAAK,EAAM,EACvB,KAAK,cAAc,GAAO,KAAK,OAAO,SAAS,GAAG,GAAM,EAGxD,EAAM,cAAc,kBAAkB,KAAK,YAAY,EAAM,CAAC,EAG9D,KAAK,gBAAgB,EAGrB,KAAK,aAAa,KAAK,EAAM,EAGtB,EAAM,MAAM;;CAOrB,MAAa,UAAyB;EAEpC,IAAM,IAAe,CAAC,GAAG,KAAK,OAAO;AAKrC,EAFA,MAAM,QAAQ,IAAI,EAAa,KAAK,MAAU,EAAM,MAAM,CAAC,CAAC,EAE5D,KAAK,mBAAmB,MAAM;;CAMhC,MAAa,YAA2B;AACtC,SAAO,KAAK,SAAS;;CAGvB,MAAgB,YAAY,GAA6B;EACvD,IAAM,IAAQ,KAAK,OAAO,QAAQ,EAAM;AACpC,QAAU,MAAM,EAAM,cAK1B,KAAK,OAAO,OAAO,GAAO,EAAE,EAG5B,KAAK,gBAAgB,EAGhB,EAAM,cACT,KAAK,UAAU,YAAY,EAAM,EACjC,EAAM,SAAS,GAIjB,KAAK,eAAe,KAAK,EAAM;;CAQjC,eAAsB,IAAmB,IAAM,IAAoB,IAAa;AAE1D,OAAK,OAAO,QAC7B,GAAO,MAAU,KAAS,CAAC,EAAM,cAAc,IAAW,MAAU,KAAK,OAAO,SAAS,IAAI,IAC/F,CAEW,SAAS,GAAO,MAAU;AACpC,QAAK,cAAc,GAAO,GAAO,EAAQ;IACzC;;CASJ,cAAwB,GAAc,GAAe,IAAmB,IAAY;AAElF,MAAI,CAAC,GAAO,UAAU,EAAM,UAC1B;EAGF,IAAM,EAAE,aAAU,YAAS,WAAQ,sBAAmB,KAAK,QACrD,IAAU,OAAO,KAAW,WAAW,IAAS,EAAQ,GACxD,IAAU,OAAO,KAAW,WAAW,IAAS,EAAQ,GAC1D,IAAI,KAAK,IAAI,KAAK,QAAQ,IAC1B,IAAI,KAAK,IAAI,KAAK,SAAS;AAG/B,UAAQ,GAAR;GACE,KAAK;GACL,KAAK;AAEH,IADA,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAM,EAAM,QAAQ,GAC/C,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM;AAClC;GACF,KAAK;GACL,KAAK;AAEH,IADA,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAM,GACjC,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM;AAClC;GACF,KAAK;GACL,KAAK;AAEH,IADA,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAM,EAAM,QAAQ,GAC/C,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM,EAAM,SAAS;AACjD;GACF,KAAK;GACL,KAAK;AAEH,IADA,KAAK,KAAK,IAAI,KAAK,QAAQ,KAAM,GACjC,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM,EAAM,SAAS;AACjD;GACF,KAAK;GACL,KAAK;AAEH,IADA,KAAK,CAAC,EAAM,QAAQ,IACpB,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM;AAClC;GACF,KAAK;GACL,KAAK;AAEH,IADA,KAAK,CAAC,EAAM,QAAQ,IACpB,KAAK,KAAK,IAAI,KAAK,SAAS,KAAM,EAAM,SAAS;AACjD;;AAIJ,EAAI,MAAmB,SACrB,KAAK,KAAS,EAAM,SAAS,KAE7B,KAAK,KAAS,EAAM,SAAS;AAG/B,MAAI;AAEF,GAAI,IACF,EAAK,GAAG,GAAO;IACb;IACA;IACA,UAAU,KAAM,KAAK,OAAO;IAC5B,MAAM;IACP,CAAC,GAEF,EAAM,SAAS,IAAI,GAAG,EAAE;WAEnB,GAAO;AACd,WAAQ,KAAK,4BAA4B,EAAM;;;CAOnD,SAAsB;AAEpB,EADA,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,KAAK,QAAQ,IAAK,CAAC,KAAK,IAAI,KAAK,SAAS,GAAI,EAC1E,KAAK,eAAe,GAAM;;CAG5B,UAAuB;AAQrB,EANA,KAAK,OAAO,SAAS,MAAU;AAC7B,KAAK,aAAa,EAAM;IACxB,EAEF,KAAK,SAAS,EACd,KAAK,SAAS,EAAE,EAChB,MAAM,QAAQ,EAAE,UAAU,IAAM,CAAC;;GCtUxB,KAA+C;CAC1D;CACA;CACA;CACA;CACA;CACA;CACD,EAYK,KAAuB;CAAE,KAAK;CAAG,OAAO;CAAG,QAAQ;CAAG,MAAM;CAAG;AAOrE,SAAgB,GAAwB,GAAkB,GAA4B;AACpF,QAAO;EACL,KAAK,EAAQ,MAAM,EAAS;EAC5B,OAAO,EAAQ,QAAQ,EAAS;EAChC,QAAQ,EAAQ,SAAS,EAAS;EAClC,MAAM,EAAQ,OAAO,EAAS;EAC/B;;AAGH,IAAM,KAAgB;CACpB,UAAU;CACV,YAAY;CACZ,oBAAoB;CACrB,EAEK,KAAY,EAAY,GAAS,CAAC,EAE3B,KAAb,MAAa,UAAiB,GAAU;CAetC,YAAY,GAAgC;AAG1C,MAFA,OAAO,qCAde,IAAI,KAA2C,mCACjD,IAAI,KAAmC,wBACjB,yBACP,2BACH,EAAE,+BACK,qBAEF,EAAE,yBAoPI,EAAE,yBA4FtB,GAAqB,MACrC,MAAM,eAAe,GAAY,EAAS,wBAMY,MACtD,MAAM,cAAc,EAAM,qBAMyB,GAAW,MAAsB;AAC3F,SAAU,MACR,wJAED;2BAM8C,GAAU,MAAwB;AAEjF,GADA,MAAM,cAAc,GAAO,EAAM,EACjC,KAAK,eAAe;2BAM2B,MACxC,MAAM,cAAc,EAAM,qBAMyB,MACnD,MAAM,WAAW,EAAM,EA/W1B,CAAC,KAAK,IAAI,OAAO,UACnB,OAAU,MAAM,oEAAoE;AA2CtF,EAxCA,EAAe,KAAK,EACpB,KAAK,sCAAsB,IAAI,KAAK,EACpC,KAAK,SAAS;GACZ,OAAO,EAAO,UAAU;GACxB,SAAS,EAAc,GAAQ,WAAW,EAAE;GAC5C,MAAM,EAAO,SAAS,KAAA,IAA2C;IAAE,OAAO;IAAG,QAAQ;IAAG,GAAtD,GAAgB,EAAO,KAAK;GAC9D,YAAY,EAAO,eAAe;GAClC,aAAa,EAAO,eAAe;GACnC,oBAAoB,EAAO,sBAAsB;GAClD,EAEG,EAAO,SACL,OAAO,EAAO,UAAW,YAC3B,KAAK,OAAO,SAAS,EAAO,SAE5B,KAAK,OAAO,SAAS;GAAE,GAAG;GAAe,GAAG,EAAO;GAAQ,GAG7D,KAAK,OAAO,SAAS,EAAE,GAAG,IAAe,EAGvC,KAAK,OAAO,eACd,KAAK,OAAO,OAAO,KAAK,IAAI,OAE9B,KAAK,SAAS;GACZ,OAAO,KAAK,OAAO,KAAK;GACxB,QAAQ,KAAK,OAAO,KAAK;GACzB,eAAe;GACf,gBAAgB;GAChB,GAAI,OAAO,KAAK,OAAO,UAAW,WAAW,KAAK,OAAO,SAAS,EAAE;GACrE,EAED,KAAK,GAAG,gBAAgB,KAAK,cAAc,EAC3C,KAAK,KAAK,SAAS,KAAK,OAAO,EAE/B,KAAK,oBAAoB,KAAK,IAAI,SAAS,QAAQ,KAAK,OAAO,CAAC,EAEhE,KAAK,mBAAmB,EACxB,KAAK,eAAe,EAEhB,KAAK,OAAO,SACd,EAAc,YAAY,KAAK,OAAO,KAAK,SAAS,YAAY,EAAY,YAAY;;CAI5F,gBAAwB;AACtB,OAAK,IAAI,OAAO,QAAQ,KAAK,aAAa;;CAG5C,oBAA4B;AAqC1B,EApCA,KAAK,wBAAwB,IAE7B,KAAK,SAAS,KAAK,IAAI,cAAc;GACnC,OAAO;GACP,QAAQ;IACN,OAAO;IACP,QAAQ;IACR,eAAe;IACf,gBAAgB;IAChB,YAAY;IACb;GACF,CAAC,EAGF,KAAK,YAAY,KAAK,IAAI,cAAc;GACtC,OAAO;GACP,QAAQ;IACN,OAAO;IACP,eAAe;IACf,gBAAgB;IAChB,YAAY;IACb;GACF,CAAC,EAGF,KAAK,YAAY,KAAK,IAAI,cAAc;GACtC,OAAO;GACP,QAAQ;IACN,OAAO;IACP,QAAQ;IACR,eAAe;IACf,gBAAgB;IAChB,YAAY;IACb;GACF,CAAC,EAEF,KAAK,wBAAwB;EAG7B,IAAM,IAAU,KAAK,yBACnB,KAAK,QACL;GACE,gBAAgB;GAChB,YAAY;GACZ,UAAU;GACV,YAAY;GACb,EACD,OACD,EACK,IAAY,KAAK,yBACrB,KAAK,QACL;GACE,gBAAgB;GAChB,YAAY;GACZ,UAAU;GACV,YAAY;GACb,EACD,SACD,EACK,IAAW,KAAK,yBACpB,KAAK,QACL;GACE,gBAAgB;GAChB,YAAY;GACZ,UAAU;GACV,YAAY;GACb,EACD,QACD,EAEK,IAAa,KAAK,yBACtB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,eAAe;GACf,UAAU;GACV,YAAY;GACb,EACD,OACD,EACK,IAAS,KAAK,yBAClB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,eAAe;GACf,UAAU;GACV,YAAY;GACb,EACD,SACD,EACK,IAAc,KAAK,yBACvB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,eAAe;GACf,UAAU;GACV,YAAY;GACb,EACD,QACD,EAEK,IAAa,KAAK,yBACtB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,eAAe;GACf,UAAU;GACV,YAAY;GACb,EACD,OACD,EACK,IAAe,KAAK,yBACxB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,UAAU;GACV,YAAY;GACZ,eAAe;GAChB,EACD,SACD,EACK,IAAc,KAAK,yBACvB,KAAK,WACL;GACE,gBAAgB;GAChB,YAAY;GACZ,eAAe;GACf,UAAU;GACV,YAAY;GACb,EACD,QACD;AA2BD,EAxBA,KAAK,oBAAoB,IAAI,YAAY,EAAQ,EACjD,KAAK,oBAAoB,IAAI,YAAY,EAAQ,EAEjD,KAAK,oBAAoB,IAAI,cAAc,EAAU,EACrD,KAAK,oBAAoB,IAAI,OAAO,EAAU,EAE9C,KAAK,oBAAoB,IAAI,aAAa,EAAS,EACnD,KAAK,oBAAoB,IAAI,aAAa,EAAS,EAEnD,KAAK,oBAAoB,IAAI,eAAe,EAAW,EACvD,KAAK,oBAAoB,IAAI,QAAQ,EAAW,EAChD,KAAK,oBAAoB,IAAI,eAAe,EAAW,EAEvD,KAAK,oBAAoB,IAAI,UAAU,EAAO,EAE9C,KAAK,oBAAoB,IAAI,gBAAgB,EAAY,EACzD,KAAK,oBAAoB,IAAI,SAAS,EAAY,EAClD,KAAK,oBAAoB,IAAI,gBAAgB,EAAY,EAEzD,KAAK,oBAAoB,IAAI,eAAe,EAAW,EAEvD,KAAK,oBAAoB,IAAI,iBAAiB,EAAa,EAC3D,KAAK,oBAAoB,IAAI,UAAU,EAAa,EAEpD,KAAK,oBAAoB,IAAI,gBAAgB,EAAY;;CAG3D,yBAAiC,GAAuB,GAAgC,GAA0B;EAChH,IAAM,IAAY,EAAO,IAAI,UAAU,EACrC,QAAQ;GACN,OAAO;GACP,QAAQ;GACR,GAAG;GACJ,EACF,CAAC;AAKF,SAJA,EAAU,QAAQ,GAClB,EAAU,GAAG,cAAc,KAAK,cAAc,EAC9C,EAAU,GAAG,gBAAgB,KAAK,cAAc,EAChD,EAAU,GAAG,UAAU,KAAK,cAAc,EACnC;;CAKT,IAAW,iBAAkC;AAC3C,SAAO,KAAK;;CAMd,IAAW,MAA+B;AACxC,SAAO,EAAY,aAAa;;CAGlC,UAAU;AAaR,EAVA,KAAK,wBAAwB,IAGzB,KAAK,OAAO,SACd,EAAgB,YAAY,KAAK,MAAM,EAEzC,AAEE,KAAK,oBADL,KAAK,eAAe,SAAS,EACP,OAExB,AAEE,KAAK,iBADL,KAAK,YAAY,SAAS,EACP;AAErB,OAAK,IAAM,KAAM,KAAK,cACpB,GAAG,SAAS;AAsBd,EApBA,KAAK,gBAAgB,EAAE,EAEvB,KAAK,gBAAgB,SAAS,MAAU;AACtC,KAAM,IAAI,UAAU,KAAK,cAAc;IACvC,EAEF,KAAK,SAAS,SAAS,MAAU;AAC/B,KAAM,IAAI,UAAU,KAAK,cAAc;IACvC,EAEF,KAAK,IAAI,cAAc,KAAK,cAAc,EAC1C,KAAK,IAAI,gBAAgB,KAAK,cAAc,EAE5C,KAAK,oBAAoB,SAAS,MAAc;AAE9C,GADA,EAAU,IAAI,cAAc,KAAK,cAAc,EAC/C,EAAU,IAAI,gBAAgB,KAAK,cAAc;IACjD,EAEF,KAAK,YAAY,EAAE,EAEnB,MAAM,SAAS;;CAGjB,IAAI,KAAK,GAAiB;AAKxB,EAJA,KAAK,OAAO,OAAO,MAAU,KAAA,IAAY;GAAE,OAAO;GAAG,QAAQ;GAAG,GAAG,GAAgB,EAAM,EAEzF,KAAK,SAAS;GAAE,OAAO,KAAK,OAAO,KAAK;GAAO,QAAQ,KAAK,OAAO,KAAK;GAAQ,EAEhF,KAAK,cAAc;;CAGrB,IAAI,QAAQ,GAAqC;AAI/C,EAHA,KAAK,OAAO,UAAU,EAAc,EAAM,EAE1C,KAAK,eAAe,EACpB,KAAK,eAAe;;CAItB,gBAAwB;EACtB,IAAM,IAAU,GACd,KAAK,OAAO,SACZ,KAAK,OAAO,cAAc,KAAK,IAAI,WAAW,GAC/C;AACD,OAAK,SAAS;GACZ,aAAa,EAAQ;GACrB,YAAY,EAAQ;GACpB,cAAc,EAAQ;GACtB,eAAe,EAAQ;GACxB;;CAGH,OAAe,gBAAgB,GAA+B;AAC5D,SAAO,aAAiB;;CAiD1B,SAA4D,GAAG,GAAmB;AAChF,MAAI,KAAK,sBACP,QAAO,MAAM,SAAS,GAAG,EAAS;AAEpC,QAAU,MACR,sJAED;;CAMH,YAAmB,GAAG,GAA2D;AAC/E,MAAI,KAAK,sBACP,QAAO,MAAM,YAAY,GAAI,EAA8B;AAE7D,QAAU,MAAM,kFAAkF;;CAGpG,SAAgB;AAGd,EADA,KAAK,eAAe,EAChB,KAAK,OAAO,cACd,KAAK,OAAO;GAAE,OAAO,KAAK,IAAI,KAAK;GAAO,QAAQ,KAAK,IAAI,KAAK;GAAQ,EACxE,KAAK,SAAS,IAAI,CAAC,KAAK,IAAI,KAAK,QAAQ,IAAK,CAAC,KAAK,IAAI,KAAK,SAAS,GAAI,IAE1E,KAAK,eAAe;;CAIxB,eAAsB;AAChB,OAAK,aAAa,CAAC,KAAK,UAAU,CAAC,KAAK,KAAK,SAAS,WAC1D,KAAK,IAAI,SAAS,OAAO,OAAO,KAAK,EAErC,KAAK,oBAAoB,SAAS,MAAc;AAC9C,QAAK,IAAI,SAAS,OAAO,OAAO,EAAU;IAC1C,EAEE,KAAK,OAAO,cACd,KAAK,SAAS,IAAI,CAAC,KAAK,OAAO,KAAK,QAAQ,IAAK,CAAC,KAAK,OAAO,KAAK,SAAS,GAAI,EAGlF,KAAK,iBAAiB,EAElB,KAAK,OAAO,SACd,KAAK,IAAI,OAAO,QAAQ,KAAK,UAAU;;CAiB3C,YAAmB,GAAsB,GAAuB,GAA6B;AAS3F,EARI,EAAM,WAAW,SACnB,KAAK,wBAAwB,IAC7B,MAAM,SAAS,EAAM,EACrB,KAAK,wBAAwB,KAE/B,EAAM,SAAS,IACf,KAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,UAAU,EAAM,EAChE,KAAK,UAAU,KAAK;GAAE;GAAO;GAAQ;GAAO,CAAC,EAC7C,KAAK,eAAe;;CAItB,cAAqB,GAA4B;EAC/C,IAAM,IAAM,KAAK,UAAU,MAAM,MAAM,EAAE,UAAU,EAAM;AAEzD,EADA,KAAK,YAAY,KAAK,UAAU,QAAQ,MAAM,EAAE,UAAU,EAAM,EAC5D,KAAO,EAAM,WAAW,SAC1B,KAAK,wBAAwB,IAC7B,MAAM,YAAY,EAAM,EACxB,KAAK,wBAAwB;;CAIjC,kBAAgC;AAC9B,OAAK,IAAM,EAAE,UAAO,WAAQ,cAAW,KAAK,WAAW;GACrD,IAAM,IAAO,KAAK,YAAY,EAAO;AACrC,GAAI,KAAM,EAAM,GAAM,EAAM;;;CAOhC,YAAoB,GAAgD;EAClE,IAAM,IAAM,EAAO,QAAQ;AAC3B,MAAI,CAAC,EAAK,QAAO;EACjB,IAAI,IAAO,GACP,IAAM;AACV,OAAK,IAAI,IAA6B,GAAQ,KAAQ,MAAS,MAAM,IAAO,EAAK,QAAQ;GACvF,IAAM,IAAK,EAAK,QAAQ;AACxB,GAAI,MACF,KAAQ,EAAG,MACX,KAAO,EAAG;;AAGd,SAAO;GAAE;GAAM;GAAK,OAAO,EAAI;GAAO,QAAQ,EAAI;GAAQ;;CAG5D,WACE,GACA,GACG;EACH,IAAM,IAAW,GAAU,SAAS,YAC9B,IAAY,KAAK,oBAAoB,IAAI,EAAS;AAsBxD,SApBK,KAKD,EAAS,gBAAgB,EAAuB,IAClD,KAAK,oBAAqB,EAAmC,iBAAiB,QAAQ,KAAK,cAAc,CAAC,EAG5G,KAAK,YAAY,IAAI,GAAO;GAC1B,OAAO;GACP,SAAS,GAAU,UAAU,EAAc,EAAS,QAAQ,GAAG;IAAE,KAAK;IAAG,MAAM;IAAG,QAAQ;IAAG,OAAO;IAAG;GACxG,CAAC,EAEF,KAAK,UAAU,IAAI,GAAO,EAAU,EACpC,KAAK,kBAAkB,MAAM,KAAK,KAAK,UAAU,MAAM,CAAC,EAExD,EAAU,IAAI,SAAS,EAAM,EAC7B,KAAK,YAAY,EAAM,EAEhB,MAnBL,EAAO,MAAM,gCAAgC,EAAS,eAAe,EAC9D;;CAqBX,cAAqB,GAAqC;EACxD,IAAM,IAAY,KAAK,UAAU,IAAI,EAAM;AAC3C,MAAI,CAAC,EACH,OAAU,MACR,uFACmB,EAAM,SAAS,cAAc,GACjD;AASH,SANA,EAAU,YAAY,EAAM,EAC5B,EAAM,IAAI,UAAU,KAAK,cAAc,EACvC,KAAK,YAAY,OAAO,EAAM,EAC9B,KAAK,UAAU,OAAO,EAAM,EAC5B,KAAK,kBAAkB,MAAM,KAAK,KAAK,UAAU,MAAM,CAAC,EACxD,KAAK,eAAe,EACb;;CAGT,YAAoB,GAAsB;AAcxC,EAbI,KAAK,OAAO,uBACd,AACE,EAAM,WAAS,IAEZ,EAAM,QAAQ,OAAO,UACxB,EAAM,SAAS,EAAE,OAAO,QAAQ,GAE7B,EAAM,QAAQ,OAAO,WACxB,EAAM,SAAS,EAAE,QAAQ,QAAQ,IAGrC,EAAM,GAAG,UAAU,KAAK,cAAc,EACtC,EAAU,WAAW,EAAM,EAC3B,KAAK,eAAe;;CAGtB,cAAsB,GAAY;AAIhC,EAHA,KAAK,YAAY,OAAO,EAAM,EAC9B,KAAK,UAAU,OAAO,EAAuB,EAC7C,KAAK,kBAAkB,MAAM,KAAK,KAAK,UAAU,MAAM,CAAC,EACxD,EAAU,aAAa,EAAM;;CAG/B,SAAiB;AACf,OAAK,eAAe;;CAItB,IAAI,QAAiB;AACnB,SAAO,KAAK,OAAO;;CAGrB,IAAI,MAAM,GAAgB;AAExB,MADA,KAAK,OAAO,QAAQ,GAChB,EAGF,CADA,EADY,YAAY,KAAK,OACV,KAAK,SAAS,YAAY,EAAY,YAAY,EACrE,KAAK,WAAW;OACX;AAKL,GAJA,EAAgB,YAAY,KAAK,MAAM,EACnC,KAAK,kBACP,KAAK,eAAe,OAAO,EAEzB,KAAK,gBACP,KAAK,YAAY,UAAU;AAE7B,QAAK,IAAM,KAAM,KAAK,cACpB,GAAG,UAAU;;;CAKnB,YAAoB;AAsBlB,EApBK,KAAK,mBACR,KAAK,wBAAwB,IAC7B,KAAK,iBAAiB,GAAoB,GAAG,KAAK,SAAS,WAAW,QAAQ,EAC9E,MAAM,SAAS,KAAK,eAAe,EACnC,KAAK,eAAe,SAAS,IAC7B,KAAK,wBAAwB,KAG1B,KAAK,gBACR,KAAK,wBAAwB,IAC7B,KAAK,cAAc,EAAiB,KAAK,SAAS,YAAY,EAAY,YAAY,EACtF,MAAM,SAAS,KAAK,YAAY,EAChC,KAAK,YAAY,SAAS,IAC1B,KAAK,wBAAwB,KAG/B,KAAK,YAAY,OAAO,KAAK,SAAS,YACtC,KAAK,YAAY,UAAU,IAC3B,KAAK,YAAY,SAAS,IAAI,GAAG,EAAE,EAEnC,KAAK,eAAe,OAAO;EAE3B,IAAM,IAAI,KAAK,OAAO,KAAK,OACrB,IAAI,KAAK,OAAO,KAAK,QACrB,IAAM,KAAK,OAAO;AAqBxB,EAlBA,KAAK,eACF,KAAK,GAAG,GAAG,GAAG,EAAE,CAChB,OAAO;GAAE,OAAO;GAAG,OAAO,EAAY;GAAa,OAAO,EAAW;GAAQ,WAAW;GAAM,CAAC,EAG9F,EAAI,MAAM,KACZ,KAAK,eAAe,KAAK,GAAG,GAAG,GAAG,EAAI,IAAI,CAAC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAEzG,EAAI,SAAS,KACf,KAAK,eACF,KAAK,GAAG,IAAI,EAAI,QAAQ,GAAG,EAAI,OAAO,CACtC,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAEjE,EAAI,OAAO,KACb,KAAK,eACF,KAAK,GAAG,EAAI,KAAK,EAAI,MAAM,IAAI,EAAI,MAAM,EAAI,OAAO,CACpD,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC,EAEjE,EAAI,QAAQ,KACd,KAAK,eACF,KAAK,IAAI,EAAI,OAAO,EAAI,KAAK,EAAI,OAAO,IAAI,EAAI,MAAM,EAAI,OAAO,CACjE,KAAK;GAAE,OAAO,EAAY;GAAa,OAAO,EAAW;GAAM,CAAC;EAIrE,IAAM,IAAS,EAAI,MACb,IAAS,EAAI,KACb,IAAS,IAAI,EAAI,OAAO,EAAI,OAC5B,IAAS,IAAI,EAAI,MAAM,EAAI;AACjC,OAAK,eACF,KAAK,GAAQ,GAAQ,GAAQ,EAAO,CACpC,OAAO;GAAE,OAAO;GAAG,OAAO,EAAY;GAAa,OAAO,EAAW;GAAQ,WAAW;GAAM,CAAC;EAIlG,IAAM,oBAAY,IAAI,KAAwB;AAC9C,OAAK,oBAAoB,SAAS,GAAW,MAAS;AAEpD,IAAI,CAAC,EAAU,IAAI,EAAU,IAAI,EAAK,SAAS,EAAU,IAAI,EAAU,CAAE,WACvE,EAAU,IAAI,GAAW,EAAK;IAEhC;EAEF,IAAM,IAAmB,CAAC,GAAG,IAAI,IAAI,KAAK,oBAAoB,QAAQ,CAAC,CAAC;AAGxE,SAAO,KAAK,cAAc,SAAS,EAAiB,SAAQ;AAC1D,QAAK,wBAAwB;GAC7B,IAAM,IAAK,EAAiB,IAAI,EAAY,OAAO;AAInD,GAHA,MAAM,SAAS,EAAG,EAClB,EAAG,SAAS,IACZ,KAAK,cAAc,KAAK,EAAG,EAC3B,KAAK,wBAAwB;;AAG/B,IAAiB,SAAS,GAAW,MAAM;AACzC,OAAI,CAAC,EAAU,QAAQ,eAAgB;GACvC,IAAM,IAAK,EAAU,OAAO,gBACtB,IAAS,EAAU;AACzB,OAAI,CAAC,GAAQ,QAAQ,eAAgB;GACrC,IAAM,IAAW,EAAO,OAAO,gBAEzB,IAAK,EAAS,OAAO,EAAG,MACxB,IAAK,EAAS,MAAM,EAAG,KACvB,IAAK,EAAG,OACR,IAAK,EAAG,QACR,IAAc,EAAU,SAAS,SAAS;AAGhD,QAAK,eACF,KAAK,GAAI,GAAI,GAAI,EAAG,CACpB,KAAK;IAAE,OAAO,EAAY;IAAQ,OAAO,IAAc,EAAW,aAAa,EAAW;IAAM,CAAC,CACjG,OAAO;IAAE,OAAO;IAAG,OAAO,EAAY;IAAQ,OAAO;IAAK,WAAW;IAAM,CAAC;GAG/E,IAAM,IAAK,KAAK,cAAc;AAG9B,GAFA,EAAG,OAAO,EAAU,IAAI,EAAU,IAAI,IACtC,EAAG,UAAU,IACb,EAAG,SAAS,IAAI,IAAK,GAAG,IAAK,EAAE;IAC/B;AAGF,OAAK,IAAI,IAAI,EAAiB,QAAQ,IAAI,KAAK,cAAc,QAAQ,IACnE,MAAK,cAAc,GAAG,UAAU;EAIlC,IAAM,IAAU,IAAI,GACd,IAAU,IAAI;AACpB,OAAK,eACF,OAAO,GAAS,IAAU,GAAG,CAC7B,OAAO,GAAS,IAAU,GAAG,CAC7B,OAAO;GAAE,OAAO;GAAG,OAAO,EAAY;GAAa,OAAO,EAAW;GAAW,WAAW;GAAM,CAAC,CAClG,OAAO,IAAU,IAAI,EAAQ,CAC7B,OAAO,IAAU,IAAI,EAAQ,CAC7B,OAAO;GAAE,OAAO;GAAG,OAAO,EAAY;GAAa,OAAO,EAAW;GAAW,WAAW;GAAM,CAAC;;GCrzBrG,IAAkD;AAEtD,SAAS,KAAiD;AACxD,KAAI,EAAU,QAAO;AACrB,qBAAW,IAAI,KAAK;CACpB,IAAM,IACH,WAAyE,OAAO,MAC/E,aACD,IAAoC,EAAE;AACzC,MAAK,IAAM,KAAQ,EACb,GAAK,WAAW,MAChB,OAAO,EAAK,UAAW,cAAc,EAAK,OAAO,aACnD,EAAS,IAAI,EAAK,IAAI,EAAK,OAA4B;AAK3D,QAAO;;AAGT,SAAgB,GAAc,GAA2C;AACvE,QAAO,IAAgB,CAAC,IAAI,EAAG;;AAGjC,SAAgB,KAAmC;AACjD,QAAO,CAAC,GAAG,IAAgB,CAAC,MAAM,CAAC;;;;AC/BrC,IAAI,IAA8C;AAElD,SAAS,KAA6C;AACpD,KAAI,EAAU,QAAO;AACrB,qBAAW,IAAI,KAAK;CACpB,IAAM,IACH,WAAyE,OAAO,MAC/E,SACD,IAAgC,EAAE;AACrC,MAAK,IAAM,KAAQ,EACb,GAAK,WAAW,MAChB,OAAO,EAAK,UAAW,cAAc,EAAK,OAAO,aACnD,EAAS,IAAI,EAAK,IAAI,EAAK,OAAwB;AAKvD,QAAO;;AAGT,SAAgB,GAAU,GAAuC;AAC/D,QAAO,IAAgB,CAAC,IAAI,EAAG;;AAGjC,SAAgB,KAA+B;AAC7C,QAAO,CAAC,GAAG,IAAgB,CAAC,MAAM,CAAC;;;;ACmBrC,IAAM,KAA2C;CAAC;CAAY;CAAS;CAAQ,EAQzE,KAAmC;CACvC;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAwBD,SAAgB,EACd,GAC6B;CAC7B,IAAM,IAAU,EAAO,WAAW,IAC5B,IAAgB,EAAQ,SAAS,WAAW,EAC5C,IAAa,EAAQ,SAAS,QAAQ,EACtC,IAAa,EAAQ,SAAS,QAAQ,EACtC,IAAc,EAAQ,SAAS,SAAS,EACxC,IAAc,CAAC,GAAG,IAAe,GAAI,EAAO,WAAW,EAAE,CAAE;AAEjE,SAAQ,MAA4B;EAClC,IAAM,IAAW,EAAO,MAAM,EAAM;AACpC,MAAI,KAAiC,KAAM,QAAO;EAIlD,IAAM,IAAW;AA6BjB,SA5BI,KACF,EACE;GAAE,UAAU,EAAS;GAAmB,GAAG,EAAS;GAAY,GAAG,EAAS;GAAY,EACxF,EACD,EAEC,KACF,EACE;GACE,OAAO,EAAS;GAChB,QAAQ,EAAS;GACjB,QAAQ,EAAS;GAClB,EACD,EACD,EAEC,KACF,EAAa,EAAS,OAAgB,EAA8B,EAElE,KACF,GAAc,EAAS,QAAiB,EAA8B,EAOxE,EADa,GAAS,GAAa,EAAS,EACnB,EAAS,EAC3B;;;;;AC7FX,IAAM,KAAqB;CAAC;CAAQ;CAAe;CAAc;CAAS;CAAU;CAAQ,EAiB/E,KAAwB;CACnC,WAAoB,GAAiB,MAA4C;AAC/E,MAAI,CAAC,EAAO,QAAO;EACnB,IAAM,EAAE,aAAU,MAAG,MAAG,UAAO,UAAO,WAAQ,WAAQ,GAAG,MAAS;AAKlE,SAJA,EAAgB;GAAE;GAAU;GAAG;GAAG,EAAE,EAAO,EAC3C,EAAa;GAAE;GAAO;GAAQ;GAAQ,EAAE,EAAO,EAC/C,EAAa,GAAO,EAAO,EAC3B,EAAmB,GAAM,EAAO,EACzB;;CAGT,WAAW,EAAmB;EAC5B,QAAQ,MACN,IAAI,EAAU,IAAQ,EAAM,GAAO,EAAoB,GAAG,KAAA,EAAU;EACtE,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;EACV,CAAC;CAEF,mBAAmB,EAAmB;EACpC,QAAQ,MACN,IAAI,GAAkB,IAAQ,EAAM,GAAO,GAA4B,GAAG,KAAA,EAAU;EACtF,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;EACV,CAAC;CAEF,SAAS;CAET,QAAQ,EAAmB;EACzB,QAAQ,MACN,IAAI,GAAO,IAAQ,EAAe,EAAM,GAAG,KAAA,EAAU;EACvD,SAAS;GAAC;GAAY;GAAS;GAAS;GAAS;EACjD,SAAS,CAAC,SAAS,QAAQ;EAC5B,CAAC;CAEF,cAAc,EAAmB;EAC/B,QAAQ,MACN,IAAI,GAAa,IAAQ,EAAe,EAAM,GAAG,KAAA,EAAU;EAC7D,SAAS;GAAC;GAAY;GAAS;GAAS;GAAS;EACjD,SAAS,CAAC,SAAS,QAAQ;EAC5B,CAAC;CAEF,gBAAgB,EAAmB;EAKjC,QAAQ,MAAyD,IAAI,GAAe,EAAM;EAC1F,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;GACP;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACA;GACD;EACF,CAAC;CAEF,UAAU,EAAmB;EAC3B,QAAQ,MAAoC,IAAI,GAAU;EAC1D,SAAS;GAAC;GAAY;GAAS;GAAQ;EACxC,CAAC;CAEF,IAAI,GAA2C;EAC7C,IAAM,IAAS,IAAI,GAAI,EAAM,IAAI,EAC3B,EAAE,aAAU,MAAG,MAAG,UAAO,UAAO,WAAQ,WAAQ,KAAK,GAAM,GAAG,MAAS;AAK7E,SAJA,EAAgB;GAAE;GAAU;GAAG;GAAG,EAAE,EAAO,EAC3C,EAAa;GAAE;GAAO;GAAQ;GAAQ,EAAE,EAAO,EAC/C,EAAa,GAAO,EAAO,EAC3B,EAAmB,GAAM,EAAO,EACzB;;CAGT,MAAM,EAAmB;EAOvB,QAAQ,MACN,IAAI,EACF,IACI;GACE,MAAM,EAAM;GACZ,aAAa,EAAM;GACnB,YAAY,EAAM;GAClB,OAAO,EAAM;GACb,QAAQ,EAAM,SAAS,EAAiB,EAAM,QAAQ,GAAK,GAAG,KAAA;GAC9D,OAAO,EAAM,QAAQ,EAAiB,EAAM,OAAO,GAAK,GAAG,KAAA;GAC5D,GACD,EAAE,CACP;EACH,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS,CAAC,GAAG,GAAmB;EACjC,CAAC;CAEF,UAAU,EAAmB;EAC3B,QAAQ,MACN,IAAI,GACF,IACI;GACE,MAAM,EAAM;GACZ,aAAa,EAAM;GACnB,YAAY,EAAM;GAClB,OAAO,EAAM;GACb,QAAQ,EAAM,SAAS,EAAiB,EAAM,QAAQ,GAAK,GAAG,KAAA;GAC9D,OAAO,EAAM,QAAQ,EAAiB,EAAM,OAAO,GAAK,GAAG,KAAA;GAC5D,GACD,EAAE,CACP;EACH,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS,CAAC,GAAG,GAAmB;EACjC,CAAC;CAEF,YAAY,EAAmB;EAG7B,QAAQ,MACN,IAAI,EACF,IACI;GACE,MAAM,EAAM;GACZ,aAAa,EAAM;GACnB,OAAO,EAAM;GACb,QAAQ,EAAM,SAAS,EAAiB,EAAM,QAAQ,GAAK,GAAG,KAAA;GAC9D,OAAO,EAAM,QAAQ,EAAiB,EAAM,OAAO,GAAK,GAAG,KAAA;GAC5D,GACD,EAAE,CACP;EACH,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS,CAAC,GAAG,GAAmB;EACjC,CAAC;CAEF,QAAQ,EAAmB;EACzB,QAAQ,MACN,IAAI,GAAQ,IAAQ,EAAM,GAAO,GAAiB,GAAG,KAAA,EAAoC;EAC3F,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;EACV,CAAC;CAEF,eAAe,EAAmB;EAKhC,QAAQ,MACN,IAAI,GAAc,EAAsC;EAC1D,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;EACV,CAAC;CAEF,UAAU,EAAmB;EAC3B,QAAQ,MAGN,IAAI,GAAS,IAAS,EAAM,GAAO,GAAmB,GAA+B,EAAE,CAA4B;EACrH,SAAS;GAAC;GAAY;GAAS;GAAQ;EACvC,SAAS;EACV,CAAC;CAEF,OAAO,EAAmB;EACxB,QAAQ,MAAuC;GAG7C,IAAI,IAA0D,IACxD,IAAO,GAAO;AACpB,OAAI,OAAO,KAAS,UAAU;IAI5B,IAAI,IAAM,EAAK,MAAM,GAAG;AAMxB,IALI,MAAQ,WAAW,MAAQ,UAC7B,IAAM,UAEN,IAAY,EAAK,UAAU,GAAG,EAAK,SAAS,EAAE,EAEhD,IAAY;KAAE,UAAU,IAAO;KAAK,OAAO,IAAO;KAAU;;GAE9D,IAAM,IAAiB,OAAiE,MAAM,KAC5F,EACD;AAOD,UAJI,GAAO,eAAe,KAAA,MAAW,EAAO,aAAa,EAAM,aAC3D,GAAO,iBACT,EAAO,MAAM,aAAa,EAAM,cAAc,GAAG,EAAM,eAAe,EAAM,KAAK,EAE5E;;EAET,SAAS;GAAC;GAAY;GAAS;GAAS;GAAS;EACjD,SAAS;GAAC;GAAQ;GAAc;GAAiB;GAAc;GAAO;EACvE,CAAC;CAEF,iBACE,MAC2B;EAM3B,IAAM,IAAS,IAAI,GAAuB,EAAM;AAChD,MAAI,CAAC,EAAO,QAAO;EACnB,IAAM,EAAE,aAAU,MAAG,MAAG,WAAQ,UAAO,UAAO,WAAQ,WAAQ,GAAG,MAAS;AAM1E,SALA,EAAgB;GAAE;GAAU;GAAG;GAAG,EAAE,EAAO,EAC3C,EAAa;GAAE;GAAO;GAAQ;GAAQ,EAAE,EAAO,EAC/C,GAAc,GAAQ,EAAO,EAC7B,EAAa,GAAO,EAAO,EAC3B,EAAmB,GAAM,EAAO,EACzB;;CAGT,UAAU,GAAwC,IAA2C,EAAE,KACtF,IAAI,GAAQ,GAAe,EAAmB;CAgBvD,SACE,GACA,MACsB;EACtB,IAAM,IAAO,GAAc,EAAa;AACxC,MAAI,CAAC,GAAM;GACT,IAAM,IAAQ,IAAwB;AACtC,SAAU,MACR,8BAA8B,OAAO,EAAG,CAAC,YAC7B,EAAM,SAAS,IAAI,EAAM,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,GAAG,uCACxE;;EAEH,IAAM,IAAW,IAAK,EAA2D,EAAM;AACvF,MAAI,GAAO;GACT,IAAM,EAAE,aAAU,MAAG,MAAG,UAAO,UAAO,WAAQ,WAAQ,UAAO,eAAY;AAKzE,GAJA,EAAgB;IAAE;IAAU;IAAG;IAAG,EAAE,EAAS,EAC7C,EAAa;IAAE;IAAO;IAAQ;IAAQ,EAAE,EAAS,EACjD,EAAa,GAAO,EAAS,EACzB,MAAU,KAAA,MAAY,EAA0C,QAAQ,IACxE,MAAY,KAAA,MAAY,EAA6C,UAAU;;AAErF,SAAO;;CAYT,KACE,GACA,MACkB;EAClB,IAAM,IAAO,GAAU,EAAa;AACpC,MAAI,CAAC,GAAM;GACT,IAAM,IAAQ,IAAoB;AAClC,SAAU,MACR,0BAA0B,OAAO,EAAG,CAAC,YACzB,EAAM,SAAS,IAAI,EAAM,KAAK,MAAM,IAAI,EAAE,GAAG,CAAC,KAAK,KAAK,GAAG,uCACxE;;EAEH,IAAM,IAAW,IAAK,EAAmD,EAAM;AAC/E,MAAI,GAAO;GACT,IAAM,EAAE,aAAU,MAAG,MAAG,UAAO,UAAO,WAAQ,WAAQ,UAAO,eAAY;AAKzE,GAJA,EAAgB;IAAE;IAAU;IAAG;IAAG,EAAE,EAAS,EAC7C,EAAa;IAAE;IAAO;IAAQ;IAAQ,EAAE,EAAS,EACjD,EAAa,GAAO,EAAS,EACzB,MAAU,KAAA,MAAY,EAA0C,QAAQ,IACxE,MAAY,KAAA,MAAY,EAA6C,UAAU;;AAErF,SAAO;;CAEV;AAID,GAAyB,GAAsB;;;ACrM/C,IAAa,KAAqC;CAAC;CAAQ;CAAU;CAAe;CAAS;CAAQ,ECoC/F,IAA+B;CACnC,OAAO;CACP,MAAM;CACN,OAAO;CACP,SAAS;CACT,OAAO;CACP,UAAU;CACV,SAAS;EAAE,KAAK;EAAG,MAAM;EAAG,QAAQ;EAAG,OAAO;EAAG;CACjD,aAAa;CACb,OAAO;EACL,YAAY;EACZ,MAAM;EACN,UAAU;EACV,YAAY;EACb;CACD,IAAI;EACF,QAAQ;EACR,MAAM,EAAE,OAAO,UAAU;EACzB,QAAQ;GAAE,OAAO;GAAG,OAAO;GAAK;EACjC;CACD,aAAa,EAAE;CACf,WAAW,EAAE,OAAO,OAAU;CAC9B,OAAO;EACL,OAAO;EACP,OAAO;EACR;CACD,cAAc;EACZ,cAAc;EACd,OAAO;EACP,WAAW;EACZ;CACF,EAEK,KAAkB;CAAC;CAAQ;CAAY;CAAU;CAAS;CAAO;CAAM,EAoChE,KAAb,MAAa,UAAc,EAAU,GAAY,EAAY,EAAU,CAAC,CAAC,CAAC;CAiFxE,YACE,GACA,IAA0B,IAC1B,IAA6B,MAC7B;AAyEA,MAxEA,MAAM;GAAE,YAAY;GAAM,YAAY,CAAC;GAAS,CAAC,EAH1C,KAAA,UAAA,GACA,KAAA,QAAA,kBA9E+C,IAAI,GAAuC,kBAO1C,IAAI,GAAuC,iBAO5C,IAAI,GAAuC,oBAoDtE,sBACC,iCACY,iCACD,0BACR,kBAGR,IASvB,KAAK,UAAU;GACb,GAAG;GACH,GAAG;GACH,OAAO;IACL,GAAG,EAAe;IAClB,GAAI,GAAS,SAAS,EAAE;IACzB;GACD,SAAS,EAAc,EAAQ,WAAW,EAAe,QAAQ;GACjE,IAAI;IACF,GAAG,EAAe;IAClB,GAAI,EAAQ,MAAM,EAAE;IACrB;GACD,cAAc;IACZ,GAAG,EAAe;IAClB,GAAI,EAAQ,gBAAgB,EAAE;IAC/B;GACF,EAEG,KAAK,QAAQ,UAAU,OAAO,KAAK,QAAQ,UAAW,WACxD,KAAK,SAAS,EAAE,GAAG,KAAK,QAAQ,QAAQ,GAExC,KAAK,SAAS,EAAE,iBAAiB,YAAY,EAG1C,KAAK,QAAQ,gBAChB,KAAK,QAAQ,cAAc,EACzB,OAAO,OAAO,KAAK,QAAQ,OAAO,KAAK,IAAI,SAC5C,GAGH,KAAK,SAAS,KAAK,IAAI,UAAU,EAC/B,QAAQ;GAAE,UAAU;GAAY,KAAK;GAAG,MAAM;GAAG,OAAO;GAAQ,QAAQ;GAAQ,EACjF,CAAC,EACF,KAAK,OAAO,EAEZ,KAAK,kBAAkB,KAAK,OAAO,IAAI,UAAU;GAC/C,GAAG;GACH,QAAQ;IACN,UAAU;IACV,iBAAiB;IACjB,OAAO;IACP,OAAO;IACP,QAAQ;IACT;GACF,CAAC,EACF,KAAK,wBAAwB,KAAK,OAAO,IAAI,UAAU;GACrD,GAAG;GACH,QAAQ;IACN,UAAU;IACV,OAAO;IACP,iBAAiB;IACjB,OAAO;IACP,QAAQ;IACT;GACF,CAAC,EACF,KAAK,sBAAsB,YAAY,QACvC,KAAK,cAAc,EACnB,KAAK,UAAU,EACf,KAAK,UAAU,EACf,KAAK,gBAAgB,EAErB,KAAK,YAAY,OAAO,KAAK,QAAQ,YAAY,QAAQ,SAAS,KAAK,QAAQ,QAE/E,KAAK,MAAM,YAAY,KAAK,YAAY,YAAY,QAEhD,KACF,KAAK,oBAAoB,KAAK,cAAc,aAAa,CAAC,QAAQ,KAAK,aAAa,GAAG,CAAC,EAE1F,KAAK,oBAAoB,KAAK,cAAc,QAAQ,CAAC,QAAQ,KAAK,aAAa,GAAG,CAAC,EAE/E,KAAK,QAAQ,OAAO;GACtB,IAAM,IAAQ,KAAK,UAAW,KAAK,OAAO,SAAS,cAAc,SAAS,IAAK;AAU/E,GATA,KAAK,QAAQ,KAAK,OAAO,IACtB,UAAU,CACV,KACC,GACA,GACA,KAAK,GAAG,QAAQ,IAAQ,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ,OACzE,KAAK,GAAG,SAAS,IAAQ,KAAK,QAAQ,QAAQ,MAAM,KAAK,QAAQ,QAAQ,OAC1E,CACA,KAAK,EAAE,OAAO,GAAK,CAAC,EACvB,KAAK,gBAAgB,OAAO,KAAK;;;CASrC,IAAI,gBAAgB;AAClB,SAAO,KAAK;;CAQd,IAAI,gBAAgB;AAClB,SAAO,KAAK;;CAOd,IAAI,MAAM,GAAe;AACvB,OAAK,SAAS;;CAQhB,IAAI,UAAmB;EACrB,IAAI,IAAS;AACb,MAAI,KAAK,WACP,KAAI,KAAK,OACP,KAAS,KAAK,OAAO,KAAK,KAAK,OAAO;OACjC;AACL,OAAI,KAAK,QAAQ,SAAS,OACxB,QAAO;AAIT,GAFA,KAAK,WAAW,WAAW,IAC3B,IAAS,KAAK,WAAW,eAAe,EACxC,KAAK,WAAW,WAAW;;AAG/B,SAAO;;CAOT,IAAW,QAAQ;AACjB,SAAO,KAAK,QAAQ,MAAM,IAAI;;CAOhC,IAAW,MAAM,GAAe;AAC9B,MAAI,KAAK,YAAY;AACnB,QAAK,WAAW,QAAQ;GACxB,IAAM,IAAQ,IAAI,MAAM,SAAS;IAC/B,SAAS;IACT,YAAY;IACb,CAAC;AACF,QAAK,WAAW,cAAc,EAAM;QAGpC,CADA,KAAK,SAAS,GACd,KAAK,MAAM,OAAO;;CAQtB,SAAS;AAEP,EADA,MAAM,QAAQ,EACV,KAAK,gBACP,KAAK,uBAAuB;;CAOhC,UAAU;AACR,OAAK,QAAQ;;CAOf,QAAQ;AAEN,EADA,MAAM,OAAO,EACT,KAAK,WACP,KAAK,YAAY;;CASrB,YAAY,GAAoB;AAE9B,MAAK,GAAG,eAA4C,IAClD;AAGF,EADA,aAAa,KAAK,YAAY,EAC9B,aAAa,KAAK,kBAAkB;EACpC,IAAM,IAAwB,IAAI,GAAyB,KAAK,OAAO,EAAE,GAAI,KAAK,MAAM,MAAM,UAAU;AACxG,OAAK,iBAAiB,EAAsB;;CAQ9C,UAAU;AACR,OAAK,aAAa;;CAGpB,iBAAiB,GAAoB;AACnC,OAAK,cAAc,iBAAiB;AAClC,QAAK,0BAA0B,EAAU;KACxC,IAAI;;CAGT,0BAA0B,GAAoB;AAC5C,MAAI,KAAK,YAAY;AACnB,OAAI;AAGF,IAFA,KAAK,WAAW,OAAO,EACvB,KAAK,WAAW,OAAO,EACnB,MAAc,KAAA,IAChB,KAAK,WAAW,iBAAiB,KAAK,YAAY,OAAO,SAEzD,KAAK,WAAW,kBAAkB,GAAW,GAAW,OAAO;WAEvD;AAGZ,QAAK,0BAA0B;;;CAInC,yBAAyB,GAA0B;EACjD,IAAM,IAAM,KAAK,QAAQ,EAAE,KAAK,OAAO;AACvC,EAAI,KAAK,WAAW,CAAC,UAAU,SAAS,EAAI,GAAG,EAAI,EAAE,GACnD,KAAK,SAAS,GAEd,KAAK,UAAU;;CAQnB,WAAW;AACT,OAAK,YAAY,MAAM;;CAGzB,SAAS;AAEP,EADA,KAAK,GAAG,IAAI,GACZ,KAAK,GAAG,IAAI;EAGZ,IAAM,IACJ,KAAK,MAAM,gBAAgB,CAAC,IAC5B,KAAK,MAAM,MAAM,WACjB,KAAK,QAAQ,QAAQ,MACrB,KAAK,QAAQ,QAAQ,QAEjB,IAAU,KAAK,QAAQ,QACzB,KAAK,QAAQ,WACb,KAAK,IAAI,KAAK,QAAQ,UAAU,KAAK,MAAM,MAAM,GAAG,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ,OAKnG,IAAO,KAAK,QAAQ,WAAW,IAAU,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ,OAC1F,IAAsB,IAAU,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ;AAEvF,UAAQ,KAAK,MAAM,MAAM,OAAzB;GACE,KAAK;AAMH,QALA,KAAK,MAAM,IAAI,IAAU,IAAI,KAAK,MAAM,QAAQ,GAC3C,KAAK,2BACR,KAAK,YAAY,IAAI,IAAU,IAAI,KAAK,YAAY,QAAQ,IAE9D,KAAK,OAAO,IAAI,KAAQ,IAAI,IAAI,IAAO,GACnC,KAAK,QAAQ,OAAO;KACtB,IAAM,IAAY,KAAK,MAAM,QAAQ;AACrC,KAAI,IAAY,MACd,KAAK,MAAM,KAAK,IAAY;;AAGhC;GACF,KAAK;AAKH,IAJA,KAAK,MAAM,IAAI,IAAU,KAAK,QAAQ,QAAQ,QAAQ,KAAK,MAAM,OAC5D,KAAK,2BACR,KAAK,YAAY,IAAI,IAAU,KAAK,QAAQ,QAAQ,QAAQ,KAAK,YAAY,QAE/E,KAAK,OAAO,IAAI,KAAQ,IAAI,IAAI;AAChC;GACF;AAME,QALA,KAAK,MAAM,IAAI,KAAK,QAAQ,QAAQ,MAC/B,KAAK,2BACR,KAAK,YAAY,IAAI,KAAK,QAAQ,QAAQ,OAE5C,KAAK,OAAO,IAAI,GACZ,KAAK,QAAQ,OAAO;KACtB,IAAM,IAAY,KAAK,MAAM,QAAQ;AACrC,KAAI,IAAY,MACd,KAAK,MAAM,KAAK;;AAGpB;;AAQJ,MALA,KAAK,MAAM,IAAI,KAAK,QAAQ,QAAQ,KAC/B,KAAK,2BACR,KAAK,YAAY,IAAI,KAAK,MAAM,IAG9B,KAAK,WAAW,KAAK,OAAO;GAC9B,IAAM,IAAa,KAAK,MAAM,SAAS,cAAc,SAAS;AAS9D,GARA,KAAK,QAAQ,KAAK,MAAM,OACxB,KAAK,SAAS,KAAK,MAAM,MAAM,MAC/B,KAAK,MAAM,OAAO,KAAK,QACvB,KAAK,iBAAiB,KAAK,MAAM,cAAe,OAAO,EACvD,KAAK,eAAe,KAAK,GACzB,KAAK,eAAe,KAAK,GACzB,KAAK,eAAe,SAAS,GAC7B,KAAK,eAAe,UAAU,GAC9B,KAAK,iBAAiB,KAAK,MAAM,gBAAgB;;AAQnD,MALA,KAAK,MAAM,IAAI,KAAK,kBAAkB,IAAI,KAAK,MAAM,IAAI,KAAK,iBAAiB,KAAK,MAAM,IAAI,KAAK,MAAM,QAAQ,GACjH,KAAK,MAAM,IAAI,KAAK,MAAM,IAAI,GAC9B,KAAK,MAAM,SAAS,KAAK,MAAM,MAAM,WAAW,MAG5C,KAAK,UAAU,IAEjB;OADA,KAAK,YAAY,UAAU,IACvB,CAAC,KAAK,WAAW,KAAK,0BAA0B,CAAC,KAAK,uBAAuB;AAC/E,SAAK,wBAAwB;IAC7B,IAAM,IAAK,KAAK,MAAM,GAChB,IAAK,KAAK,MAAM;AACtB,IAAI,KAAK,QAAQ,YAAY,kBAC3B,KAAK,aAAa,CAChB,EAAK,GAAG,KAAK,aAAa;KACxB,GAAG;KACH,GAAG;KACH,MAAM;KACN,OAAO,KAAK,QAAQ,YAAY,SAAS;KACzC,UAAU,KAAK,QAAQ,YAAY,gBAAgB,YAAY;KAC/D,MAAM,KAAK,QAAQ,YAAY,gBAAgB,QAAQ;KACvD,WAAW;KACX,kBAAkB;AAEhB,MADA,KAAK,yBAAyB,IAC9B,KAAK,wBAAwB;;KAEhC,CAAC,EACF,EAAK,GAAG,KAAK,YAAY,OAAO;KAC9B,GAAG;KACH,GAAG;KACH,UAAU,KAAK,QAAQ,YAAY,gBAAgB,YAAY;KAC/D,MAAM,KAAK,QAAQ,YAAY,gBAAgB,QAAQ;KACvD,WAAW;KACZ,CAAC,CACH,CAAC,IAEF,KAAK,YAAY,IAAI,GACrB,KAAK,YAAY,IAAI,GACrB,KAAK,YAAY,MAAM,IAAI,GAAG,EAAE,EAChC,KAAK,yBAAyB,IAC9B,KAAK,wBAAwB;;aAI7B,CAAC,KAAK,WAAW,KAAK,QAAQ,YAAY,gBAE5C;OADA,KAAK,YAAY,UAAU,IACvB,CAAC,KAAK,wBAAwB;AAChC,SAAK,yBAAyB;IAC9B,IAAI,IAAK,KAAK,YAAY,GACtB,IAAK,KAAK,YAAY;AAC1B,YAAQ,KAAK,QAAQ,YAAY,gBAAjC;KACE,KAAK;AACH,UAAK,KAAK,MAAM,IAAI,KAAK,YAAY,SAAS,KAAK,QAAQ,QAAQ;AACnE;KACF,KAAK;AACH,UAAK,KAAK,MAAM,IAAI,KAAK,MAAM,SAAS,KAAK,QAAQ,QAAQ;AAC7D;;AAGJ,QAAI,KAAK,QAAQ,YAAY,cAAc;KACzC,IAAM,IAAS,EAAiB,KAAK,QAAQ,YAAY,aAAa;AAEtE,KADA,KAAM,EAAO,GACb,KAAM,EAAO;;AAGf,QAAI,KAAK,QAAQ,YAAY,iBAa3B;SAZA,KAAK,aACH,EAAK,GAAG,KAAK,aAAa;MACxB,GAAG;MACH,GAAG;MACH,UAAU,KAAK,QAAQ,YAAY,gBAAgB,YAAY;MAC/D,MAAM,KAAK,QAAQ,YAAY,gBAAgB,QAAQ;MACvD,MAAM,KAAK,QAAQ,YAAY,gBAAgB,QAAQ;MACvD,OAAO,KAAK,QAAQ,YAAY,gBAAgB,SAAS,KAAK,QAAQ,YAAY,SAAS;MAC3F,WAAW;MACZ,CAAC,CACH,EAEG,KAAK,QAAQ,YAAY,aAAa;MACxC,IAAM,IAAQ,EAAiB,KAAK,QAAQ,YAAY,YAAY;AACpE,WAAK,aACH,EAAK,GAAG,KAAK,YAAY,OAAO;OAC9B,GAAG,EAAM;OACT,GAAG,EAAM;OACT,UAAU,KAAK,QAAQ,YAAY,gBAAgB,YAAY;OAC/D,MAAM,KAAK,QAAQ,YAAY,gBAAgB,QAAQ;OACvD,WAAW;OACZ,CAAC,CACH;;UAIH,CADA,KAAK,YAAY,IAAI,GACrB,KAAK,YAAY,IAAI;;QAIzB,MAAK,YAAY,UAAU;AAI/B,MAAI,KAAK,QAAQ,OAAO;GACtB,IAAM,IAAQ,KAAK,UAAW,KAAK,SAAS,cAAc,SAAS,IAAK;AACxE,GAAI,KAAK,UACP,KAAK,MACF,OAAO,CACP,KAAK,GAAG,IAAI,IAAU,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,QAAQ,SAAS,GAAO,IAAW,EAAM,CACxG,KAAK,EAAE,OAAO,GAAK,CAAC,EACvB,KAAK,MAAM,SAAS,IAAI,KAAK,QAAQ,QAAQ,OAAO,GAAO,EAAE;;AAcjE,EAVI,MAAY,KAAK,cACnB,KAAK,OAAO,GAAS,EAAS,EAG5B,KAAK,iBACP,KAAK,eAAe,GAEpB,KAAK,mBAAmB,OAAO,EAG7B,KAAK,gBACP,KAAK,uBAAuB;;CAIhC,gBAAgB;EACd,IAAM,IAAO,KAAK;AAClB,MAAI,CAAC,GAAM;AACT,QAAK,mBAAmB,OAAO;AAC/B;;AAGF,EADA,KAAK,mBAAmB,OAAO,EAC/B,KAAK,kBACF,KAAK,EAAK,OAAO,KAAK,MAAM,GAAG,KAAK,MAAM,GAAG,EAAK,OAAO,KAAK,MAAM,OAAO,CAC3E,KAAK,EAAE,OAAO,KAAK,QAAQ,UAAU,OAAO,CAAC;;CAGlD,OAAO,IAAgB,KAAK,YAAY,IAAiB,KAAK,aAAa;EACzE,IAAM,KACH,KAAK,SAAU,KAAK,WAAW,KAAK,OAAO,UAAW,KAAK,SAAS,OAAO,KACxE;GAAE,GAAG,KAAK,QAAQ;GAAI,GAAG,KAAK,QAAQ,MAAM;GAAI,GAChD,KAAK,QAAQ;AASnB,EAPA,KAAK,GACF,OAAO,CACP,UAAU,GAAG,GAAG,GAAO,GAAQ,GAAM,UAAU,EAAE,CACjD,KAAK,EAAK,KAAK,CACf,OAAO;GAAE,GAAI,GAAM,UAAU,EAAE;GAAG,WAAW;GAAG,CAAC,EAEpD,KAAK,aAAa,GAClB,KAAK,cAAc;;CAGrB,UAAU;AAUR,EATA,QAAQ,IAAI,iBAAiB,KAAK,EAClC,aAAa,KAAK,YAAY,EAC9B,aAAa,KAAK,kBAAkB,EAEpC,KAAK,IAAI,MAAM,IAAI,eAAe,KAAK,yBAAyB,EAEhE,KAAK,YAAY,EACjB,KAAK,mBAAmB,EAExB,MAAM,SAAS;;CAGjB,QAAkB;AAChB,OAAK,KAAK,KAAK,OAAO,IACnB,UAAU,CACV,UAAU,GAAG,GAAG,KAAK,IAAI,KAAK,SAAS,IAAI,UAAU,EAAE,CACvD,KAAK,KAAK,QAAQ,GAAG,KAAK;;CAG/B,eAAyB;AACvB,OAAK,oBAAoB,KAAK,gBAAgB,IAAI,UAAU;;CAG9D,WAAqB;AACnB,OAAK,QAAQ,KAAK,gBAAgB,IAAI,OAAO;GAC3C,OAAO,EAAQ;GACf,OAAO;GACP,QAAQ;GACR,MAAM,KAAK,QAAQ,MAAM,SAAS;GAClC,OAAO;GACP,SAAS;GACV,CAAC;;CAGJ,WAAqB;AAKnB,EADA,KAAK,SAAS,KAAK,QAAQ,SAAS,IACpC,KAAK,QAAQ,KAAK,gBAAgB,IAAI,KAAK;GACzC,GAAG,KAAK;GACR,OAAO;IAAE,GAAI,KAAK,SAAS,SAAS,EAAE;IAAG,SAAS;IAAG;GACrD,MAAM,KAAK,QAAQ,SAAS;GAC5B,OAAO;GACP,YAAY;GACZ,aAAa;GACb,QAAQ;GACT,CAAC;;CAGJ,iBAA2B;AAczB,EAbA,KAAK,cAAc,KAAK,sBAAsB,IAAI,KAAK;GACrD,GAAG,KAAK;GACR,GAAG,KAAK,QAAQ;GAChB,OAAO;IACL,GAAG,KAAK,QAAQ;IAChB,MAAM,KAAK,QAAQ,aAAa,SAAS;IAC1C;GACD,YAAY;GACZ,OAAO;GACP,aAAa;GACb,QAAQ;GACT,CAAC,EAEF,KAAK,YAAY,MAAM,QAAQ,KAAK,MAAM,MAAM;;CAGlD,iBAA2B,GAAoB;AAC7C,MAAI,KAAK,WAAW,KAAK,OAAO,YAAY;AAE1C,GADA,KAAK,aAAa,KAAK,MAAM,YAC7B,KAAK,yBAAyB;AAC9B;;AAcF,EAZA,aAAa,KAAK,YAAY,EAC9B,aAAa,KAAK,kBAAkB,EAEpC,KAAK,aAAa,SAAS,cAAc,QAAQ,EACjD,KAAK,WAAW,OAAO,QACnB,KAAK,QAAQ,QAAQ,GAAgB,SAAS,KAAK,QAAQ,KAAK,KAClE,KAAK,WAAW,OAAO,KAAK,QAAQ,OAGlC,KAAK,QAAQ,YACf,KAAK,WAAW,UAAU,KAAK,QAAQ,UAErC,KAAK,QAAQ,UACf,KAAK,SAAS,KAAK,QAAQ;EAG7B,IAAM,IAAM,KAAK,mBAAmB,EAC9B,IAAS,KAAK,WAAW;AAkC/B,EAjCA,EAAO,IAAI,EAAI,GACf,EAAO,IAAI,EAAI,GACf,EAAO,QAAQ,KAAK,QAAQ,KAAK,QAAQ,QAAQ,MASjD,KAAK,WAAW,MAAM,WAAW,SACjC,KAAK,WAAW,MAAM,SAAS,QAC/B,KAAK,WAAW,MAAM,UAAU,QAChC,KAAK,WAAW,MAAM,OAAO,KAAY,MAAM,GAAG,EAAO,KAAK,KAC9D,KAAK,WAAW,MAAM,MAAM,KAAY,MAAM,GAAG,EAAO,IAAI,KAC5D,KAAK,WAAW,MAAM,QAAQ,GAAG,EAAO,MAAM,KAC9C,KAAK,WAAW,MAAM,SAAS,GAAG,EAAO,OAAO,KAChD,KAAK,WAAW,MAAM,UAAU,KAE5B,KAAK,QAAQ,QACf,KAAK,WAAW,MAAM,UAAU,QAEhC,KAAK,WAAW,MAAM,UAAU,aAElC,KAAK,IAAI,OAAO,eAAe,YAAY,KAAK,WAAW,EAC3D,KAAK,WAAW,QAAQ,KAAK,OAC7B,KAAK,WAAW,aAAa,eAAe,KAAK,SAAS,aAAa,QAAQ,GAAG,EAC9E,KAAK,SAAS,aAChB,KAAK,WAAW,aAAa,aAAa,KAAK,QAAQ,UAAU,UAAU,CAAC,EAG9E,KAAK,yBAAyB,EAC9B,KAAK,iBAAiB,EAAU;;CAGlC,oBAA8B;AACxB,OAAK,YAGT,AAQE,KAAK,gBAPL,KAAK,4BAA4B,EACjC,KAAK,WAAW,QAAQ,EAEpB,KAAK,WAAW,cAClB,KAAK,WAAW,WAAW,YAAY,KAAK,WAAW,EAGvC;;CAItB,aAAuB;AAErB,EADA,KAAK,MAAM,UAAU,IACrB,KAAK,YAAY;;CAGnB,aAAuB;AAErB,EADA,KAAK,iBAAiB,MAAM,EAC5B,KAAK,MAAM,UAAU;;CAGvB,aAAuB;AAerB,EAdI,KAAK,mBACP,KAAK,gBAAgB,MAAM,EAE7B,KAAK,kBAAkB,EAAK,OAC1B,KAAK,OACL,EAAE,OAAO,GAAG,EACZ;GACE,UAAU;GACV,OAAO;GACP,MAAM;GACN,QAAQ;GACR,WAAW;GACZ,CACF,EACD,KAAK,aAAa,KAAK,gBAAgB;;CAGzC,WAAqB;EACnB,IAAM,IAAW,KAAK;AAkBtB,EAjBI,KAAK,UACP,KAAK,QAAQ,KAAK,OAAO,SAAS,MAElC,KAAK,QAAQ,CAAC,KAAK,SACf,KAAK,SAAS,KAAK,UAAU,KAC/B,KAAK,QAAQ,KAAK;GAAE,OAAO;GAAM,YAAY,KAAK;GAAY,OAAO,KAAK;GAAQ,CAAC,GAGnF,KAAK,UAAU,MACb,KAAK,SAAS,KAAK,UAAU,IAC/B,KAAK,MAAM,MAAM,OAAO,KAAK,SAAS,OAAO,OAAO,QAAQ,IAE5D,KAAK,MAAM,MAAM,OAAO,KAAK,QAAQ,OAAO,OAAO,QAAQ,GAE7D,KAAK,QAAQ,GAGX,KAAK,gBACP,KAAK,aAAa,UAAU;;CAIhC,6BAAqC;AAKnC,EAJA,KAAK,WAAW,oBAAoB,SAAS,KAAK,wBAAwB,GAAM,EAChF,KAAK,WAAW,oBAAoB,QAAQ,KAAK,uBAAuB,GAAM,EAC9E,KAAK,WAAW,oBAAoB,SAAS,KAAK,yBAAyB,GAAM,EACjF,KAAK,WAAW,oBAAoB,SAAS,KAAK,wBAAwB,GAAM,EAChF,KAAK,WAAW,oBAAoB,WAAW,KAAK,0BAA0B,GAAM;;CAGtF,0BAAkC;AAC5B,OAAK,YAGT,KAAK,4BAA4B,EACjC,KAAK,WAAW,iBAAiB,SAAS,KAAK,wBAAwB,GAAM,EAC7E,KAAK,WAAW,iBAAiB,QAAQ,KAAK,uBAAuB,GAAM,EAC3E,KAAK,WAAW,iBAAiB,SAAS,KAAK,yBAAyB,GAAM,EAC9E,KAAK,WAAW,iBAAiB,SAAS,KAAK,wBAAwB,GAAM,EAC7E,KAAK,WAAW,iBAAiB,WAAW,KAAK,0BAA0B,GAAM;;CAGnF,eAAuB;AAMrB,MALA,KAAK,iBAAiB,IACtB,KAAK,YAAY,EAEjB,aAAa,KAAK,kBAAkB,EAEhC,CAAC,KAAK,SAAS;AACjB,QAAK,oBAAoB,iBAAiB;AACxC,SAAK,IAAI,MAAM,GAAG,eAAe,KAAK,yBAAyB;MAC9D,IAAI;GAEP,IAAM,IAAa,EAAQ,KAAK,QAAQ,aAAa;AACrD,OAAI,GAAY;AAEd,IAAI,KAAK,gBACP,KAAK,qBAAqB;IAE5B,IAAM,IAAS,MAAM,QAAQ,KAAK,QAAQ,aAAa,aAAa,EAChE,IAAa;AACjB,QAAI,GAAQ;KACV,IAAM,IAAa,KAAK,QAAQ,aAAa;AAC7C,MACG,MAAY,EAAW,SAAS,SAAS,IACzC,KAAW,EAAW,SAAS,QAAQ,IACvC,CAAC,MAAY,CAAC,KAAW,EAAW,SAAS,UAAU,MAExD,IAAa;WAKf,IAHS,OAAO,KAAK,QAAQ,aAAa,gBAAiB,aAC9C,KAAK,QAAQ,aAAa,cAAc,GAExC;AAGf,QAAI,GAAY;KACd,IAAM,IAAO,gBAAgB,KAAK,QAAQ,EACpC,IAAQ,KAAK,QAAQ,cAAc,SAAS;AAClD,OAAK,eAAe,EAAE,cAAc,IAAO;KAC3C,IAAM,IAAW,OAAO,EAAK,OAAO,YAAY,EAAe,OAAO,YAAY,GAAG,GAAG;AA0BxF,SAzBA,AACE,EAAK,UAAQ,EAAE,EAGjB,EAAK,MAAM,WAAW,GAClB,EAAK,YACP,EAAK,QAAQ,QAAQ,GACrB,EAAK,QAAQ,OAAO,GACpB,EAAK,QAAQ,SAAS,GACtB,EAAK,QAAQ,UAAU,IAErB,EAAK,IAAI,WACX,EAAK,GAAG,UAAU,IAEhB,EAAK,IAAI,QAAQ,UACnB,EAAK,GAAG,OAAO,SAAS,IAEtB,EAAK,aACP,EAAK,YAAY,GACb,EAAK,WAAW,KAAK,IAAI,KAAK,UAChC,EAAK,WAAW,KAAK,IAAI,KAAK,SAAS,EAAK,IAAI,QAAQ,QAAQ,EAAK,GAAG,OAAO,QAAQ,IAAI,KAAK,OAKhG,KAAK,QAAQ,cAAc,SAAS,QAAQ;MAC9C,IAAM,IAAU,KAAK,KAAK,OAAO;OAC/B,OAAO,EAAQ;OACf,MAAM,KAAK,QAAQ,aAAa,QAAQ,SAAS,SAAS;OAC1D,OAAO,KAAK,QAAQ,aAAa,QAAQ,SAAS,SAAS;OAC3D,OAAO,KAAK,IAAI,KAAK;OACrB,QAAQ,KAAK,IAAI,KAAK;OACtB,WAAW;OACZ,CAAC;AACF,WAAK,iBAAiB,KAAK,IAAI,MAAM,SAAS,EAAQ;;AAUxD,KAPA,KAAK,eAAe,IAAI,EAAM,GAAM,IAAM,KAAK,EAC/C,KAAK,aAAa,QAAQ,GAAG,KAAK,MAAM,YACxC,KAAK,aAAa,QAAQ,GAC1B,KAAK,aAAa,MAAM,OAAO,KAAK,OACpC,KAAK,aAAa,UAAU,EAC5B,KAAK,IAAI,MAAM,SAAS,KAAK,aAAa,EAC1C,KAAK,uBAAuB,EAC5B,KAAK,mBAAmB;;;;;CAMhC,oBAA4B;AAG1B,EAFA,KAAK,aAAa,MAAM,IAAI,KAC5B,KAAK,aAAa,EAAK,GAAG,KAAK,cAAc;GAAE,UAAU;GAAK,OAAO;GAAK,MAAM;GAAY,OAAO;GAAK,CAAC,CAAC,EAC1G,KAAK,aAAa,EAAK,GAAG,KAAK,aAAa,OAAO;GAAE,UAAU;GAAK,GAAG;GAAG,MAAM;GAAY,OAAO;GAAK,CAAC,CAAC;;CAG5G,wBAAgC;AAC9B,MAAI,CAAC,KAAK,aACR;EAEF,IAAM,IAAI,KAAK,aAAa,QAAQ;AAGpC,EAFA,KAAK,aAAa,IAAI,KAAK,IAAI,KAAK,QAAQ,KAAM,IAAI,IACtD,KAAK,aAAa,IAAI,KAAK,QAAQ,cAAc,aAAa,IAC1D,KAAK,mBACP,KAAK,eAAe,QAAQ,KAAK,IAAI,KAAK,OAC1C,KAAK,eAAe,SAAS,KAAK,IAAI,KAAK;;CAI/C,sBAA8B;AAQ5B,EAPA,KAAK,gBAAgB,SAAS,EAC9B,KAAK,gBAAgB,QAAQ,YAAY,KAAK,eAAe,EAE7D,KAAK,iBAAiB,MACtB,KAAK,cAAc,SAAS,EAC5B,KAAK,cAAc,QAAQ,YAAY,KAAK,aAAa,EAEzD,KAAK,eAAe;;CAGtB,yBAAiC;AAE/B,EADA,KAAK,IAAI,MAAM,IAAI,eAAe,KAAK,yBAAyB,EAChE,KAAK,cAAc;;CAGrB,wBAAgC;AAC1B,OAAK,YAGT,aAAa,KAAK,YAAY,EAC9B,aAAa,KAAK,kBAAkB,EACpC,KAAK,YAAY,EACjB,KAAK,qBAAqB,EAC1B,KAAK,mBAAmB;;CAG1B,yBAAiC;AAC/B,OAAK,0BAA0B;;CAGjC,yBAAiC,GAAkB;AAEjD,EADA,KAAK,0BAA0B,EAC3B,CAAC,KAAK,WAAW,EAAE,QAAQ,YACzB,KAAK,QAAQ,eACf,KAAK,WAAW,MAAM,EAExB,KAAK,QAAQ,KAAK;GAAE,OAAO;GAAM,OAAO,KAAK;GAAQ,YAAY,KAAK;GAAY,CAAC;;CAIvF,2BAAmC;AACjC,MAAI,CAAC,KAAK,YAAY;AACpB,KAAO,KAAK,KAAK,OAAO,iBAAiB;AACzC;;EAEF,IAAM,IAAQ,KAAK,WAAW,kBAAkB,GAC1C,IAAM,KAAK,WAAW,gBAAgB,IACtC,IAAY,KAAK,WAAW,oBAC9B,IAAO,IACL,IAAQ,KAAK,QAAQ,SAAS,aAAa,KAAK,MAAM,OAAO,KAAK;AACxE,MAAI,MAAQ,KAAA,EAIV,CAHA,IAAO,EAAM,UAAU,GAAG,EAAM,EAEhC,KAAK,iBADW,EAAkB,YAAY,GAAM,KAAK,MAAM,MAAM,CACvC,OAC9B,KAAK,iBAAiB;OACjB;AACL,OAAO,EAAM,UAAU,IAAQ,IAAM,IAAM,GAAO,IAAQ,IAAM,IAAQ,EAAI;GAC5E,IAAM,IAAU,EAAM,UAAU,GAAG,IAAQ,IAAM,IAAM,EAAM,EACvD,IAAc,EAAkB,YAAY,GAAS,KAAK,MAAM,MAAM,EACtE,IAAc,EAAkB,YAAY,GAAM,KAAK,MAAM,MAAM;AAEzE,GADA,KAAK,iBAAiB,IAAI,GAAU,EAAY,OAAO,GAAG,EAAY,OAAO,KAAK,MAAM,OAAO,EAC/F,KAAK,iBACH,MAAc,aAAa,KAAK,eAAe,OAAO,KAAK,eAAe,OAAO,KAAK,eAAe;;;CAI3G,wBAAgC,GAAU;EACxC,IAAM,IAAS,EAAE;AAIjB,MAHI,KAAU,CAAC,KAAK,eAClB,KAAK,aAAa,IAEhB,KAAK,QAAQ,YAAY,IAAI;GAC/B,IAAM,IAAgB,EAAO,MAAM,QAAQ,IAAI,OAAO,KAAK,QAAQ,SAAS,IAAI,EAAE,GAAG;AAErF,GADA,EAAO,QAAQ,GACf,KAAK,SAAS;QAEd,MAAK,SAAS,EAAO;AAavB,EAVA,KAAK,MAAM,OACT,KAAK,QAAQ,SAAS,aAClB,KAAK,QACD,MAAM,GAAG,CACV,UAAU,IAAI,CACd,KAAK,GAAG,GACX,KAAK,QAEX,KAAK,0BAA0B,EAE1B,KAAK,YACR,KAAK,SAAS,KAAK;GAAE,OAAO;GAAM,YAAY,KAAK;GAAY,OAAO,KAAK;GAAQ,CAAC,EACpF,KAAK,UAAU;;CAQnB,eAAuB;EACrB,IAAM,IAAS,KAAK,gBAAgB,WAAW;AAG/C,SAFA,EAAO,QAAQ,KAAK,YACpB,EAAO,SAAS,KAAK,aACd;;GCjtCE,KAAb,cAA8B,EAA+B;CAuB3D,YAAY,GAAiC;AAW3C,MAVA,OAAO,kBAvBE,IAAI,GAAgD,iBACrD,IAAI,GAAoB,eAC1B,IAAI,GAAoB,mBACpB,IAAI,GAAoB,qBAEd,sBACA,4BAKF,oBAEA,qBACD,IAAI,GAAO,mBAGC,EAAkB,MAQ/C,KAAK,WAAW,OAAO,OACrB;GACE,YAAY;GACZ,YAAY;GACb,EACD,EACD,EAEG,CAAC,KAAK,SAAS,OAAO;GACxB,IAAM,IAAQ,IAAI,GAAU;AAG5B,GAFA,EAAM,OAAO,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,OAAO,GAAK,CAAC,EAC3C,EAAM,QAAQ,IACd,KAAK,SAAS,QAAQ;;AAGxB,MAAI,CAAC,KAAK,SAAS,OAAO;GACxB,IAAM,IAAQ,IAAI,GAAU;AAG5B,GAFA,EAAM,OAAO,GAAG,GAAG,GAAG,CAAC,KAAK,EAAE,OAAO,GAAK,CAAC,EAC3C,EAAM,QAAQ,KAAK,mBACnB,KAAK,SAAS,QAAQ;;AAKxB,EAFA,KAAK,YAAY,KAAK,SAAS,aAAa,KAE5C,KAAK,YAAY;;CAGnB,aAAa;AAqBX,EApBA,KAAK,QAAQ,KAAK,SAAS,OAC3B,KAAK,QAAQ,KAAK,SAAS,OAE3B,KAAK,MAAM,MAAM,IAAI,KAAK,SAAS,YAAY,KAAK,SAAS,WAAW,EACxE,KAAK,MAAM,MAAM,IAAI,KAAK,SAAS,YAAY,KAAK,SAAS,WAAW,EAEpE,YAAY,KAAK,SACnB,KAAK,MAAM,OAAO,IAAI,GAAI,EAExB,YAAY,KAAK,SACnB,KAAK,MAAM,OAAO,IAAI,GAAI,EAG5B,KAAK,IAAI,SAAS,KAAK,MAAM,EAC7B,KAAK,IAAI,SAAS,KAAK,MAAM,EAG7B,KAAK,cAAc,KAAK,QAAQ,KAChC,KAAK,cAAc,KAAK,MAAM,QAAQ,GAEtC,KAAK,YAAY;;CAGnB,eAAe,GAA0B;AACvC,MAAI,CAAC,KAAK,YAAY,EAAE,cAAc,KAAK,WACzC;EAEF,IAAM,IAAc,KAAK,QAAQ,EAAE,OAAO,EACpC,IAAQ,EAAY,IAAI,KAAK,cAAc,GAC3C,IAAQ,EAAY,IAAI,KAAK,cAAc,GAE3C,IAAc,IAAI,EAAM,GAAG,EAAE,EAC/B,IAAQ,GACR,IAAY,EAAkB;AAClC,MAAI,KAAS,KAAK,KAAS,GAAG;AAC5B,QAAK,YAAY;AACjB;;AAGF,MAAI,MAAU,MACR,IAAQ,KACV,EAAY,IAAI,GAAG,IAAQ,KAAK,cAAc,KAAK,cAAc,EAAM,EACvE,IAAQ,KACR,IAAY,EAAkB,WAE9B,EAAY,IAAI,GAAG,EAAE,KAAK,IAAI,EAAM,GAAG,KAAK,cAAc,KAAK,cAAc,KAAK,IAAI,EAAM,EAAE,EAC9F,IAAQ,IACR,IAAY,EAAkB,MAEhC,KAAK,MAAM,SAAS,IAAI,EAAY,GAAG,EAAY,EAAE,EACrD,KAAK,QAAQ,KAAK,SAAS,EAAY,EACnC,KAAK,SAAS,KAAK,YAAW;AAEhC,GADA,KAAK,YAAY,GACjB,KAAK,SAAS,KAAK;IAAE;IAAO;IAAW,OAAO,KAAK;IAAO,CAAC;AAC3D;;AAIJ,MAAI,MAAU,MACR,IAAQ,KACV,EAAY,IAAI,KAAK,IAAI,EAAM,GAAG,KAAK,cAAc,KAAK,cAAc,KAAK,IAAI,EAAM,EAAE,EAAE,EAC3F,IAAQ,GACR,IAAY,EAAkB,UAE9B,EAAY,IAAI,EAAE,KAAK,IAAI,EAAM,GAAG,KAAK,cAAc,KAAK,cAAc,KAAK,IAAI,EAAM,GAAG,EAAE,EAC9F,IAAQ,KACR,IAAY,EAAkB,OAGhC,KAAK,MAAM,SAAS,IAAI,EAAY,GAAG,EAAY,EAAE,EACrD,KAAK,QAAQ,KAAK,SAAS,EAAY,EACnC,KAAK,SAAS,KAAK,YAAW;AAEhC,GADA,KAAK,YAAY,GACjB,KAAK,SAAS,KAAK;IAAE;IAAO;IAAW,OAAO,KAAK;IAAO,CAAC;AAC3D;;EAIJ,IAAM,IAAS,KAAK,IAAI,IAAQ,EAAM,EAChC,IAAS,KAAK,KAAK,EAAO;AAChC,MAAS,IAAS,MAAO,KAAK;EAE9B,IAAI,IAAU,GACV,IAAU;AAgCd,EA9BI,IAAQ,IAAQ,IAAQ,KAAS,KAAK,cAAc,KAAK,eAC3D,IAAU,KAAK,cAAc,KAAK,IAAI,EAAO,EAC7C,IAAU,KAAK,cAAc,KAAK,IAAI,EAAO,KAE7C,IAAU,KAAK,IAAI,EAAM,GAAG,KAAK,cAAc,KAAK,cAAc,KAAK,IAAI,EAAM,EACjF,IAAU,KAAK,IAAI,EAAM,GAAG,KAAK,cAAc,KAAK,cAAc,KAAK,IAAI,EAAM,GAG/E,IAAQ,MACV,IAAU,CAAC,KAAK,IAAI,EAAQ,GAG1B,IAAQ,MACV,IAAU,CAAC,KAAK,IAAI,EAAQ,GAG1B,IAAQ,KAAK,IAAQ,MAEd,IAAQ,KAAK,IAAQ,IAE9B,IAAQ,MAAM,IACL,IAAQ,KAAK,IAAQ,IAE9B,KAAgB,MACP,IAAQ,KAAK,IAAQ,MAE9B,IAAQ,MAAM,KAEhB,EAAY,IAAI,GAAS,EAAQ,EACjC,KAAK,QAAQ,KAAK,SAAS,EAAY,EACnC,KAAK,SAAS,KAAK,cACrB,IAAY,KAAK,aAAa,EAAY,EAC1C,KAAK,YAAY,GACjB,KAAK,MAAM,SAAS,IAAI,EAAY,GAAG,EAAY,EAAE,EACrD,KAAK,SAAS,KAAK;GAAE;GAAO;GAAW,OAAO,KAAK;GAAO,CAAC;;CAI/D,QAAQ,GAA0B;AAOhC,EANA,KAAK,IAAI,eAAe,KAAK,gBAAgB,CAC1C,IAAI,aAAa,KAAK,cAAc,CACpC,IAAI,oBAAoB,KAAK,cAAc,CAC3C,IAAI,eAAe,KAAK,eAAe,EAC1C,OAAO,oBAAoB,aAAa,KAAK,cAAc,EAC3D,KAAK,UAAU,MAAM,EACrB,MAAM,QAAQ,EAAQ;;CAGxB,gBAA0B,GAA0B;AAC9C,OAAK,eAAe,KAAA,MAGxB,KAAK,aAAa,EAAE,WACpB,KAAK,gBAAgB,KAAK,QAAQ,EAAE,OAAO,EAC3C,KAAK,WAAW,IAChB,KAAK,MAAM,QAAQ,GACnB,KAAK,QAAQ,MAAM;;CAGrB,cAAwB,GAAyC;AAC3D,OAAK,eAAe,EAAE,cAG1B,KAAK,YAAY,EAAkB,MACnC,KAAK,MAAM,SAAS,IAAI,GAAG,EAAE,EAC7B,KAAK,WAAW,IAChB,KAAK,MAAM,QAAQ,KAAK,mBACxB,KAAK,MAAM,MAAM,EACjB,KAAK,aAAa,KAAA;;CAGpB,aAAuB;AAOrB,EANA,KAAK,YAAY,UACjB,KAAK,GAAG,eAAe,KAAK,gBAAgB,CACzC,GAAG,aAAa,KAAK,cAAc,CACnC,GAAG,oBAAoB,KAAK,cAAc,CAC1C,GAAG,eAAe,KAAK,eAAe,EAEzC,OAAO,iBAAiB,aAAa,KAAK,cAAc;;CAG1D,SAAmB,GAAoB;EACrC,IAAM,IAAI,EAAY,GAChB,IAAI,EAAY;AACtB,SAAO,KAAK,IAAI,GAAG,KAAK,KAAK,IAAI,IAAI,IAAI,EAAE,GAAG,KAAK,YAAY;;CAGjE,aAAuB,GAAe;EACpC,IAAM,IAAM,KAAK,MAAM,EAAO,GAAG,EAAO,EAAE;AAgBxC,SAfG,KAAO,CAAC,KAAK,KAAK,KAAK,IAAM,KAAO,KAAO,KAAK,IAAM,KAAK,KAAK,IAC5D,EAAkB,QAChB,KAAO,KAAK,KAAK,KAAK,IAAO,IAAI,KAAK,KAAM,IAC9C,EAAkB,cAChB,KAAQ,IAAI,KAAK,KAAM,KAAK,IAAO,IAAI,KAAK,KAAM,IACpD,EAAkB,SAChB,KAAQ,IAAI,KAAK,KAAM,KAAK,IAAO,IAAI,KAAK,KAAM,IACpD,EAAkB,aACf,KAAQ,IAAI,KAAK,KAAM,KAAK,IAAM,KAAK,MAAQ,KAAO,CAAC,KAAK,MAAM,IAAO,KAAK,KAAK,KAAM,IAC5F,EAAkB,OAChB,KAAQ,KAAK,KAAK,KAAM,KAAK,IAAO,KAAK,KAAK,KAAM,IACtD,EAAkB,UAChB,KAAQ,KAAK,KAAK,KAAM,KAAK,IAAO,KAAK,KAAK,KAAM,IACtD,EAAkB,MAElB,EAAkB;;GCxOzB,KAAuB;CAC3B,OAAO;CACP,OAAO;CACR,EAcK,KAAqB;CACzB,SAAS;CACT,eAAe;CACf,2BAA2B;CAC3B,eAAe;CAChB,EAKY,KAAb,MAAa,UAAuB,EAA+B;CASjE,IAAI,gBAA2C;AAC7C,SAAO,KAAK,OAAO;;CAWrB,YACE,GACA,IAAkC,EAAE,EACpC;AAIA,EAHA,OAAO,EAHS,KAAA,KAAA,oBArBU,gCAMgC,KAAA,GAmB1D,KAAK,SAAS,OAAO,OAAO;GAAE;GAAI,GAAG;GAAoB,EAAE,EAAO,EAElE,KAAK,aAAa;;CAGpB,IAAI,OAAU;AACZ,SAAO,KAAK,OAAO;;CAQrB,OAAe,YAAY,GAA0C,GAAoB;EACvF,IAAI,IAAc,EAAE;AACpB,EAAI,OAAO,KAAW,aACpB,IAAc;EAEhB,IAAM,IAA+B,OAAO,OAAO,EAAE,GAAG,IAAsB,EAAE,EAAY,EACtF,IAAU,IAAI,GAAO,EAAQ,MAAM;AAMzC,SALA,EAAQ,OAAO,IAAI,GAAI,EACvB,EAAQ,QAAQ,EAAc,OAC9B,EAAQ,OAAO,EAAc,OAC7B,EAAQ,QAAQ,EAAK,OACrB,EAAQ,SAAS,EAAK,QACf;;CAGT,aAAa;CAEb,aAAoB;AAElB,EADA,KAAK,oBAAoB,EACzB,KAAK,kBAAkB;;CAGzB,aAAoB;AAClB,OAAK,IAAI,MAAM,iBAAiB,KAAK,GAAG;;CAG1C,QAAQ,GAA0C;AAGhD,EAFA,KAAK,IAAI,MAAM,iBAAiB,KAAK,GAAG,EACxC,KAAK,uBAAuB,KAAA,GAC5B,MAAM,QAAQ,EAAQ;;CASxB,MAAM,OAAsB;AAE1B,SADA,KAAK,UAAU,IACR,QAAQ,SAAS;;CAS1B,MAAM,OAAsB;AAG1B,SAFA,KAAK,QAAQ,EACb,KAAK,UAAU,IACR,QAAQ,SAAS;;CAO1B,MAAM,QAAQ;CAEd,YAAY;AACV,EAAI,KAAK,yBACP,KAAK,IAAI,MAAM,IAAI,KAAK,sBAAsB,KAAK,IAAI,GAAK,EAC5D,KAAK,IAAI,MAAM,SAAS,KAAK,qBAAqB;;CAMtD,MAAM;CAGN,MAAM,QAAuB;AACtB,OAAK,IAAI,OAAO,UAAU,KAAK,IAAI,KAAK,OAAO,KAAK;;CAG3D,SAAS;AACP,OAAK,SAAS,QAAQ,KAAK,IAAI,KAAK,OAAO,KAAK,IAAI,KAAK,OAAO;;CAOlE,cAAsB;AAcpB,EAbA,KAAK,IAAI,MAAM,cAAc,KAAK,IAAI,GAAM,EAExC,KAAK,OAAO,YACd,KAAK,UAAU,KAAK,IAAI,SAAS,EAAM,YAAY,KAAK,OAAO,SAAS,KAAK,IAAI,KAAK,CAAC,EACvF,KAAK,QAAQ,YAAY,UAErB,KAAK,OAAO,8BACd,KAAK,QAAQ,KAAK,SAAS,KAAK,MAAM,EACtC,KAAK,QAAQ,KAAK,OAAO,KAAK,MAAM,IAIxC,KAAK,OAAO,KAAK,IAAI,WAAW,EAChC,KAAK,KAAK,YAAY;;CAIxB,mBAA6B;AAC3B,EAAI,KAAK,kBACP,KAAK,IAAI,gBAAgB,KAAK,eAC9B,EAAO,IAAI,SAAS,0BAA0B,KAAK,IAAI,cAAc;;CAIzE,qBAA+B;AAE7B,EADA,KAAK,uBAAuB,KAAK,IAAI,eACrC,EAAO,IAAI,SAAS,0BAA0B,KAAK,qBAAqB;;CAG1E,uBAA8B;AAK5B,EAJI,KAAK,yBACP,EAAO,IAAI,SAAS,4BAA4B,KAAK,qBAAqB,EAC1E,KAAK,IAAI,gBAAgB,KAAK,uBAEhC,KAAK,uBAAuB,KAAA"}