@getodk/xforms-engine 0.5.0 → 0.6.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/README.md +1 -1
- package/dist/client/BaseNode.d.ts +4 -0
- package/dist/client/BaseValueNode.d.ts +1 -1
- package/dist/client/GroupNode.d.ts +1 -0
- package/dist/client/InputNode.d.ts +32 -3
- package/dist/client/ModelValueNode.d.ts +1 -0
- package/dist/client/NoteNode.d.ts +24 -7
- package/dist/client/RangeNode.d.ts +36 -0
- package/dist/client/RankNode.d.ts +46 -0
- package/dist/client/RootNode.d.ts +6 -3
- package/dist/client/SelectNode.d.ts +47 -25
- package/dist/client/SubtreeNode.d.ts +1 -0
- package/dist/client/TriggerNode.d.ts +10 -6
- package/dist/client/hierarchy.d.ts +5 -5
- package/dist/client/node-types.d.ts +2 -2
- package/dist/client/unsupported/UnsupportedControlNode.d.ts +1 -3
- package/dist/error/RankMissingValueError.d.ts +3 -0
- package/dist/error/RankValueTypeError.d.ts +6 -0
- package/dist/error/SelectValueTypeError.d.ts +15 -0
- package/dist/error/XFormsSpecViolationError.d.ts +2 -0
- package/dist/index.d.ts +2 -3
- package/dist/index.js +5604 -4666
- package/dist/index.js.map +1 -1
- package/dist/instance/Group.d.ts +1 -0
- package/dist/instance/InputControl.d.ts +5 -3
- package/dist/instance/ModelValue.d.ts +2 -0
- package/dist/instance/Note.d.ts +13 -25
- package/dist/instance/PrimaryInstance.d.ts +1 -0
- package/dist/instance/RangeControl.d.ts +34 -0
- package/dist/instance/RankControl.d.ts +40 -0
- package/dist/instance/Root.d.ts +1 -0
- package/dist/instance/SelectControl.d.ts +66 -0
- package/dist/instance/Subtree.d.ts +1 -0
- package/dist/instance/TriggerControl.d.ts +9 -22
- package/dist/instance/abstract/DescendantNode.d.ts +1 -2
- package/dist/instance/abstract/InstanceNode.d.ts +3 -1
- package/dist/instance/abstract/UnsupportedControl.d.ts +1 -0
- package/dist/instance/abstract/ValueNode.d.ts +0 -1
- package/dist/instance/hierarchy.d.ts +9 -9
- package/dist/instance/internal-api/InstanceValueContext.d.ts +2 -0
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.d.ts +2 -1
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableParentNode.d.ts +2 -1
- package/dist/instance/internal-api/submission/ClientReactiveSubmittableValueNode.d.ts +2 -1
- package/dist/instance/repeat/BaseRepeatRange.d.ts +1 -0
- package/dist/instance/repeat/RepeatInstance.d.ts +1 -0
- package/dist/integration/xpath/adapter/names.d.ts +1 -11
- package/dist/integration/xpath/adapter/traversal.d.ts +10 -9
- package/dist/integration/xpath/static-dom/StaticAttribute.d.ts +10 -3
- package/dist/integration/xpath/static-dom/StaticDocument.d.ts +0 -1
- package/dist/integration/xpath/static-dom/StaticElement.d.ts +12 -4
- package/dist/lib/client-reactivity/submission/createRootSubmissionState.d.ts +3 -0
- package/dist/lib/codecs/Geopoint/Geopoint.d.ts +48 -0
- package/dist/lib/codecs/Geopoint/GeopointValueCodec.d.ts +5 -0
- package/dist/lib/codecs/NoteCodec.d.ts +8 -0
- package/dist/lib/codecs/RangeCodec.d.ts +8 -0
- package/dist/lib/codecs/TriggerCodec.d.ts +7 -0
- package/dist/lib/codecs/ValueArrayCodec.d.ts +11 -0
- package/dist/lib/codecs/ValueCodec.d.ts +2 -2
- package/dist/lib/codecs/getNoteCodec.d.ts +3 -0
- package/dist/lib/codecs/getSelectCodec.d.ts +5 -0
- package/dist/lib/codecs/getSharedValueCodec.d.ts +3 -2
- package/dist/lib/codecs/items/BaseItemCodec.d.ts +9 -0
- package/dist/lib/codecs/items/MultipleValueItemCodec.d.ts +14 -0
- package/dist/lib/codecs/items/SingleValueItemCodec.d.ts +24 -0
- package/dist/lib/dom/query.d.ts +1 -2
- package/dist/lib/names/NamespaceDeclaration.d.ts +45 -0
- package/dist/lib/names/NamespaceDeclarationMap.d.ts +137 -0
- package/dist/lib/names/NamespaceURL.d.ts +30 -0
- package/dist/lib/names/QualifiedName.d.ts +113 -0
- package/dist/lib/number-parsers.d.ts +2 -0
- package/dist/lib/reactivity/createItemCollection.d.ts +21 -0
- package/dist/lib/xml-serialization.d.ts +11 -2
- package/dist/parse/XFormDOM.d.ts +1 -1
- package/dist/parse/body/BodyDefinition.d.ts +2 -2
- package/dist/parse/body/appearance/rangeAppearanceParser.d.ts +3 -0
- package/dist/parse/body/control/InputControlDefinition.d.ts +3 -0
- package/dist/parse/body/control/ItemDefinition.d.ts +14 -0
- package/dist/parse/body/control/ItemsetDefinition.d.ts +18 -0
- package/dist/parse/body/control/RangeControlDefinition.d.ts +31 -2
- package/dist/parse/body/control/RankControlDefinition.d.ts +7 -3
- package/dist/parse/body/control/{select/SelectDefinition.d.ts → SelectControlDefinition.d.ts} +9 -9
- package/dist/parse/expression/ItemsetNodesetExpression.d.ts +1 -1
- package/dist/parse/expression/ItemsetValueExpression.d.ts +1 -1
- package/dist/parse/model/BindDefinition.d.ts +3 -1
- package/dist/parse/model/BindPreloadDefinition.d.ts +42 -0
- package/dist/parse/model/DescendentNodeDefinition.d.ts +4 -13
- package/dist/parse/model/ItextTranslation/ItextTranslationRootDefinition.d.ts +2 -1
- package/dist/parse/model/LeafNodeDefinition.d.ts +7 -4
- package/dist/parse/model/ModelBindMap.d.ts +1 -1
- package/dist/parse/model/NodeDefinition.d.ts +16 -19
- package/dist/parse/model/NoteNodeDefinition.d.ts +6 -5
- package/dist/parse/model/RangeNodeDefinition.d.ts +41 -0
- package/dist/parse/model/RepeatInstanceDefinition.d.ts +7 -4
- package/dist/parse/model/RepeatRangeDefinition.d.ts +7 -4
- package/dist/parse/model/RepeatTemplateDefinition.d.ts +7 -4
- package/dist/parse/model/RootAttributeDefinition.d.ts +24 -0
- package/dist/parse/model/RootAttributeMap.d.ts +23 -0
- package/dist/parse/model/RootDefinition.d.ts +9 -7
- package/dist/parse/model/SubtreeDefinition.d.ts +7 -4
- package/dist/parse/shared/parseStaticDocumentFromDOMSubtree.d.ts +2 -3
- package/dist/parse/text/ItemLabelDefinition.d.ts +1 -1
- package/dist/parse/text/ItemsetLabelDefinition.d.ts +2 -2
- package/dist/parse/text/abstract/TextElementDefinition.d.ts +1 -1
- package/dist/parse/xpath/semantic-analysis.d.ts +1 -3
- package/dist/solid.js +5603 -4665
- package/dist/solid.js.map +1 -1
- package/package.json +15 -12
- package/src/client/BaseNode.ts +5 -0
- package/src/client/BaseValueNode.ts +1 -1
- package/src/client/GroupNode.ts +1 -0
- package/src/client/InputNode.ts +38 -2
- package/src/client/ModelValueNode.ts +1 -0
- package/src/client/NoteNode.ts +43 -7
- package/src/client/RangeNode.ts +51 -0
- package/src/client/RankNode.ts +54 -0
- package/src/client/RootNode.ts +11 -5
- package/src/client/SelectNode.ts +53 -26
- package/src/client/SubtreeNode.ts +1 -0
- package/src/client/TriggerNode.ts +12 -6
- package/src/client/hierarchy.ts +7 -8
- package/src/client/node-types.ts +1 -1
- package/src/client/unsupported/UnsupportedControlNode.ts +2 -6
- package/src/error/RankMissingValueError.ts +5 -0
- package/src/error/RankValueTypeError.ts +13 -0
- package/src/error/SelectValueTypeError.ts +22 -0
- package/src/error/XFormsSpecViolationError.ts +1 -0
- package/src/index.ts +2 -12
- package/src/instance/Group.ts +1 -0
- package/src/instance/InputControl.ts +42 -2
- package/src/instance/ModelValue.ts +2 -0
- package/src/instance/Note.ts +34 -59
- package/src/instance/PrimaryInstance.ts +1 -0
- package/src/instance/RangeControl.ts +113 -0
- package/src/instance/RankControl.ts +199 -0
- package/src/instance/Root.ts +3 -2
- package/src/instance/SelectControl.ts +219 -0
- package/src/instance/Subtree.ts +1 -0
- package/src/instance/TriggerControl.ts +36 -75
- package/src/instance/abstract/DescendantNode.ts +1 -6
- package/src/instance/abstract/InstanceNode.ts +10 -2
- package/src/instance/abstract/UnsupportedControl.ts +1 -0
- package/src/instance/abstract/ValueNode.ts +3 -2
- package/src/instance/children.ts +71 -30
- package/src/instance/hierarchy.ts +21 -16
- package/src/instance/internal-api/InstanceValueContext.ts +2 -0
- package/src/instance/internal-api/submission/ClientReactiveSubmittableLeafNode.ts +2 -1
- package/src/instance/internal-api/submission/ClientReactiveSubmittableParentNode.ts +2 -1
- package/src/instance/internal-api/submission/ClientReactiveSubmittableValueNode.ts +2 -1
- package/src/instance/repeat/BaseRepeatRange.ts +2 -0
- package/src/instance/repeat/RepeatInstance.ts +1 -0
- package/src/instance/resource.ts +4 -1
- package/src/integration/xpath/adapter/names.ts +66 -17
- package/src/integration/xpath/adapter/traversal.ts +10 -9
- package/src/integration/xpath/static-dom/StaticAttribute.ts +15 -7
- package/src/integration/xpath/static-dom/StaticDocument.ts +0 -2
- package/src/integration/xpath/static-dom/StaticElement.ts +21 -8
- package/src/lib/client-reactivity/submission/createLeafNodeSubmissionState.ts +1 -1
- package/src/lib/client-reactivity/submission/createParentNodeSubmissionState.ts +1 -1
- package/src/lib/client-reactivity/submission/createRootSubmissionState.ts +19 -0
- package/src/lib/client-reactivity/submission/createValueNodeSubmissionState.ts +2 -2
- package/src/lib/codecs/Geopoint/Geopoint.ts +150 -0
- package/src/lib/codecs/Geopoint/GeopointValueCodec.ts +20 -0
- package/src/lib/codecs/NoteCodec.ts +32 -0
- package/src/lib/codecs/RangeCodec.ts +65 -0
- package/src/lib/codecs/TriggerCodec.ts +64 -0
- package/src/lib/codecs/ValueArrayCodec.ts +42 -0
- package/src/lib/codecs/ValueCodec.ts +2 -2
- package/src/lib/codecs/getNoteCodec.ts +27 -0
- package/src/lib/codecs/getSelectCodec.ts +27 -0
- package/src/lib/codecs/getSharedValueCodec.ts +5 -3
- package/src/lib/codecs/items/BaseItemCodec.ts +20 -0
- package/src/lib/codecs/items/MultipleValueItemCodec.ts +28 -0
- package/src/lib/codecs/items/SingleValueItemCodec.ts +67 -0
- package/src/lib/dom/query.ts +1 -2
- package/src/lib/names/NamespaceDeclaration.ts +106 -0
- package/src/lib/names/NamespaceDeclarationMap.ts +228 -0
- package/src/lib/names/NamespaceURL.ts +44 -0
- package/src/lib/names/QualifiedName.ts +170 -0
- package/src/lib/number-parsers.ts +25 -0
- package/src/lib/reactivity/createInstanceValueState.ts +50 -0
- package/src/lib/reactivity/{createSelectItems.ts → createItemCollection.ts} +41 -36
- package/src/lib/xml-serialization.ts +76 -9
- package/src/parse/XFormDOM.ts +141 -21
- package/src/parse/XFormDefinition.ts +1 -4
- package/src/parse/body/BodyDefinition.ts +4 -4
- package/src/parse/body/appearance/rangeAppearanceParser.ts +11 -0
- package/src/parse/body/control/InputControlDefinition.ts +9 -0
- package/src/parse/body/control/{select/ItemDefinition.ts → ItemDefinition.ts} +8 -6
- package/src/parse/body/control/{select/ItemsetDefinition.ts → ItemsetDefinition.ts} +11 -9
- package/src/parse/body/control/RangeControlDefinition.ts +91 -6
- package/src/parse/body/control/RankControlDefinition.ts +25 -7
- package/src/parse/body/control/{select/SelectDefinition.ts → SelectControlDefinition.ts} +9 -9
- package/src/parse/expression/ItemsetNodesetExpression.ts +1 -1
- package/src/parse/expression/ItemsetValueExpression.ts +1 -1
- package/src/parse/model/BindDefinition.ts +4 -0
- package/src/parse/model/BindPreloadDefinition.ts +100 -0
- package/src/parse/model/DescendentNodeDefinition.ts +7 -25
- package/src/parse/model/ItextTranslation/ItextTranslationRootDefinition.ts +2 -1
- package/src/parse/model/LeafNodeDefinition.ts +11 -4
- package/src/parse/model/NodeDefinition.ts +24 -45
- package/src/parse/model/NoteNodeDefinition.ts +8 -7
- package/src/parse/model/RangeNodeDefinition.ts +118 -0
- package/src/parse/model/RepeatInstanceDefinition.ts +11 -7
- package/src/parse/model/RepeatRangeDefinition.ts +11 -7
- package/src/parse/model/RepeatTemplateDefinition.ts +11 -7
- package/src/parse/model/RootAttributeDefinition.ts +45 -0
- package/src/parse/model/RootAttributeMap.ts +44 -0
- package/src/parse/model/RootDefinition.ts +29 -28
- package/src/parse/model/SecondaryInstance/sources/GeoJSONExternalSecondaryInstance.ts +1 -0
- package/src/parse/model/SubtreeDefinition.ts +12 -12
- package/src/parse/shared/parseStaticDocumentFromDOMSubtree.ts +3 -3
- package/src/parse/text/ItemLabelDefinition.ts +1 -1
- package/src/parse/text/ItemsetLabelDefinition.ts +2 -2
- package/src/parse/text/abstract/TextElementDefinition.ts +1 -1
- package/src/parse/xpath/semantic-analysis.ts +4 -3
- package/dist/client/unsupported/RangeNode.d.ts +0 -9
- package/dist/client/unsupported/RankNode.d.ts +0 -9
- package/dist/instance/SelectField.d.ts +0 -58
- package/dist/instance/unsupported/RangeControl.d.ts +0 -6
- package/dist/instance/unsupported/RankControl.d.ts +0 -6
- package/dist/integration/xpath/static-dom/StaticNamedNode.d.ts +0 -17
- package/dist/lib/reactivity/createSelectItems.d.ts +0 -16
- package/dist/parse/body/control/select/ItemDefinition.d.ts +0 -13
- package/dist/parse/body/control/select/ItemsetDefinition.d.ts +0 -17
- package/dist/parse/body/control/select/ItemsetNodesetContext.d.ts +0 -9
- package/src/client/unsupported/RangeNode.ts +0 -14
- package/src/client/unsupported/RankNode.ts +0 -14
- package/src/instance/SelectField.ts +0 -263
- package/src/instance/unsupported/RangeControl.ts +0 -9
- package/src/instance/unsupported/RankControl.ts +0 -9
- package/src/integration/xpath/static-dom/StaticNamedNode.ts +0 -45
- package/src/parse/body/control/select/ItemsetNodesetContext.ts +0 -21
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { XFormsSpecViolationError } from './XFormsSpecViolationError.ts';
|
|
2
|
+
import type { RankDefinition } from '../client/RankNode.ts';
|
|
3
|
+
import type { UnsupportedBaseItemValueType } from '../lib/codecs/items/BaseItemCodec.ts';
|
|
4
|
+
|
|
5
|
+
export class RankValueTypeError extends XFormsSpecViolationError {
|
|
6
|
+
constructor(definition: RankDefinition<UnsupportedBaseItemValueType>) {
|
|
7
|
+
const { valueType } = definition;
|
|
8
|
+
|
|
9
|
+
super(
|
|
10
|
+
`Ranks of type ${valueType} are not currently supported. If this functionality would be useful for your form, your feedback is welcome!`
|
|
11
|
+
);
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { SelectDefinition } from '../client/SelectNode.ts';
|
|
2
|
+
import type { UnsupportedBaseItemValueType } from '../lib/codecs/items/BaseItemCodec.ts';
|
|
3
|
+
import { XFormsSpecViolationError } from './XFormsSpecViolationError.ts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* @todo It would be good to have a standardized way to use specific types of
|
|
7
|
+
* errors as a prompt for feedback. There is currently a feedback link presented
|
|
8
|
+
* by `@getodk/web-forms`, which is conditionally displayed (condition is
|
|
9
|
+
* evidently controlled by a
|
|
10
|
+
* {@link https://vuejs.org/api/sfc-script-setup#defineoptions | Vue component option}).
|
|
11
|
+
*
|
|
12
|
+
* @see {@link https://github.com/getodk/web-forms/issues/276}
|
|
13
|
+
*/
|
|
14
|
+
export class SelectValueTypeError extends XFormsSpecViolationError {
|
|
15
|
+
constructor(definition: SelectDefinition<UnsupportedBaseItemValueType>) {
|
|
16
|
+
const { valueType } = definition;
|
|
17
|
+
|
|
18
|
+
super(
|
|
19
|
+
`Selects of type ${valueType} are not currently supported. If this functionality would be useful for your form, your feedback is welcome!`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export abstract class XFormsSpecViolationError extends Error {}
|
package/src/index.ts
CHANGED
|
@@ -24,6 +24,7 @@ export type * from './client/InputNode.ts';
|
|
|
24
24
|
export type * from './client/ModelValueNode.ts';
|
|
25
25
|
export type * from './client/NoteNode.ts';
|
|
26
26
|
export type * from './client/OpaqueReactiveObjectFactory.ts';
|
|
27
|
+
export type * from './client/RangeNode.ts';
|
|
27
28
|
export type * from './client/repeat/RepeatInstanceNode.ts';
|
|
28
29
|
export type * from './client/repeat/RepeatRangeControlledNode.ts';
|
|
29
30
|
export type * from './client/repeat/RepeatRangeUncontrolledNode.ts';
|
|
@@ -39,18 +40,7 @@ export type * from './client/submission/SubmissionState.ts';
|
|
|
39
40
|
export type * from './client/SubtreeNode.ts';
|
|
40
41
|
export type * from './client/TextRange.ts';
|
|
41
42
|
export type * from './client/TriggerNode.ts';
|
|
42
|
-
export type * from './client/
|
|
43
|
-
export type * from './client/unsupported/RankNode.ts';
|
|
43
|
+
export type * from './client/RankNode.ts';
|
|
44
44
|
export type * from './client/unsupported/UploadNode.ts';
|
|
45
45
|
export type * from './client/validation.ts';
|
|
46
46
|
export type * from './client/ValueType.ts';
|
|
47
|
-
|
|
48
|
-
// TODO: notwithstanding potential conflicts with parallel work on `web-forms`
|
|
49
|
-
// (former `ui-vue`), these are the last remaining references **outside of
|
|
50
|
-
// `xforms-engine`** to anything besides /client/* and the `initializeForm`
|
|
51
|
-
// entrypoint implementation. We'll refine the various `definition` types in due
|
|
52
|
-
// time.
|
|
53
|
-
export type {
|
|
54
|
-
AnySelectDefinition,
|
|
55
|
-
SelectDefinition,
|
|
56
|
-
} from './parse/body/control/select/SelectDefinition.ts';
|
package/src/instance/Group.ts
CHANGED
|
@@ -52,6 +52,7 @@ export class Group
|
|
|
52
52
|
// GroupNode
|
|
53
53
|
readonly nodeType = 'group';
|
|
54
54
|
readonly appearances: GroupNodeAppearances;
|
|
55
|
+
readonly nodeOptions = null;
|
|
55
56
|
readonly currentState: MaterializedChildren<CurrentState<GroupStateSpec>, GeneralChildNode>;
|
|
56
57
|
readonly validationState: AncestorNodeValidationState;
|
|
57
58
|
readonly submissionState: SubmissionState;
|
|
@@ -5,6 +5,7 @@ import type {
|
|
|
5
5
|
InputNode,
|
|
6
6
|
InputNodeAppearances,
|
|
7
7
|
InputNodeInputValue,
|
|
8
|
+
InputNodeOptions,
|
|
8
9
|
} from '../client/InputNode.ts';
|
|
9
10
|
import type { TextRange } from '../client/TextRange.ts';
|
|
10
11
|
import type { ValueType } from '../client/ValueType.ts';
|
|
@@ -17,20 +18,57 @@ import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedN
|
|
|
17
18
|
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
18
19
|
import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
19
20
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
20
|
-
import type {
|
|
21
|
+
import type { InputControlDefinition } from '../parse/body/control/InputControlDefinition.ts';
|
|
21
22
|
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
22
23
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
23
24
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
24
|
-
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
25
25
|
import type { ClientReactiveSubmittableValueNode } from './internal-api/submission/ClientReactiveSubmittableValueNode.ts';
|
|
26
|
+
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
27
|
+
import type { Root } from './Root.ts';
|
|
26
28
|
|
|
27
29
|
export type AnyInputDefinition = {
|
|
28
30
|
[V in ValueType]: InputDefinition<V>;
|
|
29
31
|
}[ValueType];
|
|
30
32
|
|
|
33
|
+
const stringInputNodeOptions = (control: InputControlDefinition): InputNodeOptions<'string'> => ({
|
|
34
|
+
rows: control.rows,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const geoInputNodeOptions = (
|
|
38
|
+
control: InputControlDefinition
|
|
39
|
+
): InputNodeOptions<'geopoint' | 'geoshape' | 'geotrace'> => ({
|
|
40
|
+
accuracyThreshold: control.accuracyThreshold,
|
|
41
|
+
unacceptableAccuracyThreshold: control.unacceptableAccuracyThreshold,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
type NodeOptionsFactory<V extends ValueType> = (
|
|
45
|
+
controlDefinition: InputControlDefinition
|
|
46
|
+
) => InputNodeOptions<V>;
|
|
47
|
+
|
|
48
|
+
type NodeOptionsFactoryByType = {
|
|
49
|
+
[V in ValueType]: NodeOptionsFactory<V>;
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const nodeOptionsFactoryByType: NodeOptionsFactoryByType = {
|
|
53
|
+
string: stringInputNodeOptions,
|
|
54
|
+
int: () => null,
|
|
55
|
+
boolean: () => null,
|
|
56
|
+
decimal: () => null,
|
|
57
|
+
date: () => null,
|
|
58
|
+
time: () => null,
|
|
59
|
+
dateTime: () => null,
|
|
60
|
+
geopoint: geoInputNodeOptions,
|
|
61
|
+
geotrace: geoInputNodeOptions,
|
|
62
|
+
geoshape: geoInputNodeOptions,
|
|
63
|
+
binary: () => null,
|
|
64
|
+
barcode: () => null,
|
|
65
|
+
intent: () => null,
|
|
66
|
+
};
|
|
67
|
+
|
|
31
68
|
interface InputControlStateSpec<V extends ValueType> extends ValueNodeStateSpec<RuntimeValue<V>> {
|
|
32
69
|
readonly label: Accessor<TextRange<'label'> | null>;
|
|
33
70
|
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
71
|
+
readonly valueOptions: null;
|
|
34
72
|
}
|
|
35
73
|
|
|
36
74
|
export class InputControl<V extends ValueType = ValueType>
|
|
@@ -60,6 +98,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
60
98
|
// InputNode
|
|
61
99
|
readonly nodeType = 'input';
|
|
62
100
|
readonly appearances: InputNodeAppearances;
|
|
101
|
+
readonly nodeOptions: InputNodeOptions<V>;
|
|
63
102
|
readonly currentState: CurrentState<InputControlStateSpec<V>>;
|
|
64
103
|
|
|
65
104
|
constructor(parent: GeneralParentNode, definition: InputDefinition<V>) {
|
|
@@ -68,6 +107,7 @@ export class InputControl<V extends ValueType = ValueType>
|
|
|
68
107
|
super(parent, definition, codec);
|
|
69
108
|
|
|
70
109
|
this.appearances = definition.bodyElement.appearances;
|
|
110
|
+
this.nodeOptions = nodeOptionsFactoryByType[definition.valueType](definition.bodyElement);
|
|
71
111
|
|
|
72
112
|
const sharedStateOptions = {
|
|
73
113
|
clientStateFactory: this.engineConfig.stateFactory,
|
|
@@ -17,6 +17,7 @@ import type { ClientReactiveSubmittableValueNode } from './internal-api/submissi
|
|
|
17
17
|
interface ModelValueStateSpec<V extends ValueType> extends ValueNodeStateSpec<RuntimeValue<V>> {
|
|
18
18
|
readonly label: null;
|
|
19
19
|
readonly hint: null;
|
|
20
|
+
readonly valueOptions: null;
|
|
20
21
|
}
|
|
21
22
|
|
|
22
23
|
export class ModelValue<V extends ValueType = ValueType>
|
|
@@ -46,6 +47,7 @@ export class ModelValue<V extends ValueType = ValueType>
|
|
|
46
47
|
// ModelValueNode
|
|
47
48
|
readonly nodeType = 'model-value';
|
|
48
49
|
readonly appearances = null;
|
|
50
|
+
readonly nodeOptions = null;
|
|
49
51
|
readonly currentState: CurrentState<ModelValueStateSpec<V>>;
|
|
50
52
|
|
|
51
53
|
constructor(parent: GeneralParentNode, definition: ModelValueDefinition<V>) {
|
package/src/instance/Note.ts
CHANGED
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { UnreachableError } from '@getodk/common/lib/error/UnreachableError.ts';
|
|
2
|
-
import { identity } from '@getodk/common/lib/identity.ts';
|
|
3
2
|
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
4
3
|
import type { Accessor } from 'solid-js';
|
|
5
|
-
import type { NoteNode, NoteNodeAppearances } from '../client/NoteNode.ts';
|
|
6
|
-
import type { SubmissionState } from '../client/submission/SubmissionState.ts';
|
|
4
|
+
import type { NoteNode, NoteNodeAppearances, NoteValue } from '../client/NoteNode.ts';
|
|
7
5
|
import type { TextRange } from '../client/TextRange.ts';
|
|
8
|
-
import type {
|
|
6
|
+
import type { ValueType } from '../client/ValueType.ts';
|
|
9
7
|
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
10
|
-
import {
|
|
8
|
+
import { getNoteCodec } from '../lib/codecs/getNoteCodec.ts';
|
|
9
|
+
import type { NoteInputValue, NoteRuntimeValue } from '../lib/codecs/NoteCodec.ts';
|
|
11
10
|
import { createNoteReadonlyThunk } from '../lib/reactivity/createNoteReadonlyThunk.ts';
|
|
12
|
-
import { createValueState } from '../lib/reactivity/createValueState.ts';
|
|
13
11
|
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
14
12
|
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
15
13
|
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
@@ -17,65 +15,47 @@ import { createSharedNodeState } from '../lib/reactivity/node-state/createShared
|
|
|
17
15
|
import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
18
16
|
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
19
17
|
import { createNoteText, type ComputedNoteText } from '../lib/reactivity/text/createNoteText.ts';
|
|
20
|
-
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
21
|
-
import type { SharedValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
22
|
-
import { createValidationState } from '../lib/reactivity/validation/createValidation.ts';
|
|
23
18
|
import type { NoteNodeDefinition } from '../parse/model/NoteNodeDefinition.ts';
|
|
24
|
-
import type
|
|
25
|
-
import { DescendantNode } from './abstract/DescendantNode.ts';
|
|
19
|
+
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
26
20
|
import type { GeneralParentNode } from './hierarchy.ts';
|
|
27
21
|
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
28
|
-
import type {
|
|
22
|
+
import type { ClientReactiveSubmittableValueNode } from './internal-api/submission/ClientReactiveSubmittableValueNode.ts';
|
|
29
23
|
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
30
|
-
import type { ValueContext } from './internal-api/ValueContext.ts';
|
|
31
24
|
|
|
32
|
-
interface NoteStateSpec extends
|
|
25
|
+
interface NoteStateSpec<V extends ValueType> extends ValueNodeStateSpec<NoteValue<V>> {
|
|
33
26
|
readonly readonly: Accessor<true>;
|
|
34
27
|
readonly noteText: ComputedNoteText;
|
|
35
28
|
readonly label: Accessor<TextRange<'label', 'form'> | null>;
|
|
36
29
|
readonly hint: Accessor<TextRange<'hint', 'form'> | null>;
|
|
37
|
-
readonly children: null;
|
|
38
|
-
readonly value: SimpleAtomicState<string>;
|
|
39
30
|
readonly valueOptions: null;
|
|
40
31
|
}
|
|
41
32
|
|
|
42
|
-
export class Note
|
|
43
|
-
extends
|
|
33
|
+
export class Note<V extends ValueType = ValueType>
|
|
34
|
+
extends ValueNode<V, NoteNodeDefinition<V>, NoteRuntimeValue<V>, NoteInputValue<V>>
|
|
44
35
|
implements
|
|
45
36
|
NoteNode,
|
|
46
37
|
XFormsXPathElement,
|
|
47
38
|
EvaluationContext,
|
|
48
39
|
ValidationContext,
|
|
49
|
-
|
|
50
|
-
ClientReactiveSubmittableLeafNode<string>
|
|
40
|
+
ClientReactiveSubmittableValueNode
|
|
51
41
|
{
|
|
52
|
-
private readonly validation: SharedValidationState;
|
|
53
|
-
|
|
54
42
|
// XFormsXPathElement
|
|
55
43
|
override readonly [XPathNodeKindKey] = 'element';
|
|
56
44
|
|
|
57
45
|
// InstanceNode
|
|
58
|
-
protected readonly state: SharedNodeState<NoteStateSpec
|
|
59
|
-
protected readonly engineState: EngineState<NoteStateSpec
|
|
46
|
+
protected readonly state: SharedNodeState<NoteStateSpec<V>>;
|
|
47
|
+
protected readonly engineState: EngineState<NoteStateSpec<V>>;
|
|
60
48
|
|
|
61
49
|
// NoteNode
|
|
62
50
|
readonly nodeType = 'note';
|
|
63
51
|
readonly appearances: NoteNodeAppearances;
|
|
64
|
-
readonly
|
|
65
|
-
|
|
66
|
-
get validationState(): LeafNodeValidationState {
|
|
67
|
-
return this.validation.currentState;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
readonly submissionState: SubmissionState;
|
|
52
|
+
readonly nodeOptions = null;
|
|
53
|
+
readonly currentState: CurrentState<NoteStateSpec<V>>;
|
|
71
54
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
readonly encodeValue = identity<string>;
|
|
75
|
-
readonly decodeValue = identity<string>;
|
|
55
|
+
constructor(parent: GeneralParentNode, definition: NoteNodeDefinition<V>) {
|
|
56
|
+
const codec = getNoteCodec(definition.valueType);
|
|
76
57
|
|
|
77
|
-
|
|
78
|
-
super(parent, definition);
|
|
58
|
+
super(parent, definition, codec);
|
|
79
59
|
|
|
80
60
|
this.appearances = definition.bodyElement.appearances;
|
|
81
61
|
|
|
@@ -125,7 +105,8 @@ export class Note
|
|
|
125
105
|
|
|
126
106
|
children: null,
|
|
127
107
|
valueOptions: null,
|
|
128
|
-
value:
|
|
108
|
+
value: this.valueState,
|
|
109
|
+
instanceValue: this.getInstanceValue,
|
|
129
110
|
},
|
|
130
111
|
sharedStateOptions
|
|
131
112
|
);
|
|
@@ -133,26 +114,20 @@ export class Note
|
|
|
133
114
|
this.state = state;
|
|
134
115
|
this.engineState = state.engineState;
|
|
135
116
|
this.currentState = state.currentState;
|
|
136
|
-
this.validation = createValidationState(this, sharedStateOptions);
|
|
137
|
-
this.submissionState = createLeafNodeSubmissionState(this);
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
// XFormsXPathElement
|
|
141
|
-
override getXPathValue(): string {
|
|
142
|
-
return this.engineState.value;
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
// ValidationContext
|
|
146
|
-
getViolation(): AnyViolation | null {
|
|
147
|
-
return this.validation.engineState.violation;
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
isBlank(): boolean {
|
|
151
|
-
return this.engineState.value === '';
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// InstanceNode
|
|
155
|
-
getChildren(): readonly [] {
|
|
156
|
-
return [];
|
|
157
117
|
}
|
|
158
118
|
}
|
|
119
|
+
|
|
120
|
+
export type AnyNote =
|
|
121
|
+
| Note<'barcode'>
|
|
122
|
+
| Note<'binary'>
|
|
123
|
+
| Note<'boolean'>
|
|
124
|
+
| Note<'date'>
|
|
125
|
+
| Note<'dateTime'>
|
|
126
|
+
| Note<'decimal'>
|
|
127
|
+
| Note<'geopoint'>
|
|
128
|
+
| Note<'geoshape'>
|
|
129
|
+
| Note<'geotrace'>
|
|
130
|
+
| Note<'int'>
|
|
131
|
+
| Note<'intent'>
|
|
132
|
+
| Note<'string'>
|
|
133
|
+
| Note<'time'>;
|
|
@@ -102,6 +102,7 @@ export class PrimaryInstance
|
|
|
102
102
|
// PrimaryInstanceDocument, ClientReactiveSubmittableInstance
|
|
103
103
|
readonly nodeType = 'primary-instance';
|
|
104
104
|
readonly appearances = null;
|
|
105
|
+
readonly nodeOptions = null;
|
|
105
106
|
readonly classes: BodyClassList;
|
|
106
107
|
readonly root: Root;
|
|
107
108
|
readonly currentState: MaterializedChildren<CurrentState<PrimaryInstanceStateSpec>, Root>;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
import type {
|
|
4
|
+
RangeInputValue,
|
|
5
|
+
RangeNode,
|
|
6
|
+
RangeNodeAppearances,
|
|
7
|
+
RangeValue,
|
|
8
|
+
} from '../client/RangeNode.ts';
|
|
9
|
+
import type { TextRange } from '../client/TextRange.ts';
|
|
10
|
+
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
11
|
+
import { RangeCodec } from '../lib/codecs/RangeCodec.ts';
|
|
12
|
+
import { getSharedValueCodec } from '../lib/codecs/getSharedValueCodec.ts';
|
|
13
|
+
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
14
|
+
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
15
|
+
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
16
|
+
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
17
|
+
import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
18
|
+
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
19
|
+
import type {
|
|
20
|
+
AnyRangeNodeDefinition,
|
|
21
|
+
RangeNodeDefinition,
|
|
22
|
+
RangeValueType,
|
|
23
|
+
} from '../parse/model/RangeNodeDefinition.ts';
|
|
24
|
+
import type { Root } from './Root.ts';
|
|
25
|
+
import { ValueNode, type ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
26
|
+
import type { GeneralParentNode } from './hierarchy.ts';
|
|
27
|
+
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
28
|
+
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
29
|
+
import type { ClientReactiveSubmittableValueNode } from './internal-api/submission/ClientReactiveSubmittableValueNode.ts';
|
|
30
|
+
|
|
31
|
+
interface RangeControlStateSpec<V extends RangeValueType>
|
|
32
|
+
extends ValueNodeStateSpec<RangeValue<V>> {
|
|
33
|
+
readonly label: Accessor<TextRange<'label'> | null>;
|
|
34
|
+
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
35
|
+
readonly valueOptions: null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export class RangeControl<V extends RangeValueType = RangeValueType>
|
|
39
|
+
extends ValueNode<V, RangeNodeDefinition<V>, RangeValue<V>, RangeInputValue<V>>
|
|
40
|
+
implements
|
|
41
|
+
RangeNode<V>,
|
|
42
|
+
XFormsXPathElement,
|
|
43
|
+
EvaluationContext,
|
|
44
|
+
ValidationContext,
|
|
45
|
+
ClientReactiveSubmittableValueNode
|
|
46
|
+
{
|
|
47
|
+
static from(parent: GeneralParentNode, definition: AnyRangeNodeDefinition): AnyRangeControl;
|
|
48
|
+
static from<V extends RangeValueType>(
|
|
49
|
+
parent: GeneralParentNode,
|
|
50
|
+
definition: RangeNodeDefinition<V>
|
|
51
|
+
): RangeControl<V> {
|
|
52
|
+
return new this<V>(parent, definition);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// XFormsXPathElement
|
|
56
|
+
override readonly [XPathNodeKindKey] = 'element';
|
|
57
|
+
|
|
58
|
+
// InstanceNode
|
|
59
|
+
protected readonly state: SharedNodeState<RangeControlStateSpec<V>>;
|
|
60
|
+
protected readonly engineState: EngineState<RangeControlStateSpec<V>>;
|
|
61
|
+
|
|
62
|
+
// RangeNode
|
|
63
|
+
readonly nodeType = 'range';
|
|
64
|
+
readonly appearances: RangeNodeAppearances;
|
|
65
|
+
readonly nodeOptions = null;
|
|
66
|
+
readonly currentState: CurrentState<RangeControlStateSpec<V>>;
|
|
67
|
+
|
|
68
|
+
constructor(parent: GeneralParentNode, definition: RangeNodeDefinition<V>) {
|
|
69
|
+
const baseCodec = getSharedValueCodec(definition.valueType);
|
|
70
|
+
const codec = new RangeCodec(baseCodec, definition);
|
|
71
|
+
|
|
72
|
+
super(parent, definition, codec);
|
|
73
|
+
|
|
74
|
+
this.appearances = definition.bodyElement.appearances;
|
|
75
|
+
|
|
76
|
+
const sharedStateOptions = {
|
|
77
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const state = createSharedNodeState(
|
|
81
|
+
this.scope,
|
|
82
|
+
{
|
|
83
|
+
reference: this.contextReference,
|
|
84
|
+
readonly: this.isReadonly,
|
|
85
|
+
relevant: this.isRelevant,
|
|
86
|
+
required: this.isRequired,
|
|
87
|
+
|
|
88
|
+
label: createNodeLabel(this, definition),
|
|
89
|
+
hint: createFieldHint(this, definition),
|
|
90
|
+
children: null,
|
|
91
|
+
valueOptions: null,
|
|
92
|
+
value: this.valueState,
|
|
93
|
+
instanceValue: this.getInstanceValue,
|
|
94
|
+
},
|
|
95
|
+
sharedStateOptions
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
this.state = state;
|
|
99
|
+
this.engineState = state.engineState;
|
|
100
|
+
this.currentState = state.currentState;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
setValue(value: RangeInputValue<V>): Root {
|
|
104
|
+
this.setValueState(value);
|
|
105
|
+
|
|
106
|
+
return this.root;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// prettier-ignore
|
|
111
|
+
export type AnyRangeControl =
|
|
112
|
+
| RangeControl<'decimal'>
|
|
113
|
+
| RangeControl<'int'>;
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import { XPathNodeKindKey } from '@getodk/xpath';
|
|
2
|
+
import type { Accessor } from 'solid-js';
|
|
3
|
+
import { createMemo } from 'solid-js';
|
|
4
|
+
import type { RankDefinition, RankItem, RankNode, RankValueOptions } from '../client/RankNode.ts';
|
|
5
|
+
import type { TextRange } from '../client/TextRange.ts';
|
|
6
|
+
import type { XFormsXPathElement } from '../integration/xpath/adapter/XFormsXPathNode.ts';
|
|
7
|
+
import type { CurrentState } from '../lib/reactivity/node-state/createCurrentState.ts';
|
|
8
|
+
import type { EngineState } from '../lib/reactivity/node-state/createEngineState.ts';
|
|
9
|
+
import type { SharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
10
|
+
import { createSharedNodeState } from '../lib/reactivity/node-state/createSharedNodeState.ts';
|
|
11
|
+
import { createFieldHint } from '../lib/reactivity/text/createFieldHint.ts';
|
|
12
|
+
import { createNodeLabel } from '../lib/reactivity/text/createNodeLabel.ts';
|
|
13
|
+
import type { SimpleAtomicState } from '../lib/reactivity/types.ts';
|
|
14
|
+
import type { Root } from './Root.ts';
|
|
15
|
+
import type { ValueNodeStateSpec } from './abstract/ValueNode.ts';
|
|
16
|
+
import { ValueNode } from './abstract/ValueNode.ts';
|
|
17
|
+
import type { GeneralParentNode } from './hierarchy.ts';
|
|
18
|
+
import type { EvaluationContext } from './internal-api/EvaluationContext.ts';
|
|
19
|
+
import type { ValidationContext } from './internal-api/ValidationContext.ts';
|
|
20
|
+
import type { ClientReactiveSubmittableValueNode } from './internal-api/submission/ClientReactiveSubmittableValueNode.ts';
|
|
21
|
+
import { MultipleValueItemCodec } from '../lib/codecs/items/MultipleValueItemCodec.ts';
|
|
22
|
+
import { sharedValueCodecs } from '../lib/codecs/getSharedValueCodec.ts';
|
|
23
|
+
import { createItemCollection } from '../lib/reactivity/createItemCollection.ts';
|
|
24
|
+
import type { UnknownAppearanceDefinition } from '../parse/body/appearance/unknownAppearanceParser.ts';
|
|
25
|
+
import type { ValueType } from '../client/ValueType.ts';
|
|
26
|
+
import { RankMissingValueError } from '../error/RankMissingValueError.ts';
|
|
27
|
+
import { RankValueTypeError } from '../error/RankValueTypeError.ts';
|
|
28
|
+
|
|
29
|
+
export type AnyRankDefinition = {
|
|
30
|
+
[V in ValueType]: RankDefinition<V>;
|
|
31
|
+
}[ValueType];
|
|
32
|
+
|
|
33
|
+
type AssertRankNodeDefinition = (
|
|
34
|
+
definition: AnyRankDefinition
|
|
35
|
+
) => asserts definition is RankDefinition<'string'>;
|
|
36
|
+
|
|
37
|
+
const assertRankNodeDefinition: AssertRankNodeDefinition = (definition) => {
|
|
38
|
+
if (definition.valueType !== 'string') {
|
|
39
|
+
throw new RankValueTypeError(definition);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
type RankItemMap = ReadonlyMap<string, RankItem>;
|
|
44
|
+
|
|
45
|
+
interface RankControlStateSpec extends ValueNodeStateSpec<readonly string[]> {
|
|
46
|
+
readonly label: Accessor<TextRange<'label'> | null>;
|
|
47
|
+
readonly hint: Accessor<TextRange<'hint'> | null>;
|
|
48
|
+
readonly valueOptions: Accessor<RankValueOptions>;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* @ToDo We currently represent a blank value for `<odk:rank>` as an empty array.
|
|
53
|
+
* This is ambiguous, and likely to change.
|
|
54
|
+
*
|
|
55
|
+
* @see {@link https://github.com/getodk/web-forms/issues/295}
|
|
56
|
+
*/
|
|
57
|
+
type TempBlankValueState = readonly [];
|
|
58
|
+
const isBlankValueState = (values: readonly string[]): values is TempBlankValueState => {
|
|
59
|
+
return values.length === 0;
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
export class RankControl
|
|
63
|
+
extends ValueNode<'string', RankDefinition<'string'>, readonly string[], readonly string[]>
|
|
64
|
+
implements
|
|
65
|
+
RankNode,
|
|
66
|
+
XFormsXPathElement,
|
|
67
|
+
EvaluationContext,
|
|
68
|
+
ValidationContext,
|
|
69
|
+
ClientReactiveSubmittableValueNode
|
|
70
|
+
{
|
|
71
|
+
static from(parent: GeneralParentNode, definition: RankDefinition): RankControl;
|
|
72
|
+
static from(parent: GeneralParentNode, definition: AnyRankDefinition): RankControl {
|
|
73
|
+
assertRankNodeDefinition(definition);
|
|
74
|
+
return new this(parent, definition);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
private readonly mapOptionsByValue: Accessor<RankItemMap>;
|
|
78
|
+
|
|
79
|
+
protected override readonly getInstanceValue: Accessor<string>;
|
|
80
|
+
|
|
81
|
+
// XFormsXPathElement
|
|
82
|
+
override readonly [XPathNodeKindKey] = 'element';
|
|
83
|
+
|
|
84
|
+
// InstanceNode
|
|
85
|
+
protected readonly state: SharedNodeState<RankControlStateSpec>;
|
|
86
|
+
protected readonly engineState: EngineState<RankControlStateSpec>;
|
|
87
|
+
|
|
88
|
+
// RankNode
|
|
89
|
+
readonly nodeType = 'rank';
|
|
90
|
+
readonly appearances: UnknownAppearanceDefinition;
|
|
91
|
+
readonly nodeOptions = null;
|
|
92
|
+
readonly currentState: CurrentState<RankControlStateSpec>;
|
|
93
|
+
|
|
94
|
+
private constructor(parent: GeneralParentNode, definition: RankDefinition<'string'>) {
|
|
95
|
+
const codec = new MultipleValueItemCodec(sharedValueCodecs.string);
|
|
96
|
+
super(parent, definition, codec);
|
|
97
|
+
|
|
98
|
+
this.appearances = definition.bodyElement.appearances;
|
|
99
|
+
|
|
100
|
+
const valueOptions = createItemCollection(this);
|
|
101
|
+
const mapOptionsByValue: Accessor<RankItemMap> = this.scope.runTask(() => {
|
|
102
|
+
return createMemo(() => {
|
|
103
|
+
return new Map(valueOptions().map((item) => [item.value, item]));
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
this.mapOptionsByValue = mapOptionsByValue;
|
|
108
|
+
|
|
109
|
+
const baseValueState = this.valueState;
|
|
110
|
+
const [baseGetValue, setValue] = baseValueState;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @ToDo As new value options become available, they're not yet in the
|
|
114
|
+
* `currentValues` state. This appends them. We intend to change this
|
|
115
|
+
* behavior, likely clearing the previous state instead.
|
|
116
|
+
*
|
|
117
|
+
* However, there's an open question about what we should do when a filter
|
|
118
|
+
* change **only removes values**.
|
|
119
|
+
*/
|
|
120
|
+
const getValue = this.scope.runTask(() => {
|
|
121
|
+
return createMemo(() => {
|
|
122
|
+
const options = valueOptions();
|
|
123
|
+
const values = baseGetValue();
|
|
124
|
+
|
|
125
|
+
if (isBlankValueState(values)) {
|
|
126
|
+
return values;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const optionValues = new Set(options.map((option) => option.value));
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* @see {@link getValue} ToDo paragraph 2.
|
|
133
|
+
*/
|
|
134
|
+
const currentValues = values.filter((value) => optionValues.has(value));
|
|
135
|
+
|
|
136
|
+
return Array.from(
|
|
137
|
+
new Set([
|
|
138
|
+
...currentValues,
|
|
139
|
+
/**
|
|
140
|
+
* @see {@link getValue} ToDo paragraph 1.
|
|
141
|
+
*/
|
|
142
|
+
...optionValues,
|
|
143
|
+
])
|
|
144
|
+
);
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
const valueState: SimpleAtomicState<readonly string[]> = [getValue, setValue];
|
|
148
|
+
|
|
149
|
+
this.getInstanceValue = this.scope.runTask(() => {
|
|
150
|
+
return createMemo(() => codec.encodeValue(getValue()));
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
const sharedStateOptions = {
|
|
154
|
+
clientStateFactory: this.engineConfig.stateFactory,
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
const state = createSharedNodeState(
|
|
158
|
+
this.scope,
|
|
159
|
+
{
|
|
160
|
+
reference: this.contextReference,
|
|
161
|
+
readonly: this.isReadonly,
|
|
162
|
+
relevant: this.isRelevant,
|
|
163
|
+
required: this.isRequired,
|
|
164
|
+
label: createNodeLabel(this, definition),
|
|
165
|
+
hint: createFieldHint(this, definition),
|
|
166
|
+
children: null,
|
|
167
|
+
valueOptions,
|
|
168
|
+
value: valueState,
|
|
169
|
+
instanceValue: this.getInstanceValue,
|
|
170
|
+
},
|
|
171
|
+
sharedStateOptions
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
this.state = state;
|
|
175
|
+
this.engineState = state.engineState;
|
|
176
|
+
this.currentState = state.currentState;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
getValueLabel(value: string): TextRange<'item-label'> | null {
|
|
180
|
+
const valueOption = this.currentState.valueOptions.find((item) => item.value === value);
|
|
181
|
+
return valueOption?.label ?? null;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
setValues(valuesInOrder: readonly string[]): Root {
|
|
185
|
+
if (isBlankValueState(valuesInOrder)) {
|
|
186
|
+
this.setValueState(valuesInOrder);
|
|
187
|
+
return this.root;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
const sourceValues: string[] = Array.from(this.mapOptionsByValue().keys());
|
|
191
|
+
const hasAllValues = sourceValues.every((sourceValue) => valuesInOrder.includes(sourceValue));
|
|
192
|
+
if (!hasAllValues) {
|
|
193
|
+
throw new RankMissingValueError('There are missing options. Rank should have all options.');
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
this.setValueState(valuesInOrder);
|
|
197
|
+
return this.root;
|
|
198
|
+
}
|
|
199
|
+
}
|