narraleaf-react 0.12.2 → 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.
@@ -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";
@@ -2,9 +2,18 @@ import { ControlAction } from "../../action/actions/controlAction";
2
2
  import { Chained, Proxied } from "../../action/chain";
3
3
  import { GameState } from "../../common/game";
4
4
  import { LogicAction } from "../../game";
5
+ import type { LiveGameEventToken } from "../../types";
5
6
  import { Layer } from "../layer";
6
7
  import { DynamicPersistent, Persistent } from "../persistent";
7
8
  import { Scene } from "../scene";
9
+ /** Snapshot of the dialog line currently presented to the player (ADV or NVL). */
10
+ export type DevToolsCurrentDialog = {
11
+ /** Id of the say action that produced the line (static id when assigned). */
12
+ actionId: string | null;
13
+ /** True once the line finished displaying and awaits advance. */
14
+ ended: boolean;
15
+ mode: "adv" | "nvl";
16
+ };
8
17
  export declare class DevTools {
9
18
  static getActionId(action: LogicAction.Actions): string;
10
19
  static setActionId(action: LogicAction.Actions, id: string): LogicAction.Actions;
@@ -49,5 +58,17 @@ export declare class DevTools {
49
58
  static setDisplayableTransformProps(gameState: GameState, displayable: LogicAction.DisplayableElements, props: Record<string, unknown>, options?: {
50
59
  merge?: boolean;
51
60
  }): void;
61
+ /**
62
+ * Read the dialog line currently presented to the player, or null when no
63
+ * dialog is on screen. Covers both ADV (tracked via GameState.beginAdvDialog)
64
+ * and NVL (active entry + phase) presentation.
65
+ */
66
+ static getCurrentDialog(gameState: GameState): DevToolsCurrentDialog | null;
67
+ /**
68
+ * Subscribe to changes of the currently presented dialog line (creation,
69
+ * typing completion, advance/settle) across ADV and NVL modes. The listener
70
+ * carries no payload; call {@link getCurrentDialog} to read the new state.
71
+ */
72
+ static onDialogStateChange(gameState: GameState, listener: () => void): LiveGameEventToken;
52
73
  static DynamicPersistent: typeof DynamicPersistent;
53
74
  }
@@ -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;
@@ -37,6 +37,17 @@ export type NvlDialogEntry = {
37
37
  text: string;
38
38
  };
39
39
  export type NvlDialogPhase = "idle" | "typing" | "awaitAdvance";
40
+ /**
41
+ * Transient tracking record for the currently displayed ADV dialog line.
42
+ * Rebuilt naturally on load/undo because the pending say action re-executes;
43
+ * never serialized.
44
+ */
45
+ export type AdvDialogState = {
46
+ dialogId: string;
47
+ actionId: string | null;
48
+ /** True once the sentence finished displaying (typing done or skipped to full text). */
49
+ ended: boolean;
50
+ };
40
51
  export type NvlState = {
41
52
  active: boolean;
42
53
  visible: boolean;
@@ -118,6 +129,7 @@ type GameStateEvents = {
118
129
  "event:state.end": [];
119
130
  "event:state.player.skip": [force?: boolean];
120
131
  "event:state.player.lineEnd": [];
132
+ "event:state.dialog.change": [];
121
133
  "event:state.player.requestFlush": [];
122
134
  "event:state.player.stageClick": [];
123
135
  "event:state.scene.mount": [scene: Scene];
@@ -165,6 +177,7 @@ export declare class GameState {
165
177
  pageRouter: null;
166
178
  private stageClickBuffer;
167
179
  private readonly nvlAdvanceWaiters;
180
+ private advDialogState;
168
181
  constructor(game: Game, stage: StageUtils);
169
182
  get deps(): number;
170
183
  addVideo(video: Video): this;
@@ -268,6 +281,20 @@ export declare class GameState {
268
281
  settleNvlDialog(dialogId: string): this;
269
282
  suppressNextNvlTyping(): this;
270
283
  consumeNvlTypingSuppression(): boolean;
284
+ /**
285
+ * Track the ADV dialog created by a say action. Emits `event:state.dialog.change`.
286
+ */
287
+ beginAdvDialog(dialogId: string, actionId: string | null): this;
288
+ /**
289
+ * Mark the tracked ADV dialog as fully displayed. No-op when the dialog id
290
+ * does not match the tracked one (e.g. DialogState reused outside ADV flow).
291
+ */
292
+ completeAdvDialogTyping(dialogId: string | undefined): this;
293
+ /**
294
+ * Clear the tracked ADV dialog when the line is advanced past or cancelled.
295
+ */
296
+ settleAdvDialog(dialogId: string): this;
297
+ getAdvDialogState(): AdvDialogState | null;
271
298
  recordStageClick(): this;
272
299
  consumeStageClick(maxAgeMs?: number): boolean;
273
300
  createDisplayable(displayable: LogicAction.DisplayableElements, scene?: Scene | null, layer?: Layer | null): this;