@morscherlab/mint-sdk 1.0.0 → 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.
- package/dist/BaseModal-B9UA8Y_I.js +165 -0
- package/dist/BaseModal-B9UA8Y_I.js.map +1 -0
- package/dist/BaseSelect-DksaKYq_.js +176 -0
- package/dist/BaseSelect-DksaKYq_.js.map +1 -0
- package/dist/ExperimentPopover-CCYB1oWp.js +361 -0
- package/dist/ExperimentPopover-CCYB1oWp.js.map +1 -0
- package/dist/ExperimentPopover-D0bg_fqM.js +3 -0
- package/dist/ExperimentSelectorModal-B_kPbXcg.js +4 -0
- package/dist/ExperimentSelectorModal-wm7yUdAr.js +720 -0
- package/dist/ExperimentSelectorModal-wm7yUdAr.js.map +1 -0
- package/dist/SettingsModal-L7Ejny45.js +5 -0
- package/dist/SettingsModal-LEKI6Ebl.js +521 -0
- package/dist/SettingsModal-LEKI6Ebl.js.map +1 -0
- package/dist/{auth-BulIv_km.js → auth-D9q2GIcv.js} +3 -80
- package/dist/auth-D9q2GIcv.js.map +1 -0
- package/dist/components/DataFrame.vue.d.ts +3 -0
- package/dist/components/ExperimentDataViewer.vue.d.ts +2 -0
- package/dist/components/PluginWorkspaceView.vue.d.ts +2 -2
- package/dist/components/index.js +7 -2
- package/dist/{components-DtX3LDLq.js → components-CdjRzHI2.js} +533 -2025
- package/dist/components-CdjRzHI2.js.map +1 -0
- package/dist/composables/index.js +9 -3
- package/dist/composables/usePluginClient.d.ts +2 -1
- package/dist/{composables-wNt7VtkF.js → composables-DJgqPrlR.js} +7 -12
- package/dist/{composables-wNt7VtkF.js.map → composables-DJgqPrlR.js.map} +1 -1
- package/dist/experiment-utils-hGXMHlAc.js +109 -0
- package/dist/experiment-utils-hGXMHlAc.js.map +1 -0
- package/dist/index.js +16 -5
- package/dist/index.js.map +1 -1
- package/dist/install.js +7 -2
- package/dist/install.js.map +1 -1
- package/dist/permissions.js +81 -0
- package/dist/permissions.js.map +1 -0
- package/dist/stores/index.js +1 -1
- package/dist/styles.css +3233 -3185
- package/dist/templates/index.js +3 -1
- package/dist/templates-Do43ZIMb.js +5065 -0
- package/dist/templates-Do43ZIMb.js.map +1 -0
- package/dist/{templates-DSbHJC4v.js → useControlSchema-0n8Bcftq.js} +10 -5335
- package/dist/useControlSchema-0n8Bcftq.js.map +1 -0
- package/dist/useDropdownState-Ben4DnjJ.js +47 -0
- package/dist/useDropdownState-Ben4DnjJ.js.map +1 -0
- package/dist/useEventListener-CfVkP9Xz.js +57 -0
- package/dist/useEventListener-CfVkP9Xz.js.map +1 -0
- package/dist/useExperimentSelector-BpZklTbV.js +469 -0
- package/dist/useExperimentSelector-BpZklTbV.js.map +1 -0
- package/dist/useFormBuilder-COfYWDuC.js +729 -0
- package/dist/useFormBuilder-COfYWDuC.js.map +1 -0
- package/dist/{useProtocolTemplates-DwBhEPPU.js → useProtocolTemplates-TUQO_F3n.js} +8 -1298
- package/dist/useProtocolTemplates-TUQO_F3n.js.map +1 -0
- package/dist/utils/pluginIcon.d.ts +29 -2
- package/package.json +5 -1
- package/src/__tests__/components/DataFrame.test.ts +37 -0
- package/src/__tests__/components/PluginIcon.test.ts +77 -0
- package/src/__tests__/composables/usePluginClient.test.ts +11 -10
- package/src/components/AppTopBar.vue +7 -6
- package/src/components/DataFrame.vue +27 -2
- package/src/components/ExperimentDataViewer.vue +5 -1
- package/src/components/PluginIcon.story.vue +31 -1
- package/src/components/PluginIcon.vue +94 -4
- package/src/composables/usePluginClient.ts +3 -12
- package/src/styles/components/dataframe.css +26 -0
- package/src/styles/components/plugin-icon.css +5 -0
- package/src/utils/pluginIcon.ts +159 -2
- package/dist/auth-BulIv_km.js.map +0 -1
- package/dist/components-DtX3LDLq.js.map +0 -1
- package/dist/templates-DSbHJC4v.js.map +0 -1
- package/dist/useProtocolTemplates-DwBhEPPU.js.map +0 -1
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
import { E as getFieldRegistryEntry, b as controlsToSettingsSchema, f as resolveControlModel, g as mergeControlWorkspaceOptions } from "./useControlSchema-0n8Bcftq.js";
|
|
2
|
+
import { t as BaseModal_default } from "./BaseModal-B9UA8Y_I.js";
|
|
3
|
+
import { n as colorPalettes, r as useSettingsStore, t as useAuthStore } from "./auth-D9q2GIcv.js";
|
|
4
|
+
import { i as usePlatformContext, t as useFormBuilder } from "./useFormBuilder-COfYWDuC.js";
|
|
5
|
+
import { canAccessByPolicy } from "./permissions.js";
|
|
6
|
+
import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createTextVNode, createVNode, defineComponent, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, vShow, watch, withCtx, withDirectives } from "vue";
|
|
7
|
+
//#region src/utils/items.ts
|
|
8
|
+
function normalizeItemInput(item) {
|
|
9
|
+
if (typeof item === "object") return item;
|
|
10
|
+
return {
|
|
11
|
+
id: item,
|
|
12
|
+
label: item
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
function normalizeLabelItemInput(item) {
|
|
16
|
+
if (typeof item === "object") return item;
|
|
17
|
+
return { label: item };
|
|
18
|
+
}
|
|
19
|
+
//#endregion
|
|
20
|
+
//#region src/components/FormField.vue?vue&type=script&setup=true&lang.ts
|
|
21
|
+
var _hoisted_1$1 = { class: "mint-form-field" };
|
|
22
|
+
var _hoisted_2$1 = {
|
|
23
|
+
key: 0,
|
|
24
|
+
class: "mint-form-field__label-row"
|
|
25
|
+
};
|
|
26
|
+
var _hoisted_3$1 = ["for"];
|
|
27
|
+
var _hoisted_4$1 = {
|
|
28
|
+
key: 0,
|
|
29
|
+
class: "mint-form-field__required",
|
|
30
|
+
"aria-hidden": "true"
|
|
31
|
+
};
|
|
32
|
+
var _hoisted_5$1 = {
|
|
33
|
+
key: 0,
|
|
34
|
+
class: "mint-form-field__optional"
|
|
35
|
+
};
|
|
36
|
+
var _hoisted_6$1 = ["id"];
|
|
37
|
+
var _hoisted_7$1 = ["id"];
|
|
38
|
+
//#endregion
|
|
39
|
+
//#region src/components/FormField.vue
|
|
40
|
+
var FormField_default = /* @__PURE__ */ defineComponent({
|
|
41
|
+
__name: "FormField",
|
|
42
|
+
props: {
|
|
43
|
+
label: {},
|
|
44
|
+
error: {},
|
|
45
|
+
hint: {},
|
|
46
|
+
required: { type: Boolean },
|
|
47
|
+
showOptional: { type: Boolean },
|
|
48
|
+
htmlFor: {},
|
|
49
|
+
fieldId: {}
|
|
50
|
+
},
|
|
51
|
+
setup(__props) {
|
|
52
|
+
/** Wraps a form control with a label, optional hint text, and validation error display. */
|
|
53
|
+
const props = __props;
|
|
54
|
+
const errorId = computed(() => props.error && props.fieldId ? `${props.fieldId}-error` : void 0);
|
|
55
|
+
const hintId = computed(() => !props.error && props.hint && props.fieldId ? `${props.fieldId}-hint` : void 0);
|
|
56
|
+
const describedBy = computed(() => errorId.value ?? hintId.value);
|
|
57
|
+
return (_ctx, _cache) => {
|
|
58
|
+
return openBlock(), createElementBlock("div", _hoisted_1$1, [
|
|
59
|
+
__props.label ? (openBlock(), createElementBlock("div", _hoisted_2$1, [createElementVNode("label", {
|
|
60
|
+
for: __props.htmlFor,
|
|
61
|
+
class: "mint-form-field__label"
|
|
62
|
+
}, [createTextVNode(toDisplayString(__props.label) + " ", 1), __props.required ? (openBlock(), createElementBlock("span", _hoisted_4$1, "*")) : createCommentVNode("", true)], 8, _hoisted_3$1), !__props.required && __props.showOptional ? (openBlock(), createElementBlock("span", _hoisted_5$1, " optional ")) : createCommentVNode("", true)])) : createCommentVNode("", true),
|
|
63
|
+
renderSlot(_ctx.$slots, "default", { describedBy: describedBy.value }),
|
|
64
|
+
__props.error ? (openBlock(), createElementBlock("p", {
|
|
65
|
+
key: 1,
|
|
66
|
+
id: errorId.value,
|
|
67
|
+
class: "mint-form-field__error",
|
|
68
|
+
role: "alert"
|
|
69
|
+
}, toDisplayString(__props.error), 9, _hoisted_6$1)) : __props.hint ? (openBlock(), createElementBlock("p", {
|
|
70
|
+
key: 2,
|
|
71
|
+
id: hintId.value,
|
|
72
|
+
class: "mint-form-field__hint"
|
|
73
|
+
}, toDisplayString(__props.hint), 9, _hoisted_7$1)) : createCommentVNode("", true)
|
|
74
|
+
]);
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/utils/formModelSync.ts
|
|
80
|
+
function recordValuesEqualForKeys(left, right, keys) {
|
|
81
|
+
for (const key of keys) if (!valuesEqual(left[key], right[key])) return false;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
84
|
+
function pickRecordKeys(source, keys) {
|
|
85
|
+
return Object.fromEntries(keys.map((key) => [key, source[key]]));
|
|
86
|
+
}
|
|
87
|
+
function pickExistingRecordKeys(source, keys) {
|
|
88
|
+
return Object.fromEntries(keys.filter((key) => Object.prototype.hasOwnProperty.call(source, key)).map((key) => [key, source[key]]));
|
|
89
|
+
}
|
|
90
|
+
function formSchemaFieldNames(schema) {
|
|
91
|
+
return (schema.steps ? schema.steps.flatMap((step) => step.sections) : schema.sections).flatMap((section) => section.fields.map((field) => field.name));
|
|
92
|
+
}
|
|
93
|
+
function valuesEqual(left, right) {
|
|
94
|
+
if (Object.is(left, right)) return true;
|
|
95
|
+
if (Array.isArray(left) && Array.isArray(right)) return left.length === right.length && left.every((item, index) => valuesEqual(item, right[index]));
|
|
96
|
+
if (isRecord(left) && isRecord(right)) return recordValuesEqualForKeys(left, right, [...new Set([...Object.keys(left), ...Object.keys(right)])]);
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
function isRecord(value) {
|
|
100
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
101
|
+
}
|
|
102
|
+
//#endregion
|
|
103
|
+
//#region src/components/internal/FormFieldRendererInternal.vue
|
|
104
|
+
var FormFieldRendererInternal_default = /* @__PURE__ */ defineComponent({
|
|
105
|
+
__name: "FormFieldRendererInternal",
|
|
106
|
+
props: {
|
|
107
|
+
field: {},
|
|
108
|
+
resolvedProps: {},
|
|
109
|
+
form: {}
|
|
110
|
+
},
|
|
111
|
+
setup(__props) {
|
|
112
|
+
const props = __props;
|
|
113
|
+
const entry = computed(() => getFieldRegistryEntry(props.field.type));
|
|
114
|
+
const isChoiceField = computed(() => props.field.type === "checkbox" || props.field.type === "toggle");
|
|
115
|
+
const componentProps = computed(() => {
|
|
116
|
+
if (!isChoiceField.value) return props.resolvedProps;
|
|
117
|
+
return {
|
|
118
|
+
variant: "row",
|
|
119
|
+
label: props.field.label,
|
|
120
|
+
description: props.field.hint,
|
|
121
|
+
icon: props.field.icon,
|
|
122
|
+
iconColor: props.field.iconColor,
|
|
123
|
+
iconBg: props.field.iconBg,
|
|
124
|
+
...props.resolvedProps
|
|
125
|
+
};
|
|
126
|
+
});
|
|
127
|
+
const errorMessage = computed(() => {
|
|
128
|
+
const name = props.field.name;
|
|
129
|
+
return props.form.touched[name] ? props.form.errors[name] : null;
|
|
130
|
+
});
|
|
131
|
+
function handleUpload(files) {
|
|
132
|
+
props.form.setFieldValue(props.field.name, files);
|
|
133
|
+
}
|
|
134
|
+
return (_ctx, _cache) => {
|
|
135
|
+
return openBlock(), createBlock(FormField_default, {
|
|
136
|
+
label: isChoiceField.value ? void 0 : __props.field.label,
|
|
137
|
+
error: errorMessage.value ?? void 0,
|
|
138
|
+
hint: isChoiceField.value ? void 0 : __props.field.hint,
|
|
139
|
+
required: !!__props.field.validation?.required,
|
|
140
|
+
"html-for": isChoiceField.value ? void 0 : __props.field.name
|
|
141
|
+
}, {
|
|
142
|
+
default: withCtx(() => [renderSlot(_ctx.$slots, `field:${__props.field.name}`, {
|
|
143
|
+
field: __props.field,
|
|
144
|
+
form: __props.form,
|
|
145
|
+
fieldProps: __props.form.getFieldProps(__props.field.name)
|
|
146
|
+
}, () => [entry.value.vModel ? (openBlock(), createBlock(resolveDynamicComponent(entry.value.component), normalizeProps(mergeProps({ key: 0 }, componentProps.value)), null, 16)) : (openBlock(), createBlock(resolveDynamicComponent(entry.value.component), mergeProps({ key: 1 }, componentProps.value, { onUpload: handleUpload }), null, 16))])]),
|
|
147
|
+
_: 3
|
|
148
|
+
}, 8, [
|
|
149
|
+
"label",
|
|
150
|
+
"error",
|
|
151
|
+
"hint",
|
|
152
|
+
"required",
|
|
153
|
+
"html-for"
|
|
154
|
+
]);
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
//#endregion
|
|
159
|
+
//#region src/components/SettingsModal.schema.ts
|
|
160
|
+
var APPEARANCE_TAB_ID = "appearance";
|
|
161
|
+
var APPEARANCE_TAB = {
|
|
162
|
+
id: APPEARANCE_TAB_ID,
|
|
163
|
+
label: "Appearance",
|
|
164
|
+
description: "Theme, color palette, and table density"
|
|
165
|
+
};
|
|
166
|
+
function buildFlatSettingsSchema(schema) {
|
|
167
|
+
return { sections: schema.groups.map((group) => ({
|
|
168
|
+
id: group.id,
|
|
169
|
+
title: "",
|
|
170
|
+
fields: group.fields,
|
|
171
|
+
columns: group.columns,
|
|
172
|
+
condition: group.condition
|
|
173
|
+
})) };
|
|
174
|
+
}
|
|
175
|
+
function filterSettingsSchemaByAccess(schema, canShow) {
|
|
176
|
+
return { groups: schema.groups.flatMap((group) => {
|
|
177
|
+
if (!canShow(group)) return [];
|
|
178
|
+
const fields = group.fields.filter(canShow);
|
|
179
|
+
if (fields.length === 0) return [];
|
|
180
|
+
return [{
|
|
181
|
+
...group,
|
|
182
|
+
fields
|
|
183
|
+
}];
|
|
184
|
+
}) };
|
|
185
|
+
}
|
|
186
|
+
function settingsGroupToTab(group) {
|
|
187
|
+
return {
|
|
188
|
+
id: group.id,
|
|
189
|
+
label: group.label,
|
|
190
|
+
icon: group.icon,
|
|
191
|
+
description: group.description
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
function normalizeVisibleSettingsTabs(tabs, canShow) {
|
|
195
|
+
return tabs.map(normalizeItemInput).filter(canShow);
|
|
196
|
+
}
|
|
197
|
+
function buildSettingsTabs(baseTabs, showAppearance) {
|
|
198
|
+
return showAppearance ? [...baseTabs, APPEARANCE_TAB] : baseTabs;
|
|
199
|
+
}
|
|
200
|
+
//#endregion
|
|
201
|
+
//#region src/components/SettingsModal.vue?vue&type=script&setup=true&lang.ts
|
|
202
|
+
var _hoisted_1 = {
|
|
203
|
+
key: 0,
|
|
204
|
+
class: "mint-settings-modal__tabs"
|
|
205
|
+
};
|
|
206
|
+
var _hoisted_2 = ["onClick"];
|
|
207
|
+
var _hoisted_3 = {
|
|
208
|
+
key: 1,
|
|
209
|
+
class: "mint-settings-modal__rail",
|
|
210
|
+
role: "tablist",
|
|
211
|
+
"aria-orientation": "vertical",
|
|
212
|
+
"aria-label": "Settings sections"
|
|
213
|
+
};
|
|
214
|
+
var _hoisted_4 = [
|
|
215
|
+
"id",
|
|
216
|
+
"aria-selected",
|
|
217
|
+
"aria-controls",
|
|
218
|
+
"tabindex",
|
|
219
|
+
"onClick"
|
|
220
|
+
];
|
|
221
|
+
var _hoisted_5 = {
|
|
222
|
+
class: "mint-settings-modal__rail-item-icon",
|
|
223
|
+
"aria-hidden": "true"
|
|
224
|
+
};
|
|
225
|
+
var _hoisted_6 = ["innerHTML"];
|
|
226
|
+
var _hoisted_7 = { class: "mint-settings-modal__rail-item-text" };
|
|
227
|
+
var _hoisted_8 = { class: "mint-settings-modal__rail-item-label" };
|
|
228
|
+
var _hoisted_9 = {
|
|
229
|
+
key: 0,
|
|
230
|
+
class: "mint-settings-modal__rail-item-description"
|
|
231
|
+
};
|
|
232
|
+
var _hoisted_10 = {
|
|
233
|
+
key: 0,
|
|
234
|
+
class: "mint-settings-modal__pane-header"
|
|
235
|
+
};
|
|
236
|
+
var _hoisted_11 = { class: "mint-settings-modal__pane-title" };
|
|
237
|
+
var _hoisted_12 = {
|
|
238
|
+
key: 0,
|
|
239
|
+
class: "mint-settings-modal__pane-subtitle"
|
|
240
|
+
};
|
|
241
|
+
var _hoisted_13 = { key: 2 };
|
|
242
|
+
var _hoisted_14 = { class: "mint-settings-modal__section" };
|
|
243
|
+
var _hoisted_15 = { class: "mint-settings-modal__option-group" };
|
|
244
|
+
var _hoisted_16 = ["onClick"];
|
|
245
|
+
var _hoisted_17 = { class: "mint-settings-modal__section" };
|
|
246
|
+
var _hoisted_18 = { class: "mint-settings-modal__option-group" };
|
|
247
|
+
var _hoisted_19 = ["onClick"];
|
|
248
|
+
var _hoisted_20 = { class: "mint-settings-modal__section" };
|
|
249
|
+
var _hoisted_21 = { class: "mint-settings-modal__option-group" };
|
|
250
|
+
var _hoisted_22 = ["onClick"];
|
|
251
|
+
var _hoisted_23 = {
|
|
252
|
+
key: 0,
|
|
253
|
+
class: "mint-settings-modal__footer"
|
|
254
|
+
};
|
|
255
|
+
//#endregion
|
|
256
|
+
//#region src/components/SettingsModal.vue
|
|
257
|
+
var SettingsModal_default = /* @__PURE__ */ defineComponent({
|
|
258
|
+
__name: "SettingsModal",
|
|
259
|
+
props: {
|
|
260
|
+
modelValue: { type: Boolean },
|
|
261
|
+
title: { default: "Settings" },
|
|
262
|
+
tabs: { default: () => [] },
|
|
263
|
+
showAppearance: {
|
|
264
|
+
type: Boolean,
|
|
265
|
+
default: true
|
|
266
|
+
},
|
|
267
|
+
size: { default: "lg" },
|
|
268
|
+
layout: { default: "horizontal" },
|
|
269
|
+
schema: {},
|
|
270
|
+
model: { default: void 0 },
|
|
271
|
+
controls: {},
|
|
272
|
+
controlOptions: {},
|
|
273
|
+
values: {},
|
|
274
|
+
enhancements: {},
|
|
275
|
+
userType: {}
|
|
276
|
+
},
|
|
277
|
+
emits: [
|
|
278
|
+
"update:modelValue",
|
|
279
|
+
"update:values",
|
|
280
|
+
"close"
|
|
281
|
+
],
|
|
282
|
+
setup(__props, { emit: __emit }) {
|
|
283
|
+
/**
|
|
284
|
+
* Tabbed settings modal with three usage modes:
|
|
285
|
+
*
|
|
286
|
+
* 1. Schema-driven (recommended) — pass `schema`, compact `controls`, or a
|
|
287
|
+
* complete `defineControlModel()` result plus `v-model:values`. Each
|
|
288
|
+
* group/section becomes a tab; fields auto-render via the SDK form field
|
|
289
|
+
* registry (text, select, number, toggle, molecule, concentration, …).
|
|
290
|
+
* Conditional visibility, validation, and dynamic options come for free.
|
|
291
|
+
*
|
|
292
|
+
* 2. Manual tabs + slots — pass `tabs` and a `<template #tab-{id}>` slot
|
|
293
|
+
* per tab. Use this when you need bespoke widgets the form-builder
|
|
294
|
+
* registry doesn't cover (or for legacy plugins).
|
|
295
|
+
*
|
|
296
|
+
* 3. Appearance only — `showAppearance` (default true) renders the built-in
|
|
297
|
+
* theme / palette / table-density tab. Works alongside both modes above.
|
|
298
|
+
*
|
|
299
|
+
* Layout: `horizontal` (underline tabs, default) or `vertical` (sidebar rail
|
|
300
|
+
* with optional icons + descriptions, recommended for 5+ groups).
|
|
301
|
+
*/
|
|
302
|
+
const props = __props;
|
|
303
|
+
const emit = __emit;
|
|
304
|
+
const settings = useSettingsStore();
|
|
305
|
+
const auth = useAuthStore();
|
|
306
|
+
const { user: platformUser } = usePlatformContext();
|
|
307
|
+
const isVertical = computed(() => props.layout === "vertical");
|
|
308
|
+
const uid = `mint-settings-${Math.random().toString(36).slice(2, 9)}`;
|
|
309
|
+
const tabId = (id) => `${uid}-tab-${id}`;
|
|
310
|
+
const panelId = (id) => `${uid}-panel-${id}`;
|
|
311
|
+
const resolvedModel = computed(() => {
|
|
312
|
+
return resolveControlModel(props.model);
|
|
313
|
+
});
|
|
314
|
+
const resolvedControls = computed(() => props.controls ?? resolvedModel.value?.controls);
|
|
315
|
+
const resolvedControlOptions = computed(() => mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions));
|
|
316
|
+
const sourceSettingsSchema = computed(() => props.schema ?? (resolvedControls.value ? controlsToSettingsSchema(resolvedControls.value, resolvedControlOptions.value) : void 0));
|
|
317
|
+
const currentAccessUser = computed(() => {
|
|
318
|
+
if (props.userType) return { role: props.userType === "admin" ? "admin" : "user" };
|
|
319
|
+
return auth.userInfo ?? platformUser.value ?? null;
|
|
320
|
+
});
|
|
321
|
+
const isAccessUserAuthenticated = computed(() => props.userType !== void 0 || auth.isAuthenticated || !!platformUser.value);
|
|
322
|
+
const settingsSchema = computed(() => {
|
|
323
|
+
if (!sourceSettingsSchema.value) return void 0;
|
|
324
|
+
return filterSettingsSchemaByAccess(sourceSettingsSchema.value, canShowForCurrentUser);
|
|
325
|
+
});
|
|
326
|
+
const isSchemaDriven = computed(() => !!settingsSchema.value);
|
|
327
|
+
const resolvedValues = computed(() => ({
|
|
328
|
+
...resolvedControlOptions.value.initialValues ?? {},
|
|
329
|
+
...props.values ?? {}
|
|
330
|
+
}));
|
|
331
|
+
const builder = useFormBuilder(settingsSchema.value ? buildFlatSettingsSchema(settingsSchema.value) : { sections: [] }, resolvedValues.value, props.enhancements);
|
|
332
|
+
watch(() => settingsSchema.value, (schema) => {
|
|
333
|
+
if (!schema) {
|
|
334
|
+
builder.updateSchema({ sections: [] }, {});
|
|
335
|
+
return;
|
|
336
|
+
}
|
|
337
|
+
const flatSchema = buildFlatSettingsSchema(schema);
|
|
338
|
+
const fieldNames = formSchemaFieldNames(flatSchema);
|
|
339
|
+
const sourceValues = props.values === void 0 ? {
|
|
340
|
+
...resolvedValues.value,
|
|
341
|
+
...builder.form.data
|
|
342
|
+
} : resolvedValues.value;
|
|
343
|
+
builder.updateSchema(flatSchema, pickExistingRecordKeys(sourceValues ?? {}, fieldNames));
|
|
344
|
+
}, { deep: true });
|
|
345
|
+
watch(() => ({ ...resolvedValues.value }), (data) => {
|
|
346
|
+
if (!settingsSchema.value) return;
|
|
347
|
+
const fieldNames = builderFieldNames();
|
|
348
|
+
if (recordValuesEqualForKeys(data, builder.form.data, fieldNames)) return;
|
|
349
|
+
builder.reset(pickRecordKeys(data, fieldNames));
|
|
350
|
+
}, { deep: true });
|
|
351
|
+
watch(() => ({ ...builder.form.data }), (data) => {
|
|
352
|
+
if (settingsSchema.value) emit("update:values", data);
|
|
353
|
+
}, { deep: true });
|
|
354
|
+
const visibleSchemaGroups = computed(() => settingsSchema.value ? settingsSchema.value.groups.filter((g) => builder.isSectionVisible(g.id)) : []);
|
|
355
|
+
const manualTabs = computed(() => normalizeVisibleSettingsTabs(props.tabs, canShowForCurrentUser));
|
|
356
|
+
const allTabs = computed(() => {
|
|
357
|
+
return buildSettingsTabs(settingsSchema.value ? visibleSchemaGroups.value.map(settingsGroupToTab) : manualTabs.value, props.showAppearance);
|
|
358
|
+
});
|
|
359
|
+
const activeTab = ref(allTabs.value[0]?.id || "appearance");
|
|
360
|
+
const activeTabMeta = computed(() => allTabs.value.find((t) => t.id === activeTab.value));
|
|
361
|
+
watch(allTabs, (tabs) => {
|
|
362
|
+
if (!tabs.some((t) => t.id === activeTab.value)) activeTab.value = tabs[0]?.id ?? "appearance";
|
|
363
|
+
});
|
|
364
|
+
const activeGroup = computed(() => visibleSchemaGroups.value.find((g) => g.id === activeTab.value));
|
|
365
|
+
const activeGroupVisibleFields = computed(() => {
|
|
366
|
+
if (!activeGroup.value) return [];
|
|
367
|
+
return activeGroup.value.fields.filter((f) => builder.isFieldVisible(f.name));
|
|
368
|
+
});
|
|
369
|
+
const themeOptions = [
|
|
370
|
+
{
|
|
371
|
+
value: "light",
|
|
372
|
+
label: "Light"
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
value: "dark",
|
|
376
|
+
label: "Dark"
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
value: "system",
|
|
380
|
+
label: "System"
|
|
381
|
+
}
|
|
382
|
+
];
|
|
383
|
+
const densityOptions = [
|
|
384
|
+
{
|
|
385
|
+
value: "compact",
|
|
386
|
+
label: "Compact"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
value: "normal",
|
|
390
|
+
label: "Normal"
|
|
391
|
+
},
|
|
392
|
+
{
|
|
393
|
+
value: "comfortable",
|
|
394
|
+
label: "Comfortable"
|
|
395
|
+
}
|
|
396
|
+
];
|
|
397
|
+
function handleClose() {
|
|
398
|
+
emit("update:modelValue", false);
|
|
399
|
+
emit("close");
|
|
400
|
+
}
|
|
401
|
+
function builderFieldNames() {
|
|
402
|
+
return builder.fields.map((field) => field.name);
|
|
403
|
+
}
|
|
404
|
+
function canShowForCurrentUser(item) {
|
|
405
|
+
return canAccessByPolicy(currentAccessUser.value, item, isAccessUserAuthenticated.value);
|
|
406
|
+
}
|
|
407
|
+
return (_ctx, _cache) => {
|
|
408
|
+
return openBlock(), createBlock(BaseModal_default, {
|
|
409
|
+
"model-value": __props.modelValue,
|
|
410
|
+
title: __props.title,
|
|
411
|
+
size: __props.size,
|
|
412
|
+
"onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", $event)),
|
|
413
|
+
onClose: handleClose
|
|
414
|
+
}, {
|
|
415
|
+
default: withCtx(() => [createElementVNode("div", { class: normalizeClass(["mint-settings-modal", `mint-settings-modal--${__props.layout}`]) }, [!isVertical.value && allTabs.value.length > 1 ? (openBlock(), createElementBlock("div", _hoisted_1, [(openBlock(true), createElementBlock(Fragment, null, renderList(allTabs.value, (tab) => {
|
|
416
|
+
return openBlock(), createElementBlock("button", {
|
|
417
|
+
key: tab.id,
|
|
418
|
+
type: "button",
|
|
419
|
+
class: normalizeClass(["mint-settings-modal__tab", { "mint-settings-modal__tab--active": activeTab.value === tab.id }]),
|
|
420
|
+
onClick: ($event) => activeTab.value = tab.id
|
|
421
|
+
}, toDisplayString(tab.label), 11, _hoisted_2);
|
|
422
|
+
}), 128))])) : isVertical.value ? (openBlock(), createElementBlock("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(allTabs.value, (tab) => {
|
|
423
|
+
return openBlock(), createElementBlock("button", {
|
|
424
|
+
id: tabId(tab.id),
|
|
425
|
+
key: tab.id,
|
|
426
|
+
type: "button",
|
|
427
|
+
role: "tab",
|
|
428
|
+
class: normalizeClass(["mint-settings-modal__rail-item", { "mint-settings-modal__rail-item--active": activeTab.value === tab.id }]),
|
|
429
|
+
"aria-selected": activeTab.value === tab.id,
|
|
430
|
+
"aria-controls": panelId(tab.id),
|
|
431
|
+
tabindex: activeTab.value === tab.id ? 0 : -1,
|
|
432
|
+
onClick: ($event) => activeTab.value = tab.id
|
|
433
|
+
}, [createElementVNode("span", _hoisted_5, [tab.icon ? (openBlock(), createElementBlock("span", {
|
|
434
|
+
key: 0,
|
|
435
|
+
innerHTML: tab.icon
|
|
436
|
+
}, null, 8, _hoisted_6)) : createCommentVNode("", true)]), createElementVNode("span", _hoisted_7, [createElementVNode("span", _hoisted_8, toDisplayString(tab.label), 1), tab.description ? (openBlock(), createElementBlock("span", _hoisted_9, toDisplayString(tab.description), 1)) : createCommentVNode("", true)])], 10, _hoisted_4);
|
|
437
|
+
}), 128))])) : createCommentVNode("", true), (openBlock(), createBlock(resolveDynamicComponent(isVertical.value ? "section" : "div"), {
|
|
438
|
+
class: normalizeClass(isVertical.value ? "mint-settings-modal__pane" : "mint-settings-modal__content"),
|
|
439
|
+
id: isVertical.value && activeTabMeta.value ? panelId(activeTabMeta.value.id) : void 0,
|
|
440
|
+
role: isVertical.value ? "tabpanel" : void 0,
|
|
441
|
+
"aria-labelledby": isVertical.value && activeTabMeta.value ? tabId(activeTabMeta.value.id) : void 0,
|
|
442
|
+
tabindex: isVertical.value ? 0 : void 0
|
|
443
|
+
}, {
|
|
444
|
+
default: withCtx(() => [isVertical.value && activeTabMeta.value?.label ? (openBlock(), createElementBlock("header", _hoisted_10, [createElementVNode("h4", _hoisted_11, toDisplayString(activeTabMeta.value.label), 1), activeTabMeta.value.description ? (openBlock(), createElementBlock("p", _hoisted_12, toDisplayString(activeTabMeta.value.description), 1)) : createCommentVNode("", true)])) : createCommentVNode("", true), createElementVNode("div", { class: normalizeClass(isVertical.value ? "mint-settings-modal__pane-body" : null) }, [isSchemaDriven.value && activeGroup.value ? (openBlock(), createElementBlock("div", {
|
|
445
|
+
key: 0,
|
|
446
|
+
class: "mint-settings-modal__group-grid",
|
|
447
|
+
style: normalizeStyle({ "--mint-settings-cols": activeGroup.value.columns ?? 1 })
|
|
448
|
+
}, [(openBlock(true), createElementBlock(Fragment, null, renderList(activeGroupVisibleFields.value, (field) => {
|
|
449
|
+
return openBlock(), createElementBlock("div", {
|
|
450
|
+
key: field.name,
|
|
451
|
+
style: normalizeStyle(field.colSpan ? { gridColumn: `span ${field.colSpan}` } : void 0)
|
|
452
|
+
}, [renderSlot(_ctx.$slots, `field:${field.name}`, {
|
|
453
|
+
field,
|
|
454
|
+
form: unref(builder).form,
|
|
455
|
+
fieldProps: unref(builder).form.getFieldProps(field.name)
|
|
456
|
+
}, () => [createVNode(FormFieldRendererInternal_default, {
|
|
457
|
+
field,
|
|
458
|
+
"resolved-props": unref(builder).getResolvedFieldProps(field),
|
|
459
|
+
form: unref(builder).form
|
|
460
|
+
}, null, 8, [
|
|
461
|
+
"field",
|
|
462
|
+
"resolved-props",
|
|
463
|
+
"form"
|
|
464
|
+
])])], 4);
|
|
465
|
+
}), 128))], 4)) : !isSchemaDriven.value ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(manualTabs.value, (tab) => {
|
|
466
|
+
return withDirectives((openBlock(), createElementBlock("div", { key: tab.id }, [renderSlot(_ctx.$slots, `tab-${tab.id}`)], 512)), [[vShow, activeTab.value === tab.id]]);
|
|
467
|
+
}), 128)) : createCommentVNode("", true), __props.showAppearance ? withDirectives((openBlock(), createElementBlock("div", _hoisted_13, [
|
|
468
|
+
createElementVNode("div", _hoisted_14, [_cache[1] || (_cache[1] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Theme", -1)), createElementVNode("div", _hoisted_15, [(openBlock(), createElementBlock(Fragment, null, renderList(themeOptions, (opt) => {
|
|
469
|
+
return createElementVNode("button", {
|
|
470
|
+
key: opt.value,
|
|
471
|
+
type: "button",
|
|
472
|
+
class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).theme === opt.value }]),
|
|
473
|
+
onClick: ($event) => unref(settings).theme = opt.value
|
|
474
|
+
}, toDisplayString(opt.label), 11, _hoisted_16);
|
|
475
|
+
}), 64))])]),
|
|
476
|
+
createElementVNode("div", _hoisted_17, [_cache[2] || (_cache[2] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Color Palette", -1)), createElementVNode("div", _hoisted_18, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(colorPalettes), (palette, key) => {
|
|
477
|
+
return openBlock(), createElementBlock("button", {
|
|
478
|
+
key,
|
|
479
|
+
type: "button",
|
|
480
|
+
class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).colorPalette === key }]),
|
|
481
|
+
onClick: ($event) => unref(settings).colorPalette = key
|
|
482
|
+
}, toDisplayString(palette.name), 11, _hoisted_19);
|
|
483
|
+
}), 128))])]),
|
|
484
|
+
createElementVNode("div", _hoisted_20, [
|
|
485
|
+
_cache[3] || (_cache[3] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Table Density", -1)),
|
|
486
|
+
createElementVNode("div", _hoisted_21, [(openBlock(), createElementBlock(Fragment, null, renderList(densityOptions, (opt) => {
|
|
487
|
+
return createElementVNode("button", {
|
|
488
|
+
key: opt.value,
|
|
489
|
+
type: "button",
|
|
490
|
+
class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).tableDensity === opt.value }]),
|
|
491
|
+
onClick: ($event) => unref(settings).tableDensity = opt.value
|
|
492
|
+
}, toDisplayString(opt.label), 11, _hoisted_22);
|
|
493
|
+
}), 64))]),
|
|
494
|
+
_cache[4] || (_cache[4] = createElementVNode("p", { class: "mint-settings-modal__note" }, "Adjusts row height in data tables.", -1))
|
|
495
|
+
]),
|
|
496
|
+
renderSlot(_ctx.$slots, "appearance")
|
|
497
|
+
], 512)), [[vShow, activeTab.value === unref(APPEARANCE_TAB_ID)]]) : createCommentVNode("", true)], 2)]),
|
|
498
|
+
_: 3
|
|
499
|
+
}, 8, [
|
|
500
|
+
"class",
|
|
501
|
+
"id",
|
|
502
|
+
"role",
|
|
503
|
+
"aria-labelledby",
|
|
504
|
+
"tabindex"
|
|
505
|
+
]))], 2), _ctx.$slots.footer ? (openBlock(), createElementBlock("div", _hoisted_23, [renderSlot(_ctx.$slots, "footer", {
|
|
506
|
+
values: unref(builder).form.data,
|
|
507
|
+
close: handleClose
|
|
508
|
+
})])) : createCommentVNode("", true)]),
|
|
509
|
+
_: 3
|
|
510
|
+
}, 8, [
|
|
511
|
+
"model-value",
|
|
512
|
+
"title",
|
|
513
|
+
"size"
|
|
514
|
+
]);
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
});
|
|
518
|
+
//#endregion
|
|
519
|
+
export { recordValuesEqualForKeys as a, normalizeLabelItemInput as c, pickExistingRecordKeys as i, FormFieldRendererInternal_default as n, FormField_default as o, formSchemaFieldNames as r, normalizeItemInput as s, SettingsModal_default as t };
|
|
520
|
+
|
|
521
|
+
//# sourceMappingURL=SettingsModal-LEKI6Ebl.js.map
|