@number10/phaserjsx 0.2.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6643,10 +6643,6 @@ function resolveCalcOperand(operand, parentSize, viewportSize) {
6643
6643
  }
6644
6644
  if (operand.type === "percent") {
6645
6645
  if (parentSize === void 0) {
6646
- DebugLogger.warn(
6647
- "Size",
6648
- "Cannot resolve percentage in calc() without parent size. Using 0."
6649
- );
6650
6646
  return 0;
6651
6647
  }
6652
6648
  return parentSize * operand.value / 100;
@@ -7054,6 +7050,9 @@ class GestureManager {
7054
7050
  this.activePointerDown = null;
7055
7051
  }
7056
7052
  this.hoveredContainers.delete(container);
7053
+ for (const hitContainers of this.activeContainersForMove.values()) {
7054
+ hitContainers.delete(container);
7055
+ }
7057
7056
  }
7058
7057
  /**
7059
7058
  * Check if a container is registered
@@ -11249,9 +11248,9 @@ class MountRegistry {
11249
11248
  * @param rootNode - Root game object
11250
11249
  * @returns Registry ID for this mount
11251
11250
  */
11252
- register(parent, type, props, rootNode) {
11251
+ register(parent, type, props, rootNode, vnode) {
11253
11252
  const id = this.nextId++;
11254
- this.entries.set(id, { id, parent, type, props, rootNode });
11253
+ this.entries.set(id, { id, parent, type, props, rootNode, vnode });
11255
11254
  DebugLogger.log("vdom", `Registered mount ${id}`);
11256
11255
  return id;
11257
11256
  }
@@ -11266,6 +11265,14 @@ class MountRegistry {
11266
11265
  this.entries.delete(id);
11267
11266
  }
11268
11267
  }
11268
+ /**
11269
+ * Get a specific mount entry by registry ID
11270
+ * @param id - Registry ID
11271
+ * @returns Mount entry or undefined if not found
11272
+ */
11273
+ getEntry(id) {
11274
+ return this.entries.get(id);
11275
+ }
11269
11276
  /**
11270
11277
  * Get all active mount entries
11271
11278
  * @returns Array of mount entries
@@ -11343,7 +11350,9 @@ function remountAll() {
11343
11350
  rootNode.__mountRootId = generateMountRootId();
11344
11351
  }
11345
11352
  entry.rootNode = rootNode;
11353
+ entry.vnode = vnode;
11346
11354
  rootNode.__registryId = entry.id;
11355
+ rootNode.__rootVNode = vnode;
11347
11356
  console.log("[REMOUNT] Successfully remounted entry", entry.id);
11348
11357
  } catch (error) {
11349
11358
  console.error("[REMOUNT] Failed to remount entry", entry.id, error);
@@ -12023,9 +12032,36 @@ function mountJSX(parentOrScene, type, props = { width: 0, height: 0 }) {
12023
12032
  if (rootNode instanceof Phaser$1.GameObjects.Container) {
12024
12033
  rootNode.__mountRootId = generateMountRootId();
12025
12034
  }
12026
- const registryId = mountRegistry.register(parentOrScene, type, props, rootNode);
12035
+ rootNode.__rootVNode = vnode;
12036
+ const registryId = mountRegistry.register(parentOrScene, type, props, rootNode, vnode);
12027
12037
  rootNode.__registryId = registryId;
12028
- return rootNode;
12038
+ const handle = rootNode;
12039
+ handle.unmount = () => unmountJSX(handle);
12040
+ return handle;
12041
+ }
12042
+ function unmountJSX(target) {
12043
+ const scene = target instanceof Phaser$1.Scene ? target : target.scene;
12044
+ const targetWithVNode = target;
12045
+ const sceneWithVNode = scene;
12046
+ const rootVNode = targetWithVNode.__rootVNode ?? sceneWithVNode?.__rootVNode;
12047
+ if (rootVNode) {
12048
+ unmount(rootVNode);
12049
+ if (targetWithVNode.__rootVNode === rootVNode) {
12050
+ delete targetWithVNode.__rootVNode;
12051
+ }
12052
+ if (sceneWithVNode?.__rootVNode === rootVNode) {
12053
+ delete sceneWithVNode.__rootVNode;
12054
+ }
12055
+ return;
12056
+ }
12057
+ if (targetWithVNode.__registryId !== void 0) {
12058
+ const entry = mountRegistry.getEntry(targetWithVNode.__registryId);
12059
+ if (entry?.vnode) {
12060
+ unmount(entry.vnode);
12061
+ return;
12062
+ }
12063
+ }
12064
+ DebugLogger.log("vdom", "unmountJSX called but no root VNode found on target");
12029
12065
  }
12030
12066
  const vdom = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty({
12031
12067
  __proto__: null,
@@ -12034,7 +12070,8 @@ const vdom = /* @__PURE__ */ Object.freeze(/* @__PURE__ */ Object.defineProperty
12034
12070
  mountJSX,
12035
12071
  patchVNode,
12036
12072
  remountAll,
12037
- unmount
12073
+ unmount,
12074
+ unmountJSX
12038
12075
  }, Symbol.toStringTag, { value: "Module" }));
12039
12076
  function getCurrent() {
12040
12077
  return _currentCtx;
@@ -13997,6 +14034,8 @@ function Portal(props) {
13997
14034
  const depth = props.depth ?? 1e3;
13998
14035
  const scene = useScene();
13999
14036
  const blockEvents = props.blockEvents ?? true;
14037
+ const mountedNodesRef = useRef([]);
14038
+ const previousChildrenRef = useRef([]);
14000
14039
  useEffect(() => {
14001
14040
  const portalContainer = portalRegistry.register(
14002
14041
  portalId,
@@ -14012,14 +14051,18 @@ function Portal(props) {
14012
14051
  blockerContainer.setDepth(-1);
14013
14052
  }
14014
14053
  const children = Array.isArray(props.children) ? props.children : [props.children];
14054
+ const mountedNodes = [];
14015
14055
  for (const child of children) {
14016
14056
  if (child) {
14017
14057
  const mountedNode = mount(portalContainer, child);
14018
14058
  if (mountedNode) {
14019
14059
  portalContainer.add(mountedNode);
14060
+ mountedNodes.push(mountedNode);
14020
14061
  }
14021
14062
  }
14022
14063
  }
14064
+ mountedNodesRef.current = mountedNodes;
14065
+ previousChildrenRef.current = children;
14023
14066
  const gestureManager = getGestureManager(scene);
14024
14067
  if (blockEvents && blockerContainer) {
14025
14068
  const blocker = blockerContainer;
@@ -14066,7 +14109,31 @@ function Portal(props) {
14066
14109
  }
14067
14110
  portalRegistry.unregister(portalId);
14068
14111
  };
14069
- }, [portalId, depth, scene, props.children, blockEvents]);
14112
+ }, [portalId, depth, scene, blockEvents]);
14113
+ useEffect(() => {
14114
+ const portal = portalRegistry.get(portalId);
14115
+ if (!portal) return;
14116
+ const portalContainer = portal.container;
14117
+ const newChildren = Array.isArray(props.children) ? props.children : [props.children];
14118
+ const oldChildren = previousChildrenRef.current;
14119
+ const maxLen = Math.max(oldChildren.length, newChildren.length);
14120
+ for (let i = 0; i < maxLen; i++) {
14121
+ const oldChild = oldChildren[i];
14122
+ const newChild = newChildren[i];
14123
+ if (oldChild && newChild) {
14124
+ patchVNode(portalContainer, oldChild, newChild);
14125
+ } else if (!oldChild && newChild) {
14126
+ const mountedNode = mount(portalContainer, newChild);
14127
+ if (mountedNode) {
14128
+ portalContainer.add(mountedNode);
14129
+ mountedNodesRef.current.push(mountedNode);
14130
+ }
14131
+ } else if (oldChild && !newChild) {
14132
+ unmount(oldChild);
14133
+ }
14134
+ }
14135
+ previousChildrenRef.current = newChildren;
14136
+ }, [props.children, portalId]);
14070
14137
  return null;
14071
14138
  }
14072
14139
  function Modal(props) {
@@ -14153,19 +14220,7 @@ function Modal(props) {
14153
14220
  view.setVisible(false);
14154
14221
  backdrop.setVisible(false);
14155
14222
  }
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
- ]);
14223
+ }, [props.show]);
14169
14224
  useEffect(() => {
14170
14225
  if (!closeOnEscape || !props.show) return;
14171
14226
  const handleKeyDown = (e) => {
@@ -15471,11 +15526,22 @@ function calculateSliderSize(size) {
15471
15526
  return { border, outer, dimension };
15472
15527
  }
15473
15528
  function ScrollSlider(props) {
15474
- const { direction, scrollPosition, viewportSize, contentSize, onScroll } = props;
15529
+ const {
15530
+ direction,
15531
+ scrollPosition,
15532
+ viewportSize,
15533
+ contentSize,
15534
+ onScroll,
15535
+ momentum = true,
15536
+ onMomentumEnd
15537
+ } = props;
15475
15538
  const { props: themed } = getThemedProps("ScrollSlider", void 0, {});
15476
15539
  const sliderRef = useRef(null);
15477
15540
  const isDraggingRef = useRef(false);
15478
15541
  const trackContainerRef = useRef(null);
15542
+ const velocityRef = useRef(0);
15543
+ const lastTimeRef = useRef(0);
15544
+ const tweenRef = useRef(null);
15479
15545
  const isVertical = direction === "vertical";
15480
15546
  const { border, outer, dimension } = calculateSliderSize(props.size);
15481
15547
  const containerWithLayout = trackContainerRef.current;
@@ -15491,18 +15557,60 @@ function ScrollSlider(props) {
15491
15557
  data.stopPropagation();
15492
15558
  if (data.state === "start") {
15493
15559
  isDraggingRef.current = true;
15560
+ velocityRef.current = 0;
15561
+ lastTimeRef.current = Date.now();
15562
+ if (tweenRef.current) {
15563
+ tweenRef.current.stop();
15564
+ tweenRef.current = null;
15565
+ }
15494
15566
  return;
15495
15567
  }
15496
15568
  if (data.state === "end") {
15497
15569
  isDraggingRef.current = false;
15570
+ if (momentum && Math.abs(velocityRef.current) > 0.1) {
15571
+ startMomentum(scrollPosition);
15572
+ } else if (onMomentumEnd) {
15573
+ onMomentumEnd();
15574
+ }
15498
15575
  return;
15499
15576
  }
15500
15577
  if (!isDraggingRef.current) return;
15501
15578
  const delta = isVertical ? data.dy ?? 0 : data.dx ?? 0;
15579
+ const now = Date.now();
15580
+ const deltaTime = now - lastTimeRef.current;
15581
+ if (deltaTime > 0) {
15582
+ velocityRef.current = delta / deltaTime * 1e3;
15583
+ lastTimeRef.current = now;
15584
+ }
15502
15585
  const newThumbPos = Math.max(0, Math.min(thumbRange, thumbPosition + delta));
15503
15586
  const newScrollPos = thumbRange > 0 ? newThumbPos / thumbRange * maxScroll : 0;
15504
15587
  onScroll(newScrollPos);
15505
15588
  };
15589
+ const startMomentum = (startPos) => {
15590
+ if (!sliderRef.current?.scene) return;
15591
+ const scene = sliderRef.current.scene;
15592
+ const duration = Math.min(1e3, Math.max(200, Math.abs(velocityRef.current)));
15593
+ const targetScrollPos = Math.max(
15594
+ 0,
15595
+ Math.min(maxScroll, startPos + velocityRef.current * (duration / 1e3))
15596
+ );
15597
+ tweenRef.current = scene.tweens.add({
15598
+ targets: { pos: startPos },
15599
+ pos: targetScrollPos,
15600
+ duration,
15601
+ ease: "Quad.easeOut",
15602
+ onUpdate: (tween) => {
15603
+ const target = tween.targets[0];
15604
+ onScroll(target.pos);
15605
+ },
15606
+ onComplete: () => {
15607
+ tweenRef.current = null;
15608
+ if (onMomentumEnd) {
15609
+ onMomentumEnd();
15610
+ }
15611
+ }
15612
+ });
15613
+ };
15506
15614
  const handleBackgroundTouch = (data) => {
15507
15615
  data.stopPropagation();
15508
15616
  const localPos = isVertical ? data.localY ?? 0 : data.localX ?? 0;
@@ -15568,13 +15676,23 @@ function ScrollView(props) {
15568
15676
  showVerticalSlider = "auto",
15569
15677
  showHorizontalSlider = "auto",
15570
15678
  scroll: initialScroll,
15571
- onScrollInfoChange
15679
+ onScrollInfoChange,
15680
+ snap = false,
15681
+ snapAlignment = "start",
15682
+ snapThreshold = 20,
15683
+ momentum = true
15572
15684
  } = props;
15573
15685
  const [scroll, setScroll] = useState(initialScroll ?? { dx: 0, dy: 0 });
15686
+ const scrollRef = useRef(scroll);
15574
15687
  const contentRef = useRef(null);
15575
15688
  const viewportRef = useRef(null);
15576
15689
  const [contentHeight, setContentHeight] = useState(0);
15577
15690
  const [contentWidth, setContentWidth] = useState(0);
15691
+ const [velocity, setVelocity] = useState({ vx: 0, vy: 0 });
15692
+ const [lastTime, setLastTime] = useState(0);
15693
+ const tweenRef = useRef(null);
15694
+ const wheelSnapTimeoutRef = useRef(null);
15695
+ const WHEEL_SNAP_DELAY = 200;
15578
15696
  const { outer: sliderSize } = calculateSliderSize(props.sliderSize);
15579
15697
  const viewportHeight = viewportRef.current?.height ?? 0;
15580
15698
  const viewportWidth = viewportRef.current?.width ?? 0;
@@ -15587,9 +15705,24 @@ function ScrollView(props) {
15587
15705
  const showHorizontalSliderActual = showHorizontalSlider === true || needsHorizontalScroll && showHorizontalSlider === "auto";
15588
15706
  const maxScrollY = Math.max(0, effectiveContentHeight - viewportHeight);
15589
15707
  const maxScrollX = Math.max(0, effectiveContentWidth - viewportWidth);
15708
+ const updateScroll = (value) => {
15709
+ setScroll((prev) => {
15710
+ const next = typeof value === "function" ? value(prev) : value;
15711
+ scrollRef.current = next;
15712
+ return next;
15713
+ });
15714
+ };
15715
+ const stopActiveTween = () => {
15716
+ if (tweenRef.current) {
15717
+ tweenRef.current.stop();
15718
+ tweenRef.current = null;
15719
+ }
15720
+ };
15721
+ const resolvedSnapThreshold = typeof snap === "object" && "positions" in snap ? snap.threshold ?? snapThreshold : snapThreshold;
15722
+ const effectiveSnapThreshold = resolvedSnapThreshold === void 0 || resolvedSnapThreshold < 0 ? Infinity : resolvedSnapThreshold;
15590
15723
  useEffect(() => {
15591
15724
  if (initialScroll) {
15592
- setScroll(initialScroll);
15725
+ updateScroll(initialScroll);
15593
15726
  }
15594
15727
  }, [initialScroll]);
15595
15728
  useEffect(() => {
@@ -15644,27 +15777,168 @@ function ScrollView(props) {
15644
15777
  const maxScrollX2 = Math.max(0, contentWidth2 - viewportWidth2);
15645
15778
  const newScrollY = Math.max(0, Math.min(maxScrollY2, scroll.dy - deltaY));
15646
15779
  const newScrollX = Math.max(0, Math.min(maxScrollX2, scroll.dx - deltaX));
15647
- setScroll({ dx: newScrollX, dy: newScrollY });
15780
+ updateScroll({ dx: newScrollX, dy: newScrollY });
15781
+ };
15782
+ const startMomentum = () => {
15783
+ if (!contentRef.current?.scene) return;
15784
+ const scene = contentRef.current.scene;
15785
+ const duration = Math.min(1e3, Math.max(200, Math.abs(velocity.vx) + Math.abs(velocity.vy)));
15786
+ const currentScroll = scrollRef.current;
15787
+ const baseTargetDx = Math.max(
15788
+ 0,
15789
+ Math.min(maxScrollX, currentScroll.dx - velocity.vx * (duration / 1e3))
15790
+ );
15791
+ const baseTargetDy = Math.max(
15792
+ 0,
15793
+ Math.min(maxScrollY, currentScroll.dy - velocity.vy * (duration / 1e3))
15794
+ );
15795
+ const snappedTarget = snap ? calculateSnapDestination(baseTargetDx, baseTargetDy) : null;
15796
+ stopActiveTween();
15797
+ tweenRef.current = scene.tweens.add({
15798
+ targets: { dx: currentScroll.dx, dy: currentScroll.dy },
15799
+ dx: snappedTarget?.dx ?? baseTargetDx,
15800
+ dy: snappedTarget?.dy ?? baseTargetDy,
15801
+ duration,
15802
+ ease: "Quad.easeOut",
15803
+ onUpdate: (tween) => {
15804
+ const target = tween.targets[0];
15805
+ updateScroll({ dx: target.dx, dy: target.dy });
15806
+ },
15807
+ onComplete: () => {
15808
+ tweenRef.current = null;
15809
+ }
15810
+ });
15811
+ };
15812
+ const getSnapTargets = () => {
15813
+ const viewportHeightCurrent = viewportRef.current?.height ?? viewportHeight;
15814
+ const viewportWidthCurrent = viewportRef.current?.width ?? viewportWidth;
15815
+ if (typeof snap === "object" && "positions" in snap) {
15816
+ const sorted = [...snap.positions].sort((a, b) => a - b);
15817
+ const inferredSizeY = sorted.length > 1 ? Math.max(0, (sorted[1] ?? 0) - (sorted[0] ?? 0)) : viewportHeightCurrent || 0;
15818
+ const inferredSizeX = sorted.length > 1 ? Math.max(0, (sorted[1] ?? 0) - (sorted[0] ?? 0)) : viewportWidthCurrent || 0;
15819
+ const targetsX = sorted.map((position, index) => {
15820
+ const next = sorted[index + 1];
15821
+ const size = next !== void 0 ? Math.max(0, next - position) : inferredSizeX > 0 ? inferredSizeX : viewportWidthCurrent || 0;
15822
+ return { position, size };
15823
+ });
15824
+ const targetsY = sorted.map((position, index) => {
15825
+ const next = sorted[index + 1];
15826
+ const size = next !== void 0 ? Math.max(0, next - position) : inferredSizeY > 0 ? inferredSizeY : viewportHeightCurrent || 0;
15827
+ return { position, size };
15828
+ });
15829
+ return { x: targetsX, y: targetsY };
15830
+ }
15831
+ return { x: [], y: [] };
15832
+ };
15833
+ const findNearestSnap = (current, targets, viewportSize, maxScroll) => {
15834
+ if (targets.length === 0) return current;
15835
+ let nearest = current;
15836
+ let minDistance = Infinity;
15837
+ for (const { position, size } of targets) {
15838
+ let adjustedPos = position;
15839
+ if (snapAlignment === "center") {
15840
+ adjustedPos = position + size / 2 - viewportSize / 2;
15841
+ } else if (snapAlignment === "end") {
15842
+ adjustedPos = position + size - viewportSize;
15843
+ }
15844
+ adjustedPos = Math.max(0, Math.min(maxScroll, adjustedPos));
15845
+ const distance = Math.abs(current - adjustedPos);
15846
+ if (distance < minDistance && distance <= effectiveSnapThreshold) {
15847
+ minDistance = distance;
15848
+ nearest = adjustedPos;
15849
+ } else if (distance < minDistance && effectiveSnapThreshold === Infinity) {
15850
+ minDistance = distance;
15851
+ nearest = adjustedPos;
15852
+ }
15853
+ }
15854
+ return nearest;
15855
+ };
15856
+ const calculateSnapDestination = (baseDx, baseDy) => {
15857
+ const { x: xTargets, y: yTargets } = getSnapTargets();
15858
+ const viewportHeightLocal = viewportRef.current?.height ?? 0;
15859
+ const viewportWidthLocal = viewportRef.current?.width ?? 0;
15860
+ const targetDx = findNearestSnap(baseDx, xTargets, viewportWidthLocal, maxScrollX);
15861
+ const targetDy = findNearestSnap(baseDy, yTargets, viewportHeightLocal, maxScrollY);
15862
+ return { dx: targetDx, dy: targetDy };
15863
+ };
15864
+ const applySnap = () => {
15865
+ if (!contentRef.current?.scene || !snap) return;
15866
+ const currentScroll = scrollRef.current;
15867
+ const { dx: targetDx, dy: targetDy } = calculateSnapDestination(
15868
+ currentScroll.dx,
15869
+ currentScroll.dy
15870
+ );
15871
+ if (targetDx === currentScroll.dx && targetDy === currentScroll.dy) return;
15872
+ const scene = contentRef.current.scene;
15873
+ stopActiveTween();
15874
+ tweenRef.current = scene.tweens.add({
15875
+ targets: { dx: currentScroll.dx, dy: currentScroll.dy },
15876
+ dx: targetDx,
15877
+ dy: targetDy,
15878
+ duration: 250,
15879
+ ease: "Quad.easeOut",
15880
+ onUpdate: (tween) => {
15881
+ const target = tween.targets[0];
15882
+ updateScroll({ dx: target.dx, dy: target.dy });
15883
+ },
15884
+ onComplete: () => {
15885
+ tweenRef.current = null;
15886
+ }
15887
+ });
15648
15888
  };
15649
15889
  const handleVerticalScroll = (scrollPos) => {
15650
15890
  const clampedScrollPos = Math.max(0, Math.min(maxScrollY, scrollPos));
15651
- setScroll((prev) => ({ ...prev, dy: clampedScrollPos }));
15891
+ updateScroll((prev) => ({ ...prev, dy: clampedScrollPos }));
15652
15892
  };
15653
15893
  const handleHorizontalScroll = (scrollPos) => {
15654
15894
  const clampedScrollPos = Math.max(0, Math.min(maxScrollX, scrollPos));
15655
- setScroll((prev) => ({ ...prev, dx: clampedScrollPos }));
15895
+ updateScroll((prev) => ({ ...prev, dx: clampedScrollPos }));
15896
+ };
15897
+ const handleSliderMomentumEnd = () => {
15898
+ if (snap) {
15899
+ applySnap();
15900
+ }
15656
15901
  };
15657
15902
  const handleTouchMove = (data) => {
15658
- if (data.state === "end") return;
15903
+ if (data.state === "end") {
15904
+ if (momentum && (Math.abs(velocity.vx) > 0.1 || Math.abs(velocity.vy) > 0.1)) {
15905
+ startMomentum();
15906
+ } else if (snap) {
15907
+ applySnap();
15908
+ }
15909
+ return;
15910
+ }
15911
+ if (data.state === "start") {
15912
+ stopActiveTween();
15913
+ setVelocity({ vx: 0, vy: 0 });
15914
+ setLastTime(Date.now());
15915
+ data.stopPropagation();
15916
+ return;
15917
+ }
15659
15918
  data.stopPropagation();
15660
15919
  const deltaX = data.dx ?? 0;
15661
15920
  const deltaY = data.dy ?? 0;
15921
+ const now = Date.now();
15922
+ const deltaTime = now - lastTime;
15923
+ if (deltaTime > 0) {
15924
+ const newVx = deltaX / deltaTime * 1e3;
15925
+ const newVy = deltaY / deltaTime * 1e3;
15926
+ setVelocity({ vx: newVx, vy: newVy });
15927
+ setLastTime(now);
15928
+ }
15662
15929
  calc(deltaX, deltaY);
15663
15930
  };
15664
15931
  const handleWheel = (data) => {
15665
15932
  data.stopPropagation();
15666
15933
  data.preventDefault();
15934
+ stopActiveTween();
15667
15935
  calc(-data.deltaX, -data.deltaY);
15936
+ if (snap) {
15937
+ if (wheelSnapTimeoutRef.current) {
15938
+ clearTimeout(wheelSnapTimeoutRef.current);
15939
+ }
15940
+ wheelSnapTimeoutRef.current = setTimeout(() => applySnap(), WHEEL_SNAP_DELAY);
15941
+ }
15668
15942
  };
15669
15943
  const redraw = useRedraw();
15670
15944
  const [visible, setVisible] = useState(false);
@@ -15674,6 +15948,10 @@ function ScrollView(props) {
15674
15948
  return () => {
15675
15949
  clearTimeout(timer1);
15676
15950
  clearTimeout(timer2);
15951
+ if (wheelSnapTimeoutRef.current) {
15952
+ clearTimeout(wheelSnapTimeoutRef.current);
15953
+ }
15954
+ stopActiveTween();
15677
15955
  };
15678
15956
  }, [showVerticalSliderActual, showHorizontalSliderActual]);
15679
15957
  return /* @__PURE__ */ jsx(View, { visible, children: /* @__PURE__ */ jsxs(View, { direction: "row", width: "100%", height: "100%", gap: 0, padding: 0, children: [
@@ -15730,7 +16008,9 @@ function ScrollView(props) {
15730
16008
  scrollPosition: scroll.dx,
15731
16009
  viewportSize: viewportWidth,
15732
16010
  contentSize: contentWidth,
15733
- onScroll: handleHorizontalScroll
16011
+ onScroll: handleHorizontalScroll,
16012
+ momentum,
16013
+ onMomentumEnd: handleSliderMomentumEnd
15734
16014
  }
15735
16015
  ) })
15736
16016
  ] }),
@@ -15743,7 +16023,9 @@ function ScrollView(props) {
15743
16023
  scrollPosition: scroll.dy,
15744
16024
  viewportSize: viewportHeight,
15745
16025
  contentSize: effectiveContentHeight,
15746
- onScroll: handleVerticalScroll
16026
+ onScroll: handleVerticalScroll,
16027
+ momentum,
16028
+ onMomentumEnd: handleSliderMomentumEnd
15747
16029
  }
15748
16030
  ) }),
15749
16031
  showHorizontalSliderActual && // Placeholder corner for potential icon - matches slider dimensions
@@ -17091,7 +17373,7 @@ export {
17091
17373
  svgToTexture as Z,
17092
17374
  useGameObjectEffect as _,
17093
17375
  AlertDialog as a,
17094
- spriteCreator as a$,
17376
+ nineSlicePatcher as a$,
17095
17377
  EFFECT_REGISTRY as a0,
17096
17378
  applyEffectByName as a1,
17097
17379
  resolveEffect as a2,
@@ -17118,17 +17400,17 @@ export {
17118
17400
  mount as aN,
17119
17401
  unmount as aO,
17120
17402
  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_,
17403
+ unmountJSX as aQ,
17404
+ Sprite as aR,
17405
+ Graphics as aS,
17406
+ TileSprite as aT,
17407
+ Text as aU,
17408
+ View as aV,
17409
+ textCreator as aW,
17410
+ textPatcher as aX,
17411
+ viewCreator as aY,
17412
+ viewPatcher as aZ,
17413
+ nineSliceCreator as a_,
17132
17414
  createJelloEffect as aa,
17133
17415
  createNoneEffect as ab,
17134
17416
  createPressEffect as ac,
@@ -17156,45 +17438,46 @@ export {
17156
17438
  releaseSVGTexture as ay,
17157
17439
  releaseSVGTextures as az,
17158
17440
  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,
17441
+ spriteCreator as b0,
17442
+ spritePatcher as b1,
17443
+ imageCreator as b2,
17444
+ imagePatcher as b3,
17445
+ graphicsCreator as b4,
17446
+ graphicsPatcher as b5,
17447
+ tileSpriteCreator as b6,
17448
+ tileSpritePatcher as b7,
17449
+ portalRegistry as b8,
17450
+ animatedSignal as b9,
17451
+ oceanBluePreset as bA,
17452
+ presets as bB,
17453
+ defaultTextStyleTokens as bC,
17454
+ vdom as bD,
17455
+ isAnimatedSignal as ba,
17456
+ unwrapSignal as bb,
17457
+ DEFAULT_SPRING_CONFIG as bc,
17458
+ SPRING_PRESETS as bd,
17459
+ SpringPhysics as be,
17460
+ useSpring as bf,
17461
+ useSprings as bg,
17462
+ HexColor as bh,
17463
+ hexToNumber as bi,
17464
+ numberToHex as bj,
17465
+ numberToRgb as bk,
17466
+ rgbToNumber as bl,
17467
+ darken as bm,
17468
+ darkenHex as bn,
17469
+ hex as bo,
17470
+ lighten as bp,
17471
+ lightenHex as bq,
17472
+ createTextStyle as br,
17473
+ ensureContrast as bs,
17474
+ getContrastRatio as bt,
17475
+ applyDarkMode as bu,
17476
+ applyLightMode as bv,
17477
+ forestGreenPreset as bw,
17478
+ generateColorScale as bx,
17479
+ getPreset as by,
17480
+ midnightPreset as bz,
17198
17481
  Divider as c,
17199
17482
  Dropdown as d,
17200
17483
  createIconComponent as e,
@@ -17220,4 +17503,4 @@ export {
17220
17503
  defaultSizeTokens as y,
17221
17504
  defaultSpacingTokens as z
17222
17505
  };
17223
- //# sourceMappingURL=TransformOriginView-CiFiQcku.js.map
17506
+ //# sourceMappingURL=TransformOriginView-CzVjS16F.js.map