@cohesivesystems/presentation-react 0.1.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/dist/collection-chrome-slot-renderer-registry.d.ts +12 -0
- package/dist/collection-chrome-slot-renderer-registry.d.ts.map +1 -0
- package/dist/collection-chrome-slot-renderer-registry.js +12 -0
- package/dist/collection-chrome-slot-renderer-registry.js.map +1 -0
- package/dist/collection-selection-state-context.d.ts +6 -0
- package/dist/collection-selection-state-context.d.ts.map +1 -0
- package/dist/collection-selection-state-context.js +25 -0
- package/dist/collection-selection-state-context.js.map +1 -0
- package/dist/collection-selection-state.d.ts +3 -0
- package/dist/collection-selection-state.d.ts.map +1 -0
- package/dist/collection-selection-state.js +52 -0
- package/dist/collection-selection-state.js.map +1 -0
- package/dist/document-workspace-runtime.d.ts +262 -0
- package/dist/document-workspace-runtime.d.ts.map +1 -0
- package/dist/document-workspace-runtime.js +699 -0
- package/dist/document-workspace-runtime.js.map +1 -0
- package/dist/index.d.ts +51 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +51 -0
- package/dist/index.js.map +1 -0
- package/dist/input-form-endpoint-runtime.d.ts +140 -0
- package/dist/input-form-endpoint-runtime.d.ts.map +1 -0
- package/dist/input-form-endpoint-runtime.js +280 -0
- package/dist/input-form-endpoint-runtime.js.map +1 -0
- package/dist/local-flow-state-data-source-projection.d.ts +21 -0
- package/dist/local-flow-state-data-source-projection.d.ts.map +1 -0
- package/dist/local-flow-state-data-source-projection.js +65 -0
- package/dist/local-flow-state-data-source-projection.js.map +1 -0
- package/dist/navigation-runtime-context.d.ts +22 -0
- package/dist/navigation-runtime-context.d.ts.map +1 -0
- package/dist/navigation-runtime-context.js +23 -0
- package/dist/navigation-runtime-context.js.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts +20 -0
- package/dist/navigation-shell-frame-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-frame-renderer-registry.js +9 -0
- package/dist/navigation-shell-frame-renderer-registry.js.map +1 -0
- package/dist/navigation-shell-region-component-registry.d.ts +50 -0
- package/dist/navigation-shell-region-component-registry.d.ts.map +1 -0
- package/dist/navigation-shell-region-component-registry.js +44 -0
- package/dist/navigation-shell-region-component-registry.js.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts +22 -0
- package/dist/navigation-shell-slot-renderer-registry.d.ts.map +1 -0
- package/dist/navigation-shell-slot-renderer-registry.js +9 -0
- package/dist/navigation-shell-slot-renderer-registry.js.map +1 -0
- package/dist/page-host-projection.d.ts +127 -0
- package/dist/page-host-projection.d.ts.map +1 -0
- package/dist/page-host-projection.js +59 -0
- package/dist/page-host-projection.js.map +1 -0
- package/dist/page-host-renderer-registry.d.ts +72 -0
- package/dist/page-host-renderer-registry.d.ts.map +1 -0
- package/dist/page-host-renderer-registry.js +63 -0
- package/dist/page-host-renderer-registry.js.map +1 -0
- package/dist/presentation-action-group-runtime-options.d.ts +36 -0
- package/dist/presentation-action-group-runtime-options.d.ts.map +1 -0
- package/dist/presentation-action-group-runtime-options.js +50 -0
- package/dist/presentation-action-group-runtime-options.js.map +1 -0
- package/dist/presentation-action-runtime.d.ts +52 -0
- package/dist/presentation-action-runtime.d.ts.map +1 -0
- package/dist/presentation-action-runtime.js +78 -0
- package/dist/presentation-action-runtime.js.map +1 -0
- package/dist/presentation-data-source-binding-runtime.d.ts +3 -0
- package/dist/presentation-data-source-binding-runtime.d.ts.map +1 -0
- package/dist/presentation-data-source-binding-runtime.js +65 -0
- package/dist/presentation-data-source-binding-runtime.js.map +1 -0
- package/dist/presentation-data-source-binding.d.ts +12 -0
- package/dist/presentation-data-source-binding.d.ts.map +1 -0
- package/dist/presentation-data-source-binding.js +13 -0
- package/dist/presentation-data-source-binding.js.map +1 -0
- package/dist/presentation-flow-runtime.d.ts +139 -0
- package/dist/presentation-flow-runtime.d.ts.map +1 -0
- package/dist/presentation-flow-runtime.js +514 -0
- package/dist/presentation-flow-runtime.js.map +1 -0
- package/dist/presentation-module-context.d.ts +4 -0
- package/dist/presentation-module-context.d.ts.map +1 -0
- package/dist/presentation-module-context.js +6 -0
- package/dist/presentation-module-context.js.map +1 -0
- package/dist/presentation-module-provider.d.ts +7 -0
- package/dist/presentation-module-provider.d.ts.map +1 -0
- package/dist/presentation-module-provider.js +7 -0
- package/dist/presentation-module-provider.js.map +1 -0
- package/dist/presentation-projection-diagnostics-context.d.ts +8 -0
- package/dist/presentation-projection-diagnostics-context.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-context.js +3 -0
- package/dist/presentation-projection-diagnostics-context.js.map +1 -0
- package/dist/presentation-projection-diagnostics-hooks.d.ts +4 -0
- package/dist/presentation-projection-diagnostics-hooks.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-hooks.js +17 -0
- package/dist/presentation-projection-diagnostics-hooks.js.map +1 -0
- package/dist/presentation-projection-diagnostics-runtime.d.ts +12 -0
- package/dist/presentation-projection-diagnostics-runtime.d.ts.map +1 -0
- package/dist/presentation-projection-diagnostics-runtime.js +54 -0
- package/dist/presentation-projection-diagnostics-runtime.js.map +1 -0
- package/dist/presentation-projection-trace.d.ts +27 -0
- package/dist/presentation-projection-trace.d.ts.map +1 -0
- package/dist/presentation-projection-trace.js +54 -0
- package/dist/presentation-projection-trace.js.map +1 -0
- package/dist/presentation-query-form-runtime.d.ts +30 -0
- package/dist/presentation-query-form-runtime.d.ts.map +1 -0
- package/dist/presentation-query-form-runtime.js +75 -0
- package/dist/presentation-query-form-runtime.js.map +1 -0
- package/dist/presentation-query-form-state-adapter-registry.d.ts +4 -0
- package/dist/presentation-query-form-state-adapter-registry.d.ts.map +1 -0
- package/dist/presentation-query-form-state-adapter-registry.js +13 -0
- package/dist/presentation-query-form-state-adapter-registry.js.map +1 -0
- package/dist/presentation-query-form-state-context.d.ts +20 -0
- package/dist/presentation-query-form-state-context.d.ts.map +1 -0
- package/dist/presentation-query-form-state-context.js +20 -0
- package/dist/presentation-query-form-state-context.js.map +1 -0
- package/dist/presentation-query-form-state.d.ts +29 -0
- package/dist/presentation-query-form-state.d.ts.map +1 -0
- package/dist/presentation-query-form-state.js +99 -0
- package/dist/presentation-query-form-state.js.map +1 -0
- package/dist/presentation-renderer-registry.d.ts +109 -0
- package/dist/presentation-renderer-registry.d.ts.map +1 -0
- package/dist/presentation-renderer-registry.js +25 -0
- package/dist/presentation-renderer-registry.js.map +1 -0
- package/dist/presentation-standards-context.d.ts +4 -0
- package/dist/presentation-standards-context.d.ts.map +1 -0
- package/dist/presentation-standards-context.js +12 -0
- package/dist/presentation-standards-context.js.map +1 -0
- package/dist/presentation-standards-provider.d.ts +14 -0
- package/dist/presentation-standards-provider.d.ts.map +1 -0
- package/dist/presentation-standards-provider.js +16 -0
- package/dist/presentation-standards-provider.js.map +1 -0
- package/dist/projected-document-action-runtime-bindings.d.ts +20 -0
- package/dist/projected-document-action-runtime-bindings.d.ts.map +1 -0
- package/dist/projected-document-action-runtime-bindings.js +88 -0
- package/dist/projected-document-action-runtime-bindings.js.map +1 -0
- package/dist/projected-document-action-runtime.d.ts +76 -0
- package/dist/projected-document-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-action-runtime.js +224 -0
- package/dist/projected-document-action-runtime.js.map +1 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.d.ts +26 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.d.ts.map +1 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.js +106 -0
- package/dist/projected-document-process-preview-action-runtime-bindings.js.map +1 -0
- package/dist/projected-document-process-preview-action-runtime.d.ts +321 -0
- package/dist/projected-document-process-preview-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-process-preview-action-runtime.js +729 -0
- package/dist/projected-document-process-preview-action-runtime.js.map +1 -0
- package/dist/projected-document-process-preview-capability-runtime.d.ts +47 -0
- package/dist/projected-document-process-preview-capability-runtime.d.ts.map +1 -0
- package/dist/projected-document-process-preview-capability-runtime.js +49 -0
- package/dist/projected-document-process-preview-capability-runtime.js.map +1 -0
- package/dist/projected-document-workspace-action-runtime.d.ts +87 -0
- package/dist/projected-document-workspace-action-runtime.d.ts.map +1 -0
- package/dist/projected-document-workspace-action-runtime.js +150 -0
- package/dist/projected-document-workspace-action-runtime.js.map +1 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts +18 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.d.ts.map +1 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.js +207 -0
- package/dist/projected-document-workspace-projection-renderer-diagnostics.js.map +1 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts +19 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.d.ts.map +1 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.js +124 -0
- package/dist/projected-document-workspace-runtime-binding-diagnostics.js.map +1 -0
- package/dist/projected-navigation-provider.d.ts +16 -0
- package/dist/projected-navigation-provider.d.ts.map +1 -0
- package/dist/projected-navigation-provider.js +51 -0
- package/dist/projected-navigation-provider.js.map +1 -0
- package/dist/projected-presentation-flow-host.d.ts +16 -0
- package/dist/projected-presentation-flow-host.d.ts.map +1 -0
- package/dist/projected-presentation-flow-host.js +14 -0
- package/dist/projected-presentation-flow-host.js.map +1 -0
- package/dist/projected-query-form-state-adapter.d.ts +12 -0
- package/dist/projected-query-form-state-adapter.d.ts.map +1 -0
- package/dist/projected-query-form-state-adapter.js +361 -0
- package/dist/projected-query-form-state-adapter.js.map +1 -0
- package/dist/react-router-binding.d.ts +133 -0
- package/dist/react-router-binding.d.ts.map +1 -0
- package/dist/react-router-binding.js +76 -0
- package/dist/react-router-binding.js.map +1 -0
- package/dist/react-router-path.d.ts +4 -0
- package/dist/react-router-path.d.ts.map +1 -0
- package/dist/react-router-path.js +11 -0
- package/dist/react-router-path.js.map +1 -0
- package/dist/scope-selection-context.d.ts +28 -0
- package/dist/scope-selection-context.d.ts.map +1 -0
- package/dist/scope-selection-context.js +13 -0
- package/dist/scope-selection-context.js.map +1 -0
- package/dist/scope-selection-provider.d.ts +33 -0
- package/dist/scope-selection-provider.d.ts.map +1 -0
- package/dist/scope-selection-provider.js +162 -0
- package/dist/scope-selection-provider.js.map +1 -0
- package/dist/scope-selection-request.d.ts +6 -0
- package/dist/scope-selection-request.d.ts.map +1 -0
- package/dist/scope-selection-request.js +12 -0
- package/dist/scope-selection-request.js.map +1 -0
- package/dist/standard-navigation-shell-frame-renderers.d.ts +15 -0
- package/dist/standard-navigation-shell-frame-renderers.d.ts.map +1 -0
- package/dist/standard-navigation-shell-frame-renderers.js +22 -0
- package/dist/standard-navigation-shell-frame-renderers.js.map +1 -0
- package/dist/standard-navigation-shell-slot-renderers.d.ts +59 -0
- package/dist/standard-navigation-shell-slot-renderers.d.ts.map +1 -0
- package/dist/standard-navigation-shell-slot-renderers.js +67 -0
- package/dist/standard-navigation-shell-slot-renderers.js.map +1 -0
- package/dist/view-chrome-slot-renderer-registry.d.ts +12 -0
- package/dist/view-chrome-slot-renderer-registry.d.ts.map +1 -0
- package/dist/view-chrome-slot-renderer-registry.js +12 -0
- package/dist/view-chrome-slot-renderer-registry.js.map +1 -0
- package/package.json +60 -0
- package/src/collection-chrome-slot-renderer-registry.ts +66 -0
- package/src/collection-selection-state-context.ts +51 -0
- package/src/collection-selection-state.tsx +101 -0
- package/src/document-workspace-runtime.tsx +1505 -0
- package/src/index.ts +50 -0
- package/src/input-form-endpoint-runtime.ts +632 -0
- package/src/local-flow-state-data-source-projection.ts +133 -0
- package/src/navigation-runtime-context.ts +40 -0
- package/src/navigation-shell-frame-renderer-registry.ts +54 -0
- package/src/navigation-shell-region-component-registry.tsx +127 -0
- package/src/navigation-shell-slot-renderer-registry.ts +88 -0
- package/src/page-host-projection.ts +356 -0
- package/src/page-host-renderer-registry.tsx +353 -0
- package/src/presentation-action-group-runtime-options.ts +121 -0
- package/src/presentation-action-runtime.ts +190 -0
- package/src/presentation-data-source-binding-runtime.ts +109 -0
- package/src/presentation-data-source-binding.tsx +24 -0
- package/src/presentation-flow-runtime.tsx +835 -0
- package/src/presentation-module-context.ts +10 -0
- package/src/presentation-module-provider.tsx +19 -0
- package/src/presentation-projection-diagnostics-context.ts +17 -0
- package/src/presentation-projection-diagnostics-hooks.ts +29 -0
- package/src/presentation-projection-diagnostics-runtime.tsx +95 -0
- package/src/presentation-projection-trace.ts +117 -0
- package/src/presentation-query-form-runtime.ts +148 -0
- package/src/presentation-query-form-state-adapter-registry.ts +25 -0
- package/src/presentation-query-form-state-context.ts +56 -0
- package/src/presentation-query-form-state.tsx +250 -0
- package/src/presentation-renderer-registry.ts +214 -0
- package/src/presentation-standards-context.ts +21 -0
- package/src/presentation-standards-provider.tsx +44 -0
- package/src/projected-document-action-runtime-bindings.ts +132 -0
- package/src/projected-document-action-runtime.ts +414 -0
- package/src/projected-document-process-preview-action-runtime-bindings.ts +231 -0
- package/src/projected-document-process-preview-action-runtime.ts +1725 -0
- package/src/projected-document-process-preview-capability-runtime.ts +216 -0
- package/src/projected-document-workspace-action-runtime.ts +402 -0
- package/src/projected-document-workspace-projection-renderer-diagnostics.ts +342 -0
- package/src/projected-document-workspace-runtime-binding-diagnostics.ts +208 -0
- package/src/projected-navigation-provider.tsx +104 -0
- package/src/projected-presentation-flow-host.tsx +46 -0
- package/src/projected-query-form-state-adapter.ts +578 -0
- package/src/react-router-binding.tsx +417 -0
- package/src/react-router-path.ts +16 -0
- package/src/scope-selection-context.ts +58 -0
- package/src/scope-selection-provider.tsx +324 -0
- package/src/scope-selection-request.ts +21 -0
- package/src/standard-navigation-shell-frame-renderers.tsx +106 -0
- package/src/standard-navigation-shell-slot-renderers.tsx +289 -0
- package/src/view-chrome-slot-renderer-registry.ts +66 -0
|
@@ -0,0 +1,578 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
InputFormDefinition,
|
|
3
|
+
InputFormFieldDefinition,
|
|
4
|
+
PresentationValueDefinition,
|
|
5
|
+
} from '@cohesivesystems/presentation-core'
|
|
6
|
+
import type {
|
|
7
|
+
PresentationQueryFormStateAdapter,
|
|
8
|
+
PresentationQueryFormStateAdapterContext,
|
|
9
|
+
} from './presentation-query-form-state'
|
|
10
|
+
import {
|
|
11
|
+
createQueryFormUrlFields,
|
|
12
|
+
createQueryFormUrlSearch,
|
|
13
|
+
createQueryFormUrlSearchKey,
|
|
14
|
+
readObjectPath,
|
|
15
|
+
readQueryFormUrlValue,
|
|
16
|
+
type QueryFormUrlFieldCodecs,
|
|
17
|
+
writeObjectPath,
|
|
18
|
+
} from '@cohesivesystems/presentation-core'
|
|
19
|
+
import {
|
|
20
|
+
createPresentationEnumDiscriminator,
|
|
21
|
+
matchesPresentationEnum,
|
|
22
|
+
} from '@cohesivesystems/presentation-core'
|
|
23
|
+
import {
|
|
24
|
+
inputFormChoiceDefaultSelections,
|
|
25
|
+
inputFormFieldControlKinds,
|
|
26
|
+
inputFormFieldKinds,
|
|
27
|
+
presentationValueKinds,
|
|
28
|
+
} from '@cohesivesystems/presentation-contracts'
|
|
29
|
+
import {
|
|
30
|
+
createDefaultDateTimeFilter,
|
|
31
|
+
isDateTimePreset,
|
|
32
|
+
normalizeDateTimeFilter,
|
|
33
|
+
type DateTimeFilterValue,
|
|
34
|
+
} from '@cohesivesystems/presentation-core'
|
|
35
|
+
|
|
36
|
+
type ProjectedQueryFormValue = Record<string, unknown>
|
|
37
|
+
|
|
38
|
+
const dateTimeRangeParamValue = 'range'
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Creates the default frontend interpretation for an IR-declared query form.
|
|
42
|
+
*
|
|
43
|
+
* The adapter derives draft/applied state shape, normalization, and URL state
|
|
44
|
+
* from the query form's backing input-form fields. Targets can still override a
|
|
45
|
+
* query form by registering an adapter with the same query form id.
|
|
46
|
+
*/
|
|
47
|
+
export function createProjectedQueryFormStateAdapter(
|
|
48
|
+
queryFormId: string,
|
|
49
|
+
): PresentationQueryFormStateAdapter<ProjectedQueryFormValue> {
|
|
50
|
+
return {
|
|
51
|
+
createAppliedSearch: ({
|
|
52
|
+
choiceValuesByFieldId,
|
|
53
|
+
inputForm,
|
|
54
|
+
queryForm,
|
|
55
|
+
search,
|
|
56
|
+
value,
|
|
57
|
+
}) =>
|
|
58
|
+
createQueryFormUrlSearch({
|
|
59
|
+
allValuesByFieldId: choiceValuesByFieldId,
|
|
60
|
+
defaultValue: createProjectedQueryFormDefaultValue({
|
|
61
|
+
choiceValuesByFieldId,
|
|
62
|
+
inputForm,
|
|
63
|
+
}),
|
|
64
|
+
fieldCodecs: createProjectedQueryFormUrlFieldCodecs(inputForm),
|
|
65
|
+
fields: createQueryFormUrlFields(inputForm, queryForm),
|
|
66
|
+
queryForm,
|
|
67
|
+
search,
|
|
68
|
+
value: normalizeProjectedQueryFormValue({
|
|
69
|
+
choiceValuesByFieldId,
|
|
70
|
+
inputForm,
|
|
71
|
+
value,
|
|
72
|
+
}),
|
|
73
|
+
}),
|
|
74
|
+
createDefaultValue: (context) =>
|
|
75
|
+
createProjectedQueryFormDefaultValue(context),
|
|
76
|
+
createSearchKey: ({
|
|
77
|
+
choiceValuesByFieldId = {},
|
|
78
|
+
inputForm,
|
|
79
|
+
queryForm,
|
|
80
|
+
search,
|
|
81
|
+
}) =>
|
|
82
|
+
createQueryFormUrlSearchKey({
|
|
83
|
+
allValuesByFieldId: choiceValuesByFieldId,
|
|
84
|
+
defaultValue: createProjectedQueryFormDefaultValue({
|
|
85
|
+
choiceValuesByFieldId,
|
|
86
|
+
inputForm,
|
|
87
|
+
}),
|
|
88
|
+
fieldCodecs: createProjectedQueryFormUrlFieldCodecs(inputForm),
|
|
89
|
+
fields: createQueryFormUrlFields(inputForm, queryForm),
|
|
90
|
+
queryForm,
|
|
91
|
+
search,
|
|
92
|
+
}),
|
|
93
|
+
normalizeValue: ({ choiceValuesByFieldId, inputForm, value }) =>
|
|
94
|
+
normalizeProjectedQueryFormValue({
|
|
95
|
+
choiceValuesByFieldId,
|
|
96
|
+
inputForm,
|
|
97
|
+
value,
|
|
98
|
+
}),
|
|
99
|
+
queryFormId,
|
|
100
|
+
readValueFromSearch: ({
|
|
101
|
+
choiceValuesByFieldId = {},
|
|
102
|
+
inputForm,
|
|
103
|
+
queryForm,
|
|
104
|
+
search,
|
|
105
|
+
}) =>
|
|
106
|
+
normalizeProjectedQueryFormValue({
|
|
107
|
+
choiceValuesByFieldId,
|
|
108
|
+
inputForm,
|
|
109
|
+
value: readQueryFormUrlValue({
|
|
110
|
+
defaultValue: createProjectedQueryFormDefaultValue({
|
|
111
|
+
choiceValuesByFieldId,
|
|
112
|
+
inputForm,
|
|
113
|
+
}),
|
|
114
|
+
fieldCodecs: createProjectedQueryFormUrlFieldCodecs(inputForm),
|
|
115
|
+
fields: createQueryFormUrlFields(inputForm, queryForm),
|
|
116
|
+
queryForm,
|
|
117
|
+
search,
|
|
118
|
+
}),
|
|
119
|
+
}),
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function createProjectedQueryFormDefaultValue({
|
|
124
|
+
choiceValuesByFieldId = {},
|
|
125
|
+
inputForm,
|
|
126
|
+
}: Pick<
|
|
127
|
+
PresentationQueryFormStateAdapterContext,
|
|
128
|
+
'choiceValuesByFieldId' | 'inputForm'
|
|
129
|
+
>): ProjectedQueryFormValue {
|
|
130
|
+
if (!inputForm) {
|
|
131
|
+
return {}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const value: ProjectedQueryFormValue = {}
|
|
135
|
+
for (const field of inputForm.Fields) {
|
|
136
|
+
writeObjectPath(
|
|
137
|
+
value,
|
|
138
|
+
field.ValuePath,
|
|
139
|
+
createDefaultInputFormFieldValue(
|
|
140
|
+
field,
|
|
141
|
+
readChoiceValues(choiceValuesByFieldId, field),
|
|
142
|
+
),
|
|
143
|
+
)
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
return applyLiteralInputFormDefaultValues(inputForm, value)
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function normalizeProjectedQueryFormValue({
|
|
150
|
+
choiceValuesByFieldId,
|
|
151
|
+
inputForm,
|
|
152
|
+
value,
|
|
153
|
+
}: {
|
|
154
|
+
readonly choiceValuesByFieldId: Readonly<Record<string, readonly string[]>>
|
|
155
|
+
readonly inputForm: InputFormDefinition | null
|
|
156
|
+
readonly value: ProjectedQueryFormValue
|
|
157
|
+
}) {
|
|
158
|
+
if (!inputForm) {
|
|
159
|
+
return value
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const nextValue = clonePlainObject(value)
|
|
163
|
+
for (const field of inputForm.Fields) {
|
|
164
|
+
const choiceValues = readChoiceValues(choiceValuesByFieldId, field)
|
|
165
|
+
const currentValue = readObjectPath(nextValue, field.ValuePath)
|
|
166
|
+
writeObjectPath(
|
|
167
|
+
nextValue,
|
|
168
|
+
field.ValuePath,
|
|
169
|
+
normalizeInputFormFieldValue(field, currentValue, choiceValues),
|
|
170
|
+
)
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return nextValue
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
function createDefaultInputFormFieldValue(
|
|
177
|
+
field: InputFormFieldDefinition,
|
|
178
|
+
choiceValues: readonly string[],
|
|
179
|
+
): unknown {
|
|
180
|
+
if (isInputFormFieldKind(field, 'multiSelect', 'MultiSelect')) {
|
|
181
|
+
return createDefaultChoiceSelection(field, choiceValues)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
if (isInputFormFieldKind(field, 'select', 'Select')) {
|
|
185
|
+
return createDefaultSingleChoice(field, choiceValues)
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (isInputFormFieldKind(field, 'dateTimeRange', 'DateTimeRange')) {
|
|
189
|
+
return isDateTimeFilterControl(field)
|
|
190
|
+
? createDefaultDateTimeFilter()
|
|
191
|
+
: { after: null, before: null }
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
if (isInputFormFieldKind(field, 'number', 'Number')) {
|
|
195
|
+
return readDefaultNumber(field.DefaultValue)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
if (isInputFormFieldKind(field, 'numberRange', 'NumberRange')) {
|
|
199
|
+
return { maximum: null, minimum: null }
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (isInputFormFieldKind(field, 'boolean', 'Boolean')) {
|
|
203
|
+
return field.DefaultValue === 'true'
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return field.DefaultValue ?? ''
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function normalizeInputFormFieldValue(
|
|
210
|
+
field: InputFormFieldDefinition,
|
|
211
|
+
value: unknown,
|
|
212
|
+
choiceValues: readonly string[],
|
|
213
|
+
): unknown {
|
|
214
|
+
if (isInputFormFieldKind(field, 'multiSelect', 'MultiSelect')) {
|
|
215
|
+
const selectedValues = normalizeStringSet(value)
|
|
216
|
+
const availableValues = normalizeStringSet(choiceValues)
|
|
217
|
+
const availableSet = new Set(availableValues)
|
|
218
|
+
const visibleSelectedValues = availableSet.size > 0
|
|
219
|
+
? selectedValues.filter((selectedValue) => availableSet.has(selectedValue))
|
|
220
|
+
: selectedValues
|
|
221
|
+
|
|
222
|
+
return visibleSelectedValues.length > 0
|
|
223
|
+
? visibleSelectedValues
|
|
224
|
+
: createDefaultChoiceSelection(field, availableValues)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
if (isInputFormFieldKind(field, 'select', 'Select')) {
|
|
228
|
+
const selectedValue = typeof value === 'string' ? value.trim() : ''
|
|
229
|
+
const availableValues = normalizeStringSet(choiceValues)
|
|
230
|
+
return selectedValue && (availableValues.length === 0 || availableValues.includes(selectedValue))
|
|
231
|
+
? selectedValue
|
|
232
|
+
: createDefaultSingleChoice(field, availableValues)
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (isInputFormFieldKind(field, 'dateTimeRange', 'DateTimeRange')) {
|
|
236
|
+
return isDateTimeFilterControl(field)
|
|
237
|
+
? coerceDateTimeFilterValue(value)
|
|
238
|
+
: normalizePlainDateTimeRange(value)
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (isInputFormFieldKind(field, 'dateTime', 'DateTime') ||
|
|
242
|
+
isInputFormFieldKind(field, 'date', 'Date')) {
|
|
243
|
+
return typeof value === 'string' ? value.trim() : ''
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (isInputFormFieldKind(field, 'number', 'Number')) {
|
|
247
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
248
|
+
? value
|
|
249
|
+
: readDefaultNumber(field.DefaultValue)
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if (isInputFormFieldKind(field, 'numberRange', 'NumberRange')) {
|
|
253
|
+
return normalizeNumberRange(value)
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
if (isInputFormFieldKind(field, 'boolean', 'Boolean')) {
|
|
257
|
+
return value === true
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
return typeof value === 'string' ? value.trim() : field.DefaultValue ?? ''
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function createProjectedQueryFormUrlFieldCodecs(
|
|
264
|
+
inputForm: InputFormDefinition | null,
|
|
265
|
+
): QueryFormUrlFieldCodecs<ProjectedQueryFormValue> {
|
|
266
|
+
if (!inputForm) {
|
|
267
|
+
return {}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
return Object.fromEntries(
|
|
271
|
+
inputForm.Fields
|
|
272
|
+
.filter((field) =>
|
|
273
|
+
isInputFormFieldKind(field, 'dateTimeRange', 'DateTimeRange') &&
|
|
274
|
+
isDateTimeFilterControl(field)
|
|
275
|
+
)
|
|
276
|
+
.map((field) => [
|
|
277
|
+
field.Id,
|
|
278
|
+
{
|
|
279
|
+
deleteParams: ({ key, params }) =>
|
|
280
|
+
deleteDateTimeFilterParams(params, key),
|
|
281
|
+
read: ({ defaultFieldValue, key, params }) =>
|
|
282
|
+
readDateTimeFilterParams(
|
|
283
|
+
params,
|
|
284
|
+
key,
|
|
285
|
+
coerceDateTimeFilterValue(defaultFieldValue),
|
|
286
|
+
),
|
|
287
|
+
write: ({ fieldValue, key, params }) =>
|
|
288
|
+
writeDateTimeFilterParams(
|
|
289
|
+
params,
|
|
290
|
+
key,
|
|
291
|
+
coerceDateTimeFilterValue(fieldValue),
|
|
292
|
+
),
|
|
293
|
+
},
|
|
294
|
+
]),
|
|
295
|
+
) satisfies QueryFormUrlFieldCodecs<ProjectedQueryFormValue>
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function readDateTimeFilterParams(
|
|
299
|
+
params: URLSearchParams,
|
|
300
|
+
key: string,
|
|
301
|
+
defaults: DateTimeFilterValue,
|
|
302
|
+
): DateTimeFilterValue {
|
|
303
|
+
const value = params.get(key)?.trim() ?? ''
|
|
304
|
+
const timezone = params.get(createDateTimeFilterParam(key, 'tz'))?.trim() || defaults.timezone
|
|
305
|
+
|
|
306
|
+
if (value === dateTimeRangeParamValue) {
|
|
307
|
+
return normalizeDateTimeFilter({
|
|
308
|
+
...defaults,
|
|
309
|
+
afterLocal: params.get(createDateTimeFilterParam(key, 'after'))?.trim() ?? '',
|
|
310
|
+
beforeLocal: params.get(createDateTimeFilterParam(key, 'before'))?.trim() ?? '',
|
|
311
|
+
mode: 'range',
|
|
312
|
+
timezone,
|
|
313
|
+
})
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
if (value && isDateTimePreset(value)) {
|
|
317
|
+
return normalizeDateTimeFilter({
|
|
318
|
+
...defaults,
|
|
319
|
+
mode: 'preset',
|
|
320
|
+
preset: value,
|
|
321
|
+
timezone,
|
|
322
|
+
})
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return defaults
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function writeDateTimeFilterParams(
|
|
329
|
+
params: URLSearchParams,
|
|
330
|
+
key: string,
|
|
331
|
+
value: DateTimeFilterValue,
|
|
332
|
+
) {
|
|
333
|
+
const normalizedValue = normalizeDateTimeFilter(value)
|
|
334
|
+
|
|
335
|
+
if (normalizedValue.mode === 'range') {
|
|
336
|
+
params.set(key, dateTimeRangeParamValue)
|
|
337
|
+
writeStringParam(params, createDateTimeFilterParam(key, 'after'), normalizedValue.afterLocal)
|
|
338
|
+
writeStringParam(params, createDateTimeFilterParam(key, 'before'), normalizedValue.beforeLocal)
|
|
339
|
+
writeStringParam(params, createDateTimeFilterParam(key, 'tz'), normalizedValue.timezone)
|
|
340
|
+
return
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
if (normalizedValue.preset !== 'today') {
|
|
344
|
+
params.set(key, normalizedValue.preset)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
function deleteDateTimeFilterParams(params: URLSearchParams, key: string) {
|
|
349
|
+
params.delete(key)
|
|
350
|
+
params.delete(createDateTimeFilterParam(key, 'after'))
|
|
351
|
+
params.delete(createDateTimeFilterParam(key, 'before'))
|
|
352
|
+
params.delete(createDateTimeFilterParam(key, 'tz'))
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function createDateTimeFilterParam(key: string, suffix: 'after' | 'before' | 'tz') {
|
|
356
|
+
return `${key}_${suffix}`
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
function writeStringParam(params: URLSearchParams, key: string, value: string) {
|
|
360
|
+
const trimmedValue = value.trim()
|
|
361
|
+
if (trimmedValue) {
|
|
362
|
+
params.set(key, trimmedValue)
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function createDefaultChoiceSelection(
|
|
367
|
+
field: InputFormFieldDefinition,
|
|
368
|
+
choiceValues: readonly string[],
|
|
369
|
+
) {
|
|
370
|
+
if (isInputFormChoiceDefaultSelection(field, 'all', 'All')) {
|
|
371
|
+
return [...choiceValues]
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (isInputFormChoiceDefaultSelection(field, 'first', 'First')) {
|
|
375
|
+
return choiceValues[0] ? [choiceValues[0]] : []
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
return normalizeStringSet(field.DefaultValue)
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function createDefaultSingleChoice(
|
|
382
|
+
field: InputFormFieldDefinition,
|
|
383
|
+
choiceValues: readonly string[],
|
|
384
|
+
) {
|
|
385
|
+
if (isInputFormChoiceDefaultSelection(field, 'first', 'First')) {
|
|
386
|
+
return choiceValues[0] ?? ''
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
return field.DefaultValue ?? ''
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
function readChoiceValues(
|
|
393
|
+
choiceValuesByFieldId: Readonly<Record<string, readonly string[]>>,
|
|
394
|
+
field: InputFormFieldDefinition,
|
|
395
|
+
) {
|
|
396
|
+
return choiceValuesByFieldId[field.Id] ??
|
|
397
|
+
choiceValuesByFieldId[field.FieldId] ??
|
|
398
|
+
[]
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function coerceDateTimeFilterValue(value: unknown): DateTimeFilterValue {
|
|
402
|
+
const fallback = createDefaultDateTimeFilter()
|
|
403
|
+
if (!value || typeof value !== 'object') {
|
|
404
|
+
return fallback
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
const record = value as Record<string, unknown>
|
|
408
|
+
return normalizeDateTimeFilter({
|
|
409
|
+
afterLocal: readOptionalString(record.afterLocal) || fallback.afterLocal,
|
|
410
|
+
beforeLocal: readOptionalString(record.beforeLocal) || fallback.beforeLocal,
|
|
411
|
+
mode: record.mode === 'range' ? 'range' : 'preset',
|
|
412
|
+
preset: readOptionalString(record.preset) as DateTimeFilterValue['preset'],
|
|
413
|
+
timezone: readOptionalString(record.timezone) || fallback.timezone,
|
|
414
|
+
})
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
function normalizePlainDateTimeRange(value: unknown) {
|
|
418
|
+
const range = value && typeof value === 'object'
|
|
419
|
+
? value as Record<string, unknown>
|
|
420
|
+
: {}
|
|
421
|
+
return {
|
|
422
|
+
after: readOptionalString(range.after) || null,
|
|
423
|
+
before: readOptionalString(range.before) || null,
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
function normalizeNumberRange(value: unknown) {
|
|
428
|
+
const range = value && typeof value === 'object'
|
|
429
|
+
? value as Record<string, unknown>
|
|
430
|
+
: {}
|
|
431
|
+
return {
|
|
432
|
+
maximum: readOptionalNumber(range.maximum),
|
|
433
|
+
minimum: readOptionalNumber(range.minimum),
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
function readDefaultNumber(value: string | null | undefined) {
|
|
438
|
+
return readOptionalNumber(value) ?? null
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
function readOptionalNumber(value: unknown) {
|
|
442
|
+
if (typeof value === 'string' && value.trim() === '') {
|
|
443
|
+
return null
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
const numberValue = typeof value === 'number'
|
|
447
|
+
? value
|
|
448
|
+
: Number(value)
|
|
449
|
+
return Number.isFinite(numberValue) ? numberValue : null
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
function readOptionalString(value: unknown) {
|
|
453
|
+
return typeof value === 'string' ? value : ''
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
function normalizeStringSet(value: unknown) {
|
|
457
|
+
const values = Array.isArray(value) ? value : typeof value === 'string' ? [value] : []
|
|
458
|
+
return Array.from(
|
|
459
|
+
new Set(
|
|
460
|
+
values
|
|
461
|
+
.map((entry) => typeof entry === 'string' ? entry.trim() : '')
|
|
462
|
+
.filter((entry) => entry.length > 0),
|
|
463
|
+
),
|
|
464
|
+
)
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
function applyLiteralInputFormDefaultValues(
|
|
468
|
+
inputForm: InputFormDefinition,
|
|
469
|
+
value: ProjectedQueryFormValue,
|
|
470
|
+
) {
|
|
471
|
+
const defaultValues = inputForm.DefaultValues ?? []
|
|
472
|
+
if (defaultValues.length === 0) {
|
|
473
|
+
return value
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
const target = clonePlainObject(value)
|
|
477
|
+
for (const binding of defaultValues) {
|
|
478
|
+
const resolvedValue = resolveLiteralDefaultValue(binding.Source)
|
|
479
|
+
if ((resolvedValue === null || resolvedValue === undefined) && binding.OmitWhenNull) {
|
|
480
|
+
continue
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
if (resolvedValue !== undefined) {
|
|
484
|
+
writeObjectPath(target, binding.TargetPath, resolvedValue)
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
return target
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
function resolveLiteralDefaultValue(value: PresentationValueDefinition) {
|
|
492
|
+
if (isPresentationValueKind(value.Kind, presentationValueKinds.literal, 'literal')) {
|
|
493
|
+
return parseDefaultValue(value.Literal)
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
return undefined
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
function parseDefaultValue(value: string | null | undefined) {
|
|
500
|
+
if (value === null || value === undefined) {
|
|
501
|
+
return undefined
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
if (value === 'null') {
|
|
505
|
+
return null
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
if (value === 'true') {
|
|
509
|
+
return true
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
if (value === 'false') {
|
|
513
|
+
return false
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
const numberValue = Number(value)
|
|
517
|
+
return Number.isFinite(numberValue) && value.trim() !== ''
|
|
518
|
+
? numberValue
|
|
519
|
+
: value
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
function isInputFormFieldKind(
|
|
523
|
+
field: InputFormFieldDefinition,
|
|
524
|
+
kind: keyof typeof inputFormFieldKinds,
|
|
525
|
+
label: string,
|
|
526
|
+
) {
|
|
527
|
+
return matchesPresentationEnum(
|
|
528
|
+
field.Kind,
|
|
529
|
+
createPresentationEnumDiscriminator(inputFormFieldKinds, kind, label),
|
|
530
|
+
)
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
function isInputFormChoiceDefaultSelection(
|
|
534
|
+
field: InputFormFieldDefinition,
|
|
535
|
+
selection: keyof typeof inputFormChoiceDefaultSelections,
|
|
536
|
+
label: string,
|
|
537
|
+
) {
|
|
538
|
+
const defaultSelection = field.ChoiceSource?.DefaultSelection
|
|
539
|
+
return defaultSelection !== null &&
|
|
540
|
+
defaultSelection !== undefined &&
|
|
541
|
+
matchesPresentationEnum(
|
|
542
|
+
defaultSelection,
|
|
543
|
+
createPresentationEnumDiscriminator(inputFormChoiceDefaultSelections, selection, label),
|
|
544
|
+
)
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
function isDateTimeFilterControl(field: InputFormFieldDefinition) {
|
|
548
|
+
const control = field.Display?.Control
|
|
549
|
+
return control === inputFormFieldControlKinds.dateTimeFilter ||
|
|
550
|
+
control?.toString().toLocaleLowerCase() === 'datetimefilter'
|
|
551
|
+
}
|
|
552
|
+
|
|
553
|
+
function isPresentationValueKind(
|
|
554
|
+
value: unknown,
|
|
555
|
+
numericKind: number,
|
|
556
|
+
stringKind: string,
|
|
557
|
+
) {
|
|
558
|
+
return value === numericKind ||
|
|
559
|
+
(typeof value === 'string' && value.toLowerCase() === stringKind.toLowerCase())
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
function clonePlainObject(value: ProjectedQueryFormValue) {
|
|
563
|
+
return clonePlainValue(value) as ProjectedQueryFormValue
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
function clonePlainValue(value: unknown): unknown {
|
|
567
|
+
if (Array.isArray(value)) {
|
|
568
|
+
return value.map(clonePlainValue)
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
if (value && typeof value === 'object') {
|
|
572
|
+
return Object.fromEntries(
|
|
573
|
+
Object.entries(value).map(([key, entry]) => [key, clonePlainValue(entry)]),
|
|
574
|
+
)
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return value
|
|
578
|
+
}
|