@novely/core 0.23.0 → 0.25.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/dist/index.d.ts +341 -199
- package/dist/index.global.js +258 -134
- package/dist/index.global.js.map +1 -1
- package/dist/index.js +258 -134
- package/dist/index.js.map +1 -1
- package/package.json +62 -62
package/dist/index.d.ts
CHANGED
|
@@ -6,153 +6,19 @@ type Character<LanguageKeys extends string = string> = {
|
|
|
6
6
|
emotions: Emotions;
|
|
7
7
|
};
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
type PathItem = [null, number | string] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
|
|
11
|
-
type Path = PathItem[];
|
|
12
|
-
type State = Record<string, any>;
|
|
13
|
-
type Data = Record<string, any>;
|
|
14
|
-
type SaveDate = number;
|
|
15
|
-
type SaveType = 'manual' | 'auto';
|
|
16
|
-
type SaveMeta = [date: SaveDate, type: SaveType];
|
|
17
|
-
type Save = [path: Path, state: State, meta: SaveMeta];
|
|
18
|
-
type Lang = string;
|
|
19
|
-
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
|
|
20
|
-
type SoundVolume = number;
|
|
21
|
-
type StorageMeta = [lang: Lang, typewriter_speed: TypewriterSpeed, music_volume: SoundVolume, sound_volume: SoundVolume, voice_volume: SoundVolume];
|
|
22
|
-
type Migration = (save: unknown) => unknown;
|
|
23
|
-
type StorageData = {
|
|
24
|
-
saves: Save[];
|
|
25
|
-
data: Data;
|
|
26
|
-
meta: StorageMeta;
|
|
27
|
-
};
|
|
28
|
-
type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
29
|
-
/**
|
|
30
|
-
* @see https://pendletonjones.com/deep-partial
|
|
31
|
-
*/
|
|
32
|
-
type DeepPartial<T> = unknown extends T ? T : T extends object ? {
|
|
33
|
-
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
|
|
34
|
-
} : T;
|
|
35
|
-
type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
|
|
36
|
-
type CoreData = {
|
|
37
|
-
dataLoaded: boolean;
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
type ValidAction = ['choice', [number]] | ['clear', [Set<keyof DefaultActionProxyProvider>?, Set<string>?]] | ['condition', [() => boolean, Record<string, ValidAction[]>]] | ['dialog', [string | undefined, Unwrappable<string>, string | undefined]] | ['end', []] | ['showBackground', [string | NonEmptyRecord<BackgroundImage>]] | ['playMusic', [string]] | ['stopMusic', [string]] | ['voice', [string]] | ['stopVoice', []] | ['jump', [string]] | ['showCharacter', [string, keyof Character['emotions'], string?, string?]] | ['hideCharacter', [string, string?, string?, number?]] | ['animateCharacter', [string, number, ...string[]]] | ['wait', [FunctionableValue<number>]] | ['function', [() => Thenable<void>]] | ['input', [string, (meta: ActionInputOnInputMeta<string>) => void, ActionInputSetup?]] | ['custom', [CustomHandler]] | ['vibrate', [...number[]]] | ['next', []] | ['text', [...string[]]] | ['exit', []] | ['preload', [string]] | ['block', [string]] | ValidAction[];
|
|
41
|
-
type Story = Record<string, ValidAction[]>;
|
|
42
|
-
type Unwrappable<L extends string> = string | (() => string) | Record<L, string | (() => string)>;
|
|
43
|
-
type FunctionableValue<T> = T | (() => T);
|
|
44
|
-
type CustomHandlerGetResultDataFunction = {
|
|
45
|
-
(data?: Record<string, unknown>): Record<string, unknown>;
|
|
46
|
-
};
|
|
47
|
-
type CustomHandlerGetResult<I extends boolean> = {
|
|
48
|
-
delete: () => void;
|
|
49
|
-
/**
|
|
50
|
-
* Данные
|
|
51
|
-
*/
|
|
52
|
-
data: CustomHandlerGetResultDataFunction;
|
|
53
|
-
/**
|
|
54
|
-
* Элемент слоя
|
|
55
|
-
*/
|
|
56
|
-
element: I extends true ? HTMLDivElement : null;
|
|
57
|
-
/**
|
|
58
|
-
* Корневой элемент Novely
|
|
59
|
-
*/
|
|
60
|
-
root: HTMLElement;
|
|
61
|
-
/**
|
|
62
|
-
* Устанавливает обработчик очистки
|
|
63
|
-
*/
|
|
64
|
-
clear: (fn: () => void) => void;
|
|
65
|
-
};
|
|
66
|
-
type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
|
|
67
|
-
type CustomHandlerFunctionParameters = {
|
|
68
|
-
get: CustomHandlerFunctionGetFn;
|
|
69
|
-
goingBack: boolean;
|
|
70
|
-
preview: boolean;
|
|
71
|
-
lang: string;
|
|
72
|
-
};
|
|
73
|
-
type CustomHandlerFunction = (parameters: CustomHandlerFunctionParameters) => Thenable<void>;
|
|
74
|
-
type CustomHandler = CustomHandlerFunction & {
|
|
75
|
-
callOnlyLatest?: boolean;
|
|
76
|
-
requireUserAction?: boolean;
|
|
77
|
-
skipClearOnGoingBack?: boolean;
|
|
78
|
-
id?: string | symbol;
|
|
9
|
+
interface LocalStorageStorageSettings {
|
|
79
10
|
key: string;
|
|
80
|
-
};
|
|
81
|
-
interface ActionInputOnInputMeta<L extends string> {
|
|
82
|
-
/**
|
|
83
|
-
* Input Element itself
|
|
84
|
-
*/
|
|
85
|
-
input: HTMLInputElement;
|
|
86
|
-
/**
|
|
87
|
-
* Function to show error message or hide it
|
|
88
|
-
* @param error Error message or empty string to remove it
|
|
89
|
-
*/
|
|
90
|
-
error: (error: string) => void;
|
|
91
|
-
/**
|
|
92
|
-
* Input Event
|
|
93
|
-
*/
|
|
94
|
-
event: InputEvent & {
|
|
95
|
-
currentTarget: HTMLInputElement;
|
|
96
|
-
};
|
|
97
|
-
/**
|
|
98
|
-
* Sanitized `input.value`
|
|
99
|
-
*/
|
|
100
|
-
value: string;
|
|
101
|
-
/**
|
|
102
|
-
* Language
|
|
103
|
-
*/
|
|
104
|
-
lang: L;
|
|
105
11
|
}
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
}) => ValidAction;
|
|
117
|
-
condition: <T extends string | true | false>(condition: () => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
|
|
118
|
-
exit: () => ValidAction;
|
|
119
|
-
dialog: {
|
|
120
|
-
<C extends keyof Characters>(person: C, content: Unwrappable<Languages>, emotion?: keyof Characters[C]['emotions']): ValidAction;
|
|
121
|
-
(person: undefined, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
|
|
122
|
-
(person: string, content: Unwrappable<Languages>, emotion?: undefined): ValidAction;
|
|
123
|
-
};
|
|
124
|
-
end: () => ValidAction;
|
|
125
|
-
showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
|
|
126
|
-
playMusic: (audio: string) => ValidAction;
|
|
127
|
-
stopMusic: (audio: string) => ValidAction;
|
|
128
|
-
playSound: (audio: string, loop?: boolean) => ValidAction;
|
|
129
|
-
stopSound: (audio: string) => ValidAction;
|
|
130
|
-
/**
|
|
131
|
-
* Plays voice
|
|
132
|
-
*/
|
|
133
|
-
voice: (voice: string) => ValidAction;
|
|
134
|
-
/**
|
|
135
|
-
* Stops currently playing voice
|
|
136
|
-
*/
|
|
137
|
-
stopVoice: () => ValidAction;
|
|
138
|
-
jump: (scene: string) => ValidAction;
|
|
139
|
-
showCharacter: {
|
|
140
|
-
<C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
|
|
141
|
-
};
|
|
142
|
-
hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
|
|
143
|
-
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
144
|
-
wait: (time: FunctionableValue<number>) => ValidAction;
|
|
145
|
-
function: (fn: (restoring: boolean, goingBack: boolean, preview: boolean) => Thenable<void>) => ValidAction;
|
|
146
|
-
input: (question: Unwrappable<Languages>, onInput: (meta: ActionInputOnInputMeta<Languages>) => void, setup?: ActionInputSetup) => ValidAction;
|
|
147
|
-
custom: (handler: CustomHandler) => ValidAction;
|
|
148
|
-
vibrate: (...pattern: number[]) => ValidAction;
|
|
149
|
-
next: () => ValidAction;
|
|
150
|
-
text: (...text: Unwrappable<Languages>[]) => ValidAction;
|
|
151
|
-
preload: (source: string) => ValidAction;
|
|
152
|
-
block: (scene: string) => ValidAction;
|
|
153
|
-
};
|
|
154
|
-
type DefaultActionProxyProvider = ActionProxyProvider<Record<string, Character>, string>;
|
|
155
|
-
type GetActionParameters<T extends Capitalize<keyof DefaultActionProxyProvider>> = Parameters<DefaultActionProxyProvider[Uncapitalize<T>]>;
|
|
12
|
+
interface Storage {
|
|
13
|
+
get: () => Promise<StorageData>;
|
|
14
|
+
set: (data: StorageData) => Promise<void>;
|
|
15
|
+
}
|
|
16
|
+
declare const localStorageStorage: (options: LocalStorageStorageSettings) => Storage;
|
|
17
|
+
|
|
18
|
+
type PluralType = Intl.LDMLPluralRule;
|
|
19
|
+
type Pluralization = Partial<Record<PluralType, string>>;
|
|
20
|
+
type AllowedContent = string | ((state: State) => string | string[]) | string[] | (string | ((state: State) => string | string[]))[];
|
|
21
|
+
type TranslationActions = Partial<Record<string, (str: string) => string>>;
|
|
156
22
|
|
|
157
23
|
declare const RU: {
|
|
158
24
|
NewGame: string;
|
|
@@ -272,14 +138,14 @@ type Renderer = {
|
|
|
272
138
|
character: (character: string) => CharacterHandle;
|
|
273
139
|
background: (background: string | BackgroundImage) => void;
|
|
274
140
|
dialog: (content: string, name: string, character: string | undefined, emotion: string | undefined, resolve: () => void) => void;
|
|
275
|
-
choices: (question: string, choices:
|
|
276
|
-
input: (question: string, onInput: (meta: ActionInputOnInputMeta<string>) => void, setup: ActionInputSetup, resolve: () => void) => void;
|
|
277
|
-
clear: (keep: Set<keyof
|
|
141
|
+
choices: (question: string, choices: [name: string, actions: ValidAction[], active?: boolean][], resolve: (selected: number) => void) => void;
|
|
142
|
+
input: (question: string, onInput: (meta: ActionInputOnInputMeta<string, State>) => void, setup: ActionInputSetup, resolve: () => void) => void;
|
|
143
|
+
clear: (keep: Set<keyof DefaultActionProxy>, keepCharacters: Set<string>, keepAudio: {
|
|
278
144
|
music: Set<string>;
|
|
279
145
|
sounds: Set<string>;
|
|
280
146
|
}, resolve: () => void) => void;
|
|
281
|
-
custom: (fn: Parameters<
|
|
282
|
-
clearCustom: (fn: Parameters<
|
|
147
|
+
custom: (fn: Parameters<DefaultActionProxy['custom']>[0], push: () => void) => Thenable<void>;
|
|
148
|
+
clearCustom: (fn: Parameters<DefaultActionProxy['custom']>[0]) => void;
|
|
283
149
|
text: (str: string, resolve: () => void) => void;
|
|
284
150
|
vibrate: (pattern: VibratePattern) => void;
|
|
285
151
|
audio: {
|
|
@@ -340,31 +206,87 @@ type RendererInit = {
|
|
|
340
206
|
mainContextKey: string;
|
|
341
207
|
preview: (save: Save, name: string) => Promise<void>;
|
|
342
208
|
removeContext: (name: string) => void;
|
|
209
|
+
getStateFunction: (context: string) => StateFunction<State>;
|
|
343
210
|
};
|
|
344
211
|
|
|
345
|
-
interface LocalStorageStorageSettings {
|
|
346
|
-
key: string;
|
|
347
|
-
}
|
|
348
|
-
interface Storage {
|
|
349
|
-
get: () => Promise<StorageData>;
|
|
350
|
-
set: (data: StorageData) => Promise<void>;
|
|
351
|
-
}
|
|
352
|
-
declare const localStorageStorage: (options: LocalStorageStorageSettings) => Storage;
|
|
353
|
-
|
|
354
|
-
type PluralType = Intl.LDMLPluralRule;
|
|
355
|
-
type Pluralization = Partial<Record<PluralType, string>>;
|
|
356
|
-
type AllowedContent = string | (() => string | string[]) | string[] | (string | (() => string | string[]))[];
|
|
357
|
-
type TranslationActions = Partial<Record<string, (str: string) => string>>;
|
|
358
|
-
|
|
359
212
|
declare const getLanguage: (languages: string[]) => string;
|
|
360
213
|
|
|
361
|
-
|
|
214
|
+
type Thenable<T> = T | Promise<T>;
|
|
215
|
+
type PathItem = [null, number | string] | ['jump', string] | ['choice', number] | ['choice:exit'] | ['condition', string] | ['condition:exit'] | ['exit'] | ['block', string] | ['block:exit'];
|
|
216
|
+
type Path = PathItem[];
|
|
217
|
+
type State = Record<string, any>;
|
|
218
|
+
type Data = Record<string, any>;
|
|
219
|
+
type SaveDate = number;
|
|
220
|
+
type SaveType = 'manual' | 'auto';
|
|
221
|
+
type SaveMeta = [date: SaveDate, type: SaveType];
|
|
222
|
+
type Save<S extends State = State> = [
|
|
223
|
+
path: Path,
|
|
224
|
+
state: S,
|
|
225
|
+
meta: SaveMeta
|
|
226
|
+
];
|
|
227
|
+
type Lang = string;
|
|
228
|
+
type TypewriterSpeed = 'Slow' | 'Medium' | 'Fast' | 'Auto' | (string & Record<never, never>);
|
|
229
|
+
type SoundVolume = number;
|
|
230
|
+
type StorageMeta<L extends string = string> = [
|
|
231
|
+
lang: L,
|
|
232
|
+
typewriter_speed: TypewriterSpeed,
|
|
233
|
+
music_volume: SoundVolume,
|
|
234
|
+
sound_volume: SoundVolume,
|
|
235
|
+
voice_volume: SoundVolume
|
|
236
|
+
];
|
|
237
|
+
type Migration = (save: unknown) => unknown;
|
|
238
|
+
type StorageData<L extends string = string, D extends Data = Data> = {
|
|
239
|
+
saves: Save[];
|
|
240
|
+
data: D;
|
|
241
|
+
meta: StorageMeta<L>;
|
|
242
|
+
};
|
|
243
|
+
type Stack = {
|
|
244
|
+
value: Save;
|
|
245
|
+
back(): void;
|
|
246
|
+
push(value: Save): void;
|
|
247
|
+
clear(): void;
|
|
248
|
+
};
|
|
249
|
+
type NovelyScreen = 'mainmenu' | 'game' | 'saves' | 'settings';
|
|
250
|
+
/**
|
|
251
|
+
* @see https://pendletonjones.com/deep-partial
|
|
252
|
+
*/
|
|
253
|
+
type DeepPartial<T> = unknown extends T ? T : T extends object ? {
|
|
254
|
+
[P in keyof T]?: T[P] extends Array<infer U> ? Array<DeepPartial<U>> : T[P] extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : DeepPartial<T[P]>;
|
|
255
|
+
} : T;
|
|
256
|
+
type NonEmptyRecord<T extends Record<PropertyKey, unknown>> = keyof T extends never ? never : T;
|
|
257
|
+
type CoreData = {
|
|
258
|
+
dataLoaded: boolean;
|
|
259
|
+
};
|
|
260
|
+
type StackHolder = Save[] & {
|
|
261
|
+
previous: Save | undefined;
|
|
262
|
+
};
|
|
263
|
+
type TranslationDescription = {
|
|
264
|
+
internal: Record<BaseTranslationStrings, string>;
|
|
362
265
|
/**
|
|
363
|
-
*
|
|
266
|
+
* IETF BCP 47 language tag
|
|
364
267
|
*/
|
|
365
|
-
|
|
268
|
+
tag?: string;
|
|
269
|
+
plural?: Record<string, Pluralization>;
|
|
270
|
+
actions?: TranslationActions;
|
|
271
|
+
};
|
|
272
|
+
interface NovelyInit<Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data> {
|
|
366
273
|
/**
|
|
367
274
|
* An object containing the characters in the game.
|
|
275
|
+
* @example
|
|
276
|
+
* ```ts
|
|
277
|
+
* const engine = novely({
|
|
278
|
+
* characters: {
|
|
279
|
+
* // Character ID
|
|
280
|
+
* Alexei: {
|
|
281
|
+
* name: 'Alexei',
|
|
282
|
+
* color: '#f60002',
|
|
283
|
+
* emotions: {
|
|
284
|
+
* hopeful: './hopeful.png'
|
|
285
|
+
* }
|
|
286
|
+
* }
|
|
287
|
+
* }
|
|
288
|
+
* })
|
|
289
|
+
* ```
|
|
368
290
|
*/
|
|
369
291
|
characters: Characters;
|
|
370
292
|
/**
|
|
@@ -386,22 +308,37 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
|
|
|
386
308
|
initialScreen?: NovelyScreen;
|
|
387
309
|
/**
|
|
388
310
|
* An object containing the translation functions used in the game
|
|
311
|
+
* @see https://novely.pages.dev/guide/translation.html Docs
|
|
312
|
+
* @example
|
|
313
|
+
* ```ts
|
|
314
|
+
* import { novely, EN } from 'novely';
|
|
315
|
+
*
|
|
316
|
+
* const engine = novely({
|
|
317
|
+
* translation: {
|
|
318
|
+
* internal: EN,
|
|
319
|
+
* // Optional IETF BCP 47 language tag
|
|
320
|
+
* tag: 'en-US',
|
|
321
|
+
* plural: {
|
|
322
|
+
*
|
|
323
|
+
* },
|
|
324
|
+
* actions: {
|
|
325
|
+
*
|
|
326
|
+
* }
|
|
327
|
+
* }
|
|
328
|
+
* })
|
|
329
|
+
* ```
|
|
389
330
|
*/
|
|
390
|
-
translation: Record<Languages,
|
|
391
|
-
internal: Record<BaseTranslationStrings, string>;
|
|
392
|
-
/**
|
|
393
|
-
* IETF BCP 47 language tag
|
|
394
|
-
*/
|
|
395
|
-
tag?: string;
|
|
396
|
-
plural?: Record<string, Pluralization>;
|
|
397
|
-
actions?: TranslationActions;
|
|
398
|
-
}>;
|
|
331
|
+
translation: Record<Languages, TranslationDescription>;
|
|
399
332
|
/**
|
|
400
333
|
* Initial state value
|
|
334
|
+
*
|
|
335
|
+
* State is a local value bound to one save
|
|
401
336
|
*/
|
|
402
337
|
state?: StateScheme;
|
|
403
338
|
/**
|
|
404
339
|
* Initial data value
|
|
340
|
+
*
|
|
341
|
+
* Data is a global value shared between saves
|
|
405
342
|
*/
|
|
406
343
|
data?: DataScheme;
|
|
407
344
|
/**
|
|
@@ -425,13 +362,16 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
|
|
|
425
362
|
parallelAssetsDownloadLimit?: number;
|
|
426
363
|
/**
|
|
427
364
|
* Custom language detector
|
|
428
|
-
* @param languages Supported languages
|
|
429
|
-
* @
|
|
430
|
-
*
|
|
431
|
-
*
|
|
432
|
-
*
|
|
433
|
-
*
|
|
434
|
-
*
|
|
365
|
+
* @param languages Supported languages
|
|
366
|
+
* @param original Original function that novely, could be used as fallback
|
|
367
|
+
* @example
|
|
368
|
+
* ```ts
|
|
369
|
+
* const engine = novely({
|
|
370
|
+
* getLanguage(languages, original) {
|
|
371
|
+
* if (!sdk) return original(languages);
|
|
372
|
+
*
|
|
373
|
+
* return sdk.environment.i18n.lang // i.e. custom language from some sdk
|
|
374
|
+
* }
|
|
435
375
|
* })
|
|
436
376
|
* ```
|
|
437
377
|
*/
|
|
@@ -454,34 +394,236 @@ interface NovelyInit<Languages extends string, Characters extends Record<string,
|
|
|
454
394
|
* Fetching function
|
|
455
395
|
*/
|
|
456
396
|
fetch?: typeof fetch;
|
|
397
|
+
/**
|
|
398
|
+
* When page is going to be unloaded will call `storage.set` method
|
|
399
|
+
* If 'prod' is passed enable only in production env.
|
|
400
|
+
* @default true
|
|
401
|
+
*/
|
|
402
|
+
saveOnUnload?: boolean | 'prod';
|
|
457
403
|
}
|
|
458
|
-
|
|
404
|
+
type StateFunction<S extends State> = {
|
|
405
|
+
(value: DeepPartial<S> | ((prev: S) => S)): void;
|
|
406
|
+
(): S;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
type ValidAction = ['choice', number] | ['clear', Set<keyof DefaultActionProxy>?, Set<string>?, {
|
|
410
|
+
music: Set<string>;
|
|
411
|
+
sounds: Set<string>;
|
|
412
|
+
}?] | ['condition', (state: State) => boolean, Record<string, ValidAction[]>] | ['dialog', string | undefined, TextContent<string, State>, string | undefined] | ['say', string, TextContent<string, State>] | ['end'] | ['showBackground', string | NonEmptyRecord<BackgroundImage>] | ['playMusic', string] | ['stopMusic', string] | ['playSound', audio: string, loop?: boolean] | ['voice', string] | ['stopVoice'] | ['jump', string] | ['showCharacter', string, keyof Character['emotions'], string?, string?] | ['hideCharacter', string, string?, string?, number?] | ['animateCharacter', string, number, ...string[]] | ['wait', (number | ((state: State) => number))] | ['function', FunctionAction<string, State>] | ['input', string, (meta: ActionInputOnInputMeta<string, State>) => void, ActionInputSetup?] | ['custom', CustomHandler<string, State>] | ['vibrate', ...number[]] | ['next'] | ['text', ...TextContent<string, State>[]] | ['exit'] | ['preload', string] | ['block', string] | ValidAction[];
|
|
413
|
+
type Story = Record<string, ValidAction[]>;
|
|
414
|
+
type TextContent<L extends string, S extends State> = string | ((state: S) => string) | Record<L, string | ((state: S) => string)>;
|
|
415
|
+
type FunctionableValue<T> = T | (() => T);
|
|
416
|
+
type CustomHandlerGetResultDataFunction = {
|
|
417
|
+
(data?: Record<string, unknown>): Record<string, unknown>;
|
|
418
|
+
};
|
|
419
|
+
type CustomHandlerGetResult<I extends boolean> = {
|
|
420
|
+
delete: () => void;
|
|
459
421
|
/**
|
|
460
|
-
*
|
|
422
|
+
* Данные
|
|
461
423
|
*/
|
|
462
|
-
|
|
424
|
+
data: CustomHandlerGetResultDataFunction;
|
|
425
|
+
/**
|
|
426
|
+
* Элемент слоя
|
|
427
|
+
*/
|
|
428
|
+
element: I extends true ? HTMLDivElement : null;
|
|
429
|
+
/**
|
|
430
|
+
* Корневой элемент Novely
|
|
431
|
+
*/
|
|
432
|
+
root: HTMLElement;
|
|
433
|
+
/**
|
|
434
|
+
* Устанавливает обработчик очистки
|
|
435
|
+
*/
|
|
436
|
+
clear: (fn: () => void) => void;
|
|
437
|
+
};
|
|
438
|
+
type CustomHandlerFunctionGetFn = <I extends boolean = true>(insert?: I) => CustomHandlerGetResult<I>;
|
|
439
|
+
type CustomHandlerFunctionParameters<L extends string, S extends State> = {
|
|
440
|
+
get: CustomHandlerFunctionGetFn;
|
|
441
|
+
state: StateFunction<S>;
|
|
442
|
+
goingBack: boolean;
|
|
443
|
+
preview: boolean;
|
|
444
|
+
lang: L;
|
|
445
|
+
};
|
|
446
|
+
type CustomHandlerFunction<L extends string, S extends State> = (parameters: CustomHandlerFunctionParameters<L, S>) => Thenable<void>;
|
|
447
|
+
type CustomHandler<L extends string = string, S extends State = State> = CustomHandlerFunction<L, S> & {
|
|
448
|
+
callOnlyLatest?: boolean;
|
|
449
|
+
requireUserAction?: boolean;
|
|
450
|
+
skipClearOnGoingBack?: boolean;
|
|
451
|
+
id?: string | symbol;
|
|
452
|
+
key: string;
|
|
453
|
+
};
|
|
454
|
+
interface ActionInputOnInputMeta<L extends string, S extends State> {
|
|
455
|
+
/**
|
|
456
|
+
* Input Element itself
|
|
457
|
+
*/
|
|
458
|
+
input: HTMLInputElement;
|
|
459
|
+
/**
|
|
460
|
+
* Function to show error message or hide it
|
|
461
|
+
* @param error Error message or empty string to remove it
|
|
462
|
+
*/
|
|
463
|
+
error: (error: string) => void;
|
|
464
|
+
/**
|
|
465
|
+
* Input Event
|
|
466
|
+
*/
|
|
467
|
+
event: InputEvent & {
|
|
468
|
+
currentTarget: HTMLInputElement;
|
|
469
|
+
};
|
|
470
|
+
/**
|
|
471
|
+
* Sanitized `input.value`
|
|
472
|
+
*/
|
|
473
|
+
value: string;
|
|
474
|
+
/**
|
|
475
|
+
* Language
|
|
476
|
+
*/
|
|
477
|
+
lang: L;
|
|
478
|
+
/**
|
|
479
|
+
* State function
|
|
480
|
+
*/
|
|
481
|
+
state: StateFunction<S>;
|
|
482
|
+
}
|
|
483
|
+
type FunctionActionProps<L extends string, S extends State> = {
|
|
484
|
+
restoring: boolean;
|
|
485
|
+
goingBack: boolean;
|
|
486
|
+
preview: boolean;
|
|
487
|
+
/**
|
|
488
|
+
* Language
|
|
489
|
+
*/
|
|
490
|
+
lang: L;
|
|
463
491
|
/**
|
|
464
|
-
*
|
|
492
|
+
* State function
|
|
465
493
|
*/
|
|
466
|
-
|
|
494
|
+
state: StateFunction<S>;
|
|
495
|
+
};
|
|
496
|
+
type ChoiceCheckFunctionProps<L extends string, S extends State> = {
|
|
467
497
|
/**
|
|
468
|
-
*
|
|
498
|
+
* Language
|
|
469
499
|
*/
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
500
|
+
lang: L;
|
|
501
|
+
/**
|
|
502
|
+
* State
|
|
503
|
+
*/
|
|
504
|
+
state: S;
|
|
505
|
+
};
|
|
506
|
+
type ChoiceCheckFunction<L extends string, S extends State> = {
|
|
507
|
+
(props: ChoiceCheckFunctionProps<L, S>): boolean;
|
|
508
|
+
};
|
|
509
|
+
type FunctionAction<L extends string, S extends State> = (props: FunctionActionProps<L, S>) => Thenable<void>;
|
|
510
|
+
type ActionInputSetup = (input: HTMLInputElement, cleanup: (cb: () => void) => void) => void;
|
|
511
|
+
type BackgroundImage = Partial<Record<'portrait' | 'landscape' | 'all', string>> & Record<string, string>;
|
|
512
|
+
type ActionProxy<Characters extends Record<string, Character>, Languages extends string, S extends State> = {
|
|
513
|
+
choice: {
|
|
514
|
+
(...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
|
|
515
|
+
(question: TextContent<Languages, S>, ...choices: [name: TextContent<Languages, S>, actions: ValidAction[], active?: ChoiceCheckFunction<Languages, S>][]): ValidAction;
|
|
473
516
|
};
|
|
517
|
+
clear: (keep?: Set<keyof DefaultActionProxy>, keepCharacters?: Set<string>, keepAudio?: {
|
|
518
|
+
music: Set<string>;
|
|
519
|
+
sounds: Set<string>;
|
|
520
|
+
}) => ValidAction;
|
|
521
|
+
condition: <T extends string | true | false>(condition: (state: S) => T, variants: Record<T extends true ? 'true' : T extends false ? 'false' : T, ValidAction[]>) => ValidAction;
|
|
522
|
+
exit: () => ValidAction;
|
|
523
|
+
dialog: {
|
|
524
|
+
<C extends keyof Characters>(character: C, content: TextContent<Languages, S>, emotion?: keyof Characters[C]['emotions']): ValidAction;
|
|
525
|
+
(character: undefined, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
|
|
526
|
+
(character: string, content: TextContent<Languages, S>, emotion?: undefined): ValidAction;
|
|
527
|
+
};
|
|
528
|
+
say: (character: keyof Characters, content: TextContent<Languages, S>) => ValidAction;
|
|
529
|
+
end: () => ValidAction;
|
|
530
|
+
showBackground: <T extends string | BackgroundImage>(background: T extends string ? T : T extends Record<PropertyKey, unknown> ? NonEmptyRecord<T> : never) => ValidAction;
|
|
531
|
+
playMusic: (audio: string) => ValidAction;
|
|
532
|
+
stopMusic: (audio: string) => ValidAction;
|
|
533
|
+
playSound: (audio: string, loop?: boolean) => ValidAction;
|
|
534
|
+
stopSound: (audio: string) => ValidAction;
|
|
535
|
+
/**
|
|
536
|
+
* Plays voice
|
|
537
|
+
*/
|
|
538
|
+
voice: (voice: string) => ValidAction;
|
|
474
539
|
/**
|
|
475
|
-
*
|
|
540
|
+
* Stops currently playing voice
|
|
476
541
|
*/
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
542
|
+
stopVoice: () => ValidAction;
|
|
543
|
+
jump: (scene: string) => ValidAction;
|
|
544
|
+
showCharacter: {
|
|
545
|
+
<C extends keyof Characters>(character: C, emotion: keyof Characters[C]['emotions'], className?: string, style?: string): ValidAction;
|
|
480
546
|
};
|
|
547
|
+
hideCharacter: (character: keyof Characters, className?: string, style?: string, duration?: number) => ValidAction;
|
|
548
|
+
animateCharacter: (character: keyof Characters, timeout: number, ...classes: string[]) => ValidAction;
|
|
549
|
+
wait: (time: number | ((state: State) => number)) => ValidAction;
|
|
550
|
+
function: (fn: FunctionAction<Languages, S>) => ValidAction;
|
|
551
|
+
input: (question: TextContent<Languages, S>, onInput: (meta: ActionInputOnInputMeta<Languages, S>) => void, setup?: ActionInputSetup) => ValidAction;
|
|
552
|
+
custom: (handler: CustomHandler<Languages, S> | CustomHandler) => ValidAction;
|
|
553
|
+
vibrate: (...pattern: number[]) => ValidAction;
|
|
554
|
+
next: () => ValidAction;
|
|
555
|
+
text: (...text: TextContent<Languages, S>[]) => ValidAction;
|
|
556
|
+
preload: (source: string) => ValidAction;
|
|
557
|
+
block: (scene: string) => ValidAction;
|
|
558
|
+
};
|
|
559
|
+
type DefaultActionProxy = ActionProxy<Record<string, Character>, string, State>;
|
|
560
|
+
type GetActionParameters<T extends Capitalize<keyof DefaultActionProxy>> = Parameters<DefaultActionProxy[Uncapitalize<T>]>;
|
|
561
|
+
|
|
562
|
+
declare const novely: <Languages extends string, Characters extends Record<string, Character<Languages>>, StateScheme extends State, DataScheme extends Data>({ characters, storage, storageDelay, renderer: createRenderer, initialScreen, translation, state: defaultState, data: defaultData, autosaves, migrations, throttleTimeout, getLanguage, overrideLanguage, askBeforeExit, preloadAssets, parallelAssetsDownloadLimit, fetch: request, saveOnUnload }: NovelyInit<Languages, Characters, StateScheme, DataScheme>) => {
|
|
563
|
+
/**
|
|
564
|
+
* Function to set game script
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* ```ts
|
|
568
|
+
* engine.script({
|
|
569
|
+
* start: [
|
|
570
|
+
* action.function(() => {})
|
|
571
|
+
* ]
|
|
572
|
+
* })
|
|
573
|
+
* ```
|
|
574
|
+
*/
|
|
575
|
+
script: (part: Story) => Promise<void>;
|
|
481
576
|
/**
|
|
482
|
-
*
|
|
577
|
+
* Get actions
|
|
578
|
+
*
|
|
579
|
+
* @example
|
|
580
|
+
* ```ts
|
|
581
|
+
* engine.script({
|
|
582
|
+
* start: [
|
|
583
|
+
* action.function(() => {})
|
|
584
|
+
* ]
|
|
585
|
+
* })
|
|
586
|
+
* ```
|
|
587
|
+
*/
|
|
588
|
+
action: ActionProxy<Characters, Languages, StateScheme>;
|
|
589
|
+
/**
|
|
590
|
+
* @deprecated Will be removed BUT replaced with state passed into actions as a parameter
|
|
591
|
+
*/
|
|
592
|
+
state: StateFunction<State>;
|
|
593
|
+
/**
|
|
594
|
+
* Store data between games
|
|
595
|
+
*
|
|
596
|
+
* @example
|
|
597
|
+
* ```ts
|
|
598
|
+
* engine.script({
|
|
599
|
+
* start: [
|
|
600
|
+
* action.function(() => {
|
|
601
|
+
* // Paid content should be purchased only once
|
|
602
|
+
* // So it will be available in any save
|
|
603
|
+
* data({ paid_content_purchased: true })
|
|
604
|
+
* })
|
|
605
|
+
* ]
|
|
606
|
+
* })
|
|
607
|
+
* ```
|
|
608
|
+
*/
|
|
609
|
+
data: StateFunction<DataScheme>;
|
|
610
|
+
/**
|
|
611
|
+
* @deprecated Renamed into `templateReplace`
|
|
612
|
+
*/
|
|
613
|
+
unwrap(content: TextContent<Languages, DataScheme>): string;
|
|
614
|
+
/**
|
|
615
|
+
* Replaces content inside {{braces}} with using global data
|
|
616
|
+
* @example
|
|
617
|
+
* ```ts
|
|
618
|
+
* data({ name: 'Alexei' })
|
|
619
|
+
*
|
|
620
|
+
* templateReplace('{{name}} is our hero')
|
|
621
|
+
* templateReplace({
|
|
622
|
+
* en: (data) => 'Hello, ' + data.name
|
|
623
|
+
* })
|
|
624
|
+
* ```
|
|
483
625
|
*/
|
|
484
|
-
|
|
626
|
+
templateReplace(content: TextContent<Languages, DataScheme>): string;
|
|
485
627
|
/**
|
|
486
628
|
* Cancel data loading, hide UI, ignore page change events
|
|
487
629
|
* Data updates still will work in case Novely already was loaded
|
|
@@ -489,4 +631,4 @@ declare const novely: <Languages extends string, Characters extends Record<strin
|
|
|
489
631
|
destroy(): void;
|
|
490
632
|
};
|
|
491
633
|
|
|
492
|
-
export { type
|
|
634
|
+
export { type ActionProxy, type AllowedContent, type AudioHandle, type BaseTranslationStrings, type Character, type CharacterHandle, type Context, type CoreData, type CustomHandler, type CustomHandlerFunctionGetFn, type CustomHandlerFunctionParameters, type CustomHandlerGetResult, type CustomHandlerGetResultDataFunction, type DefaultActionProxy, EN, type Emotions, type FunctionableValue, type GetActionParameters, JP, KK, type Lang, type NovelyInit, type NovelyScreen, type Path, type PluralType, type Pluralization, RU, type Renderer, type RendererInit, type Save, type Stack, type StackHolder, type Storage, type StorageData, type StorageMeta, type Stored, type Story, type TextContent, type Thenable, type TranslationActions, type TypewriterSpeed, type ValidAction, localStorageStorage, novely };
|