@morscherlab/mint-sdk 1.3.0-beta.9 → 1.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/dist/__tests__/components/AutoGroupModal.anatomy.test.d.ts +1 -0
  2. package/dist/__tests__/components/AutoGroupModal.wiring.test.d.ts +1 -0
  3. package/dist/__tests__/composables/autoGroup/fieldEdits.test.d.ts +1 -0
  4. package/dist/__tests__/composables/autoGroup/golden.test.d.ts +1 -0
  5. package/dist/components/AutoGroupModal.adapter.d.ts +27 -4
  6. package/dist/components/SmartGroup.types.d.ts +22 -0
  7. package/dist/components/SmartGroupFieldRecipe.groups.d.ts +10 -2
  8. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +3 -0
  9. package/dist/components/index.js +1 -1
  10. package/dist/{components-GDDvof8D.js → components-bbanLd1u.js} +510 -287
  11. package/dist/components-bbanLd1u.js.map +1 -0
  12. package/dist/composables/autoGroup/classify.d.ts +7 -1
  13. package/dist/composables/autoGroup/columns.d.ts +16 -1
  14. package/dist/composables/autoGroup/index.d.ts +5 -7
  15. package/dist/composables/autoGroup/tokenize.d.ts +36 -1
  16. package/dist/composables/index.js +2 -2
  17. package/dist/composables/useAutoGroup.d.ts +13 -2
  18. package/dist/{composables-D6uqp0UF.js → composables-BbHozlA7.js} +2 -2
  19. package/dist/{composables-D6uqp0UF.js.map → composables-BbHozlA7.js.map} +1 -1
  20. package/dist/index.js +3 -3
  21. package/dist/install.js +1 -1
  22. package/dist/permissions.js +2 -2
  23. package/dist/permissions.js.map +1 -1
  24. package/dist/styles.css +129 -96
  25. package/dist/types/auto-group.d.ts +1 -1
  26. package/dist/{validation-Dmp9Q5W0.js → validation-CukfLjy-.js} +323 -187
  27. package/dist/validation-CukfLjy-.js.map +1 -0
  28. package/package.json +2 -2
  29. package/src/__tests__/components/AppTopBarPageSelector.test.ts +4 -4
  30. package/src/__tests__/components/AutoGroupModal.anatomy.test.ts +86 -0
  31. package/src/__tests__/components/AutoGroupModal.wiring.test.ts +53 -0
  32. package/src/__tests__/components/SampleSelector.test.ts +14 -16
  33. package/src/__tests__/components/SmartGroupFieldRecipe.groups.test.ts +23 -0
  34. package/src/__tests__/components/SmartGroupFieldRecipe.test.ts +176 -0
  35. package/src/__tests__/composables/autoGroup/columns.test.ts +100 -11
  36. package/src/__tests__/composables/autoGroup/fieldEdits.test.ts +74 -0
  37. package/src/__tests__/composables/autoGroup/fingerprint.test.ts +9 -0
  38. package/src/__tests__/composables/autoGroup/golden.test.ts +187 -0
  39. package/src/__tests__/composables/autoGroup/groupByOrder.test.ts +7 -7
  40. package/src/__tests__/composables/autoGroup/tokenLength.test.ts +7 -0
  41. package/src/__tests__/composables/autoGroup/tokenize.test.ts +78 -1
  42. package/src/__tests__/composables/useAutoGroup.test.ts +2 -1
  43. package/src/__tests__/fixtures/auto-group/share-exp021.txt +103 -0
  44. package/src/__tests__/fixtures/auto-group/share-exp031.txt +39 -0
  45. package/src/__tests__/fixtures/auto-group/share-exp114.txt +123 -0
  46. package/src/__tests__/fixtures/auto-group/share-exp214.txt +63 -0
  47. package/src/__tests__/utils/permissions.test.ts +15 -0
  48. package/src/components/AutoGroupModal.adapter.ts +80 -9
  49. package/src/components/AutoGroupModal.vue +41 -8
  50. package/src/components/SmartGroup.types.ts +23 -0
  51. package/src/components/SmartGroupFieldRecipe.groups.ts +14 -2
  52. package/src/components/SmartGroupFieldRecipe.vue +289 -169
  53. package/src/components/internal/AppTopBarPageSelectorInternal.vue +3 -6
  54. package/src/composables/autoGroup/classify.ts +26 -7
  55. package/src/composables/autoGroup/columns.ts +144 -36
  56. package/src/composables/autoGroup/compose.ts +8 -10
  57. package/src/composables/autoGroup/fingerprint.ts +1 -1
  58. package/src/composables/autoGroup/index.ts +5 -12
  59. package/src/composables/autoGroup/tokenLength.ts +8 -0
  60. package/src/composables/autoGroup/tokenize.ts +148 -1
  61. package/src/composables/autoGroup/vocab.json +5 -11
  62. package/src/composables/useAutoGroup.ts +92 -79
  63. package/src/permissions.ts +3 -2
  64. package/src/styles/components/app-page-selector.css +58 -14
  65. package/src/styles/components/smart-group.css +71 -82
  66. package/src/types/auto-group.ts +1 -0
  67. package/dist/components-GDDvof8D.js.map +0 -1
  68. package/dist/composables/autoGroup/replicatePreGroup.d.ts +0 -36
  69. package/dist/validation-Dmp9Q5W0.js.map +0 -1
  70. package/src/composables/autoGroup/replicatePreGroup.ts +0 -124
package/dist/styles.css CHANGED
@@ -10244,22 +10244,6 @@ html.dark .mint-toast__item {
10244
10244
  }
10245
10245
  .sg-field__toggle { grid-row: 1 / 3; grid-column: 2; align-self: center; }
10246
10246
 
10247
- /* toggle switch */
10248
- .sg-switch {
10249
- position: relative; width: 1.65rem; height: 0.95rem;
10250
- border-radius: 9999px; background: var(--bg-tertiary);
10251
- border: none; cursor: pointer; flex-shrink: 0;
10252
- transition: background 0.15s ease;
10253
- }
10254
- .sg-switch.on { background: var(--color-primary); }
10255
- .sg-switch::after {
10256
- content: ''; position: absolute; top: 0.125rem; left: 0.125rem;
10257
- width: 0.7rem; height: 0.7rem; border-radius: 9999px;
10258
- background: #fff; box-shadow: 0 1px 2px rgb(0 0 0 / 0.25);
10259
- transition: transform 0.15s ease;
10260
- }
10261
- .sg-switch.on::after { transform: translateX(0.7rem); }
10262
-
10263
10247
  /* ==========================================================================
10264
10248
  Shared — live group preview (right rail)
10265
10249
  ========================================================================== */
@@ -10313,18 +10297,8 @@ html.dark .mint-toast__item {
10313
10297
  font-size: 0.6875rem; font-weight: 600;
10314
10298
  color: var(--text-secondary);
10315
10299
  }
10316
- .sg-qc__route {
10317
- margin-left: auto;
10318
- font: inherit; font-size: 0.75rem; font-weight: 500;
10319
- color: var(--text-secondary);
10320
- padding: 0.1875rem 1.5rem 0.1875rem 0.5rem;
10321
- background: var(--bg-secondary);
10322
- background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' fill='none' viewBox='0 0 20 20'%3e%3cpath stroke='%2394a3b8' stroke-linecap='round' stroke-linejoin='round' stroke-width='1.5' d='M6 8l4 4 4-4'/%3e%3c/svg%3e");
10323
- background-position: right 0.25rem center; background-repeat: no-repeat;
10324
- background-size: 1.1em 1.1em;
10325
- border: 1px solid var(--border-color); border-radius: var(--radius-sm);
10326
- appearance: none; cursor: pointer;
10327
- }
10300
+ .fr-qc__route { margin-left: auto; }
10301
+ .fr-qc__chips { display: flex; flex-wrap: wrap; gap: 0.25rem; }
10328
10302
  .sg-qc__chip {
10329
10303
  display: inline-flex; align-items: center; gap: 0.375rem;
10330
10304
  padding: 0.25rem 0.5rem; border-radius: var(--radius);
@@ -10371,47 +10345,85 @@ html.dark .mint-toast__item {
10371
10345
  /* ==========================================================================
10372
10346
  Field Recipe refinements (layered on the shared chrome above)
10373
10347
  ========================================================================== */
10348
+ /* Section label above the anatomy and each field list. */
10349
+ .fr-label { font-size: 0.75rem; font-weight: 600; color: var(--text-secondary); }
10350
+
10351
+ /* One-line field row: [grip] [layer] name [rename] values [hint] [toggle]. */
10374
10352
  .fr .sg-field {
10375
- grid-template-columns: 1fr auto;
10376
- grid-template-rows: auto auto;
10377
- row-gap: 0.25rem;
10378
- padding: 0.5rem 0.75rem;
10353
+ display: flex; align-items: center; gap: 0.5rem;
10354
+ padding: 0.375rem 0.625rem;
10379
10355
  }
10380
- .fr-field__head { display: flex; align-items: center; gap: 0.5rem; }
10381
- .fr .sg-field__role { margin-left: 0; }
10382
- .fr .sg-field__vals { grid-column: 1 / 2; grid-row: 2; }
10383
- .fr-switch { grid-column: 2; grid-row: 1 / 3; align-self: center; }
10384
-
10385
- /* Layer-order controls: which hierarchy layer this field forms, plus reorder. */
10386
- .sg-field__order {
10387
- grid-column: 1 / 3;
10388
- display: flex; align-items: center; gap: 0.25rem;
10356
+ .fr .sg-field__name { white-space: nowrap; }
10357
+ .fr .sg-field__role { margin-left: 0; white-space: nowrap; }
10358
+ .fr .sg-field__vals { flex: 1; min-width: 0; }
10359
+ .fr-row__grip,
10360
+ .fr-row__rename {
10361
+ display: inline-flex; align-items: center; justify-content: center;
10362
+ width: 1.25rem; height: 1.25rem; padding: 0; flex-shrink: 0;
10363
+ border: none; border-radius: var(--radius-sm); background: none;
10364
+ color: var(--text-muted); cursor: pointer;
10365
+ transition: background 0.15s ease, color 0.15s ease;
10389
10366
  }
10390
- .sg-field__layer {
10391
- font-size: 0.6875rem; font-weight: 600;
10392
- color: var(--color-primary);
10393
- padding: 0.0625rem 0.375rem; border-radius: 9999px;
10394
- background: var(--color-primary-soft);
10395
- margin-right: auto;
10367
+ .fr-row__grip { cursor: grab; }
10368
+ .fr-row__grip:hover,
10369
+ .fr-row__rename:hover { color: var(--text-primary); background: var(--bg-hover); }
10370
+ .fr-row__grip:focus-visible,
10371
+ .fr-row__rename:focus-visible { outline: none; box-shadow: var(--focus-ring-soft); }
10372
+ /* Which hierarchy layer this field forms (1 = the sample selector's major group). */
10373
+ .fr-row__layer {
10374
+ display: inline-grid; place-items: center; flex-shrink: 0;
10375
+ width: 1.25rem; height: 1.25rem; border-radius: 9999px;
10376
+ border: 1px solid var(--color-primary);
10377
+ background: var(--bg-secondary); color: var(--_ink-primary);
10378
+ font-size: 0.6875rem; font-weight: 700; font-variant-numeric: tabular-nums;
10396
10379
  }
10397
- .sg-field__order-btn {
10398
- display: inline-flex; align-items: center; justify-content: center;
10399
- width: 1.25rem; height: 1.25rem; padding: 0;
10400
- border: 1px solid var(--border-color); border-radius: 0.375rem;
10401
- background: var(--bg-primary); color: var(--text-secondary);
10402
- cursor: pointer; transition: background 0.15s ease, color 0.15s ease;
10380
+ .fr-row__name-input {
10381
+ width: 9rem; padding: 0.0625rem 0.375rem;
10382
+ font: inherit; font-size: 0.875rem; font-weight: 600; color: var(--text-primary);
10383
+ border: 1px solid var(--color-primary); border-radius: var(--radius-sm);
10384
+ background: var(--bg-secondary);
10385
+ }
10386
+ .fr-row__name-input:focus-visible { outline: none; box-shadow: var(--focus-ring-soft); }
10387
+ /* Groups that remain when this field is switched off. */
10388
+ .fr-row__hint {
10389
+ font-size: 0.75rem; font-weight: 500; color: var(--text-secondary-strong);
10390
+ white-space: nowrap; font-variant-numeric: tabular-nums;
10403
10391
  }
10404
- .sg-field__order-btn:hover:not(:disabled) { background: var(--bg-tertiary); color: var(--text-primary); }
10405
- .sg-field__order-btn:disabled { opacity: 0.4; cursor: default; }
10392
+ /* The message is dark text (AA on the tinted row); the input border carries the error colour. */
10393
+ .fr-row__error { font-size: 0.75rem; font-weight: 600; color: var(--text-primary); white-space: nowrap; }
10394
+ .fr-row__name-input[aria-invalid='true'] { border-color: var(--_ink-error); box-shadow: var(--focus-ring-error); }
10395
+ .fr-row--dragging { opacity: 0.5; }
10396
+ .fr-row--over { box-shadow: inset 0 2px 0 var(--color-primary); }
10406
10397
 
10407
- /* Replicate-on: the field card itself warns instead of silently shattering. */
10398
+ /* Replicate-on: the field row itself warns instead of silently shattering. */
10408
10399
  .fr-field--warn.sg-field--on {
10409
10400
  border-color: var(--mint-warning-border);
10410
10401
  background: var(--mint-warning-bg);
10411
10402
  }
10412
- .fr-field--warn.sg-field--on .fr-switch.on { background: var(--mint-warning); }
10413
- .fr-field--warn.sg-field--on .sg-field__role--rep {
10414
- color: #fff; background: var(--mint-warning);
10403
+ .fr-field--warn.sg-field--on .fr-row__layer { border-color: var(--mint-warning); color: var(--text-primary); }
10404
+
10405
+ /* Name anatomy: the tokens of one example sample and the role of each. */
10406
+ .fr-anatomy { display: flex; flex-direction: column; gap: 0.375rem; }
10407
+ .fr-anatomy__tokens { display: flex; flex-wrap: wrap; gap: 0.375rem 0.5rem; }
10408
+ .fr-token { display: inline-flex; flex-direction: column; align-items: center; gap: 0.125rem; }
10409
+ .fr-token__text {
10410
+ font-family: var(--font-mono); font-size: 0.75rem; font-weight: 500;
10411
+ padding: 0.125rem 0.375rem; border-radius: var(--radius-sm);
10412
+ border: 1px solid var(--border-color); background: var(--bg-tertiary);
10413
+ color: var(--text-secondary-strong);
10414
+ }
10415
+ .fr-token__caption { font-size: 0.6875rem; color: var(--text-secondary-strong); white-space: nowrap; }
10416
+ .fr-token--on .fr-token__text {
10417
+ border-color: var(--color-primary); background: var(--color-primary-soft);
10418
+ color: var(--text-primary);
10419
+ }
10420
+ .fr-token--on .fr-token__caption { color: var(--_ink-primary); font-weight: 700; }
10421
+ .fr-token--off .fr-token__text { border-style: dashed; background: transparent; }
10422
+
10423
+ /* No samples: say what to do. */
10424
+ .fr-blank {
10425
+ display: flex; flex-direction: column; align-items: flex-start; gap: 0.5rem;
10426
+ padding: 1rem 0;
10415
10427
  }
10416
10428
 
10417
10429
  /* Neutral (no-selection) summary variant. */
@@ -10736,29 +10748,6 @@ html.dark .sg-summary code { background: rgba(255, 255, 255, 0.1); }
10736
10748
  background: var(--bg-tertiary); color: var(--text-primary); border-color: var(--text-muted);
10737
10749
  }
10738
10750
  .fr-upload:focus-visible { outline: none; box-shadow: var(--focus-ring-soft); }
10739
- .fr-csv { position: relative; }
10740
- .fr-csv-menu {
10741
- position: absolute; top: calc(100% + 0.25rem); right: 0; z-index: 10;
10742
- min-width: 11rem; padding: 0.25rem;
10743
- display: flex; flex-direction: column; gap: 0.0625rem;
10744
- background: var(--bg-secondary);
10745
- border: 1px solid var(--border-color); border-radius: var(--radius-md);
10746
- box-shadow: var(--shadow-lg);
10747
- }
10748
- .fr-csv-item {
10749
- display: flex; align-items: center; gap: 0.5rem;
10750
- font: inherit; font-size: 0.8125rem; font-weight: 500; text-align: left;
10751
- color: var(--text-primary); cursor: pointer;
10752
- padding: 0.4375rem 0.5rem; border: none; border-radius: var(--radius);
10753
- background: none; transition: background 0.12s ease, color 0.12s ease;
10754
- }
10755
- .fr-csv-item:hover { background: var(--bg-hover); }
10756
- .fr-csv-item:disabled {
10757
- /* disabled cue: muted colour + struck label + not-allowed, not opacity alone */
10758
- color: var(--text-muted); cursor: not-allowed; opacity: 0.7;
10759
- text-decoration: line-through; text-decoration-color: var(--text-muted);
10760
- }
10761
- .fr-csv-item:disabled:hover { background: none; }
10762
10751
  /* anchor the drop overlay to the main panel */
10763
10752
  .sg-body__main { position: relative; }
10764
10753
  .fr-dropzone {
@@ -19491,8 +19480,8 @@ html.dark .mint-experiment-selector__filters-toggle--active {
19491
19480
 
19492
19481
  /* AppTopBar page selector — left-side route/page dropdown.
19493
19482
  Trigger speaks the field language (5a): 36px (the identity tile height), hover changes the background
19494
- only, open = field focus, inline 12px chevron. Menu = .mint-popover +
19495
- .mint-menu-item (2d); __menu / __item stay as aliases. */
19483
+ only, open = field focus, inline 12px chevron. The menu keeps the 1.2 panel
19484
+ (own card, tinted active row) rather than .mint-popover + .mint-menu-item. */
19496
19485
 
19497
19486
  .mint-page-selector {
19498
19487
  position: relative;
@@ -19592,44 +19581,88 @@ html.dark .mint-experiment-selector__filters-toggle--active {
19592
19581
 
19593
19582
  .mint-page-selector__menu {
19594
19583
  position: absolute;
19595
- top: calc(100% + 0.25rem);
19584
+ top: calc(100% + 0.375rem);
19596
19585
  left: 0;
19597
19586
  width: 16.25rem;
19587
+ background: var(--bg-card);
19588
+ border: 1px solid var(--border-color);
19589
+ border-radius: var(--radius-lg);
19590
+ box-shadow: var(--shadow-md);
19591
+ padding: 0.375rem;
19598
19592
  z-index: 50;
19599
19593
  }
19600
19594
 
19601
19595
  .mint-page-selector__menu-title {
19602
- padding: 0.25rem 0.5rem 0.375rem;
19596
+ padding: 0.375rem 0.625rem 0.5rem;
19603
19597
  font-size: 0.75rem;
19604
19598
  font-weight: 500;
19605
19599
  color: var(--text-secondary);
19606
19600
  }
19607
19601
 
19602
+ .mint-page-selector__item {
19603
+ display: flex;
19604
+ align-items: center;
19605
+ gap: 0.625rem;
19606
+ width: 100%;
19607
+ padding: 0.5rem 0.625rem;
19608
+ border: 0;
19609
+ background: transparent;
19610
+ border-radius: 0.4375rem;
19611
+ color: var(--text-primary);
19612
+ font-size: 0.8125rem;
19613
+ font-weight: 500;
19614
+ font-family: inherit;
19615
+ text-align: left;
19616
+ text-decoration: none;
19617
+ cursor: pointer;
19618
+ transition: background-color var(--mint-transition);
19619
+ }
19620
+
19621
+ .mint-page-selector__item:hover:not(.mint-page-selector__item--disabled) {
19622
+ background: var(--bg-hover);
19623
+ }
19624
+
19625
+ .mint-page-selector__item--active {
19626
+ background: var(--bg-tertiary);
19627
+ font-weight: 600;
19628
+ }
19629
+
19630
+ .mint-page-selector__item--disabled {
19631
+ opacity: var(--mint-disabled-opacity);
19632
+ cursor: not-allowed;
19633
+ }
19634
+
19608
19635
  .mint-page-selector__item-icon {
19609
- width: 1.25rem;
19610
- height: 1.25rem;
19611
- border-radius: var(--radius-sm);
19636
+ width: 1.375rem;
19637
+ height: 1.375rem;
19638
+ border-radius: 0.3125rem;
19612
19639
  background: var(--bg-tertiary);
19613
- color: var(--text-secondary-strong);
19640
+ color: var(--text-secondary);
19614
19641
  display: grid;
19615
19642
  place-items: center;
19616
19643
  flex-shrink: 0;
19617
19644
  }
19618
19645
 
19619
- .mint-page-selector__item-icon--metadata {
19646
+ .mint-page-selector__item--active .mint-page-selector__item-icon {
19647
+ background: var(--color-primary-soft);
19648
+ color: var(--color-primary);
19649
+ }
19650
+
19651
+ .mint-page-selector__item-icon--metadata,
19652
+ .mint-page-selector__item--active .mint-page-selector__item-icon--metadata {
19620
19653
  background: transparent;
19621
19654
  color: inherit;
19622
19655
  }
19623
19656
 
19624
19657
  .mint-page-selector__item-icon svg {
19625
- width: 0.75rem;
19626
- height: 0.75rem;
19658
+ width: 0.8125rem;
19659
+ height: 0.8125rem;
19627
19660
  }
19628
19661
 
19629
19662
  .mint-page-selector__metadata-icon.mint-plugin-icon--sm {
19630
- width: 1.25rem;
19631
- height: 1.25rem;
19632
- border-radius: var(--radius-sm);
19663
+ width: 1.375rem;
19664
+ height: 1.375rem;
19665
+ border-radius: 0.3125rem;
19633
19666
  }
19634
19667
 
19635
19668
  .mint-page-selector__item-label {
@@ -35,7 +35,7 @@ export interface SampleClass {
35
35
  */
36
36
  tokenLength?: number;
37
37
  }
38
- export type ColumnRole = 'constant' | 'factor' | 'replicate' | 'run-order' | 'numeric' | 'class-tag' | 'ignore';
38
+ export type ColumnRole = 'constant' | 'factor' | 'replicate' | 'run-order' | 'id' | 'numeric' | 'class-tag' | 'ignore';
39
39
  export interface NumericParse {
40
40
  value: number;
41
41
  unit: string;