@getodk/xforms-engine 0.15.0 → 0.16.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/dist/client/AttributeNode.d.ts +4 -6
- package/dist/client/BaseNode.d.ts +5 -0
- package/dist/client/form/FormInstanceConfig.d.ts +15 -0
- package/dist/index.js +654 -429
- package/dist/index.js.map +1 -1
- package/dist/instance/Attribute.d.ts +13 -19
- package/dist/instance/Group.d.ts +2 -1
- package/dist/instance/InputControl.d.ts +5 -0
- package/dist/instance/ModelValue.d.ts +4 -0
- package/dist/instance/Note.d.ts +4 -0
- package/dist/instance/PrimaryInstance.d.ts +3 -2
- package/dist/instance/RangeControl.d.ts +4 -0
- package/dist/instance/RankControl.d.ts +5 -1
- package/dist/instance/Root.d.ts +2 -1
- package/dist/instance/SelectControl.d.ts +5 -1
- package/dist/instance/TriggerControl.d.ts +4 -0
- package/dist/instance/UploadControl.d.ts +3 -2
- package/dist/instance/abstract/DescendantNode.d.ts +5 -4
- package/dist/instance/abstract/InstanceNode.d.ts +6 -5
- package/dist/instance/abstract/ValueNode.d.ts +2 -1
- package/dist/instance/attachments/buildAttributes.d.ts +6 -2
- package/dist/instance/hierarchy.d.ts +2 -2
- package/dist/instance/internal-api/AttributeContext.d.ts +6 -0
- package/dist/instance/internal-api/InstanceConfig.d.ts +2 -0
- package/dist/instance/internal-api/InstanceValueContext.d.ts +6 -0
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.d.ts +0 -1
- package/dist/instance/internal-api/serialization/ClientReactiveSerializableValueNode.d.ts +4 -0
- package/dist/integration/xpath/adapter/XFormsXPathNode.d.ts +1 -1
- package/dist/integration/xpath/adapter/kind.d.ts +5 -3
- package/dist/integration/xpath/adapter/traversal.d.ts +3 -3
- package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +1 -0
- package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +1 -1
- package/dist/lib/reactivity/createInstanceValueState.d.ts +4 -1
- package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +2 -2
- package/dist/lib/xml-serialization.d.ts +1 -1
- package/dist/parse/XFormDOM.d.ts +3 -0
- package/dist/parse/expression/ActionComputationExpression.d.ts +4 -0
- package/dist/parse/model/ActionDefinition.d.ts +15 -0
- package/dist/parse/model/AttributeDefinition.d.ts +5 -1
- package/dist/parse/model/BindPreloadDefinition.d.ts +6 -10
- package/dist/parse/model/Event.d.ts +8 -0
- package/dist/parse/model/LeafNodeDefinition.d.ts +5 -2
- package/dist/parse/model/ModelActionMap.d.ts +9 -0
- package/dist/parse/model/ModelDefinition.d.ts +8 -1
- package/dist/parse/model/NoteNodeDefinition.d.ts +3 -2
- package/dist/parse/model/RangeNodeDefinition.d.ts +2 -1
- package/dist/parse/model/RootDefinition.d.ts +1 -0
- package/dist/solid.js +654 -429
- package/dist/solid.js.map +1 -1
- package/package.json +21 -17
- package/src/client/AttributeNode.ts +4 -6
- package/src/client/BaseNode.ts +6 -0
- package/src/client/form/FormInstanceConfig.ts +17 -0
- package/src/client/validation.ts +1 -1
- package/src/entrypoints/FormInstance.ts +1 -0
- package/src/instance/Attribute.ts +43 -59
- package/src/instance/Group.ts +5 -6
- package/src/instance/InputControl.ts +16 -1
- package/src/instance/ModelValue.ts +16 -1
- package/src/instance/Note.ts +15 -1
- package/src/instance/PrimaryInstance.ts +8 -10
- package/src/instance/RangeControl.ts +15 -1
- package/src/instance/RankControl.ts +17 -2
- package/src/instance/Root.ts +5 -6
- package/src/instance/SelectControl.ts +16 -2
- package/src/instance/TriggerControl.ts +15 -1
- package/src/instance/UploadControl.ts +9 -8
- package/src/instance/abstract/DescendantNode.ts +4 -8
- package/src/instance/abstract/InstanceNode.ts +7 -5
- package/src/instance/abstract/ValueNode.ts +2 -1
- package/src/instance/attachments/buildAttributes.ts +15 -4
- package/src/instance/children/childrenInitOptions.ts +2 -1
- package/src/instance/children/normalizeChildInitOptions.ts +1 -1
- package/src/instance/hierarchy.ts +2 -2
- package/src/instance/internal-api/AttributeContext.ts +6 -0
- package/src/instance/internal-api/InstanceConfig.ts +6 -1
- package/src/instance/internal-api/InstanceValueContext.ts +6 -0
- package/src/instance/internal-api/serialization/ClientReactiveSerializableAttributeNode.ts +0 -1
- package/src/instance/internal-api/serialization/ClientReactiveSerializableValueNode.ts +4 -0
- package/src/instance/repeat/RepeatInstance.ts +3 -4
- package/src/integration/xpath/adapter/XFormsXPathNode.ts +1 -0
- package/src/integration/xpath/adapter/engineDOMAdapter.ts +2 -2
- package/src/integration/xpath/adapter/kind.ts +6 -1
- package/src/integration/xpath/adapter/names.ts +1 -0
- package/src/integration/xpath/adapter/traversal.ts +5 -6
- package/src/integration/xpath/static-dom/StaticAttribute.ts +1 -0
- package/src/lib/client-reactivity/instance-state/createValueNodeInstanceState.ts +2 -1
- package/src/lib/client-reactivity/instance-state/prepareInstancePayload.ts +1 -0
- package/src/lib/codecs/NoteCodec.ts +1 -1
- package/src/lib/codecs/items/SingleValueItemCodec.ts +1 -3
- package/src/lib/reactivity/createInstanceValueState.ts +177 -52
- package/src/lib/reactivity/node-state/createSharedNodeState.ts +2 -2
- package/src/lib/xml-serialization.ts +9 -1
- package/src/parse/XFormDOM.ts +9 -0
- package/src/parse/body/GroupElementDefinition.ts +1 -1
- package/src/parse/body/control/InputControlDefinition.ts +1 -1
- package/src/parse/expression/ActionComputationExpression.ts +12 -0
- package/src/parse/model/ActionDefinition.ts +70 -0
- package/src/parse/model/AttributeDefinition.ts +10 -2
- package/src/parse/model/AttributeDefinitionMap.ts +1 -1
- package/src/parse/model/BindDefinition.ts +1 -6
- package/src/parse/model/BindPreloadDefinition.ts +44 -12
- package/src/parse/model/Event.ts +9 -0
- package/src/parse/model/LeafNodeDefinition.ts +5 -1
- package/src/parse/model/ModelActionMap.ts +37 -0
- package/src/parse/model/ModelDefinition.ts +18 -3
- package/src/parse/model/NoteNodeDefinition.ts +5 -2
- package/src/parse/model/RangeNodeDefinition.ts +5 -2
- package/src/parse/model/RootDefinition.ts +22 -4
- package/dist/lib/reactivity/createAttributeValueState.d.ts +0 -15
- package/src/lib/reactivity/createAttributeValueState.ts +0 -189
|
@@ -1,189 +0,0 @@
|
|
|
1
|
-
import type { Signal } from 'solid-js';
|
|
2
|
-
import { createComputed, createMemo, createSignal, untrack } from 'solid-js';
|
|
3
|
-
import type { AttributeContext } from '../../instance/internal-api/AttributeContext.ts';
|
|
4
|
-
import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
|
|
5
|
-
import { createComputedExpression } from './createComputedExpression.ts';
|
|
6
|
-
import type { SimpleAtomicState, SimpleAtomicStateSetter } from './types.ts';
|
|
7
|
-
|
|
8
|
-
const isInstanceFirstLoad = (context: AttributeContext) => {
|
|
9
|
-
return context.rootDocument.initializationMode === 'create';
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Special case, does not correspond to any event.
|
|
14
|
-
*
|
|
15
|
-
* @see {@link shouldPreloadUID}
|
|
16
|
-
*/
|
|
17
|
-
const isEditInitialLoad = (context: AttributeContext) => {
|
|
18
|
-
return context.rootDocument.initializationMode === 'edit';
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
const getInitialValue = (context: AttributeContext): string => {
|
|
22
|
-
const sourceNode = context.instanceNode ?? context.definition.template;
|
|
23
|
-
|
|
24
|
-
return context.decodeInstanceValue(sourceNode.value);
|
|
25
|
-
};
|
|
26
|
-
|
|
27
|
-
type BaseValueState = Signal<string>;
|
|
28
|
-
|
|
29
|
-
type RelevantValueState = SimpleAtomicState<string>;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Wraps {@link baseValueState} in a signal-like interface which:
|
|
33
|
-
*
|
|
34
|
-
* - produces a blank value for nodes ({@link context}) in a non-relevant state
|
|
35
|
-
* - persists, and restores, the most recent non-blank value state when a
|
|
36
|
-
* node/context's relevance is restored
|
|
37
|
-
*/
|
|
38
|
-
const createRelevantValueState = (
|
|
39
|
-
context: AttributeContext,
|
|
40
|
-
baseValueState: BaseValueState
|
|
41
|
-
): RelevantValueState => {
|
|
42
|
-
return context.scope.runTask(() => {
|
|
43
|
-
const [getRelevantValue, setValue] = baseValueState;
|
|
44
|
-
|
|
45
|
-
const getValue = createMemo(() => {
|
|
46
|
-
if (context.isRelevant()) {
|
|
47
|
-
return getRelevantValue();
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return '';
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
return [getValue, setValue];
|
|
54
|
-
});
|
|
55
|
-
};
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* For fields with a `readonly` bind expression, prevent downstream
|
|
59
|
-
* (client/user) writes when the field is in a `readonly` state.
|
|
60
|
-
*/
|
|
61
|
-
const guardDownstreamReadonlyWrites = (
|
|
62
|
-
context: AttributeContext,
|
|
63
|
-
baseState: SimpleAtomicState<string>
|
|
64
|
-
): SimpleAtomicState<string> => {
|
|
65
|
-
const { readonly } = context.definition.bind;
|
|
66
|
-
|
|
67
|
-
if (readonly.isDefaultExpression) {
|
|
68
|
-
return baseState;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const [getValue, baseSetValue] = baseState;
|
|
72
|
-
|
|
73
|
-
const setValue: SimpleAtomicStateSetter<string> = (value) => {
|
|
74
|
-
if (context.isReadonly()) {
|
|
75
|
-
const reference = untrack(() => context.contextReference());
|
|
76
|
-
|
|
77
|
-
throw new Error(`Cannot write to readonly field: ${reference}`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
return baseSetValue(value);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
return [getValue, setValue];
|
|
84
|
-
};
|
|
85
|
-
|
|
86
|
-
/**
|
|
87
|
-
* Per {@link https://getodk.github.io/xforms-spec/#preload-attributes:~:text=concatenation%20of%20%E2%80%98uuid%3A%E2%80%99%20and%20uuid()}
|
|
88
|
-
*/
|
|
89
|
-
const PRELOAD_UID_EXPRESSION = 'concat("uuid:", uuid())';
|
|
90
|
-
|
|
91
|
-
/**
|
|
92
|
-
* @todo It feels increasingly awkward to keep piling up preload stuff here, but it won't stay that way for long. In the meantime, this seems like the best way to express the cases where `preload="uid"` should be effective, i.e.:
|
|
93
|
-
*
|
|
94
|
-
* - When an instance is first loaded ({@link isInstanceFirstLoad})
|
|
95
|
-
* - When an instance is initially loaded for editing ({@link isEditInitialLoad})
|
|
96
|
-
*/
|
|
97
|
-
const shouldPreloadUID = (context: AttributeContext) => {
|
|
98
|
-
return isInstanceFirstLoad(context) || isEditInitialLoad(context);
|
|
99
|
-
};
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* @todo This is a temporary one-off, until we support the full range of
|
|
103
|
-
* {@link https://getodk.github.io/xforms-spec/#preload-attributes | preloads}.
|
|
104
|
-
*
|
|
105
|
-
* @todo ALSO, IMPORTANTLY(!): the **call site** for this function is
|
|
106
|
-
* semantically where we would expect to trigger a
|
|
107
|
-
* {@link https://getodk.github.io/xforms-spec/#event:odk-instance-first-load | odk-instance-first-load event},
|
|
108
|
-
* _and compute_ preloads semantically associated with that event.
|
|
109
|
-
*/
|
|
110
|
-
const setPreloadUIDValue = (context: AttributeContext, valueState: RelevantValueState): void => {
|
|
111
|
-
const { preload } = context.definition.bind;
|
|
112
|
-
|
|
113
|
-
if (preload?.type !== 'uid' || !shouldPreloadUID(context)) {
|
|
114
|
-
return;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
const preloadUIDValue = context.evaluator.evaluateString(PRELOAD_UID_EXPRESSION, {
|
|
118
|
-
contextNode: context.contextNode,
|
|
119
|
-
});
|
|
120
|
-
|
|
121
|
-
const [, setValue] = valueState;
|
|
122
|
-
|
|
123
|
-
setValue(preloadUIDValue);
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
/**
|
|
127
|
-
* Defines a reactive effect which writes the result of `calculate` bind
|
|
128
|
-
* computations to the provided value setter, on initialization and any
|
|
129
|
-
* subsequent reactive update.
|
|
130
|
-
*
|
|
131
|
-
* @see {@link setPreloadUIDValue} for important details about spec ordering of
|
|
132
|
-
* events and computations.
|
|
133
|
-
*/
|
|
134
|
-
const createCalculation = (
|
|
135
|
-
context: AttributeContext,
|
|
136
|
-
setRelevantValue: SimpleAtomicStateSetter<string>,
|
|
137
|
-
calculateDefinition: BindComputationExpression<'calculate'>
|
|
138
|
-
): void => {
|
|
139
|
-
context.scope.runTask(() => {
|
|
140
|
-
const calculate = createComputedExpression(context, calculateDefinition, {
|
|
141
|
-
defaultValue: '',
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
createComputed(() => {
|
|
145
|
-
if (context.isAttached() && context.isRelevant()) {
|
|
146
|
-
const calculated = calculate();
|
|
147
|
-
const value = context.decodeInstanceValue(calculated);
|
|
148
|
-
|
|
149
|
-
setRelevantValue(value);
|
|
150
|
-
}
|
|
151
|
-
});
|
|
152
|
-
});
|
|
153
|
-
};
|
|
154
|
-
|
|
155
|
-
export type InstanceValueState = SimpleAtomicState<string>;
|
|
156
|
-
|
|
157
|
-
/**
|
|
158
|
-
* Provides a consistent interface for value nodes of any type which:
|
|
159
|
-
*
|
|
160
|
-
* - derives initial state from either an existing instance (e.g. for edits) or
|
|
161
|
-
* the node's definition (e.g. initializing a new instance)
|
|
162
|
-
* - decodes current primary instance state into the value node's runtime type
|
|
163
|
-
* - encodes updated runtime values to store updated instance state
|
|
164
|
-
* - initializes reactive computation of `calculate` bind expressions for those
|
|
165
|
-
* nodes defined with one
|
|
166
|
-
* - prevents downstream writes to nodes in a readonly state
|
|
167
|
-
*/
|
|
168
|
-
export const createAttributeValueState = (context: AttributeContext): InstanceValueState => {
|
|
169
|
-
return context.scope.runTask(() => {
|
|
170
|
-
const initialValue = getInitialValue(context);
|
|
171
|
-
const baseValueState = createSignal(initialValue);
|
|
172
|
-
const relevantValueState = createRelevantValueState(context, baseValueState);
|
|
173
|
-
|
|
174
|
-
/**
|
|
175
|
-
* @see {@link setPreloadUIDValue} for important details about spec ordering of events and computations.
|
|
176
|
-
*/
|
|
177
|
-
setPreloadUIDValue(context, relevantValueState);
|
|
178
|
-
|
|
179
|
-
const { calculate } = context.definition.bind;
|
|
180
|
-
|
|
181
|
-
if (calculate != null) {
|
|
182
|
-
const [, setValue] = relevantValueState;
|
|
183
|
-
|
|
184
|
-
createCalculation(context, setValue, calculate);
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
return guardDownstreamReadonlyWrites(context, relevantValueState);
|
|
188
|
-
});
|
|
189
|
-
};
|