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

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.
@@ -1,5 +1,5 @@
1
1
 
2
- [data-v-140d349a] .p-dropdown-label {
2
+ [data-v-310ec8e4] .p-dropdown-label {
3
3
  text-align: left;
4
4
  }
5
5
 
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderSelect.vue"],"names":[],"mappings":"AAoHA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAQlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAgLF,wBAEG"}
1
+ {"version":3,"file":"ProviderSelect.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/components/ProviderSelect.vue"],"names":[],"mappings":"AAwHA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AASlE,KAAK,WAAW,GAAG;IACjB,QAAQ,EAAE,cAAc,CAAC;IACzB,MAAM,EAAE,UAAU,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;;AAmLF,wBAEG"}
@@ -1,7 +1,7 @@
1
1
  import _sfc_main from "./ProviderSelect.vue2.js";
2
2
  /* empty css */
3
3
  import _export_sfc from "../../_virtual/_plugin-vue_export-helper.js";
4
- const ProviderSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-140d349a"]]);
4
+ const ProviderSelect = /* @__PURE__ */ _export_sfc(_sfc_main, [["__scopeId", "data-v-310ec8e4"]]);
5
5
  export {
6
6
  ProviderSelect as default
7
7
  };
@@ -1,6 +1,7 @@
1
1
  import { defineComponent, computed, inject, watch, createElementBlock, openBlock, createCommentVNode, createVNode, unref, toDisplayString } from "vue";
2
2
  import { useJsonFormsControl } from "@jsonforms/vue";
3
3
  import { useProvider } from "../composables/useProvider.js";
4
+ import { useDeriveInitialValue } from "../composables/useDeriveInitialValue.js";
4
5
  import { useProjection } from "../composables/useProjection.js";
5
6
  import { shouldAutoSelect } from "../utils/autoSelect.js";
6
7
  import Dropdown from "primevue/dropdown";
@@ -51,6 +52,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
51
52
  path: control.value.path,
52
53
  dependsOnValues: depValues.value
53
54
  });
55
+ useDeriveInitialValue({ control, handleChange });
54
56
  watch(
55
57
  [items, loading],
56
58
  ([newItems, isLoading]) => {
@@ -1 +1 @@
1
- {"version":3,"file":"ProviderSelect.vue2.js","sources":["../../../src/vue/components/ProviderSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(\n control,\n rawHandleChange,\n);\n\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(() => deps.value.map(() => null)); // you can resolve actual values via control.value.data & pointers\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 { items, loading, error } = useProvider(binding, {\n data: rootData, // Pass the reactive reference\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\n// Provider will automatically reload when rootData changes due to reactive cache key\n\n// Auto-select when provider returns only one item (enabled by default)\nwatch(\n [items, loading],\n ([newItems, isLoading]) => {\n const valueToSelect = shouldAutoSelect({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle !== false,\n isLoading,\n items: newItems,\n currentValue: projectedData.value,\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true },\n);\n\nconst value = computed({\n get: () => projectedData.value,\n set: (v) => handleChange(control.value.path, v),\n});\n\nconst placeholder = computed(() => {\n if (loading.value) return \"Loading…\";\n // Check for placeholder in uischema options\n const uischemaPlaceholder = (\n control.value.uischema as { options?: { placeholder?: string } }\n )?.options?.placeholder;\n return uischemaPlaceholder || \"Select…\";\n});\n</script>\n\n<template>\n <div class=\"jf-control\">\n <label v-if=\"control.schema.title\" class=\"jf-label\">{{\n control.schema.title\n }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\n {{ control.description }}\n </div>\n <Dropdown\n v-model=\"value\"\n class=\"w-full!\"\n :options=\"items\"\n option-label=\"label\"\n option-value=\"value\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled || loading\"\n :show-clear=\"true\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n </div>\n</template>\n\n<style scoped>\n:deep(.p-dropdown-label) {\n text-align: left;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AASA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,aAAA,IAAiB;AAAA,MAC7D;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAAA,MACX,MAEK,QAAQ,MAAM,SACb,YACF,GACC,aAA0B,CAAA;AAAA,IAAC;AAElC,UAAM,YAAY,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,IAAI,CAAC;AAG3D,UAAM,mBAAmB,OAA2B,YAAY,EAAE,OAAO,CAAA,GAAI;AAC7E,UAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAA,CAAE;AAE5D,UAAM,EAAE,OAAO,SAAS,MAAA,IAAU,YAAY,SAAS;AAAA,MACrD,MAAM;AAAA;AAAA,MACN,MAAM,QAAQ,MAAM;AAAA,MACpB,iBAAiB,UAAU;AAAA,IAAA,CAC5B;AAKD;AAAA,MACE,CAAC,OAAO,OAAO;AAAA,MACf,CAAC,CAAC,UAAU,SAAS,MAAM;AACzB,cAAM,gBAAgB,iBAAiB;AAAA,UACrC,kBACE,QAAQ,MAAM,UAAU,SAAS,qBAAqB;AAAA,UACxD;AAAA,UACA,OAAO;AAAA,UACP,cAAc,cAAc;AAAA,QAAA,CAC7B;AAED,YAAI,kBAAkB,MAAM;AAC1B,uBAAa,QAAQ,MAAM,MAAM,aAAa;AAAA,QAChD;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAA;AAAA,IAAK;AAGpB,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,cAAc;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;AAED,UAAM,cAAc,SAAS,MAAM;AACjC,UAAI,QAAQ,MAAO,QAAO;AAE1B,YAAM,sBACJ,QAAQ,MAAM,UACb,SAAS;AACZ,aAAO,uBAAuB;AAAA,IAChC,CAAC;;AAIC,aAAAA,UAAA,GAAAC,mBAoBM,OApBN,YAoBM;AAAA,QAnBSC,MAAA,OAAA,EAAQ,OAAO,SAA5BF,aAAAC,mBAEU,SAFV,YAEUE,gBADRD,eAAQ,OAAO,KAAK,GAAA,CAAA;QAEXA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YASEF,MAAA,QAAA,GAAA;AAAA,sBARS,MAAA;AAAA,uEAAA,MAAK,QAAA;AAAA,UACd,OAAM;AAAA,UACL,SAASA,MAAA,KAAA;AAAA,UACV,gBAAa;AAAA,UACb,gBAAa;AAAA,UACZ,aAAa,YAAA;AAAA,UACb,UAAQ,CAAGA,MAAA,OAAA,EAAQ,WAAWA,MAAA,OAAA;AAAA,UAC9B,cAAY;AAAA,QAAA;QAEFA,MAAA,KAAA,KAAbF,aAAAC,mBAEC,SAFD,YACG,qCAAmBC,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
1
+ {"version":3,"file":"ProviderSelect.vue2.js","sources":["../../../src/vue/components/ProviderSelect.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport type { ControlElement, JsonSchema } from \"@jsonforms/core\";\nimport { useJsonFormsControl } from \"@jsonforms/vue\";\nimport { computed, inject, watch } from \"vue\";\nimport { useProvider } from \"../composables/useProvider\";\nimport { useDeriveInitialValue } from \"../composables/useDeriveInitialValue\";\nimport { useProjection } from \"../composables/useProjection\";\nimport { shouldAutoSelect } from \"../utils/autoSelect\";\nimport Dropdown from \"primevue/dropdown\";\n\nconst props = defineProps<{\n uischema: ControlElement;\n schema: JsonSchema;\n path: string;\n}>();\nconst { control, handleChange: rawHandleChange } = useJsonFormsControl(props);\nconst { projectedData, handleProjectedChange: handleChange } = useProjection(\n control,\n rawHandleChange,\n);\n\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(() => deps.value.map(() => null)); // you can resolve actual values via control.value.data & pointers\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 { items, loading, error } = useProvider(binding, {\n data: rootData, // Pass the reactive reference\n path: control.value.path,\n dependsOnValues: depValues.value,\n});\n\n// Provider will automatically reload when rootData changes due to reactive cache key\n\n// deriveInitialValue — async API-based initial value seeding\nuseDeriveInitialValue({ control, handleChange });\n\n// Auto-select when provider returns only one item (enabled by default)\nwatch(\n [items, loading],\n ([newItems, isLoading]) => {\n const valueToSelect = shouldAutoSelect({\n autoSelectSingle:\n control.value.uischema?.options?.autoSelectSingle !== false,\n isLoading,\n items: newItems,\n currentValue: projectedData.value,\n });\n\n if (valueToSelect !== null) {\n handleChange(control.value.path, valueToSelect);\n }\n },\n { immediate: true },\n);\n\nconst value = computed({\n get: () => projectedData.value,\n set: (v) => handleChange(control.value.path, v),\n});\n\nconst placeholder = computed(() => {\n if (loading.value) return \"Loading…\";\n // Check for placeholder in uischema options\n const uischemaPlaceholder = (\n control.value.uischema as { options?: { placeholder?: string } }\n )?.options?.placeholder;\n return uischemaPlaceholder || \"Select…\";\n});\n</script>\n\n<template>\n <div class=\"jf-control\">\n <label v-if=\"control.schema.title\" class=\"jf-label\">{{\n control.schema.title\n }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\n {{ control.description }}\n </div>\n <Dropdown\n v-model=\"value\"\n class=\"w-full!\"\n :options=\"items\"\n option-label=\"label\"\n option-value=\"value\"\n :placeholder=\"placeholder\"\n :disabled=\"!control.enabled || loading\"\n :show-clear=\"true\"\n />\n <small v-if=\"error\" class=\"p-error\" role=\"alert\"\n >Failed to load: {{ error }}</small\n >\n </div>\n</template>\n\n<style scoped>\n:deep(.p-dropdown-label) {\n text-align: left;\n}\n</style>\n"],"names":["_openBlock","_createElementBlock","_unref","_toDisplayString","_createVNode"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAUA,UAAM,QAAQ;AAKd,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM,EAAE,eAAe,uBAAuB,aAAA,IAAiB;AAAA,MAC7D;AAAA,MACA;AAAA,IAAA;AAGF,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAAA,MACX,MAEK,QAAQ,MAAM,SACb,YACF,GACC,aAA0B,CAAA;AAAA,IAAC;AAElC,UAAM,YAAY,SAAS,MAAM,KAAK,MAAM,IAAI,MAAM,IAAI,CAAC;AAG3D,UAAM,mBAAmB,OAA2B,YAAY,EAAE,OAAO,CAAA,GAAI;AAC7E,UAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAA,CAAE;AAE5D,UAAM,EAAE,OAAO,SAAS,MAAA,IAAU,YAAY,SAAS;AAAA,MACrD,MAAM;AAAA;AAAA,MACN,MAAM,QAAQ,MAAM;AAAA,MACpB,iBAAiB,UAAU;AAAA,IAAA,CAC5B;AAKD,0BAAsB,EAAE,SAAS,cAAc;AAG/C;AAAA,MACE,CAAC,OAAO,OAAO;AAAA,MACf,CAAC,CAAC,UAAU,SAAS,MAAM;AACzB,cAAM,gBAAgB,iBAAiB;AAAA,UACrC,kBACE,QAAQ,MAAM,UAAU,SAAS,qBAAqB;AAAA,UACxD;AAAA,UACA,OAAO;AAAA,UACP,cAAc,cAAc;AAAA,QAAA,CAC7B;AAED,YAAI,kBAAkB,MAAM;AAC1B,uBAAa,QAAQ,MAAM,MAAM,aAAa;AAAA,QAChD;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAA;AAAA,IAAK;AAGpB,UAAM,QAAQ,SAAS;AAAA,MACrB,KAAK,MAAM,cAAc;AAAA,MACzB,KAAK,CAAC,MAAM,aAAa,QAAQ,MAAM,MAAM,CAAC;AAAA,IAAA,CAC/C;AAED,UAAM,cAAc,SAAS,MAAM;AACjC,UAAI,QAAQ,MAAO,QAAO;AAE1B,YAAM,sBACJ,QAAQ,MAAM,UACb,SAAS;AACZ,aAAO,uBAAuB;AAAA,IAChC,CAAC;;AAIC,aAAAA,UAAA,GAAAC,mBAoBM,OApBN,YAoBM;AAAA,QAnBSC,MAAA,OAAA,EAAQ,OAAO,SAA5BF,aAAAC,mBAEU,SAFV,YAEUE,gBADRD,eAAQ,OAAO,KAAK,GAAA,CAAA;QAEXA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YASEF,MAAA,QAAA,GAAA;AAAA,sBARS,MAAA;AAAA,uEAAA,MAAK,QAAA;AAAA,UACd,OAAM;AAAA,UACL,SAASA,MAAA,KAAA;AAAA,UACV,gBAAa;AAAA,UACb,gBAAa;AAAA,UACZ,aAAa,YAAA;AAAA,UACb,UAAQ,CAAGA,MAAA,OAAA,EAAQ,WAAWA,MAAA,OAAA;AAAA,UAC9B,cAAY;AAAA,QAAA;QAEFA,MAAA,KAAA,KAAbF,aAAAC,mBAEC,SAFD,YACG,qCAAmBC,MAAA,KAAA,CAAK,GAAA,CAAA;;;;;"}
@@ -0,0 +1,36 @@
1
+ import { type Ref, type ComputedRef } from "vue";
2
+ import { type ControlElement } from "@jsonforms/core";
3
+ import { type TransformPipeline } from "../../core/transforms";
4
+ import type { AuthConfig } from "../../core/types";
5
+ export interface DeriveInitialValueCfg {
6
+ protocol: string;
7
+ config: {
8
+ url: string;
9
+ method?: "GET" | "POST";
10
+ headers?: Record<string, string>;
11
+ query?: Record<string, unknown>;
12
+ body?: unknown;
13
+ auth?: AuthConfig;
14
+ items: string;
15
+ map: {
16
+ value: string;
17
+ };
18
+ transforms?: TransformPipeline;
19
+ showError?: boolean;
20
+ };
21
+ }
22
+ interface DeriveInitialValueOptions {
23
+ control: Ref<{
24
+ uischema: ControlElement;
25
+ path: string;
26
+ data: unknown;
27
+ }>;
28
+ handleChange: (path: string, value: unknown) => void;
29
+ data?: Ref<unknown> | ComputedRef<unknown>;
30
+ }
31
+ export declare function useDeriveInitialValue({ control, handleChange, }: DeriveInitialValueOptions): {
32
+ loading: Ref<boolean, boolean>;
33
+ error: Ref<string | undefined, string | undefined>;
34
+ };
35
+ export {};
36
+ //# sourceMappingURL=useDeriveInitialValue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeriveInitialValue.d.ts","sourceRoot":"","sources":["../../../src/vue/composables/useDeriveInitialValue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,KAAK,GAAG,EAAE,KAAK,WAAW,EAAE,MAAM,KAAK,CAAC;AAC/E,OAAO,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAGtD,OAAO,EAEL,KAAK,iBAAiB,EACvB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,MAAM,WAAW,qBAAqB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE;QACN,GAAG,EAAE,MAAM,CAAC;QACZ,MAAM,CAAC,EAAE,KAAK,GAAG,MAAM,CAAC;QACxB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;QACjC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QAChC,IAAI,CAAC,EAAE,OAAO,CAAC;QACf,IAAI,CAAC,EAAE,UAAU,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE;YAAE,KAAK,EAAE,MAAM,CAAA;SAAE,CAAC;QACvB,UAAU,CAAC,EAAE,iBAAiB,CAAC;QAC/B,SAAS,CAAC,EAAE,OAAO,CAAC;KACrB,CAAC;CACH;AAED,UAAU,yBAAyB;IACjC,OAAO,EAAE,GAAG,CAAC;QACX,QAAQ,EAAE,cAAc,CAAC;QACzB,IAAI,EAAE,MAAM,CAAC;QACb,IAAI,EAAE,OAAO,CAAC;KACf,CAAC,CAAC;IACH,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IACrD,IAAI,CAAC,EAAE,GAAG,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;CAC5C;AAsDD,wBAAgB,qBAAqB,CAAC,EACpC,OAAO,EACP,YAAY,GACb,EAAE,yBAAyB;;;EAuG3B"}
@@ -0,0 +1,125 @@
1
+ import { inject, computed, ref, watch } from "vue";
2
+ import "@jsonforms/core";
3
+ import { renderTpl, renderObj } from "../../core/templating.js";
4
+ import { jp } from "../../core/jsonpath.js";
5
+ import { applyTransformPipeline } from "../../core/transforms.js";
6
+ function buildAuthHeaders(auth, globalAuth) {
7
+ const headers = {};
8
+ if (!auth) return headers;
9
+ if (auth.use && globalAuth?.[auth.use]) {
10
+ const globalValue = globalAuth[auth.use];
11
+ const value = typeof globalValue === "function" ? globalValue() : globalValue;
12
+ if (auth.use === "apiKey") headers["X-API-Key"] = String(value);
13
+ else if (auth.use === "bearer")
14
+ headers["Authorization"] = `Bearer ${value}`;
15
+ else if (auth.use === "token") headers["Authorization"] = `Token ${value}`;
16
+ return headers;
17
+ }
18
+ if (auth.bearer) {
19
+ const v = typeof auth.bearer === "function" ? auth.bearer() : auth.bearer;
20
+ headers["Authorization"] = `Bearer ${v}`;
21
+ }
22
+ if (auth.apiKey) {
23
+ const v = typeof auth.apiKey === "function" ? auth.apiKey() : auth.apiKey;
24
+ headers["X-API-Key"] = String(v);
25
+ }
26
+ if (auth.token) {
27
+ const v = typeof auth.token === "function" ? auth.token() : auth.token;
28
+ headers["Authorization"] = `Token ${v}`;
29
+ }
30
+ return headers;
31
+ }
32
+ function hasUnresolvedTemplates(templateUrl, renderedUrl) {
33
+ if (!templateUrl.includes("{{")) return false;
34
+ const pathPart = renderedUrl.replace(/^https?:\/\/[^/]+/, "");
35
+ if (pathPart.includes("//")) return true;
36
+ if (renderedUrl.endsWith("/") && !templateUrl.endsWith("/")) return true;
37
+ return false;
38
+ }
39
+ function useDeriveInitialValue({
40
+ control,
41
+ handleChange
42
+ }) {
43
+ const injectedFormData = inject("formData", {
44
+ value: {}
45
+ });
46
+ const rootData = computed(() => injectedFormData.value || {});
47
+ const auth = inject("providerAuth", {});
48
+ const cfg = computed(() => {
49
+ return control.value.uischema?.options?.deriveInitialValue;
50
+ });
51
+ const resolvedUrl = computed(() => {
52
+ const c = cfg.value;
53
+ if (!c?.config?.url) return null;
54
+ const rendered = renderTpl(c.config.url, { data: rootData.value });
55
+ if (hasUnresolvedTemplates(c.config.url, rendered)) return null;
56
+ return rendered;
57
+ });
58
+ const lastFetchedUrl = ref(null);
59
+ const loading = ref(false);
60
+ const error = ref(void 0);
61
+ watch(
62
+ resolvedUrl,
63
+ async (url) => {
64
+ if (!url || !cfg.value) return;
65
+ if (url === lastFetchedUrl.value) return;
66
+ lastFetchedUrl.value = url;
67
+ loading.value = true;
68
+ error.value = void 0;
69
+ try {
70
+ const c = cfg.value.config;
71
+ const fullUrl = new URL(url);
72
+ const q = renderObj(c.query ?? {}, {
73
+ data: rootData.value
74
+ });
75
+ for (const [k, v] of Object.entries(q)) {
76
+ if (v !== void 0 && v !== "")
77
+ fullUrl.searchParams.set(k, String(v));
78
+ }
79
+ const baseHeaders = renderObj(c.headers ?? {}, {
80
+ data: rootData.value
81
+ });
82
+ const authHeaders = buildAuthHeaders(c.auth, auth);
83
+ const headers = { ...baseHeaders, ...authHeaders };
84
+ const method = c.method ?? "GET";
85
+ const requestInit = { method, headers };
86
+ if (method !== "GET" && c.body) {
87
+ requestInit.body = JSON.stringify(
88
+ renderObj(c.body, { data: rootData.value })
89
+ );
90
+ }
91
+ const res = await fetch(fullUrl.toString(), requestInit);
92
+ if (!res.ok) {
93
+ if (c.showError !== false) {
94
+ throw new Error(`REST ${res.status}`);
95
+ }
96
+ return;
97
+ }
98
+ const json = await res.json();
99
+ let items = jp(json, c.items);
100
+ if (c.transforms && c.transforms.length > 0) {
101
+ items = applyTransformPipeline(items, c.transforms);
102
+ }
103
+ if (items.length === 0) return;
104
+ const derivedValue = jp(items[0], c.map.value)[0];
105
+ if (derivedValue !== void 0) {
106
+ handleChange(control.value.path, derivedValue);
107
+ }
108
+ } catch (e) {
109
+ error.value = e?.message ?? String(e);
110
+ console.warn(
111
+ `deriveInitialValue fetch failed for ${control.value.path}:`,
112
+ e
113
+ );
114
+ } finally {
115
+ loading.value = false;
116
+ }
117
+ },
118
+ { immediate: true }
119
+ );
120
+ return { loading, error };
121
+ }
122
+ export {
123
+ useDeriveInitialValue
124
+ };
125
+ //# sourceMappingURL=useDeriveInitialValue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useDeriveInitialValue.js","sources":["../../../src/vue/composables/useDeriveInitialValue.ts"],"sourcesContent":["import { computed, inject, ref, watch, type Ref, type ComputedRef } from \"vue\";\nimport { type ControlElement } from \"@jsonforms/core\";\nimport { renderTpl, renderObj } from \"../../core/templating\";\nimport { jp } from \"../../core/jsonpath\";\nimport {\n applyTransformPipeline,\n type TransformPipeline,\n} from \"../../core/transforms\";\nimport type { AuthConfig } from \"../../core/types\";\n\nexport interface DeriveInitialValueCfg {\n protocol: string;\n config: {\n url: string;\n method?: \"GET\" | \"POST\";\n headers?: Record<string, string>;\n query?: Record<string, unknown>;\n body?: unknown;\n auth?: AuthConfig;\n items: string;\n map: { value: string };\n transforms?: TransformPipeline;\n showError?: boolean;\n };\n}\n\ninterface DeriveInitialValueOptions {\n control: Ref<{\n uischema: ControlElement;\n path: string;\n data: unknown;\n }>;\n handleChange: (path: string, value: unknown) => void;\n data?: Ref<unknown> | ComputedRef<unknown>;\n}\n\nfunction buildAuthHeaders(\n auth?: AuthConfig,\n globalAuth?: Record<string, unknown>,\n): Record<string, string> {\n const headers: Record<string, string> = {};\n if (!auth) return headers;\n\n if (auth.use && globalAuth?.[auth.use]) {\n const globalValue = globalAuth[auth.use];\n const value =\n typeof globalValue === \"function\" ? globalValue() : globalValue;\n if (auth.use === \"apiKey\") headers[\"X-API-Key\"] = String(value);\n else if (auth.use === \"bearer\")\n headers[\"Authorization\"] = `Bearer ${value}`;\n else if (auth.use === \"token\") headers[\"Authorization\"] = `Token ${value}`;\n return headers;\n }\n\n if (auth.bearer) {\n const v = typeof auth.bearer === \"function\" ? auth.bearer() : auth.bearer;\n headers[\"Authorization\"] = `Bearer ${v}`;\n }\n if (auth.apiKey) {\n const v = typeof auth.apiKey === \"function\" ? auth.apiKey() : auth.apiKey;\n headers[\"X-API-Key\"] = String(v);\n }\n if (auth.token) {\n const v = typeof auth.token === \"function\" ? auth.token() : auth.token;\n headers[\"Authorization\"] = `Token ${v}`;\n }\n\n return headers;\n}\n\n/**\n * Returns true when the template URL contains `{{…}}` placeholders but\n * one or more of those placeholders resolved to an empty string, which\n * means a required data dependency hasn't been set yet.\n */\nfunction hasUnresolvedTemplates(\n templateUrl: string,\n renderedUrl: string,\n): boolean {\n if (!templateUrl.includes(\"{{\")) return false;\n // After protocol, empty segments indicate unresolved vars\n const pathPart = renderedUrl.replace(/^https?:\\/\\/[^/]+/, \"\");\n if (pathPart.includes(\"//\")) return true;\n // Trailing slash when the template didn't have one\n if (renderedUrl.endsWith(\"/\") && !templateUrl.endsWith(\"/\")) return true;\n return false;\n}\n\nexport function useDeriveInitialValue({\n control,\n handleChange,\n}: DeriveInitialValueOptions) {\n const injectedFormData = inject<{ value: unknown }>(\"formData\", {\n value: {},\n });\n const rootData = computed(() => injectedFormData.value || {});\n const auth = inject(\"providerAuth\", {}) as Record<string, unknown>;\n\n const cfg = computed<DeriveInitialValueCfg | undefined>(() => {\n return control.value.uischema?.options?.deriveInitialValue as\n | DeriveInitialValueCfg\n | undefined;\n });\n\n // Compute the resolved URL reactively\n const resolvedUrl = computed<string | null>(() => {\n const c = cfg.value;\n if (!c?.config?.url) return null;\n const rendered = renderTpl(c.config.url, { data: rootData.value });\n if (hasUnresolvedTemplates(c.config.url, rendered)) return null;\n return rendered;\n });\n\n const lastFetchedUrl = ref<string | null>(null);\n const loading = ref(false);\n const error = ref<string | undefined>(undefined);\n\n watch(\n resolvedUrl,\n async (url) => {\n if (!url || !cfg.value) return;\n // Only fetch when the URL changes (new context).\n // Same URL = same context; don't override user selection.\n if (url === lastFetchedUrl.value) return;\n lastFetchedUrl.value = url;\n\n loading.value = true;\n error.value = undefined;\n\n try {\n const c = cfg.value.config;\n const fullUrl = new URL(url);\n\n // Query params\n const q = renderObj(c.query ?? {}, {\n data: rootData.value,\n }) as Record<string, unknown>;\n for (const [k, v] of Object.entries(q)) {\n if (v !== undefined && v !== \"\")\n fullUrl.searchParams.set(k, String(v));\n }\n\n // Headers\n const baseHeaders = renderObj(c.headers ?? {}, {\n data: rootData.value,\n }) as Record<string, string>;\n const authHeaders = buildAuthHeaders(c.auth, auth);\n const headers = { ...baseHeaders, ...authHeaders };\n\n const method = c.method ?? \"GET\";\n const requestInit: RequestInit = { method, headers };\n if (method !== \"GET\" && c.body) {\n requestInit.body = JSON.stringify(\n renderObj(c.body, { data: rootData.value }),\n );\n }\n\n const res = await fetch(fullUrl.toString(), requestInit);\n if (!res.ok) {\n if (c.showError !== false) {\n throw new Error(`REST ${res.status}`);\n }\n return;\n }\n\n const json = await res.json();\n let items = jp(json, c.items);\n\n // Apply transforms if provided\n if (c.transforms && c.transforms.length > 0) {\n items = applyTransformPipeline(items, c.transforms);\n }\n\n if (items.length === 0) return; // No items → leave field empty\n\n // Extract value from first item\n const derivedValue = jp(items[0], c.map.value)[0];\n if (derivedValue !== undefined) {\n handleChange(control.value.path, derivedValue);\n }\n } catch (e) {\n error.value = (e as Error)?.message ?? String(e);\n console.warn(\n `deriveInitialValue fetch failed for ${control.value.path}:`,\n e,\n );\n } finally {\n loading.value = false;\n }\n },\n { immediate: true },\n );\n\n return { loading, error };\n}\n"],"names":[],"mappings":"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"}
@@ -21,6 +21,8 @@ export { useProjection } from "./composables/useProjection";
21
21
  export type { ProjectionResult } from "./composables/useProjection";
22
22
  export { createDataLayer, useDataLayer } from "./composables/useDataLayer";
23
23
  export type { DataLayer } from "./composables/useDataLayer";
24
+ export { useDeriveInitialValue } from "./composables/useDeriveInitialValue";
25
+ export type { DeriveInitialValueCfg } from "./composables/useDeriveInitialValue";
24
26
  export { useDirtyValidation } from "./composables/useDirtyValidation";
25
27
  export * from "./testers";
26
28
  export { JfText, JfTextArea, JfNumber, JfEnum, JfEnumArray, JfBoolean, } from "./primevue";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAUvD,OAAO,oBAAoB,MAAM,uCAAuC,CAAC;AACzE,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;AA2DvE,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAI7B,CAAC;AAGF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,cAAc,WAAW,CAAC;AAG1B,OAAO,EACL,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/vue/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAWvD,OAAO,oBAAoB,MAAM,uCAAuC,CAAC;AACzE,OAAO,cAAc,MAAM,iCAAiC,CAAC;AAC7D,OAAO,mBAAmB,MAAM,sCAAsC,CAAC;AAqEvE,eAAO,MAAM,iBAAiB;;;;;;;;;;;GAI7B,CAAC;AAGF,OAAO,EAAE,iBAAiB,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAG1E,OAAO,EAAE,oBAAoB,EAAE,cAAc,EAAE,mBAAmB,EAAE,CAAC;AACrE,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAC;AAC5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC3E,YAAY,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AAC5E,YAAY,EAAE,qBAAqB,EAAE,MAAM,qCAAqC,CAAC;AACjF,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAC;AACtE,cAAc,WAAW,CAAC;AAG1B,OAAO,EACL,MAAM,EACN,UAAU,EACV,QAAQ,EACR,MAAM,EACN,WAAW,EACX,SAAS,GACV,MAAM,YAAY,CAAC"}
package/dist/vue/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { rankWith, and, or, isStringControl, isNumberControl, isControl } from "@jsonforms/core";
1
+ import { rankWith, and, or, isStringControl, isNumberControl, isIntegerControl, isControl } from "@jsonforms/core";
2
2
  import { resolveScopeSchema } from "../core/resolveScope.js";
3
3
  import _sfc_main from "./components/ProviderAutocomplete.vue.js";
4
4
  import ProviderSelect from "./components/ProviderSelect.vue.js";
@@ -7,6 +7,7 @@ import { primevueRenderers, registerPrimevueRenderers } from "./primevue/index.j
7
7
  import { useProvider } from "./composables/useProvider.js";
8
8
  import { useProjection } from "./composables/useProjection.js";
9
9
  import { createDataLayer, useDataLayer } from "./composables/useDataLayer.js";
10
+ import { useDeriveInitialValue } from "./composables/useDeriveInitialValue.js";
10
11
  import { useDirtyValidation } from "./composables/useDirtyValidation.js";
11
12
  import { providerTester } from "./testers.js";
12
13
  import { default as default2 } from "./primevue/JfText.vue.js";
@@ -29,19 +30,29 @@ const isIntegerScope = (uischema, schema) => {
29
30
  return propertySchema?.type === "integer";
30
31
  };
31
32
  const providerSelectTester = rankWith(
32
- 106,
33
- // Higher than PrimeVue base (100) to ensure providers take precedence
33
+ 107,
34
+ // Higher than PrimeVue JfNumber integer renderer (106) so provider wins
34
35
  and(
35
- or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),
36
+ or(
37
+ isStringControl,
38
+ isNumberControl,
39
+ isIntegerControl,
40
+ and(isControl, isIntegerScope)
41
+ ),
36
42
  hasProvider,
37
43
  (uischema) => !uischema?.options?.autocomplete
38
44
  )
39
45
  );
40
46
  const providerAutocompleteTester = rankWith(
41
- 107,
42
- // Higher than PrimeVue base (100) to ensure providers take precedence
47
+ 108,
48
+ // Higher than providerSelectTester so autocomplete variant wins when flagged
43
49
  and(
44
- or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),
50
+ or(
51
+ isStringControl,
52
+ isNumberControl,
53
+ isIntegerControl,
54
+ and(isControl, isIntegerScope)
55
+ ),
45
56
  hasProvider,
46
57
  (uischema) => uischema?.options?.autocomplete === true
47
58
  )
@@ -59,7 +70,7 @@ const isArrayControl = (uischema, schema) => {
59
70
  return propertySchema?.type === "array";
60
71
  };
61
72
  const providerMultiSelectTester = rankWith(
62
- 108,
73
+ 109,
63
74
  // Highest priority for array controls with providers
64
75
  and(isArrayControl, hasProvider)
65
76
  );
@@ -84,6 +95,7 @@ export {
84
95
  providerTester,
85
96
  registerPrimevueRenderers,
86
97
  useDataLayer,
98
+ useDeriveInitialValue,
87
99
  useDirtyValidation,
88
100
  useProjection,
89
101
  useProvider
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../src/vue/index.ts"],"sourcesContent":["import type { UISchemaElement } from \"@jsonforms/core\";\nimport {\n and,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n isControl,\n} from \"@jsonforms/core\";\nimport { resolveScopeSchema } from \"../core/resolveScope\";\nimport ProviderAutocomplete from \"./components/ProviderAutocomplete.vue\";\nimport ProviderSelect from \"./components/ProviderSelect.vue\";\nimport ProviderMultiSelect from \"./components/ProviderMultiSelect.vue\";\n\n// Custom tester that checks if provider option exists (as object or boolean)\nconst hasProvider = (uischema: UISchemaElement) => {\n return uischema?.options?.provider !== undefined;\n};\n\n// Integer fallback tester — handles nested scopes like #/properties/parent/properties/child\nconst isIntegerScope = (uischema: unknown, schema: unknown) => {\n const ui = uischema as { type?: string; scope?: string };\n if (ui?.type !== \"Control\" || !ui?.scope) return false;\n\n const propertySchema = resolveScopeSchema(\n ui.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"integer\";\n};\n\n// Create specific testers for each component type\nconst providerSelectTester = rankWith(\n 106, // Higher than PrimeVue base (100) to ensure providers take precedence\n and(\n or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),\n hasProvider,\n (uischema) => !uischema?.options?.autocomplete,\n ),\n);\n\nconst providerAutocompleteTester = rankWith(\n 107, // Higher than PrimeVue base (100) to ensure providers take precedence\n and(\n or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),\n hasProvider,\n (uischema) => uischema?.options?.autocomplete === true,\n ),\n);\n\n// Custom array tester - supports nested scope paths\nconst isArrayControl = (uischema: UISchemaElement, schema: unknown) => {\n const controlSchema = uischema as { type: string; scope?: string };\n if (controlSchema.type !== \"Control\" || !controlSchema.scope) {\n return false;\n }\n\n const propertySchema = resolveScopeSchema(\n controlSchema.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"array\";\n};\n\nconst providerMultiSelectTester = rankWith(\n 108, // Highest priority for array controls with providers\n and(isArrayControl, hasProvider),\n);\n\nexport const providerRenderers = [\n { tester: providerMultiSelectTester, renderer: ProviderMultiSelect },\n { tester: providerAutocompleteTester, renderer: ProviderAutocomplete },\n { tester: providerSelectTester, renderer: ProviderSelect },\n];\n\n// Export PrimeVue renderers (styles are auto-injected)\nexport { primevueRenderers, registerPrimevueRenderers } from \"./primevue\";\n\n// Export individual components\nexport { ProviderAutocomplete, ProviderSelect, ProviderMultiSelect };\nexport { useProvider } from \"./composables/useProvider\";\nexport { useProjection } from \"./composables/useProjection\";\nexport type { ProjectionResult } from \"./composables/useProjection\";\nexport { createDataLayer, useDataLayer } from \"./composables/useDataLayer\";\nexport type { DataLayer } from \"./composables/useDataLayer\";\nexport { useDirtyValidation } from \"./composables/useDirtyValidation\";\nexport * from \"./testers\";\n\n// Export individual PrimeVue components using lazy evaluation to avoid circular deps\nexport {\n JfText,\n JfTextArea,\n JfNumber,\n JfEnum,\n JfEnumArray,\n JfBoolean,\n} from \"./primevue\";\n"],"names":["ProviderAutocomplete"],"mappings":";;;;;;;;;;;;;;;;;AAeA,MAAM,cAAc,CAAC,aAA8B;AACjD,SAAO,UAAU,SAAS,aAAa;AACzC;AAGA,MAAM,iBAAiB,CAAC,UAAmB,WAAoB;AAC7D,QAAM,KAAK;AACX,MAAI,IAAI,SAAS,aAAa,CAAC,IAAI,MAAO,QAAO;AAEjD,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA;AAAA,IAEH;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,IAAI,WAAW,cAAc,CAAC;AAAA,IACnE;AAAA,IACA,CAAC,aAAa,CAAC,UAAU,SAAS;AAAA,EAAA;AAEtC;AAEA,MAAM,6BAA6B;AAAA,EACjC;AAAA;AAAA,EACA;AAAA,IACE,GAAG,iBAAiB,iBAAiB,IAAI,WAAW,cAAc,CAAC;AAAA,IACnE;AAAA,IACA,CAAC,aAAa,UAAU,SAAS,iBAAiB;AAAA,EAAA;AAEtD;AAGA,MAAM,iBAAiB,CAAC,UAA2B,WAAoB;AACrE,QAAM,gBAAgB;AACtB,MAAI,cAAc,SAAS,aAAa,CAAC,cAAc,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAAA,IACrB,cAAc;AAAA;AAAA,IAEd;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAEA,MAAM,4BAA4B;AAAA,EAChC;AAAA;AAAA,EACA,IAAI,gBAAgB,WAAW;AACjC;AAEO,MAAM,oBAAoB;AAAA,EAC/B,EAAE,QAAQ,2BAA2B,UAAU,oBAAA;AAAA,EAC/C,EAAE,QAAQ,4BAA4B,UAAUA,UAAA;AAAA,EAChD,EAAE,QAAQ,sBAAsB,UAAU,eAAA;AAC5C;"}
1
+ {"version":3,"file":"index.js","sources":["../../src/vue/index.ts"],"sourcesContent":["import type { UISchemaElement } from \"@jsonforms/core\";\nimport {\n and,\n isIntegerControl,\n isNumberControl,\n isStringControl,\n or,\n rankWith,\n isControl,\n} from \"@jsonforms/core\";\nimport { resolveScopeSchema } from \"../core/resolveScope\";\nimport ProviderAutocomplete from \"./components/ProviderAutocomplete.vue\";\nimport ProviderSelect from \"./components/ProviderSelect.vue\";\nimport ProviderMultiSelect from \"./components/ProviderMultiSelect.vue\";\n\n// Custom tester that checks if provider option exists (as object or boolean)\nconst hasProvider = (uischema: UISchemaElement) => {\n return uischema?.options?.provider !== undefined;\n};\n\n// Integer fallback tester — handles nested scopes like #/properties/parent/properties/child\nconst isIntegerScope = (uischema: unknown, schema: unknown) => {\n const ui = uischema as { type?: string; scope?: string };\n if (ui?.type !== \"Control\" || !ui?.scope) return false;\n\n const propertySchema = resolveScopeSchema(\n ui.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"integer\";\n};\n\n// Create specific testers for each component type\nconst providerSelectTester = rankWith(\n 107, // Higher than PrimeVue JfNumber integer renderer (106) so provider wins\n and(\n or(\n isStringControl,\n isNumberControl,\n isIntegerControl,\n and(isControl, isIntegerScope),\n ),\n hasProvider,\n (uischema) => !uischema?.options?.autocomplete,\n ),\n);\n\nconst providerAutocompleteTester = rankWith(\n 108, // Higher than providerSelectTester so autocomplete variant wins when flagged\n and(\n or(\n isStringControl,\n isNumberControl,\n isIntegerControl,\n and(isControl, isIntegerScope),\n ),\n hasProvider,\n (uischema) => uischema?.options?.autocomplete === true,\n ),\n);\n\n// Custom array tester - supports nested scope paths\nconst isArrayControl = (uischema: UISchemaElement, schema: unknown) => {\n const controlSchema = uischema as { type: string; scope?: string };\n if (controlSchema.type !== \"Control\" || !controlSchema.scope) {\n return false;\n }\n\n const propertySchema = resolveScopeSchema(\n controlSchema.scope,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n schema as Record<string, any>,\n );\n return propertySchema?.type === \"array\";\n};\n\nconst providerMultiSelectTester = rankWith(\n 109, // Highest priority for array controls with providers\n and(isArrayControl, hasProvider),\n);\n\nexport const providerRenderers = [\n { tester: providerMultiSelectTester, renderer: ProviderMultiSelect },\n { tester: providerAutocompleteTester, renderer: ProviderAutocomplete },\n { tester: providerSelectTester, renderer: ProviderSelect },\n];\n\n// Export PrimeVue renderers (styles are auto-injected)\nexport { primevueRenderers, registerPrimevueRenderers } from \"./primevue\";\n\n// Export individual components\nexport { ProviderAutocomplete, ProviderSelect, ProviderMultiSelect };\nexport { useProvider } from \"./composables/useProvider\";\nexport { useProjection } from \"./composables/useProjection\";\nexport type { ProjectionResult } from \"./composables/useProjection\";\nexport { createDataLayer, useDataLayer } from \"./composables/useDataLayer\";\nexport type { DataLayer } from \"./composables/useDataLayer\";\nexport { useDeriveInitialValue } from \"./composables/useDeriveInitialValue\";\nexport type { DeriveInitialValueCfg } from \"./composables/useDeriveInitialValue\";\nexport { useDirtyValidation } from \"./composables/useDirtyValidation\";\nexport * from \"./testers\";\n\n// Export individual PrimeVue components using lazy evaluation to avoid circular deps\nexport {\n JfText,\n JfTextArea,\n JfNumber,\n JfEnum,\n JfEnumArray,\n JfBoolean,\n} from \"./primevue\";\n"],"names":["ProviderAutocomplete"],"mappings":";;;;;;;;;;;;;;;;;;AAgBA,MAAM,cAAc,CAAC,aAA8B;AACjD,SAAO,UAAU,SAAS,aAAa;AACzC;AAGA,MAAM,iBAAiB,CAAC,UAAmB,WAAoB;AAC7D,QAAM,KAAK;AACX,MAAI,IAAI,SAAS,aAAa,CAAC,IAAI,MAAO,QAAO;AAEjD,QAAM,iBAAiB;AAAA,IACrB,GAAG;AAAA;AAAA,IAEH;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAGA,MAAM,uBAAuB;AAAA,EAC3B;AAAA;AAAA,EACA;AAAA,IACE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,IAAI,WAAW,cAAc;AAAA,IAAA;AAAA,IAE/B;AAAA,IACA,CAAC,aAAa,CAAC,UAAU,SAAS;AAAA,EAAA;AAEtC;AAEA,MAAM,6BAA6B;AAAA,EACjC;AAAA;AAAA,EACA;AAAA,IACE;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA,IAAI,WAAW,cAAc;AAAA,IAAA;AAAA,IAE/B;AAAA,IACA,CAAC,aAAa,UAAU,SAAS,iBAAiB;AAAA,EAAA;AAEtD;AAGA,MAAM,iBAAiB,CAAC,UAA2B,WAAoB;AACrE,QAAM,gBAAgB;AACtB,MAAI,cAAc,SAAS,aAAa,CAAC,cAAc,OAAO;AAC5D,WAAO;AAAA,EACT;AAEA,QAAM,iBAAiB;AAAA,IACrB,cAAc;AAAA;AAAA,IAEd;AAAA,EAAA;AAEF,SAAO,gBAAgB,SAAS;AAClC;AAEA,MAAM,4BAA4B;AAAA,EAChC;AAAA;AAAA,EACA,IAAI,gBAAgB,WAAW;AACjC;AAEO,MAAM,oBAAoB;AAAA,EAC/B,EAAE,QAAQ,2BAA2B,UAAU,oBAAA;AAAA,EAC/C,EAAE,QAAQ,4BAA4B,UAAUA,UAAA;AAAA,EAChD,EAAE,QAAQ,sBAAsB,UAAU,eAAA;AAC5C;"}
@@ -1 +1 @@
1
- {"version":3,"file":"JfEnum.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnum.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwNA,wBAqUK"}
1
+ {"version":3,"file":"JfEnum.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfEnum.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA6NA,wBAwUK"}
@@ -2,6 +2,7 @@ import { defineComponent, getCurrentInstance, computed, inject, watch, createEle
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 { useDeriveInitialValue } from "../composables/useDeriveInitialValue.js";
5
6
  import { useProjection } from "../composables/useProjection.js";
6
7
  import { useDirtyValidation } from "../composables/useDirtyValidation.js";
7
8
  import { shouldAutoSelect } from "../utils/autoSelect.js";
@@ -131,6 +132,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
131
132
  return toOptions(control.value.schema);
132
133
  });
133
134
  useDerive({ control, handleChange, data: projectedData });
135
+ useDeriveInitialValue({ control, handleChange });
134
136
  watch(
135
137
  [providerItems, loading],
136
138
  ([items, isLoading]) => {
@@ -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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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":";;;;;;;;;;;;;;;;;;;;;;;;;;AAEA,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;;;;AAgBA,UAAM,WAAW,mBAAA;AACjB,UAAM,QAAQ,SAAS;AACvB,UAAM,EAAE,SAAS,cAAc,gBAAA,IAAoB,oBAAoB,KAAK;AAC5E,UAAM;AAAA,MACJ;AAAA,MACA,uBAAuB;AAAA,MACvB;AAAA,MACA;AAAA,IAAA,IACE,cAAc,SAAS,eAAe;AAG1C,UAAM,YAAY,CAAC,WAA+B;AAChD,UAAI,CAAC,OAAQ,QAAO,CAAA;AACpB,YAAM,IAAI;AAIV,UAAI,MAAM,QAAQ,EAAE,IAAI;AACtB,eAAO,EAAE,KAAK,IAAI,CAAC,OAAgB,EAAE,OAAO,OAAO,CAAC,GAAG,OAAO,EAAA,EAAI;AACpE,UAAI,MAAM,QAAQ,EAAE,KAAK;AACvB,eAAO,EAAE,MAAM,IAAI,CAAC,OAAO;AAAA,UACzB,OAAO,EAAE,SAAS,OAAO,EAAE,KAAK;AAAA,UAChC,OAAO,EAAE;AAAA,QAAA,EACT;AACJ,aAAO,CAAA;AAAA,IACT;AAGA,UAAM,UAAU,SAAS,MAAM;AAC7B,YAAM,WAAW,QAAQ,MAAM,UAAU,SAAS;AAElD,UAAI,YAAY,OAAO,aAAa,YAAY,CAAC,SAAS,MAAM;AAC9D,eAAO,EAAE,GAAG,UAAU,MAAM,QAAA;AAAA,MAC9B;AACA,aAAO;AAAA,IACT,CAAC;AAED,UAAM,OAAO;AAAA,MACX,MAEK,QAAQ,MAAM,SACb,YACF,GACC,aAA0B,CAAA;AAAA,IAAC;AAElC,UAAM,YAAY,SAAS,MAAM;AAC/B,aAAO,KAAK,MAAM,IAAI,CAAC,QAAQ;AAE7B,cAAM,OAAO,IAAI,WAAW,IAAI,IAAI,IAAI,MAAM,CAAC,IAAI;AACnD,cAAM,OAAO,KAAK,QAAQ,OAAO,GAAG,EAAE,MAAM,GAAG;AAC/C,YAAI,QAAiB,SAAS;AAC9B,mBAAW,OAAO,MAAM;AACtB,cAAI,SAAS,OAAO,UAAU,YAAY,OAAO,OAAO;AACtD,oBAAS,MAAkC,GAAG;AAAA,UAChD,OAAO;AACL,mBAAO;AAAA,UACT;AAAA,QACF;AACA,eAAO;AAAA,MACT,CAAC;AAAA,IACH,CAAC;AAGD,UAAM,mBAAmB,OAA2B,YAAY,EAAE,OAAO,CAAA,GAAI;AAC7E,UAAM,WAAW,SAAS,MAAM,iBAAiB,SAAS,CAAA,CAAE;AAG5D,UAAM;AAAA,MACJ,OAAO;AAAA,MACP;AAAA,MACA;AAAA,IAAA,IACE,YAAY,SAAS;AAAA,MACvB,MAAM;AAAA,MACN,MAAM,QAAQ,MAAM;AAAA,MACpB,iBAAiB,UAAU;AAAA,IAAA,CAC5B;AAED,UAAM,cAAc,SAA6B,MAAM;AACrD,UAAI,QAAQ,MAAO,QAAO;AAC1B,aACG,QAAQ,MAAM,UAAqD,SAChE,eAAe,QAAQ,MAAM;AAAA,IAErC,CAAC;AAED,UAAM,UAAU,SAAS,MAAM;AAE7B,UAAI,QAAQ,SAAS,cAAc,MAAM,SAAS,GAAG;AACnD,eAAO,cAAc;AAAA,MACvB;AACA,aAAO,UAAU,QAAQ,MAAM,MAAM;AAAA,IACvC,CAAC;AAGD,cAAU,EAAE,SAAS,cAAc,MAAM,eAAe;AAGxD;AAAA,MACE,CAAC,eAAe,OAAO;AAAA,MACvB,CAAC,CAAC,OAAO,SAAS,MAAM;AACtB,cAAM,gBAAgB,iBAAiB;AAAA,UACrC,kBACE,QAAQ,MAAM,UAAU,SAAS,qBAAqB;AAAA,UACxD;AAAA,UACA;AAAA,UACA,cAAc,cAAc;AAAA,QAAA,CAC7B;AAED,YAAI,kBAAkB,MAAM;AAC1B,uBAAa,QAAQ,MAAM,MAAM,aAAa;AAAA,QAChD;AAAA,MACF;AAAA,MACA,EAAE,WAAW,KAAA;AAAA,IAAK;AAIpB,UAAM,EAAE,YAAY,UAAA,IAAc,mBAAmB,SAAS,eAAe;AAE7E,UAAM,WAAW,CAAC,QAAiB;AACjC,mBAAa,QAAQ,MAAM,MAAM,GAAG;AAAA,IACtC;;AAIE,aAAAA,UAAA,GAAAC,mBAsBM,OAtBN,YAsBM;AAAA,QArBSC,MAAA,cAAA,kBAAbD,mBAA0E,SAA1E,YAA0EE,gBAAzBD,MAAA,cAAA,CAAc,GAAA,CAAA;QACpDA,MAAA,OAAA,EAAQ,eAAnBF,UAAA,GAAAC,mBAEM,OAFN,YAEME,gBADDD,MAAA,OAAA,EAAQ,WAAW,GAAA,CAAA;QAExBE,YAYEF,MAAA,QAAA,GAAA;AAAA,UAXC,iDAAkCA,MAAA,UAAA,EAAA,CAAU,CAAA;AAAA,UAC5C,SAAS,QAAA;AAAA,UACV,gBAAa;AAAA,UACb,gBAAa;AAAA,UACZ,eAAaA,MAAA,aAAA,KAAa;AAAA,UAC1B,aAAa,YAAA;AAAA,UACb,UAAQ,CAAGA,MAAA,OAAA,EAAQ,WAAWA,MAAA,OAAA;AAAA,UAC9B,gBAAcA,MAAA,UAAA,KAAc;AAAA,UAC5B,cAAY;AAAA,UACZ,uBAAoB;AAAA,UACpB,QAAMA,MAAA,SAAA;AAAA,QAAA;QAEIA,MAAA,KAAA,KAAbF,UAAA,GAAAC,mBAEC,SAFD,YACG,qCAAmBC,MAAA,KAAA,CAAK,GAAA,CAAA,KAETA,MAAA,UAAA,kBAAlBD,mBAA2E,SAA3E,YAA2EE,gBAA1BD,MAAA,eAAA,CAAe,GAAA,CAAA;;;;;"}
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 { useDeriveInitialValue } from \"../composables/useDeriveInitialValue\";\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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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// Add deriveInitialValue — async API-based initial value seeding\nuseDeriveInitialValue({ control, handleChange });\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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuJA,wBAuQK"}
1
+ {"version":3,"file":"JfNumber.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfNumber.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4JA,wBA0QK"}
@@ -1,6 +1,7 @@
1
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 { useDeriveInitialValue } from "../composables/useDeriveInitialValue.js";
4
5
  import { useProjection } from "../composables/useProjection.js";
5
6
  import { useDirtyValidation } from "../composables/useDirtyValidation.js";
6
7
  import InputNumber from "primevue/inputnumber";
@@ -72,6 +73,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
72
73
  () => options.value.placeholder ?? control.value.description
73
74
  );
74
75
  useDerive({ control, handleChange, data: projectedData });
76
+ useDeriveInitialValue({ control, handleChange });
75
77
  const mode = computed(() => {
76
78
  if (options.value.currency) return "currency";
77
79
  if (options.value.decimal || typeof options.value.precision === "number")
@@ -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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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
+ {"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 { useDeriveInitialValue } from \"../composables/useDeriveInitialValue\";\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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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// Add deriveInitialValue — async API-based initial value seeding\nuseDeriveInitialValue({ 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 — 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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA8MA,wBA4WK"}
1
+ {"version":3,"file":"JfText.vue.d.ts","sourceRoot":"","sources":["../../../src/vue/primevue/JfText.vue"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAmNA,wBA+WK"}
@@ -2,6 +2,7 @@ import { defineComponent, getCurrentInstance, computed, inject, ref, watch, crea
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 { useDeriveInitialValue } from "../composables/useDeriveInitialValue.js";
5
6
  import { useProjection } from "../composables/useProjection.js";
6
7
  import { useDirtyValidation } from "../composables/useDirtyValidation.js";
7
8
  import InputText from "primevue/inputtext";
@@ -115,6 +116,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
115
116
  });
116
117
  const isAutocomplete = computed(() => !!binding.value);
117
118
  useDerive({ control, handleChange, data: projectedData });
119
+ useDeriveInitialValue({ control, handleChange });
118
120
  const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
119
121
  function onInput(val) {
120
122
  const newValue = val && val.trim() !== "" ? val : void 0;
@@ -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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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
+ {"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 { useDeriveInitialValue } from \"../composables/useDeriveInitialValue\";\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 {\n projectedData,\n handleProjectedChange: handleChange,\n projectedErrors,\n projectedLabel,\n} = 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// Add deriveInitialValue — async API-based initial value seeding\nuseDeriveInitialValue({ control, handleChange });\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=\"jf-control\">\n <label v-if=\"projectedLabel\" class=\"jf-label\">{{ projectedLabel }}</label>\n <div v-if=\"control.description\" class=\"jf-description\">\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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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@narrative.io/jsonforms-provider-protocols",
3
- "version": "3.0.0-beta.4",
3
+ "version": "3.0.0-beta.6",
4
4
  "description": "Dynamic data provider capabilities for JSONForms with Vue 3 integration",
5
5
  "type": "module",
6
6
  "author": "Narrative I/O",
@@ -3,6 +3,7 @@ import type { ControlElement, JsonSchema } from "@jsonforms/core";
3
3
  import { useJsonFormsControl } from "@jsonforms/vue";
4
4
  import { computed, inject, watch } from "vue";
5
5
  import { useProvider } from "../composables/useProvider";
6
+ import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
6
7
  import { useProjection } from "../composables/useProjection";
7
8
  import { shouldAutoSelect } from "../utils/autoSelect";
8
9
  import Dropdown from "primevue/dropdown";
@@ -49,6 +50,9 @@ const { items, loading, error } = useProvider(binding, {
49
50
 
50
51
  // Provider will automatically reload when rootData changes due to reactive cache key
51
52
 
53
+ // deriveInitialValue — async API-based initial value seeding
54
+ useDeriveInitialValue({ control, handleChange });
55
+
52
56
  // Auto-select when provider returns only one item (enabled by default)
53
57
  watch(
54
58
  [items, loading],
@@ -0,0 +1,195 @@
1
+ import { computed, inject, ref, watch, type Ref, type ComputedRef } from "vue";
2
+ import { type ControlElement } from "@jsonforms/core";
3
+ import { renderTpl, renderObj } from "../../core/templating";
4
+ import { jp } from "../../core/jsonpath";
5
+ import {
6
+ applyTransformPipeline,
7
+ type TransformPipeline,
8
+ } from "../../core/transforms";
9
+ import type { AuthConfig } from "../../core/types";
10
+
11
+ export interface DeriveInitialValueCfg {
12
+ protocol: string;
13
+ config: {
14
+ url: string;
15
+ method?: "GET" | "POST";
16
+ headers?: Record<string, string>;
17
+ query?: Record<string, unknown>;
18
+ body?: unknown;
19
+ auth?: AuthConfig;
20
+ items: string;
21
+ map: { value: string };
22
+ transforms?: TransformPipeline;
23
+ showError?: boolean;
24
+ };
25
+ }
26
+
27
+ interface DeriveInitialValueOptions {
28
+ control: Ref<{
29
+ uischema: ControlElement;
30
+ path: string;
31
+ data: unknown;
32
+ }>;
33
+ handleChange: (path: string, value: unknown) => void;
34
+ data?: Ref<unknown> | ComputedRef<unknown>;
35
+ }
36
+
37
+ function buildAuthHeaders(
38
+ auth?: AuthConfig,
39
+ globalAuth?: Record<string, unknown>,
40
+ ): Record<string, string> {
41
+ const headers: Record<string, string> = {};
42
+ if (!auth) return headers;
43
+
44
+ if (auth.use && globalAuth?.[auth.use]) {
45
+ const globalValue = globalAuth[auth.use];
46
+ const value =
47
+ typeof globalValue === "function" ? globalValue() : globalValue;
48
+ if (auth.use === "apiKey") headers["X-API-Key"] = String(value);
49
+ else if (auth.use === "bearer")
50
+ headers["Authorization"] = `Bearer ${value}`;
51
+ else if (auth.use === "token") headers["Authorization"] = `Token ${value}`;
52
+ return headers;
53
+ }
54
+
55
+ if (auth.bearer) {
56
+ const v = typeof auth.bearer === "function" ? auth.bearer() : auth.bearer;
57
+ headers["Authorization"] = `Bearer ${v}`;
58
+ }
59
+ if (auth.apiKey) {
60
+ const v = typeof auth.apiKey === "function" ? auth.apiKey() : auth.apiKey;
61
+ headers["X-API-Key"] = String(v);
62
+ }
63
+ if (auth.token) {
64
+ const v = typeof auth.token === "function" ? auth.token() : auth.token;
65
+ headers["Authorization"] = `Token ${v}`;
66
+ }
67
+
68
+ return headers;
69
+ }
70
+
71
+ /**
72
+ * Returns true when the template URL contains `{{…}}` placeholders but
73
+ * one or more of those placeholders resolved to an empty string, which
74
+ * means a required data dependency hasn't been set yet.
75
+ */
76
+ function hasUnresolvedTemplates(
77
+ templateUrl: string,
78
+ renderedUrl: string,
79
+ ): boolean {
80
+ if (!templateUrl.includes("{{")) return false;
81
+ // After protocol, empty segments indicate unresolved vars
82
+ const pathPart = renderedUrl.replace(/^https?:\/\/[^/]+/, "");
83
+ if (pathPart.includes("//")) return true;
84
+ // Trailing slash when the template didn't have one
85
+ if (renderedUrl.endsWith("/") && !templateUrl.endsWith("/")) return true;
86
+ return false;
87
+ }
88
+
89
+ export function useDeriveInitialValue({
90
+ control,
91
+ handleChange,
92
+ }: DeriveInitialValueOptions) {
93
+ const injectedFormData = inject<{ value: unknown }>("formData", {
94
+ value: {},
95
+ });
96
+ const rootData = computed(() => injectedFormData.value || {});
97
+ const auth = inject("providerAuth", {}) as Record<string, unknown>;
98
+
99
+ const cfg = computed<DeriveInitialValueCfg | undefined>(() => {
100
+ return control.value.uischema?.options?.deriveInitialValue as
101
+ | DeriveInitialValueCfg
102
+ | undefined;
103
+ });
104
+
105
+ // Compute the resolved URL reactively
106
+ const resolvedUrl = computed<string | null>(() => {
107
+ const c = cfg.value;
108
+ if (!c?.config?.url) return null;
109
+ const rendered = renderTpl(c.config.url, { data: rootData.value });
110
+ if (hasUnresolvedTemplates(c.config.url, rendered)) return null;
111
+ return rendered;
112
+ });
113
+
114
+ const lastFetchedUrl = ref<string | null>(null);
115
+ const loading = ref(false);
116
+ const error = ref<string | undefined>(undefined);
117
+
118
+ watch(
119
+ resolvedUrl,
120
+ async (url) => {
121
+ if (!url || !cfg.value) return;
122
+ // Only fetch when the URL changes (new context).
123
+ // Same URL = same context; don't override user selection.
124
+ if (url === lastFetchedUrl.value) return;
125
+ lastFetchedUrl.value = url;
126
+
127
+ loading.value = true;
128
+ error.value = undefined;
129
+
130
+ try {
131
+ const c = cfg.value.config;
132
+ const fullUrl = new URL(url);
133
+
134
+ // Query params
135
+ const q = renderObj(c.query ?? {}, {
136
+ data: rootData.value,
137
+ }) as Record<string, unknown>;
138
+ for (const [k, v] of Object.entries(q)) {
139
+ if (v !== undefined && v !== "")
140
+ fullUrl.searchParams.set(k, String(v));
141
+ }
142
+
143
+ // Headers
144
+ const baseHeaders = renderObj(c.headers ?? {}, {
145
+ data: rootData.value,
146
+ }) as Record<string, string>;
147
+ const authHeaders = buildAuthHeaders(c.auth, auth);
148
+ const headers = { ...baseHeaders, ...authHeaders };
149
+
150
+ const method = c.method ?? "GET";
151
+ const requestInit: RequestInit = { method, headers };
152
+ if (method !== "GET" && c.body) {
153
+ requestInit.body = JSON.stringify(
154
+ renderObj(c.body, { data: rootData.value }),
155
+ );
156
+ }
157
+
158
+ const res = await fetch(fullUrl.toString(), requestInit);
159
+ if (!res.ok) {
160
+ if (c.showError !== false) {
161
+ throw new Error(`REST ${res.status}`);
162
+ }
163
+ return;
164
+ }
165
+
166
+ const json = await res.json();
167
+ let items = jp(json, c.items);
168
+
169
+ // Apply transforms if provided
170
+ if (c.transforms && c.transforms.length > 0) {
171
+ items = applyTransformPipeline(items, c.transforms);
172
+ }
173
+
174
+ if (items.length === 0) return; // No items → leave field empty
175
+
176
+ // Extract value from first item
177
+ const derivedValue = jp(items[0], c.map.value)[0];
178
+ if (derivedValue !== undefined) {
179
+ handleChange(control.value.path, derivedValue);
180
+ }
181
+ } catch (e) {
182
+ error.value = (e as Error)?.message ?? String(e);
183
+ console.warn(
184
+ `deriveInitialValue fetch failed for ${control.value.path}:`,
185
+ e,
186
+ );
187
+ } finally {
188
+ loading.value = false;
189
+ }
190
+ },
191
+ { immediate: true },
192
+ );
193
+
194
+ return { loading, error };
195
+ }
package/src/vue/index.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import type { UISchemaElement } from "@jsonforms/core";
2
2
  import {
3
3
  and,
4
+ isIntegerControl,
4
5
  isNumberControl,
5
6
  isStringControl,
6
7
  or,
@@ -32,18 +33,28 @@ const isIntegerScope = (uischema: unknown, schema: unknown) => {
32
33
 
33
34
  // Create specific testers for each component type
34
35
  const providerSelectTester = rankWith(
35
- 106, // Higher than PrimeVue base (100) to ensure providers take precedence
36
+ 107, // Higher than PrimeVue JfNumber integer renderer (106) so provider wins
36
37
  and(
37
- or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),
38
+ or(
39
+ isStringControl,
40
+ isNumberControl,
41
+ isIntegerControl,
42
+ and(isControl, isIntegerScope),
43
+ ),
38
44
  hasProvider,
39
45
  (uischema) => !uischema?.options?.autocomplete,
40
46
  ),
41
47
  );
42
48
 
43
49
  const providerAutocompleteTester = rankWith(
44
- 107, // Higher than PrimeVue base (100) to ensure providers take precedence
50
+ 108, // Higher than providerSelectTester so autocomplete variant wins when flagged
45
51
  and(
46
- or(isStringControl, isNumberControl, and(isControl, isIntegerScope)),
52
+ or(
53
+ isStringControl,
54
+ isNumberControl,
55
+ isIntegerControl,
56
+ and(isControl, isIntegerScope),
57
+ ),
47
58
  hasProvider,
48
59
  (uischema) => uischema?.options?.autocomplete === true,
49
60
  ),
@@ -65,7 +76,7 @@ const isArrayControl = (uischema: UISchemaElement, schema: unknown) => {
65
76
  };
66
77
 
67
78
  const providerMultiSelectTester = rankWith(
68
- 108, // Highest priority for array controls with providers
79
+ 109, // Highest priority for array controls with providers
69
80
  and(isArrayControl, hasProvider),
70
81
  );
71
82
 
@@ -85,6 +96,8 @@ export { useProjection } from "./composables/useProjection";
85
96
  export type { ProjectionResult } from "./composables/useProjection";
86
97
  export { createDataLayer, useDataLayer } from "./composables/useDataLayer";
87
98
  export type { DataLayer } from "./composables/useDataLayer";
99
+ export { useDeriveInitialValue } from "./composables/useDeriveInitialValue";
100
+ export type { DeriveInitialValueCfg } from "./composables/useDeriveInitialValue";
88
101
  export { useDirtyValidation } from "./composables/useDirtyValidation";
89
102
  export * from "./testers";
90
103
 
@@ -45,6 +45,7 @@ import { useJsonFormsControl } from "@jsonforms/vue";
45
45
  import { computed, inject, getCurrentInstance, watch } from "vue";
46
46
  import { useProvider } from "../composables/useProvider";
47
47
  import { useDerive } from "../composables/useDerive";
48
+ import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
48
49
  import { useProjection } from "../composables/useProjection";
49
50
  import { useDirtyValidation } from "../composables/useDirtyValidation";
50
51
  import { shouldAutoSelect } from "../utils/autoSelect";
@@ -147,6 +148,9 @@ const options = computed(() => {
147
148
  // Add derive functionality
148
149
  useDerive({ control, handleChange, data: projectedData });
149
150
 
151
+ // Add deriveInitialValue — async API-based initial value seeding
152
+ useDeriveInitialValue({ control, handleChange });
153
+
150
154
  // Auto-select when provider returns only one item (enabled by default)
151
155
  watch(
152
156
  [providerItems, loading],
@@ -42,6 +42,7 @@ import type { ControlProps } from "@jsonforms/vue";
42
42
  import { useJsonFormsControl } from "@jsonforms/vue";
43
43
  import { computed, getCurrentInstance } from "vue";
44
44
  import { useDerive } from "../composables/useDerive";
45
+ import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
45
46
  import { useProjection } from "../composables/useProjection";
46
47
  import { useDirtyValidation } from "../composables/useDirtyValidation";
47
48
  import InputNumber from "primevue/inputnumber";
@@ -70,6 +71,9 @@ const placeholder = computed<string | undefined>(
70
71
  // Add derive functionality
71
72
  useDerive({ control, handleChange, data: projectedData });
72
73
 
74
+ // Add deriveInitialValue — async API-based initial value seeding
75
+ useDeriveInitialValue({ control, handleChange });
76
+
73
77
  // Currency and decimal configuration
74
78
  const mode = computed(() => {
75
79
  if (options.value.currency) return "currency";
@@ -43,6 +43,7 @@ import { useJsonFormsControl } from "@jsonforms/vue";
43
43
  import { computed, ref, inject, watch, getCurrentInstance } from "vue";
44
44
  import { useProvider } from "../composables/useProvider";
45
45
  import { useDerive } from "../composables/useDerive";
46
+ import { useDeriveInitialValue } from "../composables/useDeriveInitialValue";
46
47
  import { useProjection } from "../composables/useProjection";
47
48
  import { useDirtyValidation } from "../composables/useDirtyValidation";
48
49
  import InputText from "primevue/inputtext";
@@ -123,6 +124,9 @@ const isAutocomplete = computed(() => !!binding.value);
123
124
  // Add derive functionality
124
125
  useDerive({ control, handleChange, data: projectedData });
125
126
 
127
+ // Add deriveInitialValue — async API-based initial value seeding
128
+ useDeriveInitialValue({ control, handleChange });
129
+
126
130
  // Track user interaction — errors only show after blur
127
131
  const { showErrors, markDirty } = useDirtyValidation(control, projectedErrors);
128
132