@morscherlab/mld-sdk 0.6.0 → 0.6.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.
@@ -1,4 +1,4 @@
1
- import { WellPlateFormat, WellPlateSelectionMode, WellPlateSize, Well, HeatmapConfig, WellShape, WellEditField, WellEditData, WellLegendItem } from '../types';
1
+ import { WellPlateFormat, WellPlateSelectionMode, WellPlateSize, Well, HeatmapConfig, WellShape, WellEditField, WellEditData, WellLegendItem, ColumnCondition, RowCondition } from '../types';
2
2
  interface Props {
3
3
  modelValue?: string[];
4
4
  format?: WellPlateFormat;
@@ -21,6 +21,8 @@ interface Props {
21
21
  defaultInjectionVolume?: number;
22
22
  showLegend?: boolean;
23
23
  legendItems?: WellLegendItem[];
24
+ columnConditions?: ColumnCondition[];
25
+ rowConditions?: RowCondition[];
24
26
  }
25
27
  declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, import('vue').ComponentOptionsMixin, import('vue').ComponentOptionsMixin, {
26
28
  "update:modelValue": (wellIds: string[]) => any;
@@ -62,6 +64,8 @@ declare const _default: import('vue').DefineComponent<Props, {}, {}, {}, {}, imp
62
64
  editable: boolean;
63
65
  showLegend: boolean;
64
66
  legendItems: WellLegendItem[];
67
+ columnConditions: ColumnCondition[];
68
+ rowConditions: RowCondition[];
65
69
  }, {}, {}, {}, string, import('vue').ComponentProvideOptions, false, {
66
70
  plateRef: HTMLDivElement;
67
71
  tableRef: HTMLTableElement;
@@ -1,36 +1,45 @@
1
- import { defineComponent, ref, computed, onMounted, onUnmounted, openBlock, createElementBlock, normalizeStyle, normalizeClass, createElementVNode, Fragment, renderList, toDisplayString, createCommentVNode, withKeys, withModifiers, createBlock } from "vue";
1
+ import { defineComponent, ref, computed, onMounted, onUnmounted, openBlock, createElementBlock, normalizeStyle, normalizeClass, createElementVNode, createCommentVNode, Fragment, renderList, createTextVNode, toDisplayString, withKeys, withModifiers, createBlock } from "vue";
2
2
  import _sfc_main$1 from "./WellEditPopup.vue.js";
3
3
  /* empty css */
4
4
  const _hoisted_1 = { class: "mld-well-plate__scroll" };
5
5
  const _hoisted_2 = { class: "mld-well-plate__content" };
6
6
  const _hoisted_3 = ["aria-label"];
7
7
  const _hoisted_4 = { key: 0 };
8
- const _hoisted_5 = ["aria-label", "aria-selected", "aria-disabled", "draggable", "title", "onClick", "onMousedown", "onMouseenter", "onContextmenu", "onDragstart", "onDragover", "onDrop", "onKeydown"];
9
- const _hoisted_6 = {
8
+ const _hoisted_5 = ["colspan"];
9
+ const _hoisted_6 = ["colspan"];
10
+ const _hoisted_7 = { key: 1 };
11
+ const _hoisted_8 = ["rowspan"];
12
+ const _hoisted_9 = {
13
+ key: 0,
14
+ class: "mld-well-plate__row-condition-wrap"
15
+ };
16
+ const _hoisted_10 = { class: "mld-well-plate__row-condition-text" };
17
+ const _hoisted_11 = ["aria-label", "aria-selected", "aria-disabled", "draggable", "title", "onClick", "onMousedown", "onMouseenter", "onContextmenu", "onDragstart", "onDragover", "onDrop", "onKeydown"];
18
+ const _hoisted_12 = {
10
19
  key: 0,
11
20
  class: "mld-well-plate__label"
12
21
  };
13
- const _hoisted_7 = {
22
+ const _hoisted_13 = {
14
23
  key: 1,
15
24
  class: "mld-well-plate__indicator"
16
25
  };
17
- const _hoisted_8 = {
26
+ const _hoisted_14 = {
18
27
  key: 2,
19
28
  class: "mld-well-plate__well-id"
20
29
  };
21
- const _hoisted_9 = ["title"];
22
- const _hoisted_10 = {
30
+ const _hoisted_15 = ["title"];
31
+ const _hoisted_16 = {
23
32
  key: 0,
24
33
  class: "mld-well-plate__legend"
25
34
  };
26
- const _hoisted_11 = { class: "mld-well-plate__legend-label" };
27
- const _hoisted_12 = { class: "mld-well-plate__legend-bar" };
28
- const _hoisted_13 = { class: "mld-well-plate__legend-label" };
29
- const _hoisted_14 = {
35
+ const _hoisted_17 = { class: "mld-well-plate__legend-label" };
36
+ const _hoisted_18 = { class: "mld-well-plate__legend-bar" };
37
+ const _hoisted_19 = { class: "mld-well-plate__legend-label" };
38
+ const _hoisted_20 = {
30
39
  key: 1,
31
40
  class: "mld-well-plate__sample-legend"
32
41
  };
33
- const _hoisted_15 = { class: "mld-well-plate__sample-legend-text" };
42
+ const _hoisted_21 = { class: "mld-well-plate__sample-legend-text" };
34
43
  const _sfc_main = /* @__PURE__ */ defineComponent({
35
44
  __name: "WellPlate",
36
45
  props: {
@@ -54,7 +63,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
54
63
  editFields: { default: () => ["label", "sampleType", "injectionVolume", "injectionCount", "customMethod"] },
55
64
  defaultInjectionVolume: { default: 5 },
56
65
  showLegend: { type: Boolean, default: false },
57
- legendItems: { default: void 0 }
66
+ legendItems: { default: void 0 },
67
+ columnConditions: { default: () => [] },
68
+ rowConditions: { default: () => [] }
58
69
  },
59
70
  emits: ["update:modelValue", "well-click", "well-hover", "selection-change", "context-menu", "well-move", "well-edit", "well-clear"],
60
71
  setup(__props, { emit: __emit }) {
@@ -140,6 +151,86 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
140
151
  { type: "qc", label: "QC", color: "#8b5cf6" }
141
152
  ];
142
153
  const activeLegendItems = computed(() => props.legendItems ?? defaultLegendItems);
154
+ const hasColumnConditions = computed(() => props.columnConditions.length > 0);
155
+ const hasRowConditions = computed(() => props.rowConditions.length > 0);
156
+ const colConditionMap = computed(() => {
157
+ const map = /* @__PURE__ */ new Map();
158
+ for (const cond of props.columnConditions) {
159
+ cond.cols.forEach((col, i) => {
160
+ map.set(col, { condition: cond, indexInGroup: i });
161
+ });
162
+ }
163
+ return map;
164
+ });
165
+ const rowConditionMap = computed(() => {
166
+ const map = /* @__PURE__ */ new Map();
167
+ for (const cond of props.rowConditions) {
168
+ cond.rows.forEach((row, i) => {
169
+ map.set(row, { condition: cond, indexInGroup: i });
170
+ });
171
+ }
172
+ return map;
173
+ });
174
+ const colConditionSpans = computed(() => {
175
+ const spans = [];
176
+ const cols = colLabels.value;
177
+ let i = 0;
178
+ while (i < cols.length) {
179
+ const entry = colConditionMap.value.get(cols[i]);
180
+ if ((entry == null ? void 0 : entry.indexInGroup) === 0) {
181
+ spans.push({ condition: entry.condition, colspan: entry.condition.cols.length });
182
+ i += entry.condition.cols.length;
183
+ } else {
184
+ let gapCount = 0;
185
+ while (i + gapCount < cols.length && !colConditionMap.value.has(cols[i + gapCount])) {
186
+ gapCount++;
187
+ }
188
+ spans.push({ gap: true, colspan: gapCount || 1 });
189
+ i += gapCount || 1;
190
+ }
191
+ }
192
+ return spans;
193
+ });
194
+ const rowConditionSpans = computed(() => {
195
+ const spans = [];
196
+ const rows = rowLabels.value;
197
+ let i = 0;
198
+ while (i < rows.length) {
199
+ const entry = rowConditionMap.value.get(rows[i]);
200
+ if ((entry == null ? void 0 : entry.indexInGroup) === 0) {
201
+ spans.push({ condition: entry.condition, rowspan: entry.condition.rows.length, startRow: i });
202
+ i += entry.condition.rows.length;
203
+ } else {
204
+ let gapCount = 0;
205
+ while (i + gapCount < rows.length && !rowConditionMap.value.has(rows[i + gapCount])) {
206
+ gapCount++;
207
+ }
208
+ spans.push({ gap: true, rowspan: gapCount || 1, startRow: i });
209
+ i += gapCount || 1;
210
+ }
211
+ }
212
+ return spans;
213
+ });
214
+ const rowConditionSpanByRow = computed(() => {
215
+ const map = /* @__PURE__ */ new Map();
216
+ for (const span of rowConditionSpans.value) {
217
+ map.set(span.startRow, span);
218
+ }
219
+ return map;
220
+ });
221
+ function conditionGradientBg(color, index, total) {
222
+ const t = total <= 1 ? 1 : index / (total - 1);
223
+ const opacity = 0.12 + t * 0.38;
224
+ const r = parseInt(color.slice(1, 3), 16);
225
+ const g = parseInt(color.slice(3, 5), 16);
226
+ const b = parseInt(color.slice(5, 7), 16);
227
+ return `rgba(${r}, ${g}, ${b}, ${opacity})`;
228
+ }
229
+ function formatConc(value) {
230
+ if (value >= 1e3) return `${value / 1e3}k`;
231
+ if (value < 0.01) return value.toExponential(0);
232
+ return String(value);
233
+ }
143
234
  const defaultSampleTypeColors = {
144
235
  sample: { bg: "rgba(16, 185, 129, 0.15)", border: "rgba(16, 185, 129, 0.4)" },
145
236
  control: { bg: "rgba(59, 130, 246, 0.15)", border: "rgba(59, 130, 246, 0.4)" },
@@ -404,17 +495,74 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
404
495
  "aria-label": `${props.format}-well plate`,
405
496
  style: normalizeStyle(tableStyle.value)
406
497
  }, [
407
- props.showLabels ? (openBlock(), createElementBlock("thead", _hoisted_4, [
498
+ hasColumnConditions.value ? (openBlock(), createElementBlock("thead", _hoisted_4, [
499
+ createElementVNode("tr", null, [
500
+ createElementVNode("th", {
501
+ style: normalizeStyle({ width: sizeConfig.value.headerWidth })
502
+ }, null, 4),
503
+ hasRowConditions.value ? (openBlock(), createElementBlock("th", {
504
+ key: 0,
505
+ style: normalizeStyle({ width: sizeConfig.value.headerWidth })
506
+ }, null, 4)) : createCommentVNode("", true),
507
+ (openBlock(true), createElementBlock(Fragment, null, renderList(colConditionSpans.value, (span, idx) => {
508
+ return openBlock(), createElementBlock(Fragment, {
509
+ key: "clabel-" + idx
510
+ }, [
511
+ "condition" in span ? (openBlock(), createElementBlock("th", {
512
+ key: 0,
513
+ colspan: span.colspan,
514
+ class: "mld-well-plate__condition-label",
515
+ style: normalizeStyle({
516
+ height: sizeConfig.value.headerHeight,
517
+ fontSize: sizeConfig.value.fontSize,
518
+ color: span.condition.color
519
+ })
520
+ }, [
521
+ createTextVNode(toDisplayString(span.condition.label), 1),
522
+ span.condition.unit ? (openBlock(), createElementBlock(Fragment, { key: 0 }, [
523
+ createTextVNode(" (" + toDisplayString(span.condition.unit) + ")", 1)
524
+ ], 64)) : createCommentVNode("", true)
525
+ ], 12, _hoisted_5)) : (openBlock(), createElementBlock("th", {
526
+ key: 1,
527
+ colspan: span.colspan
528
+ }, null, 8, _hoisted_6))
529
+ ], 64);
530
+ }), 128))
531
+ ])
532
+ ])) : createCommentVNode("", true),
533
+ props.showLabels ? (openBlock(), createElementBlock("thead", _hoisted_7, [
408
534
  createElementVNode("tr", null, [
409
535
  createElementVNode("th", {
410
536
  style: normalizeStyle({ width: sizeConfig.value.headerWidth, height: sizeConfig.value.headerHeight })
411
537
  }, null, 4),
538
+ hasRowConditions.value ? (openBlock(), createElementBlock("th", {
539
+ key: 0,
540
+ style: normalizeStyle({ width: sizeConfig.value.headerWidth, height: sizeConfig.value.headerHeight })
541
+ }, null, 4)) : createCommentVNode("", true),
412
542
  (openBlock(true), createElementBlock(Fragment, null, renderList(colLabels.value, (col) => {
413
543
  return openBlock(), createElementBlock("th", {
414
544
  key: col,
415
545
  class: "mld-well-plate__col-header",
416
546
  style: normalizeStyle({ height: sizeConfig.value.headerHeight, fontSize: sizeConfig.value.fontSize })
417
- }, toDisplayString(col), 5);
547
+ }, [
548
+ (openBlock(true), createElementBlock(Fragment, null, renderList([colConditionMap.value.get(col)], (entry) => {
549
+ return openBlock(), createElementBlock(Fragment, { key: col }, [
550
+ entry ? (openBlock(), createElementBlock("span", {
551
+ key: 0,
552
+ class: "mld-well-plate__condition-cell",
553
+ style: normalizeStyle({
554
+ backgroundColor: conditionGradientBg(
555
+ entry.condition.color,
556
+ entry.indexInGroup,
557
+ entry.condition.cols.length
558
+ )
559
+ })
560
+ }, toDisplayString(formatConc(entry.condition.concentrations[entry.indexInGroup])), 5)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
561
+ createTextVNode(toDisplayString(col), 1)
562
+ ], 64))
563
+ ], 64);
564
+ }), 128))
565
+ ], 4);
418
566
  }), 128))
419
567
  ])
420
568
  ])) : createCommentVNode("", true),
@@ -424,11 +572,55 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
424
572
  key: rowIndex,
425
573
  role: "row"
426
574
  }, [
575
+ hasRowConditions.value && rowConditionSpanByRow.value.has(rowIndex) ? (openBlock(true), createElementBlock(Fragment, { key: 0 }, renderList([rowConditionSpanByRow.value.get(rowIndex)], (span) => {
576
+ return openBlock(), createElementBlock("td", {
577
+ key: rowIndex,
578
+ rowspan: span.rowspan,
579
+ class: normalizeClass([
580
+ "mld-well-plate__row-condition-label",
581
+ "gap" in span ? "mld-well-plate__row-condition-label--empty" : ""
582
+ ]),
583
+ style: normalizeStyle({
584
+ width: sizeConfig.value.headerWidth,
585
+ minWidth: sizeConfig.value.headerWidth,
586
+ fontSize: sizeConfig.value.fontSize,
587
+ ..."condition" in span ? { color: span.condition.color } : {}
588
+ })
589
+ }, [
590
+ "condition" in span ? (openBlock(), createElementBlock("div", _hoisted_9, [
591
+ createElementVNode("span", _hoisted_10, toDisplayString(span.condition.label), 1)
592
+ ])) : createCommentVNode("", true)
593
+ ], 14, _hoisted_8);
594
+ }), 128)) : createCommentVNode("", true),
427
595
  props.showLabels ? (openBlock(), createElementBlock("td", {
428
- key: 0,
596
+ key: 1,
429
597
  class: "mld-well-plate__row-header",
430
- style: normalizeStyle({ width: sizeConfig.value.headerWidth, height: sizeConfig.value.cellHeight, minWidth: sizeConfig.value.headerWidth, minHeight: sizeConfig.value.cellHeight, fontSize: sizeConfig.value.fontSize })
431
- }, toDisplayString(rowLabels.value[rowIndex]), 5)) : createCommentVNode("", true),
598
+ style: normalizeStyle({
599
+ width: sizeConfig.value.headerWidth,
600
+ height: sizeConfig.value.cellHeight,
601
+ minWidth: sizeConfig.value.headerWidth,
602
+ minHeight: sizeConfig.value.cellHeight,
603
+ fontSize: sizeConfig.value.fontSize
604
+ })
605
+ }, [
606
+ (openBlock(true), createElementBlock(Fragment, null, renderList([rowConditionMap.value.get(rowLabels.value[rowIndex])], (entry) => {
607
+ return openBlock(), createElementBlock(Fragment, { key: rowIndex }, [
608
+ entry ? (openBlock(), createElementBlock("span", {
609
+ key: 0,
610
+ class: "mld-well-plate__condition-cell",
611
+ style: normalizeStyle({
612
+ backgroundColor: conditionGradientBg(
613
+ entry.condition.color,
614
+ entry.indexInGroup,
615
+ entry.condition.rows.length
616
+ )
617
+ })
618
+ }, toDisplayString(formatConc(entry.condition.concentrations[entry.indexInGroup])), 5)) : (openBlock(), createElementBlock(Fragment, { key: 1 }, [
619
+ createTextVNode(toDisplayString(rowLabels.value[rowIndex]), 1)
620
+ ], 64))
621
+ ], 64);
622
+ }), 128))
623
+ ], 4)) : createCommentVNode("", true),
432
624
  (openBlock(true), createElementBlock(Fragment, null, renderList(row, (well) => {
433
625
  return openBlock(), createElementBlock("td", {
434
626
  key: well.id,
@@ -467,23 +659,23 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
467
659
  withKeys(withModifiers(($event) => handleWellClick(well, $event), ["prevent"]), ["space"])
468
660
  ]
469
661
  }, [
470
- getWellLabel(well) ? (openBlock(), createElementBlock("span", _hoisted_6, toDisplayString(getWellLabel(well)), 1)) : getSampleTypeIndicator(well) ? (openBlock(), createElementBlock("span", _hoisted_7, toDisplayString(getSampleTypeIndicator(well)), 1)) : props.showWellIds ? (openBlock(), createElementBlock("span", _hoisted_8, toDisplayString(well.id), 1)) : createCommentVNode("", true),
662
+ getWellLabel(well) ? (openBlock(), createElementBlock("span", _hoisted_12, toDisplayString(getWellLabel(well)), 1)) : getSampleTypeIndicator(well) ? (openBlock(), createElementBlock("span", _hoisted_13, toDisplayString(getSampleTypeIndicator(well)), 1)) : props.showWellIds ? (openBlock(), createElementBlock("span", _hoisted_14, toDisplayString(well.id), 1)) : createCommentVNode("", true),
471
663
  getWellBadge(well) ? (openBlock(), createElementBlock("span", {
472
664
  key: 3,
473
665
  class: "mld-well-plate__badge",
474
666
  style: normalizeStyle({ backgroundColor: getWellBadge(well).color }),
475
667
  title: getWellBadge(well).text === "+" ? "Custom method" : `${getWellBadge(well).text}x injections`
476
- }, toDisplayString(getWellBadge(well).text), 13, _hoisted_9)) : createCommentVNode("", true)
477
- ], 46, _hoisted_5)
668
+ }, toDisplayString(getWellBadge(well).text), 13, _hoisted_15)) : createCommentVNode("", true)
669
+ ], 46, _hoisted_11)
478
670
  ]);
479
671
  }), 128))
480
672
  ]);
481
673
  }), 128))
482
674
  ])
483
675
  ], 12, _hoisted_3),
484
- ((_a = props.heatmap) == null ? void 0 : _a.enabled) && props.heatmap.showLegend ? (openBlock(), createElementBlock("div", _hoisted_10, [
485
- createElementVNode("span", _hoisted_11, toDisplayString(props.heatmap.min ?? 0), 1),
486
- createElementVNode("div", _hoisted_12, [
676
+ ((_a = props.heatmap) == null ? void 0 : _a.enabled) && props.heatmap.showLegend ? (openBlock(), createElementBlock("div", _hoisted_16, [
677
+ createElementVNode("span", _hoisted_17, toDisplayString(props.heatmap.min ?? 0), 1),
678
+ createElementVNode("div", _hoisted_18, [
487
679
  (openBlock(true), createElementBlock(Fragment, null, renderList(props.heatmap.colorScale === "custom" && ((_b = props.heatmap.customColors) == null ? void 0 : _b.length) ? props.heatmap.customColors : heatmapColors[props.heatmap.colorScale || "viridis"], (color, index) => {
488
680
  return openBlock(), createElementBlock("div", {
489
681
  key: index,
@@ -492,9 +684,9 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
492
684
  }, null, 4);
493
685
  }), 128))
494
686
  ]),
495
- createElementVNode("span", _hoisted_13, toDisplayString(props.heatmap.max ?? 1), 1)
687
+ createElementVNode("span", _hoisted_19, toDisplayString(props.heatmap.max ?? 1), 1)
496
688
  ])) : createCommentVNode("", true),
497
- props.showLegend ? (openBlock(), createElementBlock("div", _hoisted_14, [
689
+ props.showLegend ? (openBlock(), createElementBlock("div", _hoisted_20, [
498
690
  (openBlock(true), createElementBlock(Fragment, null, renderList(activeLegendItems.value, (item) => {
499
691
  return openBlock(), createElementBlock("div", {
500
692
  key: item.type,
@@ -504,7 +696,7 @@ const _sfc_main = /* @__PURE__ */ defineComponent({
504
696
  class: "mld-well-plate__sample-legend-dot",
505
697
  style: normalizeStyle({ backgroundColor: `${item.color}26`, border: `1px solid ${item.color}66` })
506
698
  }, null, 4),
507
- createElementVNode("span", _hoisted_15, toDisplayString(item.label), 1)
699
+ createElementVNode("span", _hoisted_21, toDisplayString(item.label), 1)
508
700
  ]);
509
701
  }), 128))
510
702
  ])) : createCommentVNode("", true)
@@ -1 +1 @@
1
- {"version":3,"file":"WellPlate.vue.js","sources":["../../src/components/WellPlate.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type { WellPlateFormat, WellPlateSelectionMode, WellPlateSize, Well, HeatmapConfig, WellShape, WellEditField, WellEditData, WellLegendItem } from '../types'\nimport WellEditPopup from './WellEditPopup.vue'\n\ninterface Props {\n modelValue?: string[]\n format?: WellPlateFormat\n wells?: Record<string, Partial<Well>>\n selectionMode?: WellPlateSelectionMode\n showLabels?: boolean\n showWellIds?: boolean\n showSampleTypeIndicator?: boolean\n heatmap?: HeatmapConfig\n sampleColors?: Record<string, string>\n zoom?: number\n disabled?: boolean\n readonly?: boolean\n size?: WellPlateSize\n wellShape?: WellShape\n // New editing props\n showWellLabels?: boolean\n showBadges?: boolean\n editable?: boolean\n editFields?: WellEditField[]\n defaultInjectionVolume?: number\n showLegend?: boolean\n legendItems?: WellLegendItem[]\n}\n\n// Drag state for moving wells\nconst dragSourceWell = ref<string | null>(null)\nconst dragTargetWell = ref<string | null>(null)\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: () => [],\n format: 96,\n wells: () => ({}),\n selectionMode: 'multiple',\n showLabels: true,\n showWellIds: false,\n showSampleTypeIndicator: false,\n heatmap: () => ({ enabled: false }),\n sampleColors: () => ({}),\n zoom: 1,\n disabled: false,\n readonly: false,\n size: 'md',\n wellShape: 'rounded',\n // New props default to off for backward compatibility\n showWellLabels: false,\n showBadges: false,\n editable: false,\n editFields: () => ['label', 'sampleType', 'injectionVolume', 'injectionCount', 'customMethod'],\n defaultInjectionVolume: 5,\n showLegend: false,\n legendItems: undefined,\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [wellIds: string[]]\n 'well-click': [wellId: string, event: MouseEvent]\n 'well-hover': [wellId: string | null, event?: MouseEvent]\n 'selection-change': [wellIds: string[]]\n 'context-menu': [wellId: string, event: MouseEvent]\n 'well-move': [sourceWellId: string, targetWellId: string]\n // New editing emits\n 'well-edit': [wellId: string, data: WellEditData]\n 'well-clear': [wellId: string]\n}>()\n\nconst plateRef = ref<HTMLElement | null>(null)\nconst tableRef = ref<HTMLElement | null>(null)\nconst isDragging = ref(false)\nconst dragStart = ref<{ row: number; col: number } | null>(null)\nconst dragEnd = ref<{ row: number; col: number } | null>(null)\nconst hoveredWell = ref<string | null>(null)\n\n// Edit popup state\nconst editingWellId = ref<string | null>(null)\nconst editPopupPosition = ref({ x: 0, y: 0 })\n\nconst PLATE_CONFIGS: Record<WellPlateFormat, { rows: number; cols: number }> = {\n 6: { rows: 2, cols: 3 },\n 12: { rows: 3, cols: 4 },\n 24: { rows: 4, cols: 6 },\n 48: { rows: 6, cols: 8 },\n 54: { rows: 6, cols: 9 },\n 96: { rows: 8, cols: 12 },\n 384: { rows: 16, cols: 24 },\n}\n\nconst plateConfig = computed(() => PLATE_CONFIGS[props.format])\n\nconst rowLabels = computed(() =>\n Array.from({ length: plateConfig.value.rows }, (_, i) => String.fromCharCode(65 + i))\n)\n\nconst colLabels = computed(() =>\n Array.from({ length: plateConfig.value.cols }, (_, i) => i + 1)\n)\n\nconst wellGrid = computed(() => {\n const grid: Well[][] = []\n for (let row = 0; row < plateConfig.value.rows; row++) {\n const rowWells: Well[] = []\n for (let col = 0; col < plateConfig.value.cols; col++) {\n const id = `${rowLabels.value[row]}${col + 1}`\n const wellData = props.wells[id] || {}\n rowWells.push({\n id,\n row,\n col,\n state: wellData.state || 'empty',\n sampleType: wellData.sampleType,\n value: wellData.value,\n metadata: wellData.metadata,\n })\n }\n grid.push(rowWells)\n }\n return grid\n})\n\nconst selectedWellSet = computed(() => new Set(props.modelValue))\n\nconst dragSelectedWells = computed(() => {\n if (!isDragging.value || !dragStart.value || !dragEnd.value) return new Set<string>()\n\n const minRow = Math.min(dragStart.value.row, dragEnd.value.row)\n const maxRow = Math.max(dragStart.value.row, dragEnd.value.row)\n const minCol = Math.min(dragStart.value.col, dragEnd.value.col)\n const maxCol = Math.max(dragStart.value.col, dragEnd.value.col)\n\n const wells = new Set<string>()\n for (let row = minRow; row <= maxRow; row++) {\n for (let col = minCol; col <= maxCol; col++) {\n const id = `${rowLabels.value[row]}${col + 1}`\n wells.add(id)\n }\n }\n return wells\n})\n\n// Size presets with pixel values for reliable sizing\nconst sizeConfig = computed(() => {\n const sizes = {\n sm: { cellWidth: '40px', cellHeight: '40px', headerWidth: '32px', headerHeight: '32px', fontSize: '0.625rem', gap: '2px' },\n md: { cellWidth: '56px', cellHeight: '32px', headerWidth: '32px', headerHeight: '24px', fontSize: '0.75rem', gap: '3px' },\n lg: { cellWidth: '80px', cellHeight: '40px', headerWidth: '40px', headerHeight: '32px', fontSize: '0.875rem', gap: '4px' },\n xl: { cellWidth: '96px', cellHeight: '48px', headerWidth: '48px', headerHeight: '40px', fontSize: '1rem', gap: '4px' },\n fill: { cellWidth: '100%', cellHeight: '32px', headerWidth: '32px', headerHeight: '24px', fontSize: '0.75rem', gap: '2px' },\n }\n return sizes[props.size]\n})\n\nconst isFillMode = computed(() => props.size === 'fill')\n\n// Default legend items\nconst defaultLegendItems: WellLegendItem[] = [\n { type: 'sample', label: 'Sample', color: '#10b981' },\n { type: 'blank', label: 'Blank', color: '#f97316' },\n { type: 'qc', label: 'QC', color: '#8b5cf6' },\n]\n\nconst activeLegendItems = computed(() => props.legendItems ?? defaultLegendItems)\n\n// Sample type colors (matching MSExpDesigner)\nconst defaultSampleTypeColors: Record<string, { bg: string; border: string }> = {\n sample: { bg: 'rgba(16, 185, 129, 0.15)', border: 'rgba(16, 185, 129, 0.4)' },\n control: { bg: 'rgba(59, 130, 246, 0.15)', border: 'rgba(59, 130, 246, 0.4)' },\n blank: { bg: 'rgba(249, 115, 22, 0.15)', border: 'rgba(249, 115, 22, 0.4)' },\n qc: { bg: 'rgba(139, 92, 246, 0.15)', border: 'rgba(139, 92, 246, 0.4)' },\n}\n\nconst heatmapColors: Record<string, string[]> = {\n viridis: ['#440154', '#482878', '#3e4989', '#31688e', '#26828e', '#1f9e89', '#35b779', '#6ece58', '#b5de2b', '#fde725'],\n plasma: ['#0d0887', '#46039f', '#7201a8', '#9c179e', '#bd3786', '#d8576b', '#ed7953', '#fb9f3a', '#fdca26', '#f0f921'],\n turbo: ['#30123b', '#4145ab', '#4675ed', '#39a2fc', '#1bcfd4', '#24e79e', '#71f05f', '#c1f034', '#f1c83c', '#f99538', '#e45a31', '#ba2512', '#7a0403'],\n}\n\nfunction getHeatmapColor(value: number | undefined): string | null {\n if (!props.heatmap?.enabled || value === undefined) return null\n\n const min = props.heatmap.min ?? 0\n const max = props.heatmap.max ?? 1\n const normalized = Math.max(0, Math.min(1, (value - min) / (max - min)))\n\n const colors = props.heatmap.colorScale === 'custom' && props.heatmap.customColors?.length\n ? props.heatmap.customColors\n : heatmapColors[props.heatmap.colorScale || 'viridis']\n\n const index = Math.min(Math.floor(normalized * (colors.length - 1)), colors.length - 1)\n return colors[index]\n}\n\nfunction getWellClasses(well: Well): string[] {\n const isWellSelected = isSelected(well.id)\n const isDragOver = dragSelectedWells.value.has(well.id)\n const isHovered = hoveredWell.value === well.id\n const isDisabled = props.disabled || well.state === 'disabled'\n const isDragSource = dragSourceWell.value === well.id\n const isDragTarget = dragTargetWell.value === well.id\n\n const classes = [\n 'mld-well-plate__well',\n props.wellShape === 'circle' ? 'mld-well-plate__well--circle' : 'mld-well-plate__well--rounded',\n ]\n\n if (props.selectionMode === 'drag' && well.sampleType) {\n classes.push('mld-well-plate__well--draggable')\n }\n\n if (isDragSource) classes.push('mld-well-plate__well--drag-source')\n else if (isDragTarget) classes.push('mld-well-plate__well--drag-target')\n else if (isWellSelected) classes.push('mld-well-plate__well--selected')\n else if (isDragOver) classes.push('mld-well-plate__well--drag-over')\n else if (isHovered && !props.readonly) classes.push('mld-well-plate__well--hovered')\n\n if (isDisabled) classes.push('mld-well-plate__well--disabled')\n if (well.state === 'filled') classes.push('mld-well-plate__well--filled')\n\n return classes\n}\n\nfunction getWellStyle(well: Well): Record<string, string> {\n const heatmapColor = getHeatmapColor(well.value)\n if (heatmapColor) {\n return { backgroundColor: heatmapColor, border: '1px solid transparent' }\n }\n\n if (well.sampleType && props.sampleColors[well.sampleType]) {\n const color = props.sampleColors[well.sampleType]\n return {\n backgroundColor: `${color}26`,\n border: `1px solid ${color}66`,\n }\n }\n\n if (well.sampleType && defaultSampleTypeColors[well.sampleType]) {\n const colors = defaultSampleTypeColors[well.sampleType]\n return {\n backgroundColor: colors.bg,\n border: `1px solid ${colors.border}`,\n }\n }\n\n const borderStyle = well.state === 'filled' ? 'solid' : 'dashed'\n return {\n backgroundColor: 'var(--bg-tertiary)',\n border: `1px ${borderStyle} var(--border-color)`,\n }\n}\n\nfunction getSampleTypeIndicator(well: Well): string | null {\n if (!props.showSampleTypeIndicator || !well.sampleType) return null\n const typeMap: Record<string, string> = {\n sample: 'S',\n control: 'C',\n blank: 'B',\n qc: 'Q',\n }\n return typeMap[well.sampleType] || well.sampleType.charAt(0).toUpperCase()\n}\n\nfunction getWellLabel(well: Well): string | undefined {\n if (!props.showWellLabels) return undefined\n return well.metadata?.label as string | undefined\n}\n\nfunction getWellBadge(well: Well): { text: string; color: string } | null {\n if (!props.showBadges || !well.metadata) return null\n const count = well.metadata.injectionCount as number | undefined\n if (count && count > 1) {\n return { text: String(count), color: '#6366f1' }\n }\n if (well.metadata.customMethod) {\n return { text: '+', color: '#ec4899' }\n }\n return null\n}\n\nfunction isSelected(wellId: string): boolean {\n return selectedWellSet.value.has(wellId) || dragSelectedWells.value.has(wellId)\n}\n\nfunction handleWellClick(well: Well, event: MouseEvent) {\n if (props.disabled || props.readonly) return\n\n emit('well-click', well.id, event)\n\n // When editable, open popup instead of modifying selection\n if (props.editable) {\n openEditPopup(well.id, event)\n return\n }\n\n if (props.selectionMode === 'none') return\n\n const isCurrentlySelected = selectedWellSet.value.has(well.id)\n const isMultiSelect = event.shiftKey || event.metaKey || event.ctrlKey\n\n let newSelection: string[]\n if (props.selectionMode === 'single') {\n newSelection = isCurrentlySelected ? [] : [well.id]\n } else if (isMultiSelect) {\n newSelection = isCurrentlySelected\n ? props.modelValue.filter(id => id !== well.id)\n : [...props.modelValue, well.id]\n } else {\n newSelection = isCurrentlySelected && props.modelValue.length === 1 ? [] : [well.id]\n }\n\n emit('update:modelValue', newSelection)\n emit('selection-change', newSelection)\n}\n\nfunction openEditPopup(wellId: string, event: MouseEvent) {\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n editPopupPosition.value = {\n x: rect.right + 8,\n y: rect.top,\n }\n editingWellId.value = wellId\n}\n\nfunction handleEditSave(data: WellEditData) {\n emit('well-edit', data.wellId, data)\n editingWellId.value = null\n}\n\nfunction handleEditClear() {\n if (editingWellId.value) {\n emit('well-clear', editingWellId.value)\n }\n editingWellId.value = null\n}\n\nfunction handleEditClose() {\n editingWellId.value = null\n}\n\nfunction handleWellMouseDown(well: Well, event: MouseEvent) {\n if (props.disabled || props.readonly || props.selectionMode !== 'rectangle') return\n if (props.editable) return\n if (event.button !== 0) return\n\n isDragging.value = true\n dragStart.value = { row: well.row, col: well.col }\n dragEnd.value = { row: well.row, col: well.col }\n}\n\nfunction handleWellMouseEnter(well: Well, event: MouseEvent) {\n hoveredWell.value = well.id\n emit('well-hover', well.id, event)\n\n if (isDragging.value && props.selectionMode === 'rectangle') {\n dragEnd.value = { row: well.row, col: well.col }\n }\n}\n\nfunction handleWellMouseLeave() {\n hoveredWell.value = null\n emit('well-hover', null)\n}\n\nfunction handleMouseUp() {\n if (!isDragging.value || props.selectionMode !== 'rectangle') return\n\n const newSelection = Array.from(dragSelectedWells.value)\n isDragging.value = false\n dragStart.value = null\n dragEnd.value = null\n\n if (newSelection.length > 0) {\n emit('update:modelValue', newSelection)\n emit('selection-change', newSelection)\n }\n}\n\nfunction handleContextMenu(well: Well, event: MouseEvent) {\n event.preventDefault()\n emit('context-menu', well.id, event)\n}\n\n// Drag handlers for moving well contents\nfunction handleDragStart(well: Well, event: DragEvent) {\n if (props.disabled || props.readonly || props.selectionMode !== 'drag') return\n if (!well.sampleType) return\n\n dragSourceWell.value = well.id\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', well.id)\n }\n}\n\nfunction handleDragOver(well: Well, event: DragEvent) {\n if (props.selectionMode !== 'drag' || !dragSourceWell.value) return\n event.preventDefault()\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move'\n }\n dragTargetWell.value = well.id\n}\n\nfunction handleDragLeave() {\n dragTargetWell.value = null\n}\n\nfunction handleDrop(well: Well, event: DragEvent) {\n event.preventDefault()\n if (props.selectionMode !== 'drag' || !dragSourceWell.value) return\n\n const sourceId = dragSourceWell.value\n const targetId = well.id\n\n if (sourceId !== targetId) {\n emit('well-move', sourceId, targetId)\n }\n\n dragSourceWell.value = null\n dragTargetWell.value = null\n}\n\nfunction handleDragEnd() {\n dragSourceWell.value = null\n dragTargetWell.value = null\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n if (props.disabled || props.readonly) return\n\n if (event.key === 'Escape') {\n if (editingWellId.value) {\n editingWellId.value = null\n return\n }\n emit('update:modelValue', [])\n emit('selection-change', [])\n }\n\n if ((event.key === 'a' || event.key === 'A') && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n const allWells = wellGrid.value.flat().map(w => w.id)\n emit('update:modelValue', allWells)\n emit('selection-change', allWells)\n }\n}\n\nonMounted(() => {\n document.addEventListener('mouseup', handleMouseUp)\n document.addEventListener('keydown', handleKeyDown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mouseup', handleMouseUp)\n document.removeEventListener('keydown', handleKeyDown)\n})\n\nconst containerStyle = computed(() =>\n isFillMode.value ? {} : {\n transform: `scale(${props.zoom})`,\n transformOrigin: 'top left',\n }\n)\n\nconst tableStyle = computed(() => ({\n borderCollapse: 'separate' as const,\n borderSpacing: sizeConfig.value.gap,\n ...(isFillMode.value ? { width: '100%', tableLayout: 'fixed' as const } : {}),\n}))\n</script>\n\n<template>\n <div\n ref=\"plateRef\"\n :class=\"['mld-well-plate', isFillMode ? 'mld-well-plate--fill' : 'mld-well-plate--inline']\"\n :style=\"containerStyle\"\n >\n <div class=\"mld-well-plate__scroll\">\n <div class=\"mld-well-plate__content\">\n <table\n ref=\"tableRef\"\n class=\"mld-well-plate__table\"\n role=\"grid\"\n :aria-label=\"`${props.format}-well plate`\"\n :style=\"tableStyle\"\n >\n <!-- Column headers -->\n <thead v-if=\"props.showLabels\">\n <tr>\n <th :style=\"{ width: sizeConfig.headerWidth, height: sizeConfig.headerHeight }\"></th>\n <th\n v-for=\"col in colLabels\"\n :key=\"col\"\n class=\"mld-well-plate__col-header\"\n :style=\"{ height: sizeConfig.headerHeight, fontSize: sizeConfig.fontSize }\"\n >\n {{ col }}\n </th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, rowIndex) in wellGrid\" :key=\"rowIndex\" role=\"row\">\n <!-- Row header -->\n <td\n v-if=\"props.showLabels\"\n class=\"mld-well-plate__row-header\"\n :style=\"{ width: sizeConfig.headerWidth, height: sizeConfig.cellHeight, minWidth: sizeConfig.headerWidth, minHeight: sizeConfig.cellHeight, fontSize: sizeConfig.fontSize }\"\n >\n {{ rowLabels[rowIndex] }}\n </td>\n\n <!-- Wells -->\n <td v-for=\"well in row\" :key=\"well.id\" class=\"mld-well-plate__cell\">\n <div\n role=\"gridcell\"\n tabindex=\"0\"\n :aria-label=\"`Well ${well.id}${well.sampleType ? `, Sample type: ${well.sampleType}` : ''}${well.value !== undefined ? `, Value: ${well.value}` : ''}`\"\n :aria-selected=\"isSelected(well.id)\"\n :aria-disabled=\"props.disabled || well.state === 'disabled'\"\n :draggable=\"props.selectionMode === 'drag' && !!well.sampleType\"\n :class=\"getWellClasses(well)\"\n :style=\"{\n width: isFillMode ? '100%' : sizeConfig.cellWidth,\n height: sizeConfig.cellHeight,\n minWidth: isFillMode ? '0' : sizeConfig.cellWidth,\n minHeight: sizeConfig.cellHeight,\n boxSizing: 'border-box',\n fontSize: sizeConfig.fontSize,\n ...getWellStyle(well),\n }\"\n :title=\"`${well.id}${well.sampleType ? `: ${well.sampleType}` : ''}${getWellLabel(well) ? ` - ${getWellLabel(well)}` : ''}`\"\n @click=\"handleWellClick(well, $event)\"\n @mousedown=\"handleWellMouseDown(well, $event)\"\n @mouseenter=\"handleWellMouseEnter(well, $event)\"\n @mouseleave=\"handleWellMouseLeave\"\n @contextmenu=\"handleContextMenu(well, $event)\"\n @dragstart=\"handleDragStart(well, $event)\"\n @dragover.prevent=\"handleDragOver(well, $event)\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop(well, $event)\"\n @dragend=\"handleDragEnd\"\n @keydown.enter=\"handleWellClick(well, $event as unknown as MouseEvent)\"\n @keydown.space.prevent=\"handleWellClick(well, $event as unknown as MouseEvent)\"\n >\n <!-- Well label text (from metadata.label) -->\n <span\n v-if=\"getWellLabel(well)\"\n class=\"mld-well-plate__label\"\n >\n {{ getWellLabel(well) }}\n </span>\n <!-- Sample type indicator (S/B/Q/C) -->\n <span\n v-else-if=\"getSampleTypeIndicator(well)\"\n class=\"mld-well-plate__indicator\"\n >\n {{ getSampleTypeIndicator(well) }}\n </span>\n <!-- Well ID -->\n <span\n v-else-if=\"props.showWellIds\"\n class=\"mld-well-plate__well-id\"\n >\n {{ well.id }}\n </span>\n\n <!-- Badge (injection count or custom method) -->\n <span\n v-if=\"getWellBadge(well)\"\n class=\"mld-well-plate__badge\"\n :style=\"{ backgroundColor: getWellBadge(well)!.color }\"\n :title=\"getWellBadge(well)!.text === '+' ? 'Custom method' : `${getWellBadge(well)!.text}x injections`\"\n >\n {{ getWellBadge(well)!.text }}\n </span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n\n <!-- Heatmap legend (inside content wrapper to match table width) -->\n <div\n v-if=\"props.heatmap?.enabled && props.heatmap.showLegend\"\n class=\"mld-well-plate__legend\"\n >\n <span class=\"mld-well-plate__legend-label\">{{ props.heatmap.min ?? 0 }}</span>\n <div class=\"mld-well-plate__legend-bar\">\n <div\n v-for=\"(color, index) in (props.heatmap.colorScale === 'custom' && props.heatmap.customColors?.length ? props.heatmap.customColors : heatmapColors[props.heatmap.colorScale || 'viridis'])\"\n :key=\"index\"\n class=\"mld-well-plate__legend-segment\"\n :style=\"{ backgroundColor: color }\"\n />\n </div>\n <span class=\"mld-well-plate__legend-label\">{{ props.heatmap.max ?? 1 }}</span>\n </div>\n\n <!-- Sample type legend bar -->\n <div v-if=\"props.showLegend\" class=\"mld-well-plate__sample-legend\">\n <div\n v-for=\"item in activeLegendItems\"\n :key=\"item.type\"\n class=\"mld-well-plate__sample-legend-item\"\n >\n <span\n class=\"mld-well-plate__sample-legend-dot\"\n :style=\"{ backgroundColor: `${item.color}26`, border: `1px solid ${item.color}66` }\"\n />\n <span class=\"mld-well-plate__sample-legend-text\">{{ item.label }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Edit popup -->\n <WellEditPopup\n v-if=\"editable && editingWellId\"\n :well-id=\"editingWellId\"\n :well-data=\"wells[editingWellId]\"\n :edit-fields=\"editFields\"\n :default-injection-volume=\"defaultInjectionVolume\"\n :position=\"editPopupPosition\"\n @save=\"handleEditSave\"\n @clear=\"handleEditClear\"\n @close=\"handleEditClose\"\n />\n </div>\n</template>\n\n<style>\n@import '../styles/components/well-plate.css';\n</style>\n"],"names":["_createElementBlock","_createElementVNode","_Fragment","_renderList","_openBlock","_toDisplayString","_normalizeClass","_normalizeStyle","_withModifiers","_createBlock","WellEditPopup"],"mappings":"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"}
1
+ {"version":3,"file":"WellPlate.vue.js","sources":["../../src/components/WellPlate.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { ref, computed, onMounted, onUnmounted } from 'vue'\nimport type { WellPlateFormat, WellPlateSelectionMode, WellPlateSize, Well, HeatmapConfig, WellShape, WellEditField, WellEditData, WellLegendItem, ColumnCondition, RowCondition } from '../types'\nimport WellEditPopup from './WellEditPopup.vue'\n\ninterface Props {\n modelValue?: string[]\n format?: WellPlateFormat\n wells?: Record<string, Partial<Well>>\n selectionMode?: WellPlateSelectionMode\n showLabels?: boolean\n showWellIds?: boolean\n showSampleTypeIndicator?: boolean\n heatmap?: HeatmapConfig\n sampleColors?: Record<string, string>\n zoom?: number\n disabled?: boolean\n readonly?: boolean\n size?: WellPlateSize\n wellShape?: WellShape\n showWellLabels?: boolean\n showBadges?: boolean\n editable?: boolean\n editFields?: WellEditField[]\n defaultInjectionVolume?: number\n showLegend?: boolean\n legendItems?: WellLegendItem[]\n columnConditions?: ColumnCondition[]\n rowConditions?: RowCondition[]\n}\n\n// Drag state for moving wells\nconst dragSourceWell = ref<string | null>(null)\nconst dragTargetWell = ref<string | null>(null)\n\nconst props = withDefaults(defineProps<Props>(), {\n modelValue: () => [],\n format: 96,\n wells: () => ({}),\n selectionMode: 'multiple',\n showLabels: true,\n showWellIds: false,\n showSampleTypeIndicator: false,\n heatmap: () => ({ enabled: false }),\n sampleColors: () => ({}),\n zoom: 1,\n disabled: false,\n readonly: false,\n size: 'md',\n wellShape: 'rounded',\n showWellLabels: false,\n showBadges: false,\n editable: false,\n editFields: () => ['label', 'sampleType', 'injectionVolume', 'injectionCount', 'customMethod'],\n defaultInjectionVolume: 5,\n showLegend: false,\n legendItems: undefined,\n columnConditions: () => [],\n rowConditions: () => [],\n})\n\nconst emit = defineEmits<{\n 'update:modelValue': [wellIds: string[]]\n 'well-click': [wellId: string, event: MouseEvent]\n 'well-hover': [wellId: string | null, event?: MouseEvent]\n 'selection-change': [wellIds: string[]]\n 'context-menu': [wellId: string, event: MouseEvent]\n 'well-move': [sourceWellId: string, targetWellId: string]\n 'well-edit': [wellId: string, data: WellEditData]\n 'well-clear': [wellId: string]\n}>()\n\nconst plateRef = ref<HTMLElement | null>(null)\nconst tableRef = ref<HTMLElement | null>(null)\nconst isDragging = ref(false)\nconst dragStart = ref<{ row: number; col: number } | null>(null)\nconst dragEnd = ref<{ row: number; col: number } | null>(null)\nconst hoveredWell = ref<string | null>(null)\n\n// Edit popup state\nconst editingWellId = ref<string | null>(null)\nconst editPopupPosition = ref({ x: 0, y: 0 })\n\nconst PLATE_CONFIGS: Record<WellPlateFormat, { rows: number; cols: number }> = {\n 6: { rows: 2, cols: 3 },\n 12: { rows: 3, cols: 4 },\n 24: { rows: 4, cols: 6 },\n 48: { rows: 6, cols: 8 },\n 54: { rows: 6, cols: 9 },\n 96: { rows: 8, cols: 12 },\n 384: { rows: 16, cols: 24 },\n}\n\nconst plateConfig = computed(() => PLATE_CONFIGS[props.format])\n\nconst rowLabels = computed(() =>\n Array.from({ length: plateConfig.value.rows }, (_, i) => String.fromCharCode(65 + i))\n)\n\nconst colLabels = computed(() =>\n Array.from({ length: plateConfig.value.cols }, (_, i) => i + 1)\n)\n\nconst wellGrid = computed(() => {\n const grid: Well[][] = []\n for (let row = 0; row < plateConfig.value.rows; row++) {\n const rowWells: Well[] = []\n for (let col = 0; col < plateConfig.value.cols; col++) {\n const id = `${rowLabels.value[row]}${col + 1}`\n const wellData = props.wells[id] || {}\n rowWells.push({\n id,\n row,\n col,\n state: wellData.state || 'empty',\n sampleType: wellData.sampleType,\n value: wellData.value,\n metadata: wellData.metadata,\n })\n }\n grid.push(rowWells)\n }\n return grid\n})\n\nconst selectedWellSet = computed(() => new Set(props.modelValue))\n\nconst dragSelectedWells = computed(() => {\n if (!isDragging.value || !dragStart.value || !dragEnd.value) return new Set<string>()\n\n const minRow = Math.min(dragStart.value.row, dragEnd.value.row)\n const maxRow = Math.max(dragStart.value.row, dragEnd.value.row)\n const minCol = Math.min(dragStart.value.col, dragEnd.value.col)\n const maxCol = Math.max(dragStart.value.col, dragEnd.value.col)\n\n const wells = new Set<string>()\n for (let row = minRow; row <= maxRow; row++) {\n for (let col = minCol; col <= maxCol; col++) {\n const id = `${rowLabels.value[row]}${col + 1}`\n wells.add(id)\n }\n }\n return wells\n})\n\n// Size presets with pixel values for reliable sizing\nconst sizeConfig = computed(() => {\n const sizes = {\n sm: { cellWidth: '40px', cellHeight: '40px', headerWidth: '32px', headerHeight: '32px', fontSize: '0.625rem', gap: '2px' },\n md: { cellWidth: '56px', cellHeight: '32px', headerWidth: '32px', headerHeight: '24px', fontSize: '0.75rem', gap: '3px' },\n lg: { cellWidth: '80px', cellHeight: '40px', headerWidth: '40px', headerHeight: '32px', fontSize: '0.875rem', gap: '4px' },\n xl: { cellWidth: '96px', cellHeight: '48px', headerWidth: '48px', headerHeight: '40px', fontSize: '1rem', gap: '4px' },\n fill: { cellWidth: '100%', cellHeight: '32px', headerWidth: '32px', headerHeight: '24px', fontSize: '0.75rem', gap: '2px' },\n }\n return sizes[props.size]\n})\n\nconst isFillMode = computed(() => props.size === 'fill')\n\n// Default legend items\nconst defaultLegendItems: WellLegendItem[] = [\n { type: 'sample', label: 'Sample', color: '#10b981' },\n { type: 'blank', label: 'Blank', color: '#f97316' },\n { type: 'qc', label: 'QC', color: '#8b5cf6' },\n]\n\nconst activeLegendItems = computed(() => props.legendItems ?? defaultLegendItems)\n\n// --- Condition header helpers ---\n\nconst hasColumnConditions = computed(() => props.columnConditions.length > 0)\nconst hasRowConditions = computed(() => props.rowConditions.length > 0)\n\n// Map column index (1-based) → ColumnCondition\nconst colConditionMap = computed(() => {\n const map = new Map<number, { condition: ColumnCondition; indexInGroup: number }>()\n for (const cond of props.columnConditions) {\n cond.cols.forEach((col, i) => {\n map.set(col, { condition: cond, indexInGroup: i })\n })\n }\n return map\n})\n\n// Map row letter → RowCondition\nconst rowConditionMap = computed(() => {\n const map = new Map<string, { condition: RowCondition; indexInGroup: number }>()\n for (const cond of props.rowConditions) {\n cond.rows.forEach((row, i) => {\n map.set(row, { condition: cond, indexInGroup: i })\n })\n }\n return map\n})\n\ntype ColSpan = { condition: ColumnCondition; colspan: number } | { gap: true; colspan: number }\ntype RowSpan = { condition: RowCondition; rowspan: number; startRow: number } | { gap: true; rowspan: number; startRow: number }\n\n// Build column condition header spans for the label row (drug name + unit)\nconst colConditionSpans = computed<ColSpan[]>(() => {\n const spans: ColSpan[] = []\n const cols = colLabels.value\n let i = 0\n while (i < cols.length) {\n const entry = colConditionMap.value.get(cols[i])\n if (entry?.indexInGroup === 0) {\n spans.push({ condition: entry.condition, colspan: entry.condition.cols.length })\n i += entry.condition.cols.length\n } else {\n let gapCount = 0\n while (i + gapCount < cols.length && !colConditionMap.value.has(cols[i + gapCount])) {\n gapCount++\n }\n spans.push({ gap: true, colspan: gapCount || 1 })\n i += gapCount || 1\n }\n }\n return spans\n})\n\n// Build row condition spans for the label column (drug name rotated)\nconst rowConditionSpans = computed<RowSpan[]>(() => {\n const spans: RowSpan[] = []\n const rows = rowLabels.value\n let i = 0\n while (i < rows.length) {\n const entry = rowConditionMap.value.get(rows[i])\n if (entry?.indexInGroup === 0) {\n spans.push({ condition: entry.condition, rowspan: entry.condition.rows.length, startRow: i })\n i += entry.condition.rows.length\n } else {\n let gapCount = 0\n while (i + gapCount < rows.length && !rowConditionMap.value.has(rows[i + gapCount])) {\n gapCount++\n }\n spans.push({ gap: true, rowspan: gapCount || 1, startRow: i })\n i += gapCount || 1\n }\n }\n return spans\n})\n\n// Map row index → span info (only contains entries for first row of each span)\nconst rowConditionSpanByRow = computed(() => {\n const map = new Map<number, RowSpan>()\n for (const span of rowConditionSpans.value) {\n map.set(span.startRow, span)\n }\n return map\n})\n\n// Compute gradient background for a condition cell: opacity ramps from 12% to 50% across the group\nfunction conditionGradientBg(color: string, index: number, total: number): string {\n const t = total <= 1 ? 1 : index / (total - 1)\n const opacity = 0.12 + t * 0.38\n const r = parseInt(color.slice(1, 3), 16)\n const g = parseInt(color.slice(3, 5), 16)\n const b = parseInt(color.slice(5, 7), 16)\n return `rgba(${r}, ${g}, ${b}, ${opacity})`\n}\n\n// Format concentration value (drop trailing zeros)\nfunction formatConc(value: number): string {\n if (value >= 1000) return `${value / 1000}k`\n if (value < 0.01) return value.toExponential(0)\n return String(value)\n}\n\n// Sample type colors (matching MSExpDesigner)\nconst defaultSampleTypeColors: Record<string, { bg: string; border: string }> = {\n sample: { bg: 'rgba(16, 185, 129, 0.15)', border: 'rgba(16, 185, 129, 0.4)' },\n control: { bg: 'rgba(59, 130, 246, 0.15)', border: 'rgba(59, 130, 246, 0.4)' },\n blank: { bg: 'rgba(249, 115, 22, 0.15)', border: 'rgba(249, 115, 22, 0.4)' },\n qc: { bg: 'rgba(139, 92, 246, 0.15)', border: 'rgba(139, 92, 246, 0.4)' },\n}\n\nconst heatmapColors: Record<string, string[]> = {\n viridis: ['#440154', '#482878', '#3e4989', '#31688e', '#26828e', '#1f9e89', '#35b779', '#6ece58', '#b5de2b', '#fde725'],\n plasma: ['#0d0887', '#46039f', '#7201a8', '#9c179e', '#bd3786', '#d8576b', '#ed7953', '#fb9f3a', '#fdca26', '#f0f921'],\n turbo: ['#30123b', '#4145ab', '#4675ed', '#39a2fc', '#1bcfd4', '#24e79e', '#71f05f', '#c1f034', '#f1c83c', '#f99538', '#e45a31', '#ba2512', '#7a0403'],\n}\n\nfunction getHeatmapColor(value: number | undefined): string | null {\n if (!props.heatmap?.enabled || value === undefined) return null\n\n const min = props.heatmap.min ?? 0\n const max = props.heatmap.max ?? 1\n const normalized = Math.max(0, Math.min(1, (value - min) / (max - min)))\n\n const colors = props.heatmap.colorScale === 'custom' && props.heatmap.customColors?.length\n ? props.heatmap.customColors\n : heatmapColors[props.heatmap.colorScale || 'viridis']\n\n const index = Math.min(Math.floor(normalized * (colors.length - 1)), colors.length - 1)\n return colors[index]\n}\n\nfunction getWellClasses(well: Well): string[] {\n const isWellSelected = isSelected(well.id)\n const isDragOver = dragSelectedWells.value.has(well.id)\n const isHovered = hoveredWell.value === well.id\n const isDisabled = props.disabled || well.state === 'disabled'\n const isDragSource = dragSourceWell.value === well.id\n const isDragTarget = dragTargetWell.value === well.id\n\n const classes = [\n 'mld-well-plate__well',\n props.wellShape === 'circle' ? 'mld-well-plate__well--circle' : 'mld-well-plate__well--rounded',\n ]\n\n if (props.selectionMode === 'drag' && well.sampleType) {\n classes.push('mld-well-plate__well--draggable')\n }\n\n if (isDragSource) classes.push('mld-well-plate__well--drag-source')\n else if (isDragTarget) classes.push('mld-well-plate__well--drag-target')\n else if (isWellSelected) classes.push('mld-well-plate__well--selected')\n else if (isDragOver) classes.push('mld-well-plate__well--drag-over')\n else if (isHovered && !props.readonly) classes.push('mld-well-plate__well--hovered')\n\n if (isDisabled) classes.push('mld-well-plate__well--disabled')\n if (well.state === 'filled') classes.push('mld-well-plate__well--filled')\n\n return classes\n}\n\nfunction getWellStyle(well: Well): Record<string, string> {\n const heatmapColor = getHeatmapColor(well.value)\n if (heatmapColor) {\n return { backgroundColor: heatmapColor, border: '1px solid transparent' }\n }\n\n if (well.sampleType && props.sampleColors[well.sampleType]) {\n const color = props.sampleColors[well.sampleType]\n return {\n backgroundColor: `${color}26`,\n border: `1px solid ${color}66`,\n }\n }\n\n if (well.sampleType && defaultSampleTypeColors[well.sampleType]) {\n const colors = defaultSampleTypeColors[well.sampleType]\n return {\n backgroundColor: colors.bg,\n border: `1px solid ${colors.border}`,\n }\n }\n\n const borderStyle = well.state === 'filled' ? 'solid' : 'dashed'\n return {\n backgroundColor: 'var(--bg-tertiary)',\n border: `1px ${borderStyle} var(--border-color)`,\n }\n}\n\nfunction getSampleTypeIndicator(well: Well): string | null {\n if (!props.showSampleTypeIndicator || !well.sampleType) return null\n const typeMap: Record<string, string> = {\n sample: 'S',\n control: 'C',\n blank: 'B',\n qc: 'Q',\n }\n return typeMap[well.sampleType] || well.sampleType.charAt(0).toUpperCase()\n}\n\nfunction getWellLabel(well: Well): string | undefined {\n if (!props.showWellLabels) return undefined\n return well.metadata?.label as string | undefined\n}\n\nfunction getWellBadge(well: Well): { text: string; color: string } | null {\n if (!props.showBadges || !well.metadata) return null\n const count = well.metadata.injectionCount as number | undefined\n if (count && count > 1) {\n return { text: String(count), color: '#6366f1' }\n }\n if (well.metadata.customMethod) {\n return { text: '+', color: '#ec4899' }\n }\n return null\n}\n\nfunction isSelected(wellId: string): boolean {\n return selectedWellSet.value.has(wellId) || dragSelectedWells.value.has(wellId)\n}\n\nfunction handleWellClick(well: Well, event: MouseEvent) {\n if (props.disabled || props.readonly) return\n\n emit('well-click', well.id, event)\n\n // When editable, open popup instead of modifying selection\n if (props.editable) {\n openEditPopup(well.id, event)\n return\n }\n\n if (props.selectionMode === 'none') return\n\n const isCurrentlySelected = selectedWellSet.value.has(well.id)\n const isMultiSelect = event.shiftKey || event.metaKey || event.ctrlKey\n\n let newSelection: string[]\n if (props.selectionMode === 'single') {\n newSelection = isCurrentlySelected ? [] : [well.id]\n } else if (isMultiSelect) {\n newSelection = isCurrentlySelected\n ? props.modelValue.filter(id => id !== well.id)\n : [...props.modelValue, well.id]\n } else {\n newSelection = isCurrentlySelected && props.modelValue.length === 1 ? [] : [well.id]\n }\n\n emit('update:modelValue', newSelection)\n emit('selection-change', newSelection)\n}\n\nfunction openEditPopup(wellId: string, event: MouseEvent) {\n const target = event.currentTarget as HTMLElement\n const rect = target.getBoundingClientRect()\n editPopupPosition.value = {\n x: rect.right + 8,\n y: rect.top,\n }\n editingWellId.value = wellId\n}\n\nfunction handleEditSave(data: WellEditData) {\n emit('well-edit', data.wellId, data)\n editingWellId.value = null\n}\n\nfunction handleEditClear() {\n if (editingWellId.value) {\n emit('well-clear', editingWellId.value)\n }\n editingWellId.value = null\n}\n\nfunction handleEditClose() {\n editingWellId.value = null\n}\n\nfunction handleWellMouseDown(well: Well, event: MouseEvent) {\n if (props.disabled || props.readonly || props.selectionMode !== 'rectangle') return\n if (props.editable) return\n if (event.button !== 0) return\n\n isDragging.value = true\n dragStart.value = { row: well.row, col: well.col }\n dragEnd.value = { row: well.row, col: well.col }\n}\n\nfunction handleWellMouseEnter(well: Well, event: MouseEvent) {\n hoveredWell.value = well.id\n emit('well-hover', well.id, event)\n\n if (isDragging.value && props.selectionMode === 'rectangle') {\n dragEnd.value = { row: well.row, col: well.col }\n }\n}\n\nfunction handleWellMouseLeave() {\n hoveredWell.value = null\n emit('well-hover', null)\n}\n\nfunction handleMouseUp() {\n if (!isDragging.value || props.selectionMode !== 'rectangle') return\n\n const newSelection = Array.from(dragSelectedWells.value)\n isDragging.value = false\n dragStart.value = null\n dragEnd.value = null\n\n if (newSelection.length > 0) {\n emit('update:modelValue', newSelection)\n emit('selection-change', newSelection)\n }\n}\n\nfunction handleContextMenu(well: Well, event: MouseEvent) {\n event.preventDefault()\n emit('context-menu', well.id, event)\n}\n\n// Drag handlers for moving well contents\nfunction handleDragStart(well: Well, event: DragEvent) {\n if (props.disabled || props.readonly || props.selectionMode !== 'drag') return\n if (!well.sampleType) return\n\n dragSourceWell.value = well.id\n if (event.dataTransfer) {\n event.dataTransfer.effectAllowed = 'move'\n event.dataTransfer.setData('text/plain', well.id)\n }\n}\n\nfunction handleDragOver(well: Well, event: DragEvent) {\n if (props.selectionMode !== 'drag' || !dragSourceWell.value) return\n event.preventDefault()\n if (event.dataTransfer) {\n event.dataTransfer.dropEffect = 'move'\n }\n dragTargetWell.value = well.id\n}\n\nfunction handleDragLeave() {\n dragTargetWell.value = null\n}\n\nfunction handleDrop(well: Well, event: DragEvent) {\n event.preventDefault()\n if (props.selectionMode !== 'drag' || !dragSourceWell.value) return\n\n const sourceId = dragSourceWell.value\n const targetId = well.id\n\n if (sourceId !== targetId) {\n emit('well-move', sourceId, targetId)\n }\n\n dragSourceWell.value = null\n dragTargetWell.value = null\n}\n\nfunction handleDragEnd() {\n dragSourceWell.value = null\n dragTargetWell.value = null\n}\n\nfunction handleKeyDown(event: KeyboardEvent) {\n if (props.disabled || props.readonly) return\n\n if (event.key === 'Escape') {\n if (editingWellId.value) {\n editingWellId.value = null\n return\n }\n emit('update:modelValue', [])\n emit('selection-change', [])\n }\n\n if ((event.key === 'a' || event.key === 'A') && (event.metaKey || event.ctrlKey)) {\n event.preventDefault()\n const allWells = wellGrid.value.flat().map(w => w.id)\n emit('update:modelValue', allWells)\n emit('selection-change', allWells)\n }\n}\n\nonMounted(() => {\n document.addEventListener('mouseup', handleMouseUp)\n document.addEventListener('keydown', handleKeyDown)\n})\n\nonUnmounted(() => {\n document.removeEventListener('mouseup', handleMouseUp)\n document.removeEventListener('keydown', handleKeyDown)\n})\n\nconst containerStyle = computed(() =>\n isFillMode.value ? {} : {\n transform: `scale(${props.zoom})`,\n transformOrigin: 'top left',\n }\n)\n\nconst tableStyle = computed(() => ({\n borderCollapse: 'separate' as const,\n borderSpacing: sizeConfig.value.gap,\n ...(isFillMode.value ? { width: '100%', tableLayout: 'fixed' as const } : {}),\n}))\n</script>\n\n<template>\n <div\n ref=\"plateRef\"\n :class=\"['mld-well-plate', isFillMode ? 'mld-well-plate--fill' : 'mld-well-plate--inline']\"\n :style=\"containerStyle\"\n >\n <div class=\"mld-well-plate__scroll\">\n <div class=\"mld-well-plate__content\">\n <table\n ref=\"tableRef\"\n class=\"mld-well-plate__table\"\n role=\"grid\"\n :aria-label=\"`${props.format}-well plate`\"\n :style=\"tableStyle\"\n >\n <!-- Column condition label row (drug name + unit) -->\n <thead v-if=\"hasColumnConditions\">\n <tr>\n <!-- Spacer for row header column -->\n <th :style=\"{ width: sizeConfig.headerWidth }\"></th>\n <!-- Spacer for row condition column -->\n <th v-if=\"hasRowConditions\" :style=\"{ width: sizeConfig.headerWidth }\"></th>\n <template v-for=\"(span, idx) in colConditionSpans\" :key=\"'clabel-' + idx\">\n <th\n v-if=\"'condition' in span\"\n :colspan=\"span.colspan\"\n class=\"mld-well-plate__condition-label\"\n :style=\"{\n height: sizeConfig.headerHeight,\n fontSize: sizeConfig.fontSize,\n color: span.condition.color,\n }\"\n >\n {{ span.condition.label }}<template v-if=\"span.condition.unit\"> ({{ span.condition.unit }})</template>\n </th>\n <th v-else :colspan=\"span.colspan\"></th>\n </template>\n </tr>\n </thead>\n <!-- Column headers (with concentration overlay when conditions present) -->\n <thead v-if=\"props.showLabels\">\n <tr>\n <th :style=\"{ width: sizeConfig.headerWidth, height: sizeConfig.headerHeight }\"></th>\n <!-- Spacer for row condition column in column header row -->\n <th v-if=\"hasRowConditions\" :style=\"{ width: sizeConfig.headerWidth, height: sizeConfig.headerHeight }\"></th>\n <th\n v-for=\"col in colLabels\"\n :key=\"col\"\n class=\"mld-well-plate__col-header\"\n :style=\"{ height: sizeConfig.headerHeight, fontSize: sizeConfig.fontSize }\"\n >\n <template v-for=\"entry in [colConditionMap.get(col)]\" :key=\"col\">\n <span\n v-if=\"entry\"\n class=\"mld-well-plate__condition-cell\"\n :style=\"{\n backgroundColor: conditionGradientBg(\n entry.condition.color,\n entry.indexInGroup,\n entry.condition.cols.length,\n ),\n }\"\n >\n {{ formatConc(entry.condition.concentrations[entry.indexInGroup]) }}\n </span>\n <template v-else>{{ col }}</template>\n </template>\n </th>\n </tr>\n </thead>\n <tbody>\n <tr v-for=\"(row, rowIndex) in wellGrid\" :key=\"rowIndex\" role=\"row\">\n <!-- Row condition label cell (drug name, spans multiple rows) -->\n <template v-if=\"hasRowConditions && rowConditionSpanByRow.has(rowIndex)\">\n <td\n v-for=\"span in [rowConditionSpanByRow.get(rowIndex)!]\"\n :key=\"rowIndex\"\n :rowspan=\"span.rowspan\"\n :class=\"[\n 'mld-well-plate__row-condition-label',\n 'gap' in span ? 'mld-well-plate__row-condition-label--empty' : '',\n ]\"\n :style=\"{\n width: sizeConfig.headerWidth,\n minWidth: sizeConfig.headerWidth,\n fontSize: sizeConfig.fontSize,\n ...('condition' in span ? { color: span.condition.color } : {}),\n }\"\n >\n <div v-if=\"'condition' in span\" class=\"mld-well-plate__row-condition-wrap\">\n <span class=\"mld-well-plate__row-condition-text\">{{ span.condition.label }}</span>\n </div>\n </td>\n </template>\n <!-- Row header (with concentration overlay when conditions present) -->\n <td\n v-if=\"props.showLabels\"\n class=\"mld-well-plate__row-header\"\n :style=\"{\n width: sizeConfig.headerWidth,\n height: sizeConfig.cellHeight,\n minWidth: sizeConfig.headerWidth,\n minHeight: sizeConfig.cellHeight,\n fontSize: sizeConfig.fontSize,\n }\"\n >\n <template v-for=\"entry in [rowConditionMap.get(rowLabels[rowIndex])]\" :key=\"rowIndex\">\n <span\n v-if=\"entry\"\n class=\"mld-well-plate__condition-cell\"\n :style=\"{\n backgroundColor: conditionGradientBg(\n entry.condition.color,\n entry.indexInGroup,\n entry.condition.rows.length,\n ),\n }\"\n >\n {{ formatConc(entry.condition.concentrations[entry.indexInGroup]) }}\n </span>\n <template v-else>{{ rowLabels[rowIndex] }}</template>\n </template>\n </td>\n\n <!-- Wells -->\n <td v-for=\"well in row\" :key=\"well.id\" class=\"mld-well-plate__cell\">\n <div\n role=\"gridcell\"\n tabindex=\"0\"\n :aria-label=\"`Well ${well.id}${well.sampleType ? `, Sample type: ${well.sampleType}` : ''}${well.value !== undefined ? `, Value: ${well.value}` : ''}`\"\n :aria-selected=\"isSelected(well.id)\"\n :aria-disabled=\"props.disabled || well.state === 'disabled'\"\n :draggable=\"props.selectionMode === 'drag' && !!well.sampleType\"\n :class=\"getWellClasses(well)\"\n :style=\"{\n width: isFillMode ? '100%' : sizeConfig.cellWidth,\n height: sizeConfig.cellHeight,\n minWidth: isFillMode ? '0' : sizeConfig.cellWidth,\n minHeight: sizeConfig.cellHeight,\n boxSizing: 'border-box',\n fontSize: sizeConfig.fontSize,\n ...getWellStyle(well),\n }\"\n :title=\"`${well.id}${well.sampleType ? `: ${well.sampleType}` : ''}${getWellLabel(well) ? ` - ${getWellLabel(well)}` : ''}`\"\n @click=\"handleWellClick(well, $event)\"\n @mousedown=\"handleWellMouseDown(well, $event)\"\n @mouseenter=\"handleWellMouseEnter(well, $event)\"\n @mouseleave=\"handleWellMouseLeave\"\n @contextmenu=\"handleContextMenu(well, $event)\"\n @dragstart=\"handleDragStart(well, $event)\"\n @dragover.prevent=\"handleDragOver(well, $event)\"\n @dragleave=\"handleDragLeave\"\n @drop.prevent=\"handleDrop(well, $event)\"\n @dragend=\"handleDragEnd\"\n @keydown.enter=\"handleWellClick(well, $event as unknown as MouseEvent)\"\n @keydown.space.prevent=\"handleWellClick(well, $event as unknown as MouseEvent)\"\n >\n <!-- Well label text (from metadata.label) -->\n <span\n v-if=\"getWellLabel(well)\"\n class=\"mld-well-plate__label\"\n >\n {{ getWellLabel(well) }}\n </span>\n <!-- Sample type indicator (S/B/Q/C) -->\n <span\n v-else-if=\"getSampleTypeIndicator(well)\"\n class=\"mld-well-plate__indicator\"\n >\n {{ getSampleTypeIndicator(well) }}\n </span>\n <!-- Well ID -->\n <span\n v-else-if=\"props.showWellIds\"\n class=\"mld-well-plate__well-id\"\n >\n {{ well.id }}\n </span>\n\n <!-- Badge (injection count or custom method) -->\n <span\n v-if=\"getWellBadge(well)\"\n class=\"mld-well-plate__badge\"\n :style=\"{ backgroundColor: getWellBadge(well)!.color }\"\n :title=\"getWellBadge(well)!.text === '+' ? 'Custom method' : `${getWellBadge(well)!.text}x injections`\"\n >\n {{ getWellBadge(well)!.text }}\n </span>\n </div>\n </td>\n </tr>\n </tbody>\n </table>\n\n <!-- Heatmap legend (inside content wrapper to match table width) -->\n <div\n v-if=\"props.heatmap?.enabled && props.heatmap.showLegend\"\n class=\"mld-well-plate__legend\"\n >\n <span class=\"mld-well-plate__legend-label\">{{ props.heatmap.min ?? 0 }}</span>\n <div class=\"mld-well-plate__legend-bar\">\n <div\n v-for=\"(color, index) in (props.heatmap.colorScale === 'custom' && props.heatmap.customColors?.length ? props.heatmap.customColors : heatmapColors[props.heatmap.colorScale || 'viridis'])\"\n :key=\"index\"\n class=\"mld-well-plate__legend-segment\"\n :style=\"{ backgroundColor: color }\"\n />\n </div>\n <span class=\"mld-well-plate__legend-label\">{{ props.heatmap.max ?? 1 }}</span>\n </div>\n\n <!-- Sample type legend bar -->\n <div v-if=\"props.showLegend\" class=\"mld-well-plate__sample-legend\">\n <div\n v-for=\"item in activeLegendItems\"\n :key=\"item.type\"\n class=\"mld-well-plate__sample-legend-item\"\n >\n <span\n class=\"mld-well-plate__sample-legend-dot\"\n :style=\"{ backgroundColor: `${item.color}26`, border: `1px solid ${item.color}66` }\"\n />\n <span class=\"mld-well-plate__sample-legend-text\">{{ item.label }}</span>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Edit popup -->\n <WellEditPopup\n v-if=\"editable && editingWellId\"\n :well-id=\"editingWellId\"\n :well-data=\"wells[editingWellId]\"\n :edit-fields=\"editFields\"\n :default-injection-volume=\"defaultInjectionVolume\"\n :position=\"editPopupPosition\"\n @save=\"handleEditSave\"\n @clear=\"handleEditClear\"\n @close=\"handleEditClose\"\n />\n </div>\n</template>\n\n<style>\n@import '../styles/components/well-plate.css';\n</style>\n"],"names":["_createElementBlock","_createElementVNode","_normalizeStyle","_openBlock","_Fragment","_renderList","_createTextVNode","_normalizeClass","_toDisplayString","_withModifiers","_createBlock","WellEditPopup"],"mappings":"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"}