@rohal12/spindle 0.16.0 → 0.17.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pkg/format.js +1 -1
- package/package.json +1 -1
- package/src/action-registry.ts +2 -1
- package/src/components/PassageDialog.tsx +69 -0
- package/src/components/macros/Button.tsx +33 -46
- package/src/components/macros/Checkbox.tsx +32 -35
- package/src/components/macros/Computed.tsx +49 -54
- package/src/components/macros/Cycle.tsx +43 -53
- package/src/components/macros/Dialog.tsx +40 -0
- package/src/components/macros/Do.tsx +15 -21
- package/src/components/macros/For.tsx +57 -75
- package/src/components/macros/Goto.tsx +18 -22
- package/src/components/macros/If.tsx +39 -53
- package/src/components/macros/Include.tsx +30 -46
- package/src/components/macros/Listbox.tsx +38 -48
- package/src/components/macros/MacroError.tsx +18 -0
- package/src/components/macros/MacroLink.tsx +36 -51
- package/src/components/macros/MenubarButtons.tsx +158 -0
- package/src/components/macros/Meter.tsx +35 -52
- package/src/components/macros/Numberbox.tsx +30 -47
- package/src/components/macros/PassageDisplay.tsx +26 -29
- package/src/components/macros/Print.tsx +19 -36
- package/src/components/macros/Radiobutton.tsx +33 -38
- package/src/components/macros/Repeat.tsx +49 -54
- package/src/components/macros/SaveManager.tsx +400 -0
- package/src/components/macros/Set.tsx +19 -24
- package/src/components/{SettingsDialog.tsx → macros/SettingsControls.tsx} +18 -36
- package/src/components/macros/Stop.tsx +11 -12
- package/src/components/macros/StoryTitle.tsx +16 -16
- package/src/components/macros/Switch.tsx +41 -59
- package/src/components/macros/Textarea.tsx +26 -45
- package/src/components/macros/Textbox.tsx +27 -44
- package/src/components/macros/Timed.tsx +52 -63
- package/src/components/macros/Type.tsx +61 -62
- package/src/components/macros/Unset.tsx +21 -22
- package/src/components/macros/Widget.tsx +11 -15
- package/src/components/macros/option-utils.ts +13 -0
- package/src/define-macro.ts +154 -0
- package/src/macros/register-builtins.ts +4 -7
- package/src/markup/ast.ts +10 -16
- package/src/markup/render.tsx +0 -13
- package/src/story-api.ts +7 -0
- package/src/styles.css +37 -68
- package/src/components/PassageLink.tsx +0 -49
- package/src/components/SaveLoadDialog.tsx +0 -408
- package/src/components/macros/Back.tsx +0 -32
- package/src/components/macros/Forward.tsx +0 -34
- package/src/components/macros/QuickLoad.tsx +0 -42
- package/src/components/macros/QuickSave.tsx +0 -30
- package/src/components/macros/Restart.tsx +0 -35
- package/src/components/macros/Saves.tsx +0 -24
- package/src/components/macros/SettingsButton.tsx +0 -28
|
@@ -15,13 +15,10 @@ import '../components/macros/Stop';
|
|
|
15
15
|
import '../components/macros/Type';
|
|
16
16
|
import '../components/macros/Widget';
|
|
17
17
|
import '../components/macros/StoryTitle';
|
|
18
|
-
import '../components/macros/
|
|
19
|
-
import '../components/macros/
|
|
20
|
-
import '../components/macros/
|
|
21
|
-
import '../components/macros/
|
|
22
|
-
import '../components/macros/QuickLoad';
|
|
23
|
-
import '../components/macros/SettingsButton';
|
|
24
|
-
import '../components/macros/Saves';
|
|
18
|
+
import '../components/macros/MenubarButtons';
|
|
19
|
+
import '../components/macros/Dialog';
|
|
20
|
+
import '../components/macros/SaveManager';
|
|
21
|
+
import '../components/macros/SettingsControls';
|
|
25
22
|
import '../components/macros/Include';
|
|
26
23
|
import '../components/macros/Goto';
|
|
27
24
|
import '../components/macros/Unset';
|
package/src/markup/ast.ts
CHANGED
|
@@ -5,14 +5,6 @@ export interface TextNode {
|
|
|
5
5
|
value: string;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
-
export interface LinkNode {
|
|
9
|
-
type: 'link';
|
|
10
|
-
display: string;
|
|
11
|
-
target: string;
|
|
12
|
-
className?: string;
|
|
13
|
-
id?: string;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
8
|
export interface VariableNode {
|
|
17
9
|
type: 'variable';
|
|
18
10
|
name: string;
|
|
@@ -45,7 +37,7 @@ export interface HtmlNode {
|
|
|
45
37
|
children: ASTNode[];
|
|
46
38
|
}
|
|
47
39
|
|
|
48
|
-
export type ASTNode = TextNode |
|
|
40
|
+
export type ASTNode = TextNode | VariableNode | MacroNode | HtmlNode;
|
|
49
41
|
|
|
50
42
|
/** Macros that require a closing tag and can contain children */
|
|
51
43
|
const BLOCK_MACROS = new Set([
|
|
@@ -102,14 +94,16 @@ export function buildAST(tokens: Token[]): ASTNode[] {
|
|
|
102
94
|
break;
|
|
103
95
|
|
|
104
96
|
case 'link': {
|
|
105
|
-
const
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
97
|
+
const rawArgs = `"${token.display}" "${token.target}"`;
|
|
98
|
+
const macroNode: MacroNode = {
|
|
99
|
+
type: 'macro',
|
|
100
|
+
name: 'link',
|
|
101
|
+
rawArgs,
|
|
102
|
+
children: [],
|
|
109
103
|
};
|
|
110
|
-
if (token.className)
|
|
111
|
-
if (token.id)
|
|
112
|
-
current().push(
|
|
104
|
+
if (token.className) macroNode.className = token.className;
|
|
105
|
+
if (token.id) macroNode.id = token.id;
|
|
106
|
+
current().push(macroNode);
|
|
113
107
|
break;
|
|
114
108
|
}
|
|
115
109
|
|
package/src/markup/render.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { createContext } from 'preact';
|
|
2
|
-
import { PassageLink } from '../components/PassageLink';
|
|
3
2
|
import { VarDisplay } from '../components/macros/VarDisplay';
|
|
4
3
|
import { WidgetInvocation } from '../components/macros/WidgetInvocation';
|
|
5
4
|
import { getWidget } from '../widgets/widget-registry';
|
|
@@ -136,18 +135,6 @@ function renderSingleNode(
|
|
|
136
135
|
case 'text':
|
|
137
136
|
return node.value;
|
|
138
137
|
|
|
139
|
-
case 'link':
|
|
140
|
-
return (
|
|
141
|
-
<PassageLink
|
|
142
|
-
key={key}
|
|
143
|
-
target={node.target}
|
|
144
|
-
className={node.className}
|
|
145
|
-
id={node.id}
|
|
146
|
-
>
|
|
147
|
-
{node.display}
|
|
148
|
-
</PassageLink>
|
|
149
|
-
);
|
|
150
|
-
|
|
151
138
|
case 'variable':
|
|
152
139
|
return (
|
|
153
140
|
<VarDisplay
|
package/src/story-api.ts
CHANGED
|
@@ -4,6 +4,8 @@ import { settings } from './settings';
|
|
|
4
4
|
import type { SavePayload } from './saves/types';
|
|
5
5
|
import { setTitleGenerator } from './saves/save-manager';
|
|
6
6
|
import { registerClass } from './class-registry';
|
|
7
|
+
import { defineMacro } from './define-macro';
|
|
8
|
+
import type { MacroDefinition } from './define-macro';
|
|
7
9
|
import {
|
|
8
10
|
getActions,
|
|
9
11
|
getAction,
|
|
@@ -53,6 +55,7 @@ export interface StoryAPI {
|
|
|
53
55
|
readonly passage: string;
|
|
54
56
|
readonly settings: typeof settings;
|
|
55
57
|
registerClass(name: string, ctor: new (...args: any[]) => any): void;
|
|
58
|
+
defineMacro(config: MacroDefinition): void;
|
|
56
59
|
readonly saves: {
|
|
57
60
|
setTitleGenerator(fn: (payload: SavePayload) => string): void;
|
|
58
61
|
};
|
|
@@ -179,6 +182,10 @@ function createStoryAPI(): StoryAPI {
|
|
|
179
182
|
registerClass(name, ctor);
|
|
180
183
|
},
|
|
181
184
|
|
|
185
|
+
defineMacro(config: MacroDefinition): void {
|
|
186
|
+
defineMacro(config);
|
|
187
|
+
},
|
|
188
|
+
|
|
182
189
|
saves: {
|
|
183
190
|
setTitleGenerator(fn: (payload: SavePayload) => string): void {
|
|
184
191
|
setTitleGenerator(fn);
|
package/src/styles.css
CHANGED
|
@@ -44,25 +44,6 @@ tw-storydata {
|
|
|
44
44
|
}
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
-
.passage-link {
|
|
48
|
-
color: #64b5f6;
|
|
49
|
-
text-decoration: none;
|
|
50
|
-
border-bottom: 1px solid rgba(100, 181, 246, 0.3);
|
|
51
|
-
transition:
|
|
52
|
-
color 0.2s,
|
|
53
|
-
border-color 0.2s;
|
|
54
|
-
cursor: pointer;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
.passage-link:hover {
|
|
58
|
-
color: #90caf9;
|
|
59
|
-
border-bottom-color: #90caf9;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
.passage-link:active {
|
|
63
|
-
color: #42a5f5;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
47
|
.macro-button {
|
|
67
48
|
background: rgba(100, 181, 246, 0.15);
|
|
68
49
|
color: #64b5f6;
|
|
@@ -154,9 +135,9 @@ tw-storydata {
|
|
|
154
135
|
background: transparent;
|
|
155
136
|
}
|
|
156
137
|
|
|
157
|
-
/*
|
|
138
|
+
/* Generic dialog */
|
|
158
139
|
|
|
159
|
-
.
|
|
140
|
+
.dialog-overlay {
|
|
160
141
|
position: fixed;
|
|
161
142
|
inset: 0;
|
|
162
143
|
z-index: 200;
|
|
@@ -166,28 +147,33 @@ tw-storydata {
|
|
|
166
147
|
background: rgba(0, 0, 0, 0.6);
|
|
167
148
|
}
|
|
168
149
|
|
|
169
|
-
.
|
|
150
|
+
.dialog-panel {
|
|
170
151
|
background: #16213e;
|
|
171
152
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
172
153
|
border-radius: 8px;
|
|
173
154
|
width: 90%;
|
|
174
|
-
max-width:
|
|
155
|
+
max-width: 500px;
|
|
175
156
|
max-height: 80vh;
|
|
176
|
-
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
177
159
|
color: #e0e0e0;
|
|
178
160
|
font-family: system-ui, sans-serif;
|
|
161
|
+
position: relative;
|
|
179
162
|
}
|
|
180
163
|
|
|
181
|
-
.
|
|
182
|
-
|
|
183
|
-
align-items: center;
|
|
184
|
-
justify-content: space-between;
|
|
185
|
-
padding: 1em 1.25em;
|
|
186
|
-
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
187
|
-
font-weight: 600;
|
|
164
|
+
.dialog-saves {
|
|
165
|
+
max-width: 550px;
|
|
188
166
|
}
|
|
189
167
|
|
|
190
|
-
.settings
|
|
168
|
+
.dialog-settings {
|
|
169
|
+
max-width: 400px;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
.dialog-close {
|
|
173
|
+
position: absolute;
|
|
174
|
+
top: 0.75em;
|
|
175
|
+
right: 0.75em;
|
|
176
|
+
z-index: 1;
|
|
191
177
|
background: transparent;
|
|
192
178
|
border: none;
|
|
193
179
|
color: #9e9e9e;
|
|
@@ -197,11 +183,19 @@ tw-storydata {
|
|
|
197
183
|
line-height: 1;
|
|
198
184
|
}
|
|
199
185
|
|
|
200
|
-
.
|
|
186
|
+
.dialog-close:hover {
|
|
201
187
|
color: #e0e0e0;
|
|
202
188
|
}
|
|
203
189
|
|
|
204
|
-
.
|
|
190
|
+
.dialog-body {
|
|
191
|
+
overflow-y: auto;
|
|
192
|
+
flex: 1;
|
|
193
|
+
min-height: 0;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/* Settings controls */
|
|
197
|
+
|
|
198
|
+
.settings-controls {
|
|
205
199
|
padding: 1em 1.25em;
|
|
206
200
|
display: flex;
|
|
207
201
|
flex-direction: column;
|
|
@@ -235,29 +229,13 @@ tw-storydata {
|
|
|
235
229
|
height: 1.1em;
|
|
236
230
|
}
|
|
237
231
|
|
|
238
|
-
/*
|
|
239
|
-
|
|
240
|
-
.saves-overlay {
|
|
241
|
-
position: fixed;
|
|
242
|
-
inset: 0;
|
|
243
|
-
z-index: 200;
|
|
244
|
-
display: flex;
|
|
245
|
-
align-items: center;
|
|
246
|
-
justify-content: center;
|
|
247
|
-
background: rgba(0, 0, 0, 0.6);
|
|
248
|
-
}
|
|
232
|
+
/* Save manager */
|
|
249
233
|
|
|
250
|
-
.
|
|
251
|
-
background: #16213e;
|
|
252
|
-
border: 1px solid rgba(255, 255, 255, 0.1);
|
|
253
|
-
border-radius: 8px;
|
|
254
|
-
width: 90%;
|
|
255
|
-
max-width: 550px;
|
|
256
|
-
max-height: 80vh;
|
|
234
|
+
.save-manager {
|
|
257
235
|
display: flex;
|
|
258
236
|
flex-direction: column;
|
|
259
|
-
|
|
260
|
-
|
|
237
|
+
flex: 1;
|
|
238
|
+
min-height: 0;
|
|
261
239
|
}
|
|
262
240
|
|
|
263
241
|
.saves-header {
|
|
@@ -265,6 +243,7 @@ tw-storydata {
|
|
|
265
243
|
align-items: center;
|
|
266
244
|
justify-content: space-between;
|
|
267
245
|
padding: 1em 1.25em;
|
|
246
|
+
padding-right: 3em;
|
|
268
247
|
border-bottom: 1px solid rgba(255, 255, 255, 0.08);
|
|
269
248
|
font-weight: 600;
|
|
270
249
|
flex-shrink: 0;
|
|
@@ -307,20 +286,6 @@ tw-storydata {
|
|
|
307
286
|
color: #e0e0e0;
|
|
308
287
|
}
|
|
309
288
|
|
|
310
|
-
.saves-close {
|
|
311
|
-
background: transparent;
|
|
312
|
-
border: none;
|
|
313
|
-
color: #9e9e9e;
|
|
314
|
-
font-size: 1.1em;
|
|
315
|
-
cursor: pointer;
|
|
316
|
-
padding: 0.25em;
|
|
317
|
-
line-height: 1;
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
.saves-close:hover {
|
|
321
|
-
color: #e0e0e0;
|
|
322
|
-
}
|
|
323
|
-
|
|
324
289
|
.saves-body {
|
|
325
290
|
padding: 0.75em 1.25em;
|
|
326
291
|
overflow-y: auto;
|
|
@@ -560,6 +525,10 @@ tw-storydata {
|
|
|
560
525
|
border-bottom-color: #90caf9;
|
|
561
526
|
}
|
|
562
527
|
|
|
528
|
+
.macro-link:active {
|
|
529
|
+
color: #42a5f5;
|
|
530
|
+
}
|
|
531
|
+
|
|
563
532
|
/* Macro: form inputs */
|
|
564
533
|
|
|
565
534
|
.macro-textbox,
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
import { useStoryStore } from '../store';
|
|
2
|
-
import { useAction } from '../hooks/use-action';
|
|
3
|
-
import { useInterpolate } from '../hooks/use-interpolate';
|
|
4
|
-
|
|
5
|
-
interface PassageLinkProps {
|
|
6
|
-
target: string;
|
|
7
|
-
className?: string;
|
|
8
|
-
id?: string;
|
|
9
|
-
children: preact.ComponentChildren;
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
export function PassageLink({
|
|
13
|
-
target,
|
|
14
|
-
className,
|
|
15
|
-
id,
|
|
16
|
-
children,
|
|
17
|
-
}: PassageLinkProps) {
|
|
18
|
-
const navigate = useStoryStore((s) => s.navigate);
|
|
19
|
-
const resolve = useInterpolate();
|
|
20
|
-
className = resolve(className);
|
|
21
|
-
id = resolve(id);
|
|
22
|
-
|
|
23
|
-
const handleClick = (e: MouseEvent) => {
|
|
24
|
-
e.preventDefault();
|
|
25
|
-
navigate(target);
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
useAction({
|
|
29
|
-
type: 'link',
|
|
30
|
-
key: target,
|
|
31
|
-
authorId: id,
|
|
32
|
-
label: typeof children === 'string' ? children : target,
|
|
33
|
-
target,
|
|
34
|
-
perform: () => navigate(target),
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
const cls = className ? `passage-link ${className}` : 'passage-link';
|
|
38
|
-
|
|
39
|
-
return (
|
|
40
|
-
<a
|
|
41
|
-
href="#"
|
|
42
|
-
id={id}
|
|
43
|
-
class={cls}
|
|
44
|
-
onClick={handleClick}
|
|
45
|
-
>
|
|
46
|
-
{children}
|
|
47
|
-
</a>
|
|
48
|
-
);
|
|
49
|
-
}
|