@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.
Files changed (178) hide show
  1. package/README.md +744 -0
  2. package/dist/baseGameObject.d.ts +90 -0
  3. package/dist/baseGameObject.d.ts.map +1 -0
  4. package/dist/baseGameObject.js +109 -0
  5. package/dist/baseGameObject.js.map +1 -0
  6. package/dist/constants.d.ts +12 -0
  7. package/dist/constants.d.ts.map +1 -0
  8. package/dist/constants.js +12 -0
  9. package/dist/constants.js.map +1 -0
  10. package/dist/game.d.ts +294 -0
  11. package/dist/game.d.ts.map +1 -0
  12. package/dist/game.js +489 -0
  13. package/dist/game.js.map +1 -0
  14. package/dist/helpers.d.ts +2 -0
  15. package/dist/helpers.d.ts.map +1 -0
  16. package/dist/helpers.js +6 -0
  17. package/dist/helpers.js.map +1 -0
  18. package/dist/hooks/index.d.ts +4 -0
  19. package/dist/hooks/index.d.ts.map +1 -0
  20. package/dist/hooks/index.js +4 -0
  21. package/dist/hooks/index.js.map +1 -0
  22. package/dist/hooks/useCurrentPassage.d.ts +10 -0
  23. package/dist/hooks/useCurrentPassage.d.ts.map +1 -0
  24. package/dist/hooks/useCurrentPassage.js +17 -0
  25. package/dist/hooks/useCurrentPassage.js.map +1 -0
  26. package/dist/hooks/useGameEntity.d.ts +21 -0
  27. package/dist/hooks/useGameEntity.d.ts.map +1 -0
  28. package/dist/hooks/useGameEntity.js +70 -0
  29. package/dist/hooks/useGameEntity.js.map +1 -0
  30. package/dist/hooks/useGameIsStarted.d.ts +12 -0
  31. package/dist/hooks/useGameIsStarted.d.ts.map +1 -0
  32. package/dist/hooks/useGameIsStarted.js +18 -0
  33. package/dist/hooks/useGameIsStarted.js.map +1 -0
  34. package/dist/index.d.ts +12 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +10 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/logger.d.ts +8 -0
  39. package/dist/logger.d.ts.map +1 -0
  40. package/dist/logger.js +36 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/options.d.ts +13 -0
  43. package/dist/options.d.ts.map +1 -0
  44. package/dist/options.js +15 -0
  45. package/dist/options.js.map +1 -0
  46. package/dist/passages/interactiveMap/fabric.d.ts +4 -0
  47. package/dist/passages/interactiveMap/fabric.d.ts.map +1 -0
  48. package/dist/passages/interactiveMap/fabric.js +3 -0
  49. package/dist/passages/interactiveMap/fabric.js.map +1 -0
  50. package/dist/passages/interactiveMap/index.d.ts +4 -0
  51. package/dist/passages/interactiveMap/index.d.ts.map +1 -0
  52. package/dist/passages/interactiveMap/index.js +4 -0
  53. package/dist/passages/interactiveMap/index.js.map +1 -0
  54. package/dist/passages/interactiveMap/interactiveMap.d.ts +89 -0
  55. package/dist/passages/interactiveMap/interactiveMap.d.ts.map +1 -0
  56. package/dist/passages/interactiveMap/interactiveMap.js +103 -0
  57. package/dist/passages/interactiveMap/interactiveMap.js.map +1 -0
  58. package/dist/passages/interactiveMap/types.d.ts +822 -0
  59. package/dist/passages/interactiveMap/types.d.ts.map +1 -0
  60. package/dist/passages/interactiveMap/types.js +2 -0
  61. package/dist/passages/interactiveMap/types.js.map +1 -0
  62. package/dist/passages/passage.d.ts +57 -0
  63. package/dist/passages/passage.d.ts.map +1 -0
  64. package/dist/passages/passage.js +64 -0
  65. package/dist/passages/passage.js.map +1 -0
  66. package/dist/passages/story/fabric.d.ts +4 -0
  67. package/dist/passages/story/fabric.d.ts.map +1 -0
  68. package/dist/passages/story/fabric.js +3 -0
  69. package/dist/passages/story/fabric.js.map +1 -0
  70. package/dist/passages/story/index.d.ts +5 -0
  71. package/dist/passages/story/index.d.ts.map +1 -0
  72. package/dist/passages/story/index.js +5 -0
  73. package/dist/passages/story/index.js.map +1 -0
  74. package/dist/passages/story/start.d.ts +14 -0
  75. package/dist/passages/story/start.d.ts.map +1 -0
  76. package/dist/passages/story/start.js +22 -0
  77. package/dist/passages/story/start.js.map +1 -0
  78. package/dist/passages/story/story.d.ts +84 -0
  79. package/dist/passages/story/story.d.ts.map +1 -0
  80. package/dist/passages/story/story.js +88 -0
  81. package/dist/passages/story/story.js.map +1 -0
  82. package/dist/passages/story/types.d.ts +911 -0
  83. package/dist/passages/story/types.d.ts.map +1 -0
  84. package/dist/passages/story/types.js +2 -0
  85. package/dist/passages/story/types.js.map +1 -0
  86. package/dist/passages/types/index.d.ts +3 -0
  87. package/dist/passages/types/index.d.ts.map +1 -0
  88. package/dist/passages/types/index.js +2 -0
  89. package/dist/passages/types/index.js.map +1 -0
  90. package/dist/passages/widget.d.ts +62 -0
  91. package/dist/passages/widget.d.ts.map +1 -0
  92. package/dist/passages/widget.js +66 -0
  93. package/dist/passages/widget.js.map +1 -0
  94. package/dist/saves/constants.d.ts +17 -0
  95. package/dist/saves/constants.d.ts.map +1 -0
  96. package/dist/saves/constants.js +17 -0
  97. package/dist/saves/constants.js.map +1 -0
  98. package/dist/saves/db.d.ts +119 -0
  99. package/dist/saves/db.d.ts.map +1 -0
  100. package/dist/saves/db.js +231 -0
  101. package/dist/saves/db.js.map +1 -0
  102. package/dist/saves/helpers.d.ts +28 -0
  103. package/dist/saves/helpers.d.ts.map +1 -0
  104. package/dist/saves/helpers.js +84 -0
  105. package/dist/saves/helpers.js.map +1 -0
  106. package/dist/saves/hooks/index.d.ts +10 -0
  107. package/dist/saves/hooks/index.d.ts.map +1 -0
  108. package/dist/saves/hooks/index.js +10 -0
  109. package/dist/saves/hooks/index.js.map +1 -0
  110. package/dist/saves/hooks/useDeleteAllSlots.d.ts +18 -0
  111. package/dist/saves/hooks/useDeleteAllSlots.d.ts.map +1 -0
  112. package/dist/saves/hooks/useDeleteAllSlots.js +18 -0
  113. package/dist/saves/hooks/useDeleteAllSlots.js.map +1 -0
  114. package/dist/saves/hooks/useDeleteGame.d.ts +22 -0
  115. package/dist/saves/hooks/useDeleteGame.d.ts.map +1 -0
  116. package/dist/saves/hooks/useDeleteGame.js +33 -0
  117. package/dist/saves/hooks/useDeleteGame.js.map +1 -0
  118. package/dist/saves/hooks/useExportSaves.d.ts +27 -0
  119. package/dist/saves/hooks/useExportSaves.d.ts.map +1 -0
  120. package/dist/saves/hooks/useExportSaves.js +54 -0
  121. package/dist/saves/hooks/useExportSaves.js.map +1 -0
  122. package/dist/saves/hooks/useImportSaves.d.ts +29 -0
  123. package/dist/saves/hooks/useImportSaves.d.ts.map +1 -0
  124. package/dist/saves/hooks/useImportSaves.js +108 -0
  125. package/dist/saves/hooks/useImportSaves.js.map +1 -0
  126. package/dist/saves/hooks/useLastLoadGame.d.ts +39 -0
  127. package/dist/saves/hooks/useLastLoadGame.d.ts.map +1 -0
  128. package/dist/saves/hooks/useLastLoadGame.js +72 -0
  129. package/dist/saves/hooks/useLastLoadGame.js.map +1 -0
  130. package/dist/saves/hooks/useLoadGame.d.ts +22 -0
  131. package/dist/saves/hooks/useLoadGame.d.ts.map +1 -0
  132. package/dist/saves/hooks/useLoadGame.js +40 -0
  133. package/dist/saves/hooks/useLoadGame.js.map +1 -0
  134. package/dist/saves/hooks/useRestartGame.d.ts +20 -0
  135. package/dist/saves/hooks/useRestartGame.d.ts.map +1 -0
  136. package/dist/saves/hooks/useRestartGame.js +29 -0
  137. package/dist/saves/hooks/useRestartGame.js.map +1 -0
  138. package/dist/saves/hooks/useSaveGame.d.ts +22 -0
  139. package/dist/saves/hooks/useSaveGame.d.ts.map +1 -0
  140. package/dist/saves/hooks/useSaveGame.js +34 -0
  141. package/dist/saves/hooks/useSaveGame.js.map +1 -0
  142. package/dist/saves/hooks/useSaveSlots.d.ts +45 -0
  143. package/dist/saves/hooks/useSaveSlots.d.ts.map +1 -0
  144. package/dist/saves/hooks/useSaveSlots.js +42 -0
  145. package/dist/saves/hooks/useSaveSlots.js.map +1 -0
  146. package/dist/saves/index.d.ts +4 -0
  147. package/dist/saves/index.d.ts.map +1 -0
  148. package/dist/saves/index.js +3 -0
  149. package/dist/saves/index.js.map +1 -0
  150. package/dist/saves/types.d.ts +52 -0
  151. package/dist/saves/types.d.ts.map +1 -0
  152. package/dist/saves/types.js +2 -0
  153. package/dist/saves/types.js.map +1 -0
  154. package/dist/storage.d.ts +124 -0
  155. package/dist/storage.d.ts.map +1 -0
  156. package/dist/storage.js +229 -0
  157. package/dist/storage.js.map +1 -0
  158. package/dist/tests/game.test.d.ts +2 -0
  159. package/dist/tests/game.test.d.ts.map +1 -0
  160. package/dist/tests/game.test.js +602 -0
  161. package/dist/tests/game.test.js.map +1 -0
  162. package/dist/tests/interactiveMap.test.d.ts +2 -0
  163. package/dist/tests/interactiveMap.test.d.ts.map +1 -0
  164. package/dist/tests/interactiveMap.test.js +1003 -0
  165. package/dist/tests/interactiveMap.test.js.map +1 -0
  166. package/dist/tests/storage.test.d.ts +2 -0
  167. package/dist/tests/storage.test.d.ts.map +1 -0
  168. package/dist/tests/storage.test.js +328 -0
  169. package/dist/tests/storage.test.js.map +1 -0
  170. package/dist/tests/story.test.d.ts +2 -0
  171. package/dist/tests/story.test.d.ts.map +1 -0
  172. package/dist/tests/story.test.js +698 -0
  173. package/dist/tests/story.test.js.map +1 -0
  174. package/dist/types.d.ts +19 -0
  175. package/dist/types.d.ts.map +1 -0
  176. package/dist/types.js +2 -0
  177. package/dist/types.js.map +1 -0
  178. 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