@narrative.io/jsonforms-provider-protocols 2.10.0 → 3.0.0-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/README.md +166 -30
  2. package/dist/core/projection.d.ts +32 -0
  3. package/dist/core/projection.d.ts.map +1 -0
  4. package/dist/core/projection.js +74 -0
  5. package/dist/core/projection.js.map +1 -0
  6. package/dist/core/resolveScope.d.ts +11 -0
  7. package/dist/core/resolveScope.d.ts.map +1 -0
  8. package/dist/core/resolveScope.js +22 -0
  9. package/dist/core/resolveScope.js.map +1 -0
  10. package/dist/core/transforms.d.ts +8 -10
  11. package/dist/core/transforms.d.ts.map +1 -1
  12. package/dist/core/transforms.js +56 -13
  13. package/dist/core/transforms.js.map +1 -1
  14. package/dist/core/types.d.ts +7 -0
  15. package/dist/core/types.d.ts.map +1 -1
  16. package/dist/index.d.ts +4 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +12 -2
  19. package/dist/index.js.map +1 -1
  20. package/dist/jsonforms-provider-protocols.css +2 -2
  21. package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
  22. package/dist/vue/components/ProviderAutocomplete.vue.js +4 -2
  23. package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -1
  24. package/dist/vue/components/ProviderMultiSelect.vue.d.ts.map +1 -1
  25. package/dist/vue/components/ProviderMultiSelect.vue.js +1 -1
  26. package/dist/vue/components/ProviderMultiSelect.vue2.js +6 -4
  27. package/dist/vue/components/ProviderMultiSelect.vue2.js.map +1 -1
  28. package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -1
  29. package/dist/vue/components/ProviderSelect.vue.js +1 -1
  30. package/dist/vue/components/ProviderSelect.vue2.js +5 -3
  31. package/dist/vue/components/ProviderSelect.vue2.js.map +1 -1
  32. package/dist/vue/composables/useDataLayer.d.ts +9 -0
  33. package/dist/vue/composables/useDataLayer.d.ts.map +1 -0
  34. package/dist/vue/composables/useDataLayer.js +25 -0
  35. package/dist/vue/composables/useDataLayer.js.map +1 -0
  36. package/dist/vue/composables/useDerive.d.ts +5 -2
  37. package/dist/vue/composables/useDerive.d.ts.map +1 -1
  38. package/dist/vue/composables/useDerive.js +12 -12
  39. package/dist/vue/composables/useDerive.js.map +1 -1
  40. package/dist/vue/composables/useDirtyValidation.d.ts +9 -0
  41. package/dist/vue/composables/useDirtyValidation.d.ts.map +1 -0
  42. package/dist/vue/composables/useDirtyValidation.js +15 -0
  43. package/dist/vue/composables/useDirtyValidation.js.map +1 -0
  44. package/dist/vue/composables/useProjection.d.ts +35 -0
  45. package/dist/vue/composables/useProjection.d.ts.map +1 -0
  46. package/dist/vue/composables/useProjection.js +33 -0
  47. package/dist/vue/composables/useProjection.js.map +1 -0
  48. package/dist/vue/index.d.ts +5 -0
  49. package/dist/vue/index.d.ts.map +1 -1
  50. package/dist/vue/index.js +17 -29
  51. package/dist/vue/index.js.map +1 -1
  52. package/dist/vue/primevue/JfBoolean.vue.d.ts +9 -0
  53. package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -1
  54. package/dist/vue/primevue/JfBoolean.vue.js +21 -10
  55. package/dist/vue/primevue/JfBoolean.vue.js.map +1 -1
  56. package/dist/vue/primevue/JfEnum.vue.d.ts +9 -0
  57. package/dist/vue/primevue/JfEnum.vue.d.ts.map +1 -1
  58. package/dist/vue/primevue/JfEnum.vue.js +20 -18
  59. package/dist/vue/primevue/JfEnum.vue.js.map +1 -1
  60. package/dist/vue/primevue/JfEnumArray.vue.d.ts +9 -0
  61. package/dist/vue/primevue/JfEnumArray.vue.d.ts.map +1 -1
  62. package/dist/vue/primevue/JfEnumArray.vue.js +24 -14
  63. package/dist/vue/primevue/JfEnumArray.vue.js.map +1 -1
  64. package/dist/vue/primevue/JfNumber.vue.d.ts +9 -0
  65. package/dist/vue/primevue/JfNumber.vue.d.ts.map +1 -1
  66. package/dist/vue/primevue/JfNumber.vue.js +20 -18
  67. package/dist/vue/primevue/JfNumber.vue.js.map +1 -1
  68. package/dist/vue/primevue/JfText.vue.d.ts +9 -0
  69. package/dist/vue/primevue/JfText.vue.d.ts.map +1 -1
  70. package/dist/vue/primevue/JfText.vue.js +29 -28
  71. package/dist/vue/primevue/JfText.vue.js.map +1 -1
  72. package/dist/vue/primevue/JfTextArea.vue.d.ts +9 -0
  73. package/dist/vue/primevue/JfTextArea.vue.d.ts.map +1 -1
  74. package/dist/vue/primevue/JfTextArea.vue.js +23 -14
  75. package/dist/vue/primevue/JfTextArea.vue.js.map +1 -1
  76. package/dist/vue/primevue/index.d.ts.map +1 -1
  77. package/dist/vue/primevue/index.js +22 -7
  78. package/dist/vue/primevue/index.js.map +1 -1
  79. package/package.json +7 -3
  80. package/src/core/projection.ts +136 -0
  81. package/src/core/resolveScope.ts +39 -0
  82. package/src/core/transforms.ts +91 -26
  83. package/src/core/types.ts +8 -0
  84. package/src/index.ts +7 -0
  85. package/src/vue/components/ProviderAutocomplete.vue +4 -2
  86. package/src/vue/components/ProviderMultiSelect.vue +6 -4
  87. package/src/vue/components/ProviderSelect.vue +5 -3
  88. package/src/vue/composables/useDataLayer.ts +43 -0
  89. package/src/vue/composables/useDerive.ts +19 -16
  90. package/src/vue/composables/useDirtyValidation.ts +15 -0
  91. package/src/vue/composables/useProjection.ts +74 -0
  92. package/src/vue/index.ts +21 -46
  93. package/src/vue/primevue/JfBoolean.vue +18 -5
  94. package/src/vue/primevue/JfEnum.vue +16 -16
  95. package/src/vue/primevue/JfEnumArray.vue +21 -9
  96. package/src/vue/primevue/JfNumber.vue +16 -16
  97. package/src/vue/primevue/JfText.vue +22 -22
  98. package/src/vue/primevue/JfTextArea.vue +20 -11
  99. package/src/vue/primevue/index.ts +32 -7
@@ -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 },\n cells: {\n type: Array,\n required: false,\n },\n config: {\n type: Object,\n required: false,\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 { 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 } = useJsonFormsControl(props);\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 });\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(control.value.data) ? control.value.data : [],\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(control.value.data) ? control.value.data : [];\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(control.value.data) ? control.value.data : [];\n if (!sameSet(curr, next)) handleChange(control.value.path, next);\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\"\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=\"!!control.errors || 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=\"control.errors\" 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 } = 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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"}
@@ -18,14 +18,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
18
18
  renderers: {
19
19
  type: ArrayConstructor;
20
20
  required: false;
21
+ default: undefined;
21
22
  };
22
23
  cells: {
23
24
  type: ArrayConstructor;
24
25
  required: false;
26
+ default: undefined;
25
27
  };
26
28
  config: {
27
29
  type: ObjectConstructor;
28
30
  required: false;
31
+ default: undefined;
29
32
  };
30
33
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
31
34
  uischema: {
@@ -47,17 +50,23 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
47
50
  renderers: {
48
51
  type: ArrayConstructor;
49
52
  required: false;
53
+ default: undefined;
50
54
  };
51
55
  cells: {
52
56
  type: ArrayConstructor;
53
57
  required: false;
58
+ default: undefined;
54
59
  };
55
60
  config: {
56
61
  type: ObjectConstructor;
57
62
  required: false;
63
+ default: undefined;
58
64
  };
59
65
  }>> & Readonly<{}>, {
66
+ config: Record<string, any>;
60
67
  enabled: boolean;
68
+ renderers: unknown[];
69
+ cells: unknown[];
61
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
62
71
  export default _default;
63
72
  //# sourceMappingURL=JfNumber.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAkJA,wBAmQK"}
1
+ {"version":3,"file":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoJA,wBAsQK"}
@@ -1,6 +1,8 @@
1
- import { defineComponent, getCurrentInstance, computed, ref, createElementBlock, openBlock, createCommentVNode, createVNode, unref, toDisplayString } from "vue";
1
+ import { defineComponent, getCurrentInstance, computed, createElementBlock, openBlock, createCommentVNode, createVNode, unref, toDisplayString, normalizeClass } from "vue";
2
2
  import { useJsonFormsControl } from "@jsonforms/vue";
3
3
  import { useDerive } from "../composables/useDerive.js";
4
+ import { useProjection } from "../composables/useProjection.js";
5
+ import { useDirtyValidation } from "../composables/useDirtyValidation.js";
4
6
  import InputNumber from "primevue/inputnumber";
5
7
  const _hoisted_1 = { class: "flex flex-column gap-2" };
6
8
  const _hoisted_2 = {
@@ -36,15 +38,18 @@ const __default__ = {
36
38
  },
37
39
  renderers: {
38
40
  type: Array,
39
- required: false
41
+ required: false,
42
+ default: void 0
40
43
  },
41
44
  cells: {
42
45
  type: Array,
43
- required: false
46
+ required: false,
47
+ default: void 0
44
48
  },
45
49
  config: {
46
50
  type: Object,
47
- required: false
51
+ required: false,
52
+ default: void 0
48
53
  }
49
54
  }
50
55
  };
@@ -53,14 +58,15 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
53
58
  setup(__props) {
54
59
  const instance = getCurrentInstance();
55
60
  const props = instance.props;
56
- const { control, handleChange } = useJsonFormsControl(props);
61
+ const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
62
+ const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
57
63
  const options = computed(
58
64
  () => control.value.uischema?.options ?? {}
59
65
  );
60
66
  const placeholder = computed(
61
67
  () => options.value.placeholder ?? control.value.description
62
68
  );
63
- useDerive({ control, handleChange });
69
+ useDerive({ control, handleChange, data: projectedData });
64
70
  const mode = computed(() => {
65
71
  if (options.value.currency) return "currency";
66
72
  if (options.value.decimal || typeof options.value.precision === "number")
@@ -88,34 +94,30 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
88
94
  if (mode.value === "currency") return true;
89
95
  return options.value.useGrouping === true;
90
96
  });
91
- const hasInteracted = ref(false);
92
- const showErrors = computed(() => hasInteracted.value && control.value.errors);
97
+ const { showErrors, markDirty } = useDirtyValidation(control);
93
98
  const onNumber = (val) => {
94
99
  handleChange(control.value.path, val ?? void 0);
95
100
  };
96
- const onBlur = () => {
97
- hasInteracted.value = true;
98
- };
99
101
  return (_ctx, _cache) => {
100
102
  return openBlock(), createElementBlock("div", _hoisted_1, [
101
103
  unref(control).label ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(control).label), 1)) : createCommentVNode("", true),
102
104
  unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
103
105
  createVNode(unref(InputNumber), {
104
- class: "w-full",
105
- "input-class": "w-full",
106
+ class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
107
+ "input-class": ["w-full", { "p-invalid": unref(showErrors) }],
106
108
  "use-grouping": useGrouping.value,
107
109
  mode: mode.value,
108
110
  currency: currency.value,
109
111
  "min-fraction-digits": minFractionDigits.value,
110
112
  "max-fraction-digits": maxFractionDigits.value,
111
- "model-value": typeof unref(control).data === "number" ? unref(control).data : null,
113
+ "model-value": typeof unref(projectedData) === "number" ? unref(projectedData) : null,
112
114
  placeholder: placeholder.value,
113
115
  disabled: !unref(control).enabled,
114
- "aria-invalid": !!showErrors.value || void 0,
116
+ "aria-invalid": unref(showErrors) || void 0,
115
117
  "onUpdate:modelValue": onNumber,
116
- onBlur
117
- }, null, 8, ["use-grouping", "mode", "currency", "min-fraction-digits", "max-fraction-digits", "model-value", "placeholder", "disabled", "aria-invalid"]),
118
- showErrors.value ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(control).errors), 1)) : createCommentVNode("", true)
118
+ onBlur: unref(markDirty)
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(control).errors), 1)) : createCommentVNode("", true)
119
121
  ]);
120
122
  };
121
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 },\n cells: {\n type: Array,\n required: false,\n },\n config: {\n type: Object,\n required: false,\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, getCurrentInstance } from \"vue\";\nimport { useDerive } from \"../composables/useDerive\";\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 } = useJsonFormsControl(props);\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 });\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\nconst hasInteracted = ref(false);\n\nconst showErrors = computed(() => hasInteracted.value && control.value.errors);\n\nconst onNumber = (val: number | null) => {\n handleChange(control.value.path, val ?? undefined);\n};\n\nconst onBlur = () => {\n hasInteracted.value = true;\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 <InputNumber\n class=\"w-full\"\n input-class=\"w-full\"\n :use-grouping=\"useGrouping\"\n :mode=\"mode\"\n :currency=\"currency\"\n :min-fraction-digits=\"minFractionDigits\"\n :max-fraction-digits=\"maxFractionDigits\"\n :model-value=\"typeof control.data === 'number' ? control.data : null\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled\"\n :aria-invalid=\"!!showErrors || undefined\"\n @update:model-value=\"onNumber\"\n @blur=\"onBlur\"\n />\n <small v-if=\"showErrors\" class=\"p-error\">{{ control.errors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
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=\"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 <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\">{{ control.errors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":"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"}
@@ -18,14 +18,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
18
18
  renderers: {
19
19
  type: ArrayConstructor;
20
20
  required: false;
21
+ default: undefined;
21
22
  };
22
23
  cells: {
23
24
  type: ArrayConstructor;
24
25
  required: false;
26
+ default: undefined;
25
27
  };
26
28
  config: {
27
29
  type: ObjectConstructor;
28
30
  required: false;
31
+ default: undefined;
29
32
  };
30
33
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
31
34
  uischema: {
@@ -47,17 +50,23 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
47
50
  renderers: {
48
51
  type: ArrayConstructor;
49
52
  required: false;
53
+ default: undefined;
50
54
  };
51
55
  cells: {
52
56
  type: ArrayConstructor;
53
57
  required: false;
58
+ default: undefined;
54
59
  };
55
60
  config: {
56
61
  type: ObjectConstructor;
57
62
  required: false;
63
+ default: undefined;
58
64
  };
59
65
  }>> & Readonly<{}>, {
66
+ config: Record<string, any>;
60
67
  enabled: boolean;
68
+ renderers: unknown[];
69
+ cells: unknown[];
61
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
62
71
  export default _default;
63
72
  //# sourceMappingURL=JfText.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JfText.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfText.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyMA,wBAgXK"}
1
+ {"version":3,"file":"JfText.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfText.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA2MA,wBA2WK"}
@@ -1,7 +1,9 @@
1
- import { defineComponent, getCurrentInstance, computed, inject, ref, watch, createElementBlock, openBlock, createCommentVNode, createBlock, unref, toDisplayString } from "vue";
1
+ import { defineComponent, getCurrentInstance, computed, inject, ref, watch, createElementBlock, openBlock, createCommentVNode, createBlock, unref, toDisplayString, normalizeClass } from "vue";
2
2
  import { useJsonFormsControl } from "@jsonforms/vue";
3
3
  import { useProvider } from "../composables/useProvider.js";
4
4
  import { useDerive } from "../composables/useDerive.js";
5
+ import { useProjection } from "../composables/useProjection.js";
6
+ import { useDirtyValidation } from "../composables/useDirtyValidation.js";
5
7
  import InputText from "primevue/inputtext";
6
8
  import AutoComplete from "primevue/autocomplete";
7
9
  const _hoisted_1 = { class: "flex flex-column gap-2" };
@@ -43,15 +45,18 @@ const __default__ = {
43
45
  },
44
46
  renderers: {
45
47
  type: Array,
46
- required: false
48
+ required: false,
49
+ default: void 0
47
50
  },
48
51
  cells: {
49
52
  type: Array,
50
- required: false
53
+ required: false,
54
+ default: void 0
51
55
  },
52
56
  config: {
53
57
  type: Object,
54
- required: false
58
+ required: false,
59
+ default: void 0
55
60
  }
56
61
  }
57
62
  };
@@ -60,7 +65,8 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
60
65
  setup(__props) {
61
66
  const instance = getCurrentInstance();
62
67
  const props = instance.props;
63
- const { control, handleChange } = useJsonFormsControl(props);
68
+ const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
69
+ const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
64
70
  const binding = computed(() => {
65
71
  const provider = control.value.uischema?.options?.provider;
66
72
  if (provider && typeof provider === "object" && !provider.load) {
@@ -103,24 +109,21 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
103
109
  return control.value.uischema?.options?.placeholder ?? control.value.description;
104
110
  });
105
111
  const isAutocomplete = computed(() => !!binding.value);
106
- useDerive({ control, handleChange });
107
- const hasInteracted = ref(false);
108
- const hasFocused = ref(false);
109
- const showErrors = computed(() => hasInteracted.value && control.value.errors);
112
+ useDerive({ control, handleChange, data: projectedData });
113
+ const { showErrors, markDirty } = useDirtyValidation(control);
110
114
  function onInput(val) {
111
115
  const newValue = val && val.trim() !== "" ? val : void 0;
112
- if (control.value.data !== newValue) {
116
+ if (projectedData.value !== newValue) {
113
117
  handleChange(control.value.path, newValue);
114
118
  }
115
119
  }
116
120
  function onBlur() {
117
- if (hasFocused.value) {
118
- hasInteracted.value = true;
121
+ markDirty();
122
+ const val = projectedData.value;
123
+ if (typeof val === "string" && val.trim() === "") {
124
+ handleChange(control.value.path, void 0);
119
125
  }
120
126
  }
121
- function onFocus() {
122
- hasFocused.value = true;
123
- }
124
127
  const onComplete = (event) => {
125
128
  query.value = event.query;
126
129
  };
@@ -134,33 +137,31 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
134
137
  unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
135
138
  isAutocomplete.value ? (openBlock(), createBlock(unref(AutoComplete), {
136
139
  key: 2,
137
- class: "w-full",
138
- "model-value": unref(control).data ?? "",
140
+ class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
141
+ "model-value": unref(projectedData) ?? "",
139
142
  suggestions: unref(items),
140
143
  "option-label": "label",
141
144
  placeholder: placeholder.value,
142
145
  disabled: !unref(control).enabled,
143
- "aria-invalid": !!showErrors.value || void 0,
146
+ "aria-invalid": unref(showErrors) || void 0,
144
147
  onComplete,
145
148
  onItemSelect: onSelect,
146
149
  "onUpdate:modelValue": onInput,
147
- onBlur,
148
- onFocus
149
- }, null, 8, ["model-value", "suggestions", "placeholder", "disabled", "aria-invalid"])) : (openBlock(), createBlock(unref(InputText), {
150
+ onBlur
151
+ }, null, 8, ["class", "model-value", "suggestions", "placeholder", "disabled", "aria-invalid"])) : (openBlock(), createBlock(unref(InputText), {
150
152
  key: 3,
151
- class: "w-full",
152
- "model-value": unref(control).data ?? "",
153
+ class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
154
+ "model-value": unref(projectedData) ?? "",
153
155
  disabled: !unref(control).enabled,
154
- "aria-invalid": !!showErrors.value || void 0,
156
+ "aria-invalid": unref(showErrors) || void 0,
155
157
  placeholder: placeholder.value,
156
158
  autocapitalize: "off",
157
159
  autocomplete: "off",
158
160
  spellcheck: "false",
159
161
  "onUpdate:modelValue": onInput,
160
- onBlur,
161
- onFocus
162
- }, null, 8, ["model-value", "disabled", "aria-invalid", "placeholder"])),
163
- unref(error) ? (openBlock(), createElementBlock("small", _hoisted_4, "Failed: " + toDisplayString(unref(error)), 1)) : showErrors.value ? (openBlock(), createElementBlock("small", _hoisted_5, toDisplayString(unref(control).errors), 1)) : createCommentVNode("", true)
162
+ onBlur
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(control).errors), 1)) : createCommentVNode("", true)
164
165
  ]);
165
166
  };
166
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 },\n cells: {\n type: Array,\n required: false,\n },\n config: {\n type: Object,\n required: false,\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 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 } = useJsonFormsControl(props);\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 });\n\n// Track user interaction\nconst hasInteracted = ref(false);\nconst hasFocused = ref(false);\n\nconst showErrors = computed(() => hasInteracted.value && control.value.errors);\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 (control.value.data !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n if (hasFocused.value) {\n hasInteracted.value = true;\n }\n}\n\nfunction onFocus() {\n hasFocused.value = true;\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=\"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 <AutoComplete\n v-if=\"isAutocomplete\"\n class=\"w-full\"\n :model-value=\"control.data ?? ''\"\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 @focus=\"onFocus\"\n />\n <InputText\n v-else\n class=\"w-full\"\n :model-value=\"control.data ?? ''\"\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 @focus=\"onFocus\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\">Failed: {{ error }}</small>\n <small v-else-if=\"showErrors\" class=\"p-error\">{{ control.errors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createBlock"],"mappings":"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"}
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=\"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 <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\">{{ control.errors }}</small>\n </div>\n</template>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createBlock"],"mappings":"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"}
@@ -18,14 +18,17 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
18
18
  renderers: {
19
19
  type: ArrayConstructor;
20
20
  required: false;
21
+ default: undefined;
21
22
  };
22
23
  cells: {
23
24
  type: ArrayConstructor;
24
25
  required: false;
26
+ default: undefined;
25
27
  };
26
28
  config: {
27
29
  type: ObjectConstructor;
28
30
  required: false;
31
+ default: undefined;
29
32
  };
30
33
  }>, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<import("vue").ExtractPropTypes<{
31
34
  uischema: {
@@ -47,17 +50,23 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
47
50
  renderers: {
48
51
  type: ArrayConstructor;
49
52
  required: false;
53
+ default: undefined;
50
54
  };
51
55
  cells: {
52
56
  type: ArrayConstructor;
53
57
  required: false;
58
+ default: undefined;
54
59
  };
55
60
  config: {
56
61
  type: ObjectConstructor;
57
62
  required: false;
63
+ default: undefined;
58
64
  };
59
65
  }>> & Readonly<{}>, {
66
+ config: Record<string, any>;
60
67
  enabled: boolean;
68
+ renderers: unknown[];
69
+ cells: unknown[];
61
70
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
62
71
  export default _default;
63
72
  //# sourceMappingURL=JfTextArea.vue.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"JfTextArea.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfTextArea.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqGA,wBA+MK"}
1
+ {"version":3,"file":"JfTextArea.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfTextArea.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAgHA,wBA2NK"}
@@ -1,5 +1,7 @@
1
- import { defineComponent, getCurrentInstance, computed, ref, createElementBlock, openBlock, createCommentVNode, createVNode, unref, toDisplayString } from "vue";
1
+ import { defineComponent, getCurrentInstance, computed, createElementBlock, openBlock, createCommentVNode, createVNode, unref, toDisplayString, normalizeClass } from "vue";
2
2
  import { useJsonFormsControl } from "@jsonforms/vue";
3
+ import { useProjection } from "../composables/useProjection.js";
4
+ import { useDirtyValidation } from "../composables/useDirtyValidation.js";
3
5
  import Textarea from "primevue/textarea";
4
6
  const _hoisted_1 = { class: "flex flex-column gap-2" };
5
7
  const _hoisted_2 = {
@@ -35,15 +37,18 @@ const __default__ = {
35
37
  },
36
38
  renderers: {
37
39
  type: Array,
38
- required: false
40
+ required: false,
41
+ default: void 0
39
42
  },
40
43
  cells: {
41
44
  type: Array,
42
- required: false
45
+ required: false,
46
+ default: void 0
43
47
  },
44
48
  config: {
45
49
  type: Object,
46
- required: false
50
+ required: false,
51
+ default: void 0
47
52
  }
48
53
  }
49
54
  };
@@ -52,37 +57,41 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
52
57
  setup(__props) {
53
58
  const instance = getCurrentInstance();
54
59
  const props = instance.props;
55
- const { control, handleChange } = useJsonFormsControl(props);
60
+ const { control, handleChange: rawHandleChange } = useJsonFormsControl(props);
61
+ const { projectedData, handleProjectedChange: handleChange } = useProjection(control, rawHandleChange);
56
62
  const placeholder = computed(
57
63
  () => control.value.uischema?.options?.placeholder ?? control.value.description
58
64
  );
59
- const hasInteracted = ref(false);
60
- const showErrors = computed(() => hasInteracted.value && control.value.errors);
65
+ const { showErrors, markDirty } = useDirtyValidation(control);
61
66
  function onInput(val) {
62
67
  const newValue = val && val.trim() !== "" ? val : void 0;
63
- if (control.value.data !== newValue) {
68
+ if (projectedData.value !== newValue) {
64
69
  handleChange(control.value.path, newValue);
65
70
  }
66
71
  }
67
72
  function onBlur() {
68
- hasInteracted.value = true;
73
+ markDirty();
74
+ const val = projectedData.value;
75
+ if (typeof val === "string" && val.trim() === "") {
76
+ handleChange(control.value.path, void 0);
77
+ }
69
78
  }
70
79
  return (_ctx, _cache) => {
71
80
  return openBlock(), createElementBlock("div", _hoisted_1, [
72
81
  unref(control).label ? (openBlock(), createElementBlock("label", _hoisted_2, toDisplayString(unref(control).label), 1)) : createCommentVNode("", true),
73
82
  unref(control).description ? (openBlock(), createElementBlock("div", _hoisted_3, toDisplayString(unref(control).description), 1)) : createCommentVNode("", true),
74
83
  createVNode(unref(Textarea), {
75
- class: "w-full",
76
- "model-value": unref(control).data ?? "",
84
+ class: normalizeClass(["w-full", { "p-invalid": unref(showErrors) }]),
85
+ "model-value": unref(projectedData) ?? "",
77
86
  disabled: !unref(control).enabled,
78
- "aria-invalid": !!showErrors.value || void 0,
87
+ "aria-invalid": unref(showErrors) || void 0,
79
88
  placeholder: placeholder.value,
80
89
  rows: 4,
81
90
  "auto-resize": true,
82
91
  "onUpdate:modelValue": onInput,
83
92
  onBlur
84
- }, null, 8, ["model-value", "disabled", "aria-invalid", "placeholder"]),
85
- showErrors.value ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(control).errors), 1)) : createCommentVNode("", true)
93
+ }, null, 8, ["class", "model-value", "disabled", "aria-invalid", "placeholder"]),
94
+ unref(showErrors) ? (openBlock(), createElementBlock("small", _hoisted_4, toDisplayString(unref(control).errors), 1)) : createCommentVNode("", true)
86
95
  ]);
87
96
  };
88
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 },\n cells: {\n type: Array,\n required: false,\n },\n config: {\n type: Object,\n required: false,\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, getCurrentInstance } from \"vue\";\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 } = useJsonFormsControl(props);\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\nconst hasInteracted = ref(false);\n\nconst showErrors = computed(() => hasInteracted.value && control.value.errors);\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 (control.value.data !== newValue) {\n handleChange(control.value.path, newValue);\n }\n}\n\nfunction onBlur() {\n hasInteracted.value = true;\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 <Textarea\n class=\"w-full\"\n :model-value=\"control.data ?? ''\"\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\">{{ control.errors }}</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,IAAA;AAAA,IAEZ,OAAO;AAAA,MACL,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,IAEZ,QAAQ;AAAA,MACN,MAAM;AAAA,MACN,UAAU;AAAA,IAAA;AAAA,EACZ;AAEJ;;;;AAUA,UAAM,WAAW,mBAAA;AACjB,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,SAAS,iBAAiB,oBAAoB,KAAK;AAE3D,UAAM,cAAc;AAAA,MAClB,MACG,QAAQ,MAAM,UAAqD,SAChE,eAAe,QAAQ,MAAM;AAAA,IAAA;AAIrC,UAAM,gBAAgB,IAAI,KAAK;AAE/B,UAAM,aAAa,SAAS,MAAM,cAAc,SAAS,QAAQ,MAAM,MAAM;AAE7E,aAAS,QAAQ,KAAyB;AAExC,YAAM,WAAW,OAAO,IAAI,KAAA,MAAW,KAAK,MAAM;AAClD,UAAI,QAAQ,MAAM,SAAS,UAAU;AACnC,qBAAa,QAAQ,MAAM,MAAM,QAAQ;AAAA,MAC3C;AAAA,IACF;AAEA,aAAS,SAAS;AAChB,oBAAc,QAAQ;AAAA,IACxB;;AAIE,aAAAA,UAAA,GAAAC,mBAmBM,OAnBN,YAmBM;AAAA,QAlBSC,MAAA,OAAA,EAAQ,SAArBF,UAAA,GAAAC,mBAEU,SAFV,YAEUE,gBADRD,MAAA,OAAA,EAAQ,KAAK,GAAA,CAAA;QAEJA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YAUEF,MAAA,QAAA,GAAA;AAAA,UATA,OAAM;AAAA,UACL,eAAaA,MAAA,OAAA,EAAQ,QAAI;AAAA,UACzB,UAAQ,CAAGA,MAAA,OAAA,EAAQ;AAAA,UACnB,gBAAY,CAAA,CAAI,WAAA,SAAc;AAAA,UAC9B,aAAa,YAAA;AAAA,UACb,MAAM;AAAA,UACN,eAAa;AAAA,UACb,uBAAoB;AAAA,UACpB;AAAA,QAAA;QAEU,WAAA,SAAbF,UAAA,GAAAC,mBAAqE,SAArE,YAAqEE,gBAAzBD,MAAA,OAAA,EAAQ,MAAM,GAAA,CAAA;;;;;"}
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=\"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 <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\">{{ control.errors }}</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,iBAAiB,cAAc,SAAS,eAAe;AAErG,UAAM,cAAc;AAAA,MAClB,MACG,QAAQ,MAAM,UAAqD,SAChE,eAAe,QAAQ,MAAM;AAAA,IAAA;AAIrC,UAAM,EAAE,YAAY,cAAc,mBAAmB,OAAO;AAE5D,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,OAAA,EAAQ,SAArBF,UAAA,GAAAC,mBAEU,SAFV,YAEUE,gBADRD,MAAA,OAAA,EAAQ,KAAK,GAAA,CAAA;QAEJA,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,KAAbF,aAAAC,mBAAqE,SAArE,YAAqEE,gBAAzBD,MAAA,OAAA,EAAQ,MAAM,GAAA,CAAA;;;;;"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,SAAS,MAAM,iBAAiB,CAAC;AAkCxC,eAAO,MAAM,iBAAiB,EAAE,OAAO,EAAO,CAAC;AAK/C,wBAAgB,yBAAyB,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,EAAE,CAqFvE;AAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/index.ts"],"names":[],"mappings":"AAAA,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,QAAQ,MAAM,gBAAgB,CAAC;AACtC,OAAO,MAAM,MAAM,cAAc,CAAC;AAClC,OAAO,WAAW,MAAM,mBAAmB,CAAC;AAC5C,OAAO,SAAS,MAAM,iBAAiB,CAAC;AAoCxC,eAAO,MAAM,iBAAiB,EAAE,OAAO,EAAO,CAAC;AAK/C,wBAAgB,yBAAyB,CAAC,aAAa,EAAE,GAAG,GAAG,OAAO,EAAE,CA4GvE;AAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC"}