@morscherlab/mint-sdk 1.1.4 → 1.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (96) 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/GeneratedPluginView.vue.d.ts +3 -3
  14. package/dist/components/GeneratedResultRenderer.vue.d.ts +3 -3
  15. package/dist/components/index.d.ts +1 -0
  16. package/dist/components/index.js +8 -8
  17. package/dist/{components-CV5zuWa8.js → components-Dra_ac_5.js} +350 -71
  18. package/dist/components-Dra_ac_5.js.map +1 -0
  19. package/dist/composables/controlSchemaDoseDesign.d.ts +8 -1
  20. package/dist/composables/controlSchemaModel.d.ts +10 -1
  21. package/dist/composables/index.js +8 -8
  22. package/dist/composables/useAnalysisArtifacts.d.ts +9 -1
  23. package/dist/composables/useAppExperiment.d.ts +7 -0
  24. package/dist/composables/useBioTemplatePackWorkspace.d.ts +9 -1
  25. package/dist/composables/useControlWorkspace.d.ts +9 -1
  26. package/dist/composables/useGeneratedAnalysis.d.ts +9 -0
  27. package/dist/{composables-CW8NRXLB.js → composables-CRR_JxQD.js} +4 -4
  28. package/dist/{composables-CW8NRXLB.js.map → composables-CRR_JxQD.js.map} +1 -1
  29. package/dist/{experiment-utils-7Yw-h0tD.js → experiment-utils-CLnzPPq5.js} +170 -13
  30. package/dist/experiment-utils-CLnzPPq5.js.map +1 -0
  31. package/dist/index.js +13 -13
  32. package/dist/install.js +7 -7
  33. package/dist/styles.css +764 -610
  34. package/dist/templates/index.js +4 -4
  35. package/dist/{templates-CJRFiWUX.js → templates-Cr-48-u2.js} +2 -2
  36. package/dist/{templates-CJRFiWUX.js.map → templates-Cr-48-u2.js.map} +1 -1
  37. package/dist/types/components.d.ts +32 -0
  38. package/dist/types/index.d.ts +1 -1
  39. package/dist/{useControlSchema-BEAgLyyx.js → useControlSchema-BMVb2XIQ.js} +58 -10
  40. package/dist/useControlSchema-BMVb2XIQ.js.map +1 -0
  41. package/dist/{useDropdownState-Be-ug_ci.js → useDropdownState-DSb3BC3N.js} +2 -2
  42. package/dist/{useDropdownState-Be-ug_ci.js.map → useDropdownState-DSb3BC3N.js.map} +1 -1
  43. package/dist/{useExperimentSelector-DFg_iEHI.js → useExperimentSelector-D0pjj9WH.js} +3 -3
  44. package/dist/{useExperimentSelector-DFg_iEHI.js.map → useExperimentSelector-D0pjj9WH.js.map} +1 -1
  45. package/dist/{useFormBuilder-CR9pBApW.js → useFormBuilder-DG3HOFGA.js} +2 -2
  46. package/dist/{useFormBuilder-CR9pBApW.js.map → useFormBuilder-DG3HOFGA.js.map} +1 -1
  47. package/dist/{useProtocolTemplates-DXeIHMwV.js → useProtocolTemplates-BMt0LlXf.js} +21 -6
  48. package/dist/useProtocolTemplates-BMt0LlXf.js.map +1 -0
  49. package/package.json +1 -1
  50. package/src/__tests__/components/ActionMenu.test.ts +99 -0
  51. package/src/__tests__/components/BaseModal.test.ts +133 -0
  52. package/src/__tests__/components/SettingsModal.test.ts +9 -7
  53. package/src/__tests__/docs/extractDocsComponents.test.ts +15 -1
  54. package/src/__tests__/docs/extractDocsParsing.test.ts +22 -0
  55. package/src/__tests__/docs/frontendDocsCatalog.test.ts +80 -0
  56. package/src/components/ActionMenu.story.vue +26 -0
  57. package/src/components/ActionMenu.vue +212 -0
  58. package/src/components/AppSidebar.vue +2 -13
  59. package/src/components/ArtifactSelectorModal.vue +8 -1
  60. package/src/components/BaseModal.story.vue +107 -1
  61. package/src/components/BaseModal.vue +152 -4
  62. package/src/components/BioTemplateExperimentWorkspaceView.vue +8 -1
  63. package/src/components/BioTemplatePackWorkspaceView.vue +8 -1
  64. package/src/components/BioTemplatePresetWorkspaceView.vue +8 -1
  65. package/src/components/BioTemplateRenderer.vue +8 -1
  66. package/src/components/ComponentBindingRenderer.vue +8 -1
  67. package/src/components/ControlWorkspaceView.vue +8 -1
  68. package/src/components/DoseDesignWorkspaceView.vue +8 -1
  69. package/src/components/ExperimentSelectorModal.vue +8 -1
  70. package/src/components/FormBuilder.vue +5 -0
  71. package/src/components/GeneratedPluginView.vue +12 -2
  72. package/src/components/GeneratedResultRenderer.vue +12 -2
  73. package/src/components/JobsStatusTray.vue +8 -1
  74. package/src/components/PluginWorkspaceView.vue +10 -1
  75. package/src/components/SettingsModal.vue +102 -149
  76. package/src/components/index.ts +1 -0
  77. package/src/composables/controlSchemaDoseDesign.ts +8 -1
  78. package/src/composables/controlSchemaModel.ts +10 -1
  79. package/src/composables/useAnalysisArtifacts.ts +9 -1
  80. package/src/composables/useAppExperiment.ts +7 -0
  81. package/src/composables/useBioTemplatePackWorkspace.ts +9 -1
  82. package/src/composables/useControlWorkspace.ts +9 -1
  83. package/src/composables/useGeneratedAnalysis.ts +9 -0
  84. package/src/styles/components/action-menu.css +59 -0
  85. package/src/styles/components/icon-button.css +7 -3
  86. package/src/styles/components/modal.css +293 -0
  87. package/src/styles/components/settings-modal.css +3 -273
  88. package/src/styles/index.css +1 -0
  89. package/src/types/components.ts +38 -0
  90. package/src/types/index.ts +3 -0
  91. package/dist/ExperimentSelectorModal-DcQ38zua.js.map +0 -1
  92. package/dist/SettingsModal-Ccq2z-Ms.js.map +0 -1
  93. package/dist/components-CV5zuWa8.js.map +0 -1
  94. package/dist/experiment-utils-7Yw-h0tD.js.map +0 -1
  95. package/dist/useControlSchema-BEAgLyyx.js.map +0 -1
  96. package/dist/useProtocolTemplates-DXeIHMwV.js.map +0 -1
@@ -217,6 +217,293 @@
217
217
  gap: 0.5rem;
218
218
  }
219
219
 
220
+ /* ========================================================================
221
+ Tab strip (layout="tabs")
222
+ ========================================================================
223
+ A shell region, not body content: full-bleed, flush with both edges,
224
+ never scrolls with the fields.
225
+ ======================================================================== */
226
+
227
+ .mint-modal__tabs {
228
+ flex-shrink: 0;
229
+ display: flex;
230
+ gap: 2px;
231
+ padding: 0 0.75rem;
232
+ background-color: var(--bg-card);
233
+ border-bottom: 1px solid var(--border-color);
234
+ overflow-x: auto;
235
+ scrollbar-width: none;
236
+ }
237
+
238
+ .mint-modal__tabs::-webkit-scrollbar {
239
+ display: none;
240
+ }
241
+
242
+ .mint-modal__tab {
243
+ flex-shrink: 0;
244
+ display: inline-flex;
245
+ align-items: center;
246
+ gap: 0.4375rem;
247
+ height: 2.375rem; /* 38px */
248
+ padding: 0 0.75rem;
249
+ border: none;
250
+ background: transparent;
251
+ font-family: inherit;
252
+ font-size: 0.8125rem; /* 13px */
253
+ font-weight: 500;
254
+ color: var(--text-secondary);
255
+ cursor: pointer;
256
+ /* Underline drawn INSIDE the box — no margin-bottom:-1px overlap hack. */
257
+ transition: color var(--mint-transition), box-shadow var(--mint-transition);
258
+ }
259
+
260
+ .mint-modal__tab:hover:not(.mint-modal__tab--disabled) {
261
+ color: var(--text-primary);
262
+ }
263
+
264
+ .mint-modal__tab--active {
265
+ color: var(--color-primary);
266
+ font-weight: 600;
267
+ box-shadow: inset 0 -2px 0 var(--color-primary);
268
+ }
269
+
270
+ .mint-modal__tab--disabled {
271
+ color: var(--text-muted);
272
+ cursor: not-allowed;
273
+ }
274
+
275
+ .mint-modal__tab:focus-visible {
276
+ outline: none;
277
+ box-shadow: var(--focus-ring-soft), inset 0 -2px 0 var(--color-primary);
278
+ }
279
+
280
+ .mint-modal__tab-meta {
281
+ font-family: 'Fira Code', monospace;
282
+ font-size: 0.6875rem;
283
+ font-weight: 400;
284
+ color: var(--text-muted);
285
+ }
286
+
287
+ /* Fixed body height: switching tabs must not resize the card. */
288
+ .mint-modal__body--tabbed {
289
+ height: clamp(14rem, 45vh, 26rem);
290
+ overflow-y: auto;
291
+ }
292
+
293
+ /* Header rule is redundant once a strip or rail follows it. */
294
+ .mint-modal__container--tabs .mint-modal__header,
295
+ .mint-modal__container--rail .mint-modal__header {
296
+ border-bottom: none;
297
+ }
298
+
299
+ /* ========================================================================
300
+ Rail (layout="rail") — sidebar sections + pane as the shell's middle row
301
+ ======================================================================== */
302
+
303
+ .mint-modal__split {
304
+ flex: 1;
305
+ min-height: 0;
306
+ display: grid;
307
+ grid-template-columns: 13.5rem minmax(0, 1fr);
308
+ height: clamp(20rem, 62vh, 34rem);
309
+ }
310
+
311
+ .mint-modal__rail {
312
+ display: flex;
313
+ flex-direction: column;
314
+ gap: 0.625rem;
315
+ padding: 0.625rem 0.5rem;
316
+ background-color: var(--bg-primary);
317
+ border-right: 1px solid var(--border-light);
318
+ overflow-y: auto; /* rail scrolls independently of the pane */
319
+ scrollbar-width: thin;
320
+ }
321
+
322
+ .mint-modal__rail-items {
323
+ display: flex;
324
+ flex-direction: column;
325
+ gap: 2px;
326
+ }
327
+
328
+ .mint-modal__rail-item {
329
+ display: flex;
330
+ align-items: center;
331
+ gap: 0.5625rem;
332
+ width: 100%;
333
+ min-height: 2.25rem;
334
+ padding: 0.4375rem 0.625rem;
335
+ border: none;
336
+ border-radius: 0.4375rem;
337
+ background: transparent;
338
+ font-family: inherit;
339
+ font-size: 0.8125rem;
340
+ font-weight: 500;
341
+ color: var(--text-secondary);
342
+ text-align: left;
343
+ cursor: pointer;
344
+ transition: background-color var(--mint-transition), color var(--mint-transition);
345
+ }
346
+
347
+ .mint-modal__rail-item:hover:not(.mint-modal__rail-item--disabled) {
348
+ background-color: var(--bg-tertiary);
349
+ }
350
+
351
+ .mint-modal__rail-item:focus-visible {
352
+ outline: none;
353
+ box-shadow: var(--focus-ring-soft);
354
+ }
355
+
356
+ /* Active = raised card, matching the 1.1 card language (not a primary fill). */
357
+ .mint-modal__rail-item--active {
358
+ background-color: var(--bg-card);
359
+ color: var(--text-primary);
360
+ font-weight: 600;
361
+ box-shadow: 0 1px 2px rgba(15, 23, 42, 0.08);
362
+ }
363
+
364
+ .mint-modal__rail-item--disabled {
365
+ color: var(--text-muted);
366
+ cursor: not-allowed;
367
+ }
368
+
369
+ .mint-modal__rail-item-icon {
370
+ flex-shrink: 0;
371
+ width: 0.9375rem;
372
+ height: 0.9375rem;
373
+ color: var(--text-muted);
374
+ }
375
+
376
+ .mint-modal__rail-item-icon svg {
377
+ width: 100%;
378
+ height: 100%;
379
+ display: block;
380
+ }
381
+
382
+ /* v-html markup icons arrive wrapped in a span — size it like the svg. */
383
+ .mint-modal__rail-item-icon > span {
384
+ display: block;
385
+ width: 100%;
386
+ height: 100%;
387
+ }
388
+
389
+ .mint-modal__rail-item--active .mint-modal__rail-item-icon {
390
+ color: var(--color-primary);
391
+ }
392
+
393
+ .mint-modal__rail-item-text {
394
+ flex: 1;
395
+ min-width: 0;
396
+ display: flex;
397
+ flex-direction: column;
398
+ gap: 0.0625rem;
399
+ }
400
+
401
+ .mint-modal__rail-item-label {
402
+ line-height: 1.3;
403
+ overflow-wrap: anywhere;
404
+ }
405
+
406
+ .mint-modal__rail-item-description {
407
+ font-size: 0.6875rem;
408
+ font-weight: 400;
409
+ color: var(--text-muted);
410
+ line-height: 1.35;
411
+ }
412
+
413
+ .mint-modal__rail-item-meta {
414
+ flex-shrink: 0;
415
+ font-family: 'Fira Code', monospace;
416
+ font-size: 0.6875rem;
417
+ font-weight: 400;
418
+ color: var(--text-muted);
419
+ }
420
+
421
+ /* ---------- Pane ---------- */
422
+
423
+ .mint-modal__pane {
424
+ min-width: 0;
425
+ min-height: 0;
426
+ display: flex;
427
+ flex-direction: column;
428
+ }
429
+
430
+ .mint-modal__pane:focus-visible {
431
+ outline: none;
432
+ box-shadow: var(--focus-ring-soft);
433
+ }
434
+
435
+ .mint-modal__pane-header {
436
+ flex-shrink: 0;
437
+ padding: 0.875rem 1.25rem 0.75rem;
438
+ border-bottom: 1px solid var(--border-light);
439
+ }
440
+
441
+ .mint-modal__pane-title {
442
+ margin: 0 !important;
443
+ padding: 0 !important;
444
+ font-size: 0.875rem;
445
+ font-weight: 600;
446
+ letter-spacing: -0.005em;
447
+ color: var(--text-primary);
448
+ line-height: 1.3;
449
+ }
450
+
451
+ .mint-modal__pane-subtitle {
452
+ margin: 0.1875rem 0 0 !important;
453
+ padding: 0 !important;
454
+ font-size: 0.75rem;
455
+ color: var(--text-secondary);
456
+ line-height: 1.45;
457
+ }
458
+
459
+ .mint-modal__pane-body {
460
+ flex: 1;
461
+ min-height: 0;
462
+ overflow-y: auto;
463
+ overscroll-behavior: contain;
464
+ padding: 0.875rem 1.25rem 1.125rem;
465
+ font-size: 0.8125rem;
466
+ color: var(--text-primary);
467
+ line-height: 1.55;
468
+ }
469
+
470
+ /* Rail collapses to the tab-strip pattern on narrow screens — one behaviour. */
471
+ @media (max-width: 640px) {
472
+ .mint-modal__split {
473
+ grid-template-columns: minmax(0, 1fr);
474
+ height: auto;
475
+ }
476
+
477
+ .mint-modal__rail {
478
+ flex-direction: row;
479
+ align-items: center;
480
+ gap: 0.25rem;
481
+ padding: 0 0.5rem;
482
+ border-right: none;
483
+ border-bottom: 1px solid var(--border-color);
484
+ overflow-x: auto;
485
+ overflow-y: hidden;
486
+ }
487
+
488
+ .mint-modal__rail-items {
489
+ flex-direction: row;
490
+ }
491
+
492
+ .mint-modal__rail-item {
493
+ width: auto;
494
+ min-height: 2.375rem;
495
+ }
496
+
497
+ /* Strip stays compact */
498
+ .mint-modal__rail-item-description {
499
+ display: none;
500
+ }
501
+
502
+ .mint-modal__pane-body {
503
+ max-height: 60vh;
504
+ }
505
+ }
506
+
220
507
  /* ========================================================================
221
508
  Per-variant transitions
222
509
  ========================================================================
@@ -350,4 +637,10 @@
350
637
  .modal-drawer-leave-to .mint-modal__container {
351
638
  transform: translateY(100%);
352
639
  }
640
+
641
+ /* Sheets keep their natural height; the strip already scrolls horizontally */
642
+ .mint-modal__body--tabbed {
643
+ height: auto;
644
+ max-height: 60vh;
645
+ }
353
646
  }
@@ -1,4 +1,6 @@
1
- /* SettingsModal Component Styles */
1
+ /* SettingsModal Component Styles
2
+ Tab strip / rail / pane / footer chrome lives in BaseModal (modal.css);
3
+ only pane content styles remain here. */
2
4
 
3
5
  .mint-settings-modal {
4
6
  display: flex;
@@ -7,40 +9,6 @@
7
9
  min-height: 0;
8
10
  }
9
11
 
10
- .mint-settings-modal__tabs {
11
- display: flex;
12
- gap: 0.25rem;
13
- border-bottom: 1px solid var(--border-color);
14
- padding-bottom: 0;
15
- margin-bottom: 0.5rem;
16
- }
17
-
18
- .mint-settings-modal__tab {
19
- padding: 0.5rem 1rem;
20
- font-size: 0.875rem;
21
- font-weight: 500;
22
- color: var(--text-muted);
23
- background: none;
24
- border: none;
25
- border-bottom: 2px solid transparent;
26
- cursor: pointer;
27
- transition: color 0.15s ease, border-color 0.15s ease;
28
- margin-bottom: -1px;
29
- }
30
-
31
- .mint-settings-modal__tab:hover {
32
- color: var(--text-primary);
33
- }
34
-
35
- .mint-settings-modal__tab--active {
36
- color: var(--color-primary);
37
- border-bottom-color: var(--color-primary);
38
- }
39
-
40
- .mint-settings-modal__content {
41
- min-height: 12rem;
42
- }
43
-
44
12
  .mint-settings-modal__section {
45
13
  margin-bottom: 1.5rem;
46
14
  }
@@ -95,15 +63,6 @@ html.dark .mint-settings-modal__option-btn--active {
95
63
  padding: 0 !important;
96
64
  }
97
65
 
98
- .mint-settings-modal__footer {
99
- display: flex;
100
- flex-direction: column;
101
- gap: 0.75rem;
102
- margin-top: 1rem;
103
- padding-top: 1rem;
104
- border-top: 1px solid var(--border-light);
105
- }
106
-
107
66
  /* ─────────────────────────────────────────────────────────────────────
108
67
  * Schema-driven content grid (used by both layouts)
109
68
  * Cols come from `--mint-settings-cols` set inline by the component;
@@ -115,232 +74,3 @@ html.dark .mint-settings-modal__option-btn--active {
115
74
  gap: 1rem;
116
75
  grid-template-columns: repeat(var(--mint-settings-cols, 1), minmax(0, 1fr));
117
76
  }
118
-
119
- /* ─────────────────────────────────────────────────────────────────────
120
- * Vertical layout — sidebar rail + content pane (opt-in via layout="vertical")
121
- * Designed for complex plugins with 5+ setting groups. Existing horizontal
122
- * classes above are deliberately untouched.
123
- * ───────────────────────────────────────────────────────────────────── */
124
-
125
- .mint-settings-modal--vertical {
126
- flex-direction: row;
127
- gap: 1.25rem;
128
- align-items: stretch;
129
- height: clamp(22rem, calc(100vh - 9rem), 42rem);
130
- min-height: 22rem;
131
- overflow: hidden;
132
- }
133
-
134
- .mint-settings-modal__rail {
135
- flex-shrink: 0;
136
- width: 12.5rem;
137
- display: flex;
138
- flex-direction: column;
139
- gap: 0.125rem;
140
- padding: 0.125rem 0.75rem 0.125rem 0;
141
- border-right: 1px solid var(--border-light);
142
- overflow: hidden;
143
- }
144
-
145
- .mint-settings-modal__rail-item {
146
- position: relative;
147
- display: flex;
148
- align-items: flex-start;
149
- gap: 0.625rem;
150
- width: 100%;
151
- min-height: 2.5rem;
152
- padding: 0.5rem 0.75rem 0.5rem 0.875rem;
153
- font-size: 0.8125rem;
154
- font-weight: 500;
155
- color: var(--text-secondary);
156
- background: none;
157
- border: none;
158
- border-radius: var(--radius-md);
159
- cursor: pointer;
160
- text-align: left;
161
- transition:
162
- color var(--mint-transition),
163
- background-color var(--mint-transition);
164
- }
165
-
166
- .mint-settings-modal__rail-item:hover {
167
- background-color: var(--bg-hover);
168
- color: var(--text-primary);
169
- }
170
-
171
- .mint-settings-modal__rail-item:focus-visible {
172
- outline: none;
173
- box-shadow: var(--focus-ring);
174
- }
175
-
176
- .mint-settings-modal__rail-item--active {
177
- color: var(--color-primary);
178
- background-color: color-mix(in srgb, var(--color-primary) 10%, transparent);
179
- }
180
-
181
- .mint-settings-modal__rail-item--active::before {
182
- content: "";
183
- position: absolute;
184
- left: 0.375rem;
185
- top: 0.625rem;
186
- bottom: 0.625rem;
187
- width: 2px;
188
- border-radius: 9999px;
189
- background-color: var(--color-primary);
190
- }
191
-
192
- html.dark .mint-settings-modal__rail-item--active {
193
- background-color: color-mix(in srgb, var(--color-primary) 18%, transparent);
194
- }
195
-
196
- /* Reserved icon column keeps labels aligned whether or not icons are present */
197
- .mint-settings-modal__rail-item-icon {
198
- flex-shrink: 0;
199
- width: 1rem;
200
- height: 1rem;
201
- display: inline-flex;
202
- align-items: center;
203
- justify-content: center;
204
- margin-top: 0.0625rem;
205
- color: currentColor;
206
- }
207
-
208
- .mint-settings-modal__rail-item-icon svg {
209
- width: 100%;
210
- height: 100%;
211
- display: block;
212
- }
213
-
214
- .mint-settings-modal__rail-item-text {
215
- display: flex;
216
- flex-direction: column;
217
- gap: 0.125rem;
218
- min-width: 0;
219
- flex: 1;
220
- }
221
-
222
- .mint-settings-modal__rail-item-label {
223
- line-height: 1.3;
224
- overflow-wrap: anywhere;
225
- }
226
-
227
- .mint-settings-modal__rail-item-description {
228
- font-size: 0.6875rem;
229
- font-weight: 400;
230
- color: var(--text-muted);
231
- line-height: 1.35;
232
- overflow-wrap: anywhere;
233
- }
234
-
235
- .mint-settings-modal__rail-item--active .mint-settings-modal__rail-item-description {
236
- color: color-mix(in srgb, var(--color-primary) 65%, var(--text-secondary));
237
- }
238
-
239
- .mint-settings-modal__pane {
240
- flex: 1;
241
- min-width: 0;
242
- min-height: 0;
243
- display: flex;
244
- flex-direction: column;
245
- overflow: hidden;
246
- }
247
-
248
- .mint-settings-modal__pane:focus-visible {
249
- outline: none;
250
- box-shadow: var(--focus-ring);
251
- border-radius: var(--radius-md);
252
- }
253
-
254
- .mint-settings-modal__pane-header {
255
- flex-shrink: 0;
256
- margin-bottom: 1rem;
257
- padding-bottom: 0.75rem;
258
- border-bottom: 1px solid var(--border-light);
259
- }
260
-
261
- .mint-settings-modal__pane-title {
262
- font-size: 0.875rem;
263
- font-weight: 600;
264
- color: var(--text-primary);
265
- letter-spacing: -0.005em;
266
- margin: 0 !important;
267
- padding: 0 !important;
268
- line-height: 1.3;
269
- }
270
-
271
- .mint-settings-modal__pane-subtitle {
272
- font-size: 0.75rem;
273
- color: var(--text-secondary);
274
- line-height: 1.45;
275
- margin: 0.25rem 0 0 !important;
276
- padding: 0 !important;
277
- }
278
-
279
- .mint-settings-modal__pane-body {
280
- flex: 1;
281
- min-height: 0;
282
- overflow-y: auto;
283
- scrollbar-width: thin;
284
- /* Trailing breathing room so the last field doesn't hug the modal border */
285
- padding: 0 0.5rem 0.25rem 0;
286
- margin-right: -0.25rem;
287
- overscroll-behavior: contain;
288
- }
289
-
290
- .mint-settings-modal__pane-body::-webkit-scrollbar {
291
- width: 0.5rem;
292
- }
293
-
294
- .mint-settings-modal__pane-body::-webkit-scrollbar-track {
295
- background: transparent;
296
- }
297
-
298
- .mint-settings-modal__pane-body::-webkit-scrollbar-thumb {
299
- background-color: color-mix(in srgb, var(--text-muted) 30%, transparent);
300
- border: 2px solid transparent;
301
- border-radius: 9999px;
302
- background-clip: content-box;
303
- }
304
-
305
- .mint-settings-modal__pane-body::-webkit-scrollbar-thumb:hover {
306
- background-color: color-mix(in srgb, var(--text-muted) 45%, transparent);
307
- }
308
-
309
- /* Mobile — collapse the rail into a horizontal scroll-strip so the modal stays usable.
310
- * Touch targets stay ≥40px tall via 0.5rem vertical padding + 1rem text line-height. */
311
- @media (max-width: 640px) {
312
- .mint-settings-modal--vertical {
313
- flex-direction: column;
314
- gap: 0.875rem;
315
- height: auto;
316
- max-height: none;
317
- min-height: 0;
318
- overflow: visible;
319
- }
320
-
321
- .mint-settings-modal__rail {
322
- width: 100%;
323
- flex-direction: row;
324
- overflow-x: auto;
325
- padding: 0 0 0.625rem;
326
- border-right: none;
327
- border-bottom: 1px solid var(--border-light);
328
- gap: 0.25rem;
329
- scrollbar-width: thin;
330
- }
331
-
332
- .mint-settings-modal__rail-item {
333
- flex-shrink: 0;
334
- width: auto;
335
- padding: 0.5rem 0.75rem;
336
- }
337
-
338
- .mint-settings-modal__rail-item--active::before {
339
- display: none;
340
- }
341
-
342
- /* Two-line description hides on mobile so the rail strip stays compact */
343
- .mint-settings-modal__rail-item-description {
344
- display: none;
345
- }
346
- }
@@ -6,6 +6,7 @@
6
6
  @import './variables.css';
7
7
 
8
8
  /* Component styles - alphabetically ordered */
9
+ @import './components/action-menu.css';
9
10
  @import './components/alert-box.css';
10
11
  @import './components/app-container.css';
11
12
  @import './components/app-layout.css';
@@ -7,12 +7,48 @@ export type ContainerDirection = 'row' | 'column'
7
7
  export type ButtonVariant = 'primary' | 'secondary' | 'cta' | 'danger' | 'success' | 'ghost'
8
8
  export type ButtonSize = 'sm' | 'md' | 'lg'
9
9
 
10
+ // Action menu types
11
+ interface ActionMenuItemBase {
12
+ id: string
13
+ label: string
14
+ disabled?: boolean
15
+ danger?: boolean
16
+ }
17
+
18
+ export type ActionMenuItem =
19
+ | (ActionMenuItemBase & {
20
+ href?: never
21
+ target?: never
22
+ })
23
+ | (ActionMenuItemBase & {
24
+ href: string
25
+ target?: '_self' | '_blank' | '_parent' | '_top'
26
+ })
27
+
10
28
  // Input types
11
29
  export type InputType = 'text' | 'password' | 'email' | 'number' | 'search' | 'tel' | 'url'
12
30
 
13
31
  // Modal types
14
32
  export type ModalSize = 'sm' | 'md' | 'lg' | 'xl' | 'full'
15
33
  export type ModalVariant = 'centered' | 'drawer' | 'sheet'
34
+ export type ModalLayout = 'plain' | 'tabs' | 'rail'
35
+
36
+ /** Section descriptor for BaseModal's shell-level tab strip (layout="tabs") or rail (layout="rail"). */
37
+ export interface ModalTab {
38
+ id: string
39
+ label: string
40
+ /** Monospace meta on the right of the label — a count, "2 unsaved", etc. No colored badge pill. */
41
+ meta?: string
42
+ /**
43
+ * Rail only — 1rem stroke icon. Accepts SVG path data (string or string[])
44
+ * or trusted inline SVG markup rendered with `v-html`. Markup must be
45
+ * plugin-author-controlled — never user-supplied data.
46
+ */
47
+ icon?: string | string[]
48
+ /** Rail only — second line under the label; also shown as the pane subtitle. */
49
+ description?: string
50
+ disabled?: boolean
51
+ }
16
52
 
17
53
  // Alert types
18
54
  export type AlertType = 'success' | 'error' | 'warning' | 'info'
@@ -416,6 +452,8 @@ export interface SettingsTab extends AccessControlled {
416
452
  icon?: string
417
453
  /** Optional one-line hint shown under the label (vertical layout) and as a section subtitle in the right pane. */
418
454
  description?: string
455
+ /** Optional monospace meta shown right of the tab label — a count, "2 unsaved", etc. */
456
+ meta?: string
419
457
  }
420
458
 
421
459
  export type SettingsTabInput = SettingsTab | string
@@ -3,9 +3,12 @@ export type {
3
3
  ContainerDirection,
4
4
  ButtonVariant,
5
5
  ButtonSize,
6
+ ActionMenuItem,
6
7
  InputType,
7
8
  ModalSize,
8
9
  ModalVariant,
10
+ ModalLayout,
11
+ ModalTab,
9
12
  AlertType,
10
13
  Toast,
11
14
  TabItem,