@astroapps/forms-core 1.0.2 → 1.1.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@astroapps/forms-core",
3
- "version": "1.0.2",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "lib/index.cjs",
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";
@@ -58,6 +57,7 @@ export interface ControlState {
58
57
  disabled: boolean;
59
58
  clearHidden: boolean;
60
59
  variables: Record<string, any>;
60
+ meta: Control<Record<string, any>>;
61
61
  }
62
62
 
63
63
  export interface FormContextOptions {
@@ -88,10 +88,24 @@ export interface FormState {
88
88
  cleanup(): void;
89
89
 
90
90
  evalExpression(expr: EntityExpression, context: ExpressionEvalContext): void;
91
+
92
+ getExistingControlState(
93
+ parent: SchemaDataNode,
94
+ formNode: FormNode,
95
+ stateKey?: string,
96
+ ): ControlState | undefined;
91
97
  }
92
98
 
93
99
  const formStates: FormState[] = [];
94
100
 
101
+ export function getControlStateId(
102
+ parent: SchemaDataNode,
103
+ formNode: FormNode,
104
+ stateKey?: string,
105
+ ): string {
106
+ return parent.id + "$" + formNode.id + (stateKey ?? "");
107
+ }
108
+
95
109
  export function createFormState(
96
110
  schemaInterface: SchemaInterface,
97
111
  evaluators: Record<string, ExpressionEval<any>> = defaultEvaluators,
@@ -113,13 +127,25 @@ export function createFormState(
113
127
  // console.log("Cleanup form state");
114
128
  controlStates.cleanup();
115
129
  },
130
+ getExistingControlState(
131
+ parent: SchemaDataNode,
132
+ formNode: FormNode,
133
+ stateKey?: string,
134
+ ): ControlState | undefined {
135
+ const stateId = getControlStateId(parent, formNode, stateKey);
136
+ const control = getCurrentFields(controlStates)[stateId];
137
+ if (control) {
138
+ return getMetaValue<Control<ControlState>>(control, "impl")?.value;
139
+ }
140
+ return undefined;
141
+ },
116
142
  getControlState(
117
143
  parent: SchemaDataNode,
118
144
  formNode: FormNode,
119
145
  context: FormContextOptions,
120
146
  runAsync: (af: () => void) => void,
121
147
  ): ControlState {
122
- const stateId = parent.id + "$" + formNode.id + (context.stateKey ?? "");
148
+ const stateId = getControlStateId(parent, formNode, context.stateKey);
123
149
  const controlImpl = controlStates.fields[stateId];
124
150
  controlImpl.value = context;
125
151
  function evalExpr<A>(
@@ -281,6 +307,7 @@ export function createFormState(
281
307
  hidden: false,
282
308
  variables: controlImpl.fields.variables.current.value ?? {},
283
309
  stateId,
310
+ meta: newControl({}),
284
311
  });
285
312
 
286
313
  const {