@rohal12/spindle 0.15.0 → 0.16.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 (40) hide show
  1. package/dist/pkg/format.js +1 -1
  2. package/package.json +1 -1
  3. package/src/components/macros/Back.tsx +5 -6
  4. package/src/components/macros/Button.tsx +5 -9
  5. package/src/components/macros/Checkbox.tsx +5 -7
  6. package/src/components/macros/Computed.tsx +5 -5
  7. package/src/components/macros/Cycle.tsx +5 -9
  8. package/src/components/macros/Do.tsx +5 -6
  9. package/src/components/macros/For.tsx +5 -8
  10. package/src/components/macros/Forward.tsx +5 -6
  11. package/src/components/macros/Goto.tsx +5 -5
  12. package/src/components/macros/If.tsx +5 -5
  13. package/src/components/macros/Include.tsx +5 -7
  14. package/src/components/macros/Listbox.tsx +6 -9
  15. package/src/components/macros/MacroLink.tsx +6 -9
  16. package/src/components/macros/Meter.tsx +5 -7
  17. package/src/components/macros/Numberbox.tsx +5 -7
  18. package/src/components/macros/PassageDisplay.tsx +5 -6
  19. package/src/components/macros/Print.tsx +5 -7
  20. package/src/components/macros/QuickLoad.tsx +5 -6
  21. package/src/components/macros/QuickSave.tsx +5 -6
  22. package/src/components/macros/Radiobutton.tsx +5 -7
  23. package/src/components/macros/Repeat.tsx +6 -10
  24. package/src/components/macros/Restart.tsx +5 -6
  25. package/src/components/macros/Saves.tsx +5 -6
  26. package/src/components/macros/Set.tsx +5 -5
  27. package/src/components/macros/SettingsButton.tsx +5 -6
  28. package/src/components/macros/Stop.tsx +5 -1
  29. package/src/components/macros/StoryTitle.tsx +5 -6
  30. package/src/components/macros/Switch.tsx +7 -6
  31. package/src/components/macros/Textarea.tsx +5 -7
  32. package/src/components/macros/Textbox.tsx +5 -7
  33. package/src/components/macros/Timed.tsx +12 -14
  34. package/src/components/macros/Type.tsx +5 -9
  35. package/src/components/macros/Unset.tsx +5 -5
  36. package/src/components/macros/Widget.tsx +5 -7
  37. package/src/index.tsx +1 -0
  38. package/src/macros/register-builtins.ts +35 -0
  39. package/src/markup/render.tsx +36 -404
  40. package/src/registry.ts +13 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rohal12/spindle",
3
- "version": "0.15.0",
3
+ "version": "0.16.0",
4
4
  "type": "module",
5
5
  "description": "A Preact-based story format for Twine 2.",
6
6
  "license": "Unlicense",
@@ -1,12 +1,9 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface BackProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function Back({ className, id }: BackProps) {
6
+ export function Back({ className, id }: MacroProps) {
10
7
  const goBack = useStoryStore((s) => s.goBack);
11
8
  const canGoBack = useStoryStore((s) => s.historyIndex > 0);
12
9
  const cls = className ? `menubar-button ${className}` : 'menubar-button';
@@ -31,3 +28,5 @@ export function Back({ className, id }: BackProps) {
31
28
  </button>
32
29
  );
33
30
  }
31
+
32
+ registerMacro('back', Back);
@@ -5,16 +5,10 @@ import { useAction } from '../../hooks/use-action';
5
5
  import { useInterpolate } from '../../hooks/use-interpolate';
6
6
  import { executeMutation } from '../../execute-mutation';
7
7
  import { currentSourceLocation } from '../../utils/source-location';
8
- import type { ASTNode } from '../../markup/ast';
8
+ import { registerMacro } from '../../registry';
9
+ import type { MacroProps } from '../../registry';
9
10
 
10
- interface ButtonProps {
11
- rawArgs: string;
12
- children: ASTNode[];
13
- className?: string;
14
- id?: string;
15
- }
16
-
17
- export function Button({ rawArgs, children, className, id }: ButtonProps) {
11
+ export function Button({ rawArgs, children = [], className, id }: MacroProps) {
18
12
  const resolve = useInterpolate();
19
13
  className = resolve(className);
20
14
  id = resolve(id);
@@ -51,3 +45,5 @@ export function Button({ rawArgs, children, className, id }: ButtonProps) {
51
45
  </button>
52
46
  );
53
47
  }
48
+
49
+ registerMacro('button', Button);
@@ -1,11 +1,7 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
-
4
- interface CheckboxProps {
5
- rawArgs: string;
6
- className?: string;
7
- id?: string;
8
- }
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
9
5
 
10
6
  function parseArgs(rawArgs: string): { varName: string; label: string } {
11
7
  const match = rawArgs.match(/^\s*(["']?\$\w+["']?)\s+["']?(.+?)["']?\s*$/);
@@ -17,7 +13,7 @@ function parseArgs(rawArgs: string): { varName: string; label: string } {
17
13
  return { varName, label };
18
14
  }
19
15
 
20
- export function Checkbox({ rawArgs, className, id }: CheckboxProps) {
16
+ export function Checkbox({ rawArgs, className, id }: MacroProps) {
21
17
  const { varName, label } = parseArgs(rawArgs);
22
18
  const name = varName.startsWith('$') ? varName.slice(1) : varName;
23
19
 
@@ -50,3 +46,5 @@ export function Checkbox({ rawArgs, className, id }: CheckboxProps) {
50
46
  </label>
51
47
  );
52
48
  }
49
+
50
+ registerMacro('checkbox', Checkbox);
@@ -3,10 +3,8 @@ import { useStoryStore } from '../../store';
3
3
  import { evaluate } from '../../expression';
4
4
  import { useMergedLocals } from '../../hooks/use-merged-locals';
5
5
  import { currentSourceLocation } from '../../utils/source-location';
6
-
7
- interface ComputedProps {
8
- rawArgs: string;
9
- }
6
+ import { registerMacro } from '../../registry';
7
+ import type { MacroProps } from '../../registry';
10
8
 
11
9
  function parseComputedArgs(rawArgs: string): { target: string; expr: string } {
12
10
  const trimmed = rawArgs.trim();
@@ -87,7 +85,7 @@ function computeAndApply(
87
85
  }
88
86
  }
89
87
 
90
- export function Computed({ rawArgs }: ComputedProps) {
88
+ export function Computed({ rawArgs }: MacroProps) {
91
89
  const [mergedVars, mergedTemps, mergedLocals] = useMergedLocals();
92
90
 
93
91
  let target: string;
@@ -138,3 +136,5 @@ export function Computed({ rawArgs }: ComputedProps) {
138
136
 
139
137
  return null;
140
138
  }
139
+
140
+ registerMacro('computed', Computed);
@@ -1,16 +1,10 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { extractOptions } from './option-utils';
3
3
  import { useAction } from '../../hooks/use-action';
4
- import type { ASTNode } from '../../markup/ast';
4
+ import { registerMacro } from '../../registry';
5
+ import type { MacroProps } from '../../registry';
5
6
 
6
- interface CycleProps {
7
- rawArgs: string;
8
- children: ASTNode[];
9
- className?: string;
10
- id?: string;
11
- }
12
-
13
- export function Cycle({ rawArgs, children, className, id }: CycleProps) {
7
+ export function Cycle({ rawArgs, children = [], className, id }: MacroProps) {
14
8
  const varName = rawArgs.trim().replace(/["']/g, '');
15
9
  const name = varName.startsWith('$') ? varName.slice(1) : varName;
16
10
 
@@ -55,3 +49,5 @@ export function Cycle({ rawArgs, children, className, id }: CycleProps) {
55
49
  </button>
56
50
  );
57
51
  }
52
+
53
+ registerMacro('cycle', Cycle);
@@ -1,15 +1,12 @@
1
1
  import { useLayoutEffect, useContext } from 'preact/hooks';
2
- import type { ASTNode } from '../../markup/ast';
3
2
  import { LocalsUpdateContext } from '../../markup/render';
4
3
  import { executeMutation } from '../../execute-mutation';
5
4
  import { currentSourceLocation } from '../../utils/source-location';
6
5
  import { collectText } from '../../utils/extract-text';
6
+ import { registerMacro } from '../../registry';
7
+ import type { MacroProps } from '../../registry';
7
8
 
8
- interface DoProps {
9
- children: ASTNode[];
10
- }
11
-
12
- export function Do({ children }: DoProps) {
9
+ export function Do({ children = [] }: MacroProps) {
13
10
  const code = collectText(children);
14
11
  const { update, getValues } = useContext(LocalsUpdateContext);
15
12
 
@@ -23,3 +20,5 @@ export function Do({ children }: DoProps) {
23
20
 
24
21
  return null;
25
22
  }
23
+
24
+ registerMacro('do', Do);
@@ -14,15 +14,10 @@ import {
14
14
  import { useMergedLocals } from '../../hooks/use-merged-locals';
15
15
  import { useInterpolate } from '../../hooks/use-interpolate';
16
16
  import { currentSourceLocation } from '../../utils/source-location';
17
+ import { registerMacro } from '../../registry';
18
+ import type { MacroProps } from '../../registry';
17
19
  import type { ASTNode } from '../../markup/ast';
18
20
 
19
- interface ForProps {
20
- rawArgs: string;
21
- children: ASTNode[];
22
- className?: string;
23
- id?: string;
24
- }
25
-
26
21
  /**
27
22
  * Parse for-loop args: "@item, @i of $list" or "@item of $list"
28
23
  */
@@ -94,7 +89,7 @@ function ForIteration({
94
89
  );
95
90
  }
96
91
 
97
- export function For({ rawArgs, children, className, id }: ForProps) {
92
+ export function For({ rawArgs, children = [], className, id }: MacroProps) {
98
93
  const resolve = useInterpolate();
99
94
  className = resolve(className);
100
95
  id = resolve(id);
@@ -167,3 +162,5 @@ export function For({ rawArgs, children, className, id }: ForProps) {
167
162
  );
168
163
  return <>{content}</>;
169
164
  }
165
+
166
+ registerMacro('for', For);
@@ -1,12 +1,9 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface ForwardProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function Forward({ className, id }: ForwardProps) {
6
+ export function Forward({ className, id }: MacroProps) {
10
7
  const goForward = useStoryStore((s) => s.goForward);
11
8
  const canGoForward = useStoryStore(
12
9
  (s) => s.historyIndex < s.history.length - 1,
@@ -33,3 +30,5 @@ export function Forward({ className, id }: ForwardProps) {
33
30
  </button>
34
31
  );
35
32
  }
33
+
34
+ registerMacro('forward', Forward);
@@ -2,12 +2,10 @@ import { useLayoutEffect } from 'preact/hooks';
2
2
  import { useStoryStore } from '../../store';
3
3
  import { evaluate } from '../../expression';
4
4
  import { useMergedLocals } from '../../hooks/use-merged-locals';
5
+ import { registerMacro } from '../../registry';
6
+ import type { MacroProps } from '../../registry';
5
7
 
6
- interface GotoProps {
7
- rawArgs: string;
8
- }
9
-
10
- export function Goto({ rawArgs }: GotoProps) {
8
+ export function Goto({ rawArgs }: MacroProps) {
11
9
  const [variables, temporary, locals] = useMergedLocals();
12
10
 
13
11
  useLayoutEffect(() => {
@@ -23,3 +21,5 @@ export function Goto({ rawArgs }: GotoProps) {
23
21
 
24
22
  return null;
25
23
  }
24
+
25
+ registerMacro('goto', Goto);
@@ -3,13 +3,11 @@ import { renderNodes } from '../../markup/render';
3
3
  import { useMergedLocals } from '../../hooks/use-merged-locals';
4
4
  import { useInterpolate } from '../../hooks/use-interpolate';
5
5
  import { currentSourceLocation } from '../../utils/source-location';
6
+ import { registerMacro } from '../../registry';
7
+ import type { MacroProps } from '../../registry';
6
8
  import type { Branch } from '../../markup/ast';
7
9
 
8
- interface IfProps {
9
- branches: Branch[];
10
- }
11
-
12
- export function If({ branches }: IfProps) {
10
+ export function If({ branches = [] }: MacroProps) {
13
11
  const resolve = useInterpolate();
14
12
  const [mergedVars, mergedTemps, mergedLocals] = useMergedLocals();
15
13
 
@@ -59,3 +57,5 @@ export function If({ branches }: IfProps) {
59
57
 
60
58
  return null;
61
59
  }
60
+
61
+ registerMacro('if', If);
@@ -6,14 +6,10 @@ import { renderNodes } from '../../markup/render';
6
6
  import { useMergedLocals } from '../../hooks/use-merged-locals';
7
7
  import { useInterpolate } from '../../hooks/use-interpolate';
8
8
  import { currentSourceLocation } from '../../utils/source-location';
9
+ import { registerMacro } from '../../registry';
10
+ import type { MacroProps } from '../../registry';
9
11
 
10
- interface IncludeProps {
11
- rawArgs: string;
12
- className?: string;
13
- id?: string;
14
- }
15
-
16
- export function Include({ rawArgs, className, id }: IncludeProps) {
12
+ export function Include({ rawArgs, className, id }: MacroProps) {
17
13
  const resolve = useInterpolate();
18
14
  className = resolve(className);
19
15
  id = resolve(id);
@@ -55,3 +51,5 @@ export function Include({ rawArgs, className, id }: IncludeProps) {
55
51
  );
56
52
  return <>{content}</>;
57
53
  }
54
+
55
+ registerMacro('include', Include);
@@ -1,16 +1,10 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { extractOptions } from './option-utils';
3
3
  import { useAction } from '../../hooks/use-action';
4
- import type { ASTNode } from '../../markup/ast';
4
+ import { registerMacro, registerSubMacro } from '../../registry';
5
+ import type { MacroProps } from '../../registry';
5
6
 
6
- interface ListboxProps {
7
- rawArgs: string;
8
- children: ASTNode[];
9
- className?: string;
10
- id?: string;
11
- }
12
-
13
- export function Listbox({ rawArgs, children, className, id }: ListboxProps) {
7
+ export function Listbox({ rawArgs, children = [], className, id }: MacroProps) {
14
8
  const varName = rawArgs.trim().replace(/["']/g, '');
15
9
  const name = varName.startsWith('$') ? varName.slice(1) : varName;
16
10
 
@@ -52,3 +46,6 @@ export function Listbox({ rawArgs, children, className, id }: ListboxProps) {
52
46
  </select>
53
47
  );
54
48
  }
49
+
50
+ registerMacro('listbox', Listbox);
51
+ registerSubMacro('option');
@@ -5,13 +5,8 @@ import { LocalsUpdateContext } from '../../markup/render';
5
5
  import { useInterpolate } from '../../hooks/use-interpolate';
6
6
  import { executeMutation } from '../../execute-mutation';
7
7
  import { currentSourceLocation } from '../../utils/source-location';
8
-
9
- interface MacroLinkProps {
10
- rawArgs: string;
11
- children: ASTNode[];
12
- className?: string;
13
- id?: string;
14
- }
8
+ import { registerMacro } from '../../registry';
9
+ import type { MacroProps } from '../../registry';
15
10
 
16
11
  function parseArgs(rawArgs: string): {
17
12
  display: string;
@@ -72,10 +67,10 @@ function executeChildren(
72
67
 
73
68
  export function MacroLink({
74
69
  rawArgs,
75
- children,
70
+ children = [],
76
71
  className,
77
72
  id,
78
- }: MacroLinkProps) {
73
+ }: MacroProps) {
79
74
  const resolve = useInterpolate();
80
75
  className = resolve(className);
81
76
  id = resolve(id);
@@ -117,3 +112,5 @@ export function MacroLink({
117
112
  </a>
118
113
  );
119
114
  }
115
+
116
+ registerMacro('link', MacroLink);
@@ -1,12 +1,8 @@
1
1
  import { evaluate } from '../../expression';
2
2
  import { useMergedLocals } from '../../hooks/use-merged-locals';
3
3
  import { useInterpolate } from '../../hooks/use-interpolate';
4
-
5
- interface MeterProps {
6
- rawArgs: string;
7
- className?: string;
8
- id?: string;
9
- }
4
+ import { registerMacro } from '../../registry';
5
+ import type { MacroProps } from '../../registry';
10
6
 
11
7
  /**
12
8
  * Parse rawArgs into currentExpr, maxExpr, and optional labelMode.
@@ -83,7 +79,7 @@ function formatLabel(
83
79
  return `${current} / ${max}`;
84
80
  }
85
81
 
86
- export function Meter({ rawArgs, className, id }: MeterProps) {
82
+ export function Meter({ rawArgs, className, id }: MacroProps) {
87
83
  const resolve = useInterpolate();
88
84
  className = resolve(className);
89
85
  id = resolve(id);
@@ -126,3 +122,5 @@ export function Meter({ rawArgs, className, id }: MeterProps) {
126
122
  );
127
123
  }
128
124
  }
125
+
126
+ registerMacro('meter', Meter);
@@ -1,11 +1,7 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
-
4
- interface NumberboxProps {
5
- rawArgs: string;
6
- className?: string;
7
- id?: string;
8
- }
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
9
5
 
10
6
  function parseArgs(rawArgs: string): { varName: string; placeholder: string } {
11
7
  const match = rawArgs.match(/^\s*(["']?\$\w+["']?)\s*(?:["'](.*)["'])?\s*$/);
@@ -17,7 +13,7 @@ function parseArgs(rawArgs: string): { varName: string; placeholder: string } {
17
13
  return { varName, placeholder };
18
14
  }
19
15
 
20
- export function Numberbox({ rawArgs, className, id }: NumberboxProps) {
16
+ export function Numberbox({ rawArgs, className, id }: MacroProps) {
21
17
  const { varName, placeholder } = parseArgs(rawArgs);
22
18
  const name = varName.startsWith('$') ? varName.slice(1) : varName;
23
19
 
@@ -50,3 +46,5 @@ export function Numberbox({ rawArgs, className, id }: NumberboxProps) {
50
46
  />
51
47
  );
52
48
  }
49
+
50
+ registerMacro('numberbox', Numberbox);
@@ -1,13 +1,10 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { Passage } from '../Passage';
3
3
  import { useInterpolate } from '../../hooks/use-interpolate';
4
+ import { registerMacro } from '../../registry';
5
+ import type { MacroProps } from '../../registry';
4
6
 
5
- interface PassageDisplayProps {
6
- className?: string;
7
- id?: string;
8
- }
9
-
10
- export function PassageDisplay({ className, id }: PassageDisplayProps) {
7
+ export function PassageDisplay({ className, id }: MacroProps) {
11
8
  const resolve = useInterpolate();
12
9
  className = resolve(className);
13
10
  id = resolve(id);
@@ -35,3 +32,5 @@ export function PassageDisplay({ className, id }: PassageDisplayProps) {
35
32
  </div>
36
33
  );
37
34
  }
35
+
36
+ registerMacro('passage', PassageDisplay);
@@ -2,14 +2,10 @@ import { evaluate } from '../../expression';
2
2
  import { useMergedLocals } from '../../hooks/use-merged-locals';
3
3
  import { useInterpolate } from '../../hooks/use-interpolate';
4
4
  import { currentSourceLocation } from '../../utils/source-location';
5
+ import { registerMacro } from '../../registry';
6
+ import type { MacroProps } from '../../registry';
5
7
 
6
- interface PrintProps {
7
- rawArgs: string;
8
- className?: string;
9
- id?: string;
10
- }
11
-
12
- export function Print({ rawArgs, className, id }: PrintProps) {
8
+ export function Print({ rawArgs, className, id }: MacroProps) {
13
9
  const resolve = useInterpolate();
14
10
  className = resolve(className);
15
11
  id = resolve(id);
@@ -39,3 +35,5 @@ export function Print({ rawArgs, className, id }: PrintProps) {
39
35
  );
40
36
  }
41
37
  }
38
+
39
+ registerMacro('print', Print);
@@ -1,12 +1,9 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface QuickLoadProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function QuickLoad({ className, id }: QuickLoadProps) {
6
+ export function QuickLoad({ className, id }: MacroProps) {
10
7
  const load = useStoryStore((s) => s.load);
11
8
  const hasSave = useStoryStore((s) => s.hasSave);
12
9
  // Subscribe to saveVersion so we re-render when a save is created
@@ -41,3 +38,5 @@ export function QuickLoad({ className, id }: QuickLoadProps) {
41
38
  </button>
42
39
  );
43
40
  }
41
+
42
+ registerMacro('quickload', QuickLoad);
@@ -1,12 +1,9 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface QuickSaveProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function QuickSave({ className, id }: QuickSaveProps) {
6
+ export function QuickSave({ className, id }: MacroProps) {
10
7
  const save = useStoryStore((s) => s.save);
11
8
  const cls = className ? `menubar-button ${className}` : 'menubar-button';
12
9
 
@@ -29,3 +26,5 @@ export function QuickSave({ className, id }: QuickSaveProps) {
29
26
  </button>
30
27
  );
31
28
  }
29
+
30
+ registerMacro('quicksave', QuickSave);
@@ -1,11 +1,7 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
-
4
- interface RadiobuttonProps {
5
- rawArgs: string;
6
- className?: string;
7
- id?: string;
8
- }
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
9
5
 
10
6
  function parseArgs(rawArgs: string): {
11
7
  varName: string;
@@ -32,7 +28,7 @@ function parseArgs(rawArgs: string): {
32
28
  };
33
29
  }
34
30
 
35
- export function Radiobutton({ rawArgs, className, id }: RadiobuttonProps) {
31
+ export function Radiobutton({ rawArgs, className, id }: MacroProps) {
36
32
  const { varName, value: radioValue, label } = parseArgs(rawArgs);
37
33
  const name = varName.startsWith('$') ? varName.slice(1) : varName;
38
34
 
@@ -68,3 +64,5 @@ export function Radiobutton({ rawArgs, className, id }: RadiobuttonProps) {
68
64
  </label>
69
65
  );
70
66
  }
67
+
68
+ registerMacro('radiobutton', Radiobutton);
@@ -4,25 +4,19 @@ import { renderNodes } from '../../markup/render';
4
4
  import { parseDelay } from '../../utils/parse-delay';
5
5
  import { hasInterpolation, interpolate } from '../../interpolation';
6
6
  import { useStoryStore } from '../../store';
7
- import type { ASTNode } from '../../markup/ast';
7
+ import { registerMacro } from '../../registry';
8
+ import type { MacroProps } from '../../registry';
8
9
 
9
10
  export const RepeatContext = createContext<{ stop: () => void }>({
10
11
  stop: () => {},
11
12
  });
12
13
 
13
- interface RepeatProps {
14
- rawArgs: string;
15
- children: ASTNode[];
16
- className?: string;
17
- id?: string;
18
- }
19
-
20
14
  export function Repeat({
21
15
  rawArgs,
22
- children,
16
+ children = [],
23
17
  className: rawClassName,
24
18
  id: rawId,
25
- }: RepeatProps) {
19
+ }: MacroProps) {
26
20
  const [className, id] = useMemo(() => {
27
21
  const resolveOnce = (s: string | undefined) => {
28
22
  if (!s || !hasInterpolation(s)) return s;
@@ -67,3 +61,5 @@ export function Repeat({
67
61
  );
68
62
  return content;
69
63
  }
64
+
65
+ registerMacro('repeat', Repeat);
@@ -1,12 +1,9 @@
1
1
  import { useStoryStore } from '../../store';
2
2
  import { useAction } from '../../hooks/use-action';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface RestartProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function Restart({ className, id }: RestartProps) {
6
+ export function Restart({ className, id }: MacroProps) {
10
7
  const restart = useStoryStore((s) => s.restart);
11
8
  const cls = className ? `menubar-button ${className}` : 'menubar-button';
12
9
 
@@ -34,3 +31,5 @@ export function Restart({ className, id }: RestartProps) {
34
31
  </button>
35
32
  );
36
33
  }
34
+
35
+ registerMacro('restart', Restart);
@@ -1,12 +1,9 @@
1
1
  import { useState } from 'preact/hooks';
2
2
  import { SaveLoadDialog } from '../SaveLoadDialog';
3
+ import { registerMacro } from '../../registry';
4
+ import type { MacroProps } from '../../registry';
3
5
 
4
- interface SavesProps {
5
- className?: string;
6
- id?: string;
7
- }
8
-
9
- export function Saves({ className, id }: SavesProps) {
6
+ export function Saves({ className, id }: MacroProps) {
10
7
  const [open, setOpen] = useState(false);
11
8
  const cls = className ? `menubar-button ${className}` : 'menubar-button';
12
9
 
@@ -23,3 +20,5 @@ export function Saves({ className, id }: SavesProps) {
23
20
  </>
24
21
  );
25
22
  }
23
+
24
+ registerMacro('saves', Saves);
@@ -2,12 +2,10 @@ import { useRef, useContext } from 'preact/hooks';
2
2
  import { LocalsUpdateContext } from '../../markup/render';
3
3
  import { executeMutation } from '../../execute-mutation';
4
4
  import { currentSourceLocation } from '../../utils/source-location';
5
+ import { registerMacro } from '../../registry';
6
+ import type { MacroProps } from '../../registry';
5
7
 
6
- interface SetProps {
7
- rawArgs: string;
8
- }
9
-
10
- export function Set({ rawArgs }: SetProps) {
8
+ export function Set({ rawArgs }: MacroProps) {
11
9
  const { update, getValues } = useContext(LocalsUpdateContext);
12
10
  const ran = useRef(false);
13
11
 
@@ -27,3 +25,5 @@ export function Set({ rawArgs }: SetProps) {
27
25
 
28
26
  return null;
29
27
  }
28
+
29
+ registerMacro('set', Set);
@@ -1,13 +1,10 @@
1
1
  import { useState } from 'preact/hooks';
2
2
  import { settings } from '../../settings';
3
3
  import { SettingsDialog } from '../SettingsDialog';
4
+ import { registerMacro } from '../../registry';
5
+ import type { MacroProps } from '../../registry';
4
6
 
5
- interface SettingsButtonProps {
6
- className?: string;
7
- id?: string;
8
- }
9
-
10
- export function SettingsButton({ className, id }: SettingsButtonProps) {
7
+ export function SettingsButton({ className, id }: MacroProps) {
11
8
  const [open, setOpen] = useState(false);
12
9
 
13
10
  if (!settings.hasAny()) return null;
@@ -27,3 +24,5 @@ export function SettingsButton({ className, id }: SettingsButtonProps) {
27
24
  </>
28
25
  );
29
26
  }
27
+
28
+ registerMacro('settings', SettingsButton);