@react-text-game/core 0.1.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 +744 -0
- package/dist/baseGameObject.d.ts +90 -0
- package/dist/baseGameObject.d.ts.map +1 -0
- package/dist/baseGameObject.js +109 -0
- package/dist/baseGameObject.js.map +1 -0
- package/dist/constants.d.ts +12 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +12 -0
- package/dist/constants.js.map +1 -0
- package/dist/game.d.ts +294 -0
- package/dist/game.d.ts.map +1 -0
- package/dist/game.js +489 -0
- package/dist/game.js.map +1 -0
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.d.ts.map +1 -0
- package/dist/helpers.js +6 -0
- package/dist/helpers.js.map +1 -0
- package/dist/hooks/index.d.ts +4 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +4 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/useCurrentPassage.d.ts +10 -0
- package/dist/hooks/useCurrentPassage.d.ts.map +1 -0
- package/dist/hooks/useCurrentPassage.js +17 -0
- package/dist/hooks/useCurrentPassage.js.map +1 -0
- package/dist/hooks/useGameEntity.d.ts +21 -0
- package/dist/hooks/useGameEntity.d.ts.map +1 -0
- package/dist/hooks/useGameEntity.js +70 -0
- package/dist/hooks/useGameEntity.js.map +1 -0
- package/dist/hooks/useGameIsStarted.d.ts +12 -0
- package/dist/hooks/useGameIsStarted.d.ts.map +1 -0
- package/dist/hooks/useGameIsStarted.js +18 -0
- package/dist/hooks/useGameIsStarted.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +8 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +36 -0
- package/dist/logger.js.map +1 -0
- package/dist/options.d.ts +13 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +15 -0
- package/dist/options.js.map +1 -0
- package/dist/passages/interactiveMap/fabric.d.ts +4 -0
- package/dist/passages/interactiveMap/fabric.d.ts.map +1 -0
- package/dist/passages/interactiveMap/fabric.js +3 -0
- package/dist/passages/interactiveMap/fabric.js.map +1 -0
- package/dist/passages/interactiveMap/index.d.ts +4 -0
- package/dist/passages/interactiveMap/index.d.ts.map +1 -0
- package/dist/passages/interactiveMap/index.js +4 -0
- package/dist/passages/interactiveMap/index.js.map +1 -0
- package/dist/passages/interactiveMap/interactiveMap.d.ts +89 -0
- package/dist/passages/interactiveMap/interactiveMap.d.ts.map +1 -0
- package/dist/passages/interactiveMap/interactiveMap.js +103 -0
- package/dist/passages/interactiveMap/interactiveMap.js.map +1 -0
- package/dist/passages/interactiveMap/types.d.ts +822 -0
- package/dist/passages/interactiveMap/types.d.ts.map +1 -0
- package/dist/passages/interactiveMap/types.js +2 -0
- package/dist/passages/interactiveMap/types.js.map +1 -0
- package/dist/passages/passage.d.ts +57 -0
- package/dist/passages/passage.d.ts.map +1 -0
- package/dist/passages/passage.js +64 -0
- package/dist/passages/passage.js.map +1 -0
- package/dist/passages/story/fabric.d.ts +4 -0
- package/dist/passages/story/fabric.d.ts.map +1 -0
- package/dist/passages/story/fabric.js +3 -0
- package/dist/passages/story/fabric.js.map +1 -0
- package/dist/passages/story/index.d.ts +5 -0
- package/dist/passages/story/index.d.ts.map +1 -0
- package/dist/passages/story/index.js +5 -0
- package/dist/passages/story/index.js.map +1 -0
- package/dist/passages/story/start.d.ts +14 -0
- package/dist/passages/story/start.d.ts.map +1 -0
- package/dist/passages/story/start.js +22 -0
- package/dist/passages/story/start.js.map +1 -0
- package/dist/passages/story/story.d.ts +84 -0
- package/dist/passages/story/story.d.ts.map +1 -0
- package/dist/passages/story/story.js +88 -0
- package/dist/passages/story/story.js.map +1 -0
- package/dist/passages/story/types.d.ts +911 -0
- package/dist/passages/story/types.d.ts.map +1 -0
- package/dist/passages/story/types.js +2 -0
- package/dist/passages/story/types.js.map +1 -0
- package/dist/passages/types/index.d.ts +3 -0
- package/dist/passages/types/index.d.ts.map +1 -0
- package/dist/passages/types/index.js +2 -0
- package/dist/passages/types/index.js.map +1 -0
- package/dist/passages/widget.d.ts +62 -0
- package/dist/passages/widget.d.ts.map +1 -0
- package/dist/passages/widget.js +66 -0
- package/dist/passages/widget.js.map +1 -0
- package/dist/saves/constants.d.ts +17 -0
- package/dist/saves/constants.d.ts.map +1 -0
- package/dist/saves/constants.js +17 -0
- package/dist/saves/constants.js.map +1 -0
- package/dist/saves/db.d.ts +119 -0
- package/dist/saves/db.d.ts.map +1 -0
- package/dist/saves/db.js +231 -0
- package/dist/saves/db.js.map +1 -0
- package/dist/saves/helpers.d.ts +28 -0
- package/dist/saves/helpers.d.ts.map +1 -0
- package/dist/saves/helpers.js +84 -0
- package/dist/saves/helpers.js.map +1 -0
- package/dist/saves/hooks/index.d.ts +10 -0
- package/dist/saves/hooks/index.d.ts.map +1 -0
- package/dist/saves/hooks/index.js +10 -0
- package/dist/saves/hooks/index.js.map +1 -0
- package/dist/saves/hooks/useDeleteAllSlots.d.ts +18 -0
- package/dist/saves/hooks/useDeleteAllSlots.d.ts.map +1 -0
- package/dist/saves/hooks/useDeleteAllSlots.js +18 -0
- package/dist/saves/hooks/useDeleteAllSlots.js.map +1 -0
- package/dist/saves/hooks/useDeleteGame.d.ts +22 -0
- package/dist/saves/hooks/useDeleteGame.d.ts.map +1 -0
- package/dist/saves/hooks/useDeleteGame.js +33 -0
- package/dist/saves/hooks/useDeleteGame.js.map +1 -0
- package/dist/saves/hooks/useExportSaves.d.ts +27 -0
- package/dist/saves/hooks/useExportSaves.d.ts.map +1 -0
- package/dist/saves/hooks/useExportSaves.js +54 -0
- package/dist/saves/hooks/useExportSaves.js.map +1 -0
- package/dist/saves/hooks/useImportSaves.d.ts +29 -0
- package/dist/saves/hooks/useImportSaves.d.ts.map +1 -0
- package/dist/saves/hooks/useImportSaves.js +108 -0
- package/dist/saves/hooks/useImportSaves.js.map +1 -0
- package/dist/saves/hooks/useLastLoadGame.d.ts +39 -0
- package/dist/saves/hooks/useLastLoadGame.d.ts.map +1 -0
- package/dist/saves/hooks/useLastLoadGame.js +72 -0
- package/dist/saves/hooks/useLastLoadGame.js.map +1 -0
- package/dist/saves/hooks/useLoadGame.d.ts +22 -0
- package/dist/saves/hooks/useLoadGame.d.ts.map +1 -0
- package/dist/saves/hooks/useLoadGame.js +40 -0
- package/dist/saves/hooks/useLoadGame.js.map +1 -0
- package/dist/saves/hooks/useRestartGame.d.ts +20 -0
- package/dist/saves/hooks/useRestartGame.d.ts.map +1 -0
- package/dist/saves/hooks/useRestartGame.js +29 -0
- package/dist/saves/hooks/useRestartGame.js.map +1 -0
- package/dist/saves/hooks/useSaveGame.d.ts +22 -0
- package/dist/saves/hooks/useSaveGame.d.ts.map +1 -0
- package/dist/saves/hooks/useSaveGame.js +34 -0
- package/dist/saves/hooks/useSaveGame.js.map +1 -0
- package/dist/saves/hooks/useSaveSlots.d.ts +45 -0
- package/dist/saves/hooks/useSaveSlots.d.ts.map +1 -0
- package/dist/saves/hooks/useSaveSlots.js +42 -0
- package/dist/saves/hooks/useSaveSlots.js.map +1 -0
- package/dist/saves/index.d.ts +4 -0
- package/dist/saves/index.d.ts.map +1 -0
- package/dist/saves/index.js +3 -0
- package/dist/saves/index.js.map +1 -0
- package/dist/saves/types.d.ts +52 -0
- package/dist/saves/types.d.ts.map +1 -0
- package/dist/saves/types.js +2 -0
- package/dist/saves/types.js.map +1 -0
- package/dist/storage.d.ts +124 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +229 -0
- package/dist/storage.js.map +1 -0
- package/dist/tests/game.test.d.ts +2 -0
- package/dist/tests/game.test.d.ts.map +1 -0
- package/dist/tests/game.test.js +602 -0
- package/dist/tests/game.test.js.map +1 -0
- package/dist/tests/interactiveMap.test.d.ts +2 -0
- package/dist/tests/interactiveMap.test.d.ts.map +1 -0
- package/dist/tests/interactiveMap.test.js +1003 -0
- package/dist/tests/interactiveMap.test.js.map +1 -0
- package/dist/tests/storage.test.d.ts +2 -0
- package/dist/tests/storage.test.d.ts.map +1 -0
- package/dist/tests/storage.test.js +328 -0
- package/dist/tests/storage.test.js.map +1 -0
- package/dist/tests/story.test.d.ts +2 -0
- package/dist/tests/story.test.d.ts.map +1 -0
- package/dist/tests/story.test.js +698 -0
- package/dist/tests/story.test.js.map +1 -0
- package/dist/types.d.ts +19 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +60 -0
|
@@ -0,0 +1,911 @@
|
|
|
1
|
+
import { ReactNode } from "react";
|
|
2
|
+
import { ButtonColor, ButtonVariant, EmptyObject, InitVarsType } from "../../types";
|
|
3
|
+
/**
|
|
4
|
+
* Base interface shared by all story components.
|
|
5
|
+
* Provides common properties for identification and visibility control.
|
|
6
|
+
*/
|
|
7
|
+
export interface BaseComponent {
|
|
8
|
+
/**
|
|
9
|
+
* Optional unique identifier for this component.
|
|
10
|
+
* Can be used to reference or manipulate specific components programmatically.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* { type: 'text', id: 'intro-text', content: 'Welcome!' }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
id?: string;
|
|
18
|
+
/**
|
|
19
|
+
* Controls the initial visibility state of the component.
|
|
20
|
+
*
|
|
21
|
+
* @remarks
|
|
22
|
+
* This property is designed for future UI implementation to support dynamic component visibility.
|
|
23
|
+
* Currently defined but not yet implemented in the UI layer.
|
|
24
|
+
*
|
|
25
|
+
* - `"display"` - Component is visible and rendered immediately (default behavior)
|
|
26
|
+
* - `"hidden"` - Component exists but is not visible initially
|
|
27
|
+
* - `"disclosure"` - Component is initially collapsed/hidden but can be expanded by user interaction
|
|
28
|
+
*
|
|
29
|
+
* @defaultValue `"display"`
|
|
30
|
+
*/
|
|
31
|
+
initialVariant?: "display" | "hidden" | "disclosure";
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Component for displaying text content in the story.
|
|
35
|
+
* Supports rich text, JSX elements, and multi-line content with preserved whitespace.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```typescript
|
|
39
|
+
* // Simple text
|
|
40
|
+
* { type: 'text', content: 'Once upon a time...' }
|
|
41
|
+
*
|
|
42
|
+
* // Multi-line text
|
|
43
|
+
* { type: 'text', content: 'Line 1\nLine 2\nLine 3' }
|
|
44
|
+
*
|
|
45
|
+
* // JSX content
|
|
46
|
+
* { type: 'text', content: <><strong>Bold</strong> and <em>italic</em></> }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export interface TextComponent extends BaseComponent {
|
|
50
|
+
/**
|
|
51
|
+
* Discriminator property identifying this as a text component.
|
|
52
|
+
*/
|
|
53
|
+
type: "text";
|
|
54
|
+
/**
|
|
55
|
+
* The text or React element to display.
|
|
56
|
+
* Supports strings, numbers, JSX elements, and any valid React node.
|
|
57
|
+
* Multi-line text is rendered with preserved whitespace and line breaks.
|
|
58
|
+
*/
|
|
59
|
+
content: ReactNode;
|
|
60
|
+
/**
|
|
61
|
+
* Optional configuration for styling and behavior.
|
|
62
|
+
*/
|
|
63
|
+
props?: {
|
|
64
|
+
/**
|
|
65
|
+
* CSS class name(s) to apply to the text container.
|
|
66
|
+
* Can be used to customize text appearance (color, font, alignment, etc.).
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* props: { className: 'text-lg font-bold text-center' }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
className?: string;
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Defines the heading level for a HeaderComponent.
|
|
78
|
+
* Maps to HTML heading elements (h1-h6), where:
|
|
79
|
+
* - 1 = h1 (largest, main title)
|
|
80
|
+
* - 6 = h6 (smallest, sub-sub-section)
|
|
81
|
+
*/
|
|
82
|
+
export type HeaderLevel = 1 | 2 | 3 | 4 | 5 | 6;
|
|
83
|
+
/**
|
|
84
|
+
* Component for displaying heading text at various levels.
|
|
85
|
+
* Headers provide semantic structure and visual hierarchy to story content.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* // Main title
|
|
90
|
+
* { type: 'header', content: 'Chapter 1: The Beginning', props: { level: 1 } }
|
|
91
|
+
*
|
|
92
|
+
* // Section heading
|
|
93
|
+
* { type: 'header', content: 'The Journey Begins', props: { level: 2 } }
|
|
94
|
+
*
|
|
95
|
+
* // With custom styling
|
|
96
|
+
* { type: 'header', content: 'Warning!', props: { level: 3, className: 'text-danger-600' } }
|
|
97
|
+
* ```
|
|
98
|
+
*/
|
|
99
|
+
export interface HeaderComponent extends BaseComponent {
|
|
100
|
+
/**
|
|
101
|
+
* Discriminator property identifying this as a header component.
|
|
102
|
+
*/
|
|
103
|
+
type: "header";
|
|
104
|
+
/**
|
|
105
|
+
* The header text to display.
|
|
106
|
+
* Plain text only - use TextComponent for rich content.
|
|
107
|
+
*/
|
|
108
|
+
content: string;
|
|
109
|
+
/**
|
|
110
|
+
* Optional configuration for header level and styling.
|
|
111
|
+
*/
|
|
112
|
+
props?: {
|
|
113
|
+
/**
|
|
114
|
+
* Semantic heading level (1-6) corresponding to HTML h1-h6 elements.
|
|
115
|
+
* Affects both visual size and document structure.
|
|
116
|
+
*
|
|
117
|
+
* @defaultValue 1
|
|
118
|
+
*/
|
|
119
|
+
level?: HeaderLevel;
|
|
120
|
+
/**
|
|
121
|
+
* CSS class name(s) to apply to the header.
|
|
122
|
+
* Can be used to override default styling or add custom appearance.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```typescript
|
|
126
|
+
* props: { className: 'text-primary-600 font-bold' }
|
|
127
|
+
* ```
|
|
128
|
+
*/
|
|
129
|
+
className?: string;
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Component for displaying images with built-in modal viewer support.
|
|
134
|
+
* By default, images can be clicked to open in a full-screen modal for better viewing.
|
|
135
|
+
*
|
|
136
|
+
* @example
|
|
137
|
+
* ```typescript
|
|
138
|
+
* // Basic image
|
|
139
|
+
* { type: 'image', content: '/images/scene.jpg' }
|
|
140
|
+
*
|
|
141
|
+
* // Image with alt text
|
|
142
|
+
* { type: 'image', content: '/avatar.png', props: { alt: 'Player avatar' } }
|
|
143
|
+
*
|
|
144
|
+
* // Image without modal
|
|
145
|
+
* { type: 'image', content: '/icon.png', props: { disableModal: true } }
|
|
146
|
+
*
|
|
147
|
+
* // Image with custom click handler
|
|
148
|
+
* {
|
|
149
|
+
* type: 'image',
|
|
150
|
+
* content: '/button.png',
|
|
151
|
+
* props: {
|
|
152
|
+
* disableModal: true,
|
|
153
|
+
* onClick: () => Game.jumpTo('next-scene')
|
|
154
|
+
* }
|
|
155
|
+
* }
|
|
156
|
+
* ```
|
|
157
|
+
*/
|
|
158
|
+
export interface ImageComponent extends BaseComponent {
|
|
159
|
+
/**
|
|
160
|
+
* Discriminator property identifying this as an image component.
|
|
161
|
+
*/
|
|
162
|
+
type: "image";
|
|
163
|
+
/**
|
|
164
|
+
* URL or path to the image file.
|
|
165
|
+
* Can be absolute URL, relative path, or path to public assets.
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* content: 'https://example.com/image.jpg' // Absolute URL
|
|
170
|
+
* content: '/images/scene.png' // Relative path
|
|
171
|
+
* content: 'scene.png' // Public folder asset
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
content: string;
|
|
175
|
+
/**
|
|
176
|
+
* Optional configuration for image behavior and styling.
|
|
177
|
+
*/
|
|
178
|
+
props?: {
|
|
179
|
+
/**
|
|
180
|
+
* Alternative text description for accessibility and SEO.
|
|
181
|
+
* Displayed when the image fails to load or for screen readers.
|
|
182
|
+
*
|
|
183
|
+
* @defaultValue `"image"`
|
|
184
|
+
*/
|
|
185
|
+
alt?: string;
|
|
186
|
+
/**
|
|
187
|
+
* CSS class name(s) to apply to the image element.
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* ```typescript
|
|
191
|
+
* props: { className: 'rounded-lg shadow-xl' }
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
className?: string;
|
|
195
|
+
/**
|
|
196
|
+
* When `true`, disables the modal viewer functionality.
|
|
197
|
+
* The image becomes a static element without click-to-enlarge behavior.
|
|
198
|
+
*
|
|
199
|
+
* @defaultValue false
|
|
200
|
+
*
|
|
201
|
+
* @remarks
|
|
202
|
+
* Set to `true` when using custom `onClick` handlers or for decorative images
|
|
203
|
+
* that shouldn't open in full-screen mode.
|
|
204
|
+
*/
|
|
205
|
+
disableModal?: boolean;
|
|
206
|
+
/**
|
|
207
|
+
* Optional click event handler.
|
|
208
|
+
* Called when the image is clicked (in addition to or instead of modal behavior).
|
|
209
|
+
*
|
|
210
|
+
* @remarks
|
|
211
|
+
* When both `onClick` and modal are enabled, `onClick` fires before the modal opens.
|
|
212
|
+
* To use only `onClick`, set `disableModal: true`.
|
|
213
|
+
*
|
|
214
|
+
* @example
|
|
215
|
+
* ```typescript
|
|
216
|
+
* props: {
|
|
217
|
+
* onClick: () => {
|
|
218
|
+
* console.log('Image clicked');
|
|
219
|
+
* Game.jumpTo('next-passage');
|
|
220
|
+
* },
|
|
221
|
+
* disableModal: true
|
|
222
|
+
* }
|
|
223
|
+
* ```
|
|
224
|
+
*/
|
|
225
|
+
onClick?: () => void;
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Component for displaying video content with standard HTML5 video controls.
|
|
230
|
+
* Supports local files and remote URLs with customizable playback behavior.
|
|
231
|
+
*
|
|
232
|
+
* @example
|
|
233
|
+
* ```typescript
|
|
234
|
+
* // Basic video with controls
|
|
235
|
+
* {
|
|
236
|
+
* type: 'video',
|
|
237
|
+
* content: '/videos/cutscene.mp4',
|
|
238
|
+
* props: { controls: true }
|
|
239
|
+
* }
|
|
240
|
+
*
|
|
241
|
+
* // Looping background video
|
|
242
|
+
* {
|
|
243
|
+
* type: 'video',
|
|
244
|
+
* content: '/videos/ambient.mp4',
|
|
245
|
+
* props: {
|
|
246
|
+
* autoPlay: true,
|
|
247
|
+
* loop: true,
|
|
248
|
+
* muted: true,
|
|
249
|
+
* controls: false
|
|
250
|
+
* }
|
|
251
|
+
* }
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
export interface VideoComponent extends BaseComponent {
|
|
255
|
+
/**
|
|
256
|
+
* Discriminator property identifying this as a video component.
|
|
257
|
+
*/
|
|
258
|
+
type: "video";
|
|
259
|
+
/**
|
|
260
|
+
* URL or path to the video file.
|
|
261
|
+
* Supports common formats (MP4, WebM, OGG) depending on browser support.
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* content: 'https://example.com/video.mp4' // Remote URL
|
|
266
|
+
* content: '/videos/intro.mp4' // Local path
|
|
267
|
+
* content: 'cutscene.mp4' // Public folder asset
|
|
268
|
+
* ```
|
|
269
|
+
*/
|
|
270
|
+
content: string;
|
|
271
|
+
/**
|
|
272
|
+
* Optional configuration for video playback and styling.
|
|
273
|
+
*/
|
|
274
|
+
props?: {
|
|
275
|
+
/**
|
|
276
|
+
* CSS class name(s) to apply to the video element.
|
|
277
|
+
*
|
|
278
|
+
* @example
|
|
279
|
+
* ```typescript
|
|
280
|
+
* props: { className: 'rounded-lg shadow-xl' }
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
className?: string;
|
|
284
|
+
/**
|
|
285
|
+
* Whether to display native browser video controls (play, pause, volume, etc.).
|
|
286
|
+
*
|
|
287
|
+
* @defaultValue false
|
|
288
|
+
*
|
|
289
|
+
* @remarks
|
|
290
|
+
* Set to `true` to allow user control over playback.
|
|
291
|
+
* Set to `false` for non-interactive videos or custom controls.
|
|
292
|
+
*/
|
|
293
|
+
controls?: boolean;
|
|
294
|
+
/**
|
|
295
|
+
* Whether the video should start playing automatically when rendered.
|
|
296
|
+
*
|
|
297
|
+
* @defaultValue true
|
|
298
|
+
*
|
|
299
|
+
* @remarks
|
|
300
|
+
* Many browsers restrict autoplay without user interaction, especially with audio.
|
|
301
|
+
* Consider setting `muted: true` for reliable autoplay behavior.
|
|
302
|
+
*/
|
|
303
|
+
autoPlay?: boolean;
|
|
304
|
+
/**
|
|
305
|
+
* Whether the video should restart from the beginning when it reaches the end.
|
|
306
|
+
*
|
|
307
|
+
* @defaultValue true
|
|
308
|
+
*
|
|
309
|
+
* @remarks
|
|
310
|
+
* Useful for ambient/background videos that should play continuously.
|
|
311
|
+
*/
|
|
312
|
+
loop?: boolean;
|
|
313
|
+
/**
|
|
314
|
+
* Whether the video audio should be muted.
|
|
315
|
+
*
|
|
316
|
+
* @defaultValue true
|
|
317
|
+
*
|
|
318
|
+
* @remarks
|
|
319
|
+
* Setting to `true` helps bypass browser autoplay restrictions.
|
|
320
|
+
* Users can still unmute via controls if `controls: true`.
|
|
321
|
+
*/
|
|
322
|
+
muted?: boolean;
|
|
323
|
+
};
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Represents an interactive button action within a story.
|
|
327
|
+
* Used to create player choices, navigation buttons, and interactive elements.
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* ```typescript
|
|
331
|
+
* // Simple navigation action
|
|
332
|
+
* {
|
|
333
|
+
* label: 'Continue',
|
|
334
|
+
* action: () => Game.jumpTo('next-scene')
|
|
335
|
+
* }
|
|
336
|
+
*
|
|
337
|
+
* // Action with styling
|
|
338
|
+
* {
|
|
339
|
+
* label: 'Attack',
|
|
340
|
+
* action: () => combat.attack(),
|
|
341
|
+
* color: 'danger',
|
|
342
|
+
* variant: 'solid'
|
|
343
|
+
* }
|
|
344
|
+
*
|
|
345
|
+
* // Disabled action with tooltip
|
|
346
|
+
* {
|
|
347
|
+
* label: 'Open Door',
|
|
348
|
+
* action: () => {},
|
|
349
|
+
* isDisabled: true,
|
|
350
|
+
* tooltip: {
|
|
351
|
+
* content: 'You need a key to open this door',
|
|
352
|
+
* position: 'top'
|
|
353
|
+
* }
|
|
354
|
+
* }
|
|
355
|
+
* ```
|
|
356
|
+
*/
|
|
357
|
+
export type ActionType = {
|
|
358
|
+
/**
|
|
359
|
+
* The text displayed on the button.
|
|
360
|
+
* Should clearly describe the action the player will take.
|
|
361
|
+
*/
|
|
362
|
+
label: string;
|
|
363
|
+
/**
|
|
364
|
+
* Callback function executed when the button is clicked.
|
|
365
|
+
* Typically used for navigation, state changes, or triggering game events.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* action: () => {
|
|
370
|
+
* player.inventory.add('key');
|
|
371
|
+
* Game.jumpTo('next-room');
|
|
372
|
+
* }
|
|
373
|
+
* ```
|
|
374
|
+
*/
|
|
375
|
+
action: () => void;
|
|
376
|
+
/**
|
|
377
|
+
* Visual color scheme for the button.
|
|
378
|
+
* Maps to semantic color tokens in the UI theme.
|
|
379
|
+
*
|
|
380
|
+
* @defaultValue `"primary"`
|
|
381
|
+
*
|
|
382
|
+
* @remarks
|
|
383
|
+
* Available colors:
|
|
384
|
+
* - `"default"` - Neutral/muted appearance
|
|
385
|
+
* - `"primary"` - Main action color
|
|
386
|
+
* - `"secondary"` - Alternative action color
|
|
387
|
+
* - `"success"` - Positive/confirmation actions
|
|
388
|
+
* - `"warning"` - Caution/important actions
|
|
389
|
+
* - `"danger"` - Destructive/negative actions
|
|
390
|
+
*/
|
|
391
|
+
color?: ButtonColor;
|
|
392
|
+
/**
|
|
393
|
+
* Visual style variant for the button.
|
|
394
|
+
*
|
|
395
|
+
* @defaultValue `"solid"`
|
|
396
|
+
*
|
|
397
|
+
* @remarks
|
|
398
|
+
* Available variants:
|
|
399
|
+
* - `"solid"` - Filled background
|
|
400
|
+
* - `"bordered"` - Outline style
|
|
401
|
+
* - `"light"` - Subtle background
|
|
402
|
+
* - `"flat"` - No background, minimal style
|
|
403
|
+
* - `"faded"` - Translucent background
|
|
404
|
+
* - `"shadow"` - With drop shadow
|
|
405
|
+
* - `"ghost"` - Minimal, text-only style
|
|
406
|
+
*/
|
|
407
|
+
variant?: ButtonVariant;
|
|
408
|
+
/**
|
|
409
|
+
* Whether the button should be disabled (non-interactive).
|
|
410
|
+
* Disabled buttons are visually dimmed and cannot be clicked.
|
|
411
|
+
*
|
|
412
|
+
* @defaultValue false
|
|
413
|
+
*
|
|
414
|
+
* @remarks
|
|
415
|
+
* Useful for conditional actions based on game state.
|
|
416
|
+
* Combine with `tooltip` to explain why the action is unavailable.
|
|
417
|
+
*/
|
|
418
|
+
isDisabled?: boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Optional tooltip configuration.
|
|
421
|
+
* Displays additional information when the user hovers over the button.
|
|
422
|
+
*/
|
|
423
|
+
tooltip?: {
|
|
424
|
+
/**
|
|
425
|
+
* The text or message to show in the tooltip.
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```typescript
|
|
429
|
+
* content: 'Requires 50 gold coins'
|
|
430
|
+
* ```
|
|
431
|
+
*/
|
|
432
|
+
content: string;
|
|
433
|
+
/**
|
|
434
|
+
* Position of the tooltip relative to the button.
|
|
435
|
+
*
|
|
436
|
+
* @defaultValue `"top"`
|
|
437
|
+
*/
|
|
438
|
+
position?: "top" | "bottom" | "left" | "right";
|
|
439
|
+
/**
|
|
440
|
+
* CSS class name(s) to apply to the tooltip.
|
|
441
|
+
*
|
|
442
|
+
* @example
|
|
443
|
+
* ```typescript
|
|
444
|
+
* className: 'bg-danger-500 text-white'
|
|
445
|
+
* ```
|
|
446
|
+
*/
|
|
447
|
+
className?: string;
|
|
448
|
+
};
|
|
449
|
+
/**
|
|
450
|
+
* CSS class name(s) to apply to the button element.
|
|
451
|
+
*
|
|
452
|
+
* @example
|
|
453
|
+
* ```typescript
|
|
454
|
+
* className: 'w-full text-lg font-bold'
|
|
455
|
+
* ```
|
|
456
|
+
*/
|
|
457
|
+
className?: string;
|
|
458
|
+
};
|
|
459
|
+
/**
|
|
460
|
+
* Component for displaying a group of interactive action buttons.
|
|
461
|
+
* Used to present player choices, navigation options, or any interactive decisions.
|
|
462
|
+
*
|
|
463
|
+
* @example
|
|
464
|
+
* ```typescript
|
|
465
|
+
* // Horizontal action buttons (default)
|
|
466
|
+
* {
|
|
467
|
+
* type: 'actions',
|
|
468
|
+
* content: [
|
|
469
|
+
* { label: 'Go North', action: () => Game.jumpTo('north-room') },
|
|
470
|
+
* { label: 'Go South', action: () => Game.jumpTo('south-room') }
|
|
471
|
+
* ]
|
|
472
|
+
* }
|
|
473
|
+
*
|
|
474
|
+
* // Vertical layout for dialogue choices
|
|
475
|
+
* {
|
|
476
|
+
* type: 'actions',
|
|
477
|
+
* props: { direction: 'vertical' },
|
|
478
|
+
* content: [
|
|
479
|
+
* { label: 'Tell the truth', action: () => increaseHonesty() },
|
|
480
|
+
* { label: 'Lie', action: () => decreaseHonesty() },
|
|
481
|
+
* { label: 'Say nothing', action: () => Game.jumpTo('silence') }
|
|
482
|
+
* ]
|
|
483
|
+
* }
|
|
484
|
+
* ```
|
|
485
|
+
*/
|
|
486
|
+
export interface ActionsComponent extends BaseComponent {
|
|
487
|
+
/**
|
|
488
|
+
* Discriminator property identifying this as an actions component.
|
|
489
|
+
*/
|
|
490
|
+
type: "actions";
|
|
491
|
+
/**
|
|
492
|
+
* Array of action buttons to display.
|
|
493
|
+
* Each action represents a choice or interactive option for the player.
|
|
494
|
+
*/
|
|
495
|
+
content: Array<ActionType>;
|
|
496
|
+
/**
|
|
497
|
+
* Optional configuration for layout and styling.
|
|
498
|
+
*/
|
|
499
|
+
props?: {
|
|
500
|
+
/**
|
|
501
|
+
* Layout direction for the action buttons.
|
|
502
|
+
*
|
|
503
|
+
* @defaultValue `"horizontal"`
|
|
504
|
+
*
|
|
505
|
+
* @remarks
|
|
506
|
+
* - `"horizontal"` - Buttons arranged in a row (wraps on small screens)
|
|
507
|
+
* - `"vertical"` - Buttons stacked in a column (better for many options or long labels)
|
|
508
|
+
*/
|
|
509
|
+
direction?: "horizontal" | "vertical";
|
|
510
|
+
/**
|
|
511
|
+
* CSS class name(s) to apply to the actions container.
|
|
512
|
+
*
|
|
513
|
+
* @example
|
|
514
|
+
* ```typescript
|
|
515
|
+
* props: { className: 'gap-4 p-4' }
|
|
516
|
+
* ```
|
|
517
|
+
*/
|
|
518
|
+
className?: string;
|
|
519
|
+
};
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Component for embedding another story passage within the current story.
|
|
523
|
+
* Enables composition and reuse of story content.
|
|
524
|
+
*
|
|
525
|
+
* @example
|
|
526
|
+
* ```typescript
|
|
527
|
+
* // Main story that includes a shared intro
|
|
528
|
+
* newStory('chapter-1', () => [
|
|
529
|
+
* { type: 'anotherStory', storyId: 'common-intro' },
|
|
530
|
+
* { type: 'text', content: 'Chapter 1 specific content...' }
|
|
531
|
+
* ]);
|
|
532
|
+
*
|
|
533
|
+
* // Reusable story component
|
|
534
|
+
* newStory('common-intro', () => [
|
|
535
|
+
* { type: 'header', content: 'Welcome', props: { level: 1 } },
|
|
536
|
+
* { type: 'text', content: 'This intro is shared across multiple chapters.' }
|
|
537
|
+
* ]);
|
|
538
|
+
* ```
|
|
539
|
+
*
|
|
540
|
+
* @remarks
|
|
541
|
+
* Use this to:
|
|
542
|
+
* - Reuse common story segments (intros, outros, recurring dialogues)
|
|
543
|
+
* - Create modular story components
|
|
544
|
+
* - Implement story templates or patterns
|
|
545
|
+
* - Build complex narratives from smaller pieces
|
|
546
|
+
*/
|
|
547
|
+
export interface AnotherStoryComponent extends BaseComponent {
|
|
548
|
+
/**
|
|
549
|
+
* Discriminator property identifying this as an embedded story component.
|
|
550
|
+
*/
|
|
551
|
+
type: "anotherStory";
|
|
552
|
+
/**
|
|
553
|
+
* The unique identifier of the story passage to embed.
|
|
554
|
+
* Must reference a story that has been registered with `newStory()`.
|
|
555
|
+
*
|
|
556
|
+
* @example
|
|
557
|
+
* ```typescript
|
|
558
|
+
* storyId: 'common-intro'
|
|
559
|
+
* storyId: 'character-dialogue-bob'
|
|
560
|
+
* ```
|
|
561
|
+
*
|
|
562
|
+
* @remarks
|
|
563
|
+
* If the referenced story ID doesn't exist, the component will fail to render.
|
|
564
|
+
* Ensure the story is registered before it's referenced.
|
|
565
|
+
*/
|
|
566
|
+
storyId: string;
|
|
567
|
+
}
|
|
568
|
+
/**
|
|
569
|
+
* Defines which side of the conversation view a message appears on.
|
|
570
|
+
* Typically used to distinguish between different speakers or perspectives.
|
|
571
|
+
*/
|
|
572
|
+
export type ConversationBubbleSide = "left" | "right";
|
|
573
|
+
/**
|
|
574
|
+
* Represents a single message/bubble in a conversation sequence.
|
|
575
|
+
* Can include speaker information, avatar, and custom styling.
|
|
576
|
+
*
|
|
577
|
+
* @example
|
|
578
|
+
* ```typescript
|
|
579
|
+
* // Simple message
|
|
580
|
+
* { content: 'Hello there!' }
|
|
581
|
+
*
|
|
582
|
+
* // Message with speaker
|
|
583
|
+
* {
|
|
584
|
+
* content: 'How can I help you?',
|
|
585
|
+
* who: { name: 'Shopkeeper' },
|
|
586
|
+
* side: 'left'
|
|
587
|
+
* }
|
|
588
|
+
*
|
|
589
|
+
* // Message with avatar
|
|
590
|
+
* {
|
|
591
|
+
* content: 'I need supplies.',
|
|
592
|
+
* who: {
|
|
593
|
+
* name: 'Player',
|
|
594
|
+
* avatar: '/avatars/player.png'
|
|
595
|
+
* },
|
|
596
|
+
* side: 'right'
|
|
597
|
+
* }
|
|
598
|
+
*
|
|
599
|
+
* // Message with custom color
|
|
600
|
+
* {
|
|
601
|
+
* content: 'System message',
|
|
602
|
+
* color: '#ff6b6b',
|
|
603
|
+
* side: 'left'
|
|
604
|
+
* }
|
|
605
|
+
* ```
|
|
606
|
+
*/
|
|
607
|
+
export type ConversationBubble = {
|
|
608
|
+
/**
|
|
609
|
+
* Optional speaker information for this message.
|
|
610
|
+
*/
|
|
611
|
+
who?: {
|
|
612
|
+
/**
|
|
613
|
+
* Display name of the speaker.
|
|
614
|
+
* Shown with the message or as avatar fallback (first letter).
|
|
615
|
+
*/
|
|
616
|
+
name?: string;
|
|
617
|
+
/**
|
|
618
|
+
* URL or path to the speaker's avatar image.
|
|
619
|
+
* If not provided, a generated avatar with the first letter of the name is shown.
|
|
620
|
+
*
|
|
621
|
+
* @example
|
|
622
|
+
* ```typescript
|
|
623
|
+
* avatar: '/characters/merchant.png'
|
|
624
|
+
* avatar: 'https://example.com/avatars/123.jpg'
|
|
625
|
+
* ```
|
|
626
|
+
*/
|
|
627
|
+
avatar?: string;
|
|
628
|
+
};
|
|
629
|
+
/**
|
|
630
|
+
* The message content to display.
|
|
631
|
+
* Supports strings, JSX elements, and any valid React node.
|
|
632
|
+
*/
|
|
633
|
+
content: ReactNode;
|
|
634
|
+
/**
|
|
635
|
+
* Optional custom background color for the message bubble.
|
|
636
|
+
* Must be a valid hex color code.
|
|
637
|
+
*
|
|
638
|
+
* @example
|
|
639
|
+
* ```typescript
|
|
640
|
+
* color: '#3b82f6' // Blue
|
|
641
|
+
* color: '#ef4444' // Red
|
|
642
|
+
* ```
|
|
643
|
+
*
|
|
644
|
+
* @remarks
|
|
645
|
+
* When not provided, the color is determined by the conversation variant and side.
|
|
646
|
+
*/
|
|
647
|
+
color?: `#${string}`;
|
|
648
|
+
/**
|
|
649
|
+
* Which side of the conversation to display this message.
|
|
650
|
+
*
|
|
651
|
+
* @defaultValue `"left"`
|
|
652
|
+
*
|
|
653
|
+
* @remarks
|
|
654
|
+
* - `"left"` - Typically used for NPCs or other characters
|
|
655
|
+
* - `"right"` - Typically used for the player character
|
|
656
|
+
*/
|
|
657
|
+
side?: ConversationBubbleSide;
|
|
658
|
+
/**
|
|
659
|
+
* Optional CSS class overrides for fine-grained styling control.
|
|
660
|
+
*/
|
|
661
|
+
props?: {
|
|
662
|
+
/**
|
|
663
|
+
* CSS class names for different parts of the bubble.
|
|
664
|
+
*/
|
|
665
|
+
classNames?: {
|
|
666
|
+
/**
|
|
667
|
+
* CSS class for the entire bubble container.
|
|
668
|
+
* Controls layout, spacing, and alignment.
|
|
669
|
+
*/
|
|
670
|
+
base?: string;
|
|
671
|
+
/**
|
|
672
|
+
* CSS class for the message content area.
|
|
673
|
+
* Controls text styling, padding, and background.
|
|
674
|
+
*/
|
|
675
|
+
content?: string;
|
|
676
|
+
/**
|
|
677
|
+
* CSS class for the avatar element.
|
|
678
|
+
* Controls avatar size, shape, and positioning.
|
|
679
|
+
*/
|
|
680
|
+
avatar?: string;
|
|
681
|
+
};
|
|
682
|
+
};
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Visual style preset for conversation display.
|
|
686
|
+
* Each variant provides different bubble styling and layout.
|
|
687
|
+
*/
|
|
688
|
+
export type ConversationVariant = "chat" | "messenger";
|
|
689
|
+
/**
|
|
690
|
+
* Controls how conversation messages are revealed to the player.
|
|
691
|
+
*/
|
|
692
|
+
export type ConversationAppearance = "atOnce" | "byClick";
|
|
693
|
+
/**
|
|
694
|
+
* Component for displaying dialogue, conversations, or sequential messages.
|
|
695
|
+
* Supports different visual styles and progressive message reveal.
|
|
696
|
+
*
|
|
697
|
+
* @example
|
|
698
|
+
* ```typescript
|
|
699
|
+
* // All messages shown at once (default)
|
|
700
|
+
* {
|
|
701
|
+
* type: 'conversation',
|
|
702
|
+
* content: [
|
|
703
|
+
* { content: 'Hello!', who: { name: 'NPC' }, side: 'left' },
|
|
704
|
+
* { content: 'Hi there!', who: { name: 'Player' }, side: 'right' }
|
|
705
|
+
* ]
|
|
706
|
+
* }
|
|
707
|
+
*
|
|
708
|
+
* // Progressive reveal - click to show next message
|
|
709
|
+
* {
|
|
710
|
+
* type: 'conversation',
|
|
711
|
+
* appearance: 'byClick',
|
|
712
|
+
* content: [
|
|
713
|
+
* { content: 'Let me tell you a story...', side: 'left' },
|
|
714
|
+
* { content: 'It was a dark and stormy night...', side: 'left' },
|
|
715
|
+
* { content: 'When suddenly...', side: 'left' }
|
|
716
|
+
* ]
|
|
717
|
+
* }
|
|
718
|
+
*
|
|
719
|
+
* // Messenger-style conversation
|
|
720
|
+
* {
|
|
721
|
+
* type: 'conversation',
|
|
722
|
+
* props: { variant: 'messenger' },
|
|
723
|
+
* content: [
|
|
724
|
+
* {
|
|
725
|
+
* content: 'Check out this new quest!',
|
|
726
|
+
* who: { name: 'Guild Master', avatar: '/guild.png' },
|
|
727
|
+
* side: 'left'
|
|
728
|
+
* },
|
|
729
|
+
* {
|
|
730
|
+
* content: 'I\'m interested!',
|
|
731
|
+
* who: { name: 'You' },
|
|
732
|
+
* side: 'right'
|
|
733
|
+
* }
|
|
734
|
+
* ]
|
|
735
|
+
* }
|
|
736
|
+
* ```
|
|
737
|
+
*/
|
|
738
|
+
export interface ConversationComponent extends BaseComponent {
|
|
739
|
+
/**
|
|
740
|
+
* Discriminator property identifying this as a conversation component.
|
|
741
|
+
*/
|
|
742
|
+
type: "conversation";
|
|
743
|
+
/**
|
|
744
|
+
* Array of conversation bubbles/messages to display.
|
|
745
|
+
* Order determines the sequence in which messages appear.
|
|
746
|
+
*/
|
|
747
|
+
content: Array<ConversationBubble>;
|
|
748
|
+
/**
|
|
749
|
+
* Controls how messages are revealed to the player.
|
|
750
|
+
*
|
|
751
|
+
* @defaultValue `"atOnce"`
|
|
752
|
+
*
|
|
753
|
+
* @remarks
|
|
754
|
+
* - `"atOnce"` - All messages visible immediately (default)
|
|
755
|
+
* - `"byClick"` - Messages appear one at a time when clicked
|
|
756
|
+
* - Creates a progressive storytelling effect
|
|
757
|
+
* - Click anywhere in the conversation area to reveal the next message
|
|
758
|
+
* - Useful for paced dialogue or dramatic reveals
|
|
759
|
+
*/
|
|
760
|
+
appearance?: ConversationAppearance;
|
|
761
|
+
/**
|
|
762
|
+
* Optional configuration for visual style and layout.
|
|
763
|
+
*/
|
|
764
|
+
props?: {
|
|
765
|
+
/**
|
|
766
|
+
* Visual style preset for the conversation.
|
|
767
|
+
*
|
|
768
|
+
* @defaultValue `"chat"`
|
|
769
|
+
*
|
|
770
|
+
* @remarks
|
|
771
|
+
* - `"chat"` - Casual chat interface style
|
|
772
|
+
* - Rounded bubbles with colored backgrounds
|
|
773
|
+
* - Minimal shadows, compact layout
|
|
774
|
+
* - Good for informal conversations
|
|
775
|
+
*
|
|
776
|
+
* - `"messenger"` - Messaging app style (like SMS or WhatsApp)
|
|
777
|
+
* - Card-like bubbles with shadows
|
|
778
|
+
* - More pronounced visual separation
|
|
779
|
+
* - Professional appearance, good for important dialogues
|
|
780
|
+
*/
|
|
781
|
+
variant?: ConversationVariant;
|
|
782
|
+
/**
|
|
783
|
+
* CSS class name(s) to apply to the conversation container.
|
|
784
|
+
*
|
|
785
|
+
* @example
|
|
786
|
+
* ```typescript
|
|
787
|
+
* props: { className: 'my-8 p-4 bg-muted-50 rounded-lg' }
|
|
788
|
+
* ```
|
|
789
|
+
*/
|
|
790
|
+
className?: string;
|
|
791
|
+
};
|
|
792
|
+
}
|
|
793
|
+
/**
|
|
794
|
+
* Union type of all available story component types.
|
|
795
|
+
* Used for type-safe story content arrays.
|
|
796
|
+
*
|
|
797
|
+
* @remarks
|
|
798
|
+
* This discriminated union allows TypeScript to narrow component types
|
|
799
|
+
* based on the `type` property when rendering or processing components.
|
|
800
|
+
*/
|
|
801
|
+
export type Component = TextComponent | HeaderComponent | ImageComponent | VideoComponent | ActionsComponent | ConversationComponent | AnotherStoryComponent;
|
|
802
|
+
/**
|
|
803
|
+
* Function type for story content generation.
|
|
804
|
+
* Receives props and returns an array of components to display.
|
|
805
|
+
*
|
|
806
|
+
* @template T - Type of props passed to the story (extends InitVarsType)
|
|
807
|
+
* @param props - Properties used for conditional rendering or dynamic content
|
|
808
|
+
* @returns Array of components that make up the story
|
|
809
|
+
*
|
|
810
|
+
* @example
|
|
811
|
+
* ```typescript
|
|
812
|
+
* // Simple static story
|
|
813
|
+
* const story: StoryContent = () => [
|
|
814
|
+
* { type: 'header', content: 'Welcome' },
|
|
815
|
+
* { type: 'text', content: 'Your adventure begins...' }
|
|
816
|
+
* ];
|
|
817
|
+
*
|
|
818
|
+
* // Dynamic story based on game state
|
|
819
|
+
* const story: StoryContent<{ playerName: string; hasKey: boolean }> = (props) => [
|
|
820
|
+
* { type: 'text', content: `Hello, ${props.playerName}!` },
|
|
821
|
+
* {
|
|
822
|
+
* type: 'actions',
|
|
823
|
+
* content: [
|
|
824
|
+
* {
|
|
825
|
+
* label: 'Open Door',
|
|
826
|
+
* action: () => Game.jumpTo('next-room'),
|
|
827
|
+
* isDisabled: !props.hasKey,
|
|
828
|
+
* tooltip: props.hasKey ? undefined : {
|
|
829
|
+
* content: 'You need a key to open this door'
|
|
830
|
+
* }
|
|
831
|
+
* }
|
|
832
|
+
* ]
|
|
833
|
+
* }
|
|
834
|
+
* ];
|
|
835
|
+
* ```
|
|
836
|
+
*
|
|
837
|
+
* @remarks
|
|
838
|
+
* The function is called during rendering, so:
|
|
839
|
+
* - Keep logic lightweight for performance
|
|
840
|
+
* - Access reactive game state through props for dynamic content
|
|
841
|
+
* - Return value is memoized based on props
|
|
842
|
+
*/
|
|
843
|
+
export type StoryContent = <T extends InitVarsType = EmptyObject>(props: T) => Array<Component>;
|
|
844
|
+
/**
|
|
845
|
+
* Configuration options for story appearance and behavior.
|
|
846
|
+
* Applied to the entire story passage.
|
|
847
|
+
*
|
|
848
|
+
* @example
|
|
849
|
+
* ```typescript
|
|
850
|
+
* const options: StoryOptions = {
|
|
851
|
+
* background: {
|
|
852
|
+
* image: '/backgrounds/forest.jpg'
|
|
853
|
+
* },
|
|
854
|
+
* classNames: {
|
|
855
|
+
* base: 'min-h-screen bg-cover bg-center',
|
|
856
|
+
* container: 'max-w-4xl mx-auto p-8'
|
|
857
|
+
* }
|
|
858
|
+
* };
|
|
859
|
+
*
|
|
860
|
+
* newStory('forest-scene', () => [...], options);
|
|
861
|
+
* ```
|
|
862
|
+
*/
|
|
863
|
+
export type StoryOptions = {
|
|
864
|
+
/**
|
|
865
|
+
* Background configuration for the story.
|
|
866
|
+
*/
|
|
867
|
+
background?: {
|
|
868
|
+
/**
|
|
869
|
+
* URL or path to the background image.
|
|
870
|
+
* Can be a static string or a function that returns a string for dynamic backgrounds.
|
|
871
|
+
*
|
|
872
|
+
* @example
|
|
873
|
+
* ```typescript
|
|
874
|
+
* // Static background
|
|
875
|
+
* image: '/backgrounds/castle.jpg'
|
|
876
|
+
*
|
|
877
|
+
* // Dynamic background based on game state
|
|
878
|
+
* image: () => player.location === 'night'
|
|
879
|
+
* ? '/backgrounds/castle-night.jpg'
|
|
880
|
+
* : '/backgrounds/castle-day.jpg'
|
|
881
|
+
* ```
|
|
882
|
+
*/
|
|
883
|
+
image?: string | (() => string);
|
|
884
|
+
};
|
|
885
|
+
/**
|
|
886
|
+
* CSS class name overrides for story layout.
|
|
887
|
+
*/
|
|
888
|
+
classNames?: {
|
|
889
|
+
/**
|
|
890
|
+
* CSS class for the outermost story container.
|
|
891
|
+
* Controls overall layout, background, and viewport settings.
|
|
892
|
+
*
|
|
893
|
+
* @example
|
|
894
|
+
* ```typescript
|
|
895
|
+
* base: 'min-h-screen flex items-center justify-center bg-gradient-to-b from-blue-900 to-black'
|
|
896
|
+
* ```
|
|
897
|
+
*/
|
|
898
|
+
base?: string;
|
|
899
|
+
/**
|
|
900
|
+
* CSS class for the inner content container.
|
|
901
|
+
* Controls content width, padding, and component spacing.
|
|
902
|
+
*
|
|
903
|
+
* @example
|
|
904
|
+
* ```typescript
|
|
905
|
+
* container: 'max-w-2xl p-6 bg-card/90 backdrop-blur-sm rounded-xl shadow-2xl'
|
|
906
|
+
* ```
|
|
907
|
+
*/
|
|
908
|
+
container?: string;
|
|
909
|
+
};
|
|
910
|
+
};
|
|
911
|
+
//# sourceMappingURL=types.d.ts.map
|