@narrative.io/jsonforms-provider-protocols 1.0.3 → 1.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/jsonforms-provider-protocols.css +6 -2
  2. package/dist/protocols/rest_api.d.ts.map +1 -1
  3. package/dist/protocols/rest_api.js +5 -1
  4. package/dist/protocols/rest_api.js.map +1 -1
  5. package/dist/vue/components/ProviderAutocomplete.vue.d.ts.map +1 -1
  6. package/dist/vue/components/ProviderAutocomplete.vue.js +36 -23
  7. package/dist/vue/components/ProviderAutocomplete.vue.js.map +1 -1
  8. package/dist/vue/components/ProviderSelect.vue.d.ts.map +1 -1
  9. package/dist/vue/components/ProviderSelect.vue.js +1 -1
  10. package/dist/vue/components/ProviderSelect.vue2.js +34 -28
  11. package/dist/vue/components/ProviderSelect.vue2.js.map +1 -1
  12. package/dist/vue/composables/useProvider.d.ts +10 -2
  13. package/dist/vue/composables/useProvider.d.ts.map +1 -1
  14. package/dist/vue/composables/useProvider.js +4 -2
  15. package/dist/vue/composables/useProvider.js.map +1 -1
  16. package/dist/vue/index.d.ts +2 -0
  17. package/dist/vue/index.d.ts.map +1 -1
  18. package/dist/vue/index.js +18 -2
  19. package/dist/vue/index.js.map +1 -1
  20. package/dist/vue/primevue/JfBoolean.vue.d.ts +75 -0
  21. package/dist/vue/primevue/JfBoolean.vue.d.ts.map +1 -0
  22. package/dist/vue/primevue/JfBoolean.vue.js +36 -0
  23. package/dist/vue/primevue/JfBoolean.vue.js.map +1 -0
  24. package/dist/vue/primevue/JfBoolean.vue2.js +5 -0
  25. package/dist/vue/primevue/JfBoolean.vue2.js.map +1 -0
  26. package/dist/vue/primevue/JfEnum.vue.d.ts +75 -0
  27. package/dist/vue/primevue/JfEnum.vue.d.ts.map +1 -0
  28. package/dist/vue/primevue/JfEnum.vue.js +8 -0
  29. package/dist/vue/primevue/JfEnum.vue.js.map +1 -0
  30. package/dist/vue/primevue/JfEnum.vue2.js +65 -0
  31. package/dist/vue/primevue/JfEnum.vue2.js.map +1 -0
  32. package/dist/vue/primevue/JfEnumArray.vue.d.ts +75 -0
  33. package/dist/vue/primevue/JfEnumArray.vue.d.ts.map +1 -0
  34. package/dist/vue/primevue/JfEnumArray.vue.js +84 -0
  35. package/dist/vue/primevue/JfEnumArray.vue.js.map +1 -0
  36. package/dist/vue/primevue/JfEnumArray.vue2.js +5 -0
  37. package/dist/vue/primevue/JfEnumArray.vue2.js.map +1 -0
  38. package/dist/vue/primevue/JfNumber.vue.d.ts +75 -0
  39. package/dist/vue/primevue/JfNumber.vue.d.ts.map +1 -0
  40. package/dist/vue/primevue/JfNumber.vue.js +50 -0
  41. package/dist/vue/primevue/JfNumber.vue.js.map +1 -0
  42. package/dist/vue/primevue/JfNumber.vue2.js +5 -0
  43. package/dist/vue/primevue/JfNumber.vue2.js.map +1 -0
  44. package/dist/vue/primevue/JfText.vue.d.ts +75 -0
  45. package/dist/vue/primevue/JfText.vue.d.ts.map +1 -0
  46. package/dist/vue/primevue/JfText.vue.js +56 -0
  47. package/dist/vue/primevue/JfText.vue.js.map +1 -0
  48. package/dist/vue/primevue/JfText.vue2.js +5 -0
  49. package/dist/vue/primevue/JfText.vue2.js.map +1 -0
  50. package/dist/vue/primevue/JfTextArea.vue.d.ts +75 -0
  51. package/dist/vue/primevue/JfTextArea.vue.d.ts.map +1 -0
  52. package/dist/vue/primevue/JfTextArea.vue.js +55 -0
  53. package/dist/vue/primevue/JfTextArea.vue.js.map +1 -0
  54. package/dist/vue/primevue/JfTextArea.vue2.js +5 -0
  55. package/dist/vue/primevue/JfTextArea.vue2.js.map +1 -0
  56. package/dist/vue/primevue/index.d.ts +83 -0
  57. package/dist/vue/primevue/index.d.ts.map +1 -0
  58. package/dist/vue/primevue/index.js +71 -0
  59. package/dist/vue/primevue/index.js.map +1 -0
  60. package/package.json +7 -2
  61. package/src/protocols/rest_api.ts +8 -1
  62. package/src/vue/components/ProviderAutocomplete.vue +31 -12
  63. package/src/vue/components/ProviderSelect.vue +40 -21
  64. package/src/vue/composables/useProvider.ts +3 -2
  65. package/src/vue/index.ts +7 -2
  66. package/src/vue/primevue/JfBoolean.vue +26 -0
  67. package/src/vue/primevue/JfEnum.vue +67 -0
  68. package/src/vue/primevue/JfEnumArray.vue +85 -0
  69. package/src/vue/primevue/JfNumber.vue +42 -0
  70. package/src/vue/primevue/JfText.vue +47 -0
  71. package/src/vue/primevue/JfTextArea.vue +46 -0
  72. package/src/vue/primevue/index.ts +99 -0
  73. package/src/vue/styles.css +15 -0
@@ -0,0 +1,67 @@
1
+ <script setup lang="ts">
2
+ import type { ControlElement, JsonSchema } from "@jsonforms/core";
3
+ import { rendererProps, useJsonFormsControl } from "@jsonforms/vue";
4
+ import { computed } from "vue";
5
+ import Dropdown from "primevue/dropdown";
6
+
7
+ defineOptions({ name: "JfEnum" });
8
+
9
+ const props = defineProps(rendererProps<ControlElement>());
10
+ const { control, handleChange } = useJsonFormsControl(props);
11
+
12
+ type Opt = { label: string; value: unknown };
13
+ const toOptions = (schema?: JsonSchema): Opt[] => {
14
+ if (!schema) return [];
15
+ const s = schema as {
16
+ enum?: unknown[];
17
+ oneOf?: Array<{ title?: string; const: unknown }>;
18
+ };
19
+ if (Array.isArray(s.enum))
20
+ return s.enum.map((v: unknown) => ({ label: String(v), value: v }));
21
+ if (Array.isArray(s.oneOf))
22
+ return s.oneOf.map((o) => ({
23
+ label: o.title ?? String(o.const),
24
+ value: o.const,
25
+ }));
26
+ return [];
27
+ };
28
+
29
+ const placeholder = computed<string | undefined>(
30
+ () =>
31
+ (control.value.uischema as { options?: { placeholder?: string } })?.options
32
+ ?.placeholder ?? control.value.description,
33
+ );
34
+
35
+ const options = computed(() => toOptions(control.value.schema));
36
+ const onSelect = (val: unknown) => handleChange(control.value.path, val);
37
+ </script>
38
+
39
+ <template>
40
+ <div class="flex flex-column gap-2">
41
+ <label v-if="control.label" class="text-color text-left">{{
42
+ control.label
43
+ }}</label>
44
+ <div v-if="control.description" class="text-color-secondary text-left">
45
+ {{ control.description }}
46
+ </div>
47
+ <Dropdown
48
+ class="w-full"
49
+ :options="options"
50
+ option-label="label"
51
+ option-value="value"
52
+ :model-value="control.data ?? null"
53
+ :placeholder="placeholder"
54
+ :disabled="!control.enabled"
55
+ :aria-invalid="!!control.errors || undefined"
56
+ :show-clear="true"
57
+ @update:model-value="onSelect"
58
+ />
59
+ <small v-if="control.errors" class="p-error">{{ control.errors }}</small>
60
+ </div>
61
+ </template>
62
+
63
+ <style scoped>
64
+ :deep(.p-dropdown-label) {
65
+ text-align: left;
66
+ }
67
+ </style>
@@ -0,0 +1,85 @@
1
+ <script setup lang="ts">
2
+ import type { ControlElement, JsonSchema } from "@jsonforms/core";
3
+ import { rendererProps, useJsonFormsControl } from "@jsonforms/vue";
4
+ import { computed } from "vue";
5
+ import MultiSelect from "primevue/multiselect";
6
+
7
+ defineOptions({ name: "JfEnumArray" });
8
+
9
+ const props = defineProps(rendererProps<ControlElement>());
10
+ const { control, handleChange } = useJsonFormsControl(props);
11
+
12
+ type Opt = { label: string; value: unknown };
13
+ const toOptions = (schema?: JsonSchema): Opt[] => {
14
+ if (!schema) return [];
15
+ const s = schema as {
16
+ enum?: unknown[];
17
+ oneOf?: Array<{ title?: string; const: unknown }>;
18
+ };
19
+ if (Array.isArray(s.enum))
20
+ return s.enum.map((v: unknown) => ({ label: String(v), value: v }));
21
+ if (Array.isArray(s.oneOf))
22
+ return s.oneOf.map((o) => ({
23
+ label: o.title ?? String(o.const),
24
+ value: o.const,
25
+ }));
26
+ return [];
27
+ };
28
+
29
+ const options = computed(() =>
30
+ toOptions((control.value.schema as { items?: JsonSchema })?.items),
31
+ );
32
+ const placeholder = computed<string | undefined>(
33
+ () =>
34
+ (control.value.uischema as { options?: { placeholder?: string } })?.options
35
+ ?.placeholder ?? control.value.description,
36
+ );
37
+
38
+ // order-insensitive shallow equality for primitive enums
39
+ const sameSet = (a: unknown[], b: unknown[]) => {
40
+ if (!Array.isArray(a) || !Array.isArray(b) || a.length !== b.length)
41
+ return false;
42
+ const s = new Set(b);
43
+ return a.every((v) => s.has(v));
44
+ };
45
+
46
+ // v-model with guard to avoid recursive updates
47
+ const model = computed<unknown[]>({
48
+ get() {
49
+ const curr = Array.isArray(control.value.data) ? control.value.data : [];
50
+ // return a fresh copy so PrimeMultiSelect can't mutate JSONForms' array in place
51
+ return [...curr];
52
+ },
53
+ set(val) {
54
+ const next = Array.isArray(val) ? [...val] : [];
55
+ const curr = Array.isArray(control.value.data) ? control.value.data : [];
56
+ if (!sameSet(curr, next)) handleChange(control.value.path, next);
57
+ },
58
+ });
59
+ </script>
60
+
61
+ <template>
62
+ <div class="flex flex-column gap-2">
63
+ <label v-if="control.label" class="text-color text-left">{{
64
+ control.label
65
+ }}</label>
66
+ <div v-if="control.description" class="text-color-secondary text-left">
67
+ {{ control.description }}
68
+ </div>
69
+
70
+ <MultiSelect
71
+ v-model="model"
72
+ class="w-full"
73
+ :options="options"
74
+ option-label="label"
75
+ option-value="value"
76
+ data-key="value"
77
+ display="chip"
78
+ :disabled="!control.enabled"
79
+ :aria-invalid="!!control.errors || undefined"
80
+ :placeholder="placeholder"
81
+ />
82
+
83
+ <small v-if="control.errors" class="p-error">{{ control.errors }}</small>
84
+ </div>
85
+ </template>
@@ -0,0 +1,42 @@
1
+ <script setup lang="ts">
2
+ import type { ControlElement } from "@jsonforms/core";
3
+ import { rendererProps, useJsonFormsControl } from "@jsonforms/vue";
4
+ import { computed } from "vue";
5
+ import InputNumber from "primevue/inputnumber";
6
+
7
+ defineOptions({ name: "JfNumber" });
8
+
9
+ const props = defineProps(rendererProps<ControlElement>());
10
+ const { control, handleChange } = useJsonFormsControl(props);
11
+
12
+ const placeholder = computed<string | undefined>(
13
+ () =>
14
+ (control.value.uischema as { options?: { placeholder?: string } })?.options
15
+ ?.placeholder ?? control.value.description,
16
+ );
17
+
18
+ const onNumber = (val: number | null) =>
19
+ handleChange(control.value.path, val ?? undefined);
20
+ </script>
21
+
22
+ <template>
23
+ <div class="flex flex-column gap-2">
24
+ <label v-if="control.label" class="text-color text-left">{{
25
+ control.label
26
+ }}</label>
27
+ <div v-if="control.description" class="text-color-secondary text-left">
28
+ {{ control.description }}
29
+ </div>
30
+ <InputNumber
31
+ class="w-full"
32
+ input-class="w-full"
33
+ :use-grouping="false"
34
+ :model-value="typeof control.data === 'number' ? control.data : null"
35
+ :placeholder="placeholder"
36
+ :disabled="!control.enabled"
37
+ :aria-invalid="!!control.errors || undefined"
38
+ @update:model-value="onNumber"
39
+ />
40
+ <small v-if="control.errors" class="p-error">{{ control.errors }}</small>
41
+ </div>
42
+ </template>
@@ -0,0 +1,47 @@
1
+ <script setup lang="ts">
2
+ import type { ControlElement } from "@jsonforms/core";
3
+ import { rendererProps, useJsonFormsControl } from "@jsonforms/vue";
4
+ import { computed } from "vue";
5
+ import InputText from "primevue/inputtext";
6
+
7
+ defineOptions({ name: "JfText" });
8
+
9
+ const props = defineProps(rendererProps<ControlElement>());
10
+ const { control, handleChange } = useJsonFormsControl(props);
11
+
12
+ const placeholder = computed<string | undefined>(
13
+ () =>
14
+ (control.value.uischema as { options?: { placeholder?: string } })?.options
15
+ ?.placeholder ?? control.value.description,
16
+ );
17
+
18
+ function onInput(val: string | undefined) {
19
+ const newValue = val ?? "";
20
+ if ((control.value.data ?? "") !== newValue) {
21
+ handleChange(control.value.path, newValue);
22
+ }
23
+ }
24
+ </script>
25
+
26
+ <template>
27
+ <div class="flex flex-column gap-2">
28
+ <label v-if="control.label" class="text-color text-left">{{
29
+ control.label
30
+ }}</label>
31
+ <div v-if="control.description" class="text-color-secondary text-left">
32
+ {{ control.description }}
33
+ </div>
34
+ <InputText
35
+ class="w-full"
36
+ :model-value="control.data ?? ''"
37
+ :disabled="!control.enabled"
38
+ :aria-invalid="!!control.errors || undefined"
39
+ :placeholder="placeholder"
40
+ autocapitalize="off"
41
+ autocomplete="off"
42
+ spellcheck="false"
43
+ @update:model-value="onInput"
44
+ />
45
+ <small v-if="control.errors" class="p-error">{{ control.errors }}</small>
46
+ </div>
47
+ </template>
@@ -0,0 +1,46 @@
1
+ <script setup lang="ts">
2
+ import type { ControlElement } from "@jsonforms/core";
3
+ import { rendererProps, useJsonFormsControl } from "@jsonforms/vue";
4
+ import { computed } from "vue";
5
+ import Textarea from "primevue/textarea";
6
+
7
+ defineOptions({ name: "JfTextArea" });
8
+
9
+ const props = defineProps(rendererProps<ControlElement>());
10
+ const { control, handleChange } = useJsonFormsControl(props);
11
+
12
+ const placeholder = computed<string | undefined>(
13
+ () =>
14
+ (control.value.uischema as { options?: { placeholder?: string } })?.options
15
+ ?.placeholder ?? control.value.description,
16
+ );
17
+
18
+ function onInput(val: string | undefined) {
19
+ const newValue = val ?? "";
20
+ if ((control.value.data ?? "") !== newValue) {
21
+ handleChange(control.value.path, newValue);
22
+ }
23
+ }
24
+ </script>
25
+
26
+ <template>
27
+ <div class="flex flex-column gap-2">
28
+ <label v-if="control.label" class="text-color text-left">{{
29
+ control.label
30
+ }}</label>
31
+ <div v-if="control.description" class="text-color-secondary text-left">
32
+ {{ control.description }}
33
+ </div>
34
+ <Textarea
35
+ class="w-full"
36
+ :model-value="control.data ?? ''"
37
+ :disabled="!control.enabled"
38
+ :aria-invalid="!!control.errors || undefined"
39
+ :placeholder="placeholder"
40
+ :rows="4"
41
+ :auto-resize="true"
42
+ @update:model-value="onInput"
43
+ />
44
+ <small v-if="control.errors" class="p-error">{{ control.errors }}</small>
45
+ </div>
46
+ </template>
@@ -0,0 +1,99 @@
1
+ import JfText from "./JfText.vue";
2
+ import JfTextArea from "./JfTextArea.vue";
3
+ import JfNumber from "./JfNumber.vue";
4
+ import JfEnum from "./JfEnum.vue";
5
+ import JfEnumArray from "./JfEnumArray.vue";
6
+ import JfBoolean from "./JfBoolean.vue";
7
+
8
+ // Auto-inject layout styles
9
+ const injectLayoutStyles = () => {
10
+ if (typeof window !== "undefined" && typeof document !== "undefined") {
11
+ if (!document.getElementById("jsonforms-primevue-styles")) {
12
+ const style = document.createElement("style");
13
+ style.id = "jsonforms-primevue-styles";
14
+ style.textContent = `
15
+ /* JSONForms PrimeVue Provider Protocols Layout Styles */
16
+ .vertical-layout {
17
+ display: flex;
18
+ flex-direction: column;
19
+ align-items: flex-start;
20
+ gap: 1rem;
21
+ width: 100%;
22
+ }
23
+
24
+ .vertical-layout-item {
25
+ width: 100%;
26
+ }
27
+ `;
28
+ document.head.appendChild(style);
29
+ }
30
+ }
31
+ };
32
+
33
+ // Inject styles when this module is imported
34
+ injectLayoutStyles();
35
+
36
+ import {
37
+ rankWith,
38
+ isStringControl,
39
+ or,
40
+ isNumberControl,
41
+ isIntegerControl,
42
+ and,
43
+ isControl,
44
+ schemaMatches,
45
+ isBooleanControl,
46
+ } from "@jsonforms/core";
47
+
48
+ // helpers for enum detection
49
+ const isScalarEnum = (s?: object) => {
50
+ const schema = s as { type?: string; enum?: unknown[]; oneOf?: unknown[] };
51
+ return (
52
+ schema &&
53
+ schema.type !== "array" &&
54
+ (Array.isArray(schema.enum) || Array.isArray(schema.oneOf))
55
+ );
56
+ };
57
+
58
+ const isEnumArray = (s?: object) => {
59
+ const schema = s as {
60
+ type?: string;
61
+ items?: { enum?: unknown[]; oneOf?: unknown[] };
62
+ };
63
+ return (
64
+ schema?.type === "array" &&
65
+ (Array.isArray(schema.items?.enum) || Array.isArray(schema.items?.oneOf))
66
+ );
67
+ };
68
+
69
+ // helper for multiline detection
70
+ const isMultilineString = (uischema: unknown, schema: unknown) => {
71
+ return (
72
+ isStringControl(uischema as never, schema as never, {} as never) &&
73
+ (uischema as { options?: { multi?: boolean } })?.options?.multi === true
74
+ );
75
+ };
76
+
77
+ // Give PrimeVue renderers a high base rank; vanilla commonly uses small ranks (2–5)
78
+ const PRIME = 100;
79
+
80
+ export const primevueRenderers = [
81
+ // Multiline text has higher priority than regular text
82
+ { tester: rankWith(PRIME + 4, isMultilineString), renderer: JfTextArea },
83
+ { tester: rankWith(PRIME + 3, isStringControl), renderer: JfText },
84
+ {
85
+ tester: rankWith(PRIME + 4, or(isNumberControl, isIntegerControl)),
86
+ renderer: JfNumber,
87
+ },
88
+ {
89
+ tester: rankWith(PRIME + 5, and(isControl, schemaMatches(isScalarEnum))),
90
+ renderer: JfEnum,
91
+ },
92
+ {
93
+ tester: rankWith(PRIME + 6, and(isControl, schemaMatches(isEnumArray))),
94
+ renderer: JfEnumArray,
95
+ },
96
+ { tester: rankWith(PRIME + 3, isBooleanControl), renderer: JfBoolean },
97
+ ];
98
+
99
+ export { JfText, JfTextArea, JfNumber, JfEnum, JfEnumArray, JfBoolean };
@@ -0,0 +1,15 @@
1
+ /* JSONForms PrimeVue Provider Protocols Layout Styles */
2
+
3
+ /* Style the vanilla VerticalLayout to be centered with gaps */
4
+ .vertical-layout {
5
+ display: flex;
6
+ flex-direction: column;
7
+ align-items: flex-start;
8
+ gap: 1rem;
9
+ width: 100%;
10
+ }
11
+
12
+ /* Style individual vertical layout items */
13
+ .vertical-layout-item {
14
+ width: 100%;
15
+ }