narraleaf-react 0.12.3 → 0.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,165 +1,165 @@
1
- <picture>
2
- <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-transparent.png">
3
- <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-light.png">
4
- <img alt="NarraLeaf Logo" src="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-light.png">
5
- </picture>
6
-
7
- <h1 align="center">NarraLeaf-React</h1>
8
-
9
- <h4 align="center">A React visual novel player framework</h4>
10
-
11
- <p align="center">English | <a href="docs/README.zh-CN.md">简体中文</a></p>
12
-
13
-
14
- ## What is NarraLeaf-React?
15
-
16
- NarraLeaf-React is a lightweight front-end visual novel player.
17
- NL focuses on visual novel playing, so the user interface can be customized very easily.
18
-
19
- It doesn't use any rendering libraries and can be used on any web platform (e.g. Electron)
20
-
21
- ## Why NarraLeaf-React?
22
-
23
- - **Lightweight**: NarraLeaf-React is a front-end framework, and it doesn't use any rendering libraries.
24
- - **Customizable**: You can customize the UI as you like, even replace the whole components.
25
- - **Easy to use**: It is easy to use and has a simple API that is built for developers. Based on OOP principles.
26
-
27
- ### Scripting
28
-
29
- NarraLeaf-React uses TypeScript for all scripting, so you don't have to learn a whole new language to use it.
30
-
31
- It also has a highly abstracted and easy-to-use API, for example:
32
-
33
- ```typescript
34
- import {Character, Menu, Scene, c, b} from "narraleaf-react";
35
- ```
36
-
37
- ```typescript
38
- const scene1 = new Scene("Scene1: Hello World", {
39
- background: "/link/to/background.jpg",
40
- });
41
-
42
- const jS = new Character("John Smith");
43
- const jD = new Character("John Doe");
44
-
45
- scene1.action([
46
- jS`Hello, world!`,
47
- jS`This is my first ${b("NarraLeaf")} story.`,
48
- jS`Start editing ${c("src/story.js", "#00f")} and enjoy the journey!`,
49
-
50
- jD`Also, don't forget to check out the ${c("documentation", "#00f")}!`,
51
-
52
- "By the way, the documentation is available on https://www.narraleaf.com/docs/narraleaf-react",
53
- "You can also visit the website for demo and more information.",
54
-
55
- Menu.prompt("Start the journey")
56
-
57
- .choose("Yes I will!", [
58
- jS`Great! Let's start the journey!`,
59
- jS`You can open issues on GitHub if you have any questions.`
60
- ])
61
-
62
- .choose("No, I'm going to check the documentation", [
63
- jS`Sure! Take your time!`
64
- ])
65
- ]);
66
- ```
67
-
68
- For more information, please visit the [NarraLeaf-React documentation](https://www.narraleaf.com/docs/narraleaf-react).
69
-
70
- ## Get Started
71
-
72
- ### Install
73
-
74
- ```bash
75
- npm install narraleaf-react
76
- ```
77
-
78
- ### Documentation
79
-
80
- - [Introduction](https://www.narraleaf.com/docs/narraleaf-react)
81
- - [Quick Start](https://www.narraleaf.com/docs/narraleaf-react/quick-start)
82
- - [Installation](https://www.narraleaf.com/docs/narraleaf-react/installation)
83
- - [Basic](https://www.narraleaf.com/docs/narraleaf-react/basic)
84
- - [Create a Scene](https://www.narraleaf.com/docs/narraleaf-react/basic/create-scene)
85
- - [Add Actions](https://www.narraleaf.com/docs/narraleaf-react/basic/add-actions)
86
- - [Show Dialog](https://www.narraleaf.com/docs/narraleaf-react/basic/show-dialog)
87
- - [Show Image](https://www.narraleaf.com/docs/narraleaf-react/basic/show-image)
88
- - [Play Story](https://www.narraleaf.com/docs/narraleaf-react/basic/play-story)
89
- - [Make Choices](https://www.narraleaf.com/docs/narraleaf-react/basic/make-choices)
90
- - [Play Sound](https://www.narraleaf.com/docs/narraleaf-react/basic/sound)
91
- - [Store Data](https://www.narraleaf.com/docs/narraleaf-react/basic/store-data)
92
- - [Conditional](https://www.narraleaf.com/docs/narraleaf-react/basic/conditional)
93
- - [Voice](https://www.narraleaf.com/docs/narraleaf-react/basic/voice)
94
- - [Manage Preferences](https://www.narraleaf.com/docs/narraleaf-react/basic/manage-preferences)
95
- - [Solutions](https://www.narraleaf.com/docs/narraleaf-react/solutions)
96
- - [Customizing the Font](https://www.narraleaf.com/docs/narraleaf-react/solutions/font)
97
- - [Migration from Ren'Py](https://www.narraleaf.com/docs/narraleaf-react/solutions/from-renpy)
98
- - [Quick Menu](https://www.narraleaf.com/docs/narraleaf-react/solutions/quick-menu)
99
- - [Dialog Avatar](https://www.narraleaf.com/docs/narraleaf-react/solutions/dialog-avatar)
100
- - [Custom Dialog](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-dialog)
101
- - [Custom NVL Dialog](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-nvl-dialog)
102
- - [Custom Menu](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-menu)
103
- - [Page Overlay Settings](https://www.narraleaf.com/docs/narraleaf-react/solutions/page-overlay-settings)
104
- - [Save System with localStorage](https://www.narraleaf.com/docs/narraleaf-react/solutions/save-system-localstorage)
105
- - [Custom Notification](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-notification)
106
- - [Gallery Service with localStorage](https://www.narraleaf.com/docs/narraleaf-react/solutions/gallery-service-localstorage)
107
- - [Core](https://www.narraleaf.com/docs/narraleaf-react/core)
108
- - [Elements](https://www.narraleaf.com/docs/narraleaf-react/core/elements)
109
- - [Scene](https://www.narraleaf.com/docs/narraleaf-react/core/elements/scene)
110
- - [Character](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character)
111
- - [Sentence](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/sentence)
112
- - [Word](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/word)
113
- - [Pause](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/pause)
114
- - [Image](https://www.narraleaf.com/docs/narraleaf-react/core/elements/image)
115
- - [Sound](https://www.narraleaf.com/docs/narraleaf-react/core/elements/sound)
116
- - [Menu](https://www.narraleaf.com/docs/narraleaf-react/core/elements/menu)
117
- - [Script](https://www.narraleaf.com/docs/narraleaf-react/core/elements/script)
118
- - [Condition](https://www.narraleaf.com/docs/narraleaf-react/core/elements/condition)
119
- - [Control](https://www.narraleaf.com/docs/narraleaf-react/core/elements/control)
120
- - [Text](https://www.narraleaf.com/docs/narraleaf-react/core/elements/text)
121
- - [Persistent](https://www.narraleaf.com/docs/narraleaf-react/core/elements/persistent)
122
- - [Story](https://www.narraleaf.com/docs/narraleaf-react/core/elements/story)
123
- - [Displayable](https://www.narraleaf.com/docs/narraleaf-react/core/elements/displayable)
124
- - [Layer](https://www.narraleaf.com/docs/narraleaf-react/core/elements/layer)
125
- - [Service](https://www.narraleaf.com/docs/narraleaf-react/core/elements/service)
126
- - [Video](https://www.narraleaf.com/docs/narraleaf-react/core/elements/video)
127
- - [Built-in Gallery](https://www.narraleaf.com/docs/narraleaf-react/core/elements/built-in/gallery)
128
- - [Animation](https://www.narraleaf.com/docs/narraleaf-react/core/animation)
129
- - [Transform](https://www.narraleaf.com/docs/narraleaf-react/core/animation/transform)
130
- - [Transitions](https://www.narraleaf.com/docs/narraleaf-react/core/animation/transition)
131
- - [Game](https://www.narraleaf.com/docs/narraleaf-react/core/game)
132
- - [LiveGame](https://www.narraleaf.com/docs/narraleaf-react/core/game/live-game)
133
- - [Storable](https://www.narraleaf.com/docs/narraleaf-react/core/game/storable)
134
- - [Preference](https://www.narraleaf.com/docs/narraleaf-react/core/game/preference/preference)
135
- - [Key Map](https://www.narraleaf.com/docs/narraleaf-react/core/game/key-map)
136
- - [Hooks](https://www.narraleaf.com/docs/narraleaf-react/core/game/hooks)
137
- - [Plugin](https://www.narraleaf.com/docs/narraleaf-react/core/plugin)
138
- - [Utils](https://www.narraleaf.com/docs/narraleaf-react/core/utils)
139
- - [Player](https://www.narraleaf.com/docs/narraleaf-react/player)
140
- - [Player](https://www.narraleaf.com/docs/narraleaf-react/player/player)
141
- - [FixedAspectRatioContainer](https://www.narraleaf.com/docs/narraleaf-react/player/fixed-aspect-ratio-container)
142
- - [GameProviders](https://www.narraleaf.com/docs/narraleaf-react/player/game-providers)
143
- - [Hooks](https://www.narraleaf.com/docs/narraleaf-react/player/hooks)
144
- - [LayoutRouter](https://www.narraleaf.com/docs/narraleaf-react/player/page-router)
145
- - [Dialog](https://www.narraleaf.com/docs/narraleaf-react/player/dialog)
146
- - [Notification](https://www.narraleaf.com/docs/narraleaf-react/player/notification)
147
- - [Menu](https://www.narraleaf.com/docs/narraleaf-react/player/menu)
148
- - [NvlContainer](https://www.narraleaf.com/docs/narraleaf-react/player/nvl-container)
149
- - About
150
- - [License](https://www.narraleaf.com/docs/narraleaf-react/info/license)
151
- - [Incompatible Changes](https://www.narraleaf.com/docs/narraleaf-react/info/incompatible-changes)
152
-
153
- Read more in the [NarraLeaf-React documentation](https://www.narraleaf.com/docs/narraleaf-react).
154
-
155
- ## License
156
-
157
- > NarraLeaf-React is licensed under the MPL-2.0 License.
158
- >
159
- > We updated the license to MPL-2.0 on 2024-9-24.
160
-
161
- ## Contributing
162
-
163
- We welcome all contributions.
164
- If you have any ideas, just open an issue or a pull request.
165
-
1
+ <picture>
2
+ <source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-transparent.png">
3
+ <source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-light.png">
4
+ <img alt="NarraLeaf Logo" src="https://raw.githubusercontent.com/NarraLeaf/.github/refs/heads/master/doc/banner-md-light.png">
5
+ </picture>
6
+
7
+ <h1 align="center">NarraLeaf-React</h1>
8
+
9
+ <h4 align="center">A React visual novel player framework</h4>
10
+
11
+ <p align="center">English | <a href="docs/README.zh-CN.md">简体中文</a></p>
12
+
13
+
14
+ ## What is NarraLeaf-React?
15
+
16
+ NarraLeaf-React is a lightweight front-end visual novel player.
17
+ NL focuses on visual novel playing, so the user interface can be customized very easily.
18
+
19
+ It doesn't use any rendering libraries and can be used on any web platform (e.g. Electron)
20
+
21
+ ## Why NarraLeaf-React?
22
+
23
+ - **Lightweight**: NarraLeaf-React is a front-end framework, and it doesn't use any rendering libraries.
24
+ - **Customizable**: You can customize the UI as you like, even replace the whole components.
25
+ - **Easy to use**: It is easy to use and has a simple API that is built for developers. Based on OOP principles.
26
+
27
+ ### Scripting
28
+
29
+ NarraLeaf-React uses TypeScript for all scripting, so you don't have to learn a whole new language to use it.
30
+
31
+ It also has a highly abstracted and easy-to-use API, for example:
32
+
33
+ ```typescript
34
+ import {Character, Menu, Scene, c, b} from "narraleaf-react";
35
+ ```
36
+
37
+ ```typescript
38
+ const scene1 = new Scene("Scene1: Hello World", {
39
+ background: "/link/to/background.jpg",
40
+ });
41
+
42
+ const jS = new Character("John Smith");
43
+ const jD = new Character("John Doe");
44
+
45
+ scene1.action([
46
+ jS`Hello, world!`,
47
+ jS`This is my first ${b("NarraLeaf")} story.`,
48
+ jS`Start editing ${c("src/story.js", "#00f")} and enjoy the journey!`,
49
+
50
+ jD`Also, don't forget to check out the ${c("documentation", "#00f")}!`,
51
+
52
+ "By the way, the documentation is available on https://www.narraleaf.com/docs/narraleaf-react",
53
+ "You can also visit the website for demo and more information.",
54
+
55
+ Menu.prompt("Start the journey")
56
+
57
+ .choose("Yes I will!", [
58
+ jS`Great! Let's start the journey!`,
59
+ jS`You can open issues on GitHub if you have any questions.`
60
+ ])
61
+
62
+ .choose("No, I'm going to check the documentation", [
63
+ jS`Sure! Take your time!`
64
+ ])
65
+ ]);
66
+ ```
67
+
68
+ For more information, please visit the [NarraLeaf-React documentation](https://www.narraleaf.com/docs/narraleaf-react).
69
+
70
+ ## Get Started
71
+
72
+ ### Install
73
+
74
+ ```bash
75
+ npm install narraleaf-react
76
+ ```
77
+
78
+ ### Documentation
79
+
80
+ - [Introduction](https://www.narraleaf.com/docs/narraleaf-react)
81
+ - [Quick Start](https://www.narraleaf.com/docs/narraleaf-react/quick-start)
82
+ - [Installation](https://www.narraleaf.com/docs/narraleaf-react/installation)
83
+ - [Basic](https://www.narraleaf.com/docs/narraleaf-react/basic)
84
+ - [Create a Scene](https://www.narraleaf.com/docs/narraleaf-react/basic/create-scene)
85
+ - [Add Actions](https://www.narraleaf.com/docs/narraleaf-react/basic/add-actions)
86
+ - [Show Dialog](https://www.narraleaf.com/docs/narraleaf-react/basic/show-dialog)
87
+ - [Show Image](https://www.narraleaf.com/docs/narraleaf-react/basic/show-image)
88
+ - [Play Story](https://www.narraleaf.com/docs/narraleaf-react/basic/play-story)
89
+ - [Make Choices](https://www.narraleaf.com/docs/narraleaf-react/basic/make-choices)
90
+ - [Play Sound](https://www.narraleaf.com/docs/narraleaf-react/basic/sound)
91
+ - [Store Data](https://www.narraleaf.com/docs/narraleaf-react/basic/store-data)
92
+ - [Conditional](https://www.narraleaf.com/docs/narraleaf-react/basic/conditional)
93
+ - [Voice](https://www.narraleaf.com/docs/narraleaf-react/basic/voice)
94
+ - [Manage Preferences](https://www.narraleaf.com/docs/narraleaf-react/basic/manage-preferences)
95
+ - [Solutions](https://www.narraleaf.com/docs/narraleaf-react/solutions)
96
+ - [Customizing the Font](https://www.narraleaf.com/docs/narraleaf-react/solutions/font)
97
+ - [Migration from Ren'Py](https://www.narraleaf.com/docs/narraleaf-react/solutions/from-renpy)
98
+ - [Quick Menu](https://www.narraleaf.com/docs/narraleaf-react/solutions/quick-menu)
99
+ - [Dialog Avatar](https://www.narraleaf.com/docs/narraleaf-react/solutions/dialog-avatar)
100
+ - [Custom Dialog](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-dialog)
101
+ - [Custom NVL Dialog](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-nvl-dialog)
102
+ - [Custom Menu](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-menu)
103
+ - [Page Overlay Settings](https://www.narraleaf.com/docs/narraleaf-react/solutions/page-overlay-settings)
104
+ - [Save System with localStorage](https://www.narraleaf.com/docs/narraleaf-react/solutions/save-system-localstorage)
105
+ - [Custom Notification](https://www.narraleaf.com/docs/narraleaf-react/solutions/custom-notification)
106
+ - [Gallery Service with localStorage](https://www.narraleaf.com/docs/narraleaf-react/solutions/gallery-service-localstorage)
107
+ - [Core](https://www.narraleaf.com/docs/narraleaf-react/core)
108
+ - [Elements](https://www.narraleaf.com/docs/narraleaf-react/core/elements)
109
+ - [Scene](https://www.narraleaf.com/docs/narraleaf-react/core/elements/scene)
110
+ - [Character](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character)
111
+ - [Sentence](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/sentence)
112
+ - [Word](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/word)
113
+ - [Pause](https://www.narraleaf.com/docs/narraleaf-react/core/elements/character/pause)
114
+ - [Image](https://www.narraleaf.com/docs/narraleaf-react/core/elements/image)
115
+ - [Sound](https://www.narraleaf.com/docs/narraleaf-react/core/elements/sound)
116
+ - [Menu](https://www.narraleaf.com/docs/narraleaf-react/core/elements/menu)
117
+ - [Script](https://www.narraleaf.com/docs/narraleaf-react/core/elements/script)
118
+ - [Condition](https://www.narraleaf.com/docs/narraleaf-react/core/elements/condition)
119
+ - [Control](https://www.narraleaf.com/docs/narraleaf-react/core/elements/control)
120
+ - [Text](https://www.narraleaf.com/docs/narraleaf-react/core/elements/text)
121
+ - [Persistent](https://www.narraleaf.com/docs/narraleaf-react/core/elements/persistent)
122
+ - [Story](https://www.narraleaf.com/docs/narraleaf-react/core/elements/story)
123
+ - [Displayable](https://www.narraleaf.com/docs/narraleaf-react/core/elements/displayable)
124
+ - [Layer](https://www.narraleaf.com/docs/narraleaf-react/core/elements/layer)
125
+ - [Service](https://www.narraleaf.com/docs/narraleaf-react/core/elements/service)
126
+ - [Video](https://www.narraleaf.com/docs/narraleaf-react/core/elements/video)
127
+ - [Built-in Gallery](https://www.narraleaf.com/docs/narraleaf-react/core/elements/built-in/gallery)
128
+ - [Animation](https://www.narraleaf.com/docs/narraleaf-react/core/animation)
129
+ - [Transform](https://www.narraleaf.com/docs/narraleaf-react/core/animation/transform)
130
+ - [Transitions](https://www.narraleaf.com/docs/narraleaf-react/core/animation/transition)
131
+ - [Game](https://www.narraleaf.com/docs/narraleaf-react/core/game)
132
+ - [LiveGame](https://www.narraleaf.com/docs/narraleaf-react/core/game/live-game)
133
+ - [Storable](https://www.narraleaf.com/docs/narraleaf-react/core/game/storable)
134
+ - [Preference](https://www.narraleaf.com/docs/narraleaf-react/core/game/preference/preference)
135
+ - [Key Map](https://www.narraleaf.com/docs/narraleaf-react/core/game/key-map)
136
+ - [Hooks](https://www.narraleaf.com/docs/narraleaf-react/core/game/hooks)
137
+ - [Plugin](https://www.narraleaf.com/docs/narraleaf-react/core/plugin)
138
+ - [Utils](https://www.narraleaf.com/docs/narraleaf-react/core/utils)
139
+ - [Player](https://www.narraleaf.com/docs/narraleaf-react/player)
140
+ - [Player](https://www.narraleaf.com/docs/narraleaf-react/player/player)
141
+ - [FixedAspectRatioContainer](https://www.narraleaf.com/docs/narraleaf-react/player/fixed-aspect-ratio-container)
142
+ - [GameProviders](https://www.narraleaf.com/docs/narraleaf-react/player/game-providers)
143
+ - [Hooks](https://www.narraleaf.com/docs/narraleaf-react/player/hooks)
144
+ - [LayoutRouter](https://www.narraleaf.com/docs/narraleaf-react/player/page-router)
145
+ - [Dialog](https://www.narraleaf.com/docs/narraleaf-react/player/dialog)
146
+ - [Notification](https://www.narraleaf.com/docs/narraleaf-react/player/notification)
147
+ - [Menu](https://www.narraleaf.com/docs/narraleaf-react/player/menu)
148
+ - [NvlContainer](https://www.narraleaf.com/docs/narraleaf-react/player/nvl-container)
149
+ - About
150
+ - [License](https://www.narraleaf.com/docs/narraleaf-react/info/license)
151
+ - [Incompatible Changes](https://www.narraleaf.com/docs/narraleaf-react/info/incompatible-changes)
152
+
153
+ Read more in the [NarraLeaf-React documentation](https://www.narraleaf.com/docs/narraleaf-react).
154
+
155
+ ## License
156
+
157
+ > NarraLeaf-React is licensed under the MPL-2.0 License.
158
+ >
159
+ > We updated the license to MPL-2.0 on 2024-9-24.
160
+
161
+ ## Contributing
162
+
163
+ We welcome all contributions.
164
+ If you have any ideas, just open an issue or a pull request.
165
+
@@ -18,5 +18,6 @@ import { Layer } from "../elements/layer";
18
18
  import { Video } from "../elements/video";
19
19
  import { NVLToken } from "../elements/nvl";
20
20
  export { Character, Narrator, Condition, Control, Image, Lambda, Menu, NVLToken, Scene, Script, Sentence, Sound, Story, Transform, Word, Text, Pause, Persistent, Service, Layer, Video, };
21
+ export type { LayeredDefinition, LayerGroupDefinition, LayerResolver, LayerSlot, LayerTagsOf, LayerVariants, } from "../elements/displayable/image";
21
22
  export type { SentenceMetadata } from "../elements/character/sentence";
22
23
  export type { CharacterPortraitConfig, DialogAvatar, DialogAvatarResolver, DialogAvatarResolverContext, DialogAvatarResolution, DialogAvatarSource, } from "../elements/character/avatar";
@@ -14,7 +14,7 @@ export type TagDefinitionObject<T extends TagGroupDefinition> = {
14
14
  resolve: TagSrcResolver<T>;
15
15
  };
16
16
  type ImageSrcType<T extends TagGroupDefinition | null = TagGroupDefinition | null> = T extends TagGroupDefinition ? TagDefinition<T> : (Color | ImageSrc);
17
- export interface IImageUserConfig<Tag extends TagGroupDefinition | null = TagGroupDefinition | null> extends TransformDefinitions.ImageTransformProps {
17
+ export interface IImageUserConfig<Tag extends TagGroupDefinition | null = TagGroupDefinition | null, Layers extends LayerGroupDefinition = LayerGroupDefinition> extends TransformDefinitions.ImageTransformProps {
18
18
  /**
19
19
  * The name of the image, only for debugging purposes
20
20
  */
@@ -27,7 +27,7 @@ export interface IImageUserConfig<Tag extends TagGroupDefinition | null = TagGro
27
27
  /**
28
28
  * Image Src, see [Image](https://react.narraleaf.com/documentation/core/elements/image) for more information
29
29
  */
30
- src: ImageSrcType<Tag>;
30
+ src: ImageSrcType<Tag> | LayeredDefinition<Layers>;
31
31
  /**
32
32
  * Auto resize image's width to fit the screen
33
33
  * @default false
@@ -45,7 +45,40 @@ export interface IImageUserConfig<Tag extends TagGroupDefinition | null = TagGro
45
45
  }
46
46
  export type TagGroupDefinition = string[][];
47
47
  export type TagSrcResolver<T extends TagGroupDefinition> = (...tags: SelectElementFromEach<T>) => string;
48
- export declare class Image<Tags extends TagGroupDefinition | null = TagGroupDefinition | null> extends Displayable<ImageDataRaw, Image, TransformDefinitions.ImageTransformProps> implements EventfulDisplayable {
48
+ /**
49
+ * A set of mutually exclusive variants for one layer, keyed by tag.
50
+ *
51
+ * `null` means the layer draws nothing for that tag.
52
+ */
53
+ export type LayerVariants = Record<string, string | null>;
54
+ /**
55
+ * Derives a layer's src from the currently active tags. Declares no tags of its own.
56
+ */
57
+ export type LayerResolver = (tags: ReadonlySet<string>) => string | null;
58
+ /**
59
+ * One slot of a layered image, from bottom to top. Either a constant src, `null`,
60
+ * a {@link LayerVariants} map, or a {@link LayerResolver}.
61
+ */
62
+ export type LayerSlot = string | null | LayerVariants | LayerResolver;
63
+ export type LayerGroupDefinition = readonly LayerSlot[];
64
+ /**
65
+ * The union of every tag declared by a layer stack.
66
+ */
67
+ export type LayerTagsOf<L> = L extends readonly (infer E)[] ? (E extends LayerResolver ? never : E extends LayerVariants ? keyof E & string : never) : never;
68
+ /**
69
+ * Layered image src, see [Image](https://react.narraleaf.com/documentation/core/elements/image).
70
+ */
71
+ export type LayeredDefinition<L extends LayerGroupDefinition = LayerGroupDefinition> = {
72
+ /**
73
+ * The layer stack, from bottom to top. Array order is the stacking order.
74
+ */
75
+ layers: L;
76
+ /**
77
+ * One tag per variant layer, in any order.
78
+ */
79
+ defaults: readonly LayerTagsOf<L>[];
80
+ };
81
+ export declare class Image<Tags extends TagGroupDefinition | null = TagGroupDefinition | null, const Layers extends LayerGroupDefinition = LayerGroupDefinition> extends Displayable<ImageDataRaw, Image, TransformDefinitions.ImageTransformProps> implements EventfulDisplayable {
49
82
  /**
50
83
  * Construct an image element. The config can describe either static sources or tagged outfits, but not both.
51
84
  * @param config - Image metadata such as tags, source, layer, and wearables.
@@ -53,14 +86,17 @@ export declare class Image<Tags extends TagGroupDefinition | null = TagGroupDefi
53
86
  * ```ts
54
87
  * const image = new Image({
55
88
  * src: {
56
- * groups: [["happy", "sad"], ["top", "coat"]],
57
- * defaults: ["happy", "top"],
58
- * resolve: (emotion, top) => `https://img/${emotion}_${top}.png`
89
+ * layers: [
90
+ * "body.png",
91
+ * {happy: "happy.png", sad: "sad.png"},
92
+ * {shirt: "shirt.png", coat: "coat.png"},
93
+ * ],
94
+ * defaults: ["happy", "shirt"],
59
95
  * }
60
96
  * });
61
97
  * ```
62
98
  */
63
- constructor(config?: Partial<IImageUserConfig<Tags>>);
99
+ constructor(config?: Partial<IImageUserConfig<Tags, Layers>>);
64
100
  /**
65
101
  * Set the source of the image
66
102
  *
@@ -78,6 +114,7 @@ export declare class Image<Tags extends TagGroupDefinition | null = TagGroupDefi
78
114
  */
79
115
  char(src: ImageSrc | Color, transition?: ImageTransition): Proxied<Image, Chained<LogicAction.Actions>>;
80
116
  char(tags: SelectElementFromEach<Tags> | FlexibleTuple<SelectElementFromEach<Tags>>, transition?: ImageTransition): Proxied<Image, Chained<LogicAction.Actions>>;
117
+ char(tags: LayerTagsOf<Layers>[], transition?: ImageTransition): Proxied<Image, Chained<LogicAction.Actions>>;
81
118
  /**
82
119
  * Set the darkness of the image
83
120
  * @param darkness - The darkness of the image, between 0 and 1
@@ -2,3 +2,20 @@ export type StorableData<K extends string = string> = {
2
2
  [key in K]: number | boolean | string | StorableData | StorableData[] | undefined | null | Date;
3
3
  };
4
4
  export type StorableType = BaseStorableType | Record<string, BaseStorableType> | Array<BaseStorableType>;
5
+ /**
6
+ * A single stored value as it appears in a saved game. Values are tagged on the way out so
7
+ * that types JSON cannot express (currently `Date`) survive the round-trip.
8
+ *
9
+ * This is part of the on-disk save format rather than an implementation detail: it is what
10
+ * {@link SavedGame}'s `store` actually contains. Read it through `Namespace`, never by hand.
11
+ */
12
+ export type WrappedStorableData<T extends StorableType = any> = {
13
+ type: BaseStorableTypeName;
14
+ data: T;
15
+ };
16
+ /**
17
+ * One namespace's contents in a saved game: every value wrapped by {@link WrappedStorableData}.
18
+ */
19
+ export type SerializedNamespaceData = {
20
+ [key: string]: WrappedStorableData;
21
+ };
@@ -3,6 +3,17 @@ import { TransformDefinitions } from "../../../../elements/transform/type";
3
3
  import { ImageTransition } from "../../../../elements/transition/transitions/image/imageTransition";
4
4
  import { GameState } from "../../../../../player/gameState";
5
5
  type AnimationType = [TransitionAnimationType.Number, TransitionAnimationType.Number, TransitionAnimationType.Number];
6
+ /**
7
+ * A fade in, optionally travelling from a pixel offset to rest.
8
+ *
9
+ * The offset rides on the independent CSS `translate` property (not `transform`,
10
+ * and not `left`/`top`) for the same reason as {@link Push}: it composes additively
11
+ * with whatever base positioning the driven element already has, and it is the
12
+ * identity at offset `0`. Writing `transform` here instead would overwrite that
13
+ * base — a layered image's stack wrapper is positioned by `inset: 0` and carries
14
+ * no transform of its own, so a leftover `transform` from this transition would
15
+ * survive the crossfade and displace the settled stack.
16
+ */
6
17
  export declare class FadeIn extends ImageTransition<AnimationType> {
7
18
  private duration;
8
19
  private startPos;
@@ -9,6 +9,20 @@ export declare abstract class ImageTransition<T extends TransitionAnimationType[
9
9
  /**@package */
10
10
  private _currentSrc;
11
11
  /**@package */
12
+ private _prevLayers;
13
+ /**@package */
14
+ private _targetLayers;
15
+ /**@package */
16
+ _setPrevLayers(layers: (string | null)[]): this;
17
+ /**@package */
18
+ _setTargetLayers(layers: (string | null)[]): this;
19
+ /**@package */
20
+ _getPrevLayers(): (string | null)[] | undefined;
21
+ /**@package */
22
+ _getTargetLayers(): (string | null)[] | undefined;
23
+ /**@package */
24
+ _isLayered(): boolean;
25
+ /**@package */
12
26
  _setPrevSrc(src: Color | ImageSrc | undefined): this;
13
27
  /**@package */
14
28
  _setTargetSrc(src: Color | ImageSrc | undefined): this;
@@ -1,6 +1,6 @@
1
1
  import { LogicAction } from "./action/logicAction";
2
2
  import { ContentNode, RawData } from "./action/tree/actionTree";
3
- import { StorableData } from "./elements/persistent/type";
3
+ import { SerializedNamespaceData } from "./elements/persistent/type";
4
4
  import { ElementStateRaw } from "./elements/story";
5
5
  import { StringKeyOf } from "../../util/data";
6
6
  import { PlayerStateData } from "../player/gameState";
@@ -40,7 +40,7 @@ export interface SavedGame {
40
40
  meta: SavedGameMetaData;
41
41
  game: {
42
42
  store: {
43
- [key: string]: StorableData;
43
+ [key: string]: SerializedNamespaceData;
44
44
  };
45
45
  elementStates: RawData<ElementStateRaw>[];
46
46
  stage: PlayerStateData;
@@ -1,3 +1,5 @@
1
+ import React from "react";
1
2
  export type ImageEvents = {
2
3
  "event:image.onLoad": [];
3
4
  };
5
+ export declare function stackStyle(darkness: number): React.CSSProperties;