narraleaf-react 0.1.3 → 0.1.4

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/README.md CHANGED
@@ -1,8 +1,8 @@
1
- ![](./docs/nlr-logo-banner.png)
1
+ ![](docs/nlr-logo-banner.png)
2
2
 
3
3
  # NarraLeaf-React
4
4
 
5
- English | [简体中文](./docs/README.zh-CN.md)
5
+ English | [简体中文](docs/README.zh-CN.md)
6
6
 
7
7
  A React visual novel player framework
8
8
 
@@ -34,7 +34,7 @@ Read more in [🛠React.NarraLeaf.com](https://react.narraleaf.com)
34
34
  ### Example
35
35
 
36
36
  ```bash
37
- npx create-react-app my-first-narraleaf-app --template my-first-narraleaf-app
37
+ npx create-react-app nlr-app --template my-first-narraleaf-app
38
38
  ```
39
39
 
40
40
  to start
@@ -43,39 +43,11 @@ to start
43
43
  npm start
44
44
  ```
45
45
 
46
- ### Performance
47
-
48
- Please enable image cache for a better performance.
49
- Narraleaf-React tries to cache the images before showing them, but it is recommended to enable cache on your server.
50
-
51
- for NextJS, add this to your `next.config.js`:
52
-
53
- ```js
54
- /** @type {import('next').NextConfig} */
55
- const nextConfig = {
56
- async headers() {
57
- return [
58
- {
59
- source: '/YOUR_IMAGE_ENDPOINT/(.*)', // ex: /static/images/(.*)
60
- headers: [
61
- {
62
- key: 'Cache-Control',
63
- value: 'public, max-age=31536000, immutable',
64
- },
65
- ],
66
- }
67
- ]
68
- }
69
- };
70
-
71
- export default nextConfig;
72
- ```
73
-
74
46
  ## License
75
47
 
76
48
  > NarraLeaf-React is licensed under the MPL License.
77
- >
78
- > We updated the license to MPL on 2024-9-24.
49
+ >
50
+ > We updated the license to MPL on 2024-9-24.
79
51
 
80
52
  ## Contributing
81
53
 
@@ -11,6 +11,7 @@ import type { Sound } from "../elements/sound";
11
11
  import type { Script } from "../elements/script";
12
12
  import { Sentence } from "../elements/character/sentence";
13
13
  import type { TransformDefinitions } from "../elements/transform/type";
14
+ import { Image } from "../elements/image";
14
15
  export declare const CharacterActionTypes: {
15
16
  readonly say: "character:say";
16
17
  readonly action: "character:action";
@@ -56,9 +57,10 @@ export declare const ImageActionTypes: {
56
57
  readonly setTransition: "image:setTransition";
57
58
  readonly applyTransition: "image:applyTransition";
58
59
  readonly flush: "image:flush";
60
+ readonly initWearable: "image:initWearable";
59
61
  };
60
62
  export type ImageActionContentType = {
61
- [K in typeof ImageActionTypes[keyof typeof ImageActionTypes]]: K extends "image:setSrc" ? [string] : K extends "image:setPosition" ? [CommonDisplayable["position"], Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:show" ? [void, Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:hide" ? [void, Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:applyTransform" ? [void, Transform<TransformDefinitions.ImageTransformProps>, string] : K extends "image:init" ? [Scene?] : K extends "image:dispose" ? [] : K extends "image:setTransition" ? [ITransition | null] : K extends "image:applyTransition" ? [ITransition] : K extends "image:flush" ? [] : any;
63
+ [K in typeof ImageActionTypes[keyof typeof ImageActionTypes]]: K extends "image:setSrc" ? [string] : K extends "image:setPosition" ? [CommonDisplayable["position"], Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:show" ? [void, Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:hide" ? [void, Transform<TransformDefinitions.ImageTransformProps>] : K extends "image:applyTransform" ? [void, Transform<TransformDefinitions.ImageTransformProps>, string] : K extends "image:init" ? [Scene?] : K extends "image:dispose" ? [] : K extends "image:setTransition" ? [ITransition | null] : K extends "image:applyTransition" ? [ITransition] : K extends "image:flush" ? [] : K extends "image:initWearable" ? [Image] : any;
62
64
  };
63
65
  export declare const ConditionActionTypes: {
64
66
  readonly action: "condition:action";
@@ -17,6 +17,7 @@ export declare class ImageAction<T extends typeof ImageActionTypes[keyof typeof
17
17
  readonly setTransition: "image:setTransition";
18
18
  readonly applyTransition: "image:applyTransition";
19
19
  readonly flush: "image:flush";
20
+ readonly initWearable: "image:initWearable";
20
21
  };
21
22
  executeAction(state: GameState): CalledActionResult | Awaitable<CalledActionResult, any>;
22
23
  }
@@ -2,8 +2,11 @@ import { ContentNode } from "../action/tree/actionTree";
2
2
  import { LogicAction } from "../action/logicAction";
3
3
  import { Action } from "../action/action";
4
4
  import { Chained, Proxied } from "../action/chain";
5
+ import { Awaitable } from "../../../util/data";
6
+ import { CalledActionResult } from "../gameTypes";
5
7
  export declare class TypedAction<ContentType extends Record<string, any> = Record<string, any>, T extends keyof ContentType & string = keyof ContentType & string, Callee extends LogicAction.GameElement = LogicAction.GameElement> extends Action<ContentType[T], Callee, T> {
6
8
  callee: Callee;
7
9
  constructor(callee: Proxied<Callee, Chained<LogicAction.Actions, Callee>>, type: T, contentNode: ContentNode<ContentType[T]>);
8
10
  unknownType(): void;
11
+ resolveAwaitable<T extends CalledActionResult = any>(handler: (resolve: ((value: T) => void), awaitable: Awaitable<CalledActionResult, T>) => Promise<void> | void, awaitable?: Awaitable<CalledActionResult, T>): Awaitable<CalledActionResult, T>;
9
12
  }
@@ -22,7 +22,7 @@ import { ControlAction } from "../action/actions/controlAction";
22
22
  import { Text } from "../elements/text";
23
23
  import { TextAction } from "../action/actions/textAction";
24
24
  export declare namespace LogicAction {
25
- type Displayable = Text;
25
+ type Displayable = Text | Image;
26
26
  type GameElement = Character | Scene | Story | Image | Condition | Script | Menu | Sound | Control | Text;
27
27
  type Actions = (TypedAction | CharacterAction | ConditionAction | ImageAction | SceneAction | ScriptAction | StoryAction | MenuAction | SoundAction | ControlAction | TextAction);
28
28
  type ActionTypes = Values<typeof CharacterActionTypes> | Values<typeof ConditionActionTypes> | Values<typeof ImageActionTypes> | Values<typeof SceneActionTypes> | Values<typeof ScriptActionTypes> | Values<typeof StoryActionTypes> | Values<typeof MenuActionTypes> | Values<typeof SoundAction.ActionTypes> | Values<typeof ControlAction.ActionTypes> | Values<typeof TextAction.ActionTypes>;
@@ -1,4 +1,3 @@
1
- import React from "react";
2
1
  import type { TransformDefinitions } from "../elements/transform/type";
3
2
  import { Actionable } from "../action/actionable";
4
3
  import { Transform } from "./transform/transform";
@@ -11,25 +10,21 @@ export type ImageConfig = {
11
10
  src: string | StaticImageData;
12
11
  display: boolean;
13
12
  disposed?: boolean;
13
+ wearables: Image[];
14
+ isWearable?: boolean;
14
15
  } & CommonDisplayable;
15
16
  export type ImageDataRaw = {
16
17
  state: Record<string, any>;
17
18
  };
18
19
  export type ImageEventTypes = {
19
- "event:image.init": [];
20
- "event:image.mount": [];
21
- "event:image.unmount": [];
22
- "event:image.ready": [React.MutableRefObject<HTMLDivElement | null>];
23
- "event:image.elementLoaded": [];
24
- "event:image.flush": [];
25
- "event:image.flushComponent": [];
26
20
  "event:displayable.applyTransition": [ITransition];
27
21
  "event:displayable.applyTransform": [Transform];
28
22
  "event:displayable.init": [];
23
+ "event:wearable.create": [Image];
29
24
  };
30
25
  export declare class Image extends Actionable<ImageDataRaw, Image> implements EventfulDisplayable {
31
- constructor(name: string, config: DeepPartial<ImageConfig>);
32
- constructor(config: DeepPartial<ImageConfig>);
26
+ constructor(name: string, config: Partial<ImageConfig>);
27
+ constructor(config?: DeepPartial<ImageConfig>);
33
28
  /**
34
29
  * Dispose the image
35
30
  *
@@ -109,5 +104,14 @@ export declare class Image extends Actionable<ImageDataRaw, Image> implements Ev
109
104
  hide(): Proxied<Image, Chained<LogicAction.Actions>>;
110
105
  hide(transform: Transform<TransformDefinitions.ImageTransformProps>): Proxied<Image, Chained<LogicAction.Actions>>;
111
106
  hide(transform: Partial<TransformDefinitions.CommonTransformProps>): Proxied<Image, Chained<LogicAction.Actions>>;
107
+ /**
108
+ * Add a wearable to the image
109
+ * @param children - Wearable image or images
110
+ */
111
+ addWearable(children: Image | Image[]): this;
112
+ /**
113
+ * Bind this image to a parent image as a wearable
114
+ */
115
+ bindWearable(parent: Image): this;
112
116
  copy(): Image;
113
117
  }
@@ -1,6 +1,6 @@
1
1
  import { Constructable } from "../action/constructable";
2
2
  import { Awaitable } from "../../../util/data";
3
- import { Background, EventfulDisplayable, ImageColor, ImageSrc } from "../types";
3
+ import { color, EventfulDisplayable, ImageColor, ImageSrc, StaticImageData } from "../types";
4
4
  import { LogicAction } from "../action/logicAction";
5
5
  import { Transform } from "../elements/transform/transform";
6
6
  import { IImageTransition, ITransition } from "../elements/transition/type";
@@ -38,7 +38,7 @@ type ChainedScene = Proxied<Scene, Chained<LogicAction.Actions>>;
38
38
  export type SceneDataRaw = {
39
39
  state: {
40
40
  backgroundMusic?: SoundDataRaw | null;
41
- background?: Background["background"];
41
+ background?: color | StaticImageData | null;
42
42
  };
43
43
  backgroundImageState?: ImageDataRaw | null;
44
44
  };
@@ -22,6 +22,9 @@ export interface SavedGame {
22
22
  }
23
23
  export type GameConfig = {
24
24
  player: {
25
+ /**
26
+ * The id of the container element for the game
27
+ */
25
28
  contentContainerId: string;
26
29
  /**
27
30
  * The aspect ratio of the game
@@ -38,10 +41,14 @@ export type GameConfig = {
38
41
  minHeight: number;
39
42
  /**
40
43
  * Base width of the player in pixels, Image scale will be calculated based on this value
44
+ *
45
+ * For 16/9, recommended value is 1920
41
46
  */
42
47
  width: number;
43
48
  /**
44
49
  * Base height of the player in pixels, Image scale will be calculated based on this value
50
+ *
51
+ * For 16/9, recommended value is 1080
45
52
  */
46
53
  height: number;
47
54
  /**
@@ -89,25 +96,47 @@ export type GameConfig = {
89
96
  */
90
97
  slowLoadWarning: boolean;
91
98
  slowLoadThreshold: number;
99
+ /**
100
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the image transform
101
+ */
92
102
  allowSkipTransform: boolean;
103
+ /**
104
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the image transition
105
+ */
93
106
  allowSkipTransition: boolean;
94
107
  };
95
108
  menu: {
96
109
  use: MenuComponent;
97
110
  };
98
111
  background: {
112
+ /**
113
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the background transform
114
+ */
99
115
  allowSkipTransform: boolean;
116
+ /**
117
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the background transition
118
+ */
100
119
  allowSkipTransition: boolean;
101
120
  };
102
121
  text: {
122
+ /**
123
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the text transform
124
+ */
103
125
  allowSkipTransform: boolean;
126
+ /**
127
+ * If true, when you press [GameConfig.player.skipKey], the game will skip the text transition
128
+ */
104
129
  allowSkipTransition: boolean;
105
130
  /**
106
131
  * Base width of the dialog in pixels
132
+ *
133
+ * For 16/9, recommended value is 1920
107
134
  */
108
135
  width: number;
109
136
  /**
110
137
  * Base height of the dialog in pixels
138
+ *
139
+ * For 16/9, recommended value is 1080 * 0.2
111
140
  */
112
141
  height: number;
113
142
  };
@@ -157,6 +186,9 @@ export type GameConfig = {
157
186
  debug: boolean;
158
187
  trace: boolean;
159
188
  };
189
+ /**
190
+ * If true, the game will show the inspector when you hover over the element
191
+ */
160
192
  inspector: boolean;
161
193
  };
162
194
  };
@@ -0,0 +1,4 @@
1
+ import React from "react";
2
+ export default function SizeUpdateAnnouncer({ containerRef }: Readonly<{
3
+ containerRef: React.RefObject<HTMLDivElement>;
4
+ }>): null;
@@ -16,7 +16,6 @@ import { Text, TextEventTypes } from "../nlcore/elements/text";
16
16
  type PlayerStateElement = {
17
17
  texts: Clickable<TextElement>[];
18
18
  menus: Clickable<MenuElement, Choice>[];
19
- images: Image[];
20
19
  displayable: LogicAction.Displayable[];
21
20
  };
22
21
  export type PlayerState = {
@@ -31,7 +30,7 @@ export type PlayerStateData = {
31
30
  scenes: {
32
31
  sceneId: string;
33
32
  elements: {
34
- images: string[];
33
+ displayable: string[];
35
34
  };
36
35
  }[];
37
36
  };
@@ -65,10 +64,6 @@ export declare class GameState {
65
64
  scene: Scene;
66
65
  ele: PlayerStateElement;
67
66
  } | null;
68
- findElementByImage(image: Image): {
69
- scene: Scene;
70
- ele: PlayerStateElement;
71
- } | null;
72
67
  findElementByDisplayable(displayable: LogicAction.Displayable): {
73
68
  scene: Scene;
74
69
  ele: PlayerStateElement;
@@ -87,6 +82,7 @@ export declare class GameState {
87
82
  createText(id: string, sentence: Sentence, afterClick?: () => void, scene?: Scene): void;
88
83
  createMenu(menu: MenuData, afterChoose?: (choice: Choice) => void, scene?: Scene): void;
89
84
  createImage(image: Image, scene?: Scene): this;
85
+ createWearable(parent: Image, image: Image): Promise<any>;
90
86
  disposeImage(image: Image, scene?: Scene): this;
91
87
  createDisplayable(displayable: LogicAction.Displayable, scene?: Scene): this;
92
88
  disposeDisplayable(displayable: LogicAction.Displayable, scene?: Scene): this;
@@ -23,6 +23,6 @@ export declare class ErrorBoundary extends React.Component<ErrorBoundaryProps, E
23
23
  errorInfo: null;
24
24
  };
25
25
  componentDidCatch(error: Error, errorInfo: ErrorInfo): void;
26
- render(): string | number | boolean | React.JSX.Element | Iterable<React.ReactNode> | null | undefined;
26
+ render(): string | number | boolean | Iterable<React.ReactNode> | React.JSX.Element | null | undefined;
27
27
  }
28
28
  export {};
@@ -12,6 +12,7 @@ type AspectRatioEvents = {
12
12
  "event:aspectRatio.update": [width: number, height: number];
13
13
  "event:aspectRatio.pause": [];
14
14
  "event:aspectRatio.resume": [];
15
+ "event:aspectRatio.requestUpdate": [];
15
16
  };
16
17
  declare class AspectRatio {
17
18
  static EventTypes: {
@@ -37,6 +38,8 @@ declare class AspectRatio {
37
38
  pause(): void;
38
39
  resume(): void;
39
40
  onUpdate(callback: (width: number, height: number) => void): () => void;
41
+ requestUpdate(): void;
42
+ onRequestedUpdate(callback: () => void): () => void;
40
43
  private triggerUpdate;
41
44
  }
42
45
  export declare function RatioProvider({ children }: {