@number10/phaserjsx 0.3.1 → 0.4.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (137) hide show
  1. package/dist/{TransformOriginView-KcTgaYRi.cjs → TransformOriginView-Bx81YEUU.cjs} +1077 -1500
  2. package/dist/TransformOriginView-Bx81YEUU.cjs.map +1 -0
  3. package/dist/{TransformOriginView-CzVjS16F.js → TransformOriginView-DCvId72M.js} +1200 -1623
  4. package/dist/TransformOriginView-DCvId72M.js.map +1 -0
  5. package/dist/camera/camera-fx-registry.d.ts +47 -0
  6. package/dist/camera/camera-fx-registry.d.ts.map +1 -0
  7. package/dist/camera/index.d.ts +6 -0
  8. package/dist/camera/index.d.ts.map +1 -0
  9. package/dist/camera/use-camera-fx.d.ts +59 -0
  10. package/dist/camera/use-camera-fx.d.ts.map +1 -0
  11. package/dist/components/appliers/applyBackground.d.ts +4 -0
  12. package/dist/components/appliers/applyBackground.d.ts.map +1 -1
  13. package/dist/components/appliers/applyParticles.d.ts +7 -0
  14. package/dist/components/appliers/applyParticles.d.ts.map +1 -0
  15. package/dist/components/appliers/applyParticlesLayout.d.ts +11 -0
  16. package/dist/components/appliers/applyParticlesLayout.d.ts.map +1 -0
  17. package/dist/components/creators/createParticlesLayout.d.ts +14 -0
  18. package/dist/components/creators/createParticlesLayout.d.ts.map +1 -0
  19. package/dist/components/custom/Accordion.d.ts +3 -2
  20. package/dist/components/custom/Accordion.d.ts.map +1 -1
  21. package/dist/components/custom/AlertDialog.d.ts +2 -1
  22. package/dist/components/custom/AlertDialog.d.ts.map +1 -1
  23. package/dist/components/custom/Button.d.ts +2 -1
  24. package/dist/components/custom/Button.d.ts.map +1 -1
  25. package/dist/components/custom/CharText/CharText.d.ts +2 -1
  26. package/dist/components/custom/CharText/CharText.d.ts.map +1 -1
  27. package/dist/components/custom/CharTextInput.d.ts +2 -1
  28. package/dist/components/custom/CharTextInput.d.ts.map +1 -1
  29. package/dist/components/custom/Dialog.d.ts +2 -1
  30. package/dist/components/custom/Dialog.d.ts.map +1 -1
  31. package/dist/components/custom/Divider.d.ts +2 -1
  32. package/dist/components/custom/Divider.d.ts.map +1 -1
  33. package/dist/components/custom/Dropdown.d.ts +2 -1
  34. package/dist/components/custom/Dropdown.d.ts.map +1 -1
  35. package/dist/components/custom/Graphics.d.ts +45 -0
  36. package/dist/components/custom/Graphics.d.ts.map +1 -0
  37. package/dist/components/custom/Icon.d.ts +3 -2
  38. package/dist/components/custom/Icon.d.ts.map +1 -1
  39. package/dist/components/custom/Image.d.ts +2 -1
  40. package/dist/components/custom/Image.d.ts.map +1 -1
  41. package/dist/components/custom/Joystick.d.ts +42 -0
  42. package/dist/components/custom/Joystick.d.ts.map +1 -0
  43. package/dist/components/custom/Modal.d.ts +2 -1
  44. package/dist/components/custom/Modal.d.ts.map +1 -1
  45. package/dist/components/custom/NineSlice.d.ts +2 -1
  46. package/dist/components/custom/NineSlice.d.ts.map +1 -1
  47. package/dist/components/custom/NineSliceButton.d.ts +2 -1
  48. package/dist/components/custom/NineSliceButton.d.ts.map +1 -1
  49. package/dist/components/custom/Particles.d.ts +17 -0
  50. package/dist/components/custom/Particles.d.ts.map +1 -0
  51. package/dist/components/custom/Portal.d.ts +2 -1
  52. package/dist/components/custom/Portal.d.ts.map +1 -1
  53. package/dist/components/custom/RadioButton.d.ts +2 -1
  54. package/dist/components/custom/RadioButton.d.ts.map +1 -1
  55. package/dist/components/custom/RadioGroup.d.ts +2 -5
  56. package/dist/components/custom/RadioGroup.d.ts.map +1 -1
  57. package/dist/components/custom/RefOriginView.d.ts +2 -1
  58. package/dist/components/custom/RefOriginView.d.ts.map +1 -1
  59. package/dist/components/custom/ScrollSlider.d.ts +3 -2
  60. package/dist/components/custom/ScrollSlider.d.ts.map +1 -1
  61. package/dist/components/custom/ScrollView.d.ts +13 -4
  62. package/dist/components/custom/ScrollView.d.ts.map +1 -1
  63. package/dist/components/custom/Sidebar.d.ts +2 -1
  64. package/dist/components/custom/Sidebar.d.ts.map +1 -1
  65. package/dist/components/custom/Slider.d.ts +4 -3
  66. package/dist/components/custom/Slider.d.ts.map +1 -1
  67. package/dist/components/custom/Sprite.d.ts +74 -0
  68. package/dist/components/custom/Sprite.d.ts.map +1 -0
  69. package/dist/components/custom/Tabs.d.ts +50 -0
  70. package/dist/components/custom/Tabs.d.ts.map +1 -0
  71. package/dist/components/custom/Text.d.ts +2 -1
  72. package/dist/components/custom/Text.d.ts.map +1 -1
  73. package/dist/components/custom/TileSprite.d.ts +60 -0
  74. package/dist/components/custom/TileSprite.d.ts.map +1 -0
  75. package/dist/components/custom/Toggle.d.ts +2 -1
  76. package/dist/components/custom/Toggle.d.ts.map +1 -1
  77. package/dist/components/custom/TransformOriginView.d.ts +3 -2
  78. package/dist/components/custom/TransformOriginView.d.ts.map +1 -1
  79. package/dist/components/custom/View.d.ts +2 -1
  80. package/dist/components/custom/View.d.ts.map +1 -1
  81. package/dist/components/custom/WrapText.d.ts +2 -1
  82. package/dist/components/custom/WrapText.d.ts.map +1 -1
  83. package/dist/components/custom/index.cjs +6 -1
  84. package/dist/components/custom/index.cjs.map +1 -1
  85. package/dist/components/custom/index.d.ts +3 -0
  86. package/dist/components/custom/index.d.ts.map +1 -1
  87. package/dist/components/custom/index.js +16 -11
  88. package/dist/components/index.d.ts +10 -8
  89. package/dist/components/index.d.ts.map +1 -1
  90. package/dist/components/internal/SceneWrapper.d.ts +1 -1
  91. package/dist/components/internal/SceneWrapper.d.ts.map +1 -1
  92. package/dist/components/primitives/particles.d.ts +37 -0
  93. package/dist/components/primitives/particles.d.ts.map +1 -0
  94. package/dist/core-types.d.ts +5 -0
  95. package/dist/core-types.d.ts.map +1 -1
  96. package/dist/gestures/gesture-manager.d.ts.map +1 -1
  97. package/dist/hooks.d.ts +124 -3
  98. package/dist/hooks.d.ts.map +1 -1
  99. package/dist/index.cjs +2152 -20
  100. package/dist/index.cjs.map +1 -1
  101. package/dist/index.d.ts +4 -1
  102. package/dist/index.d.ts.map +1 -1
  103. package/dist/index.js +2265 -132
  104. package/dist/index.js.map +1 -1
  105. package/dist/jsx-runtime.cjs.map +1 -1
  106. package/dist/jsx-runtime.d.ts +2 -3
  107. package/dist/jsx-runtime.d.ts.map +1 -1
  108. package/dist/jsx-runtime.js.map +1 -1
  109. package/dist/jsx-types.d.ts +8 -0
  110. package/dist/jsx-types.d.ts.map +1 -1
  111. package/dist/layout/layout-engine.d.ts.map +1 -1
  112. package/dist/particles/emit-zone.d.ts +67 -0
  113. package/dist/particles/emit-zone.d.ts.map +1 -0
  114. package/dist/particles/index.d.ts +8 -0
  115. package/dist/particles/index.d.ts.map +1 -0
  116. package/dist/particles/particle-types.d.ts +20 -0
  117. package/dist/particles/particle-types.d.ts.map +1 -0
  118. package/dist/particles/preset-registry.d.ts +46 -0
  119. package/dist/particles/preset-registry.d.ts.map +1 -0
  120. package/dist/particles/use-particles.d.ts +15 -0
  121. package/dist/particles/use-particles.d.ts.map +1 -0
  122. package/dist/particles/utils.d.ts +10 -0
  123. package/dist/particles/utils.d.ts.map +1 -0
  124. package/dist/plugin.d.ts +157 -0
  125. package/dist/plugin.d.ts.map +1 -0
  126. package/dist/theme-base.d.ts +10 -1
  127. package/dist/theme-base.d.ts.map +1 -1
  128. package/dist/theme-custom.d.ts +7 -0
  129. package/dist/theme-custom.d.ts.map +1 -1
  130. package/dist/theme-defaults.d.ts.map +1 -1
  131. package/dist/types.d.ts +18 -1
  132. package/dist/types.d.ts.map +1 -1
  133. package/dist/vdom.d.ts +28 -3
  134. package/dist/vdom.d.ts.map +1 -1
  135. package/package.json +11 -1
  136. package/dist/TransformOriginView-CzVjS16F.js.map +0 -1
  137. package/dist/TransformOriginView-KcTgaYRi.cjs.map +0 -1
@@ -75,623 +75,6 @@ const host = {
75
75
  layout() {
76
76
  }
77
77
  };
78
- function shallowEqual$1(a, b) {
79
- if (!a || !b) return a === b;
80
- if (a.length !== b.length) return false;
81
- return a.every((val, i) => val === b[i]);
82
- }
83
- function applyGraphicsProps(node, _prev, next) {
84
- const prevDeps = node.__drawDependencies;
85
- const nextDeps = next.dependencies;
86
- const depsChanged2 = !shallowEqual$1(prevDeps, nextDeps);
87
- if (depsChanged2 && next.onDraw) {
88
- if (next.autoClear !== false) {
89
- node.clear();
90
- }
91
- next.onDraw(node, next);
92
- node.__drawDependencies = nextDeps;
93
- }
94
- }
95
- function applyGraphicsLayout(node, prev, next) {
96
- node.__layoutProps = next;
97
- if (prev.width !== next.width || prev.height !== next.height || prev.headless !== next.headless) {
98
- node.__getLayoutSize = () => {
99
- if (next.headless ?? true) {
100
- return { width: 0.01, height: 0.01 };
101
- }
102
- return {
103
- width: typeof next.width === "number" ? next.width : 0,
104
- height: typeof next.height === "number" ? next.height : 0
105
- };
106
- };
107
- }
108
- }
109
- function normalizeVisible$1(visible) {
110
- if (visible === void 0) return true;
111
- if (typeof visible === "boolean") return visible;
112
- if (visible === "visible") return true;
113
- if (visible === "invisible" || visible === "none") return false;
114
- return true;
115
- }
116
- function applyPhaserProps(node, prev, next) {
117
- if (prev.alpha !== next.alpha && typeof next.alpha === "number") {
118
- node.setAlpha?.(next.alpha);
119
- }
120
- if (prev.depth !== next.depth && typeof next.depth === "number") {
121
- node.setDepth?.(next.depth);
122
- }
123
- if (prev.visible !== next.visible) {
124
- const visibleValue = normalizeVisible$1(next.visible);
125
- node.visible = visibleValue;
126
- }
127
- }
128
- function applyTransformProps(node, prev, next) {
129
- if (prev.x !== next.x && typeof next.x === "number") {
130
- node.x = next.x;
131
- }
132
- if (prev.y !== next.y && typeof next.y === "number") {
133
- node.y = next.y;
134
- }
135
- if (prev.rotation !== next.rotation && typeof next.rotation === "number") {
136
- node.rotation = next.rotation;
137
- }
138
- const nextScale = next.scale;
139
- const nextScaleX = next.scaleX;
140
- const nextScaleY = next.scaleY;
141
- const prevScale = prev.scale;
142
- const prevScaleX = prev.scaleX;
143
- const prevScaleY = prev.scaleY;
144
- if (nextScale !== void 0 && nextScale !== prevScale) {
145
- node.setScale?.(nextScale, nextScale);
146
- } else if (nextScaleX !== prevScaleX || nextScaleY !== prevScaleY) {
147
- const currentScaleX = node.scaleX ?? 1;
148
- const currentScaleY = node.scaleY ?? 1;
149
- const sx = nextScaleX ?? currentScaleX;
150
- const sy = nextScaleY ?? currentScaleY;
151
- node.setScale?.(sx, sy);
152
- }
153
- }
154
- function createGraphicsLayout(graphics, props) {
155
- if (props.headless === false) {
156
- if (typeof props.width !== "number" || typeof props.height !== "number") {
157
- throw new Error(
158
- "Graphics component requires explicit width and height props when headless=false"
159
- );
160
- }
161
- }
162
- graphics.__layoutProps = props;
163
- graphics.__getLayoutSize = () => {
164
- if (graphics.__layoutProps?.headless ?? true) {
165
- return { width: 0.01, height: 0.01 };
166
- }
167
- return {
168
- width: props.width ?? 0,
169
- height: props.height ?? 0
170
- };
171
- };
172
- graphics.__drawDependencies = props.dependencies;
173
- }
174
- function normalizeVisible(visible) {
175
- if (visible === void 0) return true;
176
- if (typeof visible === "boolean") return visible;
177
- if (visible === "visible") return true;
178
- if (visible === "invisible" || visible === "none") return false;
179
- return true;
180
- }
181
- function createPhaser(node, props) {
182
- if (props.visible !== void 0) {
183
- node.visible = normalizeVisible(props.visible);
184
- }
185
- if (props.depth !== void 0) {
186
- node.setDepth(props.depth);
187
- }
188
- if (props.alpha !== void 0) {
189
- node.setAlpha(props.alpha);
190
- }
191
- }
192
- function createTransform(node, props) {
193
- if (props.scaleX !== void 0 || props.scaleY !== void 0) {
194
- node.setScale(
195
- props.scaleX ?? 1,
196
- props.scaleY ?? 1
197
- );
198
- }
199
- if (props.rotation !== void 0) {
200
- node.setRotation(props.rotation);
201
- }
202
- }
203
- const graphicsCreator = (scene, props) => {
204
- const graphics = scene.add.graphics();
205
- graphics.setPosition(props.x ?? 0, props.y ?? 0);
206
- createTransform(graphics, props);
207
- createPhaser(graphics, props);
208
- createGraphicsLayout(graphics, props);
209
- if (props.onDraw) {
210
- props.onDraw(graphics, props);
211
- }
212
- return graphics;
213
- };
214
- const graphicsPatcher = (node, prev, next) => {
215
- applyTransformProps(node, prev, next);
216
- applyPhaserProps(node, prev, next);
217
- applyGraphicsProps(node, prev, next);
218
- applyGraphicsLayout(node, prev, next);
219
- };
220
- function calculateFitScale$1(image, targetWidth, targetHeight, fit = "fill") {
221
- const textureWidth = image.width;
222
- const textureHeight = image.height;
223
- if (textureWidth === 0 || textureHeight === 0) {
224
- return { scaleX: 1, scaleY: 1 };
225
- }
226
- if (fit === "fill") {
227
- return {
228
- scaleX: targetWidth / textureWidth,
229
- scaleY: targetHeight / textureHeight
230
- };
231
- }
232
- const targetAspect = targetWidth / targetHeight;
233
- const textureAspect = textureWidth / textureHeight;
234
- if (fit === "contain") {
235
- const scale = targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
236
- return { scaleX: scale, scaleY: scale };
237
- }
238
- if (fit === "cover") {
239
- const scale = targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
240
- return { scaleX: scale, scaleY: scale };
241
- }
242
- return { scaleX: 1, scaleY: 1 };
243
- }
244
- function applyImageProps(image, prev, next) {
245
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
246
- if (textureChanged && next.texture) {
247
- image.setTexture(next.texture, next.frame);
248
- }
249
- if (prev.tint !== next.tint) {
250
- if (typeof next.tint === "number") {
251
- image.setTint(next.tint);
252
- } else {
253
- image.clearTint();
254
- }
255
- }
256
- if (prev.originX !== next.originX || prev.originY !== next.originY) {
257
- const originX = next.originX ?? image.originX;
258
- const originY = next.originY ?? image.originY;
259
- image.setOrigin(originX, originY);
260
- }
261
- const displayWidthChanged = prev.displayWidth !== next.displayWidth;
262
- const displayHeightChanged = prev.displayHeight !== next.displayHeight;
263
- const fitChanged = prev.fit !== next.fit;
264
- if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {
265
- if (typeof next.displayWidth === "number" && typeof next.displayHeight === "number") {
266
- const { scaleX, scaleY } = calculateFitScale$1(
267
- image,
268
- next.displayWidth,
269
- next.displayHeight,
270
- next.fit
271
- );
272
- image.setScale(scaleX, scaleY);
273
- } else if (typeof next.displayWidth === "number") {
274
- const scale = next.displayWidth / image.width;
275
- image.setScale(scale);
276
- } else if (typeof next.displayHeight === "number") {
277
- const scale = next.displayHeight / image.height;
278
- image.setScale(scale, scale);
279
- }
280
- }
281
- }
282
- function applyImageLayout(image, prev, next) {
283
- image.__layoutProps = next;
284
- if (prev.headless !== next.headless) {
285
- image.__getLayoutSize = () => {
286
- if (image.__layoutProps?.headless) {
287
- return { width: 0.01, height: 0.01 };
288
- }
289
- return {
290
- width: image.displayWidth,
291
- height: image.displayHeight
292
- };
293
- };
294
- }
295
- }
296
- function createImageLayout(image, props) {
297
- image.__layoutProps = props;
298
- image.__getLayoutSize = () => {
299
- if (image.__layoutProps?.headless) {
300
- return { width: 0.01, height: 0.01 };
301
- }
302
- return {
303
- width: image.displayWidth,
304
- height: image.displayHeight
305
- };
306
- };
307
- }
308
- const imageCreator = (scene, props) => {
309
- const image = scene.add.image(props.x ?? 0, props.y ?? 0, props.texture, props.frame);
310
- if (props.headless) {
311
- image.setOrigin(0.5, 0.5);
312
- } else {
313
- image.setOrigin(0, 0);
314
- }
315
- if (props.originX !== void 0 || props.originY !== void 0) {
316
- image.setOrigin(props.originX ?? image.originX, props.originY ?? image.originY);
317
- }
318
- const normalizedProps = { ...props };
319
- if (props.headless) {
320
- delete normalizedProps.padding;
321
- delete normalizedProps.margin;
322
- delete normalizedProps.gap;
323
- } else {
324
- if (normalizedProps.rotation !== void 0) {
325
- delete normalizedProps.rotation;
326
- }
327
- }
328
- createTransform(image, normalizedProps);
329
- createPhaser(image, normalizedProps);
330
- if (props.tint !== void 0) {
331
- image.setTint(props.tint);
332
- }
333
- if (props.displayWidth !== void 0 || props.displayHeight !== void 0) {
334
- if (props.displayWidth !== void 0 && props.displayHeight !== void 0) {
335
- const fit = props.fit ?? "fill";
336
- const textureWidth = image.width;
337
- const textureHeight = image.height;
338
- if (textureWidth > 0 && textureHeight > 0) {
339
- if (fit === "fill") {
340
- image.setDisplaySize(props.displayWidth, props.displayHeight);
341
- } else if (fit === "contain") {
342
- const targetAspect = props.displayWidth / props.displayHeight;
343
- const textureAspect = textureWidth / textureHeight;
344
- const scale = targetAspect > textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
345
- image.setScale(scale);
346
- } else if (fit === "cover") {
347
- const targetAspect = props.displayWidth / props.displayHeight;
348
- const textureAspect = textureWidth / textureHeight;
349
- const scale = targetAspect < textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
350
- image.setScale(scale);
351
- }
352
- }
353
- } else if (props.displayWidth !== void 0) {
354
- const scale = props.displayWidth / image.width;
355
- image.setScale(scale);
356
- } else if (props.displayHeight !== void 0) {
357
- const scale = props.displayHeight / image.height;
358
- image.setScale(scale);
359
- }
360
- }
361
- createImageLayout(image, normalizedProps);
362
- if (props.onReady) {
363
- props.onReady(image);
364
- }
365
- return image;
366
- };
367
- const imagePatcher = (node, prev, next) => {
368
- if (prev.headless !== next.headless) {
369
- if (next.headless) {
370
- node.setOrigin(0.5, 0.5);
371
- } else {
372
- node.setOrigin(0, 0);
373
- }
374
- }
375
- const normalizedPrev = { ...prev };
376
- const normalizedNext = { ...next };
377
- if (next.headless) {
378
- delete normalizedNext.padding;
379
- delete normalizedNext.margin;
380
- delete normalizedNext.gap;
381
- } else {
382
- if (normalizedNext.rotation !== void 0) {
383
- delete normalizedNext.rotation;
384
- }
385
- }
386
- if (prev.headless) {
387
- delete normalizedPrev.padding;
388
- delete normalizedPrev.margin;
389
- delete normalizedPrev.gap;
390
- } else {
391
- if (normalizedPrev.rotation !== void 0) {
392
- delete normalizedPrev.rotation;
393
- }
394
- }
395
- applyTransformProps(node, normalizedPrev, normalizedNext);
396
- applyPhaserProps(node, normalizedPrev, normalizedNext);
397
- applyImageProps(node, normalizedPrev, normalizedNext);
398
- applyImageLayout(node, normalizedPrev, normalizedNext);
399
- };
400
- function applyNineSliceProps(nineSlice, prev, next) {
401
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
402
- if (textureChanged && next.texture) {
403
- nineSlice.setTexture(next.texture, next.frame);
404
- }
405
- const sliceChanged = prev.leftWidth !== next.leftWidth || prev.rightWidth !== next.rightWidth || prev.topHeight !== next.topHeight || prev.bottomHeight !== next.bottomHeight;
406
- if (sliceChanged) {
407
- const width = typeof next.width === "number" ? next.width : nineSlice.width;
408
- const height = typeof next.height === "number" ? next.height : nineSlice.height;
409
- nineSlice.setSlices(
410
- width,
411
- height,
412
- next.leftWidth ?? prev.leftWidth ?? 0,
413
- next.rightWidth ?? prev.rightWidth ?? 0,
414
- next.topHeight ?? prev.topHeight,
415
- next.bottomHeight ?? prev.bottomHeight
416
- );
417
- }
418
- const prevWidth = typeof prev.width === "number" ? prev.width : nineSlice.width;
419
- const nextWidth = typeof next.width === "number" ? next.width : nineSlice.width;
420
- const prevHeight = typeof prev.height === "number" ? prev.height : nineSlice.height;
421
- const nextHeight = typeof next.height === "number" ? next.height : nineSlice.height;
422
- if (prevWidth !== nextWidth || prevHeight !== nextHeight) {
423
- nineSlice.setSize(nextWidth, nextHeight);
424
- }
425
- if (prev.tint !== next.tint) {
426
- if (next.tint !== void 0) {
427
- nineSlice.setTint(next.tint);
428
- } else {
429
- nineSlice.clearTint();
430
- }
431
- }
432
- }
433
- function applyNineSliceLayout(nineSlice, prev, next) {
434
- nineSlice.__layoutProps = next;
435
- if (prev.width !== next.width || prev.height !== next.height) {
436
- nineSlice.__getLayoutSize = () => {
437
- return {
438
- width: nineSlice.width,
439
- height: nineSlice.height
440
- };
441
- };
442
- }
443
- }
444
- function createNineSliceLayout(nineSlice, props) {
445
- nineSlice.__layoutProps = props;
446
- nineSlice.__getLayoutSize = () => {
447
- return {
448
- width: nineSlice.width,
449
- height: nineSlice.height
450
- };
451
- };
452
- }
453
- const nineSliceCreator = (scene, props) => {
454
- const initialWidth = typeof props.width === "number" ? props.width : 64;
455
- const initialHeight = typeof props.height === "number" ? props.height : 64;
456
- const nineSlice = scene.add.nineslice(
457
- props.x ?? 0,
458
- props.y ?? 0,
459
- props.texture,
460
- props.frame,
461
- initialWidth,
462
- initialHeight,
463
- props.leftWidth,
464
- props.rightWidth,
465
- props.topHeight,
466
- props.bottomHeight
467
- );
468
- nineSlice.setOrigin(0, 0);
469
- if (props.tint !== void 0) {
470
- nineSlice.setTint(props.tint);
471
- }
472
- createTransform(nineSlice, props);
473
- createPhaser(nineSlice, props);
474
- createNineSliceLayout(nineSlice, props);
475
- return nineSlice;
476
- };
477
- const nineSlicePatcher = (node, prev, next) => {
478
- applyTransformProps(node, prev, next);
479
- applyPhaserProps(node, prev, next);
480
- applyNineSliceProps(node, prev, next);
481
- applyNineSliceLayout(node, prev, next);
482
- };
483
- function getOriginalTextureDimensions(sprite) {
484
- const frame = sprite.frame;
485
- return {
486
- width: frame.width,
487
- height: frame.height
488
- };
489
- }
490
- function calculateFitScale(sprite, targetWidth, targetHeight, fit = "fill") {
491
- const { width: textureWidth, height: textureHeight } = getOriginalTextureDimensions(sprite);
492
- if (textureWidth === 0 || textureHeight === 0) {
493
- return { scaleX: 1, scaleY: 1 };
494
- }
495
- if (fit === "fill") {
496
- return {
497
- scaleX: targetWidth / textureWidth,
498
- scaleY: targetHeight / textureHeight
499
- };
500
- }
501
- const targetAspect = targetWidth / targetHeight;
502
- const textureAspect = textureWidth / textureHeight;
503
- if (fit === "contain") {
504
- const scale = targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
505
- return { scaleX: scale, scaleY: scale };
506
- }
507
- if (fit === "cover") {
508
- const scale = targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
509
- return { scaleX: scale, scaleY: scale };
510
- }
511
- return { scaleX: 1, scaleY: 1 };
512
- }
513
- function applySpriteProps(sprite, prev, next) {
514
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
515
- if (textureChanged && next.texture) {
516
- sprite.setTexture(next.texture, next.frame);
517
- }
518
- if (prev.tint !== next.tint) {
519
- if (typeof next.tint === "number") {
520
- sprite.setTint(next.tint);
521
- } else {
522
- sprite.clearTint();
523
- }
524
- }
525
- if (prev.originX !== next.originX || prev.originY !== next.originY) {
526
- const originX = next.originX ?? sprite.originX;
527
- const originY = next.originY ?? sprite.originY;
528
- sprite.setOrigin(originX, originY);
529
- }
530
- const displayWidthChanged = prev.displayWidth !== next.displayWidth;
531
- const displayHeightChanged = prev.displayHeight !== next.displayHeight;
532
- const fitChanged = prev.fit !== next.fit;
533
- if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {
534
- if (typeof next.displayWidth === "number" && typeof next.displayHeight === "number") {
535
- const fit = next.fit ?? "fill";
536
- if (fit === "fill") {
537
- sprite.setDisplaySize(next.displayWidth, next.displayHeight);
538
- } else {
539
- const { scaleX, scaleY } = calculateFitScale(
540
- sprite,
541
- next.displayWidth,
542
- next.displayHeight,
543
- fit
544
- );
545
- sprite.setScale(scaleX, scaleY);
546
- }
547
- } else if (typeof next.displayWidth === "number") {
548
- const { width: origWidth } = getOriginalTextureDimensions(sprite);
549
- const scale = next.displayWidth / origWidth;
550
- sprite.setScale(scale);
551
- } else if (typeof next.displayHeight === "number") {
552
- const { height: origHeight } = getOriginalTextureDimensions(sprite);
553
- const scale = next.displayHeight / origHeight;
554
- sprite.setScale(scale, scale);
555
- } else {
556
- sprite.setScale(1);
557
- }
558
- }
559
- const animationChanged = prev.animationKey !== next.animationKey || prev.loop !== next.loop || prev.repeatDelay !== next.repeatDelay;
560
- if (animationChanged) {
561
- if (sprite.anims.isPlaying) {
562
- sprite.anims.stop();
563
- }
564
- if (next.animationKey) {
565
- sprite.anims.play({
566
- key: next.animationKey,
567
- repeat: next.loop ? -1 : 0,
568
- repeatDelay: next.repeatDelay ?? 0
569
- });
570
- }
571
- }
572
- const callbacksChanged = prev.onAnimationStart !== next.onAnimationStart || prev.onAnimationComplete !== next.onAnimationComplete || prev.onAnimationRepeat !== next.onAnimationRepeat || prev.onAnimationUpdate !== next.onAnimationUpdate;
573
- if (callbacksChanged) {
574
- sprite.off("animationstart");
575
- sprite.off("animationcomplete");
576
- sprite.off("animationrepeat");
577
- sprite.off("animationupdate");
578
- if (next.onAnimationStart) {
579
- sprite.on("animationstart", (anim) => {
580
- next.onAnimationStart?.(anim.key);
581
- });
582
- }
583
- if (next.onAnimationComplete) {
584
- sprite.on("animationcomplete", (anim) => {
585
- next.onAnimationComplete?.(anim.key);
586
- });
587
- }
588
- if (next.onAnimationRepeat) {
589
- sprite.on("animationrepeat", (anim) => {
590
- next.onAnimationRepeat?.(anim.key);
591
- });
592
- }
593
- if (next.onAnimationUpdate) {
594
- sprite.on(
595
- "animationupdate",
596
- (anim, frame) => {
597
- next.onAnimationUpdate?.(anim.key, frame);
598
- }
599
- );
600
- }
601
- }
602
- }
603
- function applySpriteLayout(sprite, _prev, next) {
604
- sprite.__layoutProps = next;
605
- }
606
- function createSpriteLayout(sprite, props) {
607
- sprite.__layoutProps = props;
608
- sprite.__getLayoutSize = () => {
609
- return { width: 0.01, height: 0.01 };
610
- };
611
- }
612
- const spriteCreator = (scene, props) => {
613
- const sprite = scene.add.sprite(props.x ?? 0, props.y ?? 0, props.texture, props.frame);
614
- sprite.setOrigin(0.5, 0.5);
615
- if (props.originX !== void 0 || props.originY !== void 0) {
616
- sprite.setOrigin(props.originX ?? sprite.originX, props.originY ?? sprite.originY);
617
- }
618
- createTransform(sprite, props);
619
- createPhaser(sprite, props);
620
- if (props.tint !== void 0) {
621
- sprite.setTint(props.tint);
622
- }
623
- if (props.displayWidth !== void 0 || props.displayHeight !== void 0) {
624
- if (props.displayWidth !== void 0 && props.displayHeight !== void 0) {
625
- const fit = props.fit ?? "fill";
626
- const textureWidth = sprite.width;
627
- const textureHeight = sprite.height;
628
- if (textureWidth > 0 && textureHeight > 0) {
629
- if (fit === "fill") {
630
- sprite.setDisplaySize(props.displayWidth, props.displayHeight);
631
- } else if (fit === "contain") {
632
- const targetAspect = props.displayWidth / props.displayHeight;
633
- const textureAspect = textureWidth / textureHeight;
634
- const scale = targetAspect > textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
635
- sprite.setScale(scale);
636
- } else if (fit === "cover") {
637
- const targetAspect = props.displayWidth / props.displayHeight;
638
- const textureAspect = textureWidth / textureHeight;
639
- const scale = targetAspect < textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
640
- sprite.setScale(scale);
641
- }
642
- }
643
- } else if (props.displayWidth !== void 0) {
644
- const scale = props.displayWidth / sprite.width;
645
- sprite.setScale(scale);
646
- } else if (props.displayHeight !== void 0) {
647
- const scale = props.displayHeight / sprite.height;
648
- sprite.setScale(scale);
649
- }
650
- }
651
- if (props.animationKey) {
652
- if (sprite.scene && sprite.scene.anims.exists(props.animationKey)) {
653
- sprite.anims.play({
654
- key: props.animationKey,
655
- repeat: props.loop ? -1 : 0,
656
- repeatDelay: props.repeatDelay ?? 0
657
- });
658
- }
659
- }
660
- if (props.onAnimationStart) {
661
- sprite.on("animationstart", (anim) => {
662
- props.onAnimationStart?.(anim.key);
663
- });
664
- }
665
- if (props.onAnimationComplete) {
666
- sprite.on("animationcomplete", (anim) => {
667
- props.onAnimationComplete?.(anim.key);
668
- });
669
- }
670
- if (props.onAnimationRepeat) {
671
- sprite.on("animationrepeat", (anim) => {
672
- props.onAnimationRepeat?.(anim.key);
673
- });
674
- }
675
- if (props.onAnimationUpdate) {
676
- sprite.on(
677
- "animationupdate",
678
- (anim, frame) => {
679
- props.onAnimationUpdate?.(anim.key, frame);
680
- }
681
- );
682
- }
683
- createSpriteLayout(sprite, props);
684
- if (props.onReady) {
685
- props.onReady(sprite);
686
- }
687
- return sprite;
688
- };
689
- const spritePatcher = (node, prev, next) => {
690
- applyTransformProps(node, prev, next);
691
- applyPhaserProps(node, prev, next);
692
- applySpriteProps(node, prev, next);
693
- applySpriteLayout(node, prev, next);
694
- };
695
78
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
696
79
  function getDefaultExportFromCjs(x) {
697
80
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -6766,213 +6149,6 @@ function clampSize(size, minSize, maxSize, parentSize, fallbackSize, parentPaddi
6766
6149
  }
6767
6150
  return clamped;
6768
6151
  }
6769
- function applyTextProps(node, prev, next) {
6770
- if (node.active === false || node.scene && !node.scene.sys.game) {
6771
- return;
6772
- }
6773
- let needsUpdate = false;
6774
- if (prev.text !== next.text && typeof next.text === "string") {
6775
- node.setText(next.text);
6776
- needsUpdate = true;
6777
- }
6778
- if (next.style !== void 0 && !equal(next.style, prev.style || {})) {
6779
- try {
6780
- node.setStyle(next.style);
6781
- needsUpdate = true;
6782
- } catch (error) {
6783
- console.warn("Failed to apply text style (scene may be transitioning):", error);
6784
- }
6785
- }
6786
- if (next.maxWidth !== prev.maxWidth && next.maxWidth !== void 0) {
6787
- const viewport = viewportRegistry.getViewport();
6788
- const parsedMaxWidth = parseSize(next.maxWidth);
6789
- const resolvedMaxWidth = resolveSize(parsedMaxWidth, viewport?.width, void 0, void 0);
6790
- node.setWordWrapWidth(resolvedMaxWidth, true);
6791
- needsUpdate = true;
6792
- }
6793
- if (prev.style !== next.style && next.style !== void 0) {
6794
- try {
6795
- node.setStyle(next.style);
6796
- needsUpdate = true;
6797
- } catch (error) {
6798
- console.warn("Failed to apply text style (scene may be transitioning):", error);
6799
- }
6800
- }
6801
- if (needsUpdate && node.updateText) {
6802
- node.updateText();
6803
- }
6804
- }
6805
- function applyTextLayout(text, _prev, next) {
6806
- text.__layoutProps = next;
6807
- text.__getLayoutSize = () => {
6808
- if (text.__layoutProps?.headless) {
6809
- return { width: 0.01, height: 0.01 };
6810
- }
6811
- return {
6812
- width: text.width,
6813
- height: text.height
6814
- };
6815
- };
6816
- }
6817
- function createTextLayout(text, props) {
6818
- text.__layoutProps = props;
6819
- text.__getLayoutSize = () => {
6820
- if (text.__layoutProps?.headless) {
6821
- return { width: 0.01, height: 0.01 };
6822
- }
6823
- return {
6824
- width: text.width,
6825
- height: text.height
6826
- };
6827
- };
6828
- }
6829
- const textCreator = (scene, props) => {
6830
- const text = scene.add.text(props.x ?? 0, props.y ?? 0, props.text ?? "", props.style);
6831
- if (props.headless) {
6832
- text.setOrigin(0.5, 0.5);
6833
- } else {
6834
- text.setOrigin(0, 0);
6835
- }
6836
- const normalizedProps = { ...props };
6837
- if (props.headless) {
6838
- delete normalizedProps.padding;
6839
- delete normalizedProps.margin;
6840
- delete normalizedProps.gap;
6841
- } else {
6842
- if (normalizedProps.rotation !== void 0) {
6843
- delete normalizedProps.rotation;
6844
- }
6845
- }
6846
- createTransform(text, normalizedProps);
6847
- createPhaser(text, normalizedProps);
6848
- createTextLayout(text, normalizedProps);
6849
- return text;
6850
- };
6851
- const textPatcher = (node, prev, next) => {
6852
- if (prev.headless !== next.headless) {
6853
- if (next.headless) {
6854
- node.setOrigin(0.5, 0.5);
6855
- } else {
6856
- node.setOrigin(0, 0);
6857
- }
6858
- }
6859
- const normalizedPrev = { ...prev };
6860
- const normalizedNext = { ...next };
6861
- if (next.headless) {
6862
- delete normalizedNext.padding;
6863
- delete normalizedNext.margin;
6864
- delete normalizedNext.gap;
6865
- } else {
6866
- if (normalizedNext.rotation !== void 0) {
6867
- delete normalizedNext.rotation;
6868
- }
6869
- }
6870
- if (prev.headless) {
6871
- delete normalizedPrev.padding;
6872
- delete normalizedPrev.margin;
6873
- delete normalizedPrev.gap;
6874
- } else {
6875
- if (normalizedPrev.rotation !== void 0) {
6876
- delete normalizedPrev.rotation;
6877
- }
6878
- }
6879
- applyTransformProps(node, normalizedPrev, normalizedNext);
6880
- applyPhaserProps(node, normalizedPrev, normalizedNext);
6881
- applyTextProps(node, normalizedPrev, normalizedNext);
6882
- applyTextLayout(node, normalizedPrev, normalizedNext);
6883
- };
6884
- const tileSpriteCreator = (_scene, _props) => {
6885
- throw new Error(
6886
- "TileSprite component not implemented yet. This is a placeholder for architecture planning."
6887
- );
6888
- };
6889
- const tileSpritePatcher = (_node, _prev, _next) => {
6890
- throw new Error(
6891
- "TileSprite component not implemented yet. This is a placeholder for architecture planning."
6892
- );
6893
- };
6894
- function applyBackgroundProps(container, prev, next) {
6895
- const prevBgColor = prev.backgroundColor;
6896
- const nextBgColor = next.backgroundColor;
6897
- const prevBgAlpha = prev.backgroundAlpha ?? 1;
6898
- const nextBgAlpha = next.backgroundAlpha ?? 1;
6899
- const prevWidth = typeof prev.width === "number" ? prev.width : 100;
6900
- const nextWidth = typeof next.width === "number" ? next.width : 100;
6901
- const prevHeight = typeof prev.height === "number" ? prev.height : 100;
6902
- const nextHeight = typeof next.height === "number" ? next.height : 100;
6903
- const prevCornerRadius = prev.cornerRadius ?? 0;
6904
- const nextCornerRadius = next.cornerRadius ?? 0;
6905
- const prevBorderColor = prev.borderColor;
6906
- const nextBorderColor = next.borderColor;
6907
- const prevBorderWidth = prev.borderWidth ?? 0;
6908
- const nextBorderWidth = next.borderWidth ?? 0;
6909
- const prevBorderAlpha = prev.borderAlpha ?? 1;
6910
- const nextBorderAlpha = next.borderAlpha ?? 1;
6911
- const prevHasBorder = prevBorderWidth > 0 && prevBorderColor !== void 0;
6912
- const nextHasBorder = nextBorderWidth > 0 && nextBorderColor !== void 0;
6913
- const prevHasGraphics = prevBgColor !== void 0 || prevHasBorder;
6914
- const nextHasGraphics = nextBgColor !== void 0 || nextHasBorder;
6915
- if (prevHasGraphics && !nextHasGraphics) {
6916
- if (container.__background) {
6917
- container.__background.destroy();
6918
- delete container.__background;
6919
- }
6920
- } else if (!prevHasGraphics && nextHasGraphics) {
6921
- if (container.scene) {
6922
- const background = container.scene.add.graphics();
6923
- if (nextBgColor !== void 0) {
6924
- background.fillStyle(nextBgColor, nextBgAlpha);
6925
- }
6926
- if (nextHasBorder) {
6927
- background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha);
6928
- }
6929
- if (nextCornerRadius !== 0) {
6930
- if (nextBgColor !== void 0) {
6931
- background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6932
- }
6933
- if (nextHasBorder) {
6934
- background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6935
- }
6936
- } else {
6937
- if (nextBgColor !== void 0) {
6938
- background.fillRect(0, 0, nextWidth, nextHeight);
6939
- }
6940
- if (nextHasBorder) {
6941
- background.strokeRect(0, 0, nextWidth, nextHeight);
6942
- }
6943
- }
6944
- container.addAt(background, 0);
6945
- container.__background = background;
6946
- background.__isBackground = true;
6947
- }
6948
- } else if (container.__background && nextHasGraphics) {
6949
- const needsRedraw = prevBgColor !== nextBgColor || prevBgAlpha !== nextBgAlpha || prevWidth !== nextWidth || prevHeight !== nextHeight || prevCornerRadius !== nextCornerRadius || prevBorderWidth !== nextBorderWidth || prevBorderColor !== nextBorderColor || prevBorderAlpha !== nextBorderAlpha;
6950
- if (needsRedraw) {
6951
- container.__background.clear();
6952
- if (nextBgColor !== void 0) {
6953
- container.__background.fillStyle(nextBgColor, nextBgAlpha);
6954
- }
6955
- if (nextHasBorder) {
6956
- container.__background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha);
6957
- }
6958
- if (nextCornerRadius !== 0) {
6959
- if (nextBgColor !== void 0) {
6960
- container.__background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6961
- }
6962
- if (nextHasBorder) {
6963
- container.__background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6964
- }
6965
- } else {
6966
- if (nextBgColor !== void 0) {
6967
- container.__background.fillRect(0, 0, nextWidth, nextHeight);
6968
- }
6969
- if (nextHasBorder) {
6970
- container.__background.strokeRect(0, 0, nextWidth, nextHeight);
6971
- }
6972
- }
6973
- }
6974
- }
6975
- }
6976
6152
  const DEFAULT_GESTURE_CONFIG = {
6977
6153
  longPressDuration: 500,
6978
6154
  doubleTapDelay: 300,
@@ -7232,8 +6408,8 @@ class GestureManager {
7232
6408
  this.activePointerDown = {
7233
6409
  pointerId: pointer.id,
7234
6410
  container: state.container,
7235
- startX: pointer.x,
7236
- startY: pointer.y
6411
+ startX: pointer.worldX,
6412
+ startY: pointer.worldY
7237
6413
  };
7238
6414
  state.longPressTriggered = false;
7239
6415
  state.pointerDownTime = Date.now();
@@ -7255,12 +6431,31 @@ class GestureManager {
7255
6431
  }
7256
6432
  }, state.config.longPressDuration);
7257
6433
  }
7258
- state.pointerDownPosition = { x: pointer.x, y: pointer.y };
6434
+ state.pointerDownPosition = { x: pointer.worldX, y: pointer.worldY };
7259
6435
  }
7260
6436
  }
7261
6437
  }
7262
6438
  if (hitContainers.size > 0) {
7263
6439
  this.activeContainersForMove.set(pointer.id, hitContainers);
6440
+ this.bubbleEvent(
6441
+ pointer,
6442
+ "onTouchMove",
6443
+ (targetState, targetLocalPos) => {
6444
+ const isInside = this.isPointerInContainer(pointer, targetState);
6445
+ const data = this.createEventData(
6446
+ pointer,
6447
+ targetLocalPos.x,
6448
+ targetLocalPos.y,
6449
+ targetState.hitArea.width,
6450
+ targetState.hitArea.height,
6451
+ { dx: 0, dy: 0, isInside, state: "start" }
6452
+ );
6453
+ targetState.callbacks.onTouchMove?.(data);
6454
+ targetState.isFirstMove = false;
6455
+ return data.isPropagationStopped();
6456
+ },
6457
+ hitContainers
6458
+ );
7264
6459
  }
7265
6460
  }
7266
6461
  /**
@@ -7282,8 +6477,8 @@ class GestureManager {
7282
6477
  const touchDuration = state.pointerDownTime ? Date.now() - state.pointerDownTime : 0;
7283
6478
  const isTouchTooLong = touchDuration > state.config.maxTouchDuration;
7284
6479
  const last = this.lastPointerPositions.get(pointer.id);
7285
- const dx = last ? pointer.x - last.x : 0;
7286
- const dy = last ? pointer.y - last.y : 0;
6480
+ const dx = last ? pointer.worldX - last.x : 0;
6481
+ const dy = last ? pointer.worldY - last.y : 0;
7287
6482
  const hitContainers = this.activeContainersForMove.get(pointer.id);
7288
6483
  this.bubbleEvent(
7289
6484
  pointer,
@@ -7419,8 +6614,8 @@ class GestureManager {
7419
6614
  state.longPressTimer = void 0;
7420
6615
  }
7421
6616
  const last = this.lastPointerPositions.get(pointer.id);
7422
- const dx = last ? pointer.x - last.x : 0;
7423
- const dy = last ? pointer.y - last.y : 0;
6617
+ const dx = last ? pointer.worldX - last.x : 0;
6618
+ const dy = last ? pointer.worldY - last.y : 0;
7424
6619
  const hitContainers = this.activeContainersForMove.get(pointer.id);
7425
6620
  this.bubbleEvent(
7426
6621
  pointer,
@@ -7458,9 +6653,9 @@ class GestureManager {
7458
6653
  */
7459
6654
  handlePointerMove(pointer) {
7460
6655
  const last = this.lastPointerPositions.get(pointer.id);
7461
- const dx = last ? pointer.x - last.x : 0;
7462
- const dy = last ? pointer.y - last.y : 0;
7463
- this.lastPointerPositions.set(pointer.id, { x: pointer.x, y: pointer.y });
6656
+ const dx = last ? pointer.worldX - last.x : 0;
6657
+ const dy = last ? pointer.worldY - last.y : 0;
6658
+ this.lastPointerPositions.set(pointer.id, { x: pointer.worldX, y: pointer.worldY });
7464
6659
  this.detectHoverChanges(pointer);
7465
6660
  if (!this.activePointerDown || pointer.id !== this.activePointerDown.pointerId) {
7466
6661
  return;
@@ -7534,7 +6729,7 @@ class GestureManager {
7534
6729
  getLocalPosition(pointer, container) {
7535
6730
  const matrix = container.getWorldTransformMatrix();
7536
6731
  const inverseMatrix = matrix.invert();
7537
- const localPos = inverseMatrix.transformPoint(pointer.x, pointer.y);
6732
+ const localPos = inverseMatrix.transformPoint(pointer.worldX, pointer.worldY);
7538
6733
  return { x: localPos.x, y: localPos.y };
7539
6734
  }
7540
6735
  /**
@@ -7604,6 +6799,7 @@ class GestureManager {
7604
6799
  const scaleY = canvas.height / rect.height;
7605
6800
  pointer.x = (event.clientX - rect.left) * scaleX;
7606
6801
  pointer.y = (event.clientY - rect.top) * scaleY;
6802
+ pointer.updateWorldPoint(pointer.camera ?? this.scene.cameras.main);
7607
6803
  const containersUnderPointer = [];
7608
6804
  Array.from(this.containers.values()).forEach((state, originalIndex) => {
7609
6805
  if (!state.callbacks.onWheel) return;
@@ -7704,83 +6900,6 @@ function getGestureManager(scene) {
7704
6900
  }
7705
6901
  return manager;
7706
6902
  }
7707
- function applyGesturesProps(scene, container, prev, next) {
7708
- if (!scene || !scene.sys || !scene.data) {
7709
- console.warn("applyGesturesProps: Invalid scene or scene not initialized");
7710
- return;
7711
- }
7712
- if (!scene.sys.isActive() || scene.sys.game === null) {
7713
- console.warn("applyGesturesProps: Scene is not active or game is null");
7714
- return;
7715
- }
7716
- const hasAnyGesture = !!(next.onTouch || next.onTouchOutside || next.onTouchMove || next.onDoubleTap || next.onLongPress || next.onHoverStart || next.onHoverEnd || next.onWheel);
7717
- const hadAnyGesture = !!(prev.onTouch || prev.onTouchOutside || prev.onTouchMove || prev.onDoubleTap || prev.onLongPress || prev.onHoverStart || prev.onHoverEnd || prev.onWheel);
7718
- const prevEnabled = hadAnyGesture && prev.enableGestures !== false;
7719
- const nextEnabled = hasAnyGesture && next.enableGestures !== false;
7720
- const manager = getGestureManager(scene);
7721
- if (!prevEnabled && nextEnabled && hasAnyGesture) {
7722
- const containerWithLayout = container;
7723
- let width = 100;
7724
- let height = 100;
7725
- if (containerWithLayout.__getLayoutSize) {
7726
- const size = containerWithLayout.__getLayoutSize();
7727
- width = size.width;
7728
- height = size.height;
7729
- } else {
7730
- const bounds = container.getBounds();
7731
- width = bounds.width || 100;
7732
- height = bounds.height || 100;
7733
- }
7734
- const hitArea = new Phaser$1.Geom.Rectangle(0, 0, width, height);
7735
- const callbacks = {};
7736
- if (next.onTouch) callbacks.onTouch = next.onTouch;
7737
- if (next.onTouchOutside) callbacks.onTouchOutside = next.onTouchOutside;
7738
- if (next.onTouchMove) callbacks.onTouchMove = next.onTouchMove;
7739
- if (next.onDoubleTap) callbacks.onDoubleTap = next.onDoubleTap;
7740
- if (next.onLongPress) callbacks.onLongPress = next.onLongPress;
7741
- if (next.onHoverStart) callbacks.onHoverStart = next.onHoverStart;
7742
- if (next.onHoverEnd) callbacks.onHoverEnd = next.onHoverEnd;
7743
- if (next.onWheel) callbacks.onWheel = next.onWheel;
7744
- const config = {};
7745
- if (next.longPressDuration !== void 0) config.longPressDuration = next.longPressDuration;
7746
- if (next.doubleTapDelay !== void 0) config.doubleTapDelay = next.doubleTapDelay;
7747
- manager.registerContainer(container, callbacks, hitArea, config);
7748
- return;
7749
- }
7750
- if (prevEnabled && (!nextEnabled || !hasAnyGesture)) {
7751
- manager.unregisterContainer(container);
7752
- return;
7753
- }
7754
- if (nextEnabled && hasAnyGesture) {
7755
- const callbacksChanged = prev.onTouch !== next.onTouch || prev.onTouchOutside !== next.onTouchOutside || prev.onTouchMove !== next.onTouchMove || prev.onDoubleTap !== next.onDoubleTap || prev.onLongPress !== next.onLongPress || prev.onHoverStart !== next.onHoverStart || prev.onHoverEnd !== next.onHoverEnd || prev.onWheel !== next.onWheel;
7756
- if (callbacksChanged) {
7757
- const callbacks = {};
7758
- if (next.onTouch) callbacks.onTouch = next.onTouch;
7759
- if (next.onTouchOutside) callbacks.onTouchOutside = next.onTouchOutside;
7760
- if (next.onTouchMove) callbacks.onTouchMove = next.onTouchMove;
7761
- if (next.onDoubleTap) callbacks.onDoubleTap = next.onDoubleTap;
7762
- if (next.onLongPress) callbacks.onLongPress = next.onLongPress;
7763
- if (next.onHoverStart) callbacks.onHoverStart = next.onHoverStart;
7764
- if (next.onHoverEnd) callbacks.onHoverEnd = next.onHoverEnd;
7765
- if (next.onWheel) callbacks.onWheel = next.onWheel;
7766
- manager.updateCallbacks(container, callbacks);
7767
- }
7768
- const containerWithLayout = container;
7769
- let width = 100;
7770
- let height = 100;
7771
- if (containerWithLayout.__getLayoutSize) {
7772
- const size = containerWithLayout.__getLayoutSize();
7773
- width = size.width;
7774
- height = size.height;
7775
- } else {
7776
- const bounds = container.getBounds();
7777
- width = bounds.width || 100;
7778
- height = bounds.height || 100;
7779
- }
7780
- const hitArea = new Phaser$1.Geom.Rectangle(0, 0, width, height);
7781
- manager.updateHitArea(container, hitArea);
7782
- }
7783
- }
7784
6903
  function normalizeEdgeInsets(value) {
7785
6904
  if (value === void 0) {
7786
6905
  return {};
@@ -8856,10 +7975,57 @@ const strategies = {
8856
7975
  row: new RowLayoutStrategy(),
8857
7976
  stack: new StackLayoutStrategy()
8858
7977
  };
7978
+ const LAYOUT_CYCLE_EPSILON = 0.5;
7979
+ const LAYOUT_CYCLE_TIME_MS = 100;
7980
+ const LAYOUT_CYCLE_MAX = 5;
7981
+ const LAYOUT_MAX_SIZE = 2e5;
7982
+ const layoutCycleGuard = /* @__PURE__ */ new WeakMap();
7983
+ function isCloseSize(a, b, epsilon) {
7984
+ return Math.abs(a.width - b.width) < epsilon && Math.abs(a.height - b.height) < epsilon;
7985
+ }
8859
7986
  function invalidateParentLayoutIfNeeded(container, oldSize, newWidth, newHeight) {
8860
- if (!oldSize || oldSize.width === newWidth && oldSize.height === newHeight) {
7987
+ if (!oldSize || Math.abs(oldSize.width - newWidth) < LAYOUT_CYCLE_EPSILON && Math.abs(oldSize.height - newHeight) < LAYOUT_CYCLE_EPSILON) {
7988
+ return;
7989
+ }
7990
+ if (!Number.isFinite(newWidth) || !Number.isFinite(newHeight) || newWidth > LAYOUT_MAX_SIZE || newHeight > LAYOUT_MAX_SIZE) {
7991
+ const containerWithProps = container;
7992
+ DebugLogger.warn("layout", "Runaway layout size detected, skipping parent invalidation", {
7993
+ oldSize,
7994
+ newSize: { width: newWidth, height: newHeight },
7995
+ containerProps: containerWithProps.__layoutProps,
7996
+ childCount: containerWithProps.list?.length ?? 0
7997
+ });
8861
7998
  return;
8862
7999
  }
8000
+ const newSize = { width: newWidth, height: newHeight };
8001
+ const now = Date.now();
8002
+ const guard = layoutCycleGuard.get(container);
8003
+ if (guard) {
8004
+ const repeatsPrev = guard.prev ? isCloseSize(guard.prev, newSize, LAYOUT_CYCLE_EPSILON) : false;
8005
+ if (repeatsPrev && now - guard.lastTime < LAYOUT_CYCLE_TIME_MS) {
8006
+ guard.count += 1;
8007
+ } else {
8008
+ guard.count = 0;
8009
+ }
8010
+ guard.prev = guard.last;
8011
+ guard.last = newSize;
8012
+ guard.lastTime = now;
8013
+ layoutCycleGuard.set(container, guard);
8014
+ if (guard.count >= LAYOUT_CYCLE_MAX) {
8015
+ DebugLogger.warn("layout", "Layout cycle detected, skipping parent invalidation", {
8016
+ container,
8017
+ oldSize,
8018
+ newSize
8019
+ });
8020
+ return;
8021
+ }
8022
+ } else {
8023
+ layoutCycleGuard.set(container, {
8024
+ last: newSize,
8025
+ count: 0,
8026
+ lastTime: now
8027
+ });
8028
+ }
8863
8029
  const parent = container.parentContainer;
8864
8030
  if (!parent || !parent.__layoutProps) {
8865
8031
  return;
@@ -9244,87 +8410,6 @@ function calculateLayoutImmediate(container, containerProps, parentSize, parentP
9244
8410
  function calculateLayout(container, containerProps, parentSize, parentPadding) {
9245
8411
  LayoutBatchQueue.schedule(container, containerProps, parentSize, parentPadding);
9246
8412
  }
9247
- function updateGestureHitAreaIfNeeded(node) {
9248
- const containerWithLayout = node;
9249
- if (!containerWithLayout.__getLayoutSize) return;
9250
- try {
9251
- const manager = getGestureManager(containerWithLayout.scene);
9252
- const size = containerWithLayout.__getLayoutSize();
9253
- const hitArea = new Phaser.Geom.Rectangle(0, 0, size.width, size.height);
9254
- manager.updateHitArea(node, hitArea);
9255
- } catch {
9256
- }
9257
- }
9258
- const LAYOUT_RELEVANT_PROPS = [
9259
- "width",
9260
- "height",
9261
- "minWidth",
9262
- "maxWidth",
9263
- "minHeight",
9264
- "maxHeight",
9265
- "flex",
9266
- "margin",
9267
- "padding",
9268
- "gap",
9269
- "direction",
9270
- "justifyContent",
9271
- "alignItems",
9272
- "overflow"
9273
- ];
9274
- const DEEP_COMPARE_PROPS$1 = /* @__PURE__ */ new Set(["margin", "padding"]);
9275
- function hasLayoutPropsChanged$1(prev, next) {
9276
- for (const prop of LAYOUT_RELEVANT_PROPS) {
9277
- const oldVal = prev[prop];
9278
- const newVal = next[prop];
9279
- if (DEEP_COMPARE_PROPS$1.has(prop)) {
9280
- if (!equal(oldVal, newVal)) {
9281
- return true;
9282
- }
9283
- } else {
9284
- if (oldVal !== newVal) {
9285
- return true;
9286
- }
9287
- }
9288
- }
9289
- return false;
9290
- }
9291
- function getParentLayoutContext(node) {
9292
- const parent = node.parentContainer;
9293
- if (parent && parent.__layoutProps && parent.__getLayoutSize) {
9294
- const parentSize = parent.__getLayoutSize();
9295
- const padding = parent.__layoutProps.padding ?? 0;
9296
- const normPadding = typeof padding === "number" ? { left: padding, right: padding, top: padding, bottom: padding } : {
9297
- left: padding.left ?? 0,
9298
- right: padding.right ?? 0,
9299
- top: padding.top ?? 0,
9300
- bottom: padding.bottom ?? 0
9301
- };
9302
- return {
9303
- parentSize: {
9304
- width: parentSize.width - normPadding.left - normPadding.right,
9305
- height: parentSize.height - normPadding.top - normPadding.bottom
9306
- }
9307
- // Parent already provides content-area, no padding offset needed
9308
- };
9309
- }
9310
- if (node.scene) {
9311
- return {
9312
- parentSize: {
9313
- width: node.scene.scale.width,
9314
- height: node.scene.scale.height
9315
- }
9316
- };
9317
- }
9318
- return {};
9319
- }
9320
- function applyLayoutProps(node, prev, next) {
9321
- node.__layoutProps = next;
9322
- if (hasLayoutPropsChanged$1(prev, next)) {
9323
- const { parentSize, parentPadding } = getParentLayoutContext(node);
9324
- calculateLayout(node, next, parentSize, parentPadding);
9325
- updateGestureHitAreaIfNeeded(node);
9326
- }
9327
- }
9328
8413
  class HexColor extends String {
9329
8414
  /**
9330
8415
  * Convert to Phaser number format
@@ -9818,6 +8903,10 @@ function buildDefaultTheme(colors) {
9818
8903
  alpha: 1,
9819
8904
  visible: true
9820
8905
  },
8906
+ particles: {
8907
+ alpha: 1,
8908
+ visible: true
8909
+ },
9821
8910
  // Public API (uppercase)
9822
8911
  View: {
9823
8912
  alpha: 1,
@@ -9849,6 +8938,10 @@ function buildDefaultTheme(colors) {
9849
8938
  alpha: 1,
9850
8939
  visible: true
9851
8940
  },
8941
+ Particles: {
8942
+ alpha: 1,
8943
+ visible: true
8944
+ },
9852
8945
  RadioButton: {
9853
8946
  selectedColor: colors.primary.DEFAULT.toNumber(),
9854
8947
  color: colors.border.medium.toNumber(),
@@ -10033,6 +9126,41 @@ function buildDefaultTheme(colors) {
10033
9126
  fontSize: "18px"
10034
9127
  }
10035
9128
  },
9129
+ Tabs: {
9130
+ tabListStyle: {
9131
+ backgroundColor: colors.surface.dark.toNumber(),
9132
+ padding: { left: 8, right: 8, top: 8, bottom: 0 },
9133
+ cornerRadius: { tl: 6, tr: 6, bl: 0, br: 0 },
9134
+ width: "fill",
9135
+ gap: 10,
9136
+ alignItems: "end",
9137
+ justifyContent: "start"
9138
+ },
9139
+ tabStyle: {
9140
+ backgroundColor: colors.surface.medium.toNumber(),
9141
+ borderColor: colors.border.medium.toNumber(),
9142
+ borderWidth: 1,
9143
+ padding: { left: 8, right: 8, top: 8, bottom: 3 },
9144
+ cornerRadius: { tl: 6, tr: 6, bl: 0, br: 0 }
9145
+ },
9146
+ tabActiveStyle: {
9147
+ padding: { left: 8, right: 8, top: 8, bottom: 8 },
9148
+ backgroundColor: colors.primary.DEFAULT.toNumber(),
9149
+ borderColor: colors.primary.dark.toNumber(),
9150
+ borderWidth: 2
9151
+ },
9152
+ tabDisabledStyle: {
9153
+ alpha: 0.4
9154
+ },
9155
+ panelStyle: {
9156
+ backgroundColor: colors.surface.light.toNumber(),
9157
+ borderColor: colors.border.medium.toNumber(),
9158
+ borderWidth: 1,
9159
+ padding: 10,
9160
+ cornerRadius: { tl: 0, tr: 0, bl: 6, br: 6 },
9161
+ width: "fill"
9162
+ }
9163
+ },
10036
9164
  NineSliceButton: {},
10037
9165
  CharText: {
10038
9166
  charSpacing: 0,
@@ -10487,442 +9615,6 @@ function getThemedProps(componentName, localTheme, explicitProps) {
10487
9615
  nestedTheme: mergedNestedThemes
10488
9616
  };
10489
9617
  }
10490
- const tooltipStates = /* @__PURE__ */ new Map();
10491
- function calculateTooltipPosition(targetBounds, position, offset, tooltipWidth, tooltipHeight) {
10492
- const viewport = {
10493
- width: window.innerWidth,
10494
- height: window.innerHeight
10495
- };
10496
- let x = 0;
10497
- let y = 0;
10498
- switch (position) {
10499
- case "top":
10500
- x = targetBounds.centerX - tooltipWidth / 2;
10501
- y = targetBounds.top - tooltipHeight - offset;
10502
- break;
10503
- case "bottom":
10504
- x = targetBounds.centerX - tooltipWidth / 2;
10505
- y = targetBounds.bottom + offset;
10506
- break;
10507
- case "left":
10508
- x = targetBounds.left - tooltipWidth - offset;
10509
- y = targetBounds.centerY - tooltipHeight / 2;
10510
- break;
10511
- case "right":
10512
- x = targetBounds.right + offset;
10513
- y = targetBounds.centerY - tooltipHeight / 2;
10514
- break;
10515
- }
10516
- x = Math.max(8, Math.min(x, viewport.width - tooltipWidth - 8));
10517
- y = Math.max(8, Math.min(y, viewport.height - tooltipHeight - 8));
10518
- return { x, y };
10519
- }
10520
- function showTooltip(scene, container, config) {
10521
- const state = tooltipStates.get(container);
10522
- if (!state || state.isVisible) return;
10523
- state.isVisible = true;
10524
- state.currentConfig = config;
10525
- const theme = themeRegistry.getGlobalTheme();
10526
- const tooltipTheme = theme.Tooltip || {};
10527
- const position = config.position ?? tooltipTheme.position ?? "top";
10528
- const offset = config.offset ?? tooltipTheme.offset ?? 8;
10529
- const content = config.content;
10530
- const targetBounds = container.getBounds();
10531
- const textStyle = tooltipTheme.textStyle ?? {
10532
- fontSize: "14px",
10533
- fontFamily: "Arial",
10534
- color: "#ffffff",
10535
- padding: { x: 8, y: 4 }
10536
- };
10537
- const { backgroundColor: bgColor, ...styleWithoutBg } = textStyle;
10538
- const text = scene.add.text(0, 0, content, styleWithoutBg);
10539
- text.setOrigin(0.5);
10540
- const padding = textStyle.padding ?? { x: 8, y: 4 };
10541
- const paddingX = typeof padding === "number" ? padding : padding.x ?? 8;
10542
- const paddingY = typeof padding === "number" ? padding : padding.y ?? 4;
10543
- const textWidth = text.width;
10544
- const textHeight = text.height;
10545
- const bgWidth = textWidth + paddingX * 2;
10546
- const bgHeight = textHeight + paddingY * 2;
10547
- const cornerRadius = tooltipTheme.cornerRadius ?? 6;
10548
- const graphics = scene.add.graphics();
10549
- const bg = bgColor ?? "#000000dd";
10550
- let fillColor = 0;
10551
- let fillAlpha = 0.87;
10552
- if (typeof bg === "string") {
10553
- if (bg.startsWith("#")) {
10554
- const hex2 = bg.slice(1);
10555
- if (hex2.length === 8) {
10556
- fillColor = parseInt(hex2.slice(0, 6), 16);
10557
- fillAlpha = parseInt(hex2.slice(6, 8), 16) / 255;
10558
- } else if (hex2.length === 6) {
10559
- fillColor = parseInt(hex2, 16);
10560
- fillAlpha = 1;
10561
- }
10562
- }
10563
- }
10564
- graphics.fillStyle(fillColor, fillAlpha);
10565
- graphics.fillRoundedRect(-bgWidth / 2, -bgHeight / 2, bgWidth, bgHeight, cornerRadius);
10566
- const tooltipContainer = scene.add.container(0, 0, [graphics, text]);
10567
- tooltipContainer.setDepth(1e4);
10568
- const textBounds = tooltipContainer.getBounds();
10569
- const pos = calculateTooltipPosition(
10570
- targetBounds,
10571
- position,
10572
- offset,
10573
- textBounds.width,
10574
- textBounds.height
10575
- );
10576
- const themeAnim = tooltipTheme.animation || {};
10577
- const anim = config.animation || {};
10578
- const fadeInDuration = anim.fadeIn ?? themeAnim.fadeIn ?? 200;
10579
- const moveOffset = {
10580
- dx: anim.move?.dx ?? themeAnim.move?.dx ?? 0,
10581
- dy: anim.move?.dy ?? themeAnim.move?.dy ?? 0
10582
- };
10583
- const pulse = anim.pulse ?? themeAnim.pulse ?? false;
10584
- const pulseScale = anim.pulseScale ?? [0.75, 1.25];
10585
- tooltipContainer.setPosition(
10586
- pos.x + textBounds.width / 2 - moveOffset.dx,
10587
- pos.y + textBounds.height / 2 - moveOffset.dy
10588
- );
10589
- tooltipContainer.setAlpha(0);
10590
- state.tooltip = tooltipContainer;
10591
- const fadeTween = scene.tweens.add({
10592
- targets: tooltipContainer,
10593
- alpha: 1,
10594
- x: pos.x + textBounds.width / 2,
10595
- y: pos.y + textBounds.height / 2,
10596
- duration: fadeInDuration,
10597
- ease: "Cubic.Out"
10598
- });
10599
- state.activeTweens.push(fadeTween);
10600
- if (pulse) {
10601
- const pulseTween = scene.tweens.add({
10602
- targets: tooltipContainer,
10603
- scale: { from: pulseScale[0], to: pulseScale[1] },
10604
- duration: 600,
10605
- yoyo: true,
10606
- repeat: -1,
10607
- ease: "Sine.InOut"
10608
- });
10609
- state.activeTweens.push(pulseTween);
10610
- }
10611
- if (config.autoDismiss && config.autoDismiss > 0) {
10612
- state.autoDismissTimer = setTimeout(() => {
10613
- hideTooltip(container);
10614
- }, config.autoDismiss);
10615
- }
10616
- }
10617
- function hideTooltip(container) {
10618
- const state = tooltipStates.get(container);
10619
- if (!state || !state.isVisible) return;
10620
- state.isVisible = false;
10621
- const config = state.currentConfig;
10622
- state.currentConfig = null;
10623
- if (state.autoDismissTimer) {
10624
- clearTimeout(state.autoDismissTimer);
10625
- state.autoDismissTimer = null;
10626
- }
10627
- if (!state.tooltip) return;
10628
- const tooltip = state.tooltip;
10629
- const scene = tooltip.scene;
10630
- const theme = themeRegistry.getGlobalTheme();
10631
- const tooltipTheme = theme.Tooltip || {};
10632
- const themeAnim = tooltipTheme.animation || {};
10633
- const anim = config?.animation || {};
10634
- const fadeOutDuration = anim.fadeOut ?? themeAnim.fadeOut ?? 200;
10635
- state.activeTweens.forEach((tween) => tween.stop());
10636
- state.activeTweens = [];
10637
- scene.tweens.add({
10638
- targets: tooltip,
10639
- alpha: 0,
10640
- duration: fadeOutDuration,
10641
- ease: "Cubic.In",
10642
- onComplete: () => {
10643
- tooltip.destroy();
10644
- }
10645
- });
10646
- state.tooltip = null;
10647
- }
10648
- function applyTooltip(scene, container, nextCallback, existingOnHoverStart, existingOnHoverEnd) {
10649
- if (!tooltipStates.has(container)) {
10650
- tooltipStates.set(container, {
10651
- isVisible: false,
10652
- tooltip: null,
10653
- activeTweens: [],
10654
- showTimer: null,
10655
- hideTimer: null,
10656
- autoDismissTimer: null,
10657
- currentConfig: null
10658
- });
10659
- container.once("destroy", () => {
10660
- const state2 = tooltipStates.get(container);
10661
- if (state2) {
10662
- if (state2.showTimer) clearTimeout(state2.showTimer);
10663
- if (state2.hideTimer) clearTimeout(state2.hideTimer);
10664
- if (state2.autoDismissTimer) clearTimeout(state2.autoDismissTimer);
10665
- state2.activeTweens.forEach((tween) => tween.stop());
10666
- hideTooltip(container);
10667
- tooltipStates.delete(container);
10668
- }
10669
- });
10670
- }
10671
- const state = tooltipStates.get(container);
10672
- if (!state) {
10673
- throw new Error("applyTooltip: state not initialized");
10674
- }
10675
- const theme = themeRegistry.getGlobalTheme();
10676
- const tooltipTheme = theme.Tooltip || {};
10677
- const onHoverStart = (data) => {
10678
- if (existingOnHoverStart) existingOnHoverStart(data);
10679
- if (!nextCallback) return;
10680
- const result = nextCallback();
10681
- if (!result) return;
10682
- const config = typeof result === "string" ? { content: result } : result;
10683
- if (config.disabled) return;
10684
- if (state.hideTimer) {
10685
- clearTimeout(state.hideTimer);
10686
- state.hideTimer = null;
10687
- }
10688
- if (state.autoDismissTimer) {
10689
- clearTimeout(state.autoDismissTimer);
10690
- state.autoDismissTimer = null;
10691
- }
10692
- const showDelay = config.showDelay ?? tooltipTheme.showDelay ?? 500;
10693
- state.showTimer = setTimeout(() => {
10694
- showTooltip(scene, container, config);
10695
- }, showDelay);
10696
- };
10697
- const onHoverEnd = (data) => {
10698
- if (existingOnHoverEnd) existingOnHoverEnd(data);
10699
- if (state.showTimer) {
10700
- clearTimeout(state.showTimer);
10701
- state.showTimer = null;
10702
- }
10703
- const hideDelay = state.currentConfig?.hideDelay ?? tooltipTheme.hideDelay ?? 0;
10704
- if (hideDelay > 0) {
10705
- state.hideTimer = setTimeout(() => {
10706
- hideTooltip(container);
10707
- }, hideDelay);
10708
- } else {
10709
- hideTooltip(container);
10710
- }
10711
- };
10712
- return { onHoverStart, onHoverEnd };
10713
- }
10714
- function createBackground(scene, container, props) {
10715
- const hasBackground = props.backgroundColor !== void 0;
10716
- const hasBorder = props.borderColor !== void 0;
10717
- if (hasBackground || hasBorder) {
10718
- const width = typeof props.width === "number" ? props.width : 100;
10719
- const height = typeof props.height === "number" ? props.height : 100;
10720
- const bgColor = props.backgroundColor;
10721
- const bgAlpha = props.backgroundAlpha ?? 1;
10722
- const cornerRadius = props.cornerRadius ?? 0;
10723
- const borderColor = props.borderColor;
10724
- const borderWidth = props.borderWidth ?? 0;
10725
- const borderAlpha = props.borderAlpha ?? 1;
10726
- const background = scene.add.graphics();
10727
- if (bgColor !== void 0) {
10728
- background.fillStyle(bgColor, bgAlpha);
10729
- }
10730
- if (borderWidth > 0 && borderColor !== void 0) {
10731
- background.lineStyle(borderWidth, borderColor, borderAlpha);
10732
- }
10733
- if (cornerRadius !== 0) {
10734
- if (bgColor !== void 0) {
10735
- background.fillRoundedRect(0, 0, width, height, cornerRadius);
10736
- }
10737
- if (borderWidth > 0 && borderColor !== void 0) {
10738
- background.strokeRoundedRect(0, 0, width, height, cornerRadius);
10739
- }
10740
- } else {
10741
- if (bgColor !== void 0) {
10742
- background.fillRect(0, 0, width, height);
10743
- }
10744
- if (borderWidth > 0 && borderColor !== void 0) {
10745
- background.strokeRect(0, 0, width, height);
10746
- }
10747
- }
10748
- container.addAt(background, 0);
10749
- container.__background = background;
10750
- background.__isBackground = true;
10751
- }
10752
- }
10753
- function createGestures(scene, container, props) {
10754
- const hasAnyGesture = !!(props.onTouch || props.onTouchOutside || props.onTouchMove || props.onDoubleTap || props.onLongPress || props.onHoverStart || props.onHoverEnd || props.onWheel);
10755
- const shouldEnable = hasAnyGesture && props.enableGestures !== false;
10756
- if (!shouldEnable) {
10757
- return;
10758
- }
10759
- const manager = getGestureManager(scene);
10760
- const containerWithLayout = container;
10761
- let width = 100;
10762
- let height = 100;
10763
- if (containerWithLayout.__getLayoutSize) {
10764
- const size = containerWithLayout.__getLayoutSize();
10765
- width = size.width;
10766
- height = size.height;
10767
- } else {
10768
- const bounds = container.getBounds();
10769
- width = bounds.width || 100;
10770
- height = bounds.height || 100;
10771
- }
10772
- const hitArea = new Phaser$1.Geom.Rectangle(0, 0, width, height);
10773
- const callbacks = {};
10774
- if (props.onTouch) callbacks.onTouch = props.onTouch;
10775
- if (props.onTouchOutside) callbacks.onTouchOutside = props.onTouchOutside;
10776
- if (props.onTouchMove) callbacks.onTouchMove = props.onTouchMove;
10777
- if (props.onDoubleTap) callbacks.onDoubleTap = props.onDoubleTap;
10778
- if (props.onLongPress) callbacks.onLongPress = props.onLongPress;
10779
- if (props.onHoverStart) callbacks.onHoverStart = props.onHoverStart;
10780
- if (props.onHoverEnd) callbacks.onHoverEnd = props.onHoverEnd;
10781
- if (props.onWheel) callbacks.onWheel = props.onWheel;
10782
- const config = {};
10783
- if (props.longPressDuration !== void 0) config.longPressDuration = props.longPressDuration;
10784
- if (props.doubleTapDelay !== void 0) config.doubleTapDelay = props.doubleTapDelay;
10785
- if (props.maxTouchDuration !== void 0) config.maxTouchDuration = props.maxTouchDuration;
10786
- manager.registerContainer(container, callbacks, hitArea, config);
10787
- }
10788
- function createLayout(container, props) {
10789
- container.__layoutProps = props;
10790
- container.__getLayoutSize = () => {
10791
- const children = container.list;
10792
- const direction = props.direction ?? "column";
10793
- const paddingRaw = props.padding ?? {};
10794
- const padding = typeof paddingRaw === "number" ? { left: paddingRaw, top: paddingRaw, right: paddingRaw, bottom: paddingRaw } : paddingRaw;
10795
- const paddingLeft = padding.left ?? 0;
10796
- const paddingTop = padding.top ?? 0;
10797
- const paddingRight = padding.right ?? 0;
10798
- const paddingBottom = padding.bottom ?? 0;
10799
- const gapNormalized = normalizeGap(props.gap);
10800
- let maxWidth = 0;
10801
- let maxHeight = 0;
10802
- let totalMainSize = 0;
10803
- let childCount = 0;
10804
- for (const child of children) {
10805
- if (child.__isBackground) {
10806
- continue;
10807
- }
10808
- childCount++;
10809
- const marginRaw = child.__layoutProps?.margin ?? {};
10810
- const margin = typeof marginRaw === "number" ? { top: marginRaw, right: marginRaw, bottom: marginRaw, left: marginRaw } : marginRaw;
10811
- const marginTop = margin.top ?? 0;
10812
- const marginBottom = margin.bottom ?? 0;
10813
- const marginLeft = margin.left ?? 0;
10814
- const marginRight = margin.right ?? 0;
10815
- const childSize = getChildSize(child);
10816
- if (direction === "row") {
10817
- totalMainSize += marginLeft + childSize.width + marginRight;
10818
- const childTotalHeight = marginTop + childSize.height + marginBottom;
10819
- maxHeight = Math.max(maxHeight, childTotalHeight);
10820
- } else {
10821
- const childTotalWidth = marginLeft + childSize.width + marginRight;
10822
- maxWidth = Math.max(maxWidth, childTotalWidth);
10823
- totalMainSize += marginTop + childSize.height + marginBottom;
10824
- }
10825
- }
10826
- if (childCount > 1) {
10827
- const gapValue = direction === "row" ? gapNormalized.horizontal : gapNormalized.vertical;
10828
- totalMainSize += gapValue * (childCount - 1);
10829
- }
10830
- const defaultWidth = direction === "row" ? totalMainSize + paddingLeft + paddingRight : maxWidth + paddingLeft + paddingRight;
10831
- const defaultHeight = direction === "row" ? maxHeight + paddingTop + paddingBottom : totalMainSize + paddingTop + paddingBottom;
10832
- const parsedWidth = parseSize(props.width);
10833
- const finalWidth = resolveSize(parsedWidth, void 0, defaultWidth);
10834
- const parsedHeight = parseSize(props.height);
10835
- const finalHeight = resolveSize(parsedHeight, void 0, defaultHeight);
10836
- return {
10837
- width: finalWidth,
10838
- height: finalHeight
10839
- };
10840
- };
10841
- }
10842
- function normalizeBackgroundProps(props) {
10843
- const bgProps = props;
10844
- const hasBackground = bgProps.backgroundColor !== void 0;
10845
- const hasBorder = bgProps.borderColor !== void 0;
10846
- if (!hasBackground && !hasBorder) {
10847
- return props;
10848
- }
10849
- const normalized = { ...props };
10850
- if (hasBackground && (bgProps.backgroundAlpha === void 0 || bgProps.backgroundAlpha === 0)) {
10851
- normalized.backgroundAlpha = 1;
10852
- }
10853
- if (hasBorder) {
10854
- if (bgProps.borderWidth === void 0 || bgProps.borderWidth === 0) {
10855
- normalized.borderWidth = 1;
10856
- }
10857
- if (bgProps.borderAlpha === void 0 || bgProps.borderAlpha === 0) {
10858
- normalized.borderAlpha = 1;
10859
- }
10860
- }
10861
- return normalized;
10862
- }
10863
- const viewCreator = (scene, props) => {
10864
- if (props.backgroundColor !== void 0 || props.cornerRadius !== void 0) {
10865
- DebugLogger.log("theme", "View Creator - Props received:", {
10866
- backgroundColor: props.backgroundColor,
10867
- cornerRadius: props.cornerRadius,
10868
- width: props.width,
10869
- height: props.height
10870
- });
10871
- }
10872
- const normalizedProps = normalizeBackgroundProps(props);
10873
- const container = scene.add.container(normalizedProps.x ?? 0, normalizedProps.y ?? 0);
10874
- createTransform(container, normalizedProps);
10875
- createPhaser(container, normalizedProps);
10876
- createBackground(
10877
- scene,
10878
- container,
10879
- normalizedProps
10880
- );
10881
- createLayout(container, normalizedProps);
10882
- if (normalizedProps.onTooltip) {
10883
- const handlers = applyTooltip(
10884
- scene,
10885
- container,
10886
- normalizedProps.onTooltip,
10887
- normalizedProps.onHoverStart,
10888
- normalizedProps.onHoverEnd
10889
- );
10890
- normalizedProps.onHoverStart = handlers.onHoverStart;
10891
- normalizedProps.onHoverEnd = handlers.onHoverEnd;
10892
- }
10893
- createGestures(scene, container, normalizedProps);
10894
- DebugLogger.log(
10895
- "layout",
10896
- "View creator storing __layoutProps with padding:",
10897
- normalizedProps.padding
10898
- );
10899
- return container;
10900
- };
10901
- const viewPatcher = (node, prev, next) => {
10902
- const normalizedPrev = normalizeBackgroundProps(prev);
10903
- const normalizedNext = normalizeBackgroundProps(next);
10904
- applyTransformProps(node, normalizedPrev, normalizedNext);
10905
- applyPhaserProps(node, normalizedPrev, normalizedNext);
10906
- const container = node;
10907
- applyBackgroundProps(container, normalizedPrev, normalizedNext);
10908
- if (container.scene && container.scene.data) {
10909
- if (normalizedNext.onTooltip) {
10910
- const handlers = applyTooltip(
10911
- container.scene,
10912
- container,
10913
- normalizedNext.onTooltip,
10914
- normalizedNext.onHoverStart,
10915
- normalizedNext.onHoverEnd
10916
- );
10917
- normalizedNext.onHoverStart = handlers.onHoverStart;
10918
- normalizedNext.onHoverEnd = handlers.onHoverEnd;
10919
- }
10920
- }
10921
- if (container.scene && container.scene.data) {
10922
- applyGesturesProps(container.scene, container, normalizedPrev, normalizedNext);
10923
- }
10924
- applyLayoutProps(container, normalizedPrev, normalizedNext);
10925
- };
10926
9618
  class RenderContext {
10927
9619
  constructor(scene) {
10928
9620
  this.scene = scene;
@@ -11274,6 +9966,41 @@ class MountRegistry {
11274
9966
  getEntry(id) {
11275
9967
  return this.entries.get(id);
11276
9968
  }
9969
+ /**
9970
+ * Find a mount entry by parent and optional key
9971
+ * If key is provided, matches parent AND key
9972
+ * If key is omitted, returns first mount with matching parent (backward compatibility)
9973
+ * Validates that scene is still active and objects are not destroyed
9974
+ * @param parent - Parent container or scene
9975
+ * @param key - Optional unique key to distinguish multiple mounts on same parent
9976
+ * @returns Mount entry or undefined if not found or invalid
9977
+ */
9978
+ findByParentAndKey(parent, key) {
9979
+ for (const entry of this.entries.values()) {
9980
+ const scene = entry.parent instanceof Phaser$1.Scene ? entry.parent : entry.parent.scene;
9981
+ if (!scene || !scene.sys || !scene.sys.settings.active) {
9982
+ DebugLogger.log("vdom", `Removing mount ${entry.id} - scene inactive`);
9983
+ this.unregister(entry.id);
9984
+ continue;
9985
+ }
9986
+ if (!entry.rootNode.active || entry.rootNode.scene !== scene) {
9987
+ DebugLogger.log("vdom", `Removing mount ${entry.id} - rootNode destroyed or scene changed`);
9988
+ this.unregister(entry.id);
9989
+ continue;
9990
+ }
9991
+ const entryKey = entry.props.key;
9992
+ if (key !== void 0) {
9993
+ if (entry.parent === parent && entryKey === key) {
9994
+ return entry;
9995
+ }
9996
+ } else {
9997
+ if (entry.parent === parent) {
9998
+ return entry;
9999
+ }
10000
+ }
10001
+ }
10002
+ return void 0;
10003
+ }
11277
10004
  /**
11278
10005
  * Get all active mount entries
11279
10006
  * @returns Array of mount entries
@@ -11281,6 +10008,50 @@ class MountRegistry {
11281
10008
  getAllEntries() {
11282
10009
  return Array.from(this.entries.values());
11283
10010
  }
10011
+ /**
10012
+ * Get count of active mounts
10013
+ * @returns Number of registered mounts
10014
+ */
10015
+ getCount() {
10016
+ return this.entries.size;
10017
+ }
10018
+ /**
10019
+ * Get statistics about active mounts
10020
+ * @returns Object with mount statistics
10021
+ */
10022
+ getStats() {
10023
+ const byType = /* @__PURE__ */ new Map();
10024
+ const byParent = /* @__PURE__ */ new Map();
10025
+ const byKey = /* @__PURE__ */ new Map();
10026
+ const mounts = [];
10027
+ for (const entry of this.entries.values()) {
10028
+ const typeName = typeof entry.type === "string" ? entry.type : entry.type.name || "Component";
10029
+ byType.set(typeName, (byType.get(typeName) ?? 0) + 1);
10030
+ byParent.set(entry.parent, (byParent.get(entry.parent) ?? 0) + 1);
10031
+ const key = entry.props.key;
10032
+ if (key) {
10033
+ byKey.set(key, (byKey.get(key) ?? 0) + 1);
10034
+ }
10035
+ const parentType = entry.parent instanceof Phaser$1.Scene ? "Scene" : "Container";
10036
+ const mountInfo = {
10037
+ id: entry.id,
10038
+ type: typeName,
10039
+ parentType,
10040
+ propsKeys: Object.keys(entry.props)
10041
+ };
10042
+ if (key !== void 0) {
10043
+ mountInfo.key = key;
10044
+ }
10045
+ mounts.push(mountInfo);
10046
+ }
10047
+ return {
10048
+ totalMounts: this.entries.size,
10049
+ byType,
10050
+ byParent,
10051
+ byKey,
10052
+ mounts
10053
+ };
10054
+ }
11284
10055
  /**
11285
10056
  * Clear all entries (for testing)
11286
10057
  */
@@ -11290,6 +10061,9 @@ class MountRegistry {
11290
10061
  }
11291
10062
  }
11292
10063
  const mountRegistry = new MountRegistry();
10064
+ function getMountStats() {
10065
+ return mountRegistry.getStats();
10066
+ }
11293
10067
  function remountAll() {
11294
10068
  const entries = mountRegistry.getAllEntries();
11295
10069
  if (entries.length === 0) {
@@ -11361,6 +10135,14 @@ function remountAll() {
11361
10135
  });
11362
10136
  console.log("[REMOUNT] Remount complete");
11363
10137
  }
10138
+ function normalizeVNodeLike(rendered) {
10139
+ if (!rendered) return null;
10140
+ if (Array.isArray(rendered)) {
10141
+ const flat = rendered.flat(Infinity);
10142
+ return { type: jsxRuntime.Fragment, props: {}, children: flat };
10143
+ }
10144
+ return rendered;
10145
+ }
11364
10146
  function flattenChildren(children) {
11365
10147
  if (!children) return [];
11366
10148
  return children.flat(Infinity);
@@ -11614,10 +10396,11 @@ function mount(parentOrScene, vnode) {
11614
10396
  };
11615
10397
  vnode = setVNodePropSafe(vnode, "__ctx", ctx);
11616
10398
  const propsWithChildren = vnode.children?.length ? { ...vnode.props ?? {}, children: vnode.children } : vnode.props;
11617
- let rendered = withHooks(
10399
+ const renderedRaw = withHooks(
11618
10400
  ctx,
11619
10401
  () => vnode.type(propsWithChildren)
11620
10402
  );
10403
+ let rendered = normalizeVNodeLike(renderedRaw);
11621
10404
  if (!rendered) {
11622
10405
  ctx.vnode = rendered;
11623
10406
  for (const run of ctx.effects) run();
@@ -11776,6 +10559,30 @@ function patchVNode(parent, oldV, newV) {
11776
10559
  warnUnnecessaryRemount(oldV, newV);
11777
10560
  unmount(oldV);
11778
10561
  mount(parent, newV);
10562
+ if (parent && typeof parent === "object" && "list" in parent) {
10563
+ const parentContainer = parent;
10564
+ if (parentContainer.__layoutProps) {
10565
+ let grandparentSize;
10566
+ const grandparent = parentContainer.parentContainer;
10567
+ if (grandparent && grandparent.__layoutProps && grandparent.__getLayoutSize) {
10568
+ const gpSize = grandparent.__getLayoutSize();
10569
+ const gpPadding = grandparent.__layoutProps.padding ?? 0;
10570
+ const normGpPadding = typeof gpPadding === "number" ? { left: gpPadding, right: gpPadding, top: gpPadding, bottom: gpPadding } : {
10571
+ left: gpPadding.left ?? 0,
10572
+ right: gpPadding.right ?? 0,
10573
+ top: gpPadding.top ?? 0,
10574
+ bottom: gpPadding.bottom ?? 0
10575
+ };
10576
+ grandparentSize = {
10577
+ width: gpSize.width - normGpPadding.left - normGpPadding.right,
10578
+ height: gpSize.height - normGpPadding.top - normGpPadding.bottom
10579
+ };
10580
+ }
10581
+ calculateLayout(parentContainer, parentContainer.__layoutProps, grandparentSize);
10582
+ const renderContext = getRenderContext(parent);
10583
+ renderContext.deferLayout(() => updateGestureHitAreaAfterLayout(parentContainer));
10584
+ }
10585
+ }
11779
10586
  return;
11780
10587
  }
11781
10588
  if (oldV.type === jsxRuntime.Fragment && newV.type === jsxRuntime.Fragment) {
@@ -11821,10 +10628,12 @@ function patchVNode(parent, oldV, newV) {
11821
10628
  if (!ctx) {
11822
10629
  if (!newV || !oldV) return;
11823
10630
  const propsWithChildren2 = newV.children?.length ? { ...newV.props ?? {}, children: newV.children } : newV.props;
11824
- const oldRendered = oldV.type(
10631
+ const oldRenderedRaw = oldV.type(
11825
10632
  oldV.children?.length ? { ...oldV.props ?? {}, children: oldV.children } : oldV.props
11826
10633
  );
11827
- const newRendered = newV.type(propsWithChildren2);
10634
+ const newRenderedRaw = newV.type(propsWithChildren2);
10635
+ const oldRendered = normalizeVNodeLike(oldRenderedRaw);
10636
+ const newRendered = normalizeVNodeLike(newRenderedRaw);
11828
10637
  patchVNode(parent, oldRendered, newRendered);
11829
10638
  return;
11830
10639
  }
@@ -11842,10 +10651,11 @@ function patchVNode(parent, oldV, newV) {
11842
10651
  if (!shouldComponentUpdate(ctx, propsWithChildren)) {
11843
10652
  return;
11844
10653
  }
11845
- const renderedNext = withHooks(
10654
+ const renderedNextRaw = withHooks(
11846
10655
  ctx,
11847
10656
  () => newVWithCtx.type(propsWithChildren)
11848
10657
  );
10658
+ const renderedNext = normalizeVNodeLike(renderedNextRaw);
11849
10659
  if (!renderedNext) {
11850
10660
  ctx.vnode = renderedNext;
11851
10661
  for (const run of ctx.effects) run();
@@ -11876,6 +10686,7 @@ function patchVNode(parent, oldV, newV) {
11876
10686
  }
11877
10687
  const nodeType = oldV.type;
11878
10688
  newV = setVNodePropSafe(newV, "__node", oldV.__node);
10689
+ newV = setVNodePropSafe(newV, "__parent", parent);
11879
10690
  if (newV.__theme !== void 0) {
11880
10691
  const themed = setThemeSafe(oldV, newV.__theme);
11881
10692
  if (themed !== oldV) {
@@ -11920,6 +10731,11 @@ function patchVNode(parent, oldV, newV) {
11920
10731
  warnMissingKeys(newV, b);
11921
10732
  }
11922
10733
  const containerLayoutChanged = hasLayoutPropsChanged(oldV, newV);
10734
+ const oldValidChildCount = a.filter((c) => c != null && c !== false).length;
10735
+ const newValidChildCount = b.filter((c) => c != null && c !== false).length;
10736
+ if (oldValidChildCount !== newValidChildCount) {
10737
+ childrenChanged = true;
10738
+ }
11923
10739
  for (let i = 0; i < len; i++) {
11924
10740
  const c1 = a[i], c2 = b[i];
11925
10741
  const isValidC1 = c1 != null && c1 !== false;
@@ -12000,7 +10816,74 @@ function patchVNode(parent, oldV, newV) {
12000
10816
  }
12001
10817
  }
12002
10818
  function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
12003
- const { width, height, disableAutoSize = false, ...componentProps } = props;
10819
+ const key = props.key;
10820
+ const existingMount = mountRegistry.findByParentAndKey(parentOrScene, key);
10821
+ if (existingMount) {
10822
+ if (existingMount.type !== type) {
10823
+ const oldTypeName = typeof existingMount.type === "string" ? existingMount.type : existingMount.type.name || "Component";
10824
+ const newTypeName = typeof type === "string" ? type : type.name || "Component";
10825
+ console.warn(
10826
+ `[PhaserJSX] mountJSX type mismatch: Attempting to patch <${oldTypeName}> with <${newTypeName}>.
10827
+ This usually means you're missing a 'key' prop to distinguish multiple mounts on the same parent.
10828
+ Solution: Add unique keys like { key: 'sidebar', ... } and { key: 'main', ... }`
10829
+ );
10830
+ }
10831
+ const newWidth = props.width ?? existingMount.props.width;
10832
+ const newHeight = props.height ?? existingMount.props.height;
10833
+ const dimensionsChanged = newWidth !== existingMount.props.width || newHeight !== existingMount.props.height;
10834
+ const { disableAutoSize: _d, key: _k, ...componentProps2 } = props;
10835
+ if (dimensionsChanged) {
10836
+ existingMount.props = {
10837
+ ...existingMount.props,
10838
+ ...componentProps2,
10839
+ width: newWidth,
10840
+ height: newHeight
10841
+ };
10842
+ } else {
10843
+ existingMount.props = { ...existingMount.props, ...componentProps2 };
10844
+ }
10845
+ let newVNode;
10846
+ if (existingMount.props.disableAutoSize) {
10847
+ newVNode = {
10848
+ type: existingMount.type,
10849
+ props: {
10850
+ ...componentProps2,
10851
+ width: existingMount.props.width,
10852
+ height: existingMount.props.height
10853
+ },
10854
+ children: []
10855
+ };
10856
+ } else {
10857
+ const componentVNode = {
10858
+ type: existingMount.type,
10859
+ props: {
10860
+ ...componentProps2,
10861
+ width: existingMount.props.width,
10862
+ height: existingMount.props.height
10863
+ },
10864
+ children: []
10865
+ };
10866
+ newVNode = {
10867
+ type: SceneWrapper,
10868
+ props: {
10869
+ width: existingMount.props.width,
10870
+ height: existingMount.props.height,
10871
+ children: componentVNode
10872
+ },
10873
+ children: []
10874
+ };
10875
+ }
10876
+ patchVNode(parentOrScene, existingMount.vnode, newVNode);
10877
+ existingMount.vnode = newVNode;
10878
+ const handle2 = existingMount.rootNode;
10879
+ handle2.unmount = () => unmountJSX(handle2);
10880
+ DebugLogger.log(
10881
+ "vdom",
10882
+ `Patched existing mount ${existingMount.id} on same parent (type: ${typeof type === "string" ? type : type.name})`
10883
+ );
10884
+ return handle2;
10885
+ }
10886
+ const { width, height, disableAutoSize = false, key: _key, ...componentProps } = props;
12004
10887
  const scene = parentOrScene instanceof Phaser$1.Scene ? parentOrScene : parentOrScene.scene;
12005
10888
  if (scene) {
12006
10889
  const renderContext = getRenderContext(parentOrScene);
@@ -12013,7 +10896,11 @@ function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
12013
10896
  } else {
12014
10897
  const componentVNode = {
12015
10898
  type,
12016
- props: componentProps,
10899
+ props: {
10900
+ ...componentProps,
10901
+ width,
10902
+ height
10903
+ },
12017
10904
  children: []
12018
10905
  };
12019
10906
  vnode = {
@@ -12067,8 +10954,10 @@ function unmountJSX(target) {
12067
10954
  const vdom = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12068
10955
  __proto__: null,
12069
10956
  createElement,
10957
+ getMountStats,
12070
10958
  mount,
12071
10959
  mountJSX,
10960
+ normalizeVNodeLike,
12072
10961
  patchVNode,
12073
10962
  remountAll,
12074
10963
  unmount,
@@ -12163,6 +11052,68 @@ function useScene() {
12163
11052
  const renderContext = getContextFromParent(ctx.parent);
12164
11053
  return renderContext.scene;
12165
11054
  }
11055
+ function useViewportSize() {
11056
+ const ctx = getCurrent();
11057
+ if (!ctx) {
11058
+ throw new Error("useViewportSize must be called within a component");
11059
+ }
11060
+ const renderContext = getContextFromParent(ctx.parent);
11061
+ return renderContext.getViewport();
11062
+ }
11063
+ function getLayoutSize(container) {
11064
+ if (!container) return void 0;
11065
+ const withLayout = container;
11066
+ return withLayout.__getLayoutSize?.();
11067
+ }
11068
+ function useLayoutSize(ref) {
11069
+ return getLayoutSize(ref.current);
11070
+ }
11071
+ function getLayoutProps(container) {
11072
+ if (!container) return void 0;
11073
+ const withLayout = container;
11074
+ return withLayout.__layoutProps;
11075
+ }
11076
+ function getBackgroundGraphics(container) {
11077
+ if (!container) return void 0;
11078
+ const withBackground = container;
11079
+ return withBackground.__background;
11080
+ }
11081
+ function useBackgroundGraphics(ref) {
11082
+ return getBackgroundGraphics(ref.current);
11083
+ }
11084
+ function getLayoutRect(container) {
11085
+ if (!container) return void 0;
11086
+ const size = getLayoutSize(container);
11087
+ if (!size) return void 0;
11088
+ return {
11089
+ x: container.x,
11090
+ y: container.y,
11091
+ width: size.width,
11092
+ height: size.height
11093
+ };
11094
+ }
11095
+ function useLayoutRect(ref) {
11096
+ return getLayoutRect(ref.current);
11097
+ }
11098
+ function getWorldLayoutRect(container) {
11099
+ if (!container) return void 0;
11100
+ const size = getLayoutSize(container);
11101
+ if (!size) return void 0;
11102
+ const matrix = container.getWorldTransformMatrix();
11103
+ const worldX = matrix.tx;
11104
+ const worldY = matrix.ty;
11105
+ const worldWidth = size.width * Math.abs(matrix.scaleX);
11106
+ const worldHeight = size.height * Math.abs(matrix.scaleY);
11107
+ return {
11108
+ x: worldX,
11109
+ y: worldY,
11110
+ width: worldWidth,
11111
+ height: worldHeight
11112
+ };
11113
+ }
11114
+ function useWorldLayoutRect(ref) {
11115
+ return getWorldLayoutRect(ref.current);
11116
+ }
12166
11117
  function useEffect(fn, deps) {
12167
11118
  const c = getCurrent();
12168
11119
  const i = c.index++;
@@ -12176,6 +11127,21 @@ function useEffect(fn, deps) {
12176
11127
  }
12177
11128
  });
12178
11129
  }
11130
+ function useLayoutEffect(fn, deps) {
11131
+ const c = getCurrent();
11132
+ const i = c.index++;
11133
+ const slot = c.slots[i] ?? (c.slots[i] = { deps: void 0, cleanup: void 0 });
11134
+ c.effects.push(() => {
11135
+ if (!depsChanged(slot.deps, deps)) return;
11136
+ if (typeof slot.cleanup === "function") slot.cleanup();
11137
+ requestAnimationFrame(() => {
11138
+ slot.cleanup = fn();
11139
+ });
11140
+ if (deps !== void 0) {
11141
+ slot.deps = deps;
11142
+ }
11143
+ });
11144
+ }
12179
11145
  function depsChanged(a, b) {
12180
11146
  if (!a || !b) return true;
12181
11147
  if (a.length !== b.length) return true;
@@ -12228,7 +11194,7 @@ function scheduleUpdate(c) {
12228
11194
  }
12229
11195
  const componentProps = c.componentVNode.props ?? {};
12230
11196
  const propsWithChildren = c.componentVNode.children?.length ? { ...componentProps, children: c.componentVNode.children } : componentProps;
12231
- const nextVNode = withHooks(c, () => c.function(propsWithChildren));
11197
+ const nextVNode = normalizeVNodeLike(withHooks(c, () => c.function(propsWithChildren)));
12232
11198
  patchVNode(c.parent, c.vnode, nextVNode);
12233
11199
  c.vnode = nextVNode;
12234
11200
  for (const run of c.effects) run();
@@ -13012,6 +11978,11 @@ function Button(props) {
13012
11978
  }
13013
11979
  );
13014
11980
  }
11981
+ function Graphics(props) {
11982
+ const localTheme = useTheme();
11983
+ const { props: themed, nestedTheme } = getThemedProps("Graphics", localTheme, props);
11984
+ return /* @__PURE__ */ jsxRuntime.jsx("graphics", { ...themed, theme: nestedTheme });
11985
+ }
13015
11986
  function RadioButton(props) {
13016
11987
  const { props: themed, nestedTheme } = getThemedProps("RadioButton", void 0, {});
13017
11988
  const size = themed.size ?? 16;
@@ -13114,24 +12085,8 @@ function Text(props) {
13114
12085
  const { props: themed, nestedTheme } = getThemedProps("Text", localTheme, props);
13115
12086
  return /* @__PURE__ */ jsxRuntime.jsx("text", { ...themed, theme: nestedTheme });
13116
12087
  }
13117
- const Sprite = "Sprite";
13118
- const Graphics = "Graphics";
13119
- const TileSprite = "TileSprite";
13120
- function registerBuiltins() {
13121
- register("view", { create: viewCreator, patch: viewPatcher });
13122
- register("text", { create: textCreator, patch: textPatcher });
13123
- register("nineslice", { create: nineSliceCreator, patch: nineSlicePatcher });
13124
- register("sprite", { create: spriteCreator, patch: spritePatcher });
13125
- register("image", { create: imageCreator, patch: imagePatcher });
13126
- register("graphics", { create: graphicsCreator, patch: graphicsPatcher });
13127
- register("tilesprite", { create: tileSpriteCreator, patch: tileSpritePatcher });
13128
- register("View", { create: viewCreator, patch: viewPatcher });
13129
- register("Text", { create: textCreator, patch: textPatcher });
13130
- register("NineSlice", { create: nineSliceCreator, patch: nineSlicePatcher });
13131
- register("Sprite", { create: spriteCreator, patch: spritePatcher });
13132
- register("Image", { create: imageCreator, patch: imagePatcher });
13133
- register("Graphics", { create: graphicsCreator, patch: graphicsPatcher });
13134
- register("TileSprite", { create: tileSpriteCreator, patch: tileSpritePatcher });
12088
+ function Particles(props) {
12089
+ return /* @__PURE__ */ jsxRuntime.jsx("particles", { ...props });
13135
12090
  }
13136
12091
  function preprocessSvgForTinting(svg) {
13137
12092
  return svg.replace(/fill="currentColor"/gi, 'fill="#FFFFFF"').replace(/fill='currentColor'/gi, "fill='#FFFFFF'").replace(/fill:\s*currentColor/gi, "fill: #FFFFFF").replace(/fill="#000000"/gi, 'fill="#FFFFFF"').replace(/fill="#000"/gi, 'fill="#FFFFFF"').replace(/fill='#000000'/gi, "fill='#FFFFFF'").replace(/fill='#000'/gi, "fill='#FFFFFF'");
@@ -14037,6 +12992,13 @@ function Portal(props) {
14037
12992
  const blockEvents = props.blockEvents ?? true;
14038
12993
  const mountedNodesRef = useRef([]);
14039
12994
  const previousChildrenRef = useRef([]);
12995
+ const normalizeChildren2 = (children) => {
12996
+ if (!children) return [];
12997
+ const flat = Array.isArray(children) ? children.flat(Infinity) : [children];
12998
+ return flat.filter(
12999
+ (child) => !!child && typeof child === "object" && "type" in child
13000
+ );
13001
+ };
14040
13002
  useEffect(() => {
14041
13003
  const portalContainer = portalRegistry.register(
14042
13004
  portalId,
@@ -14051,7 +13013,7 @@ function Portal(props) {
14051
13013
  portalContainer.add(blockerContainer);
14052
13014
  blockerContainer.setDepth(-1);
14053
13015
  }
14054
- const children = Array.isArray(props.children) ? props.children : [props.children];
13016
+ const children = normalizeChildren2(props.children);
14055
13017
  const mountedNodes = [];
14056
13018
  for (const child of children) {
14057
13019
  if (child) {
@@ -14115,7 +13077,7 @@ function Portal(props) {
14115
13077
  const portal = portalRegistry.get(portalId);
14116
13078
  if (!portal) return;
14117
13079
  const portalContainer = portal.container;
14118
- const newChildren = Array.isArray(props.children) ? props.children : [props.children];
13080
+ const newChildren = normalizeChildren2(props.children);
14119
13081
  const oldChildren = previousChildrenRef.current;
14120
13082
  const maxLen = Math.max(oldChildren.length, newChildren.length);
14121
13083
  for (let i = 0; i < maxLen; i++) {
@@ -15520,7 +14482,7 @@ function Divider(props) {
15520
14482
  }
15521
14483
  function calculateSliderSize(size) {
15522
14484
  const { props: themed } = getThemedProps("ScrollSlider", void 0, {});
15523
- const sizeFactor = size === "large" ? 1.25 : size === "small" ? 0.75 : size === "tiny" ? 0.5 : 1;
14485
+ const sizeFactor = size === "large" ? 1.25 : size === "small" ? 0.75 : size === "tiny" ? 0.5 : size === "micro" ? 0.25 : size === "nano" ? 0.125 : 1;
15524
14486
  const border = (themed.borderWidth ?? 1) * sizeFactor;
15525
14487
  const outer = (themed.size ?? 24) * sizeFactor;
15526
14488
  const dimension = outer - border * 2;
@@ -15681,10 +14643,17 @@ function ScrollView(props) {
15681
14643
  snap = false,
15682
14644
  snapAlignment = "start",
15683
14645
  snapThreshold = 20,
15684
- momentum = true
14646
+ momentum = true,
14647
+ onSnap,
14648
+ ...viewProps
15685
14649
  } = props;
15686
- const [scroll, setScroll] = useState(initialScroll ?? { dx: 0, dy: 0 });
14650
+ const [scroll, setScroll] = useState({
14651
+ dx: initialScroll?.dx ?? 0,
14652
+ dy: initialScroll?.dy ?? 0
14653
+ });
15687
14654
  const scrollRef = useRef(scroll);
14655
+ const hasMountedRef = useRef(false);
14656
+ const lastAppliedSnapIndexRef = useRef(initialScroll?.snapIndex);
15688
14657
  const contentRef = useRef(null);
15689
14658
  const viewportRef = useRef(null);
15690
14659
  const [contentHeight, setContentHeight] = useState(0);
@@ -15694,7 +14663,6 @@ function ScrollView(props) {
15694
14663
  const tweenRef = useRef(null);
15695
14664
  const wheelSnapTimeoutRef = useRef(null);
15696
14665
  const WHEEL_SNAP_DELAY = 200;
15697
- const { outer: sliderSize } = calculateSliderSize(props.sliderSize);
15698
14666
  const viewportHeight = viewportRef.current?.height ?? 0;
15699
14667
  const viewportWidth = viewportRef.current?.width ?? 0;
15700
14668
  const effectiveContentHeight = Math.max(contentHeight, viewportHeight);
@@ -15704,6 +14672,11 @@ function ScrollView(props) {
15704
14672
  const needsHorizontalScroll = effectiveContentWidth > viewportWidth + epsilon;
15705
14673
  const showVerticalSliderActual = showVerticalSlider === true || needsVerticalScroll && showVerticalSlider === "auto";
15706
14674
  const showHorizontalSliderActual = showHorizontalSlider === true || needsHorizontalScroll && showHorizontalSlider === "auto";
14675
+ const { outer: sliderSize } = calculateSliderSize(props.sliderSize);
14676
+ props.onSliderSize?.({
14677
+ width: showVerticalSlider ? sliderSize : 0,
14678
+ height: showHorizontalSliderActual ? sliderSize : 0
14679
+ });
15707
14680
  const maxScrollY = Math.max(0, effectiveContentHeight - viewportHeight);
15708
14681
  const maxScrollX = Math.max(0, effectiveContentWidth - viewportWidth);
15709
14682
  const updateScroll = (value) => {
@@ -15722,10 +14695,77 @@ function ScrollView(props) {
15722
14695
  const resolvedSnapThreshold = typeof snap === "object" && "positions" in snap ? snap.threshold ?? snapThreshold : snapThreshold;
15723
14696
  const effectiveSnapThreshold = resolvedSnapThreshold === void 0 || resolvedSnapThreshold < 0 ? Infinity : resolvedSnapThreshold;
15724
14697
  useEffect(() => {
15725
- if (initialScroll) {
15726
- updateScroll(initialScroll);
14698
+ if (!initialScroll) return;
14699
+ const allowAnimate = hasMountedRef.current;
14700
+ if (snap && typeof snap === "object" && "positions" in snap) {
14701
+ const { x: xTargets, y: yTargets } = getSnapTargets();
14702
+ const hasTargets = xTargets.length > 0 || yTargets.length > 0;
14703
+ if (initialScroll.snapIndex !== void 0 && hasTargets) {
14704
+ const maxIdx = Math.max(xTargets.length, yTargets.length) - 1;
14705
+ const clampedIdx = Math.max(0, Math.min(initialScroll.snapIndex, maxIdx));
14706
+ const targetX = xTargets[clampedIdx];
14707
+ const targetY = yTargets[clampedIdx];
14708
+ const nextDx = targetX !== void 0 ? alignTargetPosition(targetX, viewportWidth, maxScrollX) : initialScroll.dx ?? scrollRef.current.dx;
14709
+ const nextDy = targetY !== void 0 ? alignTargetPosition(targetY, viewportHeight, maxScrollY) : initialScroll.dy ?? scrollRef.current.dy;
14710
+ const shouldAnimate = allowAnimate && (clampedIdx !== lastAppliedSnapIndexRef.current || Math.abs(scrollRef.current.dx - nextDx) > 0.5 || Math.abs(scrollRef.current.dy - nextDy) > 0.5);
14711
+ lastAppliedSnapIndexRef.current = clampedIdx;
14712
+ if (shouldAnimate && contentRef.current?.scene) {
14713
+ stopActiveTween();
14714
+ const scene = contentRef.current.scene;
14715
+ tweenRef.current = scene.tweens.add({
14716
+ targets: { dx: scrollRef.current.dx, dy: scrollRef.current.dy },
14717
+ dx: nextDx,
14718
+ dy: nextDy,
14719
+ duration: 220,
14720
+ ease: "Quad.easeOut",
14721
+ onUpdate: (tween) => {
14722
+ const target = tween.targets[0];
14723
+ updateScroll({ dx: target.dx, dy: target.dy });
14724
+ },
14725
+ onComplete: () => {
14726
+ tweenRef.current = null;
14727
+ if (onSnap) {
14728
+ onSnap(clampedIdx);
14729
+ }
14730
+ }
14731
+ });
14732
+ } else {
14733
+ updateScroll({ dx: nextDx, dy: nextDy });
14734
+ if (onSnap) {
14735
+ onSnap(clampedIdx);
14736
+ }
14737
+ }
14738
+ hasMountedRef.current = true;
14739
+ return;
14740
+ }
14741
+ }
14742
+ if (initialScroll.dx !== void 0 && initialScroll.dy !== void 0) {
14743
+ const nextDx = initialScroll.dx;
14744
+ const nextDy = initialScroll.dy;
14745
+ const shouldAnimate = allowAnimate && (Math.abs(scrollRef.current.dx - nextDx) > 0.5 || Math.abs(scrollRef.current.dy - nextDy) > 0.5);
14746
+ if (shouldAnimate && contentRef.current?.scene) {
14747
+ stopActiveTween();
14748
+ const scene = contentRef.current.scene;
14749
+ tweenRef.current = scene.tweens.add({
14750
+ targets: { dx: scrollRef.current.dx, dy: scrollRef.current.dy },
14751
+ dx: nextDx,
14752
+ dy: nextDy,
14753
+ duration: 220,
14754
+ ease: "Quad.easeOut",
14755
+ onUpdate: (tween) => {
14756
+ const target = tween.targets[0];
14757
+ updateScroll({ dx: target.dx, dy: target.dy });
14758
+ },
14759
+ onComplete: () => {
14760
+ tweenRef.current = null;
14761
+ }
14762
+ });
14763
+ } else {
14764
+ updateScroll({ dx: nextDx, dy: nextDy });
14765
+ }
15727
14766
  }
15728
- }, [initialScroll]);
14767
+ hasMountedRef.current = true;
14768
+ }, [initialScroll, snap, viewportWidth, viewportHeight, maxScrollX, maxScrollY]);
15729
14769
  useEffect(() => {
15730
14770
  if (onScrollInfoChange && viewportWidth > 0 && viewportHeight > 0) {
15731
14771
  onScrollInfoChange({
@@ -15807,6 +14847,9 @@ function ScrollView(props) {
15807
14847
  },
15808
14848
  onComplete: () => {
15809
14849
  tweenRef.current = null;
14850
+ if (snappedTarget && snappedTarget.index >= 0 && onSnap) {
14851
+ onSnap(snappedTarget.index);
14852
+ }
15810
14853
  }
15811
14854
  });
15812
14855
  };
@@ -15832,10 +14875,12 @@ function ScrollView(props) {
15832
14875
  return { x: [], y: [] };
15833
14876
  };
15834
14877
  const findNearestSnap = (current, targets, viewportSize, maxScroll) => {
15835
- if (targets.length === 0) return current;
14878
+ if (targets.length === 0) return { position: current, index: -1 };
15836
14879
  let nearest = current;
15837
14880
  let minDistance = Infinity;
15838
- for (const { position, size } of targets) {
14881
+ let nearestIndex = -1;
14882
+ for (let index = 0; index < targets.length; index++) {
14883
+ const { position, size } = targets[index] ?? { position: 0, size: 0 };
15839
14884
  let adjustedPos = position;
15840
14885
  if (snapAlignment === "center") {
15841
14886
  adjustedPos = position + size / 2 - viewportSize / 2;
@@ -15847,29 +14892,47 @@ function ScrollView(props) {
15847
14892
  if (distance < minDistance && distance <= effectiveSnapThreshold) {
15848
14893
  minDistance = distance;
15849
14894
  nearest = adjustedPos;
14895
+ nearestIndex = index;
15850
14896
  } else if (distance < minDistance && effectiveSnapThreshold === Infinity) {
15851
14897
  minDistance = distance;
15852
14898
  nearest = adjustedPos;
14899
+ nearestIndex = index;
15853
14900
  }
15854
14901
  }
15855
- return nearest;
14902
+ return { position: nearest, index: nearestIndex };
15856
14903
  };
15857
14904
  const calculateSnapDestination = (baseDx, baseDy) => {
15858
14905
  const { x: xTargets, y: yTargets } = getSnapTargets();
15859
14906
  const viewportHeightLocal = viewportRef.current?.height ?? 0;
15860
14907
  const viewportWidthLocal = viewportRef.current?.width ?? 0;
15861
- const targetDx = findNearestSnap(baseDx, xTargets, viewportWidthLocal, maxScrollX);
15862
- const targetDy = findNearestSnap(baseDy, yTargets, viewportHeightLocal, maxScrollY);
15863
- return { dx: targetDx, dy: targetDy };
14908
+ const snapX = findNearestSnap(baseDx, xTargets, viewportWidthLocal, maxScrollX);
14909
+ const snapY = findNearestSnap(baseDy, yTargets, viewportHeightLocal, maxScrollY);
14910
+ const snapIndex = snapY.index >= 0 ? snapY.index : snapX.index;
14911
+ return { dx: snapX.position, dy: snapY.position, index: snapIndex };
14912
+ };
14913
+ const alignTargetPosition = (target, viewportSize, maxScroll) => {
14914
+ let adjustedPos = target.position;
14915
+ if (snapAlignment === "center") {
14916
+ adjustedPos = target.position + target.size / 2 - viewportSize / 2;
14917
+ } else if (snapAlignment === "end") {
14918
+ adjustedPos = target.position + target.size - viewportSize;
14919
+ }
14920
+ return Math.max(0, Math.min(maxScroll, adjustedPos));
15864
14921
  };
15865
14922
  const applySnap = () => {
15866
14923
  if (!contentRef.current?.scene || !snap) return;
15867
14924
  const currentScroll = scrollRef.current;
15868
- const { dx: targetDx, dy: targetDy } = calculateSnapDestination(
15869
- currentScroll.dx,
15870
- currentScroll.dy
15871
- );
15872
- if (targetDx === currentScroll.dx && targetDy === currentScroll.dy) return;
14925
+ const {
14926
+ dx: targetDx,
14927
+ dy: targetDy,
14928
+ index: snapIndex
14929
+ } = calculateSnapDestination(currentScroll.dx, currentScroll.dy);
14930
+ if (targetDx === currentScroll.dx && targetDy === currentScroll.dy) {
14931
+ if (snapIndex >= 0 && onSnap) {
14932
+ onSnap(snapIndex);
14933
+ }
14934
+ return;
14935
+ }
15873
14936
  const scene = contentRef.current.scene;
15874
14937
  stopActiveTween();
15875
14938
  tweenRef.current = scene.tweens.add({
@@ -15884,6 +14947,9 @@ function ScrollView(props) {
15884
14947
  },
15885
14948
  onComplete: () => {
15886
14949
  tweenRef.current = null;
14950
+ if (snapIndex >= 0 && onSnap) {
14951
+ onSnap(snapIndex);
14952
+ }
15887
14953
  }
15888
14954
  });
15889
14955
  };
@@ -15955,7 +15021,8 @@ function ScrollView(props) {
15955
15021
  stopActiveTween();
15956
15022
  };
15957
15023
  }, [showVerticalSliderActual, showHorizontalSliderActual]);
15958
- return /* @__PURE__ */ jsxRuntime.jsx(View, { visible, children: /* @__PURE__ */ jsxRuntime.jsxs(View, { direction: "row", width: "100%", height: "100%", gap: 0, padding: 0, children: [
15024
+ const resolvedVisible = viewProps.visible === "none" ? "none" : visible ? viewProps.visible ?? true : false;
15025
+ return /* @__PURE__ */ jsxRuntime.jsx(View, { ...viewProps, visible: resolvedVisible, children: /* @__PURE__ */ jsxRuntime.jsxs(View, { direction: "row", width: "100%", height: "100%", gap: 0, padding: 0, children: [
15959
15026
  /* @__PURE__ */ jsxRuntime.jsxs(View, { flex: 1, height: "100%", direction: "column", children: [
15960
15027
  /* @__PURE__ */ jsxRuntime.jsxs(
15961
15028
  View,
@@ -16374,6 +15441,395 @@ function useIconPreload(type, loader) {
16374
15441
  }, [type, loader]);
16375
15442
  return svg !== null;
16376
15443
  }
15444
+ function joystickThemeFactory(joystickTheme, radius) {
15445
+ function createNeonBase(radius2, color = 65280) {
15446
+ return /* @__PURE__ */ jsxRuntime.jsx(
15447
+ Graphics,
15448
+ {
15449
+ onDraw: (g) => {
15450
+ g.fillStyle(color, 0.1);
15451
+ g.fillCircle(0, 0, radius2 + 10);
15452
+ g.fillStyle(0, 0.4);
15453
+ g.fillCircle(0, 0, radius2);
15454
+ g.lineStyle(3, color, 1);
15455
+ g.strokeCircle(0, 0, radius2);
15456
+ g.lineStyle(1, color, 0.5);
15457
+ g.strokeCircle(0, 0, radius2 - 5);
15458
+ for (let i = 0; i < 4; i++) {
15459
+ const angle = i * 90 * Math.PI / 180;
15460
+ const x1 = Math.cos(angle) * (radius2 - 15);
15461
+ const y1 = Math.sin(angle) * (radius2 - 15);
15462
+ const x2 = Math.cos(angle) * (radius2 - 5);
15463
+ const y2 = Math.sin(angle) * (radius2 - 5);
15464
+ g.lineStyle(2, color, 0.7);
15465
+ g.lineBetween(x1, y1, x2, y2);
15466
+ }
15467
+ }
15468
+ }
15469
+ );
15470
+ }
15471
+ function createNeonThumb(radius2, color = 65280) {
15472
+ const r = radius2 * 0.4;
15473
+ return /* @__PURE__ */ jsxRuntime.jsx(
15474
+ Graphics,
15475
+ {
15476
+ onDraw: (g) => {
15477
+ g.fillStyle(color, 0.2);
15478
+ g.fillCircle(0, 0, r + 5);
15479
+ g.fillStyle(color, 0.8);
15480
+ g.fillCircle(0, 0, r);
15481
+ g.lineStyle(2, color, 1);
15482
+ g.strokeCircle(0, 0, r);
15483
+ g.lineStyle(2, 0, 0.8);
15484
+ g.moveTo(0, -r * 0.6);
15485
+ g.lineTo(0, r * 0.6);
15486
+ g.moveTo(-r * 0.6, 0);
15487
+ g.lineTo(r * 0.6, 0);
15488
+ g.strokePath();
15489
+ }
15490
+ }
15491
+ );
15492
+ }
15493
+ function createTargetBase(radius2, tint2 = 16711680) {
15494
+ return /* @__PURE__ */ jsxRuntime.jsx(
15495
+ Graphics,
15496
+ {
15497
+ onDraw: (g) => {
15498
+ g.fillStyle(0, 0.3);
15499
+ g.fillCircle(0, 0, radius2);
15500
+ for (let i = 0; i < 3; i++) {
15501
+ const r = radius2 - i * 20;
15502
+ g.lineStyle(2, tint2, 0.6 - i * 0.15);
15503
+ g.strokeCircle(0, 0, r);
15504
+ }
15505
+ g.lineStyle(1, tint2, 0.5);
15506
+ g.moveTo(-radius2, 0);
15507
+ g.lineTo(radius2, 0);
15508
+ g.moveTo(0, -radius2);
15509
+ g.lineTo(0, radius2);
15510
+ g.strokePath();
15511
+ g.fillStyle(tint2, 0.8);
15512
+ g.fillCircle(0, 0, 5);
15513
+ }
15514
+ }
15515
+ );
15516
+ }
15517
+ function createTargetThumb(radius2, tint2 = 16711680) {
15518
+ const r = radius2 * 0.35;
15519
+ return /* @__PURE__ */ jsxRuntime.jsx(
15520
+ Graphics,
15521
+ {
15522
+ onDraw: (g) => {
15523
+ g.fillStyle(tint2, 0.7);
15524
+ g.fillCircle(0, 0, r);
15525
+ g.fillStyle(16777215, 0.9);
15526
+ g.fillCircle(0, 0, r * 0.5);
15527
+ g.fillStyle(tint2, 1);
15528
+ g.fillCircle(0, 0, r * 0.2);
15529
+ g.lineStyle(3, tint2, 1);
15530
+ g.beginPath();
15531
+ g.moveTo(0, -r);
15532
+ g.lineTo(r * 0.3, -r * 0.6);
15533
+ g.lineTo(-r * 0.3, -r * 0.6);
15534
+ g.closePath();
15535
+ g.fillPath();
15536
+ }
15537
+ }
15538
+ );
15539
+ }
15540
+ function createGlassBase(radius2, tint2 = 16777215) {
15541
+ return /* @__PURE__ */ jsxRuntime.jsx(
15542
+ Graphics,
15543
+ {
15544
+ onDraw: (g) => {
15545
+ g.fillStyle(tint2, 0.15);
15546
+ g.fillCircle(0, 0, radius2);
15547
+ g.fillStyle(tint2, 0.3);
15548
+ g.fillCircle(-radius2 * 0.3, -radius2 * 0.3, radius2 * 0.4);
15549
+ g.lineStyle(2, tint2, 0.5);
15550
+ g.strokeCircle(0, 0, radius2);
15551
+ g.lineStyle(1, tint2, 0.3);
15552
+ g.strokeCircle(0, 0, radius2 - 3);
15553
+ }
15554
+ }
15555
+ );
15556
+ }
15557
+ function createGlassThumb(radius2, tint2 = 16777215) {
15558
+ const r = radius2 * 0.4;
15559
+ return /* @__PURE__ */ jsxRuntime.jsx(
15560
+ Graphics,
15561
+ {
15562
+ onDraw: (g) => {
15563
+ g.fillStyle(0, 0.2);
15564
+ g.fillCircle(r * 0.1, r * 0.1, r);
15565
+ g.fillStyle(tint2, 0.4);
15566
+ g.fillCircle(0, 0, r);
15567
+ g.fillStyle(tint2, 0.6);
15568
+ g.fillCircle(-r * 0.3, -r * 0.3, r * 0.4);
15569
+ g.lineStyle(2, tint2, 0.7);
15570
+ g.strokeCircle(0, 0, r);
15571
+ }
15572
+ }
15573
+ );
15574
+ }
15575
+ function createMilitaryBase(radius2, tint2 = 65280) {
15576
+ return /* @__PURE__ */ jsxRuntime.jsx(
15577
+ Graphics,
15578
+ {
15579
+ onDraw: (g) => {
15580
+ g.fillStyle(1710618, 0.8);
15581
+ g.fillCircle(0, 0, radius2);
15582
+ g.lineStyle(1, tint2, 0.3);
15583
+ const step = 20;
15584
+ for (let i = -radius2; i <= radius2; i += step) {
15585
+ g.moveTo(-radius2, i);
15586
+ g.lineTo(radius2, i);
15587
+ g.moveTo(i, -radius2);
15588
+ g.lineTo(i, radius2);
15589
+ }
15590
+ g.strokePath();
15591
+ g.lineStyle(2, tint2, 0.6);
15592
+ g.strokeCircle(0, 0, radius2);
15593
+ g.strokeCircle(0, 0, radius2 * 0.66);
15594
+ g.strokeCircle(0, 0, radius2 * 0.33);
15595
+ const corners = [
15596
+ { x: -radius2 * 0.7, y: -radius2 * 0.7 },
15597
+ { x: radius2 * 0.7, y: -radius2 * 0.7 },
15598
+ { x: -radius2 * 0.7, y: radius2 * 0.7 },
15599
+ { x: radius2 * 0.7, y: radius2 * 0.7 }
15600
+ ];
15601
+ g.lineStyle(3, tint2, 0.8);
15602
+ corners.forEach(({ x, y }) => {
15603
+ g.moveTo(x - 10, y);
15604
+ g.lineTo(x + 10, y);
15605
+ g.moveTo(x, y - 10);
15606
+ g.lineTo(x, y + 10);
15607
+ });
15608
+ g.strokePath();
15609
+ }
15610
+ }
15611
+ );
15612
+ }
15613
+ function createMilitaryThumb(radius2, tint2 = 65280) {
15614
+ const r = radius2 * 0.3;
15615
+ return /* @__PURE__ */ jsxRuntime.jsx(
15616
+ Graphics,
15617
+ {
15618
+ onDraw: (g) => {
15619
+ g.fillStyle(tint2, 0.9);
15620
+ g.fillCircle(0, 0, r);
15621
+ g.fillStyle(0, 1);
15622
+ g.beginPath();
15623
+ g.moveTo(0, -r);
15624
+ g.lineTo(r * 0.5, r * 0.3);
15625
+ g.lineTo(-r * 0.5, r * 0.3);
15626
+ g.closePath();
15627
+ g.fillPath();
15628
+ g.lineStyle(2, 0, 0.8);
15629
+ g.strokeCircle(0, 0, r);
15630
+ }
15631
+ }
15632
+ );
15633
+ }
15634
+ function createDefaultBase(radius2, tint2 = 65280) {
15635
+ const size = { width: radius2 * 2 };
15636
+ return /* @__PURE__ */ jsxRuntime.jsx(
15637
+ Graphics,
15638
+ {
15639
+ onDraw: (g) => {
15640
+ g.fillStyle(0, 0.25);
15641
+ g.lineStyle(1, tint2);
15642
+ g.fillCircle(0, 0, size.width / 2);
15643
+ g.strokeCircle(0, 0, size.width / 2);
15644
+ }
15645
+ }
15646
+ );
15647
+ }
15648
+ function createDefaultThumb(radius2, tint2 = 65280) {
15649
+ const size = { width: radius2 * 2 };
15650
+ return /* @__PURE__ */ jsxRuntime.jsx(
15651
+ Graphics,
15652
+ {
15653
+ onDraw: (g) => {
15654
+ const r = size.width * 0.2;
15655
+ g.lineStyle(2, 0, 1);
15656
+ g.moveTo(0, -r);
15657
+ g.lineTo(0, r);
15658
+ g.moveTo(-r, 0);
15659
+ g.lineTo(r, 0);
15660
+ g.strokePath();
15661
+ g.lineStyle(2, tint2, 0.75);
15662
+ g.strokeCircle(0, 0, r * 1.1);
15663
+ }
15664
+ }
15665
+ );
15666
+ }
15667
+ const theme = joystickTheme != null ? joystickTheme.theme : "default";
15668
+ const tint = (joystickTheme != null ? joystickTheme.tint : 65280) ?? 65280;
15669
+ switch (theme) {
15670
+ case "neon":
15671
+ return {
15672
+ base: createNeonBase(radius, tint),
15673
+ thumb: createNeonThumb(radius, tint),
15674
+ rotateThumb: false
15675
+ };
15676
+ case "target":
15677
+ return {
15678
+ base: createTargetBase(radius, tint),
15679
+ thumb: createTargetThumb(radius, tint),
15680
+ rotateThumb: true
15681
+ };
15682
+ case "glass":
15683
+ return {
15684
+ base: createGlassBase(radius, tint),
15685
+ thumb: createGlassThumb(radius, tint),
15686
+ rotateThumb: false
15687
+ };
15688
+ case "military":
15689
+ return {
15690
+ base: createMilitaryBase(radius, tint),
15691
+ thumb: createMilitaryThumb(radius, tint),
15692
+ rotateThumb: true
15693
+ };
15694
+ case "default":
15695
+ default:
15696
+ return {
15697
+ base: createDefaultBase(radius, tint),
15698
+ thumb: createDefaultThumb(radius, tint),
15699
+ rotateThumb: false
15700
+ };
15701
+ }
15702
+ }
15703
+ function Joystick(props) {
15704
+ const outerRef = useRef(null);
15705
+ const [center, setCenter] = useState({ x: 0, y: 0 });
15706
+ const [size, setSize] = useState({ width: 0, height: 0 });
15707
+ const thumbRef = useRef(null);
15708
+ const forceExceededMinimumRef = useRef(false);
15709
+ const activeTweenRef = useRef(null);
15710
+ const isDraggingRef = useRef(false);
15711
+ const currentThumbPosRef = useRef({ x: 0, y: 0 });
15712
+ useEffect(() => {
15713
+ setTimeout(() => {
15714
+ const size2 = getLayoutSize(outerRef.current);
15715
+ console.log(`Joystick size: ${JSON.stringify(size2)}`);
15716
+ if (size2 != null) {
15717
+ const newCenter = { x: size2.width / 2, y: size2.height / 2 };
15718
+ setCenter(newCenter);
15719
+ setSize({ width: size2.width, height: size2.height });
15720
+ if (!isDraggingRef.current && !activeTweenRef.current) {
15721
+ currentThumbPosRef.current = newCenter;
15722
+ if (thumbRef.current != null) {
15723
+ thumbRef.current.setPosition(newCenter.x, newCenter.y);
15724
+ }
15725
+ }
15726
+ }
15727
+ }, 0);
15728
+ }, [outerRef]);
15729
+ const themeType = props.joystickTheme?.theme;
15730
+ const themeTint = props.joystickTheme?.tint;
15731
+ const sizeKey = `${size.width}x${size.height}`;
15732
+ const elements = useMemo(() => {
15733
+ if (props.base != null && props.thumb)
15734
+ return {
15735
+ base: props.base,
15736
+ thumb: props.thumb,
15737
+ rotateThumb: props.rotateThumb ?? false
15738
+ };
15739
+ if (size.width === 0 || size.height === 0)
15740
+ return {
15741
+ base: null,
15742
+ thumb: null,
15743
+ rotateThumb: false
15744
+ };
15745
+ const radius = Math.min(size.width, size.height) / 2;
15746
+ return joystickThemeFactory(props.joystickTheme, radius);
15747
+ }, [props.base, props.thumb, props.rotateThumb, themeType, themeTint, sizeKey]);
15748
+ const touchMove = (data) => {
15749
+ data.stopPropagation();
15750
+ if (thumbRef.current == null) return;
15751
+ if (data.state === "start") {
15752
+ forceExceededMinimumRef.current = false;
15753
+ isDraggingRef.current = true;
15754
+ }
15755
+ if (data.state === "end") {
15756
+ isDraggingRef.current = false;
15757
+ if (activeTweenRef.current) {
15758
+ activeTweenRef.current.stop();
15759
+ activeTweenRef.current = null;
15760
+ }
15761
+ if (thumbRef.current.scene) {
15762
+ activeTweenRef.current = thumbRef.current.scene.tweens.add({
15763
+ targets: thumbRef.current,
15764
+ x: center.x,
15765
+ y: center.y,
15766
+ angle: 0,
15767
+ duration: 150,
15768
+ ease: "Cubic.easeOut",
15769
+ onComplete: () => {
15770
+ activeTweenRef.current = null;
15771
+ currentThumbPosRef.current = { x: center.x, y: center.y };
15772
+ }
15773
+ });
15774
+ }
15775
+ props.onMove?.(false, 0, 0);
15776
+ return;
15777
+ }
15778
+ let offsetX = data.localX - data.width / 2 + center.x;
15779
+ let offsetY = data.localY - data.height / 2 + center.y;
15780
+ const radius = size.width / 2;
15781
+ const dx = offsetX - center.x;
15782
+ const dy = offsetY - center.y;
15783
+ const dist = Math.sqrt(dx * dx + dy * dy);
15784
+ const angle = Math.atan2(dy, dx) * (180 / Math.PI);
15785
+ const rawForce = Math.min(dist / radius, 1);
15786
+ const minForce = props.minForce ?? 0.2;
15787
+ const force = rawForce < minForce ? 0 : (rawForce - minForce) / (1 - minForce);
15788
+ if (force > 0) {
15789
+ forceExceededMinimumRef.current = true;
15790
+ }
15791
+ if (dist > radius) {
15792
+ const angleRad = Math.atan2(dy, dx);
15793
+ offsetX = center.x + Math.cos(angleRad) * radius;
15794
+ offsetY = center.y + Math.sin(angleRad) * radius;
15795
+ }
15796
+ if (activeTweenRef.current) {
15797
+ activeTweenRef.current.stop();
15798
+ activeTweenRef.current = null;
15799
+ }
15800
+ thumbRef.current.setPosition(offsetX, offsetY);
15801
+ currentThumbPosRef.current = { x: offsetX, y: offsetY };
15802
+ if (props.rotateThumb || elements.rotateThumb) {
15803
+ thumbRef.current.setAngle(angle + 90);
15804
+ }
15805
+ if (force > 0) {
15806
+ props.onMove?.(true, angle, force);
15807
+ } else {
15808
+ props.onMove?.(true, 0, 0);
15809
+ }
15810
+ };
15811
+ const handleTouch = () => {
15812
+ if (!forceExceededMinimumRef.current) {
15813
+ props.onTap?.();
15814
+ }
15815
+ };
15816
+ return /* @__PURE__ */ jsxRuntime.jsx(View, { ref: outerRef, width: props.width, height: props.height, children: /* @__PURE__ */ jsxRuntime.jsxs(
15817
+ RefOriginView,
15818
+ {
15819
+ width: props.width,
15820
+ height: props.height,
15821
+ originX: 0.5,
15822
+ originY: 0.5,
15823
+ onTouchMove: touchMove,
15824
+ onTouch: handleTouch,
15825
+ direction: "stack",
15826
+ children: [
15827
+ /* @__PURE__ */ jsxRuntime.jsx(View, { x: center.x, y: center.y, children: elements.base }),
15828
+ /* @__PURE__ */ jsxRuntime.jsx(View, { ref: thumbRef, x: currentThumbPosRef.current.x, y: currentThumbPosRef.current.y, children: elements.thumb })
15829
+ ]
15830
+ }
15831
+ ) });
15832
+ }
16377
15833
  function NineSlice(props) {
16378
15834
  const localTheme = useTheme();
16379
15835
  const { props: themed, nestedTheme } = getThemedProps("NineSlice", localTheme, props);
@@ -16573,7 +16029,13 @@ function Sidebar(props) {
16573
16029
  ...itemContainer
16574
16030
  } = itemStyle ?? {};
16575
16031
  const { textStyle: badgeTextStyle, ...badgeContainer } = badgeStyle ?? {};
16576
- const normalizeChildren = (child) => child ? Array.isArray(child) ? child : [child] : [];
16032
+ const normalizeChildren2 = (child) => {
16033
+ if (!child) return [];
16034
+ const flat = Array.isArray(child) ? child.flat(Infinity) : [child];
16035
+ return flat.filter(
16036
+ (node) => !!node && typeof node === "object" && "type" in node
16037
+ );
16038
+ };
16577
16039
  const renderTitle = (title) => {
16578
16040
  if (!title) return null;
16579
16041
  return typeof title === "string" ? /* @__PURE__ */ jsxRuntime.jsx(Text, { text: title, style: titleStyle }) : title;
@@ -16600,9 +16062,9 @@ function Sidebar(props) {
16600
16062
  const activeProps = item.active ? activeItemStyle ?? {} : {};
16601
16063
  const disabledProps = item.disabled && disabledAlpha !== void 0 ? { alpha: disabledAlpha } : {};
16602
16064
  const content = item.content ?? (item.label ? /* @__PURE__ */ jsxRuntime.jsx(Text, { text: item.label, style: itemTextStyle }) : null);
16603
- const iconNodes = normalizeChildren(item.icon ?? null);
16604
- const contentNodes2 = normalizeChildren(content);
16605
- const badgeNodes = normalizeChildren(renderBadge(item.badge));
16065
+ const iconNodes = normalizeChildren2(item.icon ?? null);
16066
+ const contentNodes2 = normalizeChildren2(content);
16067
+ const badgeNodes = normalizeChildren2(renderBadge(item.badge));
16606
16068
  const handleTouch = item.disabled ? void 0 : () => item.onSelect?.(item.key ?? key);
16607
16069
  return /* @__PURE__ */ jsxRuntime.jsx(
16608
16070
  View,
@@ -16647,7 +16109,7 @@ function Sidebar(props) {
16647
16109
  const hasSections = !!props.sections?.length;
16648
16110
  const primaryContent = sectionsContent ?? (!hasSections ? props.children : null) ?? null;
16649
16111
  const extraContent = hasSections ? props.children ?? null : null;
16650
- const contentNodes = [...normalizeChildren(primaryContent), ...normalizeChildren(extraContent)];
16112
+ const contentNodes = [...normalizeChildren2(primaryContent), ...normalizeChildren2(extraContent)];
16651
16113
  return /* @__PURE__ */ jsxRuntime.jsxs(
16652
16114
  View,
16653
16115
  {
@@ -17120,6 +16582,114 @@ function Slider(props) {
17120
16582
  function RangeSlider(props) {
17121
16583
  return /* @__PURE__ */ jsxRuntime.jsx(BaseSlider, { ...props, mode: "range" });
17122
16584
  }
16585
+ function Tab(_props) {
16586
+ return null;
16587
+ }
16588
+ function TabPanel(_props) {
16589
+ return null;
16590
+ }
16591
+ const normalizeChildren = (children) => {
16592
+ if (!children) return [];
16593
+ const flat = Array.isArray(children) ? children.flat(Infinity) : [children];
16594
+ return flat.filter(
16595
+ (child) => !!child && typeof child === "object" && "type" in child
16596
+ );
16597
+ };
16598
+ function Tabs(props) {
16599
+ const localTheme = useTheme();
16600
+ const { props: themed, nestedTheme } = getThemedProps("Tabs", localTheme, {});
16601
+ const [internalIndex, setInternalIndex] = useState(props.defaultIndex ?? 0);
16602
+ const rawIndex = props.activeIndex ?? internalIndex;
16603
+ const { tabs, panels } = useMemo(() => {
16604
+ const nodes = normalizeChildren(props.children);
16605
+ const collectedTabs = [];
16606
+ const collectedPanels = [];
16607
+ for (const node of nodes) {
16608
+ if (node.type === Tab) collectedTabs.push(node);
16609
+ if (node.type === TabPanel) collectedPanels.push(node);
16610
+ }
16611
+ return { tabs: collectedTabs, panels: collectedPanels };
16612
+ }, [props.children]);
16613
+ const panelCount = Math.min(tabs.length, panels.length);
16614
+ const safeIndex = panelCount > 0 ? Math.min(Math.max(rawIndex, 0), panelCount - 1) : 0;
16615
+ const handleSelect = (index) => {
16616
+ if (props.activeIndex === void 0) {
16617
+ setInternalIndex(index);
16618
+ }
16619
+ if (index !== safeIndex) {
16620
+ props.onChange?.(index);
16621
+ }
16622
+ };
16623
+ const tabListStyle = themed.tabListStyle ?? {};
16624
+ const tabStyle = themed.tabStyle ?? {};
16625
+ const tabActiveStyle = themed.tabActiveStyle ?? {};
16626
+ const tabDisabledStyle = themed.tabDisabledStyle ?? {};
16627
+ const panelStyle = themed.panelStyle ?? {};
16628
+ const {
16629
+ children: _children,
16630
+ activeIndex: _activeIndex,
16631
+ defaultIndex: _defaultIndex,
16632
+ onChange: _onChange,
16633
+ ...viewProps
16634
+ } = props;
16635
+ const activePanel = panels[safeIndex];
16636
+ const activePanelProps = activePanel?.props ?? {};
16637
+ const panelChildren = activePanel?.children ?? activePanelProps.children;
16638
+ const { children: _panelChildren, ...panelViewProps } = activePanelProps;
16639
+ const scrollableTabs = props.scrollableTabs ?? true;
16640
+ const tabListScrollProps = props.tabListScrollProps ?? {};
16641
+ const tabListContent = /* @__PURE__ */ jsxRuntime.jsx(View, { ...tabListStyle, direction: "row", width: scrollableTabs ? "auto" : "100%", children: tabs.slice(0, panelCount).map((tab, index) => {
16642
+ const tabProps = tab.props ?? {};
16643
+ const { disabled, onTouch, enableGestures, ...tabViewProps } = tabProps;
16644
+ const tabChildren = tab.children ?? tabProps.children;
16645
+ const isActive = index === safeIndex;
16646
+ const combinedTabStyle = {
16647
+ ...tabStyle,
16648
+ ...isActive ? tabActiveStyle : {},
16649
+ ...disabled ? tabDisabledStyle : {},
16650
+ ...tabViewProps
16651
+ };
16652
+ const tabKey = tab.__key ?? tabProps.key ?? index;
16653
+ return /* @__PURE__ */ jsxRuntime.jsx(
16654
+ View,
16655
+ {
16656
+ ...combinedTabStyle,
16657
+ enableGestures: !disabled && (enableGestures ?? true),
16658
+ onTouch: (data) => {
16659
+ if (disabled) return;
16660
+ handleSelect(index);
16661
+ onTouch?.(data);
16662
+ },
16663
+ children: tabChildren
16664
+ },
16665
+ tabKey
16666
+ );
16667
+ }) });
16668
+ const [tabHeight, setTabHeight] = useState(0);
16669
+ const [sliderHeight, setSliderHeight] = useState(0);
16670
+ const ref = useRef(null);
16671
+ useLayoutEffect(() => {
16672
+ const layout = useLayoutRect(ref);
16673
+ if (layout) setTabHeight(layout.height);
16674
+ }, [props, ref]);
16675
+ return /* @__PURE__ */ jsxRuntime.jsxs(View, { ...themed, ...viewProps, direction: "column", theme: nestedTheme, children: [
16676
+ scrollableTabs ? /* @__PURE__ */ jsxRuntime.jsx(
16677
+ ScrollView,
16678
+ {
16679
+ width: "100%",
16680
+ height: tabHeight + sliderHeight,
16681
+ showHorizontalSlider: "auto",
16682
+ showVerticalSlider: false,
16683
+ sliderSize: "nano",
16684
+ theme: nestedTheme,
16685
+ onSliderSize: (size) => setSliderHeight(size.height),
16686
+ ...tabListScrollProps,
16687
+ children: /* @__PURE__ */ jsxRuntime.jsx(View, { ref, children: tabListContent })
16688
+ }
16689
+ ) : tabListContent,
16690
+ activePanel ? /* @__PURE__ */ jsxRuntime.jsx(View, { ...panelStyle, ...panelViewProps, children: panelChildren }) : null
16691
+ ] });
16692
+ }
17123
16693
  function interpolateColor(color1, color2, progress) {
17124
16694
  const rgb1 = numberToRgb(color1);
17125
16695
  const rgb2 = numberToRgb(color2);
@@ -17251,7 +16821,7 @@ function Toggle(props) {
17251
16821
  ]
17252
16822
  }
17253
16823
  );
17254
- const labelElement = props.label && labelPosition !== "none" && /* @__PURE__ */ jsxRuntime.jsx(Text, { text: props.label, style: themed.labelStyle });
16824
+ const labelElement = props.label && labelPosition !== "none" ? /* @__PURE__ */ jsxRuntime.jsx(Text, { text: props.label, style: themed.labelStyle }) : null;
17255
16825
  if (!props.label || labelPosition === "none") {
17256
16826
  return /* @__PURE__ */ jsxRuntime.jsxs(View, { ref: containerRef, direction: "row", alignItems: "center", gap, theme: nestedTheme, children: [
17257
16827
  props.prefix,
@@ -17363,10 +16933,12 @@ exports.Graphics = Graphics;
17363
16933
  exports.HexColor = HexColor;
17364
16934
  exports.Icon = Icon;
17365
16935
  exports.Image = Image$1;
16936
+ exports.Joystick = Joystick;
17366
16937
  exports.KeyboardInputManager = KeyboardInputManager;
17367
16938
  exports.Modal = Modal;
17368
16939
  exports.NineSlice = NineSlice;
17369
16940
  exports.NineSliceButton = NineSliceButton;
16941
+ exports.Particles = Particles;
17370
16942
  exports.Portal = Portal;
17371
16943
  exports.RadioButton = RadioButton;
17372
16944
  exports.RadioGroup = RadioGroup;
@@ -17378,9 +16950,10 @@ exports.ScrollView = ScrollView;
17378
16950
  exports.Sidebar = Sidebar;
17379
16951
  exports.Slider = Slider;
17380
16952
  exports.SpringPhysics = SpringPhysics;
17381
- exports.Sprite = Sprite;
16953
+ exports.Tab = Tab;
16954
+ exports.TabPanel = TabPanel;
16955
+ exports.Tabs = Tabs;
17382
16956
  exports.Text = Text;
17383
- exports.TileSprite = TileSprite;
17384
16957
  exports.Toggle = Toggle;
17385
16958
  exports.TransformOriginView = TransformOriginView;
17386
16959
  exports.View = View;
@@ -17390,6 +16963,7 @@ exports.animatedSignal = animatedSignal;
17390
16963
  exports.applyDarkMode = applyDarkMode;
17391
16964
  exports.applyEffectByName = applyEffectByName;
17392
16965
  exports.applyLightMode = applyLightMode;
16966
+ exports.calculateLayout = calculateLayout;
17393
16967
  exports.calculateSliderSize = calculateSliderSize;
17394
16968
  exports.createBounceEffect = createBounceEffect;
17395
16969
  exports.createBreatheEffect = createBreatheEffect;
@@ -17427,21 +17001,26 @@ exports.defaultTextStyleTokens = defaultTextStyleTokens;
17427
17001
  exports.defaultTheme = defaultTheme;
17428
17002
  exports.disposeCtx = disposeCtx;
17429
17003
  exports.ensureContrast = ensureContrast;
17004
+ exports.equal = equal;
17430
17005
  exports.forestGreenPreset = forestGreenPreset;
17431
17006
  exports.generateColorScale = generateColorScale;
17007
+ exports.getBackgroundGraphics = getBackgroundGraphics;
17008
+ exports.getChildSize = getChildSize;
17432
17009
  exports.getContrastRatio = getContrastRatio;
17433
17010
  exports.getCurrent = getCurrent;
17011
+ exports.getGestureManager = getGestureManager;
17012
+ exports.getLayoutProps = getLayoutProps;
17013
+ exports.getLayoutRect = getLayoutRect;
17014
+ exports.getLayoutSize = getLayoutSize;
17015
+ exports.getMountStats = getMountStats;
17434
17016
  exports.getPreset = getPreset;
17435
17017
  exports.getPresetWithMode = getPresetWithMode;
17436
17018
  exports.getRenderContext = getRenderContext;
17437
17019
  exports.getThemedProps = getThemedProps;
17438
- exports.graphicsCreator = graphicsCreator;
17439
- exports.graphicsPatcher = graphicsPatcher;
17020
+ exports.getWorldLayoutRect = getWorldLayoutRect;
17440
17021
  exports.hex = hex;
17441
17022
  exports.hexToNumber = hexToNumber;
17442
17023
  exports.host = host;
17443
- exports.imageCreator = imageCreator;
17444
- exports.imagePatcher = imagePatcher;
17445
17024
  exports.isAnimatedSignal = isAnimatedSignal;
17446
17025
  exports.lighten = lighten;
17447
17026
  exports.lightenHex = lightenHex;
@@ -17449,44 +17028,42 @@ exports.mergeThemes = mergeThemes;
17449
17028
  exports.midnightPreset = midnightPreset;
17450
17029
  exports.mount = mount;
17451
17030
  exports.mountJSX = mountJSX;
17452
- exports.nineSliceCreator = nineSliceCreator;
17453
- exports.nineSlicePatcher = nineSlicePatcher;
17454
17031
  exports.nodeRegistry = nodeRegistry;
17455
17032
  exports.normalizeCornerRadius = normalizeCornerRadius;
17456
17033
  exports.normalizeEdgeInsets = normalizeEdgeInsets;
17457
17034
  exports.normalizeGap = normalizeGap;
17035
+ exports.normalizeVNodeLike = normalizeVNodeLike;
17458
17036
  exports.numberToHex = numberToHex;
17459
17037
  exports.numberToRgb = numberToRgb;
17460
17038
  exports.oceanBluePreset = oceanBluePreset;
17039
+ exports.parseSize = parseSize;
17461
17040
  exports.patchVNode = patchVNode;
17462
17041
  exports.portalRegistry = portalRegistry;
17463
17042
  exports.presets = presets;
17464
17043
  exports.register = register;
17465
- exports.registerBuiltins = registerBuiltins;
17466
17044
  exports.releaseAllSVGTextures = releaseAllSVGTextures;
17467
17045
  exports.releaseSVGTexture = releaseSVGTexture;
17468
17046
  exports.releaseSVGTextures = releaseSVGTextures;
17469
17047
  exports.remountAll = remountAll;
17470
17048
  exports.resolveEffect = resolveEffect;
17049
+ exports.resolveSize = resolveSize;
17471
17050
  exports.rgbToNumber = rgbToNumber;
17472
17051
  exports.shallowEqual = shallowEqual;
17473
17052
  exports.shouldComponentUpdate = shouldComponentUpdate;
17474
- exports.spriteCreator = spriteCreator;
17475
- exports.spritePatcher = spritePatcher;
17476
17053
  exports.svgToTexture = svgToTexture;
17477
- exports.textCreator = textCreator;
17478
- exports.textPatcher = textPatcher;
17479
17054
  exports.themeRegistry = themeRegistry;
17480
- exports.tileSpriteCreator = tileSpriteCreator;
17481
- exports.tileSpritePatcher = tileSpritePatcher;
17482
17055
  exports.unmount = unmount;
17483
17056
  exports.unmountJSX = unmountJSX;
17484
17057
  exports.unwrapSignal = unwrapSignal;
17058
+ exports.useBackgroundGraphics = useBackgroundGraphics;
17485
17059
  exports.useCallback = useCallback;
17486
17060
  exports.useEffect = useEffect;
17487
17061
  exports.useForceRedraw = useForceRedraw;
17488
17062
  exports.useGameObjectEffect = useGameObjectEffect;
17489
17063
  exports.useIconPreload = useIconPreload;
17064
+ exports.useLayoutEffect = useLayoutEffect;
17065
+ exports.useLayoutRect = useLayoutRect;
17066
+ exports.useLayoutSize = useLayoutSize;
17490
17067
  exports.useMemo = useMemo;
17491
17068
  exports.useRedraw = useRedraw;
17492
17069
  exports.useRef = useRef;
@@ -17497,9 +17074,9 @@ exports.useSpring = useSpring;
17497
17074
  exports.useSprings = useSprings;
17498
17075
  exports.useState = useState;
17499
17076
  exports.useTheme = useTheme;
17077
+ exports.useViewportSize = useViewportSize;
17078
+ exports.useWorldLayoutRect = useWorldLayoutRect;
17500
17079
  exports.vdom = vdom;
17501
- exports.viewCreator = viewCreator;
17502
- exports.viewPatcher = viewPatcher;
17503
17080
  exports.viewportRegistry = viewportRegistry;
17504
17081
  exports.withHooks = withHooks;
17505
- //# sourceMappingURL=TransformOriginView-KcTgaYRi.cjs.map
17082
+ //# sourceMappingURL=TransformOriginView-Bx81YEUU.cjs.map