@morscherlab/mint-sdk 1.1.5 → 1.1.7

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 (100) hide show
  1. package/dist/{EmptyState-LMPS3keb.js → EmptyState-p90quq8Z.js} +2 -2
  2. package/dist/{EmptyState-LMPS3keb.js.map → EmptyState-p90quq8Z.js.map} +1 -1
  3. package/dist/{ExperimentPopover-D6_RGzTY.js → ExperimentPopover-tLwJ7XF4.js} +3 -3
  4. package/dist/{ExperimentPopover-D6_RGzTY.js.map → ExperimentPopover-tLwJ7XF4.js.map} +1 -1
  5. package/dist/{ExperimentSelectorModal-DcQ38zua.js → ExperimentSelectorModal-B6P2msT4.js} +12 -5
  6. package/dist/ExperimentSelectorModal-B6P2msT4.js.map +1 -0
  7. package/dist/{SettingsModal-Ccq2z-Ms.js → SettingsModal-D7LFUokT.js} +100 -156
  8. package/dist/SettingsModal-D7LFUokT.js.map +1 -0
  9. package/dist/__tests__/components/ActionMenu.test.d.ts +1 -0
  10. package/dist/__tests__/components/BaseModal.test.d.ts +1 -0
  11. package/dist/components/ActionMenu.vue.d.ts +21 -0
  12. package/dist/components/BaseModal.vue.d.ts +17 -1
  13. package/dist/components/ExperimentTimeline.vue.d.ts +1 -1
  14. package/dist/components/GeneratedPluginView.vue.d.ts +3 -3
  15. package/dist/components/GeneratedResultRenderer.vue.d.ts +3 -3
  16. package/dist/components/RackEditor.vue.d.ts +1 -1
  17. package/dist/components/SampleLegend.vue.d.ts +1 -1
  18. package/dist/components/SmartGroupManual.vue.d.ts +1 -1
  19. package/dist/components/index.d.ts +1 -0
  20. package/dist/components/index.js +8 -8
  21. package/dist/{components-CV5zuWa8.js → components-CDomhGSj.js} +477 -71
  22. package/dist/components-CDomhGSj.js.map +1 -0
  23. package/dist/composables/controlSchemaDoseDesign.d.ts +8 -1
  24. package/dist/composables/controlSchemaModel.d.ts +10 -1
  25. package/dist/composables/index.js +8 -8
  26. package/dist/composables/useAnalysisArtifacts.d.ts +9 -1
  27. package/dist/composables/useAppExperiment.d.ts +7 -0
  28. package/dist/composables/useBioTemplatePackWorkspace.d.ts +9 -1
  29. package/dist/composables/useControlWorkspace.d.ts +9 -1
  30. package/dist/composables/useGeneratedAnalysis.d.ts +9 -0
  31. package/dist/{composables-CW8NRXLB.js → composables-CRR_JxQD.js} +4 -4
  32. package/dist/{composables-CW8NRXLB.js.map → composables-CRR_JxQD.js.map} +1 -1
  33. package/dist/{experiment-utils-7Yw-h0tD.js → experiment-utils-CLnzPPq5.js} +170 -13
  34. package/dist/experiment-utils-CLnzPPq5.js.map +1 -0
  35. package/dist/index.js +13 -13
  36. package/dist/install.js +7 -7
  37. package/dist/styles.css +764 -610
  38. package/dist/templates/index.js +4 -4
  39. package/dist/{templates-CJRFiWUX.js → templates-Cr-48-u2.js} +2 -2
  40. package/dist/{templates-CJRFiWUX.js.map → templates-Cr-48-u2.js.map} +1 -1
  41. package/dist/types/components.d.ts +32 -0
  42. package/dist/types/index.d.ts +1 -1
  43. package/dist/{useControlSchema-BEAgLyyx.js → useControlSchema-BMVb2XIQ.js} +58 -10
  44. package/dist/useControlSchema-BMVb2XIQ.js.map +1 -0
  45. package/dist/{useDropdownState-Be-ug_ci.js → useDropdownState-DSb3BC3N.js} +2 -2
  46. package/dist/{useDropdownState-Be-ug_ci.js.map → useDropdownState-DSb3BC3N.js.map} +1 -1
  47. package/dist/{useExperimentSelector-DFg_iEHI.js → useExperimentSelector-D0pjj9WH.js} +3 -3
  48. package/dist/{useExperimentSelector-DFg_iEHI.js.map → useExperimentSelector-D0pjj9WH.js.map} +1 -1
  49. package/dist/{useFormBuilder-CR9pBApW.js → useFormBuilder-DG3HOFGA.js} +2 -2
  50. package/dist/{useFormBuilder-CR9pBApW.js.map → useFormBuilder-DG3HOFGA.js.map} +1 -1
  51. package/dist/{useProtocolTemplates-DXeIHMwV.js → useProtocolTemplates-BMt0LlXf.js} +21 -6
  52. package/dist/useProtocolTemplates-BMt0LlXf.js.map +1 -0
  53. package/package.json +2 -1
  54. package/src/__tests__/components/ActionMenu.test.ts +120 -0
  55. package/src/__tests__/components/BaseModal.test.ts +133 -0
  56. package/src/__tests__/components/SettingsModal.test.ts +9 -7
  57. package/src/__tests__/docs/extractDocsComponents.test.ts +15 -1
  58. package/src/__tests__/docs/extractDocsParsing.test.ts +22 -0
  59. package/src/__tests__/docs/frontendDocsCatalog.test.ts +80 -0
  60. package/src/components/ActionMenu.story.vue +26 -0
  61. package/src/components/ActionMenu.vue +209 -0
  62. package/src/components/AppSidebar.vue +2 -13
  63. package/src/components/ArtifactSelectorModal.vue +8 -1
  64. package/src/components/BaseModal.story.vue +107 -1
  65. package/src/components/BaseModal.vue +152 -4
  66. package/src/components/BioTemplateExperimentWorkspaceView.vue +8 -1
  67. package/src/components/BioTemplatePackWorkspaceView.vue +8 -1
  68. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -1
  69. package/src/components/BioTemplateRenderer.vue +8 -1
  70. package/src/components/ComponentBindingRenderer.vue +8 -1
  71. package/src/components/ControlWorkspaceView.vue +8 -1
  72. package/src/components/DoseDesignWorkspaceView.vue +8 -1
  73. package/src/components/ExperimentSelectorModal.vue +8 -1
  74. package/src/components/FormBuilder.vue +5 -0
  75. package/src/components/GeneratedPluginView.vue +12 -2
  76. package/src/components/GeneratedResultRenderer.vue +12 -2
  77. package/src/components/JobsStatusTray.vue +8 -1
  78. package/src/components/PluginWorkspaceView.vue +10 -1
  79. package/src/components/SettingsModal.vue +102 -149
  80. package/src/components/index.ts +1 -0
  81. package/src/composables/controlSchemaDoseDesign.ts +8 -1
  82. package/src/composables/controlSchemaModel.ts +10 -1
  83. package/src/composables/useAnalysisArtifacts.ts +9 -1
  84. package/src/composables/useAppExperiment.ts +7 -0
  85. package/src/composables/useBioTemplatePackWorkspace.ts +9 -1
  86. package/src/composables/useControlWorkspace.ts +9 -1
  87. package/src/composables/useGeneratedAnalysis.ts +9 -0
  88. package/src/styles/components/action-menu.css +59 -0
  89. package/src/styles/components/icon-button.css +7 -3
  90. package/src/styles/components/modal.css +293 -0
  91. package/src/styles/components/settings-modal.css +3 -273
  92. package/src/styles/index.css +1 -0
  93. package/src/types/components.ts +38 -0
  94. package/src/types/index.ts +3 -0
  95. package/dist/ExperimentSelectorModal-DcQ38zua.js.map +0 -1
  96. package/dist/SettingsModal-Ccq2z-Ms.js.map +0 -1
  97. package/dist/components-CV5zuWa8.js.map +0 -1
  98. package/dist/experiment-utils-7Yw-h0tD.js.map +0 -1
  99. package/dist/useControlSchema-BEAgLyyx.js.map +0 -1
  100. package/dist/useProtocolTemplates-DXeIHMwV.js.map +0 -1
@@ -1,10 +1,10 @@
1
1
  import { n as __exportAll } from "./chunk-BoAXSpZd.js";
2
- import { f as BaseModal_default } from "./experiment-utils-7Yw-h0tD.js";
3
- import { E as getFieldRegistryEntry, b as controlsToSettingsSchema, f as resolveControlModel, g as mergeControlWorkspaceOptions } from "./useControlSchema-BEAgLyyx.js";
2
+ import { f as BaseModal_default } from "./experiment-utils-CLnzPPq5.js";
3
+ import { E as getFieldRegistryEntry, b as controlsToSettingsSchema, f as resolveControlModel, g as mergeControlWorkspaceOptions } from "./useControlSchema-BMVb2XIQ.js";
4
4
  import { a as colorPalettes, i as useAuthStore, o as useSettingsStore } from "./useApi-CDBq6z23.js";
5
- import { i as usePlatformContext, t as useFormBuilder } from "./useFormBuilder-CR9pBApW.js";
5
+ import { i as usePlatformContext, t as useFormBuilder } from "./useFormBuilder-DG3HOFGA.js";
6
6
  import { canAccessByPolicy } from "./permissions.js";
7
- 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
+ import { Fragment, computed, createBlock, createCommentVNode, createElementBlock, createElementVNode, createSlots, createTextVNode, createVNode, defineComponent, mergeProps, normalizeClass, normalizeProps, normalizeStyle, openBlock, ref, renderList, renderSlot, resolveDynamicComponent, toDisplayString, unref, vShow, watch, withCtx, withDirectives } from "vue";
8
8
  //#region src/utils/items.ts
9
9
  function normalizeItemInput(item) {
10
10
  if (typeof item === "object") return item;
@@ -200,59 +200,17 @@ function buildSettingsTabs(baseTabs, showAppearance) {
200
200
  }
201
201
  //#endregion
202
202
  //#region src/components/SettingsModal.vue?vue&type=script&setup=true&lang.ts
203
- var _hoisted_1 = {
204
- key: 0,
205
- class: "mint-settings-modal__tabs"
206
- };
207
- var _hoisted_2 = ["onClick"];
208
- var _hoisted_3 = {
209
- key: 1,
210
- class: "mint-settings-modal__rail",
211
- role: "tablist",
212
- "aria-orientation": "vertical",
213
- "aria-label": "Settings sections"
214
- };
215
- var _hoisted_4 = [
216
- "id",
217
- "aria-selected",
218
- "aria-controls",
219
- "tabindex",
220
- "onClick"
221
- ];
222
- var _hoisted_5 = {
223
- class: "mint-settings-modal__rail-item-icon",
224
- "aria-hidden": "true"
225
- };
226
- var _hoisted_6 = ["innerHTML"];
227
- var _hoisted_7 = { class: "mint-settings-modal__rail-item-text" };
228
- var _hoisted_8 = { class: "mint-settings-modal__rail-item-label" };
229
- var _hoisted_9 = {
230
- key: 0,
231
- class: "mint-settings-modal__rail-item-description"
232
- };
233
- var _hoisted_10 = {
234
- key: 0,
235
- class: "mint-settings-modal__pane-header"
236
- };
237
- var _hoisted_11 = { class: "mint-settings-modal__pane-title" };
238
- var _hoisted_12 = {
239
- key: 0,
240
- class: "mint-settings-modal__pane-subtitle"
241
- };
242
- var _hoisted_13 = { key: 2 };
243
- var _hoisted_14 = { class: "mint-settings-modal__section" };
244
- var _hoisted_15 = { class: "mint-settings-modal__option-group" };
245
- var _hoisted_16 = ["onClick"];
246
- var _hoisted_17 = { class: "mint-settings-modal__section" };
247
- var _hoisted_18 = { class: "mint-settings-modal__option-group" };
248
- var _hoisted_19 = ["onClick"];
249
- var _hoisted_20 = { class: "mint-settings-modal__section" };
250
- var _hoisted_21 = { class: "mint-settings-modal__option-group" };
251
- var _hoisted_22 = ["onClick"];
252
- var _hoisted_23 = {
253
- key: 0,
254
- class: "mint-settings-modal__footer"
255
- };
203
+ var _hoisted_1 = { class: "mint-settings-modal" };
204
+ var _hoisted_2 = { key: 2 };
205
+ var _hoisted_3 = { class: "mint-settings-modal__section" };
206
+ var _hoisted_4 = { class: "mint-settings-modal__option-group" };
207
+ var _hoisted_5 = ["onClick"];
208
+ var _hoisted_6 = { class: "mint-settings-modal__section" };
209
+ var _hoisted_7 = { class: "mint-settings-modal__option-group" };
210
+ var _hoisted_8 = ["onClick"];
211
+ var _hoisted_9 = { class: "mint-settings-modal__section" };
212
+ var _hoisted_10 = { class: "mint-settings-modal__option-group" };
213
+ var _hoisted_11 = ["onClick"];
256
214
  var SettingsModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */ defineComponent({
257
215
  __name: "SettingsModal",
258
216
  props: {
@@ -297,6 +255,11 @@ var SettingsModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
297
255
  *
298
256
  * Layout: `horizontal` (underline tabs, default) or `vertical` (sidebar rail
299
257
  * with optional icons + descriptions, recommended for 5+ groups).
258
+ *
259
+ * @example Recommended
260
+ * ```vue
261
+ * <SettingsModal v-model="open" v-model:values="values" :model="settingsModel" />
262
+ * ```
300
263
  */
301
264
  const props = __props;
302
265
  const emit = __emit;
@@ -304,9 +267,6 @@ var SettingsModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
304
267
  const auth = useAuthStore();
305
268
  const { user: platformUser } = usePlatformContext();
306
269
  const isVertical = computed(() => props.layout === "vertical");
307
- const uid = `mint-settings-${Math.random().toString(36).slice(2, 9)}`;
308
- const tabId = (id) => `${uid}-tab-${id}`;
309
- const panelId = (id) => `${uid}-panel-${id}`;
310
270
  const resolvedModel = computed(() => {
311
271
  return resolveControlModel(props.model);
312
272
  });
@@ -359,7 +319,17 @@ var SettingsModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
359
319
  return buildSettingsTabs(settingsSchema.value ? visibleSchemaGroups.value.map(settingsGroupToTab) : manualTabs.value, props.showAppearance);
360
320
  });
361
321
  const activeTab = ref(allTabs.value[0]?.id || "appearance");
362
- const activeTabMeta = computed(() => allTabs.value.find((t) => t.id === activeTab.value));
322
+ const baseLayout = computed(() => {
323
+ if (isVertical.value) return "rail";
324
+ return allTabs.value.length > 1 ? "tabs" : "plain";
325
+ });
326
+ const modalTabs = computed(() => allTabs.value.map((tab) => ({
327
+ id: tab.id,
328
+ label: tab.label,
329
+ icon: tab.icon,
330
+ description: tab.description,
331
+ meta: tab.meta
332
+ })));
363
333
  watch(allTabs, (tabs) => {
364
334
  if (!tabs.some((t) => t.id === activeTab.value)) activeTab.value = tabs[0]?.id ?? "appearance";
365
335
  });
@@ -411,108 +381,82 @@ var SettingsModal_vue_vue_type_script_setup_true_lang_default = /* @__PURE__ */
411
381
  "model-value": __props.modelValue,
412
382
  title: __props.title,
413
383
  size: __props.size,
414
- "onUpdate:modelValue": _cache[0] || (_cache[0] = ($event) => emit("update:modelValue", $event)),
384
+ layout: baseLayout.value,
385
+ tabs: modalTabs.value,
386
+ "active-tab": activeTab.value,
387
+ "onUpdate:activeTab": _cache[0] || (_cache[0] = ($event) => activeTab.value = $event),
388
+ "onUpdate:modelValue": _cache[1] || (_cache[1] = ($event) => emit("update:modelValue", $event)),
415
389
  onClose: handleClose
416
- }, {
417
- 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) => {
418
- return openBlock(), createElementBlock("button", {
419
- key: tab.id,
420
- type: "button",
421
- class: normalizeClass(["mint-settings-modal__tab", { "mint-settings-modal__tab--active": activeTab.value === tab.id }]),
422
- onClick: ($event) => activeTab.value = tab.id
423
- }, toDisplayString(tab.label), 11, _hoisted_2);
424
- }), 128))])) : isVertical.value ? (openBlock(), createElementBlock("div", _hoisted_3, [(openBlock(true), createElementBlock(Fragment, null, renderList(allTabs.value, (tab) => {
425
- return openBlock(), createElementBlock("button", {
426
- id: tabId(tab.id),
427
- key: tab.id,
428
- type: "button",
429
- role: "tab",
430
- class: normalizeClass(["mint-settings-modal__rail-item", { "mint-settings-modal__rail-item--active": activeTab.value === tab.id }]),
431
- "aria-selected": activeTab.value === tab.id,
432
- "aria-controls": panelId(tab.id),
433
- tabindex: activeTab.value === tab.id ? 0 : -1,
434
- onClick: ($event) => activeTab.value = tab.id
435
- }, [createElementVNode("span", _hoisted_5, [tab.icon ? (openBlock(), createElementBlock("span", {
436
- key: 0,
437
- innerHTML: tab.icon
438
- }, 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);
439
- }), 128))])) : createCommentVNode("", true), (openBlock(), createBlock(resolveDynamicComponent(isVertical.value ? "section" : "div"), {
440
- class: normalizeClass(isVertical.value ? "mint-settings-modal__pane" : "mint-settings-modal__content"),
441
- id: isVertical.value && activeTabMeta.value ? panelId(activeTabMeta.value.id) : void 0,
442
- role: isVertical.value ? "tabpanel" : void 0,
443
- "aria-labelledby": isVertical.value && activeTabMeta.value ? tabId(activeTabMeta.value.id) : void 0,
444
- tabindex: isVertical.value ? 0 : void 0
445
- }, {
446
- 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", {
447
- key: 0,
448
- class: "mint-settings-modal__group-grid",
449
- style: normalizeStyle({ "--mint-settings-cols": activeGroup.value.columns ?? 1 })
450
- }, [(openBlock(true), createElementBlock(Fragment, null, renderList(activeGroupVisibleFields.value, (field) => {
451
- return openBlock(), createElementBlock("div", {
452
- key: field.name,
453
- style: normalizeStyle(field.colSpan ? { gridColumn: `span ${field.colSpan}` } : void 0)
454
- }, [renderSlot(_ctx.$slots, `field:${field.name}`, {
455
- field,
456
- form: unref(builder).form,
457
- fieldProps: unref(builder).form.getFieldProps(field.name)
458
- }, () => [createVNode(FormFieldRendererInternal_default, {
459
- field,
460
- "resolved-props": unref(builder).getResolvedFieldProps(field),
461
- form: unref(builder).form
462
- }, null, 8, [
463
- "field",
464
- "resolved-props",
465
- "form"
466
- ])])], 4);
467
- }), 128))], 4)) : !isSchemaDriven.value ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(manualTabs.value, (tab) => {
468
- return withDirectives((openBlock(), createElementBlock("div", { key: tab.id }, [renderSlot(_ctx.$slots, `tab-${tab.id}`)], 512)), [[vShow, activeTab.value === tab.id]]);
469
- }), 128)) : createCommentVNode("", true), __props.showAppearance ? withDirectives((openBlock(), createElementBlock("div", _hoisted_13, [
470
- 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) => {
390
+ }, createSlots({
391
+ default: withCtx(() => [createElementVNode("div", _hoisted_1, [isSchemaDriven.value && activeGroup.value ? (openBlock(), createElementBlock("div", {
392
+ key: 0,
393
+ class: "mint-settings-modal__group-grid",
394
+ style: normalizeStyle({ "--mint-settings-cols": activeGroup.value.columns ?? 1 })
395
+ }, [(openBlock(true), createElementBlock(Fragment, null, renderList(activeGroupVisibleFields.value, (field) => {
396
+ return openBlock(), createElementBlock("div", {
397
+ key: field.name,
398
+ style: normalizeStyle(field.colSpan ? { gridColumn: `span ${field.colSpan}` } : void 0)
399
+ }, [renderSlot(_ctx.$slots, `field:${field.name}`, {
400
+ field,
401
+ form: unref(builder).form,
402
+ fieldProps: unref(builder).form.getFieldProps(field.name)
403
+ }, () => [createVNode(FormFieldRendererInternal_default, {
404
+ field,
405
+ "resolved-props": unref(builder).getResolvedFieldProps(field),
406
+ form: unref(builder).form
407
+ }, null, 8, [
408
+ "field",
409
+ "resolved-props",
410
+ "form"
411
+ ])])], 4);
412
+ }), 128))], 4)) : !isSchemaDriven.value ? (openBlock(true), createElementBlock(Fragment, { key: 1 }, renderList(manualTabs.value, (tab) => {
413
+ return withDirectives((openBlock(), createElementBlock("div", { key: tab.id }, [renderSlot(_ctx.$slots, `tab-${tab.id}`)], 512)), [[vShow, activeTab.value === tab.id]]);
414
+ }), 128)) : createCommentVNode("", true), __props.showAppearance ? withDirectives((openBlock(), createElementBlock("div", _hoisted_2, [
415
+ createElementVNode("div", _hoisted_3, [_cache[2] || (_cache[2] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Theme", -1)), createElementVNode("div", _hoisted_4, [(openBlock(), createElementBlock(Fragment, null, renderList(themeOptions, (opt) => {
416
+ return createElementVNode("button", {
417
+ key: opt.value,
418
+ type: "button",
419
+ class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).theme === opt.value }]),
420
+ onClick: ($event) => unref(settings).theme = opt.value
421
+ }, toDisplayString(opt.label), 11, _hoisted_5);
422
+ }), 64))])]),
423
+ createElementVNode("div", _hoisted_6, [_cache[3] || (_cache[3] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Color Palette", -1)), createElementVNode("div", _hoisted_7, [(openBlock(true), createElementBlock(Fragment, null, renderList(unref(colorPalettes), (palette, key) => {
424
+ return openBlock(), createElementBlock("button", {
425
+ key,
426
+ type: "button",
427
+ class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).colorPalette === key }]),
428
+ onClick: ($event) => unref(settings).colorPalette = key
429
+ }, toDisplayString(palette.name), 11, _hoisted_8);
430
+ }), 128))])]),
431
+ createElementVNode("div", _hoisted_9, [
432
+ _cache[4] || (_cache[4] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Table Density", -1)),
433
+ createElementVNode("div", _hoisted_10, [(openBlock(), createElementBlock(Fragment, null, renderList(densityOptions, (opt) => {
471
434
  return createElementVNode("button", {
472
435
  key: opt.value,
473
436
  type: "button",
474
- class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).theme === opt.value }]),
475
- onClick: ($event) => unref(settings).theme = opt.value
476
- }, toDisplayString(opt.label), 11, _hoisted_16);
477
- }), 64))])]),
478
- 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) => {
479
- return openBlock(), createElementBlock("button", {
480
- key,
481
- type: "button",
482
- class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).colorPalette === key }]),
483
- onClick: ($event) => unref(settings).colorPalette = key
484
- }, toDisplayString(palette.name), 11, _hoisted_19);
485
- }), 128))])]),
486
- createElementVNode("div", _hoisted_20, [
487
- _cache[3] || (_cache[3] = createElementVNode("div", { class: "mint-settings-modal__section-label" }, "Table Density", -1)),
488
- createElementVNode("div", _hoisted_21, [(openBlock(), createElementBlock(Fragment, null, renderList(densityOptions, (opt) => {
489
- return createElementVNode("button", {
490
- key: opt.value,
491
- type: "button",
492
- class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).tableDensity === opt.value }]),
493
- onClick: ($event) => unref(settings).tableDensity = opt.value
494
- }, toDisplayString(opt.label), 11, _hoisted_22);
495
- }), 64))]),
496
- _cache[4] || (_cache[4] = createElementVNode("p", { class: "mint-settings-modal__note" }, "Adjusts row height in data tables.", -1))
497
- ]),
498
- renderSlot(_ctx.$slots, "appearance")
499
- ], 512)), [[vShow, activeTab.value === unref(APPEARANCE_TAB_ID)]]) : createCommentVNode("", true)], 2)]),
500
- _: 3
501
- }, 8, [
502
- "class",
503
- "id",
504
- "role",
505
- "aria-labelledby",
506
- "tabindex"
507
- ]))], 2), _ctx.$slots.footer ? (openBlock(), createElementBlock("div", _hoisted_23, [renderSlot(_ctx.$slots, "footer", {
437
+ class: normalizeClass(["mint-settings-modal__option-btn", { "mint-settings-modal__option-btn--active": unref(settings).tableDensity === opt.value }]),
438
+ onClick: ($event) => unref(settings).tableDensity = opt.value
439
+ }, toDisplayString(opt.label), 11, _hoisted_11);
440
+ }), 64))]),
441
+ _cache[5] || (_cache[5] = createElementVNode("p", { class: "mint-settings-modal__note" }, "Adjusts row height in data tables.", -1))
442
+ ]),
443
+ renderSlot(_ctx.$slots, "appearance")
444
+ ], 512)), [[vShow, activeTab.value === unref(APPEARANCE_TAB_ID)]]) : createCommentVNode("", true)])]),
445
+ _: 2
446
+ }, [_ctx.$slots.footer ? {
447
+ name: "footer",
448
+ fn: withCtx(() => [renderSlot(_ctx.$slots, "footer", {
508
449
  values: unref(builder).form.data,
509
450
  close: handleClose
510
- })])) : createCommentVNode("", true)]),
511
- _: 3
512
- }, 8, [
451
+ })]),
452
+ key: "0"
453
+ } : void 0]), 1032, [
513
454
  "model-value",
514
455
  "title",
515
- "size"
456
+ "size",
457
+ "layout",
458
+ "tabs",
459
+ "active-tab"
516
460
  ]);
517
461
  };
518
462
  }
@@ -524,4 +468,4 @@ var SettingsModal_default = SettingsModal_vue_vue_type_script_setup_true_lang_de
524
468
  //#endregion
525
469
  export { pickExistingRecordKeys as a, normalizeItemInput as c, formSchemaFieldNames as i, normalizeLabelItemInput as l, SettingsModal_exports as n, recordValuesEqualForKeys as o, FormFieldRendererInternal_default as r, FormField_default as s, SettingsModal_default as t };
526
470
 
527
- //# sourceMappingURL=SettingsModal-Ccq2z-Ms.js.map
471
+ //# sourceMappingURL=SettingsModal-D7LFUokT.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SettingsModal-D7LFUokT.js","names":["$slots"],"sources":["../src/utils/items.ts","../src/components/FormField.vue","../src/components/FormField.vue","../src/utils/formModelSync.ts","../src/components/internal/FormFieldRendererInternal.vue","../src/components/internal/FormFieldRendererInternal.vue","../src/components/SettingsModal.schema.ts","../src/components/SettingsModal.vue","../src/components/SettingsModal.vue"],"sourcesContent":["export type ItemWithLabel = {\n label: string\n}\n\nexport type ItemWithId = ItemWithLabel & {\n id: string\n}\n\nexport function normalizeItemInput<TItem extends ItemWithId>(\n item: TItem | string,\n): TItem {\n if (typeof item === 'object') return item\n\n return {\n id: item,\n label: item,\n } as TItem\n}\n\nexport function normalizeLabelItemInput<TItem extends ItemWithLabel>(\n item: TItem | string,\n): TItem {\n if (typeof item === 'object') return item\n\n return {\n label: item,\n } as TItem\n}\n","<script setup lang=\"ts\">\n/** Wraps a form control with a label, optional hint text, and validation error display. */\nimport { computed } from 'vue'\n\ninterface Props {\n label?: string\n error?: string\n hint?: string\n required?: boolean\n showOptional?: boolean\n htmlFor?: string\n fieldId?: string\n}\n\nconst props = defineProps<Props>()\n\nconst errorId = computed(() =>\n props.error && props.fieldId ? `${props.fieldId}-error` : undefined\n)\n\nconst hintId = computed(() =>\n !props.error && props.hint && props.fieldId ? `${props.fieldId}-hint` : undefined\n)\n\nconst describedBy = computed(() => errorId.value ?? hintId.value)\n</script>\n\n<template>\n <div class=\"mint-form-field\">\n <div v-if=\"label\" class=\"mint-form-field__label-row\">\n <label\n :for=\"htmlFor\"\n class=\"mint-form-field__label\"\n >\n {{ label }}\n <span v-if=\"required\" class=\"mint-form-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <span\n v-if=\"!required && showOptional\"\n class=\"mint-form-field__optional\"\n >\n optional\n </span>\n </div>\n\n <slot :described-by=\"describedBy\" />\n\n <p v-if=\"error\" :id=\"errorId\" class=\"mint-form-field__error\" role=\"alert\">\n {{ error }}\n </p>\n <p v-else-if=\"hint\" :id=\"hintId\" class=\"mint-form-field__hint\">\n {{ hint }}\n </p>\n </div>\n</template>\n\n<style>\n@import '../styles/components/form-field.css';\n</style>\n","<script setup lang=\"ts\">\n/** Wraps a form control with a label, optional hint text, and validation error display. */\nimport { computed } from 'vue'\n\ninterface Props {\n label?: string\n error?: string\n hint?: string\n required?: boolean\n showOptional?: boolean\n htmlFor?: string\n fieldId?: string\n}\n\nconst props = defineProps<Props>()\n\nconst errorId = computed(() =>\n props.error && props.fieldId ? `${props.fieldId}-error` : undefined\n)\n\nconst hintId = computed(() =>\n !props.error && props.hint && props.fieldId ? `${props.fieldId}-hint` : undefined\n)\n\nconst describedBy = computed(() => errorId.value ?? hintId.value)\n</script>\n\n<template>\n <div class=\"mint-form-field\">\n <div v-if=\"label\" class=\"mint-form-field__label-row\">\n <label\n :for=\"htmlFor\"\n class=\"mint-form-field__label\"\n >\n {{ label }}\n <span v-if=\"required\" class=\"mint-form-field__required\" aria-hidden=\"true\">*</span>\n </label>\n <span\n v-if=\"!required && showOptional\"\n class=\"mint-form-field__optional\"\n >\n optional\n </span>\n </div>\n\n <slot :described-by=\"describedBy\" />\n\n <p v-if=\"error\" :id=\"errorId\" class=\"mint-form-field__error\" role=\"alert\">\n {{ error }}\n </p>\n <p v-else-if=\"hint\" :id=\"hintId\" class=\"mint-form-field__hint\">\n {{ hint }}\n </p>\n </div>\n</template>\n\n<style>\n@import '../styles/components/form-field.css';\n</style>\n","import type { FormSchema } from '../types/form-builder'\n\nexport function recordValuesEqualForKeys(\n left: Record<string, unknown>,\n right: Record<string, unknown>,\n keys: readonly string[],\n): boolean {\n for (const key of keys) {\n if (!valuesEqual(left[key], right[key])) return false\n }\n return true\n}\n\nexport function pickRecordKeys(\n source: Record<string, unknown>,\n keys: readonly string[],\n): Record<string, unknown> {\n return Object.fromEntries(keys.map(key => [key, source[key]]))\n}\n\nexport function pickExistingRecordKeys(\n source: Record<string, unknown>,\n keys: readonly string[],\n): Record<string, unknown> {\n return Object.fromEntries(\n keys\n .filter(key => Object.prototype.hasOwnProperty.call(source, key))\n .map(key => [key, source[key]]),\n )\n}\n\nexport function formSchemaFieldNames(schema: FormSchema): string[] {\n const sections = schema.steps\n ? schema.steps.flatMap(step => step.sections)\n : schema.sections\n return sections.flatMap(section => section.fields.map(field => field.name))\n}\n\nfunction valuesEqual(left: unknown, right: unknown): boolean {\n if (Object.is(left, right)) return true\n if (Array.isArray(left) && Array.isArray(right)) {\n return left.length === right.length && left.every((item, index) => valuesEqual(item, right[index]))\n }\n if (isRecord(left) && isRecord(right)) {\n return recordValuesEqualForKeys(left, right, [...new Set([...Object.keys(left), ...Object.keys(right)])])\n }\n return false\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { FormFieldSchema } from '../../types/form-builder'\nimport type { UseFormReturn } from '../../composables/useForm'\nimport { getFieldRegistryEntry } from '../../composables/formBuilderRegistry'\nimport FormField from '../FormField.vue'\n\ninterface Props {\n field: FormFieldSchema\n resolvedProps: Record<string, unknown>\n form: UseFormReturn<Record<string, unknown>>\n}\n\nconst props = defineProps<Props>()\n\nconst entry = computed(() => getFieldRegistryEntry(props.field.type))\n\nconst isChoiceField = computed(() =>\n props.field.type === 'checkbox' || props.field.type === 'toggle',\n)\n\nconst componentProps = computed<Record<string, unknown>>(() => {\n if (!isChoiceField.value) return props.resolvedProps\n\n return {\n variant: 'row',\n label: props.field.label,\n description: props.field.hint,\n icon: props.field.icon,\n iconColor: props.field.iconColor,\n iconBg: props.field.iconBg,\n ...props.resolvedProps,\n }\n})\n\nconst errorMessage = computed(() => {\n const name = props.field.name\n return props.form.touched[name] ? props.form.errors[name] : null\n})\n\nfunction handleUpload(files: File[]) {\n props.form.setFieldValue(props.field.name, files)\n}\n</script>\n\n<template>\n <FormField\n :label=\"isChoiceField ? undefined : field.label\"\n :error=\"errorMessage ?? undefined\"\n :hint=\"isChoiceField ? undefined : field.hint\"\n :required=\"!!field.validation?.required\"\n :html-for=\"isChoiceField ? undefined : field.name\"\n >\n <slot :name=\"`field:${field.name}`\" :field=\"field\" :form=\"form\" :field-props=\"form.getFieldProps(field.name)\">\n <component\n :is=\"entry.component\"\n v-if=\"entry.vModel\"\n v-bind=\"componentProps\"\n />\n <component\n :is=\"entry.component\"\n v-else\n v-bind=\"componentProps\"\n @upload=\"handleUpload\"\n />\n </slot>\n </FormField>\n</template>\n","<script setup lang=\"ts\">\nimport { computed } from 'vue'\nimport type { FormFieldSchema } from '../../types/form-builder'\nimport type { UseFormReturn } from '../../composables/useForm'\nimport { getFieldRegistryEntry } from '../../composables/formBuilderRegistry'\nimport FormField from '../FormField.vue'\n\ninterface Props {\n field: FormFieldSchema\n resolvedProps: Record<string, unknown>\n form: UseFormReturn<Record<string, unknown>>\n}\n\nconst props = defineProps<Props>()\n\nconst entry = computed(() => getFieldRegistryEntry(props.field.type))\n\nconst isChoiceField = computed(() =>\n props.field.type === 'checkbox' || props.field.type === 'toggle',\n)\n\nconst componentProps = computed<Record<string, unknown>>(() => {\n if (!isChoiceField.value) return props.resolvedProps\n\n return {\n variant: 'row',\n label: props.field.label,\n description: props.field.hint,\n icon: props.field.icon,\n iconColor: props.field.iconColor,\n iconBg: props.field.iconBg,\n ...props.resolvedProps,\n }\n})\n\nconst errorMessage = computed(() => {\n const name = props.field.name\n return props.form.touched[name] ? props.form.errors[name] : null\n})\n\nfunction handleUpload(files: File[]) {\n props.form.setFieldValue(props.field.name, files)\n}\n</script>\n\n<template>\n <FormField\n :label=\"isChoiceField ? undefined : field.label\"\n :error=\"errorMessage ?? undefined\"\n :hint=\"isChoiceField ? undefined : field.hint\"\n :required=\"!!field.validation?.required\"\n :html-for=\"isChoiceField ? undefined : field.name\"\n >\n <slot :name=\"`field:${field.name}`\" :field=\"field\" :form=\"form\" :field-props=\"form.getFieldProps(field.name)\">\n <component\n :is=\"entry.component\"\n v-if=\"entry.vModel\"\n v-bind=\"componentProps\"\n />\n <component\n :is=\"entry.component\"\n v-else\n v-bind=\"componentProps\"\n @upload=\"handleUpload\"\n />\n </slot>\n </FormField>\n</template>\n","import type {\n FormSchema,\n FormSectionSchema,\n SettingsGroup,\n SettingsModalSchema,\n SettingsTab,\n SettingsTabInput,\n} from '../types'\nimport type { AccessControlled } from '../permissions'\nimport { normalizeItemInput } from '../utils/items'\n\nexport const APPEARANCE_TAB_ID = 'appearance'\n\nexport const APPEARANCE_TAB: SettingsTab = {\n id: APPEARANCE_TAB_ID,\n label: 'Appearance',\n description: 'Theme, color palette, and table density',\n}\n\n// Map settings groups onto the form-builder's flat-section shape.\n// `title: ''` because the rail/pane header already shows the group name.\nexport function buildFlatSettingsSchema(schema: SettingsModalSchema): FormSchema {\n return {\n sections: schema.groups.map<FormSectionSchema>((group) => ({\n id: group.id,\n title: '',\n fields: group.fields,\n columns: group.columns,\n condition: group.condition,\n })),\n }\n}\n\nexport function filterSettingsSchemaByAccess(\n schema: SettingsModalSchema,\n canShow: (item: AccessControlled) => boolean\n): SettingsModalSchema {\n const groups = schema.groups.flatMap((group) => {\n if (!canShow(group)) return []\n\n const fields = group.fields.filter(canShow)\n if (fields.length === 0) return []\n\n return [{ ...group, fields }]\n })\n\n return { groups }\n}\n\nexport function settingsGroupToTab(group: SettingsGroup): SettingsTab {\n return {\n id: group.id,\n label: group.label,\n icon: group.icon,\n description: group.description,\n }\n}\n\nexport function normalizeVisibleSettingsTabs(\n tabs: SettingsTabInput[],\n canShow: (item: AccessControlled) => boolean\n): SettingsTab[] {\n return tabs.map(normalizeItemInput).filter(canShow)\n}\n\nexport function buildSettingsTabs(\n baseTabs: SettingsTab[],\n showAppearance: boolean\n): SettingsTab[] {\n return showAppearance ? [...baseTabs, APPEARANCE_TAB] : baseTabs\n}\n","<script setup lang=\"ts\">\n/**\n * Tabbed settings modal with three usage modes:\n *\n * 1. Schema-driven (recommended) — pass `schema`, compact `controls`, or a\n * complete `defineControlModel()` result plus `v-model:values`. Each\n * group/section becomes a tab; fields auto-render via the SDK form field\n * registry (text, select, number, toggle, molecule, concentration, …).\n * Conditional visibility, validation, and dynamic options come for free.\n *\n * 2. Manual tabs + slots — pass `tabs` and a `<template #tab-{id}>` slot\n * per tab. Use this when you need bespoke widgets the form-builder\n * registry doesn't cover (or for legacy plugins).\n *\n * 3. Appearance only — `showAppearance` (default true) renders the built-in\n * theme / palette / table-density tab. Works alongside both modes above.\n *\n * Layout: `horizontal` (underline tabs, default) or `vertical` (sidebar rail\n * with optional icons + descriptions, recommended for 5+ groups).\n *\n * @example Recommended\n * ```vue\n * <SettingsModal v-model=\"open\" v-model:values=\"values\" :model=\"settingsModel\" />\n * ```\n */\nimport { ref, computed, watch } from 'vue'\nimport BaseModal from './BaseModal.vue'\nimport FormFieldRendererInternal from './internal/FormFieldRendererInternal.vue'\nimport { useFormBuilder } from '../composables/useFormBuilder'\nimport {\n controlsToSettingsSchema,\n mergeControlWorkspaceOptions,\n resolveControlModel,\n type ControlModel,\n type ControlModelBinding,\n type ControlSchema,\n type ControlWorkspaceOptions,\n} from '../composables/useControlSchema'\nimport { useSettingsStore, colorPalettes } from '../stores/settings'\nimport { useAuthStore } from '../stores/auth'\nimport { usePlatformContext } from '../composables/usePlatformContext'\nimport { canAccessByPolicy } from '../permissions'\nimport {\n formSchemaFieldNames,\n pickExistingRecordKeys,\n pickRecordKeys,\n recordValuesEqualForKeys,\n} from '../utils/formModelSync'\nimport type {\n ThemeMode,\n ColorPalette,\n TableDensity,\n ModalLayout,\n ModalTab,\n SettingsTab,\n SettingsTabInput,\n SettingsModalLayout,\n SettingsModalSchema,\n SettingsUserType,\n FormEnhancements,\n} from '../types'\nimport type { AccessControlled, PermissionUser } from '../permissions'\nimport {\n APPEARANCE_TAB_ID,\n buildFlatSettingsSchema,\n buildSettingsTabs,\n filterSettingsSchemaByAccess,\n normalizeVisibleSettingsTabs,\n settingsGroupToTab,\n} from './SettingsModal.schema'\n\ninterface Props {\n modelValue: boolean\n title?: string\n /** Manual tab descriptors. Ignored when `schema` is set (groups become tabs). */\n tabs?: SettingsTabInput[]\n showAppearance?: boolean\n size?: 'md' | 'lg' | 'xl'\n layout?: SettingsModalLayout\n /** Declarative schema — fields auto-render via SDK form components. */\n schema?: SettingsModalSchema\n /** Model returned by defineControlModel(), or a raw nested ControlModel for one-step settings generation. */\n model?: ControlModel | ControlModelBinding\n /** Compact controls model — converted to `schema` when `schema` is not set. */\n controls?: ControlSchema\n /** Conversion options for `controls`, such as section labels, columns, and shared initialValues. */\n controlOptions?: ControlWorkspaceOptions\n /** Two-way bound values when `schema`, `model`, or `controls` is set. */\n values?: Record<string, unknown>\n /** Optional dynamic enhancements (validators, dynamic options, callbacks). */\n enhancements?: FormEnhancements<Record<string, unknown>>\n /** Optional user type override for permission-filtered settings content. Defaults to SDK auth/platform context. */\n userType?: SettingsUserType\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Settings',\n tabs: () => [],\n showAppearance: true,\n size: 'lg',\n layout: 'horizontal',\n model: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'update:values': [data: Record<string, unknown>]\n close: []\n}>()\n\nconst settings = useSettingsStore()\nconst auth = useAuthStore()\nconst { user: platformUser } = usePlatformContext()\n\nconst isVertical = computed(() => props.layout === 'vertical')\n\nconst resolvedModel = computed<ControlModelBinding | undefined>(() => {\n return resolveControlModel(props.model)\n})\nconst resolvedControls = computed<ControlSchema | undefined>(() =>\n props.controls ?? resolvedModel.value?.controls,\n)\nconst resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>\n mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)\n)\nconst sourceSettingsSchema = computed<SettingsModalSchema | undefined>(() =>\n props.schema ?? (\n resolvedControls.value\n ? controlsToSettingsSchema(resolvedControls.value, resolvedControlOptions.value)\n : undefined\n ),\n)\nconst currentAccessUser = computed<PermissionUser | null>(() => {\n if (props.userType) {\n return { role: props.userType === 'admin' ? 'admin' : 'user' }\n }\n return auth.userInfo ?? platformUser.value ?? null\n})\nconst isAccessUserAuthenticated = computed(() =>\n props.userType !== undefined || auth.isAuthenticated || !!platformUser.value,\n)\nconst settingsSchema = computed<SettingsModalSchema | undefined>(() => {\n if (!sourceSettingsSchema.value) return undefined\n return filterSettingsSchemaByAccess(sourceSettingsSchema.value, canShowForCurrentUser)\n})\nconst isSchemaDriven = computed(() => !!settingsSchema.value)\nconst resolvedValues = computed<Record<string, unknown>>(() => ({\n ...(resolvedControlOptions.value.initialValues ?? {}),\n ...(props.values ?? {}),\n}))\n\n// Schema-driven mode keeps one form-builder instance and syncs schema changes\n// into it, so callers can swap groups/fields without remounting the modal.\nconst builder = useFormBuilder(\n settingsSchema.value ? buildFlatSettingsSchema(settingsSchema.value) : { sections: [] },\n resolvedValues.value,\n props.enhancements,\n)\n\nwatch(\n () => settingsSchema.value,\n (schema) => {\n if (!schema) {\n builder.updateSchema({ sections: [] }, {})\n return\n }\n\n const flatSchema = buildFlatSettingsSchema(schema)\n const fieldNames = formSchemaFieldNames(flatSchema)\n const sourceValues = props.values === undefined\n ? {\n ...resolvedValues.value,\n ...(builder.form.data as Record<string, unknown>),\n }\n : resolvedValues.value\n\n builder.updateSchema(flatSchema, pickExistingRecordKeys(sourceValues ?? {}, fieldNames))\n },\n { deep: true },\n)\n\nwatch(\n () => ({ ...resolvedValues.value }),\n (data) => {\n if (!settingsSchema.value) return\n const fieldNames = builderFieldNames()\n if (recordValuesEqualForKeys(data, builder.form.data as Record<string, unknown>, fieldNames)) return\n builder.reset(pickRecordKeys(data, fieldNames))\n },\n { deep: true },\n)\n\nwatch(\n () => ({ ...builder.form.data }),\n (data) => {\n if (settingsSchema.value) {\n emit('update:values', {\n ...resolvedValues.value,\n ...data,\n })\n }\n },\n { deep: true },\n)\n\n// Schema groups whose `condition` evaluates false against the current data are\n// dropped from the rail entirely — same semantics as section visibility in\n// FormBuilder. Manual `tabs` have no condition mechanism, so they pass through.\nconst visibleSchemaGroups = computed(() =>\n settingsSchema.value\n ? settingsSchema.value.groups.filter((g) => builder.isSectionVisible(g.id))\n : [],\n)\n\nconst manualTabs = computed<SettingsTab[]>(() =>\n normalizeVisibleSettingsTabs(props.tabs, canShowForCurrentUser)\n)\n\nconst allTabs = computed<SettingsTab[]>(() => {\n const base: SettingsTab[] = settingsSchema.value\n ? visibleSchemaGroups.value.map(settingsGroupToTab)\n : manualTabs.value\n return buildSettingsTabs(base, props.showAppearance)\n})\n\nconst activeTab = ref(allTabs.value[0]?.id || APPEARANCE_TAB_ID)\n\n// BaseModal owns the tab chrome: 'vertical' keeps its public name and maps to\n// the shell rail; horizontal maps to the shell strip (plain when single-tab).\nconst baseLayout = computed<ModalLayout>(() => {\n if (isVertical.value) return 'rail'\n return allTabs.value.length > 1 ? 'tabs' : 'plain'\n})\n\nconst modalTabs = computed<ModalTab[]>(() =>\n allTabs.value.map((tab) => ({\n id: tab.id,\n label: tab.label,\n icon: tab.icon,\n description: tab.description,\n meta: tab.meta,\n })),\n)\n\n// If the active tab vanishes (group hidden by condition), drop back to the first available.\nwatch(allTabs, (tabs) => {\n if (!tabs.some((t) => t.id === activeTab.value)) {\n activeTab.value = tabs[0]?.id ?? APPEARANCE_TAB_ID\n }\n})\n\nconst activeGroup = computed(() =>\n visibleSchemaGroups.value.find((g) => g.id === activeTab.value),\n)\n\nconst activeGroupVisibleFields = computed(() => {\n if (!activeGroup.value) return []\n return activeGroup.value.fields.filter((f) => builder.isFieldVisible(f.name))\n})\n\nconst themeOptions: { value: ThemeMode; label: string }[] = [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'system', label: 'System' },\n]\n\nconst densityOptions: { value: TableDensity; label: string }[] = [\n { value: 'compact', label: 'Compact' },\n { value: 'normal', label: 'Normal' },\n { value: 'comfortable', label: 'Comfortable' },\n]\n\nfunction handleClose() {\n emit('update:modelValue', false)\n emit('close')\n}\n\nfunction builderFieldNames(): string[] {\n return builder.fields.map(field => field.name)\n}\n\nfunction canShowForCurrentUser(item: AccessControlled): boolean {\n return canAccessByPolicy(\n currentAccessUser.value,\n item,\n isAccessUserAuthenticated.value,\n )\n}\n</script>\n\n<template>\n <BaseModal\n :model-value=\"modelValue\"\n :title=\"title\"\n :size=\"size\"\n :layout=\"baseLayout\"\n :tabs=\"modalTabs\"\n :active-tab=\"activeTab\"\n @update:active-tab=\"activeTab = $event\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @close=\"handleClose\"\n >\n <!-- Body: the active pane only — tab strip / rail / footer are BaseModal's shell. -->\n <div class=\"mint-settings-modal\">\n <div\n v-if=\"isSchemaDriven && activeGroup\"\n class=\"mint-settings-modal__group-grid\"\n :style=\"{ '--mint-settings-cols': activeGroup.columns ?? 1 }\"\n >\n <template v-for=\"field in activeGroupVisibleFields\" :key=\"field.name\">\n <div :style=\"field.colSpan ? { gridColumn: `span ${field.colSpan}` } : undefined\">\n <slot\n :name=\"`field:${field.name}`\"\n :field=\"field\"\n :form=\"builder.form\"\n :field-props=\"builder.form.getFieldProps(field.name)\"\n >\n <FormFieldRendererInternal\n :field=\"field\"\n :resolved-props=\"builder.getResolvedFieldProps(field)\"\n :form=\"builder.form\"\n />\n </slot>\n </div>\n </template>\n </div>\n\n <template v-else-if=\"!isSchemaDriven\">\n <template v-for=\"tab in manualTabs\" :key=\"tab.id\">\n <div v-show=\"activeTab === tab.id\">\n <slot :name=\"`tab-${tab.id}`\" />\n </div>\n </template>\n </template>\n\n <div v-if=\"showAppearance\" v-show=\"activeTab === APPEARANCE_TAB_ID\">\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Theme</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"opt in themeOptions\"\n :key=\"opt.value\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.theme === opt.value }]\"\n @click=\"settings.theme = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Color Palette</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"(palette, key) in colorPalettes\"\n :key=\"key\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.colorPalette === key }]\"\n @click=\"settings.colorPalette = key as ColorPalette\"\n >\n {{ palette.name }}\n </button>\n </div>\n </div>\n\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Table Density</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"opt in densityOptions\"\n :key=\"opt.value\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.tableDensity === opt.value }]\"\n @click=\"settings.tableDensity = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n <p class=\"mint-settings-modal__note\">Adjusts row height in data tables.</p>\n </div>\n\n <slot name=\"appearance\" />\n </div>\n </div>\n\n <template v-if=\"$slots.footer\" #footer>\n <slot\n name=\"footer\"\n :values=\"builder.form.data\"\n :close=\"handleClose\"\n />\n </template>\n </BaseModal>\n</template>\n\n<style>\n@import '../styles/components/settings-modal.css';\n</style>\n","<script setup lang=\"ts\">\n/**\n * Tabbed settings modal with three usage modes:\n *\n * 1. Schema-driven (recommended) — pass `schema`, compact `controls`, or a\n * complete `defineControlModel()` result plus `v-model:values`. Each\n * group/section becomes a tab; fields auto-render via the SDK form field\n * registry (text, select, number, toggle, molecule, concentration, …).\n * Conditional visibility, validation, and dynamic options come for free.\n *\n * 2. Manual tabs + slots — pass `tabs` and a `<template #tab-{id}>` slot\n * per tab. Use this when you need bespoke widgets the form-builder\n * registry doesn't cover (or for legacy plugins).\n *\n * 3. Appearance only — `showAppearance` (default true) renders the built-in\n * theme / palette / table-density tab. Works alongside both modes above.\n *\n * Layout: `horizontal` (underline tabs, default) or `vertical` (sidebar rail\n * with optional icons + descriptions, recommended for 5+ groups).\n *\n * @example Recommended\n * ```vue\n * <SettingsModal v-model=\"open\" v-model:values=\"values\" :model=\"settingsModel\" />\n * ```\n */\nimport { ref, computed, watch } from 'vue'\nimport BaseModal from './BaseModal.vue'\nimport FormFieldRendererInternal from './internal/FormFieldRendererInternal.vue'\nimport { useFormBuilder } from '../composables/useFormBuilder'\nimport {\n controlsToSettingsSchema,\n mergeControlWorkspaceOptions,\n resolveControlModel,\n type ControlModel,\n type ControlModelBinding,\n type ControlSchema,\n type ControlWorkspaceOptions,\n} from '../composables/useControlSchema'\nimport { useSettingsStore, colorPalettes } from '../stores/settings'\nimport { useAuthStore } from '../stores/auth'\nimport { usePlatformContext } from '../composables/usePlatformContext'\nimport { canAccessByPolicy } from '../permissions'\nimport {\n formSchemaFieldNames,\n pickExistingRecordKeys,\n pickRecordKeys,\n recordValuesEqualForKeys,\n} from '../utils/formModelSync'\nimport type {\n ThemeMode,\n ColorPalette,\n TableDensity,\n ModalLayout,\n ModalTab,\n SettingsTab,\n SettingsTabInput,\n SettingsModalLayout,\n SettingsModalSchema,\n SettingsUserType,\n FormEnhancements,\n} from '../types'\nimport type { AccessControlled, PermissionUser } from '../permissions'\nimport {\n APPEARANCE_TAB_ID,\n buildFlatSettingsSchema,\n buildSettingsTabs,\n filterSettingsSchemaByAccess,\n normalizeVisibleSettingsTabs,\n settingsGroupToTab,\n} from './SettingsModal.schema'\n\ninterface Props {\n modelValue: boolean\n title?: string\n /** Manual tab descriptors. Ignored when `schema` is set (groups become tabs). */\n tabs?: SettingsTabInput[]\n showAppearance?: boolean\n size?: 'md' | 'lg' | 'xl'\n layout?: SettingsModalLayout\n /** Declarative schema — fields auto-render via SDK form components. */\n schema?: SettingsModalSchema\n /** Model returned by defineControlModel(), or a raw nested ControlModel for one-step settings generation. */\n model?: ControlModel | ControlModelBinding\n /** Compact controls model — converted to `schema` when `schema` is not set. */\n controls?: ControlSchema\n /** Conversion options for `controls`, such as section labels, columns, and shared initialValues. */\n controlOptions?: ControlWorkspaceOptions\n /** Two-way bound values when `schema`, `model`, or `controls` is set. */\n values?: Record<string, unknown>\n /** Optional dynamic enhancements (validators, dynamic options, callbacks). */\n enhancements?: FormEnhancements<Record<string, unknown>>\n /** Optional user type override for permission-filtered settings content. Defaults to SDK auth/platform context. */\n userType?: SettingsUserType\n}\n\nconst props = withDefaults(defineProps<Props>(), {\n title: 'Settings',\n tabs: () => [],\n showAppearance: true,\n size: 'lg',\n layout: 'horizontal',\n model: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [value: boolean]\n 'update:values': [data: Record<string, unknown>]\n close: []\n}>()\n\nconst settings = useSettingsStore()\nconst auth = useAuthStore()\nconst { user: platformUser } = usePlatformContext()\n\nconst isVertical = computed(() => props.layout === 'vertical')\n\nconst resolvedModel = computed<ControlModelBinding | undefined>(() => {\n return resolveControlModel(props.model)\n})\nconst resolvedControls = computed<ControlSchema | undefined>(() =>\n props.controls ?? resolvedModel.value?.controls,\n)\nconst resolvedControlOptions = computed<ControlWorkspaceOptions>(() =>\n mergeControlWorkspaceOptions(resolvedModel.value?.controlOptions ?? {}, props.controlOptions)\n)\nconst sourceSettingsSchema = computed<SettingsModalSchema | undefined>(() =>\n props.schema ?? (\n resolvedControls.value\n ? controlsToSettingsSchema(resolvedControls.value, resolvedControlOptions.value)\n : undefined\n ),\n)\nconst currentAccessUser = computed<PermissionUser | null>(() => {\n if (props.userType) {\n return { role: props.userType === 'admin' ? 'admin' : 'user' }\n }\n return auth.userInfo ?? platformUser.value ?? null\n})\nconst isAccessUserAuthenticated = computed(() =>\n props.userType !== undefined || auth.isAuthenticated || !!platformUser.value,\n)\nconst settingsSchema = computed<SettingsModalSchema | undefined>(() => {\n if (!sourceSettingsSchema.value) return undefined\n return filterSettingsSchemaByAccess(sourceSettingsSchema.value, canShowForCurrentUser)\n})\nconst isSchemaDriven = computed(() => !!settingsSchema.value)\nconst resolvedValues = computed<Record<string, unknown>>(() => ({\n ...(resolvedControlOptions.value.initialValues ?? {}),\n ...(props.values ?? {}),\n}))\n\n// Schema-driven mode keeps one form-builder instance and syncs schema changes\n// into it, so callers can swap groups/fields without remounting the modal.\nconst builder = useFormBuilder(\n settingsSchema.value ? buildFlatSettingsSchema(settingsSchema.value) : { sections: [] },\n resolvedValues.value,\n props.enhancements,\n)\n\nwatch(\n () => settingsSchema.value,\n (schema) => {\n if (!schema) {\n builder.updateSchema({ sections: [] }, {})\n return\n }\n\n const flatSchema = buildFlatSettingsSchema(schema)\n const fieldNames = formSchemaFieldNames(flatSchema)\n const sourceValues = props.values === undefined\n ? {\n ...resolvedValues.value,\n ...(builder.form.data as Record<string, unknown>),\n }\n : resolvedValues.value\n\n builder.updateSchema(flatSchema, pickExistingRecordKeys(sourceValues ?? {}, fieldNames))\n },\n { deep: true },\n)\n\nwatch(\n () => ({ ...resolvedValues.value }),\n (data) => {\n if (!settingsSchema.value) return\n const fieldNames = builderFieldNames()\n if (recordValuesEqualForKeys(data, builder.form.data as Record<string, unknown>, fieldNames)) return\n builder.reset(pickRecordKeys(data, fieldNames))\n },\n { deep: true },\n)\n\nwatch(\n () => ({ ...builder.form.data }),\n (data) => {\n if (settingsSchema.value) {\n emit('update:values', {\n ...resolvedValues.value,\n ...data,\n })\n }\n },\n { deep: true },\n)\n\n// Schema groups whose `condition` evaluates false against the current data are\n// dropped from the rail entirely — same semantics as section visibility in\n// FormBuilder. Manual `tabs` have no condition mechanism, so they pass through.\nconst visibleSchemaGroups = computed(() =>\n settingsSchema.value\n ? settingsSchema.value.groups.filter((g) => builder.isSectionVisible(g.id))\n : [],\n)\n\nconst manualTabs = computed<SettingsTab[]>(() =>\n normalizeVisibleSettingsTabs(props.tabs, canShowForCurrentUser)\n)\n\nconst allTabs = computed<SettingsTab[]>(() => {\n const base: SettingsTab[] = settingsSchema.value\n ? visibleSchemaGroups.value.map(settingsGroupToTab)\n : manualTabs.value\n return buildSettingsTabs(base, props.showAppearance)\n})\n\nconst activeTab = ref(allTabs.value[0]?.id || APPEARANCE_TAB_ID)\n\n// BaseModal owns the tab chrome: 'vertical' keeps its public name and maps to\n// the shell rail; horizontal maps to the shell strip (plain when single-tab).\nconst baseLayout = computed<ModalLayout>(() => {\n if (isVertical.value) return 'rail'\n return allTabs.value.length > 1 ? 'tabs' : 'plain'\n})\n\nconst modalTabs = computed<ModalTab[]>(() =>\n allTabs.value.map((tab) => ({\n id: tab.id,\n label: tab.label,\n icon: tab.icon,\n description: tab.description,\n meta: tab.meta,\n })),\n)\n\n// If the active tab vanishes (group hidden by condition), drop back to the first available.\nwatch(allTabs, (tabs) => {\n if (!tabs.some((t) => t.id === activeTab.value)) {\n activeTab.value = tabs[0]?.id ?? APPEARANCE_TAB_ID\n }\n})\n\nconst activeGroup = computed(() =>\n visibleSchemaGroups.value.find((g) => g.id === activeTab.value),\n)\n\nconst activeGroupVisibleFields = computed(() => {\n if (!activeGroup.value) return []\n return activeGroup.value.fields.filter((f) => builder.isFieldVisible(f.name))\n})\n\nconst themeOptions: { value: ThemeMode; label: string }[] = [\n { value: 'light', label: 'Light' },\n { value: 'dark', label: 'Dark' },\n { value: 'system', label: 'System' },\n]\n\nconst densityOptions: { value: TableDensity; label: string }[] = [\n { value: 'compact', label: 'Compact' },\n { value: 'normal', label: 'Normal' },\n { value: 'comfortable', label: 'Comfortable' },\n]\n\nfunction handleClose() {\n emit('update:modelValue', false)\n emit('close')\n}\n\nfunction builderFieldNames(): string[] {\n return builder.fields.map(field => field.name)\n}\n\nfunction canShowForCurrentUser(item: AccessControlled): boolean {\n return canAccessByPolicy(\n currentAccessUser.value,\n item,\n isAccessUserAuthenticated.value,\n )\n}\n</script>\n\n<template>\n <BaseModal\n :model-value=\"modelValue\"\n :title=\"title\"\n :size=\"size\"\n :layout=\"baseLayout\"\n :tabs=\"modalTabs\"\n :active-tab=\"activeTab\"\n @update:active-tab=\"activeTab = $event\"\n @update:model-value=\"emit('update:modelValue', $event)\"\n @close=\"handleClose\"\n >\n <!-- Body: the active pane only — tab strip / rail / footer are BaseModal's shell. -->\n <div class=\"mint-settings-modal\">\n <div\n v-if=\"isSchemaDriven && activeGroup\"\n class=\"mint-settings-modal__group-grid\"\n :style=\"{ '--mint-settings-cols': activeGroup.columns ?? 1 }\"\n >\n <template v-for=\"field in activeGroupVisibleFields\" :key=\"field.name\">\n <div :style=\"field.colSpan ? { gridColumn: `span ${field.colSpan}` } : undefined\">\n <slot\n :name=\"`field:${field.name}`\"\n :field=\"field\"\n :form=\"builder.form\"\n :field-props=\"builder.form.getFieldProps(field.name)\"\n >\n <FormFieldRendererInternal\n :field=\"field\"\n :resolved-props=\"builder.getResolvedFieldProps(field)\"\n :form=\"builder.form\"\n />\n </slot>\n </div>\n </template>\n </div>\n\n <template v-else-if=\"!isSchemaDriven\">\n <template v-for=\"tab in manualTabs\" :key=\"tab.id\">\n <div v-show=\"activeTab === tab.id\">\n <slot :name=\"`tab-${tab.id}`\" />\n </div>\n </template>\n </template>\n\n <div v-if=\"showAppearance\" v-show=\"activeTab === APPEARANCE_TAB_ID\">\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Theme</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"opt in themeOptions\"\n :key=\"opt.value\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.theme === opt.value }]\"\n @click=\"settings.theme = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n </div>\n\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Color Palette</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"(palette, key) in colorPalettes\"\n :key=\"key\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.colorPalette === key }]\"\n @click=\"settings.colorPalette = key as ColorPalette\"\n >\n {{ palette.name }}\n </button>\n </div>\n </div>\n\n <div class=\"mint-settings-modal__section\">\n <div class=\"mint-settings-modal__section-label\">Table Density</div>\n <div class=\"mint-settings-modal__option-group\">\n <button\n v-for=\"opt in densityOptions\"\n :key=\"opt.value\"\n type=\"button\"\n :class=\"['mint-settings-modal__option-btn', { 'mint-settings-modal__option-btn--active': settings.tableDensity === opt.value }]\"\n @click=\"settings.tableDensity = opt.value\"\n >\n {{ opt.label }}\n </button>\n </div>\n <p class=\"mint-settings-modal__note\">Adjusts row height in data tables.</p>\n </div>\n\n <slot name=\"appearance\" />\n </div>\n </div>\n\n <template v-if=\"$slots.footer\" #footer>\n <slot\n name=\"footer\"\n :values=\"builder.form.data\"\n :close=\"handleClose\"\n />\n </template>\n </BaseModal>\n</template>\n\n<style>\n@import '../styles/components/settings-modal.css';\n</style>\n"],"mappings":";;;;;;;;AAQA,SAAgB,mBACd,MACO;AACP,KAAI,OAAO,SAAS,SAAU,QAAO;AAErC,QAAO;EACL,IAAI;EACJ,OAAO;EACR;;AAGH,SAAgB,wBACd,MACO;AACP,KAAI,OAAO,SAAS,SAAU,QAAO;AAErC,QAAO,EACL,OAAO,MACR;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EEZH,MAAM,QAAQ;EAEd,MAAM,UAAU,eACd,MAAM,SAAS,MAAM,UAAU,GAAG,MAAM,QAAQ,UAAU,KAAA,EAC5D;EAEA,MAAM,SAAS,eACb,CAAC,MAAM,SAAS,MAAM,QAAQ,MAAM,UAAU,GAAG,MAAM,QAAQ,SAAS,KAAA,EAC1E;EAEA,MAAM,cAAc,eAAe,QAAQ,SAAS,OAAO,MAAK;;uBAI9D,mBAyBM,OAzBN,cAyBM;IAxBO,QAAA,SAAA,WAAA,EAAX,mBAcM,OAdN,cAcM,CAbJ,mBAMQ,SAAA;KALL,KAAK,QAAA;KACN,OAAM;wCAEH,QAAA,MAAK,GAAG,KACX,EAAA,EAAY,QAAA,YAAA,WAAA,EAAZ,mBAAmF,QAAnF,cAA2E,IAAC,IAAA,mBAAA,IAAA,KAAA,CAAA,EAAA,GAAA,aAAA,EAAA,CAGrE,QAAA,YAAY,QAAA,gBAAA,WAAA,EADrB,mBAKO,QALP,cAGC,aAED,IAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,IAAA,mBAAA,IAAA,KAAA;IAGF,WAAoC,KAAA,QAAA,WAAA,EAA7B,aAAc,YAAA,OAAW,CAAA;IAEvB,QAAA,SAAA,WAAA,EAAT,mBAEI,KAAA;;KAFa,IAAI,QAAA;KAAS,OAAM;KAAyB,MAAK;uBAC7D,QAAA,MAAK,EAAA,GAAA,aAAA,IAEI,QAAA,QAAA,WAAA,EAAd,mBAEI,KAAA;;KAFiB,IAAI,OAAA;KAAQ,OAAM;uBAClC,QAAA,KAAI,EAAA,GAAA,aAAA,IAAA,mBAAA,IAAA,KAAA;;;;;;;ACjDb,SAAgB,yBACd,MACA,OACA,MACS;AACT,MAAK,MAAM,OAAO,KAChB,KAAI,CAAC,YAAY,KAAK,MAAM,MAAM,KAAK,CAAE,QAAO;AAElD,QAAO;;AAGT,SAAgB,eACd,QACA,MACyB;AACzB,QAAO,OAAO,YAAY,KAAK,KAAI,QAAO,CAAC,KAAK,OAAO,KAAK,CAAC,CAAC;;AAGhE,SAAgB,uBACd,QACA,MACyB;AACzB,QAAO,OAAO,YACZ,KACG,QAAO,QAAO,OAAO,UAAU,eAAe,KAAK,QAAQ,IAAI,CAAC,CAChE,KAAI,QAAO,CAAC,KAAK,OAAO,KAAK,CAAC,CAClC;;AAGH,SAAgB,qBAAqB,QAA8B;AAIjE,SAHiB,OAAO,QACpB,OAAO,MAAM,SAAQ,SAAQ,KAAK,SAAS,GAC3C,OAAO,UACK,SAAQ,YAAW,QAAQ,OAAO,KAAI,UAAS,MAAM,KAAK,CAAC;;AAG7E,SAAS,YAAY,MAAe,OAAyB;AAC3D,KAAI,OAAO,GAAG,MAAM,MAAM,CAAE,QAAO;AACnC,KAAI,MAAM,QAAQ,KAAK,IAAI,MAAM,QAAQ,MAAM,CAC7C,QAAO,KAAK,WAAW,MAAM,UAAU,KAAK,OAAO,MAAM,UAAU,YAAY,MAAM,MAAM,OAAO,CAAC;AAErG,KAAI,SAAS,KAAK,IAAI,SAAS,MAAM,CACnC,QAAO,yBAAyB,MAAM,OAAO,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,OAAO,KAAK,KAAK,EAAE,GAAG,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC;AAE3G,QAAO;;AAGT,SAAS,SAAS,OAAkD;AAClE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;;;;;;;;;;;EErC7E,MAAM,QAAQ;EAEd,MAAM,QAAQ,eAAe,sBAAsB,MAAM,MAAM,KAAK,CAAA;EAEpE,MAAM,gBAAgB,eACpB,MAAM,MAAM,SAAS,cAAc,MAAM,MAAM,SAAS,SAC1D;EAEA,MAAM,iBAAiB,eAAwC;AAC7D,OAAI,CAAC,cAAc,MAAO,QAAO,MAAM;AAEvC,UAAO;IACL,SAAS;IACT,OAAO,MAAM,MAAM;IACnB,aAAa,MAAM,MAAM;IACzB,MAAM,MAAM,MAAM;IAClB,WAAW,MAAM,MAAM;IACvB,QAAQ,MAAM,MAAM;IACpB,GAAG,MAAM;IACX;IACD;EAED,MAAM,eAAe,eAAe;GAClC,MAAM,OAAO,MAAM,MAAM;AACzB,UAAO,MAAM,KAAK,QAAQ,QAAQ,MAAM,KAAK,OAAO,QAAQ;IAC7D;EAED,SAAS,aAAa,OAAe;AACnC,SAAM,KAAK,cAAc,MAAM,MAAM,MAAM,MAAK;;;uBAKhD,YAoBY,mBAAA;IAnBT,OAAO,cAAA,QAAgB,KAAA,IAAY,QAAA,MAAM;IACzC,OAAO,aAAA,SAAgB,KAAA;IACvB,MAAM,cAAA,QAAgB,KAAA,IAAY,QAAA,MAAM;IACxC,UAAQ,CAAA,CAAI,QAAA,MAAM,YAAY;IAC9B,YAAU,cAAA,QAAgB,KAAA,IAAY,QAAA,MAAM;;2BActC,CAZP,WAYO,KAAA,QAAA,SAZe,QAAA,MAAM,QAAI;KAAK,OAAO,QAAA;KAAQ,MAAM,QAAA;KAAO,YAAa,QAAA,KAAK,cAAc,QAAA,MAAM,KAAI;aAYpG,CATG,MAAA,MAAM,UAAA,WAAA,EAFd,YAIE,wBAHK,MAAA,MAAM,UAAS,EAAA,eAAA,WAAA,EAAA,KAAA,GAAA,EAEZ,eAAA,MAAc,CAAA,EAAA,MAAA,GAAA,KAAA,WAAA,EAExB,YAKE,wBAJK,MAAA,MAAM,UAAS,EADtB,WAKE,EAAA,KAAA,GAAA,EAFQ,eAAA,OAAc,EACrB,UAAQ,cAAY,CAAA,EAAA,MAAA,GAAA,EAAA,CAAA,CAAA,CAAA;;;;;;;;;;;;;;ACpD7B,IAAa,oBAAoB;AAEjC,IAAa,iBAA8B;CACzC,IAAI;CACJ,OAAO;CACP,aAAa;CACd;AAID,SAAgB,wBAAwB,QAAyC;AAC/E,QAAO,EACL,UAAU,OAAO,OAAO,KAAwB,WAAW;EACzD,IAAI,MAAM;EACV,OAAO;EACP,QAAQ,MAAM;EACd,SAAS,MAAM;EACf,WAAW,MAAM;EAClB,EAAE,EACJ;;AAGH,SAAgB,6BACd,QACA,SACqB;AAUrB,QAAO,EAAE,QATM,OAAO,OAAO,SAAS,UAAU;AAC9C,MAAI,CAAC,QAAQ,MAAM,CAAE,QAAO,EAAE;EAE9B,MAAM,SAAS,MAAM,OAAO,OAAO,QAAQ;AAC3C,MAAI,OAAO,WAAW,EAAG,QAAO,EAAE;AAElC,SAAO,CAAC;GAAE,GAAG;GAAO;GAAQ,CAAC;GAC7B,EAEe;;AAGnB,SAAgB,mBAAmB,OAAmC;AACpE,QAAO;EACL,IAAI,MAAM;EACV,OAAO,MAAM;EACb,MAAM,MAAM;EACZ,aAAa,MAAM;EACpB;;AAGH,SAAgB,6BACd,MACA,SACe;AACf,QAAO,KAAK,IAAI,mBAAmB,CAAC,OAAO,QAAQ;;AAGrD,SAAgB,kBACd,UACA,gBACe;AACf,QAAO,iBAAiB,CAAC,GAAG,UAAU,eAAe,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EE0B1D,MAAM,QAAQ;EASd,MAAM,OAAO;EAMb,MAAM,WAAW,kBAAiB;EAClC,MAAM,OAAO,cAAa;EAC1B,MAAM,EAAE,MAAM,iBAAiB,oBAAmB;EAElD,MAAM,aAAa,eAAe,MAAM,WAAW,WAAU;EAE7D,MAAM,gBAAgB,eAAgD;AACpE,UAAO,oBAAoB,MAAM,MAAK;IACvC;EACD,MAAM,mBAAmB,eACvB,MAAM,YAAY,cAAc,OAAO,SACzC;EACA,MAAM,yBAAyB,eAC7B,6BAA6B,cAAc,OAAO,kBAAkB,EAAE,EAAE,MAAM,eAAc,CAC9F;EACA,MAAM,uBAAuB,eAC3B,MAAM,WACJ,iBAAiB,QACb,yBAAyB,iBAAiB,OAAO,uBAAuB,MAAK,GAC7E,KAAA,GAER;EACA,MAAM,oBAAoB,eAAsC;AAC9D,OAAI,MAAM,SACR,QAAO,EAAE,MAAM,MAAM,aAAa,UAAU,UAAU,QAAO;AAE/D,UAAO,KAAK,YAAY,aAAa,SAAS;IAC/C;EACD,MAAM,4BAA4B,eAChC,MAAM,aAAa,KAAA,KAAa,KAAK,mBAAmB,CAAC,CAAC,aAAa,MACzE;EACA,MAAM,iBAAiB,eAAgD;AACrE,OAAI,CAAC,qBAAqB,MAAO,QAAO,KAAA;AACxC,UAAO,6BAA6B,qBAAqB,OAAO,sBAAqB;IACtF;EACD,MAAM,iBAAiB,eAAe,CAAC,CAAC,eAAe,MAAK;EAC5D,MAAM,iBAAiB,gBAAyC;GAC9D,GAAI,uBAAuB,MAAM,iBAAiB,EAAE;GACpD,GAAI,MAAM,UAAU,EAAE;GACvB,EAAC;EAIF,MAAM,UAAU,eACd,eAAe,QAAQ,wBAAwB,eAAe,MAAM,GAAG,EAAE,UAAU,EAAE,EAAE,EACvF,eAAe,OACf,MAAM,aACR;AAEA,cACQ,eAAe,QACpB,WAAW;AACV,OAAI,CAAC,QAAQ;AACX,YAAQ,aAAa,EAAE,UAAU,EAAE,EAAE,EAAE,EAAE,CAAA;AACzC;;GAGF,MAAM,aAAa,wBAAwB,OAAM;GACjD,MAAM,aAAa,qBAAqB,WAAU;GAClD,MAAM,eAAe,MAAM,WAAW,KAAA,IAClC;IACE,GAAG,eAAe;IAClB,GAAI,QAAQ,KAAK;IACnB,GACA,eAAe;AAEnB,WAAQ,aAAa,YAAY,uBAAuB,gBAAgB,EAAE,EAAE,WAAW,CAAA;KAEzF,EAAE,MAAM,MAAM,CAChB;AAEA,eACS,EAAE,GAAG,eAAe,OAAO,IACjC,SAAS;AACR,OAAI,CAAC,eAAe,MAAO;GAC3B,MAAM,aAAa,mBAAkB;AACrC,OAAI,yBAAyB,MAAM,QAAQ,KAAK,MAAiC,WAAW,CAAE;AAC9F,WAAQ,MAAM,eAAe,MAAM,WAAW,CAAA;KAEhD,EAAE,MAAM,MAAM,CAChB;AAEA,eACS,EAAE,GAAG,QAAQ,KAAK,MAAM,IAC9B,SAAS;AACR,OAAI,eAAe,MACjB,MAAK,iBAAiB;IACpB,GAAG,eAAe;IAClB,GAAG;IACJ,CAAA;KAGL,EAAE,MAAM,MAAM,CAChB;EAKA,MAAM,sBAAsB,eAC1B,eAAe,QACX,eAAe,MAAM,OAAO,QAAQ,MAAM,QAAQ,iBAAiB,EAAE,GAAG,CAAA,GACxE,EAAE,CACR;EAEA,MAAM,aAAa,eACjB,6BAA6B,MAAM,MAAM,sBAAqB,CAChE;EAEA,MAAM,UAAU,eAA8B;AAI5C,UAAO,kBAHqB,eAAe,QACvC,oBAAoB,MAAM,IAAI,mBAAkB,GAChD,WAAW,OACgB,MAAM,eAAc;IACpD;EAED,MAAM,YAAY,IAAI,QAAQ,MAAM,IAAI,MAAA,aAAuB;EAI/D,MAAM,aAAa,eAA4B;AAC7C,OAAI,WAAW,MAAO,QAAO;AAC7B,UAAO,QAAQ,MAAM,SAAS,IAAI,SAAS;IAC5C;EAED,MAAM,YAAY,eAChB,QAAQ,MAAM,KAAK,SAAS;GAC1B,IAAI,IAAI;GACR,OAAO,IAAI;GACX,MAAM,IAAI;GACV,aAAa,IAAI;GACjB,MAAM,IAAI;GACX,EAAE,CACL;AAGA,QAAM,UAAU,SAAS;AACvB,OAAI,CAAC,KAAK,MAAM,MAAM,EAAE,OAAO,UAAU,MAAM,CAC7C,WAAU,QAAQ,KAAK,IAAI,MAAA;IAE9B;EAED,MAAM,cAAc,eAClB,oBAAoB,MAAM,MAAM,MAAM,EAAE,OAAO,UAAU,MAAM,CACjE;EAEA,MAAM,2BAA2B,eAAe;AAC9C,OAAI,CAAC,YAAY,MAAO,QAAO,EAAC;AAChC,UAAO,YAAY,MAAM,OAAO,QAAQ,MAAM,QAAQ,eAAe,EAAE,KAAK,CAAA;IAC7E;EAED,MAAM,eAAsD;GAC1D;IAAE,OAAO;IAAS,OAAO;IAAS;GAClC;IAAE,OAAO;IAAQ,OAAO;IAAQ;GAChC;IAAE,OAAO;IAAU,OAAO;IAAU;GACtC;EAEA,MAAM,iBAA2D;GAC/D;IAAE,OAAO;IAAW,OAAO;IAAW;GACtC;IAAE,OAAO;IAAU,OAAO;IAAU;GACpC;IAAE,OAAO;IAAe,OAAO;IAAe;GAChD;EAEA,SAAS,cAAc;AACrB,QAAK,qBAAqB,MAAK;AAC/B,QAAK,QAAO;;EAGd,SAAS,oBAA8B;AACrC,UAAO,QAAQ,OAAO,KAAI,UAAS,MAAM,KAAI;;EAG/C,SAAS,sBAAsB,MAAiC;AAC9D,UAAO,kBACL,kBAAkB,OAClB,MACA,0BAA0B,MAC5B;;;uBAKA,YAsGY,mBAAA;IArGT,eAAa,QAAA;IACb,OAAO,QAAA;IACP,MAAM,QAAA;IACN,QAAQ,WAAA;IACR,MAAM,UAAA;IACN,cAAY,UAAA;IACZ,sBAAiB,OAAA,OAAA,OAAA,MAAA,WAAE,UAAA,QAAY;IAC/B,uBAAkB,OAAA,OAAA,OAAA,MAAA,WAAE,KAAI,qBAAsB,OAAM;IACpD,SAAO;;2BAoFF,CAjFN,mBAiFM,OAjFN,YAiFM,CA/EI,eAAA,SAAkB,YAAA,SAAA,WAAA,EAD1B,mBAqBM,OAAA;;KAnBJ,OAAM;KACL,OAAK,eAAA,EAAA,wBAA4B,YAAA,MAAY,WAAO,GAAA,CAAA;0BAErD,mBAeW,UAAA,MAAA,WAfe,yBAAA,QAAT,UAAK;yBACpB,mBAaM,OAAA;WAdkD,MAAM;MACxD,OAAK,eAAE,MAAM,UAAO,EAAA,YAAA,QAAyB,MAAM,WAAO,GAAO,KAAA,EAAS;SAC9E,WAWO,KAAA,QAAA,SAVW,MAAM,QAAI;MAClB;MACP,MAAM,MAAA,QAAO,CAAC;MACd,YAAa,MAAA,QAAO,CAAC,KAAK,cAAc,MAAM,KAAI;cAO9C,CALL,YAIE,mCAAA;MAHQ;MACP,kBAAgB,MAAA,QAAO,CAAC,sBAAsB,MAAK;MACnD,MAAM,MAAA,QAAO,CAAC;;;;;;uBAOH,eAAA,SAAA,UAAA,KAAA,EACpB,mBAIW,UAAA,EAAA,KAAA,GAAA,EAAA,WAJa,WAAA,QAAP,QAAG;yCAClB,mBAEM,OAAA,EAAA,KAHkC,IAAI,IAAA,EAAA,CAE1C,WAAgC,KAAA,QAAA,OAAZ,IAAI,KAAE,CAAA,EAAA,IAAA,GAAA,CAAA,CAAA,OADf,UAAA,UAAc,IAAI,GAAE,CAAA,CAAA;8CAM1B,QAAA,iBAAA,gBAAA,WAAA,EAAX,mBAgDM,OAAA,YAAA;KA/CJ,mBAaM,OAbN,YAaM,CAAA,OAAA,OAAA,OAAA,KAZJ,mBAA2D,OAAA,EAAtD,OAAM,sCAAoC,EAAC,SAAK,GAAA,GACrD,mBAUM,OAVN,YAUM,EAAA,WAAA,EATJ,mBAQS,UAAA,MAAA,WAPO,eAAP,QAAG;aADZ,mBAQS,UAAA;OANN,KAAK,IAAI;OACV,MAAK;OACJ,OAAK,eAAA,CAAA,mCAAA,EAAA,2CAAmF,MAAA,SAAQ,CAAC,UAAU,IAAI,OAAK,CAAA,CAAA;OACpH,UAAK,WAAE,MAAA,SAAQ,CAAC,QAAQ,IAAI;yBAE1B,IAAI,MAAK,EAAA,IAAA,WAAA;;KAKlB,mBAaM,OAbN,YAaM,CAAA,OAAA,OAAA,OAAA,KAZJ,mBAAmE,OAAA,EAA9D,OAAM,sCAAoC,EAAC,iBAAa,GAAA,GAC7D,mBAUM,OAVN,YAUM,EAAA,UAAA,KAAA,EATJ,mBAQS,UAAA,MAAA,WAPkB,MAAA,cAAa,GAA9B,SAAS,QAAG;0BADtB,mBAQS,UAAA;OAND;OACN,MAAK;OACJ,OAAK,eAAA,CAAA,mCAAA,EAAA,2CAAmF,MAAA,SAAQ,CAAC,iBAAiB,KAAG,CAAA,CAAA;OACrH,UAAK,WAAE,MAAA,SAAQ,CAAC,eAAe;yBAE7B,QAAQ,KAAI,EAAA,IAAA,WAAA;;KAKrB,mBAcM,OAdN,YAcM;gCAbJ,mBAAmE,OAAA,EAA9D,OAAM,sCAAoC,EAAC,iBAAa,GAAA;MAC7D,mBAUM,OAVN,aAUM,EAAA,WAAA,EATJ,mBAQS,UAAA,MAAA,WAPO,iBAAP,QAAG;cADZ,mBAQS,UAAA;QANN,KAAK,IAAI;QACV,MAAK;QACJ,OAAK,eAAA,CAAA,mCAAA,EAAA,2CAAmF,MAAA,SAAQ,CAAC,iBAAiB,IAAI,OAAK,CAAA,CAAA;QAC3H,UAAK,WAAE,MAAA,SAAQ,CAAC,eAAe,IAAI;0BAEjC,IAAI,MAAK,EAAA,IAAA,YAAA;;gCAGhB,mBAA2E,KAAA,EAAxE,OAAM,6BAA2B,EAAC,sCAAkC,GAAA;;KAGzE,WAA0B,KAAA,QAAA,aAAA;uBA/CO,UAAA,UAAc,MAAA,kBAAiB,CAAA,CAAA,CAAA,GAAA,mBAAA,IAAA,KAAA,CAAA,CAAA,CAAA,CAAA;;OAmDpDA,KAAAA,OAAO,SAAA;UAAS;sBAK5B,CAJF,WAIE,KAAA,QAAA,UAAA;KAFC,QAAQ,MAAA,QAAO,CAAC,KAAK;KACrB,OAAO"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,21 @@
1
+ import { ActionMenuItem } from '../types/components';
2
+ interface Props {
3
+ label: string;
4
+ items: ActionMenuItem[];
5
+ disabled?: boolean;
6
+ }
7
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
8
+ select: (item: ActionMenuItem) => any;
9
+ close: () => any;
10
+ open: () => any;
11
+ }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
12
+ onSelect?: ((item: ActionMenuItem) => any) | undefined;
13
+ onClose?: (() => any) | undefined;
14
+ onOpen?: (() => any) | undefined;
15
+ }>, {
16
+ disabled: boolean;
17
+ }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
18
+ triggerRootRef: HTMLSpanElement;
19
+ panelRef: HTMLDivElement;
20
+ }, any>;
21
+ export default _default;
@@ -1,4 +1,4 @@
1
- import { ModalSize, ModalVariant } from '../types';
1
+ import { ModalLayout, ModalSize, ModalTab, ModalVariant } from '../types';
2
2
  interface Props {
3
3
  modelValue: boolean;
4
4
  title?: string;
@@ -8,11 +8,23 @@ interface Props {
8
8
  closable?: boolean;
9
9
  closeOnOverlay?: boolean;
10
10
  closeOnEscape?: boolean;
11
+ /**
12
+ * Shell layout. 'tabs' renders a tab strip between header and body;
13
+ * 'rail' renders a sidebar rail + pane as the shell's middle row.
14
+ * Both are shell regions — never part of the scrolling body content.
15
+ */
16
+ layout?: ModalLayout;
17
+ /** Sections for the tab strip / rail. The strip renders only with 2+ tabs. */
18
+ tabs?: ModalTab[];
19
+ /** Id of the selected tab. Two-way bindable via update:activeTab. */
20
+ activeTab?: string;
11
21
  }
12
22
  declare function __VLS_template(): {
13
23
  attrs: Partial<{}>;
14
24
  slots: {
15
25
  header?(_: {}): any;
26
+ 'rail-footer'?(_: {}): any;
27
+ default?(_: {}): any;
16
28
  default?(_: {}): any;
17
29
  footer?(_: {}): any;
18
30
  };
@@ -25,15 +37,19 @@ type __VLS_TemplateResult = ReturnType<typeof __VLS_template>;
25
37
  declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
26
38
  "update:modelValue": (value: boolean) => any;
27
39
  close: () => any;
40
+ "update:activeTab": (id: string) => any;
28
41
  }, string, import('vue').PublicProps, Readonly<Props> & Readonly<{
29
42
  "onUpdate:modelValue"?: ((value: boolean) => any) | undefined;
30
43
  onClose?: (() => any) | undefined;
44
+ "onUpdate:activeTab"?: ((id: string) => any) | undefined;
31
45
  }>, {
32
46
  size: ModalSize;
33
47
  variant: ModalVariant;
48
+ tabs: ModalTab[];
34
49
  closable: boolean;
35
50
  closeOnOverlay: boolean;
36
51
  closeOnEscape: boolean;
52
+ layout: ModalLayout;
37
53
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
38
54
  containerRef: HTMLDivElement;
39
55
  }, any>;
@@ -32,9 +32,9 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
32
32
  }>, {
33
33
  size: "sm" | "md" | "lg";
34
34
  modelValue: ProtocolStep[];
35
+ orientation: "horizontal" | "vertical";
35
36
  collapsible: boolean;
36
37
  editable: boolean;
37
- orientation: "horizontal" | "vertical";
38
38
  showDuration: boolean;
39
39
  showTime: boolean;
40
40
  expandedStepId: string;
@@ -1,10 +1,10 @@
1
1
  import { GeneratedAnalysisTransport } from '../composables/useGeneratedAnalysis';
2
- type __VLS_Props = {
2
+ interface Props {
3
3
  baseUrl: string;
4
4
  showStandaloneLabel?: boolean;
5
5
  transport?: GeneratedAnalysisTransport;
6
- };
7
- declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {
6
+ }
7
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {
8
8
  showStandaloneLabel: boolean;
9
9
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
10
10
  export default _default;
@@ -1,6 +1,6 @@
1
1
  import { GeneratedAnalysisResult } from '../types/generated-ui';
2
- type __VLS_Props = {
2
+ interface Props {
3
3
  result: GeneratedAnalysisResult;
4
- };
5
- declare const _default: import('vue').DefineComponent<__VLS_Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLElement>;
4
+ }
5
+ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {}, string, import('vue').PublicProps, Readonly<Props> & Readonly<{}>, {}, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLElement>;
6
6
  export default _default;
@@ -59,13 +59,13 @@ declare const __VLS_component: import('vue').DefineComponent<Props, {}, {}, {},
59
59
  readonly: boolean;
60
60
  modelValue: Rack[];
61
61
  showLegend: boolean;
62
+ allowReorder: boolean;
62
63
  editable: boolean;
63
64
  showBadges: boolean;
64
65
  allowSampleDrop: boolean;
65
66
  activeRackId: string;
66
67
  maxRacks: number;
67
68
  minRacks: number;
68
- allowReorder: boolean;
69
69
  wellPlateSize: WellPlateSize;
70
70
  sampleDropMapper: RackSampleDropMapper;
71
71
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
@@ -25,8 +25,8 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
25
25
  modelValue: string;
26
26
  colorPalette: string[];
27
27
  samples: SampleType[];
28
- editable: boolean;
29
28
  orientation: "vertical" | "horizontal";
29
+ editable: boolean;
30
30
  showCounts: boolean;
31
31
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
32
32
  export default _default;
@@ -10,8 +10,8 @@ declare const _default: import('vue').DefineComponent<SmartGroupManualProps, {},
10
10
  onCancel?: (() => any) | undefined;
11
11
  onClose?: (() => any) | undefined;
12
12
  }>, {
13
+ seed: Record<string, SmartGroupSeed>;
13
14
  palette: ManualPaletteEntry[];
14
15
  sampleNames: string[];
15
- seed: Record<string, SmartGroupSeed>;
16
16
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {}, HTMLDivElement>;
17
17
  export default _default;
@@ -23,6 +23,7 @@ export { default as NumberInput } from './NumberInput.vue';
23
23
  export { default as FileUploader } from './FileUploader.vue';
24
24
  export { default as AlertBox } from './AlertBox.vue';
25
25
  export { default as AppToastContainer } from './AppToastContainer.vue';
26
+ export { default as ActionMenu } from './ActionMenu.vue';
26
27
  export { default as IconButton } from './IconButton.vue';
27
28
  export { default as ThemeToggle } from './ThemeToggle.vue';
28
29
  export { default as CollapsibleCard } from './CollapsibleCard.vue';