@getodk/xforms-engine 0.2.0 → 0.4.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/client/BaseNode.d.ts +69 -4
- package/dist/client/EngineConfig.d.ts +0 -1
- package/dist/client/GroupNode.d.ts +4 -3
- package/dist/client/ModelValueNode.d.ts +36 -0
- package/dist/client/NodeAppearances.d.ts +1 -2
- package/dist/client/NoteNode.d.ts +52 -0
- package/dist/client/RootNode.d.ts +4 -3
- package/dist/client/SelectNode.d.ts +6 -5
- package/dist/client/StringNode.d.ts +6 -5
- package/dist/client/SubtreeNode.d.ts +3 -2
- package/dist/client/TextRange.d.ts +85 -3
- package/dist/client/TriggerNode.d.ts +25 -0
- package/dist/client/constants.d.ts +8 -0
- package/dist/client/hierarchy.d.ts +19 -10
- package/dist/client/index.d.ts +0 -1
- package/dist/client/node-types.d.ts +3 -1
- package/dist/client/{RepeatRangeNode.d.ts → repeat/BaseRepeatRangeNode.d.ts} +18 -18
- package/dist/client/{RepeatInstanceNode.d.ts → repeat/RepeatInstanceNode.d.ts} +9 -9
- package/dist/client/repeat/RepeatRangeControlledNode.d.ts +18 -0
- package/dist/client/repeat/RepeatRangeUncontrolledNode.d.ts +19 -0
- package/dist/client/unsupported/RangeNode.d.ts +9 -0
- package/dist/client/unsupported/RankNode.d.ts +9 -0
- package/dist/client/unsupported/UnsupportedControlNode.d.ts +32 -0
- package/dist/client/unsupported/UploadNode.d.ts +9 -0
- package/dist/client/validation.d.ts +162 -0
- package/dist/index.d.ts +14 -6
- package/dist/index.js +39696 -36151
- package/dist/index.js.map +1 -1
- package/dist/instance/Group.d.ts +3 -2
- package/dist/instance/ModelValue.d.ts +39 -0
- package/dist/instance/Note.d.ts +41 -0
- package/dist/instance/Root.d.ts +5 -4
- package/dist/instance/SelectField.d.ts +11 -6
- package/dist/instance/StringField.d.ts +12 -7
- package/dist/instance/Subtree.d.ts +2 -1
- package/dist/instance/TriggerControl.d.ts +40 -0
- package/dist/instance/abstract/DescendantNode.d.ts +8 -10
- package/dist/instance/abstract/InstanceNode.d.ts +3 -2
- package/dist/instance/abstract/UnsupportedControl.d.ts +46 -0
- package/dist/instance/children.d.ts +0 -1
- package/dist/instance/hierarchy.d.ts +15 -6
- package/dist/instance/index.d.ts +0 -1
- package/dist/instance/internal-api/EvaluationContext.d.ts +0 -1
- package/dist/instance/internal-api/InstanceConfig.d.ts +0 -1
- package/dist/instance/internal-api/SubscribableDependency.d.ts +0 -1
- package/dist/instance/internal-api/TranslationContext.d.ts +0 -1
- package/dist/instance/internal-api/ValidationContext.d.ts +28 -0
- package/dist/instance/internal-api/ValueContext.d.ts +3 -4
- package/dist/instance/{RepeatRange.d.ts → repeat/BaseRepeatRange.d.ts} +46 -46
- package/dist/instance/{RepeatInstance.d.ts → repeat/RepeatInstance.d.ts} +13 -13
- package/dist/instance/repeat/RepeatRangeControlled.d.ts +15 -0
- package/dist/instance/repeat/RepeatRangeUncontrolled.d.ts +34 -0
- package/dist/instance/resource.d.ts +0 -1
- package/dist/instance/text/TextChunk.d.ts +0 -1
- package/dist/instance/text/TextRange.d.ts +4 -5
- package/dist/instance/unsupported/RangeControl.d.ts +4 -0
- package/dist/instance/unsupported/RankControl.d.ts +4 -0
- package/dist/instance/unsupported/UploadControl.d.ts +4 -0
- package/dist/lib/TokenListParser.d.ts +3 -3
- package/dist/lib/dom/query.d.ts +1 -2
- package/dist/lib/reactivity/createChildrenState.d.ts +0 -1
- package/dist/lib/reactivity/createComputedExpression.d.ts +7 -3
- package/dist/lib/reactivity/createNoteReadonlyThunk.d.ts +4 -0
- package/dist/lib/reactivity/createSelectItems.d.ts +0 -1
- package/dist/lib/reactivity/createValueState.d.ts +0 -1
- package/dist/lib/reactivity/materializeCurrentStateChildren.d.ts +0 -1
- package/dist/lib/reactivity/node-state/createClientState.d.ts +0 -1
- package/dist/lib/reactivity/node-state/createCurrentState.d.ts +0 -1
- package/dist/lib/reactivity/node-state/createEngineState.d.ts +0 -1
- package/dist/lib/reactivity/node-state/createSharedNodeState.d.ts +1 -2
- package/dist/lib/reactivity/node-state/createSpecifiedPropertyDescriptor.d.ts +0 -1
- package/dist/lib/reactivity/node-state/createSpecifiedState.d.ts +1 -2
- package/dist/lib/reactivity/node-state/representations.d.ts +0 -1
- package/dist/lib/reactivity/scope.d.ts +0 -1
- package/dist/lib/reactivity/text/createFieldHint.d.ts +3 -4
- package/dist/lib/reactivity/text/createNodeLabel.d.ts +3 -4
- package/dist/lib/reactivity/text/createNoteText.d.ts +24 -0
- package/dist/lib/reactivity/text/createTextRange.d.ts +5 -8
- package/dist/lib/reactivity/types.d.ts +0 -1
- package/dist/lib/reactivity/validation/createAggregatedViolations.d.ts +8 -0
- package/dist/lib/reactivity/validation/createValidation.d.ts +17 -0
- package/dist/{XFormDOM.d.ts → parse/XFormDOM.d.ts} +1 -2
- package/dist/{XFormDataType.d.ts → parse/XFormDataType.d.ts} +2 -4
- package/dist/{XFormDefinition.d.ts → parse/XFormDefinition.d.ts} +2 -3
- package/dist/{body → parse/body}/BodyDefinition.d.ts +15 -10
- package/dist/{body → parse/body}/BodyElementDefinition.d.ts +8 -7
- package/dist/{body → parse/body}/RepeatElementDefinition.d.ts +4 -5
- package/dist/{body → parse/body}/UnsupportedBodyElementDefinition.d.ts +0 -1
- package/dist/{body → parse/body}/appearance/inputAppearanceParser.d.ts +1 -2
- package/dist/{body → parse/body}/appearance/selectAppearanceParser.d.ts +1 -2
- package/dist/{body → parse/body}/appearance/structureElementAppearanceParser.d.ts +1 -2
- package/dist/parse/body/appearance/unknownAppearanceParser.d.ts +3 -0
- package/dist/{body → parse/body}/control/ControlDefinition.d.ts +3 -4
- package/dist/{body → parse/body}/control/InputDefinition.d.ts +1 -2
- package/dist/parse/body/control/RangeControlDefinition.d.ts +11 -0
- package/dist/parse/body/control/RankControlDefinition.d.ts +11 -0
- package/dist/parse/body/control/TriggerControlDefinition.d.ts +11 -0
- package/dist/parse/body/control/UploadControlDefinition.d.ts +11 -0
- package/dist/{body → parse/body}/control/select/ItemDefinition.d.ts +3 -4
- package/dist/{body → parse/body}/control/select/ItemsetDefinition.d.ts +7 -7
- package/dist/{body → parse/body}/control/select/ItemsetNodesetContext.d.ts +2 -3
- package/dist/{body → parse/body}/control/select/SelectDefinition.d.ts +3 -12
- package/dist/{body → parse/body}/group/BaseGroupDefinition.d.ts +3 -5
- package/dist/{body → parse/body}/group/LogicalGroupDefinition.d.ts +0 -1
- package/dist/{body → parse/body}/group/PresentationGroupDefinition.d.ts +1 -2
- package/dist/{body → parse/body}/group/StructuralGroupDefinition.d.ts +0 -1
- package/dist/{model/BindComputation.d.ts → parse/expression/BindComputationExpression.d.ts} +5 -6
- package/dist/{body/control/select → parse/expression}/ItemsetNodesetExpression.d.ts +2 -3
- package/dist/{body/control/select → parse/expression}/ItemsetValueExpression.d.ts +2 -3
- package/dist/parse/expression/RepeatCountControlExpression.d.ts +18 -0
- package/dist/parse/expression/TextLiteralExpression.d.ts +9 -0
- package/dist/parse/expression/TextOutputExpression.d.ts +7 -0
- package/dist/parse/expression/TextReferenceExpression.d.ts +7 -0
- package/dist/parse/expression/TextTranslationExpression.d.ts +8 -0
- package/dist/{expression → parse/expression/abstract}/DependencyContext.d.ts +0 -1
- package/dist/{expression → parse/expression/abstract}/DependentExpression.d.ts +13 -10
- package/dist/parse/expression/abstract/TextChunkExpression.d.ts +17 -0
- package/dist/parse/model/BindDefinition.d.ts +39 -0
- package/dist/{model → parse/model}/BindElement.d.ts +1 -0
- package/dist/{model → parse/model}/DescendentNodeDefinition.d.ts +0 -1
- package/dist/{model/ValueNodeDefinition.d.ts → parse/model/LeafNodeDefinition.d.ts} +3 -4
- package/dist/{model → parse/model}/ModelBindMap.d.ts +0 -1
- package/dist/{model → parse/model}/ModelDefinition.d.ts +1 -2
- package/dist/{model → parse/model}/NodeDefinition.d.ts +8 -9
- package/dist/parse/model/NoteNodeDefinition.d.ts +30 -0
- package/dist/{model → parse/model}/RepeatInstanceDefinition.d.ts +3 -4
- package/dist/{model → parse/model}/RepeatRangeDefinition.d.ts +14 -5
- package/dist/{model → parse/model}/RepeatTemplateDefinition.d.ts +2 -3
- package/dist/{model → parse/model}/RootDefinition.d.ts +2 -3
- package/dist/{model → parse/model}/SubtreeDefinition.d.ts +1 -2
- package/dist/parse/text/HintDefinition.d.ts +8 -0
- package/dist/parse/text/ItemLabelDefinition.d.ts +8 -0
- package/dist/parse/text/ItemsetLabelDefinition.d.ts +12 -0
- package/dist/parse/text/LabelDefinition.d.ts +14 -0
- package/dist/parse/text/MessageDefinition.d.ts +14 -0
- package/dist/parse/text/abstract/TextElementDefinition.d.ts +22 -0
- package/dist/parse/text/abstract/TextRangeDefinition.d.ts +34 -0
- package/dist/parse/xpath/dependency-analysis.d.ts +40 -0
- package/dist/parse/xpath/path-resolution.d.ts +69 -0
- package/dist/parse/xpath/predicate-analysis.d.ts +29 -0
- package/dist/parse/xpath/reference-parsing.d.ts +17 -0
- package/dist/parse/xpath/semantic-analysis.d.ts +97 -0
- package/dist/parse/xpath/syntax-traversal.d.ts +68 -0
- package/dist/solid.js +8745 -5186
- package/dist/solid.js.map +1 -1
- package/package.json +15 -16
- package/src/client/BaseNode.ts +74 -8
- package/src/client/GroupNode.ts +4 -2
- package/src/client/ModelValueNode.ts +40 -0
- package/src/client/NodeAppearances.ts +1 -1
- package/src/client/NoteNode.ts +74 -0
- package/src/client/README.md +1 -0
- package/src/client/RootNode.ts +4 -2
- package/src/client/SelectNode.ts +6 -4
- package/src/client/StringNode.ts +6 -4
- package/src/client/SubtreeNode.ts +3 -1
- package/src/client/TextRange.ts +98 -2
- package/src/client/TriggerNode.ts +29 -0
- package/src/client/constants.ts +10 -0
- package/src/client/hierarchy.ts +43 -15
- package/src/client/node-types.ts +17 -2
- package/src/client/{RepeatRangeNode.ts → repeat/BaseRepeatRangeNode.ts} +18 -19
- package/src/client/{RepeatInstanceNode.ts → repeat/RepeatInstanceNode.ts} +10 -8
- package/src/client/repeat/RepeatRangeControlledNode.ts +20 -0
- package/src/client/repeat/RepeatRangeUncontrolledNode.ts +21 -0
- package/src/client/unsupported/RangeNode.ts +14 -0
- package/src/client/unsupported/RankNode.ts +14 -0
- package/src/client/unsupported/UnsupportedControlNode.ts +40 -0
- package/src/client/unsupported/UploadNode.ts +14 -0
- package/src/client/validation.ts +199 -0
- package/src/index.ts +21 -9
- package/src/instance/Group.ts +10 -4
- package/src/instance/ModelValue.ts +104 -0
- package/src/instance/Note.ts +142 -0
- package/src/instance/Root.ts +16 -6
- package/src/instance/SelectField.ts +29 -7
- package/src/instance/StringField.ts +36 -10
- package/src/instance/Subtree.ts +9 -3
- package/src/instance/TriggerControl.ts +134 -0
- package/src/instance/abstract/DescendantNode.ts +9 -10
- package/src/instance/abstract/InstanceNode.ts +29 -7
- package/src/instance/abstract/UnsupportedControl.ts +151 -0
- package/src/instance/children.ts +113 -16
- package/src/instance/hierarchy.ts +42 -5
- package/src/instance/index.ts +1 -1
- package/src/instance/internal-api/EvaluationContext.ts +1 -1
- package/src/instance/internal-api/ValidationContext.ts +32 -0
- package/src/instance/internal-api/ValueContext.ts +3 -3
- package/src/instance/{RepeatRange.ts → repeat/BaseRepeatRange.ts} +114 -99
- package/src/instance/{RepeatInstance.ts → repeat/RepeatInstance.ts} +27 -22
- package/src/instance/repeat/RepeatRangeControlled.ts +82 -0
- package/src/instance/repeat/RepeatRangeUncontrolled.ts +67 -0
- package/src/instance/text/TextRange.ts +10 -4
- package/src/instance/unsupported/RangeControl.ts +5 -0
- package/src/instance/unsupported/RankControl.ts +5 -0
- package/src/instance/unsupported/UploadControl.ts +5 -0
- package/src/lib/TokenListParser.ts +11 -7
- package/src/lib/dom/query.ts +1 -1
- package/src/lib/reactivity/createComputedExpression.ts +25 -27
- package/src/lib/reactivity/createNoteReadonlyThunk.ts +33 -0
- package/src/lib/reactivity/createSelectItems.ts +23 -16
- package/src/lib/reactivity/createValueState.ts +3 -3
- package/src/lib/reactivity/node-state/createSharedNodeState.ts +1 -1
- package/src/lib/reactivity/node-state/createSpecifiedState.ts +1 -1
- package/src/lib/reactivity/text/createFieldHint.ts +9 -7
- package/src/lib/reactivity/text/createNodeLabel.ts +8 -6
- package/src/lib/reactivity/text/createNoteText.ts +72 -0
- package/src/lib/reactivity/text/createTextRange.ts +17 -90
- package/src/lib/reactivity/validation/createAggregatedViolations.ts +75 -0
- package/src/lib/reactivity/validation/createValidation.ts +196 -0
- package/src/{XFormDataType.ts → parse/XFormDataType.ts} +1 -3
- package/src/{XFormDefinition.ts → parse/XFormDefinition.ts} +2 -2
- package/src/{body → parse/body}/BodyDefinition.ts +44 -27
- package/src/{body → parse/body}/BodyElementDefinition.ts +13 -6
- package/src/{body → parse/body}/RepeatElementDefinition.ts +10 -20
- package/src/{body → parse/body}/appearance/inputAppearanceParser.ts +1 -1
- package/src/{body → parse/body}/appearance/selectAppearanceParser.ts +1 -1
- package/src/{body → parse/body}/appearance/structureElementAppearanceParser.ts +1 -1
- package/src/parse/body/appearance/unknownAppearanceParser.ts +5 -0
- package/src/{body → parse/body}/control/ControlDefinition.ts +5 -4
- package/src/parse/body/control/RangeControlDefinition.ts +26 -0
- package/src/parse/body/control/RankControlDefinition.ts +27 -0
- package/src/parse/body/control/TriggerControlDefinition.ts +26 -0
- package/src/parse/body/control/UploadControlDefinition.ts +26 -0
- package/src/{body → parse/body}/control/select/ItemDefinition.ts +4 -4
- package/src/parse/body/control/select/ItemsetDefinition.ts +53 -0
- package/src/{body → parse/body}/control/select/ItemsetNodesetContext.ts +2 -2
- package/src/{body → parse/body}/control/select/SelectDefinition.ts +3 -11
- package/src/{body → parse/body}/group/BaseGroupDefinition.ts +11 -21
- package/src/{body → parse/body}/group/PresentationGroupDefinition.ts +1 -1
- package/src/{model/BindComputation.ts → parse/expression/BindComputationExpression.ts} +8 -12
- package/src/parse/expression/ItemsetNodesetExpression.ts +8 -0
- package/src/{body/control/select → parse/expression}/ItemsetValueExpression.ts +2 -2
- package/src/parse/expression/RepeatCountControlExpression.ts +44 -0
- package/src/parse/expression/TextLiteralExpression.ts +19 -0
- package/src/parse/expression/TextOutputExpression.ts +25 -0
- package/src/parse/expression/TextReferenceExpression.ts +14 -0
- package/src/parse/expression/TextTranslationExpression.ts +38 -0
- package/src/{expression → parse/expression/abstract}/DependentExpression.ts +46 -28
- package/src/parse/expression/abstract/TextChunkExpression.ts +38 -0
- package/src/{model → parse/model}/BindDefinition.ts +30 -27
- package/src/{model → parse/model}/BindElement.ts +1 -0
- package/src/{model/ValueNodeDefinition.ts → parse/model/LeafNodeDefinition.ts} +4 -4
- package/src/{model → parse/model}/ModelBindMap.ts +4 -0
- package/src/{model → parse/model}/NodeDefinition.ts +12 -12
- package/src/parse/model/NoteNodeDefinition.ts +70 -0
- package/src/{model → parse/model}/RepeatInstanceDefinition.ts +2 -2
- package/src/parse/model/RepeatRangeDefinition.ts +94 -0
- package/src/{model → parse/model}/RootDefinition.ts +8 -4
- package/src/parse/text/HintDefinition.ts +25 -0
- package/src/parse/text/ItemLabelDefinition.ts +25 -0
- package/src/parse/text/ItemsetLabelDefinition.ts +44 -0
- package/src/parse/text/LabelDefinition.ts +61 -0
- package/src/parse/text/MessageDefinition.ts +49 -0
- package/src/parse/text/abstract/TextElementDefinition.ts +71 -0
- package/src/parse/text/abstract/TextRangeDefinition.ts +70 -0
- package/src/parse/xpath/dependency-analysis.ts +105 -0
- package/src/parse/xpath/path-resolution.ts +475 -0
- package/src/parse/xpath/predicate-analysis.ts +61 -0
- package/src/parse/xpath/reference-parsing.ts +90 -0
- package/src/parse/xpath/semantic-analysis.ts +466 -0
- package/src/parse/xpath/syntax-traversal.ts +129 -0
- package/dist/body/text/HintDefinition.d.ts +0 -11
- package/dist/body/text/LabelDefinition.d.ts +0 -22
- package/dist/body/text/TextElementDefinition.d.ts +0 -33
- package/dist/body/text/TextElementOutputPart.d.ts +0 -13
- package/dist/body/text/TextElementPart.d.ts +0 -13
- package/dist/body/text/TextElementReferencePart.d.ts +0 -7
- package/dist/body/text/TextElementStaticPart.d.ts +0 -7
- package/dist/lib/xpath/analysis.d.ts +0 -23
- package/dist/model/BindDefinition.d.ts +0 -32
- package/src/body/control/select/ItemsetDefinition.ts +0 -36
- package/src/body/control/select/ItemsetNodesetExpression.ts +0 -8
- package/src/body/text/HintDefinition.ts +0 -26
- package/src/body/text/LabelDefinition.ts +0 -68
- package/src/body/text/TextElementDefinition.ts +0 -97
- package/src/body/text/TextElementOutputPart.ts +0 -27
- package/src/body/text/TextElementPart.ts +0 -31
- package/src/body/text/TextElementReferencePart.ts +0 -21
- package/src/body/text/TextElementStaticPart.ts +0 -26
- package/src/lib/xpath/analysis.ts +0 -241
- package/src/model/RepeatRangeDefinition.ts +0 -53
- package/src/{XFormDOM.ts → parse/XFormDOM.ts} +0 -0
- package/src/{body → parse/body}/UnsupportedBodyElementDefinition.ts +0 -0
- package/src/{body → parse/body}/control/InputDefinition.ts +1 -1
- /package/src/{body → parse/body}/group/LogicalGroupDefinition.ts +0 -0
- /package/src/{body → parse/body}/group/StructuralGroupDefinition.ts +0 -0
- /package/src/{expression → parse/expression/abstract}/DependencyContext.ts +0 -0
- /package/src/{model → parse/model}/DescendentNodeDefinition.ts +0 -0
- /package/src/{model → parse/model}/ModelDefinition.ts +0 -0
- /package/src/{model → parse/model}/RepeatTemplateDefinition.ts +0 -0
- /package/src/{model → parse/model}/SubtreeDefinition.ts +0 -0
|
@@ -11,16 +11,20 @@ type TokenListIterator<CanonicalToken extends string> = IterableIterator<
|
|
|
11
11
|
PartiallyKnownString<CanonicalToken>
|
|
12
12
|
>;
|
|
13
13
|
|
|
14
|
+
type PassthroughTokenList = Readonly<Record<string, boolean>>;
|
|
15
|
+
|
|
14
16
|
/**
|
|
15
17
|
* @see {@link TokenListParser}
|
|
16
18
|
*/
|
|
17
19
|
// prettier-ignore
|
|
18
|
-
export type TokenList<CanonicalToken extends string = string> =
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
export type TokenList<CanonicalToken extends string = string> =
|
|
21
|
+
& PassthroughTokenList
|
|
22
|
+
& {
|
|
23
|
+
readonly [Key in TokenListKey<CanonicalToken>]:
|
|
24
|
+
Key extends SymbolIterator
|
|
25
|
+
? () => TokenListIterator<CanonicalToken>
|
|
26
|
+
: boolean;
|
|
27
|
+
};
|
|
24
28
|
|
|
25
29
|
interface TokenListAlias<CanonicalToken extends string> {
|
|
26
30
|
readonly fromAlias: string;
|
|
@@ -101,7 +105,7 @@ export class TokenListParser<
|
|
|
101
105
|
private readonly aliases: ReadonlyMap<string, CanonicalToken>;
|
|
102
106
|
|
|
103
107
|
constructor(
|
|
104
|
-
readonly canonicalTokens: readonly CanonicalToken[],
|
|
108
|
+
readonly canonicalTokens: readonly CanonicalToken[] = [],
|
|
105
109
|
options?: TokenListParserOptions<TokenAlias>
|
|
106
110
|
) {
|
|
107
111
|
this.aliases = new Map(
|
package/src/lib/dom/query.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type {
|
|
|
3
3
|
KnownAttributeLocalNamedElement,
|
|
4
4
|
LocalNamedElement,
|
|
5
5
|
} from '@getodk/common/types/dom.ts';
|
|
6
|
-
import type { SelectElement } from '../../body/control/select/SelectDefinition';
|
|
6
|
+
import type { SelectElement } from '../../parse/body/control/select/SelectDefinition';
|
|
7
7
|
|
|
8
8
|
const hintLookup = new ScopedElementLookup(':scope > hint', 'hint');
|
|
9
9
|
const itemLookup = new ScopedElementLookup(':scope > item', 'item');
|
|
@@ -2,16 +2,18 @@ import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
|
|
|
2
2
|
import type { XFormsXPathEvaluator } from '@getodk/xpath';
|
|
3
3
|
import type { Accessor } from 'solid-js';
|
|
4
4
|
import { createMemo } from 'solid-js';
|
|
5
|
+
import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
|
|
6
|
+
import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
|
|
5
7
|
import type {
|
|
6
8
|
DependentExpression,
|
|
7
9
|
DependentExpressionResultType,
|
|
8
|
-
} from '../../expression/DependentExpression.ts';
|
|
9
|
-
import
|
|
10
|
-
import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
|
|
10
|
+
} from '../../parse/expression/abstract/DependentExpression.ts';
|
|
11
|
+
import { isConstantExpression } from '../../parse/xpath/semantic-analysis.ts';
|
|
11
12
|
|
|
12
13
|
interface ComputedExpressionResults {
|
|
13
14
|
readonly boolean: boolean;
|
|
14
15
|
readonly nodes: Node[];
|
|
16
|
+
readonly number: number;
|
|
15
17
|
readonly string: string;
|
|
16
18
|
}
|
|
17
19
|
|
|
@@ -44,6 +46,11 @@ const expressionEvaluator = <Type extends DependentExpressionResultType>(
|
|
|
44
46
|
return evaluator.evaluateNodes(expression, options);
|
|
45
47
|
}) as ExpressionEvaluator<Type>;
|
|
46
48
|
|
|
49
|
+
case 'number':
|
|
50
|
+
return (() => {
|
|
51
|
+
return evaluator.evaluateNumber(expression, options);
|
|
52
|
+
}) as ExpressionEvaluator<Type>;
|
|
53
|
+
|
|
47
54
|
case 'string':
|
|
48
55
|
return (() => {
|
|
49
56
|
return evaluator.evaluateString(expression, options);
|
|
@@ -54,26 +61,19 @@ const expressionEvaluator = <Type extends DependentExpressionResultType>(
|
|
|
54
61
|
}
|
|
55
62
|
};
|
|
56
63
|
|
|
57
|
-
/**
|
|
58
|
-
* Determines if an XPath expression will always produce the same value.
|
|
59
|
-
*
|
|
60
|
-
* @todo There are quite a few more cases than this, and it also likely belongs
|
|
61
|
-
* in another `lib` module.
|
|
62
|
-
*/
|
|
63
|
-
const isConstantExpression = (expression: string): boolean => {
|
|
64
|
-
const normalized = expression.replaceAll(/\s/g, '');
|
|
65
|
-
|
|
66
|
-
return normalized === 'true()' || normalized === 'false()';
|
|
67
|
-
};
|
|
68
|
-
|
|
69
64
|
// prettier-ignore
|
|
70
65
|
type ComputedExpression<Type extends DependentExpressionResultType> = Accessor<
|
|
71
66
|
EvaluatedExpression<Type>
|
|
72
67
|
>;
|
|
73
68
|
|
|
69
|
+
interface CreateComputedExpressionOptions {
|
|
70
|
+
readonly arbitraryDependencies?: readonly SubscribableDependency[];
|
|
71
|
+
}
|
|
72
|
+
|
|
74
73
|
export const createComputedExpression = <Type extends DependentExpressionResultType>(
|
|
75
74
|
context: EvaluationContext,
|
|
76
|
-
dependentExpression: DependentExpression<Type
|
|
75
|
+
dependentExpression: DependentExpression<Type>,
|
|
76
|
+
options: CreateComputedExpressionOptions = {}
|
|
77
77
|
): ComputedExpression<Type> => {
|
|
78
78
|
const { contextNode, evaluator, root, scope } = context;
|
|
79
79
|
const { expression, isTranslated, resultType } = dependentExpression;
|
|
@@ -85,26 +85,24 @@ export const createComputedExpression = <Type extends DependentExpressionResultT
|
|
|
85
85
|
return createMemo(evaluateExpression);
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
const { arbitraryDependencies = [] } = options;
|
|
89
|
+
|
|
88
90
|
const getReferencedDependencies = createMemo(() => {
|
|
89
91
|
return dependencyReferences.flatMap((reference) => {
|
|
90
92
|
return context.getSubscribableDependenciesByReference(reference) ?? [];
|
|
91
93
|
});
|
|
92
94
|
});
|
|
93
95
|
|
|
94
|
-
|
|
96
|
+
return createMemo(() => {
|
|
97
|
+
if (isTranslated) {
|
|
98
|
+
root.subscribe();
|
|
99
|
+
}
|
|
95
100
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
return [root, ...getReferencedDependencies()];
|
|
101
|
+
arbitraryDependencies.forEach((dependency) => {
|
|
102
|
+
dependency.subscribe();
|
|
99
103
|
});
|
|
100
|
-
} else {
|
|
101
|
-
getDependencies = getReferencedDependencies;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
return createMemo(() => {
|
|
105
|
-
const dependencies = getDependencies();
|
|
106
104
|
|
|
107
|
-
|
|
105
|
+
getReferencedDependencies().forEach((dependency) => {
|
|
108
106
|
dependency.subscribe();
|
|
109
107
|
});
|
|
110
108
|
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import type { EvaluationContext } from '../../instance/internal-api/EvaluationContext.ts';
|
|
3
|
+
import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
|
|
4
|
+
import { createComputedExpression } from './createComputedExpression.ts';
|
|
5
|
+
|
|
6
|
+
export const createNoteReadonlyThunk = (
|
|
7
|
+
context: EvaluationContext,
|
|
8
|
+
readonlyDefinition: BindComputationExpression<'readonly'>
|
|
9
|
+
): Accessor<true> => {
|
|
10
|
+
if (!readonlyDefinition.isConstantTruthyExpression()) {
|
|
11
|
+
throw new Error('Expected a static readonly expression');
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
let result = true;
|
|
15
|
+
|
|
16
|
+
if (import.meta.env.DEV) {
|
|
17
|
+
const { expression } = readonlyDefinition;
|
|
18
|
+
|
|
19
|
+
if (readonlyDefinition.dependencyReferences.size > 0) {
|
|
20
|
+
throw new Error(`Expected expression ${expression} to have no dependencies`);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
const computedExpression = createComputedExpression(context, readonlyDefinition);
|
|
24
|
+
|
|
25
|
+
result = computedExpression();
|
|
26
|
+
|
|
27
|
+
if (result !== true) {
|
|
28
|
+
throw new Error(`Expected expression ${readonlyDefinition.expression} to return true`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return () => result;
|
|
33
|
+
};
|
|
@@ -2,8 +2,7 @@ import { UpsertableMap } from '@getodk/common/lib/collections/UpsertableMap.ts';
|
|
|
2
2
|
import type { XFormsXPathEvaluator } from '@getodk/xpath';
|
|
3
3
|
import type { Accessor } from 'solid-js';
|
|
4
4
|
import { createMemo } from 'solid-js';
|
|
5
|
-
import type {
|
|
6
|
-
import type { ItemsetDefinition } from '../../body/control/select/ItemsetDefinition.ts';
|
|
5
|
+
import type { TextRange as ClientTextRange } from '../../client/TextRange.ts';
|
|
7
6
|
import type { SelectItem } from '../../index.ts';
|
|
8
7
|
import type { SelectField } from '../../instance/SelectField.ts';
|
|
9
8
|
import type {
|
|
@@ -11,20 +10,33 @@ import type {
|
|
|
11
10
|
EvaluationContextRoot,
|
|
12
11
|
} from '../../instance/internal-api/EvaluationContext.ts';
|
|
13
12
|
import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
|
|
14
|
-
import
|
|
13
|
+
import { TextChunk } from '../../instance/text/TextChunk.ts';
|
|
14
|
+
import { TextRange } from '../../instance/text/TextRange.ts';
|
|
15
|
+
import type { ItemDefinition } from '../../parse/body/control/select/ItemDefinition.ts';
|
|
16
|
+
import type { ItemsetDefinition } from '../../parse/body/control/select/ItemsetDefinition.ts';
|
|
15
17
|
import { createComputedExpression } from './createComputedExpression.ts';
|
|
16
18
|
import type { ReactiveScope } from './scope.ts';
|
|
17
19
|
import { createTextRange } from './text/createTextRange.ts';
|
|
18
20
|
|
|
21
|
+
type DerivedItemLabel = ClientTextRange<'item-label', 'form-derived'>;
|
|
22
|
+
|
|
23
|
+
const derivedItemLabel = (context: EvaluationContext, value: string): DerivedItemLabel => {
|
|
24
|
+
const chunk = new TextChunk(context.root, 'literal', value);
|
|
25
|
+
|
|
26
|
+
return new TextRange('form-derived', 'item-label', [chunk]);
|
|
27
|
+
};
|
|
28
|
+
|
|
19
29
|
const createSelectItemLabel = (
|
|
20
30
|
context: EvaluationContext,
|
|
21
31
|
definition: ItemDefinition
|
|
22
|
-
): Accessor<
|
|
32
|
+
): Accessor<ClientTextRange<'item-label'>> => {
|
|
23
33
|
const { label, value } = definition;
|
|
24
34
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
35
|
+
if (label == null) {
|
|
36
|
+
return () => derivedItemLabel(context, value);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return createTextRange(context, 'item-label', label);
|
|
28
40
|
};
|
|
29
41
|
|
|
30
42
|
const createTranslatedStaticSelectItems = (
|
|
@@ -73,25 +85,20 @@ const createSelectItemsetItemLabel = (
|
|
|
73
85
|
context: EvaluationContext,
|
|
74
86
|
definition: ItemsetDefinition,
|
|
75
87
|
itemValue: Accessor<string>
|
|
76
|
-
): Accessor<
|
|
88
|
+
): Accessor<ClientTextRange<'item-label'>> => {
|
|
77
89
|
const { label } = definition;
|
|
78
90
|
|
|
79
91
|
if (label == null) {
|
|
80
92
|
return createMemo(() => {
|
|
81
|
-
|
|
82
|
-
const staticValueLabel = createTextRange(context, 'label', label, {
|
|
83
|
-
fallbackValue: value,
|
|
84
|
-
});
|
|
85
|
-
|
|
86
|
-
return staticValueLabel();
|
|
93
|
+
return derivedItemLabel(context, itemValue());
|
|
87
94
|
});
|
|
88
95
|
}
|
|
89
96
|
|
|
90
|
-
return createTextRange(context, 'label', label);
|
|
97
|
+
return createTextRange(context, 'item-label', label);
|
|
91
98
|
};
|
|
92
99
|
|
|
93
100
|
interface ItemsetItem {
|
|
94
|
-
label():
|
|
101
|
+
label(): ClientTextRange<'item-label'>;
|
|
95
102
|
value(): string;
|
|
96
103
|
}
|
|
97
104
|
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { createComputed, createMemo, createSignal, untrack } from 'solid-js';
|
|
2
|
-
import type { DependentExpression } from '../../expression/DependentExpression.ts';
|
|
3
2
|
import type { SubscribableDependency } from '../../instance/internal-api/SubscribableDependency.ts';
|
|
4
3
|
import type { ValueContext } from '../../instance/internal-api/ValueContext.ts';
|
|
5
|
-
import type {
|
|
4
|
+
import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
|
|
5
|
+
import type { DependentExpression } from '../../parse/expression/abstract/DependentExpression.ts';
|
|
6
6
|
import { createComputedExpression } from './createComputedExpression.ts';
|
|
7
7
|
import type { SimpleAtomicState, SimpleAtomicStateSetter } from './types.ts';
|
|
8
8
|
|
|
@@ -209,7 +209,7 @@ const guardDownstreamReadonlyWrites = <RuntimeValue>(
|
|
|
209
209
|
const createCalculation = <RuntimeValue>(
|
|
210
210
|
context: ValueContext<RuntimeValue>,
|
|
211
211
|
setValue: SimpleAtomicStateSetter<RuntimeValue>,
|
|
212
|
-
calculateDefinition:
|
|
212
|
+
calculateDefinition: BindComputationExpression<'calculate'>
|
|
213
213
|
): void => {
|
|
214
214
|
context.scope.runTask(() => {
|
|
215
215
|
const calculate = createComputedExpression(context, calculateDefinition);
|
|
@@ -31,7 +31,7 @@ export interface SharedNodeState<Spec extends StateSpec> {
|
|
|
31
31
|
readonly setProperty: SetEnginePropertyState<Spec>;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
-
interface SharedNodeStateOptions<
|
|
34
|
+
export interface SharedNodeStateOptions<
|
|
35
35
|
Factory extends OpaqueReactiveObjectFactory,
|
|
36
36
|
Spec extends StateSpec,
|
|
37
37
|
> {
|
|
@@ -80,7 +80,7 @@ export type ComputedPropertySpec<T> = Accessor<T>;
|
|
|
80
80
|
/**
|
|
81
81
|
* @see {@link StaticPropertySpec}
|
|
82
82
|
*/
|
|
83
|
-
// eslint-disable-next-line @typescript-eslint/
|
|
83
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-function-type, @typescript-eslint/no-explicit-any
|
|
84
84
|
type NonStaticValue = Function | Signal<any> | SimpleAtomicState<any>;
|
|
85
85
|
|
|
86
86
|
/**
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { type Accessor } from 'solid-js';
|
|
2
|
+
import type { TextRange } from '../../../client/TextRange.ts';
|
|
2
3
|
import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
|
|
3
|
-
import {
|
|
4
|
-
import type { ValueNodeDefinition } from '../../../model/ValueNodeDefinition.ts';
|
|
4
|
+
import type { LeafNodeDefinition } from '../../../parse/model/LeafNodeDefinition.ts';
|
|
5
5
|
import { createTextRange } from './createTextRange.ts';
|
|
6
6
|
|
|
7
7
|
export const createFieldHint = (
|
|
8
8
|
context: EvaluationContext,
|
|
9
|
-
definition:
|
|
10
|
-
): Accessor<TextRange<'hint'> | null> => {
|
|
9
|
+
definition: LeafNodeDefinition
|
|
10
|
+
): Accessor<TextRange<'hint', 'form'> | null> => {
|
|
11
11
|
const hintDefinition = definition.bodyElement?.hint ?? null;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
if (hintDefinition == null) {
|
|
14
|
+
return () => null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return createTextRange(context, 'hint', hintDefinition);
|
|
16
18
|
};
|
|
@@ -1,16 +1,18 @@
|
|
|
1
1
|
import { type Accessor } from 'solid-js';
|
|
2
|
+
import type { TextRange } from '../../../client/TextRange.ts';
|
|
2
3
|
import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
|
|
3
|
-
import {
|
|
4
|
-
import type { AnyNodeDefinition } from '../../../model/NodeDefinition.ts';
|
|
4
|
+
import type { AnyNodeDefinition } from '../../../parse/model/NodeDefinition.ts';
|
|
5
5
|
import { createTextRange } from './createTextRange.ts';
|
|
6
6
|
|
|
7
7
|
export const createNodeLabel = (
|
|
8
8
|
context: EvaluationContext,
|
|
9
9
|
definition: AnyNodeDefinition
|
|
10
|
-
): Accessor<TextRange<'label'> | null> => {
|
|
10
|
+
): Accessor<TextRange<'label', 'form'> | null> => {
|
|
11
11
|
const labelDefinition = definition.bodyElement?.label ?? null;
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
13
|
+
if (labelDefinition == null) {
|
|
14
|
+
return () => null;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
return createTextRange(context, 'label', labelDefinition);
|
|
16
18
|
};
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
import type { TextRange } from '../../../client/TextRange.ts';
|
|
4
|
+
import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
|
|
5
|
+
import type { NoteTextDefinition } from '../../../parse/model/NoteNodeDefinition.ts';
|
|
6
|
+
import { createTextRange } from './createTextRange.ts';
|
|
7
|
+
|
|
8
|
+
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
|
|
9
|
+
export type NoteTextRole = 'label' | 'hint';
|
|
10
|
+
|
|
11
|
+
export type ComputedNoteText<Role extends NoteTextRole = NoteTextRole> = Accessor<
|
|
12
|
+
TextRange<Role, 'form'>
|
|
13
|
+
>;
|
|
14
|
+
|
|
15
|
+
interface BaseNoteText {
|
|
16
|
+
readonly role: NoteTextRole;
|
|
17
|
+
readonly label: ComputedNoteText<'label'> | null;
|
|
18
|
+
readonly hint: ComputedNoteText<'hint'> | null;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
interface LabelNoteText extends BaseNoteText {
|
|
22
|
+
readonly role: 'label';
|
|
23
|
+
readonly label: ComputedNoteText<'label'>;
|
|
24
|
+
readonly hint: null;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
interface HintNoteText extends BaseNoteText {
|
|
28
|
+
readonly role: 'hint';
|
|
29
|
+
readonly label: null;
|
|
30
|
+
readonly hint: ComputedNoteText<'hint'>;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// prettier-ignore
|
|
34
|
+
export type NoteTextComputation =
|
|
35
|
+
// eslint-disable-next-line @typescript-eslint/sort-type-constituents
|
|
36
|
+
| LabelNoteText
|
|
37
|
+
| HintNoteText;
|
|
38
|
+
|
|
39
|
+
export const createNoteText = (
|
|
40
|
+
context: EvaluationContext,
|
|
41
|
+
noteTextDefinition: NoteTextDefinition
|
|
42
|
+
): NoteTextComputation => {
|
|
43
|
+
const { scope } = context;
|
|
44
|
+
const { role } = noteTextDefinition;
|
|
45
|
+
|
|
46
|
+
return scope.runTask(() => {
|
|
47
|
+
switch (role) {
|
|
48
|
+
case 'label': {
|
|
49
|
+
const label = createTextRange(context, role, noteTextDefinition);
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
role,
|
|
53
|
+
label,
|
|
54
|
+
hint: null,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
case 'hint': {
|
|
59
|
+
const hint = createTextRange(context, role, noteTextDefinition);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
role,
|
|
63
|
+
label: null,
|
|
64
|
+
hint,
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
default:
|
|
69
|
+
throw new UnreachableError(noteTextDefinition);
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
};
|
|
@@ -1,23 +1,13 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import { createMemo
|
|
3
|
-
import type {
|
|
4
|
-
TextElementChild,
|
|
5
|
-
TextElementDefinition,
|
|
6
|
-
} from '../../../body/text/TextElementDefinition.ts';
|
|
7
|
-
import type { TextElementReferencePart } from '../../../body/text/TextElementReferencePart.ts';
|
|
8
|
-
import type { TextChunkSource } from '../../../client/TextRange.ts';
|
|
1
|
+
import type { Accessor } from 'solid-js';
|
|
2
|
+
import { createMemo } from 'solid-js';
|
|
3
|
+
import type { TextChunkSource, TextRole } from '../../../client/TextRange.ts';
|
|
9
4
|
import type { EvaluationContext } from '../../../instance/internal-api/EvaluationContext.ts';
|
|
10
5
|
import { TextChunk } from '../../../instance/text/TextChunk.ts';
|
|
11
|
-
import { TextRange
|
|
6
|
+
import { TextRange } from '../../../instance/text/TextRange.ts';
|
|
7
|
+
import type { AnyTextChunkExpression } from '../../../parse/expression/abstract/TextChunkExpression.ts';
|
|
8
|
+
import type { TextRangeDefinition } from '../../../parse/text/abstract/TextRangeDefinition.ts';
|
|
12
9
|
import { createComputedExpression } from '../createComputedExpression.ts';
|
|
13
10
|
|
|
14
|
-
// prettier-ignore
|
|
15
|
-
type TextSources =
|
|
16
|
-
| readonly [TextElementReferencePart]
|
|
17
|
-
| readonly TextElementChild[];
|
|
18
|
-
|
|
19
|
-
type TextSource = CollectionValues<TextSources>;
|
|
20
|
-
|
|
21
11
|
interface TextChunkComputation {
|
|
22
12
|
readonly source: TextChunkSource;
|
|
23
13
|
readonly getText: Accessor<string>;
|
|
@@ -25,21 +15,20 @@ interface TextChunkComputation {
|
|
|
25
15
|
|
|
26
16
|
const createComputedTextChunk = (
|
|
27
17
|
context: EvaluationContext,
|
|
28
|
-
textSource:
|
|
18
|
+
textSource: AnyTextChunkExpression
|
|
29
19
|
): TextChunkComputation => {
|
|
30
|
-
const {
|
|
20
|
+
const { source } = textSource;
|
|
31
21
|
|
|
32
|
-
if (
|
|
22
|
+
if (source === 'literal') {
|
|
33
23
|
const { stringValue } = textSource;
|
|
34
24
|
|
|
35
25
|
return {
|
|
36
|
-
source
|
|
26
|
+
source,
|
|
37
27
|
getText: () => stringValue,
|
|
38
28
|
};
|
|
39
29
|
}
|
|
40
30
|
|
|
41
31
|
return context.scope.runTask(() => {
|
|
42
|
-
const source: TextChunkSource = type === 'reference' ? 'itext' : type;
|
|
43
32
|
const getText = createComputedExpression(context, textSource);
|
|
44
33
|
|
|
45
34
|
return {
|
|
@@ -51,7 +40,7 @@ const createComputedTextChunk = (
|
|
|
51
40
|
|
|
52
41
|
const createTextChunks = (
|
|
53
42
|
context: EvaluationContext,
|
|
54
|
-
textSources:
|
|
43
|
+
textSources: readonly AnyTextChunkExpression[]
|
|
55
44
|
): Accessor<readonly TextChunk[]> => {
|
|
56
45
|
return context.scope.runTask(() => {
|
|
57
46
|
const { root } = context;
|
|
@@ -67,45 +56,7 @@ const createTextChunks = (
|
|
|
67
56
|
});
|
|
68
57
|
};
|
|
69
58
|
|
|
70
|
-
|
|
71
|
-
readonly fallbackValue?: FallbackValue;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// prettier-ignore
|
|
75
|
-
type ComputedTextRange<
|
|
76
|
-
Role extends TextRole,
|
|
77
|
-
Definition extends TextElementDefinition<Role> | null,
|
|
78
|
-
FallbackValue extends string | null
|
|
79
|
-
> = Accessor<
|
|
80
|
-
Definition extends null
|
|
81
|
-
? FallbackValue extends null
|
|
82
|
-
? TextRange<Role> | null
|
|
83
|
-
: TextRange<Role>
|
|
84
|
-
: TextRange<Role>
|
|
85
|
-
>;
|
|
86
|
-
|
|
87
|
-
// prettier-ignore
|
|
88
|
-
type FallbackTextRange<
|
|
89
|
-
Role extends TextRole,
|
|
90
|
-
FallbackValue extends string | null
|
|
91
|
-
> =
|
|
92
|
-
FallbackValue extends null
|
|
93
|
-
? TextRange<Role> | null
|
|
94
|
-
: TextRange<Role>;
|
|
95
|
-
|
|
96
|
-
const createFallbackTextRange = <Role extends TextRole, FallbackValue extends string | null>(
|
|
97
|
-
context: EvaluationContext,
|
|
98
|
-
role: Role,
|
|
99
|
-
fallbackValue: FallbackValue
|
|
100
|
-
): FallbackTextRange<Role, FallbackValue> => {
|
|
101
|
-
if (fallbackValue == null) {
|
|
102
|
-
return null as FallbackTextRange<Role, FallbackValue>;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
const staticChunk = new TextChunk(context.root, 'static', fallbackValue);
|
|
106
|
-
|
|
107
|
-
return new TextRange(role, [staticChunk]);
|
|
108
|
-
};
|
|
59
|
+
type ComputedFormTextRange<Role extends TextRole> = Accessor<TextRange<Role, 'form'>>;
|
|
109
60
|
|
|
110
61
|
/**
|
|
111
62
|
* Creates a text range (e.g. label or hint) from the provided definition,
|
|
@@ -116,40 +67,16 @@ const createFallbackTextRange = <Role extends TextRole, FallbackValue extends st
|
|
|
116
67
|
*
|
|
117
68
|
* @todo This does not yet handle itext translations **with** outputs!
|
|
118
69
|
*/
|
|
119
|
-
export const createTextRange = <
|
|
120
|
-
Role extends TextRole,
|
|
121
|
-
Definition extends TextElementDefinition<Role> | null,
|
|
122
|
-
FallbackValue extends string | null = null,
|
|
123
|
-
>(
|
|
70
|
+
export const createTextRange = <Role extends TextRole>(
|
|
124
71
|
context: EvaluationContext,
|
|
125
72
|
role: Role,
|
|
126
|
-
definition:
|
|
127
|
-
|
|
128
|
-
): ComputedTextRange<Role, Definition, FallbackValue> => {
|
|
73
|
+
definition: TextRangeDefinition<Role>
|
|
74
|
+
): ComputedFormTextRange<Role> => {
|
|
129
75
|
return context.scope.runTask(() => {
|
|
130
|
-
|
|
131
|
-
const textRange = createFallbackTextRange(
|
|
132
|
-
context,
|
|
133
|
-
role,
|
|
134
|
-
options?.fallbackValue ?? (null as FallbackValue)
|
|
135
|
-
);
|
|
136
|
-
const getTextRange = () => textRange;
|
|
137
|
-
|
|
138
|
-
return getTextRange as ComputedTextRange<Role, Definition, FallbackValue>;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
const { children, referenceExpression } = definition;
|
|
142
|
-
|
|
143
|
-
let getTextChunks: Accessor<readonly TextChunk[]>;
|
|
144
|
-
|
|
145
|
-
if (referenceExpression == null) {
|
|
146
|
-
getTextChunks = createTextChunks(context, children);
|
|
147
|
-
} else {
|
|
148
|
-
getTextChunks = createTextChunks(context, [referenceExpression]);
|
|
149
|
-
}
|
|
76
|
+
const getTextChunks = createTextChunks(context, definition.chunks);
|
|
150
77
|
|
|
151
78
|
return createMemo(() => {
|
|
152
|
-
return new TextRange(role, getTextChunks());
|
|
79
|
+
return new TextRange('form', role, getTextChunks());
|
|
153
80
|
});
|
|
154
81
|
});
|
|
155
82
|
};
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import { createMemo } from 'solid-js';
|
|
2
|
+
import type { OpaqueReactiveObjectFactory } from '../../../client/OpaqueReactiveObjectFactory.ts';
|
|
3
|
+
import type {
|
|
4
|
+
AncestorNodeValidationState,
|
|
5
|
+
DescendantNodeViolationReference,
|
|
6
|
+
} from '../../../client/validation.ts';
|
|
7
|
+
import type { AnyParentNode } from '../../../instance/hierarchy.ts';
|
|
8
|
+
import type { ValidationContext } from '../../../instance/internal-api/ValidationContext.ts';
|
|
9
|
+
import { createSharedNodeState } from '../node-state/createSharedNodeState.ts';
|
|
10
|
+
|
|
11
|
+
const violationReference = (node: ValidationContext): DescendantNodeViolationReference | null => {
|
|
12
|
+
const violation = node.getViolation();
|
|
13
|
+
|
|
14
|
+
if (violation == null) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
const { nodeId } = node;
|
|
19
|
+
|
|
20
|
+
return {
|
|
21
|
+
nodeId,
|
|
22
|
+
get reference() {
|
|
23
|
+
return node.currentState.reference;
|
|
24
|
+
},
|
|
25
|
+
violation,
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const collectViolationReferences = (
|
|
30
|
+
context: AnyParentNode
|
|
31
|
+
): readonly DescendantNodeViolationReference[] => {
|
|
32
|
+
return context.getChildren().flatMap((child) => {
|
|
33
|
+
switch (child.nodeType) {
|
|
34
|
+
case 'model-value':
|
|
35
|
+
case 'note':
|
|
36
|
+
case 'string':
|
|
37
|
+
case 'select':
|
|
38
|
+
case 'range':
|
|
39
|
+
case 'rank':
|
|
40
|
+
case 'trigger':
|
|
41
|
+
case 'upload': {
|
|
42
|
+
const reference = violationReference(child);
|
|
43
|
+
|
|
44
|
+
if (reference == null) {
|
|
45
|
+
return [];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return [reference];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
default:
|
|
52
|
+
return collectViolationReferences(child);
|
|
53
|
+
}
|
|
54
|
+
});
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
interface AggregatedViolationsOptions {
|
|
58
|
+
readonly clientStateFactory: OpaqueReactiveObjectFactory<AncestorNodeValidationState>;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const createAggregatedViolations = (
|
|
62
|
+
context: AnyParentNode,
|
|
63
|
+
options: AggregatedViolationsOptions
|
|
64
|
+
): AncestorNodeValidationState => {
|
|
65
|
+
const { scope } = context;
|
|
66
|
+
|
|
67
|
+
return scope.runTask(() => {
|
|
68
|
+
const violations = createMemo(() => {
|
|
69
|
+
return collectViolationReferences(context);
|
|
70
|
+
});
|
|
71
|
+
const spec = { violations };
|
|
72
|
+
|
|
73
|
+
return createSharedNodeState(scope, spec, options).currentState;
|
|
74
|
+
});
|
|
75
|
+
};
|