@rohal12/spindle 0.27.0 → 0.28.1

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rohal12/spindle",
3
- "version": "0.27.0",
3
+ "version": "0.28.1",
4
4
  "type": "module",
5
5
  "description": "A Preact-based story format for Twine 2.",
6
6
  "license": "Unlicense",
@@ -23,14 +23,14 @@
23
23
  ],
24
24
  "exports": {
25
25
  ".": {
26
- "types": "./dist/pkg/types/index.d.ts",
26
+ "types": "./types/index.d.ts",
27
27
  "import": "./dist/pkg/index.js"
28
28
  }
29
29
  },
30
30
  "files": [
31
31
  "dist/pkg/index.js",
32
32
  "dist/pkg/format.js",
33
- "dist/pkg/types",
33
+ "types",
34
34
  "src"
35
35
  ],
36
36
  "scripts": {
@@ -12,6 +12,7 @@ interface PassageDialogProps {
12
12
  fallbackMarkup?: string;
13
13
  panelClass?: string;
14
14
  onClose: () => void;
15
+ showCloseButton?: boolean;
15
16
  }
16
17
 
17
18
  export function PassageDialog({
@@ -19,6 +20,7 @@ export function PassageDialog({
19
20
  fallbackMarkup,
20
21
  panelClass,
21
22
  onClose,
23
+ showCloseButton = true,
22
24
  }: PassageDialogProps) {
23
25
  const storyData = useStoryStore((s) => s.storyData);
24
26
 
@@ -55,12 +57,14 @@ export function PassageDialog({
55
57
  onClick={handleBackdrop}
56
58
  >
57
59
  <div class={cls}>
58
- <button
59
- class="dialog-close"
60
- onClick={onClose}
61
- >
62
- ✕
63
- </button>
60
+ {showCloseButton && (
61
+ <button
62
+ class="dialog-close"
63
+ onClick={onClose}
64
+ >
65
+ ✕
66
+ </button>
67
+ )}
64
68
  <div class="dialog-body">{content}</div>
65
69
  </div>
66
70
  </div>
@@ -49,6 +49,7 @@ export function TriggerDialogHost() {
49
49
  passageName={current.passageName}
50
50
  panelClass={current.panelClass}
51
51
  onClose={handleClose}
52
+ showCloseButton={current.showCloseButton}
52
53
  />
53
54
  );
54
55
  }
@@ -3,11 +3,15 @@ import { PassageDialog } from '../PassageDialog';
3
3
 
4
4
  defineMacro({
5
5
  name: 'dialog',
6
+ block: true,
6
7
  interpolate: true,
7
8
  render({ rawArgs, children = [] }, ctx) {
8
9
  const [open, setOpen] = ctx.hooks.useState(false);
9
10
 
10
- const label = ctx.resolve?.(rawArgs.replace(/^["']|["']$/g, '')) ?? rawArgs;
11
+ const noclose = /\bnoclose\s*$/.test(rawArgs);
12
+ const labelRaw = rawArgs.replace(/\bnoclose\s*$/, '').trim();
13
+ const label =
14
+ ctx.resolve?.(labelRaw.replace(/^["']|["']$/g, '')) ?? labelRaw;
11
15
  const passageName = ctx
12
16
  .collectText(children)
13
17
  .trim()
@@ -26,6 +30,7 @@ defineMacro({
26
30
  <PassageDialog
27
31
  passageName={passageName}
28
32
  onClose={() => setOpen(false)}
33
+ showCloseButton={!noclose}
29
34
  />
30
35
  )}
31
36
  </>
@@ -18,6 +18,7 @@ interface MenubarActionConfig {
18
18
  passageName: string;
19
19
  fallbackMarkup?: string;
20
20
  panelClass?: string;
21
+ showCloseButton?: boolean;
21
22
  };
22
23
  }
23
24
 
@@ -72,6 +73,7 @@ export function defineMenubarAction(config: MenubarActionConfig) {
72
73
  fallbackMarkup={config.dialog.fallbackMarkup}
73
74
  panelClass={config.dialog.panelClass}
74
75
  onClose={() => setDialogOpen(false)}
76
+ showCloseButton={config.dialog.showCloseButton}
75
77
  />
76
78
  )}
77
79
  </>
package/src/story-api.ts CHANGED
@@ -80,7 +80,10 @@ export interface StoryAPI {
80
80
  callbackOrOptions: (() => void) | WatchOptions,
81
81
  ): () => void;
82
82
  unwatch(name: string): void;
83
- openDialog(passageName: string, options?: { panelClass?: string }): void;
83
+ openDialog(
84
+ passageName: string,
85
+ options?: { panelClass?: string; showCloseButton?: boolean },
86
+ ): void;
84
87
  closeDialog(): void;
85
88
  closeAllDialogs(): void;
86
89
  isDialogOpen(): boolean;
@@ -297,8 +300,15 @@ function createStoryAPI(): StoryAPI {
297
300
  removeTrigger(name);
298
301
  },
299
302
 
300
- openDialog(passageName: string, options?: { panelClass?: string }): void {
301
- pushDialog({ passageName, panelClass: options?.panelClass });
303
+ openDialog(
304
+ passageName: string,
305
+ options?: { panelClass?: string; showCloseButton?: boolean },
306
+ ): void {
307
+ pushDialog({
308
+ passageName,
309
+ panelClass: options?.panelClass,
310
+ showCloseButton: options?.showCloseButton,
311
+ });
302
312
  },
303
313
 
304
314
  closeDialog(): void {
package/src/triggers.ts CHANGED
@@ -13,6 +13,7 @@ export interface WatchOptions {
13
13
  export interface QueuedDialog {
14
14
  passageName: string;
15
15
  panelClass?: string;
16
+ showCloseButton?: boolean;
16
17
  }
17
18
 
18
19
  interface Trigger {
@@ -181,4 +181,23 @@ export interface StoryAPI {
181
181
  /** Set a custom function to generate save titles. */
182
182
  setTitleGenerator(fn: (payload: SavePayload) => string): void;
183
183
  };
184
+
185
+ /**
186
+ * Open a dialog rendering the given passage.
187
+ * @param passageName - The passage to render inside the dialog.
188
+ * @param options - Optional configuration for the dialog panel.
189
+ */
190
+ openDialog(
191
+ passageName: string,
192
+ options?: { panelClass?: string; showCloseButton?: boolean },
193
+ ): void;
194
+
195
+ /** Close the topmost open dialog. */
196
+ closeDialog(): void;
197
+
198
+ /** Close all open dialogs. */
199
+ closeAllDialogs(): void;
200
+
201
+ /** Check whether any dialog is currently open. */
202
+ isDialogOpen(): boolean;
184
203
  }
@@ -1,18 +0,0 @@
1
- import type { StoryAPI } from './index.js';
2
-
3
- declare global {
4
- /**
5
- * The main Spindle story API, available globally at runtime.
6
- * Provides access to variables, navigation, save/load, and visit tracking.
7
- *
8
- * @example
9
- * ```typescript
10
- * Story.set("health", 100);
11
- * Story.goto("Chapter 2");
12
- * if (Story.hasVisited("Secret Room")) { ... }
13
- * ```
14
- */
15
- const Story: StoryAPI;
16
- }
17
-
18
- export {};