@narrative.io/jsonforms-provider-protocols 3.0.0-beta.3 → 3.0.0-beta.4

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.
Files changed (67) hide show
  1. package/dist/core/projection.d.ts.map +1 -1
  2. package/dist/core/projection.js.map +1 -1
  3. package/dist/core/transforms.d.ts.map +1 -1
  4. package/dist/core/transforms.js +3 -1
  5. package/dist/core/transforms.js.map +1 -1
  6. package/dist/jsonforms-provider-protocols.css +2 -2
  7. package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
  8. package/dist/vue/components/ProviderAutocomplete.vue.js +8 -5
  9. package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -1
  10. package/dist/vue/components/ProviderMultiSelect.vue.d.ts.map +1 -1
  11. package/dist/vue/components/ProviderMultiSelect.vue.js +1 -1
  12. package/dist/vue/components/ProviderMultiSelect.vue2.js +8 -5
  13. package/dist/vue/components/ProviderMultiSelect.vue2.js.map +1 -1
  14. package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -1
  15. package/dist/vue/components/ProviderSelect.vue.js +1 -1
  16. package/dist/vue/components/ProviderSelect.vue2.js +8 -5
  17. package/dist/vue/components/ProviderSelect.vue2.js.map +1 -1
  18. package/dist/vue/composables/useDerive.d.ts +1 -1
  19. package/dist/vue/composables/useDerive.d.ts.map +1 -1
  20. package/dist/vue/composables/useDerive.js +5 -1
  21. package/dist/vue/composables/useDerive.js.map +1 -1
  22. package/dist/vue/composables/useProjection.d.ts.map +1 -1
  23. package/dist/vue/composables/useProjection.js +1 -3
  24. package/dist/vue/composables/useProjection.js.map +1 -1
  25. package/dist/vue/index.d.ts.map +1 -1
  26. package/dist/vue/index.js +10 -2
  27. package/dist/vue/index.js.map +1 -1
  28. package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -1
  29. package/dist/vue/primevue/JfBoolean.vue.js +14 -3
  30. package/dist/vue/primevue/JfBoolean.vue.js.map +1 -1
  31. package/dist/vue/primevue/JfEnum.vue.d.ts.map +1 -1
  32. package/dist/vue/primevue/JfEnum.vue.js +10 -5
  33. package/dist/vue/primevue/JfEnum.vue.js.map +1 -1
  34. package/dist/vue/primevue/JfEnumArray.vue.d.ts.map +1 -1
  35. package/dist/vue/primevue/JfEnumArray.vue.js +10 -5
  36. package/dist/vue/primevue/JfEnumArray.vue.js.map +1 -1
  37. package/dist/vue/primevue/JfNumber.vue.d.ts.map +1 -1
  38. package/dist/vue/primevue/JfNumber.vue.js +11 -6
  39. package/dist/vue/primevue/JfNumber.vue.js.map +1 -1
  40. package/dist/vue/primevue/JfText.vue.d.ts.map +1 -1
  41. package/dist/vue/primevue/JfText.vue.js +11 -6
  42. package/dist/vue/primevue/JfText.vue.js.map +1 -1
  43. package/dist/vue/primevue/JfTextArea.vue.d.ts.map +1 -1
  44. package/dist/vue/primevue/JfTextArea.vue.js +10 -5
  45. package/dist/vue/primevue/JfTextArea.vue.js.map +1 -1
  46. package/dist/vue/primevue/index.d.ts.map +1 -1
  47. package/dist/vue/primevue/index.js +93 -16
  48. package/dist/vue/primevue/index.js.map +1 -1
  49. package/dist/vue/utils/autoSelect.js.map +1 -1
  50. package/package.json +1 -1
  51. package/src/core/projection.ts +5 -5
  52. package/src/core/transforms.ts +33 -6
  53. package/src/vue/components/ProviderAutocomplete.vue +8 -5
  54. package/src/vue/components/ProviderMultiSelect.vue +12 -7
  55. package/src/vue/components/ProviderSelect.vue +9 -6
  56. package/src/vue/composables/useDerive.ts +16 -3
  57. package/src/vue/composables/useProjection.ts +6 -12
  58. package/src/vue/index.ts +10 -4
  59. package/src/vue/primevue/JfBoolean.vue +8 -3
  60. package/src/vue/primevue/JfEnum.vue +11 -8
  61. package/src/vue/primevue/JfEnumArray.vue +15 -12
  62. package/src/vue/primevue/JfNumber.vue +11 -8
  63. package/src/vue/primevue/JfText.vue +11 -8
  64. package/src/vue/primevue/JfTextArea.vue +10 -7
  65. package/src/vue/primevue/index.ts +104 -23
  66. package/src/vue/styles.css +26 -1
  67. package/src/vue/utils/autoSelect.ts +2 -2
@@ -53,7 +53,12 @@ import MultiSelect from "primevue/multiselect";
53
53
  const instance = getCurrentInstance()!;
54
54
  const props = instance.props as unknown as ControlProps;
55
55
  const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
56
- const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
56
+ const {
57
+ projectedData,
58
+ handleProjectedChange: handleChange,
59
+ projectedErrors,
60
+ projectedLabel,
61
+ } = useProjection(control, rawHandleChange);
57
62
 
58
63
  type Opt = { label: string; value: unknown };
59
64
  const toOptions = (schema?: JsonSchema): Opt[] => {
@@ -145,14 +150,16 @@ watch(
145
150
  control.value.uischema?.options?.autoSelectSingle === true,
146
151
  isLoading,
147
152
  items,
148
- currentValue: Array.isArray(projectedData.value) ? projectedData.value : [],
153
+ currentValue: Array.isArray(projectedData.value)
154
+ ? projectedData.value
155
+ : [],
149
156
  });
150
157
 
151
158
  if (valueToSelect !== null) {
152
159
  handleChange(control.value.path, valueToSelect);
153
160
  }
154
161
  },
155
- { immediate: true }
162
+ { immediate: true },
156
163
  );
157
164
 
158
165
  const placeholder = computed<string | undefined>(() => {
@@ -190,17 +197,15 @@ const model = computed<unknown[]>({
190
197
  </script>
191
198
 
192
199
  <template>
193
- <div class="flex flex-column gap-2">
194
- <label v-if="projectedLabel" class="text-color text-left">{{
195
- projectedLabel
196
- }}</label>
197
- <div v-if="control.description" class="text-color-secondary text-left">
200
+ <div class="jf-control">
201
+ <label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
202
+ <div v-if="control.description" class="jf-description">
198
203
  {{ control.description }}
199
204
  </div>
200
205
 
201
206
  <MultiSelect
202
207
  v-model="model"
203
- :class="['w-full', { 'p-invalid': showErrors }]"
208
+ :class="['w-full!', { 'p-invalid': showErrors }]"
204
209
  :options="options"
205
210
  option-label="label"
206
211
  option-value="value"
@@ -214,8 +219,6 @@ const model = computed<unknown[]>({
214
219
  <small v-if="error" class="p-error" role="alert"
215
220
  >Failed to load: {{ error }}</small
216
221
  >
217
- <small v-else-if="showErrors" class="p-error">{{
218
- projectedErrors
219
- }}</small>
222
+ <small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
220
223
  </div>
221
224
  </template>
@@ -50,7 +50,12 @@ import InputNumber from "primevue/inputnumber";
50
50
  const instance = getCurrentInstance()!;
51
51
  const props = instance.props as unknown as ControlProps;
52
52
  const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
53
- const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
53
+ const {
54
+ projectedData,
55
+ handleProjectedChange: handleChange,
56
+ projectedErrors,
57
+ projectedLabel,
58
+ } = useProjection(control, rawHandleChange);
54
59
 
55
60
  const options = computed(
56
61
  () =>
@@ -110,16 +115,14 @@ const onNumber = (val: number | null) => {
110
115
  </script>
111
116
 
112
117
  <template>
113
- <div class="flex flex-column gap-2">
114
- <label v-if="projectedLabel" class="text-color text-left">{{
115
- projectedLabel
116
- }}</label>
117
- <div v-if="control.description" class="text-color-secondary text-left">
118
+ <div class="jf-control">
119
+ <label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
120
+ <div v-if="control.description" class="jf-description">
118
121
  {{ control.description }}
119
122
  </div>
120
123
  <InputNumber
121
- :class="['w-full', { 'p-invalid': showErrors }]"
122
- :input-class="['w-full', { 'p-invalid': showErrors }]"
124
+ :class="['w-full!', { 'p-invalid': showErrors }]"
125
+ :input-class="['w-full!', { 'p-invalid': showErrors }]"
123
126
  :use-grouping="useGrouping"
124
127
  :mode="mode"
125
128
  :currency="currency"
@@ -52,7 +52,12 @@ import AutoComplete from "primevue/autocomplete";
52
52
  const instance = getCurrentInstance()!;
53
53
  const props = instance.props as unknown as ControlProps;
54
54
  const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
55
- const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
55
+ const {
56
+ projectedData,
57
+ handleProjectedChange: handleChange,
58
+ projectedErrors,
59
+ projectedLabel,
60
+ } = useProjection(control, rawHandleChange);
56
61
 
57
62
  // Provider support for autocomplete functionality
58
63
  const binding = computed(() => {
@@ -150,16 +155,14 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
150
155
  </script>
151
156
 
152
157
  <template>
153
- <div class="flex flex-column gap-2">
154
- <label v-if="projectedLabel" class="text-color text-left">{{
155
- projectedLabel
156
- }}</label>
157
- <div v-if="control.description" class="text-color-secondary text-left">
158
+ <div class="jf-control">
159
+ <label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
160
+ <div v-if="control.description" class="jf-description">
158
161
  {{ control.description }}
159
162
  </div>
160
163
  <AutoComplete
161
164
  v-if="isAutocomplete"
162
- :class="['w-full', { 'p-invalid': showErrors }]"
165
+ :class="['w-full!', { 'p-invalid': showErrors }]"
163
166
  :model-value="projectedData ?? ''"
164
167
  :suggestions="items"
165
168
  option-label="label"
@@ -173,7 +176,7 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
173
176
  />
174
177
  <InputText
175
178
  v-else
176
- :class="['w-full', { 'p-invalid': showErrors }]"
179
+ :class="['w-full!', { 'p-invalid': showErrors }]"
177
180
  :model-value="(projectedData as string) ?? ''"
178
181
  :disabled="!control.enabled"
179
182
  :aria-invalid="showErrors || undefined"
@@ -49,7 +49,12 @@ import Textarea from "primevue/textarea";
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 { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
52
+ const {
53
+ projectedData,
54
+ handleProjectedChange: handleChange,
55
+ projectedErrors,
56
+ projectedLabel,
57
+ } = useProjection(control, rawHandleChange);
53
58
 
54
59
  const placeholder = computed<string | undefined>(
55
60
  () =>
@@ -79,15 +84,13 @@ function onBlur() {
79
84
  </script>
80
85
 
81
86
  <template>
82
- <div class="flex flex-column gap-2">
83
- <label v-if="projectedLabel" class="text-color text-left">{{
84
- projectedLabel
85
- }}</label>
86
- <div v-if="control.description" class="text-color-secondary text-left">
87
+ <div class="jf-control">
88
+ <label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
89
+ <div v-if="control.description" class="jf-description">
87
90
  {{ control.description }}
88
91
  </div>
89
92
  <Textarea
90
- :class="['w-full', { 'p-invalid': showErrors }]"
93
+ :class="['w-full!', { 'p-invalid': showErrors }]"
91
94
  :model-value="(projectedData as string) ?? ''"
92
95
  :disabled="!control.enabled"
93
96
  :aria-invalid="showErrors || undefined"
@@ -19,13 +19,38 @@ const injectLayoutStyles = () => {
19
19
  display: flex;
20
20
  flex-direction: column;
21
21
  align-items: flex-start;
22
- gap: 1rem;
22
+ gap: 24px;
23
23
  width: 100%;
24
24
  }
25
25
 
26
26
  .vertical-layout-item {
27
27
  width: 100%;
28
28
  }
29
+
30
+ /* Form control wrapper */
31
+ .jf-control {
32
+ display: flex;
33
+ flex-direction: column;
34
+ gap: 12px;
35
+ }
36
+
37
+ /* Form control label typography */
38
+ .jf-label {
39
+ font-weight: 600;
40
+ font-size: 14px;
41
+ line-height: 14px;
42
+ color: #031553;
43
+ text-align: left;
44
+ }
45
+
46
+ /* Form control description typography */
47
+ .jf-description {
48
+ font-weight: 400;
49
+ font-size: 14px;
50
+ line-height: 14px;
51
+ color: #415290;
52
+ text-align: left;
53
+ }
29
54
  `;
30
55
  document.head.appendChild(style);
31
56
  }
@@ -102,47 +127,103 @@ export function registerPrimevueRenderers(jsonformsCore: any): unknown[] {
102
127
 
103
128
  // Projection-aware schema check: when options.projection is set,
104
129
  // resolve the projected schema and test against it instead of the original
105
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
- const projectedSchemaMatches = (check: (schema: any) => boolean) =>
107
- (uischema: unknown, schema: unknown): boolean => {
108
- const ui = uischema as { type?: string; scope?: string; options?: { projection?: string } };
109
- const projection = ui?.options?.projection;
110
- if (!projection || ui?.type !== "Control" || !ui?.scope) return false;
111
-
112
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
113
- const propertySchema = resolveScopeSchema(ui.scope, schema as Record<string, any>);
114
- if (!propertySchema) return false;
115
-
116
- return check(getProjectedSchema(propertySchema, projection));
117
- };
130
+
131
+ const projectedSchemaMatches =
132
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
133
+ (check: (schema: any) => boolean) =>
134
+ (uischema: unknown, schema: unknown): boolean => {
135
+ const ui = uischema as {
136
+ type?: string;
137
+ scope?: string;
138
+ options?: { projection?: string };
139
+ };
140
+ const projection = ui?.options?.projection;
141
+ if (!projection || ui?.type !== "Control" || !ui?.scope) return false;
142
+
143
+ const propertySchema = resolveScopeSchema(
144
+ ui.scope,
145
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
146
+ schema as Record<string, any>,
147
+ );
148
+ if (!propertySchema) return false;
149
+
150
+ return check(getProjectedSchema(propertySchema, projection));
151
+ };
118
152
 
119
153
  const isMultilineProjection = (uischema: unknown, schema: unknown) => {
120
154
  const ui = uischema as { options?: { multi?: boolean } };
121
- return ui?.options?.multi === true &&
122
- projectedSchemaMatches((s) => s?.type === "string")(uischema, schema);
155
+ return (
156
+ ui?.options?.multi === true &&
157
+ projectedSchemaMatches((s) => s?.type === "string")(uischema, schema)
158
+ );
123
159
  };
124
160
 
125
161
  const renderers = [
126
162
  // Multiline text has higher priority than regular text
127
- { tester: rankWith(PRIME + 4, or(isMultilineString, isMultilineProjection)), renderer: JfTextArea },
128
- { tester: rankWith(PRIME + 3, or(isStringControl, projectedSchemaMatches((s) => s?.type === "string"))), renderer: JfText },
129
163
  {
130
- tester: rankWith(PRIME + 6, or(isIntegerControl, projectedSchemaMatches((s) => s?.type === "integer"))),
164
+ tester: rankWith(PRIME + 4, or(isMultilineString, isMultilineProjection)),
165
+ renderer: JfTextArea,
166
+ },
167
+ {
168
+ tester: rankWith(
169
+ PRIME + 3,
170
+ or(
171
+ isStringControl,
172
+ projectedSchemaMatches((s) => s?.type === "string"),
173
+ ),
174
+ ),
175
+ renderer: JfText,
176
+ },
177
+ {
178
+ tester: rankWith(
179
+ PRIME + 6,
180
+ or(
181
+ isIntegerControl,
182
+ projectedSchemaMatches((s) => s?.type === "integer"),
183
+ ),
184
+ ),
131
185
  renderer: JfNumber,
132
186
  },
133
187
  {
134
- tester: rankWith(PRIME + 4, or(isNumberControl, projectedSchemaMatches((s) => s?.type === "number"))),
188
+ tester: rankWith(
189
+ PRIME + 4,
190
+ or(
191
+ isNumberControl,
192
+ projectedSchemaMatches((s) => s?.type === "number"),
193
+ ),
194
+ ),
135
195
  renderer: JfNumber,
136
196
  },
137
197
  {
138
- tester: rankWith(PRIME + 7, or(and(isControl, schemaMatches(isScalarEnum)), and(isControl, projectedSchemaMatches(isScalarEnum)))),
198
+ tester: rankWith(
199
+ PRIME + 7,
200
+ or(
201
+ and(isControl, schemaMatches(isScalarEnum)),
202
+ and(isControl, projectedSchemaMatches(isScalarEnum)),
203
+ ),
204
+ ),
139
205
  renderer: JfEnum,
140
206
  },
141
207
  {
142
- tester: rankWith(PRIME + 8, or(and(isControl, schemaMatches(isEnumArray)), and(isControl, projectedSchemaMatches(isEnumArray)))),
208
+ tester: rankWith(
209
+ PRIME + 8,
210
+ or(
211
+ and(isControl, schemaMatches(isEnumArray)),
212
+ and(isControl, projectedSchemaMatches(isEnumArray)),
213
+ ),
214
+ ),
143
215
  renderer: JfEnumArray,
144
216
  },
145
- { tester: rankWith(PRIME + 3, or(isBooleanControl, projectedSchemaMatches((s) => s?.type === "boolean"))), renderer: JfBoolean },
217
+ {
218
+ tester: rankWith(
219
+ PRIME + 3,
220
+ or(
221
+ isBooleanControl,
222
+ projectedSchemaMatches((s) => s?.type === "boolean"),
223
+ ),
224
+ ),
225
+ renderer: JfBoolean,
226
+ },
146
227
  ];
147
228
 
148
229
  // Update the exported array
@@ -5,7 +5,7 @@
5
5
  display: flex;
6
6
  flex-direction: column;
7
7
  align-items: flex-start;
8
- gap: 1rem;
8
+ gap: 24px;
9
9
  width: 100%;
10
10
  }
11
11
 
@@ -14,6 +14,31 @@
14
14
  width: 100%;
15
15
  }
16
16
 
17
+ /* Form control wrapper */
18
+ .jf-control {
19
+ display: flex;
20
+ flex-direction: column;
21
+ gap: 12px;
22
+ }
23
+
24
+ /* Form control label typography */
25
+ .jf-label {
26
+ font-weight: 600;
27
+ font-size: 14px;
28
+ line-height: 14px;
29
+ color: #031553;
30
+ text-align: left;
31
+ }
32
+
33
+ /* Form control description typography */
34
+ .jf-description {
35
+ font-weight: 400;
36
+ font-size: 14px;
37
+ line-height: 14px;
38
+ color: #415290;
39
+ text-align: left;
40
+ }
41
+
17
42
  /* PrimeVue dropdown text alignment fix */
18
43
  .p-dropdown-label {
19
44
  text-align: left !important;
@@ -57,7 +57,7 @@ export interface AutoSelectMultiParams {
57
57
  * - Current value is empty array OR current selection is not in the current options
58
58
  */
59
59
  export function shouldAutoSelectMulti(
60
- params: AutoSelectMultiParams
60
+ params: AutoSelectMultiParams,
61
61
  ): unknown[] | null {
62
62
  const { autoSelectSingle, isLoading, items, currentValue } = params;
63
63
 
@@ -73,7 +73,7 @@ export function shouldAutoSelectMulti(
73
73
  const currentArray = Array.isArray(currentValue) ? currentValue : [];
74
74
  const isValueEmpty = currentArray.length === 0;
75
75
  const hasValidSelection = currentArray.some((val) =>
76
- items.some((item) => item.value === val)
76
+ items.some((item) => item.value === val),
77
77
  );
78
78
 
79
79
  if (isValueEmpty || !hasValidSelection) {