@momoyu-ink/kit 0.11.2 → 0.12.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/` 下的文件。流程:
@@ -429,7 +429,7 @@ type SteamCommand = {
429
429
 
430
430
  type ReadFormat = 'text' | 'binary';
431
431
 
432
- type WindowState = 'idle' | 'maximized' | 'minimized' | 'fullscreen';
432
+ type WindowState = "idle" | "maximized" | "minimized" | "fullscreen";
433
433
 
434
434
  type SystemCommand = {
435
435
  subCommand: 'setWindowSize';
@@ -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';
@@ -622,6 +670,13 @@ type LayoutEvent = {
622
670
  height: number;
623
671
  };
624
672
 
673
+ type PointerEventKind = 'over' | 'enter' | 'leave' | 'down' | 'up' | 'click';
674
+
675
+ type TextInteractionEvent = {
676
+ id: string;
677
+ kind: PointerEventKind;
678
+ };
679
+
625
680
  type TextLayoutEvent = {
626
681
  text: string;
627
682
  width: number;
@@ -631,8 +686,9 @@ type TextLayoutEvent = {
631
686
 
632
687
  type WheelEventDeltaMode = 'pixel' | 'line' | 'page';
633
688
 
634
- interface WheelEvent extends Omit<MouseEvent, 'kind'> {
689
+ interface WheelEvent extends BubbleEvent {
635
690
  kind: 'Wheel';
691
+ currentTargetLabel?: string;
636
692
  deltaX: number;
637
693
  deltaY: number;
638
694
  deltaZ: number;
@@ -806,11 +862,6 @@ type TextProps = {
806
862
  printMode?: TextPrintMode;
807
863
  printSpeed?: number;
808
864
  parseMarkup?: boolean;
809
- /**
810
- * the writing direction of the text in the box,
811
- * only `Horizontal` (right-to-left) or `Vertical` (top-to-bottom) is valid.
812
- */
813
- direction?: 'horizontal' | 'vertical';
814
865
  /**
815
866
  * the width of box.
816
867
  */
@@ -819,10 +870,6 @@ type TextProps = {
819
870
  * the height of box.
820
871
  */
821
872
  boxHeight?: number;
822
- /**
823
- * the size of the glyph grid which each character be fit to, usually equals to `font_size`.
824
- */
825
- glyphGridSize?: number;
826
873
  fontSize?: number;
827
874
  fillColor?: string;
828
875
  lineHeight?: number;
@@ -911,7 +958,7 @@ type ShaderSlotProps = {
911
958
  height?: number;
912
959
  };
913
960
 
914
- type AnimationFormat = 'apng' | 'webp';
961
+ type AnimationFormat = 'apng' | 'webp' | 'jxl';
915
962
 
916
963
  type AnimationProps = {
917
964
  src: string | null;
@@ -939,6 +986,9 @@ interface MoyuListenerAttributes {
939
986
  onMouseDown?: MoyuEventHandler<MouseEvent>;
940
987
  onMouseUp?: MoyuEventHandler<MouseEvent>;
941
988
  onMouseMove?: MoyuEventHandler<MouseEvent>;
989
+ onAuxClick?: MoyuEventHandler<MouseEvent>;
990
+ onDoubleClick?: MoyuEventHandler<MouseEvent>;
991
+ onContextMenu?: MoyuEventHandler<MouseEvent>;
942
992
  onKeyDown?: MoyuEventHandler<KeyboardEvent>;
943
993
  onKeyUp?: MoyuEventHandler<KeyboardEvent>;
944
994
  onKeyPress?: MoyuEventHandler<KeyboardEvent>;
@@ -1000,6 +1050,7 @@ type MoyuTextAttributes = TextProps & MoyuNodeAttributes & {
1000
1050
  onFinish?: () => void;
1001
1051
  onProgress?: (progress: number) => void;
1002
1052
  onTextLayout?: (event: TextLayoutEvent) => void;
1053
+ onInteraction?: (event: TextInteractionEvent) => void;
1003
1054
  };
1004
1055
  declare namespace JSX {
1005
1056
  type ElementType = string | React.JSXElementConstructor<any>;
@@ -1052,4 +1103,4 @@ type _Command = AudioCommand | EditableCommand | TextCommand | GamepadCommand |
1052
1103
  type Command = MakeNullOptional<_Command>;
1053
1104
  type MaybePromise = any;
1054
1105
 
1055
- export { type ShaderTimeControl 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 RetainMode as U, type ScenarioCommand as V, type WheelEvent as W, type ShaderCommand as X, type ShaderParam as Y, type ShaderParamType as Z, type ShaderSource as _, type MaybePromise as a, type SteamCommand as a0, type SystemCommand as a1, type TextCommand as a2, type TextLayoutEvent as a3, type TimelinePossibleClip as a4, type TouchEventKind as a5, type Tuple2 as a6, type Tuple3 as a7, type Tuple4 as a8, type VideoCommand as a9, type WheelEventDeltaMode as aa, type WindowState as ab, createBubbleEvent as ac, getPlatform as ad, getStageSize as ae, mergeEvent as af, 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 };
1106
+ 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 };
@@ -429,7 +429,7 @@ type SteamCommand = {
429
429
 
430
430
  type ReadFormat = 'text' | 'binary';
431
431
 
432
- type WindowState = 'idle' | 'maximized' | 'minimized' | 'fullscreen';
432
+ type WindowState = "idle" | "maximized" | "minimized" | "fullscreen";
433
433
 
434
434
  type SystemCommand = {
435
435
  subCommand: 'setWindowSize';
@@ -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';
@@ -622,6 +670,13 @@ type LayoutEvent = {
622
670
  height: number;
623
671
  };
624
672
 
673
+ type PointerEventKind = 'over' | 'enter' | 'leave' | 'down' | 'up' | 'click';
674
+
675
+ type TextInteractionEvent = {
676
+ id: string;
677
+ kind: PointerEventKind;
678
+ };
679
+
625
680
  type TextLayoutEvent = {
626
681
  text: string;
627
682
  width: number;
@@ -631,8 +686,9 @@ type TextLayoutEvent = {
631
686
 
632
687
  type WheelEventDeltaMode = 'pixel' | 'line' | 'page';
633
688
 
634
- interface WheelEvent extends Omit<MouseEvent, 'kind'> {
689
+ interface WheelEvent extends BubbleEvent {
635
690
  kind: 'Wheel';
691
+ currentTargetLabel?: string;
636
692
  deltaX: number;
637
693
  deltaY: number;
638
694
  deltaZ: number;
@@ -806,11 +862,6 @@ type TextProps = {
806
862
  printMode?: TextPrintMode;
807
863
  printSpeed?: number;
808
864
  parseMarkup?: boolean;
809
- /**
810
- * the writing direction of the text in the box,
811
- * only `Horizontal` (right-to-left) or `Vertical` (top-to-bottom) is valid.
812
- */
813
- direction?: 'horizontal' | 'vertical';
814
865
  /**
815
866
  * the width of box.
816
867
  */
@@ -819,10 +870,6 @@ type TextProps = {
819
870
  * the height of box.
820
871
  */
821
872
  boxHeight?: number;
822
- /**
823
- * the size of the glyph grid which each character be fit to, usually equals to `font_size`.
824
- */
825
- glyphGridSize?: number;
826
873
  fontSize?: number;
827
874
  fillColor?: string;
828
875
  lineHeight?: number;
@@ -911,7 +958,7 @@ type ShaderSlotProps = {
911
958
  height?: number;
912
959
  };
913
960
 
914
- type AnimationFormat = 'apng' | 'webp';
961
+ type AnimationFormat = 'apng' | 'webp' | 'jxl';
915
962
 
916
963
  type AnimationProps = {
917
964
  src: string | null;
@@ -939,6 +986,9 @@ interface MoyuListenerAttributes {
939
986
  onMouseDown?: MoyuEventHandler<MouseEvent>;
940
987
  onMouseUp?: MoyuEventHandler<MouseEvent>;
941
988
  onMouseMove?: MoyuEventHandler<MouseEvent>;
989
+ onAuxClick?: MoyuEventHandler<MouseEvent>;
990
+ onDoubleClick?: MoyuEventHandler<MouseEvent>;
991
+ onContextMenu?: MoyuEventHandler<MouseEvent>;
942
992
  onKeyDown?: MoyuEventHandler<KeyboardEvent>;
943
993
  onKeyUp?: MoyuEventHandler<KeyboardEvent>;
944
994
  onKeyPress?: MoyuEventHandler<KeyboardEvent>;
@@ -1000,6 +1050,7 @@ type MoyuTextAttributes = TextProps & MoyuNodeAttributes & {
1000
1050
  onFinish?: () => void;
1001
1051
  onProgress?: (progress: number) => void;
1002
1052
  onTextLayout?: (event: TextLayoutEvent) => void;
1053
+ onInteraction?: (event: TextInteractionEvent) => void;
1003
1054
  };
1004
1055
  declare namespace JSX {
1005
1056
  type ElementType = string | React.JSXElementConstructor<any>;
@@ -1052,4 +1103,4 @@ type _Command = AudioCommand | EditableCommand | TextCommand | GamepadCommand |
1052
1103
  type Command = MakeNullOptional<_Command>;
1053
1104
  type MaybePromise = any;
1054
1105
 
1055
- export { type ShaderTimeControl 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 RetainMode as U, type ScenarioCommand as V, type WheelEvent as W, type ShaderCommand as X, type ShaderParam as Y, type ShaderParamType as Z, type ShaderSource as _, type MaybePromise as a, type SteamCommand as a0, type SystemCommand as a1, type TextCommand as a2, type TextLayoutEvent as a3, type TimelinePossibleClip as a4, type TouchEventKind as a5, type Tuple2 as a6, type Tuple3 as a7, type Tuple4 as a8, type VideoCommand as a9, type WheelEventDeltaMode as aa, type WindowState as ab, createBubbleEvent as ac, getPlatform as ad, getStageSize as ae, mergeEvent as af, 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 };
1106
+ 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-WLUT_h4x.mjs';
2
+ export { J as JSX } from './jsx-dev-runtime-M-Dr-KG3.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-WLUT_h4x.js';
2
+ export { J as JSX } from './jsx-dev-runtime-M-Dr-KG3.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-WLUT_h4x.mjs';
2
+ export { J as JSX } from './jsx-dev-runtime-M-Dr-KG3.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-WLUT_h4x.js';
2
+ export { J as JSX } from './jsx-dev-runtime-M-Dr-KG3.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", {
@@ -1354,18 +1370,12 @@ function Button({
1354
1370
  setPressed(false);
1355
1371
  }),
1356
1372
  onMouseDown: mergeEvent(onMouseDown, () => setPressed(true)),
1357
- onMouseUp: mergeEvent(onMouseUp, (event) => {
1358
- if (pressed) {
1359
- onPress?.(event);
1360
- }
1373
+ onMouseUp: mergeEvent(onMouseUp, () => {
1361
1374
  setPressed(false);
1362
1375
  setHovered(true);
1363
1376
  }),
1364
1377
  onTouchStart: mergeEvent(onTouchStart, () => setPressed(true)),
1365
- onTouchEnd: mergeEvent(onTouchEnd, (event) => {
1366
- if (pressed) {
1367
- onPress?.(event);
1368
- }
1378
+ onTouchEnd: mergeEvent(onTouchEnd, () => {
1369
1379
  setPressed(false);
1370
1380
  setHovered(true);
1371
1381
  }),
@@ -1373,7 +1383,10 @@ function Button({
1373
1383
  setHovered(false);
1374
1384
  setPressed(false);
1375
1385
  }),
1376
- onClick: (event) => event.stopPropagation(),
1386
+ onClick: (event) => {
1387
+ onPress?.(event);
1388
+ event.stopPropagation();
1389
+ },
1377
1390
  children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("sprite", { ...spriteProps, src: resolveControlStateValue(src, state), cursor: "pointer", children: [
1378
1391
  text !== void 0 ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
1379
1392
  "text",
@@ -1909,14 +1922,18 @@ function Slider({
1909
1922
  }
1910
1923
  }, [onValueCommit]);
1911
1924
  (0, import_react9.useEffect)(() => {
1912
- const handleMouseUp = () => endDragging(true);
1925
+ const handleMouseUp = () => {
1926
+ if (dragStateRef.current?.pointerIdentifier === void 0) {
1927
+ endDragging(true);
1928
+ }
1929
+ };
1913
1930
  const handleTouchEnd = (event) => {
1914
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1931
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1915
1932
  endDragging(true);
1916
1933
  }
1917
1934
  };
1918
1935
  const handleTouchCancel2 = (event) => {
1919
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1936
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1920
1937
  endDragging(false);
1921
1938
  }
1922
1939
  };
@@ -1939,45 +1956,37 @@ function Slider({
1939
1956
  if (dragStateRef.current !== null) {
1940
1957
  return;
1941
1958
  }
1959
+ onPress?.(event);
1960
+ if (event.defaultPrevented) {
1961
+ return;
1962
+ }
1942
1963
  const thumbPosition = currentValueRef.current * distance;
1964
+ const onThumb = event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth;
1965
+ let startValue = currentValueRef.current;
1966
+ if (!onThumb && distance > 0) {
1967
+ startValue = clampValue((event.offsetX - thumb.targetWidth / 2) / distance);
1968
+ setSliderValue(startValue);
1969
+ }
1943
1970
  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
1971
+ // The movement is measured in stage coordinates: `offsetX` is relative to the node
1972
+ // the pointer is over, which changes when the pointer leaves the track.
1973
+ startPointerX: event.clientX,
1974
+ startValue,
1975
+ pointerIdentifier: "identifier" in event ? event.identifier : void 0
1949
1976
  };
1950
1977
  setDragging(true);
1951
1978
  };
1952
1979
  const moveDragging = (event) => {
1953
1980
  const dragState = dragStateRef.current;
1954
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier || distance === 0) {
1981
+ const eventIdentifier = "identifier" in event ? event.identifier : void 0;
1982
+ if (dragState === null || dragState.pointerIdentifier !== eventIdentifier || distance === 0) {
1955
1983
  return;
1956
1984
  }
1957
1985
  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);
1986
+ setSliderValue(dragState.startValue + (event.clientX - dragState.startPointerX) / distance);
1978
1987
  };
1979
1988
  const handleTouchCancel = (event) => {
1980
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1989
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1981
1990
  endDragging(false);
1982
1991
  }
1983
1992
  };
@@ -1995,7 +2004,6 @@ function Slider({
1995
2004
  pivot: [0, 0.5],
1996
2005
  y: (track.targetHeight ?? 0) / 2
1997
2006
  },
1998
- onPress: handlePress,
1999
2007
  onMouseEnter,
2000
2008
  onMouseLeave,
2001
2009
  onMouseDown: mergeEvent(onMouseDown, startDragging),
@@ -4097,5 +4105,58 @@ function useBeforeHandleCommandCallback(callback) {
4097
4105
  }, [stage, callback]);
4098
4106
  }
4099
4107
 
4108
+ // src/hooks/useTouchInput.ts
4109
+ var import_react14 = require("react");
4110
+ var touchInput = false;
4111
+ var subscribers = /* @__PURE__ */ new Set();
4112
+ var uninstall = null;
4113
+ function setTouchInput(value) {
4114
+ if (value === touchInput) {
4115
+ return;
4116
+ }
4117
+ touchInput = value;
4118
+ for (const notify of [...subscribers]) {
4119
+ notify(value);
4120
+ }
4121
+ }
4122
+ function install() {
4123
+ if (uninstall) {
4124
+ return;
4125
+ }
4126
+ const cleanups = [
4127
+ // A touch means the device is being used by hand.
4128
+ addEventListener("touchstart", () => setTouchInput(true)),
4129
+ // Only a mouse event the engine did not produce on its own means the user reached
4130
+ // for the mouse: a tap's mouse compatibility gesture and the hover refresh a frame
4131
+ // repeats both carry `synthetic`.
4132
+ addEventListener("mousemove", (event) => {
4133
+ if (!event.synthetic) {
4134
+ setTouchInput(false);
4135
+ }
4136
+ })
4137
+ ];
4138
+ uninstall = () => {
4139
+ for (const cleanup of cleanups) {
4140
+ cleanup();
4141
+ }
4142
+ uninstall = null;
4143
+ };
4144
+ }
4145
+ function useTouchInput() {
4146
+ const [value, setValue] = (0, import_react14.useState)(touchInput);
4147
+ (0, import_react14.useEffect)(() => {
4148
+ subscribers.add(setValue);
4149
+ setValue(touchInput);
4150
+ install();
4151
+ return () => {
4152
+ subscribers.delete(setValue);
4153
+ if (subscribers.size === 0) {
4154
+ uninstall?.();
4155
+ }
4156
+ };
4157
+ }, []);
4158
+ return value;
4159
+ }
4160
+
4100
4161
  // src/lib.ts
4101
4162
  __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-WLUT_h4x.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 RetainMode, V as ScenarioCommand, X as ShaderCommand, Y as ShaderParam, Z as ShaderParamType, _ as ShaderSource, $ as ShaderTimeControl, a0 as SteamCommand, a1 as SystemCommand, a2 as TextCommand, a3 as TextLayoutEvent, a4 as TimelinePossibleClip, a5 as TouchEventKind, a6 as Tuple2, a7 as Tuple3, a8 as Tuple4, a9 as VideoCommand, aa as WheelEventDeltaMode, ab as WindowState, ac as createBubbleEvent, ad as getPlatform, ae as getStageSize, af as mergeEvent } from './jsx-dev-runtime-WLUT_h4x.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-M-Dr-KG3.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-M-Dr-KG3.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-WLUT_h4x.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 RetainMode, V as ScenarioCommand, X as ShaderCommand, Y as ShaderParam, Z as ShaderParamType, _ as ShaderSource, $ as ShaderTimeControl, a0 as SteamCommand, a1 as SystemCommand, a2 as TextCommand, a3 as TextLayoutEvent, a4 as TimelinePossibleClip, a5 as TouchEventKind, a6 as Tuple2, a7 as Tuple3, a8 as Tuple4, a9 as VideoCommand, aa as WheelEventDeltaMode, ab as WindowState, ac as createBubbleEvent, ad as getPlatform, ae as getStageSize, af as mergeEvent } from './jsx-dev-runtime-WLUT_h4x.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-M-Dr-KG3.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-M-Dr-KG3.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", {
@@ -1348,18 +1364,12 @@ function Button({
1348
1364
  setPressed(false);
1349
1365
  }),
1350
1366
  onMouseDown: mergeEvent(onMouseDown, () => setPressed(true)),
1351
- onMouseUp: mergeEvent(onMouseUp, (event) => {
1352
- if (pressed) {
1353
- onPress?.(event);
1354
- }
1367
+ onMouseUp: mergeEvent(onMouseUp, () => {
1355
1368
  setPressed(false);
1356
1369
  setHovered(true);
1357
1370
  }),
1358
1371
  onTouchStart: mergeEvent(onTouchStart, () => setPressed(true)),
1359
- onTouchEnd: mergeEvent(onTouchEnd, (event) => {
1360
- if (pressed) {
1361
- onPress?.(event);
1362
- }
1372
+ onTouchEnd: mergeEvent(onTouchEnd, () => {
1363
1373
  setPressed(false);
1364
1374
  setHovered(true);
1365
1375
  }),
@@ -1367,7 +1377,10 @@ function Button({
1367
1377
  setHovered(false);
1368
1378
  setPressed(false);
1369
1379
  }),
1370
- onClick: (event) => event.stopPropagation(),
1380
+ onClick: (event) => {
1381
+ onPress?.(event);
1382
+ event.stopPropagation();
1383
+ },
1371
1384
  children: /* @__PURE__ */ jsxs("sprite", { ...spriteProps, src: resolveControlStateValue(src, state), cursor: "pointer", children: [
1372
1385
  text !== void 0 ? /* @__PURE__ */ jsx(
1373
1386
  "text",
@@ -1903,14 +1916,18 @@ function Slider({
1903
1916
  }
1904
1917
  }, [onValueCommit]);
1905
1918
  useEffect3(() => {
1906
- const handleMouseUp = () => endDragging(true);
1919
+ const handleMouseUp = () => {
1920
+ if (dragStateRef.current?.pointerIdentifier === void 0) {
1921
+ endDragging(true);
1922
+ }
1923
+ };
1907
1924
  const handleTouchEnd = (event) => {
1908
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1925
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1909
1926
  endDragging(true);
1910
1927
  }
1911
1928
  };
1912
1929
  const handleTouchCancel2 = (event) => {
1913
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1930
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1914
1931
  endDragging(false);
1915
1932
  }
1916
1933
  };
@@ -1933,45 +1950,37 @@ function Slider({
1933
1950
  if (dragStateRef.current !== null) {
1934
1951
  return;
1935
1952
  }
1953
+ onPress?.(event);
1954
+ if (event.defaultPrevented) {
1955
+ return;
1956
+ }
1936
1957
  const thumbPosition = currentValueRef.current * distance;
1958
+ const onThumb = event.offsetX >= thumbPosition && event.offsetX <= thumbPosition + thumb.targetWidth;
1959
+ let startValue = currentValueRef.current;
1960
+ if (!onThumb && distance > 0) {
1961
+ startValue = clampValue((event.offsetX - thumb.targetWidth / 2) / distance);
1962
+ setSliderValue(startValue);
1963
+ }
1937
1964
  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
1965
+ // The movement is measured in stage coordinates: `offsetX` is relative to the node
1966
+ // the pointer is over, which changes when the pointer leaves the track.
1967
+ startPointerX: event.clientX,
1968
+ startValue,
1969
+ pointerIdentifier: "identifier" in event ? event.identifier : void 0
1943
1970
  };
1944
1971
  setDragging(true);
1945
1972
  };
1946
1973
  const moveDragging = (event) => {
1947
1974
  const dragState = dragStateRef.current;
1948
- if (dragState === null || "identifier" in event && dragState.touchIdentifier !== event.identifier || distance === 0) {
1975
+ const eventIdentifier = "identifier" in event ? event.identifier : void 0;
1976
+ if (dragState === null || dragState.pointerIdentifier !== eventIdentifier || distance === 0) {
1949
1977
  return;
1950
1978
  }
1951
1979
  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);
1980
+ setSliderValue(dragState.startValue + (event.clientX - dragState.startPointerX) / distance);
1972
1981
  };
1973
1982
  const handleTouchCancel = (event) => {
1974
- if (dragStateRef.current?.touchIdentifier === event.identifier) {
1983
+ if (dragStateRef.current?.pointerIdentifier === event.identifier) {
1975
1984
  endDragging(false);
1976
1985
  }
1977
1986
  };
@@ -1989,7 +1998,6 @@ function Slider({
1989
1998
  pivot: [0, 0.5],
1990
1999
  y: (track.targetHeight ?? 0) / 2
1991
2000
  },
1992
- onPress: handlePress,
1993
2001
  onMouseEnter,
1994
2002
  onMouseLeave,
1995
2003
  onMouseDown: mergeEvent(onMouseDown, startDragging),
@@ -4091,6 +4099,59 @@ function useBeforeHandleCommandCallback(callback) {
4091
4099
  }, [stage, callback]);
4092
4100
  }
4093
4101
 
4102
+ // src/hooks/useTouchInput.ts
4103
+ import { useEffect as useEffect8, useState as useState8 } from "react";
4104
+ var touchInput = false;
4105
+ var subscribers = /* @__PURE__ */ new Set();
4106
+ var uninstall = null;
4107
+ function setTouchInput(value) {
4108
+ if (value === touchInput) {
4109
+ return;
4110
+ }
4111
+ touchInput = value;
4112
+ for (const notify of [...subscribers]) {
4113
+ notify(value);
4114
+ }
4115
+ }
4116
+ function install() {
4117
+ if (uninstall) {
4118
+ return;
4119
+ }
4120
+ const cleanups = [
4121
+ // A touch means the device is being used by hand.
4122
+ addEventListener("touchstart", () => setTouchInput(true)),
4123
+ // Only a mouse event the engine did not produce on its own means the user reached
4124
+ // for the mouse: a tap's mouse compatibility gesture and the hover refresh a frame
4125
+ // repeats both carry `synthetic`.
4126
+ addEventListener("mousemove", (event) => {
4127
+ if (!event.synthetic) {
4128
+ setTouchInput(false);
4129
+ }
4130
+ })
4131
+ ];
4132
+ uninstall = () => {
4133
+ for (const cleanup of cleanups) {
4134
+ cleanup();
4135
+ }
4136
+ uninstall = null;
4137
+ };
4138
+ }
4139
+ function useTouchInput() {
4140
+ const [value, setValue] = useState8(touchInput);
4141
+ useEffect8(() => {
4142
+ subscribers.add(setValue);
4143
+ setValue(touchInput);
4144
+ install();
4145
+ return () => {
4146
+ subscribers.delete(setValue);
4147
+ if (subscribers.size === 0) {
4148
+ uninstall?.();
4149
+ }
4150
+ };
4151
+ }, []);
4152
+ return value;
4153
+ }
4154
+
4094
4155
  // src/lib.ts
4095
4156
  export * from "@react-spring/core";
4096
4157
  export {
@@ -4098,6 +4159,8 @@ export {
4098
4159
  Checkbox,
4099
4160
  DEBUG_EMPTY_PAGE,
4100
4161
  Input,
4162
+ MouseButton,
4163
+ MouseButtons,
4101
4164
  OverlayParamsContext,
4102
4165
  PageParamsContext,
4103
4166
  Radio,
@@ -4165,6 +4228,7 @@ export {
4165
4228
  useSkipCallback,
4166
4229
  useSoundEffect,
4167
4230
  useStageContext,
4231
+ useTouchInput,
4168
4232
  useUiData,
4169
4233
  warpState
4170
4234
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momoyu-ink/kit",
3
- "version": "0.11.2",
3
+ "version": "0.12.0",
4
4
  "description": "Software Development Kit of Moyu Visual Novel Engine",
5
5
  "main": "dist/lib.cjs",
6
6
  "module": "dist/lib.mjs",