@ghentcdh/json-forms-vue 0.8.5 → 1.0.1

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 (72) hide show
  1. package/form.store.d.ts +1 -1
  2. package/forms/Dispatch.vue.d.ts +10 -0
  3. package/forms/FormComponent.properties.d.ts +48 -0
  4. package/{form.component.vue.d.ts → forms/FormComponent.vue.d.ts} +19 -17
  5. package/forms/FormWithActions.properties.d.ts +52 -0
  6. package/forms/FormWithActions.vue.d.ts +258 -0
  7. package/forms/FormWithTable.properties.d.ts +65 -0
  8. package/{form-with-table.component.vue.d.ts → forms/FormWithTable.vue.d.ts} +24 -15
  9. package/forms/errorMessages.d.ts +10 -0
  10. package/forms/errorMode.d.ts +4 -0
  11. package/forms/modal/FormModal.properties.d.ts +64 -0
  12. package/forms/modal/FormModal.vue.d.ts +275 -0
  13. package/{modal/form-modal.service.d.ts → forms/modal/FormModalService.d.ts} +4 -5
  14. package/forms/renderer-registry.d.ts +7 -0
  15. package/forms/renderers/array/ArrayRenderer.vue.d.ts +7 -0
  16. package/forms/renderers/array/ArrayRenderers.d.ts +10 -0
  17. package/forms/renderers/controls/AutocompleteControlRenderer.vue.d.ts +7 -0
  18. package/forms/renderers/controls/BooleanControlRenderer.vue.d.ts +7 -0
  19. package/forms/renderers/controls/MarkdownControlRenderer.vue.d.ts +7 -0
  20. package/forms/renderers/controls/MultiSelectControlRenderer.vue.d.ts +7 -0
  21. package/forms/renderers/controls/NumberControlRenderer.vue.d.ts +7 -0
  22. package/forms/renderers/controls/SelectControlRenderer.vue.d.ts +7 -0
  23. package/forms/renderers/controls/StringControlRenderer.vue.d.ts +7 -0
  24. package/forms/renderers/controls/TextAreaControlRenderer.vue.d.ts +7 -0
  25. package/forms/renderers/controls/composable/UseControlBinding.d.ts +29 -0
  26. package/forms/renderers/controls/composable/UseFetchOption.d.ts +16 -0
  27. package/forms/renderers/controls/composable/UseInput.d.ts +24 -0
  28. package/forms/renderers/controls/composable/UseSelectBinding.d.ts +23 -0
  29. package/forms/renderers/controls/composable/resource.d.ts +187 -0
  30. package/forms/renderers/controls/index.d.ts +10 -0
  31. package/forms/renderers/index.d.ts +3 -0
  32. package/forms/renderers/layout/CollapseLayoutRenderer.vue.d.ts +7 -0
  33. package/forms/renderers/layout/LayoutRenderer.vue.d.ts +7 -0
  34. package/forms/renderers/layout/LayoutRenders.d.ts +10 -0
  35. package/forms/renderers/layout/colspan.d.ts +1 -0
  36. package/forms/renderes.d.ts +19 -0
  37. package/forms/scope.d.ts +4 -0
  38. package/forms/types.d.ts +36 -0
  39. package/index.d.ts +9 -12
  40. package/index.js +1828 -1491
  41. package/index.mjs +1879 -1542
  42. package/package.json +4 -5
  43. package/renderes/tester.d.ts +2 -0
  44. package/form-with-actions.component.properties.d.ts +0 -40
  45. package/form-with-actions.component.vue.d.ts +0 -88
  46. package/form-with-table.component.properties.d.ts +0 -58
  47. package/form.component.properties.d.ts +0 -49
  48. package/modal/form-modal.props.d.ts +0 -30
  49. package/modal/form-modal.vue.d.ts +0 -35
  50. package/modal/index.d.ts +0 -3
  51. package/renderes/array/ArrayRenderer.vue.d.ts +0 -74
  52. package/renderes/array/index.d.ts +0 -76
  53. package/renderes/controls/AutocompleteControlRenderer.vue.d.ts +0 -74
  54. package/renderes/controls/BooleanControlRenderer.vue.d.ts +0 -74
  55. package/renderes/controls/IntegerControlRenderer.vue.d.ts +0 -74
  56. package/renderes/controls/MarkdownControlRenderer.vue.d.ts +0 -74
  57. package/renderes/controls/MultiSelectControlRender.vue.d.ts +0 -74
  58. package/renderes/controls/NumberControlRenderer.vue.d.ts +0 -74
  59. package/renderes/controls/SelectControlRender.vue.d.ts +0 -74
  60. package/renderes/controls/StringControlRenderer.vue.d.ts +0 -74
  61. package/renderes/controls/TextAreaControlRenderer.vue.d.ts +0 -74
  62. package/renderes/controls/index.d.ts +0 -675
  63. package/renderes/index.d.ts +0 -817
  64. package/renderes/layouts/CollapseLayout.vue.d.ts +0 -73
  65. package/renderes/layouts/GridLayout.vue.d.ts +0 -73
  66. package/renderes/layouts/HorizontalLayout.vue.d.ts +0 -73
  67. package/renderes/layouts/VerticalLayout.vue.d.ts +0 -73
  68. package/renderes/layouts/index.d.ts +0 -75
  69. package/standalone/emits.d.ts +0 -5
  70. package/standalone/properties.d.ts +0 -2
  71. package/utils/style.d.ts +0 -6
  72. package/utils/vanillaControl.d.ts +0 -15
package/index.js CHANGED
@@ -1,1115 +1,398 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const toolsVue = require("@ghentcdh/tools-vue");
4
- const ui = require("@ghentcdh/ui");
5
- const core = require("@jsonforms/core");
6
3
  const vue = require("vue");
7
- const vue$1 = require("@jsonforms/vue");
8
- const axios = require("axios");
9
- const vueVanilla = require("@jsonforms/vue-vanilla");
10
4
  const lodashEs = require("lodash-es");
11
- const testers = require("@jsonforms/core/src/testers/testers");
12
5
  const jsonFormsCore = require("@ghentcdh/json-forms-core");
13
- const core$1 = require("@vueuse/core");
6
+ const ui = require("@ghentcdh/ui");
7
+ const core = require("@vueuse/core");
14
8
  const vueRouter = require("vue-router");
15
- class FormStore {
16
- constructor(uri) {
17
- this.uri = uri;
18
- }
19
- async delete(data) {
20
- return toolsVue.useApi().delete(`${this.uri}/${data.id}`).then(() => {
21
- ui.NotificationService.success("Data deleted");
22
- }).catch((error2) => {
23
- console.error(error2);
24
- ui.NotificationService.error("Error deleting data");
25
- });
26
- }
27
- async save(id, data) {
28
- if (!this.uri) return;
29
- const promise2 = id ? toolsVue.useApi().patch(`${this.uri}/${id}`, data) : toolsVue.useApi().post(this.uri, data);
30
- return promise2.then(() => {
31
- ui.NotificationService.success("Data saved");
32
- }).catch((error2) => {
33
- console.error(error2);
34
- ui.NotificationService.error("Error saving data");
35
- });
36
- }
37
- }
38
- const FormComponentProperties = {
39
- /** Unique id applied to the `<form>` element and used as `<json-forms>` key. */
40
- id: { type: String, required: true },
41
- name: { type: String, default: "form" },
9
+ const toolsVue = require("@ghentcdh/tools-vue");
10
+ const veeValidate = require("vee-validate");
11
+ const core$1 = require("@jsonforms/core");
12
+ const testers = require("@jsonforms/core/src/testers/testers");
13
+ const axios = require("axios");
14
+ const FormModalProperties = {
15
+ /** Title displayed in the modal header. */
16
+ modalTitle: { type: String, required: true },
17
+ /** Label for the save button. */
18
+ saveLabel: { type: String, default: "save" },
19
+ /** Label for the cancel button. */
20
+ cancelLabel: { type: String, default: "cancel" },
42
21
  /** JSON schema describing the shape of the form data. */
43
22
  schema: { type: Object, required: true },
44
23
  /** UI schema describing the layout and controls. */
45
24
  uiSchema: { type: Object, required: true },
46
- /** Extra renderer entries merged in front of the built-in tailwind renderers. */
47
- renderers: {
48
- type: Array,
49
- default: void 0
25
+ /** Modal width (`'xs'`, `'sm'`, `'md'`, `'lg'`, `'xl'`). */
26
+ modalSize: { type: String, default: "md" },
27
+ /** Callback invoked when the modal closes (with result or `null` on cancel). */
28
+ onClose: {
29
+ type: Function,
30
+ required: true
50
31
  },
51
- /** Disables all controls inside the form. */
52
- disabled: { type: Boolean, default: false },
53
- formData: { type: Object, default: () => ({}) }
54
- };
55
- const FormComponentEmits = [
56
- /** Emitted whenever validity changes (`true` = no errors). */
57
- "valid",
58
- /** Emitted on every change with the latest form data. */
59
- "change",
60
- /** Emitted when the native form submit fires. Payload: `SubmitFormEvent`. */
61
- "submit",
62
- /** Emitted with the raw Ajv validation errors array. */
63
- "errors",
64
- /** Generic event channel for custom renderer dispatches (`FormEventPayload`). */
65
- "events"
66
- ];
67
- const FormWithActionsProperties = {
68
- /** Unique identifier; the inner form receives `form_${id}` as its id. */
69
- id: { type: String, required: true },
70
- /** Title shown when creating a new record (`formData.id` is falsy). */
71
- createTitle: { type: String, required: true },
72
- /** Title shown when editing an existing record. Falls back to `createTitle`. */
73
- updateTitle: { type: String },
74
- /** JSON schema describing the shape of the form data. */
75
- schema: { type: Object },
76
- /** UI schema describing the layout and controls. */
77
- uiSchema: { type: Object },
78
- /** When provided, the component submits the form to this URI via `FormStore`. */
79
- uri: { type: String },
80
- /** When true, the form content scrolls and the action bar stays pinned. */
81
- scrollable: { type: Boolean, default: false },
82
- /** When true, the component takes the full height of its parent. */
83
- fullHeight: { type: Boolean, default: false }
32
+ /** Callback for form events dispatched by custom renderers. */
33
+ onEvents: {
34
+ type: Function
35
+ },
36
+ /** Initial form data to populate the form with. */
37
+ data: { type: Object, required: true },
38
+ /** When validation errors are shown. */
39
+ errorMode: {
40
+ type: String,
41
+ default: "onBlur"
42
+ }
84
43
  };
85
- const FormWithActionsEmits = [
86
- /** v-model binding. */
87
- "update:modelValue",
88
- /** Emitted after a successful backend save (only when `uri` is defined). */
89
- "success",
90
- /** Emitted with form data when saving without a `uri`. */
91
- "submit",
92
- /** Emitted whenever the form validity changes. */
93
- "valid",
94
- /** Forwards custom renderer events (`FormEventPayload`). */
44
+ const FormModalEmits = [
45
+ /** Emitted when the modal is closed (submit or cancel). */
46
+ "closeModal",
47
+ /** Emitted when a custom renderer dispatches a form event. */
95
48
  "events",
49
+ /** Emitted when validation errors change. */
96
50
  "errors",
97
- /** Emitted when the cancel button is clicked (only visible when editing). */
98
- "cancel"
99
- ];
100
- const FormWithTableProperties = {
101
- /** Unique identifier used to generate the table form id (`form_table_${id}`). */
102
- id: { type: String, required: true },
103
- /** Heading displayed above the table. */
104
- tableTitle: { type: String, required: true },
105
- /** Title shown in the create modal. */
106
- createTitle: { type: String, required: true },
107
- /** Title shown in the edit modal. Falls back to `createTitle`. */
108
- updateTitle: { type: String },
109
- /** Overrides `uri` as the data source for the table. */
110
- dataUri: { type: String },
111
- /** Custom action buttons rendered in each table row. */
112
- tableActions: { type: Array },
113
- /** Layout for the create/edit modal form. */
114
- form: { type: Object },
115
- /** Layout for the table columns. */
116
- table: { type: Object },
117
- /** Layout for the table filter controls. */
118
- filter: { type: Object },
119
- /** Base URI used by `FormStore` for CRUD operations and as the default table data source. */
120
- uri: { type: String },
121
- /** Default data used when opening the create modal. */
122
- initialData: { type: Object, default: () => ({}) }
123
- };
124
- const FormWithTableEmits = [
125
- /** Emitted when a table row is edited and a custom listener is bound. */
126
- "editData",
127
- /** Emitted after a record is successfully saved (created or updated). Payload: `{ id?: string, data: Data }`. */
128
- "save",
129
- /** Emitted after a record is successfully deleted. Payload: the deleted record. */
130
- "delete",
131
- /** Forwarded form events dispatched by custom renderers inside the modal (e.g. "create"). Payload: `FormEventPayload`. */
132
- "events",
133
- "custom:edit",
134
- "custom:create"
51
+ /** Emitted when form validity changes. */
52
+ "valid"
135
53
  ];
136
- const createFormEvents = (dispatch) => ({
137
- dispatch
138
- });
139
- const FORM_EVENTS_KEY = /* @__PURE__ */ Symbol("json-forms:events");
140
- const provideFormEvents = (dispatch) => {
141
- const events = createFormEvents(dispatch);
142
- vue.provide(FORM_EVENTS_KEY, events);
143
- return events;
144
- };
145
- const useFormEvents = () => {
146
- return vue.inject(
147
- FORM_EVENTS_KEY,
148
- createFormEvents(() => {
149
- })
150
- );
151
- };
152
- const useVanillaControlCustom = (input, adaptTarget = (v) => v.value) => {
153
- const vanillaControl = vueVanilla.useVanillaControl(input, adaptTarget);
154
- const isTouched = vue.ref(false);
155
- const isFocused = vue.ref(false);
156
- const onFocus = () => {
157
- isFocused.value = true;
158
- };
159
- const onBlur = () => {
160
- isTouched.value = true;
161
- isFocused.value = false;
162
- };
163
- const controlWrapper = vue.computed(() => {
164
- return {
165
- ...vanillaControl.controlWrapper.value,
166
- ...lodashEs.omit(vanillaControl.appliedOptions.value, "styles"),
167
- ...lodashEs.pick(vanillaControl.appliedOptions.value.styles, ["width"]),
168
- isFocused: isFocused.value,
169
- isTouched: isTouched.value
54
+ const _hoisted_1$8 = { class: "" };
55
+ const _hoisted_2$2 = { class: "flex gap-2 items-center mb-2" };
56
+ const _hoisted_3$1 = { class: "flex gap-2" };
57
+ const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
58
+ __name: "table-filter",
59
+ props: {
60
+ layout: {},
61
+ filters: {}
62
+ },
63
+ emits: ["changeFilters", "removeFilter"],
64
+ setup(__props, { emit: __emit }) {
65
+ const formData = vue.ref();
66
+ const properties = __props;
67
+ const emits = __emit;
68
+ vue.watch(
69
+ () => properties.filters,
70
+ () => {
71
+ formData.value = {};
72
+ properties.filters.forEach((filter) => {
73
+ formData.value[filter.key] = filter.value;
74
+ });
75
+ },
76
+ { immediate: true }
77
+ );
78
+ const onResetFilters = () => {
79
+ emits("changeFilters", {});
170
80
  };
171
- });
172
- return {
173
- ...vanillaControl,
174
- appliedOptions: vanillaControl.appliedOptions,
175
- controlWrapper,
176
- isFocused,
177
- isTouched,
178
- onFocus,
179
- onBlur
180
- // handleChange,
181
- };
81
+ const removeFilter = (filter) => {
82
+ formData.value[filter.key] = void 0;
83
+ emits("changeFilters", formData.value);
84
+ };
85
+ return (_ctx, _cache) => {
86
+ return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$8, [
87
+ vue.createElementVNode("div", _hoisted_2$2, [
88
+ __props.filters.length ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
89
+ key: 0,
90
+ size: "xs",
91
+ outline: true,
92
+ onClick: onResetFilters
93
+ }, {
94
+ default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
95
+ vue.createTextVNode(" Reset all filters ", -1)
96
+ ])]),
97
+ _: 1
98
+ })) : vue.createCommentVNode("", true)
99
+ ]),
100
+ vue.createElementVNode("div", _hoisted_3$1, [
101
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.filters, (filter) => {
102
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.BtnBadge), {
103
+ key: filter.key,
104
+ icon: vue.unref(ui.IconEnum).Close,
105
+ onClick: ($event) => removeFilter(filter)
106
+ }, {
107
+ default: vue.withCtx(() => [
108
+ vue.createTextVNode(vue.toDisplayString(filter.label) + ": " + vue.toDisplayString(filter.value), 1)
109
+ ]),
110
+ _: 2
111
+ }, 1032, ["icon", "onClick"]);
112
+ }), 128))
113
+ ])
114
+ ]);
115
+ };
116
+ }
117
+ });
118
+ const TableComponentProperties = {
119
+ id: { type: String, required: true },
120
+ uiSchema: { type: Object, required: true },
121
+ schema: { type: Object, required: true },
122
+ filterUiSchema: { type: Object },
123
+ filterSchema: { type: Object },
124
+ uri: { type: String, required: true },
125
+ reload: { type: Number },
126
+ actions: { type: Array }
182
127
  };
183
- const _sfc_main$j = /* @__PURE__ */ vue.defineComponent({
184
- __name: "AutocompleteControlRenderer",
185
- props: { ...vue$1.rendererProps() },
186
- setup(__props) {
187
- const props = __props;
188
- const {
189
- control,
190
- handleChange: _handleChange,
191
- appliedOptions,
192
- onFocus,
193
- onBlur,
194
- controlWrapper
195
- } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
196
- const bindProperties = vue.computed(() => ({
197
- ...controlWrapper.value,
198
- ...appliedOptions.value,
199
- enableCreate: !!appliedOptions.value.enableCreate
200
- }));
201
- const fetchOptions = vue.computed(() => {
202
- const options = appliedOptions.value;
203
- if (!options.uri) return null;
204
- return (searchTerm, signal) => {
205
- const fetch = options.skipAuth ? axios : toolsVue.useApi();
206
- return fetch.get(`${options.uri}${searchTerm}`, { signal }).then((data) => data.data[options.dataField ?? "data"]);
128
+ const TableComponentEmits = ["delete", "edit"];
129
+ class TableStore {
130
+ constructor() {
131
+ this.route = vueRouter.useRoute();
132
+ this.router = vueRouter.useRouter();
133
+ this.requestData = vue.ref(jsonFormsCore.RequestSchema.parse(this.route.query));
134
+ this._reload = vue.ref(Date.now());
135
+ this.loading = vue.ref(true);
136
+ this.uri = vue.ref("");
137
+ this.data = core.computedAsync(async () => {
138
+ this._reload.value;
139
+ if (!this.uri.value) return null;
140
+ this.loading.value = true;
141
+ if (this.requestData.value.page < 1) {
142
+ this.requestData.value.page = 1;
143
+ }
144
+ const response = await toolsVue.useApi().get(this.uri.value, {
145
+ params: this.requestData.value
146
+ }).catch((error2) => {
147
+ console.error(error2);
148
+ return { data: [], request: { totalPages: 1, page: 1 } };
149
+ }).finally(() => this.loading.value = false);
150
+ const data = response.data;
151
+ if (data.request.totalPages < data.request.page) {
152
+ this.updateRequest({ page: data.request.totalPages });
153
+ }
154
+ return data;
155
+ });
156
+ this.pageData = vue.computed(() => {
157
+ const request = this.data.value?.request ?? {
158
+ count: 0,
159
+ pageSize: 1,
160
+ page: 1
161
+ };
162
+ return {
163
+ count: request.count,
164
+ pageSize: request.pageSize,
165
+ page: request.page
207
166
  };
208
167
  });
209
- const handleChange = (result) => {
210
- const { path } = control.value;
211
- _handleChange(path, result);
168
+ this.tableData = vue.computed(() => {
169
+ const d = this.data.value;
170
+ if (!d) return [];
171
+ if (this.loading.value) return [];
172
+ return d.data ?? [];
173
+ });
174
+ this.init = (url2) => {
175
+ this.uri.value = url2;
212
176
  };
213
- const formEvents = useFormEvents();
214
- const create = () => {
215
- formEvents.dispatch({
216
- event: "create",
217
- type: control.value.path,
218
- onSuccess: (result) => {
219
- handleChange(result);
177
+ this.updateRequest = (data) => {
178
+ this.requestData.value = { ...this.requestData.value, ...data };
179
+ this.router.replace({
180
+ query: {
181
+ ...this.route.query,
182
+ ...this.requestData.value
220
183
  }
221
184
  });
222
185
  };
223
- return (_ctx, _cache) => {
224
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Autocomplete), vue.mergeProps(bindProperties.value, {
225
- "model-value": vue.unref(control).data,
226
- enabled: vue.unref(control).enabled,
227
- "fetch-options": fetchOptions.value,
228
- onChange: handleChange,
229
- onFocus: vue.unref(onFocus),
230
- onBlur: vue.unref(onBlur),
231
- onCreate: _cache[0] || (_cache[0] = ($event) => create())
232
- }), null, 16, ["model-value", "enabled", "fetch-options", "onFocus", "onBlur"]);
186
+ this.sort = (id) => {
187
+ const sortDir = this.requestData.value.sort === id && this.requestData.value.sortDir === "asc" ? "desc" : "asc";
188
+ this.updateRequest({ sort: id, sortDir });
233
189
  };
234
- }
235
- });
236
- const _sfc_main$i = /* @__PURE__ */ vue.defineComponent({
237
- __name: "BooleanControlRenderer",
238
- props: { ...vue$1.rendererProps() },
239
- setup(__props) {
240
- const props = __props;
241
- const { control, onChange, appliedOptions, onFocus, onBlur, controlWrapper } = useVanillaControlCustom(vue$1.useJsonFormsControl(props), (target) => {
242
- return Boolean(target.value) ?? false;
243
- });
244
- return (_ctx, _cache) => {
245
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Checkbox), vue.mergeProps(vue.unref(controlWrapper), {
246
- "model-value": vue.unref(control).data,
247
- enabled: vue.unref(control).enabled,
248
- config: vue.unref(appliedOptions),
249
- onChange: vue.unref(onChange),
250
- onFocus: vue.unref(onFocus),
251
- onBlur: vue.unref(onBlur)
252
- }), null, 16, ["model-value", "enabled", "config", "onChange", "onFocus", "onBlur"]);
190
+ this.updateFilters = (filters) => {
191
+ const filter = [];
192
+ Object.entries(filters).forEach(([key, value]) => {
193
+ if (!value) return;
194
+ const operator = value?.operator || "contains";
195
+ filter.push(`${key}:${value}:${operator}`);
196
+ });
197
+ this.updateRequest({ filter });
253
198
  };
254
- }
255
- });
256
- const _sfc_main$h = /* @__PURE__ */ vue.defineComponent({
257
- __name: "IntegerControlRenderer",
258
- props: { ...vue$1.rendererProps() },
259
- setup(__props) {
260
- const props = __props;
261
- const { control, onChange, appliedOptions, onFocus, onBlur, controlWrapper } = useVanillaControlCustom(
262
- vue$1.useJsonFormsControl(props),
263
- (target) => target.value === "" ? void 0 : Number(target.value)
264
- );
265
- const steps = vue.computed(() => appliedOptions.value.steps ?? 1);
266
- return (_ctx, _cache) => {
267
- return vue.openBlock(), vue.createBlock(vue.unref(ui.InputNumber), vue.mergeProps(vue.unref(controlWrapper), {
268
- "model-value": vue.unref(control).data,
269
- enabled: vue.unref(control).enabled,
270
- config: vue.unref(appliedOptions),
271
- steps: steps.value,
272
- onChange: vue.unref(onChange),
273
- onFocus: vue.unref(onFocus),
274
- onBlur: vue.unref(onBlur)
275
- }), null, 16, ["model-value", "enabled", "config", "steps", "onChange", "onFocus", "onBlur"]);
276
- };
277
- }
278
- });
279
- const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
280
- __name: "MarkdownControlRenderer",
281
- props: { ...vue$1.rendererProps() },
282
- setup(__props) {
283
- const props = __props;
284
- const {
285
- control,
286
- handleChange,
287
- appliedOptions,
288
- onFocus,
289
- onBlur,
290
- controlWrapper
291
- } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
292
- const changeValue = (value) => {
293
- handleChange(control.value.path, value);
294
- };
295
- return (_ctx, _cache) => {
296
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Markdown), vue.mergeProps(vue.unref(controlWrapper), {
297
- "model-value": vue.unref(control).data,
298
- enabled: vue.unref(control).enabled,
299
- config: vue.unref(appliedOptions),
300
- onChange: changeValue,
301
- onFocus: vue.unref(onFocus),
302
- onBlur: vue.unref(onBlur)
303
- }), null, 16, ["model-value", "enabled", "config", "onFocus", "onBlur"]);
304
- };
305
- }
306
- });
307
- const _sfc_main$f = /* @__PURE__ */ vue.defineComponent({
308
- __name: "MultiSelectControlRender",
309
- props: { ...vue$1.rendererProps() },
310
- setup(__props) {
311
- const props = __props;
312
- const {
313
- control,
314
- handleChange: _handleChange,
315
- onFocus,
316
- onBlur,
317
- controlWrapper
318
- } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
319
- const handleChange = (result) => {
320
- const { path } = control.value;
321
- _handleChange(path, result);
322
- };
323
- return (_ctx, _cache) => {
324
- return vue.openBlock(), vue.createBlock(vue.unref(ui.MultiSelect), vue.mergeProps(vue.unref(controlWrapper), {
325
- "model-value": vue.unref(control).data,
326
- enabled: vue.unref(control).enabled,
327
- onChange: handleChange,
328
- onFocus: vue.unref(onFocus),
329
- onBlur: vue.unref(onBlur)
330
- }), null, 16, ["model-value", "enabled", "onFocus", "onBlur"]);
331
- };
332
- }
333
- });
334
- const _sfc_main$e = /* @__PURE__ */ vue.defineComponent({
335
- __name: "NumberControlRenderer",
336
- props: { ...vue$1.rendererProps() },
337
- setup(__props) {
338
- const props = __props;
339
- const { control, onChange, appliedOptions, onFocus, onBlur, controlWrapper } = useVanillaControlCustom(
340
- vue$1.useJsonFormsControl(props),
341
- (target) => target.value === "" ? void 0 : Number(target.value)
199
+ this.sorting = vue.computed(() => {
200
+ const requestData = this.requestData.value;
201
+ return {
202
+ sortColumn: requestData.sort,
203
+ sortDirection: requestData.sortDir ?? "asc"
204
+ };
205
+ });
206
+ this.filters = vue.computed(
207
+ () => jsonFormsCore.extractFilters(this.requestData.value.filter)
342
208
  );
343
- const steps = vue.computed(() => appliedOptions.value.steps ?? 0.01);
344
- return (_ctx, _cache) => {
345
- return vue.openBlock(), vue.createBlock(vue.unref(ui.InputNumber), vue.mergeProps(vue.unref(controlWrapper), {
346
- "model-value": vue.unref(control).data,
347
- enabled: vue.unref(control).enabled,
348
- config: vue.unref(appliedOptions),
349
- steps: steps.value,
350
- onChange: vue.unref(onChange),
351
- onFocus: vue.unref(onFocus),
352
- onBlur: vue.unref(onBlur)
353
- }), null, 16, ["model-value", "enabled", "config", "steps", "onChange", "onFocus", "onBlur"]);
354
- };
355
209
  }
356
- });
357
- const _sfc_main$d = /* @__PURE__ */ vue.defineComponent({
358
- __name: "SelectControlRender",
359
- props: { ...vue$1.rendererProps() },
360
- setup(__props) {
361
- const props = __props;
362
- const {
363
- control,
364
- handleChange: _handleChange,
365
- appliedOptions,
366
- onFocus,
367
- onBlur,
368
- controlWrapper
369
- } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
370
- const handleChange = (result) => {
371
- const { path } = control.value;
372
- _handleChange(path, result);
373
- };
374
- return (_ctx, _cache) => {
375
- return vue.openBlock(), vue.createBlock(vue.unref(ui.SelectComponent), vue.mergeProps(vue.unref(controlWrapper), {
376
- "model-value": vue.unref(control).data,
377
- enabled: vue.unref(control).enabled,
378
- options: vue.unref(appliedOptions)?.options,
379
- onChange: handleChange,
380
- onFocus: vue.unref(onFocus),
381
- onBlur: vue.unref(onBlur)
382
- }), null, 16, ["model-value", "enabled", "options", "onFocus", "onBlur"]);
383
- };
210
+ get httpRequest() {
211
+ return toolsVue.useApi();
384
212
  }
385
- });
386
- const _sfc_main$c = /* @__PURE__ */ vue.defineComponent({
387
- __name: "StringControlRenderer",
388
- props: { ...vue$1.rendererProps() },
389
- setup(__props) {
390
- const props = __props;
391
- const {
392
- control,
393
- onChange,
394
- appliedOptions,
395
- onFocus,
396
- onBlur,
397
- controlWrapper,
398
- styles
399
- } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
400
- return (_ctx, _cache) => {
401
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Input), vue.mergeProps(vue.unref(controlWrapper), {
402
- "model-value": vue.unref(control).data,
403
- enabled: vue.unref(control).enabled,
404
- config: vue.unref(appliedOptions),
405
- styles: vue.unref(styles),
406
- onChange: vue.unref(onChange),
407
- onFocus: vue.unref(onFocus),
408
- onBlur: vue.unref(onBlur)
409
- }), null, 16, ["model-value", "enabled", "config", "styles", "onChange", "onFocus", "onBlur"]);
410
- };
213
+ reload() {
214
+ this._reload.value = Date.now();
411
215
  }
412
- });
413
- const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
414
- __name: "TextAreaControlRenderer",
415
- props: { ...vue$1.rendererProps() },
416
- setup(__props) {
417
- const props = __props;
418
- const { control, onChange, appliedOptions, onFocus, onBlur, controlWrapper } = useVanillaControlCustom(vue$1.useJsonFormsControl(props));
419
- return (_ctx, _cache) => {
420
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Textarea), vue.mergeProps(vue.unref(controlWrapper), {
421
- "model-value": vue.unref(control).data,
422
- enabled: vue.unref(control).enabled,
423
- config: vue.unref(appliedOptions),
424
- onChange: vue.unref(onChange),
425
- onFocus: vue.unref(onFocus),
426
- onBlur: vue.unref(onBlur)
427
- }), null, 16, ["model-value", "enabled", "config", "onChange", "onFocus", "onBlur"]);
428
- };
216
+ updatePage(page) {
217
+ this.updateRequest({ page });
429
218
  }
430
- });
431
- const isAutoCompleteControl = testers.and(
432
- // uiTypeIs('Control'),
433
- testers.optionIs("format", jsonFormsCore.ControlType.autocomplete)
434
- );
435
- const isTextAreaControl = testers.and(
436
- core.uiTypeIs("Control"),
437
- testers.optionIs("format", jsonFormsCore.ControlType.textArea)
438
- );
439
- const isStringFormat = testers.and(
440
- core.uiTypeIs("Control"),
441
- testers.or(testers.optionIs("format", jsonFormsCore.ControlType.string), testers.schemaTypeIs("string"))
442
- );
443
- const isMarkdownControl = testers.and(
444
- core.uiTypeIs("Control"),
445
- testers.optionIs("format", jsonFormsCore.ControlType.markdown)
446
- );
447
- const isArrayRenderer = testers.and(
448
- testers.schemaTypeIs("array")
449
- // optionIs('format', ControlType.array),
450
- );
451
- const isCustomControl = (customType) => {
452
- return testers.and(
453
- testers.optionIs("format", jsonFormsCore.ControlType.custom),
454
- testers.optionIs("type", customType)
455
- );
219
+ }
220
+ const tableCache = /* @__PURE__ */ new Map();
221
+ const useTableStore = (name) => {
222
+ const tableStore = tableCache.get(name);
223
+ if (tableStore) {
224
+ return tableStore;
225
+ }
226
+ const newTableStore = new TableStore();
227
+ tableCache.set(name, newTableStore);
228
+ return newTableStore;
456
229
  };
457
- const isMultiselectControl = testers.and(
458
- core.uiTypeIs("Control"),
459
- testers.optionIs("format", jsonFormsCore.ControlType.mutliSelect)
460
- );
461
- const isSelectControl = testers.and(
462
- core.uiTypeIs("Control"),
463
- testers.optionIs("format", jsonFormsCore.ControlType.select)
464
- );
465
- const isBooleanControl = testers.or(
466
- testers.isBooleanControl,
467
- testers.and(core.uiTypeIs("Control"), testers.optionIs("format", jsonFormsCore.ControlType.boolean))
468
- );
469
- const controlRenderers = [
470
- // First custom renderers on format
471
- {
472
- tester: core.rankWith(10, isMarkdownControl),
473
- renderer: _sfc_main$g
474
- },
475
- {
476
- tester: core.rankWith(10, isAutoCompleteControl),
477
- renderer: _sfc_main$j
478
- },
479
- {
480
- tester: core.rankWith(10, isTextAreaControl),
481
- renderer: _sfc_main$b
482
- },
483
- // Renderers based on type if no format is provided
484
- { tester: core.rankWith(10, isStringFormat), renderer: _sfc_main$c },
485
- { tester: core.rankWith(10, isSelectControl), renderer: _sfc_main$d },
486
- {
487
- tester: core.rankWith(10, isMultiselectControl),
488
- renderer: _sfc_main$f
489
- },
490
- { tester: core.rankWith(10, core.isNumberControl), renderer: _sfc_main$e },
491
- {
492
- tester: core.rankWith(10, core.isIntegerControl),
493
- renderer: _sfc_main$h
494
- },
495
- { tester: core.rankWith(10, isBooleanControl), renderer: _sfc_main$i }
496
- ];
497
- const _hoisted_1$9 = ["title"];
498
- const _hoisted_2$2 = { key: 0 };
499
- const _hoisted_3$1 = {
500
- key: 1,
501
- class: "list-row"
230
+ const _hoisted_1$7 = {
231
+ key: 0,
232
+ class: "mb-2"
502
233
  };
503
- const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
504
- __name: "ArrayRenderer",
505
- props: { ...vue$1.rendererProps() },
506
- setup(__props) {
507
- const props = __props;
508
- const vanillaArrayControl = vueVanilla.useVanillaArrayControl(
509
- vue$1.useJsonFormsArrayControl(props)
234
+ const _sfc_main$g = /* @__PURE__ */ vue.defineComponent({
235
+ __name: "table.component",
236
+ props: TableComponentProperties,
237
+ emits: TableComponentEmits,
238
+ setup(__props, { emit: __emit }) {
239
+ const properties = __props;
240
+ const emit = __emit;
241
+ vue.watch(
242
+ () => properties.reload,
243
+ () => {
244
+ store.reload();
245
+ }
510
246
  );
511
- const { styles, childUiSchema, control, appliedOptions } = vanillaArrayControl;
512
- if (!control.value.data || control.value.data.length < 1) {
513
- vanillaArrayControl.addItem(
514
- control.value.path,
515
- core.createDefaultValue(control.value.schema, control.value.rootSchema)
516
- )();
517
- }
518
- const noData = vue.computed(
519
- () => !control.value.data || control.value.data.length === 0
247
+ let store = useTableStore(properties.id);
248
+ vue.watch(
249
+ () => properties.uri,
250
+ () => {
251
+ store.init(properties.uri);
252
+ },
253
+ { immediate: true }
520
254
  );
521
- const showDelete = vue.computed(() => control.value.data?.length > 1);
522
- const deleteButtonClick = (index) => {
523
- vanillaArrayControl.removeItems(control.value.path, [index])();
255
+ const edit = (data) => {
256
+ emit("edit", data);
257
+ };
258
+ const deleteFn = (data) => {
259
+ emit("delete", data);
260
+ };
261
+ const components = {
262
+ TextCell: ui.TextCell,
263
+ BooleanCell: ui.BooleanCell
264
+ };
265
+ const displayColumns = vue.computed(() => {
266
+ return properties.uiSchema.elements.map((e) => {
267
+ const element = e;
268
+ const def = jsonFormsCore.findColumnDef(element, properties.schema);
269
+ const type = lodashEs.isArray(def.type) ? def.type[0] : def.type;
270
+ let component;
271
+ if (element.options?.format && element.options.format in components) {
272
+ component = components[element.options.format];
273
+ } else {
274
+ component = components[element.type];
275
+ }
276
+ if (!component) console.warn("No component found for type", element.type);
277
+ return {
278
+ ...def,
279
+ type,
280
+ component
281
+ };
282
+ });
283
+ });
284
+ const onChangeFilters = (filters) => {
285
+ store.updateFilters(filters);
286
+ };
287
+ const onUpdatePage = (page) => {
288
+ store.updatePage(page);
524
289
  };
525
- const addButtonClick = () => {
526
- vanillaArrayControl.addItem(
527
- control.value.path,
528
- core.createDefaultValue(control.value.schema, control.value.rootSchema)
529
- )();
290
+ const onSort = (id) => {
291
+ store.sort(id);
530
292
  };
531
- const showActions = vue.computed(() => {
532
- return !appliedOptions.value.hideActions;
293
+ const sort = vue.computed(() => {
294
+ return store.sorting.value ?? { orderBy: "", ascending: 1 };
533
295
  });
534
296
  return (_ctx, _cache) => {
535
- return vue.openBlock(), vue.createElementBlock("div", {
536
- title: vue.unref(control).label
537
- }, [
538
- vue.createElementVNode("div", {
539
- class: vue.normalizeClass([
540
- "flex gap-2",
541
- vue.unref(appliedOptions)?.layout === "row" ? "flex-row items-center" : "flex-col"
542
- ])
543
- }, [
544
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(control).data, (element, index) => {
545
- return vue.openBlock(), vue.createElementBlock("div", {
546
- key: `${vue.unref(control).path}-${index}`,
547
- class: "flex-1"
548
- }, [
549
- vue.createElementVNode("div", {
550
- class: vue.normalizeClass([
551
- "flex gap-2",
552
- vue.unref(appliedOptions)?.layout === "row" ? "flex-col" : "flex-row items-center"
553
- ])
554
- }, [
555
- vue.createElementVNode("div", null, [
556
- vue.createVNode(vue.unref(vue$1.DispatchRenderer), {
557
- schema: vue.unref(control).schema,
558
- uischema: vue.unref(childUiSchema),
559
- path: vue.unref(core.composePaths)(vue.unref(control).path, `${index}`),
560
- enabled: vue.unref(control).enabled,
561
- renderers: vue.unref(control).renderers,
562
- cells: vue.unref(control).cells
563
- }, null, 8, ["schema", "uischema", "path", "enabled", "renderers", "cells"])
564
- ]),
565
- showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$2, [
566
- showDelete.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
567
- key: 0,
568
- icon: vue.unref(ui.IconEnum).Delete,
569
- outline: true,
570
- onClick: ($event) => deleteButtonClick(index)
571
- }, null, 8, ["icon", "onClick"])) : vue.createCommentVNode("", true)
572
- ])) : vue.createCommentVNode("", true)
573
- ], 2)
574
- ]);
575
- }), 128)),
576
- noData.value ? (vue.openBlock(), vue.createElementBlock("div", {
577
- key: 0,
578
- class: vue.normalizeClass(["list-row", vue.unref(styles).arrayList.noData])
579
- }, " No data ", 2)) : vue.createCommentVNode("", true),
580
- showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3$1, [
581
- vue.createVNode(vue.unref(ui.Btn), {
582
- icon: vue.unref(ui.IconEnum).Plus,
583
- outline: true,
584
- onClick: addButtonClick
585
- }, {
586
- default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
587
- vue.createTextVNode(" Add ", -1)
588
- ])]),
589
- _: 1
590
- }, 8, ["icon"])
591
- ])) : vue.createCommentVNode("", true)
592
- ], 2)
593
- ], 8, _hoisted_1$9);
297
+ return vue.openBlock(), vue.createElementBlock("div", null, [
298
+ _ctx.filterUiSchema && _ctx.filterSchema ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$7, [
299
+ vue.createVNode(_sfc_main$h, {
300
+ layout: { uiSchema: _ctx.filterUiSchema, schema: _ctx.filterSchema },
301
+ filters: vue.unref(store).filters.value,
302
+ onChangeFilters
303
+ }, null, 8, ["layout", "filters"])
304
+ ])) : vue.createCommentVNode("", true),
305
+ vue.createElementVNode("div", null, [
306
+ vue.createVNode(vue.unref(ui.Table), {
307
+ "display-columns": displayColumns.value,
308
+ sort: sort.value,
309
+ page: vue.unref(store).pageData.value,
310
+ loading: vue.unref(store).loading.value,
311
+ data: vue.unref(store).tableData.value,
312
+ actions: _ctx.actions,
313
+ onUpdatePage,
314
+ onDelete: deleteFn,
315
+ onEdit: edit,
316
+ onSort
317
+ }, null, 8, ["display-columns", "sort", "page", "loading", "data", "actions"])
318
+ ])
319
+ ]);
594
320
  };
595
321
  }
596
322
  });
597
- const arrayRenderers = [
598
- {
599
- tester: core.rankWith(12, isArrayRenderer),
600
- renderer: _sfc_main$a
601
- }
602
- ];
603
- const _hoisted_1$8 = { class: "flex flex-col gap-4" };
604
- const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
605
- __name: "CollapseLayout",
606
- props: { ...vue$1.rendererProps() },
607
- setup(__props) {
608
- const props = __props;
609
- const jsonLayout = vue$1.useJsonFormsLayout(props);
610
- const { layout, renderers, cells } = jsonLayout;
611
- const title = vue.computed(() => {
612
- const { titleKey, title: title2 } = layout?.value.uischema?.options ?? {};
613
- if (title2) return title2;
614
- if (titleKey) return layout?.value.data[titleKey];
615
- return layout?.value.uischema?.options?.titleKey;
616
- });
617
- return (_ctx, _cache) => {
618
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), { title: title.value }, {
619
- default: vue.withCtx(() => [
620
- vue.createElementVNode("div", _hoisted_1$8, [
621
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(layout).uischema.elements, (element, index) => {
622
- return vue.openBlock(), vue.createBlock(vue.unref(vue$1.DispatchRenderer), {
623
- key: index,
624
- schema: vue.unref(layout).schema,
625
- uischema: element,
626
- path: vue.unref(layout).path,
627
- renderers: vue.unref(renderers),
628
- cells: vue.unref(cells)
629
- }, null, 8, ["schema", "uischema", "path", "renderers", "cells"]);
630
- }), 128))
631
- ])
632
- ]),
633
- _: 1
634
- }, 8, ["title"]);
635
- };
636
- }
637
- });
638
- const _hoisted_1$7 = {
639
- class: "grid gap-4 items-center",
640
- style: { "grid-template-columns": "repeat(12, 1fr)" }
641
- };
642
- const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
643
- __name: "GridLayout",
644
- props: { ...vue$1.rendererProps() },
645
- setup(__props) {
646
- const props = __props;
647
- const { layout, renderers, cells } = vue$1.useJsonFormsLayout(props);
648
- return (_ctx, _cache) => {
649
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$7, [
650
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(layout).uischema.elements, (element, index) => {
651
- return vue.openBlock(), vue.createElementBlock("div", {
652
- key: index,
653
- style: vue.normalizeStyle({
654
- "grid-column": `span ${element.options?.colspan ?? 12}`
655
- })
656
- }, [
657
- vue.createVNode(vue.unref(vue$1.DispatchRenderer), {
658
- schema: vue.unref(layout).schema,
659
- uischema: element,
660
- path: vue.unref(layout).path,
661
- renderers: vue.unref(renderers),
662
- cells: vue.unref(cells)
663
- }, null, 8, ["schema", "uischema", "path", "renderers", "cells"])
664
- ], 4);
665
- }), 128))
666
- ]);
667
- };
668
- }
669
- });
670
- const _hoisted_1$6 = { class: "flex flex-row gap-4 items-center" };
671
- const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
672
- __name: "HorizontalLayout",
673
- props: { ...vue$1.rendererProps() },
674
- setup(__props) {
675
- const props = __props;
676
- const { layout, renderers, cells } = vue$1.useJsonFormsLayout(props);
677
- return (_ctx, _cache) => {
678
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, [
679
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(layout).uischema.elements, (element, index) => {
680
- return vue.openBlock(), vue.createBlock(vue.unref(vue$1.DispatchRenderer), {
681
- key: index,
682
- schema: vue.unref(layout).schema,
683
- uischema: element,
684
- path: vue.unref(layout).path,
685
- renderers: vue.unref(renderers),
686
- cells: vue.unref(cells)
687
- }, null, 8, ["schema", "uischema", "path", "renderers", "cells"]);
688
- }), 128))
689
- ]);
690
- };
691
- }
692
- });
693
- const _hoisted_1$5 = { class: "flex flex-col gap-4" };
694
- const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
695
- __name: "VerticalLayout",
696
- props: { ...vue$1.rendererProps() },
697
- setup(__props) {
698
- const props = __props;
699
- const { layout, renderers, cells } = vue$1.useJsonFormsLayout(props);
700
- return (_ctx, _cache) => {
701
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$5, [
702
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(layout).uischema.elements, (element, index) => {
703
- return vue.openBlock(), vue.createBlock(vue.unref(vue$1.DispatchRenderer), {
704
- key: index,
705
- schema: vue.unref(layout).schema,
706
- uischema: element,
707
- path: vue.unref(layout).path,
708
- renderers: vue.unref(renderers),
709
- cells: vue.unref(cells)
710
- }, null, 8, ["schema", "uischema", "path", "renderers", "cells"]);
711
- }), 128))
712
- ]);
713
- };
714
- }
715
- });
716
- const layoutRenderers = [
717
- {
718
- tester: core.rankWith(10, core.uiTypeIs(jsonFormsCore.LayoutTypes.VerticalLayout)),
719
- renderer: _sfc_main$6
720
- },
721
- {
722
- tester: core.rankWith(10, core.uiTypeIs(jsonFormsCore.LayoutTypes.HorizontalLayout)),
723
- renderer: _sfc_main$7
724
- },
725
- {
726
- tester: core.rankWith(10, core.uiTypeIs(jsonFormsCore.LayoutTypes.CollapseLayout)),
727
- renderer: _sfc_main$9
728
- },
729
- {
730
- tester: core.rankWith(10, core.uiTypeIs(jsonFormsCore.LayoutTypes.GridLayout)),
731
- renderer: _sfc_main$8
732
- }
733
- ];
734
- const _hoisted_1$4 = { class: "" };
735
- const _hoisted_2$1 = { class: "flex gap-2 items-center mb-2" };
736
- const _hoisted_3 = { class: "flex gap-2" };
737
- const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
738
- __name: "table-filter",
739
- props: {
740
- layout: {},
741
- filters: {}
742
- },
743
- emits: ["changeFilters", "removeFilter"],
744
- setup(__props, { emit: __emit }) {
745
- const formData = vue.ref();
746
- const properties = __props;
747
- const emits = __emit;
748
- vue.watch(
749
- () => properties.filters,
750
- () => {
751
- formData.value = {};
752
- properties.filters.forEach((filter) => {
753
- formData.value[filter.key] = filter.value;
754
- });
755
- },
756
- { immediate: true }
757
- );
758
- const onResetFilters = () => {
759
- emits("changeFilters", {});
760
- };
761
- const removeFilter = (filter) => {
762
- formData.value[filter.key] = void 0;
763
- emits("changeFilters", formData.value);
764
- };
765
- return (_ctx, _cache) => {
766
- return vue.openBlock(), vue.createElementBlock("div", _hoisted_1$4, [
767
- vue.createElementVNode("div", _hoisted_2$1, [
768
- __props.filters.length ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
769
- key: 0,
770
- size: "xs",
771
- outline: true,
772
- onClick: onResetFilters
773
- }, {
774
- default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
775
- vue.createTextVNode(" Reset all filters ", -1)
776
- ])]),
777
- _: 1
778
- })) : vue.createCommentVNode("", true)
779
- ]),
780
- vue.createElementVNode("div", _hoisted_3, [
781
- (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.filters, (filter) => {
782
- return vue.openBlock(), vue.createBlock(vue.unref(ui.BtnBadge), {
783
- key: filter.key,
784
- icon: vue.unref(ui.IconEnum).Close,
785
- onClick: ($event) => removeFilter(filter)
786
- }, {
787
- default: vue.withCtx(() => [
788
- vue.createTextVNode(vue.toDisplayString(filter.label) + ": " + vue.toDisplayString(filter.value), 1)
789
- ]),
790
- _: 2
791
- }, 1032, ["icon", "onClick"]);
792
- }), 128))
793
- ])
794
- ]);
795
- };
796
- }
797
- });
798
- const TableComponentProperties = {
799
- id: { type: String, required: true },
800
- uiSchema: { type: Object, required: true },
801
- schema: { type: Object, required: true },
802
- filterUiSchema: { type: Object },
803
- filterSchema: { type: Object },
804
- uri: { type: String, required: true },
805
- reload: { type: Number },
806
- actions: { type: Array }
807
- };
808
- const TableComponentEmits = ["delete", "edit"];
809
- class TableStore {
810
- constructor() {
811
- this.route = vueRouter.useRoute();
812
- this.router = vueRouter.useRouter();
813
- this.requestData = vue.ref(jsonFormsCore.RequestSchema.parse(this.route.query));
814
- this._reload = vue.ref(Date.now());
815
- this.loading = vue.ref(true);
816
- this.uri = vue.ref("");
817
- this.data = core$1.computedAsync(async () => {
818
- this._reload.value;
819
- if (!this.uri.value) return null;
820
- this.loading.value = true;
821
- if (this.requestData.value.page < 1) {
822
- this.requestData.value.page = 1;
823
- }
824
- const response = await toolsVue.useApi().get(this.uri.value, {
825
- params: this.requestData.value
826
- }).catch((error2) => {
827
- console.error(error2);
828
- return { data: [], request: { totalPages: 1, page: 1 } };
829
- }).finally(() => this.loading.value = false);
830
- const data = response.data;
831
- if (data.request.totalPages < data.request.page) {
832
- this.updateRequest({ page: data.request.totalPages });
833
- }
834
- return data;
835
- });
836
- this.pageData = vue.computed(() => {
837
- const request = this.data.value?.request ?? {
838
- count: 0,
839
- pageSize: 1,
840
- page: 1
841
- };
842
- return {
843
- count: request.count,
844
- pageSize: request.pageSize,
845
- page: request.page
846
- };
847
- });
848
- this.tableData = vue.computed(() => {
849
- const d = this.data.value;
850
- if (!d) return [];
851
- if (this.loading.value) return [];
852
- return d.data ?? [];
323
+ const createRepository = (formSchemaModel, httpRequest, options = {}) => {
324
+ const notificationEntity = options.notification?.entityType || "entity";
325
+ const notificationStore = options.notification?.notification ?? null;
326
+ const getDataUri = (...suffix) => {
327
+ return [formSchemaModel.uri, ...suffix].join("/");
328
+ };
329
+ const handleSuccess = (message) => {
330
+ notificationStore?.success(message);
331
+ };
332
+ const handleError = (error2, message) => {
333
+ console.error(error2);
334
+ notificationStore?.error(message);
335
+ throw new Error(error2);
336
+ };
337
+ const create = (object2, options2) => {
338
+ return httpRequest.post(getDataUri(), object2, options2).then((response) => {
339
+ handleSuccess(`Created ${notificationEntity}`);
340
+ return response.data;
341
+ }).catch((response) => {
342
+ handleError(response, `Failed to create ${notificationEntity}`);
853
343
  });
854
- this.init = (url2) => {
855
- this.uri.value = url2;
856
- };
857
- this.updateRequest = (data) => {
858
- this.requestData.value = { ...this.requestData.value, ...data };
859
- this.router.replace({
860
- query: {
861
- ...this.route.query,
862
- ...this.requestData.value
863
- }
864
- });
865
- };
866
- this.sort = (id) => {
867
- const sortDir = this.requestData.value.sort === id && this.requestData.value.sortDir === "asc" ? "desc" : "asc";
868
- this.updateRequest({ sort: id, sortDir });
869
- };
870
- this.updateFilters = (filters) => {
871
- const filter = [];
872
- Object.entries(filters).forEach(([key, value]) => {
873
- if (!value) return;
874
- const operator = value?.operator || "contains";
875
- filter.push(`${key}:${value}:${operator}`);
876
- });
877
- this.updateRequest({ filter });
878
- };
879
- this.sorting = vue.computed(() => {
880
- const requestData = this.requestData.value;
881
- return {
882
- sortColumn: requestData.sort,
883
- sortDirection: requestData.sortDir ?? "asc"
884
- };
344
+ };
345
+ const patch = (id, object2, options2) => {
346
+ return httpRequest.patch(getDataUri(id), object2, options2).then((response) => {
347
+ handleSuccess(`Saved ${notificationEntity}`);
348
+ return response.data;
349
+ }).catch((response) => {
350
+ handleError(response, `Failed to save ${notificationEntity}`);
885
351
  });
886
- this.filters = vue.computed(
887
- () => jsonFormsCore.extractFilters(this.requestData.value.filter)
888
- );
889
- }
890
- get httpRequest() {
891
- return toolsVue.useApi();
892
- }
893
- reload() {
894
- this._reload.value = Date.now();
895
- }
896
- updatePage(page) {
897
- this.updateRequest({ page });
898
- }
899
- }
900
- const tableCache = /* @__PURE__ */ new Map();
901
- const useTableStore = (name) => {
902
- const tableStore = tableCache.get(name);
903
- if (tableStore) {
904
- return tableStore;
905
- }
906
- const newTableStore = new TableStore();
907
- tableCache.set(name, newTableStore);
908
- return newTableStore;
909
- };
910
- const _hoisted_1$3 = {
911
- key: 0,
912
- class: "mb-2"
913
- };
914
- const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
915
- __name: "table.component",
916
- props: TableComponentProperties,
917
- emits: TableComponentEmits,
918
- setup(__props, { emit: __emit }) {
919
- const properties = __props;
920
- const emit = __emit;
921
- vue.watch(
922
- () => properties.reload,
923
- () => {
924
- store.reload();
925
- }
926
- );
927
- let store = useTableStore(properties.id);
928
- vue.watch(
929
- () => properties.uri,
930
- () => {
931
- store.init(properties.uri);
932
- },
933
- { immediate: true }
934
- );
935
- const edit = (data) => {
936
- emit("edit", data);
937
- };
938
- const deleteFn = (data) => {
939
- emit("delete", data);
940
- };
941
- const components = {
942
- TextCell: ui.TextCell
943
- };
944
- const displayColumns = vue.computed(() => {
945
- return properties.uiSchema.elements.map((e) => {
946
- const element = e;
947
- const def = jsonFormsCore.findColumnDef(element, properties.schema);
948
- const type = lodashEs.isArray(def.type) ? def.type[0] : def.type;
949
- let component;
950
- if (element.options?.format && element.options.format in components) {
951
- component = components[element.options.format];
952
- } else {
953
- component = components[element.type];
954
- }
955
- if (!component) console.warn("No component found for type", element.type);
956
- return {
957
- ...def,
958
- type,
959
- component
960
- };
961
- });
352
+ };
353
+ const get = (id, options2) => {
354
+ return httpRequest.get(getDataUri(id), options2).then((response) => {
355
+ return response.data;
356
+ }).catch((response) => {
357
+ handleError(response, `Failed to load data`);
962
358
  });
963
- const onChangeFilters = (filters) => {
964
- store.updateFilters(filters);
965
- };
966
- const onUpdatePage = (page) => {
967
- store.updatePage(page);
968
- };
969
- const onSort = (id) => {
970
- store.sort(id);
971
- };
972
- const sort = vue.computed(() => {
973
- return store.sorting.value ?? { orderBy: "", ascending: 1 };
359
+ };
360
+ const _delete = (id, options2) => {
361
+ return httpRequest.delete(getDataUri(id), options2).then((response) => {
362
+ handleSuccess(`${notificationEntity} deleted`);
363
+ return response;
364
+ }).catch((response) => {
365
+ handleError(response, `Failed to delete ${notificationEntity}`);
974
366
  });
975
- return (_ctx, _cache) => {
976
- return vue.openBlock(), vue.createElementBlock("div", null, [
977
- _ctx.filterUiSchema && _ctx.filterSchema ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, [
978
- vue.createVNode(_sfc_main$5, {
979
- layout: { uiSchema: _ctx.filterUiSchema, schema: _ctx.filterSchema },
980
- filters: vue.unref(store).filters.value,
981
- onChangeFilters
982
- }, null, 8, ["layout", "filters"])
983
- ])) : vue.createCommentVNode("", true),
984
- vue.createElementVNode("div", null, [
985
- vue.createVNode(vue.unref(ui.Table), {
986
- "display-columns": displayColumns.value,
987
- sort: sort.value,
988
- page: vue.unref(store).pageData.value,
989
- loading: vue.unref(store).loading.value,
990
- data: vue.unref(store).tableData.value,
991
- actions: _ctx.actions,
992
- onUpdatePage,
993
- onDelete: deleteFn,
994
- onEdit: edit,
995
- onSort
996
- }, null, 8, ["display-columns", "sort", "page", "loading", "data", "actions"])
997
- ])
998
- ]);
999
- };
1000
- }
1001
- });
1002
- const _hoisted_1$2 = { class: "flex justify-between items-center mb-2" };
1003
- const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
1004
- __name: "form-with-table.component",
1005
- props: FormWithTableProperties,
1006
- emits: FormWithTableEmits,
1007
- setup(__props, { emit: __emit }) {
1008
- const properties = __props;
1009
- const emit = __emit;
1010
- const reload = vue.ref(0);
1011
- const resolvedForm = vue.computed(() => properties.form);
1012
- const resolvedTable = vue.computed(() => properties.table);
1013
- const resolvedFilter = vue.computed(() => properties.filter);
1014
- const resolvedUri = vue.computed(() => properties.uri);
1015
- let store = new FormStore(resolvedUri.value ?? "");
1016
- vue.watch(resolvedUri, (uri) => {
1017
- store = new FormStore(uri ?? "");
367
+ };
368
+ const createMulti = (objects, options2) => {
369
+ return Promise.all(
370
+ objects.map((object2) => httpRequest.post(getDataUri(), object2, options2))
371
+ ).then((response) => {
372
+ handleSuccess(`Created ${notificationEntity}`);
373
+ return response.data;
374
+ }).catch((response) => {
375
+ handleError(response, `Failed to save ${notificationEntity}`);
1018
376
  });
1019
- const hasEdit = ui.hasCustomEventListener("editData");
1020
- const customEdit = ui.hasCustomEventListener("custom:edit");
1021
- const customCreate = ui.hasCustomEventListener("custom:create");
1022
- const edit = (data) => {
1023
- if (customEdit) {
1024
- emit("custom:edit", data);
1025
- return;
1026
- }
1027
- if (hasEdit) {
1028
- emit("editData", data);
1029
- return;
1030
- }
1031
- openModal(data);
1032
- };
1033
- const create = () => {
1034
- if (customCreate) {
1035
- emit("custom:create");
1036
- return;
1037
- }
1038
- openModal();
1039
- };
1040
- const deleteFn = (data) => {
1041
- ui.ModalService.showConfirm({
1042
- title: "Delete record",
1043
- message: "Are you sure to delete, the data will be lost?",
1044
- onClose: (result) => {
1045
- if (result.confirmed) {
1046
- store.delete(data).then(() => {
1047
- reload.value = Date.now();
1048
- emit("delete", data);
1049
- });
1050
- }
1051
- }
1052
- });
1053
- };
1054
- const openModal = (formData) => {
1055
- if (!resolvedForm.value) return;
1056
- const isUpdate = !!formData?.id;
1057
- FormModalService.openModal({
1058
- schema: resolvedForm.value.schema,
1059
- uiSchema: resolvedForm.value.uiSchema,
1060
- modalSize: resolvedForm.value.modalSize,
1061
- initialData: formData ?? properties.initialData,
1062
- modalTitle: (isUpdate ? properties.updateTitle ?? properties.createTitle : properties.createTitle) ?? "",
1063
- onClose: (result) => {
1064
- if (result && result.valid) {
1065
- store.save(formData?.id, result.data).then(() => {
1066
- reload.value = Date.now();
1067
- emit("save", { id: formData?.id, data: result.data });
1068
- });
1069
- }
1070
- },
1071
- onEvents: (payload) => emit("events", payload)
1072
- });
1073
- };
1074
- return (_ctx, _cache) => {
1075
- return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
1076
- vue.createElementVNode("div", _hoisted_1$2, [
1077
- vue.createElementVNode("h1", null, vue.toDisplayString(_ctx.tableTitle), 1),
1078
- vue.createElementVNode("div", null, [
1079
- vue.createVNode(vue.unref(ui.Btn), {
1080
- icon: vue.unref(ui.IconEnum).Plus,
1081
- outline: true,
1082
- onClick: create
1083
- }, {
1084
- default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
1085
- vue.createTextVNode(" Add new record ", -1)
1086
- ])]),
1087
- _: 1
1088
- }, 8, ["icon"])
1089
- ])
1090
- ]),
1091
- resolvedTable.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Card), { key: 0 }, {
1092
- default: vue.withCtx(() => [
1093
- resolvedUri.value ? (vue.openBlock(), vue.createBlock(vue.unref(_sfc_main$4), {
1094
- key: 0,
1095
- id: `form_table_${_ctx.id}`,
1096
- "ui-schema": resolvedTable.value.uiSchema,
1097
- schema: resolvedTable.value.schema,
1098
- "filter-ui-schema": resolvedFilter.value?.uiSchema,
1099
- "filter-schema": resolvedFilter.value?.schema,
1100
- uri: _ctx.dataUri ?? resolvedUri.value,
1101
- reload: reload.value,
1102
- actions: _ctx.tableActions,
1103
- onEdit: edit,
1104
- onDelete: deleteFn
1105
- }, null, 8, ["id", "ui-schema", "schema", "filter-ui-schema", "filter-schema", "uri", "reload", "actions"])) : vue.createCommentVNode("", true)
1106
- ]),
1107
- _: 1
1108
- })) : vue.createCommentVNode("", true)
1109
- ], 64);
1110
- };
1111
- }
377
+ };
378
+ return { create, patch, createMulti, delete: _delete, get };
379
+ };
380
+ const createFormEvents = (dispatch) => ({
381
+ dispatch
1112
382
  });
383
+ const FORM_EVENTS_KEY = /* @__PURE__ */ Symbol("json-forms:events");
384
+ const provideFormEvents = (dispatch) => {
385
+ const events = createFormEvents(dispatch);
386
+ vue.provide(FORM_EVENTS_KEY, events);
387
+ return events;
388
+ };
389
+ const useFormEvents = () => {
390
+ return vue.inject(
391
+ FORM_EVENTS_KEY,
392
+ createFormEvents(() => {
393
+ })
394
+ );
395
+ };
1113
396
  function $constructor(name, initializer2, params) {
1114
397
  function init(inst, def) {
1115
398
  if (!inst._zod) {
@@ -1644,7 +927,7 @@ function flattenError(error2, mapper = (issue2) => issue2.message) {
1644
927
  }
1645
928
  return { formErrors, fieldErrors };
1646
929
  }
1647
- function formatError(error2, mapper = (issue2) => issue2.message) {
930
+ function formatError$1(error2, mapper = (issue2) => issue2.message) {
1648
931
  const fieldErrors = { _errors: [] };
1649
932
  const processError = (error3) => {
1650
933
  for (const issue2 of error3.issues) {
@@ -3097,11 +2380,11 @@ const $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
3097
2380
  return payload;
3098
2381
  };
3099
2382
  });
3100
- function handleArrayResult(result, final, index) {
2383
+ function handleArrayResult(result, final, index2) {
3101
2384
  if (result.issues.length) {
3102
- final.issues.push(...prefixIssues(index, result.issues));
2385
+ final.issues.push(...prefixIssues(index2, result.issues));
3103
2386
  }
3104
- final.value[index] = result.value;
2387
+ final.value[index2] = result.value;
3105
2388
  }
3106
2389
  const $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
3107
2390
  $ZodType.init(inst, def);
@@ -3592,14 +2875,14 @@ function mergeValues(a, b) {
3592
2875
  return { valid: false, mergeErrorPath: [] };
3593
2876
  }
3594
2877
  const newArray = [];
3595
- for (let index = 0; index < a.length; index++) {
3596
- const itemA = a[index];
3597
- const itemB = b[index];
2878
+ for (let index2 = 0; index2 < a.length; index2++) {
2879
+ const itemA = a[index2];
2880
+ const itemB = b[index2];
3598
2881
  const sharedValue = mergeValues(itemA, itemB);
3599
2882
  if (!sharedValue.valid) {
3600
2883
  return {
3601
2884
  valid: false,
3602
- mergeErrorPath: [index, ...sharedValue.mergeErrorPath]
2885
+ mergeErrorPath: [index2, ...sharedValue.mergeErrorPath]
3603
2886
  };
3604
2887
  }
3605
2888
  newArray.push(sharedValue.data);
@@ -3715,11 +2998,11 @@ const $ZodTuple = /* @__PURE__ */ $constructor("$ZodTuple", (inst, def) => {
3715
2998
  return payload;
3716
2999
  };
3717
3000
  });
3718
- function handleTupleResult(result, final, index) {
3001
+ function handleTupleResult(result, final, index2) {
3719
3002
  if (result.issues.length) {
3720
- final.issues.push(...prefixIssues(index, result.issues));
3003
+ final.issues.push(...prefixIssues(index2, result.issues));
3721
3004
  }
3722
- final.value[index] = result.value;
3005
+ final.value[index2] = result.value;
3723
3006
  }
3724
3007
  const $ZodRecord = /* @__PURE__ */ $constructor("$ZodRecord", (inst, def) => {
3725
3008
  $ZodType.init(inst, def);
@@ -6317,7 +5600,7 @@ const initializer = (inst, issues) => {
6317
5600
  inst.name = "ZodError";
6318
5601
  Object.defineProperties(inst, {
6319
5602
  format: {
6320
- value: (mapper) => formatError(inst, mapper)
5603
+ value: (mapper) => formatError$1(inst, mapper)
6321
5604
  // enumerable: false,
6322
5605
  },
6323
5606
  flatten: {
@@ -7937,245 +7220,1344 @@ function convertBaseSchema(schema, ctx) {
7937
7220
  }
7938
7221
  break;
7939
7222
  }
7940
- const objectSchema = z.object(shape);
7941
- if (schema.additionalProperties === false) {
7942
- zodSchema = objectSchema.strict();
7943
- } else if (typeof schema.additionalProperties === "object") {
7944
- zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx));
7945
- } else {
7946
- zodSchema = objectSchema.passthrough();
7223
+ const objectSchema = z.object(shape);
7224
+ if (schema.additionalProperties === false) {
7225
+ zodSchema = objectSchema.strict();
7226
+ } else if (typeof schema.additionalProperties === "object") {
7227
+ zodSchema = objectSchema.catchall(convertSchema(schema.additionalProperties, ctx));
7228
+ } else {
7229
+ zodSchema = objectSchema.passthrough();
7230
+ }
7231
+ break;
7232
+ }
7233
+ case "array": {
7234
+ const prefixItems = schema.prefixItems;
7235
+ const items = schema.items;
7236
+ if (prefixItems && Array.isArray(prefixItems)) {
7237
+ const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
7238
+ const rest = items && typeof items === "object" && !Array.isArray(items) ? convertSchema(items, ctx) : void 0;
7239
+ if (rest) {
7240
+ zodSchema = z.tuple(tupleItems).rest(rest);
7241
+ } else {
7242
+ zodSchema = z.tuple(tupleItems);
7243
+ }
7244
+ if (typeof schema.minItems === "number") {
7245
+ zodSchema = zodSchema.check(z.minLength(schema.minItems));
7246
+ }
7247
+ if (typeof schema.maxItems === "number") {
7248
+ zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
7249
+ }
7250
+ } else if (Array.isArray(items)) {
7251
+ const tupleItems = items.map((item) => convertSchema(item, ctx));
7252
+ const rest = schema.additionalItems && typeof schema.additionalItems === "object" ? convertSchema(schema.additionalItems, ctx) : void 0;
7253
+ if (rest) {
7254
+ zodSchema = z.tuple(tupleItems).rest(rest);
7255
+ } else {
7256
+ zodSchema = z.tuple(tupleItems);
7257
+ }
7258
+ if (typeof schema.minItems === "number") {
7259
+ zodSchema = zodSchema.check(z.minLength(schema.minItems));
7260
+ }
7261
+ if (typeof schema.maxItems === "number") {
7262
+ zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
7263
+ }
7264
+ } else if (items !== void 0) {
7265
+ const element = convertSchema(items, ctx);
7266
+ let arraySchema = z.array(element);
7267
+ if (typeof schema.minItems === "number") {
7268
+ arraySchema = arraySchema.min(schema.minItems);
7269
+ }
7270
+ if (typeof schema.maxItems === "number") {
7271
+ arraySchema = arraySchema.max(schema.maxItems);
7272
+ }
7273
+ zodSchema = arraySchema;
7274
+ } else {
7275
+ zodSchema = z.array(z.any());
7276
+ }
7277
+ break;
7278
+ }
7279
+ default:
7280
+ throw new Error(`Unsupported type: ${type}`);
7281
+ }
7282
+ if (schema.description) {
7283
+ zodSchema = zodSchema.describe(schema.description);
7284
+ }
7285
+ if (schema.default !== void 0) {
7286
+ zodSchema = zodSchema.default(schema.default);
7287
+ }
7288
+ return zodSchema;
7289
+ }
7290
+ function convertSchema(schema, ctx) {
7291
+ if (typeof schema === "boolean") {
7292
+ return schema ? z.any() : z.never();
7293
+ }
7294
+ let baseSchema = convertBaseSchema(schema, ctx);
7295
+ const hasExplicitType = schema.type || schema.enum !== void 0 || schema.const !== void 0;
7296
+ if (schema.anyOf && Array.isArray(schema.anyOf)) {
7297
+ const options = schema.anyOf.map((s) => convertSchema(s, ctx));
7298
+ const anyOfUnion = z.union(options);
7299
+ baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
7300
+ }
7301
+ if (schema.oneOf && Array.isArray(schema.oneOf)) {
7302
+ const options = schema.oneOf.map((s) => convertSchema(s, ctx));
7303
+ const oneOfUnion = z.xor(options);
7304
+ baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
7305
+ }
7306
+ if (schema.allOf && Array.isArray(schema.allOf)) {
7307
+ if (schema.allOf.length === 0) {
7308
+ baseSchema = hasExplicitType ? baseSchema : z.any();
7309
+ } else {
7310
+ let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx);
7311
+ const startIdx = hasExplicitType ? 0 : 1;
7312
+ for (let i = startIdx; i < schema.allOf.length; i++) {
7313
+ result = z.intersection(result, convertSchema(schema.allOf[i], ctx));
7314
+ }
7315
+ baseSchema = result;
7316
+ }
7317
+ }
7318
+ if (schema.nullable === true && ctx.version === "openapi-3.0") {
7319
+ baseSchema = z.nullable(baseSchema);
7320
+ }
7321
+ if (schema.readOnly === true) {
7322
+ baseSchema = z.readonly(baseSchema);
7323
+ }
7324
+ const extraMeta = {};
7325
+ const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
7326
+ for (const key of coreMetadataKeys) {
7327
+ if (key in schema) {
7328
+ extraMeta[key] = schema[key];
7329
+ }
7330
+ }
7331
+ const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
7332
+ for (const key of contentMetadataKeys) {
7333
+ if (key in schema) {
7334
+ extraMeta[key] = schema[key];
7335
+ }
7336
+ }
7337
+ for (const key of Object.keys(schema)) {
7338
+ if (!RECOGNIZED_KEYS.has(key)) {
7339
+ extraMeta[key] = schema[key];
7340
+ }
7341
+ }
7342
+ if (Object.keys(extraMeta).length > 0) {
7343
+ ctx.registry.add(baseSchema, extraMeta);
7344
+ }
7345
+ return baseSchema;
7346
+ }
7347
+ function fromJSONSchema(schema, params) {
7348
+ if (typeof schema === "boolean") {
7349
+ return schema ? z.any() : z.never();
7350
+ }
7351
+ const version2 = detectVersion(schema);
7352
+ const defs = schema.$defs || schema.definitions || {};
7353
+ const ctx = {
7354
+ version: version2,
7355
+ defs,
7356
+ refs: /* @__PURE__ */ new Map(),
7357
+ processing: /* @__PURE__ */ new Set(),
7358
+ rootSchema: schema,
7359
+ registry: globalRegistry
7360
+ };
7361
+ return convertSchema(schema, ctx);
7362
+ }
7363
+ config(en());
7364
+ const errorPatterns = [
7365
+ [/^Invalid input: expected \w+, received undefined$/, "This field is required"],
7366
+ [/^Invalid input: expected \w+, received null$/, "This field is required"],
7367
+ [/^Expected string, received/, "Invalid value"],
7368
+ [/^String must contain at least (\d+)/, "Must be at least $1 characters"],
7369
+ [/^Number must be greater than or equal to (\d+)/, "Minimum value is $1"],
7370
+ [/^Number must be less than or equal to (\d+)/, "Maximum value is $1"]
7371
+ ];
7372
+ const formatError = (message) => {
7373
+ if (!message) return void 0;
7374
+ for (const [pattern, replacement] of errorPatterns) {
7375
+ if (pattern.test(message)) {
7376
+ return message.replace(pattern, replacement);
7377
+ }
7378
+ }
7379
+ return message;
7380
+ };
7381
+ const registerZodErrorMap = () => {
7382
+ config({
7383
+ customError: (issue2) => {
7384
+ if (issue2.code === "invalid_type" && issue2.received === "undefined") {
7385
+ return { message: "This field is required" };
7386
+ }
7387
+ if (issue2.code === "invalid_type" && issue2.received === "null") {
7388
+ return { message: "This field is required" };
7389
+ }
7390
+ if (issue2.code === "too_small") {
7391
+ const i = issue2;
7392
+ if (i.type === "string" && i.minimum === 1) {
7393
+ return { message: "This field is required" };
7394
+ }
7395
+ if (i.type === "string") {
7396
+ return { message: `Must be at least ${i.minimum} characters` };
7397
+ }
7398
+ }
7399
+ if (issue2.code === "too_big") {
7400
+ const i = issue2;
7401
+ if (i.type === "string") {
7402
+ return { message: `Must be at most ${i.maximum} characters` };
7403
+ }
7404
+ }
7405
+ return { message: issue2.message };
7406
+ }
7407
+ });
7408
+ };
7409
+ function findRenderer(registry2, uischema, schema) {
7410
+ let best = null;
7411
+ for (const entry of registry2) {
7412
+ const rank = entry.tester(uischema, schema);
7413
+ if (rank > -1 && (!best || rank > best.rank)) {
7414
+ best = { rank, renderer: entry.renderer };
7415
+ }
7416
+ }
7417
+ return best?.renderer ?? null;
7418
+ }
7419
+ const scopeToPath = (scope) => {
7420
+ if (!scope) return "";
7421
+ return scope.replace(/^#\//, "").split("/").filter((s) => s !== "properties").join(".");
7422
+ };
7423
+ const resolveSchema = (root, scope) => {
7424
+ const segments = scope.replace(/^#\//, "").split("/").filter(Boolean);
7425
+ return segments.reduce((acc, key) => acc?.[key], root);
7426
+ };
7427
+ const _hoisted_1$6 = {
7428
+ key: 1,
7429
+ class: "text-error text-xs"
7430
+ };
7431
+ const _sfc_main$f = /* @__PURE__ */ vue.defineComponent({
7432
+ __name: "Dispatch",
7433
+ props: {
7434
+ uischema: {},
7435
+ schema: {},
7436
+ pathPrefix: { default: void 0 }
7437
+ },
7438
+ setup(__props) {
7439
+ const props = __props;
7440
+ const registry2 = vue.inject("renderers");
7441
+ const rootSchema = vue.inject("rootSchema");
7442
+ const parentPrefix = vue.inject("pathPrefix", "");
7443
+ const effectivePrefix = props.pathPrefix ?? parentPrefix;
7444
+ if (props.pathPrefix !== void 0) {
7445
+ vue.provide("pathPrefix", effectivePrefix);
7446
+ }
7447
+ const resolved = vue.computed(() => {
7448
+ const u = props.uischema;
7449
+ if (!u.scope) return props.schema;
7450
+ const fromRoot = resolveSchema(rootSchema, u.scope);
7451
+ if (fromRoot) return fromRoot;
7452
+ return resolveSchema(props.schema, u.scope) ?? props.schema;
7453
+ });
7454
+ const renderer = vue.computed(
7455
+ () => findRenderer(registry2, props.uischema, resolved.value)
7456
+ );
7457
+ return (_ctx, _cache) => {
7458
+ return renderer.value ? (vue.openBlock(), vue.createBlock(vue.resolveDynamicComponent(renderer.value), {
7459
+ key: 0,
7460
+ uischema: __props.uischema,
7461
+ schema: resolved.value
7462
+ }, null, 8, ["uischema", "schema"])) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$6, " No renderer for " + vue.toDisplayString(__props.uischema.scope ?? __props.uischema.type), 1));
7463
+ };
7464
+ }
7465
+ });
7466
+ const JsonFormComponentProperties = {
7467
+ /** Unique identifier used to namespace the form element. */
7468
+ id: { type: String, required: true },
7469
+ /** HTML name attribute for the form. */
7470
+ name: { type: String, default: "form" },
7471
+ /** JSON schema describing the shape of the form data. */
7472
+ schema: { type: Object, required: true },
7473
+ /** UI schema describing the layout and controls. */
7474
+ uiSchema: { type: Object, required: true },
7475
+ /** Disable all form controls. */
7476
+ disabled: { type: Boolean, default: false },
7477
+ /** Current form data object. */
7478
+ formData: { type: Object, default: () => ({}) },
7479
+ /** When validation errors are shown (`'onBlur'`, `'onChange'`, `'onSubmit'`, `'always'`). */
7480
+ errorMode: {
7481
+ type: String,
7482
+ default: "onChanges"
7483
+ }
7484
+ };
7485
+ const JsonFormComponentEmits = [
7486
+ /** Emitted when form data changes. */
7487
+ "change",
7488
+ /** Emitted on form submission. */
7489
+ "submit",
7490
+ /** Emitted when validation errors change. */
7491
+ "errors",
7492
+ /** Emitted when form validity changes. */
7493
+ "valid",
7494
+ /** Emitted when a custom renderer dispatches a form event. */
7495
+ "events"
7496
+ ];
7497
+ const ERROR_MODE_KEY = /* @__PURE__ */ Symbol("errorMode");
7498
+ const FORM_SUBMITTED_KEY = /* @__PURE__ */ Symbol("formSubmitted");
7499
+ const _hoisted_1$5 = { class: "flex-1" };
7500
+ const _hoisted_2$1 = { key: 0 };
7501
+ const _hoisted_3 = {
7502
+ key: 0,
7503
+ class: "text-sm text-base-content/50"
7504
+ };
7505
+ const _hoisted_4 = { key: 1 };
7506
+ const _sfc_main$e = /* @__PURE__ */ vue.defineComponent({
7507
+ __name: "ArrayRenderer",
7508
+ props: {
7509
+ uischema: {},
7510
+ schema: {}
7511
+ },
7512
+ setup(__props) {
7513
+ const props = __props;
7514
+ const parentPrefix = vue.inject("pathPrefix", "");
7515
+ const scope = props.uischema.scope;
7516
+ const scopePath = scopeToPath(scope);
7517
+ const path = parentPrefix ? `${parentPrefix}.${scopePath}` : scopePath;
7518
+ const rootSchema = vue.inject("rootSchema");
7519
+ const arraySchema = resolveSchema(rootSchema, scope);
7520
+ const itemSchema = arraySchema?.items ?? {};
7521
+ const { fields, push, remove } = veeValidate.useFieldArray(path);
7522
+ if (fields.value.length === 0) {
7523
+ push({});
7524
+ }
7525
+ const opts = props.uischema.options ?? {};
7526
+ const layout = opts.layout ?? "column";
7527
+ const showActions = vue.computed(() => !opts.hideActions);
7528
+ const detail = vue.computed(
7529
+ () => props.uischema._detail ?? opts.detail
7530
+ );
7531
+ const childElements = vue.computed(() => {
7532
+ if (!detail.value) {
7533
+ return props.uischema.elements ?? [];
7534
+ }
7535
+ const type = detail.value.type;
7536
+ if (type && type !== "Control") {
7537
+ return [detail.value];
7538
+ }
7539
+ return detail.value.elements ?? [detail.value];
7540
+ });
7541
+ return (_ctx, _cache) => {
7542
+ return vue.openBlock(), vue.createElementBlock("div", null, [
7543
+ vue.createElementVNode("div", {
7544
+ class: vue.normalizeClass([
7545
+ "flex gap-2",
7546
+ vue.unref(layout) === "row" ? "flex-row items-center" : "flex-col"
7547
+ ])
7548
+ }, [
7549
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(vue.unref(fields), (entry, index2) => {
7550
+ return vue.openBlock(), vue.createElementBlock("div", {
7551
+ key: entry.key,
7552
+ class: "flex-1"
7553
+ }, [
7554
+ vue.createElementVNode("div", {
7555
+ class: vue.normalizeClass([
7556
+ "flex gap-2",
7557
+ vue.unref(layout) === "row" ? "flex-col" : "flex-row items-center"
7558
+ ])
7559
+ }, [
7560
+ vue.createElementVNode("div", _hoisted_1$5, [
7561
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(childElements.value, (child, ci) => {
7562
+ return vue.openBlock(), vue.createBlock(_sfc_main$f, {
7563
+ key: ci,
7564
+ uischema: child,
7565
+ schema: vue.unref(itemSchema),
7566
+ "path-prefix": `${vue.unref(path)}[${index2}]`
7567
+ }, null, 8, ["uischema", "schema", "path-prefix"]);
7568
+ }), 128))
7569
+ ]),
7570
+ showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_2$1, [
7571
+ vue.unref(fields).length > 1 ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
7572
+ key: 0,
7573
+ icon: vue.unref(ui.IconEnum).Delete,
7574
+ outline: true,
7575
+ onClick: ($event) => vue.unref(remove)(index2)
7576
+ }, null, 8, ["icon", "onClick"])) : vue.createCommentVNode("", true)
7577
+ ])) : vue.createCommentVNode("", true)
7578
+ ], 2)
7579
+ ]);
7580
+ }), 128)),
7581
+ vue.unref(fields).length === 0 ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_3, " No data ")) : vue.createCommentVNode("", true),
7582
+ showActions.value ? (vue.openBlock(), vue.createElementBlock("div", _hoisted_4, [
7583
+ vue.createVNode(vue.unref(ui.Btn), {
7584
+ icon: vue.unref(ui.IconEnum).Plus,
7585
+ outline: true,
7586
+ onClick: _cache[0] || (_cache[0] = ($event) => vue.unref(push)({}))
7587
+ }, {
7588
+ default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
7589
+ vue.createTextVNode(" Add ", -1)
7590
+ ])]),
7591
+ _: 1
7592
+ }, 8, ["icon"])
7593
+ ])) : vue.createCommentVNode("", true)
7594
+ ], 2)
7595
+ ]);
7596
+ };
7597
+ }
7598
+ });
7599
+ const isAutoCompleteControl = testers.and(
7600
+ // uiTypeIs('Control'),
7601
+ testers.optionIs("format", jsonFormsCore.ControlType.autocomplete)
7602
+ );
7603
+ const isTextAreaControl = testers.and(
7604
+ core$1.uiTypeIs("Control"),
7605
+ testers.optionIs("format", jsonFormsCore.ControlType.textArea)
7606
+ );
7607
+ const isStringFormat = testers.and(
7608
+ core$1.uiTypeIs("Control"),
7609
+ testers.or(testers.optionIs("format", jsonFormsCore.ControlType.string), testers.schemaTypeIs("string"))
7610
+ );
7611
+ const isMarkdownControl = testers.and(
7612
+ core$1.uiTypeIs("Control"),
7613
+ testers.optionIs("format", jsonFormsCore.ControlType.markdown)
7614
+ );
7615
+ const isArrayRenderer = testers.and(
7616
+ testers.schemaTypeIs("array")
7617
+ // optionIs('format', ControlType.array),
7618
+ );
7619
+ const isMultiselectControl = testers.and(
7620
+ core$1.uiTypeIs("Control"),
7621
+ testers.optionIs("format", jsonFormsCore.ControlType.mutliSelect)
7622
+ );
7623
+ const isSelectControl = testers.and(
7624
+ core$1.uiTypeIs("Control"),
7625
+ testers.optionIs("format", jsonFormsCore.ControlType.select)
7626
+ );
7627
+ const isBooleanControl = testers.or(
7628
+ testers.isBooleanControl,
7629
+ testers.and(core$1.uiTypeIs("Control"), testers.optionIs("format", jsonFormsCore.ControlType.boolean))
7630
+ );
7631
+ const isNumberFormat = testers.and(
7632
+ core$1.uiTypeIs("Control"),
7633
+ testers.or(testers.optionIs("format", jsonFormsCore.ControlType.number), testers.schemaTypeIs("number"))
7634
+ );
7635
+ const isIntegerFormat = testers.and(
7636
+ core$1.uiTypeIs("Control"),
7637
+ testers.or(testers.optionIs("format", jsonFormsCore.ControlType.integer), testers.schemaTypeIs("integer"))
7638
+ );
7639
+ const arrayRenderers = [
7640
+ { tester: core$1.rankWith(12, isArrayRenderer), renderer: _sfc_main$e }
7641
+ ];
7642
+ const MethodSchema = _enum(["get", "post", "delete", "put", "patch"]);
7643
+ const OperationSchema = object({
7644
+ uri: string(),
7645
+ method: MethodSchema
7646
+ });
7647
+ const OperationsSchema = string().or(OperationSchema);
7648
+ const BooleanOperationSchema = boolean().or(OperationSchema).optional().default(false);
7649
+ const Operations = object({
7650
+ findAll: BooleanOperationSchema,
7651
+ findOne: BooleanOperationSchema,
7652
+ create: BooleanOperationSchema,
7653
+ update: BooleanOperationSchema,
7654
+ delete: BooleanOperationSchema,
7655
+ lookup: OperationsSchema.optional()
7656
+ });
7657
+ const OperationMap = {
7658
+ create: "post",
7659
+ delete: "delete",
7660
+ findAll: "get",
7661
+ findOne: "get",
7662
+ lookup: "get",
7663
+ update: "get"
7664
+ };
7665
+ const ResourceSchema = object({
7666
+ id: string(),
7667
+ uri: string(),
7668
+ operations: Operations,
7669
+ schema: object({
7670
+ ui: any().optional(),
7671
+ data: any()
7672
+ }).optional()
7673
+ }).transform((data) => {
7674
+ const schema = data.schema;
7675
+ if (schema) {
7676
+ if (!schema.ui) {
7677
+ schema.ui = jsonFormsCore.uiFromJsonSchema(schema.data);
7678
+ }
7679
+ }
7680
+ const operations = {};
7681
+ for (const k in OperationMap) {
7682
+ const key = k;
7683
+ const defaultOperation = OperationMap[key];
7684
+ const operation = data.operations[key];
7685
+ const mapResourceSchema = () => {
7686
+ if (lodashEs.isUndefined(operation) || operation === false) return null;
7687
+ if (operation === true)
7688
+ return { uri: data.uri, method: defaultOperation };
7689
+ if (typeof operation === "string")
7690
+ return { uri: operation, method: "get" };
7691
+ return {
7692
+ uri: operation.uri,
7693
+ method: operation.method ?? defaultOperation
7694
+ };
7695
+ };
7696
+ operations[key] = mapResourceSchema();
7697
+ }
7698
+ return {
7699
+ ...data,
7700
+ schema,
7701
+ operations
7702
+ };
7703
+ });
7704
+ const getResourceSchema = async (resourceUri, skipAuth) => {
7705
+ const fetch = skipAuth ? axios : toolsVue.useApi();
7706
+ return fetch.get(resourceUri).then((response) => {
7707
+ const resource = ResourceSchema.safeParse(response.data);
7708
+ if (!resource.success)
7709
+ throw new Error(`Invalid resource schema: ${resource.error}`);
7710
+ return resource.data;
7711
+ });
7712
+ };
7713
+ const useRemoteOption = (options) => {
7714
+ return {
7715
+ fetchOptions: (searchTerm, signal) => {
7716
+ const fetch = options.skipAuth ? axios : toolsVue.useApi();
7717
+ return fetch.get(`${options.uri}${searchTerm}`, { signal }).then((data) => data.data[options.dataField ?? "data"]);
7718
+ }
7719
+ };
7720
+ };
7721
+ const useResourceOptions = async (options) => {
7722
+ const resource = await getResourceSchema(
7723
+ options.resource,
7724
+ options.skipAuth ?? false
7725
+ );
7726
+ const fetch = options.skipAuth ? axios : toolsVue.useApi();
7727
+ const lookup = resource.operations.lookup;
7728
+ return {
7729
+ fetchOptions: (searchTerm, signal) => {
7730
+ const uri = lookup.uri.replace("{text}", searchTerm);
7731
+ const method = lookup.method;
7732
+ return fetch[method](uri, { signal }).then(
7733
+ (data) => data.data[options.dataField ?? "data"]
7734
+ );
7735
+ },
7736
+ enableCreate: !!resource.operations.create,
7737
+ form: resource.operations.create ? {
7738
+ ui_schema: resource.schema.ui,
7739
+ json_schema: resource.schema.data,
7740
+ title: `Create new ${resource.id}`,
7741
+ create: async (data) => {
7742
+ const create = resource.operations.create;
7743
+ return fetch[create.method](create.uri, data).then(
7744
+ (result) => result.data
7745
+ );
7746
+ }
7747
+ } : null
7748
+ };
7749
+ };
7750
+ const useFetchOptions = async (options) => {
7751
+ let config2 = {};
7752
+ if (options.uri)
7753
+ config2 = useRemoteOption(options);
7754
+ if (options.resource)
7755
+ config2 = await useResourceOptions(options);
7756
+ return {
7757
+ fetchOptions: null,
7758
+ labelKey: options.labelKey,
7759
+ valueKey: options.valueKey,
7760
+ enableCreate: options.enableCreate ?? false,
7761
+ form: null,
7762
+ ...config2
7763
+ };
7764
+ };
7765
+ const checkRequired = (rootSchema, scope, fieldName) => {
7766
+ const segments = scope.replace(/^#\//, "").split("/");
7767
+ const parentSegments = segments.slice(0, -2);
7768
+ if (parentSegments.length === 0) {
7769
+ const req2 = rootSchema?.required;
7770
+ return Array.isArray(req2) && req2.includes(fieldName);
7771
+ }
7772
+ const parentScope = `#/${parentSegments.join("/")}`;
7773
+ const parentSchema = resolveSchema(rootSchema, parentScope);
7774
+ const req = parentSchema?.required;
7775
+ return Array.isArray(req) && req.includes(fieldName);
7776
+ };
7777
+ const useInputProps = (uischema, schema, field, options = {}) => {
7778
+ const rootSchema = vue.inject("rootSchema");
7779
+ const path = scopeToPath(uischema.scope);
7780
+ const { errorMessage, meta: meta2 } = field;
7781
+ const opts = uischema.options ?? {};
7782
+ const labelFromScope = path.split(".").pop() ?? "";
7783
+ const isRequired = rootSchema ? checkRequired(rootSchema, uischema.scope, labelFromScope) : false;
7784
+ const s = schema ?? {};
7785
+ const inferredType = (() => {
7786
+ if (opts.format === "text") return "text";
7787
+ if (s.format === "email") return "email";
7788
+ if (s.format === "uri") return "url";
7789
+ if (s.type === "number" || s.type === "integer") return "number";
7790
+ return options.defaultType ?? "text";
7791
+ })();
7792
+ const styles = ui.mergeStyles(opts.styles);
7793
+ const errorMode = vue.inject(ERROR_MODE_KEY, vue.ref("onBlur"));
7794
+ const submitted = vue.inject(FORM_SUBMITTED_KEY, vue.ref(false));
7795
+ const shouldShowError = vue.computed(() => {
7796
+ if (!errorMessage.value) return false;
7797
+ switch (errorMode.value) {
7798
+ case "always":
7799
+ return true;
7800
+ case "onChange":
7801
+ return meta2.dirty;
7802
+ case "onSubmit":
7803
+ return submitted.value;
7804
+ case "onBlur":
7805
+ default:
7806
+ return meta2.touched;
7807
+ }
7808
+ });
7809
+ const width = opts.colspan || styles?.width === "full" ? "w-full" : opts.width ?? "min-w-input";
7810
+ return vue.computed(() => ({
7811
+ id: path,
7812
+ placeholder: opts.placeholder,
7813
+ description: s.description,
7814
+ errors: shouldShowError.value ? opts.errorMessage ?? formatError(errorMessage.value) : void 0,
7815
+ label: opts.label ?? labelFromScope.charAt(0).toUpperCase() + labelFromScope.slice(1),
7816
+ visible: opts.visible ?? true,
7817
+ required: isRequired,
7818
+ enabled: opts.readonly !== true,
7819
+ isFocused: false,
7820
+ isTouched: shouldShowError.value,
7821
+ hideLabel: opts.hideLabel ?? false,
7822
+ styles,
7823
+ width,
7824
+ type: inferredType,
7825
+ ...options.overrides
7826
+ }));
7827
+ };
7828
+ const useCustomControlBinding = ({
7829
+ useProps,
7830
+ setDefaultValue
7831
+ } = {}) => {
7832
+ return (uischema, schema, options = {}) => {
7833
+ const pathPrefix = vue.inject("pathPrefix", "");
7834
+ const scopePath = scopeToPath(uischema.scope);
7835
+ const path = pathPrefix ? `${pathPrefix}.${scopePath}` : scopePath;
7836
+ const field = veeValidate.useField(() => path);
7837
+ setDefaultValue?.(field);
7838
+ const wrapper = useInputProps(uischema, schema, field, options);
7839
+ const customWrapper = useProps?.(uischema, schema, field, options) ?? {
7840
+ value: {}
7841
+ };
7842
+ const onBlur = () => field.handleBlur(new Event("blur"));
7843
+ const onChange = () => field.handleChange(field.value.value);
7844
+ let initialized = false;
7845
+ vue.watch(field.value, (val) => {
7846
+ if (!initialized) {
7847
+ initialized = true;
7848
+ return;
7947
7849
  }
7948
- break;
7850
+ field.handleChange(val);
7851
+ });
7852
+ return {
7853
+ wrapper: vue.computed(() => ({ ...wrapper.value, ...customWrapper.value })),
7854
+ value: field.value,
7855
+ field,
7856
+ onBlur,
7857
+ onChange,
7858
+ appliedOptions: vue.computed(
7859
+ () => uischema.options ?? {}
7860
+ )
7861
+ };
7862
+ };
7863
+ };
7864
+ const useControlBinding = (uischema, schema, options = {}) => {
7865
+ return useCustomControlBinding()(uischema, schema, options);
7866
+ };
7867
+ const useSelectInput = (...fields) => (uischema, schema, field) => {
7868
+ const opts = uischema.options ?? {};
7869
+ return vue.computed(() => {
7870
+ return lodashEs.pick(opts, fields);
7871
+ });
7872
+ };
7873
+ const useSelectBinding = useCustomControlBinding({
7874
+ useProps: useSelectInput("options", "labelKey", "valueKey")
7875
+ });
7876
+ const useAutocompleteBinding = useCustomControlBinding({
7877
+ useProps: useSelectInput(
7878
+ "options",
7879
+ "labelKey",
7880
+ "valueKey",
7881
+ "uri",
7882
+ "freeText",
7883
+ "enableCreate",
7884
+ "dataField",
7885
+ "skipAuth"
7886
+ )
7887
+ });
7888
+ const _sfc_main$d = /* @__PURE__ */ vue.defineComponent({
7889
+ __name: "FormModal",
7890
+ props: /* @__PURE__ */ vue.mergeModels(FormModalProperties, {
7891
+ "modelValue": {},
7892
+ "modelModifiers": {}
7893
+ }),
7894
+ emits: /* @__PURE__ */ vue.mergeModels(FormModalEmits, ["update:modelValue"]),
7895
+ setup(__props, { emit: __emit }) {
7896
+ const properties = __props;
7897
+ const id = `modal_${Math.floor(Math.random() * 1e3)}`;
7898
+ const formRef = vue.ref();
7899
+ const valid = vue.ref(false);
7900
+ const formData = vue.useModel(__props, "modelValue");
7901
+ const emits = __emit;
7902
+ if (properties.data) {
7903
+ formData.value = properties.data;
7949
7904
  }
7950
- case "array": {
7951
- const prefixItems = schema.prefixItems;
7952
- const items = schema.items;
7953
- if (prefixItems && Array.isArray(prefixItems)) {
7954
- const tupleItems = prefixItems.map((item) => convertSchema(item, ctx));
7955
- const rest = items && typeof items === "object" && !Array.isArray(items) ? convertSchema(items, ctx) : void 0;
7956
- if (rest) {
7957
- zodSchema = z.tuple(tupleItems).rest(rest);
7958
- } else {
7959
- zodSchema = z.tuple(tupleItems);
7960
- }
7961
- if (typeof schema.minItems === "number") {
7962
- zodSchema = zodSchema.check(z.minLength(schema.minItems));
7963
- }
7964
- if (typeof schema.maxItems === "number") {
7965
- zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
7966
- }
7967
- } else if (Array.isArray(items)) {
7968
- const tupleItems = items.map((item) => convertSchema(item, ctx));
7969
- const rest = schema.additionalItems && typeof schema.additionalItems === "object" ? convertSchema(schema.additionalItems, ctx) : void 0;
7970
- if (rest) {
7971
- zodSchema = z.tuple(tupleItems).rest(rest);
7972
- } else {
7973
- zodSchema = z.tuple(tupleItems);
7974
- }
7975
- if (typeof schema.minItems === "number") {
7976
- zodSchema = zodSchema.check(z.minLength(schema.minItems));
7977
- }
7978
- if (typeof schema.maxItems === "number") {
7979
- zodSchema = zodSchema.check(z.maxLength(schema.maxItems));
7980
- }
7981
- } else if (items !== void 0) {
7982
- const element = convertSchema(items, ctx);
7983
- let arraySchema = z.array(element);
7984
- if (typeof schema.minItems === "number") {
7985
- arraySchema = arraySchema.min(schema.minItems);
7986
- }
7987
- if (typeof schema.maxItems === "number") {
7988
- arraySchema = arraySchema.max(schema.maxItems);
7989
- }
7990
- zodSchema = arraySchema;
7991
- } else {
7992
- zodSchema = z.array(z.any());
7905
+ const onCancel = () => {
7906
+ formData.value = {};
7907
+ emits("closeModal", null);
7908
+ };
7909
+ const onChange = (data) => {
7910
+ formData.value = data;
7911
+ };
7912
+ const onSubmit = () => {
7913
+ formRef.value?.markSubmitted();
7914
+ if (!valid.value) return;
7915
+ emits("closeModal", { data: formData.value, valid: valid.value });
7916
+ };
7917
+ const onErrors = (errors) => {
7918
+ emits("errors", errors);
7919
+ valid.value = lodashEs.isEmpty(errors);
7920
+ };
7921
+ vue.watch(valid, (newValid, oldValid) => {
7922
+ if (newValid !== oldValid) {
7923
+ emits("valid", newValid);
7993
7924
  }
7994
- break;
7995
- }
7996
- default:
7997
- throw new Error(`Unsupported type: ${type}`);
7998
- }
7999
- if (schema.description) {
8000
- zodSchema = zodSchema.describe(schema.description);
7925
+ });
7926
+ return (_ctx, _cache) => {
7927
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Modal), vue.mergeProps(properties, {
7928
+ open: true,
7929
+ "disable-close": false,
7930
+ width: _ctx.modalSize,
7931
+ onCloseModal: onCancel
7932
+ }), {
7933
+ content: vue.withCtx(() => [
7934
+ vue.renderSlot(_ctx.$slots, "content-before"),
7935
+ vue.createVNode(_sfc_main$2, {
7936
+ id: `modal-${id}`,
7937
+ ref_key: "formRef",
7938
+ ref: formRef,
7939
+ "form-data": formData.value,
7940
+ schema: _ctx.schema,
7941
+ "ui-schema": _ctx.uiSchema,
7942
+ "error-mode": _ctx.errorMode,
7943
+ onErrors,
7944
+ onChange,
7945
+ onEvents: _cache[0] || (_cache[0] = ($event) => emits("events", $event))
7946
+ }, null, 8, ["id", "form-data", "schema", "ui-schema", "error-mode"]),
7947
+ vue.renderSlot(_ctx.$slots, "content-after")
7948
+ ]),
7949
+ actions: vue.withCtx(() => [
7950
+ vue.createVNode(vue.unref(ui.Btn), {
7951
+ color: vue.unref(ui.Color).secondary,
7952
+ outline: true,
7953
+ "aria-label": "Cancel",
7954
+ onClick: onCancel
7955
+ }, {
7956
+ default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
7957
+ vue.createTextVNode(" Cancel ", -1)
7958
+ ])]),
7959
+ _: 1
7960
+ }, 8, ["color"]),
7961
+ vue.createVNode(vue.unref(ui.Btn), {
7962
+ disabled: !valid.value,
7963
+ "aria-label": "Save",
7964
+ onClick: onSubmit
7965
+ }, {
7966
+ default: vue.withCtx(() => [..._cache[2] || (_cache[2] = [
7967
+ vue.createTextVNode(" Save ", -1)
7968
+ ])]),
7969
+ _: 1
7970
+ }, 8, ["disabled"])
7971
+ ]),
7972
+ _: 3
7973
+ }, 16, ["width"]);
7974
+ };
8001
7975
  }
8002
- if (schema.default !== void 0) {
8003
- zodSchema = zodSchema.default(schema.default);
7976
+ });
7977
+ class JsonFormModalService {
7978
+ static openModal({
7979
+ initialData,
7980
+ modalTitle,
7981
+ schema,
7982
+ uiSchema,
7983
+ modalSize,
7984
+ onClose,
7985
+ onEvents
7986
+ }) {
7987
+ ui.ModalService.openModal({
7988
+ component: _sfc_main$d,
7989
+ props: {
7990
+ schema,
7991
+ uiSchema,
7992
+ modalSize,
7993
+ data: initialData ?? {},
7994
+ modalTitle,
7995
+ onClose,
7996
+ onEvents
7997
+ }
7998
+ });
8004
7999
  }
8005
- return zodSchema;
8006
8000
  }
8007
- function convertSchema(schema, ctx) {
8008
- if (typeof schema === "boolean") {
8009
- return schema ? z.any() : z.never();
8001
+ const _sfc_main$c = /* @__PURE__ */ vue.defineComponent({
8002
+ __name: "AutocompleteControlRenderer",
8003
+ props: {
8004
+ uischema: {},
8005
+ schema: {}
8006
+ },
8007
+ setup(__props) {
8008
+ const props = __props;
8009
+ const {
8010
+ wrapper,
8011
+ value,
8012
+ field,
8013
+ onBlur,
8014
+ onChange: onFieldChange,
8015
+ appliedOptions
8016
+ } = useAutocompleteBinding(props.uischema, props.schema);
8017
+ const fetchOptions = core.computedAsync(async () => {
8018
+ const config2 = await useFetchOptions(
8019
+ appliedOptions.value
8020
+ );
8021
+ return config2;
8022
+ });
8023
+ const onChange = (val) => {
8024
+ field.setValue(val);
8025
+ onFieldChange();
8026
+ };
8027
+ const formEvents = useFormEvents();
8028
+ const path = scopeToPath(props.uischema.scope);
8029
+ const onCreate = () => {
8030
+ if (fetchOptions.value?.enableCreate === false) return;
8031
+ const form = fetchOptions.value.form;
8032
+ if (form) {
8033
+ JsonFormModalService.openModal({
8034
+ schema: form.json_schema,
8035
+ uiSchema: form.ui_schema,
8036
+ modalTitle: `Create new ${wrapper.value.label}`,
8037
+ onClose: (result) => {
8038
+ if (!result || !result.valid) return;
8039
+ form.create(result.data).then((res) => {
8040
+ field.setValue(res);
8041
+ });
8042
+ }
8043
+ });
8044
+ return;
8045
+ }
8046
+ formEvents.dispatch({
8047
+ event: "create",
8048
+ type: path,
8049
+ data: value.value,
8050
+ onSuccess: (result) => {
8051
+ field.setValue(result);
8052
+ }
8053
+ });
8054
+ };
8055
+ return (_ctx, _cache) => {
8056
+ return vue.unref(fetchOptions) ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Autocomplete), vue.mergeProps({ key: 0 }, vue.unref(wrapper), {
8057
+ "model-value": vue.unref(value),
8058
+ "fetch-options": vue.unref(fetchOptions).fetchOptions,
8059
+ "label-key": vue.unref(fetchOptions).labelKey,
8060
+ "value-key": vue.unref(fetchOptions).valueKey,
8061
+ "enable-create": vue.unref(fetchOptions).enableCreate,
8062
+ onChange,
8063
+ onBlur: vue.unref(onBlur),
8064
+ onCreate
8065
+ }), null, 16, ["model-value", "fetch-options", "label-key", "value-key", "enable-create", "onBlur"])) : vue.createCommentVNode("", true);
8066
+ };
8010
8067
  }
8011
- let baseSchema = convertBaseSchema(schema, ctx);
8012
- const hasExplicitType = schema.type || schema.enum !== void 0 || schema.const !== void 0;
8013
- if (schema.anyOf && Array.isArray(schema.anyOf)) {
8014
- const options = schema.anyOf.map((s) => convertSchema(s, ctx));
8015
- const anyOfUnion = z.union(options);
8016
- baseSchema = hasExplicitType ? z.intersection(baseSchema, anyOfUnion) : anyOfUnion;
8068
+ });
8069
+ const _sfc_main$b = /* @__PURE__ */ vue.defineComponent({
8070
+ __name: "BooleanControlRenderer",
8071
+ props: {
8072
+ uischema: {},
8073
+ schema: {}
8074
+ },
8075
+ setup(__props) {
8076
+ const props = __props;
8077
+ const useBooleanBinding = useCustomControlBinding({
8078
+ setDefaultValue: (field2) => {
8079
+ if (field2.value.value === void 0) field2.setValue(false);
8080
+ }
8081
+ });
8082
+ const { wrapper, value, field, onBlur, onChange: onFieldChange } = useBooleanBinding(props.uischema, props.schema);
8083
+ const onChange = (val) => {
8084
+ field.setValue(Boolean(val) ?? false);
8085
+ onFieldChange();
8086
+ };
8087
+ return (_ctx, _cache) => {
8088
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Checkbox), vue.mergeProps(vue.unref(wrapper), {
8089
+ "model-value": vue.unref(value),
8090
+ onChange,
8091
+ onBlur: vue.unref(onBlur)
8092
+ }), null, 16, ["model-value", "onBlur"]);
8093
+ };
8094
+ }
8095
+ });
8096
+ const _sfc_main$a = /* @__PURE__ */ vue.defineComponent({
8097
+ __name: "MarkdownControlRenderer",
8098
+ props: {
8099
+ uischema: {},
8100
+ schema: {}
8101
+ },
8102
+ setup(__props) {
8103
+ const props = __props;
8104
+ const {
8105
+ wrapper,
8106
+ value,
8107
+ field,
8108
+ onBlur,
8109
+ onChange: onFieldChange
8110
+ } = useControlBinding(props.uischema, props.schema);
8111
+ const onChange = (val) => {
8112
+ field.setValue(val);
8113
+ onFieldChange();
8114
+ };
8115
+ return (_ctx, _cache) => {
8116
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Markdown), vue.mergeProps(vue.unref(wrapper), {
8117
+ "model-value": vue.unref(value),
8118
+ onChange,
8119
+ onBlur: vue.unref(onBlur)
8120
+ }), null, 16, ["model-value", "onBlur"]);
8121
+ };
8017
8122
  }
8018
- if (schema.oneOf && Array.isArray(schema.oneOf)) {
8019
- const options = schema.oneOf.map((s) => convertSchema(s, ctx));
8020
- const oneOfUnion = z.xor(options);
8021
- baseSchema = hasExplicitType ? z.intersection(baseSchema, oneOfUnion) : oneOfUnion;
8123
+ });
8124
+ const _sfc_main$9 = /* @__PURE__ */ vue.defineComponent({
8125
+ __name: "MultiSelectControlRenderer",
8126
+ props: {
8127
+ uischema: {},
8128
+ schema: {}
8129
+ },
8130
+ setup(__props) {
8131
+ const props = __props;
8132
+ const {
8133
+ wrapper,
8134
+ value,
8135
+ field,
8136
+ onBlur,
8137
+ onChange: onFieldChange
8138
+ } = useSelectBinding(props.uischema, props.schema);
8139
+ const onChange = (val) => {
8140
+ field.setValue(val);
8141
+ onFieldChange();
8142
+ };
8143
+ return (_ctx, _cache) => {
8144
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.MultiSelect), vue.mergeProps(vue.unref(wrapper), {
8145
+ "model-value": vue.unref(value),
8146
+ onChange,
8147
+ onBlur: vue.unref(onBlur)
8148
+ }), null, 16, ["model-value", "onBlur"]);
8149
+ };
8022
8150
  }
8023
- if (schema.allOf && Array.isArray(schema.allOf)) {
8024
- if (schema.allOf.length === 0) {
8025
- baseSchema = hasExplicitType ? baseSchema : z.any();
8026
- } else {
8027
- let result = hasExplicitType ? baseSchema : convertSchema(schema.allOf[0], ctx);
8028
- const startIdx = hasExplicitType ? 0 : 1;
8029
- for (let i = startIdx; i < schema.allOf.length; i++) {
8030
- result = z.intersection(result, convertSchema(schema.allOf[i], ctx));
8031
- }
8032
- baseSchema = result;
8033
- }
8151
+ });
8152
+ const _sfc_main$8 = /* @__PURE__ */ vue.defineComponent({
8153
+ __name: "NumberControlRenderer",
8154
+ props: {
8155
+ uischema: {},
8156
+ schema: {}
8157
+ },
8158
+ setup(__props) {
8159
+ const props = __props;
8160
+ const { wrapper, value, onBlur, onChange } = useControlBinding(
8161
+ props.uischema,
8162
+ props.schema,
8163
+ { defaultType: "number" }
8164
+ );
8165
+ return (_ctx, _cache) => {
8166
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.InputNumber), vue.mergeProps(vue.unref(wrapper), {
8167
+ modelValue: vue.unref(value),
8168
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
8169
+ steps: 0.01,
8170
+ onBlur: vue.unref(onBlur),
8171
+ onChange: vue.unref(onChange)
8172
+ }), null, 16, ["modelValue", "onBlur", "onChange"]);
8173
+ };
8034
8174
  }
8035
- if (schema.nullable === true && ctx.version === "openapi-3.0") {
8036
- baseSchema = z.nullable(baseSchema);
8175
+ });
8176
+ const _sfc_main$7 = /* @__PURE__ */ vue.defineComponent({
8177
+ __name: "SelectControlRenderer",
8178
+ props: {
8179
+ uischema: {},
8180
+ schema: {}
8181
+ },
8182
+ setup(__props) {
8183
+ const props = __props;
8184
+ const {
8185
+ wrapper,
8186
+ value,
8187
+ field,
8188
+ onBlur,
8189
+ onChange: onFieldChange,
8190
+ appliedOptions
8191
+ } = useSelectBinding(props.uischema, props.schema);
8192
+ const selectOptions = vue.computed(() => {
8193
+ return appliedOptions.options ?? [];
8194
+ });
8195
+ const onChange = (val) => {
8196
+ field.setValue(val);
8197
+ onFieldChange();
8198
+ };
8199
+ return (_ctx, _cache) => {
8200
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.SelectComponent), vue.mergeProps(vue.unref(wrapper), {
8201
+ "model-value": vue.unref(value),
8202
+ options: selectOptions.value,
8203
+ onChange,
8204
+ onBlur: vue.unref(onBlur)
8205
+ }), null, 16, ["model-value", "options", "onBlur"]);
8206
+ };
8037
8207
  }
8038
- if (schema.readOnly === true) {
8039
- baseSchema = z.readonly(baseSchema);
8208
+ });
8209
+ const _sfc_main$6 = /* @__PURE__ */ vue.defineComponent({
8210
+ __name: "StringControlRenderer",
8211
+ props: {
8212
+ uischema: {},
8213
+ schema: {}
8214
+ },
8215
+ setup(__props) {
8216
+ const props = __props;
8217
+ const { wrapper, value, onBlur, onChange } = useControlBinding(
8218
+ props.uischema,
8219
+ props.schema
8220
+ );
8221
+ return (_ctx, _cache) => {
8222
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Input), vue.mergeProps(vue.unref(wrapper), {
8223
+ modelValue: vue.unref(value),
8224
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
8225
+ onBlur: vue.unref(onBlur),
8226
+ onChange: vue.unref(onChange)
8227
+ }), null, 16, ["modelValue", "onBlur", "onChange"]);
8228
+ };
8040
8229
  }
8041
- const extraMeta = {};
8042
- const coreMetadataKeys = ["$id", "id", "$comment", "$anchor", "$vocabulary", "$dynamicRef", "$dynamicAnchor"];
8043
- for (const key of coreMetadataKeys) {
8044
- if (key in schema) {
8045
- extraMeta[key] = schema[key];
8046
- }
8230
+ });
8231
+ const _sfc_main$5 = /* @__PURE__ */ vue.defineComponent({
8232
+ __name: "TextAreaControlRenderer",
8233
+ props: {
8234
+ uischema: {},
8235
+ schema: {}
8236
+ },
8237
+ setup(__props) {
8238
+ const props = __props;
8239
+ const { wrapper, value, onBlur, onChange } = useControlBinding(
8240
+ props.uischema,
8241
+ props.schema
8242
+ );
8243
+ return (_ctx, _cache) => {
8244
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Textarea), vue.mergeProps(vue.unref(wrapper), {
8245
+ modelValue: vue.unref(value),
8246
+ "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => vue.isRef(value) ? value.value = $event : null),
8247
+ onBlur: vue.unref(onBlur),
8248
+ onChange: vue.unref(onChange)
8249
+ }), null, 16, ["modelValue", "onBlur", "onChange"]);
8250
+ };
8047
8251
  }
8048
- const contentMetadataKeys = ["contentEncoding", "contentMediaType", "contentSchema"];
8049
- for (const key of contentMetadataKeys) {
8050
- if (key in schema) {
8051
- extraMeta[key] = schema[key];
8052
- }
8252
+ });
8253
+ const index = [
8254
+ { tester: core$1.rankWith(10, isStringFormat), renderer: _sfc_main$6 },
8255
+ {
8256
+ tester: core$1.rankWith(11, isTextAreaControl),
8257
+ renderer: _sfc_main$5
8258
+ },
8259
+ {
8260
+ tester: core$1.rankWith(11, isMarkdownControl),
8261
+ renderer: _sfc_main$a
8262
+ },
8263
+ { tester: core$1.rankWith(11, isBooleanControl), renderer: _sfc_main$b },
8264
+ { tester: core$1.rankWith(11, isSelectControl), renderer: _sfc_main$7 },
8265
+ {
8266
+ tester: core$1.rankWith(11, isMultiselectControl),
8267
+ renderer: _sfc_main$9
8268
+ },
8269
+ {
8270
+ tester: core$1.rankWith(12, isAutoCompleteControl),
8271
+ renderer: _sfc_main$c
8272
+ },
8273
+ {
8274
+ tester: core$1.rankWith(12, isNumberFormat),
8275
+ renderer: _sfc_main$8
8276
+ },
8277
+ {
8278
+ tester: core$1.rankWith(12, isIntegerFormat),
8279
+ renderer: _sfc_main$8
8053
8280
  }
8054
- for (const key of Object.keys(schema)) {
8055
- if (!RECOGNIZED_KEYS.has(key)) {
8056
- extraMeta[key] = schema[key];
8057
- }
8281
+ ];
8282
+ const COLSPAN = {
8283
+ 1: "col-span-1",
8284
+ 2: "col-span-2",
8285
+ 3: "col-span-3",
8286
+ 4: "col-span-4",
8287
+ 5: "col-span-5",
8288
+ 6: "col-span-6",
8289
+ 7: "col-span-7",
8290
+ 8: "col-span-8",
8291
+ 9: "col-span-9",
8292
+ 10: "col-span-10",
8293
+ 11: "col-span-11",
8294
+ 12: "col-span-12"
8295
+ };
8296
+ const _hoisted_1$4 = { class: "flex flex-col gap-4" };
8297
+ const _sfc_main$4 = /* @__PURE__ */ vue.defineComponent({
8298
+ __name: "CollapseLayoutRenderer",
8299
+ props: {
8300
+ uischema: {},
8301
+ schema: {}
8302
+ },
8303
+ setup(__props) {
8304
+ const props = __props;
8305
+ const pathPrefix = vue.inject("pathPrefix", "");
8306
+ const opts = props.uischema.options ?? {};
8307
+ const titleKeyField = opts.titleKey ? veeValidate.useFieldValue(
8308
+ () => pathPrefix ? `${pathPrefix}.${opts.titleKey}` : opts.titleKey
8309
+ ) : void 0;
8310
+ const title = vue.computed(() => {
8311
+ if (titleKeyField?.value) return titleKeyField.value;
8312
+ return props.uischema.label ?? opts.title ?? "Details";
8313
+ });
8314
+ return (_ctx, _cache) => {
8315
+ return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), { title: title.value }, {
8316
+ default: vue.withCtx(() => [
8317
+ vue.createElementVNode("div", _hoisted_1$4, [
8318
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
8319
+ return vue.openBlock(), vue.createElementBlock("div", {
8320
+ key: i,
8321
+ class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
8322
+ }, [
8323
+ vue.createVNode(_sfc_main$f, {
8324
+ uischema: child,
8325
+ schema: __props.schema
8326
+ }, null, 8, ["uischema", "schema"])
8327
+ ], 2);
8328
+ }), 128))
8329
+ ])
8330
+ ]),
8331
+ _: 1
8332
+ }, 8, ["title"]);
8333
+ };
8058
8334
  }
8059
- if (Object.keys(extraMeta).length > 0) {
8060
- ctx.registry.add(baseSchema, extraMeta);
8335
+ });
8336
+ const _hoisted_1$3 = {
8337
+ key: 1,
8338
+ class: "flex flex-col gap-3"
8339
+ };
8340
+ const _sfc_main$3 = /* @__PURE__ */ vue.defineComponent({
8341
+ __name: "LayoutRenderer",
8342
+ props: {
8343
+ uischema: {},
8344
+ schema: {}
8345
+ },
8346
+ setup(__props) {
8347
+ const props = __props;
8348
+ const LAYOUT = {
8349
+ GridLayout: "grid grid-cols-12 gap-3",
8350
+ HorizontalLayout: "flex flex-row gap-3",
8351
+ VerticalLayout: "flex flex-col gap-3"
8352
+ };
8353
+ const getLayout = vue.computed(() => LAYOUT[props.uischema.type]);
8354
+ const isLayout = vue.computed(() => props.uischema.type in LAYOUT);
8355
+ return (_ctx, _cache) => {
8356
+ return isLayout.value ? (vue.openBlock(), vue.createElementBlock("div", {
8357
+ key: 0,
8358
+ class: vue.normalizeClass(getLayout.value)
8359
+ }, [
8360
+ (vue.openBlock(true), vue.createElementBlock(vue.Fragment, null, vue.renderList(__props.uischema.elements, (child, i) => {
8361
+ return vue.openBlock(), vue.createElementBlock("div", {
8362
+ key: i,
8363
+ class: vue.normalizeClass(vue.unref(COLSPAN)[child.options?.colspan ?? 12])
8364
+ }, [
8365
+ vue.createVNode(_sfc_main$f, {
8366
+ uischema: child,
8367
+ schema: __props.schema
8368
+ }, null, 8, ["uischema", "schema"])
8369
+ ], 2);
8370
+ }), 128))
8371
+ ], 2)) : (vue.openBlock(), vue.createElementBlock("div", _hoisted_1$3, " No Applicable Layout found "));
8372
+ };
8061
8373
  }
8062
- return baseSchema;
8063
- }
8064
- function fromJSONSchema(schema, params) {
8065
- if (typeof schema === "boolean") {
8066
- return schema ? z.any() : z.never();
8374
+ });
8375
+ const isLayoutType = core$1.or(
8376
+ core$1.uiTypeIs("GridLayout"),
8377
+ core$1.uiTypeIs("HorizontalLayout"),
8378
+ core$1.uiTypeIs("VerticalLayout")
8379
+ );
8380
+ const layoutRenderes = [
8381
+ { tester: core$1.rankWith(10, isLayoutType), renderer: _sfc_main$3 },
8382
+ {
8383
+ tester: core$1.rankWith(10, core$1.uiTypeIs("CollapseLayout")),
8384
+ renderer: _sfc_main$4
8067
8385
  }
8068
- const version2 = detectVersion(schema);
8069
- const defs = schema.$defs || schema.definitions || {};
8070
- const ctx = {
8071
- version: version2,
8072
- defs,
8073
- refs: /* @__PURE__ */ new Map(),
8074
- processing: /* @__PURE__ */ new Set(),
8075
- rootSchema: schema,
8076
- registry: globalRegistry
8077
- };
8078
- return convertSchema(schema, ctx);
8079
- }
8080
- config(en());
8081
- const customRenderers = [
8082
- controlRenderers,
8083
- layoutRenderers,
8084
- // ...complexRenderers,
8085
- arrayRenderers
8086
- // ...labelRenderers,
8087
- ].flat();
8088
- const tailwindRenderers = [
8089
- ...vueVanilla.vanillaRenderers,
8090
- ...customRenderers
8091
8386
  ];
8092
- const _hoisted_1$1 = ["id", "aria-label"];
8387
+ const customRenderes = [layoutRenderes, index, arrayRenderers].flat();
8388
+ const _hoisted_1$2 = ["id"];
8093
8389
  const _sfc_main$2 = /* @__PURE__ */ vue.defineComponent({
8094
- __name: "form.component",
8095
- props: FormComponentProperties,
8096
- emits: FormComponentEmits,
8097
- setup(__props, { emit: __emit }) {
8390
+ __name: "FormComponent",
8391
+ props: JsonFormComponentProperties,
8392
+ emits: JsonFormComponentEmits,
8393
+ setup(__props, { expose: __expose, emit: __emit }) {
8394
+ registerZodErrorMap();
8098
8395
  const properties = __props;
8099
8396
  const emits = __emit;
8100
- const valid = vue.ref(false);
8101
- const zodSchema = vue.computed(() => fromJSONSchema(properties.schema));
8102
- const stripFormData = (data) => {
8103
- const safeParse2 = zodSchema.value?.strip().safeParse(data);
8104
- return safeParse2?.success ? safeParse2.data : data ?? {};
8105
- };
8106
- const internalFormData = vue.ref(properties.formData ?? {});
8397
+ const zodSchema = vue.computed(() => {
8398
+ if (!properties.schema) return void 0;
8399
+ try {
8400
+ const patched = jsonFormsCore.enforceRequiredStringMinLength(properties.schema);
8401
+ return fromJSONSchema(patched);
8402
+ } catch {
8403
+ return void 0;
8404
+ }
8405
+ });
8406
+ const { values, errors, meta: meta2, setValues, validate } = veeValidate.useForm({
8407
+ validationSchema: zodSchema,
8408
+ initialValues: properties.formData
8409
+ });
8410
+ vue.provide("renderers", customRenderes);
8411
+ vue.provide("rootSchema", properties.schema);
8412
+ vue.provide("styles", ui.myStyles);
8413
+ const submitted = vue.ref(false);
8414
+ vue.provide(ERROR_MODE_KEY, vue.toRef(properties, "errorMode"));
8415
+ vue.provide(FORM_SUBMITTED_KEY, submitted);
8416
+ vue.onMounted(async () => {
8417
+ const result = await validate();
8418
+ emits("valid", result.valid);
8419
+ });
8420
+ provideFormEvents((payload) => {
8421
+ emits("events", payload);
8422
+ });
8423
+ let syncing = false;
8107
8424
  vue.watch(
8108
8425
  () => properties.formData,
8109
- (data, oldData) => {
8110
- if (JSON.stringify(data) === JSON.stringify(internalFormData.value)) return;
8111
- internalFormData.value = stripFormData(data);
8112
- emits("change", internalFormData.value);
8426
+ (newData) => {
8427
+ if (!newData) return;
8428
+ if (JSON.stringify(newData) === JSON.stringify(vue.toRaw(values))) return;
8429
+ syncing = true;
8430
+ setValues(newData);
8431
+ vue.nextTick(() => {
8432
+ syncing = false;
8433
+ });
8113
8434
  },
8114
- { deep: true, immediate: true }
8435
+ { deep: true }
8115
8436
  );
8116
- provideFormEvents((payload) => {
8117
- emits("events", payload);
8118
- });
8119
- const onChange = (event) => {
8120
- internalFormData.value = event.data;
8121
- valid.value = event.errors.length === 0;
8122
- emits("valid", valid.value);
8123
- emits("change", internalFormData.value);
8124
- emits("errors", event.errors);
8125
- toolsVue.Debugger.debug(event.errors);
8126
- };
8127
- const onSubmit = (event) => {
8128
- event.preventDefault();
8437
+ vue.watch(
8438
+ values,
8439
+ (newValues) => {
8440
+ if (syncing) return;
8441
+ const isValid = meta2.value.valid;
8442
+ emits("valid", isValid);
8443
+ emits("change", vue.toRaw(newValues));
8444
+ },
8445
+ { deep: true }
8446
+ );
8447
+ vue.watch(
8448
+ errors,
8449
+ (newErrors) => {
8450
+ const errorList = Object.entries(newErrors).filter(([, msg]) => !!msg).map(([path, message]) => ({ path, message }));
8451
+ emits("errors", errorList);
8452
+ },
8453
+ { deep: true }
8454
+ );
8455
+ const onSubmit = () => {
8456
+ submitted.value = true;
8129
8457
  emits("submit", {
8130
- data: internalFormData.value,
8131
- valid: valid.value
8458
+ data: vue.toRaw(values),
8459
+ valid: meta2.value.valid
8132
8460
  });
8133
8461
  };
8134
- vue.provide("styles", ui.myStyles);
8135
- const renderers = Object.freeze([
8136
- ...properties.renderers ?? [],
8137
- ...tailwindRenderers
8138
- ]);
8462
+ const markSubmitted = () => {
8463
+ submitted.value = true;
8464
+ };
8465
+ __expose({ markSubmitted });
8139
8466
  return (_ctx, _cache) => {
8140
8467
  return vue.openBlock(), vue.createElementBlock("form", {
8141
8468
  id: _ctx.id,
8142
- "aria-label": _ctx.name,
8143
8469
  onSubmit: vue.withModifiers(onSubmit, ["prevent"])
8144
8470
  }, [
8145
- (vue.openBlock(), vue.createBlock(vue.unref(vue$1.JsonForms), {
8146
- key: _ctx.id,
8147
- data: internalFormData.value,
8148
- schema: _ctx.schema,
8471
+ vue.createVNode(_sfc_main$f, {
8149
8472
  uischema: _ctx.uiSchema,
8150
- renderers: vue.unref(renderers),
8151
- enabled: !_ctx.disabled,
8152
- onChange,
8153
- onSubmit
8154
- }, null, 8, ["data", "schema", "uischema", "renderers", "enabled"]))
8155
- ], 40, _hoisted_1$1);
8473
+ schema: _ctx.schema
8474
+ }, null, 8, ["uischema", "schema"])
8475
+ ], 40, _hoisted_1$2);
8156
8476
  };
8157
8477
  }
8158
8478
  });
8159
- const _hoisted_1 = { class: "flex justify-end gap-2 p-2 mt-2 border-t border-gray-300 z-[30] shrink-0" };
8479
+ const FormWithActionsProperties = {
8480
+ /** Unique identifier used to namespace the inner form element. */
8481
+ id: { type: String, required: true },
8482
+ /** Title shown when creating a new record. */
8483
+ createTitle: { type: String, required: true },
8484
+ /** Title shown when editing an existing record. Falls back to `createTitle` when omitted. */
8485
+ updateTitle: { type: String },
8486
+ /** JSON schema describing the shape of the form data. */
8487
+ schema: { type: Object },
8488
+ /** UI schema describing the layout and controls. */
8489
+ uiSchema: { type: Object },
8490
+ /** REST endpoint used by `FormStore` to persist data. When omitted the form emits `submit` instead. */
8491
+ uri: { type: String },
8492
+ /** Enable vertical scrolling inside the form area. */
8493
+ scrollable: { type: Boolean, default: false },
8494
+ /** Stretch the collapse wrapper to full height. */
8495
+ fullHeight: { type: Boolean, default: false },
8496
+ /** Two-way bound form data object. */
8497
+ modelValue: { type: Object, default: () => ({}) },
8498
+ /** When validation errors are shown (`'onBlur'`, `'onChange'`, `'onSubmit'`, `'always'`). */
8499
+ errorMode: {
8500
+ type: String,
8501
+ default: "onBlur"
8502
+ }
8503
+ };
8504
+ const FormWithActionsEmits = [
8505
+ /** Emitted when `modelValue` changes. */
8506
+ "update:modelValue",
8507
+ /** Emitted after a successful `FormStore.save()`. */
8508
+ "success",
8509
+ /** Emitted on submit when no `uri` is provided. */
8510
+ "submit",
8511
+ /** Emitted whenever form validity changes. */
8512
+ "valid",
8513
+ /** Emitted when a custom renderer dispatches a form event. */
8514
+ "events",
8515
+ /** Emitted when validation errors change. */
8516
+ "errors",
8517
+ /** Emitted when the user cancels editing an existing record. */
8518
+ "cancel"
8519
+ ];
8520
+ class FormStore {
8521
+ constructor(uri) {
8522
+ this.uri = uri;
8523
+ }
8524
+ async delete(data) {
8525
+ return toolsVue.useApi().delete(`${this.uri}/${data.id}`).then(() => {
8526
+ ui.NotificationService.success("Data deleted");
8527
+ }).catch((error2) => {
8528
+ console.error(error2);
8529
+ ui.NotificationService.error("Error deleting data");
8530
+ });
8531
+ }
8532
+ async save(id, data) {
8533
+ if (!this.uri) return;
8534
+ const promise2 = id ? toolsVue.useApi().patch(`${this.uri}/${id}`, data) : toolsVue.useApi().post(this.uri, data);
8535
+ return promise2.then((response) => {
8536
+ ui.NotificationService.success("Data saved");
8537
+ return response.data;
8538
+ }).catch((error2) => {
8539
+ console.error(error2);
8540
+ ui.NotificationService.error("Error saving data");
8541
+ });
8542
+ }
8543
+ }
8544
+ const _hoisted_1$1 = { class: "flex justify-end gap-2 p-2 mt-2 border-t border-gray-300 z-[30] shrink-0" };
8160
8545
  const _hoisted_2 = { class: "flex justify-end gap-2" };
8161
8546
  const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8162
- __name: "form-with-actions.component",
8163
- props: {
8164
- ...FormWithActionsProperties,
8165
- modelValue: { type: Object, default: () => ({}) }
8166
- },
8547
+ __name: "FormWithActions",
8548
+ props: FormWithActionsProperties,
8167
8549
  emits: FormWithActionsEmits,
8168
8550
  setup(__props, { emit: __emit }) {
8169
8551
  const properties = __props;
8170
8552
  const emits = __emit;
8553
+ const formRef = vue.ref();
8171
8554
  const formData = vue.ref(properties.modelValue);
8172
8555
  const initialFormData = vue.ref(structuredClone(vue.toRaw(properties.modelValue)));
8173
8556
  const recordId = vue.ref(properties.modelValue?.id ?? null);
8174
8557
  const valid = vue.ref(false);
8175
- const submitted = vue.ref(false);
8176
8558
  vue.watch(
8177
8559
  () => properties.modelValue,
8178
- (newValue, oldValue) => {
8560
+ (newValue) => {
8179
8561
  if (newValue === formData.value) return;
8180
8562
  recordId.value = newValue?.id ?? null;
8181
8563
  initialFormData.value = structuredClone(vue.toRaw(newValue));
@@ -8190,13 +8572,11 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8190
8572
  emits("update:modelValue", data);
8191
8573
  };
8192
8574
  const save = () => {
8193
- submitted.value = true;
8194
- if (!valid.value) {
8195
- return;
8196
- }
8575
+ formRef.value?.markSubmitted();
8576
+ if (!valid.value) return;
8197
8577
  if (store.value) {
8198
- store.value.save(recordId.value, formData.value).then(() => {
8199
- emits("success");
8578
+ store.value.save(recordId.value, formData.value).then((response) => {
8579
+ emits("success", response);
8200
8580
  });
8201
8581
  } else {
8202
8582
  emits("submit", formData.value);
@@ -8204,28 +8584,31 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8204
8584
  };
8205
8585
  const clear = () => {
8206
8586
  formData.value = { id: null };
8207
- submitted.value = false;
8208
8587
  emits("update:modelValue", formData.value);
8209
8588
  };
8210
8589
  const cancel = () => {
8211
8590
  formData.value = structuredClone(vue.toRaw(initialFormData.value));
8212
- submitted.value = false;
8213
8591
  emits("update:modelValue", formData.value);
8214
8592
  emits("cancel");
8215
8593
  };
8216
- const onValid = (v) => {
8217
- submitted.value = false;
8218
- valid.value = v;
8219
- emits("valid", v);
8220
- };
8221
8594
  const title = vue.computed(() => {
8222
8595
  if (!properties.updateTitle) return properties.createTitle;
8223
8596
  return recordId.value ? properties.updateTitle : properties.createTitle;
8224
8597
  });
8598
+ const onErrors = (errors) => {
8599
+ emits("errors", errors);
8600
+ valid.value = lodashEs.isEmpty(errors);
8601
+ };
8602
+ vue.watch(valid, (newValid, oldValid) => {
8603
+ if (newValid !== oldValid) {
8604
+ emits("valid", newValid);
8605
+ }
8606
+ });
8225
8607
  return (_ctx, _cache) => {
8226
8608
  return vue.openBlock(), vue.createBlock(vue.unref(ui.Collapse), {
8227
8609
  title: title.value,
8228
- "height-full": _ctx.fullHeight
8610
+ "height-full": _ctx.fullHeight,
8611
+ scrollable: true
8229
8612
  }, {
8230
8613
  default: vue.withCtx(() => [
8231
8614
  vue.createElementVNode("div", {
@@ -8236,24 +8619,19 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8236
8619
  }, [
8237
8620
  vue.createVNode(_sfc_main$2, {
8238
8621
  id: `form_${_ctx.id}`,
8622
+ ref_key: "formRef",
8623
+ ref: formRef,
8239
8624
  "form-data": formData.value,
8240
8625
  schema: _ctx.schema,
8241
8626
  "ui-schema": _ctx.uiSchema,
8627
+ "error-mode": _ctx.errorMode,
8242
8628
  onChange: updateValue,
8243
- onValid: _cache[0] || (_cache[0] = ($event) => onValid($event)),
8244
8629
  onSubmit: save,
8245
- onErrors: _cache[1] || (_cache[1] = ($event) => emits("errors", $event)),
8246
- onEvents: _cache[2] || (_cache[2] = ($event) => emits("events", $event))
8247
- }, null, 8, ["id", "form-data", "schema", "ui-schema"])
8630
+ onErrors,
8631
+ onEvents: _cache[0] || (_cache[0] = ($event) => emits("events", $event))
8632
+ }, null, 8, ["id", "form-data", "schema", "ui-schema", "error-mode"])
8248
8633
  ], 2),
8249
- vue.createElementVNode("div", _hoisted_1, [
8250
- vue.createElementVNode("div", null, [
8251
- !valid.value && submitted.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Alert), {
8252
- key: 0,
8253
- message: "The form is not valid",
8254
- type: "error"
8255
- })) : vue.createCommentVNode("", true)
8256
- ]),
8634
+ vue.createElementVNode("div", _hoisted_1$1, [
8257
8635
  vue.createElementVNode("div", _hoisted_2, [
8258
8636
  vue.renderSlot(_ctx.$slots, "actions"),
8259
8637
  recordId.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Btn), {
@@ -8262,7 +8640,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8262
8640
  outline: true,
8263
8641
  onClick: cancel
8264
8642
  }, {
8265
- default: vue.withCtx(() => [..._cache[3] || (_cache[3] = [
8643
+ default: vue.withCtx(() => [..._cache[1] || (_cache[1] = [
8266
8644
  vue.createTextVNode(" Cancel ", -1)
8267
8645
  ])]),
8268
8646
  _: 1
@@ -8272,7 +8650,7 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8272
8650
  outline: true,
8273
8651
  onClick: clear
8274
8652
  }, {
8275
- default: vue.withCtx(() => [..._cache[4] || (_cache[4] = [
8653
+ default: vue.withCtx(() => [..._cache[2] || (_cache[2] = [
8276
8654
  vue.createTextVNode(" Clear ", -1)
8277
8655
  ])]),
8278
8656
  _: 1
@@ -8280,10 +8658,10 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8280
8658
  vue.createVNode(vue.unref(ui.Btn), {
8281
8659
  "aria-label": "Save",
8282
8660
  color: vue.unref(ui.Color).primary,
8283
- disabled: submitted.value,
8661
+ disabled: !valid.value,
8284
8662
  onClick: save
8285
8663
  }, {
8286
- default: vue.withCtx(() => [..._cache[5] || (_cache[5] = [
8664
+ default: vue.withCtx(() => [..._cache[3] || (_cache[3] = [
8287
8665
  vue.createTextVNode(" Save ", -1)
8288
8666
  ])]),
8289
8667
  _: 1
@@ -8297,214 +8675,173 @@ const _sfc_main$1 = /* @__PURE__ */ vue.defineComponent({
8297
8675
  };
8298
8676
  }
8299
8677
  });
8678
+ const FormWithTableProperties = {
8679
+ /** Unique identifier used to namespace the inner table element. */
8680
+ id: { type: String, required: true },
8681
+ /** Heading displayed above the table. */
8682
+ tableTitle: { type: String, required: true },
8683
+ /** Title shown in the modal when creating a new record. */
8684
+ createTitle: { type: String, required: true },
8685
+ /** Title shown in the modal when editing a record. Falls back to `createTitle` when omitted. */
8686
+ updateTitle: { type: String },
8687
+ /** Override URI used to fetch table data. Defaults to `uri` when omitted. */
8688
+ dataUri: { type: String },
8689
+ /** Custom row actions rendered in the table. */
8690
+ tableActions: { type: Array },
8691
+ /** JSON Forms layout for the create/edit modal form. */
8692
+ form: { type: Object },
8693
+ /** JSON Forms layout for the table. */
8694
+ table: { type: Object },
8695
+ /** JSON Forms layout for the table filter. */
8696
+ filter: { type: Object },
8697
+ /** REST endpoint used by `FormStore` for CRUD operations. */
8698
+ uri: { type: String },
8699
+ /** Default data pre-filled when creating a new record. */
8700
+ initialData: { type: Object, default: () => ({}) },
8701
+ /** When validation errors are shown in the modal form. */
8702
+ errorMode: {
8703
+ type: String,
8704
+ default: "onBlur"
8705
+ }
8706
+ };
8707
+ const FormWithTableEmits = [
8708
+ /** Emitted when a row is selected for editing (listener-based routing). */
8709
+ "editData",
8710
+ /** Emitted after a record is saved through the modal. */
8711
+ "save",
8712
+ /** Emitted after a record is deleted. */
8713
+ "delete",
8714
+ /** Emitted when a custom renderer dispatches a form event. */
8715
+ "events",
8716
+ /** Emitted when a custom edit handler is registered. */
8717
+ "custom:edit",
8718
+ /** Emitted when a custom create handler is registered. */
8719
+ "custom:create"
8720
+ ];
8721
+ const _hoisted_1 = { class: "flex justify-between items-center mb-2" };
8300
8722
  const _sfc_main = /* @__PURE__ */ vue.defineComponent({
8301
- __name: "form-modal",
8302
- props: /* @__PURE__ */ vue.mergeModels({
8303
- modalTitle: {},
8304
- saveLabel: { default: "save" },
8305
- cancelLabel: { default: "cancel" },
8306
- schema: {},
8307
- uiSchema: {},
8308
- modalSize: { default: "md" },
8309
- onClose: {},
8310
- onEvents: {},
8311
- data: {}
8312
- }, {
8313
- "modelValue": {},
8314
- "modelModifiers": {}
8315
- }),
8316
- emits: /* @__PURE__ */ vue.mergeModels(["closeModal", "events"], ["update:modelValue"]),
8723
+ __name: "FormWithTable",
8724
+ props: FormWithTableProperties,
8725
+ emits: FormWithTableEmits,
8317
8726
  setup(__props, { emit: __emit }) {
8318
8727
  const properties = __props;
8319
- const id = `modal_${Math.floor(Math.random() * 1e3)}`;
8320
- const valid = vue.ref(false);
8321
- const hasBeenValid = vue.ref(false);
8322
- const formData = vue.useModel(__props, "modelValue");
8323
- const emits = __emit;
8324
- if (properties.data) {
8325
- formData.value = properties.data;
8326
- }
8327
- const onValid = (v) => {
8328
- valid.value = v;
8329
- if (v) hasBeenValid.value = true;
8728
+ const emit = __emit;
8729
+ const reload = vue.ref(0);
8730
+ const resolvedForm = vue.computed(() => properties.form);
8731
+ const resolvedTable = vue.computed(() => properties.table);
8732
+ const resolvedFilter = vue.computed(() => properties.filter);
8733
+ const resolvedUri = vue.computed(() => properties.uri);
8734
+ let store = new FormStore(resolvedUri.value ?? "");
8735
+ vue.watch(resolvedUri, (uri) => {
8736
+ store = new FormStore(uri ?? "");
8737
+ });
8738
+ const hasEdit = ui.hasCustomEventListener("editData");
8739
+ const customEdit = ui.hasCustomEventListener("custom:edit");
8740
+ const customCreate = ui.hasCustomEventListener("custom:create");
8741
+ const edit = (data) => {
8742
+ if (customEdit) {
8743
+ emit("custom:edit", data);
8744
+ return;
8745
+ }
8746
+ if (hasEdit) {
8747
+ emit("editData", data);
8748
+ return;
8749
+ }
8750
+ openModal(data);
8330
8751
  };
8331
- const onCancel = () => {
8332
- formData.value = {};
8333
- emits("closeModal", null);
8752
+ const create = () => {
8753
+ if (customCreate) {
8754
+ emit("custom:create");
8755
+ return;
8756
+ }
8757
+ openModal();
8334
8758
  };
8335
- const onChange = (data) => {
8336
- formData.value = data;
8759
+ const deleteFn = (data) => {
8760
+ ui.ModalService.showConfirm({
8761
+ title: "Delete record",
8762
+ message: "Are you sure to delete, the data will be lost?",
8763
+ onClose: (result) => {
8764
+ if (result.confirmed) {
8765
+ store.delete(data).then(() => {
8766
+ reload.value = Date.now();
8767
+ emit("delete", data);
8768
+ });
8769
+ }
8770
+ }
8771
+ });
8337
8772
  };
8338
- const onSubmit = () => {
8339
- if (!valid.value) return;
8340
- emits("closeModal", { data: formData.value, valid: valid.value });
8773
+ const openModal = (formData) => {
8774
+ if (!resolvedForm.value) return;
8775
+ const isUpdate = !!formData?.id;
8776
+ JsonFormModalService.openModal({
8777
+ schema: resolvedForm.value.schema,
8778
+ uiSchema: resolvedForm.value.uiSchema,
8779
+ modalSize: resolvedForm.value.modalSize,
8780
+ initialData: formData ?? properties.initialData,
8781
+ modalTitle: (isUpdate ? properties.updateTitle ?? properties.createTitle : properties.createTitle) ?? "",
8782
+ onClose: (result) => {
8783
+ if (result && result.valid) {
8784
+ store.save(formData?.id, result.data).then(() => {
8785
+ reload.value = Date.now();
8786
+ emit("save", { id: formData?.id, data: result.data });
8787
+ });
8788
+ }
8789
+ },
8790
+ onEvents: (payload) => emit("events", payload)
8791
+ });
8341
8792
  };
8342
8793
  return (_ctx, _cache) => {
8343
- return vue.openBlock(), vue.createBlock(vue.unref(ui.Modal), vue.mergeProps(properties, {
8344
- open: true,
8345
- "disable-close": false,
8346
- width: __props.modalSize,
8347
- onCloseModal: onCancel
8348
- }), {
8349
- content: vue.withCtx(() => [
8350
- vue.renderSlot(_ctx.$slots, "content-before"),
8351
- vue.createVNode(_sfc_main$2, {
8352
- id: `modal-${id}`,
8353
- modelValue: formData.value,
8354
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => formData.value = $event),
8355
- schema: __props.schema,
8356
- "ui-schema": __props.uiSchema,
8357
- onValid: _cache[1] || (_cache[1] = ($event) => onValid($event)),
8358
- onChange,
8359
- onEvents: _cache[2] || (_cache[2] = ($event) => emits("events", $event))
8360
- }, null, 8, ["id", "modelValue", "schema", "ui-schema"]),
8361
- vue.renderSlot(_ctx.$slots, "content-after")
8362
- ]),
8363
- actions: vue.withCtx(() => [
8364
- vue.createVNode(vue.unref(ui.Btn), {
8365
- color: vue.unref(ui.Color).secondary,
8366
- outline: true,
8367
- "aria-label": "Cancel",
8368
- onClick: onCancel
8369
- }, {
8370
- default: vue.withCtx(() => [..._cache[3] || (_cache[3] = [
8371
- vue.createTextVNode(" Cancel ", -1)
8372
- ])]),
8373
- _: 1
8374
- }, 8, ["color"]),
8375
- vue.createVNode(vue.unref(ui.Btn), {
8376
- disabled: !hasBeenValid.value,
8377
- "aria-label": "Save",
8378
- onClick: onSubmit
8379
- }, {
8380
- default: vue.withCtx(() => [..._cache[4] || (_cache[4] = [
8381
- vue.createTextVNode(" Save ", -1)
8382
- ])]),
8383
- _: 1
8384
- }, 8, ["disabled"])
8794
+ return vue.openBlock(), vue.createElementBlock(vue.Fragment, null, [
8795
+ vue.createElementVNode("div", _hoisted_1, [
8796
+ vue.createElementVNode("h1", null, vue.toDisplayString(_ctx.tableTitle), 1),
8797
+ vue.createElementVNode("div", null, [
8798
+ vue.createVNode(vue.unref(ui.Btn), {
8799
+ icon: vue.unref(ui.IconEnum).Plus,
8800
+ outline: true,
8801
+ onClick: create
8802
+ }, {
8803
+ default: vue.withCtx(() => [..._cache[0] || (_cache[0] = [
8804
+ vue.createTextVNode(" Add new record ", -1)
8805
+ ])]),
8806
+ _: 1
8807
+ }, 8, ["icon"])
8808
+ ])
8385
8809
  ]),
8386
- _: 3
8387
- }, 16, ["width"]);
8810
+ resolvedTable.value ? (vue.openBlock(), vue.createBlock(vue.unref(ui.Card), { key: 0 }, {
8811
+ default: vue.withCtx(() => [
8812
+ resolvedUri.value ? (vue.openBlock(), vue.createBlock(vue.unref(_sfc_main$g), {
8813
+ key: 0,
8814
+ id: `form_table_${_ctx.id}`,
8815
+ "ui-schema": resolvedTable.value.uiSchema,
8816
+ schema: resolvedTable.value.schema,
8817
+ "filter-ui-schema": resolvedFilter.value?.uiSchema,
8818
+ "filter-schema": resolvedFilter.value?.schema,
8819
+ uri: _ctx.dataUri ?? resolvedUri.value,
8820
+ reload: reload.value,
8821
+ actions: _ctx.tableActions,
8822
+ onEdit: edit,
8823
+ onDelete: deleteFn
8824
+ }, null, 8, ["id", "ui-schema", "schema", "filter-ui-schema", "filter-schema", "uri", "reload", "actions"])) : vue.createCommentVNode("", true)
8825
+ ]),
8826
+ _: 1
8827
+ })) : vue.createCommentVNode("", true)
8828
+ ], 64);
8388
8829
  };
8389
8830
  }
8390
8831
  });
8391
- class FormModalService {
8392
- static openModal({
8393
- initialData,
8394
- modalTitle,
8395
- schema,
8396
- uiSchema,
8397
- modalSize,
8398
- onClose,
8399
- onEvents
8400
- }) {
8401
- ui.ModalService.openModal({
8402
- component: _sfc_main,
8403
- props: {
8404
- schema,
8405
- uiSchema,
8406
- modalSize,
8407
- data: initialData ?? {},
8408
- modalTitle,
8409
- onClose,
8410
- onEvents
8411
- }
8412
- });
8413
- }
8414
- }
8415
- const createRepository = (formSchemaModel, httpRequest, options = {}) => {
8416
- const notificationEntity = options.notification?.entityType || "entity";
8417
- const notificationStore = options.notification?.notification ?? null;
8418
- const getDataUri = (...suffix) => {
8419
- return [formSchemaModel.uri, ...suffix].join("/");
8420
- };
8421
- const handleSuccess = (message) => {
8422
- notificationStore?.success(message);
8423
- };
8424
- const handleError = (error2, message) => {
8425
- console.error(error2);
8426
- notificationStore?.error(message);
8427
- throw new Error(error2);
8428
- };
8429
- const create = (object2, options2) => {
8430
- return httpRequest.post(getDataUri(), object2, options2).then((response) => {
8431
- handleSuccess(`Created ${notificationEntity}`);
8432
- return response.data;
8433
- }).catch((response) => {
8434
- handleError(response, `Failed to create ${notificationEntity}`);
8435
- });
8436
- };
8437
- const patch = (id, object2, options2) => {
8438
- return httpRequest.patch(getDataUri(id), object2, options2).then((response) => {
8439
- handleSuccess(`Saved ${notificationEntity}`);
8440
- return response.data;
8441
- }).catch((response) => {
8442
- handleError(response, `Failed to save ${notificationEntity}`);
8443
- });
8444
- };
8445
- const get = (id, options2) => {
8446
- return httpRequest.get(getDataUri(id), options2).then((response) => {
8447
- return response.data;
8448
- }).catch((response) => {
8449
- handleError(response, `Failed to load data`);
8450
- });
8451
- };
8452
- const _delete = (id, options2) => {
8453
- return httpRequest.delete(getDataUri(id), options2).then((response) => {
8454
- handleSuccess(`${notificationEntity} deleted`);
8455
- return response;
8456
- }).catch((response) => {
8457
- handleError(response, `Failed to delete ${notificationEntity}`);
8458
- });
8459
- };
8460
- const createMulti = (objects, options2) => {
8461
- return Promise.all(
8462
- objects.map((object2) => httpRequest.post(getDataUri(), object2, options2))
8463
- ).then((response) => {
8464
- handleSuccess(`Created ${notificationEntity}`);
8465
- return response.data;
8466
- }).catch((response) => {
8467
- handleError(response, `Failed to save ${notificationEntity}`);
8468
- });
8469
- };
8470
- return { create, patch, createMulti, delete: _delete, get };
8471
- };
8472
- exports.ArrayRenderer = _sfc_main$a;
8473
- exports.AutocompleteControlRenderer = _sfc_main$j;
8474
- exports.BooleanControlRenderer = _sfc_main$i;
8475
- exports.FormComponent = _sfc_main$2;
8476
- exports.FormComponentEmits = FormComponentEmits;
8477
- exports.FormComponentProperties = FormComponentProperties;
8478
- exports.FormModal = _sfc_main;
8479
- exports.FormModalService = FormModalService;
8480
- exports.FormStore = FormStore;
8481
- exports.FormWithActions = _sfc_main$1;
8482
- exports.FormWithActionsEmits = FormWithActionsEmits;
8483
- exports.FormWithActionsProperties = FormWithActionsProperties;
8484
- exports.FormWithTableComponent = _sfc_main$3;
8485
- exports.FormWithTableEmits = FormWithTableEmits;
8486
- exports.FormWithTableProperties = FormWithTableProperties;
8487
- exports.IntegerControlRenderer = _sfc_main$h;
8488
- exports.MultiSelectControlRender = _sfc_main$f;
8489
- exports.NumberControlRenderer = _sfc_main$e;
8490
- exports.SelectControlRender = _sfc_main$d;
8491
- exports.StringControlRenderer = _sfc_main$c;
8492
- exports.TableComponent = _sfc_main$4;
8832
+ exports.FormModalEmits = FormModalEmits;
8833
+ exports.FormModalProperties = FormModalProperties;
8834
+ exports.JsonForm = _sfc_main$2;
8835
+ exports.JsonFormModal = _sfc_main$d;
8836
+ exports.JsonFormModalService = JsonFormModalService;
8837
+ exports.JsonFormWithActions = _sfc_main$1;
8838
+ exports.JsonFormWithTable = _sfc_main;
8839
+ exports.TableComponent = _sfc_main$g;
8493
8840
  exports.TableComponentEmits = TableComponentEmits;
8494
8841
  exports.TableComponentProperties = TableComponentProperties;
8495
- exports.arrayRenderers = arrayRenderers;
8496
- exports.controlRenderers = controlRenderers;
8497
8842
  exports.createRepository = createRepository;
8498
- exports.isArrayRenderer = isArrayRenderer;
8499
- exports.isAutoCompleteControl = isAutoCompleteControl;
8500
- exports.isBooleanControl = isBooleanControl;
8501
- exports.isCustomControl = isCustomControl;
8502
- exports.isMarkdownControl = isMarkdownControl;
8503
- exports.isMultiselectControl = isMultiselectControl;
8504
- exports.isSelectControl = isSelectControl;
8505
- exports.isStringFormat = isStringFormat;
8506
- exports.isTextAreaControl = isTextAreaControl;
8507
- exports.layoutRenderers = layoutRenderers;
8508
- exports.markdownControlRenderer = _sfc_main$g;
8843
+ exports.formatError = formatError;
8509
8844
  exports.provideFormEvents = provideFormEvents;
8845
+ exports.registerZodErrorMap = registerZodErrorMap;
8510
8846
  exports.useFormEvents = useFormEvents;
8847
+ exports.veeRenderers = customRenderes;