@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
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { AnyViolation } from '../../client/validation.ts';
|
|
2
|
+
import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
|
|
3
|
+
import type { MessageDefinition } from '../../parse/text/MessageDefinition.ts';
|
|
4
|
+
import type { NodeID } from '../identity.ts';
|
|
5
|
+
import type { EvaluationContext } from './EvaluationContext.ts';
|
|
6
|
+
import type { SubscribableDependency } from './SubscribableDependency.ts';
|
|
7
|
+
|
|
8
|
+
interface ValidationContextCurrentState {
|
|
9
|
+
get reference(): string;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface ValidationContextDefinitionBind {
|
|
13
|
+
readonly constraint: BindComputationExpression<'constraint'>;
|
|
14
|
+
readonly constraintMsg: MessageDefinition<'constraintMsg'> | null;
|
|
15
|
+
readonly required: BindComputationExpression<'required'>;
|
|
16
|
+
readonly requiredMsg: MessageDefinition<'requiredMsg'> | null;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface ValidationContextDefinition {
|
|
20
|
+
readonly bind: ValidationContextDefinitionBind;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export interface ValidationContext extends EvaluationContext, SubscribableDependency {
|
|
24
|
+
readonly nodeId: NodeID;
|
|
25
|
+
readonly definition: ValidationContextDefinition;
|
|
26
|
+
readonly currentState: ValidationContextCurrentState;
|
|
27
|
+
|
|
28
|
+
getViolation(): AnyViolation | null;
|
|
29
|
+
isRelevant(): boolean;
|
|
30
|
+
isRequired(): boolean;
|
|
31
|
+
isBlank(): boolean;
|
|
32
|
+
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import type { ReactiveScope } from '../../lib/reactivity/scope.ts';
|
|
2
|
-
import type {
|
|
2
|
+
import type { BindComputationExpression } from '../../parse/expression/BindComputationExpression.ts';
|
|
3
3
|
import type { EvaluationContext } from './EvaluationContext.ts';
|
|
4
4
|
|
|
5
5
|
export type InstanceValue = string;
|
|
6
6
|
|
|
7
7
|
interface ValueContextDefinitionBind {
|
|
8
|
-
readonly calculate:
|
|
9
|
-
readonly readonly:
|
|
8
|
+
readonly calculate: BindComputationExpression<'calculate'> | null;
|
|
9
|
+
readonly readonly: BindComputationExpression<'readonly'>;
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
export interface ValueContextDefinition {
|
|
@@ -1,27 +1,34 @@
|
|
|
1
1
|
import { insertAtIndex } from '@getodk/common/lib/array/insert.ts';
|
|
2
|
-
import type
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import type {
|
|
8
|
-
import {
|
|
9
|
-
import
|
|
10
|
-
import type {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import type {
|
|
15
|
-
import
|
|
16
|
-
import {
|
|
17
|
-
import type {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
import type {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
import { untrack, type Accessor } from 'solid-js';
|
|
3
|
+
import type { NodeAppearances } from '../../client/NodeAppearances.ts';
|
|
4
|
+
import type { BaseRepeatRangeNode } from '../../client/repeat/BaseRepeatRangeNode.ts';
|
|
5
|
+
import type { TextRange } from '../../client/TextRange.ts';
|
|
6
|
+
import type { AncestorNodeValidationState } from '../../client/validation.ts';
|
|
7
|
+
import type { ChildrenState } from '../../lib/reactivity/createChildrenState.ts';
|
|
8
|
+
import { createChildrenState } from '../../lib/reactivity/createChildrenState.ts';
|
|
9
|
+
import { createComputedExpression } from '../../lib/reactivity/createComputedExpression.ts';
|
|
10
|
+
import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
11
|
+
import { materializeCurrentStateChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
12
|
+
import type { CurrentState } from '../../lib/reactivity/node-state/createCurrentState.ts';
|
|
13
|
+
import type { EngineState } from '../../lib/reactivity/node-state/createEngineState.ts';
|
|
14
|
+
import type { SharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
15
|
+
import { createSharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
16
|
+
import { createNodeLabel } from '../../lib/reactivity/text/createNodeLabel.ts';
|
|
17
|
+
import type {
|
|
18
|
+
AnyRepeatRangeDefinition,
|
|
19
|
+
ControlledRepeatRangeDefinition,
|
|
20
|
+
} from '../../parse/model/RepeatRangeDefinition.ts';
|
|
21
|
+
import type {
|
|
22
|
+
AnyDescendantNode,
|
|
23
|
+
DescendantNodeParent,
|
|
24
|
+
DescendantNodeSharedStateSpec,
|
|
25
|
+
} from '../abstract/DescendantNode.ts';
|
|
26
|
+
import { DescendantNode } from '../abstract/DescendantNode.ts';
|
|
27
|
+
import type { RepeatRange } from '../hierarchy.ts';
|
|
28
|
+
import type { NodeID } from '../identity.ts';
|
|
29
|
+
import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
|
|
30
|
+
import type { SubscribableDependency } from '../internal-api/SubscribableDependency.ts';
|
|
31
|
+
import { RepeatInstance, type RepeatDefinition } from './RepeatInstance.ts';
|
|
25
32
|
|
|
26
33
|
interface RepeatRangeStateSpec extends DescendantNodeSharedStateSpec {
|
|
27
34
|
readonly hint: null;
|
|
@@ -31,9 +38,15 @@ interface RepeatRangeStateSpec extends DescendantNodeSharedStateSpec {
|
|
|
31
38
|
readonly value: null;
|
|
32
39
|
}
|
|
33
40
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
41
|
+
// prettier-ignore
|
|
42
|
+
type BaseRepeatRangeNodeType<Definition extends AnyRepeatRangeDefinition> =
|
|
43
|
+
Definition extends ControlledRepeatRangeDefinition
|
|
44
|
+
? 'repeat-range:controlled'
|
|
45
|
+
: 'repeat-range:uncontrolled';
|
|
46
|
+
|
|
47
|
+
export abstract class BaseRepeatRange<Definition extends AnyRepeatRangeDefinition>
|
|
48
|
+
extends DescendantNode<Definition, RepeatRangeStateSpec, RepeatInstance>
|
|
49
|
+
implements BaseRepeatRangeNode, EvaluationContext, SubscribableDependency
|
|
37
50
|
{
|
|
38
51
|
/**
|
|
39
52
|
* A repeat range doesn't have a corresponding primary instance element of its
|
|
@@ -57,14 +70,36 @@ export class RepeatRange
|
|
|
57
70
|
* {@link https://developer.mozilla.org/en-US/docs/Web/API/Range | DOM Range}
|
|
58
71
|
* instead?
|
|
59
72
|
*/
|
|
60
|
-
|
|
73
|
+
protected readonly anchorNode: Comment;
|
|
74
|
+
|
|
75
|
+
protected readonly childrenState: ChildrenState<RepeatInstance>;
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* Provides an {@link EvaluationContext} from which to evaluate expressions
|
|
79
|
+
* where some LocationPath sub-expressions may be **relative to the repeat
|
|
80
|
+
* range itself**. This is useful for evaluation of expressions where:
|
|
81
|
+
*
|
|
82
|
+
* - the expression is typically contextualized to any of its
|
|
83
|
+
* {@link RepeatInstance} children, but it presently has none (i.e.
|
|
84
|
+
* `relevant`)
|
|
85
|
+
*
|
|
86
|
+
* - the expression is conceptually intended to be evaluated in the context of
|
|
87
|
+
* the repeat range itself (i.e. `jr:count`)
|
|
88
|
+
*/
|
|
89
|
+
protected readonly selfEvaluationContext: EvaluationContext & {
|
|
90
|
+
readonly contextNode: Comment;
|
|
91
|
+
};
|
|
61
92
|
|
|
62
|
-
|
|
93
|
+
/**
|
|
94
|
+
* @see {@link isSelfRelevant}
|
|
95
|
+
*/
|
|
96
|
+
protected readonly isEmptyRangeSelfRelevant: Accessor<boolean>;
|
|
63
97
|
|
|
64
98
|
// InstanceNode
|
|
65
99
|
protected readonly state: SharedNodeState<RepeatRangeStateSpec>;
|
|
66
100
|
protected override engineState: EngineState<RepeatRangeStateSpec>;
|
|
67
101
|
|
|
102
|
+
// DescendantNode
|
|
68
103
|
/**
|
|
69
104
|
* @todo Should we special case repeat `readonly` state the same way
|
|
70
105
|
* we do for `relevant`?
|
|
@@ -73,15 +108,6 @@ export class RepeatRange
|
|
|
73
108
|
*/
|
|
74
109
|
declare isSelfReadonly: Accessor<boolean>;
|
|
75
110
|
|
|
76
|
-
private readonly emptyRangeEvaluationContext: EvaluationContext & {
|
|
77
|
-
readonly contextNode: Comment;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* @see {@link isSelfRelevant}
|
|
82
|
-
*/
|
|
83
|
-
private readonly isEmptyRangeSelfRelevant: Accessor<boolean>;
|
|
84
|
-
|
|
85
111
|
/**
|
|
86
112
|
* A repeat range does not exist in the primary instance tree. A `relevant`
|
|
87
113
|
* expression applies to each {@link RepeatInstance} child of the repeat
|
|
@@ -125,8 +151,8 @@ export class RepeatRange
|
|
|
125
151
|
return this.isEmptyRangeSelfRelevant();
|
|
126
152
|
};
|
|
127
153
|
|
|
128
|
-
//
|
|
129
|
-
readonly nodeType
|
|
154
|
+
// BaseRepeatRangeNode
|
|
155
|
+
abstract override readonly nodeType: BaseRepeatRangeNodeType<Definition>;
|
|
130
156
|
|
|
131
157
|
/**
|
|
132
158
|
* @todo RepeatRange*, RepeatInstance* (and RepeatTemplate*) all share the
|
|
@@ -161,16 +187,18 @@ export class RepeatRange
|
|
|
161
187
|
* All of the above creates considerable ambiguity about where "repeat
|
|
162
188
|
* appearances" should apply, under which circumstances.
|
|
163
189
|
*/
|
|
164
|
-
readonly appearances:
|
|
190
|
+
abstract override readonly appearances: NodeAppearances<Definition>;
|
|
165
191
|
|
|
166
192
|
readonly currentState: MaterializedChildren<CurrentState<RepeatRangeStateSpec>, RepeatInstance>;
|
|
167
193
|
|
|
168
|
-
|
|
194
|
+
abstract override readonly validationState: AncestorNodeValidationState;
|
|
195
|
+
|
|
196
|
+
constructor(parent: DescendantNodeParent<Definition>, definition: Definition) {
|
|
169
197
|
super(parent, definition);
|
|
170
198
|
|
|
171
|
-
|
|
199
|
+
const repeatRange = this as AnyDescendantNode as RepeatRange;
|
|
172
200
|
|
|
173
|
-
const childrenState = createChildrenState<RepeatRange, RepeatInstance>(
|
|
201
|
+
const childrenState = createChildrenState<RepeatRange, RepeatInstance>(repeatRange);
|
|
174
202
|
|
|
175
203
|
this.childrenState = childrenState;
|
|
176
204
|
|
|
@@ -179,7 +207,7 @@ export class RepeatRange
|
|
|
179
207
|
);
|
|
180
208
|
this.contextNode.append(this.anchorNode);
|
|
181
209
|
|
|
182
|
-
this.
|
|
210
|
+
this.selfEvaluationContext = {
|
|
183
211
|
scope: this.scope,
|
|
184
212
|
evaluator: this.evaluator,
|
|
185
213
|
root: this.root,
|
|
@@ -187,15 +215,19 @@ export class RepeatRange
|
|
|
187
215
|
contextNode: this.anchorNode,
|
|
188
216
|
|
|
189
217
|
getSubscribableDependenciesByReference: (reference) => {
|
|
190
|
-
return
|
|
218
|
+
return repeatRange.getSubscribableDependenciesByReference(reference);
|
|
191
219
|
},
|
|
192
220
|
};
|
|
193
221
|
|
|
194
222
|
this.isEmptyRangeSelfRelevant = createComputedExpression(
|
|
195
|
-
this.
|
|
223
|
+
this.selfEvaluationContext,
|
|
196
224
|
definition.bind.relevant
|
|
197
225
|
);
|
|
198
226
|
|
|
227
|
+
const sharedStateOptions = {
|
|
228
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
229
|
+
};
|
|
230
|
+
|
|
199
231
|
const state = createSharedNodeState(
|
|
200
232
|
this.scope,
|
|
201
233
|
{
|
|
@@ -210,9 +242,7 @@ export class RepeatRange
|
|
|
210
242
|
valueOptions: null,
|
|
211
243
|
value: null,
|
|
212
244
|
},
|
|
213
|
-
|
|
214
|
-
clientStateFactory: this.engineConfig.stateFactory,
|
|
215
|
-
}
|
|
245
|
+
sharedStateOptions
|
|
216
246
|
);
|
|
217
247
|
|
|
218
248
|
this.state = state;
|
|
@@ -222,15 +252,9 @@ export class RepeatRange
|
|
|
222
252
|
state.currentState,
|
|
223
253
|
childrenState
|
|
224
254
|
);
|
|
225
|
-
|
|
226
|
-
definition.instances.forEach((instanceDefinition, index) => {
|
|
227
|
-
const afterIndex = index - 1;
|
|
228
|
-
|
|
229
|
-
this.addInstances(afterIndex, 1, instanceDefinition);
|
|
230
|
-
});
|
|
231
255
|
}
|
|
232
256
|
|
|
233
|
-
|
|
257
|
+
protected getLastIndex(): number {
|
|
234
258
|
return this.engineState.children.length - 1;
|
|
235
259
|
}
|
|
236
260
|
|
|
@@ -242,66 +266,59 @@ export class RepeatRange
|
|
|
242
266
|
return this.engineState.children.indexOf(instance.nodeId);
|
|
243
267
|
}
|
|
244
268
|
|
|
245
|
-
|
|
246
|
-
afterIndex
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
): Root {
|
|
269
|
+
private createChildren(
|
|
270
|
+
afterIndex: number,
|
|
271
|
+
definitions: readonly RepeatDefinition[]
|
|
272
|
+
): readonly RepeatInstance[] {
|
|
250
273
|
return this.scope.runTask(() => {
|
|
251
|
-
let
|
|
274
|
+
let initialPrecedingInstance: RepeatInstance | null;
|
|
252
275
|
|
|
253
276
|
if (afterIndex === -1) {
|
|
254
|
-
|
|
277
|
+
initialPrecedingInstance = null;
|
|
255
278
|
} else {
|
|
256
|
-
const instance = this.childrenState.getChildren()[afterIndex];
|
|
279
|
+
const instance = untrack(() => this.childrenState.getChildren()[afterIndex]);
|
|
257
280
|
|
|
258
281
|
if (instance == null) {
|
|
259
282
|
throw new Error(`No repeat instance at index ${afterIndex}`);
|
|
260
283
|
}
|
|
261
284
|
|
|
262
|
-
|
|
285
|
+
initialPrecedingInstance = instance;
|
|
263
286
|
}
|
|
264
287
|
|
|
265
|
-
const
|
|
288
|
+
const repeatRange = this as AnyDescendantNode as RepeatRange;
|
|
266
289
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
precedingInstance
|
|
270
|
-
|
|
271
|
-
|
|
290
|
+
return definitions.reduce<RepeatInstance[]>((acc, definition) => {
|
|
291
|
+
const precedingInstance = acc[acc.length - 1] ?? initialPrecedingInstance;
|
|
292
|
+
const precedingPrimaryInstanceNode = precedingInstance?.contextNode ?? this.anchorNode;
|
|
293
|
+
const newInstance = new RepeatInstance(repeatRange, definition, {
|
|
294
|
+
precedingPrimaryInstanceNode,
|
|
295
|
+
precedingInstance,
|
|
296
|
+
});
|
|
272
297
|
|
|
273
|
-
|
|
274
|
-
return insertAtIndex(currentInstances, initialIndex, newInstance);
|
|
275
|
-
});
|
|
298
|
+
acc.push(newInstance);
|
|
276
299
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
300
|
+
return acc;
|
|
301
|
+
}, []);
|
|
302
|
+
});
|
|
303
|
+
}
|
|
280
304
|
|
|
281
|
-
|
|
305
|
+
protected addChildren(
|
|
306
|
+
afterIndex: number,
|
|
307
|
+
definitions: readonly RepeatDefinition[]
|
|
308
|
+
): readonly RepeatInstance[] {
|
|
309
|
+
return this.scope.runTask(() => {
|
|
310
|
+
const initialIndex = afterIndex + 1;
|
|
311
|
+
const newInstances = this.createChildren(afterIndex, definitions);
|
|
312
|
+
|
|
313
|
+
return this.childrenState.setChildren((currentInstances) => {
|
|
314
|
+
return insertAtIndex(currentInstances, initialIndex, newInstances);
|
|
315
|
+
});
|
|
282
316
|
});
|
|
283
317
|
}
|
|
284
318
|
|
|
285
|
-
|
|
286
|
-
* Removes the {@link RepeatInstance}s corresponding to the specified range of
|
|
287
|
-
* indexes, and then removes those repeat instances from the repeat range's
|
|
288
|
-
* own children state in that order:
|
|
289
|
-
*
|
|
290
|
-
* 1. Identify the set of {@link RepeatInstance}s to be removed.
|
|
291
|
-
*
|
|
292
|
-
* 2. For each {@link RepeatInstance} pending removal, perform that node's
|
|
293
|
-
* removal logic. @see {@link RepeatInstance.remove} for more detail.
|
|
294
|
-
*
|
|
295
|
-
* 3. Finalize update to the repeat range's own {@link childrenState},
|
|
296
|
-
* omitting those {@link RepeatInstance}s which were removed.
|
|
297
|
-
*
|
|
298
|
-
* This ordering ensures a consistent representation of state is established
|
|
299
|
-
* prior to any downstream reactive updates, and ensures that removed nodes'
|
|
300
|
-
* reactivity is cleaned up.
|
|
301
|
-
*/
|
|
302
|
-
removeInstances(startIndex: number, count = 1): Root {
|
|
319
|
+
protected removeChildren(startIndex: number, count: number): readonly RepeatInstance[] {
|
|
303
320
|
return this.scope.runTask(() => {
|
|
304
|
-
this.childrenState.setChildren((currentInstances) => {
|
|
321
|
+
return this.childrenState.setChildren((currentInstances) => {
|
|
305
322
|
const updatedInstances = currentInstances.slice();
|
|
306
323
|
const removedInstances = updatedInstances.splice(startIndex, count);
|
|
307
324
|
|
|
@@ -311,8 +328,6 @@ export class RepeatRange
|
|
|
311
328
|
|
|
312
329
|
return updatedInstances;
|
|
313
330
|
});
|
|
314
|
-
|
|
315
|
-
return this.root;
|
|
316
331
|
});
|
|
317
332
|
}
|
|
318
333
|
|
|
@@ -4,25 +4,26 @@ import type {
|
|
|
4
4
|
RepeatDefinition,
|
|
5
5
|
RepeatInstanceNode,
|
|
6
6
|
RepeatInstanceNodeAppearances,
|
|
7
|
-
} from '
|
|
8
|
-
import type { TextRange } from '
|
|
9
|
-
import type {
|
|
10
|
-
import {
|
|
11
|
-
import
|
|
12
|
-
import {
|
|
13
|
-
import
|
|
14
|
-
import type {
|
|
15
|
-
import type {
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import
|
|
19
|
-
import
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
22
|
-
import
|
|
23
|
-
import type {
|
|
24
|
-
import type {
|
|
25
|
-
import type {
|
|
7
|
+
} from '../../client/repeat/RepeatInstanceNode.ts';
|
|
8
|
+
import type { TextRange } from '../../client/TextRange.ts';
|
|
9
|
+
import type { AncestorNodeValidationState } from '../../client/validation.ts';
|
|
10
|
+
import type { ChildrenState } from '../../lib/reactivity/createChildrenState.ts';
|
|
11
|
+
import { createChildrenState } from '../../lib/reactivity/createChildrenState.ts';
|
|
12
|
+
import type { MaterializedChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
13
|
+
import { materializeCurrentStateChildren } from '../../lib/reactivity/materializeCurrentStateChildren.ts';
|
|
14
|
+
import type { CurrentState } from '../../lib/reactivity/node-state/createCurrentState.ts';
|
|
15
|
+
import type { EngineState } from '../../lib/reactivity/node-state/createEngineState.ts';
|
|
16
|
+
import type { SharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
17
|
+
import { createSharedNodeState } from '../../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
18
|
+
import { createNodeLabel } from '../../lib/reactivity/text/createNodeLabel.ts';
|
|
19
|
+
import { createAggregatedViolations } from '../../lib/reactivity/validation/createAggregatedViolations.ts';
|
|
20
|
+
import type { DescendantNodeSharedStateSpec } from '../abstract/DescendantNode.ts';
|
|
21
|
+
import { DescendantNode } from '../abstract/DescendantNode.ts';
|
|
22
|
+
import { buildChildren } from '../children.ts';
|
|
23
|
+
import type { AnyChildNode, GeneralChildNode, RepeatRange } from '../hierarchy.ts';
|
|
24
|
+
import type { NodeID } from '../identity.ts';
|
|
25
|
+
import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
|
|
26
|
+
import type { SubscribableDependency } from '../internal-api/SubscribableDependency.ts';
|
|
26
27
|
|
|
27
28
|
export type { RepeatDefinition };
|
|
28
29
|
|
|
@@ -87,6 +88,7 @@ export class RepeatInstance
|
|
|
87
88
|
CurrentState<RepeatInstanceStateSpec>,
|
|
88
89
|
GeneralChildNode
|
|
89
90
|
>;
|
|
91
|
+
readonly validationState: AncestorNodeValidationState;
|
|
90
92
|
|
|
91
93
|
constructor(
|
|
92
94
|
override readonly parent: RepeatRange,
|
|
@@ -116,6 +118,10 @@ export class RepeatInstance
|
|
|
116
118
|
|
|
117
119
|
this.currentIndex = currentIndex;
|
|
118
120
|
|
|
121
|
+
const sharedStateOptions = {
|
|
122
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
123
|
+
};
|
|
124
|
+
|
|
119
125
|
const state = createSharedNodeState(
|
|
120
126
|
this.scope,
|
|
121
127
|
{
|
|
@@ -131,9 +137,7 @@ export class RepeatInstance
|
|
|
131
137
|
valueOptions: null,
|
|
132
138
|
value: null,
|
|
133
139
|
},
|
|
134
|
-
|
|
135
|
-
clientStateFactory: this.engineConfig.stateFactory,
|
|
136
|
-
}
|
|
140
|
+
sharedStateOptions
|
|
137
141
|
);
|
|
138
142
|
|
|
139
143
|
this.state = state;
|
|
@@ -166,6 +170,7 @@ export class RepeatInstance
|
|
|
166
170
|
});
|
|
167
171
|
|
|
168
172
|
childrenState.setChildren(buildChildren(this));
|
|
173
|
+
this.validationState = createAggregatedViolations(this, sharedStateOptions);
|
|
169
174
|
}
|
|
170
175
|
|
|
171
176
|
protected override initializeContextNode(parentContextNode: Element, nodeName: string): Element {
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { createComputed } from 'solid-js';
|
|
2
|
+
import type { RepeatRangeNodeAppearances } from '../../client/repeat/BaseRepeatRangeNode.ts';
|
|
3
|
+
import type { RepeatRangeControlledNode } from '../../client/repeat/RepeatRangeControlledNode.ts';
|
|
4
|
+
import type { AncestorNodeValidationState } from '../../client/validation.ts';
|
|
5
|
+
import { createComputedExpression } from '../../lib/reactivity/createComputedExpression.ts';
|
|
6
|
+
import { createAggregatedViolations } from '../../lib/reactivity/validation/createAggregatedViolations.ts';
|
|
7
|
+
import type { ControlledRepeatRangeDefinition } from '../../parse/model/RepeatRangeDefinition.ts';
|
|
8
|
+
import type { GeneralParentNode } from '../hierarchy.ts';
|
|
9
|
+
import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
|
|
10
|
+
import type { SubscribableDependency } from '../internal-api/SubscribableDependency.ts';
|
|
11
|
+
import { BaseRepeatRange } from './BaseRepeatRange.ts';
|
|
12
|
+
import type { RepeatDefinition } from './RepeatInstance.ts';
|
|
13
|
+
|
|
14
|
+
export class RepeatRangeControlled
|
|
15
|
+
extends BaseRepeatRange<ControlledRepeatRangeDefinition>
|
|
16
|
+
implements RepeatRangeControlledNode, EvaluationContext, SubscribableDependency
|
|
17
|
+
{
|
|
18
|
+
// RepeatRangeControlledNode
|
|
19
|
+
readonly nodeType = 'repeat-range:controlled';
|
|
20
|
+
|
|
21
|
+
readonly appearances: RepeatRangeNodeAppearances;
|
|
22
|
+
|
|
23
|
+
readonly validationState: AncestorNodeValidationState;
|
|
24
|
+
|
|
25
|
+
constructor(parent: GeneralParentNode, definition: ControlledRepeatRangeDefinition) {
|
|
26
|
+
super(parent, definition);
|
|
27
|
+
|
|
28
|
+
this.appearances = definition.bodyElement.appearances;
|
|
29
|
+
|
|
30
|
+
this.initializeControlledChildrenState(definition);
|
|
31
|
+
|
|
32
|
+
this.validationState = createAggregatedViolations(this, {
|
|
33
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
private initializeControlledChildrenState(definition: ControlledRepeatRangeDefinition): void {
|
|
38
|
+
this.scope.runTask(() => {
|
|
39
|
+
const { count, instances, template } = definition;
|
|
40
|
+
const computeCount = createComputedExpression(this.selfEvaluationContext, count);
|
|
41
|
+
|
|
42
|
+
createComputed<number>((previousCount) => {
|
|
43
|
+
let currentCount = computeCount();
|
|
44
|
+
|
|
45
|
+
if (Number.isFinite(currentCount) && currentCount < 0) {
|
|
46
|
+
currentCount = 0;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (
|
|
50
|
+
currentCount === previousCount ||
|
|
51
|
+
// TODO: the intent of this check is to defer a count update when the
|
|
52
|
+
// count expression produces a blank value. This "feels right" when
|
|
53
|
+
// the count is directly controlled by the user (i.e. entering a
|
|
54
|
+
// number in an input), but probably does not make sense in every
|
|
55
|
+
// scenario! For instance, when a referenced node's relevance changes.
|
|
56
|
+
Number.isNaN(currentCount)
|
|
57
|
+
) {
|
|
58
|
+
return previousCount;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (currentCount > previousCount) {
|
|
62
|
+
const delta = currentCount - previousCount;
|
|
63
|
+
const definitions = Array<RepeatDefinition>(delta)
|
|
64
|
+
.fill(template)
|
|
65
|
+
.map((baseDefinition, index) => {
|
|
66
|
+
const instanceIndex = previousCount + index;
|
|
67
|
+
|
|
68
|
+
return instances[instanceIndex] ?? baseDefinition;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this.addChildren(previousCount - 1, definitions);
|
|
72
|
+
} else {
|
|
73
|
+
const delta = previousCount - currentCount;
|
|
74
|
+
|
|
75
|
+
this.removeChildren(currentCount, delta);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return currentCount;
|
|
79
|
+
}, 0);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { RepeatRangeNodeAppearances } from '../../client/repeat/BaseRepeatRangeNode.ts';
|
|
2
|
+
import type { RepeatRangeUncontrolledNode } from '../../client/repeat/RepeatRangeUncontrolledNode.ts';
|
|
3
|
+
import type { AncestorNodeValidationState } from '../../client/validation.ts';
|
|
4
|
+
import { createAggregatedViolations } from '../../lib/reactivity/validation/createAggregatedViolations.ts';
|
|
5
|
+
import type { UncontrolledRepeatRangeDefinition } from '../../parse/model/RepeatRangeDefinition.ts';
|
|
6
|
+
import type { GeneralParentNode } from '../hierarchy.ts';
|
|
7
|
+
import type { EvaluationContext } from '../internal-api/EvaluationContext.ts';
|
|
8
|
+
import type { SubscribableDependency } from '../internal-api/SubscribableDependency.ts';
|
|
9
|
+
import type { Root } from '../Root.ts';
|
|
10
|
+
import { BaseRepeatRange } from './BaseRepeatRange.ts';
|
|
11
|
+
import { RepeatInstance } from './RepeatInstance.ts';
|
|
12
|
+
|
|
13
|
+
export class RepeatRangeUncontrolled
|
|
14
|
+
extends BaseRepeatRange<UncontrolledRepeatRangeDefinition>
|
|
15
|
+
implements RepeatRangeUncontrolledNode, EvaluationContext, SubscribableDependency
|
|
16
|
+
{
|
|
17
|
+
// RepeatRangeUncontrolledNode
|
|
18
|
+
readonly nodeType = 'repeat-range:uncontrolled';
|
|
19
|
+
|
|
20
|
+
readonly appearances: RepeatRangeNodeAppearances;
|
|
21
|
+
|
|
22
|
+
readonly validationState: AncestorNodeValidationState;
|
|
23
|
+
|
|
24
|
+
constructor(parent: GeneralParentNode, definition: UncontrolledRepeatRangeDefinition) {
|
|
25
|
+
super(parent, definition);
|
|
26
|
+
|
|
27
|
+
this.appearances = definition.bodyElement.appearances;
|
|
28
|
+
|
|
29
|
+
this.addChildren(-1, definition.instances);
|
|
30
|
+
|
|
31
|
+
this.validationState = createAggregatedViolations(this, {
|
|
32
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// RepeatRangeUncontrolledNode
|
|
37
|
+
addInstances(afterIndex = this.getLastIndex(), count = 1): Root {
|
|
38
|
+
const definitions = Array(count).fill(this.definition.template);
|
|
39
|
+
|
|
40
|
+
this.addChildren(afterIndex, definitions);
|
|
41
|
+
|
|
42
|
+
return this.root;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Removes the {@link RepeatInstance}s corresponding to the specified range of
|
|
47
|
+
* indexes, and then removes those repeat instances from the repeat range's
|
|
48
|
+
* own children state in that order:
|
|
49
|
+
*
|
|
50
|
+
* 1. Identify the set of {@link RepeatInstance}s to be removed.
|
|
51
|
+
*
|
|
52
|
+
* 2. For each {@link RepeatInstance} pending removal, perform that node's
|
|
53
|
+
* removal logic. @see {@link RepeatInstance.remove} for more detail.
|
|
54
|
+
*
|
|
55
|
+
* 3. Finalize update to the repeat range's own {@link childrenState},
|
|
56
|
+
* omitting those {@link RepeatInstance}s which were removed.
|
|
57
|
+
*
|
|
58
|
+
* This ordering ensures a consistent representation of state is established
|
|
59
|
+
* prior to any downstream reactive updates, and ensures that removed nodes'
|
|
60
|
+
* reactivity is cleaned up.
|
|
61
|
+
*/
|
|
62
|
+
removeInstances(startIndex: number, count = 1): Root {
|
|
63
|
+
this.removeChildren(startIndex, count);
|
|
64
|
+
|
|
65
|
+
return this.root;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
TextRange as ClientTextRange,
|
|
3
|
+
TextChunk,
|
|
4
|
+
TextOrigin,
|
|
5
|
+
TextRole,
|
|
6
|
+
} from '../../client/TextRange.ts';
|
|
2
7
|
import { FormattedTextStub } from './FormattedTextStub.ts';
|
|
3
8
|
|
|
4
|
-
export
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
export class TextRange<Role extends TextRole, Origin extends TextOrigin>
|
|
10
|
+
implements ClientTextRange<Role, Origin>
|
|
11
|
+
{
|
|
7
12
|
*[Symbol.iterator]() {
|
|
8
13
|
yield* this.chunks;
|
|
9
14
|
}
|
|
@@ -17,6 +22,7 @@ export class TextRange<Role extends TextRole> implements ClientTextRange<Role> {
|
|
|
17
22
|
}
|
|
18
23
|
|
|
19
24
|
constructor(
|
|
25
|
+
readonly origin: Origin,
|
|
20
26
|
readonly role: Role,
|
|
21
27
|
protected readonly chunks: readonly TextChunk[]
|
|
22
28
|
) {}
|