@astroapps/forms-core 1.0.2 → 1.1.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/lib/formNode.d.ts +7 -0
- package/lib/formState.d.ts +4 -0
- package/lib/index.cjs +56 -12
- package/lib/index.cjs.map +1 -1
- package/lib/index.js +54 -14
- package/lib/index.js.map +1 -1
- package/package.json +1 -1
- package/src/formNode.ts +45 -0
- package/src/formState.ts +52 -31
package/package.json
CHANGED
package/src/formNode.ts
CHANGED
|
@@ -247,3 +247,48 @@ export function visitFormDataInContext<A>(
|
|
|
247
247
|
const dataNode = lookupDataNode(node.definition, parentContext);
|
|
248
248
|
return visitFormData(node, dataNode ?? parentContext, cb, !dataNode);
|
|
249
249
|
}
|
|
250
|
+
|
|
251
|
+
export interface FormDataNode {
|
|
252
|
+
parent?: FormDataNode;
|
|
253
|
+
formNode: FormNode;
|
|
254
|
+
parentData: SchemaDataNode;
|
|
255
|
+
childIndex?: number;
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
export function visitFormDataNode<A>(
|
|
259
|
+
node: FormDataNode,
|
|
260
|
+
visitFn: (node: FormDataNode, data?: SchemaDataNode) => A | undefined,
|
|
261
|
+
): A | undefined {
|
|
262
|
+
const dataNode = lookupDataNode(node.formNode.definition, node.parentData);
|
|
263
|
+
const v = visitFn(node, dataNode);
|
|
264
|
+
if (v !== undefined) return v;
|
|
265
|
+
|
|
266
|
+
const parentData = dataNode ?? node.parentData;
|
|
267
|
+
if (parentData.schema.field.collection && parentData.elementIndex == null) {
|
|
268
|
+
const elemCount = parentData.control.elements.length;
|
|
269
|
+
for (let i = 0; i < elemCount; i++) {
|
|
270
|
+
const v = visitChildren(parentData.getChildElement(i));
|
|
271
|
+
if (v !== undefined) return v;
|
|
272
|
+
}
|
|
273
|
+
return undefined;
|
|
274
|
+
} else {
|
|
275
|
+
return visitChildren(parentData);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
function visitChildren(parentData: SchemaDataNode) {
|
|
279
|
+
const children = node.formNode.getChildNodes();
|
|
280
|
+
for (let i = 0; i < children.length; i++) {
|
|
281
|
+
const child = children[i];
|
|
282
|
+
const res = visitFormDataNode(
|
|
283
|
+
{
|
|
284
|
+
formNode: child,
|
|
285
|
+
parent: node,
|
|
286
|
+
parentData,
|
|
287
|
+
childIndex: i,
|
|
288
|
+
},
|
|
289
|
+
visitFn,
|
|
290
|
+
);
|
|
291
|
+
if (res !== undefined) return res;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
}
|
package/src/formState.ts
CHANGED
|
@@ -24,15 +24,14 @@ import { SchemaInterface } from "./schemaInterface";
|
|
|
24
24
|
import { FieldOption } from "./schemaField";
|
|
25
25
|
import {
|
|
26
26
|
CleanupScope,
|
|
27
|
-
clearMetaValue,
|
|
28
27
|
Control,
|
|
29
28
|
createScopedEffect,
|
|
30
29
|
createSyncEffect,
|
|
31
30
|
ensureMetaValue,
|
|
32
31
|
getControlPath,
|
|
33
32
|
getCurrentFields,
|
|
33
|
+
getMetaValue,
|
|
34
34
|
newControl,
|
|
35
|
-
trackedValue,
|
|
36
35
|
unsafeRestoreControl,
|
|
37
36
|
updateComputedValue,
|
|
38
37
|
} from "@astroapps/controls";
|
|
@@ -49,6 +48,7 @@ export interface ControlState {
|
|
|
49
48
|
definition: ControlDefinition;
|
|
50
49
|
schemaInterface: SchemaInterface;
|
|
51
50
|
dataNode?: SchemaDataNode | undefined;
|
|
51
|
+
display?: string;
|
|
52
52
|
stateId?: string;
|
|
53
53
|
style?: object;
|
|
54
54
|
layoutStyle?: object;
|
|
@@ -58,6 +58,7 @@ export interface ControlState {
|
|
|
58
58
|
disabled: boolean;
|
|
59
59
|
clearHidden: boolean;
|
|
60
60
|
variables: Record<string, any>;
|
|
61
|
+
meta: Control<Record<string, any>>;
|
|
61
62
|
}
|
|
62
63
|
|
|
63
64
|
export interface FormContextOptions {
|
|
@@ -88,10 +89,24 @@ export interface FormState {
|
|
|
88
89
|
cleanup(): void;
|
|
89
90
|
|
|
90
91
|
evalExpression(expr: EntityExpression, context: ExpressionEvalContext): void;
|
|
92
|
+
|
|
93
|
+
getExistingControlState(
|
|
94
|
+
parent: SchemaDataNode,
|
|
95
|
+
formNode: FormNode,
|
|
96
|
+
stateKey?: string,
|
|
97
|
+
): ControlState | undefined;
|
|
91
98
|
}
|
|
92
99
|
|
|
93
100
|
const formStates: FormState[] = [];
|
|
94
101
|
|
|
102
|
+
export function getControlStateId(
|
|
103
|
+
parent: SchemaDataNode,
|
|
104
|
+
formNode: FormNode,
|
|
105
|
+
stateKey?: string,
|
|
106
|
+
): string {
|
|
107
|
+
return parent.id + "$" + formNode.id + (stateKey ?? "");
|
|
108
|
+
}
|
|
109
|
+
|
|
95
110
|
export function createFormState(
|
|
96
111
|
schemaInterface: SchemaInterface,
|
|
97
112
|
evaluators: Record<string, ExpressionEval<any>> = defaultEvaluators,
|
|
@@ -113,13 +128,25 @@ export function createFormState(
|
|
|
113
128
|
// console.log("Cleanup form state");
|
|
114
129
|
controlStates.cleanup();
|
|
115
130
|
},
|
|
131
|
+
getExistingControlState(
|
|
132
|
+
parent: SchemaDataNode,
|
|
133
|
+
formNode: FormNode,
|
|
134
|
+
stateKey?: string,
|
|
135
|
+
): ControlState | undefined {
|
|
136
|
+
const stateId = getControlStateId(parent, formNode, stateKey);
|
|
137
|
+
const control = getCurrentFields(controlStates)[stateId];
|
|
138
|
+
if (control) {
|
|
139
|
+
return getMetaValue<Control<ControlState>>(control, "impl")?.value;
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
},
|
|
116
143
|
getControlState(
|
|
117
144
|
parent: SchemaDataNode,
|
|
118
145
|
formNode: FormNode,
|
|
119
146
|
context: FormContextOptions,
|
|
120
147
|
runAsync: (af: () => void) => void,
|
|
121
148
|
): ControlState {
|
|
122
|
-
const stateId = parent
|
|
149
|
+
const stateId = getControlStateId(parent, formNode, context.stateKey);
|
|
123
150
|
const controlImpl = controlStates.fields[stateId];
|
|
124
151
|
controlImpl.value = context;
|
|
125
152
|
function evalExpr<A>(
|
|
@@ -173,34 +200,6 @@ export function createFormState(
|
|
|
173
200
|
Control<any>
|
|
174
201
|
>;
|
|
175
202
|
|
|
176
|
-
createScopedEffect((c) => {
|
|
177
|
-
const textDisplay =
|
|
178
|
-
isDisplayControl(def) && isTextDisplay(def.displayData)
|
|
179
|
-
? def.displayData
|
|
180
|
-
: undefined;
|
|
181
|
-
evalExpr(
|
|
182
|
-
c,
|
|
183
|
-
textDisplay?.text,
|
|
184
|
-
df.text,
|
|
185
|
-
textDisplay && firstExpr(formNode, DynamicPropertyType.Display),
|
|
186
|
-
coerceString,
|
|
187
|
-
);
|
|
188
|
-
}, displayOverrides);
|
|
189
|
-
|
|
190
|
-
createScopedEffect((c) => {
|
|
191
|
-
const htmlDisplay =
|
|
192
|
-
isDisplayControl(def) && isHtmlDisplay(def.displayData)
|
|
193
|
-
? def.displayData
|
|
194
|
-
: undefined;
|
|
195
|
-
evalExpr(
|
|
196
|
-
c,
|
|
197
|
-
htmlDisplay?.html,
|
|
198
|
-
df.html,
|
|
199
|
-
htmlDisplay && firstExpr(formNode, DynamicPropertyType.Display),
|
|
200
|
-
coerceString,
|
|
201
|
-
);
|
|
202
|
-
}, displayOverrides);
|
|
203
|
-
|
|
204
203
|
updateComputedValue(of.displayData, () =>
|
|
205
204
|
isDisplayControl(def)
|
|
206
205
|
? createOverrideProxy(def.displayData, displayOverrides)
|
|
@@ -281,6 +280,7 @@ export function createFormState(
|
|
|
281
280
|
hidden: false,
|
|
282
281
|
variables: controlImpl.fields.variables.current.value ?? {},
|
|
283
282
|
stateId,
|
|
283
|
+
meta: newControl({}),
|
|
284
284
|
});
|
|
285
285
|
|
|
286
286
|
const {
|
|
@@ -292,6 +292,7 @@ export function createFormState(
|
|
|
292
292
|
allowedOptions,
|
|
293
293
|
disabled,
|
|
294
294
|
variables,
|
|
295
|
+
display,
|
|
295
296
|
} = control.fields;
|
|
296
297
|
|
|
297
298
|
createScopedEffect(
|
|
@@ -330,6 +331,18 @@ export function createFormState(
|
|
|
330
331
|
scope,
|
|
331
332
|
);
|
|
332
333
|
|
|
334
|
+
createScopedEffect(
|
|
335
|
+
(c) =>
|
|
336
|
+
evalExpr(
|
|
337
|
+
c,
|
|
338
|
+
undefined,
|
|
339
|
+
display,
|
|
340
|
+
firstExpr(formNode, DynamicPropertyType.Display),
|
|
341
|
+
coerceString,
|
|
342
|
+
),
|
|
343
|
+
scope,
|
|
344
|
+
);
|
|
345
|
+
|
|
333
346
|
updateComputedValue(dataNode, () => lookupDataNode(definition, parent));
|
|
334
347
|
updateComputedValue(
|
|
335
348
|
hidden,
|
|
@@ -361,6 +374,14 @@ export function createFormState(
|
|
|
361
374
|
}
|
|
362
375
|
}, scope);
|
|
363
376
|
|
|
377
|
+
createSyncEffect(() => {
|
|
378
|
+
if (isDisplayControl(def)) {
|
|
379
|
+
if (isTextDisplay(def.displayData)) df.text.value = display.value;
|
|
380
|
+
else if (isHtmlDisplay(def.displayData))
|
|
381
|
+
df.html.value = display.value;
|
|
382
|
+
}
|
|
383
|
+
}, displayOverrides);
|
|
384
|
+
|
|
364
385
|
setupValidation(
|
|
365
386
|
controlImpl,
|
|
366
387
|
definition,
|