@narrative.io/jsonforms-provider-protocols 3.0.0-beta.2 → 3.0.0-beta.3
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/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 +6 -0
- package/dist/vue/composables/useProjection.d.ts.map +1 -1
- package/dist/vue/composables/useProjection.js +56 -3
- package/dist/vue/composables/useProjection.js.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -1
- package/dist/vue/primevue/JfBoolean.vue.js +4 -4
- 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 +4 -4
- 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 +4 -4
- 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 +4 -4
- 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 +4 -4
- 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 +4 -4
- package/dist/vue/primevue/JfTextArea.vue.js.map +1 -1
- package/package.json +3 -1
- package/src/vue/composables/useDirtyValidation.ts +8 -3
- package/src/vue/composables/useProjection.ts +114 -1
- package/src/vue/primevue/JfBoolean.vue +4 -4
- package/src/vue/primevue/JfEnum.vue +5 -5
- package/src/vue/primevue/JfEnumArray.vue +5 -5
- package/src/vue/primevue/JfNumber.vue +5 -5
- package/src/vue/primevue/JfText.vue +5 -5
- package/src/vue/primevue/JfTextArea.vue +5 -5
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { type Ref } from "vue";
|
|
1
|
+
import { type Ref, type ComputedRef } from "vue";
|
|
2
2
|
export declare function useDirtyValidation(control: Ref<{
|
|
3
3
|
errors: string;
|
|
4
|
-
}>): {
|
|
4
|
+
}>, errorsOverride?: Ref<string> | ComputedRef<string>): {
|
|
5
5
|
hasInteracted: Ref<boolean, boolean>;
|
|
6
|
-
showErrors:
|
|
6
|
+
showErrors: ComputedRef<boolean>;
|
|
7
7
|
markDirty: () => void;
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=useDirtyValidation.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDirtyValidation.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useDirtyValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"useDirtyValidation.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useDirtyValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,GAAG,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAEhE,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,GAAG,CAAC;IAAE,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC,EAChC,cAAc,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;;;;EAenD"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { ref, computed } from "vue";
|
|
2
|
-
function useDirtyValidation(control) {
|
|
2
|
+
function useDirtyValidation(control, errorsOverride) {
|
|
3
3
|
const hasInteracted = ref(false);
|
|
4
4
|
const showErrors = computed(
|
|
5
|
-
() => hasInteracted.value && !!control.value.errors
|
|
5
|
+
() => hasInteracted.value && !!(errorsOverride ? errorsOverride.value : control.value.errors)
|
|
6
6
|
);
|
|
7
7
|
const markDirty = () => {
|
|
8
8
|
hasInteracted.value = true;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useDirtyValidation.js","sources":["../../../src/vue/composables/useDirtyValidation.ts"],"sourcesContent":["import { ref, computed, type Ref } from \"vue\";\n\nexport function useDirtyValidation(control: Ref<{ errors: string }>) {\n const hasInteracted = ref(false);\n\n const showErrors = computed(\n ()
|
|
1
|
+
{"version":3,"file":"useDirtyValidation.js","sources":["../../../src/vue/composables/useDirtyValidation.ts"],"sourcesContent":["import { ref, computed, type Ref, type ComputedRef } from \"vue\";\n\nexport function useDirtyValidation(\n control: Ref<{ errors: string }>,\n errorsOverride?: Ref<string> | ComputedRef<string>,\n) {\n const hasInteracted = ref(false);\n\n const showErrors = computed(\n () =>\n hasInteracted.value &&\n !!(errorsOverride ? errorsOverride.value : control.value.errors),\n );\n\n const markDirty = () => {\n hasInteracted.value = true;\n };\n\n return { hasInteracted, showErrors, markDirty };\n}\n"],"names":[],"mappings":";AAEO,SAAS,mBACd,SACA,gBACA;AACA,QAAM,gBAAgB,IAAI,KAAK;AAE/B,QAAM,aAAa;AAAA,IACjB,MACE,cAAc,SACd,CAAC,EAAE,iBAAiB,eAAe,QAAQ,QAAQ,MAAM;AAAA,EAAA;AAG7D,QAAM,YAAY,MAAM;AACtB,kBAAc,QAAQ;AAAA,EACxB;AAEA,SAAO,EAAE,eAAe,YAAY,UAAA;AACtC;"}
|
|
@@ -2,6 +2,8 @@ import { type ComputedRef, type Ref } from "vue";
|
|
|
2
2
|
interface ProjectionControl {
|
|
3
3
|
data: unknown;
|
|
4
4
|
path: string;
|
|
5
|
+
errors: string;
|
|
6
|
+
label?: string;
|
|
5
7
|
schema: Record<string, any>;
|
|
6
8
|
uischema: {
|
|
7
9
|
options?: {
|
|
@@ -19,6 +21,10 @@ export interface ProjectionResult {
|
|
|
19
21
|
handleProjectedChange: (path: string, value: unknown) => void;
|
|
20
22
|
/** Whether projection is active */
|
|
21
23
|
hasProjection: boolean;
|
|
24
|
+
/** Resolved display label (options.label → projected schema title → control.label) */
|
|
25
|
+
projectedLabel: ComputedRef<string>;
|
|
26
|
+
/** Error string combining base-path and projected sub-path errors */
|
|
27
|
+
projectedErrors: ComputedRef<string>;
|
|
22
28
|
}
|
|
23
29
|
/**
|
|
24
30
|
* Composable that wraps a JSON Forms control with projection support.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProjection.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useProjection.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"useProjection.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useProjection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,WAAW,EAAE,KAAK,GAAG,EAAE,MAAM,KAAK,CAAC;AAOnE,UAAU,iBAAiB;IACzB,IAAI,EAAE,OAAO,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,QAAQ,EAAE;QAAE,OAAO,CAAC,EAAE;YAAE,UAAU,CAAC,EAAE,MAAM,CAAC;YAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;SAAE,CAAA;KAAE,CAAC;CACzE;AA6DD,MAAM,WAAW,gBAAgB;IAC/B,sDAAsD;IACtD,aAAa,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;IACpC,gEAAgE;IAEhE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC;IAClD,8DAA8D;IAC9D,qBAAqB,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC9D,mCAAmC;IACnC,aAAa,EAAE,OAAO,CAAC;IACvB,sFAAsF;IACtF,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpC,qEAAqE;IACrE,eAAe,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;CACtC;AAED;;;;;;;;;GASG;AACH,wBAAgB,aAAa,CAC3B,OAAO,EAAE,GAAG,CAAC,iBAAiB,CAAC,EAC/B,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,GACnD,gBAAgB,CAiFlB"}
|
|
@@ -1,21 +1,72 @@
|
|
|
1
|
-
import { computed } from "vue";
|
|
1
|
+
import { computed, inject } from "vue";
|
|
2
2
|
import { getProjectedValue, getProjectedSchema, setProjectedValue } from "../../core/projection.js";
|
|
3
|
+
function resolveLabel(ctrl, schemaTitle) {
|
|
4
|
+
return ctrl.uischema?.options?.label ?? schemaTitle ?? ctrl.label ?? "";
|
|
5
|
+
}
|
|
6
|
+
function normalizeErrors(errors) {
|
|
7
|
+
if (!errors) return errors;
|
|
8
|
+
return errors.replace(/is a required property/g, "is required").replace(/must have required property '[^']*'/g, "is required");
|
|
9
|
+
}
|
|
10
|
+
function prefixErrors(label, errors) {
|
|
11
|
+
if (!label || !errors) return errors;
|
|
12
|
+
return errors.split("\n").map((line) => `${label} ${line}`).join("\n");
|
|
13
|
+
}
|
|
14
|
+
function getErrorPath(error) {
|
|
15
|
+
let p = (error.instancePath || "").replace(/\//g, ".").replace(/^\./, "");
|
|
16
|
+
if (error.keyword === "required" && error.params?.missingProperty) {
|
|
17
|
+
p = p ? p + "." + error.params.missingProperty : error.params.missingProperty;
|
|
18
|
+
}
|
|
19
|
+
return p;
|
|
20
|
+
}
|
|
3
21
|
function useProjection(control, handleChange) {
|
|
4
22
|
const projection = control.value.uischema?.options?.projection;
|
|
5
23
|
if (!projection) {
|
|
24
|
+
const label2 = computed(() => resolveLabel(control.value));
|
|
6
25
|
return {
|
|
7
26
|
projectedData: computed(() => control.value.data),
|
|
8
27
|
projectedSchema: computed(() => control.value.schema),
|
|
9
28
|
handleProjectedChange: handleChange,
|
|
10
|
-
hasProjection: false
|
|
29
|
+
hasProjection: false,
|
|
30
|
+
projectedLabel: label2,
|
|
31
|
+
projectedErrors: computed(
|
|
32
|
+
() => prefixErrors(
|
|
33
|
+
label2.value.replace(/\*$/, "").trim(),
|
|
34
|
+
normalizeErrors(control.value.errors)
|
|
35
|
+
)
|
|
36
|
+
)
|
|
11
37
|
};
|
|
12
38
|
}
|
|
39
|
+
const jsonforms = inject(
|
|
40
|
+
"jsonforms",
|
|
41
|
+
null
|
|
42
|
+
);
|
|
43
|
+
const fullProjectedPath = control.value.path + "." + projection;
|
|
13
44
|
const projectedData = computed(
|
|
14
45
|
() => getProjectedValue(control.value.data, projection)
|
|
15
46
|
);
|
|
16
47
|
const projectedSchema = computed(
|
|
17
48
|
() => getProjectedSchema(control.value.schema, projection)
|
|
18
49
|
);
|
|
50
|
+
const label = computed(
|
|
51
|
+
() => resolveLabel(control.value, projectedSchema.value?.title)
|
|
52
|
+
);
|
|
53
|
+
const projectedErrors = computed(() => {
|
|
54
|
+
const baseErrors = normalizeErrors(control.value.errors || "");
|
|
55
|
+
const rawErrors = jsonforms?.core?.errors ?? [];
|
|
56
|
+
const matching = rawErrors.filter(
|
|
57
|
+
(err) => getErrorPath(err) === fullProjectedPath
|
|
58
|
+
);
|
|
59
|
+
let errStr;
|
|
60
|
+
if (matching.length === 0) {
|
|
61
|
+
errStr = baseErrors;
|
|
62
|
+
} else {
|
|
63
|
+
const projMsg = matching.map(
|
|
64
|
+
(e) => e.keyword === "required" ? "is required" : e.message
|
|
65
|
+
).filter(Boolean).join("\n");
|
|
66
|
+
errStr = [baseErrors, projMsg].filter(Boolean).join("\n");
|
|
67
|
+
}
|
|
68
|
+
return prefixErrors(label.value.replace(/\*$/, "").trim(), errStr);
|
|
69
|
+
});
|
|
19
70
|
const handleProjectedChange = (path, value) => {
|
|
20
71
|
const fullValue = setProjectedValue(control.value.data, projection, value);
|
|
21
72
|
handleChange(path, fullValue);
|
|
@@ -24,7 +75,9 @@ function useProjection(control, handleChange) {
|
|
|
24
75
|
projectedData,
|
|
25
76
|
projectedSchema,
|
|
26
77
|
handleProjectedChange,
|
|
27
|
-
hasProjection: true
|
|
78
|
+
hasProjection: true,
|
|
79
|
+
projectedLabel: label,
|
|
80
|
+
projectedErrors
|
|
28
81
|
};
|
|
29
82
|
}
|
|
30
83
|
export {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useProjection.js","sources":["../../../src/vue/composables/useProjection.ts"],"sourcesContent":["import { computed, type ComputedRef, type Ref } from \"vue\";\nimport {\n getProjectedValue,\n setProjectedValue,\n getProjectedSchema,\n} from \"../../core/projection\";\n\ninterface ProjectionControl {\n data: unknown;\n path: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: Record<string, any>;\n uischema: { options?: { projection?: string; [key: string]: unknown } };\n}\n\nexport interface ProjectionResult {\n /** The value at the projected path (for rendering) */\n projectedData: ComputedRef<unknown>;\n /** The schema at the projected path (for renderer selection) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n projectedSchema: ComputedRef<Record<string, any>>;\n /** Wrapped handleChange that writes through the projection */\n handleProjectedChange: (path: string, value: unknown) => void;\n /** Whether projection is active */\n hasProjection: boolean;\n}\n\n/**\n * Composable that wraps a JSON Forms control with projection support.\n *\n * When `options.projection` is set on the uischema, this composable:\n * - Reads the projected sub-value from the control data\n * - Resolves the projected sub-schema for renderer type resolution\n * - Wraps handleChange to write back through the projection path (preserving siblings)\n *\n * When no projection is set, it passes through control data/schema/handleChange unchanged.\n */\nexport function useProjection(\n control: Ref<ProjectionControl>,\n handleChange: (path: string, value: unknown) => void,\n): ProjectionResult {\n const projection = control.value.uischema?.options?.projection as\n | string\n | undefined;\n\n if (!projection) {\n return {\n projectedData: computed(() => control.value.data),\n projectedSchema: computed(() => control.value.schema),\n handleProjectedChange: handleChange,\n hasProjection: false,\n };\n }\n\n const projectedData = computed(() =>\n getProjectedValue(control.value.data, projection),\n );\n\n const projectedSchema = computed(() =>\n getProjectedSchema(control.value.schema, projection),\n );\n\n const handleProjectedChange = (path: string, value: unknown) => {\n const fullValue = setProjectedValue(control.value.data, projection, value);\n handleChange(path, fullValue);\n };\n\n return {\n projectedData,\n projectedSchema,\n handleProjectedChange,\n hasProjection: true,\n };\n}\n"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"useProjection.js","sources":["../../../src/vue/composables/useProjection.ts"],"sourcesContent":["import { computed, inject, type ComputedRef, type Ref } from \"vue\";\nimport {\n getProjectedValue,\n setProjectedValue,\n getProjectedSchema,\n} from \"../../core/projection\";\n\ninterface ProjectionControl {\n data: unknown;\n path: string;\n errors: string;\n label?: string;\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema: Record<string, any>;\n uischema: { options?: { projection?: string; [key: string]: unknown } };\n}\n\n// Minimal AJV ErrorObject shape for filtering\ninterface ErrorLike {\n instancePath?: string;\n keyword?: string;\n message?: string;\n params?: { missingProperty?: string };\n}\n\n/**\n * Resolve the display label for a control.\n * Priority: uischema options.label → schemaTitle (projected sub-schema) → control.label.\n */\nfunction resolveLabel(\n ctrl: ProjectionControl,\n schemaTitle?: string,\n): string {\n return (\n (ctrl.uischema?.options?.label as string) ??\n schemaTitle ??\n ctrl.label ??\n \"\"\n );\n}\n\n/**\n * Normalize AJV error message fragments into user-friendly text.\n * e.g. \"is a required property\" → \"is required\"\n */\nfunction normalizeErrors(errors: string): string {\n if (!errors) return errors;\n return errors\n .replace(/is a required property/g, \"is required\")\n .replace(/must have required property '[^']*'/g, \"is required\");\n}\n\n/**\n * Prefix each error message line with the field label so that AJV fragments\n * like \"is required\" become \"Name is required\".\n */\nfunction prefixErrors(label: string, errors: string): string {\n if (!label || !errors) return errors;\n return errors\n .split(\"\\n\")\n .map((line) => `${label} ${line}`)\n .join(\"\\n\");\n}\n\n/**\n * Convert an AJV ErrorObject's instancePath to a dot-separated control path.\n * Replicates the logic from @jsonforms/core getControlPath.\n */\nfunction getErrorPath(error: ErrorLike): string {\n let p = (error.instancePath || \"\").replace(/\\//g, \".\").replace(/^\\./, \"\");\n if (error.keyword === \"required\" && error.params?.missingProperty) {\n p = p ? p + \".\" + error.params.missingProperty : error.params.missingProperty;\n }\n return p;\n}\n\nexport interface ProjectionResult {\n /** The value at the projected path (for rendering) */\n projectedData: ComputedRef<unknown>;\n /** The schema at the projected path (for renderer selection) */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n projectedSchema: ComputedRef<Record<string, any>>;\n /** Wrapped handleChange that writes through the projection */\n handleProjectedChange: (path: string, value: unknown) => void;\n /** Whether projection is active */\n hasProjection: boolean;\n /** Resolved display label (options.label → projected schema title → control.label) */\n projectedLabel: ComputedRef<string>;\n /** Error string combining base-path and projected sub-path errors */\n projectedErrors: ComputedRef<string>;\n}\n\n/**\n * Composable that wraps a JSON Forms control with projection support.\n *\n * When `options.projection` is set on the uischema, this composable:\n * - Reads the projected sub-value from the control data\n * - Resolves the projected sub-schema for renderer type resolution\n * - Wraps handleChange to write back through the projection path (preserving siblings)\n *\n * When no projection is set, it passes through control data/schema/handleChange unchanged.\n */\nexport function useProjection(\n control: Ref<ProjectionControl>,\n handleChange: (path: string, value: unknown) => void,\n): ProjectionResult {\n const projection = control.value.uischema?.options?.projection as\n | string\n | undefined;\n\n if (!projection) {\n const label = computed(() => resolveLabel(control.value));\n return {\n projectedData: computed(() => control.value.data),\n projectedSchema: computed(() => control.value.schema),\n handleProjectedChange: handleChange,\n hasProjection: false,\n projectedLabel: label,\n projectedErrors: computed(() =>\n prefixErrors(\n label.value.replace(/\\*$/, \"\").trim(),\n normalizeErrors(control.value.errors),\n ),\n ),\n };\n }\n\n // Inject JSONForms state to access raw AJV errors for projected sub-paths.\n // control.errors only contains errors at the exact control path (e.g. \"data_rates\"),\n // but projected fields need errors at the full path (e.g. \"data_rates.0.video_rate_usd\").\n const jsonforms = inject<{ core?: { errors?: ErrorLike[] } } | null>(\n \"jsonforms\",\n null,\n );\n\n const fullProjectedPath = control.value.path + \".\" + projection;\n\n const projectedData = computed(() =>\n getProjectedValue(control.value.data, projection),\n );\n\n const projectedSchema = computed(() =>\n getProjectedSchema(control.value.schema, projection),\n );\n\n const label = computed(() =>\n resolveLabel(control.value, projectedSchema.value?.title),\n );\n\n const projectedErrors = computed(() => {\n const baseErrors = normalizeErrors(control.value.errors || \"\");\n\n const rawErrors = jsonforms?.core?.errors ?? [];\n const matching = rawErrors.filter(\n (err) => getErrorPath(err) === fullProjectedPath,\n );\n\n let errStr: string;\n if (matching.length === 0) {\n errStr = baseErrors;\n } else {\n const projMsg = matching\n .map((e) =>\n e.keyword === \"required\" ? \"is required\" : e.message,\n )\n .filter(Boolean)\n .join(\"\\n\");\n errStr = [baseErrors, projMsg].filter(Boolean).join(\"\\n\");\n }\n\n return prefixErrors(label.value.replace(/\\*$/, \"\").trim(), errStr);\n });\n\n const handleProjectedChange = (path: string, value: unknown) => {\n const fullValue = setProjectedValue(control.value.data, projection, value);\n handleChange(path, fullValue);\n };\n\n return {\n projectedData,\n projectedSchema,\n handleProjectedChange,\n hasProjection: true,\n projectedLabel: label,\n projectedErrors,\n };\n}\n"],"names":["label"],"mappings":";;AA6BA,SAAS,aACP,MACA,aACQ;AACR,SACG,KAAK,UAAU,SAAS,SACzB,eACA,KAAK,SACL;AAEJ;AAMA,SAAS,gBAAgB,QAAwB;AAC/C,MAAI,CAAC,OAAQ,QAAO;AACpB,SAAO,OACJ,QAAQ,2BAA2B,aAAa,EAChD,QAAQ,wCAAwC,aAAa;AAClE;AAMA,SAAS,aAAa,OAAe,QAAwB;AAC3D,MAAI,CAAC,SAAS,CAAC,OAAQ,QAAO;AAC9B,SAAO,OACJ,MAAM,IAAI,EACV,IAAI,CAAC,SAAS,GAAG,KAAK,IAAI,IAAI,EAAE,EAChC,KAAK,IAAI;AACd;AAMA,SAAS,aAAa,OAA0B;AAC9C,MAAI,KAAK,MAAM,gBAAgB,IAAI,QAAQ,OAAO,GAAG,EAAE,QAAQ,OAAO,EAAE;AACxE,MAAI,MAAM,YAAY,cAAc,MAAM,QAAQ,iBAAiB;AACjE,QAAI,IAAI,IAAI,MAAM,MAAM,OAAO,kBAAkB,MAAM,OAAO;AAAA,EAChE;AACA,SAAO;AACT;AA4BO,SAAS,cACd,SACA,cACkB;AAClB,QAAM,aAAa,QAAQ,MAAM,UAAU,SAAS;AAIpD,MAAI,CAAC,YAAY;AACf,UAAMA,SAAQ,SAAS,MAAM,aAAa,QAAQ,KAAK,CAAC;AACxD,WAAO;AAAA,MACL,eAAe,SAAS,MAAM,QAAQ,MAAM,IAAI;AAAA,MAChD,iBAAiB,SAAS,MAAM,QAAQ,MAAM,MAAM;AAAA,MACpD,uBAAuB;AAAA,MACvB,eAAe;AAAA,MACf,gBAAgBA;AAAAA,MAChB,iBAAiB;AAAA,QAAS,MACxB;AAAA,UACEA,OAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,KAAA;AAAA,UAC/B,gBAAgB,QAAQ,MAAM,MAAM;AAAA,QAAA;AAAA,MACtC;AAAA,IACF;AAAA,EAEJ;AAKA,QAAM,YAAY;AAAA,IAChB;AAAA,IACA;AAAA,EAAA;AAGF,QAAM,oBAAoB,QAAQ,MAAM,OAAO,MAAM;AAErD,QAAM,gBAAgB;AAAA,IAAS,MAC7B,kBAAkB,QAAQ,MAAM,MAAM,UAAU;AAAA,EAAA;AAGlD,QAAM,kBAAkB;AAAA,IAAS,MAC/B,mBAAmB,QAAQ,MAAM,QAAQ,UAAU;AAAA,EAAA;AAGrD,QAAM,QAAQ;AAAA,IAAS,MACrB,aAAa,QAAQ,OAAO,gBAAgB,OAAO,KAAK;AAAA,EAAA;AAG1D,QAAM,kBAAkB,SAAS,MAAM;AACrC,UAAM,aAAa,gBAAgB,QAAQ,MAAM,UAAU,EAAE;AAE7D,UAAM,YAAY,WAAW,MAAM,UAAU,CAAA;AAC7C,UAAM,WAAW,UAAU;AAAA,MACzB,CAAC,QAAQ,aAAa,GAAG,MAAM;AAAA,IAAA;AAGjC,QAAI;AACJ,QAAI,SAAS,WAAW,GAAG;AACzB,eAAS;AAAA,IACX,OAAO;AACL,YAAM,UAAU,SACb;AAAA,QAAI,CAAC,MACJ,EAAE,YAAY,aAAa,gBAAgB,EAAE;AAAA,MAAA,EAE9C,OAAO,OAAO,EACd,KAAK,IAAI;AACZ,eAAS,CAAC,YAAY,OAAO,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAAA,IAC1D;AAEA,WAAO,aAAa,MAAM,MAAM,QAAQ,OAAO,EAAE,EAAE,KAAA,GAAQ,MAAM;AAAA,EACnE,CAAC;AAED,QAAM,wBAAwB,CAAC,MAAc,UAAmB;AAC9D,UAAM,YAAY,kBAAkB,QAAQ,MAAM,MAAM,YAAY,KAAK;AACzE,iBAAa,MAAM,SAAS;AAAA,EAC9B;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA,eAAe;AAAA,IACf,gBAAgB;AAAA,IAChB;AAAA,EAAA;AAEJ;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfBoolean.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfBoolean.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,
|
|
1
|
+
{"version":3,"file":"JfBoolean.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfBoolean.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsFA,wBA8KK"}
|
|
@@ -51,8 +51,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
51
51
|
const instance = getCurrentInstance();
|
|
52
52
|
const props = instance.props;
|
|
53
53
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
54
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
55
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
54
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
55
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
56
56
|
const onToggle = (val) => {
|
|
57
57
|
markDirty();
|
|
58
58
|
handleChange(control.value.path, val);
|
|
@@ -67,8 +67,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
67
67
|
"aria-invalid": unref(showErrors) || void 0,
|
|
68
68
|
"onUpdate:modelValue": onToggle
|
|
69
69
|
}, null, 8, ["model-value", "disabled", "class", "aria-invalid"]),
|
|
70
|
-
unref(
|
|
71
|
-
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_3, toDisplayString(unref(
|
|
70
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
71
|
+
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_3, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
72
72
|
]);
|
|
73
73
|
};
|
|
74
74
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfBoolean.vue.js","sources":["../../../src/vue/primevue/JfBoolean.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfBoolean\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { getCurrentInstance } from \"vue\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport Checkbox from \"primevue/checkbox\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\n// Track user interaction — errors only show after first toggle\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\nconst onToggle = (val: boolean) => {\n markDirty();\n handleChange(control.value.path, val);\n};\n</script>\n\n<template>\n <div class=\"flex items-center gap-2\">\n <Checkbox\n :binary=\"true\"\n :model-value=\"!!projectedData\"\n :disabled=\"!control.enabled\"\n :class=\"{ 'p-invalid': showErrors }\"\n :aria-invalid=\"showErrors || undefined\"\n @update:model-value=\"onToggle\"\n />\n <label v-if=\"
|
|
1
|
+
{"version":3,"file":"JfBoolean.vue.js","sources":["../../../src/vue/primevue/JfBoolean.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfBoolean\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { getCurrentInstance } from \"vue\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport Checkbox from \"primevue/checkbox\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\n// Track user interaction — errors only show after first toggle\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\nconst onToggle = (val: boolean) => {\n markDirty();\n handleChange(control.value.path, val);\n};\n</script>\n\n<template>\n <div class=\"flex items-center gap-2\">\n <Checkbox\n :binary=\"true\"\n :model-value=\"!!projectedData\"\n :disabled=\"!control.enabled\"\n :class=\"{ 'p-invalid': showErrors }\"\n :aria-invalid=\"showErrors || undefined\"\n @update:model-value=\"onToggle\"\n />\n <label v-if=\"projectedLabel\">{{ projectedLabel }}</label>\n <small v-if=\"showErrors\" class=\"p-error\">{{ projectedErrors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_createVNode","_unref","_toDisplayString"],"mappings":";;;;;;;;;;;AACA,MAAA,cAAe;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IAAA;AAAA,IAEX,WAAW;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,IAEX,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,IAEX,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;;;;AAYA,UAAM,WAAW,mBAAA;AACjB,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,cAAc,iBAAiB,mBAAmB,cAAc,SAAS,eAAe;AAGtI,UAAM,EAAE,YAAY,UAAA,IAAc,mBAAmB,SAAS,eAAe;AAE7E,UAAM,WAAW,CAAC,QAAiB;AACjC,gBAAA;AACA,mBAAa,QAAQ,MAAM,MAAM,GAAG;AAAA,IACtC;;AAIE,aAAAA,UAAA,GAAAC,mBAWM,OAXN,YAWM;AAAA,QAVJC,YAOEC,MAAA,QAAA,GAAA;AAAA,UANC,QAAQ;AAAA,UACR,iBAAeA,MAAA,aAAA;AAAA,UACf,UAAQ,CAAGA,MAAA,OAAA,EAAQ;AAAA,UACnB,qCAAsBA,MAAA,UAAA,GAAU;AAAA,UAChC,gBAAcA,MAAA,UAAA,KAAc;AAAA,UAC5B,uBAAoB;AAAA,QAAA;QAEVA,MAAA,cAAA,KAAbH,UAAA,GAAAC,mBAAyD,qCAAzBE,MAAA,cAAA,CAAc,GAAA,CAAA;QACjCA,MAAA,UAAA,kBAAbF,mBAAsE,SAAtE,YAAsEG,gBAA1BD,MAAA,eAAA,CAAe,GAAA,CAAA;;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfEnum.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnum.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqNA,
|
|
1
|
+
{"version":3,"file":"JfEnum.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnum.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqNA,wBAsUK"}
|
|
@@ -66,7 +66,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
66
66
|
const instance = getCurrentInstance();
|
|
67
67
|
const props = instance.props;
|
|
68
68
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
69
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
69
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
70
70
|
const toOptions = (schema) => {
|
|
71
71
|
if (!schema) return [];
|
|
72
72
|
const s = schema;
|
|
@@ -141,13 +141,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
141
141
|
},
|
|
142
142
|
{ immediate: true }
|
|
143
143
|
);
|
|
144
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
144
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
145
145
|
const onSelect = (val) => {
|
|
146
146
|
handleChange(control.value.path, val);
|
|
147
147
|
};
|
|
148
148
|
return (_ctx, _cache) => {
|
|
149
149
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
150
|
-
unref(
|
|
150
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
151
151
|
unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
|
|
152
152
|
createVNode(unref(Dropdown), {
|
|
153
153
|
class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
|
|
@@ -162,7 +162,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
162
162
|
"onUpdate:modelValue": onSelect,
|
|
163
163
|
onBlur: unref(markDirty)
|
|
164
164
|
}, null, 8, ["class", "options", "model-value", "placeholder", "disabled", "aria-invalid", "onBlur"]),
|
|
165
|
-
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed to load: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(
|
|
165
|
+
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed to load: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
166
166
|
]);
|
|
167
167
|
};
|
|
168
168
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfEnum.vue.js","sources":["../../../src/vue/primevue/JfEnum.vue"],"sourcesContent":["<script lang=\"ts\">\n// Define props manually to avoid any potential circular dependency issues\nexport default {\n name: \"JfEnum\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { JsonSchema } from \"@jsonforms/core\";\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, getCurrentInstance, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\ntype Opt = { label: string; value: unknown };\nconst toOptions = (schema?: JsonSchema): Opt[] => {\n if (!schema) return [];\n const s = schema as {\n enum?: unknown[];\n oneOf?: Array<{ title?: string; const: unknown }>;\n };\n if (Array.isArray(s.enum))\n return s.enum.map((v: unknown) => ({ label: String(v), value: v }));\n if (Array.isArray(s.oneOf))\n return s.oneOf.map((o) => ({\n label: o.title ?? String(o.const),\n value: o.const,\n }));\n return [];\n};\n\n// Provider support\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\n// Use provider if available, otherwise fall back to schema enum/oneOf\nconst {\n items: providerItems,\n loading,\n error,\n} = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\nconst options = computed(() => {\n // Use provider items if available, otherwise fall back to schema enum/oneOf\n if (binding.value && providerItems.value.length > 0) {\n return providerItems.value;\n }\n return toOptions(control.value.schema);\n});\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Auto-select when provider returns only one item (enabled by default)\nwatch(\n [providerItems, loading],\n ([items, isLoading]) => {\n const valueToSelect = shouldAutoSelect({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle !== false,\n isLoading,\n items,\n currentValue: projectedData.value,\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true }\n);\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\nconst onSelect = (val: unknown) => {\n handleChange(control.value.path, val);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"
|
|
1
|
+
{"version":3,"file":"JfEnum.vue.js","sources":["../../../src/vue/primevue/JfEnum.vue"],"sourcesContent":["<script lang=\"ts\">\n// Define props manually to avoid any potential circular dependency issues\nexport default {\n name: \"JfEnum\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { JsonSchema } from \"@jsonforms/core\";\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, getCurrentInstance, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\ntype Opt = { label: string; value: unknown };\nconst toOptions = (schema?: JsonSchema): Opt[] => {\n if (!schema) return [];\n const s = schema as {\n enum?: unknown[];\n oneOf?: Array<{ title?: string; const: unknown }>;\n };\n if (Array.isArray(s.enum))\n return s.enum.map((v: unknown) => ({ label: String(v), value: v }));\n if (Array.isArray(s.oneOf))\n return s.oneOf.map((o) => ({\n label: o.title ?? String(o.const),\n value: o.const,\n }));\n return [];\n};\n\n// Provider support\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\n// Use provider if available, otherwise fall back to schema enum/oneOf\nconst {\n items: providerItems,\n loading,\n error,\n} = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\nconst options = computed(() => {\n // Use provider items if available, otherwise fall back to schema enum/oneOf\n if (binding.value && providerItems.value.length > 0) {\n return providerItems.value;\n }\n return toOptions(control.value.schema);\n});\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Auto-select when provider returns only one item (enabled by default)\nwatch(\n [providerItems, loading],\n ([items, isLoading]) => {\n const valueToSelect = shouldAutoSelect({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle !== false,\n isLoading,\n items,\n currentValue: projectedData.value,\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true }\n);\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\nconst onSelect = (val: unknown) => {\n handleChange(control.value.path, val);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"projectedLabel\" class=\"text-color text-left\">{{\n projectedLabel\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n <Dropdown\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :options=\"options\"\n option-label=\"label\"\n option-value=\"value\"\n :model-value=\"projectedData ?? null\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled || loading\"\n :aria-invalid=\"showErrors || undefined\"\n :show-clear=\"true\"\n @update:model-value=\"onSelect\"\n @blur=\"markDirty\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n <small v-else-if=\"showErrors\" class=\"p-error\">{{ projectedErrors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfEnumArray.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnumArray.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2OA,
|
|
1
|
+
{"version":3,"file":"JfEnumArray.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnumArray.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2OA,wBAgVK"}
|
|
@@ -66,7 +66,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
66
66
|
const instance = getCurrentInstance();
|
|
67
67
|
const props = instance.props;
|
|
68
68
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
69
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
69
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
70
70
|
const toOptions = (schema) => {
|
|
71
71
|
if (!schema) return [];
|
|
72
72
|
const s = schema;
|
|
@@ -122,7 +122,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
122
122
|
return toOptions(control.value.schema?.items);
|
|
123
123
|
});
|
|
124
124
|
useDerive({ control, handleChange, data: projectedData });
|
|
125
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
125
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
126
126
|
watch(
|
|
127
127
|
[providerItems, loading],
|
|
128
128
|
([items, isLoading]) => {
|
|
@@ -164,7 +164,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
164
164
|
});
|
|
165
165
|
return (_ctx, _cache) => {
|
|
166
166
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
167
|
-
unref(
|
|
167
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
168
168
|
unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
|
|
169
169
|
createVNode(unref(MultiSelect), {
|
|
170
170
|
modelValue: model.value,
|
|
@@ -179,7 +179,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
179
179
|
"aria-invalid": unref(showErrors) || void 0,
|
|
180
180
|
placeholder: placeholder.value
|
|
181
181
|
}, null, 8, ["modelValue", "class", "options", "disabled", "aria-invalid", "placeholder"]),
|
|
182
|
-
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed to load: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(
|
|
182
|
+
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed to load: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
183
183
|
]);
|
|
184
184
|
};
|
|
185
185
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfEnumArray.vue.js","sources":["../../../src/vue/primevue/JfEnumArray.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfEnumArray\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { JsonSchema } from \"@jsonforms/core\";\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, getCurrentInstance, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport { shouldAutoSelectMulti } from \"../utils/autoSelect\";\nimport MultiSelect from \"primevue/multiselect\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\ntype Opt = { label: string; value: unknown };\nconst toOptions = (schema?: JsonSchema): Opt[] => {\n if (!schema) return [];\n const s = schema as {\n enum?: unknown[];\n oneOf?: Array<{ title?: string; const: unknown }>;\n };\n if (Array.isArray(s.enum))\n return s.enum.map((v: unknown) => ({ label: String(v), value: v }));\n if (Array.isArray(s.oneOf))\n return s.oneOf.map((o) => ({\n label: o.title ?? String(o.const),\n value: o.const,\n }));\n return [];\n};\n\n// Provider support\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\n// Use provider if available, otherwise fall back to schema enum/oneOf\nconst {\n items: providerItems,\n loading,\n error,\n} = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\nconst options = computed(() => {\n // Use provider items if available, otherwise fall back to schema enum/oneOf\n if (binding.value && providerItems.value.length > 0) {\n return providerItems.value;\n }\n return toOptions((control.value.schema as { items?: JsonSchema })?.items);\n});\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Track user interaction — errors only show after first change\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\n// Auto-select when provider returns only one item (opt-in for multiselect)\nwatch(\n [providerItems, loading],\n ([items, isLoading]) => {\n const valueToSelect = shouldAutoSelectMulti({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle === true,\n isLoading,\n items,\n currentValue: Array.isArray(projectedData.value) ? projectedData.value : [],\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true }\n);\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\n// order-insensitive shallow equality for primitive enums\nconst sameSet = (a: unknown[], b: unknown[]) => {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n const s = new Set(b);\n return a.every((v) => s.has(v));\n};\n\n// v-model with guard to avoid recursive updates\nconst model = computed<unknown[]>({\n get() {\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n // return a fresh copy so PrimeMultiSelect can't mutate JSONForms' array in place\n return [...curr];\n },\n set(val) {\n const next = Array.isArray(val) ? [...val] : [];\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n if (!sameSet(curr, next)) {\n markDirty();\n handleChange(control.value.path, next);\n }\n },\n});\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"control.label\" class=\"text-color text-left\">{{\n control.label\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n\n <MultiSelect\n v-model=\"model\"\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :options=\"options\"\n option-label=\"label\"\n option-value=\"value\"\n data-key=\"value\"\n display=\"chip\"\n :disabled=\"!control.enabled || loading\"\n :aria-invalid=\"showErrors || undefined\"\n :placeholder=\"placeholder\"\n />\n\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n <small v-else-if=\"showErrors\" class=\"p-error\">{{\n control.errors\n }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JfEnumArray.vue.js","sources":["../../../src/vue/primevue/JfEnumArray.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfEnumArray\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { JsonSchema } from \"@jsonforms/core\";\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, getCurrentInstance, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport { shouldAutoSelectMulti } from \"../utils/autoSelect\";\nimport MultiSelect from \"primevue/multiselect\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\ntype Opt = { label: string; value: unknown };\nconst toOptions = (schema?: JsonSchema): Opt[] => {\n if (!schema) return [];\n const s = schema as {\n enum?: unknown[];\n oneOf?: Array<{ title?: string; const: unknown }>;\n };\n if (Array.isArray(s.enum))\n return s.enum.map((v: unknown) => ({ label: String(v), value: v }));\n if (Array.isArray(s.oneOf))\n return s.oneOf.map((o) => ({\n label: o.title ?? String(o.const),\n value: o.const,\n }));\n return [];\n};\n\n// Provider support\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'mount' by default\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"mount\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\n// Use provider if available, otherwise fall back to schema enum/oneOf\nconst {\n items: providerItems,\n loading,\n error,\n} = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\nconst options = computed(() => {\n // Use provider items if available, otherwise fall back to schema enum/oneOf\n if (binding.value && providerItems.value.length > 0) {\n return providerItems.value;\n }\n return toOptions((control.value.schema as { items?: JsonSchema })?.items);\n});\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Track user interaction — errors only show after first change\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\n// Auto-select when provider returns only one item (opt-in for multiselect)\nwatch(\n [providerItems, loading],\n ([items, isLoading]) => {\n const valueToSelect = shouldAutoSelectMulti({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle === true,\n isLoading,\n items,\n currentValue: Array.isArray(projectedData.value) ? projectedData.value : [],\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true }\n);\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\n// order-insensitive shallow equality for primitive enums\nconst sameSet = (a: unknown[], b: unknown[]) => {\n if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)\n return false;\n const s = new Set(b);\n return a.every((v) => s.has(v));\n};\n\n// v-model with guard to avoid recursive updates\nconst model = computed<unknown[]>({\n get() {\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n // return a fresh copy so PrimeMultiSelect can't mutate JSONForms' array in place\n return [...curr];\n },\n set(val) {\n const next = Array.isArray(val) ? [...val] : [];\n const curr = Array.isArray(projectedData.value) ? projectedData.value : [];\n if (!sameSet(curr, next)) {\n markDirty();\n handleChange(control.value.path, next);\n }\n },\n});\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"projectedLabel\" class=\"text-color text-left\">{{\n projectedLabel\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n\n <MultiSelect\n v-model=\"model\"\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :options=\"options\"\n option-label=\"label\"\n option-value=\"value\"\n data-key=\"value\"\n display=\"chip\"\n :disabled=\"!control.enabled || loading\"\n :aria-invalid=\"showErrors || undefined\"\n :placeholder=\"placeholder\"\n />\n\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n <small v-else-if=\"showErrors\" class=\"p-error\">{{\n projectedErrors\n }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoJA,
|
|
1
|
+
{"version":3,"file":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoJA,wBAwQK"}
|
|
@@ -59,7 +59,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
59
59
|
const instance = getCurrentInstance();
|
|
60
60
|
const props = instance.props;
|
|
61
61
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
62
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
62
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
63
63
|
const options = computed(
|
|
64
64
|
() => control.value.uischema?.options ?? {}
|
|
65
65
|
);
|
|
@@ -94,13 +94,13 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
94
94
|
if (mode.value === "currency") return true;
|
|
95
95
|
return options.value.useGrouping === true;
|
|
96
96
|
});
|
|
97
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
97
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
98
98
|
const onNumber = (val) => {
|
|
99
99
|
handleChange(control.value.path, val ?? void 0);
|
|
100
100
|
};
|
|
101
101
|
return (_ctx, _cache) => {
|
|
102
102
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
103
|
-
unref(
|
|
103
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
104
104
|
unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
|
|
105
105
|
createVNode(unref(InputNumber), {
|
|
106
106
|
class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
|
|
@@ -117,7 +117,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
117
117
|
"onUpdate:modelValue": onNumber,
|
|
118
118
|
onBlur: unref(markDirty)
|
|
119
119
|
}, null, 8, ["class", "input-class", "use-grouping", "mode", "currency", "min-fraction-digits", "max-fraction-digits", "model-value", "placeholder", "disabled", "aria-invalid", "onBlur"]),
|
|
120
|
-
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(
|
|
120
|
+
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
121
121
|
]);
|
|
122
122
|
};
|
|
123
123
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfNumber.vue.js","sources":["../../../src/vue/primevue/JfNumber.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfNumber\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, getCurrentInstance } from \"vue\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport InputNumber from \"primevue/inputnumber\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\nconst options = computed(\n () =>\n (control.value.uischema as { options?: Record<string, unknown> })\n ?.options ?? {},\n);\n\nconst placeholder = computed<string | undefined>(\n () => (options.value.placeholder as string) ?? control.value.description,\n);\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Currency and decimal configuration\nconst mode = computed(() => {\n if (options.value.currency) return \"currency\";\n if (options.value.decimal || typeof options.value.precision === \"number\")\n return \"decimal\";\n return undefined;\n});\n\nconst currency = computed(() =>\n typeof options.value.currency === \"string\" ? options.value.currency : \"USD\",\n);\n\nconst minFractionDigits = computed(() => {\n // For integer types, no fractional digits\n if (control.value.schema?.type === \"integer\") return 0;\n if (mode.value === \"currency\") return 2;\n if (typeof options.value.precision === \"number\")\n return options.value.precision;\n return undefined;\n});\n\nconst maxFractionDigits = computed(() => {\n // For integer types, no fractional digits\n if (control.value.schema?.type === \"integer\") return 0;\n if (mode.value === \"currency\") return 2;\n if (typeof options.value.precision === \"number\")\n return options.value.precision;\n return undefined;\n});\n\nconst useGrouping = computed(() => {\n // Enable grouping for currency by default, or if explicitly set\n if (mode.value === \"currency\") return true;\n return options.value.useGrouping === true;\n});\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\nconst onNumber = (val: number | null) => {\n handleChange(control.value.path, val ?? undefined);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"
|
|
1
|
+
{"version":3,"file":"JfNumber.vue.js","sources":["../../../src/vue/primevue/JfNumber.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfNumber\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, getCurrentInstance } from \"vue\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport InputNumber from \"primevue/inputnumber\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\nconst options = computed(\n () =>\n (control.value.uischema as { options?: Record<string, unknown> })\n ?.options ?? {},\n);\n\nconst placeholder = computed<string | undefined>(\n () => (options.value.placeholder as string) ?? control.value.description,\n);\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Currency and decimal configuration\nconst mode = computed(() => {\n if (options.value.currency) return \"currency\";\n if (options.value.decimal || typeof options.value.precision === \"number\")\n return \"decimal\";\n return undefined;\n});\n\nconst currency = computed(() =>\n typeof options.value.currency === \"string\" ? options.value.currency : \"USD\",\n);\n\nconst minFractionDigits = computed(() => {\n // For integer types, no fractional digits\n if (control.value.schema?.type === \"integer\") return 0;\n if (mode.value === \"currency\") return 2;\n if (typeof options.value.precision === \"number\")\n return options.value.precision;\n return undefined;\n});\n\nconst maxFractionDigits = computed(() => {\n // For integer types, no fractional digits\n if (control.value.schema?.type === \"integer\") return 0;\n if (mode.value === \"currency\") return 2;\n if (typeof options.value.precision === \"number\")\n return options.value.precision;\n return undefined;\n});\n\nconst useGrouping = computed(() => {\n // Enable grouping for currency by default, or if explicitly set\n if (mode.value === \"currency\") return true;\n return options.value.useGrouping === true;\n});\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\nconst onNumber = (val: number | null) => {\n handleChange(control.value.path, val ?? undefined);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"projectedLabel\" class=\"text-color text-left\">{{\n projectedLabel\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n <InputNumber\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :input-class=\"['w-full', { 'p-invalid': showErrors }]\"\n :use-grouping=\"useGrouping\"\n :mode=\"mode\"\n :currency=\"currency\"\n :min-fraction-digits=\"minFractionDigits\"\n :max-fraction-digits=\"maxFractionDigits\"\n :model-value=\"typeof projectedData === 'number' ? projectedData : null\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled\"\n :aria-invalid=\"showErrors || undefined\"\n @update:model-value=\"onNumber\"\n @blur=\"markDirty\"\n />\n <small v-if=\"showErrors\" class=\"p-error\">{{ projectedErrors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfText.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfText.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2MA,
|
|
1
|
+
{"version":3,"file":"JfText.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfText.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2MA,wBA6WK"}
|
|
@@ -66,7 +66,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
66
66
|
const instance = getCurrentInstance();
|
|
67
67
|
const props = instance.props;
|
|
68
68
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
69
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
69
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
70
70
|
const binding = computed(() => {
|
|
71
71
|
const provider = control.value.uischema?.options?.provider;
|
|
72
72
|
if (provider && typeof provider === "object" && !provider.load) {
|
|
@@ -110,7 +110,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
110
110
|
});
|
|
111
111
|
const isAutocomplete = computed(() => !!binding.value);
|
|
112
112
|
useDerive({ control, handleChange, data: projectedData });
|
|
113
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
113
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
114
114
|
function onInput(val) {
|
|
115
115
|
const newValue = val && val.trim() !== "" ? val : void 0;
|
|
116
116
|
if (projectedData.value !== newValue) {
|
|
@@ -133,7 +133,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
133
133
|
};
|
|
134
134
|
return (_ctx, _cache) => {
|
|
135
135
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
136
|
-
unref(
|
|
136
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
137
137
|
unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
|
|
138
138
|
isAutocomplete.value ? (openBlock(), createBlock(unref(AutoComplete), {
|
|
139
139
|
key: 2,
|
|
@@ -161,7 +161,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
161
161
|
"onUpdate:modelValue": onInput,
|
|
162
162
|
onBlur
|
|
163
163
|
}, null, 8, ["class", "model-value", "disabled", "aria-invalid", "placeholder"])),
|
|
164
|
-
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(
|
|
164
|
+
unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed: " + toDisplayString(unref(error)), 1)) : unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
165
165
|
]);
|
|
166
166
|
};
|
|
167
167
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfText.vue.js","sources":["../../../src/vue/primevue/JfText.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfText\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, ref, inject, watch, getCurrentInstance } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport InputText from \"primevue/inputtext\";\nimport AutoComplete from \"primevue/autocomplete\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\n// Provider support for autocomplete functionality\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'query' by default for autocomplete\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"query\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\nconst query = ref(\"\");\nconst { items, loading, error, reload } = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n uiQuery: query.value,\n dependsOnValues: depValues.value,\n});\n\nwatch(query, () => {\n if (binding.value?.load === \"query\") reload();\n});\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\nconst isAutocomplete = computed(() => !!binding.value);\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\nfunction onInput(val: string | undefined) {\n // Convert empty strings to undefined for proper required field validation\n const newValue = val && val.trim() !== \"\" ? val : undefined;\n if (projectedData.value !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n markDirty();\n // Normalize empty strings to undefined so required validation fires\n const val = projectedData.value;\n if (typeof val === \"string\" && val.trim() === \"\") {\n handleChange(control.value.path, undefined);\n }\n}\n\n// Autocomplete specific handlers\nconst onComplete = (event: { query: string }) => {\n query.value = event.query;\n};\n\nconst onSelect = (event: { value?: { value?: unknown } | unknown }) => {\n const newValue = (event.value as { value?: unknown })?.value ?? event.value;\n handleChange(control.value.path, newValue);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"
|
|
1
|
+
{"version":3,"file":"JfText.vue.js","sources":["../../../src/vue/primevue/JfText.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfText\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, ref, inject, watch, getCurrentInstance } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDerive } from \"../composables/useDerive\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport InputText from \"primevue/inputtext\";\nimport AutoComplete from \"primevue/autocomplete\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\n// Provider support for autocomplete functionality\nconst binding = computed(() => {\n const provider = control.value.uischema?.options?.provider;\n // Ensure load property is set to 'query' by default for autocomplete\n if (provider && typeof provider === \"object\" && !provider.load) {\n return { ...provider, load: \"query\" };\n }\n return provider;\n});\n\nconst deps = computed(\n () =>\n ((\n (control.value.schema as Record<string, unknown>)?.[\n \"x-provider\"\n ] as Record<string, unknown>\n )?.dependsOn as string[]) ?? [],\n);\nconst depValues = computed(() => {\n return deps.value.map((dep) => {\n // Resolve dependency value from form data using JSON pointer-like path\n const path = dep.startsWith(\"#/\") ? dep.slice(2) : dep;\n const keys = path.replace(/\\//g, \".\").split(\".\");\n let value: unknown = rootData.value;\n for (const key of keys) {\n if (value && typeof value === \"object\" && key in value) {\n value = (value as Record<string, unknown>)[key];\n } else {\n return null;\n }\n }\n return value;\n });\n});\n\n// Get the root form data from JSONForms context for template URL resolution\nconst injectedFormData = inject<{ value: unknown }>(\"formData\", { value: {} });\nconst rootData = computed(() => injectedFormData.value || {});\n\nconst query = ref(\"\");\nconst { items, loading, error, reload } = useProvider(binding, {\n data: rootData,\n path: control.value.path,\n uiQuery: query.value,\n dependsOnValues: depValues.value,\n});\n\nwatch(query, () => {\n if (binding.value?.load === \"query\") reload();\n});\n\nconst placeholder = computed<string | undefined>(() => {\n if (loading.value) return \"Loading…\";\n return (\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description\n );\n});\n\nconst isAutocomplete = computed(() => !!binding.value);\n\n// Add derive functionality\nuseDerive({ control, handleChange, data: projectedData });\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\nfunction onInput(val: string | undefined) {\n // Convert empty strings to undefined for proper required field validation\n const newValue = val && val.trim() !== \"\" ? val : undefined;\n if (projectedData.value !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n markDirty();\n // Normalize empty strings to undefined so required validation fires\n const val = projectedData.value;\n if (typeof val === \"string\" && val.trim() === \"\") {\n handleChange(control.value.path, undefined);\n }\n}\n\n// Autocomplete specific handlers\nconst onComplete = (event: { query: string }) => {\n query.value = event.query;\n};\n\nconst onSelect = (event: { value?: { value?: unknown } | unknown }) => {\n const newValue = (event.value as { value?: unknown })?.value ?? event.value;\n handleChange(control.value.path, newValue);\n};\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"projectedLabel\" class=\"text-color text-left\">{{\n projectedLabel\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n <AutoComplete\n v-if=\"isAutocomplete\"\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :model-value=\"projectedData ?? ''\"\n :suggestions=\"items\"\n option-label=\"label\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled\"\n :aria-invalid=\"showErrors || undefined\"\n @complete=\"onComplete\"\n @item-select=\"onSelect\"\n @update:model-value=\"onInput\"\n @blur=\"onBlur\"\n />\n <InputText\n v-else\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :model-value=\"(projectedData as string) ?? ''\"\n :disabled=\"!control.enabled\"\n :aria-invalid=\"showErrors || undefined\"\n :placeholder=\"placeholder\"\n autocapitalize=\"off\"\n autocomplete=\"off\"\n spellcheck=\"false\"\n @update:model-value=\"onInput\"\n @blur=\"onBlur\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\">Failed: {{ error }}</small>\n <small v-else-if=\"showErrors\" class=\"p-error\">{{ projectedErrors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createBlock"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfTextArea.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfTextArea.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHA,
|
|
1
|
+
{"version":3,"file":"JfTextArea.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfTextArea.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHA,wBA6NK"}
|
|
@@ -58,11 +58,11 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
58
58
|
const instance = getCurrentInstance();
|
|
59
59
|
const props = instance.props;
|
|
60
60
|
const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
|
|
61
|
-
const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
61
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
62
62
|
const placeholder = computed(
|
|
63
63
|
() => control.value.uischema?.options?.placeholder ?? control.value.description
|
|
64
64
|
);
|
|
65
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
65
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
66
66
|
function onInput(val) {
|
|
67
67
|
const newValue = val && val.trim() !== "" ? val : void 0;
|
|
68
68
|
if (projectedData.value !== newValue) {
|
|
@@ -78,7 +78,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
78
78
|
}
|
|
79
79
|
return (_ctx, _cache) => {
|
|
80
80
|
return openBlock(), createElementBlock("div", _hoisted_1, [
|
|
81
|
-
unref(
|
|
81
|
+
unref(projectedLabel) ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(projectedLabel)), 1)) : createCommentVNode("", true),
|
|
82
82
|
unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
|
|
83
83
|
createVNode(unref(Textarea), {
|
|
84
84
|
class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
|
|
@@ -91,7 +91,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
|
|
|
91
91
|
"onUpdate:modelValue": onInput,
|
|
92
92
|
onBlur
|
|
93
93
|
}, null, 8, ["class", "model-value", "disabled", "aria-invalid", "placeholder"]),
|
|
94
|
-
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(
|
|
94
|
+
unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(projectedErrors)), 1)) : createCommentVNode("", true)
|
|
95
95
|
]);
|
|
96
96
|
};
|
|
97
97
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JfTextArea.vue.js","sources":["../../../src/vue/primevue/JfTextArea.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfTextArea\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, getCurrentInstance } from \"vue\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport Textarea from \"primevue/textarea\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);\n\nconst placeholder = computed<string | undefined>(\n () =>\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description,\n);\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control);\n\nfunction onInput(val: string | undefined) {\n // Convert empty strings to undefined for proper required field validation\n const newValue = val && val.trim() !== \"\" ? val : undefined;\n if (projectedData.value !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n markDirty();\n // Normalize empty strings to undefined so required validation fires\n const val = projectedData.value;\n if (typeof val === \"string\" && val.trim() === \"\") {\n handleChange(control.value.path, undefined);\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"
|
|
1
|
+
{"version":3,"file":"JfTextArea.vue.js","sources":["../../../src/vue/primevue/JfTextArea.vue"],"sourcesContent":["<script lang=\"ts\">\nexport default {\n name: \"JfTextArea\",\n props: {\n uischema: {\n type: Object,\n required: true,\n },\n schema: {\n type: Object,\n required: true,\n },\n path: {\n type: String,\n required: true,\n },\n enabled: {\n type: Boolean,\n default: undefined,\n },\n renderers: {\n type: Array,\n required: false,\n default: undefined,\n },\n cells: {\n type: Array,\n required: false,\n default: undefined,\n },\n config: {\n type: Object,\n required: false,\n default: undefined,\n },\n },\n};\n</script>\n\n<script setup lang=\"ts\">\nimport type { ControlProps } from \"@jsonforms/vue\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, getCurrentInstance } from \"vue\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { useDirtyValidation } from \"../composables/useDirtyValidation\";\nimport Textarea from \"primevue/textarea\";\n\n// Access props from the component instance\nconst instance = getCurrentInstance()!;\nconst props = instance.props as unknown as ControlProps;\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);\n\nconst placeholder = computed<string | undefined>(\n () =>\n (control.value.uischema as { options?: { placeholder?: string } })?.options\n ?.placeholder ?? control.value.description,\n);\n\n// Track user interaction — errors only show after blur\nconst { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);\n\nfunction onInput(val: string | undefined) {\n // Convert empty strings to undefined for proper required field validation\n const newValue = val && val.trim() !== \"\" ? val : undefined;\n if (projectedData.value !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n markDirty();\n // Normalize empty strings to undefined so required validation fires\n const val = projectedData.value;\n if (typeof val === \"string\" && val.trim() === \"\") {\n handleChange(control.value.path, undefined);\n }\n}\n</script>\n\n<template>\n <div class=\"flex flex-column gap-2\">\n <label v-if=\"projectedLabel\" class=\"text-color text-left\">{{\n projectedLabel\n }}</label>\n <div v-if=\"control.description\" class=\"text-color-secondary text-left\">\n {{ control.description }}\n </div>\n <Textarea\n :class=\"['w-full', { 'p-invalid': showErrors }]\"\n :model-value=\"(projectedData as string) ?? ''\"\n :disabled=\"!control.enabled\"\n :aria-invalid=\"showErrors || undefined\"\n :placeholder=\"placeholder\"\n :rows=\"4\"\n :auto-resize=\"true\"\n @update:model-value=\"onInput\"\n @blur=\"onBlur\"\n />\n <small v-if=\"showErrors\" class=\"p-error\">{{ projectedErrors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":";;;;;;;;;;;;;;;;;;AACA,MAAA,cAAe;AAAA,EACb,MAAM;AAAA,EACN,OAAO;AAAA,IACL,UAAU;AAAA,MACR,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,MAAM;AAAA,MACJ,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,SAAS;AAAA,MACP,MAAM;AAAA,MACN,SAAS;AAAA,IAAA;AAAA,IAEX,WAAW;AAAA,MACT,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,IAEX,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,IAEX,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,MACV,SAAS;AAAA,IAAA;AAAA,EACX;AAEJ;;;;AAYA,UAAM,WAAW,mBAAA;AACjB,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,cAAc,iBAAiB,mBAAmB,cAAc,SAAS,eAAe;AAEtI,UAAM,cAAc;AAAA,MAClB,MACG,QAAQ,MAAM,UAAqD,SAChE,eAAe,QAAQ,MAAM;AAAA,IAAA;AAIrC,UAAM,EAAE,YAAY,UAAA,IAAc,mBAAmB,SAAS,eAAe;AAE7E,aAAS,QAAQ,KAAyB;AAExC,YAAM,WAAW,OAAO,IAAI,KAAA,MAAW,KAAK,MAAM;AAClD,UAAI,cAAc,UAAU,UAAU;AACpC,qBAAa,QAAQ,MAAM,MAAM,QAAQ;AAAA,MAC3C;AAAA,IACF;AAEA,aAAS,SAAS;AAChB,gBAAA;AAEA,YAAM,MAAM,cAAc;AAC1B,UAAI,OAAO,QAAQ,YAAY,IAAI,KAAA,MAAW,IAAI;AAChD,qBAAa,QAAQ,MAAM,MAAM,MAAS;AAAA,MAC5C;AAAA,IACF;;AAIE,aAAAA,UAAA,GAAAC,mBAmBM,OAnBN,YAmBM;AAAA,QAlBSC,MAAA,cAAA,kBAAbD,mBAEU,SAFV,YAEUE,gBADRD,MAAA,cAAA,CAAc,GAAA,CAAA;QAELA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YAUEF,MAAA,QAAA,GAAA;AAAA,UATC,gDAAiCA,MAAA,UAAA,EAAA,CAAU,CAAA;AAAA,UAC3C,eAAcA,MAAA,aAAA,KAAa;AAAA,UAC3B,UAAQ,CAAGA,MAAA,OAAA,EAAQ;AAAA,UACnB,gBAAcA,MAAA,UAAA,KAAc;AAAA,UAC5B,aAAa,YAAA;AAAA,UACb,MAAM;AAAA,UACN,eAAa;AAAA,UACb,uBAAoB;AAAA,UACpB;AAAA,QAAA;QAEUA,MAAA,UAAA,kBAAbD,mBAAsE,SAAtE,YAAsEE,gBAA1BD,MAAA,eAAA,CAAe,GAAA,CAAA;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@narrative.io/jsonforms-provider-protocols",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.3",
|
|
4
4
|
"description": "Dynamic data provider capabilities for JSONForms with Vue 3 integration",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "Narrative I/O",
|
|
@@ -84,12 +84,14 @@
|
|
|
84
84
|
"@vitejs/plugin-vue": "^6.0.1",
|
|
85
85
|
"@vue/eslint-config-typescript": "^14.6.0",
|
|
86
86
|
"@vue/runtime-core": "^3.5.20",
|
|
87
|
+
"@vue/test-utils": "^2.4.6",
|
|
87
88
|
"bun-git-hooks": "^0.2.19",
|
|
88
89
|
"commitlint": "^20.0.0",
|
|
89
90
|
"eslint": "^9.34.0",
|
|
90
91
|
"eslint-config-prettier": "^10.1.8",
|
|
91
92
|
"eslint-plugin-vue": "^10.4.0",
|
|
92
93
|
"globals": "^16.3.0",
|
|
94
|
+
"happy-dom": "^20.6.3",
|
|
93
95
|
"prettier": "^3.6.2",
|
|
94
96
|
"primevue": "^4.3.8",
|
|
95
97
|
"typescript": "^5.9.2",
|
|
@@ -1,10 +1,15 @@
|
|
|
1
|
-
import { ref, computed, type Ref } from "vue";
|
|
1
|
+
import { ref, computed, type Ref, type ComputedRef } from "vue";
|
|
2
2
|
|
|
3
|
-
export function useDirtyValidation(
|
|
3
|
+
export function useDirtyValidation(
|
|
4
|
+
control: Ref<{ errors: string }>,
|
|
5
|
+
errorsOverride?: Ref<string> | ComputedRef<string>,
|
|
6
|
+
) {
|
|
4
7
|
const hasInteracted = ref(false);
|
|
5
8
|
|
|
6
9
|
const showErrors = computed(
|
|
7
|
-
() =>
|
|
10
|
+
() =>
|
|
11
|
+
hasInteracted.value &&
|
|
12
|
+
!!(errorsOverride ? errorsOverride.value : control.value.errors),
|
|
8
13
|
);
|
|
9
14
|
|
|
10
15
|
const markDirty = () => {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { computed, type ComputedRef, type Ref } from "vue";
|
|
1
|
+
import { computed, inject, type ComputedRef, type Ref } from "vue";
|
|
2
2
|
import {
|
|
3
3
|
getProjectedValue,
|
|
4
4
|
setProjectedValue,
|
|
@@ -8,11 +8,72 @@ import {
|
|
|
8
8
|
interface ProjectionControl {
|
|
9
9
|
data: unknown;
|
|
10
10
|
path: string;
|
|
11
|
+
errors: string;
|
|
12
|
+
label?: string;
|
|
11
13
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
12
14
|
schema: Record<string, any>;
|
|
13
15
|
uischema: { options?: { projection?: string; [key: string]: unknown } };
|
|
14
16
|
}
|
|
15
17
|
|
|
18
|
+
// Minimal AJV ErrorObject shape for filtering
|
|
19
|
+
interface ErrorLike {
|
|
20
|
+
instancePath?: string;
|
|
21
|
+
keyword?: string;
|
|
22
|
+
message?: string;
|
|
23
|
+
params?: { missingProperty?: string };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Resolve the display label for a control.
|
|
28
|
+
* Priority: uischema options.label → schemaTitle (projected sub-schema) → control.label.
|
|
29
|
+
*/
|
|
30
|
+
function resolveLabel(
|
|
31
|
+
ctrl: ProjectionControl,
|
|
32
|
+
schemaTitle?: string,
|
|
33
|
+
): string {
|
|
34
|
+
return (
|
|
35
|
+
(ctrl.uischema?.options?.label as string) ??
|
|
36
|
+
schemaTitle ??
|
|
37
|
+
ctrl.label ??
|
|
38
|
+
""
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Normalize AJV error message fragments into user-friendly text.
|
|
44
|
+
* e.g. "is a required property" → "is required"
|
|
45
|
+
*/
|
|
46
|
+
function normalizeErrors(errors: string): string {
|
|
47
|
+
if (!errors) return errors;
|
|
48
|
+
return errors
|
|
49
|
+
.replace(/is a required property/g, "is required")
|
|
50
|
+
.replace(/must have required property '[^']*'/g, "is required");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Prefix each error message line with the field label so that AJV fragments
|
|
55
|
+
* like "is required" become "Name is required".
|
|
56
|
+
*/
|
|
57
|
+
function prefixErrors(label: string, errors: string): string {
|
|
58
|
+
if (!label || !errors) return errors;
|
|
59
|
+
return errors
|
|
60
|
+
.split("\n")
|
|
61
|
+
.map((line) => `${label} ${line}`)
|
|
62
|
+
.join("\n");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Convert an AJV ErrorObject's instancePath to a dot-separated control path.
|
|
67
|
+
* Replicates the logic from @jsonforms/core getControlPath.
|
|
68
|
+
*/
|
|
69
|
+
function getErrorPath(error: ErrorLike): string {
|
|
70
|
+
let p = (error.instancePath || "").replace(/\//g, ".").replace(/^\./, "");
|
|
71
|
+
if (error.keyword === "required" && error.params?.missingProperty) {
|
|
72
|
+
p = p ? p + "." + error.params.missingProperty : error.params.missingProperty;
|
|
73
|
+
}
|
|
74
|
+
return p;
|
|
75
|
+
}
|
|
76
|
+
|
|
16
77
|
export interface ProjectionResult {
|
|
17
78
|
/** The value at the projected path (for rendering) */
|
|
18
79
|
projectedData: ComputedRef<unknown>;
|
|
@@ -23,6 +84,10 @@ export interface ProjectionResult {
|
|
|
23
84
|
handleProjectedChange: (path: string, value: unknown) => void;
|
|
24
85
|
/** Whether projection is active */
|
|
25
86
|
hasProjection: boolean;
|
|
87
|
+
/** Resolved display label (options.label → projected schema title → control.label) */
|
|
88
|
+
projectedLabel: ComputedRef<string>;
|
|
89
|
+
/** Error string combining base-path and projected sub-path errors */
|
|
90
|
+
projectedErrors: ComputedRef<string>;
|
|
26
91
|
}
|
|
27
92
|
|
|
28
93
|
/**
|
|
@@ -44,14 +109,32 @@ export function useProjection(
|
|
|
44
109
|
| undefined;
|
|
45
110
|
|
|
46
111
|
if (!projection) {
|
|
112
|
+
const label = computed(() => resolveLabel(control.value));
|
|
47
113
|
return {
|
|
48
114
|
projectedData: computed(() => control.value.data),
|
|
49
115
|
projectedSchema: computed(() => control.value.schema),
|
|
50
116
|
handleProjectedChange: handleChange,
|
|
51
117
|
hasProjection: false,
|
|
118
|
+
projectedLabel: label,
|
|
119
|
+
projectedErrors: computed(() =>
|
|
120
|
+
prefixErrors(
|
|
121
|
+
label.value.replace(/\*$/, "").trim(),
|
|
122
|
+
normalizeErrors(control.value.errors),
|
|
123
|
+
),
|
|
124
|
+
),
|
|
52
125
|
};
|
|
53
126
|
}
|
|
54
127
|
|
|
128
|
+
// Inject JSONForms state to access raw AJV errors for projected sub-paths.
|
|
129
|
+
// control.errors only contains errors at the exact control path (e.g. "data_rates"),
|
|
130
|
+
// but projected fields need errors at the full path (e.g. "data_rates.0.video_rate_usd").
|
|
131
|
+
const jsonforms = inject<{ core?: { errors?: ErrorLike[] } } | null>(
|
|
132
|
+
"jsonforms",
|
|
133
|
+
null,
|
|
134
|
+
);
|
|
135
|
+
|
|
136
|
+
const fullProjectedPath = control.value.path + "." + projection;
|
|
137
|
+
|
|
55
138
|
const projectedData = computed(() =>
|
|
56
139
|
getProjectedValue(control.value.data, projection),
|
|
57
140
|
);
|
|
@@ -60,6 +143,34 @@ export function useProjection(
|
|
|
60
143
|
getProjectedSchema(control.value.schema, projection),
|
|
61
144
|
);
|
|
62
145
|
|
|
146
|
+
const label = computed(() =>
|
|
147
|
+
resolveLabel(control.value, projectedSchema.value?.title),
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
const projectedErrors = computed(() => {
|
|
151
|
+
const baseErrors = normalizeErrors(control.value.errors || "");
|
|
152
|
+
|
|
153
|
+
const rawErrors = jsonforms?.core?.errors ?? [];
|
|
154
|
+
const matching = rawErrors.filter(
|
|
155
|
+
(err) => getErrorPath(err) === fullProjectedPath,
|
|
156
|
+
);
|
|
157
|
+
|
|
158
|
+
let errStr: string;
|
|
159
|
+
if (matching.length === 0) {
|
|
160
|
+
errStr = baseErrors;
|
|
161
|
+
} else {
|
|
162
|
+
const projMsg = matching
|
|
163
|
+
.map((e) =>
|
|
164
|
+
e.keyword === "required" ? "is required" : e.message,
|
|
165
|
+
)
|
|
166
|
+
.filter(Boolean)
|
|
167
|
+
.join("\n");
|
|
168
|
+
errStr = [baseErrors, projMsg].filter(Boolean).join("\n");
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
return prefixErrors(label.value.replace(/\*$/, "").trim(), errStr);
|
|
172
|
+
});
|
|
173
|
+
|
|
63
174
|
const handleProjectedChange = (path: string, value: unknown) => {
|
|
64
175
|
const fullValue = setProjectedValue(control.value.data, projection, value);
|
|
65
176
|
handleChange(path, fullValue);
|
|
@@ -70,5 +181,7 @@ export function useProjection(
|
|
|
70
181
|
projectedSchema,
|
|
71
182
|
handleProjectedChange,
|
|
72
183
|
hasProjection: true,
|
|
184
|
+
projectedLabel: label,
|
|
185
|
+
projectedErrors,
|
|
73
186
|
};
|
|
74
187
|
}
|
|
@@ -49,10 +49,10 @@ 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 { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
52
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
53
53
|
|
|
54
54
|
// Track user interaction — errors only show after first toggle
|
|
55
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
55
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
56
56
|
|
|
57
57
|
const onToggle = (val: boolean) => {
|
|
58
58
|
markDirty();
|
|
@@ -70,7 +70,7 @@ const onToggle = (val: boolean) => {
|
|
|
70
70
|
:aria-invalid="showErrors || undefined"
|
|
71
71
|
@update:model-value="onToggle"
|
|
72
72
|
/>
|
|
73
|
-
<label v-if="
|
|
74
|
-
<small v-if="showErrors" class="p-error">{{
|
|
73
|
+
<label v-if="projectedLabel">{{ projectedLabel }}</label>
|
|
74
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
75
75
|
</div>
|
|
76
76
|
</template>
|
|
@@ -54,7 +54,7 @@ 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 { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
|
|
57
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
58
58
|
|
|
59
59
|
type Opt = { label: string; value: unknown };
|
|
60
60
|
const toOptions = (schema?: JsonSchema): Opt[] => {
|
|
@@ -162,7 +162,7 @@ watch(
|
|
|
162
162
|
);
|
|
163
163
|
|
|
164
164
|
// Track user interaction — errors only show after blur
|
|
165
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
165
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
166
166
|
|
|
167
167
|
const onSelect = (val: unknown) => {
|
|
168
168
|
handleChange(control.value.path, val);
|
|
@@ -171,8 +171,8 @@ const onSelect = (val: unknown) => {
|
|
|
171
171
|
|
|
172
172
|
<template>
|
|
173
173
|
<div class="flex flex-column gap-2">
|
|
174
|
-
<label v-if="
|
|
175
|
-
|
|
174
|
+
<label v-if="projectedLabel" class="text-color text-left">{{
|
|
175
|
+
projectedLabel
|
|
176
176
|
}}</label>
|
|
177
177
|
<div v-if="control.description" class="text-color-secondary text-left">
|
|
178
178
|
{{ control.description }}
|
|
@@ -193,6 +193,6 @@ const onSelect = (val: unknown) => {
|
|
|
193
193
|
<small v-if="error" class="p-error" role="alert"
|
|
194
194
|
>Failed to load: {{ error }}</small
|
|
195
195
|
>
|
|
196
|
-
<small v-else-if="showErrors" class="p-error">{{
|
|
196
|
+
<small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
197
197
|
</div>
|
|
198
198
|
</template>
|
|
@@ -53,7 +53,7 @@ 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 } = useProjection(control, rawHandleChange);
|
|
56
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
57
57
|
|
|
58
58
|
type Opt = { label: string; value: unknown };
|
|
59
59
|
const toOptions = (schema?: JsonSchema): Opt[] => {
|
|
@@ -134,7 +134,7 @@ const options = computed(() => {
|
|
|
134
134
|
useDerive({ control, handleChange, data: projectedData });
|
|
135
135
|
|
|
136
136
|
// Track user interaction — errors only show after first change
|
|
137
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
137
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
138
138
|
|
|
139
139
|
// Auto-select when provider returns only one item (opt-in for multiselect)
|
|
140
140
|
watch(
|
|
@@ -191,8 +191,8 @@ const model = computed<unknown[]>({
|
|
|
191
191
|
|
|
192
192
|
<template>
|
|
193
193
|
<div class="flex flex-column gap-2">
|
|
194
|
-
<label v-if="
|
|
195
|
-
|
|
194
|
+
<label v-if="projectedLabel" class="text-color text-left">{{
|
|
195
|
+
projectedLabel
|
|
196
196
|
}}</label>
|
|
197
197
|
<div v-if="control.description" class="text-color-secondary text-left">
|
|
198
198
|
{{ control.description }}
|
|
@@ -215,7 +215,7 @@ const model = computed<unknown[]>({
|
|
|
215
215
|
>Failed to load: {{ error }}</small
|
|
216
216
|
>
|
|
217
217
|
<small v-else-if="showErrors" class="p-error">{{
|
|
218
|
-
|
|
218
|
+
projectedErrors
|
|
219
219
|
}}</small>
|
|
220
220
|
</div>
|
|
221
221
|
</template>
|
|
@@ -50,7 +50,7 @@ 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 } = useProjection(control, rawHandleChange);
|
|
53
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
54
54
|
|
|
55
55
|
const options = computed(
|
|
56
56
|
() =>
|
|
@@ -102,7 +102,7 @@ const useGrouping = computed(() => {
|
|
|
102
102
|
});
|
|
103
103
|
|
|
104
104
|
// Track user interaction — errors only show after blur
|
|
105
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
105
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
106
106
|
|
|
107
107
|
const onNumber = (val: number | null) => {
|
|
108
108
|
handleChange(control.value.path, val ?? undefined);
|
|
@@ -111,8 +111,8 @@ const onNumber = (val: number | null) => {
|
|
|
111
111
|
|
|
112
112
|
<template>
|
|
113
113
|
<div class="flex flex-column gap-2">
|
|
114
|
-
<label v-if="
|
|
115
|
-
|
|
114
|
+
<label v-if="projectedLabel" class="text-color text-left">{{
|
|
115
|
+
projectedLabel
|
|
116
116
|
}}</label>
|
|
117
117
|
<div v-if="control.description" class="text-color-secondary text-left">
|
|
118
118
|
{{ control.description }}
|
|
@@ -132,6 +132,6 @@ const onNumber = (val: number | null) => {
|
|
|
132
132
|
@update:model-value="onNumber"
|
|
133
133
|
@blur="markDirty"
|
|
134
134
|
/>
|
|
135
|
-
<small v-if="showErrors" class="p-error">{{
|
|
135
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
136
136
|
</div>
|
|
137
137
|
</template>
|
|
@@ -52,7 +52,7 @@ 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 } = useProjection(control, rawHandleChange);
|
|
55
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
56
56
|
|
|
57
57
|
// Provider support for autocomplete functionality
|
|
58
58
|
const binding = computed(() => {
|
|
@@ -119,7 +119,7 @@ const isAutocomplete = computed(() => !!binding.value);
|
|
|
119
119
|
useDerive({ control, handleChange, data: projectedData });
|
|
120
120
|
|
|
121
121
|
// Track user interaction — errors only show after blur
|
|
122
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
122
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
123
123
|
|
|
124
124
|
function onInput(val: string | undefined) {
|
|
125
125
|
// Convert empty strings to undefined for proper required field validation
|
|
@@ -151,8 +151,8 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
151
151
|
|
|
152
152
|
<template>
|
|
153
153
|
<div class="flex flex-column gap-2">
|
|
154
|
-
<label v-if="
|
|
155
|
-
|
|
154
|
+
<label v-if="projectedLabel" class="text-color text-left">{{
|
|
155
|
+
projectedLabel
|
|
156
156
|
}}</label>
|
|
157
157
|
<div v-if="control.description" class="text-color-secondary text-left">
|
|
158
158
|
{{ control.description }}
|
|
@@ -185,6 +185,6 @@ const onSelect = (event: { value?: { value?: unknown } | unknown }) => {
|
|
|
185
185
|
@blur="onBlur"
|
|
186
186
|
/>
|
|
187
187
|
<small v-if="error" class="p-error" role="alert">Failed: {{ error }}</small>
|
|
188
|
-
<small v-else-if="showErrors" class="p-error">{{
|
|
188
|
+
<small v-else-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
189
189
|
</div>
|
|
190
190
|
</template>
|
|
@@ -49,7 +49,7 @@ 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 } = useProjection(control, rawHandleChange);
|
|
52
|
+
const { projectedData, handleProjectedChange: handleChange, projectedErrors, projectedLabel } = useProjection(control, rawHandleChange);
|
|
53
53
|
|
|
54
54
|
const placeholder = computed<string | undefined>(
|
|
55
55
|
() =>
|
|
@@ -58,7 +58,7 @@ const placeholder = computed<string | undefined>(
|
|
|
58
58
|
);
|
|
59
59
|
|
|
60
60
|
// Track user interaction — errors only show after blur
|
|
61
|
-
const { showErrors, markDirty } = useDirtyValidation(control);
|
|
61
|
+
const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
|
|
62
62
|
|
|
63
63
|
function onInput(val: string | undefined) {
|
|
64
64
|
// Convert empty strings to undefined for proper required field validation
|
|
@@ -80,8 +80,8 @@ function onBlur() {
|
|
|
80
80
|
|
|
81
81
|
<template>
|
|
82
82
|
<div class="flex flex-column gap-2">
|
|
83
|
-
<label v-if="
|
|
84
|
-
|
|
83
|
+
<label v-if="projectedLabel" class="text-color text-left">{{
|
|
84
|
+
projectedLabel
|
|
85
85
|
}}</label>
|
|
86
86
|
<div v-if="control.description" class="text-color-secondary text-left">
|
|
87
87
|
{{ control.description }}
|
|
@@ -97,6 +97,6 @@ function onBlur() {
|
|
|
97
97
|
@update:model-value="onInput"
|
|
98
98
|
@blur="onBlur"
|
|
99
99
|
/>
|
|
100
|
-
<small v-if="showErrors" class="p-error">{{
|
|
100
|
+
<small v-if="showErrors" class="p-error">{{ projectedErrors }}</small>
|
|
101
101
|
</div>
|
|
102
102
|
</template>
|