@number10/phaserjsx 0.2.0 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (138) hide show
  1. package/dist/{TransformOriginView-BDM6GE2F.cjs → TransformOriginView-Bx81YEUU.cjs} +1378 -1518
  2. package/dist/TransformOriginView-Bx81YEUU.cjs.map +1 -0
  3. package/dist/{TransformOriginView-CiFiQcku.js → TransformOriginView-DCvId72M.js} +1500 -1640
  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 +7 -2
  60. package/dist/components/custom/ScrollSlider.d.ts.map +1 -1
  61. package/dist/components/custom/ScrollView.d.ts +29 -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 +2153 -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 -131
  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/layout/utils/size-resolver.d.ts.map +1 -1
  113. package/dist/particles/emit-zone.d.ts +67 -0
  114. package/dist/particles/emit-zone.d.ts.map +1 -0
  115. package/dist/particles/index.d.ts +8 -0
  116. package/dist/particles/index.d.ts.map +1 -0
  117. package/dist/particles/particle-types.d.ts +20 -0
  118. package/dist/particles/particle-types.d.ts.map +1 -0
  119. package/dist/particles/preset-registry.d.ts +46 -0
  120. package/dist/particles/preset-registry.d.ts.map +1 -0
  121. package/dist/particles/use-particles.d.ts +15 -0
  122. package/dist/particles/use-particles.d.ts.map +1 -0
  123. package/dist/particles/utils.d.ts +10 -0
  124. package/dist/particles/utils.d.ts.map +1 -0
  125. package/dist/plugin.d.ts +157 -0
  126. package/dist/plugin.d.ts.map +1 -0
  127. package/dist/theme-base.d.ts +10 -1
  128. package/dist/theme-base.d.ts.map +1 -1
  129. package/dist/theme-custom.d.ts +7 -0
  130. package/dist/theme-custom.d.ts.map +1 -1
  131. package/dist/theme-defaults.d.ts.map +1 -1
  132. package/dist/types.d.ts +18 -1
  133. package/dist/types.d.ts.map +1 -1
  134. package/dist/vdom.d.ts +42 -4
  135. package/dist/vdom.d.ts.map +1 -1
  136. package/package.json +4 -5
  137. package/dist/TransformOriginView-BDM6GE2F.cjs.map +0 -1
  138. package/dist/TransformOriginView-CiFiQcku.js.map +0 -1
@@ -74,623 +74,6 @@ const host = {
74
74
  layout() {
75
75
  }
76
76
  };
77
- function shallowEqual$1(a, b) {
78
- if (!a || !b) return a === b;
79
- if (a.length !== b.length) return false;
80
- return a.every((val, i) => val === b[i]);
81
- }
82
- function applyGraphicsProps(node, _prev, next) {
83
- const prevDeps = node.__drawDependencies;
84
- const nextDeps = next.dependencies;
85
- const depsChanged2 = !shallowEqual$1(prevDeps, nextDeps);
86
- if (depsChanged2 && next.onDraw) {
87
- if (next.autoClear !== false) {
88
- node.clear();
89
- }
90
- next.onDraw(node, next);
91
- node.__drawDependencies = nextDeps;
92
- }
93
- }
94
- function applyGraphicsLayout(node, prev, next) {
95
- node.__layoutProps = next;
96
- if (prev.width !== next.width || prev.height !== next.height || prev.headless !== next.headless) {
97
- node.__getLayoutSize = () => {
98
- if (next.headless ?? true) {
99
- return { width: 0.01, height: 0.01 };
100
- }
101
- return {
102
- width: typeof next.width === "number" ? next.width : 0,
103
- height: typeof next.height === "number" ? next.height : 0
104
- };
105
- };
106
- }
107
- }
108
- function normalizeVisible$1(visible) {
109
- if (visible === void 0) return true;
110
- if (typeof visible === "boolean") return visible;
111
- if (visible === "visible") return true;
112
- if (visible === "invisible" || visible === "none") return false;
113
- return true;
114
- }
115
- function applyPhaserProps(node, prev, next) {
116
- if (prev.alpha !== next.alpha && typeof next.alpha === "number") {
117
- node.setAlpha?.(next.alpha);
118
- }
119
- if (prev.depth !== next.depth && typeof next.depth === "number") {
120
- node.setDepth?.(next.depth);
121
- }
122
- if (prev.visible !== next.visible) {
123
- const visibleValue = normalizeVisible$1(next.visible);
124
- node.visible = visibleValue;
125
- }
126
- }
127
- function applyTransformProps(node, prev, next) {
128
- if (prev.x !== next.x && typeof next.x === "number") {
129
- node.x = next.x;
130
- }
131
- if (prev.y !== next.y && typeof next.y === "number") {
132
- node.y = next.y;
133
- }
134
- if (prev.rotation !== next.rotation && typeof next.rotation === "number") {
135
- node.rotation = next.rotation;
136
- }
137
- const nextScale = next.scale;
138
- const nextScaleX = next.scaleX;
139
- const nextScaleY = next.scaleY;
140
- const prevScale = prev.scale;
141
- const prevScaleX = prev.scaleX;
142
- const prevScaleY = prev.scaleY;
143
- if (nextScale !== void 0 && nextScale !== prevScale) {
144
- node.setScale?.(nextScale, nextScale);
145
- } else if (nextScaleX !== prevScaleX || nextScaleY !== prevScaleY) {
146
- const currentScaleX = node.scaleX ?? 1;
147
- const currentScaleY = node.scaleY ?? 1;
148
- const sx = nextScaleX ?? currentScaleX;
149
- const sy = nextScaleY ?? currentScaleY;
150
- node.setScale?.(sx, sy);
151
- }
152
- }
153
- function createGraphicsLayout(graphics, props) {
154
- if (props.headless === false) {
155
- if (typeof props.width !== "number" || typeof props.height !== "number") {
156
- throw new Error(
157
- "Graphics component requires explicit width and height props when headless=false"
158
- );
159
- }
160
- }
161
- graphics.__layoutProps = props;
162
- graphics.__getLayoutSize = () => {
163
- if (graphics.__layoutProps?.headless ?? true) {
164
- return { width: 0.01, height: 0.01 };
165
- }
166
- return {
167
- width: props.width ?? 0,
168
- height: props.height ?? 0
169
- };
170
- };
171
- graphics.__drawDependencies = props.dependencies;
172
- }
173
- function normalizeVisible(visible) {
174
- if (visible === void 0) return true;
175
- if (typeof visible === "boolean") return visible;
176
- if (visible === "visible") return true;
177
- if (visible === "invisible" || visible === "none") return false;
178
- return true;
179
- }
180
- function createPhaser(node, props) {
181
- if (props.visible !== void 0) {
182
- node.visible = normalizeVisible(props.visible);
183
- }
184
- if (props.depth !== void 0) {
185
- node.setDepth(props.depth);
186
- }
187
- if (props.alpha !== void 0) {
188
- node.setAlpha(props.alpha);
189
- }
190
- }
191
- function createTransform(node, props) {
192
- if (props.scaleX !== void 0 || props.scaleY !== void 0) {
193
- node.setScale(
194
- props.scaleX ?? 1,
195
- props.scaleY ?? 1
196
- );
197
- }
198
- if (props.rotation !== void 0) {
199
- node.setRotation(props.rotation);
200
- }
201
- }
202
- const graphicsCreator = (scene, props) => {
203
- const graphics = scene.add.graphics();
204
- graphics.setPosition(props.x ?? 0, props.y ?? 0);
205
- createTransform(graphics, props);
206
- createPhaser(graphics, props);
207
- createGraphicsLayout(graphics, props);
208
- if (props.onDraw) {
209
- props.onDraw(graphics, props);
210
- }
211
- return graphics;
212
- };
213
- const graphicsPatcher = (node, prev, next) => {
214
- applyTransformProps(node, prev, next);
215
- applyPhaserProps(node, prev, next);
216
- applyGraphicsProps(node, prev, next);
217
- applyGraphicsLayout(node, prev, next);
218
- };
219
- function calculateFitScale$1(image, targetWidth, targetHeight, fit = "fill") {
220
- const textureWidth = image.width;
221
- const textureHeight = image.height;
222
- if (textureWidth === 0 || textureHeight === 0) {
223
- return { scaleX: 1, scaleY: 1 };
224
- }
225
- if (fit === "fill") {
226
- return {
227
- scaleX: targetWidth / textureWidth,
228
- scaleY: targetHeight / textureHeight
229
- };
230
- }
231
- const targetAspect = targetWidth / targetHeight;
232
- const textureAspect = textureWidth / textureHeight;
233
- if (fit === "contain") {
234
- const scale = targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
235
- return { scaleX: scale, scaleY: scale };
236
- }
237
- if (fit === "cover") {
238
- const scale = targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
239
- return { scaleX: scale, scaleY: scale };
240
- }
241
- return { scaleX: 1, scaleY: 1 };
242
- }
243
- function applyImageProps(image, prev, next) {
244
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
245
- if (textureChanged && next.texture) {
246
- image.setTexture(next.texture, next.frame);
247
- }
248
- if (prev.tint !== next.tint) {
249
- if (typeof next.tint === "number") {
250
- image.setTint(next.tint);
251
- } else {
252
- image.clearTint();
253
- }
254
- }
255
- if (prev.originX !== next.originX || prev.originY !== next.originY) {
256
- const originX = next.originX ?? image.originX;
257
- const originY = next.originY ?? image.originY;
258
- image.setOrigin(originX, originY);
259
- }
260
- const displayWidthChanged = prev.displayWidth !== next.displayWidth;
261
- const displayHeightChanged = prev.displayHeight !== next.displayHeight;
262
- const fitChanged = prev.fit !== next.fit;
263
- if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {
264
- if (typeof next.displayWidth === "number" && typeof next.displayHeight === "number") {
265
- const { scaleX, scaleY } = calculateFitScale$1(
266
- image,
267
- next.displayWidth,
268
- next.displayHeight,
269
- next.fit
270
- );
271
- image.setScale(scaleX, scaleY);
272
- } else if (typeof next.displayWidth === "number") {
273
- const scale = next.displayWidth / image.width;
274
- image.setScale(scale);
275
- } else if (typeof next.displayHeight === "number") {
276
- const scale = next.displayHeight / image.height;
277
- image.setScale(scale, scale);
278
- }
279
- }
280
- }
281
- function applyImageLayout(image, prev, next) {
282
- image.__layoutProps = next;
283
- if (prev.headless !== next.headless) {
284
- image.__getLayoutSize = () => {
285
- if (image.__layoutProps?.headless) {
286
- return { width: 0.01, height: 0.01 };
287
- }
288
- return {
289
- width: image.displayWidth,
290
- height: image.displayHeight
291
- };
292
- };
293
- }
294
- }
295
- function createImageLayout(image, props) {
296
- image.__layoutProps = props;
297
- image.__getLayoutSize = () => {
298
- if (image.__layoutProps?.headless) {
299
- return { width: 0.01, height: 0.01 };
300
- }
301
- return {
302
- width: image.displayWidth,
303
- height: image.displayHeight
304
- };
305
- };
306
- }
307
- const imageCreator = (scene, props) => {
308
- const image = scene.add.image(props.x ?? 0, props.y ?? 0, props.texture, props.frame);
309
- if (props.headless) {
310
- image.setOrigin(0.5, 0.5);
311
- } else {
312
- image.setOrigin(0, 0);
313
- }
314
- if (props.originX !== void 0 || props.originY !== void 0) {
315
- image.setOrigin(props.originX ?? image.originX, props.originY ?? image.originY);
316
- }
317
- const normalizedProps = { ...props };
318
- if (props.headless) {
319
- delete normalizedProps.padding;
320
- delete normalizedProps.margin;
321
- delete normalizedProps.gap;
322
- } else {
323
- if (normalizedProps.rotation !== void 0) {
324
- delete normalizedProps.rotation;
325
- }
326
- }
327
- createTransform(image, normalizedProps);
328
- createPhaser(image, normalizedProps);
329
- if (props.tint !== void 0) {
330
- image.setTint(props.tint);
331
- }
332
- if (props.displayWidth !== void 0 || props.displayHeight !== void 0) {
333
- if (props.displayWidth !== void 0 && props.displayHeight !== void 0) {
334
- const fit = props.fit ?? "fill";
335
- const textureWidth = image.width;
336
- const textureHeight = image.height;
337
- if (textureWidth > 0 && textureHeight > 0) {
338
- if (fit === "fill") {
339
- image.setDisplaySize(props.displayWidth, props.displayHeight);
340
- } else if (fit === "contain") {
341
- const targetAspect = props.displayWidth / props.displayHeight;
342
- const textureAspect = textureWidth / textureHeight;
343
- const scale = targetAspect > textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
344
- image.setScale(scale);
345
- } else if (fit === "cover") {
346
- const targetAspect = props.displayWidth / props.displayHeight;
347
- const textureAspect = textureWidth / textureHeight;
348
- const scale = targetAspect < textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
349
- image.setScale(scale);
350
- }
351
- }
352
- } else if (props.displayWidth !== void 0) {
353
- const scale = props.displayWidth / image.width;
354
- image.setScale(scale);
355
- } else if (props.displayHeight !== void 0) {
356
- const scale = props.displayHeight / image.height;
357
- image.setScale(scale);
358
- }
359
- }
360
- createImageLayout(image, normalizedProps);
361
- if (props.onReady) {
362
- props.onReady(image);
363
- }
364
- return image;
365
- };
366
- const imagePatcher = (node, prev, next) => {
367
- if (prev.headless !== next.headless) {
368
- if (next.headless) {
369
- node.setOrigin(0.5, 0.5);
370
- } else {
371
- node.setOrigin(0, 0);
372
- }
373
- }
374
- const normalizedPrev = { ...prev };
375
- const normalizedNext = { ...next };
376
- if (next.headless) {
377
- delete normalizedNext.padding;
378
- delete normalizedNext.margin;
379
- delete normalizedNext.gap;
380
- } else {
381
- if (normalizedNext.rotation !== void 0) {
382
- delete normalizedNext.rotation;
383
- }
384
- }
385
- if (prev.headless) {
386
- delete normalizedPrev.padding;
387
- delete normalizedPrev.margin;
388
- delete normalizedPrev.gap;
389
- } else {
390
- if (normalizedPrev.rotation !== void 0) {
391
- delete normalizedPrev.rotation;
392
- }
393
- }
394
- applyTransformProps(node, normalizedPrev, normalizedNext);
395
- applyPhaserProps(node, normalizedPrev, normalizedNext);
396
- applyImageProps(node, normalizedPrev, normalizedNext);
397
- applyImageLayout(node, normalizedPrev, normalizedNext);
398
- };
399
- function applyNineSliceProps(nineSlice, prev, next) {
400
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
401
- if (textureChanged && next.texture) {
402
- nineSlice.setTexture(next.texture, next.frame);
403
- }
404
- const sliceChanged = prev.leftWidth !== next.leftWidth || prev.rightWidth !== next.rightWidth || prev.topHeight !== next.topHeight || prev.bottomHeight !== next.bottomHeight;
405
- if (sliceChanged) {
406
- const width = typeof next.width === "number" ? next.width : nineSlice.width;
407
- const height = typeof next.height === "number" ? next.height : nineSlice.height;
408
- nineSlice.setSlices(
409
- width,
410
- height,
411
- next.leftWidth ?? prev.leftWidth ?? 0,
412
- next.rightWidth ?? prev.rightWidth ?? 0,
413
- next.topHeight ?? prev.topHeight,
414
- next.bottomHeight ?? prev.bottomHeight
415
- );
416
- }
417
- const prevWidth = typeof prev.width === "number" ? prev.width : nineSlice.width;
418
- const nextWidth = typeof next.width === "number" ? next.width : nineSlice.width;
419
- const prevHeight = typeof prev.height === "number" ? prev.height : nineSlice.height;
420
- const nextHeight = typeof next.height === "number" ? next.height : nineSlice.height;
421
- if (prevWidth !== nextWidth || prevHeight !== nextHeight) {
422
- nineSlice.setSize(nextWidth, nextHeight);
423
- }
424
- if (prev.tint !== next.tint) {
425
- if (next.tint !== void 0) {
426
- nineSlice.setTint(next.tint);
427
- } else {
428
- nineSlice.clearTint();
429
- }
430
- }
431
- }
432
- function applyNineSliceLayout(nineSlice, prev, next) {
433
- nineSlice.__layoutProps = next;
434
- if (prev.width !== next.width || prev.height !== next.height) {
435
- nineSlice.__getLayoutSize = () => {
436
- return {
437
- width: nineSlice.width,
438
- height: nineSlice.height
439
- };
440
- };
441
- }
442
- }
443
- function createNineSliceLayout(nineSlice, props) {
444
- nineSlice.__layoutProps = props;
445
- nineSlice.__getLayoutSize = () => {
446
- return {
447
- width: nineSlice.width,
448
- height: nineSlice.height
449
- };
450
- };
451
- }
452
- const nineSliceCreator = (scene, props) => {
453
- const initialWidth = typeof props.width === "number" ? props.width : 64;
454
- const initialHeight = typeof props.height === "number" ? props.height : 64;
455
- const nineSlice = scene.add.nineslice(
456
- props.x ?? 0,
457
- props.y ?? 0,
458
- props.texture,
459
- props.frame,
460
- initialWidth,
461
- initialHeight,
462
- props.leftWidth,
463
- props.rightWidth,
464
- props.topHeight,
465
- props.bottomHeight
466
- );
467
- nineSlice.setOrigin(0, 0);
468
- if (props.tint !== void 0) {
469
- nineSlice.setTint(props.tint);
470
- }
471
- createTransform(nineSlice, props);
472
- createPhaser(nineSlice, props);
473
- createNineSliceLayout(nineSlice, props);
474
- return nineSlice;
475
- };
476
- const nineSlicePatcher = (node, prev, next) => {
477
- applyTransformProps(node, prev, next);
478
- applyPhaserProps(node, prev, next);
479
- applyNineSliceProps(node, prev, next);
480
- applyNineSliceLayout(node, prev, next);
481
- };
482
- function getOriginalTextureDimensions(sprite) {
483
- const frame = sprite.frame;
484
- return {
485
- width: frame.width,
486
- height: frame.height
487
- };
488
- }
489
- function calculateFitScale(sprite, targetWidth, targetHeight, fit = "fill") {
490
- const { width: textureWidth, height: textureHeight } = getOriginalTextureDimensions(sprite);
491
- if (textureWidth === 0 || textureHeight === 0) {
492
- return { scaleX: 1, scaleY: 1 };
493
- }
494
- if (fit === "fill") {
495
- return {
496
- scaleX: targetWidth / textureWidth,
497
- scaleY: targetHeight / textureHeight
498
- };
499
- }
500
- const targetAspect = targetWidth / targetHeight;
501
- const textureAspect = textureWidth / textureHeight;
502
- if (fit === "contain") {
503
- const scale = targetAspect > textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
504
- return { scaleX: scale, scaleY: scale };
505
- }
506
- if (fit === "cover") {
507
- const scale = targetAspect < textureAspect ? targetHeight / textureHeight : targetWidth / textureWidth;
508
- return { scaleX: scale, scaleY: scale };
509
- }
510
- return { scaleX: 1, scaleY: 1 };
511
- }
512
- function applySpriteProps(sprite, prev, next) {
513
- const textureChanged = prev.texture !== next.texture || prev.frame !== next.frame;
514
- if (textureChanged && next.texture) {
515
- sprite.setTexture(next.texture, next.frame);
516
- }
517
- if (prev.tint !== next.tint) {
518
- if (typeof next.tint === "number") {
519
- sprite.setTint(next.tint);
520
- } else {
521
- sprite.clearTint();
522
- }
523
- }
524
- if (prev.originX !== next.originX || prev.originY !== next.originY) {
525
- const originX = next.originX ?? sprite.originX;
526
- const originY = next.originY ?? sprite.originY;
527
- sprite.setOrigin(originX, originY);
528
- }
529
- const displayWidthChanged = prev.displayWidth !== next.displayWidth;
530
- const displayHeightChanged = prev.displayHeight !== next.displayHeight;
531
- const fitChanged = prev.fit !== next.fit;
532
- if (displayWidthChanged || displayHeightChanged || fitChanged || textureChanged) {
533
- if (typeof next.displayWidth === "number" && typeof next.displayHeight === "number") {
534
- const fit = next.fit ?? "fill";
535
- if (fit === "fill") {
536
- sprite.setDisplaySize(next.displayWidth, next.displayHeight);
537
- } else {
538
- const { scaleX, scaleY } = calculateFitScale(
539
- sprite,
540
- next.displayWidth,
541
- next.displayHeight,
542
- fit
543
- );
544
- sprite.setScale(scaleX, scaleY);
545
- }
546
- } else if (typeof next.displayWidth === "number") {
547
- const { width: origWidth } = getOriginalTextureDimensions(sprite);
548
- const scale = next.displayWidth / origWidth;
549
- sprite.setScale(scale);
550
- } else if (typeof next.displayHeight === "number") {
551
- const { height: origHeight } = getOriginalTextureDimensions(sprite);
552
- const scale = next.displayHeight / origHeight;
553
- sprite.setScale(scale, scale);
554
- } else {
555
- sprite.setScale(1);
556
- }
557
- }
558
- const animationChanged = prev.animationKey !== next.animationKey || prev.loop !== next.loop || prev.repeatDelay !== next.repeatDelay;
559
- if (animationChanged) {
560
- if (sprite.anims.isPlaying) {
561
- sprite.anims.stop();
562
- }
563
- if (next.animationKey) {
564
- sprite.anims.play({
565
- key: next.animationKey,
566
- repeat: next.loop ? -1 : 0,
567
- repeatDelay: next.repeatDelay ?? 0
568
- });
569
- }
570
- }
571
- const callbacksChanged = prev.onAnimationStart !== next.onAnimationStart || prev.onAnimationComplete !== next.onAnimationComplete || prev.onAnimationRepeat !== next.onAnimationRepeat || prev.onAnimationUpdate !== next.onAnimationUpdate;
572
- if (callbacksChanged) {
573
- sprite.off("animationstart");
574
- sprite.off("animationcomplete");
575
- sprite.off("animationrepeat");
576
- sprite.off("animationupdate");
577
- if (next.onAnimationStart) {
578
- sprite.on("animationstart", (anim) => {
579
- next.onAnimationStart?.(anim.key);
580
- });
581
- }
582
- if (next.onAnimationComplete) {
583
- sprite.on("animationcomplete", (anim) => {
584
- next.onAnimationComplete?.(anim.key);
585
- });
586
- }
587
- if (next.onAnimationRepeat) {
588
- sprite.on("animationrepeat", (anim) => {
589
- next.onAnimationRepeat?.(anim.key);
590
- });
591
- }
592
- if (next.onAnimationUpdate) {
593
- sprite.on(
594
- "animationupdate",
595
- (anim, frame) => {
596
- next.onAnimationUpdate?.(anim.key, frame);
597
- }
598
- );
599
- }
600
- }
601
- }
602
- function applySpriteLayout(sprite, _prev, next) {
603
- sprite.__layoutProps = next;
604
- }
605
- function createSpriteLayout(sprite, props) {
606
- sprite.__layoutProps = props;
607
- sprite.__getLayoutSize = () => {
608
- return { width: 0.01, height: 0.01 };
609
- };
610
- }
611
- const spriteCreator = (scene, props) => {
612
- const sprite = scene.add.sprite(props.x ?? 0, props.y ?? 0, props.texture, props.frame);
613
- sprite.setOrigin(0.5, 0.5);
614
- if (props.originX !== void 0 || props.originY !== void 0) {
615
- sprite.setOrigin(props.originX ?? sprite.originX, props.originY ?? sprite.originY);
616
- }
617
- createTransform(sprite, props);
618
- createPhaser(sprite, props);
619
- if (props.tint !== void 0) {
620
- sprite.setTint(props.tint);
621
- }
622
- if (props.displayWidth !== void 0 || props.displayHeight !== void 0) {
623
- if (props.displayWidth !== void 0 && props.displayHeight !== void 0) {
624
- const fit = props.fit ?? "fill";
625
- const textureWidth = sprite.width;
626
- const textureHeight = sprite.height;
627
- if (textureWidth > 0 && textureHeight > 0) {
628
- if (fit === "fill") {
629
- sprite.setDisplaySize(props.displayWidth, props.displayHeight);
630
- } else if (fit === "contain") {
631
- const targetAspect = props.displayWidth / props.displayHeight;
632
- const textureAspect = textureWidth / textureHeight;
633
- const scale = targetAspect > textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
634
- sprite.setScale(scale);
635
- } else if (fit === "cover") {
636
- const targetAspect = props.displayWidth / props.displayHeight;
637
- const textureAspect = textureWidth / textureHeight;
638
- const scale = targetAspect < textureAspect ? props.displayHeight / textureHeight : props.displayWidth / textureWidth;
639
- sprite.setScale(scale);
640
- }
641
- }
642
- } else if (props.displayWidth !== void 0) {
643
- const scale = props.displayWidth / sprite.width;
644
- sprite.setScale(scale);
645
- } else if (props.displayHeight !== void 0) {
646
- const scale = props.displayHeight / sprite.height;
647
- sprite.setScale(scale);
648
- }
649
- }
650
- if (props.animationKey) {
651
- if (sprite.scene && sprite.scene.anims.exists(props.animationKey)) {
652
- sprite.anims.play({
653
- key: props.animationKey,
654
- repeat: props.loop ? -1 : 0,
655
- repeatDelay: props.repeatDelay ?? 0
656
- });
657
- }
658
- }
659
- if (props.onAnimationStart) {
660
- sprite.on("animationstart", (anim) => {
661
- props.onAnimationStart?.(anim.key);
662
- });
663
- }
664
- if (props.onAnimationComplete) {
665
- sprite.on("animationcomplete", (anim) => {
666
- props.onAnimationComplete?.(anim.key);
667
- });
668
- }
669
- if (props.onAnimationRepeat) {
670
- sprite.on("animationrepeat", (anim) => {
671
- props.onAnimationRepeat?.(anim.key);
672
- });
673
- }
674
- if (props.onAnimationUpdate) {
675
- sprite.on(
676
- "animationupdate",
677
- (anim, frame) => {
678
- props.onAnimationUpdate?.(anim.key, frame);
679
- }
680
- );
681
- }
682
- createSpriteLayout(sprite, props);
683
- if (props.onReady) {
684
- props.onReady(sprite);
685
- }
686
- return sprite;
687
- };
688
- const spritePatcher = (node, prev, next) => {
689
- applyTransformProps(node, prev, next);
690
- applyPhaserProps(node, prev, next);
691
- applySpriteProps(node, prev, next);
692
- applySpriteLayout(node, prev, next);
693
- };
694
77
  var commonjsGlobal = typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : typeof global !== "undefined" ? global : typeof self !== "undefined" ? self : {};
695
78
  function getDefaultExportFromCjs(x) {
696
79
  return x && x.__esModule && Object.prototype.hasOwnProperty.call(x, "default") ? x["default"] : x;
@@ -6643,10 +6026,6 @@ function resolveCalcOperand(operand, parentSize, viewportSize) {
6643
6026
  }
6644
6027
  if (operand.type === "percent") {
6645
6028
  if (parentSize === void 0) {
6646
- DebugLogger.warn(
6647
- "Size",
6648
- "Cannot resolve percentage in calc() without parent size. Using 0."
6649
- );
6650
6029
  return 0;
6651
6030
  }
6652
6031
  return parentSize * operand.value / 100;
@@ -6769,213 +6148,6 @@ function clampSize(size, minSize, maxSize, parentSize, fallbackSize, parentPaddi
6769
6148
  }
6770
6149
  return clamped;
6771
6150
  }
6772
- function applyTextProps(node, prev, next) {
6773
- if (node.active === false || node.scene && !node.scene.sys.game) {
6774
- return;
6775
- }
6776
- let needsUpdate = false;
6777
- if (prev.text !== next.text && typeof next.text === "string") {
6778
- node.setText(next.text);
6779
- needsUpdate = true;
6780
- }
6781
- if (next.style !== void 0 && !equal(next.style, prev.style || {})) {
6782
- try {
6783
- node.setStyle(next.style);
6784
- needsUpdate = true;
6785
- } catch (error) {
6786
- console.warn("Failed to apply text style (scene may be transitioning):", error);
6787
- }
6788
- }
6789
- if (next.maxWidth !== prev.maxWidth && next.maxWidth !== void 0) {
6790
- const viewport = viewportRegistry.getViewport();
6791
- const parsedMaxWidth = parseSize(next.maxWidth);
6792
- const resolvedMaxWidth = resolveSize(parsedMaxWidth, viewport?.width, void 0, void 0);
6793
- node.setWordWrapWidth(resolvedMaxWidth, true);
6794
- needsUpdate = true;
6795
- }
6796
- if (prev.style !== next.style && next.style !== void 0) {
6797
- try {
6798
- node.setStyle(next.style);
6799
- needsUpdate = true;
6800
- } catch (error) {
6801
- console.warn("Failed to apply text style (scene may be transitioning):", error);
6802
- }
6803
- }
6804
- if (needsUpdate && node.updateText) {
6805
- node.updateText();
6806
- }
6807
- }
6808
- function applyTextLayout(text, _prev, next) {
6809
- text.__layoutProps = next;
6810
- text.__getLayoutSize = () => {
6811
- if (text.__layoutProps?.headless) {
6812
- return { width: 0.01, height: 0.01 };
6813
- }
6814
- return {
6815
- width: text.width,
6816
- height: text.height
6817
- };
6818
- };
6819
- }
6820
- function createTextLayout(text, props) {
6821
- text.__layoutProps = props;
6822
- text.__getLayoutSize = () => {
6823
- if (text.__layoutProps?.headless) {
6824
- return { width: 0.01, height: 0.01 };
6825
- }
6826
- return {
6827
- width: text.width,
6828
- height: text.height
6829
- };
6830
- };
6831
- }
6832
- const textCreator = (scene, props) => {
6833
- const text = scene.add.text(props.x ?? 0, props.y ?? 0, props.text ?? "", props.style);
6834
- if (props.headless) {
6835
- text.setOrigin(0.5, 0.5);
6836
- } else {
6837
- text.setOrigin(0, 0);
6838
- }
6839
- const normalizedProps = { ...props };
6840
- if (props.headless) {
6841
- delete normalizedProps.padding;
6842
- delete normalizedProps.margin;
6843
- delete normalizedProps.gap;
6844
- } else {
6845
- if (normalizedProps.rotation !== void 0) {
6846
- delete normalizedProps.rotation;
6847
- }
6848
- }
6849
- createTransform(text, normalizedProps);
6850
- createPhaser(text, normalizedProps);
6851
- createTextLayout(text, normalizedProps);
6852
- return text;
6853
- };
6854
- const textPatcher = (node, prev, next) => {
6855
- if (prev.headless !== next.headless) {
6856
- if (next.headless) {
6857
- node.setOrigin(0.5, 0.5);
6858
- } else {
6859
- node.setOrigin(0, 0);
6860
- }
6861
- }
6862
- const normalizedPrev = { ...prev };
6863
- const normalizedNext = { ...next };
6864
- if (next.headless) {
6865
- delete normalizedNext.padding;
6866
- delete normalizedNext.margin;
6867
- delete normalizedNext.gap;
6868
- } else {
6869
- if (normalizedNext.rotation !== void 0) {
6870
- delete normalizedNext.rotation;
6871
- }
6872
- }
6873
- if (prev.headless) {
6874
- delete normalizedPrev.padding;
6875
- delete normalizedPrev.margin;
6876
- delete normalizedPrev.gap;
6877
- } else {
6878
- if (normalizedPrev.rotation !== void 0) {
6879
- delete normalizedPrev.rotation;
6880
- }
6881
- }
6882
- applyTransformProps(node, normalizedPrev, normalizedNext);
6883
- applyPhaserProps(node, normalizedPrev, normalizedNext);
6884
- applyTextProps(node, normalizedPrev, normalizedNext);
6885
- applyTextLayout(node, normalizedPrev, normalizedNext);
6886
- };
6887
- const tileSpriteCreator = (_scene, _props) => {
6888
- throw new Error(
6889
- "TileSprite component not implemented yet. This is a placeholder for architecture planning."
6890
- );
6891
- };
6892
- const tileSpritePatcher = (_node, _prev, _next) => {
6893
- throw new Error(
6894
- "TileSprite component not implemented yet. This is a placeholder for architecture planning."
6895
- );
6896
- };
6897
- function applyBackgroundProps(container, prev, next) {
6898
- const prevBgColor = prev.backgroundColor;
6899
- const nextBgColor = next.backgroundColor;
6900
- const prevBgAlpha = prev.backgroundAlpha ?? 1;
6901
- const nextBgAlpha = next.backgroundAlpha ?? 1;
6902
- const prevWidth = typeof prev.width === "number" ? prev.width : 100;
6903
- const nextWidth = typeof next.width === "number" ? next.width : 100;
6904
- const prevHeight = typeof prev.height === "number" ? prev.height : 100;
6905
- const nextHeight = typeof next.height === "number" ? next.height : 100;
6906
- const prevCornerRadius = prev.cornerRadius ?? 0;
6907
- const nextCornerRadius = next.cornerRadius ?? 0;
6908
- const prevBorderColor = prev.borderColor;
6909
- const nextBorderColor = next.borderColor;
6910
- const prevBorderWidth = prev.borderWidth ?? 0;
6911
- const nextBorderWidth = next.borderWidth ?? 0;
6912
- const prevBorderAlpha = prev.borderAlpha ?? 1;
6913
- const nextBorderAlpha = next.borderAlpha ?? 1;
6914
- const prevHasBorder = prevBorderWidth > 0 && prevBorderColor !== void 0;
6915
- const nextHasBorder = nextBorderWidth > 0 && nextBorderColor !== void 0;
6916
- const prevHasGraphics = prevBgColor !== void 0 || prevHasBorder;
6917
- const nextHasGraphics = nextBgColor !== void 0 || nextHasBorder;
6918
- if (prevHasGraphics && !nextHasGraphics) {
6919
- if (container.__background) {
6920
- container.__background.destroy();
6921
- delete container.__background;
6922
- }
6923
- } else if (!prevHasGraphics && nextHasGraphics) {
6924
- if (container.scene) {
6925
- const background = container.scene.add.graphics();
6926
- if (nextBgColor !== void 0) {
6927
- background.fillStyle(nextBgColor, nextBgAlpha);
6928
- }
6929
- if (nextHasBorder) {
6930
- background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha);
6931
- }
6932
- if (nextCornerRadius !== 0) {
6933
- if (nextBgColor !== void 0) {
6934
- background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6935
- }
6936
- if (nextHasBorder) {
6937
- background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6938
- }
6939
- } else {
6940
- if (nextBgColor !== void 0) {
6941
- background.fillRect(0, 0, nextWidth, nextHeight);
6942
- }
6943
- if (nextHasBorder) {
6944
- background.strokeRect(0, 0, nextWidth, nextHeight);
6945
- }
6946
- }
6947
- container.addAt(background, 0);
6948
- container.__background = background;
6949
- background.__isBackground = true;
6950
- }
6951
- } else if (container.__background && nextHasGraphics) {
6952
- const needsRedraw = prevBgColor !== nextBgColor || prevBgAlpha !== nextBgAlpha || prevWidth !== nextWidth || prevHeight !== nextHeight || prevCornerRadius !== nextCornerRadius || prevBorderWidth !== nextBorderWidth || prevBorderColor !== nextBorderColor || prevBorderAlpha !== nextBorderAlpha;
6953
- if (needsRedraw) {
6954
- container.__background.clear();
6955
- if (nextBgColor !== void 0) {
6956
- container.__background.fillStyle(nextBgColor, nextBgAlpha);
6957
- }
6958
- if (nextHasBorder) {
6959
- container.__background.lineStyle(nextBorderWidth, nextBorderColor, nextBorderAlpha);
6960
- }
6961
- if (nextCornerRadius !== 0) {
6962
- if (nextBgColor !== void 0) {
6963
- container.__background.fillRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6964
- }
6965
- if (nextHasBorder) {
6966
- container.__background.strokeRoundedRect(0, 0, nextWidth, nextHeight, nextCornerRadius);
6967
- }
6968
- } else {
6969
- if (nextBgColor !== void 0) {
6970
- container.__background.fillRect(0, 0, nextWidth, nextHeight);
6971
- }
6972
- if (nextHasBorder) {
6973
- container.__background.strokeRect(0, 0, nextWidth, nextHeight);
6974
- }
6975
- }
6976
- }
6977
- }
6978
- }
6979
6151
  const DEFAULT_GESTURE_CONFIG = {
6980
6152
  longPressDuration: 500,
6981
6153
  doubleTapDelay: 300,
@@ -7054,6 +6226,9 @@ class GestureManager {
7054
6226
  this.activePointerDown = null;
7055
6227
  }
7056
6228
  this.hoveredContainers.delete(container);
6229
+ for (const hitContainers of this.activeContainersForMove.values()) {
6230
+ hitContainers.delete(container);
6231
+ }
7057
6232
  }
7058
6233
  /**
7059
6234
  * Check if a container is registered
@@ -7232,8 +6407,8 @@ class GestureManager {
7232
6407
  this.activePointerDown = {
7233
6408
  pointerId: pointer.id,
7234
6409
  container: state.container,
7235
- startX: pointer.x,
7236
- startY: pointer.y
6410
+ startX: pointer.worldX,
6411
+ startY: pointer.worldY
7237
6412
  };
7238
6413
  state.longPressTriggered = false;
7239
6414
  state.pointerDownTime = Date.now();
@@ -7255,12 +6430,31 @@ class GestureManager {
7255
6430
  }
7256
6431
  }, state.config.longPressDuration);
7257
6432
  }
7258
- state.pointerDownPosition = { x: pointer.x, y: pointer.y };
6433
+ state.pointerDownPosition = { x: pointer.worldX, y: pointer.worldY };
7259
6434
  }
7260
6435
  }
7261
6436
  }
7262
6437
  if (hitContainers.size > 0) {
7263
6438
  this.activeContainersForMove.set(pointer.id, hitContainers);
6439
+ this.bubbleEvent(
6440
+ pointer,
6441
+ "onTouchMove",
6442
+ (targetState, targetLocalPos) => {
6443
+ const isInside = this.isPointerInContainer(pointer, targetState);
6444
+ const data = this.createEventData(
6445
+ pointer,
6446
+ targetLocalPos.x,
6447
+ targetLocalPos.y,
6448
+ targetState.hitArea.width,
6449
+ targetState.hitArea.height,
6450
+ { dx: 0, dy: 0, isInside, state: "start" }
6451
+ );
6452
+ targetState.callbacks.onTouchMove?.(data);
6453
+ targetState.isFirstMove = false;
6454
+ return data.isPropagationStopped();
6455
+ },
6456
+ hitContainers
6457
+ );
7264
6458
  }
7265
6459
  }
7266
6460
  /**
@@ -7282,8 +6476,8 @@ class GestureManager {
7282
6476
  const touchDuration = state.pointerDownTime ? Date.now() - state.pointerDownTime : 0;
7283
6477
  const isTouchTooLong = touchDuration > state.config.maxTouchDuration;
7284
6478
  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;
6479
+ const dx = last ? pointer.worldX - last.x : 0;
6480
+ const dy = last ? pointer.worldY - last.y : 0;
7287
6481
  const hitContainers = this.activeContainersForMove.get(pointer.id);
7288
6482
  this.bubbleEvent(
7289
6483
  pointer,
@@ -7419,8 +6613,8 @@ class GestureManager {
7419
6613
  state.longPressTimer = void 0;
7420
6614
  }
7421
6615
  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;
6616
+ const dx = last ? pointer.worldX - last.x : 0;
6617
+ const dy = last ? pointer.worldY - last.y : 0;
7424
6618
  const hitContainers = this.activeContainersForMove.get(pointer.id);
7425
6619
  this.bubbleEvent(
7426
6620
  pointer,
@@ -7458,9 +6652,9 @@ class GestureManager {
7458
6652
  */
7459
6653
  handlePointerMove(pointer) {
7460
6654
  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 });
6655
+ const dx = last ? pointer.worldX - last.x : 0;
6656
+ const dy = last ? pointer.worldY - last.y : 0;
6657
+ this.lastPointerPositions.set(pointer.id, { x: pointer.worldX, y: pointer.worldY });
7464
6658
  this.detectHoverChanges(pointer);
7465
6659
  if (!this.activePointerDown || pointer.id !== this.activePointerDown.pointerId) {
7466
6660
  return;
@@ -7534,7 +6728,7 @@ class GestureManager {
7534
6728
  getLocalPosition(pointer, container) {
7535
6729
  const matrix = container.getWorldTransformMatrix();
7536
6730
  const inverseMatrix = matrix.invert();
7537
- const localPos = inverseMatrix.transformPoint(pointer.x, pointer.y);
6731
+ const localPos = inverseMatrix.transformPoint(pointer.worldX, pointer.worldY);
7538
6732
  return { x: localPos.x, y: localPos.y };
7539
6733
  }
7540
6734
  /**
@@ -7604,6 +6798,7 @@ class GestureManager {
7604
6798
  const scaleY = canvas.height / rect.height;
7605
6799
  pointer.x = (event.clientX - rect.left) * scaleX;
7606
6800
  pointer.y = (event.clientY - rect.top) * scaleY;
6801
+ pointer.updateWorldPoint(pointer.camera ?? this.scene.cameras.main);
7607
6802
  const containersUnderPointer = [];
7608
6803
  Array.from(this.containers.values()).forEach((state, originalIndex) => {
7609
6804
  if (!state.callbacks.onWheel) return;
@@ -7704,83 +6899,6 @@ function getGestureManager(scene) {
7704
6899
  }
7705
6900
  return manager;
7706
6901
  }
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
6902
  function normalizeEdgeInsets(value) {
7785
6903
  if (value === void 0) {
7786
6904
  return {};
@@ -8856,10 +7974,57 @@ const strategies = {
8856
7974
  row: new RowLayoutStrategy(),
8857
7975
  stack: new StackLayoutStrategy()
8858
7976
  };
7977
+ const LAYOUT_CYCLE_EPSILON = 0.5;
7978
+ const LAYOUT_CYCLE_TIME_MS = 100;
7979
+ const LAYOUT_CYCLE_MAX = 5;
7980
+ const LAYOUT_MAX_SIZE = 2e5;
7981
+ const layoutCycleGuard = /* @__PURE__ */ new WeakMap();
7982
+ function isCloseSize(a, b, epsilon) {
7983
+ return Math.abs(a.width - b.width) < epsilon && Math.abs(a.height - b.height) < epsilon;
7984
+ }
8859
7985
  function invalidateParentLayoutIfNeeded(container, oldSize, newWidth, newHeight) {
8860
- if (!oldSize || oldSize.width === newWidth && oldSize.height === newHeight) {
7986
+ if (!oldSize || Math.abs(oldSize.width - newWidth) < LAYOUT_CYCLE_EPSILON && Math.abs(oldSize.height - newHeight) < LAYOUT_CYCLE_EPSILON) {
7987
+ return;
7988
+ }
7989
+ if (!Number.isFinite(newWidth) || !Number.isFinite(newHeight) || newWidth > LAYOUT_MAX_SIZE || newHeight > LAYOUT_MAX_SIZE) {
7990
+ const containerWithProps = container;
7991
+ DebugLogger.warn("layout", "Runaway layout size detected, skipping parent invalidation", {
7992
+ oldSize,
7993
+ newSize: { width: newWidth, height: newHeight },
7994
+ containerProps: containerWithProps.__layoutProps,
7995
+ childCount: containerWithProps.list?.length ?? 0
7996
+ });
8861
7997
  return;
8862
7998
  }
7999
+ const newSize = { width: newWidth, height: newHeight };
8000
+ const now = Date.now();
8001
+ const guard = layoutCycleGuard.get(container);
8002
+ if (guard) {
8003
+ const repeatsPrev = guard.prev ? isCloseSize(guard.prev, newSize, LAYOUT_CYCLE_EPSILON) : false;
8004
+ if (repeatsPrev && now - guard.lastTime < LAYOUT_CYCLE_TIME_MS) {
8005
+ guard.count += 1;
8006
+ } else {
8007
+ guard.count = 0;
8008
+ }
8009
+ guard.prev = guard.last;
8010
+ guard.last = newSize;
8011
+ guard.lastTime = now;
8012
+ layoutCycleGuard.set(container, guard);
8013
+ if (guard.count >= LAYOUT_CYCLE_MAX) {
8014
+ DebugLogger.warn("layout", "Layout cycle detected, skipping parent invalidation", {
8015
+ container,
8016
+ oldSize,
8017
+ newSize
8018
+ });
8019
+ return;
8020
+ }
8021
+ } else {
8022
+ layoutCycleGuard.set(container, {
8023
+ last: newSize,
8024
+ count: 0,
8025
+ lastTime: now
8026
+ });
8027
+ }
8863
8028
  const parent = container.parentContainer;
8864
8029
  if (!parent || !parent.__layoutProps) {
8865
8030
  return;
@@ -9244,87 +8409,6 @@ function calculateLayoutImmediate(container, containerProps, parentSize, parentP
9244
8409
  function calculateLayout(container, containerProps, parentSize, parentPadding) {
9245
8410
  LayoutBatchQueue.schedule(container, containerProps, parentSize, parentPadding);
9246
8411
  }
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
8412
  class HexColor extends String {
9329
8413
  /**
9330
8414
  * Convert to Phaser number format
@@ -9818,6 +8902,10 @@ function buildDefaultTheme(colors) {
9818
8902
  alpha: 1,
9819
8903
  visible: true
9820
8904
  },
8905
+ particles: {
8906
+ alpha: 1,
8907
+ visible: true
8908
+ },
9821
8909
  // Public API (uppercase)
9822
8910
  View: {
9823
8911
  alpha: 1,
@@ -9849,6 +8937,10 @@ function buildDefaultTheme(colors) {
9849
8937
  alpha: 1,
9850
8938
  visible: true
9851
8939
  },
8940
+ Particles: {
8941
+ alpha: 1,
8942
+ visible: true
8943
+ },
9852
8944
  RadioButton: {
9853
8945
  selectedColor: colors.primary.DEFAULT.toNumber(),
9854
8946
  color: colors.border.medium.toNumber(),
@@ -10033,6 +9125,41 @@ function buildDefaultTheme(colors) {
10033
9125
  fontSize: "18px"
10034
9126
  }
10035
9127
  },
9128
+ Tabs: {
9129
+ tabListStyle: {
9130
+ backgroundColor: colors.surface.dark.toNumber(),
9131
+ padding: { left: 8, right: 8, top: 8, bottom: 0 },
9132
+ cornerRadius: { tl: 6, tr: 6, bl: 0, br: 0 },
9133
+ width: "fill",
9134
+ gap: 10,
9135
+ alignItems: "end",
9136
+ justifyContent: "start"
9137
+ },
9138
+ tabStyle: {
9139
+ backgroundColor: colors.surface.medium.toNumber(),
9140
+ borderColor: colors.border.medium.toNumber(),
9141
+ borderWidth: 1,
9142
+ padding: { left: 8, right: 8, top: 8, bottom: 3 },
9143
+ cornerRadius: { tl: 6, tr: 6, bl: 0, br: 0 }
9144
+ },
9145
+ tabActiveStyle: {
9146
+ padding: { left: 8, right: 8, top: 8, bottom: 8 },
9147
+ backgroundColor: colors.primary.DEFAULT.toNumber(),
9148
+ borderColor: colors.primary.dark.toNumber(),
9149
+ borderWidth: 2
9150
+ },
9151
+ tabDisabledStyle: {
9152
+ alpha: 0.4
9153
+ },
9154
+ panelStyle: {
9155
+ backgroundColor: colors.surface.light.toNumber(),
9156
+ borderColor: colors.border.medium.toNumber(),
9157
+ borderWidth: 1,
9158
+ padding: 10,
9159
+ cornerRadius: { tl: 0, tr: 0, bl: 6, br: 6 },
9160
+ width: "fill"
9161
+ }
9162
+ },
10036
9163
  NineSliceButton: {},
10037
9164
  CharText: {
10038
9165
  charSpacing: 0,
@@ -10487,442 +9614,6 @@ function getThemedProps(componentName, localTheme, explicitProps) {
10487
9614
  nestedTheme: mergedNestedThemes
10488
9615
  };
10489
9616
  }
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
9617
  class RenderContext {
10927
9618
  constructor(scene) {
10928
9619
  this.scene = scene;
@@ -11249,9 +9940,9 @@ class MountRegistry {
11249
9940
  * @param rootNode - Root game object
11250
9941
  * @returns Registry ID for this mount
11251
9942
  */
11252
- register(parent, type, props, rootNode) {
9943
+ register(parent, type, props, rootNode, vnode) {
11253
9944
  const id = this.nextId++;
11254
- this.entries.set(id, { id, parent, type, props, rootNode });
9945
+ this.entries.set(id, { id, parent, type, props, rootNode, vnode });
11255
9946
  DebugLogger.log("vdom", `Registered mount ${id}`);
11256
9947
  return id;
11257
9948
  }
@@ -11266,6 +9957,49 @@ class MountRegistry {
11266
9957
  this.entries.delete(id);
11267
9958
  }
11268
9959
  }
9960
+ /**
9961
+ * Get a specific mount entry by registry ID
9962
+ * @param id - Registry ID
9963
+ * @returns Mount entry or undefined if not found
9964
+ */
9965
+ getEntry(id) {
9966
+ return this.entries.get(id);
9967
+ }
9968
+ /**
9969
+ * Find a mount entry by parent and optional key
9970
+ * If key is provided, matches parent AND key
9971
+ * If key is omitted, returns first mount with matching parent (backward compatibility)
9972
+ * Validates that scene is still active and objects are not destroyed
9973
+ * @param parent - Parent container or scene
9974
+ * @param key - Optional unique key to distinguish multiple mounts on same parent
9975
+ * @returns Mount entry or undefined if not found or invalid
9976
+ */
9977
+ findByParentAndKey(parent, key) {
9978
+ for (const entry of this.entries.values()) {
9979
+ const scene = entry.parent instanceof Phaser$1.Scene ? entry.parent : entry.parent.scene;
9980
+ if (!scene || !scene.sys || !scene.sys.settings.active) {
9981
+ DebugLogger.log("vdom", `Removing mount ${entry.id} - scene inactive`);
9982
+ this.unregister(entry.id);
9983
+ continue;
9984
+ }
9985
+ if (!entry.rootNode.active || entry.rootNode.scene !== scene) {
9986
+ DebugLogger.log("vdom", `Removing mount ${entry.id} - rootNode destroyed or scene changed`);
9987
+ this.unregister(entry.id);
9988
+ continue;
9989
+ }
9990
+ const entryKey = entry.props.key;
9991
+ if (key !== void 0) {
9992
+ if (entry.parent === parent && entryKey === key) {
9993
+ return entry;
9994
+ }
9995
+ } else {
9996
+ if (entry.parent === parent) {
9997
+ return entry;
9998
+ }
9999
+ }
10000
+ }
10001
+ return void 0;
10002
+ }
11269
10003
  /**
11270
10004
  * Get all active mount entries
11271
10005
  * @returns Array of mount entries
@@ -11273,6 +10007,50 @@ class MountRegistry {
11273
10007
  getAllEntries() {
11274
10008
  return Array.from(this.entries.values());
11275
10009
  }
10010
+ /**
10011
+ * Get count of active mounts
10012
+ * @returns Number of registered mounts
10013
+ */
10014
+ getCount() {
10015
+ return this.entries.size;
10016
+ }
10017
+ /**
10018
+ * Get statistics about active mounts
10019
+ * @returns Object with mount statistics
10020
+ */
10021
+ getStats() {
10022
+ const byType = /* @__PURE__ */ new Map();
10023
+ const byParent = /* @__PURE__ */ new Map();
10024
+ const byKey = /* @__PURE__ */ new Map();
10025
+ const mounts = [];
10026
+ for (const entry of this.entries.values()) {
10027
+ const typeName = typeof entry.type === "string" ? entry.type : entry.type.name || "Component";
10028
+ byType.set(typeName, (byType.get(typeName) ?? 0) + 1);
10029
+ byParent.set(entry.parent, (byParent.get(entry.parent) ?? 0) + 1);
10030
+ const key = entry.props.key;
10031
+ if (key) {
10032
+ byKey.set(key, (byKey.get(key) ?? 0) + 1);
10033
+ }
10034
+ const parentType = entry.parent instanceof Phaser$1.Scene ? "Scene" : "Container";
10035
+ const mountInfo = {
10036
+ id: entry.id,
10037
+ type: typeName,
10038
+ parentType,
10039
+ propsKeys: Object.keys(entry.props)
10040
+ };
10041
+ if (key !== void 0) {
10042
+ mountInfo.key = key;
10043
+ }
10044
+ mounts.push(mountInfo);
10045
+ }
10046
+ return {
10047
+ totalMounts: this.entries.size,
10048
+ byType,
10049
+ byParent,
10050
+ byKey,
10051
+ mounts
10052
+ };
10053
+ }
11276
10054
  /**
11277
10055
  * Clear all entries (for testing)
11278
10056
  */
@@ -11282,6 +10060,9 @@ class MountRegistry {
11282
10060
  }
11283
10061
  }
11284
10062
  const mountRegistry = new MountRegistry();
10063
+ function getMountStats() {
10064
+ return mountRegistry.getStats();
10065
+ }
11285
10066
  function remountAll() {
11286
10067
  const entries = mountRegistry.getAllEntries();
11287
10068
  if (entries.length === 0) {
@@ -11343,7 +10124,9 @@ function remountAll() {
11343
10124
  rootNode.__mountRootId = generateMountRootId();
11344
10125
  }
11345
10126
  entry.rootNode = rootNode;
10127
+ entry.vnode = vnode;
11346
10128
  rootNode.__registryId = entry.id;
10129
+ rootNode.__rootVNode = vnode;
11347
10130
  console.log("[REMOUNT] Successfully remounted entry", entry.id);
11348
10131
  } catch (error) {
11349
10132
  console.error("[REMOUNT] Failed to remount entry", entry.id, error);
@@ -11351,6 +10134,14 @@ function remountAll() {
11351
10134
  });
11352
10135
  console.log("[REMOUNT] Remount complete");
11353
10136
  }
10137
+ function normalizeVNodeLike(rendered) {
10138
+ if (!rendered) return null;
10139
+ if (Array.isArray(rendered)) {
10140
+ const flat = rendered.flat(Infinity);
10141
+ return { type: Fragment, props: {}, children: flat };
10142
+ }
10143
+ return rendered;
10144
+ }
11354
10145
  function flattenChildren(children) {
11355
10146
  if (!children) return [];
11356
10147
  return children.flat(Infinity);
@@ -11604,10 +10395,11 @@ function mount(parentOrScene, vnode) {
11604
10395
  };
11605
10396
  vnode = setVNodePropSafe(vnode, "__ctx", ctx);
11606
10397
  const propsWithChildren = vnode.children?.length ? { ...vnode.props ?? {}, children: vnode.children } : vnode.props;
11607
- let rendered = withHooks(
10398
+ const renderedRaw = withHooks(
11608
10399
  ctx,
11609
10400
  () => vnode.type(propsWithChildren)
11610
10401
  );
10402
+ let rendered = normalizeVNodeLike(renderedRaw);
11611
10403
  if (!rendered) {
11612
10404
  ctx.vnode = rendered;
11613
10405
  for (const run of ctx.effects) run();
@@ -11766,6 +10558,30 @@ function patchVNode(parent, oldV, newV) {
11766
10558
  warnUnnecessaryRemount(oldV, newV);
11767
10559
  unmount(oldV);
11768
10560
  mount(parent, newV);
10561
+ if (parent && typeof parent === "object" && "list" in parent) {
10562
+ const parentContainer = parent;
10563
+ if (parentContainer.__layoutProps) {
10564
+ let grandparentSize;
10565
+ const grandparent = parentContainer.parentContainer;
10566
+ if (grandparent && grandparent.__layoutProps && grandparent.__getLayoutSize) {
10567
+ const gpSize = grandparent.__getLayoutSize();
10568
+ const gpPadding = grandparent.__layoutProps.padding ?? 0;
10569
+ const normGpPadding = typeof gpPadding === "number" ? { left: gpPadding, right: gpPadding, top: gpPadding, bottom: gpPadding } : {
10570
+ left: gpPadding.left ?? 0,
10571
+ right: gpPadding.right ?? 0,
10572
+ top: gpPadding.top ?? 0,
10573
+ bottom: gpPadding.bottom ?? 0
10574
+ };
10575
+ grandparentSize = {
10576
+ width: gpSize.width - normGpPadding.left - normGpPadding.right,
10577
+ height: gpSize.height - normGpPadding.top - normGpPadding.bottom
10578
+ };
10579
+ }
10580
+ calculateLayout(parentContainer, parentContainer.__layoutProps, grandparentSize);
10581
+ const renderContext = getRenderContext(parent);
10582
+ renderContext.deferLayout(() => updateGestureHitAreaAfterLayout(parentContainer));
10583
+ }
10584
+ }
11769
10585
  return;
11770
10586
  }
11771
10587
  if (oldV.type === Fragment && newV.type === Fragment) {
@@ -11811,10 +10627,12 @@ function patchVNode(parent, oldV, newV) {
11811
10627
  if (!ctx) {
11812
10628
  if (!newV || !oldV) return;
11813
10629
  const propsWithChildren2 = newV.children?.length ? { ...newV.props ?? {}, children: newV.children } : newV.props;
11814
- const oldRendered = oldV.type(
10630
+ const oldRenderedRaw = oldV.type(
11815
10631
  oldV.children?.length ? { ...oldV.props ?? {}, children: oldV.children } : oldV.props
11816
10632
  );
11817
- const newRendered = newV.type(propsWithChildren2);
10633
+ const newRenderedRaw = newV.type(propsWithChildren2);
10634
+ const oldRendered = normalizeVNodeLike(oldRenderedRaw);
10635
+ const newRendered = normalizeVNodeLike(newRenderedRaw);
11818
10636
  patchVNode(parent, oldRendered, newRendered);
11819
10637
  return;
11820
10638
  }
@@ -11832,10 +10650,11 @@ function patchVNode(parent, oldV, newV) {
11832
10650
  if (!shouldComponentUpdate(ctx, propsWithChildren)) {
11833
10651
  return;
11834
10652
  }
11835
- const renderedNext = withHooks(
10653
+ const renderedNextRaw = withHooks(
11836
10654
  ctx,
11837
10655
  () => newVWithCtx.type(propsWithChildren)
11838
10656
  );
10657
+ const renderedNext = normalizeVNodeLike(renderedNextRaw);
11839
10658
  if (!renderedNext) {
11840
10659
  ctx.vnode = renderedNext;
11841
10660
  for (const run of ctx.effects) run();
@@ -11866,6 +10685,7 @@ function patchVNode(parent, oldV, newV) {
11866
10685
  }
11867
10686
  const nodeType = oldV.type;
11868
10687
  newV = setVNodePropSafe(newV, "__node", oldV.__node);
10688
+ newV = setVNodePropSafe(newV, "__parent", parent);
11869
10689
  if (newV.__theme !== void 0) {
11870
10690
  const themed = setThemeSafe(oldV, newV.__theme);
11871
10691
  if (themed !== oldV) {
@@ -11910,6 +10730,11 @@ function patchVNode(parent, oldV, newV) {
11910
10730
  warnMissingKeys(newV, b);
11911
10731
  }
11912
10732
  const containerLayoutChanged = hasLayoutPropsChanged(oldV, newV);
10733
+ const oldValidChildCount = a.filter((c) => c != null && c !== false).length;
10734
+ const newValidChildCount = b.filter((c) => c != null && c !== false).length;
10735
+ if (oldValidChildCount !== newValidChildCount) {
10736
+ childrenChanged = true;
10737
+ }
11913
10738
  for (let i = 0; i < len; i++) {
11914
10739
  const c1 = a[i], c2 = b[i];
11915
10740
  const isValidC1 = c1 != null && c1 !== false;
@@ -11990,7 +10815,74 @@ function patchVNode(parent, oldV, newV) {
11990
10815
  }
11991
10816
  }
11992
10817
  function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
11993
- const { width, height, disableAutoSize = false, ...componentProps } = props;
10818
+ const key = props.key;
10819
+ const existingMount = mountRegistry.findByParentAndKey(parentOrScene, key);
10820
+ if (existingMount) {
10821
+ if (existingMount.type !== type) {
10822
+ const oldTypeName = typeof existingMount.type === "string" ? existingMount.type : existingMount.type.name || "Component";
10823
+ const newTypeName = typeof type === "string" ? type : type.name || "Component";
10824
+ console.warn(
10825
+ `[PhaserJSX] mountJSX type mismatch: Attempting to patch <${oldTypeName}> with <${newTypeName}>.
10826
+ This usually means you're missing a 'key' prop to distinguish multiple mounts on the same parent.
10827
+ Solution: Add unique keys like { key: 'sidebar', ... } and { key: 'main', ... }`
10828
+ );
10829
+ }
10830
+ const newWidth = props.width ?? existingMount.props.width;
10831
+ const newHeight = props.height ?? existingMount.props.height;
10832
+ const dimensionsChanged = newWidth !== existingMount.props.width || newHeight !== existingMount.props.height;
10833
+ const { disableAutoSize: _d, key: _k, ...componentProps2 } = props;
10834
+ if (dimensionsChanged) {
10835
+ existingMount.props = {
10836
+ ...existingMount.props,
10837
+ ...componentProps2,
10838
+ width: newWidth,
10839
+ height: newHeight
10840
+ };
10841
+ } else {
10842
+ existingMount.props = { ...existingMount.props, ...componentProps2 };
10843
+ }
10844
+ let newVNode;
10845
+ if (existingMount.props.disableAutoSize) {
10846
+ newVNode = {
10847
+ type: existingMount.type,
10848
+ props: {
10849
+ ...componentProps2,
10850
+ width: existingMount.props.width,
10851
+ height: existingMount.props.height
10852
+ },
10853
+ children: []
10854
+ };
10855
+ } else {
10856
+ const componentVNode = {
10857
+ type: existingMount.type,
10858
+ props: {
10859
+ ...componentProps2,
10860
+ width: existingMount.props.width,
10861
+ height: existingMount.props.height
10862
+ },
10863
+ children: []
10864
+ };
10865
+ newVNode = {
10866
+ type: SceneWrapper,
10867
+ props: {
10868
+ width: existingMount.props.width,
10869
+ height: existingMount.props.height,
10870
+ children: componentVNode
10871
+ },
10872
+ children: []
10873
+ };
10874
+ }
10875
+ patchVNode(parentOrScene, existingMount.vnode, newVNode);
10876
+ existingMount.vnode = newVNode;
10877
+ const handle2 = existingMount.rootNode;
10878
+ handle2.unmount = () => unmountJSX(handle2);
10879
+ DebugLogger.log(
10880
+ "vdom",
10881
+ `Patched existing mount ${existingMount.id} on same parent (type: ${typeof type === "string" ? type : type.name})`
10882
+ );
10883
+ return handle2;
10884
+ }
10885
+ const { width, height, disableAutoSize = false, key: _key, ...componentProps } = props;
11994
10886
  const scene = parentOrScene instanceof Phaser$1.Scene ? parentOrScene : parentOrScene.scene;
11995
10887
  if (scene) {
11996
10888
  const renderContext = getRenderContext(parentOrScene);
@@ -12003,7 +10895,11 @@ function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
12003
10895
  } else {
12004
10896
  const componentVNode = {
12005
10897
  type,
12006
- props: componentProps,
10898
+ props: {
10899
+ ...componentProps,
10900
+ width,
10901
+ height
10902
+ },
12007
10903
  children: []
12008
10904
  };
12009
10905
  vnode = {
@@ -12023,18 +10919,48 @@ function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
12023
10919
  if (rootNode instanceof Phaser$1.GameObjects.Container) {
12024
10920
  rootNode.__mountRootId = generateMountRootId();
12025
10921
  }
12026
- const registryId = mountRegistry.register(parentOrScene, type, props, rootNode);
10922
+ rootNode.__rootVNode = vnode;
10923
+ const registryId = mountRegistry.register(parentOrScene, type, props, rootNode, vnode);
12027
10924
  rootNode.__registryId = registryId;
12028
- return rootNode;
10925
+ const handle = rootNode;
10926
+ handle.unmount = () => unmountJSX(handle);
10927
+ return handle;
10928
+ }
10929
+ function unmountJSX(target) {
10930
+ const scene = target instanceof Phaser$1.Scene ? target : target.scene;
10931
+ const targetWithVNode = target;
10932
+ const sceneWithVNode = scene;
10933
+ const rootVNode = targetWithVNode.__rootVNode ?? sceneWithVNode?.__rootVNode;
10934
+ if (rootVNode) {
10935
+ unmount(rootVNode);
10936
+ if (targetWithVNode.__rootVNode === rootVNode) {
10937
+ delete targetWithVNode.__rootVNode;
10938
+ }
10939
+ if (sceneWithVNode?.__rootVNode === rootVNode) {
10940
+ delete sceneWithVNode.__rootVNode;
10941
+ }
10942
+ return;
10943
+ }
10944
+ if (targetWithVNode.__registryId !== void 0) {
10945
+ const entry = mountRegistry.getEntry(targetWithVNode.__registryId);
10946
+ if (entry?.vnode) {
10947
+ unmount(entry.vnode);
10948
+ return;
10949
+ }
10950
+ }
10951
+ DebugLogger.log("vdom", "unmountJSX called but no root VNode found on target");
12029
10952
  }
12030
10953
  const vdom = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12031
10954
  __proto__: null,
12032
10955
  createElement,
10956
+ getMountStats,
12033
10957
  mount,
12034
10958
  mountJSX,
10959
+ normalizeVNodeLike,
12035
10960
  patchVNode,
12036
10961
  remountAll,
12037
- unmount
10962
+ unmount,
10963
+ unmountJSX
12038
10964
  }, Symbol.toStringTag, { value: "Module" }));
12039
10965
  function getCurrent() {
12040
10966
  return _currentCtx;
@@ -12125,6 +11051,68 @@ function useScene() {
12125
11051
  const renderContext = getContextFromParent(ctx.parent);
12126
11052
  return renderContext.scene;
12127
11053
  }
11054
+ function useViewportSize() {
11055
+ const ctx = getCurrent();
11056
+ if (!ctx) {
11057
+ throw new Error("useViewportSize must be called within a component");
11058
+ }
11059
+ const renderContext = getContextFromParent(ctx.parent);
11060
+ return renderContext.getViewport();
11061
+ }
11062
+ function getLayoutSize(container) {
11063
+ if (!container) return void 0;
11064
+ const withLayout = container;
11065
+ return withLayout.__getLayoutSize?.();
11066
+ }
11067
+ function useLayoutSize(ref) {
11068
+ return getLayoutSize(ref.current);
11069
+ }
11070
+ function getLayoutProps(container) {
11071
+ if (!container) return void 0;
11072
+ const withLayout = container;
11073
+ return withLayout.__layoutProps;
11074
+ }
11075
+ function getBackgroundGraphics(container) {
11076
+ if (!container) return void 0;
11077
+ const withBackground = container;
11078
+ return withBackground.__background;
11079
+ }
11080
+ function useBackgroundGraphics(ref) {
11081
+ return getBackgroundGraphics(ref.current);
11082
+ }
11083
+ function getLayoutRect(container) {
11084
+ if (!container) return void 0;
11085
+ const size = getLayoutSize(container);
11086
+ if (!size) return void 0;
11087
+ return {
11088
+ x: container.x,
11089
+ y: container.y,
11090
+ width: size.width,
11091
+ height: size.height
11092
+ };
11093
+ }
11094
+ function useLayoutRect(ref) {
11095
+ return getLayoutRect(ref.current);
11096
+ }
11097
+ function getWorldLayoutRect(container) {
11098
+ if (!container) return void 0;
11099
+ const size = getLayoutSize(container);
11100
+ if (!size) return void 0;
11101
+ const matrix = container.getWorldTransformMatrix();
11102
+ const worldX = matrix.tx;
11103
+ const worldY = matrix.ty;
11104
+ const worldWidth = size.width * Math.abs(matrix.scaleX);
11105
+ const worldHeight = size.height * Math.abs(matrix.scaleY);
11106
+ return {
11107
+ x: worldX,
11108
+ y: worldY,
11109
+ width: worldWidth,
11110
+ height: worldHeight
11111
+ };
11112
+ }
11113
+ function useWorldLayoutRect(ref) {
11114
+ return getWorldLayoutRect(ref.current);
11115
+ }
12128
11116
  function useEffect(fn, deps) {
12129
11117
  const c = getCurrent();
12130
11118
  const i = c.index++;
@@ -12138,6 +11126,21 @@ function useEffect(fn, deps) {
12138
11126
  }
12139
11127
  });
12140
11128
  }
11129
+ function useLayoutEffect(fn, deps) {
11130
+ const c = getCurrent();
11131
+ const i = c.index++;
11132
+ const slot = c.slots[i] ?? (c.slots[i] = { deps: void 0, cleanup: void 0 });
11133
+ c.effects.push(() => {
11134
+ if (!depsChanged(slot.deps, deps)) return;
11135
+ if (typeof slot.cleanup === "function") slot.cleanup();
11136
+ requestAnimationFrame(() => {
11137
+ slot.cleanup = fn();
11138
+ });
11139
+ if (deps !== void 0) {
11140
+ slot.deps = deps;
11141
+ }
11142
+ });
11143
+ }
12141
11144
  function depsChanged(a, b) {
12142
11145
  if (!a || !b) return true;
12143
11146
  if (a.length !== b.length) return true;
@@ -12190,7 +11193,7 @@ function scheduleUpdate(c) {
12190
11193
  }
12191
11194
  const componentProps = c.componentVNode.props ?? {};
12192
11195
  const propsWithChildren = c.componentVNode.children?.length ? { ...componentProps, children: c.componentVNode.children } : componentProps;
12193
- const nextVNode = withHooks(c, () => c.function(propsWithChildren));
11196
+ const nextVNode = normalizeVNodeLike(withHooks(c, () => c.function(propsWithChildren)));
12194
11197
  patchVNode(c.parent, c.vnode, nextVNode);
12195
11198
  c.vnode = nextVNode;
12196
11199
  for (const run of c.effects) run();
@@ -12974,6 +11977,11 @@ function Button(props) {
12974
11977
  }
12975
11978
  );
12976
11979
  }
11980
+ function Graphics(props) {
11981
+ const localTheme = useTheme();
11982
+ const { props: themed, nestedTheme } = getThemedProps("Graphics", localTheme, props);
11983
+ return /* @__PURE__ */ jsx("graphics", { ...themed, theme: nestedTheme });
11984
+ }
12977
11985
  function RadioButton(props) {
12978
11986
  const { props: themed, nestedTheme } = getThemedProps("RadioButton", void 0, {});
12979
11987
  const size = themed.size ?? 16;
@@ -13076,24 +12084,8 @@ function Text(props) {
13076
12084
  const { props: themed, nestedTheme } = getThemedProps("Text", localTheme, props);
13077
12085
  return /* @__PURE__ */ jsx("text", { ...themed, theme: nestedTheme });
13078
12086
  }
13079
- const Sprite = "Sprite";
13080
- const Graphics = "Graphics";
13081
- const TileSprite = "TileSprite";
13082
- function registerBuiltins() {
13083
- register("view", { create: viewCreator, patch: viewPatcher });
13084
- register("text", { create: textCreator, patch: textPatcher });
13085
- register("nineslice", { create: nineSliceCreator, patch: nineSlicePatcher });
13086
- register("sprite", { create: spriteCreator, patch: spritePatcher });
13087
- register("image", { create: imageCreator, patch: imagePatcher });
13088
- register("graphics", { create: graphicsCreator, patch: graphicsPatcher });
13089
- register("tilesprite", { create: tileSpriteCreator, patch: tileSpritePatcher });
13090
- register("View", { create: viewCreator, patch: viewPatcher });
13091
- register("Text", { create: textCreator, patch: textPatcher });
13092
- register("NineSlice", { create: nineSliceCreator, patch: nineSlicePatcher });
13093
- register("Sprite", { create: spriteCreator, patch: spritePatcher });
13094
- register("Image", { create: imageCreator, patch: imagePatcher });
13095
- register("Graphics", { create: graphicsCreator, patch: graphicsPatcher });
13096
- register("TileSprite", { create: tileSpriteCreator, patch: tileSpritePatcher });
12087
+ function Particles(props) {
12088
+ return /* @__PURE__ */ jsx("particles", { ...props });
13097
12089
  }
13098
12090
  function preprocessSvgForTinting(svg) {
13099
12091
  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'");
@@ -13997,6 +12989,15 @@ function Portal(props) {
13997
12989
  const depth = props.depth ?? 1e3;
13998
12990
  const scene = useScene();
13999
12991
  const blockEvents = props.blockEvents ?? true;
12992
+ const mountedNodesRef = useRef([]);
12993
+ const previousChildrenRef = useRef([]);
12994
+ const normalizeChildren2 = (children) => {
12995
+ if (!children) return [];
12996
+ const flat = Array.isArray(children) ? children.flat(Infinity) : [children];
12997
+ return flat.filter(
12998
+ (child) => !!child && typeof child === "object" && "type" in child
12999
+ );
13000
+ };
14000
13001
  useEffect(() => {
14001
13002
  const portalContainer = portalRegistry.register(
14002
13003
  portalId,
@@ -14011,15 +13012,19 @@ function Portal(props) {
14011
13012
  portalContainer.add(blockerContainer);
14012
13013
  blockerContainer.setDepth(-1);
14013
13014
  }
14014
- const children = Array.isArray(props.children) ? props.children : [props.children];
13015
+ const children = normalizeChildren2(props.children);
13016
+ const mountedNodes = [];
14015
13017
  for (const child of children) {
14016
13018
  if (child) {
14017
13019
  const mountedNode = mount(portalContainer, child);
14018
13020
  if (mountedNode) {
14019
13021
  portalContainer.add(mountedNode);
13022
+ mountedNodes.push(mountedNode);
14020
13023
  }
14021
13024
  }
14022
13025
  }
13026
+ mountedNodesRef.current = mountedNodes;
13027
+ previousChildrenRef.current = children;
14023
13028
  const gestureManager = getGestureManager(scene);
14024
13029
  if (blockEvents && blockerContainer) {
14025
13030
  const blocker = blockerContainer;
@@ -14066,7 +13071,31 @@ function Portal(props) {
14066
13071
  }
14067
13072
  portalRegistry.unregister(portalId);
14068
13073
  };
14069
- }, [portalId, depth, scene, props.children, blockEvents]);
13074
+ }, [portalId, depth, scene, blockEvents]);
13075
+ useEffect(() => {
13076
+ const portal = portalRegistry.get(portalId);
13077
+ if (!portal) return;
13078
+ const portalContainer = portal.container;
13079
+ const newChildren = normalizeChildren2(props.children);
13080
+ const oldChildren = previousChildrenRef.current;
13081
+ const maxLen = Math.max(oldChildren.length, newChildren.length);
13082
+ for (let i = 0; i < maxLen; i++) {
13083
+ const oldChild = oldChildren[i];
13084
+ const newChild = newChildren[i];
13085
+ if (oldChild && newChild) {
13086
+ patchVNode(portalContainer, oldChild, newChild);
13087
+ } else if (!oldChild && newChild) {
13088
+ const mountedNode = mount(portalContainer, newChild);
13089
+ if (mountedNode) {
13090
+ portalContainer.add(mountedNode);
13091
+ mountedNodesRef.current.push(mountedNode);
13092
+ }
13093
+ } else if (oldChild && !newChild) {
13094
+ unmount(oldChild);
13095
+ }
13096
+ }
13097
+ previousChildrenRef.current = newChildren;
13098
+ }, [props.children, portalId]);
14070
13099
  return null;
14071
13100
  }
14072
13101
  function Modal(props) {
@@ -14153,19 +13182,7 @@ function Modal(props) {
14153
13182
  view.setVisible(false);
14154
13183
  backdrop.setVisible(false);
14155
13184
  }
14156
- }, [
14157
- backdropAnimation,
14158
- closeDurationMs,
14159
- isVisible,
14160
- openDurationMs,
14161
- props.onClosed,
14162
- props.onOpen,
14163
- props.onRequestClose,
14164
- props.show,
14165
- stopBackdropEffects,
14166
- stopViewEffects,
14167
- viewAnimation
14168
- ]);
13185
+ }, [props.show]);
14169
13186
  useEffect(() => {
14170
13187
  if (!closeOnEscape || !props.show) return;
14171
13188
  const handleKeyDown = (e) => {
@@ -15464,18 +14481,29 @@ function Divider(props) {
15464
14481
  }
15465
14482
  function calculateSliderSize(size) {
15466
14483
  const { props: themed } = getThemedProps("ScrollSlider", void 0, {});
15467
- const sizeFactor = size === "large" ? 1.25 : size === "small" ? 0.75 : size === "tiny" ? 0.5 : 1;
14484
+ const sizeFactor = size === "large" ? 1.25 : size === "small" ? 0.75 : size === "tiny" ? 0.5 : size === "micro" ? 0.25 : size === "nano" ? 0.125 : 1;
15468
14485
  const border = (themed.borderWidth ?? 1) * sizeFactor;
15469
14486
  const outer = (themed.size ?? 24) * sizeFactor;
15470
14487
  const dimension = outer - border * 2;
15471
14488
  return { border, outer, dimension };
15472
14489
  }
15473
14490
  function ScrollSlider(props) {
15474
- const { direction, scrollPosition, viewportSize, contentSize, onScroll } = props;
14491
+ const {
14492
+ direction,
14493
+ scrollPosition,
14494
+ viewportSize,
14495
+ contentSize,
14496
+ onScroll,
14497
+ momentum = true,
14498
+ onMomentumEnd
14499
+ } = props;
15475
14500
  const { props: themed } = getThemedProps("ScrollSlider", void 0, {});
15476
14501
  const sliderRef = useRef(null);
15477
14502
  const isDraggingRef = useRef(false);
15478
14503
  const trackContainerRef = useRef(null);
14504
+ const velocityRef = useRef(0);
14505
+ const lastTimeRef = useRef(0);
14506
+ const tweenRef = useRef(null);
15479
14507
  const isVertical = direction === "vertical";
15480
14508
  const { border, outer, dimension } = calculateSliderSize(props.size);
15481
14509
  const containerWithLayout = trackContainerRef.current;
@@ -15491,18 +14519,60 @@ function ScrollSlider(props) {
15491
14519
  data.stopPropagation();
15492
14520
  if (data.state === "start") {
15493
14521
  isDraggingRef.current = true;
14522
+ velocityRef.current = 0;
14523
+ lastTimeRef.current = Date.now();
14524
+ if (tweenRef.current) {
14525
+ tweenRef.current.stop();
14526
+ tweenRef.current = null;
14527
+ }
15494
14528
  return;
15495
14529
  }
15496
14530
  if (data.state === "end") {
15497
14531
  isDraggingRef.current = false;
14532
+ if (momentum && Math.abs(velocityRef.current) > 0.1) {
14533
+ startMomentum(scrollPosition);
14534
+ } else if (onMomentumEnd) {
14535
+ onMomentumEnd();
14536
+ }
15498
14537
  return;
15499
14538
  }
15500
14539
  if (!isDraggingRef.current) return;
15501
14540
  const delta = isVertical ? data.dy ?? 0 : data.dx ?? 0;
14541
+ const now = Date.now();
14542
+ const deltaTime = now - lastTimeRef.current;
14543
+ if (deltaTime > 0) {
14544
+ velocityRef.current = delta / deltaTime * 1e3;
14545
+ lastTimeRef.current = now;
14546
+ }
15502
14547
  const newThumbPos = Math.max(0, Math.min(thumbRange, thumbPosition + delta));
15503
14548
  const newScrollPos = thumbRange > 0 ? newThumbPos / thumbRange * maxScroll : 0;
15504
14549
  onScroll(newScrollPos);
15505
14550
  };
14551
+ const startMomentum = (startPos) => {
14552
+ if (!sliderRef.current?.scene) return;
14553
+ const scene = sliderRef.current.scene;
14554
+ const duration = Math.min(1e3, Math.max(200, Math.abs(velocityRef.current)));
14555
+ const targetScrollPos = Math.max(
14556
+ 0,
14557
+ Math.min(maxScroll, startPos + velocityRef.current * (duration / 1e3))
14558
+ );
14559
+ tweenRef.current = scene.tweens.add({
14560
+ targets: { pos: startPos },
14561
+ pos: targetScrollPos,
14562
+ duration,
14563
+ ease: "Quad.easeOut",
14564
+ onUpdate: (tween) => {
14565
+ const target = tween.targets[0];
14566
+ onScroll(target.pos);
14567
+ },
14568
+ onComplete: () => {
14569
+ tweenRef.current = null;
14570
+ if (onMomentumEnd) {
14571
+ onMomentumEnd();
14572
+ }
14573
+ }
14574
+ });
14575
+ };
15506
14576
  const handleBackgroundTouch = (data) => {
15507
14577
  data.stopPropagation();
15508
14578
  const localPos = isVertical ? data.localY ?? 0 : data.localX ?? 0;
@@ -15568,14 +14638,30 @@ function ScrollView(props) {
15568
14638
  showVerticalSlider = "auto",
15569
14639
  showHorizontalSlider = "auto",
15570
14640
  scroll: initialScroll,
15571
- onScrollInfoChange
14641
+ onScrollInfoChange,
14642
+ snap = false,
14643
+ snapAlignment = "start",
14644
+ snapThreshold = 20,
14645
+ momentum = true,
14646
+ onSnap,
14647
+ ...viewProps
15572
14648
  } = props;
15573
- const [scroll, setScroll] = useState(initialScroll ?? { dx: 0, dy: 0 });
14649
+ const [scroll, setScroll] = useState({
14650
+ dx: initialScroll?.dx ?? 0,
14651
+ dy: initialScroll?.dy ?? 0
14652
+ });
14653
+ const scrollRef = useRef(scroll);
14654
+ const hasMountedRef = useRef(false);
14655
+ const lastAppliedSnapIndexRef = useRef(initialScroll?.snapIndex);
15574
14656
  const contentRef = useRef(null);
15575
14657
  const viewportRef = useRef(null);
15576
14658
  const [contentHeight, setContentHeight] = useState(0);
15577
14659
  const [contentWidth, setContentWidth] = useState(0);
15578
- const { outer: sliderSize } = calculateSliderSize(props.sliderSize);
14660
+ const [velocity, setVelocity] = useState({ vx: 0, vy: 0 });
14661
+ const [lastTime, setLastTime] = useState(0);
14662
+ const tweenRef = useRef(null);
14663
+ const wheelSnapTimeoutRef = useRef(null);
14664
+ const WHEEL_SNAP_DELAY = 200;
15579
14665
  const viewportHeight = viewportRef.current?.height ?? 0;
15580
14666
  const viewportWidth = viewportRef.current?.width ?? 0;
15581
14667
  const effectiveContentHeight = Math.max(contentHeight, viewportHeight);
@@ -15585,13 +14671,100 @@ function ScrollView(props) {
15585
14671
  const needsHorizontalScroll = effectiveContentWidth > viewportWidth + epsilon;
15586
14672
  const showVerticalSliderActual = showVerticalSlider === true || needsVerticalScroll && showVerticalSlider === "auto";
15587
14673
  const showHorizontalSliderActual = showHorizontalSlider === true || needsHorizontalScroll && showHorizontalSlider === "auto";
14674
+ const { outer: sliderSize } = calculateSliderSize(props.sliderSize);
14675
+ props.onSliderSize?.({
14676
+ width: showVerticalSlider ? sliderSize : 0,
14677
+ height: showHorizontalSliderActual ? sliderSize : 0
14678
+ });
15588
14679
  const maxScrollY = Math.max(0, effectiveContentHeight - viewportHeight);
15589
14680
  const maxScrollX = Math.max(0, effectiveContentWidth - viewportWidth);
14681
+ const updateScroll = (value) => {
14682
+ setScroll((prev) => {
14683
+ const next = typeof value === "function" ? value(prev) : value;
14684
+ scrollRef.current = next;
14685
+ return next;
14686
+ });
14687
+ };
14688
+ const stopActiveTween = () => {
14689
+ if (tweenRef.current) {
14690
+ tweenRef.current.stop();
14691
+ tweenRef.current = null;
14692
+ }
14693
+ };
14694
+ const resolvedSnapThreshold = typeof snap === "object" && "positions" in snap ? snap.threshold ?? snapThreshold : snapThreshold;
14695
+ const effectiveSnapThreshold = resolvedSnapThreshold === void 0 || resolvedSnapThreshold < 0 ? Infinity : resolvedSnapThreshold;
15590
14696
  useEffect(() => {
15591
- if (initialScroll) {
15592
- setScroll(initialScroll);
14697
+ if (!initialScroll) return;
14698
+ const allowAnimate = hasMountedRef.current;
14699
+ if (snap && typeof snap === "object" && "positions" in snap) {
14700
+ const { x: xTargets, y: yTargets } = getSnapTargets();
14701
+ const hasTargets = xTargets.length > 0 || yTargets.length > 0;
14702
+ if (initialScroll.snapIndex !== void 0 && hasTargets) {
14703
+ const maxIdx = Math.max(xTargets.length, yTargets.length) - 1;
14704
+ const clampedIdx = Math.max(0, Math.min(initialScroll.snapIndex, maxIdx));
14705
+ const targetX = xTargets[clampedIdx];
14706
+ const targetY = yTargets[clampedIdx];
14707
+ const nextDx = targetX !== void 0 ? alignTargetPosition(targetX, viewportWidth, maxScrollX) : initialScroll.dx ?? scrollRef.current.dx;
14708
+ const nextDy = targetY !== void 0 ? alignTargetPosition(targetY, viewportHeight, maxScrollY) : initialScroll.dy ?? scrollRef.current.dy;
14709
+ const shouldAnimate = allowAnimate && (clampedIdx !== lastAppliedSnapIndexRef.current || Math.abs(scrollRef.current.dx - nextDx) > 0.5 || Math.abs(scrollRef.current.dy - nextDy) > 0.5);
14710
+ lastAppliedSnapIndexRef.current = clampedIdx;
14711
+ if (shouldAnimate && contentRef.current?.scene) {
14712
+ stopActiveTween();
14713
+ const scene = contentRef.current.scene;
14714
+ tweenRef.current = scene.tweens.add({
14715
+ targets: { dx: scrollRef.current.dx, dy: scrollRef.current.dy },
14716
+ dx: nextDx,
14717
+ dy: nextDy,
14718
+ duration: 220,
14719
+ ease: "Quad.easeOut",
14720
+ onUpdate: (tween) => {
14721
+ const target = tween.targets[0];
14722
+ updateScroll({ dx: target.dx, dy: target.dy });
14723
+ },
14724
+ onComplete: () => {
14725
+ tweenRef.current = null;
14726
+ if (onSnap) {
14727
+ onSnap(clampedIdx);
14728
+ }
14729
+ }
14730
+ });
14731
+ } else {
14732
+ updateScroll({ dx: nextDx, dy: nextDy });
14733
+ if (onSnap) {
14734
+ onSnap(clampedIdx);
14735
+ }
14736
+ }
14737
+ hasMountedRef.current = true;
14738
+ return;
14739
+ }
15593
14740
  }
15594
- }, [initialScroll]);
14741
+ if (initialScroll.dx !== void 0 && initialScroll.dy !== void 0) {
14742
+ const nextDx = initialScroll.dx;
14743
+ const nextDy = initialScroll.dy;
14744
+ const shouldAnimate = allowAnimate && (Math.abs(scrollRef.current.dx - nextDx) > 0.5 || Math.abs(scrollRef.current.dy - nextDy) > 0.5);
14745
+ if (shouldAnimate && contentRef.current?.scene) {
14746
+ stopActiveTween();
14747
+ const scene = contentRef.current.scene;
14748
+ tweenRef.current = scene.tweens.add({
14749
+ targets: { dx: scrollRef.current.dx, dy: scrollRef.current.dy },
14750
+ dx: nextDx,
14751
+ dy: nextDy,
14752
+ duration: 220,
14753
+ ease: "Quad.easeOut",
14754
+ onUpdate: (tween) => {
14755
+ const target = tween.targets[0];
14756
+ updateScroll({ dx: target.dx, dy: target.dy });
14757
+ },
14758
+ onComplete: () => {
14759
+ tweenRef.current = null;
14760
+ }
14761
+ });
14762
+ } else {
14763
+ updateScroll({ dx: nextDx, dy: nextDy });
14764
+ }
14765
+ }
14766
+ hasMountedRef.current = true;
14767
+ }, [initialScroll, snap, viewportWidth, viewportHeight, maxScrollX, maxScrollY]);
15595
14768
  useEffect(() => {
15596
14769
  if (onScrollInfoChange && viewportWidth > 0 && viewportHeight > 0) {
15597
14770
  onScrollInfoChange({
@@ -15644,27 +14817,194 @@ function ScrollView(props) {
15644
14817
  const maxScrollX2 = Math.max(0, contentWidth2 - viewportWidth2);
15645
14818
  const newScrollY = Math.max(0, Math.min(maxScrollY2, scroll.dy - deltaY));
15646
14819
  const newScrollX = Math.max(0, Math.min(maxScrollX2, scroll.dx - deltaX));
15647
- setScroll({ dx: newScrollX, dy: newScrollY });
14820
+ updateScroll({ dx: newScrollX, dy: newScrollY });
14821
+ };
14822
+ const startMomentum = () => {
14823
+ if (!contentRef.current?.scene) return;
14824
+ const scene = contentRef.current.scene;
14825
+ const duration = Math.min(1e3, Math.max(200, Math.abs(velocity.vx) + Math.abs(velocity.vy)));
14826
+ const currentScroll = scrollRef.current;
14827
+ const baseTargetDx = Math.max(
14828
+ 0,
14829
+ Math.min(maxScrollX, currentScroll.dx - velocity.vx * (duration / 1e3))
14830
+ );
14831
+ const baseTargetDy = Math.max(
14832
+ 0,
14833
+ Math.min(maxScrollY, currentScroll.dy - velocity.vy * (duration / 1e3))
14834
+ );
14835
+ const snappedTarget = snap ? calculateSnapDestination(baseTargetDx, baseTargetDy) : null;
14836
+ stopActiveTween();
14837
+ tweenRef.current = scene.tweens.add({
14838
+ targets: { dx: currentScroll.dx, dy: currentScroll.dy },
14839
+ dx: snappedTarget?.dx ?? baseTargetDx,
14840
+ dy: snappedTarget?.dy ?? baseTargetDy,
14841
+ duration,
14842
+ ease: "Quad.easeOut",
14843
+ onUpdate: (tween) => {
14844
+ const target = tween.targets[0];
14845
+ updateScroll({ dx: target.dx, dy: target.dy });
14846
+ },
14847
+ onComplete: () => {
14848
+ tweenRef.current = null;
14849
+ if (snappedTarget && snappedTarget.index >= 0 && onSnap) {
14850
+ onSnap(snappedTarget.index);
14851
+ }
14852
+ }
14853
+ });
14854
+ };
14855
+ const getSnapTargets = () => {
14856
+ const viewportHeightCurrent = viewportRef.current?.height ?? viewportHeight;
14857
+ const viewportWidthCurrent = viewportRef.current?.width ?? viewportWidth;
14858
+ if (typeof snap === "object" && "positions" in snap) {
14859
+ const sorted = [...snap.positions].sort((a, b) => a - b);
14860
+ const inferredSizeY = sorted.length > 1 ? Math.max(0, (sorted[1] ?? 0) - (sorted[0] ?? 0)) : viewportHeightCurrent || 0;
14861
+ const inferredSizeX = sorted.length > 1 ? Math.max(0, (sorted[1] ?? 0) - (sorted[0] ?? 0)) : viewportWidthCurrent || 0;
14862
+ const targetsX = sorted.map((position, index) => {
14863
+ const next = sorted[index + 1];
14864
+ const size = next !== void 0 ? Math.max(0, next - position) : inferredSizeX > 0 ? inferredSizeX : viewportWidthCurrent || 0;
14865
+ return { position, size };
14866
+ });
14867
+ const targetsY = sorted.map((position, index) => {
14868
+ const next = sorted[index + 1];
14869
+ const size = next !== void 0 ? Math.max(0, next - position) : inferredSizeY > 0 ? inferredSizeY : viewportHeightCurrent || 0;
14870
+ return { position, size };
14871
+ });
14872
+ return { x: targetsX, y: targetsY };
14873
+ }
14874
+ return { x: [], y: [] };
14875
+ };
14876
+ const findNearestSnap = (current, targets, viewportSize, maxScroll) => {
14877
+ if (targets.length === 0) return { position: current, index: -1 };
14878
+ let nearest = current;
14879
+ let minDistance = Infinity;
14880
+ let nearestIndex = -1;
14881
+ for (let index = 0; index < targets.length; index++) {
14882
+ const { position, size } = targets[index] ?? { position: 0, size: 0 };
14883
+ let adjustedPos = position;
14884
+ if (snapAlignment === "center") {
14885
+ adjustedPos = position + size / 2 - viewportSize / 2;
14886
+ } else if (snapAlignment === "end") {
14887
+ adjustedPos = position + size - viewportSize;
14888
+ }
14889
+ adjustedPos = Math.max(0, Math.min(maxScroll, adjustedPos));
14890
+ const distance = Math.abs(current - adjustedPos);
14891
+ if (distance < minDistance && distance <= effectiveSnapThreshold) {
14892
+ minDistance = distance;
14893
+ nearest = adjustedPos;
14894
+ nearestIndex = index;
14895
+ } else if (distance < minDistance && effectiveSnapThreshold === Infinity) {
14896
+ minDistance = distance;
14897
+ nearest = adjustedPos;
14898
+ nearestIndex = index;
14899
+ }
14900
+ }
14901
+ return { position: nearest, index: nearestIndex };
14902
+ };
14903
+ const calculateSnapDestination = (baseDx, baseDy) => {
14904
+ const { x: xTargets, y: yTargets } = getSnapTargets();
14905
+ const viewportHeightLocal = viewportRef.current?.height ?? 0;
14906
+ const viewportWidthLocal = viewportRef.current?.width ?? 0;
14907
+ const snapX = findNearestSnap(baseDx, xTargets, viewportWidthLocal, maxScrollX);
14908
+ const snapY = findNearestSnap(baseDy, yTargets, viewportHeightLocal, maxScrollY);
14909
+ const snapIndex = snapY.index >= 0 ? snapY.index : snapX.index;
14910
+ return { dx: snapX.position, dy: snapY.position, index: snapIndex };
14911
+ };
14912
+ const alignTargetPosition = (target, viewportSize, maxScroll) => {
14913
+ let adjustedPos = target.position;
14914
+ if (snapAlignment === "center") {
14915
+ adjustedPos = target.position + target.size / 2 - viewportSize / 2;
14916
+ } else if (snapAlignment === "end") {
14917
+ adjustedPos = target.position + target.size - viewportSize;
14918
+ }
14919
+ return Math.max(0, Math.min(maxScroll, adjustedPos));
14920
+ };
14921
+ const applySnap = () => {
14922
+ if (!contentRef.current?.scene || !snap) return;
14923
+ const currentScroll = scrollRef.current;
14924
+ const {
14925
+ dx: targetDx,
14926
+ dy: targetDy,
14927
+ index: snapIndex
14928
+ } = calculateSnapDestination(currentScroll.dx, currentScroll.dy);
14929
+ if (targetDx === currentScroll.dx && targetDy === currentScroll.dy) {
14930
+ if (snapIndex >= 0 && onSnap) {
14931
+ onSnap(snapIndex);
14932
+ }
14933
+ return;
14934
+ }
14935
+ const scene = contentRef.current.scene;
14936
+ stopActiveTween();
14937
+ tweenRef.current = scene.tweens.add({
14938
+ targets: { dx: currentScroll.dx, dy: currentScroll.dy },
14939
+ dx: targetDx,
14940
+ dy: targetDy,
14941
+ duration: 250,
14942
+ ease: "Quad.easeOut",
14943
+ onUpdate: (tween) => {
14944
+ const target = tween.targets[0];
14945
+ updateScroll({ dx: target.dx, dy: target.dy });
14946
+ },
14947
+ onComplete: () => {
14948
+ tweenRef.current = null;
14949
+ if (snapIndex >= 0 && onSnap) {
14950
+ onSnap(snapIndex);
14951
+ }
14952
+ }
14953
+ });
15648
14954
  };
15649
14955
  const handleVerticalScroll = (scrollPos) => {
15650
14956
  const clampedScrollPos = Math.max(0, Math.min(maxScrollY, scrollPos));
15651
- setScroll((prev) => ({ ...prev, dy: clampedScrollPos }));
14957
+ updateScroll((prev) => ({ ...prev, dy: clampedScrollPos }));
15652
14958
  };
15653
14959
  const handleHorizontalScroll = (scrollPos) => {
15654
14960
  const clampedScrollPos = Math.max(0, Math.min(maxScrollX, scrollPos));
15655
- setScroll((prev) => ({ ...prev, dx: clampedScrollPos }));
14961
+ updateScroll((prev) => ({ ...prev, dx: clampedScrollPos }));
14962
+ };
14963
+ const handleSliderMomentumEnd = () => {
14964
+ if (snap) {
14965
+ applySnap();
14966
+ }
15656
14967
  };
15657
14968
  const handleTouchMove = (data) => {
15658
- if (data.state === "end") return;
14969
+ if (data.state === "end") {
14970
+ if (momentum && (Math.abs(velocity.vx) > 0.1 || Math.abs(velocity.vy) > 0.1)) {
14971
+ startMomentum();
14972
+ } else if (snap) {
14973
+ applySnap();
14974
+ }
14975
+ return;
14976
+ }
14977
+ if (data.state === "start") {
14978
+ stopActiveTween();
14979
+ setVelocity({ vx: 0, vy: 0 });
14980
+ setLastTime(Date.now());
14981
+ data.stopPropagation();
14982
+ return;
14983
+ }
15659
14984
  data.stopPropagation();
15660
14985
  const deltaX = data.dx ?? 0;
15661
14986
  const deltaY = data.dy ?? 0;
14987
+ const now = Date.now();
14988
+ const deltaTime = now - lastTime;
14989
+ if (deltaTime > 0) {
14990
+ const newVx = deltaX / deltaTime * 1e3;
14991
+ const newVy = deltaY / deltaTime * 1e3;
14992
+ setVelocity({ vx: newVx, vy: newVy });
14993
+ setLastTime(now);
14994
+ }
15662
14995
  calc(deltaX, deltaY);
15663
14996
  };
15664
14997
  const handleWheel = (data) => {
15665
14998
  data.stopPropagation();
15666
14999
  data.preventDefault();
15000
+ stopActiveTween();
15667
15001
  calc(-data.deltaX, -data.deltaY);
15002
+ if (snap) {
15003
+ if (wheelSnapTimeoutRef.current) {
15004
+ clearTimeout(wheelSnapTimeoutRef.current);
15005
+ }
15006
+ wheelSnapTimeoutRef.current = setTimeout(() => applySnap(), WHEEL_SNAP_DELAY);
15007
+ }
15668
15008
  };
15669
15009
  const redraw = useRedraw();
15670
15010
  const [visible, setVisible] = useState(false);
@@ -15674,9 +15014,14 @@ function ScrollView(props) {
15674
15014
  return () => {
15675
15015
  clearTimeout(timer1);
15676
15016
  clearTimeout(timer2);
15017
+ if (wheelSnapTimeoutRef.current) {
15018
+ clearTimeout(wheelSnapTimeoutRef.current);
15019
+ }
15020
+ stopActiveTween();
15677
15021
  };
15678
15022
  }, [showVerticalSliderActual, showHorizontalSliderActual]);
15679
- return /* @__PURE__ */ jsx(View, { visible, children: /* @__PURE__ */ jsxs(View, { direction: "row", width: "100%", height: "100%", gap: 0, padding: 0, children: [
15023
+ const resolvedVisible = viewProps.visible === "none" ? "none" : visible ? viewProps.visible ?? true : false;
15024
+ return /* @__PURE__ */ jsx(View, { ...viewProps, visible: resolvedVisible, children: /* @__PURE__ */ jsxs(View, { direction: "row", width: "100%", height: "100%", gap: 0, padding: 0, children: [
15680
15025
  /* @__PURE__ */ jsxs(View, { flex: 1, height: "100%", direction: "column", children: [
15681
15026
  /* @__PURE__ */ jsxs(
15682
15027
  View,
@@ -15730,7 +15075,9 @@ function ScrollView(props) {
15730
15075
  scrollPosition: scroll.dx,
15731
15076
  viewportSize: viewportWidth,
15732
15077
  contentSize: contentWidth,
15733
- onScroll: handleHorizontalScroll
15078
+ onScroll: handleHorizontalScroll,
15079
+ momentum,
15080
+ onMomentumEnd: handleSliderMomentumEnd
15734
15081
  }
15735
15082
  ) })
15736
15083
  ] }),
@@ -15743,7 +15090,9 @@ function ScrollView(props) {
15743
15090
  scrollPosition: scroll.dy,
15744
15091
  viewportSize: viewportHeight,
15745
15092
  contentSize: effectiveContentHeight,
15746
- onScroll: handleVerticalScroll
15093
+ onScroll: handleVerticalScroll,
15094
+ momentum,
15095
+ onMomentumEnd: handleSliderMomentumEnd
15747
15096
  }
15748
15097
  ) }),
15749
15098
  showHorizontalSliderActual && // Placeholder corner for potential icon - matches slider dimensions
@@ -16091,6 +15440,395 @@ function useIconPreload(type, loader) {
16091
15440
  }, [type, loader]);
16092
15441
  return svg !== null;
16093
15442
  }
15443
+ function joystickThemeFactory(joystickTheme, radius) {
15444
+ function createNeonBase(radius2, color = 65280) {
15445
+ return /* @__PURE__ */ jsx(
15446
+ Graphics,
15447
+ {
15448
+ onDraw: (g) => {
15449
+ g.fillStyle(color, 0.1);
15450
+ g.fillCircle(0, 0, radius2 + 10);
15451
+ g.fillStyle(0, 0.4);
15452
+ g.fillCircle(0, 0, radius2);
15453
+ g.lineStyle(3, color, 1);
15454
+ g.strokeCircle(0, 0, radius2);
15455
+ g.lineStyle(1, color, 0.5);
15456
+ g.strokeCircle(0, 0, radius2 - 5);
15457
+ for (let i = 0; i < 4; i++) {
15458
+ const angle = i * 90 * Math.PI / 180;
15459
+ const x1 = Math.cos(angle) * (radius2 - 15);
15460
+ const y1 = Math.sin(angle) * (radius2 - 15);
15461
+ const x2 = Math.cos(angle) * (radius2 - 5);
15462
+ const y2 = Math.sin(angle) * (radius2 - 5);
15463
+ g.lineStyle(2, color, 0.7);
15464
+ g.lineBetween(x1, y1, x2, y2);
15465
+ }
15466
+ }
15467
+ }
15468
+ );
15469
+ }
15470
+ function createNeonThumb(radius2, color = 65280) {
15471
+ const r = radius2 * 0.4;
15472
+ return /* @__PURE__ */ jsx(
15473
+ Graphics,
15474
+ {
15475
+ onDraw: (g) => {
15476
+ g.fillStyle(color, 0.2);
15477
+ g.fillCircle(0, 0, r + 5);
15478
+ g.fillStyle(color, 0.8);
15479
+ g.fillCircle(0, 0, r);
15480
+ g.lineStyle(2, color, 1);
15481
+ g.strokeCircle(0, 0, r);
15482
+ g.lineStyle(2, 0, 0.8);
15483
+ g.moveTo(0, -r * 0.6);
15484
+ g.lineTo(0, r * 0.6);
15485
+ g.moveTo(-r * 0.6, 0);
15486
+ g.lineTo(r * 0.6, 0);
15487
+ g.strokePath();
15488
+ }
15489
+ }
15490
+ );
15491
+ }
15492
+ function createTargetBase(radius2, tint2 = 16711680) {
15493
+ return /* @__PURE__ */ jsx(
15494
+ Graphics,
15495
+ {
15496
+ onDraw: (g) => {
15497
+ g.fillStyle(0, 0.3);
15498
+ g.fillCircle(0, 0, radius2);
15499
+ for (let i = 0; i < 3; i++) {
15500
+ const r = radius2 - i * 20;
15501
+ g.lineStyle(2, tint2, 0.6 - i * 0.15);
15502
+ g.strokeCircle(0, 0, r);
15503
+ }
15504
+ g.lineStyle(1, tint2, 0.5);
15505
+ g.moveTo(-radius2, 0);
15506
+ g.lineTo(radius2, 0);
15507
+ g.moveTo(0, -radius2);
15508
+ g.lineTo(0, radius2);
15509
+ g.strokePath();
15510
+ g.fillStyle(tint2, 0.8);
15511
+ g.fillCircle(0, 0, 5);
15512
+ }
15513
+ }
15514
+ );
15515
+ }
15516
+ function createTargetThumb(radius2, tint2 = 16711680) {
15517
+ const r = radius2 * 0.35;
15518
+ return /* @__PURE__ */ jsx(
15519
+ Graphics,
15520
+ {
15521
+ onDraw: (g) => {
15522
+ g.fillStyle(tint2, 0.7);
15523
+ g.fillCircle(0, 0, r);
15524
+ g.fillStyle(16777215, 0.9);
15525
+ g.fillCircle(0, 0, r * 0.5);
15526
+ g.fillStyle(tint2, 1);
15527
+ g.fillCircle(0, 0, r * 0.2);
15528
+ g.lineStyle(3, tint2, 1);
15529
+ g.beginPath();
15530
+ g.moveTo(0, -r);
15531
+ g.lineTo(r * 0.3, -r * 0.6);
15532
+ g.lineTo(-r * 0.3, -r * 0.6);
15533
+ g.closePath();
15534
+ g.fillPath();
15535
+ }
15536
+ }
15537
+ );
15538
+ }
15539
+ function createGlassBase(radius2, tint2 = 16777215) {
15540
+ return /* @__PURE__ */ jsx(
15541
+ Graphics,
15542
+ {
15543
+ onDraw: (g) => {
15544
+ g.fillStyle(tint2, 0.15);
15545
+ g.fillCircle(0, 0, radius2);
15546
+ g.fillStyle(tint2, 0.3);
15547
+ g.fillCircle(-radius2 * 0.3, -radius2 * 0.3, radius2 * 0.4);
15548
+ g.lineStyle(2, tint2, 0.5);
15549
+ g.strokeCircle(0, 0, radius2);
15550
+ g.lineStyle(1, tint2, 0.3);
15551
+ g.strokeCircle(0, 0, radius2 - 3);
15552
+ }
15553
+ }
15554
+ );
15555
+ }
15556
+ function createGlassThumb(radius2, tint2 = 16777215) {
15557
+ const r = radius2 * 0.4;
15558
+ return /* @__PURE__ */ jsx(
15559
+ Graphics,
15560
+ {
15561
+ onDraw: (g) => {
15562
+ g.fillStyle(0, 0.2);
15563
+ g.fillCircle(r * 0.1, r * 0.1, r);
15564
+ g.fillStyle(tint2, 0.4);
15565
+ g.fillCircle(0, 0, r);
15566
+ g.fillStyle(tint2, 0.6);
15567
+ g.fillCircle(-r * 0.3, -r * 0.3, r * 0.4);
15568
+ g.lineStyle(2, tint2, 0.7);
15569
+ g.strokeCircle(0, 0, r);
15570
+ }
15571
+ }
15572
+ );
15573
+ }
15574
+ function createMilitaryBase(radius2, tint2 = 65280) {
15575
+ return /* @__PURE__ */ jsx(
15576
+ Graphics,
15577
+ {
15578
+ onDraw: (g) => {
15579
+ g.fillStyle(1710618, 0.8);
15580
+ g.fillCircle(0, 0, radius2);
15581
+ g.lineStyle(1, tint2, 0.3);
15582
+ const step = 20;
15583
+ for (let i = -radius2; i <= radius2; i += step) {
15584
+ g.moveTo(-radius2, i);
15585
+ g.lineTo(radius2, i);
15586
+ g.moveTo(i, -radius2);
15587
+ g.lineTo(i, radius2);
15588
+ }
15589
+ g.strokePath();
15590
+ g.lineStyle(2, tint2, 0.6);
15591
+ g.strokeCircle(0, 0, radius2);
15592
+ g.strokeCircle(0, 0, radius2 * 0.66);
15593
+ g.strokeCircle(0, 0, radius2 * 0.33);
15594
+ const corners = [
15595
+ { x: -radius2 * 0.7, y: -radius2 * 0.7 },
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
+ ];
15600
+ g.lineStyle(3, tint2, 0.8);
15601
+ corners.forEach(({ x, y }) => {
15602
+ g.moveTo(x - 10, y);
15603
+ g.lineTo(x + 10, y);
15604
+ g.moveTo(x, y - 10);
15605
+ g.lineTo(x, y + 10);
15606
+ });
15607
+ g.strokePath();
15608
+ }
15609
+ }
15610
+ );
15611
+ }
15612
+ function createMilitaryThumb(radius2, tint2 = 65280) {
15613
+ const r = radius2 * 0.3;
15614
+ return /* @__PURE__ */ jsx(
15615
+ Graphics,
15616
+ {
15617
+ onDraw: (g) => {
15618
+ g.fillStyle(tint2, 0.9);
15619
+ g.fillCircle(0, 0, r);
15620
+ g.fillStyle(0, 1);
15621
+ g.beginPath();
15622
+ g.moveTo(0, -r);
15623
+ g.lineTo(r * 0.5, r * 0.3);
15624
+ g.lineTo(-r * 0.5, r * 0.3);
15625
+ g.closePath();
15626
+ g.fillPath();
15627
+ g.lineStyle(2, 0, 0.8);
15628
+ g.strokeCircle(0, 0, r);
15629
+ }
15630
+ }
15631
+ );
15632
+ }
15633
+ function createDefaultBase(radius2, tint2 = 65280) {
15634
+ const size = { width: radius2 * 2 };
15635
+ return /* @__PURE__ */ jsx(
15636
+ Graphics,
15637
+ {
15638
+ onDraw: (g) => {
15639
+ g.fillStyle(0, 0.25);
15640
+ g.lineStyle(1, tint2);
15641
+ g.fillCircle(0, 0, size.width / 2);
15642
+ g.strokeCircle(0, 0, size.width / 2);
15643
+ }
15644
+ }
15645
+ );
15646
+ }
15647
+ function createDefaultThumb(radius2, tint2 = 65280) {
15648
+ const size = { width: radius2 * 2 };
15649
+ return /* @__PURE__ */ jsx(
15650
+ Graphics,
15651
+ {
15652
+ onDraw: (g) => {
15653
+ const r = size.width * 0.2;
15654
+ g.lineStyle(2, 0, 1);
15655
+ g.moveTo(0, -r);
15656
+ g.lineTo(0, r);
15657
+ g.moveTo(-r, 0);
15658
+ g.lineTo(r, 0);
15659
+ g.strokePath();
15660
+ g.lineStyle(2, tint2, 0.75);
15661
+ g.strokeCircle(0, 0, r * 1.1);
15662
+ }
15663
+ }
15664
+ );
15665
+ }
15666
+ const theme = joystickTheme != null ? joystickTheme.theme : "default";
15667
+ const tint = (joystickTheme != null ? joystickTheme.tint : 65280) ?? 65280;
15668
+ switch (theme) {
15669
+ case "neon":
15670
+ return {
15671
+ base: createNeonBase(radius, tint),
15672
+ thumb: createNeonThumb(radius, tint),
15673
+ rotateThumb: false
15674
+ };
15675
+ case "target":
15676
+ return {
15677
+ base: createTargetBase(radius, tint),
15678
+ thumb: createTargetThumb(radius, tint),
15679
+ rotateThumb: true
15680
+ };
15681
+ case "glass":
15682
+ return {
15683
+ base: createGlassBase(radius, tint),
15684
+ thumb: createGlassThumb(radius, tint),
15685
+ rotateThumb: false
15686
+ };
15687
+ case "military":
15688
+ return {
15689
+ base: createMilitaryBase(radius, tint),
15690
+ thumb: createMilitaryThumb(radius, tint),
15691
+ rotateThumb: true
15692
+ };
15693
+ case "default":
15694
+ default:
15695
+ return {
15696
+ base: createDefaultBase(radius, tint),
15697
+ thumb: createDefaultThumb(radius, tint),
15698
+ rotateThumb: false
15699
+ };
15700
+ }
15701
+ }
15702
+ function Joystick(props) {
15703
+ const outerRef = useRef(null);
15704
+ const [center, setCenter] = useState({ x: 0, y: 0 });
15705
+ const [size, setSize] = useState({ width: 0, height: 0 });
15706
+ const thumbRef = useRef(null);
15707
+ const forceExceededMinimumRef = useRef(false);
15708
+ const activeTweenRef = useRef(null);
15709
+ const isDraggingRef = useRef(false);
15710
+ const currentThumbPosRef = useRef({ x: 0, y: 0 });
15711
+ useEffect(() => {
15712
+ setTimeout(() => {
15713
+ const size2 = getLayoutSize(outerRef.current);
15714
+ console.log(`Joystick size: ${JSON.stringify(size2)}`);
15715
+ if (size2 != null) {
15716
+ const newCenter = { x: size2.width / 2, y: size2.height / 2 };
15717
+ setCenter(newCenter);
15718
+ setSize({ width: size2.width, height: size2.height });
15719
+ if (!isDraggingRef.current && !activeTweenRef.current) {
15720
+ currentThumbPosRef.current = newCenter;
15721
+ if (thumbRef.current != null) {
15722
+ thumbRef.current.setPosition(newCenter.x, newCenter.y);
15723
+ }
15724
+ }
15725
+ }
15726
+ }, 0);
15727
+ }, [outerRef]);
15728
+ const themeType = props.joystickTheme?.theme;
15729
+ const themeTint = props.joystickTheme?.tint;
15730
+ const sizeKey = `${size.width}x${size.height}`;
15731
+ const elements = useMemo(() => {
15732
+ if (props.base != null && props.thumb)
15733
+ return {
15734
+ base: props.base,
15735
+ thumb: props.thumb,
15736
+ rotateThumb: props.rotateThumb ?? false
15737
+ };
15738
+ if (size.width === 0 || size.height === 0)
15739
+ return {
15740
+ base: null,
15741
+ thumb: null,
15742
+ rotateThumb: false
15743
+ };
15744
+ const radius = Math.min(size.width, size.height) / 2;
15745
+ return joystickThemeFactory(props.joystickTheme, radius);
15746
+ }, [props.base, props.thumb, props.rotateThumb, themeType, themeTint, sizeKey]);
15747
+ const touchMove = (data) => {
15748
+ data.stopPropagation();
15749
+ if (thumbRef.current == null) return;
15750
+ if (data.state === "start") {
15751
+ forceExceededMinimumRef.current = false;
15752
+ isDraggingRef.current = true;
15753
+ }
15754
+ if (data.state === "end") {
15755
+ isDraggingRef.current = false;
15756
+ if (activeTweenRef.current) {
15757
+ activeTweenRef.current.stop();
15758
+ activeTweenRef.current = null;
15759
+ }
15760
+ if (thumbRef.current.scene) {
15761
+ activeTweenRef.current = thumbRef.current.scene.tweens.add({
15762
+ targets: thumbRef.current,
15763
+ x: center.x,
15764
+ y: center.y,
15765
+ angle: 0,
15766
+ duration: 150,
15767
+ ease: "Cubic.easeOut",
15768
+ onComplete: () => {
15769
+ activeTweenRef.current = null;
15770
+ currentThumbPosRef.current = { x: center.x, y: center.y };
15771
+ }
15772
+ });
15773
+ }
15774
+ props.onMove?.(false, 0, 0);
15775
+ return;
15776
+ }
15777
+ let offsetX = data.localX - data.width / 2 + center.x;
15778
+ let offsetY = data.localY - data.height / 2 + center.y;
15779
+ const radius = size.width / 2;
15780
+ const dx = offsetX - center.x;
15781
+ const dy = offsetY - center.y;
15782
+ const dist = Math.sqrt(dx * dx + dy * dy);
15783
+ const angle = Math.atan2(dy, dx) * (180 / Math.PI);
15784
+ const rawForce = Math.min(dist / radius, 1);
15785
+ const minForce = props.minForce ?? 0.2;
15786
+ const force = rawForce < minForce ? 0 : (rawForce - minForce) / (1 - minForce);
15787
+ if (force > 0) {
15788
+ forceExceededMinimumRef.current = true;
15789
+ }
15790
+ if (dist > radius) {
15791
+ const angleRad = Math.atan2(dy, dx);
15792
+ offsetX = center.x + Math.cos(angleRad) * radius;
15793
+ offsetY = center.y + Math.sin(angleRad) * radius;
15794
+ }
15795
+ if (activeTweenRef.current) {
15796
+ activeTweenRef.current.stop();
15797
+ activeTweenRef.current = null;
15798
+ }
15799
+ thumbRef.current.setPosition(offsetX, offsetY);
15800
+ currentThumbPosRef.current = { x: offsetX, y: offsetY };
15801
+ if (props.rotateThumb || elements.rotateThumb) {
15802
+ thumbRef.current.setAngle(angle + 90);
15803
+ }
15804
+ if (force > 0) {
15805
+ props.onMove?.(true, angle, force);
15806
+ } else {
15807
+ props.onMove?.(true, 0, 0);
15808
+ }
15809
+ };
15810
+ const handleTouch = () => {
15811
+ if (!forceExceededMinimumRef.current) {
15812
+ props.onTap?.();
15813
+ }
15814
+ };
15815
+ return /* @__PURE__ */ jsx(View, { ref: outerRef, width: props.width, height: props.height, children: /* @__PURE__ */ jsxs(
15816
+ RefOriginView,
15817
+ {
15818
+ width: props.width,
15819
+ height: props.height,
15820
+ originX: 0.5,
15821
+ originY: 0.5,
15822
+ onTouchMove: touchMove,
15823
+ onTouch: handleTouch,
15824
+ direction: "stack",
15825
+ children: [
15826
+ /* @__PURE__ */ jsx(View, { x: center.x, y: center.y, children: elements.base }),
15827
+ /* @__PURE__ */ jsx(View, { ref: thumbRef, x: currentThumbPosRef.current.x, y: currentThumbPosRef.current.y, children: elements.thumb })
15828
+ ]
15829
+ }
15830
+ ) });
15831
+ }
16094
15832
  function NineSlice(props) {
16095
15833
  const localTheme = useTheme();
16096
15834
  const { props: themed, nestedTheme } = getThemedProps("NineSlice", localTheme, props);
@@ -16290,7 +16028,13 @@ function Sidebar(props) {
16290
16028
  ...itemContainer
16291
16029
  } = itemStyle ?? {};
16292
16030
  const { textStyle: badgeTextStyle, ...badgeContainer } = badgeStyle ?? {};
16293
- const normalizeChildren = (child) => child ? Array.isArray(child) ? child : [child] : [];
16031
+ const normalizeChildren2 = (child) => {
16032
+ if (!child) return [];
16033
+ const flat = Array.isArray(child) ? child.flat(Infinity) : [child];
16034
+ return flat.filter(
16035
+ (node) => !!node && typeof node === "object" && "type" in node
16036
+ );
16037
+ };
16294
16038
  const renderTitle = (title) => {
16295
16039
  if (!title) return null;
16296
16040
  return typeof title === "string" ? /* @__PURE__ */ jsx(Text, { text: title, style: titleStyle }) : title;
@@ -16317,9 +16061,9 @@ function Sidebar(props) {
16317
16061
  const activeProps = item.active ? activeItemStyle ?? {} : {};
16318
16062
  const disabledProps = item.disabled && disabledAlpha !== void 0 ? { alpha: disabledAlpha } : {};
16319
16063
  const content = item.content ?? (item.label ? /* @__PURE__ */ jsx(Text, { text: item.label, style: itemTextStyle }) : null);
16320
- const iconNodes = normalizeChildren(item.icon ?? null);
16321
- const contentNodes2 = normalizeChildren(content);
16322
- const badgeNodes = normalizeChildren(renderBadge(item.badge));
16064
+ const iconNodes = normalizeChildren2(item.icon ?? null);
16065
+ const contentNodes2 = normalizeChildren2(content);
16066
+ const badgeNodes = normalizeChildren2(renderBadge(item.badge));
16323
16067
  const handleTouch = item.disabled ? void 0 : () => item.onSelect?.(item.key ?? key);
16324
16068
  return /* @__PURE__ */ jsx(
16325
16069
  View,
@@ -16364,7 +16108,7 @@ function Sidebar(props) {
16364
16108
  const hasSections = !!props.sections?.length;
16365
16109
  const primaryContent = sectionsContent ?? (!hasSections ? props.children : null) ?? null;
16366
16110
  const extraContent = hasSections ? props.children ?? null : null;
16367
- const contentNodes = [...normalizeChildren(primaryContent), ...normalizeChildren(extraContent)];
16111
+ const contentNodes = [...normalizeChildren2(primaryContent), ...normalizeChildren2(extraContent)];
16368
16112
  return /* @__PURE__ */ jsxs(
16369
16113
  View,
16370
16114
  {
@@ -16837,6 +16581,114 @@ function Slider(props) {
16837
16581
  function RangeSlider(props) {
16838
16582
  return /* @__PURE__ */ jsx(BaseSlider, { ...props, mode: "range" });
16839
16583
  }
16584
+ function Tab(_props) {
16585
+ return null;
16586
+ }
16587
+ function TabPanel(_props) {
16588
+ return null;
16589
+ }
16590
+ const normalizeChildren = (children) => {
16591
+ if (!children) return [];
16592
+ const flat = Array.isArray(children) ? children.flat(Infinity) : [children];
16593
+ return flat.filter(
16594
+ (child) => !!child && typeof child === "object" && "type" in child
16595
+ );
16596
+ };
16597
+ function Tabs(props) {
16598
+ const localTheme = useTheme();
16599
+ const { props: themed, nestedTheme } = getThemedProps("Tabs", localTheme, {});
16600
+ const [internalIndex, setInternalIndex] = useState(props.defaultIndex ?? 0);
16601
+ const rawIndex = props.activeIndex ?? internalIndex;
16602
+ const { tabs, panels } = useMemo(() => {
16603
+ const nodes = normalizeChildren(props.children);
16604
+ const collectedTabs = [];
16605
+ const collectedPanels = [];
16606
+ for (const node of nodes) {
16607
+ if (node.type === Tab) collectedTabs.push(node);
16608
+ if (node.type === TabPanel) collectedPanels.push(node);
16609
+ }
16610
+ return { tabs: collectedTabs, panels: collectedPanels };
16611
+ }, [props.children]);
16612
+ const panelCount = Math.min(tabs.length, panels.length);
16613
+ const safeIndex = panelCount > 0 ? Math.min(Math.max(rawIndex, 0), panelCount - 1) : 0;
16614
+ const handleSelect = (index) => {
16615
+ if (props.activeIndex === void 0) {
16616
+ setInternalIndex(index);
16617
+ }
16618
+ if (index !== safeIndex) {
16619
+ props.onChange?.(index);
16620
+ }
16621
+ };
16622
+ const tabListStyle = themed.tabListStyle ?? {};
16623
+ const tabStyle = themed.tabStyle ?? {};
16624
+ const tabActiveStyle = themed.tabActiveStyle ?? {};
16625
+ const tabDisabledStyle = themed.tabDisabledStyle ?? {};
16626
+ const panelStyle = themed.panelStyle ?? {};
16627
+ const {
16628
+ children: _children,
16629
+ activeIndex: _activeIndex,
16630
+ defaultIndex: _defaultIndex,
16631
+ onChange: _onChange,
16632
+ ...viewProps
16633
+ } = props;
16634
+ const activePanel = panels[safeIndex];
16635
+ const activePanelProps = activePanel?.props ?? {};
16636
+ const panelChildren = activePanel?.children ?? activePanelProps.children;
16637
+ const { children: _panelChildren, ...panelViewProps } = activePanelProps;
16638
+ const scrollableTabs = props.scrollableTabs ?? true;
16639
+ const tabListScrollProps = props.tabListScrollProps ?? {};
16640
+ const tabListContent = /* @__PURE__ */ jsx(View, { ...tabListStyle, direction: "row", width: scrollableTabs ? "auto" : "100%", children: tabs.slice(0, panelCount).map((tab, index) => {
16641
+ const tabProps = tab.props ?? {};
16642
+ const { disabled, onTouch, enableGestures, ...tabViewProps } = tabProps;
16643
+ const tabChildren = tab.children ?? tabProps.children;
16644
+ const isActive = index === safeIndex;
16645
+ const combinedTabStyle = {
16646
+ ...tabStyle,
16647
+ ...isActive ? tabActiveStyle : {},
16648
+ ...disabled ? tabDisabledStyle : {},
16649
+ ...tabViewProps
16650
+ };
16651
+ const tabKey = tab.__key ?? tabProps.key ?? index;
16652
+ return /* @__PURE__ */ jsx(
16653
+ View,
16654
+ {
16655
+ ...combinedTabStyle,
16656
+ enableGestures: !disabled && (enableGestures ?? true),
16657
+ onTouch: (data) => {
16658
+ if (disabled) return;
16659
+ handleSelect(index);
16660
+ onTouch?.(data);
16661
+ },
16662
+ children: tabChildren
16663
+ },
16664
+ tabKey
16665
+ );
16666
+ }) });
16667
+ const [tabHeight, setTabHeight] = useState(0);
16668
+ const [sliderHeight, setSliderHeight] = useState(0);
16669
+ const ref = useRef(null);
16670
+ useLayoutEffect(() => {
16671
+ const layout = useLayoutRect(ref);
16672
+ if (layout) setTabHeight(layout.height);
16673
+ }, [props, ref]);
16674
+ return /* @__PURE__ */ jsxs(View, { ...themed, ...viewProps, direction: "column", theme: nestedTheme, children: [
16675
+ scrollableTabs ? /* @__PURE__ */ jsx(
16676
+ ScrollView,
16677
+ {
16678
+ width: "100%",
16679
+ height: tabHeight + sliderHeight,
16680
+ showHorizontalSlider: "auto",
16681
+ showVerticalSlider: false,
16682
+ sliderSize: "nano",
16683
+ theme: nestedTheme,
16684
+ onSliderSize: (size) => setSliderHeight(size.height),
16685
+ ...tabListScrollProps,
16686
+ children: /* @__PURE__ */ jsx(View, { ref, children: tabListContent })
16687
+ }
16688
+ ) : tabListContent,
16689
+ activePanel ? /* @__PURE__ */ jsx(View, { ...panelStyle, ...panelViewProps, children: panelChildren }) : null
16690
+ ] });
16691
+ }
16840
16692
  function interpolateColor(color1, color2, progress) {
16841
16693
  const rgb1 = numberToRgb(color1);
16842
16694
  const rgb2 = numberToRgb(color2);
@@ -16968,7 +16820,7 @@ function Toggle(props) {
16968
16820
  ]
16969
16821
  }
16970
16822
  );
16971
- const labelElement = props.label && labelPosition !== "none" && /* @__PURE__ */ jsx(Text, { text: props.label, style: themed.labelStyle });
16823
+ const labelElement = props.label && labelPosition !== "none" ? /* @__PURE__ */ jsx(Text, { text: props.label, style: themed.labelStyle }) : null;
16972
16824
  if (!props.label || labelPosition === "none") {
16973
16825
  return /* @__PURE__ */ jsxs(View, { ref: containerRef, direction: "row", alignItems: "center", gap, theme: nestedTheme, children: [
16974
16826
  props.prefix,
@@ -17062,162 +16914,170 @@ function TransformOriginView({
17062
16914
  );
17063
16915
  }
17064
16916
  export {
17065
- DEFAULT_EFFECT as $,
16917
+ alpha as $,
17066
16918
  Accordion as A,
17067
16919
  Button as B,
17068
16920
  CharText as C,
17069
16921
  Dialog as D,
17070
- createTextStyleTokens as E,
17071
- registerBuiltins as F,
17072
- normalizeCornerRadius as G,
17073
- normalizeEdgeInsets as H,
16922
+ themeRegistry as E,
16923
+ normalizeGap as F,
16924
+ getChildSize as G,
16925
+ DebugLogger as H,
17074
16926
  Icon as I,
17075
- normalizeGap as J,
17076
- DOMInputElement as K,
17077
- KeyboardInputManager as L,
16927
+ Joystick as J,
16928
+ useTheme as K,
16929
+ getThemedProps as L,
17078
16930
  Modal as M,
17079
16931
  NineSlice as N,
17080
- mountJSX as O,
17081
- Portal as P,
17082
- viewportRegistry as Q,
16932
+ register as O,
16933
+ Particles as P,
16934
+ useEffect as Q,
17083
16935
  RadioButton as R,
17084
16936
  ScrollSlider as S,
17085
- Toggle as T,
17086
- getRenderContext as U,
17087
- DebugLogger as V,
16937
+ Tab as T,
16938
+ useScene as U,
16939
+ useRef as V,
17088
16940
  WrapText as W,
17089
- DevConfig as X,
17090
- DevPresets as Y,
17091
- svgToTexture as Z,
17092
- useGameObjectEffect as _,
16941
+ useCallback as X,
16942
+ mountJSX as Y,
16943
+ useState as Z,
16944
+ getPresetWithMode as _,
17093
16945
  AlertDialog as a,
17094
- spriteCreator as a$,
17095
- EFFECT_REGISTRY as a0,
17096
- applyEffectByName as a1,
17097
- resolveEffect as a2,
17098
- createBounceEffect as a3,
17099
- createBreatheEffect as a4,
17100
- createFadeEffect as a5,
17101
- createFlashEffect as a6,
17102
- createFlipInEffect as a7,
17103
- createFlipOutEffect as a8,
17104
- createFloatEffect as a9,
17105
- releaseAllSVGTextures as aA,
17106
- useSVGTexture as aB,
17107
- useSVGTextures as aC,
17108
- nodeRegistry as aD,
17109
- register as aE,
17110
- host as aF,
17111
- createDefaultTheme as aG,
17112
- defaultTheme as aH,
17113
- mergeThemes as aI,
17114
- createTheme as aJ,
17115
- getThemedProps as aK,
17116
- remountAll as aL,
17117
- createElement as aM,
17118
- mount as aN,
17119
- unmount as aO,
17120
- patchVNode as aP,
17121
- Sprite as aQ,
17122
- Graphics as aR,
17123
- TileSprite as aS,
17124
- Text as aT,
17125
- View as aU,
17126
- textCreator as aV,
17127
- textPatcher as aW,
17128
- viewCreator as aX,
17129
- viewPatcher as aY,
17130
- nineSliceCreator as aZ,
17131
- nineSlicePatcher as a_,
17132
- createJelloEffect as aa,
17133
- createNoneEffect as ab,
17134
- createPressEffect as ac,
17135
- createPulseEffect as ad,
17136
- createShakeEffect as ae,
17137
- createSlideInEffect as af,
17138
- createSlideOutEffect as ag,
17139
- createSpinEffect as ah,
17140
- createSwingEffect as ai,
17141
- createTadaEffect as aj,
17142
- createWiggleEffect as ak,
17143
- createWobbleEffect as al,
17144
- createZoomInEffect as am,
17145
- createZoomOutEffect as an,
17146
- getCurrent as ao,
17147
- withHooks as ap,
17148
- useForceRedraw as aq,
17149
- useMemo as ar,
17150
- useCallback as as,
17151
- useScene as at,
17152
- shallowEqual as au,
17153
- shouldComponentUpdate as av,
17154
- useRedraw as aw,
17155
- disposeCtx as ax,
17156
- releaseSVGTexture as ay,
17157
- releaseSVGTextures as az,
16946
+ nodeRegistry as a$,
16947
+ defaultRadiusTokens as a0,
16948
+ defaultSizeTokens as a1,
16949
+ defaultSpacingTokens as a2,
16950
+ createTextStyleTokens as a3,
16951
+ normalizeCornerRadius as a4,
16952
+ normalizeEdgeInsets as a5,
16953
+ DOMInputElement as a6,
16954
+ KeyboardInputManager as a7,
16955
+ getMountStats as a8,
16956
+ getRenderContext as a9,
16957
+ createWobbleEffect as aA,
16958
+ createZoomInEffect as aB,
16959
+ createZoomOutEffect as aC,
16960
+ getCurrent as aD,
16961
+ withHooks as aE,
16962
+ useForceRedraw as aF,
16963
+ useMemo as aG,
16964
+ useViewportSize as aH,
16965
+ getLayoutSize as aI,
16966
+ useLayoutSize as aJ,
16967
+ getLayoutProps as aK,
16968
+ getBackgroundGraphics as aL,
16969
+ useBackgroundGraphics as aM,
16970
+ getLayoutRect as aN,
16971
+ useLayoutRect as aO,
16972
+ getWorldLayoutRect as aP,
16973
+ useWorldLayoutRect as aQ,
16974
+ useLayoutEffect as aR,
16975
+ shallowEqual as aS,
16976
+ shouldComponentUpdate as aT,
16977
+ useRedraw as aU,
16978
+ disposeCtx as aV,
16979
+ releaseSVGTexture as aW,
16980
+ releaseSVGTextures as aX,
16981
+ releaseAllSVGTextures as aY,
16982
+ useSVGTexture as aZ,
16983
+ useSVGTextures as a_,
16984
+ DevConfig as aa,
16985
+ DevPresets as ab,
16986
+ svgToTexture as ac,
16987
+ useGameObjectEffect as ad,
16988
+ DEFAULT_EFFECT as ae,
16989
+ EFFECT_REGISTRY as af,
16990
+ applyEffectByName as ag,
16991
+ resolveEffect as ah,
16992
+ createBounceEffect as ai,
16993
+ createBreatheEffect as aj,
16994
+ createFadeEffect as ak,
16995
+ createFlashEffect as al,
16996
+ createFlipInEffect as am,
16997
+ createFlipOutEffect as an,
16998
+ createFloatEffect as ao,
16999
+ createJelloEffect as ap,
17000
+ createNoneEffect as aq,
17001
+ createPressEffect as ar,
17002
+ createPulseEffect as as,
17003
+ createShakeEffect as at,
17004
+ createSlideInEffect as au,
17005
+ createSlideOutEffect as av,
17006
+ createSpinEffect as aw,
17007
+ createSwingEffect as ax,
17008
+ createTadaEffect as ay,
17009
+ createWiggleEffect as az,
17158
17010
  CharTextInput as b,
17159
- spritePatcher as b0,
17160
- imageCreator as b1,
17161
- imagePatcher as b2,
17162
- graphicsCreator as b3,
17163
- graphicsPatcher as b4,
17164
- tileSpriteCreator as b5,
17165
- tileSpritePatcher as b6,
17166
- portalRegistry as b7,
17167
- animatedSignal as b8,
17168
- isAnimatedSignal as b9,
17169
- presets as bA,
17170
- defaultTextStyleTokens as bB,
17171
- vdom as bC,
17172
- unwrapSignal as ba,
17173
- DEFAULT_SPRING_CONFIG as bb,
17174
- SPRING_PRESETS as bc,
17175
- SpringPhysics as bd,
17176
- useSpring as be,
17177
- useSprings as bf,
17178
- HexColor as bg,
17179
- hexToNumber as bh,
17180
- numberToHex as bi,
17181
- numberToRgb as bj,
17182
- rgbToNumber as bk,
17183
- darken as bl,
17184
- darkenHex as bm,
17185
- hex as bn,
17186
- lighten as bo,
17187
- lightenHex as bp,
17188
- createTextStyle as bq,
17189
- ensureContrast as br,
17190
- getContrastRatio as bs,
17191
- applyDarkMode as bt,
17192
- applyLightMode as bu,
17193
- forestGreenPreset as bv,
17194
- generateColorScale as bw,
17195
- getPreset as bx,
17196
- midnightPreset as by,
17197
- oceanBluePreset as bz,
17011
+ host as b0,
17012
+ createDefaultTheme as b1,
17013
+ defaultTheme as b2,
17014
+ mergeThemes as b3,
17015
+ createTheme as b4,
17016
+ remountAll as b5,
17017
+ normalizeVNodeLike as b6,
17018
+ createElement as b7,
17019
+ mount as b8,
17020
+ unmount as b9,
17021
+ getContrastRatio as bA,
17022
+ applyDarkMode as bB,
17023
+ applyLightMode as bC,
17024
+ forestGreenPreset as bD,
17025
+ generateColorScale as bE,
17026
+ getPreset as bF,
17027
+ midnightPreset as bG,
17028
+ oceanBluePreset as bH,
17029
+ presets as bI,
17030
+ defaultTextStyleTokens as bJ,
17031
+ vdom as bK,
17032
+ patchVNode as ba,
17033
+ unmountJSX as bb,
17034
+ Graphics as bc,
17035
+ Text as bd,
17036
+ View as be,
17037
+ portalRegistry as bf,
17038
+ animatedSignal as bg,
17039
+ isAnimatedSignal as bh,
17040
+ unwrapSignal as bi,
17041
+ DEFAULT_SPRING_CONFIG as bj,
17042
+ SPRING_PRESETS as bk,
17043
+ SpringPhysics as bl,
17044
+ useSpring as bm,
17045
+ useSprings as bn,
17046
+ HexColor as bo,
17047
+ hexToNumber as bp,
17048
+ numberToHex as bq,
17049
+ numberToRgb as br,
17050
+ rgbToNumber as bs,
17051
+ darken as bt,
17052
+ darkenHex as bu,
17053
+ hex as bv,
17054
+ lighten as bw,
17055
+ lightenHex as bx,
17056
+ createTextStyle as by,
17057
+ ensureContrast as bz,
17198
17058
  Divider as c,
17199
17059
  Dropdown as d,
17200
17060
  createIconComponent as e,
17201
17061
  Image$1 as f,
17202
17062
  NineSliceButton as g,
17203
- RadioGroup as h,
17204
- RefOriginView as i,
17205
- calculateSliderSize as j,
17206
- ScrollView as k,
17207
- Sidebar as l,
17208
- RangeSlider as m,
17209
- Slider as n,
17210
- TransformOriginView as o,
17211
- useRef as p,
17212
- useEffect as q,
17213
- useState as r,
17214
- useTheme as s,
17215
- themeRegistry as t,
17063
+ Portal as h,
17064
+ RadioGroup as i,
17065
+ RefOriginView as j,
17066
+ calculateSliderSize as k,
17067
+ ScrollView as l,
17068
+ Sidebar as m,
17069
+ RangeSlider as n,
17070
+ Slider as o,
17071
+ TabPanel as p,
17072
+ Tabs as q,
17073
+ Toggle as r,
17074
+ TransformOriginView as s,
17075
+ equal as t,
17216
17076
  useIconPreload as u,
17217
- getPresetWithMode as v,
17218
- alpha as w,
17219
- defaultRadiusTokens as x,
17220
- defaultSizeTokens as y,
17221
- defaultSpacingTokens as z
17077
+ viewportRegistry as v,
17078
+ parseSize as w,
17079
+ resolveSize as x,
17080
+ getGestureManager as y,
17081
+ calculateLayout as z
17222
17082
  };
17223
- //# sourceMappingURL=TransformOriginView-CiFiQcku.js.map
17083
+ //# sourceMappingURL=TransformOriginView-DCvId72M.js.map