@morscherlab/mint-sdk 1.1.7 → 1.1.9

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 (90) hide show
  1. package/dist/__tests__/components/RetiredStyles.test.d.ts +1 -0
  2. package/dist/__tests__/composables/autoGroup/groupByOrder.test.d.ts +1 -0
  3. package/dist/__tests__/composables/useSampleGroups.tree.test.d.ts +1 -0
  4. package/dist/components/AppTopBar.vue.d.ts +6 -11
  5. package/dist/components/AutoGroupModal.adapter.d.ts +10 -6
  6. package/dist/components/PluginIcon.vue.d.ts +2 -2
  7. package/dist/components/PluginWorkspaceView.props.d.ts +5 -7
  8. package/dist/components/PluginWorkspaceView.vue.d.ts +0 -3
  9. package/dist/components/SampleSelector.groups.d.ts +7 -7
  10. package/dist/components/SampleSelector.selection.d.ts +6 -12
  11. package/dist/components/SampleSelector.tree.d.ts +39 -0
  12. package/dist/components/SampleSelectorGroupNode.vue.d.ts +9 -0
  13. package/dist/components/SmartGroup.types.d.ts +5 -0
  14. package/dist/components/SmartGroupFieldRecipe.groups.d.ts +3 -2
  15. package/dist/components/SmartGroupFieldRecipe.vue.d.ts +2 -0
  16. package/dist/components/index.js +1 -1
  17. package/dist/{components-CDomhGSj.js → components-BbtUpCTv.js} +913 -943
  18. package/dist/components-BbtUpCTv.js.map +1 -0
  19. package/dist/composables/index.d.ts +1 -1
  20. package/dist/composables/index.js +1 -1
  21. package/dist/composables/useAutoGroup.d.ts +3 -0
  22. package/dist/composables/usePlatformContext.d.ts +3 -0
  23. package/dist/composables/useSampleGroups.d.ts +25 -0
  24. package/dist/index.js +2 -2
  25. package/dist/install.js +1 -1
  26. package/dist/styles.css +130 -557
  27. package/dist/types/platform.d.ts +1 -0
  28. package/dist/{useProtocolTemplates-BMt0LlXf.js → useProtocolTemplates-BWfNaynA.js} +199 -24
  29. package/dist/useProtocolTemplates-BWfNaynA.js.map +1 -0
  30. package/dist/utils/pluginIcon.d.ts +1 -1
  31. package/dist/utils/sampleGroupPath.d.ts +6 -0
  32. package/package.json +1 -1
  33. package/src/__tests__/components/AppAvatarMenu.test.ts +11 -0
  34. package/src/__tests__/components/AppTopBar.test.ts +84 -10
  35. package/src/__tests__/components/AppTopBarPageSelector.test.ts +1 -1
  36. package/src/__tests__/components/AutoGroupModal.adapter.test.ts +16 -6
  37. package/src/__tests__/components/PluginIcon.test.ts +19 -0
  38. package/src/__tests__/components/PluginWorkspaceView.test.ts +8 -0
  39. package/src/__tests__/components/RetiredStyles.test.ts +82 -0
  40. package/src/__tests__/components/SampleSelector.drag.test.ts +26 -0
  41. package/src/__tests__/components/SampleSelector.groups.test.ts +19 -6
  42. package/src/__tests__/components/SampleSelector.selection.test.ts +9 -23
  43. package/src/__tests__/components/SmartGroupFieldRecipe.groups.test.ts +5 -0
  44. package/src/__tests__/composables/autoGroup/compose.test.ts +9 -10
  45. package/src/__tests__/composables/autoGroup/groupByOrder.test.ts +249 -0
  46. package/src/__tests__/composables/autoGroup/integration.test.ts +3 -7
  47. package/src/__tests__/composables/useSampleGroups.tree.test.ts +145 -0
  48. package/src/components/AppTopBar.story.vue +9 -7
  49. package/src/components/AppTopBar.vue +79 -72
  50. package/src/components/AutoGroupModal.adapter.ts +17 -12
  51. package/src/components/AutoGroupModal.story.vue +89 -0
  52. package/src/components/AutoGroupModal.vue +16 -8
  53. package/src/components/PluginIcon.story.vue +11 -9
  54. package/src/components/PluginIcon.vue +3 -3
  55. package/src/components/PluginWorkspaceView.props.ts +5 -7
  56. package/src/components/PluginWorkspaceView.vue +0 -4
  57. package/src/components/SampleSelector.drag.ts +5 -5
  58. package/src/components/SampleSelector.groups.ts +15 -15
  59. package/src/components/SampleSelector.selection.ts +7 -46
  60. package/src/components/SampleSelector.story.vue +37 -0
  61. package/src/components/SampleSelector.tree.ts +48 -0
  62. package/src/components/SampleSelector.vue +52 -320
  63. package/src/components/SampleSelectorGroupNode.vue +197 -0
  64. package/src/components/SmartGroup.types.ts +5 -0
  65. package/src/components/SmartGroupFieldRecipe.groups.ts +6 -2
  66. package/src/components/SmartGroupFieldRecipe.vue +76 -4
  67. package/src/components/internal/AppTopBarPageSelectorInternal.vue +2 -2
  68. package/src/composables/autoGroup/compose.ts +31 -10
  69. package/src/composables/index.ts +1 -0
  70. package/src/composables/useAutoGroup.ts +108 -5
  71. package/src/composables/useSampleGroups.ts +118 -33
  72. package/src/styles/components/app-avatar-menu.css +2 -1
  73. package/src/styles/components/app-plugin-switcher.css +0 -13
  74. package/src/styles/components/app-top-bar.css +13 -54
  75. package/src/styles/components/dose-calculator.css +0 -4
  76. package/src/styles/components/experiment-popover.css +2 -104
  77. package/src/styles/components/experiment-selector-modal.css +0 -7
  78. package/src/styles/components/plugin-icon.css +3 -0
  79. package/src/styles/components/protocol-step-editor.css +0 -6
  80. package/src/styles/components/reagent-editor.css +0 -5
  81. package/src/styles/components/sample-hierarchy-tree.css +0 -4
  82. package/src/styles/components/sample-selector.css +0 -96
  83. package/src/styles/components/schedule-calendar.css +0 -6
  84. package/src/styles/components/smart-group.css +22 -0
  85. package/src/styles/components/well-plate.css +1 -27
  86. package/src/types/platform.ts +1 -0
  87. package/src/utils/pluginIcon.ts +5 -2
  88. package/src/utils/sampleGroupPath.ts +19 -0
  89. package/dist/components-CDomhGSj.js.map +0 -1
  90. package/dist/useProtocolTemplates-BMt0LlXf.js.map +0 -1
@@ -3,6 +3,7 @@ export interface PluginInfo {
3
3
  id: string;
4
4
  name: string;
5
5
  version: string;
6
+ plugin_type?: string;
6
7
  description?: string;
7
8
  icon?: string;
8
9
  color?: string;
@@ -1657,6 +1657,19 @@ function composeGroups(input) {
1657
1657
  const excludedSamples = [];
1658
1658
  const metadata = [];
1659
1659
  let colorIdx = 0;
1660
+ const experimentalClasses = input.classes.filter((c) => c.disposition === "group" && input.schemas[classKey(c)]);
1661
+ const classPrefix = /* @__PURE__ */ new Map();
1662
+ if (input.prefixClassLabels !== false && experimentalClasses.length > 1) {
1663
+ const shortCounts = /* @__PURE__ */ new Map();
1664
+ for (const c of experimentalClasses) {
1665
+ const short = c.subKind ?? c.label;
1666
+ shortCounts.set(short, (shortCounts.get(short) ?? 0) + 1);
1667
+ }
1668
+ for (const c of experimentalClasses) {
1669
+ const short = c.subKind ?? c.label;
1670
+ classPrefix.set(c, (shortCounts.get(short) ?? 0) > 1 ? c.label : short);
1671
+ }
1672
+ }
1660
1673
  const PATH_SEP = String.fromCharCode(1);
1661
1674
  const groupTree = [];
1662
1675
  const treeIndex = /* @__PURE__ */ new Map();
@@ -1696,8 +1709,8 @@ function composeGroups(input) {
1696
1709
  return fieldValues[col.displayName ?? col.name];
1697
1710
  }) : [cls.label];
1698
1711
  const hasMissingGroupPart = input.missingGroupName && cls.disposition === "group" && keyParts.some((part) => part.trim().length === 0);
1699
- const useClassPrefix = input.prefixClassLabels !== false && cls.disposition === "group" && cls.kind !== "unknown" && keyParts.length > 0;
1700
- const groupKey = hasMissingGroupPart ? input.missingGroupName : useClassPrefix ? `${cls.label} / ${keyParts.join(" / ")}` : keyParts.length > 0 ? keyParts.join(" / ") : cls.label;
1712
+ const prefix = cls.kind !== "unknown" && keyParts.length > 0 ? classPrefix.get(cls) : void 0;
1713
+ const groupKey = hasMissingGroupPart ? input.missingGroupName : prefix ? `${prefix} / ${keyParts.join(" / ")}` : keyParts.length > 0 ? keyParts.join(" / ") : cls.label;
1701
1714
  const bucket = groupMap.get(groupKey);
1702
1715
  if (bucket) bucket.samples.push(rowName);
1703
1716
  else groupMap.set(groupKey, {
@@ -2357,17 +2370,109 @@ function useAutoGroup() {
2357
2370
  function toggleGroupBy(key, idx) {
2358
2371
  const schema = schemas.value[key];
2359
2372
  if (!schema) return;
2360
- const set = new Set(schema.groupBy);
2361
- if (set.has(idx)) set.delete(idx);
2362
- else set.add(idx);
2373
+ const groupBy = schema.groupBy.includes(idx) ? schema.groupBy.filter((i) => i !== idx) : [...schema.groupBy, idx];
2363
2374
  schemas.value = {
2364
2375
  ...schemas.value,
2365
2376
  [key]: {
2366
2377
  ...schema,
2367
- groupBy: [...set].sort((a, b) => a - b)
2378
+ groupBy
2368
2379
  }
2369
2380
  };
2370
2381
  }
2382
+ /** Move an enabled column one step up (toward layer 1) or down in the layer order. */
2383
+ function moveGroupBy(key, idx, direction) {
2384
+ const schema = schemas.value[key];
2385
+ if (!schema) return;
2386
+ const from = schema.groupBy.indexOf(idx);
2387
+ if (from === -1) return;
2388
+ const to = direction === "up" ? from - 1 : from + 1;
2389
+ if (to < 0 || to >= schema.groupBy.length) return;
2390
+ const groupBy = [...schema.groupBy];
2391
+ [groupBy[from], groupBy[to]] = [groupBy[to], groupBy[from]];
2392
+ schemas.value = {
2393
+ ...schemas.value,
2394
+ [key]: {
2395
+ ...schema,
2396
+ groupBy
2397
+ }
2398
+ };
2399
+ }
2400
+ function schemasExposing(fieldKey) {
2401
+ return Object.entries(schemas.value).flatMap(([key, schema]) => {
2402
+ const col = schema.columns.find((c) => (c.displayName ?? c.name) === fieldKey);
2403
+ return col ? [{
2404
+ key,
2405
+ index: col.index
2406
+ }] : [];
2407
+ });
2408
+ }
2409
+ function fieldIdentity(schema, index) {
2410
+ const column = schema.columns.find((candidate) => candidate.index === index);
2411
+ return column ? column.displayName ?? column.name : void 0;
2412
+ }
2413
+ /**
2414
+ * Toggle a grouping field across every class exposing it. The target state
2415
+ * comes from the active class (what the card shows), so already-diverged
2416
+ * classes converge instead of flipping in opposite directions.
2417
+ */
2418
+ function toggleGroupByField(fieldKey) {
2419
+ const targets = schemasExposing(fieldKey);
2420
+ if (targets.length === 0) return;
2421
+ const active = targets.find((t) => t.key === activeClassKey.value) ?? targets[0];
2422
+ const enable = !(schemas.value[active.key]?.groupBy.includes(active.index) ?? false);
2423
+ for (const { key, index } of targets) {
2424
+ const schema = schemas.value[key];
2425
+ if (!schema || schema.groupBy.includes(index) === enable) continue;
2426
+ toggleGroupBy(key, index);
2427
+ }
2428
+ }
2429
+ /**
2430
+ * Move a grouping field in the active schema, then project that visible field
2431
+ * order across every class. Class-only fields keep their relative order after
2432
+ * the shared fields because the Field Recipe has no card with which to place
2433
+ * them explicitly.
2434
+ */
2435
+ function moveGroupByField(fieldKey, direction) {
2436
+ const targets = schemasExposing(fieldKey);
2437
+ if (targets.length === 0) return;
2438
+ const active = targets.find((target) => target.key === activeClassKey.value) ?? targets[0];
2439
+ const activeSchema = schemas.value[active.key];
2440
+ if (!activeSchema) return;
2441
+ const from = activeSchema.groupBy.indexOf(active.index);
2442
+ if (from === -1) return;
2443
+ const to = direction === "up" ? from - 1 : from + 1;
2444
+ if (to < 0 || to >= activeSchema.groupBy.length) return;
2445
+ const activeOrder = [...activeSchema.groupBy];
2446
+ [activeOrder[from], activeOrder[to]] = [activeOrder[to], activeOrder[from]];
2447
+ const desiredRank = new Map(activeOrder.flatMap((index, rank) => {
2448
+ const identity = fieldIdentity(activeSchema, index);
2449
+ return identity === void 0 ? [] : [[identity, rank]];
2450
+ }));
2451
+ let changed = false;
2452
+ const nextSchemas = { ...schemas.value };
2453
+ for (const [key, schema] of Object.entries(schemas.value)) {
2454
+ const shared = [];
2455
+ const classOnly = [];
2456
+ for (const index of schema.groupBy) {
2457
+ const identity = fieldIdentity(schema, index);
2458
+ const rank = identity === void 0 ? void 0 : desiredRank.get(identity);
2459
+ if (rank === void 0) classOnly.push(index);
2460
+ else shared.push({
2461
+ index,
2462
+ rank
2463
+ });
2464
+ }
2465
+ shared.sort((left, right) => left.rank - right.rank);
2466
+ const groupBy = [...shared.map((entry) => entry.index), ...classOnly];
2467
+ if (groupBy.every((index, position) => index === schema.groupBy[position])) continue;
2468
+ nextSchemas[key] = {
2469
+ ...schema,
2470
+ groupBy
2471
+ };
2472
+ changed = true;
2473
+ }
2474
+ if (changed) schemas.value = nextSchemas;
2475
+ }
2371
2476
  function updateColumn(key, idx, patch) {
2372
2477
  const schema = schemas.value[key];
2373
2478
  if (!schema) return;
@@ -2552,6 +2657,9 @@ function useAutoGroup() {
2552
2657
  setClassDisposition,
2553
2658
  setClassDispositions,
2554
2659
  toggleGroupBy,
2660
+ moveGroupBy,
2661
+ toggleGroupByField,
2662
+ moveGroupByField,
2555
2663
  setRole,
2556
2664
  setColumnName,
2557
2665
  setValueOps,
@@ -2882,6 +2990,22 @@ function deriveShade(parentHex, index, total) {
2882
2990
  return hslToHex(h, clamp(s, 35, 100), childL);
2883
2991
  }
2884
2992
  //#endregion
2993
+ //#region src/utils/sampleGroupPath.ts
2994
+ /** Split a group name into normalized hierarchy segments. */
2995
+ function splitSampleGroupPath(groupName, separator) {
2996
+ const parts = groupName.split(separator).map((part) => part.trim()).filter((part) => part.length > 0);
2997
+ return parts.length > 0 ? parts : [groupName];
2998
+ }
2999
+ /** First normalized hierarchy segment, used as the reorderable family key. */
3000
+ function getSampleGroupMajorPrefix(groupName, separator) {
3001
+ return splitSampleGroupPath(groupName, separator)[0];
3002
+ }
3003
+ /** Normalized path above a concrete leaf group. */
3004
+ function getSampleGroupParentPath(groupName, separator) {
3005
+ const parts = splitSampleGroupPath(groupName, separator);
3006
+ return parts.length > 1 ? parts.slice(0, -1).join(separator) : "";
3007
+ }
3008
+ //#endregion
2885
3009
  //#region src/composables/useSampleGroups.ts
2886
3010
  /** Shared sample-group hierarchy, color, and ungrouped-sample derivation for lab selectors. */
2887
3011
  function useSampleGroups(options) {
@@ -2893,34 +3017,84 @@ function useSampleGroups(options) {
2893
3017
  if (explicit) return explicit;
2894
3018
  return groups.value.some((group) => group.name.includes("/")) ? "/" : "_";
2895
3019
  });
2896
- const hierarchicalGroups = computed(() => {
2897
- if (groups.value.length === 0) return [];
2898
- const groupedByMajor = /* @__PURE__ */ new Map();
3020
+ const families = computed(() => {
3021
+ const byMajor = /* @__PURE__ */ new Map();
2899
3022
  for (const group of groups.value) {
2900
3023
  const majorName = getMajorGroupName(group.name, separator.value);
2901
- const existing = groupedByMajor.get(majorName);
3024
+ const existing = byMajor.get(majorName);
2902
3025
  if (existing) existing.push(group);
2903
- else groupedByMajor.set(majorName, [group]);
3026
+ else byMajor.set(majorName, [group]);
2904
3027
  }
2905
- return [...groupedByMajor.entries()].map(([majorName, subGroups]) => {
2906
- const color = subGroups[0]?.color || fallbackColor.value;
3028
+ return [...byMajor.entries()].map(([name, members]) => {
3029
+ const color = members[0]?.color || fallbackColor.value;
2907
3030
  return {
2908
- name: majorName,
3031
+ name,
2909
3032
  color,
2910
- subGroups: subGroups.map((subGroup, index) => {
2911
- const displayColor = deriveShade(color, index, subGroups.length);
3033
+ subGroups: members.map((group, index) => {
3034
+ const displayColor = deriveShade(color, index, members.length);
2912
3035
  return {
2913
- ...subGroup,
3036
+ ...group,
2914
3037
  displayColor,
2915
3038
  displayBg: displayColor + "20",
2916
3039
  displayBorder: displayColor + "40"
2917
3040
  };
2918
- }),
2919
- allSamples: subGroups.flatMap((group) => group.samples)
3041
+ })
2920
3042
  };
2921
3043
  });
2922
3044
  });
2923
- const showHierarchy = computed(() => hierarchicalGroups.value.some((major) => major.subGroups.length > 1 || major.subGroups.length === 1 && major.name !== major.subGroups[0].name));
3045
+ const groupTree = computed(() => {
3046
+ const roots = [];
3047
+ for (const family of families.value) {
3048
+ const interior = /* @__PURE__ */ new Map();
3049
+ for (const subGroup of family.subGroups) {
3050
+ const segments = splitSampleGroupPath(subGroup.name, separator.value);
3051
+ const leafLabel = segments[segments.length - 1] ?? subGroup.name;
3052
+ let siblings = roots;
3053
+ let path = "";
3054
+ for (const segment of segments.slice(0, -1)) {
3055
+ path = path ? `${path}/${segment}` : segment;
3056
+ let node = interior.get(path);
3057
+ if (!node) {
3058
+ node = {
3059
+ key: `node:${family.name}/${path}`,
3060
+ label: segment,
3061
+ color: family.color,
3062
+ displayBg: family.color + "20",
3063
+ displayBorder: family.color + "40",
3064
+ allSamples: [],
3065
+ children: []
3066
+ };
3067
+ interior.set(path, node);
3068
+ siblings.push(node);
3069
+ }
3070
+ node.allSamples.push(...subGroup.samples);
3071
+ siblings = node.children;
3072
+ }
3073
+ siblings.push({
3074
+ key: `leaf:${subGroup.name}`,
3075
+ label: leafLabel,
3076
+ color: subGroup.displayColor,
3077
+ displayBg: subGroup.displayBg,
3078
+ displayBorder: subGroup.displayBorder,
3079
+ allSamples: [...subGroup.samples],
3080
+ children: [],
3081
+ group: subGroup
3082
+ });
3083
+ }
3084
+ }
3085
+ return roots;
3086
+ });
3087
+ const maxDepth = computed(() => {
3088
+ const depthOf = (nodes) => nodes.reduce((deepest, node) => Math.max(deepest, 1 + depthOf(node.children)), 0);
3089
+ return depthOf(groupTree.value);
3090
+ });
3091
+ const hierarchicalGroups = computed(() => families.value.map((family) => ({
3092
+ name: family.name,
3093
+ color: family.color,
3094
+ subGroups: family.subGroups,
3095
+ allSamples: family.subGroups.flatMap((group) => group.samples)
3096
+ })));
3097
+ const showHierarchy = computed(() => maxDepth.value > 1);
2924
3098
  const groupedSamples = computed(() => new Set(groups.value.flatMap((group) => group.samples)));
2925
3099
  const ungroupedSamples = computed(() => samples.value.filter((sample) => !groupedSamples.value.has(sample)));
2926
3100
  function findGroup(groupName) {
@@ -2932,6 +3106,8 @@ function useSampleGroups(options) {
2932
3106
  return {
2933
3107
  groups,
2934
3108
  separator,
3109
+ groupTree,
3110
+ maxDepth,
2935
3111
  hierarchicalGroups,
2936
3112
  showHierarchy,
2937
3113
  groupedSamples,
@@ -2941,8 +3117,7 @@ function useSampleGroups(options) {
2941
3117
  };
2942
3118
  }
2943
3119
  function getMajorGroupName(groupName, separator) {
2944
- const parts = groupName.split(separator);
2945
- return parts.length > 1 ? parts[0] : groupName;
3120
+ return splitSampleGroupPath(groupName, separator)[0];
2946
3121
  }
2947
3122
  //#endregion
2948
3123
  //#region src/composables/useExpansionSet.ts
@@ -4760,6 +4935,6 @@ function useProtocolTemplates() {
4760
4935
  };
4761
4936
  }
4762
4937
  //#endregion
4763
- export { extractSamplesFromDesignData as A, useJobsStatusTray as B, hexToHsl as C, readFileAsText as D, parseDelimitedText as E, unwrapExperimentDesignData as F, useAppExperiment as G, DEFAULT_MOBILE_VIEWPORT_QUERY as H, DEFAULT_COLORS as I, candidateMatchesSearch as J, useTheme as K, useWellPlateEditor as L, parseCSV as M, extractSampleNamesFromDesignData as N, useFileImport as O, extractSampleOptionsFromDesignData as P, useSortedItems as Q, useDoseCalculator as R, deriveShade as S, detectDelimiter as T, useMobileSupportGate as U, usePluginJobCenter as V, APP_EXPERIMENT_KEY as W, useTextSearch as X, normalizeSearchQuery as Y, compareSortValues as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, useAutoGroup as j, validateImportFile as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, useGroupAssignment as o, useBioTemplateComponents as p, useToast as q, DEFAULT_UNITS as r, useRackEditor as s, useProtocolTemplates as t, useBioTemplateWorkspace as u, useExperimentSamples as v, hslToHex as w, useSampleGroups as x, useExperimentData as y, combinePluginJobSources as z };
4938
+ export { compareSortValues as $, useFileImport as A, useDoseCalculator as B, getSampleGroupParentPath as C, detectDelimiter as D, hslToHex as E, extractSampleNamesFromDesignData as F, useMobileSupportGate as G, useJobsStatusTray as H, extractSampleOptionsFromDesignData as I, useTheme as J, APP_EXPERIMENT_KEY as K, unwrapExperimentDesignData as L, extractSamplesFromDesignData as M, useAutoGroup as N, parseDelimitedText as O, parseCSV as P, useTextSearch as Q, DEFAULT_COLORS as R, getSampleGroupMajorPrefix as S, hexToHsl as T, usePluginJobCenter as U, combinePluginJobSources as V, DEFAULT_MOBILE_VIEWPORT_QUERY as W, candidateMatchesSearch as X, useToast as Y, normalizeSearchQuery as Z, useScheduleDrag as _, useReagentSeries as a, useExpansionSet as b, useBioTemplatePresetWorkspace as c, getBioTemplateComponentProps as d, useSortedItems as et, toBioTemplateComponentPropsByComponent as f, useExperimentSave as g, useTemplateCollection as h, generateDilutionSeries as i, validateImportFile as j, readFileAsText as k, useBioTemplatePackWorkspace as l, useBioTemplateControls as m, DEFAULT_PRESETS as n, useGroupAssignment as o, useBioTemplateComponents as p, useAppExperiment as q, DEFAULT_UNITS as r, useRackEditor as s, useProtocolTemplates as t, useBioTemplateWorkspace as u, useExperimentSamples as v, deriveShade as w, useSampleGroups as x, useExperimentData as y, useWellPlateEditor as z };
4764
4939
 
4765
- //# sourceMappingURL=useProtocolTemplates-BMt0LlXf.js.map
4940
+ //# sourceMappingURL=useProtocolTemplates-BWfNaynA.js.map