@narrative.io/jsonforms-provider-protocols 3.0.0-beta.2 → 3.0.0-beta.20
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/core/initFormData.d.ts +17 -0
- package/dist/core/initFormData.d.ts.map +1 -0
- package/dist/core/initFormData.js +99 -0
- package/dist/core/initFormData.js.map +1 -0
- package/dist/core/projection.d.ts +4 -0
- package/dist/core/projection.d.ts.map +1 -1
- package/dist/core/projection.js +17 -14
- package/dist/core/projection.js.map +1 -1
- package/dist/core/refs.d.ts +58 -0
- package/dist/core/refs.d.ts.map +1 -0
- package/dist/core/refs.js +70 -0
- package/dist/core/refs.js.map +1 -0
- package/dist/core/resolveScope.d.ts +6 -0
- package/dist/core/resolveScope.d.ts.map +1 -1
- package/dist/core/resolveScope.js +14 -8
- package/dist/core/resolveScope.js.map +1 -1
- package/dist/core/transforms.d.ts.map +1 -1
- package/dist/core/transforms.js +3 -1
- package/dist/core/transforms.js.map +1 -1
- package/dist/core/types.d.ts +1 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -1
- package/dist/index.js.map +1 -1
- package/dist/jsonforms-provider-protocols.css +2 -2
- package/dist/no-eval-ajv.d.ts +70 -0
- package/dist/no-eval-ajv.d.ts.map +1 -0
- package/dist/no-eval-ajv.js +247 -0
- package/dist/no-eval-ajv.js.map +1 -0
- package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderAutocomplete.vue.js +10 -6
- package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue.js +1 -1
- package/dist/vue/components/ProviderMultiSelect.vue2.js +17 -9
- package/dist/vue/components/ProviderMultiSelect.vue2.js.map +1 -1
- package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderSelect.vue.js +1 -1
- package/dist/vue/components/ProviderSelect.vue2.js +19 -9
- package/dist/vue/components/ProviderSelect.vue2.js.map +1 -1
- package/dist/vue/composables/useDataLayer.d.ts +1 -0
- package/dist/vue/composables/useDataLayer.d.ts.map +1 -1
- package/dist/vue/composables/useDataLayer.js +1 -0
- package/dist/vue/composables/useDataLayer.js.map +1 -1
- package/dist/vue/composables/useDerive.d.ts +1 -1
- package/dist/vue/composables/useDerive.d.ts.map +1 -1
- package/dist/vue/composables/useDerive.js +19 -2
- package/dist/vue/composables/useDerive.js.map +1 -1
- package/dist/vue/composables/useDeriveInitialValue.d.ts +36 -0
- package/dist/vue/composables/useDeriveInitialValue.d.ts.map +1 -0
- package/dist/vue/composables/useDeriveInitialValue.js +125 -0
- package/dist/vue/composables/useDeriveInitialValue.js.map +1 -0
- package/dist/vue/composables/useDirtyValidation.d.ts +3 -3
- package/dist/vue/composables/useDirtyValidation.d.ts.map +1 -1
- package/dist/vue/composables/useDirtyValidation.js +2 -2
- package/dist/vue/composables/useDirtyValidation.js.map +1 -1
- package/dist/vue/composables/useProjection.d.ts +7 -0
- package/dist/vue/composables/useProjection.d.ts.map +1 -1
- package/dist/vue/composables/useProjection.js +87 -4
- package/dist/vue/composables/useProjection.js.map +1 -1
- package/dist/vue/composables/useProvider.d.ts +2 -2
- package/dist/vue/composables/useProvider.d.ts.map +1 -1
- package/dist/vue/composables/useProvider.js +14 -10
- package/dist/vue/composables/useProvider.js.map +1 -1
- package/dist/vue/index.d.ts +2 -0
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/index.js +30 -10
- package/dist/vue/index.js.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.js +17 -6
- package/dist/vue/primevue/JfBoolean.vue.js.map +1 -1
- package/dist/vue/primevue/JfEnum.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfEnum.vue.js +22 -10
- package/dist/vue/primevue/JfEnum.vue.js.map +1 -1
- package/dist/vue/primevue/JfEnumArray.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfEnumArray.vue.js +20 -10
- package/dist/vue/primevue/JfEnumArray.vue.js.map +1 -1
- package/dist/vue/primevue/JfNumber.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfNumber.vue.js +18 -10
- package/dist/vue/primevue/JfNumber.vue.js.map +1 -1
- package/dist/vue/primevue/JfText.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfText.vue.js +27 -12
- package/dist/vue/primevue/JfText.vue.js.map +1 -1
- package/dist/vue/primevue/JfTextArea.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfTextArea.vue.js +15 -9
- package/dist/vue/primevue/JfTextArea.vue.js.map +1 -1
- package/dist/vue/primevue/index.d.ts.map +1 -1
- package/dist/vue/primevue/index.js +93 -16
- package/dist/vue/primevue/index.js.map +1 -1
- package/dist/vue/utils/autoSelect.js.map +1 -1
- package/dist/vue/utils/placeholder.d.ts +17 -0
- package/dist/vue/utils/placeholder.d.ts.map +1 -0
- package/dist/vue/utils/placeholder.js +17 -0
- package/dist/vue/utils/placeholder.js.map +1 -0
- package/package.json +10 -2
- package/src/core/initFormData.ts +208 -0
- package/src/core/projection.ts +33 -22
- package/src/core/refs.ts +166 -0
- package/src/core/resolveScope.ts +23 -8
- package/src/core/transforms.ts +33 -6
- package/src/core/types.ts +1 -0
- package/src/index.ts +14 -2
- package/src/no-eval-ajv.ts +381 -0
- package/src/vue/components/ProviderAutocomplete.vue +9 -7
- package/src/vue/components/ProviderMultiSelect.vue +20 -15
- package/src/vue/components/ProviderSelect.vue +21 -14
- package/src/vue/composables/useDataLayer.ts +1 -1
- package/src/vue/composables/useDerive.ts +46 -3
- package/src/vue/composables/useDeriveInitialValue.ts +195 -0
- package/src/vue/composables/useDirtyValidation.ts +8 -3
- package/src/vue/composables/useProjection.ts +172 -1
- package/src/vue/composables/useProvider.ts +28 -11
- package/src/vue/index.ts +28 -9
- package/src/vue/primevue/JfBoolean.vue +10 -5
- package/src/vue/primevue/JfEnum.vue +23 -14
- package/src/vue/primevue/JfEnumArray.vue +22 -17
- package/src/vue/primevue/JfNumber.vue +20 -12
- package/src/vue/primevue/JfText.vue +31 -16
- package/src/vue/primevue/JfTextArea.vue +15 -13
- package/src/vue/primevue/index.ts +104 -23
- package/src/vue/styles.css +26 -1
- package/src/vue/utils/autoSelect.ts +2 -2
- package/src/vue/utils/placeholder.ts +42 -0
package/src/vue/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { UISchemaElement } from "@jsonforms/core";
|
|
2
2
|
import {
|
|
3
3
|
and,
|
|
4
|
+
isIntegerControl,
|
|
4
5
|
isNumberControl,
|
|
5
6
|
isStringControl,
|
|
6
7
|
or,
|
|
@@ -22,25 +23,38 @@ const isIntegerScope = (uischema: unknown, schema: unknown) => {
|
|
|
22
23
|
const ui = uischema as { type?: string; scope?: string };
|
|
23
24
|
if (ui?.type !== "Control" || !ui?.scope) return false;
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
const propertySchema = resolveScopeSchema(
|
|
27
|
+
ui.scope,
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
|
+
schema as Record<string, any>,
|
|
30
|
+
);
|
|
27
31
|
return propertySchema?.type === "integer";
|
|
28
32
|
};
|
|
29
33
|
|
|
30
34
|
// Create specific testers for each component type
|
|
31
35
|
const providerSelectTester = rankWith(
|
|
32
|
-
|
|
36
|
+
107, // Higher than PrimeVue JfNumber integer renderer (106) so provider wins
|
|
33
37
|
and(
|
|
34
|
-
or(
|
|
38
|
+
or(
|
|
39
|
+
isStringControl,
|
|
40
|
+
isNumberControl,
|
|
41
|
+
isIntegerControl,
|
|
42
|
+
and(isControl, isIntegerScope),
|
|
43
|
+
),
|
|
35
44
|
hasProvider,
|
|
36
45
|
(uischema) => !uischema?.options?.autocomplete,
|
|
37
46
|
),
|
|
38
47
|
);
|
|
39
48
|
|
|
40
49
|
const providerAutocompleteTester = rankWith(
|
|
41
|
-
|
|
50
|
+
108, // Higher than providerSelectTester so autocomplete variant wins when flagged
|
|
42
51
|
and(
|
|
43
|
-
or(
|
|
52
|
+
or(
|
|
53
|
+
isStringControl,
|
|
54
|
+
isNumberControl,
|
|
55
|
+
isIntegerControl,
|
|
56
|
+
and(isControl, isIntegerScope),
|
|
57
|
+
),
|
|
44
58
|
hasProvider,
|
|
45
59
|
(uischema) => uischema?.options?.autocomplete === true,
|
|
46
60
|
),
|
|
@@ -53,13 +67,16 @@ const isArrayControl = (uischema: UISchemaElement, schema: unknown) => {
|
|
|
53
67
|
return false;
|
|
54
68
|
}
|
|
55
69
|
|
|
56
|
-
|
|
57
|
-
|
|
70
|
+
const propertySchema = resolveScopeSchema(
|
|
71
|
+
controlSchema.scope,
|
|
72
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
73
|
+
schema as Record<string, any>,
|
|
74
|
+
);
|
|
58
75
|
return propertySchema?.type === "array";
|
|
59
76
|
};
|
|
60
77
|
|
|
61
78
|
const providerMultiSelectTester = rankWith(
|
|
62
|
-
|
|
79
|
+
109, // Highest priority for array controls with providers
|
|
63
80
|
and(isArrayControl, hasProvider),
|
|
64
81
|
);
|
|
65
82
|
|
|
@@ -79,6 +96,8 @@ export { useProjection } from "./composables/useProjection";
|
|
|
79
96
|
export type { ProjectionResult } from "./composables/useProjection";
|
|
80
97
|
export { createDataLayer, useDataLayer } from "./composables/useDataLayer";
|
|
81
98
|
export type { DataLayer } from "./composables/useDataLayer";
|
|
99
|
+
export { useDeriveInitialValue } from "./composables/useDeriveInitialValue";
|
|
100
|
+
export type { DeriveInitialValueCfg } from "./composables/useDeriveInitialValue";
|
|
82
101
|
export { useDirtyValidation } from "./composables/useDirtyValidation";
|
|
83
102
|
export * from "./testers";
|
|
84
103
|
|
|
@@ -49,10 +49,15 @@ import Checkbox from "primevue/checkbox";
|
|
|
49
49
|
const instance = getCurrentInstance()!;
|
|
50
50
|
const props = instance.props as unknown as ControlProps;
|
|
51
51
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
52
|
-
const {
|
|
52
|
+
const {
|
|
53
|
+
projectedData,
|
|
54
|
+
handleProjectedChange: handleChange,
|
|
55
|
+
projectedErrors,
|
|
56
|
+
projectedLabel,
|
|
57
|
+
} = useProjection(control, rawHandleChange);
|
|
53
58
|
|
|
54
59
|
// Track user interaction — errors only show after first toggle
|
|
55
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
60
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
56
61
|
|
|
57
62
|
const onToggle = (val: boolean) => {
|
|
58
63
|
markDirty();
|
|
@@ -61,7 +66,7 @@ const onToggle = (val: boolean) => {
|
|
|
61
66
|
</script>
|
|
62
67
|
|
|
63
68
|
<template>
|
|
64
|
-
<div class="flex items
|
|
69
|
+
<div class="jf-control" style="flex-direction: row; align-items: center">
|
|
65
70
|
<Checkbox
|
|
66
71
|
:binary="true"
|
|
67
72
|
:model-value="!!projectedData"
|
|
@@ -70,7 +75,7 @@ const onToggle = (val: boolean) => {
|
|
|
70
75
|
:aria-invalid="showErrors || undefined"
|
|
71
76
|
@update:model-value="onToggle"
|
|
72
77
|
/>
|
|
73
|
-
<label v-if="
|
|
74
|
-
<small v-if="showErrors" class="p-error">{{
|
|
78
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
79
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
75
80
|
</div>
|
|
76
81
|
</template>
|
|
@@ -45,16 +45,23 @@ import { useJsonFormsControl } from "@jsonforms/vue";
|
|
|
45
45
|
import { computed, inject, getCurrentInstance, watch } from "vue";
|
|
46
46
|
import { useProvider } from "../composables/useProvider";
|
|
47
47
|
import { useDerive } from "../composables/useDerive";
|
|
48
|
+
import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
|
|
48
49
|
import { useProjection } from "../composables/useProjection";
|
|
49
50
|
import { useDirtyValidation } from "../composables/useDirtyValidation";
|
|
50
51
|
import { shouldAutoSelect } from "../utils/autoSelect";
|
|
52
|
+
import { resolvePlaceholder } from "../utils/placeholder";
|
|
51
53
|
import Dropdown from "primevue/dropdown";
|
|
52
54
|
|
|
53
55
|
// Access props from the component instance
|
|
54
56
|
const instance = getCurrentInstance()!;
|
|
55
57
|
const props = instance.props as unknown as ControlProps;
|
|
56
58
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
57
|
-
const {
|
|
59
|
+
const {
|
|
60
|
+
projectedData,
|
|
61
|
+
handleProjectedChange: handleChange,
|
|
62
|
+
projectedErrors,
|
|
63
|
+
projectedLabel,
|
|
64
|
+
} = useProjection(control, rawHandleChange);
|
|
58
65
|
|
|
59
66
|
type Opt = { label: string; value: unknown };
|
|
60
67
|
const toOptions = (schema?: JsonSchema): Opt[] => {
|
|
@@ -120,14 +127,15 @@ const {
|
|
|
120
127
|
} = useProvider(binding, {
|
|
121
128
|
data: rootData,
|
|
122
129
|
path: control.value.path,
|
|
123
|
-
dependsOnValues: depValues
|
|
130
|
+
dependsOnValues: depValues,
|
|
124
131
|
});
|
|
125
132
|
|
|
126
133
|
const placeholder = computed<string | undefined>(() => {
|
|
127
134
|
if (loading.value) return "Loading…";
|
|
128
|
-
return (
|
|
129
|
-
|
|
130
|
-
|
|
135
|
+
return resolvePlaceholder(
|
|
136
|
+
control.value.uischema,
|
|
137
|
+
projectedLabel.value,
|
|
138
|
+
"select",
|
|
131
139
|
);
|
|
132
140
|
});
|
|
133
141
|
|
|
@@ -142,6 +150,9 @@ const options = computed(() => {
|
|
|
142
150
|
// Add derive functionality
|
|
143
151
|
useDerive({ control, handleChange, data: projectedData });
|
|
144
152
|
|
|
153
|
+
// Add deriveInitialValue — async API-based initial value seeding
|
|
154
|
+
useDeriveInitialValue({ control, handleChange });
|
|
155
|
+
|
|
145
156
|
// Auto-select when provider returns only one item (enabled by default)
|
|
146
157
|
watch(
|
|
147
158
|
[providerItems, loading],
|
|
@@ -158,11 +169,11 @@ watch(
|
|
|
158
169
|
handleChange(control.value.path, valueToSelect);
|
|
159
170
|
}
|
|
160
171
|
},
|
|
161
|
-
{ immediate: true }
|
|
172
|
+
{ immediate: true },
|
|
162
173
|
);
|
|
163
174
|
|
|
164
175
|
// Track user interaction — errors only show after blur
|
|
165
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
176
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
166
177
|
|
|
167
178
|
const onSelect = (val: unknown) => {
|
|
168
179
|
handleChange(control.value.path, val);
|
|
@@ -170,15 +181,13 @@ const onSelect = (val: unknown) => {
|
|
|
170
181
|
</script>
|
|
171
182
|
|
|
172
183
|
<template>
|
|
173
|
-
<div class="
|
|
174
|
-
<label v-if="
|
|
175
|
-
|
|
176
|
-
}}</label>
|
|
177
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
184
|
+
<div class="jf-control">
|
|
185
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
186
|
+
<div v-if="control.description" class="jf-description">
|
|
178
187
|
{{ control.description }}
|
|
179
188
|
</div>
|
|
180
189
|
<Dropdown
|
|
181
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
190
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
182
191
|
:options="options"
|
|
183
192
|
option-label="label"
|
|
184
193
|
option-value="value"
|
|
@@ -193,6 +202,6 @@ const onSelect = (val: unknown) => {
|
|
|
193
202
|
<small v-if="error" class="p-error" role="alert"
|
|
194
203
|
>Failed to load: {{ error }}</small
|
|
195
204
|
>
|
|
196
|
-
<small v-else-if="showErrors" class="p-error">{{
|
|
205
|
+
<small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
197
206
|
</div>
|
|
198
207
|
</template>
|
|
@@ -47,13 +47,19 @@ import { useDerive } from "../composables/useDerive";
|
|
|
47
47
|
import { useProjection } from "../composables/useProjection";
|
|
48
48
|
import { useDirtyValidation } from "../composables/useDirtyValidation";
|
|
49
49
|
import { shouldAutoSelectMulti } from "../utils/autoSelect";
|
|
50
|
+
import { resolvePlaceholder } from "../utils/placeholder";
|
|
50
51
|
import MultiSelect from "primevue/multiselect";
|
|
51
52
|
|
|
52
53
|
// Access props from the component instance
|
|
53
54
|
const instance = getCurrentInstance()!;
|
|
54
55
|
const props = instance.props as unknown as ControlProps;
|
|
55
56
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
56
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
projectedData,
|
|
59
|
+
handleProjectedChange: handleChange,
|
|
60
|
+
projectedErrors,
|
|
61
|
+
projectedLabel,
|
|
62
|
+
} = useProjection(control, rawHandleChange);
|
|
57
63
|
|
|
58
64
|
type Opt = { label: string; value: unknown };
|
|
59
65
|
const toOptions = (schema?: JsonSchema): Opt[] => {
|
|
@@ -119,7 +125,7 @@ const {
|
|
|
119
125
|
} = useProvider(binding, {
|
|
120
126
|
data: rootData,
|
|
121
127
|
path: control.value.path,
|
|
122
|
-
dependsOnValues: depValues
|
|
128
|
+
dependsOnValues: depValues,
|
|
123
129
|
});
|
|
124
130
|
|
|
125
131
|
const options = computed(() => {
|
|
@@ -134,7 +140,7 @@ const options = computed(() => {
|
|
|
134
140
|
useDerive({ control, handleChange, data: projectedData });
|
|
135
141
|
|
|
136
142
|
// Track user interaction — errors only show after first change
|
|
137
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
143
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
138
144
|
|
|
139
145
|
// Auto-select when provider returns only one item (opt-in for multiselect)
|
|
140
146
|
watch(
|
|
@@ -145,21 +151,24 @@ watch(
|
|
|
145
151
|
control.value.uischema?.options?.autoSelectSingle === true,
|
|
146
152
|
isLoading,
|
|
147
153
|
items,
|
|
148
|
-
currentValue: Array.isArray(projectedData.value)
|
|
154
|
+
currentValue: Array.isArray(projectedData.value)
|
|
155
|
+
? projectedData.value
|
|
156
|
+
: [],
|
|
149
157
|
});
|
|
150
158
|
|
|
151
159
|
if (valueToSelect !== null) {
|
|
152
160
|
handleChange(control.value.path, valueToSelect);
|
|
153
161
|
}
|
|
154
162
|
},
|
|
155
|
-
{ immediate: true }
|
|
163
|
+
{ immediate: true },
|
|
156
164
|
);
|
|
157
165
|
|
|
158
166
|
const placeholder = computed<string | undefined>(() => {
|
|
159
167
|
if (loading.value) return "Loading…";
|
|
160
|
-
return (
|
|
161
|
-
|
|
162
|
-
|
|
168
|
+
return resolvePlaceholder(
|
|
169
|
+
control.value.uischema,
|
|
170
|
+
projectedLabel.value,
|
|
171
|
+
"select",
|
|
163
172
|
);
|
|
164
173
|
});
|
|
165
174
|
|
|
@@ -190,17 +199,15 @@ const model = computed<unknown[]>({
|
|
|
190
199
|
</script>
|
|
191
200
|
|
|
192
201
|
<template>
|
|
193
|
-
<div class="
|
|
194
|
-
<label v-if="
|
|
195
|
-
|
|
196
|
-
}}</label>
|
|
197
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
202
|
+
<div class="jf-control">
|
|
203
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
204
|
+
<div v-if="control.description" class="jf-description">
|
|
198
205
|
{{ control.description }}
|
|
199
206
|
</div>
|
|
200
207
|
|
|
201
208
|
<MultiSelect
|
|
202
209
|
v-model="model"
|
|
203
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
210
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
204
211
|
:options="options"
|
|
205
212
|
option-label="label"
|
|
206
213
|
option-value="value"
|
|
@@ -214,8 +221,6 @@ const model = computed<unknown[]>({
|
|
|
214
221
|
<small v-if="error" class="p-error" role="alert"
|
|
215
222
|
>Failed to load: {{ error }}</small
|
|
216
223
|
>
|
|
217
|
-
<small v-else-if="showErrors" class="p-error">{{
|
|
218
|
-
control.errors
|
|
219
|
-
}}</small>
|
|
224
|
+
<small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
220
225
|
</div>
|
|
221
226
|
</template>
|
|
@@ -42,15 +42,22 @@ import type { ControlProps } from "@jsonforms/vue";
|
|
|
42
42
|
import { useJsonFormsControl } from "@jsonforms/vue";
|
|
43
43
|
import { computed, getCurrentInstance } from "vue";
|
|
44
44
|
import { useDerive } from "../composables/useDerive";
|
|
45
|
+
import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
|
|
45
46
|
import { useProjection } from "../composables/useProjection";
|
|
46
47
|
import { useDirtyValidation } from "../composables/useDirtyValidation";
|
|
48
|
+
import { resolvePlaceholder } from "../utils/placeholder";
|
|
47
49
|
import InputNumber from "primevue/inputnumber";
|
|
48
50
|
|
|
49
51
|
// Access props from the component instance
|
|
50
52
|
const instance = getCurrentInstance()!;
|
|
51
53
|
const props = instance.props as unknown as ControlProps;
|
|
52
54
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
53
|
-
const {
|
|
55
|
+
const {
|
|
56
|
+
projectedData,
|
|
57
|
+
handleProjectedChange: handleChange,
|
|
58
|
+
projectedErrors,
|
|
59
|
+
projectedLabel,
|
|
60
|
+
} = useProjection(control, rawHandleChange);
|
|
54
61
|
|
|
55
62
|
const options = computed(
|
|
56
63
|
() =>
|
|
@@ -58,13 +65,16 @@ const options = computed(
|
|
|
58
65
|
?.options ?? {},
|
|
59
66
|
);
|
|
60
67
|
|
|
61
|
-
const placeholder = computed<string | undefined>(
|
|
62
|
-
(
|
|
68
|
+
const placeholder = computed<string | undefined>(() =>
|
|
69
|
+
resolvePlaceholder(control.value.uischema, projectedLabel.value, "input"),
|
|
63
70
|
);
|
|
64
71
|
|
|
65
72
|
// Add derive functionality
|
|
66
73
|
useDerive({ control, handleChange, data: projectedData });
|
|
67
74
|
|
|
75
|
+
// Add deriveInitialValue — async API-based initial value seeding
|
|
76
|
+
useDeriveInitialValue({ control, handleChange });
|
|
77
|
+
|
|
68
78
|
// Currency and decimal configuration
|
|
69
79
|
const mode = computed(() => {
|
|
70
80
|
if (options.value.currency) return "currency";
|
|
@@ -102,7 +112,7 @@ const useGrouping = computed(() => {
|
|
|
102
112
|
});
|
|
103
113
|
|
|
104
114
|
// Track user interaction — errors only show after blur
|
|
105
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
115
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
106
116
|
|
|
107
117
|
const onNumber = (val: number | null) => {
|
|
108
118
|
handleChange(control.value.path, val ?? undefined);
|
|
@@ -110,16 +120,14 @@ const onNumber = (val: number | null) => {
|
|
|
110
120
|
</script>
|
|
111
121
|
|
|
112
122
|
<template>
|
|
113
|
-
<div class="
|
|
114
|
-
<label v-if="
|
|
115
|
-
|
|
116
|
-
}}</label>
|
|
117
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
123
|
+
<div class="jf-control">
|
|
124
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
125
|
+
<div v-if="control.description" class="jf-description">
|
|
118
126
|
{{ control.description }}
|
|
119
127
|
</div>
|
|
120
128
|
<InputNumber
|
|
121
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
122
|
-
:input-class="['w-full', { 'p-invalid': showErrors }]"
|
|
129
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
130
|
+
:input-class="['w-full!', { 'p-invalid': showErrors }]"
|
|
123
131
|
:use-grouping="useGrouping"
|
|
124
132
|
:mode="mode"
|
|
125
133
|
:currency="currency"
|
|
@@ -132,6 +140,6 @@ const onNumber = (val: number | null) => {
|
|
|
132
140
|
@update:model-value="onNumber"
|
|
133
141
|
@blur="markDirty"
|
|
134
142
|
/>
|
|
135
|
-
<small v-if="showErrors" class="p-error">{{
|
|
143
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
136
144
|
</div>
|
|
137
145
|
</template>
|
|
@@ -43,8 +43,10 @@ import { useJsonFormsControl } from "@jsonforms/vue";
|
|
|
43
43
|
import { computed, ref, inject, watch, getCurrentInstance } from "vue";
|
|
44
44
|
import { useProvider } from "../composables/useProvider";
|
|
45
45
|
import { useDerive } from "../composables/useDerive";
|
|
46
|
+
import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
|
|
46
47
|
import { useProjection } from "../composables/useProjection";
|
|
47
48
|
import { useDirtyValidation } from "../composables/useDirtyValidation";
|
|
49
|
+
import { resolvePlaceholder } from "../utils/placeholder";
|
|
48
50
|
import InputText from "primevue/inputtext";
|
|
49
51
|
import AutoComplete from "primevue/autocomplete";
|
|
50
52
|
|
|
@@ -52,7 +54,12 @@ import AutoComplete from "primevue/autocomplete";
|
|
|
52
54
|
const instance = getCurrentInstance()!;
|
|
53
55
|
const props = instance.props as unknown as ControlProps;
|
|
54
56
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
55
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
projectedData,
|
|
59
|
+
handleProjectedChange: handleChange,
|
|
60
|
+
projectedErrors,
|
|
61
|
+
projectedLabel,
|
|
62
|
+
} = useProjection(control, rawHandleChange);
|
|
56
63
|
|
|
57
64
|
// Provider support for autocomplete functionality
|
|
58
65
|
const binding = computed(() => {
|
|
@@ -98,28 +105,38 @@ const { items, loading, error, reload } = useProvider(binding, {
|
|
|
98
105
|
data: rootData,
|
|
99
106
|
path: control.value.path,
|
|
100
107
|
uiQuery: query.value,
|
|
101
|
-
dependsOnValues: depValues
|
|
108
|
+
dependsOnValues: depValues,
|
|
102
109
|
});
|
|
103
110
|
|
|
104
111
|
watch(query, () => {
|
|
105
112
|
if (binding.value?.load === "query") reload();
|
|
106
113
|
});
|
|
107
114
|
|
|
115
|
+
const isAutocomplete = computed(() => !!binding.value);
|
|
116
|
+
|
|
108
117
|
const placeholder = computed<string | undefined>(() => {
|
|
109
118
|
if (loading.value) return "Loading…";
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
119
|
+
const explicit = (
|
|
120
|
+
control.value.uischema as { options?: { placeholder?: string } }
|
|
121
|
+
)?.options?.placeholder;
|
|
122
|
+
if (explicit) return explicit;
|
|
123
|
+
// In autocomplete mode the input is really a search box — use matching UX.
|
|
124
|
+
if (isAutocomplete.value) return "Type to search…";
|
|
125
|
+
return resolvePlaceholder(
|
|
126
|
+
control.value.uischema,
|
|
127
|
+
projectedLabel.value,
|
|
128
|
+
"input",
|
|
113
129
|
);
|
|
114
130
|
});
|
|
115
131
|
|
|
116
|
-
const isAutocomplete = computed(() => !!binding.value);
|
|
117
|
-
|
|
118
132
|
// Add derive functionality
|
|
119
133
|
useDerive({ control, handleChange, data: projectedData });
|
|
120
134
|
|
|
135
|
+
// Add deriveInitialValue — async API-based initial value seeding
|
|
136
|
+
useDeriveInitialValue({ control, handleChange });
|
|
137
|
+
|
|
121
138
|
// Track user interaction — errors only show after blur
|
|
122
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
139
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
123
140
|
|
|
124
141
|
function onInput(val: string | undefined) {
|
|
125
142
|
// Convert empty strings to undefined for proper required field validation
|
|
@@ -150,16 +167,14 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
150
167
|
</script>
|
|
151
168
|
|
|
152
169
|
<template>
|
|
153
|
-
<div class="
|
|
154
|
-
<label v-if="
|
|
155
|
-
|
|
156
|
-
}}</label>
|
|
157
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
170
|
+
<div class="jf-control">
|
|
171
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
172
|
+
<div v-if="control.description" class="jf-description">
|
|
158
173
|
{{ control.description }}
|
|
159
174
|
</div>
|
|
160
175
|
<AutoComplete
|
|
161
176
|
v-if="isAutocomplete"
|
|
162
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
177
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
163
178
|
:model-value="projectedData ?? ''"
|
|
164
179
|
:suggestions="items"
|
|
165
180
|
option-label="label"
|
|
@@ -173,7 +188,7 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
173
188
|
/>
|
|
174
189
|
<InputText
|
|
175
190
|
v-else
|
|
176
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
191
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
177
192
|
:model-value="(projectedData as string) ?? ''"
|
|
178
193
|
:disabled="!control.enabled"
|
|
179
194
|
:aria-invalid="showErrors || undefined"
|
|
@@ -185,6 +200,6 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
185
200
|
@blur="onBlur"
|
|
186
201
|
/>
|
|
187
202
|
<small v-if="error" class="p-error" role="alert">Failed: {{ error }}</small>
|
|
188
|
-
<small v-else-if="showErrors" class="p-error">{{
|
|
203
|
+
<small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
189
204
|
</div>
|
|
190
205
|
</template>
|
|
@@ -43,22 +43,26 @@ import { useJsonFormsControl } from "@jsonforms/vue";
|
|
|
43
43
|
import { computed, getCurrentInstance } from "vue";
|
|
44
44
|
import { useProjection } from "../composables/useProjection";
|
|
45
45
|
import { useDirtyValidation } from "../composables/useDirtyValidation";
|
|
46
|
+
import { resolvePlaceholder } from "../utils/placeholder";
|
|
46
47
|
import Textarea from "primevue/textarea";
|
|
47
48
|
|
|
48
49
|
// Access props from the component instance
|
|
49
50
|
const instance = getCurrentInstance()!;
|
|
50
51
|
const props = instance.props as unknown as ControlProps;
|
|
51
52
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
52
|
-
const {
|
|
53
|
+
const {
|
|
54
|
+
projectedData,
|
|
55
|
+
handleProjectedChange: handleChange,
|
|
56
|
+
projectedErrors,
|
|
57
|
+
projectedLabel,
|
|
58
|
+
} = useProjection(control, rawHandleChange);
|
|
53
59
|
|
|
54
|
-
const placeholder = computed<string | undefined>(
|
|
55
|
-
()
|
|
56
|
-
(control.value.uischema as { options?: { placeholder?: string } })?.options
|
|
57
|
-
?.placeholder ?? control.value.description,
|
|
60
|
+
const placeholder = computed<string | undefined>(() =>
|
|
61
|
+
resolvePlaceholder(control.value.uischema, projectedLabel.value, "input"),
|
|
58
62
|
);
|
|
59
63
|
|
|
60
64
|
// Track user interaction — errors only show after blur
|
|
61
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
65
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
62
66
|
|
|
63
67
|
function onInput(val: string | undefined) {
|
|
64
68
|
// Convert empty strings to undefined for proper required field validation
|
|
@@ -79,15 +83,13 @@ function onBlur() {
|
|
|
79
83
|
</script>
|
|
80
84
|
|
|
81
85
|
<template>
|
|
82
|
-
<div class="
|
|
83
|
-
<label v-if="
|
|
84
|
-
|
|
85
|
-
}}</label>
|
|
86
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
86
|
+
<div class="jf-control">
|
|
87
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
88
|
+
<div v-if="control.description" class="jf-description">
|
|
87
89
|
{{ control.description }}
|
|
88
90
|
</div>
|
|
89
91
|
<Textarea
|
|
90
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
92
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
91
93
|
:model-value="(projectedData as string) ?? ''"
|
|
92
94
|
:disabled="!control.enabled"
|
|
93
95
|
:aria-invalid="showErrors || undefined"
|
|
@@ -97,6 +99,6 @@ function onBlur() {
|
|
|
97
99
|
@update:model-value="onInput"
|
|
98
100
|
@blur="onBlur"
|
|
99
101
|
/>
|
|
100
|
-
<small v-if="showErrors" class="p-error">{{
|
|
102
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
101
103
|
</div>
|
|
102
104
|
</template>
|