@rohal12/spindle 0.43.0 → 0.43.2
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
|
@@ -22,9 +22,9 @@ function parseComputedArgs(rawArgs: string): { target: string; expr: string } {
|
|
|
22
22
|
const target = trimmed.slice(0, i).trim();
|
|
23
23
|
const expr = trimmed.slice(i + 1).trim();
|
|
24
24
|
|
|
25
|
-
if (!target.match(/^[$_]\w+$/)) {
|
|
25
|
+
if (!target.match(/^[$_@]\w+$/)) {
|
|
26
26
|
throw new Error(
|
|
27
|
-
`{computed}: target must be $name or
|
|
27
|
+
`{computed}: target must be $name, _name, or @name, got "${target}"`,
|
|
28
28
|
);
|
|
29
29
|
}
|
|
30
30
|
|
|
@@ -58,11 +58,14 @@ function computeAndApply(
|
|
|
58
58
|
expr: string,
|
|
59
59
|
name: string,
|
|
60
60
|
isTemp: boolean,
|
|
61
|
+
isLocal: boolean,
|
|
61
62
|
variables: Record<string, unknown>,
|
|
62
63
|
temporary: Record<string, unknown>,
|
|
63
64
|
locals: Record<string, unknown>,
|
|
64
65
|
transient: Record<string, unknown>,
|
|
65
66
|
rawArgs: string,
|
|
67
|
+
prevRef: { current: unknown },
|
|
68
|
+
localsUpdate: ((key: string, value: unknown) => void) | null,
|
|
66
69
|
): void {
|
|
67
70
|
let newValue: unknown;
|
|
68
71
|
try {
|
|
@@ -75,11 +78,22 @@ function computeAndApply(
|
|
|
75
78
|
return;
|
|
76
79
|
}
|
|
77
80
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
81
|
+
if (!valuesEqual(prevRef.current, newValue)) {
|
|
82
|
+
prevRef.current = newValue;
|
|
83
|
+
if (isLocal) {
|
|
84
|
+
try {
|
|
85
|
+
localsUpdate!(name, newValue);
|
|
86
|
+
} catch (err) {
|
|
87
|
+
console.error(
|
|
88
|
+
`spindle: Error in {computed ${rawArgs}}${currentSourceLocation()}:`,
|
|
89
|
+
err,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
const state = useStoryStore.getState();
|
|
94
|
+
if (isTemp) state.setTemporary(name, newValue);
|
|
95
|
+
else state.setVariable(name, newValue);
|
|
96
|
+
}
|
|
83
97
|
}
|
|
84
98
|
}
|
|
85
99
|
|
|
@@ -101,8 +115,12 @@ defineMacro({
|
|
|
101
115
|
/>
|
|
102
116
|
);
|
|
103
117
|
}
|
|
118
|
+
const isLocal = target.startsWith('@');
|
|
104
119
|
const isTemp = target.startsWith('_');
|
|
105
120
|
const name = target.slice(1);
|
|
121
|
+
const localsUpdate = isLocal ? ctx.update : null;
|
|
122
|
+
|
|
123
|
+
const prevOutput = ctx.hooks.useRef<unknown>(undefined);
|
|
106
124
|
|
|
107
125
|
const ran = ctx.hooks.useRef(false);
|
|
108
126
|
if (!ran.current) {
|
|
@@ -111,11 +129,14 @@ defineMacro({
|
|
|
111
129
|
expr,
|
|
112
130
|
name,
|
|
113
131
|
isTemp,
|
|
132
|
+
isLocal,
|
|
114
133
|
mergedVars,
|
|
115
134
|
mergedTemps,
|
|
116
135
|
mergedLocals,
|
|
117
136
|
mergedTrans,
|
|
118
137
|
rawArgs,
|
|
138
|
+
prevOutput,
|
|
139
|
+
localsUpdate,
|
|
119
140
|
);
|
|
120
141
|
}
|
|
121
142
|
|
|
@@ -124,11 +145,14 @@ defineMacro({
|
|
|
124
145
|
expr,
|
|
125
146
|
name,
|
|
126
147
|
isTemp,
|
|
148
|
+
isLocal,
|
|
127
149
|
mergedVars,
|
|
128
150
|
mergedTemps,
|
|
129
151
|
mergedLocals,
|
|
130
152
|
mergedTrans,
|
|
131
153
|
rawArgs,
|
|
154
|
+
prevOutput,
|
|
155
|
+
localsUpdate,
|
|
132
156
|
);
|
|
133
157
|
}, [mergedVars, mergedTemps, mergedLocals, mergedTrans]);
|
|
134
158
|
|
|
@@ -53,21 +53,35 @@ function parseForArgs(rawArgs: string): {
|
|
|
53
53
|
|
|
54
54
|
function ForIteration({
|
|
55
55
|
parentValues,
|
|
56
|
-
|
|
57
|
-
|
|
56
|
+
itemVar,
|
|
57
|
+
itemValue,
|
|
58
|
+
indexVar,
|
|
59
|
+
indexValue,
|
|
58
60
|
children,
|
|
59
61
|
}: {
|
|
60
62
|
parentValues: Record<string, unknown>;
|
|
61
|
-
|
|
62
|
-
|
|
63
|
+
itemVar: string;
|
|
64
|
+
itemValue: unknown;
|
|
65
|
+
indexVar: string | null;
|
|
66
|
+
indexValue: number;
|
|
63
67
|
children: ASTNode[];
|
|
64
68
|
}) {
|
|
65
69
|
const [localMutations, setLocalMutations] = useState<Record<string, unknown>>(
|
|
66
|
-
() => ({
|
|
70
|
+
() => ({}),
|
|
67
71
|
);
|
|
68
72
|
|
|
69
|
-
|
|
70
|
-
|
|
73
|
+
const ownKeys = useMemo(
|
|
74
|
+
() => ({
|
|
75
|
+
[itemVar]: itemValue,
|
|
76
|
+
...(indexVar ? { [indexVar]: indexValue } : undefined),
|
|
77
|
+
}),
|
|
78
|
+
[itemVar, itemValue, indexVar, indexValue],
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
const localState = useMemo(
|
|
82
|
+
() => ({ ...parentValues, ...ownKeys, ...localMutations }),
|
|
83
|
+
[parentValues, ownKeys, localMutations],
|
|
84
|
+
);
|
|
71
85
|
|
|
72
86
|
const valuesRef = useRef(localState);
|
|
73
87
|
valuesRef.current = localState;
|
|
@@ -131,22 +145,17 @@ defineMacro({
|
|
|
131
145
|
);
|
|
132
146
|
}
|
|
133
147
|
|
|
134
|
-
const content = list.map((item, i) =>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
initialValues={{}}
|
|
146
|
-
children={children}
|
|
147
|
-
/>
|
|
148
|
-
);
|
|
149
|
-
});
|
|
148
|
+
const content = list.map((item, i) => (
|
|
149
|
+
<ForIteration
|
|
150
|
+
key={`${i}-${JSON.stringify(item)}`}
|
|
151
|
+
parentValues={parentValues}
|
|
152
|
+
itemVar={itemVar}
|
|
153
|
+
itemValue={item}
|
|
154
|
+
indexVar={indexVar}
|
|
155
|
+
indexValue={i}
|
|
156
|
+
children={children}
|
|
157
|
+
/>
|
|
158
|
+
));
|
|
150
159
|
|
|
151
160
|
return ctx.wrap(content);
|
|
152
161
|
},
|
|
@@ -190,8 +190,10 @@ function WidgetBody({
|
|
|
190
190
|
{},
|
|
191
191
|
);
|
|
192
192
|
|
|
193
|
-
|
|
194
|
-
|
|
193
|
+
const localState = useMemo(
|
|
194
|
+
() => ({ ...parentValues, ...ownKeys, ...localMutations }),
|
|
195
|
+
[parentValues, ownKeys, localMutations],
|
|
196
|
+
);
|
|
195
197
|
|
|
196
198
|
const valuesRef = useRef(localState);
|
|
197
199
|
valuesRef.current = localState;
|
|
@@ -233,10 +235,9 @@ export function WidgetInvocation({
|
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
const argExprs = splitArgs(rawArgs);
|
|
236
|
-
const
|
|
238
|
+
const values: unknown[] = [];
|
|
237
239
|
|
|
238
240
|
for (let i = 0; i < params.length; i++) {
|
|
239
|
-
const param = params[i]!;
|
|
240
241
|
const expr = argExprs[i];
|
|
241
242
|
let value: unknown;
|
|
242
243
|
if (expr !== undefined) {
|
|
@@ -252,9 +253,20 @@ export function WidgetInvocation({
|
|
|
252
253
|
value = undefined;
|
|
253
254
|
}
|
|
254
255
|
}
|
|
255
|
-
|
|
256
|
+
values.push(value);
|
|
256
257
|
}
|
|
257
258
|
|
|
259
|
+
const ownKeys = useMemo(() => {
|
|
260
|
+
const keys: Record<string, unknown> = {};
|
|
261
|
+
for (let i = 0; i < params.length; i++) {
|
|
262
|
+
keys[params[i]!.startsWith('@') ? params[i]!.slice(1) : params[i]!] =
|
|
263
|
+
values[i];
|
|
264
|
+
}
|
|
265
|
+
return keys;
|
|
266
|
+
// params is stable per widget instance; values tracks evaluated args
|
|
267
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
268
|
+
}, values);
|
|
269
|
+
|
|
258
270
|
return (
|
|
259
271
|
<WidgetChildrenContext.Provider value={childrenValue}>
|
|
260
272
|
<WidgetBody
|