@momoyu-ink/kit 0.11.3 → 0.13.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.
package/AGENTS.md CHANGED
@@ -47,7 +47,8 @@ packages/kit/src/
47
47
  │ ├── useStage.ts # createStage / StageContextProvider / GameControl
48
48
  │ ├── useScenario.ts # useScenario / nextLine / setWaiting
49
49
  │ ├── useFadeInOut.ts # 淡入淡出辅助
50
- │ └── useSoundEffect.ts # 音效便捷 hook
50
+ │ ├── useSoundEffect.ts # 音效便捷 hook
51
+ │ └── useTouchInput.ts # 当前输入是否来自触摸
51
52
  ├── components/
52
53
  │ └── navigation.tsx # createStackNavigator / Navigation / useNavigation
53
54
  ├── spring/ # react-spring 集成
@@ -120,7 +121,8 @@ moyu.executePluginCommand(pluginName, payload); // 插件命令
120
121
 
121
122
  **事件类别:**
122
123
 
123
- - **冒泡事件**:`MouseEvent` / `TouchEvent` / `KeyboardEvent` / `WheelEvent`,从目标节点向上冒泡
124
+ - **冒泡事件**:`MouseEvent` / `TouchEvent` / `KeyboardEvent` / `WheelEvent`,从目标节点向上冒泡;`MouseEvent.synthetic` 为 `true` 表示事件由引擎产生(tap 的鼠标兼容手势,或每帧的 hover 刷新),而不是鼠标设备。
125
+ - **触摸的鼠标兼容事件**:触摸 tap 结束时,引擎会补发一套鼠标事件(`MouseMove` / `MouseDown` / `MouseUp` / `Click`),因此 `onClick` 与 `onPress` 在鼠标与触摸下都生效。控件不要再从 `onTouchEnd` 触发点击动作,否则同一次 tap 会触发两次;拖动类交互继续用触摸事件。
124
126
  - **节点事件**:`NodeEvent`(创建、销毁)
125
127
  - **全局事件**:通过 `addEventListener(type, handler)` 监听
126
128
 
@@ -349,6 +351,10 @@ declare namespace JSX {
349
351
  - 落在 `hooks/` 下单独文件,在 `hooks.ts` 中 re-export。
350
352
  - 优先复用 `useStage` / `useScenario` / valtio snapshot 等既有能力。
351
353
 
354
+ ### 输入方式相关的 UI
355
+
356
+ 鼠标专有的 hover 交互在触摸设备上无法触发。需要根据输入方式调整 UI 时用 `useTouchInput()`:它在触摸输入后返回 `true`,直到用户真正移动鼠标(`MouseEvent.synthetic` 为 `true` 的事件不计)。状态在模块内共享,多个组件不会重复安装监听。
357
+
352
358
  ### 修改 bindings
353
359
 
354
360
  **绝对不要**直接编辑 `bindings/` 下的文件。流程:
@@ -546,20 +546,68 @@ declare class Node {
546
546
  executeCommand(payload: Command): any;
547
547
  }
548
548
 
549
- type MouseEventKind = 'MouseEnter' | 'MouseLeave' | 'MouseDown' | 'MouseUp' | 'MouseMove' | 'Click' | 'DoubleClick' | 'ContextMenu';
549
+ type MouseEventKind = 'MouseEnter' | 'MouseLeave' | 'MouseDown' | 'MouseUp' | 'MouseMove' | 'Click' | 'AuxClick' | 'DoubleClick' | 'ContextMenu';
550
550
 
551
+ /**
552
+ * Buttons of a mouse, as `MouseEvent.button` reports them. Middle is 1, not 2: the
553
+ * middle button is DOM's auxiliary button.
554
+ */
555
+ declare const MouseButton: {
556
+ readonly Left: 0;
557
+ readonly Middle: 1;
558
+ readonly Right: 2;
559
+ readonly Back: 3;
560
+ readonly Forward: 4;
561
+ };
562
+ /**
563
+ * Bits of the `MouseEvent.buttons` mask. The auxiliary (middle) button is 4, because
564
+ * the low three bits are reserved for primary, secondary and auxiliary.
565
+ */
566
+ declare const MouseButtons: {
567
+ readonly Left: 1;
568
+ readonly Right: 2;
569
+ readonly Middle: 4;
570
+ readonly Back: 8;
571
+ readonly Forward: 16;
572
+ };
551
573
  interface MouseEvent extends BubbleEvent {
552
574
  kind: MouseEventKind;
553
575
  targetId: number;
554
576
  currentTargetId: number;
555
577
  targetLabel?: string;
556
578
  currentTargetLabel?: string;
579
+ /**
580
+ * Stage logical coordinates of the pointer, an alias of `clientX` / `clientY` that
581
+ * matches the DOM `MouseEvent.x` / `MouseEvent.y`.
582
+ */
583
+ x: number;
584
+ y: number;
557
585
  clientX: number;
558
586
  clientY: number;
559
587
  screenX: number;
560
588
  screenY: number;
561
589
  offsetX: number;
562
590
  offsetY: number;
591
+ /**
592
+ * The button this event is about: 0 left, 1 middle, 2 right, 3 back, 4 forward.
593
+ */
594
+ button: number;
595
+ /**
596
+ * Buttons held when the event fired, as a bitmask: 1 left, 2 right, 4 middle, 8 back,
597
+ * 16 forward.
598
+ */
599
+ buttons: number;
600
+ ctrlKey: boolean;
601
+ shiftKey: boolean;
602
+ altKey: boolean;
603
+ metaKey: boolean;
604
+ /**
605
+ * True when the engine produced this event rather than a mouse device: the mouse
606
+ * compatibility gesture of a touch tap, and the hover refresh a frame performs while
607
+ * the pointer stays where it is. A consumer that wants to know whether the user is
608
+ * operating a mouse should ignore synthetic events.
609
+ */
610
+ synthetic: boolean;
563
611
  }
564
612
 
565
613
  type TouchEventKind = 'TouchStart' | 'TouchMove' | 'TouchEnd' | 'TouchCancel';
@@ -638,8 +686,9 @@ type TextLayoutEvent = {
638
686
 
639
687
  type WheelEventDeltaMode = 'pixel' | 'line' | 'page';
640
688
 
641
- interface WheelEvent extends Omit<MouseEvent, 'kind'> {
689
+ interface WheelEvent extends BubbleEvent {
642
690
  kind: 'Wheel';
691
+ currentTargetLabel?: string;
643
692
  deltaX: number;
644
693
  deltaY: number;
645
694
  deltaZ: number;
@@ -665,6 +714,7 @@ type NodeProps = {
665
714
  tint?: string;
666
715
  opacity?: number;
667
716
  interactive?: boolean;
717
+ hitTestSelf?: boolean;
668
718
  cursor?: MoyuCursor;
669
719
  zIndex?: number;
670
720
  excludeFromLayout?: boolean;
@@ -796,6 +846,7 @@ type SpriteProps = {
796
846
  nineSliceMode?: NineSliceMode;
797
847
  targetWidth?: number;
798
848
  targetHeight?: number;
849
+ alphaHitTest?: boolean;
799
850
  };
800
851
 
801
852
  /**
@@ -937,6 +988,9 @@ interface MoyuListenerAttributes {
937
988
  onMouseDown?: MoyuEventHandler<MouseEvent>;
938
989
  onMouseUp?: MoyuEventHandler<MouseEvent>;
939
990
  onMouseMove?: MoyuEventHandler<MouseEvent>;
991
+ onAuxClick?: MoyuEventHandler<MouseEvent>;
992
+ onDoubleClick?: MoyuEventHandler<MouseEvent>;
993
+ onContextMenu?: MoyuEventHandler<MouseEvent>;
940
994
  onKeyDown?: MoyuEventHandler<KeyboardEvent>;
941
995
  onKeyUp?: MoyuEventHandler<KeyboardEvent>;
942
996
  onKeyPress?: MoyuEventHandler<KeyboardEvent>;
@@ -1051,4 +1105,4 @@ type _Command = AudioCommand | EditableCommand | TextCommand | GamepadCommand |
1051
1105
  type Command = MakeNullOptional<_Command>;
1052
1106
  type MaybePromise = any;
1053
1107
 
1054
- export { type ShaderSource as $, type AudioCommand as A, type BubbleEvent as B, type Command as C, type DetailedMoyuProps as D, type EditableState as E, type MoyuShaderAttributes as F, type GamepadCommand as G, type MoyuShaderSlotAttributes as H, type MoyuVideoAttributes as I, JSX as J, type KeyboardEvent as K, type LayoutEvent as L, type MoyuEvent as M, Node as N, type OverlayDialog as O, type OverlayNotificationPosition as P, type OverlayStoreFlag as Q, type PlatformInfo as R, type ShaderDirection as S, type TouchEvent as T, type PointerEventKind as U, type RetainMode as V, type WheelEvent as W, type ScenarioCommand as X, type ShaderCommand as Y, type ShaderParam as Z, type ShaderParamType as _, type MaybePromise as a, type ShaderTimeControl as a0, type SteamCommand as a1, type SystemCommand as a2, type TextCommand as a3, type TextInteractionEvent as a4, type TextLayoutEvent as a5, type TimelinePossibleClip as a6, type TouchEventKind as a7, type Tuple2 as a8, type Tuple3 as a9, type Tuple4 as aa, type VideoCommand as ab, type WheelEventDeltaMode as ac, type WindowState as ad, createBubbleEvent as ae, getPlatform as af, getStageSize as ag, mergeEvent as ah, type MoyuClipAttributes as b, type MoyuVBoxAttributes as c, type MoyuSpriteAttributes as d, type TextProps as e, type MoyuNodeAttributes as f, type MouseEvent as g, type MoyuTextAttributes as h, type EditableChangeSource as i, type SpriteProps as j, type JsonValue as k, type AudioSettings as l, type EditableCommand as m, type EditableEvent as n, type EffectParams as o, type KeyboardEventKind as p, type MakeNullOptional as q, type MouseEventKind as r, type MoyuAnimationAttributes as s, type MoyuBackdropAttributes as t, type MoyuContainerAttributes as u, type MoyuEditableAttributes as v, type MoyuEventHandler as w, type MoyuFilterAttributes as x, type MoyuHBoxAttributes as y, type MoyuListenerAttributes as z };
1108
+ export { type ShaderParam as $, type AudioCommand as A, type BubbleEvent as B, type Command as C, type DetailedMoyuProps as D, type EditableState as E, type MoyuHBoxAttributes as F, type GamepadCommand as G, type MoyuListenerAttributes as H, type MoyuShaderAttributes as I, JSX as J, type KeyboardEvent as K, type LayoutEvent as L, type MoyuEvent as M, type MoyuShaderSlotAttributes as N, type MoyuVideoAttributes as O, Node as P, type OverlayDialog as Q, type OverlayNotificationPosition as R, type ShaderDirection as S, type TouchEvent as T, type OverlayStoreFlag as U, type PlatformInfo as V, type WheelEvent as W, type PointerEventKind as X, type RetainMode as Y, type ScenarioCommand as Z, type ShaderCommand as _, type MaybePromise as a, type ShaderParamType as a0, type ShaderSource as a1, type ShaderTimeControl as a2, type SteamCommand as a3, type SystemCommand as a4, type TextCommand as a5, type TextInteractionEvent as a6, type TextLayoutEvent as a7, type TimelinePossibleClip as a8, type TouchEventKind as a9, type Tuple2 as aa, type Tuple3 as ab, type Tuple4 as ac, type VideoCommand as ad, type WheelEventDeltaMode as ae, type WindowState as af, createBubbleEvent as ag, getPlatform as ah, getStageSize as ai, mergeEvent as aj, type MoyuClipAttributes as b, type MoyuVBoxAttributes as c, type MoyuSpriteAttributes as d, type TextProps as e, type MoyuNodeAttributes as f, type MouseEvent as g, type MoyuTextAttributes as h, type EditableChangeSource as i, type SpriteProps as j, type JsonValue as k, type AudioSettings as l, type EditableCommand as m, type EditableEvent as n, type EffectParams as o, type KeyboardEventKind as p, type MakeNullOptional as q, MouseButton as r, MouseButtons as s, type MouseEventKind as t, type MoyuAnimationAttributes as u, type MoyuBackdropAttributes as v, type MoyuContainerAttributes as w, type MoyuEditableAttributes as x, type MoyuEventHandler as y, type MoyuFilterAttributes as z };
@@ -546,20 +546,68 @@ declare class Node {
546
546
  executeCommand(payload: Command): any;
547
547
  }
548
548
 
549
- type MouseEventKind = 'MouseEnter' | 'MouseLeave' | 'MouseDown' | 'MouseUp' | 'MouseMove' | 'Click' | 'DoubleClick' | 'ContextMenu';
549
+ type MouseEventKind = 'MouseEnter' | 'MouseLeave' | 'MouseDown' | 'MouseUp' | 'MouseMove' | 'Click' | 'AuxClick' | 'DoubleClick' | 'ContextMenu';
550
550
 
551
+ /**
552
+ * Buttons of a mouse, as `MouseEvent.button` reports them. Middle is 1, not 2: the
553
+ * middle button is DOM's auxiliary button.
554
+ */
555
+ declare const MouseButton: {
556
+ readonly Left: 0;
557
+ readonly Middle: 1;
558
+ readonly Right: 2;
559
+ readonly Back: 3;
560
+ readonly Forward: 4;
561
+ };
562
+ /**
563
+ * Bits of the `MouseEvent.buttons` mask. The auxiliary (middle) button is 4, because
564
+ * the low three bits are reserved for primary, secondary and auxiliary.
565
+ */
566
+ declare const MouseButtons: {
567
+ readonly Left: 1;
568
+ readonly Right: 2;
569
+ readonly Middle: 4;
570
+ readonly Back: 8;
571
+ readonly Forward: 16;
572
+ };
551
573
  interface MouseEvent extends BubbleEvent {
552
574
  kind: MouseEventKind;
553
575
  targetId: number;
554
576
  currentTargetId: number;
555
577
  targetLabel?: string;
556
578
  currentTargetLabel?: string;
579
+ /**
580
+ * Stage logical coordinates of the pointer, an alias of `clientX` / `clientY` that
581
+ * matches the DOM `MouseEvent.x` / `MouseEvent.y`.
582
+ */
583
+ x: number;
584
+ y: number;
557
585
  clientX: number;
558
586
  clientY: number;
559
587
  screenX: number;
560
588
  screenY: number;
561
589
  offsetX: number;
562
590
  offsetY: number;
591
+ /**
592
+ * The button this event is about: 0 left, 1 middle, 2 right, 3 back, 4 forward.
593
+ */
594
+ button: number;
595
+ /**
596
+ * Buttons held when the event fired, as a bitmask: 1 left, 2 right, 4 middle, 8 back,
597
+ * 16 forward.
598
+ */
599
+ buttons: number;
600
+ ctrlKey: boolean;
601
+ shiftKey: boolean;
602
+ altKey: boolean;
603
+ metaKey: boolean;
604
+ /**
605
+ * True when the engine produced this event rather than a mouse device: the mouse
606
+ * compatibility gesture of a touch tap, and the hover refresh a frame performs while
607
+ * the pointer stays where it is. A consumer that wants to know whether the user is
608
+ * operating a mouse should ignore synthetic events.
609
+ */
610
+ synthetic: boolean;
563
611
  }
564
612
 
565
613
  type TouchEventKind = 'TouchStart' | 'TouchMove' | 'TouchEnd' | 'TouchCancel';
@@ -638,8 +686,9 @@ type TextLayoutEvent = {
638
686
 
639
687
  type WheelEventDeltaMode = 'pixel' | 'line' | 'page';
640
688
 
641
- interface WheelEvent extends Omit<MouseEvent, 'kind'> {
689
+ interface WheelEvent extends BubbleEvent {
642
690
  kind: 'Wheel';
691
+ currentTargetLabel?: string;
643
692
  deltaX: number;
644
693
  deltaY: number;
645
694
  deltaZ: number;
@@ -665,6 +714,7 @@ type NodeProps = {
665
714
  tint?: string;
666
715
  opacity?: number;
667
716
  interactive?: boolean;
717
+ hitTestSelf?: boolean;
668
718
  cursor?: MoyuCursor;
669
719
  zIndex?: number;
670
720
  excludeFromLayout?: boolean;
@@ -796,6 +846,7 @@ type SpriteProps = {
796
846
  nineSliceMode?: NineSliceMode;
797
847
  targetWidth?: number;
798
848
  targetHeight?: number;
849
+ alphaHitTest?: boolean;
799
850
  };
800
851
 
801
852
  /**
@@ -937,6 +988,9 @@ interface MoyuListenerAttributes {
937
988
  onMouseDown?: MoyuEventHandler<MouseEvent>;
938
989
  onMouseUp?: MoyuEventHandler<MouseEvent>;
939
990
  onMouseMove?: MoyuEventHandler<MouseEvent>;
991
+ onAuxClick?: MoyuEventHandler<MouseEvent>;
992
+ onDoubleClick?: MoyuEventHandler<MouseEvent>;
993
+ onContextMenu?: MoyuEventHandler<MouseEvent>;
940
994
  onKeyDown?: MoyuEventHandler<KeyboardEvent>;
941
995
  onKeyUp?: MoyuEventHandler<KeyboardEvent>;
942
996
  onKeyPress?: MoyuEventHandler<KeyboardEvent>;
@@ -1051,4 +1105,4 @@ type _Command = AudioCommand | EditableCommand | TextCommand | GamepadCommand |
1051
1105
  type Command = MakeNullOptional<_Command>;
1052
1106
  type MaybePromise = any;
1053
1107
 
1054
- export { type ShaderSource as $, type AudioCommand as A, type BubbleEvent as B, type Command as C, type DetailedMoyuProps as D, type EditableState as E, type MoyuShaderAttributes as F, type GamepadCommand as G, type MoyuShaderSlotAttributes as H, type MoyuVideoAttributes as I, JSX as J, type KeyboardEvent as K, type LayoutEvent as L, type MoyuEvent as M, Node as N, type OverlayDialog as O, type OverlayNotificationPosition as P, type OverlayStoreFlag as Q, type PlatformInfo as R, type ShaderDirection as S, type TouchEvent as T, type PointerEventKind as U, type RetainMode as V, type WheelEvent as W, type ScenarioCommand as X, type ShaderCommand as Y, type ShaderParam as Z, type ShaderParamType as _, type MaybePromise as a, type ShaderTimeControl as a0, type SteamCommand as a1, type SystemCommand as a2, type TextCommand as a3, type TextInteractionEvent as a4, type TextLayoutEvent as a5, type TimelinePossibleClip as a6, type TouchEventKind as a7, type Tuple2 as a8, type Tuple3 as a9, type Tuple4 as aa, type VideoCommand as ab, type WheelEventDeltaMode as ac, type WindowState as ad, createBubbleEvent as ae, getPlatform as af, getStageSize as ag, mergeEvent as ah, type MoyuClipAttributes as b, type MoyuVBoxAttributes as c, type MoyuSpriteAttributes as d, type TextProps as e, type MoyuNodeAttributes as f, type MouseEvent as g, type MoyuTextAttributes as h, type EditableChangeSource as i, type SpriteProps as j, type JsonValue as k, type AudioSettings as l, type EditableCommand as m, type EditableEvent as n, type EffectParams as o, type KeyboardEventKind as p, type MakeNullOptional as q, type MouseEventKind as r, type MoyuAnimationAttributes as s, type MoyuBackdropAttributes as t, type MoyuContainerAttributes as u, type MoyuEditableAttributes as v, type MoyuEventHandler as w, type MoyuFilterAttributes as x, type MoyuHBoxAttributes as y, type MoyuListenerAttributes as z };
1108
+ export { type ShaderParam as $, type AudioCommand as A, type BubbleEvent as B, type Command as C, type DetailedMoyuProps as D, type EditableState as E, type MoyuHBoxAttributes as F, type GamepadCommand as G, type MoyuListenerAttributes as H, type MoyuShaderAttributes as I, JSX as J, type KeyboardEvent as K, type LayoutEvent as L, type MoyuEvent as M, type MoyuShaderSlotAttributes as N, type MoyuVideoAttributes as O, Node as P, type OverlayDialog as Q, type OverlayNotificationPosition as R, type ShaderDirection as S, type TouchEvent as T, type OverlayStoreFlag as U, type PlatformInfo as V, type WheelEvent as W, type PointerEventKind as X, type RetainMode as Y, type ScenarioCommand as Z, type ShaderCommand as _, type MaybePromise as a, type ShaderParamType as a0, type ShaderSource as a1, type ShaderTimeControl as a2, type SteamCommand as a3, type SystemCommand as a4, type TextCommand as a5, type TextInteractionEvent as a6, type TextLayoutEvent as a7, type TimelinePossibleClip as a8, type TouchEventKind as a9, type Tuple2 as aa, type Tuple3 as ab, type Tuple4 as ac, type VideoCommand as ad, type WheelEventDeltaMode as ae, type WindowState as af, createBubbleEvent as ag, getPlatform as ah, getStageSize as ai, mergeEvent as aj, type MoyuClipAttributes as b, type MoyuVBoxAttributes as c, type MoyuSpriteAttributes as d, type TextProps as e, type MoyuNodeAttributes as f, type MouseEvent as g, type MoyuTextAttributes as h, type EditableChangeSource as i, type SpriteProps as j, type JsonValue as k, type AudioSettings as l, type EditableCommand as m, type EditableEvent as n, type EffectParams as o, type KeyboardEventKind as p, type MakeNullOptional as q, MouseButton as r, MouseButtons as s, type MouseEventKind as t, type MoyuAnimationAttributes as u, type MoyuBackdropAttributes as v, type MoyuContainerAttributes as w, type MoyuEditableAttributes as x, type MoyuEventHandler as y, type MoyuFilterAttributes as z };
@@ -1,4 +1,4 @@
1
1
  export { Fragment, jsxDEV } from 'react/jsx-dev-runtime';
2
- export { J as JSX } from './jsx-dev-runtime-xC0sDJ2D.mjs';
2
+ export { J as JSX } from './jsx-dev-runtime-Dvhilv0K.mjs';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
1
  export { Fragment, jsxDEV } from 'react/jsx-dev-runtime';
2
- export { J as JSX } from './jsx-dev-runtime-xC0sDJ2D.js';
2
+ export { J as JSX } from './jsx-dev-runtime-Dvhilv0K.js';
3
3
  import 'react/jsx-runtime';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
1
  export { Fragment, jsx, jsxs } from 'react/jsx-runtime';
2
- export { J as JSX } from './jsx-dev-runtime-xC0sDJ2D.mjs';
2
+ export { J as JSX } from './jsx-dev-runtime-Dvhilv0K.mjs';
3
3
  import 'react/jsx-dev-runtime';
4
4
  import 'react';
@@ -1,4 +1,4 @@
1
1
  export { Fragment, jsx, jsxs } from 'react/jsx-runtime';
2
- export { J as JSX } from './jsx-dev-runtime-xC0sDJ2D.js';
2
+ export { J as JSX } from './jsx-dev-runtime-Dvhilv0K.js';
3
3
  import 'react/jsx-dev-runtime';
4
4
  import 'react';
package/dist/lib.cjs CHANGED
@@ -35,6 +35,8 @@ __export(lib_exports, {
35
35
  Checkbox: () => Checkbox,
36
36
  DEBUG_EMPTY_PAGE: () => DEBUG_EMPTY_PAGE,
37
37
  Input: () => Input,
38
+ MouseButton: () => MouseButton,
39
+ MouseButtons: () => MouseButtons,
38
40
  OverlayParamsContext: () => OverlayParamsContext,
39
41
  PageParamsContext: () => PageParamsContext,
40
42
  Radio: () => Radio,
@@ -102,6 +104,7 @@ __export(lib_exports, {
102
104
  useSkipCallback: () => useSkipCallback,
103
105
  useSoundEffect: () => useSoundEffect,
104
106
  useStageContext: () => useStageContext,
107
+ useTouchInput: () => useTouchInput,
105
108
  useUiData: () => useUiData,
106
109
  warpState: () => warpState
107
110
  });
@@ -174,8 +177,7 @@ function executePluginCommand(pluginName, payload) {
174
177
 
175
178
  // src/state.ts
176
179
  var STATE = {
177
- nodeMap: {},
178
- touchMoved: {}
180
+ nodeMap: {}
179
181
  };
180
182
 
181
183
  // src/node.ts
@@ -914,6 +916,11 @@ globalThis.__moyu_receive_event = (raw_event) => {
914
916
  };
915
917
  function handleBubbleEvent(name, body) {
916
918
  const event = createBubbleEvent(body, body.targetId);
919
+ if (name === "mouseevent") {
920
+ const mouseEvent = event;
921
+ mouseEvent.x = mouseEvent.clientX;
922
+ mouseEvent.y = mouseEvent.clientY;
923
+ }
917
924
  const { kind, bubbleTargetIds } = body;
918
925
  if (body.targetId !== 0) {
919
926
  const node = STATE.nodeMap[body.targetId];
@@ -939,13 +946,6 @@ function handleBubbleEvent(name, body) {
939
946
  STATE.nodeMap[event.currentTargetId]?.listeners?.[`on${kind}`]?.(event);
940
947
  }
941
948
  }
942
- if (kind === "TouchStart") {
943
- STATE.touchMoved[identifier] = false;
944
- } else if (kind === "TouchMove") {
945
- STATE.touchMoved[identifier] = true;
946
- } else if (kind === "TouchEnd" || kind === "TouchCancel") {
947
- delete STATE.touchMoved[identifier];
948
- }
949
949
  }
950
950
  }
951
951
  if (event.bubbles) {
@@ -977,6 +977,22 @@ function addEventListener(name, callback) {
977
977
  };
978
978
  }
979
979
 
980
+ // src/events/mouse.ts
981
+ var MouseButton = {
982
+ Left: 0,
983
+ Middle: 1,
984
+ Right: 2,
985
+ Back: 3,
986
+ Forward: 4
987
+ };
988
+ var MouseButtons = {
989
+ Left: 1,
990
+ Right: 2,
991
+ Middle: 4,
992
+ Back: 8,
993
+ Forward: 16
994
+ };
995
+
980
996
  // src/utils.ts
981
997
  function getStageSize() {
982
998
  const stageSize = executePluginCommand("system", {
@@ -1342,6 +1358,7 @@ function Button({
1342
1358
  anchor,
1343
1359
  pivot,
1344
1360
  interactive: disabled ? false : interactive,
1361
+ hitTestSelf: false,
1345
1362
  onMouseEnter: mergeEvent(onMouseEnter, (event) => {
1346
1363
  if (event.targetId === event.currentTargetId) {
1347
1364
  event.stopPropagation();
@@ -1354,18 +1371,12 @@ function Button({
1354
1371
  setPressed(false);
1355
1372
  }),
1356
1373
  onMouseDown: mergeEvent(onMouseDown, () => setPressed(true)),
1357
- onMouseUp: mergeEvent(onMouseUp, (event) => {
1358
- if (pressed) {
1359
- onPress?.(event);
1360
- }
1374
+ onMouseUp: mergeEvent(onMouseUp, () => {
1361
1375
  setPressed(false);
1362
1376
  setHovered(true);
1363
1377
  }),
1364
1378
  onTouchStart: mergeEvent(onTouchStart, () => setPressed(true)),
1365
- onTouchEnd: mergeEvent(onTouchEnd, (event) => {
1366
- if (pressed) {
1367
- onPress?.(event);
1368
- }
1379
+ onTouchEnd: mergeEvent(onTouchEnd, () => {
1369
1380
  setPressed(false);
1370
1381
  setHovered(true);
1371
1382
  }),
@@ -1373,7 +1384,10 @@ function Button({
1373
1384
  setHovered(false);
1374
1385
  setPressed(false);
1375
1386
  }),
1376
- onClick: (event) => event.stopPropagation(),
1387
+ onClick: (event) => {
1388
+ onPress?.(event);
1389
+ event.stopPropagation();
1390
+ },
1377
1391
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("sprite", { ...spriteProps, src: resolveControlStateValue(src, state), cursor: "pointer", children: [
1378
1392
  text !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1379
1393
  "text",
@@ -1794,6 +1808,7 @@ function Select({
1794
1808
  anchor,
1795
1809
  pivot,
1796
1810
  interactive: disabled ? false : containerProps.interactive,
1811
+ hitTestSelf: false,
1797
1812
  children: [
1798
1813
  /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1799
1814
  Button,
@@ -1909,14 +1924,18 @@ function Slider({
1909
1924
  }
1910
1925
  }, [onValueCommit]);
1911
1926
  (0, import_react9.useEffect)(() => {
1912
- const handleMouseUp = () => endDragging(true);
1927
+ const handleMouseUp = () => {
1928
+ if (dragStateRef.current?.pointerIdentifier === void 0) {
1929
+ endDragging(true);
1930
+ }
1931
+ };
1913
1932
  const handleTouchEnd = (event) => {
1914
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1933
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1915
1934
  endDragging(true);
1916
1935
  }
1917
1936
  };
1918
1937
  const handleTouchCancel2 = (event) => {
1919
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1938
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1920
1939
  endDragging(false);
1921
1940
  }
1922
1941
  };
@@ -1939,45 +1958,37 @@ function Slider({
1939
1958
  if (dragStateRef.current !== null) {
1940
1959
  return;
1941
1960
  }
1961
+ onPress?.(event);
1962
+ if (event.defaultPrevented) {
1963
+ return;
1964
+ }
1942
1965
  const thumbPosition = currentValueRef.current * distance;
1966
+ const onThumb = event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth;
1967
+ let startValue = currentValueRef.current;
1968
+ if (!onThumb && distance > 0) {
1969
+ startValue = clampValue((event.offsetX - thumb.targetWidth / 2) / distance);
1970
+ setSliderValue(startValue);
1971
+ }
1943
1972
  dragStateRef.current = {
1944
- startPosition: event.offsetX,
1945
- startValue: currentValueRef.current,
1946
- touchIdentifier: "identifier" in event ? event.identifier : void 0,
1947
- startedOnThumb: event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth,
1948
- moved: false
1973
+ // The movement is measured in stage coordinates: `offsetX` is relative to the node
1974
+ // the pointer is over, which changes when the pointer leaves the track.
1975
+ startPointerX: event.clientX,
1976
+ startValue,
1977
+ pointerIdentifier: "identifier" in event ? event.identifier : void 0
1949
1978
  };
1950
1979
  setDragging(true);
1951
1980
  };
1952
1981
  const moveDragging = (event) => {
1953
1982
  const dragState = dragStateRef.current;
1954
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier || distance === 0) {
1983
+ const eventIdentifier = "identifier" in event ? event.identifier : void 0;
1984
+ if (dragState === null || dragState.pointerIdentifier !== eventIdentifier || distance === 0) {
1955
1985
  return;
1956
1986
  }
1957
1987
  event.stopPropagation();
1958
- const delta = event.offsetX - dragState.startPosition;
1959
- if (delta !== 0) {
1960
- dragState.moved = true;
1961
- }
1962
- setSliderValue(dragState.startValue + delta / distance);
1963
- };
1964
- const handlePress = (event) => {
1965
- const dragState = dragStateRef.current;
1966
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier) {
1967
- return;
1968
- }
1969
- onPress?.(event);
1970
- if (event.defaultPrevented) {
1971
- endDragging(false);
1972
- return;
1973
- }
1974
- if (!dragState.moved && !dragState.startedOnThumb && distance > 0) {
1975
- setSliderValue((event.offsetX - thumb.targetWidth / 2) / distance);
1976
- }
1977
- endDragging(true);
1988
+ setSliderValue(dragState.startValue + (event.clientX - dragState.startPointerX) / distance);
1978
1989
  };
1979
1990
  const handleTouchCancel = (event) => {
1980
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1991
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1981
1992
  endDragging(false);
1982
1993
  }
1983
1994
  };
@@ -1995,7 +2006,6 @@ function Slider({
1995
2006
  pivot: [0, 0.5],
1996
2007
  y: (track.targetHeight ?? 0) / 2
1997
2008
  },
1998
- onPress: handlePress,
1999
2009
  onMouseEnter,
2000
2010
  onMouseLeave,
2001
2011
  onMouseDown: mergeEvent(onMouseDown, startDragging),
@@ -4097,5 +4107,58 @@ function useBeforeHandleCommandCallback(callback) {
4097
4107
  }, [stage, callback]);
4098
4108
  }
4099
4109
 
4110
+ // src/hooks/useTouchInput.ts
4111
+ var import_react14 = require("react");
4112
+ var touchInput = false;
4113
+ var subscribers = /* @__PURE__ */ new Set();
4114
+ var uninstall = null;
4115
+ function setTouchInput(value) {
4116
+ if (value === touchInput) {
4117
+ return;
4118
+ }
4119
+ touchInput = value;
4120
+ for (const notify of [...subscribers]) {
4121
+ notify(value);
4122
+ }
4123
+ }
4124
+ function install() {
4125
+ if (uninstall) {
4126
+ return;
4127
+ }
4128
+ const cleanups = [
4129
+ // A touch means the device is being used by hand.
4130
+ addEventListener("touchstart", () => setTouchInput(true)),
4131
+ // Only a mouse event the engine did not produce on its own means the user reached
4132
+ // for the mouse: a tap's mouse compatibility gesture and the hover refresh a frame
4133
+ // repeats both carry `synthetic`.
4134
+ addEventListener("mousemove", (event) => {
4135
+ if (!event.synthetic) {
4136
+ setTouchInput(false);
4137
+ }
4138
+ })
4139
+ ];
4140
+ uninstall = () => {
4141
+ for (const cleanup of cleanups) {
4142
+ cleanup();
4143
+ }
4144
+ uninstall = null;
4145
+ };
4146
+ }
4147
+ function useTouchInput() {
4148
+ const [value, setValue] = (0, import_react14.useState)(touchInput);
4149
+ (0, import_react14.useEffect)(() => {
4150
+ subscribers.add(setValue);
4151
+ setValue(touchInput);
4152
+ install();
4153
+ return () => {
4154
+ subscribers.delete(setValue);
4155
+ if (subscribers.size === 0) {
4156
+ uninstall?.();
4157
+ }
4158
+ };
4159
+ }, []);
4160
+ return value;
4161
+ }
4162
+
4100
4163
  // src/lib.ts
4101
4164
  __reExport(lib_exports, require("@react-spring/core"), module.exports);
package/dist/lib.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactElement, Component, ForwardRefExoticComponent, CSSProperties, FC, ReactNode, ComponentType } from 'react';
3
- import { S as ShaderDirection, M as MoyuEvent, C as Command, a as MaybePromise, J as JSX, L as LayoutEvent, W as WheelEvent, T as TouchEvent, b as MoyuClipAttributes, c as MoyuVBoxAttributes, d as MoyuSpriteAttributes, e as TextProps, f as MoyuNodeAttributes, g as MouseEvent, h as MoyuTextAttributes, E as EditableState, i as EditableChangeSource, j as SpriteProps, k as JsonValue } from './jsx-dev-runtime-xC0sDJ2D.mjs';
4
- export { A as AudioCommand, l as AudioSettings, B as BubbleEvent, D as DetailedMoyuProps, m as EditableCommand, n as EditableEvent, o as EffectParams, G as GamepadCommand, K as KeyboardEvent, p as KeyboardEventKind, q as MakeNullOptional, r as MouseEventKind, s as MoyuAnimationAttributes, t as MoyuBackdropAttributes, u as MoyuContainerAttributes, v as MoyuEditableAttributes, w as MoyuEventHandler, x as MoyuFilterAttributes, y as MoyuHBoxAttributes, z as MoyuListenerAttributes, F as MoyuShaderAttributes, H as MoyuShaderSlotAttributes, I as MoyuVideoAttributes, N as Node, O as OverlayDialog, P as OverlayNotificationPosition, Q as OverlayStoreFlag, R as PlatformInfo, U as PointerEventKind, V as RetainMode, X as ScenarioCommand, Y as ShaderCommand, Z as ShaderParam, _ as ShaderParamType, $ as ShaderSource, a0 as ShaderTimeControl, a1 as SteamCommand, a2 as SystemCommand, a3 as TextCommand, a4 as TextInteractionEvent, a5 as TextLayoutEvent, a6 as TimelinePossibleClip, a7 as TouchEventKind, a8 as Tuple2, a9 as Tuple3, aa as Tuple4, ab as VideoCommand, ac as WheelEventDeltaMode, ad as WindowState, ae as createBubbleEvent, af as getPlatform, ag as getStageSize, ah as mergeEvent } from './jsx-dev-runtime-xC0sDJ2D.mjs';
3
+ import { S as ShaderDirection, M as MoyuEvent, C as Command, a as MaybePromise, J as JSX, L as LayoutEvent, W as WheelEvent, T as TouchEvent, b as MoyuClipAttributes, c as MoyuVBoxAttributes, d as MoyuSpriteAttributes, e as TextProps, f as MoyuNodeAttributes, g as MouseEvent, h as MoyuTextAttributes, E as EditableState, i as EditableChangeSource, j as SpriteProps, k as JsonValue } from './jsx-dev-runtime-Dvhilv0K.mjs';
4
+ export { A as AudioCommand, l as AudioSettings, B as BubbleEvent, D as DetailedMoyuProps, m as EditableCommand, n as EditableEvent, o as EffectParams, G as GamepadCommand, K as KeyboardEvent, p as KeyboardEventKind, q as MakeNullOptional, r as MouseButton, s as MouseButtons, t as MouseEventKind, u as MoyuAnimationAttributes, v as MoyuBackdropAttributes, w as MoyuContainerAttributes, x as MoyuEditableAttributes, y as MoyuEventHandler, z as MoyuFilterAttributes, F as MoyuHBoxAttributes, H as MoyuListenerAttributes, I as MoyuShaderAttributes, N as MoyuShaderSlotAttributes, O as MoyuVideoAttributes, P as Node, Q as OverlayDialog, R as OverlayNotificationPosition, U as OverlayStoreFlag, V as PlatformInfo, X as PointerEventKind, Y as RetainMode, Z as ScenarioCommand, _ as ShaderCommand, $ as ShaderParam, a0 as ShaderParamType, a1 as ShaderSource, a2 as ShaderTimeControl, a3 as SteamCommand, a4 as SystemCommand, a5 as TextCommand, a6 as TextInteractionEvent, a7 as TextLayoutEvent, a8 as TimelinePossibleClip, a9 as TouchEventKind, aa as Tuple2, ab as Tuple3, ac as Tuple4, ad as VideoCommand, ae as WheelEventDeltaMode, af as WindowState, ag as createBubbleEvent, ah as getPlatform, ai as getStageSize, aj as mergeEvent } from './jsx-dev-runtime-Dvhilv0K.mjs';
5
5
  import { FluidValue, addFluidObserver as addFluidObserver$1, removeFluidObserver as removeFluidObserver$1 } from '@react-spring/shared';
6
6
  import { ElementType, AssignableKeys, ComponentPropsWithRef } from '@react-spring/types';
7
7
  import { Snapshot } from 'valtio';
@@ -617,7 +617,12 @@ interface ButtonProps extends Omit<MoyuNodeAttributes, 'onClick'> {
617
617
  sprite: ControlSpriteProps;
618
618
  disabled?: boolean;
619
619
  lockOn?: Exclude<ControlState, 'disabled'>;
620
- onPress?: (event: PressEvent) => void;
620
+ /**
621
+ * Called when the button is activated, which is the engine's click gesture. The press
622
+ * visual comes from the pointer press instead, so a gesture that ends away from the
623
+ * button shows as pressed but does not activate it.
624
+ */
625
+ onPress?: (event: MouseEvent) => void;
621
626
  text?: string;
622
627
  textStyle?: ControlStateValue<ControlTextStyle>;
623
628
  textOffsetX?: number;
@@ -737,6 +742,7 @@ interface SliderProps extends Omit<MoyuNodeAttributes, 'onClick'> {
737
742
  defaultValue?: number;
738
743
  onValueChange?: (value: number) => void;
739
744
  onValueCommit?: (value: number) => void;
745
+ /** Called when the pointer presses the slider, before the drag starts. */
740
746
  onPress?: (event: PressEvent) => void;
741
747
  disabled?: boolean;
742
748
  track: SliderTrackProps;
@@ -1050,6 +1056,8 @@ declare function useScenario(stories: string[], startName?: string, entryName?:
1050
1056
  */
1051
1057
  declare function useSoundEffect(src?: string): () => void;
1052
1058
 
1059
+ declare function useTouchInput(): boolean;
1060
+
1053
1061
  type UiDocument = Record<string, unknown>;
1054
1062
  type UiSchema<TUiDocument extends UiDocument> = ZodType<TUiDocument>;
1055
1063
  interface RootUiDataMap {
@@ -1086,4 +1094,4 @@ declare module 'zod' {
1086
1094
  }
1087
1095
  }
1088
1096
 
1089
- export { type AnimatedComponent, type AnimatedProps, type AnimationFrameCallbackEvent, type AppStateAdapter, type AutoTicketHandle, type AutoTicketOptions, type BeforeUnloadEvent, Button, type ButtonProps, Checkbox, type CheckboxProps, type CombinedCheckpoint, Command, type CommandHandler, type ControlSpriteProps, type ControlState, type ControlStateValue, type ControlTextStyle, type CustomEvent, DEBUG_EMPTY_PAGE, type DebugSessionConfig, type DebugSessionController, type DebugWarpBoundary, type DebugWarpOptions, type DefaultOverlayName, type DefaultPageName, type DlcProgress, EditableChangeSource, EditableState, type FastForwardOptions, type FocusEvent, type FocusEventKind, type FullScreenEvent, type FullscreenEventKind, type GameControl, type GameEvent, type GameStateSourceProps, type GameStateStore, type Gamepad, type GamepadButton, type GamepadEvent, type GamepadHapticActuator, Input, type InputBackground, type InputBackgroundStates, type InputBackgroundStyle, type InputCaretStyle, type InputHandle, type InputProps, JSX, type KeyboardLocation, LayoutEvent, type Literal, MaybePromise, MouseEvent, MoyuClipAttributes, MoyuEvent, MoyuNodeAttributes, MoyuSpriteAttributes, MoyuTextAttributes, MoyuVBoxAttributes, type NavigationState, type Navigator, type NodeEvent, type OverlayConfig, type OverlayDescriptor, type OverlayInfo, OverlayParamsContext, type PageConfig, type PageDescriptor, PageParamsContext, type PressEvent, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type RegisterNavigator, type ResizeEvent, type ResolvedArgument, type ResolvedCommandLine, type ResolvedSystemCallLine, type RootErrorInfo, type RootHandle, type RootNavigatorList, type RootOptions, type RootUiDataMap, type RootUncaughtErrorInfo, type ScenarioCommandBaseType, type ScenarioEvent, ScrollView, type ScrollViewController, type ScrollViewProps, Select, type SelectListProps, type SelectOption, type SelectOptionSpriteProps, type SelectProps, type ShaderBuiltin, type ShaderBuiltinName, type ShaderEvent, Slider, type SliderProps, type SliderThumbProps, type SliderTrackProps, type StackNavigatorOptions, StageContextProvider, type StageInstance, type TextLine, type TextLineHandler, TouchEvent, type UseScrollViewOptions, WheelEvent, type WithAnimated, animated as a, addEventListener, addFluidObserver, animated, autoState, createGameStateContext, createRoot, createStackNavigator, createStage, createStaticNavigation, ensureArchiveVariableDefaults, executeNodeCommand, executePluginCommand, fastForwardState, getAppStateAdapter, getNavigator, getSeekingType, getUiData, globalEventListeners, globalRequestAnimationFrameListeners, initGlobalVariableDefaults, initUiData, loadVariablesDocument, moyu, nextLine, registerAppStateAdapter, removeFluidObserver, replaceUiData, setDefaultAutoTailMs, setWaiting, skipState, startDebugSession, startRuntimeDebugSession, stopDebugSession, stopRuntimeDebugSession, useAutoBlocker, useAutoTicket, useBeforeHandleCommandCallback, useDebugSession, useFadeIn, useFadeInOut, useFadeOut, useInterruptCallback, useIsAutoing, useIsSeeking, useIsSkipping, useNavigation, useNavigationParams, useNavigationState, useScenario, useScrollView, useSkipBlocker, useSkipCallback, useSoundEffect, useStageContext, useUiData, warpState };
1097
+ export { type AnimatedComponent, type AnimatedProps, type AnimationFrameCallbackEvent, type AppStateAdapter, type AutoTicketHandle, type AutoTicketOptions, type BeforeUnloadEvent, Button, type ButtonProps, Checkbox, type CheckboxProps, type CombinedCheckpoint, Command, type CommandHandler, type ControlSpriteProps, type ControlState, type ControlStateValue, type ControlTextStyle, type CustomEvent, DEBUG_EMPTY_PAGE, type DebugSessionConfig, type DebugSessionController, type DebugWarpBoundary, type DebugWarpOptions, type DefaultOverlayName, type DefaultPageName, type DlcProgress, EditableChangeSource, EditableState, type FastForwardOptions, type FocusEvent, type FocusEventKind, type FullScreenEvent, type FullscreenEventKind, type GameControl, type GameEvent, type GameStateSourceProps, type GameStateStore, type Gamepad, type GamepadButton, type GamepadEvent, type GamepadHapticActuator, Input, type InputBackground, type InputBackgroundStates, type InputBackgroundStyle, type InputCaretStyle, type InputHandle, type InputProps, JSX, type KeyboardLocation, LayoutEvent, type Literal, MaybePromise, MouseEvent, MoyuClipAttributes, MoyuEvent, MoyuNodeAttributes, MoyuSpriteAttributes, MoyuTextAttributes, MoyuVBoxAttributes, type NavigationState, type Navigator, type NodeEvent, type OverlayConfig, type OverlayDescriptor, type OverlayInfo, OverlayParamsContext, type PageConfig, type PageDescriptor, PageParamsContext, type PressEvent, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type RegisterNavigator, type ResizeEvent, type ResolvedArgument, type ResolvedCommandLine, type ResolvedSystemCallLine, type RootErrorInfo, type RootHandle, type RootNavigatorList, type RootOptions, type RootUiDataMap, type RootUncaughtErrorInfo, type ScenarioCommandBaseType, type ScenarioEvent, ScrollView, type ScrollViewController, type ScrollViewProps, Select, type SelectListProps, type SelectOption, type SelectOptionSpriteProps, type SelectProps, type ShaderBuiltin, type ShaderBuiltinName, type ShaderEvent, Slider, type SliderProps, type SliderThumbProps, type SliderTrackProps, type StackNavigatorOptions, StageContextProvider, type StageInstance, type TextLine, type TextLineHandler, TouchEvent, type UseScrollViewOptions, WheelEvent, type WithAnimated, animated as a, addEventListener, addFluidObserver, animated, autoState, createGameStateContext, createRoot, createStackNavigator, createStage, createStaticNavigation, ensureArchiveVariableDefaults, executeNodeCommand, executePluginCommand, fastForwardState, getAppStateAdapter, getNavigator, getSeekingType, getUiData, globalEventListeners, globalRequestAnimationFrameListeners, initGlobalVariableDefaults, initUiData, loadVariablesDocument, moyu, nextLine, registerAppStateAdapter, removeFluidObserver, replaceUiData, setDefaultAutoTailMs, setWaiting, skipState, startDebugSession, startRuntimeDebugSession, stopDebugSession, stopRuntimeDebugSession, useAutoBlocker, useAutoTicket, useBeforeHandleCommandCallback, useDebugSession, useFadeIn, useFadeInOut, useFadeOut, useInterruptCallback, useIsAutoing, useIsSeeking, useIsSkipping, useNavigation, useNavigationParams, useNavigationState, useScenario, useScrollView, useSkipBlocker, useSkipCallback, useSoundEffect, useStageContext, useTouchInput, useUiData, warpState };
package/dist/lib.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import * as react from 'react';
2
2
  import { ReactElement, Component, ForwardRefExoticComponent, CSSProperties, FC, ReactNode, ComponentType } from 'react';
3
- import { S as ShaderDirection, M as MoyuEvent, C as Command, a as MaybePromise, J as JSX, L as LayoutEvent, W as WheelEvent, T as TouchEvent, b as MoyuClipAttributes, c as MoyuVBoxAttributes, d as MoyuSpriteAttributes, e as TextProps, f as MoyuNodeAttributes, g as MouseEvent, h as MoyuTextAttributes, E as EditableState, i as EditableChangeSource, j as SpriteProps, k as JsonValue } from './jsx-dev-runtime-xC0sDJ2D.js';
4
- export { A as AudioCommand, l as AudioSettings, B as BubbleEvent, D as DetailedMoyuProps, m as EditableCommand, n as EditableEvent, o as EffectParams, G as GamepadCommand, K as KeyboardEvent, p as KeyboardEventKind, q as MakeNullOptional, r as MouseEventKind, s as MoyuAnimationAttributes, t as MoyuBackdropAttributes, u as MoyuContainerAttributes, v as MoyuEditableAttributes, w as MoyuEventHandler, x as MoyuFilterAttributes, y as MoyuHBoxAttributes, z as MoyuListenerAttributes, F as MoyuShaderAttributes, H as MoyuShaderSlotAttributes, I as MoyuVideoAttributes, N as Node, O as OverlayDialog, P as OverlayNotificationPosition, Q as OverlayStoreFlag, R as PlatformInfo, U as PointerEventKind, V as RetainMode, X as ScenarioCommand, Y as ShaderCommand, Z as ShaderParam, _ as ShaderParamType, $ as ShaderSource, a0 as ShaderTimeControl, a1 as SteamCommand, a2 as SystemCommand, a3 as TextCommand, a4 as TextInteractionEvent, a5 as TextLayoutEvent, a6 as TimelinePossibleClip, a7 as TouchEventKind, a8 as Tuple2, a9 as Tuple3, aa as Tuple4, ab as VideoCommand, ac as WheelEventDeltaMode, ad as WindowState, ae as createBubbleEvent, af as getPlatform, ag as getStageSize, ah as mergeEvent } from './jsx-dev-runtime-xC0sDJ2D.js';
3
+ import { S as ShaderDirection, M as MoyuEvent, C as Command, a as MaybePromise, J as JSX, L as LayoutEvent, W as WheelEvent, T as TouchEvent, b as MoyuClipAttributes, c as MoyuVBoxAttributes, d as MoyuSpriteAttributes, e as TextProps, f as MoyuNodeAttributes, g as MouseEvent, h as MoyuTextAttributes, E as EditableState, i as EditableChangeSource, j as SpriteProps, k as JsonValue } from './jsx-dev-runtime-Dvhilv0K.js';
4
+ export { A as AudioCommand, l as AudioSettings, B as BubbleEvent, D as DetailedMoyuProps, m as EditableCommand, n as EditableEvent, o as EffectParams, G as GamepadCommand, K as KeyboardEvent, p as KeyboardEventKind, q as MakeNullOptional, r as MouseButton, s as MouseButtons, t as MouseEventKind, u as MoyuAnimationAttributes, v as MoyuBackdropAttributes, w as MoyuContainerAttributes, x as MoyuEditableAttributes, y as MoyuEventHandler, z as MoyuFilterAttributes, F as MoyuHBoxAttributes, H as MoyuListenerAttributes, I as MoyuShaderAttributes, N as MoyuShaderSlotAttributes, O as MoyuVideoAttributes, P as Node, Q as OverlayDialog, R as OverlayNotificationPosition, U as OverlayStoreFlag, V as PlatformInfo, X as PointerEventKind, Y as RetainMode, Z as ScenarioCommand, _ as ShaderCommand, $ as ShaderParam, a0 as ShaderParamType, a1 as ShaderSource, a2 as ShaderTimeControl, a3 as SteamCommand, a4 as SystemCommand, a5 as TextCommand, a6 as TextInteractionEvent, a7 as TextLayoutEvent, a8 as TimelinePossibleClip, a9 as TouchEventKind, aa as Tuple2, ab as Tuple3, ac as Tuple4, ad as VideoCommand, ae as WheelEventDeltaMode, af as WindowState, ag as createBubbleEvent, ah as getPlatform, ai as getStageSize, aj as mergeEvent } from './jsx-dev-runtime-Dvhilv0K.js';
5
5
  import { FluidValue, addFluidObserver as addFluidObserver$1, removeFluidObserver as removeFluidObserver$1 } from '@react-spring/shared';
6
6
  import { ElementType, AssignableKeys, ComponentPropsWithRef } from '@react-spring/types';
7
7
  import { Snapshot } from 'valtio';
@@ -617,7 +617,12 @@ interface ButtonProps extends Omit<MoyuNodeAttributes, 'onClick'> {
617
617
  sprite: ControlSpriteProps;
618
618
  disabled?: boolean;
619
619
  lockOn?: Exclude<ControlState, 'disabled'>;
620
- onPress?: (event: PressEvent) => void;
620
+ /**
621
+ * Called when the button is activated, which is the engine's click gesture. The press
622
+ * visual comes from the pointer press instead, so a gesture that ends away from the
623
+ * button shows as pressed but does not activate it.
624
+ */
625
+ onPress?: (event: MouseEvent) => void;
621
626
  text?: string;
622
627
  textStyle?: ControlStateValue<ControlTextStyle>;
623
628
  textOffsetX?: number;
@@ -737,6 +742,7 @@ interface SliderProps extends Omit<MoyuNodeAttributes, 'onClick'> {
737
742
  defaultValue?: number;
738
743
  onValueChange?: (value: number) => void;
739
744
  onValueCommit?: (value: number) => void;
745
+ /** Called when the pointer presses the slider, before the drag starts. */
740
746
  onPress?: (event: PressEvent) => void;
741
747
  disabled?: boolean;
742
748
  track: SliderTrackProps;
@@ -1050,6 +1056,8 @@ declare function useScenario(stories: string[], startName?: string, entryName?:
1050
1056
  */
1051
1057
  declare function useSoundEffect(src?: string): () => void;
1052
1058
 
1059
+ declare function useTouchInput(): boolean;
1060
+
1053
1061
  type UiDocument = Record<string, unknown>;
1054
1062
  type UiSchema<TUiDocument extends UiDocument> = ZodType<TUiDocument>;
1055
1063
  interface RootUiDataMap {
@@ -1086,4 +1094,4 @@ declare module 'zod' {
1086
1094
  }
1087
1095
  }
1088
1096
 
1089
- export { type AnimatedComponent, type AnimatedProps, type AnimationFrameCallbackEvent, type AppStateAdapter, type AutoTicketHandle, type AutoTicketOptions, type BeforeUnloadEvent, Button, type ButtonProps, Checkbox, type CheckboxProps, type CombinedCheckpoint, Command, type CommandHandler, type ControlSpriteProps, type ControlState, type ControlStateValue, type ControlTextStyle, type CustomEvent, DEBUG_EMPTY_PAGE, type DebugSessionConfig, type DebugSessionController, type DebugWarpBoundary, type DebugWarpOptions, type DefaultOverlayName, type DefaultPageName, type DlcProgress, EditableChangeSource, EditableState, type FastForwardOptions, type FocusEvent, type FocusEventKind, type FullScreenEvent, type FullscreenEventKind, type GameControl, type GameEvent, type GameStateSourceProps, type GameStateStore, type Gamepad, type GamepadButton, type GamepadEvent, type GamepadHapticActuator, Input, type InputBackground, type InputBackgroundStates, type InputBackgroundStyle, type InputCaretStyle, type InputHandle, type InputProps, JSX, type KeyboardLocation, LayoutEvent, type Literal, MaybePromise, MouseEvent, MoyuClipAttributes, MoyuEvent, MoyuNodeAttributes, MoyuSpriteAttributes, MoyuTextAttributes, MoyuVBoxAttributes, type NavigationState, type Navigator, type NodeEvent, type OverlayConfig, type OverlayDescriptor, type OverlayInfo, OverlayParamsContext, type PageConfig, type PageDescriptor, PageParamsContext, type PressEvent, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type RegisterNavigator, type ResizeEvent, type ResolvedArgument, type ResolvedCommandLine, type ResolvedSystemCallLine, type RootErrorInfo, type RootHandle, type RootNavigatorList, type RootOptions, type RootUiDataMap, type RootUncaughtErrorInfo, type ScenarioCommandBaseType, type ScenarioEvent, ScrollView, type ScrollViewController, type ScrollViewProps, Select, type SelectListProps, type SelectOption, type SelectOptionSpriteProps, type SelectProps, type ShaderBuiltin, type ShaderBuiltinName, type ShaderEvent, Slider, type SliderProps, type SliderThumbProps, type SliderTrackProps, type StackNavigatorOptions, StageContextProvider, type StageInstance, type TextLine, type TextLineHandler, TouchEvent, type UseScrollViewOptions, WheelEvent, type WithAnimated, animated as a, addEventListener, addFluidObserver, animated, autoState, createGameStateContext, createRoot, createStackNavigator, createStage, createStaticNavigation, ensureArchiveVariableDefaults, executeNodeCommand, executePluginCommand, fastForwardState, getAppStateAdapter, getNavigator, getSeekingType, getUiData, globalEventListeners, globalRequestAnimationFrameListeners, initGlobalVariableDefaults, initUiData, loadVariablesDocument, moyu, nextLine, registerAppStateAdapter, removeFluidObserver, replaceUiData, setDefaultAutoTailMs, setWaiting, skipState, startDebugSession, startRuntimeDebugSession, stopDebugSession, stopRuntimeDebugSession, useAutoBlocker, useAutoTicket, useBeforeHandleCommandCallback, useDebugSession, useFadeIn, useFadeInOut, useFadeOut, useInterruptCallback, useIsAutoing, useIsSeeking, useIsSkipping, useNavigation, useNavigationParams, useNavigationState, useScenario, useScrollView, useSkipBlocker, useSkipCallback, useSoundEffect, useStageContext, useUiData, warpState };
1097
+ export { type AnimatedComponent, type AnimatedProps, type AnimationFrameCallbackEvent, type AppStateAdapter, type AutoTicketHandle, type AutoTicketOptions, type BeforeUnloadEvent, Button, type ButtonProps, Checkbox, type CheckboxProps, type CombinedCheckpoint, Command, type CommandHandler, type ControlSpriteProps, type ControlState, type ControlStateValue, type ControlTextStyle, type CustomEvent, DEBUG_EMPTY_PAGE, type DebugSessionConfig, type DebugSessionController, type DebugWarpBoundary, type DebugWarpOptions, type DefaultOverlayName, type DefaultPageName, type DlcProgress, EditableChangeSource, EditableState, type FastForwardOptions, type FocusEvent, type FocusEventKind, type FullScreenEvent, type FullscreenEventKind, type GameControl, type GameEvent, type GameStateSourceProps, type GameStateStore, type Gamepad, type GamepadButton, type GamepadEvent, type GamepadHapticActuator, Input, type InputBackground, type InputBackgroundStates, type InputBackgroundStyle, type InputCaretStyle, type InputHandle, type InputProps, JSX, type KeyboardLocation, LayoutEvent, type Literal, MaybePromise, MouseEvent, MoyuClipAttributes, MoyuEvent, MoyuNodeAttributes, MoyuSpriteAttributes, MoyuTextAttributes, MoyuVBoxAttributes, type NavigationState, type Navigator, type NodeEvent, type OverlayConfig, type OverlayDescriptor, type OverlayInfo, OverlayParamsContext, type PageConfig, type PageDescriptor, PageParamsContext, type PressEvent, Radio, RadioGroup, type RadioGroupProps, type RadioProps, type RegisterNavigator, type ResizeEvent, type ResolvedArgument, type ResolvedCommandLine, type ResolvedSystemCallLine, type RootErrorInfo, type RootHandle, type RootNavigatorList, type RootOptions, type RootUiDataMap, type RootUncaughtErrorInfo, type ScenarioCommandBaseType, type ScenarioEvent, ScrollView, type ScrollViewController, type ScrollViewProps, Select, type SelectListProps, type SelectOption, type SelectOptionSpriteProps, type SelectProps, type ShaderBuiltin, type ShaderBuiltinName, type ShaderEvent, Slider, type SliderProps, type SliderThumbProps, type SliderTrackProps, type StackNavigatorOptions, StageContextProvider, type StageInstance, type TextLine, type TextLineHandler, TouchEvent, type UseScrollViewOptions, WheelEvent, type WithAnimated, animated as a, addEventListener, addFluidObserver, animated, autoState, createGameStateContext, createRoot, createStackNavigator, createStage, createStaticNavigation, ensureArchiveVariableDefaults, executeNodeCommand, executePluginCommand, fastForwardState, getAppStateAdapter, getNavigator, getSeekingType, getUiData, globalEventListeners, globalRequestAnimationFrameListeners, initGlobalVariableDefaults, initUiData, loadVariablesDocument, moyu, nextLine, registerAppStateAdapter, removeFluidObserver, replaceUiData, setDefaultAutoTailMs, setWaiting, skipState, startDebugSession, startRuntimeDebugSession, stopDebugSession, stopRuntimeDebugSession, useAutoBlocker, useAutoTicket, useBeforeHandleCommandCallback, useDebugSession, useFadeIn, useFadeInOut, useFadeOut, useInterruptCallback, useIsAutoing, useIsSeeking, useIsSkipping, useNavigation, useNavigationParams, useNavigationState, useScenario, useScrollView, useSkipBlocker, useSkipCallback, useSoundEffect, useStageContext, useTouchInput, useUiData, warpState };
package/dist/lib.mjs CHANGED
@@ -23,6 +23,8 @@ __export(lib_exports, {
23
23
  Checkbox: () => Checkbox,
24
24
  DEBUG_EMPTY_PAGE: () => DEBUG_EMPTY_PAGE,
25
25
  Input: () => Input,
26
+ MouseButton: () => MouseButton,
27
+ MouseButtons: () => MouseButtons,
26
28
  OverlayParamsContext: () => OverlayParamsContext,
27
29
  PageParamsContext: () => PageParamsContext,
28
30
  Radio: () => Radio,
@@ -90,6 +92,7 @@ __export(lib_exports, {
90
92
  useSkipCallback: () => useSkipCallback,
91
93
  useSoundEffect: () => useSoundEffect,
92
94
  useStageContext: () => useStageContext,
95
+ useTouchInput: () => useTouchInput,
93
96
  useUiData: () => useUiData,
94
97
  warpState: () => warpState
95
98
  });
@@ -161,8 +164,7 @@ function executePluginCommand(pluginName, payload) {
161
164
 
162
165
  // src/state.ts
163
166
  var STATE = {
164
- nodeMap: {},
165
- touchMoved: {}
167
+ nodeMap: {}
166
168
  };
167
169
 
168
170
  // src/node.ts
@@ -908,6 +910,11 @@ globalThis.__moyu_receive_event = (raw_event) => {
908
910
  };
909
911
  function handleBubbleEvent(name, body) {
910
912
  const event = createBubbleEvent(body, body.targetId);
913
+ if (name === "mouseevent") {
914
+ const mouseEvent = event;
915
+ mouseEvent.x = mouseEvent.clientX;
916
+ mouseEvent.y = mouseEvent.clientY;
917
+ }
911
918
  const { kind, bubbleTargetIds } = body;
912
919
  if (body.targetId !== 0) {
913
920
  const node = STATE.nodeMap[body.targetId];
@@ -933,13 +940,6 @@ function handleBubbleEvent(name, body) {
933
940
  STATE.nodeMap[event.currentTargetId]?.listeners?.[`on${kind}`]?.(event);
934
941
  }
935
942
  }
936
- if (kind === "TouchStart") {
937
- STATE.touchMoved[identifier] = false;
938
- } else if (kind === "TouchMove") {
939
- STATE.touchMoved[identifier] = true;
940
- } else if (kind === "TouchEnd" || kind === "TouchCancel") {
941
- delete STATE.touchMoved[identifier];
942
- }
943
943
  }
944
944
  }
945
945
  if (event.bubbles) {
@@ -971,6 +971,22 @@ function addEventListener(name, callback) {
971
971
  };
972
972
  }
973
973
 
974
+ // src/events/mouse.ts
975
+ var MouseButton = {
976
+ Left: 0,
977
+ Middle: 1,
978
+ Right: 2,
979
+ Back: 3,
980
+ Forward: 4
981
+ };
982
+ var MouseButtons = {
983
+ Left: 1,
984
+ Right: 2,
985
+ Middle: 4,
986
+ Back: 8,
987
+ Forward: 16
988
+ };
989
+
974
990
  // src/utils.ts
975
991
  function getStageSize() {
976
992
  const stageSize = executePluginCommand("system", {
@@ -1336,6 +1352,7 @@ function Button({
1336
1352
  anchor,
1337
1353
  pivot,
1338
1354
  interactive: disabled ? false : interactive,
1355
+ hitTestSelf: false,
1339
1356
  onMouseEnter: mergeEvent(onMouseEnter, (event) => {
1340
1357
  if (event.targetId === event.currentTargetId) {
1341
1358
  event.stopPropagation();
@@ -1348,18 +1365,12 @@ function Button({
1348
1365
  setPressed(false);
1349
1366
  }),
1350
1367
  onMouseDown: mergeEvent(onMouseDown, () => setPressed(true)),
1351
- onMouseUp: mergeEvent(onMouseUp, (event) => {
1352
- if (pressed) {
1353
- onPress?.(event);
1354
- }
1368
+ onMouseUp: mergeEvent(onMouseUp, () => {
1355
1369
  setPressed(false);
1356
1370
  setHovered(true);
1357
1371
  }),
1358
1372
  onTouchStart: mergeEvent(onTouchStart, () => setPressed(true)),
1359
- onTouchEnd: mergeEvent(onTouchEnd, (event) => {
1360
- if (pressed) {
1361
- onPress?.(event);
1362
- }
1373
+ onTouchEnd: mergeEvent(onTouchEnd, () => {
1363
1374
  setPressed(false);
1364
1375
  setHovered(true);
1365
1376
  }),
@@ -1367,7 +1378,10 @@ function Button({
1367
1378
  setHovered(false);
1368
1379
  setPressed(false);
1369
1380
  }),
1370
- onClick: (event) => event.stopPropagation(),
1381
+ onClick: (event) => {
1382
+ onPress?.(event);
1383
+ event.stopPropagation();
1384
+ },
1371
1385
  children: /* @__PURE__ */ jsxs("sprite", { ...spriteProps, src: resolveControlStateValue(src, state), cursor: "pointer", children: [
1372
1386
  text !== void 0 ? /* @__PURE__ */ jsx(
1373
1387
  "text",
@@ -1788,6 +1802,7 @@ function Select({
1788
1802
  anchor,
1789
1803
  pivot,
1790
1804
  interactive: disabled ? false : containerProps.interactive,
1805
+ hitTestSelf: false,
1791
1806
  children: [
1792
1807
  /* @__PURE__ */ jsx(
1793
1808
  Button,
@@ -1903,14 +1918,18 @@ function Slider({
1903
1918
  }
1904
1919
  }, [onValueCommit]);
1905
1920
  useEffect3(() => {
1906
- const handleMouseUp = () => endDragging(true);
1921
+ const handleMouseUp = () => {
1922
+ if (dragStateRef.current?.pointerIdentifier === void 0) {
1923
+ endDragging(true);
1924
+ }
1925
+ };
1907
1926
  const handleTouchEnd = (event) => {
1908
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1927
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1909
1928
  endDragging(true);
1910
1929
  }
1911
1930
  };
1912
1931
  const handleTouchCancel2 = (event) => {
1913
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1932
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1914
1933
  endDragging(false);
1915
1934
  }
1916
1935
  };
@@ -1933,45 +1952,37 @@ function Slider({
1933
1952
  if (dragStateRef.current !== null) {
1934
1953
  return;
1935
1954
  }
1955
+ onPress?.(event);
1956
+ if (event.defaultPrevented) {
1957
+ return;
1958
+ }
1936
1959
  const thumbPosition = currentValueRef.current * distance;
1960
+ const onThumb = event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth;
1961
+ let startValue = currentValueRef.current;
1962
+ if (!onThumb && distance > 0) {
1963
+ startValue = clampValue((event.offsetX - thumb.targetWidth / 2) / distance);
1964
+ setSliderValue(startValue);
1965
+ }
1937
1966
  dragStateRef.current = {
1938
- startPosition: event.offsetX,
1939
- startValue: currentValueRef.current,
1940
- touchIdentifier: "identifier" in event ? event.identifier : void 0,
1941
- startedOnThumb: event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth,
1942
- moved: false
1967
+ // The movement is measured in stage coordinates: `offsetX` is relative to the node
1968
+ // the pointer is over, which changes when the pointer leaves the track.
1969
+ startPointerX: event.clientX,
1970
+ startValue,
1971
+ pointerIdentifier: "identifier" in event ? event.identifier : void 0
1943
1972
  };
1944
1973
  setDragging(true);
1945
1974
  };
1946
1975
  const moveDragging = (event) => {
1947
1976
  const dragState = dragStateRef.current;
1948
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier || distance === 0) {
1977
+ const eventIdentifier = "identifier" in event ? event.identifier : void 0;
1978
+ if (dragState === null || dragState.pointerIdentifier !== eventIdentifier || distance === 0) {
1949
1979
  return;
1950
1980
  }
1951
1981
  event.stopPropagation();
1952
- const delta = event.offsetX - dragState.startPosition;
1953
- if (delta !== 0) {
1954
- dragState.moved = true;
1955
- }
1956
- setSliderValue(dragState.startValue + delta / distance);
1957
- };
1958
- const handlePress = (event) => {
1959
- const dragState = dragStateRef.current;
1960
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier) {
1961
- return;
1962
- }
1963
- onPress?.(event);
1964
- if (event.defaultPrevented) {
1965
- endDragging(false);
1966
- return;
1967
- }
1968
- if (!dragState.moved && !dragState.startedOnThumb && distance > 0) {
1969
- setSliderValue((event.offsetX - thumb.targetWidth / 2) / distance);
1970
- }
1971
- endDragging(true);
1982
+ setSliderValue(dragState.startValue + (event.clientX - dragState.startPointerX) / distance);
1972
1983
  };
1973
1984
  const handleTouchCancel = (event) => {
1974
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1985
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1975
1986
  endDragging(false);
1976
1987
  }
1977
1988
  };
@@ -1989,7 +2000,6 @@ function Slider({
1989
2000
  pivot: [0, 0.5],
1990
2001
  y: (track.targetHeight ?? 0) / 2
1991
2002
  },
1992
- onPress: handlePress,
1993
2003
  onMouseEnter,
1994
2004
  onMouseLeave,
1995
2005
  onMouseDown: mergeEvent(onMouseDown, startDragging),
@@ -4091,6 +4101,59 @@ function useBeforeHandleCommandCallback(callback) {
4091
4101
  }, [stage, callback]);
4092
4102
  }
4093
4103
 
4104
+ // src/hooks/useTouchInput.ts
4105
+ import { useEffect as useEffect8, useState as useState8 } from "react";
4106
+ var touchInput = false;
4107
+ var subscribers = /* @__PURE__ */ new Set();
4108
+ var uninstall = null;
4109
+ function setTouchInput(value) {
4110
+ if (value === touchInput) {
4111
+ return;
4112
+ }
4113
+ touchInput = value;
4114
+ for (const notify of [...subscribers]) {
4115
+ notify(value);
4116
+ }
4117
+ }
4118
+ function install() {
4119
+ if (uninstall) {
4120
+ return;
4121
+ }
4122
+ const cleanups = [
4123
+ // A touch means the device is being used by hand.
4124
+ addEventListener("touchstart", () => setTouchInput(true)),
4125
+ // Only a mouse event the engine did not produce on its own means the user reached
4126
+ // for the mouse: a tap's mouse compatibility gesture and the hover refresh a frame
4127
+ // repeats both carry `synthetic`.
4128
+ addEventListener("mousemove", (event) => {
4129
+ if (!event.synthetic) {
4130
+ setTouchInput(false);
4131
+ }
4132
+ })
4133
+ ];
4134
+ uninstall = () => {
4135
+ for (const cleanup of cleanups) {
4136
+ cleanup();
4137
+ }
4138
+ uninstall = null;
4139
+ };
4140
+ }
4141
+ function useTouchInput() {
4142
+ const [value, setValue] = useState8(touchInput);
4143
+ useEffect8(() => {
4144
+ subscribers.add(setValue);
4145
+ setValue(touchInput);
4146
+ install();
4147
+ return () => {
4148
+ subscribers.delete(setValue);
4149
+ if (subscribers.size === 0) {
4150
+ uninstall?.();
4151
+ }
4152
+ };
4153
+ }, []);
4154
+ return value;
4155
+ }
4156
+
4094
4157
  // src/lib.ts
4095
4158
  export * from "@react-spring/core";
4096
4159
  export {
@@ -4098,6 +4161,8 @@ export {
4098
4161
  Checkbox,
4099
4162
  DEBUG_EMPTY_PAGE,
4100
4163
  Input,
4164
+ MouseButton,
4165
+ MouseButtons,
4101
4166
  OverlayParamsContext,
4102
4167
  PageParamsContext,
4103
4168
  Radio,
@@ -4165,6 +4230,7 @@ export {
4165
4230
  useSkipCallback,
4166
4231
  useSoundEffect,
4167
4232
  useStageContext,
4233
+ useTouchInput,
4168
4234
  useUiData,
4169
4235
  warpState
4170
4236
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momoyu-ink/kit",
3
- "version": "0.11.3",
3
+ "version": "0.13.0",
4
4
  "description": "Software Development Kit of Moyu Visual Novel Engine",
5
5
  "main": "dist/lib.cjs",
6
6
  "module": "dist/lib.mjs",