@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.
- package/dist/core/projection.d.ts.map +1 -1
- package/dist/core/projection.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/jsonforms-provider-protocols.css +2 -2
- package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
- package/dist/vue/components/ProviderAutocomplete.vue.js +8 -5
- 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 +8 -5
- 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 +8 -5
- package/dist/vue/components/ProviderSelect.vue2.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 +5 -1
- package/dist/vue/composables/useDerive.js.map +1 -1
- package/dist/vue/composables/useProjection.d.ts.map +1 -1
- package/dist/vue/composables/useProjection.js +1 -3
- package/dist/vue/composables/useProjection.js.map +1 -1
- package/dist/vue/index.d.ts.map +1 -1
- package/dist/vue/index.js +10 -2
- 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 +14 -3
- 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 +10 -5
- 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 +10 -5
- 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 +11 -6
- 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 +11 -6
- 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 +10 -5
- 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/package.json +1 -1
- package/src/core/projection.ts +5 -5
- package/src/core/transforms.ts +33 -6
- package/src/vue/components/ProviderAutocomplete.vue +8 -5
- package/src/vue/components/ProviderMultiSelect.vue +12 -7
- package/src/vue/components/ProviderSelect.vue +9 -6
- package/src/vue/composables/useDerive.ts +16 -3
- package/src/vue/composables/useProjection.ts +6 -12
- package/src/vue/index.ts +10 -4
- package/src/vue/primevue/JfBoolean.vue +8 -3
- package/src/vue/primevue/JfEnum.vue +11 -8
- package/src/vue/primevue/JfEnumArray.vue +15 -12
- package/src/vue/primevue/JfNumber.vue +11 -8
- package/src/vue/primevue/JfText.vue +11 -8
- package/src/vue/primevue/JfTextArea.vue +10 -7
- package/src/vue/primevue/index.ts +104 -23
- package/src/vue/styles.css +26 -1
- package/src/vue/utils/autoSelect.ts +2 -2
|
@@ -17,13 +17,38 @@ const injectLayoutStyles = () => {
|
|
|
17
17
|
display: flex;
|
|
18
18
|
flex-direction: column;
|
|
19
19
|
align-items: flex-start;
|
|
20
|
-
gap:
|
|
20
|
+
gap: 24px;
|
|
21
21
|
width: 100%;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
.vertical-layout-item {
|
|
25
25
|
width: 100%;
|
|
26
26
|
}
|
|
27
|
+
|
|
28
|
+
/* Form control wrapper */
|
|
29
|
+
.jf-control {
|
|
30
|
+
display: flex;
|
|
31
|
+
flex-direction: column;
|
|
32
|
+
gap: 12px;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Form control label typography */
|
|
36
|
+
.jf-label {
|
|
37
|
+
font-weight: 600;
|
|
38
|
+
font-size: 14px;
|
|
39
|
+
line-height: 14px;
|
|
40
|
+
color: #031553;
|
|
41
|
+
text-align: left;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* Form control description typography */
|
|
45
|
+
.jf-description {
|
|
46
|
+
font-weight: 400;
|
|
47
|
+
font-size: 14px;
|
|
48
|
+
line-height: 14px;
|
|
49
|
+
color: #415290;
|
|
50
|
+
text-align: left;
|
|
51
|
+
}
|
|
27
52
|
`;
|
|
28
53
|
document.head.appendChild(style);
|
|
29
54
|
}
|
|
@@ -64,39 +89,91 @@ function registerPrimevueRenderers(jsonformsCore) {
|
|
|
64
89
|
{}
|
|
65
90
|
);
|
|
66
91
|
};
|
|
67
|
-
const projectedSchemaMatches = (
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
92
|
+
const projectedSchemaMatches = (
|
|
93
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
94
|
+
((check) => (uischema, schema) => {
|
|
95
|
+
const ui = uischema;
|
|
96
|
+
const projection = ui?.options?.projection;
|
|
97
|
+
if (!projection || ui?.type !== "Control" || !ui?.scope) return false;
|
|
98
|
+
const propertySchema = resolveScopeSchema(
|
|
99
|
+
ui.scope,
|
|
100
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
101
|
+
schema
|
|
102
|
+
);
|
|
103
|
+
if (!propertySchema) return false;
|
|
104
|
+
return check(getProjectedSchema(propertySchema, projection));
|
|
105
|
+
})
|
|
106
|
+
);
|
|
75
107
|
const isMultilineProjection = (uischema, schema) => {
|
|
76
108
|
const ui = uischema;
|
|
77
109
|
return ui?.options?.multi === true && projectedSchemaMatches((s) => s?.type === "string")(uischema, schema);
|
|
78
110
|
};
|
|
79
111
|
const renderers = [
|
|
80
112
|
// Multiline text has higher priority than regular text
|
|
81
|
-
{ tester: rankWith(PRIME + 4, or(isMultilineString, isMultilineProjection)), renderer: _sfc_main },
|
|
82
|
-
{ tester: rankWith(PRIME + 3, or(isStringControl, projectedSchemaMatches((s) => s?.type === "string"))), renderer: _sfc_main$1 },
|
|
83
113
|
{
|
|
84
|
-
tester: rankWith(PRIME +
|
|
114
|
+
tester: rankWith(PRIME + 4, or(isMultilineString, isMultilineProjection)),
|
|
115
|
+
renderer: _sfc_main
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
tester: rankWith(
|
|
119
|
+
PRIME + 3,
|
|
120
|
+
or(
|
|
121
|
+
isStringControl,
|
|
122
|
+
projectedSchemaMatches((s) => s?.type === "string")
|
|
123
|
+
)
|
|
124
|
+
),
|
|
125
|
+
renderer: _sfc_main$1
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
tester: rankWith(
|
|
129
|
+
PRIME + 6,
|
|
130
|
+
or(
|
|
131
|
+
isIntegerControl,
|
|
132
|
+
projectedSchemaMatches((s) => s?.type === "integer")
|
|
133
|
+
)
|
|
134
|
+
),
|
|
85
135
|
renderer: _sfc_main$2
|
|
86
136
|
},
|
|
87
137
|
{
|
|
88
|
-
tester: rankWith(
|
|
138
|
+
tester: rankWith(
|
|
139
|
+
PRIME + 4,
|
|
140
|
+
or(
|
|
141
|
+
isNumberControl,
|
|
142
|
+
projectedSchemaMatches((s) => s?.type === "number")
|
|
143
|
+
)
|
|
144
|
+
),
|
|
89
145
|
renderer: _sfc_main$2
|
|
90
146
|
},
|
|
91
147
|
{
|
|
92
|
-
tester: rankWith(
|
|
148
|
+
tester: rankWith(
|
|
149
|
+
PRIME + 7,
|
|
150
|
+
or(
|
|
151
|
+
and(isControl, schemaMatches(isScalarEnum)),
|
|
152
|
+
and(isControl, projectedSchemaMatches(isScalarEnum))
|
|
153
|
+
)
|
|
154
|
+
),
|
|
93
155
|
renderer: _sfc_main$3
|
|
94
156
|
},
|
|
95
157
|
{
|
|
96
|
-
tester: rankWith(
|
|
158
|
+
tester: rankWith(
|
|
159
|
+
PRIME + 8,
|
|
160
|
+
or(
|
|
161
|
+
and(isControl, schemaMatches(isEnumArray)),
|
|
162
|
+
and(isControl, projectedSchemaMatches(isEnumArray))
|
|
163
|
+
)
|
|
164
|
+
),
|
|
97
165
|
renderer: _sfc_main$4
|
|
98
166
|
},
|
|
99
|
-
{
|
|
167
|
+
{
|
|
168
|
+
tester: rankWith(
|
|
169
|
+
PRIME + 3,
|
|
170
|
+
or(
|
|
171
|
+
isBooleanControl,
|
|
172
|
+
projectedSchemaMatches((s) => s?.type === "boolean")
|
|
173
|
+
)
|
|
174
|
+
),
|
|
175
|
+
renderer: _sfc_main$5
|
|
176
|
+
}
|
|
100
177
|
];
|
|
101
178
|
primevueRenderers.splice(0, primevueRenderers.length, ...renderers);
|
|
102
179
|
renderersInitialized = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../../../src/vue/primevue/index.ts"],"sourcesContent":["import JfText from \"./JfText.vue\";\nimport JfTextArea from \"./JfTextArea.vue\";\nimport JfNumber from \"./JfNumber.vue\";\nimport JfEnum from \"./JfEnum.vue\";\nimport JfEnumArray from \"./JfEnumArray.vue\";\nimport JfBoolean from \"./JfBoolean.vue\";\nimport { getProjectedSchema } from \"../../core/projection\";\nimport { resolveScopeSchema } from \"../../core/resolveScope\";\n\n// Auto-inject layout styles\nconst injectLayoutStyles = () => {\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n if (!document.getElementById(\"jsonforms-primevue-styles\")) {\n const style = document.createElement(\"style\");\n style.id = \"jsonforms-primevue-styles\";\n style.textContent = `\n/* JSONForms PrimeVue Provider Protocols Layout Styles */\n.vertical-layout {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap:
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../src/vue/primevue/index.ts"],"sourcesContent":["import JfText from \"./JfText.vue\";\nimport JfTextArea from \"./JfTextArea.vue\";\nimport JfNumber from \"./JfNumber.vue\";\nimport JfEnum from \"./JfEnum.vue\";\nimport JfEnumArray from \"./JfEnumArray.vue\";\nimport JfBoolean from \"./JfBoolean.vue\";\nimport { getProjectedSchema } from \"../../core/projection\";\nimport { resolveScopeSchema } from \"../../core/resolveScope\";\n\n// Auto-inject layout styles\nconst injectLayoutStyles = () => {\n if (typeof window !== \"undefined\" && typeof document !== \"undefined\") {\n if (!document.getElementById(\"jsonforms-primevue-styles\")) {\n const style = document.createElement(\"style\");\n style.id = \"jsonforms-primevue-styles\";\n style.textContent = `\n/* JSONForms PrimeVue Provider Protocols Layout Styles */\n.vertical-layout {\n display: flex;\n flex-direction: column;\n align-items: flex-start;\n gap: 24px;\n width: 100%;\n}\n\n.vertical-layout-item {\n width: 100%;\n}\n\n/* Form control wrapper */\n.jf-control {\n display: flex;\n flex-direction: column;\n gap: 12px;\n}\n\n/* Form control label typography */\n.jf-label {\n font-weight: 600;\n font-size: 14px;\n line-height: 14px;\n color: #031553;\n text-align: left;\n}\n\n/* Form control description typography */\n.jf-description {\n font-weight: 400;\n font-size: 14px;\n line-height: 14px;\n color: #415290;\n text-align: left;\n}\n `;\n document.head.appendChild(style);\n }\n }\n};\n\n// Inject styles when this module is imported\ninjectLayoutStyles();\n\n// Track whether renderers have been registered to avoid duplicate registrations\nlet renderersInitialized = false;\n\n// Return empty renderers array initially\nexport const primevueRenderers: unknown[] = [];\n\n// Export a function that can be called by the consumer to register renderers\n// This should only be called once during application initialization\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function registerPrimevueRenderers(jsonformsCore: any): unknown[] {\n // Prevent duplicate registration which causes AJV schema recompilation\n if (renderersInitialized) {\n return primevueRenderers as unknown[];\n }\n\n const {\n rankWith,\n isStringControl,\n isNumberControl,\n isIntegerControl,\n and,\n or,\n isControl,\n schemaMatches,\n isBooleanControl,\n } = jsonformsCore;\n\n // Give PrimeVue renderers a high base rank; vanilla commonly uses small ranks (2–5)\n const PRIME = 100;\n\n // helpers for enum detection - using simple schema checks instead of JSONForms internal functions\n const isScalarEnum = (s?: object) => {\n const schema = s as {\n type?: string;\n enum?: unknown[];\n oneOf?: unknown[];\n };\n return (\n schema &&\n schema.type !== \"array\" &&\n (Array.isArray(schema.enum) || Array.isArray(schema.oneOf))\n );\n };\n\n const isEnumArray = (s?: object) => {\n const schema = s as {\n type?: string;\n items?: { enum?: unknown[]; oneOf?: unknown[] };\n };\n return (\n schema?.type === \"array\" &&\n (Array.isArray(schema.items?.enum) || Array.isArray(schema.items?.oneOf))\n );\n };\n\n // helper for multiline detection\n const isMultilineString = (uischema: unknown, schema: unknown) => {\n const controlUischema = uischema as { options?: { multi?: boolean } };\n return and(isStringControl, () => controlUischema?.options?.multi === true)(\n uischema as Parameters<typeof isStringControl>[0],\n schema as Parameters<typeof isStringControl>[1],\n {} as Parameters<typeof isStringControl>[2],\n );\n };\n\n // Projection-aware schema check: when options.projection is set,\n // resolve the projected schema and test against it instead of the original\n\n const projectedSchemaMatches =\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (check: (schema: any) => boolean) =>\n (uischema: unknown, schema: unknown): boolean => {\n const ui = uischema as {\n type?: string;\n scope?: string;\n options?: { projection?: string };\n };\n const projection = ui?.options?.projection;\n if (!projection || ui?.type !== \"Control\" || !ui?.scope) return false;\n\n const propertySchema = resolveScopeSchema(\n ui.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n if (!propertySchema) return false;\n\n return check(getProjectedSchema(propertySchema, projection));\n };\n\n const isMultilineProjection = (uischema: unknown, schema: unknown) => {\n const ui = uischema as { options?: { multi?: boolean } };\n return (\n ui?.options?.multi === true &&\n projectedSchemaMatches((s) => s?.type === \"string\")(uischema, schema)\n );\n };\n\n const renderers = [\n // Multiline text has higher priority than regular text\n {\n tester: rankWith(PRIME + 4, or(isMultilineString, isMultilineProjection)),\n renderer: JfTextArea,\n },\n {\n tester: rankWith(\n PRIME + 3,\n or(\n isStringControl,\n projectedSchemaMatches((s) => s?.type === \"string\"),\n ),\n ),\n renderer: JfText,\n },\n {\n tester: rankWith(\n PRIME + 6,\n or(\n isIntegerControl,\n projectedSchemaMatches((s) => s?.type === \"integer\"),\n ),\n ),\n renderer: JfNumber,\n },\n {\n tester: rankWith(\n PRIME + 4,\n or(\n isNumberControl,\n projectedSchemaMatches((s) => s?.type === \"number\"),\n ),\n ),\n renderer: JfNumber,\n },\n {\n tester: rankWith(\n PRIME + 7,\n or(\n and(isControl, schemaMatches(isScalarEnum)),\n and(isControl, projectedSchemaMatches(isScalarEnum)),\n ),\n ),\n renderer: JfEnum,\n },\n {\n tester: rankWith(\n PRIME + 8,\n or(\n and(isControl, schemaMatches(isEnumArray)),\n and(isControl, projectedSchemaMatches(isEnumArray)),\n ),\n ),\n renderer: JfEnumArray,\n },\n {\n tester: rankWith(\n PRIME + 3,\n or(\n isBooleanControl,\n projectedSchemaMatches((s) => s?.type === \"boolean\"),\n ),\n ),\n renderer: JfBoolean,\n },\n ];\n\n // Update the exported array\n primevueRenderers.splice(0, primevueRenderers.length, ...renderers);\n\n // Mark as initialized to prevent duplicate registrations\n renderersInitialized = true;\n\n return renderers;\n}\n\nexport { JfText, JfTextArea, JfNumber, JfEnum, JfEnumArray, JfBoolean };\n"],"names":["JfTextArea","JfText","JfNumber","JfEnum","JfEnumArray","JfBoolean"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"autoSelect.js","sources":["../../../src/vue/utils/autoSelect.ts"],"sourcesContent":["import type { ProviderItem } from \"../../core/types\";\n\nexport interface AutoSelectParams {\n autoSelectSingle: boolean;\n isLoading: boolean;\n items: ProviderItem[];\n currentValue: unknown;\n}\n\n/**\n * Determines if auto-select should trigger for single-select dropdowns.\n * Returns null if auto-select should not trigger.\n *\n * Auto-select triggers when:\n * - autoSelectSingle option is enabled (default: true for single-select)\n * - Provider has finished loading\n * - Exactly one item is available\n * - Current value is empty (undefined/null) OR not in the current options\n */\nexport function shouldAutoSelect(params: AutoSelectParams): unknown | null {\n const { autoSelectSingle, isLoading, items, currentValue } = params;\n\n if (!autoSelectSingle || isLoading || items.length !== 1) {\n return null;\n }\n\n const singleItem = items[0];\n if (!singleItem) {\n return null;\n }\n\n const isValueEmpty = currentValue === undefined || currentValue === null;\n const isValueInOptions = items.some((item) => item.value === currentValue);\n\n if (isValueEmpty || !isValueInOptions) {\n return singleItem.value;\n }\n\n return null;\n}\n\nexport interface AutoSelectMultiParams {\n autoSelectSingle: boolean;\n isLoading: boolean;\n items: ProviderItem[];\n currentValue: unknown[];\n}\n\n/**\n * Determines if auto-select should trigger for multiselect dropdowns.\n * Returns null if auto-select should not trigger, otherwise returns an array with the single value.\n *\n * Auto-select triggers when:\n * - autoSelectSingle option is explicitly enabled (default: false for multiselect)\n * - Provider has finished loading\n * - Exactly one item is available\n * - Current value is empty array OR current selection is not in the current options\n */\nexport function shouldAutoSelectMulti(\n params: AutoSelectMultiParams
|
|
1
|
+
{"version":3,"file":"autoSelect.js","sources":["../../../src/vue/utils/autoSelect.ts"],"sourcesContent":["import type { ProviderItem } from \"../../core/types\";\n\nexport interface AutoSelectParams {\n autoSelectSingle: boolean;\n isLoading: boolean;\n items: ProviderItem[];\n currentValue: unknown;\n}\n\n/**\n * Determines if auto-select should trigger for single-select dropdowns.\n * Returns null if auto-select should not trigger.\n *\n * Auto-select triggers when:\n * - autoSelectSingle option is enabled (default: true for single-select)\n * - Provider has finished loading\n * - Exactly one item is available\n * - Current value is empty (undefined/null) OR not in the current options\n */\nexport function shouldAutoSelect(params: AutoSelectParams): unknown | null {\n const { autoSelectSingle, isLoading, items, currentValue } = params;\n\n if (!autoSelectSingle || isLoading || items.length !== 1) {\n return null;\n }\n\n const singleItem = items[0];\n if (!singleItem) {\n return null;\n }\n\n const isValueEmpty = currentValue === undefined || currentValue === null;\n const isValueInOptions = items.some((item) => item.value === currentValue);\n\n if (isValueEmpty || !isValueInOptions) {\n return singleItem.value;\n }\n\n return null;\n}\n\nexport interface AutoSelectMultiParams {\n autoSelectSingle: boolean;\n isLoading: boolean;\n items: ProviderItem[];\n currentValue: unknown[];\n}\n\n/**\n * Determines if auto-select should trigger for multiselect dropdowns.\n * Returns null if auto-select should not trigger, otherwise returns an array with the single value.\n *\n * Auto-select triggers when:\n * - autoSelectSingle option is explicitly enabled (default: false for multiselect)\n * - Provider has finished loading\n * - Exactly one item is available\n * - Current value is empty array OR current selection is not in the current options\n */\nexport function shouldAutoSelectMulti(\n params: AutoSelectMultiParams,\n): unknown[] | null {\n const { autoSelectSingle, isLoading, items, currentValue } = params;\n\n if (!autoSelectSingle || isLoading || items.length !== 1) {\n return null;\n }\n\n const singleItem = items[0];\n if (!singleItem) {\n return null;\n }\n\n const currentArray = Array.isArray(currentValue) ? currentValue : [];\n const isValueEmpty = currentArray.length === 0;\n const hasValidSelection = currentArray.some((val) =>\n items.some((item) => item.value === val),\n );\n\n if (isValueEmpty || !hasValidSelection) {\n return [singleItem.value];\n }\n\n return null;\n}\n"],"names":[],"mappings":"AAmBO,SAAS,iBAAiB,QAA0C;AACzE,QAAM,EAAE,kBAAkB,WAAW,OAAO,iBAAiB;AAE7D,MAAI,CAAC,oBAAoB,aAAa,MAAM,WAAW,GAAG;AACxD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,CAAC;AAC1B,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,iBAAiB,UAAa,iBAAiB;AACpE,QAAM,mBAAmB,MAAM,KAAK,CAAC,SAAS,KAAK,UAAU,YAAY;AAEzE,MAAI,gBAAgB,CAAC,kBAAkB;AACrC,WAAO,WAAW;AAAA,EACpB;AAEA,SAAO;AACT;AAmBO,SAAS,sBACd,QACkB;AAClB,QAAM,EAAE,kBAAkB,WAAW,OAAO,iBAAiB;AAE7D,MAAI,CAAC,oBAAoB,aAAa,MAAM,WAAW,GAAG;AACxD,WAAO;AAAA,EACT;AAEA,QAAM,aAAa,MAAM,CAAC;AAC1B,MAAI,CAAC,YAAY;AACf,WAAO;AAAA,EACT;AAEA,QAAM,eAAe,MAAM,QAAQ,YAAY,IAAI,eAAe,CAAA;AAClE,QAAM,eAAe,aAAa,WAAW;AAC7C,QAAM,oBAAoB,aAAa;AAAA,IAAK,CAAC,QAC3C,MAAM,KAAK,CAAC,SAAS,KAAK,UAAU,GAAG;AAAA,EAAA;AAGzC,MAAI,gBAAgB,CAAC,mBAAmB;AACtC,WAAO,CAAC,WAAW,KAAK;AAAA,EAC1B;AAEA,SAAO;AACT;"}
|
package/package.json
CHANGED
package/src/core/projection.ts
CHANGED
|
@@ -26,10 +26,7 @@ export function parseProjectionPath(path: string): ProjectionSegment[] {
|
|
|
26
26
|
* Read a value from `data` by following the projection path.
|
|
27
27
|
* Returns `undefined` if any segment along the path is missing.
|
|
28
28
|
*/
|
|
29
|
-
export function getProjectedValue(
|
|
30
|
-
data: unknown,
|
|
31
|
-
path: string,
|
|
32
|
-
): unknown {
|
|
29
|
+
export function getProjectedValue(data: unknown, path: string): unknown {
|
|
33
30
|
const segments = parseProjectionPath(path);
|
|
34
31
|
let current: unknown = data;
|
|
35
32
|
|
|
@@ -85,7 +82,10 @@ function setAtPath(
|
|
|
85
82
|
} else {
|
|
86
83
|
// Object key — ensure we have an object
|
|
87
84
|
const obj: Record<string, unknown> =
|
|
88
|
-
current !== null &&
|
|
85
|
+
current !== null &&
|
|
86
|
+
current !== undefined &&
|
|
87
|
+
typeof current === "object" &&
|
|
88
|
+
!Array.isArray(current)
|
|
89
89
|
? { ...(current as Record<string, unknown>) }
|
|
90
90
|
: {};
|
|
91
91
|
obj[seg] = setAtPath(obj[seg], segments, index + 1, value);
|
package/src/core/transforms.ts
CHANGED
|
@@ -14,7 +14,16 @@ export interface FlattenTransform extends Transform {
|
|
|
14
14
|
labelFormat?: string; // Optional format string like "{parent.name} → {name}"
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export type FilterOperator =
|
|
17
|
+
export type FilterOperator =
|
|
18
|
+
| "eq"
|
|
19
|
+
| "neq"
|
|
20
|
+
| "empty"
|
|
21
|
+
| "notEmpty"
|
|
22
|
+
| "gt"
|
|
23
|
+
| "gte"
|
|
24
|
+
| "lt"
|
|
25
|
+
| "lte"
|
|
26
|
+
| "contains";
|
|
18
27
|
|
|
19
28
|
export interface FilterCondition {
|
|
20
29
|
key: string;
|
|
@@ -153,13 +162,29 @@ function evaluateCondition(
|
|
|
153
162
|
case "notEmpty":
|
|
154
163
|
return !isEmpty(value);
|
|
155
164
|
case "gt":
|
|
156
|
-
return
|
|
165
|
+
return (
|
|
166
|
+
typeof value === "number" &&
|
|
167
|
+
condition.values !== undefined &&
|
|
168
|
+
value > (condition.values[0] as number)
|
|
169
|
+
);
|
|
157
170
|
case "gte":
|
|
158
|
-
return
|
|
171
|
+
return (
|
|
172
|
+
typeof value === "number" &&
|
|
173
|
+
condition.values !== undefined &&
|
|
174
|
+
value >= (condition.values[0] as number)
|
|
175
|
+
);
|
|
159
176
|
case "lt":
|
|
160
|
-
return
|
|
177
|
+
return (
|
|
178
|
+
typeof value === "number" &&
|
|
179
|
+
condition.values !== undefined &&
|
|
180
|
+
value < (condition.values[0] as number)
|
|
181
|
+
);
|
|
161
182
|
case "lte":
|
|
162
|
-
return
|
|
183
|
+
return (
|
|
184
|
+
typeof value === "number" &&
|
|
185
|
+
condition.values !== undefined &&
|
|
186
|
+
value <= (condition.values[0] as number)
|
|
187
|
+
);
|
|
163
188
|
case "contains":
|
|
164
189
|
if (typeof value === "string" && condition.values) {
|
|
165
190
|
return condition.values.some((v) => value.includes(String(v)));
|
|
@@ -208,7 +233,9 @@ function filterTransform(items: unknown[], config: Transform): unknown[] {
|
|
|
208
233
|
return items.filter((item) => {
|
|
209
234
|
if (typeof item !== "object" || item === null) return false;
|
|
210
235
|
const itemObj = item as Record<string, unknown>;
|
|
211
|
-
return conditions.every((condition) =>
|
|
236
|
+
return conditions.every((condition) =>
|
|
237
|
+
evaluateCondition(itemObj, condition),
|
|
238
|
+
);
|
|
212
239
|
});
|
|
213
240
|
}
|
|
214
241
|
|
|
@@ -12,7 +12,10 @@ const props = defineProps<{
|
|
|
12
12
|
path: string;
|
|
13
13
|
}>();
|
|
14
14
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
15
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
15
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
16
|
+
control,
|
|
17
|
+
rawHandleChange,
|
|
18
|
+
);
|
|
16
19
|
|
|
17
20
|
const binding = computed(() => {
|
|
18
21
|
const provider = control.value.uischema?.options?.provider;
|
|
@@ -53,16 +56,16 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
53
56
|
</script>
|
|
54
57
|
|
|
55
58
|
<template>
|
|
56
|
-
<div class="
|
|
57
|
-
<label v-if="control.schema.title" class="
|
|
59
|
+
<div class="jf-control">
|
|
60
|
+
<label v-if="control.schema.title" class="jf-label">{{
|
|
58
61
|
control.schema.title
|
|
59
62
|
}}</label>
|
|
60
|
-
<div v-if="control.description" class="
|
|
63
|
+
<div v-if="control.description" class="jf-description">
|
|
61
64
|
{{ control.description }}
|
|
62
65
|
</div>
|
|
63
66
|
<AutoComplete
|
|
64
67
|
v-model="value"
|
|
65
|
-
class="w-full"
|
|
68
|
+
class="w-full!"
|
|
66
69
|
:suggestions="items"
|
|
67
70
|
option-label="label"
|
|
68
71
|
:placeholder="placeholder"
|
|
@@ -13,7 +13,10 @@ const props = defineProps<{
|
|
|
13
13
|
path: string;
|
|
14
14
|
}>();
|
|
15
15
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
16
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
16
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
17
|
+
control,
|
|
18
|
+
rawHandleChange,
|
|
19
|
+
);
|
|
17
20
|
|
|
18
21
|
const binding = computed(() => {
|
|
19
22
|
const provider = control.value.uischema?.options?.provider;
|
|
@@ -55,14 +58,16 @@ watch(
|
|
|
55
58
|
control.value.uischema?.options?.autoSelectSingle === true,
|
|
56
59
|
isLoading,
|
|
57
60
|
items: newItems,
|
|
58
|
-
currentValue: Array.isArray(projectedData.value)
|
|
61
|
+
currentValue: Array.isArray(projectedData.value)
|
|
62
|
+
? projectedData.value
|
|
63
|
+
: [],
|
|
59
64
|
});
|
|
60
65
|
|
|
61
66
|
if (valueToSelect !== null) {
|
|
62
67
|
handleChange(control.value.path, valueToSelect);
|
|
63
68
|
}
|
|
64
69
|
},
|
|
65
|
-
{ immediate: true }
|
|
70
|
+
{ immediate: true },
|
|
66
71
|
);
|
|
67
72
|
|
|
68
73
|
// order-insensitive shallow equality for primitive arrays
|
|
@@ -98,16 +103,16 @@ const placeholder = computed(() => {
|
|
|
98
103
|
</script>
|
|
99
104
|
|
|
100
105
|
<template>
|
|
101
|
-
<div class="
|
|
102
|
-
<label v-if="control.schema.title" class="
|
|
106
|
+
<div class="jf-control">
|
|
107
|
+
<label v-if="control.schema.title" class="jf-label">{{
|
|
103
108
|
control.schema.title
|
|
104
109
|
}}</label>
|
|
105
|
-
<div v-if="control.description" class="
|
|
110
|
+
<div v-if="control.description" class="jf-description">
|
|
106
111
|
{{ control.description }}
|
|
107
112
|
</div>
|
|
108
113
|
<MultiSelect
|
|
109
114
|
v-model="value"
|
|
110
|
-
class="w-full"
|
|
115
|
+
class="w-full!"
|
|
111
116
|
:options="items"
|
|
112
117
|
option-label="label"
|
|
113
118
|
option-value="value"
|
|
@@ -13,7 +13,10 @@ const props = defineProps<{
|
|
|
13
13
|
path: string;
|
|
14
14
|
}>();
|
|
15
15
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
16
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
16
|
+
const { projectedData, handleProjectedChange: handleChange } = useProjection(
|
|
17
|
+
control,
|
|
18
|
+
rawHandleChange,
|
|
19
|
+
);
|
|
17
20
|
|
|
18
21
|
const binding = computed(() => {
|
|
19
22
|
const provider = control.value.uischema?.options?.provider;
|
|
@@ -62,7 +65,7 @@ watch(
|
|
|
62
65
|
handleChange(control.value.path, valueToSelect);
|
|
63
66
|
}
|
|
64
67
|
},
|
|
65
|
-
{ immediate: true }
|
|
68
|
+
{ immediate: true },
|
|
66
69
|
);
|
|
67
70
|
|
|
68
71
|
const value = computed({
|
|
@@ -81,16 +84,16 @@ const placeholder = computed(() => {
|
|
|
81
84
|
</script>
|
|
82
85
|
|
|
83
86
|
<template>
|
|
84
|
-
<div class="
|
|
85
|
-
<label v-if="control.schema.title" class="
|
|
87
|
+
<div class="jf-control">
|
|
88
|
+
<label v-if="control.schema.title" class="jf-label">{{
|
|
86
89
|
control.schema.title
|
|
87
90
|
}}</label>
|
|
88
|
-
<div v-if="control.description" class="
|
|
91
|
+
<div v-if="control.description" class="jf-description">
|
|
89
92
|
{{ control.description }}
|
|
90
93
|
</div>
|
|
91
94
|
<Dropdown
|
|
92
95
|
v-model="value"
|
|
93
|
-
class="w-full"
|
|
96
|
+
class="w-full!"
|
|
94
97
|
:options="items"
|
|
95
98
|
option-label="label"
|
|
96
99
|
option-value="value"
|
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
computed,
|
|
3
|
+
watch,
|
|
4
|
+
unref,
|
|
5
|
+
inject,
|
|
6
|
+
type Ref,
|
|
7
|
+
type ComputedRef,
|
|
8
|
+
} from "vue";
|
|
2
9
|
import { type ControlElement } from "@jsonforms/core";
|
|
3
10
|
import { useDataLayer } from "./useDataLayer";
|
|
4
11
|
|
|
@@ -14,7 +21,11 @@ interface DeriveOptions {
|
|
|
14
21
|
data?: Ref<unknown> | ComputedRef<unknown>;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
|
-
export function useDerive({
|
|
24
|
+
export function useDerive({
|
|
25
|
+
control,
|
|
26
|
+
handleChange,
|
|
27
|
+
data: dataOverride,
|
|
28
|
+
}: DeriveOptions) {
|
|
18
29
|
// Get the root form data from JSONForms context
|
|
19
30
|
const injectedFormData = inject<{ value: unknown }>("formData", {
|
|
20
31
|
value: {},
|
|
@@ -50,7 +61,9 @@ export function useDerive({ control, handleChange, data: dataOverride }: DeriveO
|
|
|
50
61
|
data,
|
|
51
62
|
extData,
|
|
52
63
|
);
|
|
53
|
-
const compareData = dataOverride
|
|
64
|
+
const compareData = dataOverride
|
|
65
|
+
? unref(dataOverride)
|
|
66
|
+
: control.value.data;
|
|
54
67
|
if (derivedValue !== compareData) {
|
|
55
68
|
handleChange(control.value.path, derivedValue);
|
|
56
69
|
}
|
|
@@ -27,15 +27,9 @@ interface ErrorLike {
|
|
|
27
27
|
* Resolve the display label for a control.
|
|
28
28
|
* Priority: uischema options.label → schemaTitle (projected sub-schema) → control.label.
|
|
29
29
|
*/
|
|
30
|
-
function resolveLabel(
|
|
31
|
-
ctrl: ProjectionControl,
|
|
32
|
-
schemaTitle?: string,
|
|
33
|
-
): string {
|
|
30
|
+
function resolveLabel(ctrl: ProjectionControl, schemaTitle?: string): string {
|
|
34
31
|
return (
|
|
35
|
-
(ctrl.uischema?.options?.label as string) ??
|
|
36
|
-
schemaTitle ??
|
|
37
|
-
ctrl.label ??
|
|
38
|
-
""
|
|
32
|
+
(ctrl.uischema?.options?.label as string) ?? schemaTitle ?? ctrl.label ?? ""
|
|
39
33
|
);
|
|
40
34
|
}
|
|
41
35
|
|
|
@@ -69,7 +63,9 @@ function prefixErrors(label: string, errors: string): string {
|
|
|
69
63
|
function getErrorPath(error: ErrorLike): string {
|
|
70
64
|
let p = (error.instancePath || "").replace(/\//g, ".").replace(/^\./, "");
|
|
71
65
|
if (error.keyword === "required" && error.params?.missingProperty) {
|
|
72
|
-
p = p
|
|
66
|
+
p = p
|
|
67
|
+
? p + "." + error.params.missingProperty
|
|
68
|
+
: error.params.missingProperty;
|
|
73
69
|
}
|
|
74
70
|
return p;
|
|
75
71
|
}
|
|
@@ -160,9 +156,7 @@ export function useProjection(
|
|
|
160
156
|
errStr = baseErrors;
|
|
161
157
|
} else {
|
|
162
158
|
const projMsg = matching
|
|
163
|
-
.map((e) =>
|
|
164
|
-
e.keyword === "required" ? "is required" : e.message,
|
|
165
|
-
)
|
|
159
|
+
.map((e) => (e.keyword === "required" ? "is required" : e.message))
|
|
166
160
|
.filter(Boolean)
|
|
167
161
|
.join("\n");
|
|
168
162
|
errStr = [baseErrors, projMsg].filter(Boolean).join("\n");
|
package/src/vue/index.ts
CHANGED
|
@@ -22,8 +22,11 @@ const isIntegerScope = (uischema: unknown, schema: unknown) => {
|
|
|
22
22
|
const ui = uischema as { type?: string; scope?: string };
|
|
23
23
|
if (ui?.type !== "Control" || !ui?.scope) return false;
|
|
24
24
|
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
const propertySchema = resolveScopeSchema(
|
|
26
|
+
ui.scope,
|
|
27
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
+
schema as Record<string, any>,
|
|
29
|
+
);
|
|
27
30
|
return propertySchema?.type === "integer";
|
|
28
31
|
};
|
|
29
32
|
|
|
@@ -53,8 +56,11 @@ const isArrayControl = (uischema: UISchemaElement, schema: unknown) => {
|
|
|
53
56
|
return false;
|
|
54
57
|
}
|
|
55
58
|
|
|
56
|
-
|
|
57
|
-
|
|
59
|
+
const propertySchema = resolveScopeSchema(
|
|
60
|
+
controlSchema.scope,
|
|
61
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
62
|
+
schema as Record<string, any>,
|
|
63
|
+
);
|
|
58
64
|
return propertySchema?.type === "array";
|
|
59
65
|
};
|
|
60
66
|
|
|
@@ -49,7 +49,12 @@ 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
60
|
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
@@ -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="projectedLabel">{{ projectedLabel }}</label>
|
|
78
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
74
79
|
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
75
80
|
</div>
|
|
76
81
|
</template>
|
|
@@ -54,7 +54,12 @@ import Dropdown from "primevue/dropdown";
|
|
|
54
54
|
const instance = getCurrentInstance()!;
|
|
55
55
|
const props = instance.props as unknown as ControlProps;
|
|
56
56
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
57
|
-
const {
|
|
57
|
+
const {
|
|
58
|
+
projectedData,
|
|
59
|
+
handleProjectedChange: handleChange,
|
|
60
|
+
projectedErrors,
|
|
61
|
+
projectedLabel,
|
|
62
|
+
} = useProjection(control, rawHandleChange);
|
|
58
63
|
|
|
59
64
|
type Opt = { label: string; value: unknown };
|
|
60
65
|
const toOptions = (schema?: JsonSchema): Opt[] => {
|
|
@@ -158,7 +163,7 @@ watch(
|
|
|
158
163
|
handleChange(control.value.path, valueToSelect);
|
|
159
164
|
}
|
|
160
165
|
},
|
|
161
|
-
{ immediate: true }
|
|
166
|
+
{ immediate: true },
|
|
162
167
|
);
|
|
163
168
|
|
|
164
169
|
// Track user interaction — errors only show after blur
|
|
@@ -170,15 +175,13 @@ const onSelect = (val: unknown) => {
|
|
|
170
175
|
</script>
|
|
171
176
|
|
|
172
177
|
<template>
|
|
173
|
-
<div class="
|
|
174
|
-
<label v-if="projectedLabel" class="
|
|
175
|
-
|
|
176
|
-
}}</label>
|
|
177
|
-
<div v-if="control.description" class="text-color-secondary text-left">
|
|
178
|
+
<div class="jf-control">
|
|
179
|
+
<label v-if="projectedLabel" class="jf-label">{{ projectedLabel }}</label>
|
|
180
|
+
<div v-if="control.description" class="jf-description">
|
|
178
181
|
{{ control.description }}
|
|
179
182
|
</div>
|
|
180
183
|
<Dropdown
|
|
181
|
-
:class="['w-full', { 'p-invalid': showErrors }]"
|
|
184
|
+
:class="['w-full!', { 'p-invalid': showErrors }]"
|
|
182
185
|
:options="options"
|
|
183
186
|
option-label="label"
|
|
184
187
|
option-value="value"
|