narraleaf-react 0.6.0 → 0.7.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.
@@ -5,4 +5,4 @@ export * from "./player";
5
5
  export * from "./types";
6
6
  export * from "./position";
7
7
  export * from "./transition";
8
- export { i, c, b, };
8
+ export { i, c, b };
@@ -4,5 +4,6 @@ import { Storable, Namespace } from "../elements/persistent/storable";
4
4
  import { LiveGame } from "../game/liveGame";
5
5
  import { Preference } from "../game/preference";
6
6
  import type { SavedGame } from "../gameTypes";
7
- export { LiveGame, GameState, Game, Storable, Namespace, Preference, };
7
+ import { KeyMap } from "../game/keyMap";
8
+ export { LiveGame, GameState, Game, Storable, Namespace, Preference, KeyMap, };
8
9
  export type { SavedGame, };
@@ -2,6 +2,8 @@ import Player from "../../player/elements/Player";
2
2
  import GameProviders from "../../player/provider/providers";
3
3
  import { useGame } from "../../../game/player/provider/game-state";
4
4
  import { useRouter } from "../../player/lib/PageRouter/router";
5
+ import { usePathname, useParams, useQueryParams } from "../../player/lib/PageRouter/routerHooks";
5
6
  export * from "../../player/type";
6
7
  export * from "../../player/libElements";
7
- export { GameProviders, Player, useGame, useRouter, };
8
+ export { GameProviders, Player, useGame, useRouter, usePathname, useParams, useQueryParams, };
9
+ export { PresenceContext } from "motion/react";
@@ -5,5 +5,9 @@ import { IGamePluginRegistry } from "../game/plugin/plugin";
5
5
  import { LiveGameEventToken } from "../types";
6
6
  import { GameHistory } from "../action/gameHistory";
7
7
  import { GameConfig, SavedGame, NotificationToken, SavedGameMetaData } from "../gameTypes";
8
+ import type { LayoutRouter } from "../../../game/player/lib/PageRouter/router";
9
+ import { KeyBindingType, WebKeyboardKey } from "../game/types";
10
+ import { KeyBindingValue } from "../game/keyMap";
8
11
  export * from "../elements/type";
9
- export type { GameHistory, IGamePluginRegistry, LiveGameEventToken, Origins, ServiceHandlerCtx, TransformDefinitions, GameConfig, SavedGame, NotificationToken, SavedGameMetaData, };
12
+ export type { GameHistory, IGamePluginRegistry, LiveGameEventToken, Origins, ServiceHandlerCtx, TransformDefinitions, GameConfig, SavedGame, NotificationToken, SavedGameMetaData, LayoutRouter, KeyBindingValue, WebKeyboardKey, };
13
+ export { KeyBindingType, };
@@ -0,0 +1,82 @@
1
+ import { EventDispatcher } from "../../../util/data";
2
+ import { KeyBindingType, WebKeyboardKey } from "./types";
3
+ export type KeyBindingValue = WebKeyboardKey[] | WebKeyboardKey | null;
4
+ export declare class KeyMap {
5
+ private keyMap;
6
+ readonly events: EventDispatcher<{
7
+ "event:keyMap.change": [KeyBindingType | string, KeyBindingValue];
8
+ }>;
9
+ constructor(keyMap?: Record<KeyBindingType | string, KeyBindingValue>);
10
+ /**
11
+ * Set a key binding (case-insensitive)
12
+ * @param type - The type of key binding
13
+ * @param value - The value of the key binding
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * // Set the skip action to the space key
18
+ * game.keyMap.setKeyBinding(KeyBindingType.skipAction, " ");
19
+ *
20
+ * // Press either Control or F3 to skip the action
21
+ * game.keyMap.setKeyBinding(KeyBindingType.skipAction, ["Control", "F3"]);
22
+ *
23
+ * // Remove the key binding
24
+ * game.keyMap.setKeyBinding(KeyBindingType.skipAction, null);
25
+ * ```
26
+ */
27
+ setKeyBinding(type: KeyBindingType | string, value: KeyBindingValue): void;
28
+ /**
29
+ * Get a key binding
30
+ * @param type - The type of key binding
31
+ * @returns The value of the key binding
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * const skipKeyBinding = game.keyMap.getKeyBinding(KeyBindingType.skipAction);
36
+ * // ["Control"]
37
+ * ```
38
+ */
39
+ getKeyBinding(type: KeyBindingType | string): KeyBindingValue;
40
+ /**
41
+ * Add a key binding (case-insensitive)
42
+ * @param type - The type of key binding
43
+ * @param value - The value of the key binding
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * game.keyMap.addKeyBinding(KeyBindingType.skipAction, "F3");
48
+ * // Now you can press F3 to skip the action
49
+ *
50
+ * // equivalent to
51
+ * const currentKeyBinding = game.keyMap.getKeyBinding(KeyBindingType.skipAction);
52
+ * game.keyMap.setKeyBinding(
53
+ * KeyBindingType.skipAction,
54
+ * [
55
+ * ...(Array.isArray(currentKeyBinding) ? currentKeyBinding :
56
+ * currentKeyBinding !== null ? [currentKeyBinding] : []),
57
+ * "F3"
58
+ * ]
59
+ * );
60
+ * ```
61
+ */
62
+ addKeyBinding(type: KeyBindingType | string, value: KeyBindingValue): void;
63
+ getKeyBindings(): Record<KeyBindingType | string, KeyBindingValue>;
64
+ onKeyBindingChange(type: KeyBindingType | string, listener: (value: KeyBindingValue) => void): import("../../../util/data").EventToken<import("../../../util/data").EventTypes>;
65
+ importKeyBindings(keyBindings: Record<KeyBindingType | string, KeyBindingValue>): void;
66
+ exportKeyBindings(): Record<KeyBindingType | string, KeyBindingValue>;
67
+ /**
68
+ * Check if a key matches a key binding (case-insensitive)
69
+ * @param type - The type of key binding
70
+ * @param key - The key to check
71
+ * @returns True if the key matches the key binding, false otherwise
72
+ *
73
+ * @example
74
+ * ```ts
75
+ * // if the skip action is set to [" ", "F3"]
76
+ * game.keyMap.match(KeyBindingType.skipAction, " "); // true
77
+ * game.keyMap.match(KeyBindingType.skipAction, "F3"); // true
78
+ * game.keyMap.match(KeyBindingType.skipAction, "A"); // false
79
+ * ```
80
+ */
81
+ match(type: KeyBindingType | string, key: WebKeyboardKey): boolean;
82
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * See [Key_Values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
3
+ *
4
+ * Case-insensitive
5
+ */
6
+ export type WebKeyboardKey = string;
7
+ export declare enum KeyBindingType {
8
+ /**
9
+ * When the player presses one of these keys, the game will show the next sentence
10
+ *
11
+ * See [Key_Values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
12
+ * @default [" "]
13
+ */
14
+ skipAction = "skipAction",
15
+ /**
16
+ * When the player presses one of these keys, the game will skip the current action
17
+ *
18
+ * See [Key_Values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
19
+ * @default ["Control"]
20
+ */
21
+ nextAction = "nextAction"
22
+ }
@@ -4,6 +4,8 @@ import { LogicAction } from "./action/logicAction";
4
4
  import { LiveGame } from "./game/liveGame";
5
5
  import { Preference } from "./game/preference";
6
6
  import { Plugins, IGamePluginRegistry } from "./game/plugin/plugin";
7
+ import { LayoutRouter } from "../player/lib/PageRouter/router";
8
+ import { KeyMap } from "./game/keyMap";
7
9
  declare enum GameSettingsNamespace {
8
10
  game = "game"
9
11
  }
@@ -31,10 +33,15 @@ export declare class Game {
31
33
  * Game settings
32
34
  */
33
35
  preference: Preference<GamePreference>;
36
+ /**
37
+ * Game key bindings
38
+ */
39
+ keyMap: KeyMap;
34
40
  /**
35
41
  * Plugin registry
36
42
  */
37
43
  plugins: Plugins;
44
+ router: LayoutRouter;
38
45
  /**
39
46
  * Create a new game
40
47
  * @param config - Game configuration
@@ -87,13 +87,6 @@ export type GameConfig = {
87
87
  * @default 1080
88
88
  */
89
89
  height: number;
90
- /**
91
- * When the player presses one of these keys, the game will skip the current action
92
- *
93
- * See [Key_Values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
94
- * @default ["Control"]
95
- */
96
- skipKey: React.KeyboardEvent["key"][];
97
90
  /**
98
91
  * If true, the game will listen to the window events instead of the player element
99
92
  *
@@ -173,13 +166,6 @@ export type GameConfig = {
173
166
  * @default 1
174
167
  */
175
168
  screenshotQuality: number;
176
- /**
177
- * When the player presses one of these keys, the game will show the next sentence
178
- *
179
- * See [Key_Values](https://developer.mozilla.org/en-US/docs/Web/API/KeyboardEvent/key/Key_Values)
180
- * @default [" "]
181
- */
182
- nextKey: React.KeyboardEvent["key"][];
183
169
  /**
184
170
  * If true, the game will scale the dialog to fit the screen
185
171
  *
@@ -231,6 +217,13 @@ export type GameConfig = {
231
217
  * @default true
232
218
  */
233
219
  allowSkipTextTransition: boolean;
220
+ /**
221
+ * If true, the animation will propagate to the children
222
+ *
223
+ * This behavior is controlled by [motion](https://motion.dev): `When true, exit animations will be propagated to nested AnimatePresence components.`
224
+ * @default true
225
+ */
226
+ animationPropagate: boolean;
234
227
  /**
235
228
  * Base width of the dialog in pixels
236
229
  *
@@ -1,4 +1,4 @@
1
1
  import "client-only";
2
2
  import { PlayerProps } from "../elements/type";
3
3
  import React from "react";
4
- export default function Player({ story, width, height, className, onReady, onEnd, children, active, }: Readonly<PlayerProps>): React.JSX.Element;
4
+ export default function Player({ story, width, height, className, onReady, onEnd, onError, children, active, }: Readonly<PlayerProps>): React.JSX.Element;
@@ -1,4 +1,4 @@
1
- import React from "react";
1
+ import React, { ErrorInfo } from "react";
2
2
  import { IDialogProps, SayElementProps } from "../elements/say/type";
3
3
  import { IUserMenuProps, MenuElementProps } from "../elements/menu/type";
4
4
  import { Story } from "../../nlcore/elements/story";
@@ -41,6 +41,12 @@ export interface PlayerProps {
41
41
  * only called each lifecycle once
42
42
  */
43
43
  onEnd?: (ctx: PlayerEventContext) => void;
44
+ /**
45
+ * Once the game encounters an error
46
+ *
47
+ * only called each lifecycle once
48
+ */
49
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
44
50
  children?: React.ReactNode;
45
51
  /**
46
52
  * Whether to show the player
@@ -24,7 +24,6 @@ import { Timelines } from "./Tasks";
24
24
  import { Notification, NotificationManager } from "./lib/notification";
25
25
  import { ActionHistoryManager } from "../../game/nlcore/action/actionHistory";
26
26
  import { GameHistoryManager } from "../../game/nlcore/action/gameHistory";
27
- import { Router } from "./lib/PageRouter/router";
28
27
  type Legacy_PlayerStateElement = {
29
28
  texts: Clickable<TextElement>[];
30
29
  menus: Clickable<MenuElement, Chosen>[];
@@ -105,7 +104,7 @@ export declare class GameState {
105
104
  readonly idManager: IdManager;
106
105
  readonly actionHistory: ActionHistoryManager;
107
106
  readonly gameHistory: GameHistoryManager;
108
- pageRouter: Router | null;
107
+ pageRouter: null;
109
108
  constructor(game: Game, stage: StageUtils);
110
109
  get deps(): number;
111
110
  addVideo(video: Video): this;
@@ -1,6 +1,7 @@
1
1
  import React, { ErrorInfo, ReactNode } from "react";
2
2
  interface ErrorBoundaryProps {
3
3
  children: ReactNode;
4
+ onError?: (error: Error, errorInfo: ErrorInfo) => void;
4
5
  }
5
6
  interface ErrorBoundaryState {
6
7
  hasError: boolean;
@@ -1,4 +1,5 @@
1
1
  import { FirstParam } from "../../../../util/data";
2
- import { AnimatePresence } from "motion/react";
3
2
  import { JSX } from "react";
4
- export type AnimatePresenceComponent = (arg0: FirstParam<typeof AnimatePresence>) => JSX.Element;
3
+ import { AnimatePresence as OriginalAnimatePresence } from "motion/react";
4
+ export type AnimatePresenceComponent = (arg0: FirstParam<typeof OriginalAnimatePresence>) => JSX.Element;
5
+ export declare const AnimatePresence: AnimatePresenceComponent;
@@ -0,0 +1,48 @@
1
+ import React from "react";
2
+ import { LayoutRouter } from "./router";
3
+ type LayoutContextType = {
4
+ router: LayoutRouter;
5
+ path: string | null;
6
+ consumedBy?: string;
7
+ };
8
+ type LayoutContextProviderProps = {
9
+ children: React.ReactNode;
10
+ path: string | null;
11
+ consumedBy?: string;
12
+ };
13
+ export declare function LayoutRouterProvider({ children, path, consumedBy }: LayoutContextProviderProps): React.JSX.Element;
14
+ export declare function useLayout(): Omit<LayoutContextType, "path"> & {
15
+ path: string;
16
+ };
17
+ export type LayoutProps = {
18
+ children: React.ReactNode;
19
+ /**
20
+ * The relative path of the layout. It can be a path or a path pattern.
21
+ *
22
+ * @example
23
+ * ```typescript
24
+ * // Can be navigated to by "/home"
25
+ * <Layout name="home">
26
+ * <div>Home</div>
27
+ * </Layout>
28
+ *
29
+ * <Layout name="user">
30
+ * // equivalent to "/user/:id"
31
+ * // Can be navigated to by "/user/123"
32
+ * <Layout name=":id">
33
+ * <div>User</div>
34
+ * </Layout>
35
+ * </Layout>
36
+ * ```
37
+ */
38
+ name: string;
39
+ /**
40
+ * When true, exit animations will be propagated to nested AnimatePresence components.
41
+ */
42
+ propagate?: boolean;
43
+ };
44
+ export declare function Layout({ children, name, propagate }: LayoutProps): React.JSX.Element;
45
+ export declare function RootLayout({ children }: {
46
+ children: React.ReactNode;
47
+ }): React.JSX.Element;
48
+ export {};
@@ -1,9 +1,46 @@
1
1
  import React from "react";
2
- import { HTMLMotionProps } from "motion/react";
3
2
  export type PageProps = Readonly<{
4
- id: string;
5
3
  children?: React.ReactNode;
6
- className?: string;
7
- style?: React.CSSProperties;
8
- } & HTMLMotionProps<"div">>;
9
- export declare function Page({ id, children, className, style, ...motionProps }: PageProps): React.JSX.Element;
4
+ /**
5
+ * The name of the page. It can be a dynamic string, null, or undefined.
6
+ *
7
+ * If name is null or undefined, this page becomes the default handler for its parent layout.
8
+ * It will be rendered whenever the parent layout matches and no specific page name matches.
9
+ *
10
+ * @example
11
+ * <Page name="home">
12
+ * // Can be navigated to by "/home"
13
+ * <div>Home</div>
14
+ * </Page>
15
+ *
16
+ * <Layout path="user">
17
+ * <Page name="profile">
18
+ * // Can be navigated to by "/user/profile"
19
+ * <div>User Profile</div>
20
+ * </Page>
21
+ *
22
+ * <Page name={null}>
23
+ * // Default handler for "/user" - renders when no specific page matches
24
+ * <div>User Default Page</div>
25
+ * </Page>
26
+ * </Layout>
27
+ *
28
+ * <Layout path="user">
29
+ * <Layout path=":id">
30
+ * <Page name="profile">
31
+ * // Can be navigated to by "/user/123/profile"
32
+ * <div>User Profile</div>
33
+ * </Page>
34
+ * </Layout>
35
+ * </Layout>
36
+ * ```
37
+ */
38
+ name?: string | null;
39
+ }>;
40
+ type PageInjectContextType = {
41
+ name: string | null | undefined;
42
+ };
43
+ export declare const PageInjectContext: React.Context<PageInjectContextType | null>;
44
+ export declare function usePageInject(): PageInjectContextType | null;
45
+ export declare function Page({ children, name: nameProp }: PageProps): string | number | bigint | boolean | Iterable<React.ReactNode> | Promise<string | number | bigint | boolean | React.ReactPortal | React.ReactElement<unknown, string | React.JSXElementConstructor<any>> | Iterable<React.ReactNode> | null | undefined> | React.JSX.Element | null | undefined;
46
+ export {};