@tetrascience-npm/tetrascience-react-ui 0.5.0 → 0.6.0-beta.78.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 (192) hide show
  1. package/README.md +84 -37
  2. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +2 -0
  3. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -0
  4. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +140 -0
  5. package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -0
  6. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs +2 -0
  7. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs.map +1 -0
  8. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js +126 -0
  9. package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js.map +1 -0
  10. package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs +2 -0
  11. package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs.map +1 -0
  12. package/dist/components/composed/PlateMapEditor/PlateMapEditor.js +341 -0
  13. package/dist/components/composed/PlateMapEditor/PlateMapEditor.js.map +1 -0
  14. package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs +2 -0
  15. package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs.map +1 -0
  16. package/dist/components/composed/PlateMapEditor/PlateMapForm.js +43 -0
  17. package/dist/components/composed/PlateMapEditor/PlateMapForm.js.map +1 -0
  18. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +2 -0
  19. package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -0
  20. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +154 -0
  21. package/dist/components/composed/PlateMapEditor/PlateMapGrid.js.map +1 -0
  22. package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs +2 -0
  23. package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs.map +1 -0
  24. package/dist/components/composed/PlateMapEditor/PlateMapManifest.js +44 -0
  25. package/dist/components/composed/PlateMapEditor/PlateMapManifest.js.map +1 -0
  26. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs +2 -0
  27. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs.map +1 -0
  28. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js +136 -0
  29. package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js.map +1 -0
  30. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +2 -0
  31. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -0
  32. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +389 -0
  33. package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -0
  34. package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs +2 -0
  35. package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs.map +1 -0
  36. package/dist/components/composed/PlateMapEditor/PlateZoomControl.js +54 -0
  37. package/dist/components/composed/PlateMapEditor/PlateZoomControl.js.map +1 -0
  38. package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs +2 -0
  39. package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs.map +1 -0
  40. package/dist/components/composed/PlateMapEditor/TemplateIOPanel.js +96 -0
  41. package/dist/components/composed/PlateMapEditor/TemplateIOPanel.js.map +1 -0
  42. package/dist/components/composed/PlateMapEditor/WellLegend.cjs +2 -0
  43. package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -0
  44. package/dist/components/composed/PlateMapEditor/WellLegend.js +58 -0
  45. package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -0
  46. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +2 -0
  47. package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -0
  48. package/dist/components/composed/PlateMapEditor/WellManifestTable.js +421 -0
  49. package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -0
  50. package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs +2 -0
  51. package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs.map +1 -0
  52. package/dist/components/composed/PlateMapEditor/WellMetadataForm.js +177 -0
  53. package/dist/components/composed/PlateMapEditor/WellMetadataForm.js.map +1 -0
  54. package/dist/components/composed/PlateMapEditor/autoFill.cjs +2 -0
  55. package/dist/components/composed/PlateMapEditor/autoFill.cjs.map +1 -0
  56. package/dist/components/composed/PlateMapEditor/autoFill.js +41 -0
  57. package/dist/components/composed/PlateMapEditor/autoFill.js.map +1 -0
  58. package/dist/components/composed/PlateMapEditor/csvPlateTriage.cjs +4 -0
  59. package/dist/components/composed/PlateMapEditor/csvPlateTriage.cjs.map +1 -0
  60. package/dist/components/composed/PlateMapEditor/csvPlateTriage.js +103 -0
  61. package/dist/components/composed/PlateMapEditor/csvPlateTriage.js.map +1 -0
  62. package/dist/components/composed/PlateMapEditor/helpers.cjs +2 -0
  63. package/dist/components/composed/PlateMapEditor/helpers.cjs.map +1 -0
  64. package/dist/components/composed/PlateMapEditor/helpers.js +11 -0
  65. package/dist/components/composed/PlateMapEditor/helpers.js.map +1 -0
  66. package/dist/components/composed/PlateMapEditor/wellGrid.cjs +2 -0
  67. package/dist/components/composed/PlateMapEditor/wellGrid.cjs.map +1 -0
  68. package/dist/components/composed/PlateMapEditor/wellGrid.js +56 -0
  69. package/dist/components/composed/PlateMapEditor/wellGrid.js.map +1 -0
  70. package/dist/components/composed/ProcessFlow/ProcessFlow.cjs +2 -0
  71. package/dist/components/composed/ProcessFlow/ProcessFlow.cjs.map +1 -0
  72. package/dist/components/composed/ProcessFlow/ProcessFlow.js +543 -0
  73. package/dist/components/composed/ProcessFlow/ProcessFlow.js.map +1 -0
  74. package/dist/components/composed/ProcessFlow/ProcessFlow.utils.cjs +2 -0
  75. package/dist/components/composed/ProcessFlow/ProcessFlow.utils.cjs.map +1 -0
  76. package/dist/components/composed/ProcessFlow/ProcessFlow.utils.js +84 -0
  77. package/dist/components/composed/ProcessFlow/ProcessFlow.utils.js.map +1 -0
  78. package/dist/components/ui/accordion.cjs +1 -1
  79. package/dist/components/ui/accordion.cjs.map +1 -1
  80. package/dist/components/ui/accordion.js +1 -1
  81. package/dist/components/ui/accordion.js.map +1 -1
  82. package/dist/components/ui/badge.cjs +1 -1
  83. package/dist/components/ui/badge.cjs.map +1 -1
  84. package/dist/components/ui/badge.js +18 -18
  85. package/dist/components/ui/badge.js.map +1 -1
  86. package/dist/components/ui/button.cjs +1 -1
  87. package/dist/components/ui/button.cjs.map +1 -1
  88. package/dist/components/ui/button.js +16 -16
  89. package/dist/components/ui/button.js.map +1 -1
  90. package/dist/components/ui/calendar.cjs +1 -1
  91. package/dist/components/ui/calendar.cjs.map +1 -1
  92. package/dist/components/ui/calendar.js +5 -5
  93. package/dist/components/ui/calendar.js.map +1 -1
  94. package/dist/components/ui/card.cjs +1 -1
  95. package/dist/components/ui/card.cjs.map +1 -1
  96. package/dist/components/ui/card.js +1 -1
  97. package/dist/components/ui/card.js.map +1 -1
  98. package/dist/components/ui/checkbox.cjs +1 -1
  99. package/dist/components/ui/checkbox.cjs.map +1 -1
  100. package/dist/components/ui/checkbox.js +9 -9
  101. package/dist/components/ui/checkbox.js.map +1 -1
  102. package/dist/components/ui/combobox.cjs +1 -1
  103. package/dist/components/ui/combobox.cjs.map +1 -1
  104. package/dist/components/ui/combobox.js +5 -5
  105. package/dist/components/ui/combobox.js.map +1 -1
  106. package/dist/components/ui/data-table/data-table-group.cjs +2 -0
  107. package/dist/components/ui/data-table/data-table-group.cjs.map +1 -0
  108. package/dist/components/ui/data-table/data-table-group.js +118 -0
  109. package/dist/components/ui/data-table/data-table-group.js.map +1 -0
  110. package/dist/components/ui/data-table/data-table-pagination.cjs +1 -1
  111. package/dist/components/ui/data-table/data-table-pagination.cjs.map +1 -1
  112. package/dist/components/ui/data-table/data-table-pagination.js +22 -22
  113. package/dist/components/ui/data-table/data-table-pagination.js.map +1 -1
  114. package/dist/components/ui/data-table/data-table.cjs +1 -1
  115. package/dist/components/ui/data-table/data-table.cjs.map +1 -1
  116. package/dist/components/ui/data-table/data-table.js +567 -316
  117. package/dist/components/ui/data-table/data-table.js.map +1 -1
  118. package/dist/components/ui/dialog.cjs +1 -1
  119. package/dist/components/ui/dialog.cjs.map +1 -1
  120. package/dist/components/ui/dialog.js +13 -13
  121. package/dist/components/ui/dialog.js.map +1 -1
  122. package/dist/components/ui/input-group.cjs +1 -1
  123. package/dist/components/ui/input-group.cjs.map +1 -1
  124. package/dist/components/ui/input-group.js +29 -29
  125. package/dist/components/ui/input-group.js.map +1 -1
  126. package/dist/components/ui/input-otp.cjs +1 -1
  127. package/dist/components/ui/input-otp.cjs.map +1 -1
  128. package/dist/components/ui/input-otp.js +10 -10
  129. package/dist/components/ui/input-otp.js.map +1 -1
  130. package/dist/components/ui/input.cjs +1 -1
  131. package/dist/components/ui/input.cjs.map +1 -1
  132. package/dist/components/ui/input.js +7 -7
  133. package/dist/components/ui/input.js.map +1 -1
  134. package/dist/components/ui/item.cjs +1 -1
  135. package/dist/components/ui/item.cjs.map +1 -1
  136. package/dist/components/ui/item.js +17 -17
  137. package/dist/components/ui/item.js.map +1 -1
  138. package/dist/components/ui/navigation-menu.cjs +1 -1
  139. package/dist/components/ui/navigation-menu.cjs.map +1 -1
  140. package/dist/components/ui/navigation-menu.js +24 -24
  141. package/dist/components/ui/navigation-menu.js.map +1 -1
  142. package/dist/components/ui/popover.cjs +2 -0
  143. package/dist/components/ui/popover.cjs.map +1 -0
  144. package/dist/components/ui/popover.js +45 -0
  145. package/dist/components/ui/popover.js.map +1 -0
  146. package/dist/components/ui/radio-group.cjs +1 -1
  147. package/dist/components/ui/radio-group.cjs.map +1 -1
  148. package/dist/components/ui/radio-group.js +16 -16
  149. package/dist/components/ui/radio-group.js.map +1 -1
  150. package/dist/components/ui/scroll-area.cjs +1 -1
  151. package/dist/components/ui/scroll-area.cjs.map +1 -1
  152. package/dist/components/ui/scroll-area.js +6 -6
  153. package/dist/components/ui/scroll-area.js.map +1 -1
  154. package/dist/components/ui/select.cjs +1 -1
  155. package/dist/components/ui/select.cjs.map +1 -1
  156. package/dist/components/ui/select.js +48 -48
  157. package/dist/components/ui/select.js.map +1 -1
  158. package/dist/components/ui/slider.cjs +1 -1
  159. package/dist/components/ui/slider.cjs.map +1 -1
  160. package/dist/components/ui/slider.js +22 -22
  161. package/dist/components/ui/slider.js.map +1 -1
  162. package/dist/components/ui/switch.cjs +1 -1
  163. package/dist/components/ui/switch.cjs.map +1 -1
  164. package/dist/components/ui/switch.js +14 -14
  165. package/dist/components/ui/switch.js.map +1 -1
  166. package/dist/components/ui/table.cjs +1 -1
  167. package/dist/components/ui/table.cjs.map +1 -1
  168. package/dist/components/ui/table.js +2 -2
  169. package/dist/components/ui/table.js.map +1 -1
  170. package/dist/components/ui/tabs.cjs +1 -1
  171. package/dist/components/ui/tabs.cjs.map +1 -1
  172. package/dist/components/ui/tabs.js +9 -9
  173. package/dist/components/ui/tabs.js.map +1 -1
  174. package/dist/components/ui/textarea.cjs +1 -1
  175. package/dist/components/ui/textarea.cjs.map +1 -1
  176. package/dist/components/ui/textarea.js +6 -6
  177. package/dist/components/ui/textarea.js.map +1 -1
  178. package/dist/components/ui/toggle.cjs +1 -1
  179. package/dist/components/ui/toggle.cjs.map +1 -1
  180. package/dist/components/ui/toggle.js +13 -13
  181. package/dist/components/ui/toggle.js.map +1 -1
  182. package/dist/index.cjs +1 -1
  183. package/dist/index.css +1 -1
  184. package/dist/index.d.ts +830 -3
  185. package/dist/index.js +649 -593
  186. package/dist/index.js.map +1 -1
  187. package/dist/index.tailwind.css +1 -1
  188. package/dist/utils/colors.cjs +1 -1
  189. package/dist/utils/colors.cjs.map +1 -1
  190. package/dist/utils/colors.js +43 -21
  191. package/dist/utils/colors.js.map +1 -1
  192. package/package.json +1 -1
@@ -0,0 +1,96 @@
1
+ import { jsxs as l, jsx as e, Fragment as h } from "react/jsx-runtime";
2
+ import { Download as x, Upload as z } from "lucide-react";
3
+ import * as S from "react";
4
+ import { triagePlateMapCsvFile as P } from "./csvPlateTriage.js";
5
+ import { groupTemplateOptions as w } from "./helpers.js";
6
+ import { Button as p } from "../../ui/button.js";
7
+ import { Label as F } from "../../ui/label.js";
8
+ import { Select as O, SelectTrigger as V, SelectValue as j, SelectContent as y, SelectGroup as R, SelectLabel as B, SelectItem as J } from "../../ui/select.js";
9
+ import { Separator as v } from "../../ui/separator.js";
10
+ import { cn as L } from "../../../lib/utils.js";
11
+ function g({ label: n, accept: m, onPick: c, disabled: u, triageCsv: d }) {
12
+ const i = S.useRef(null);
13
+ return /* @__PURE__ */ l(h, { children: [
14
+ /* @__PURE__ */ l(p, { type: "button", variant: "outline", size: "sm", disabled: u, onClick: () => i.current?.click(), children: [
15
+ /* @__PURE__ */ e(z, { "aria-hidden": !0 }),
16
+ " ",
17
+ n
18
+ ] }),
19
+ /* @__PURE__ */ e(
20
+ "input",
21
+ {
22
+ ref: i,
23
+ type: "file",
24
+ accept: m,
25
+ hidden: !0,
26
+ onChange: (a) => {
27
+ const r = a.currentTarget, t = a.target.files?.[0];
28
+ if (!t) {
29
+ r.value = "";
30
+ return;
31
+ }
32
+ (async () => {
33
+ const s = d ? await P(t) : void 0;
34
+ await (s ? c(t, s) : c(t)), r.value = "";
35
+ })();
36
+ }
37
+ }
38
+ )
39
+ ] });
40
+ }
41
+ function K({
42
+ templates: n,
43
+ templateId: m,
44
+ onTemplateChange: c,
45
+ onClearTemplate: u,
46
+ hasEntries: d,
47
+ onImportCsv: i,
48
+ onExportCsv: a,
49
+ onImportTemplate: r,
50
+ onExportTemplate: t,
51
+ className: s,
52
+ csvAccept: N = ".csv,text/csv",
53
+ templateAccept: b = "application/json"
54
+ }) {
55
+ const k = S.useMemo(() => w(n), [n]);
56
+ return /* @__PURE__ */ l("div", { "data-slot": "template-io-panel", className: L("flex flex-col gap-3", s), children: [
57
+ /* @__PURE__ */ e("div", { className: "text-sm font-medium", children: "Template & import / export" }),
58
+ n && c ? /* @__PURE__ */ l("div", { className: "flex flex-col gap-1.5", children: [
59
+ /* @__PURE__ */ e(F, { htmlFor: "plate-template", children: "Template" }),
60
+ /* @__PURE__ */ l(O, { value: m ?? "", onValueChange: (o) => c(o), children: [
61
+ /* @__PURE__ */ e(V, { id: "plate-template", size: "sm", className: "w-full", children: /* @__PURE__ */ e(j, { placeholder: "Select template…" }) }),
62
+ /* @__PURE__ */ e(y, { children: k.map(([o, C]) => /* @__PURE__ */ l(R, { children: [
63
+ o ? /* @__PURE__ */ e(B, { children: o }) : null,
64
+ C.map((f) => /* @__PURE__ */ e(J, { value: f.id, children: f.label }, f.id))
65
+ ] }, o || "_")) })
66
+ ] }),
67
+ u ? /* @__PURE__ */ e(p, { variant: "outline", size: "sm", onClick: u, disabled: !m && !d, children: "Clear template" }) : null
68
+ ] }) : null,
69
+ r || t ? /* @__PURE__ */ l(h, { children: [
70
+ /* @__PURE__ */ e(v, {}),
71
+ /* @__PURE__ */ e("div", { className: "text-xs font-medium text-muted-foreground", children: "Template" }),
72
+ /* @__PURE__ */ l("div", { className: "flex flex-col gap-2", children: [
73
+ r ? /* @__PURE__ */ e(g, { label: "Import template (JSON)", accept: b, onPick: r }) : null,
74
+ t ? /* @__PURE__ */ l(p, { variant: "outline", size: "sm", disabled: !d, onClick: t, children: [
75
+ /* @__PURE__ */ e(x, { "aria-hidden": !0 }),
76
+ " Export template (JSON)"
77
+ ] }) : null
78
+ ] })
79
+ ] }) : null,
80
+ i || a ? /* @__PURE__ */ l(h, { children: [
81
+ /* @__PURE__ */ e(v, {}),
82
+ /* @__PURE__ */ e("div", { className: "text-xs font-medium text-muted-foreground", children: "Plate map" }),
83
+ /* @__PURE__ */ l("div", { className: "flex flex-col gap-2", children: [
84
+ i ? /* @__PURE__ */ e(g, { label: "Import plate map (CSV)", accept: N, onPick: i, triageCsv: !0 }) : null,
85
+ a ? /* @__PURE__ */ l(p, { variant: "outline", size: "sm", disabled: !d, onClick: a, children: [
86
+ /* @__PURE__ */ e(x, { "aria-hidden": !0 }),
87
+ " Export plate map (CSV)"
88
+ ] }) : null
89
+ ] })
90
+ ] }) : null
91
+ ] });
92
+ }
93
+ export {
94
+ K as TemplateIOPanel
95
+ };
96
+ //# sourceMappingURL=TemplateIOPanel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TemplateIOPanel.js","sources":["../../../../src/components/composed/PlateMapEditor/TemplateIOPanel.tsx"],"sourcesContent":["import { Download, Upload } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { triagePlateMapCsvFile } from \"./csvPlateTriage\";\nimport { groupTemplateOptions } from \"./helpers\";\n\nimport type { ImportExportHandlers, PlateMapCsvTriage, TemplateOption } from \"./types\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Label } from \"@/components/ui/label\";\nimport {\n Select,\n SelectContent,\n SelectGroup,\n SelectItem,\n SelectLabel,\n SelectTrigger,\n SelectValue,\n} from \"@/components/ui/select\";\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface TemplateIOPanelProps extends ImportExportHandlers {\n templates?: TemplateOption[];\n templateId?: string;\n onTemplateChange?: (id: string) => void;\n onClearTemplate?: () => void;\n /** Disable export buttons when there's nothing to export. */\n hasEntries?: boolean;\n className?: string;\n csvAccept?: string;\n templateAccept?: string;\n}\n\ninterface FilePickerButtonProps {\n label: string;\n accept: string;\n onPick: (file: File, triage?: PlateMapCsvTriage) => void | Promise<void>;\n disabled?: boolean;\n triageCsv?: boolean;\n}\n\nfunction FilePickerButton({ label, accept, onPick, disabled, triageCsv }: FilePickerButtonProps) {\n const inputRef = React.useRef<HTMLInputElement>(null);\n return (\n <>\n <Button type=\"button\" variant=\"outline\" size=\"sm\" disabled={disabled} onClick={() => inputRef.current?.click()}>\n <Upload aria-hidden /> {label}\n </Button>\n <input\n ref={inputRef}\n type=\"file\"\n accept={accept}\n hidden\n onChange={(e) => {\n const input = e.currentTarget;\n const f = e.target.files?.[0];\n if (!f) {\n input.value = \"\";\n return;\n }\n\n void (async () => {\n const triage = triageCsv ? await triagePlateMapCsvFile(f) : undefined;\n await (triage ? onPick(f, triage) : onPick(f));\n input.value = \"\";\n })();\n }}\n />\n </>\n );\n}\n\nexport function TemplateIOPanel({\n templates,\n templateId,\n onTemplateChange,\n onClearTemplate,\n hasEntries,\n onImportCsv,\n onExportCsv,\n onImportTemplate,\n onExportTemplate,\n className,\n csvAccept = \".csv,text/csv\",\n templateAccept = \"application/json\",\n}: TemplateIOPanelProps) {\n const groups = React.useMemo(() => groupTemplateOptions(templates), [templates]);\n\n return (\n <div data-slot=\"template-io-panel\" className={cn(\"flex flex-col gap-3\", className)}>\n <div className=\"text-sm font-medium\">Template &amp; import / export</div>\n\n {templates && onTemplateChange ? (\n <div className=\"flex flex-col gap-1.5\">\n <Label htmlFor=\"plate-template\">Template</Label>\n <Select value={templateId ?? \"\"} onValueChange={(v) => onTemplateChange(v)}>\n <SelectTrigger id=\"plate-template\" size=\"sm\" className=\"w-full\">\n <SelectValue placeholder=\"Select template…\" />\n </SelectTrigger>\n <SelectContent>\n {groups.map(([group, opts]) => (\n <SelectGroup key={group || \"_\"}>\n {group ? <SelectLabel>{group}</SelectLabel> : null}\n {opts.map((t) => (\n <SelectItem key={t.id} value={t.id}>\n {t.label}\n </SelectItem>\n ))}\n </SelectGroup>\n ))}\n </SelectContent>\n </Select>\n {onClearTemplate ? (\n <Button variant=\"outline\" size=\"sm\" onClick={onClearTemplate} disabled={!templateId && !hasEntries}>\n Clear template\n </Button>\n ) : null}\n </div>\n ) : null}\n\n {onImportTemplate || onExportTemplate ? (\n <>\n <Separator />\n <div className=\"text-xs font-medium text-muted-foreground\">Template</div>\n <div className=\"flex flex-col gap-2\">\n {onImportTemplate ? (\n <FilePickerButton label=\"Import template (JSON)\" accept={templateAccept} onPick={onImportTemplate} />\n ) : null}\n {onExportTemplate ? (\n <Button variant=\"outline\" size=\"sm\" disabled={!hasEntries} onClick={onExportTemplate}>\n <Download aria-hidden /> Export template (JSON)\n </Button>\n ) : null}\n </div>\n </>\n ) : null}\n\n {onImportCsv || onExportCsv ? (\n <>\n <Separator />\n <div className=\"text-xs font-medium text-muted-foreground\">Plate map</div>\n <div className=\"flex flex-col gap-2\">\n {onImportCsv ? (\n <FilePickerButton label=\"Import plate map (CSV)\" accept={csvAccept} onPick={onImportCsv} triageCsv />\n ) : null}\n {onExportCsv ? (\n <Button variant=\"outline\" size=\"sm\" disabled={!hasEntries} onClick={onExportCsv}>\n <Download aria-hidden /> Export plate map (CSV)\n </Button>\n ) : null}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n"],"names":["FilePickerButton","label","accept","onPick","disabled","triageCsv","inputRef","React","jsxs","Fragment","Button","jsx","Upload","e","input","f","triage","triagePlateMapCsvFile","TemplateIOPanel","templates","templateId","onTemplateChange","onClearTemplate","hasEntries","onImportCsv","onExportCsv","onImportTemplate","onExportTemplate","className","csvAccept","templateAccept","groups","groupTemplateOptions","cn","Label","Select","v","SelectTrigger","SelectValue","SelectContent","group","opts","SelectGroup","SelectLabel","t","SelectItem","Separator","Download"],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),x=require("lucide-react"),g=require("react"),f=require("../../ui/button.cjs"),c=require("../../ui/card.cjs"),s=require("../../../lib/utils.cjs");function b(r){const n=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const l in r)if(l!=="default"){const a=Object.getOwnPropertyDescriptor(r,l);Object.defineProperty(n,l,a.get?a:{enumerable:!0,get:()=>r[l]})}}return n.default=r,Object.freeze(n)}const j=b(g);function p({items:r,renderItem:n,onHoverEnter:l,onHoverLeave:a,onRemove:d,removeLabel:i="Remove",emptyLabel:u="No items",className:o}){return r.length===0?t.jsx("div",{className:s.cn("text-xs text-muted-foreground",o),"data-slot":"well-legend-empty",children:u}):t.jsx("div",{className:s.cn("flex flex-col gap-1.5",o),"data-slot":"well-legend",children:r.map(e=>n?t.jsx(j.Fragment,{children:n(e)},e.id):t.jsx(c.Card,{size:"sm","data-slot":"well-legend-item","data-disabled":e.disabled||void 0,className:s.cn("py-2 hover:bg-muted/40",e.disabled&&"opacity-50"),onMouseEnter:()=>l?.(e.id),onMouseLeave:()=>a?.(e.id),children:t.jsxs(c.CardContent,{className:"flex items-start gap-2",children:[t.jsx("span",{"aria-hidden":!0,className:"mt-0.5 size-3.5 shrink-0 rounded-sm border border-foreground/20",style:{backgroundColor:e.color}}),t.jsxs("div",{className:"min-w-0 flex-1",children:[t.jsx("div",{className:"truncate text-xs font-medium",children:e.label}),e.meta?t.jsx("div",{className:"truncate text-[0.65rem] text-muted-foreground",children:e.meta}):null]}),d?t.jsx(f.Button,{type:"button",variant:"ghost",size:"icon-xs","aria-label":`${i} ${typeof e.label=="string"?e.label:e.id}`,onClick:()=>d(e.id),children:t.jsx(x.X,{"aria-hidden":!0})}):null]})},e.id))})}exports.WellLegend=p;
2
+ //# sourceMappingURL=WellLegend.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WellLegend.cjs","sources":["../../../../src/components/composed/PlateMapEditor/WellLegend.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface WellLegendItem {\n id: string;\n label: React.ReactNode;\n color: string;\n /** Optional secondary text shown beneath the label. */\n meta?: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface WellLegendProps {\n items: WellLegendItem[];\n /** Render-prop for fully custom cards. Bypasses the default card layout. */\n renderItem?: (item: WellLegendItem) => React.ReactNode;\n onHoverEnter?: (id: string) => void;\n onHoverLeave?: (id: string) => void;\n onRemove?: (id: string) => void;\n removeLabel?: string;\n emptyLabel?: string;\n className?: string;\n}\n\nexport function WellLegend({\n items,\n renderItem,\n onHoverEnter,\n onHoverLeave,\n onRemove,\n removeLabel = \"Remove\",\n emptyLabel = \"No items\",\n className,\n}: WellLegendProps) {\n if (items.length === 0) {\n return (\n <div className={cn(\"text-xs text-muted-foreground\", className)} data-slot=\"well-legend-empty\">\n {emptyLabel}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex flex-col gap-1.5\", className)} data-slot=\"well-legend\">\n {items.map((item) => {\n if (renderItem) return <React.Fragment key={item.id}>{renderItem(item)}</React.Fragment>;\n return (\n <Card\n key={item.id}\n size=\"sm\"\n data-slot=\"well-legend-item\"\n data-disabled={item.disabled || undefined}\n className={cn(\"py-2 hover:bg-muted/40\", item.disabled && \"opacity-50\")}\n onMouseEnter={() => onHoverEnter?.(item.id)}\n onMouseLeave={() => onHoverLeave?.(item.id)}\n >\n <CardContent className=\"flex items-start gap-2\">\n <span\n aria-hidden\n className=\"mt-0.5 size-3.5 shrink-0 rounded-sm border border-foreground/20\"\n style={{ backgroundColor: item.color }}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-xs font-medium\">{item.label}</div>\n {item.meta ? (\n <div className=\"truncate text-[0.65rem] text-muted-foreground\">{item.meta}</div>\n ) : null}\n </div>\n {onRemove ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`${removeLabel} ${typeof item.label === \"string\" ? item.label : item.id}`}\n onClick={() => onRemove(item.id)}\n >\n <X aria-hidden />\n </Button>\n ) : null}\n </CardContent>\n </Card>\n );\n })}\n </div>\n );\n}\n"],"names":["WellLegend","items","renderItem","onHoverEnter","onHoverLeave","onRemove","removeLabel","emptyLabel","className","jsx","cn","item","React","Card","jsxs","CardContent","Button","X"],"mappings":"giBA4BO,SAASA,EAAW,CACzB,MAAAC,EACA,WAAAC,EACA,aAAAC,EACA,aAAAC,EACA,SAAAC,EACA,YAAAC,EAAc,SACd,WAAAC,EAAa,WACb,UAAAC,CACF,EAAoB,CAClB,OAAIP,EAAM,SAAW,EAEjBQ,MAAC,OAAI,UAAWC,EAAAA,GAAG,gCAAiCF,CAAS,EAAG,YAAU,oBACvE,SAAAD,CAAA,CACH,EAKFE,EAAAA,IAAC,MAAA,CAAI,UAAWC,EAAAA,GAAG,wBAAyBF,CAAS,EAAG,YAAU,cAC/D,SAAAP,EAAM,IAAKU,GACNT,EAAmBO,MAACG,EAAM,SAAN,CAA8B,SAAAV,EAAWS,CAAI,GAAzBA,EAAK,EAAsB,EAErEF,EAAAA,IAACI,EAAAA,KAAA,CAEC,KAAK,KACL,YAAU,mBACV,gBAAeF,EAAK,UAAY,OAChC,UAAWD,EAAAA,GAAG,yBAA0BC,EAAK,UAAY,YAAY,EACrE,aAAc,IAAMR,IAAeQ,EAAK,EAAE,EAC1C,aAAc,IAAMP,IAAeO,EAAK,EAAE,EAE1C,SAAAG,EAAAA,KAACC,EAAAA,YAAA,CAAY,UAAU,yBACrB,SAAA,CAAAN,EAAAA,IAAC,OAAA,CACC,cAAW,GACX,UAAU,kEACV,MAAO,CAAE,gBAAiBE,EAAK,KAAA,CAAM,CAAA,EAEvCG,EAAAA,KAAC,MAAA,CAAI,UAAU,iBACb,SAAA,CAAAL,EAAAA,IAAC,MAAA,CAAI,UAAU,+BAAgC,SAAAE,EAAK,MAAM,EACzDA,EAAK,KACJF,MAAC,MAAA,CAAI,UAAU,gDAAiD,SAAAE,EAAK,KAAK,EACxE,IAAA,EACN,EACCN,EACCI,EAAAA,IAACO,EAAAA,OAAA,CACC,KAAK,SACL,QAAQ,QACR,KAAK,UACL,aAAY,GAAGV,CAAW,IAAI,OAAOK,EAAK,OAAU,SAAWA,EAAK,MAAQA,EAAK,EAAE,GACnF,QAAS,IAAMN,EAASM,EAAK,EAAE,EAE/B,SAAAF,EAAAA,IAACQ,EAAAA,EAAA,CAAE,cAAW,EAAA,CAAC,CAAA,CAAA,EAEf,IAAA,CAAA,CACN,CAAA,EA/BKN,EAAK,EAAA,CAkCf,CAAA,CACH,CAEJ"}
@@ -0,0 +1,58 @@
1
+ import { jsx as r, jsxs as n } from "react/jsx-runtime";
2
+ import { X as m } from "lucide-react";
3
+ import * as f from "react";
4
+ import { Button as p } from "../../ui/button.js";
5
+ import { Card as g, CardContent as h } from "../../ui/card.js";
6
+ import { cn as l } from "../../../lib/utils.js";
7
+ function C({
8
+ items: a,
9
+ renderItem: d,
10
+ onHoverEnter: s,
11
+ onHoverLeave: i,
12
+ onRemove: t,
13
+ removeLabel: c = "Remove",
14
+ emptyLabel: u = "No items",
15
+ className: o
16
+ }) {
17
+ return a.length === 0 ? /* @__PURE__ */ r("div", { className: l("text-xs text-muted-foreground", o), "data-slot": "well-legend-empty", children: u }) : /* @__PURE__ */ r("div", { className: l("flex flex-col gap-1.5", o), "data-slot": "well-legend", children: a.map((e) => d ? /* @__PURE__ */ r(f.Fragment, { children: d(e) }, e.id) : /* @__PURE__ */ r(
18
+ g,
19
+ {
20
+ size: "sm",
21
+ "data-slot": "well-legend-item",
22
+ "data-disabled": e.disabled || void 0,
23
+ className: l("py-2 hover:bg-muted/40", e.disabled && "opacity-50"),
24
+ onMouseEnter: () => s?.(e.id),
25
+ onMouseLeave: () => i?.(e.id),
26
+ children: /* @__PURE__ */ n(h, { className: "flex items-start gap-2", children: [
27
+ /* @__PURE__ */ r(
28
+ "span",
29
+ {
30
+ "aria-hidden": !0,
31
+ className: "mt-0.5 size-3.5 shrink-0 rounded-sm border border-foreground/20",
32
+ style: { backgroundColor: e.color }
33
+ }
34
+ ),
35
+ /* @__PURE__ */ n("div", { className: "min-w-0 flex-1", children: [
36
+ /* @__PURE__ */ r("div", { className: "truncate text-xs font-medium", children: e.label }),
37
+ e.meta ? /* @__PURE__ */ r("div", { className: "truncate text-[0.65rem] text-muted-foreground", children: e.meta }) : null
38
+ ] }),
39
+ t ? /* @__PURE__ */ r(
40
+ p,
41
+ {
42
+ type: "button",
43
+ variant: "ghost",
44
+ size: "icon-xs",
45
+ "aria-label": `${c} ${typeof e.label == "string" ? e.label : e.id}`,
46
+ onClick: () => t(e.id),
47
+ children: /* @__PURE__ */ r(m, { "aria-hidden": !0 })
48
+ }
49
+ ) : null
50
+ ] })
51
+ },
52
+ e.id
53
+ )) });
54
+ }
55
+ export {
56
+ C as WellLegend
57
+ };
58
+ //# sourceMappingURL=WellLegend.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WellLegend.js","sources":["../../../../src/components/composed/PlateMapEditor/WellLegend.tsx"],"sourcesContent":["import { X } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { Button } from \"@/components/ui/button\";\nimport { Card, CardContent } from \"@/components/ui/card\";\nimport { cn } from \"@/lib/utils\";\n\nexport interface WellLegendItem {\n id: string;\n label: React.ReactNode;\n color: string;\n /** Optional secondary text shown beneath the label. */\n meta?: React.ReactNode;\n disabled?: boolean;\n}\n\nexport interface WellLegendProps {\n items: WellLegendItem[];\n /** Render-prop for fully custom cards. Bypasses the default card layout. */\n renderItem?: (item: WellLegendItem) => React.ReactNode;\n onHoverEnter?: (id: string) => void;\n onHoverLeave?: (id: string) => void;\n onRemove?: (id: string) => void;\n removeLabel?: string;\n emptyLabel?: string;\n className?: string;\n}\n\nexport function WellLegend({\n items,\n renderItem,\n onHoverEnter,\n onHoverLeave,\n onRemove,\n removeLabel = \"Remove\",\n emptyLabel = \"No items\",\n className,\n}: WellLegendProps) {\n if (items.length === 0) {\n return (\n <div className={cn(\"text-xs text-muted-foreground\", className)} data-slot=\"well-legend-empty\">\n {emptyLabel}\n </div>\n );\n }\n\n return (\n <div className={cn(\"flex flex-col gap-1.5\", className)} data-slot=\"well-legend\">\n {items.map((item) => {\n if (renderItem) return <React.Fragment key={item.id}>{renderItem(item)}</React.Fragment>;\n return (\n <Card\n key={item.id}\n size=\"sm\"\n data-slot=\"well-legend-item\"\n data-disabled={item.disabled || undefined}\n className={cn(\"py-2 hover:bg-muted/40\", item.disabled && \"opacity-50\")}\n onMouseEnter={() => onHoverEnter?.(item.id)}\n onMouseLeave={() => onHoverLeave?.(item.id)}\n >\n <CardContent className=\"flex items-start gap-2\">\n <span\n aria-hidden\n className=\"mt-0.5 size-3.5 shrink-0 rounded-sm border border-foreground/20\"\n style={{ backgroundColor: item.color }}\n />\n <div className=\"min-w-0 flex-1\">\n <div className=\"truncate text-xs font-medium\">{item.label}</div>\n {item.meta ? (\n <div className=\"truncate text-[0.65rem] text-muted-foreground\">{item.meta}</div>\n ) : null}\n </div>\n {onRemove ? (\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n aria-label={`${removeLabel} ${typeof item.label === \"string\" ? item.label : item.id}`}\n onClick={() => onRemove(item.id)}\n >\n <X aria-hidden />\n </Button>\n ) : null}\n </CardContent>\n </Card>\n );\n })}\n </div>\n );\n}\n"],"names":["WellLegend","items","renderItem","onHoverEnter","onHoverLeave","onRemove","removeLabel","emptyLabel","className","jsx","cn","item","React","Card","jsxs","CardContent","Button","X"],"mappings":";;;;;;AA4BO,SAASA,EAAW;AAAA,EACzB,OAAAC;AAAA,EACA,YAAAC;AAAA,EACA,cAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,EACA,aAAAC,IAAc;AAAA,EACd,YAAAC,IAAa;AAAA,EACb,WAAAC;AACF,GAAoB;AAClB,SAAIP,EAAM,WAAW,IAEjB,gBAAAQ,EAAC,SAAI,WAAWC,EAAG,iCAAiCF,CAAS,GAAG,aAAU,qBACvE,UAAAD,EAAA,CACH,IAKF,gBAAAE,EAAC,OAAA,EAAI,WAAWC,EAAG,yBAAyBF,CAAS,GAAG,aAAU,eAC/D,UAAAP,EAAM,IAAI,CAACU,MACNT,IAAmB,gBAAAO,EAACG,EAAM,UAAN,EAA8B,UAAAV,EAAWS,CAAI,KAAzBA,EAAK,EAAsB,IAErE,gBAAAF;AAAA,IAACI;AAAA,IAAA;AAAA,MAEC,MAAK;AAAA,MACL,aAAU;AAAA,MACV,iBAAeF,EAAK,YAAY;AAAA,MAChC,WAAWD,EAAG,0BAA0BC,EAAK,YAAY,YAAY;AAAA,MACrE,cAAc,MAAMR,IAAeQ,EAAK,EAAE;AAAA,MAC1C,cAAc,MAAMP,IAAeO,EAAK,EAAE;AAAA,MAE1C,UAAA,gBAAAG,EAACC,GAAA,EAAY,WAAU,0BACrB,UAAA;AAAA,QAAA,gBAAAN;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,eAAW;AAAA,YACX,WAAU;AAAA,YACV,OAAO,EAAE,iBAAiBE,EAAK,MAAA;AAAA,UAAM;AAAA,QAAA;AAAA,QAEvC,gBAAAG,EAAC,OAAA,EAAI,WAAU,kBACb,UAAA;AAAA,UAAA,gBAAAL,EAAC,OAAA,EAAI,WAAU,gCAAgC,UAAAE,EAAK,OAAM;AAAA,UACzDA,EAAK,OACJ,gBAAAF,EAAC,OAAA,EAAI,WAAU,iDAAiD,UAAAE,EAAK,MAAK,IACxE;AAAA,QAAA,GACN;AAAA,QACCN,IACC,gBAAAI;AAAA,UAACO;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,SAAQ;AAAA,YACR,MAAK;AAAA,YACL,cAAY,GAAGV,CAAW,IAAI,OAAOK,EAAK,SAAU,WAAWA,EAAK,QAAQA,EAAK,EAAE;AAAA,YACnF,SAAS,MAAMN,EAASM,EAAK,EAAE;AAAA,YAE/B,UAAA,gBAAAF,EAACQ,GAAA,EAAE,eAAW,GAAA,CAAC;AAAA,UAAA;AAAA,QAAA,IAEf;AAAA,MAAA,EAAA,CACN;AAAA,IAAA;AAAA,IA/BKN,EAAK;AAAA,EAAA,CAkCf,EAAA,CACH;AAEJ;"}
@@ -0,0 +1,2 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const t=require("react/jsx-runtime"),T=require("lucide-react"),we=require("react"),ve=require("./ManifestFilterPopover.cjs"),Y=require("../../ui/badge.cjs"),A=require("../../ui/button.cjs"),J=require("../../ui/checkbox.cjs"),b=require("../../ui/combobox.cjs"),Ne=require("../../ui/data-table/data-table.cjs"),ye=require("../../ui/input.cjs"),u=require("../../ui/select.cjs"),ke=require("../../ui/switch.cjs"),f=require("../../ui/table.cjs"),P=require("../../ui/tooltip.cjs"),I=require("../../../lib/utils.cjs");function Te(o){const i=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(o){for(const c in o)if(c!=="default"){const d=Object.getOwnPropertyDescriptor(o,c);Object.defineProperty(i,c,d.get?d:{enumerable:!0,get:()=>o[c]})}}return i.default=o,Object.freeze(i)}const h=Te(we);function _e({ariaLabel:o,value:i,options:c,placeholder:d,onChange:p}){const j=b.useComboboxAnchor(),g=h.useMemo(()=>{const x=new Map;return c.forEach(C=>x.set(C.value,C.label)),x},[c]);return t.jsxs(b.Combobox,{multiple:!0,items:c.map(x=>x.value),value:i,onValueChange:p,children:[t.jsxs(b.ComboboxChips,{ref:j,className:I.cn("min-h-7 w-full py-0.5",G),children:[t.jsx(b.ComboboxValue,{children:x=>x.map(C=>t.jsx(b.ComboboxChip,{children:g.get(C)??C},C))}),t.jsx(b.ComboboxChipsInput,{"aria-label":o,placeholder:d??"Select…"})]}),t.jsxs(b.ComboboxContent,{anchor:j,children:[t.jsx(b.ComboboxEmpty,{children:"No options."}),t.jsx(b.ComboboxList,{children:x=>t.jsx(b.ComboboxItem,{value:x,children:g.get(x)??x},x)})]})]})}const G="border-transparent shadow-none hover:border-input/40",X=25,Me=50,Ee=100,ze=X,Fe=[X,Me,Ee];function Q(o){return o!=null&&o!==""}const Re={number:"number",integer:"number",date:"date",datetime:"datetime-local",time:"time"};function Ae(o){return Re[o]??"text"}function Pe(o,i){if(i!==""){if(o==="number"){const c=parseFloat(i);return Number.isFinite(c)?c:i}if(o==="integer"){const c=parseInt(i,10);return Number.isFinite(c)?c:i}return i}}function Ie(o,i){const c=new Map;for(const d of o){const p=d.row[i],j=p==null||p===""?"(blank)":String(p),g=c.get(j);g?g.rows.push(d):c.set(j,{key:j,rows:[d]})}return[...c.values()]}function qe(o){return o.filter(i=>!!i.field).map(i=>({columnId:i.field,label:i.header}))}function De({values:o,columns:i,fields:c,selection:d,onSelectionChange:p,onChange:j,emptyEntry:g,isPopulated:x,pageSize:C=ze,pageSizeOptions:ee=Fe,enableFillDown:L=!0,rowProps:te,filterable:q=!1,filterColumns:V,groupable:D=!1,className:ne}){const[F,se]=h.useState(!1),[w,_]=h.useState(0),[S,re]=h.useState(C),[M,le]=h.useState([]),[R,ae]=h.useState(""),[ie,oe]=h.useState(new Set);h.useEffect(()=>{_(0)},[F]);const W=h.useMemo(()=>{const e=new Map;return(c??[]).forEach(n=>e.set(n.key,n)),e},[c]),ce=h.useMemo(()=>V??qe(i),[i,V]),v=h.useMemo(()=>{const e=[...o.entries()].map(([s,r])=>({id:s,row:r}));let n=e;if(!F&&x&&(n=e.filter(s=>x(s.row))),q&&M.length>0&&(n=n.filter(s=>{const r=s.row;return M.every(l=>{const a=r[l.columnId],m=a==null?"":String(a);return Ne.applyFilterCondition(m,l.operator,l.value)})})),d&&d.size>0){const s=new Set(n.map(r=>r.id));d.forEach(r=>{!s.has(r)&&!o.has(r)&&(n=[...n,{id:r,row:g(r)}])})}return n.sort((s,r)=>s.id.localeCompare(r.id))},[o,F,x,d,g,q,M]);h.useEffect(()=>{_(0)},[M]);const B=h.useMemo(()=>v.slice(w*S,w*S+S),[v,w,S]),y=(e,n)=>{const s=new Map(o),r=s.get(e)??g(e);s.set(e,{...r,...n}),j(s)},de=e=>{if(!p)return;const n=new Set(d??[]);n.has(e)?n.delete(e):n.add(e),p(n)},O=e=>{if(!e.field)return null;const n=!!d&&d.size>0,r=n?v.filter(({id:N})=>d.has(N)):D&&!!R?v:B,l=r.findIndex(({row:N})=>Q(N[e.field]));if(l<0)return null;const a=r[l],m=n?r.filter(({id:N})=>N!==a.id):r.slice(l+1);return{field:e.field,source:a,targets:m,value:a.row[e.field]}},ue=e=>{const n=O(e);if(!n||n.targets.length===0)return;const s=new Map(o);n.targets.forEach(({id:r})=>{const l=s.get(r)??g(r);s.set(r,{...l,[n.field]:n.value})}),j(s)},he=(e,n,s,r,l)=>t.jsxs(u.Select,{value:s??"",onValueChange:a=>y(r,{[n]:a}),children:[t.jsx(u.SelectTrigger,{size:"sm",className:I.cn("h-7 w-full",G),"aria-label":l,children:t.jsx(u.SelectValue,{placeholder:e.placeholder??"Select…"})}),t.jsx(u.SelectContent,{children:(e.options??[]).map(a=>t.jsx(u.SelectItem,{value:a.value,children:t.jsxs("span",{className:"inline-flex items-center gap-2",children:[a.swatch?t.jsx("span",{className:"inline-block h-2.5 w-2.5 rounded-sm border border-foreground/20",style:{backgroundColor:a.swatch},"aria-hidden":!0}):null,a.label]})},a.value))})]}),xe=(e,n,s,r,l)=>{const a=!!s;return e.boolStyle==="switch"?t.jsx(ke.Switch,{"aria-label":l,checked:a,onCheckedChange:m=>y(r,{[n]:m})}):t.jsx(J.Checkbox,{"aria-label":l,checked:a,onCheckedChange:m=>y(r,{[n]:m===!0})})},me=(e,n,s,r,l)=>t.jsx(ye.Input,{type:Ae(e.kind),step:e.kind==="integer"?1:void 0,placeholder:e.placeholder,"aria-label":l,className:I.cn("h-7",G),value:s??"",onChange:a=>y(r,{[n]:Pe(e.kind,a.target.value)})}),fe=(e,n,s,r)=>{const l=n.field,a=r[l],m=`${e.label} for ${s}`;if(e.kind==="select")return he(e,l,a,s,m);if(e.kind==="multiselect"){const N=Array.isArray(a)?a:[];return t.jsx(_e,{ariaLabel:m,value:N,options:e.options??[],placeholder:e.placeholder,onChange:K=>y(s,{[l]:K.length===0?void 0:K})})}return e.kind==="boolean"?xe(e,l,a,s,m):me(e,l,a,s,m)},pe=(e,n)=>{if(e?.kind==="select"){const s=(e.options??[]).find(r=>r.value===n);return s?t.jsxs(Y.Badge,{variant:"secondary",children:[s.swatch?t.jsx("span",{className:"size-2 rounded-sm border border-foreground/20",style:{backgroundColor:s.swatch},"aria-hidden":!0}):null,s.label]}):t.jsx("span",{className:"text-muted-foreground",children:"—"})}if(e?.kind==="multiselect"){const s=Array.isArray(n)?n:[];return s.length===0?t.jsx("span",{className:"text-muted-foreground",children:"—"}):t.jsx("div",{className:"flex flex-wrap gap-1",children:s.map(r=>{const l=(e.options??[]).find(a=>a.value===r);return t.jsxs(Y.Badge,{variant:"secondary",children:[l?.swatch?t.jsx("span",{className:"size-2 rounded-sm border border-foreground/20",style:{backgroundColor:l.swatch},"aria-hidden":!0}):null,l?.label??r]},r)})})}return e?.kind==="boolean"?n?t.jsx(T.Check,{"aria-label":"Yes",className:"size-4 text-foreground"}):t.jsx("span",{className:"text-muted-foreground",children:"—"}):Q(n)?String(n):t.jsx("span",{className:"text-muted-foreground",children:"—"})},ge=(e,n,s)=>{if(e.render)return e.render({row:s,wellId:n,update:a=>y(n,a)});if(!e.field)return null;const r=W.get(e.field),l=s[e.field];return r?.editableInTable&&r.kind!=="custom"?fe(r,e,n,s):pe(r,l)},be=e=>{const n=e.field?W.get(e.field):void 0,s=e.icon??n?.icon,r=L?O(e):null,l=!!r&&r.targets.length>0,a=d&&d.size>0?`Fill selected ${e.header} cells from the first selected value`:`Fill visible ${e.header} cells downward from the first value`;return t.jsxs("span",{className:"flex min-w-0 items-center justify-between gap-2",children:[t.jsxs("span",{className:"inline-flex min-w-0 items-center gap-1.5",children:[s?t.jsx("span",{className:"inline-flex text-muted-foreground [&_svg]:size-3.5",children:s}):null,t.jsx("span",{className:"truncate",children:e.header})]}),L&&e.field?t.jsxs(P.Tooltip,{children:[t.jsx(P.TooltipTrigger,{asChild:!0,children:t.jsx(A.Button,{type:"button",variant:"ghost",size:"icon-xs",className:"-mr-1 text-muted-foreground hover:text-foreground",disabled:!l,"aria-label":`Fill down ${e.header}`,onClick:m=>{m.preventDefault(),m.stopPropagation(),ue(e)},children:t.jsx(T.ArrowDownToLine,{})})}),t.jsx(P.TooltipContent,{children:a})]}):null]})},je=h.useMemo(()=>i.filter(e=>!!e.field),[i]),k=D&&R?R:"",E=h.useMemo(()=>k?Ie(v,k):null,[k,v]),z=v.length,$=Math.max(0,Math.ceil(z/S)-1),Ce=d?.size??0,H=i.length+1+(p?1:0),Z=(e,n)=>{const s=d?.has(e),r=te?.({wellId:e,row:n,isSelected:!!s});return t.jsxs(f.TableRow,{...r,children:[p?t.jsx(f.TableCell,{className:"w-10",children:t.jsx(J.Checkbox,{checked:!!s,onCheckedChange:()=>de(e),"aria-label":`Select ${e}`})}):null,t.jsx(f.TableCell,{className:"font-semibold",children:e}),i.map(l=>t.jsx(f.TableCell,{style:l.minWidth?{minWidth:l.minWidth}:void 0,children:ge(l,e,n)},l.id??l.field??l.header))]},e)},U=e=>{oe(n=>{const s=new Set(n);return s.has(e)?s.delete(e):s.add(e),s})},Se=k?i.find(n=>n.field===k)?.header??k:"";return t.jsxs("div",{"data-slot":"well-manifest-table",className:I.cn("flex flex-col gap-2",ne),children:[t.jsxs("div",{className:"flex flex-wrap items-center gap-2",children:[t.jsx(A.Button,{variant:"outline",size:"sm",onClick:()=>se(e=>!e),children:F?"Hide empty wells":"Show all wells"}),q?t.jsx(ve.ManifestFilterPopover,{columns:ce,filters:M,onFiltersChange:le}):null,D?t.jsxs("div",{className:"inline-flex items-center gap-1.5",children:[t.jsx(T.Layers,{"aria-hidden":!0,className:"size-3.5 text-muted-foreground"}),t.jsxs(u.Select,{value:R||"__none",onValueChange:e=>ae(e==="__none"?"":e),children:[t.jsx(u.SelectTrigger,{size:"sm",className:"h-7 min-w-40","aria-label":"Group by",children:t.jsx(u.SelectValue,{placeholder:"Group by…"})}),t.jsxs(u.SelectContent,{children:[t.jsx(u.SelectItem,{value:"__none",children:"No grouping"}),je.map(e=>t.jsx(u.SelectItem,{value:e.field??"",children:e.header},e.id??e.field))]})]})]}):null,t.jsxs("span",{className:"text-xs text-muted-foreground",children:[z," rows · ",Ce," selected"]})]}),t.jsx(P.TooltipProvider,{children:t.jsxs(f.Table,{"data-density":"default",children:[t.jsx(f.TableHeader,{children:t.jsxs(f.TableRow,{children:[p?t.jsx(f.TableHead,{className:"w-10 text-center",children:t.jsxs("span",{className:"inline-flex items-center justify-center text-muted-foreground [&_svg]:size-3.5",children:[t.jsx(T.Check,{"aria-hidden":!0}),t.jsx("span",{className:"sr-only",children:"Selected"})]})}):null,t.jsx(f.TableHead,{style:{minWidth:60},children:"Well"}),i.map(e=>t.jsx(f.TableHead,{style:e.minWidth?{minWidth:e.minWidth}:void 0,children:be(e)},e.id??e.field??e.header))]})}),t.jsxs(f.TableBody,{children:[E?E.map(e=>{const n=ie.has(e.key);return t.jsxs(h.Fragment,{children:[t.jsx(f.TableRow,{className:"cursor-pointer bg-muted/40",onClick:()=>U(e.key),onKeyDown:s=>{(s.key==="Enter"||s.key===" ")&&(s.preventDefault(),U(e.key))},role:"button",tabIndex:0,"aria-expanded":!n,children:t.jsx(f.TableCell,{colSpan:H,className:"py-1.5",children:t.jsxs("div",{className:"flex items-center gap-2 text-xs font-medium",children:[n?t.jsx(T.ChevronRight,{"aria-hidden":!0,className:"size-3.5 text-muted-foreground"}):t.jsx(T.ChevronDown,{"aria-hidden":!0,className:"size-3.5 text-muted-foreground"}),t.jsxs("span",{children:[Se,": ",e.key]}),t.jsxs("span",{className:"text-muted-foreground",children:["(",e.rows.length," ",e.rows.length===1?"row":"rows",")"]})]})})}),n?null:e.rows.map(({id:s,row:r})=>Z(s,r))]},e.key)}):B.map(({id:e,row:n})=>Z(e,n)),(E?E.length===0:B.length===0)?t.jsx(f.TableRow,{children:t.jsx(f.TableCell,{colSpan:H,className:"text-xs text-muted-foreground",children:"No rows. Paint wells on the plate."})}):null]})]})}),E?null:t.jsxs("div",{className:"flex items-center justify-end gap-3 text-xs text-muted-foreground",children:[t.jsx("span",{className:"text-muted-foreground",children:"Rows per page"}),t.jsxs(u.Select,{value:String(S),onValueChange:e=>{re(parseInt(e,10)),_(0)},children:[t.jsx(u.SelectTrigger,{size:"sm",className:"h-7 w-18","aria-label":"Rows per page",children:t.jsx(u.SelectValue,{})}),t.jsx(u.SelectContent,{children:ee.map(e=>t.jsx(u.SelectItem,{value:String(e),children:e},e))})]}),t.jsx("span",{children:z===0?"0 of 0":`${w*S+1}–${Math.min((w+1)*S,z)} of ${z}`}),t.jsx(A.Button,{variant:"outline",size:"sm",disabled:w===0,onClick:()=>_(e=>Math.max(0,e-1)),children:"Prev"}),t.jsx(A.Button,{variant:"outline",size:"sm",disabled:w>=$,onClick:()=>_(e=>Math.min($,e+1)),children:"Next"})]})]})}exports.WellManifestTable=De;
2
+ //# sourceMappingURL=WellManifestTable.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WellManifestTable.cjs","sources":["../../../../src/components/composed/PlateMapEditor/WellManifestTable.tsx"],"sourcesContent":["import { ArrowDownToLine, Check, ChevronDown, ChevronRight, Layers } from \"lucide-react\";\nimport * as React from \"react\";\n\nimport { ManifestFilterPopover } from \"./ManifestFilterPopover\";\n\nimport type { WellColumn, WellField, WellId, WellRecord, WellSelectOption } from \"./types\";\nimport type { FilterColumnConfig, FilterCondition } from \"@/components/ui/data-table/data-table\";\n\nimport { Badge } from \"@/components/ui/badge\";\nimport { Button } from \"@/components/ui/button\";\nimport { Checkbox } from \"@/components/ui/checkbox\";\nimport {\n Combobox,\n ComboboxChip,\n ComboboxChips,\n ComboboxChipsInput,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxItem,\n ComboboxList,\n ComboboxValue,\n useComboboxAnchor,\n} from \"@/components/ui/combobox\";\nimport { applyFilterCondition } from \"@/components/ui/data-table/data-table\";\nimport { Input } from \"@/components/ui/input\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from \"@/components/ui/table\";\nimport { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from \"@/components/ui/tooltip\";\nimport { cn } from \"@/lib/utils\";\n\nfunction MultiSelectCell({\n ariaLabel,\n value,\n options,\n placeholder,\n onChange,\n}: {\n ariaLabel: string;\n value: string[];\n options: WellSelectOption[];\n placeholder?: string;\n onChange: (next: string[]) => void;\n}) {\n const anchorRef = useComboboxAnchor();\n const labelByValue = React.useMemo(() => {\n const m = new Map<string, string>();\n options.forEach((o) => m.set(o.value, o.label));\n return m;\n }, [options]);\n\n return (\n <Combobox multiple items={options.map((o) => o.value)} value={value} onValueChange={onChange}>\n <ComboboxChips ref={anchorRef} className={cn(\"min-h-7 w-full py-0.5\", CELL_EDITOR_CLASS)}>\n <ComboboxValue>\n {(items: string[]) =>\n items.map((item) => <ComboboxChip key={item}>{labelByValue.get(item) ?? item}</ComboboxChip>)\n }\n </ComboboxValue>\n <ComboboxChipsInput aria-label={ariaLabel} placeholder={placeholder ?? \"Select…\"} />\n </ComboboxChips>\n <ComboboxContent anchor={anchorRef}>\n <ComboboxEmpty>No options.</ComboboxEmpty>\n <ComboboxList>\n {(item: string) => (\n <ComboboxItem key={item} value={item}>\n {labelByValue.get(item) ?? item}\n </ComboboxItem>\n )}\n </ComboboxList>\n </ComboboxContent>\n </Combobox>\n );\n}\n\n/**\n * Cell editors render borderless by default so the table reads flat. The\n * underlying primitives keep their `focus-visible` / `focus-within` rings, so\n * an outline only appears while the user is actively editing the cell.\n */\nconst CELL_EDITOR_CLASS = \"border-transparent shadow-none hover:border-input/40\";\n\nconst PAGE_SIZE_SMALL = 25;\nconst PAGE_SIZE_MEDIUM = 50;\nconst PAGE_SIZE_LARGE = 100;\nconst DEFAULT_PAGE_SIZE = PAGE_SIZE_SMALL;\nconst DEFAULT_PAGE_SIZE_OPTIONS: number[] = [PAGE_SIZE_SMALL, PAGE_SIZE_MEDIUM, PAGE_SIZE_LARGE];\n\nfunction hasFillValue(value: unknown): boolean {\n return value !== undefined && value !== null && value !== \"\";\n}\n\nconst INPUT_TYPE_BY_KIND: Record<string, string> = {\n number: \"number\",\n integer: \"number\",\n date: \"date\",\n datetime: \"datetime-local\",\n time: \"time\",\n};\n\nfunction resolveInputType(kind: string): string {\n return INPUT_TYPE_BY_KIND[kind] ?? \"text\";\n}\n\nfunction parseInputValue(kind: string, raw: string): unknown {\n if (raw === \"\") return undefined;\n if (kind === \"number\") {\n const num = parseFloat(raw);\n return Number.isFinite(num) ? num : raw;\n }\n if (kind === \"integer\") {\n const num = parseInt(raw, 10);\n return Number.isFinite(num) ? num : raw;\n }\n return raw;\n}\n\nexport interface WellManifestTableRowContext<T extends WellRecord = WellRecord> {\n wellId: WellId;\n row: T;\n isSelected: boolean;\n}\n\nexport interface WellManifestTableProps<T extends WellRecord = WellRecord> {\n values: Map<WellId, T>;\n columns: WellColumn<T>[];\n /**\n * Field schema. If a column has `field` matching a `select`-kind field, a\n * Select cell renders automatically with that field's options.\n */\n fields?: WellField<T>[];\n selection?: Set<WellId>;\n onSelectionChange?: (next: Set<WellId>) => void;\n onChange: (next: Map<WellId, T>) => void;\n /** Builds an empty record for a freshly-created row. */\n emptyEntry: (id: WellId) => T;\n /** Filter that controls which empty rows surface. Defaults to `false`. */\n isPopulated?: (row: T) => boolean;\n pageSize?: number;\n pageSizeOptions?: number[];\n /** Adds a column header action that copies the first non-empty value downward. */\n enableFillDown?: boolean;\n /**\n * Extra props spread onto each `<tr>` — typically used to attach a DnD\n * library's `setNodeRef`, listeners, and data attributes so rows can act as\n * drag sources. The kit stays DnD-library-agnostic.\n */\n rowProps?: (ctx: WellManifestTableRowContext<T>) => React.ComponentProps<\"tr\"> | undefined;\n /** Enables an inline filter popover above the table. Defaults to false. */\n filterable?: boolean;\n /**\n * Optional override of filterable column configs. When omitted, every column\n * with a `field` becomes filterable using the default operator set from the\n * shared data-table filter system.\n */\n filterColumns?: FilterColumnConfig[];\n /** Enables an inline group-by selector. Defaults to false. */\n groupable?: boolean;\n className?: string;\n}\n\ninterface GroupedRow<T> {\n key: string;\n rows: Array<{ id: WellId; row: T }>;\n}\n\nfunction groupRowsBy<T extends WellRecord>(rows: Array<{ id: WellId; row: T }>, field: string): GroupedRow<T>[] {\n const map = new Map<string, GroupedRow<T>>();\n for (const entry of rows) {\n const raw = (entry.row as Record<string, unknown>)[field];\n const key = raw === undefined || raw === null || raw === \"\" ? \"(blank)\" : String(raw);\n const existing = map.get(key);\n if (existing) existing.rows.push(entry);\n else map.set(key, { key, rows: [entry] });\n }\n return [...map.values()];\n}\n\nfunction inferFilterColumns<T extends WellRecord>(columns: WellColumn<T>[]): FilterColumnConfig[] {\n return columns.filter((col) => !!col.field).map((col) => ({ columnId: col.field as string, label: col.header }));\n}\n\nexport function WellManifestTable<T extends WellRecord = WellRecord>({\n values,\n columns,\n fields,\n selection,\n onSelectionChange,\n onChange,\n emptyEntry,\n isPopulated,\n pageSize: initialPageSize = DEFAULT_PAGE_SIZE,\n pageSizeOptions = DEFAULT_PAGE_SIZE_OPTIONS,\n enableFillDown = true,\n rowProps,\n filterable = false,\n filterColumns,\n groupable = false,\n className,\n}: WellManifestTableProps<T>) {\n const [showAll, setShowAll] = React.useState(false);\n const [page, setPage] = React.useState(0);\n const [pageSize, setPageSize] = React.useState(initialPageSize);\n const [filters, setFilters] = React.useState<FilterCondition[]>([]);\n const [groupByField, setGroupByField] = React.useState<string>(\"\");\n const [collapsedGroups, setCollapsedGroups] = React.useState<Set<string>>(new Set());\n\n React.useEffect(() => {\n setPage(0);\n }, [showAll]);\n\n const fieldByKey = React.useMemo(() => {\n const m = new Map<string, WellField<T>>();\n (fields ?? []).forEach((f) => m.set(f.key, f));\n return m;\n }, [fields]);\n\n const resolvedFilterColumns = React.useMemo<FilterColumnConfig[]>(\n () => filterColumns ?? inferFilterColumns(columns),\n [columns, filterColumns],\n );\n\n const rows = React.useMemo(() => {\n const arr = [...values.entries()].map(([id, row]) => ({\n id,\n row,\n }));\n let filtered = arr;\n if (!showAll && isPopulated) {\n filtered = arr.filter((r) => isPopulated(r.row));\n }\n if (filterable && filters.length > 0) {\n filtered = filtered.filter((entry) => {\n const record = entry.row as Record<string, unknown>;\n return filters.every((condition) => {\n const cellRaw = record[condition.columnId];\n const cellValue = cellRaw === undefined || cellRaw === null ? \"\" : String(cellRaw);\n return applyFilterCondition(cellValue, condition.operator, condition.value);\n });\n });\n }\n if (selection && selection.size > 0) {\n const have = new Set(filtered.map((r) => r.id));\n selection.forEach((p) => {\n if (!have.has(p) && !values.has(p)) {\n filtered = [...filtered, { id: p, row: emptyEntry(p) }];\n }\n });\n }\n return filtered.sort((a, b) => a.id.localeCompare(b.id));\n }, [values, showAll, isPopulated, selection, emptyEntry, filterable, filters]);\n\n React.useEffect(() => {\n setPage(0);\n }, [filters]);\n\n const pagedRows = React.useMemo(\n () => rows.slice(page * pageSize, page * pageSize + pageSize),\n [rows, page, pageSize],\n );\n\n const updateRow = (wellId: WellId, patch: Partial<T>) => {\n const next = new Map(values);\n const cur = next.get(wellId) ?? emptyEntry(wellId);\n next.set(wellId, { ...cur, ...patch });\n onChange(next);\n };\n\n const toggleSelect = (wellId: WellId) => {\n if (!onSelectionChange) return;\n const s = new Set(selection ?? []);\n if (s.has(wellId)) {\n s.delete(wellId);\n } else {\n s.add(wellId);\n }\n onSelectionChange(s);\n };\n\n const getFillDownPlan = (col: WellColumn<T>) => {\n if (!col.field) return null;\n\n const selectionActive = !!selection && selection.size > 0;\n const groupingActive = groupable && !!groupByField;\n const sourceRows = selectionActive\n ? rows.filter(({ id }) => selection.has(id))\n : groupingActive\n ? rows\n : pagedRows;\n const sourceIndex = sourceRows.findIndex(({ row }) => hasFillValue(row[col.field!]));\n if (sourceIndex < 0) return null;\n\n const source = sourceRows[sourceIndex];\n const targets = selectionActive\n ? sourceRows.filter(({ id }) => id !== source.id)\n : sourceRows.slice(sourceIndex + 1);\n\n return {\n field: col.field,\n source,\n targets,\n value: source.row[col.field],\n };\n };\n\n const fillColumnDown = (col: WellColumn<T>) => {\n const plan = getFillDownPlan(col);\n if (!plan || plan.targets.length === 0) return;\n\n const next = new Map(values);\n plan.targets.forEach(({ id }) => {\n const cur = next.get(id) ?? emptyEntry(id);\n next.set(id, { ...cur, [plan.field]: plan.value } as T);\n });\n onChange(next);\n };\n\n const renderSelectCellEditable = (\n field: WellField<T>,\n fieldKey: keyof T & string,\n value: unknown,\n wellId: WellId,\n ariaLabel: string,\n ) => (\n <Select\n value={(value as string | undefined) ?? \"\"}\n onValueChange={(v) => updateRow(wellId, { [fieldKey]: v } as Partial<T>)}\n >\n <SelectTrigger size=\"sm\" className={cn(\"h-7 w-full\", CELL_EDITOR_CLASS)} aria-label={ariaLabel}>\n <SelectValue placeholder={field.placeholder ?? \"Select…\"} />\n </SelectTrigger>\n <SelectContent>\n {(field.options ?? []).map((opt) => (\n <SelectItem key={opt.value} value={opt.value}>\n <span className=\"inline-flex items-center gap-2\">\n {opt.swatch ? (\n <span\n className=\"inline-block h-2.5 w-2.5 rounded-sm border border-foreground/20\"\n style={{ backgroundColor: opt.swatch }}\n aria-hidden\n />\n ) : null}\n {opt.label}\n </span>\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n );\n\n const renderBooleanCellEditable = (\n field: WellField<T>,\n fieldKey: keyof T & string,\n value: unknown,\n wellId: WellId,\n ariaLabel: string,\n ) => {\n const checked = !!value;\n if (field.boolStyle === \"switch\") {\n return (\n <Switch\n aria-label={ariaLabel}\n checked={checked}\n onCheckedChange={(c) => updateRow(wellId, { [fieldKey]: c } as Partial<T>)}\n />\n );\n }\n return (\n <Checkbox\n aria-label={ariaLabel}\n checked={checked}\n onCheckedChange={(c) => updateRow(wellId, { [fieldKey]: c === true } as Partial<T>)}\n />\n );\n };\n\n const renderInputCellEditable = (\n field: WellField<T>,\n fieldKey: keyof T & string,\n value: unknown,\n wellId: WellId,\n ariaLabel: string,\n ) => (\n <Input\n type={resolveInputType(field.kind)}\n step={field.kind === \"integer\" ? 1 : undefined}\n placeholder={field.placeholder}\n aria-label={ariaLabel}\n className={cn(\"h-7\", CELL_EDITOR_CLASS)}\n value={(value as string | number | undefined) ?? \"\"}\n onChange={(e) => updateRow(wellId, { [fieldKey]: parseInputValue(field.kind, e.target.value) } as Partial<T>)}\n />\n );\n\n const renderEditableCell = (field: WellField<T>, col: WellColumn<T>, wellId: WellId, row: T) => {\n const fieldKey = col.field!;\n const value = row[fieldKey];\n const ariaLabel = `${field.label} for ${wellId}`;\n\n if (field.kind === \"select\") return renderSelectCellEditable(field, fieldKey, value, wellId, ariaLabel);\n if (field.kind === \"multiselect\") {\n const current = Array.isArray(value) ? (value as string[]) : [];\n return (\n <MultiSelectCell\n ariaLabel={ariaLabel}\n value={current}\n options={field.options ?? []}\n placeholder={field.placeholder}\n onChange={(next) => updateRow(wellId, { [fieldKey]: next.length === 0 ? undefined : next } as Partial<T>)}\n />\n );\n }\n if (field.kind === \"boolean\") return renderBooleanCellEditable(field, fieldKey, value, wellId, ariaLabel);\n return renderInputCellEditable(field, fieldKey, value, wellId, ariaLabel);\n };\n\n const renderReadonlyCell = (field: WellField<T> | undefined, value: unknown) => {\n if (field?.kind === \"select\") {\n const option = (field.options ?? []).find((opt) => opt.value === value);\n if (!option) {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n\n return (\n <Badge variant=\"secondary\">\n {option.swatch ? (\n <span\n className=\"size-2 rounded-sm border border-foreground/20\"\n style={{ backgroundColor: option.swatch }}\n aria-hidden\n />\n ) : null}\n {option.label}\n </Badge>\n );\n }\n\n if (field?.kind === \"multiselect\") {\n const arr = Array.isArray(value) ? (value as string[]) : [];\n if (arr.length === 0) {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n return (\n <div className=\"flex flex-wrap gap-1\">\n {arr.map((v) => {\n const opt = (field.options ?? []).find((o) => o.value === v);\n return (\n <Badge key={v} variant=\"secondary\">\n {opt?.swatch ? (\n <span\n className=\"size-2 rounded-sm border border-foreground/20\"\n style={{ backgroundColor: opt.swatch }}\n aria-hidden\n />\n ) : null}\n {opt?.label ?? v}\n </Badge>\n );\n })}\n </div>\n );\n }\n\n if (field?.kind === \"boolean\") {\n return value ? (\n <Check aria-label=\"Yes\" className=\"size-4 text-foreground\" />\n ) : (\n <span className=\"text-muted-foreground\">—</span>\n );\n }\n\n if (!hasFillValue(value)) {\n return <span className=\"text-muted-foreground\">—</span>;\n }\n\n return String(value);\n };\n\n const renderCell = (col: WellColumn<T>, wellId: WellId, row: T) => {\n if (col.render) {\n return col.render({\n row,\n wellId,\n update: (patch) => updateRow(wellId, patch),\n });\n }\n if (!col.field) return null;\n\n const field = fieldByKey.get(col.field);\n const value = row[col.field];\n\n if (field?.editableInTable && field.kind !== \"custom\") {\n return renderEditableCell(field, col, wellId, row);\n }\n\n return renderReadonlyCell(field, value);\n };\n\n const renderColumnHeader = (col: WellColumn<T>) => {\n const matchingField = col.field ? fieldByKey.get(col.field) : undefined;\n const icon = col.icon ?? matchingField?.icon;\n const fillPlan = enableFillDown ? getFillDownPlan(col) : null;\n const canFillDown = !!fillPlan && fillPlan.targets.length > 0;\n const fillHint =\n selection && selection.size > 0\n ? `Fill selected ${col.header} cells from the first selected value`\n : `Fill visible ${col.header} cells downward from the first value`;\n return (\n <span className=\"flex min-w-0 items-center justify-between gap-2\">\n <span className=\"inline-flex min-w-0 items-center gap-1.5\">\n {icon ? <span className=\"inline-flex text-muted-foreground [&_svg]:size-3.5\">{icon}</span> : null}\n <span className=\"truncate\">{col.header}</span>\n </span>\n {enableFillDown && col.field ? (\n <Tooltip>\n <TooltipTrigger asChild>\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n className=\"-mr-1 text-muted-foreground hover:text-foreground\"\n disabled={!canFillDown}\n aria-label={`Fill down ${col.header}`}\n onClick={(e) => {\n e.preventDefault();\n e.stopPropagation();\n fillColumnDown(col);\n }}\n >\n <ArrowDownToLine />\n </Button>\n </TooltipTrigger>\n <TooltipContent>{fillHint}</TooltipContent>\n </Tooltip>\n ) : null}\n </span>\n );\n };\n\n const groupableColumns = React.useMemo(() => columns.filter((col) => !!col.field), [columns]);\n const activeGroupField = groupable && groupByField ? groupByField : \"\";\n const grouped = React.useMemo(\n () => (activeGroupField ? groupRowsBy(rows, activeGroupField) : null),\n [activeGroupField, rows],\n );\n\n const totalRows = rows.length;\n const lastPage = Math.max(0, Math.ceil(totalRows / pageSize) - 1);\n const selSize = selection?.size ?? 0;\n const totalColSpan = columns.length + 1 + (onSelectionChange ? 1 : 0);\n\n const renderDataRow = (id: WellId, row: T) => {\n const isSelected = selection?.has(id);\n const extra = rowProps?.({ wellId: id, row, isSelected: !!isSelected });\n return (\n <TableRow key={id} {...extra}>\n {onSelectionChange ? (\n <TableCell className=\"w-10\">\n <Checkbox checked={!!isSelected} onCheckedChange={() => toggleSelect(id)} aria-label={`Select ${id}`} />\n </TableCell>\n ) : null}\n <TableCell className=\"font-semibold\">{id}</TableCell>\n {columns.map((col) => (\n <TableCell\n key={col.id ?? col.field ?? col.header}\n style={col.minWidth ? { minWidth: col.minWidth } : undefined}\n >\n {renderCell(col, id, row)}\n </TableCell>\n ))}\n </TableRow>\n );\n };\n\n const toggleGroup = (key: string) => {\n setCollapsedGroups((prev) => {\n const next = new Set(prev);\n if (next.has(key)) next.delete(key);\n else next.add(key);\n return next;\n });\n };\n\n const groupHeaderLabel = (() => {\n if (!activeGroupField) return \"\";\n const col = columns.find((c) => c.field === activeGroupField);\n return col?.header ?? activeGroupField;\n })();\n\n return (\n <div data-slot=\"well-manifest-table\" className={cn(\"flex flex-col gap-2\", className)}>\n <div className=\"flex flex-wrap items-center gap-2\">\n <Button variant=\"outline\" size=\"sm\" onClick={() => setShowAll((v) => !v)}>\n {showAll ? \"Hide empty wells\" : \"Show all wells\"}\n </Button>\n {filterable ? (\n <ManifestFilterPopover columns={resolvedFilterColumns} filters={filters} onFiltersChange={setFilters} />\n ) : null}\n {groupable ? (\n <div className=\"inline-flex items-center gap-1.5\">\n <Layers aria-hidden className=\"size-3.5 text-muted-foreground\" />\n <Select value={groupByField || \"__none\"} onValueChange={(v) => setGroupByField(v === \"__none\" ? \"\" : v)}>\n <SelectTrigger size=\"sm\" className=\"h-7 min-w-40\" aria-label=\"Group by\">\n <SelectValue placeholder=\"Group by…\" />\n </SelectTrigger>\n <SelectContent>\n <SelectItem value=\"__none\">No grouping</SelectItem>\n {groupableColumns.map((col) => (\n <SelectItem key={col.id ?? col.field} value={col.field ?? \"\"}>\n {col.header}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n </div>\n ) : null}\n <span className=\"text-xs text-muted-foreground\">\n {totalRows} rows · {selSize} selected\n </span>\n </div>\n\n <TooltipProvider>\n <Table data-density=\"default\">\n <TableHeader>\n <TableRow>\n {onSelectionChange ? (\n <TableHead className=\"w-10 text-center\">\n <span className=\"inline-flex items-center justify-center text-muted-foreground [&_svg]:size-3.5\">\n <Check aria-hidden />\n <span className=\"sr-only\">Selected</span>\n </span>\n </TableHead>\n ) : null}\n <TableHead style={{ minWidth: 60 }}>Well</TableHead>\n {columns.map((col) => (\n <TableHead\n key={col.id ?? col.field ?? col.header}\n style={col.minWidth ? { minWidth: col.minWidth } : undefined}\n >\n {renderColumnHeader(col)}\n </TableHead>\n ))}\n </TableRow>\n </TableHeader>\n <TableBody>\n {grouped\n ? grouped.map((group) => {\n const isCollapsed = collapsedGroups.has(group.key);\n return (\n <React.Fragment key={group.key}>\n <TableRow\n className=\"cursor-pointer bg-muted/40\"\n onClick={() => toggleGroup(group.key)}\n onKeyDown={(e) => {\n if (e.key === \"Enter\" || e.key === \" \") {\n e.preventDefault();\n toggleGroup(group.key);\n }\n }}\n role=\"button\"\n tabIndex={0}\n aria-expanded={!isCollapsed}\n >\n <TableCell colSpan={totalColSpan} className=\"py-1.5\">\n <div className=\"flex items-center gap-2 text-xs font-medium\">\n {isCollapsed ? (\n <ChevronRight aria-hidden className=\"size-3.5 text-muted-foreground\" />\n ) : (\n <ChevronDown aria-hidden className=\"size-3.5 text-muted-foreground\" />\n )}\n <span>\n {groupHeaderLabel}: {group.key}\n </span>\n <span className=\"text-muted-foreground\">\n ({group.rows.length} {group.rows.length === 1 ? \"row\" : \"rows\"})\n </span>\n </div>\n </TableCell>\n </TableRow>\n {isCollapsed ? null : group.rows.map(({ id, row }) => renderDataRow(id, row))}\n </React.Fragment>\n );\n })\n : pagedRows.map(({ id, row }) => renderDataRow(id, row))}\n {(grouped ? grouped.length === 0 : pagedRows.length === 0) ? (\n <TableRow>\n <TableCell colSpan={totalColSpan} className=\"text-xs text-muted-foreground\">\n No rows. Paint wells on the plate.\n </TableCell>\n </TableRow>\n ) : null}\n </TableBody>\n </Table>\n </TooltipProvider>\n\n {grouped ? null : (\n <div className=\"flex items-center justify-end gap-3 text-xs text-muted-foreground\">\n <span className=\"text-muted-foreground\">Rows per page</span>\n <Select\n value={String(pageSize)}\n onValueChange={(v) => {\n setPageSize(parseInt(v, 10));\n setPage(0);\n }}\n >\n <SelectTrigger size=\"sm\" className=\"h-7 w-18\" aria-label=\"Rows per page\">\n <SelectValue />\n </SelectTrigger>\n <SelectContent>\n {pageSizeOptions.map((s) => (\n <SelectItem key={s} value={String(s)}>\n {s}\n </SelectItem>\n ))}\n </SelectContent>\n </Select>\n <span>\n {totalRows === 0\n ? \"0 of 0\"\n : `${page * pageSize + 1}–${Math.min((page + 1) * pageSize, totalRows)} of ${totalRows}`}\n </span>\n <Button variant=\"outline\" size=\"sm\" disabled={page === 0} onClick={() => setPage((p) => Math.max(0, p - 1))}>\n Prev\n </Button>\n <Button\n variant=\"outline\"\n size=\"sm\"\n disabled={page >= lastPage}\n onClick={() => setPage((p) => Math.min(lastPage, p + 1))}\n >\n Next\n </Button>\n </div>\n )}\n </div>\n );\n}\n"],"names":["MultiSelectCell","ariaLabel","value","options","placeholder","onChange","anchorRef","useComboboxAnchor","labelByValue","React","m","o","jsxs","Combobox","ComboboxChips","cn","CELL_EDITOR_CLASS","jsx","ComboboxValue","items","item","ComboboxChip","ComboboxChipsInput","ComboboxContent","ComboboxEmpty","ComboboxList","ComboboxItem","PAGE_SIZE_SMALL","PAGE_SIZE_MEDIUM","PAGE_SIZE_LARGE","DEFAULT_PAGE_SIZE","DEFAULT_PAGE_SIZE_OPTIONS","hasFillValue","INPUT_TYPE_BY_KIND","resolveInputType","kind","parseInputValue","raw","num","groupRowsBy","rows","field","map","entry","key","existing","inferFilterColumns","columns","col","WellManifestTable","values","fields","selection","onSelectionChange","emptyEntry","isPopulated","initialPageSize","pageSizeOptions","enableFillDown","rowProps","filterable","filterColumns","groupable","className","showAll","setShowAll","page","setPage","pageSize","setPageSize","filters","setFilters","groupByField","setGroupByField","collapsedGroups","setCollapsedGroups","fieldByKey","f","resolvedFilterColumns","arr","id","row","filtered","r","record","condition","cellRaw","cellValue","applyFilterCondition","have","p","a","b","pagedRows","updateRow","wellId","patch","next","cur","toggleSelect","s","getFillDownPlan","selectionActive","sourceRows","sourceIndex","source","targets","fillColumnDown","plan","renderSelectCellEditable","fieldKey","Select","v","SelectTrigger","SelectValue","SelectContent","opt","SelectItem","renderBooleanCellEditable","checked","Switch","c","Checkbox","renderInputCellEditable","Input","e","renderEditableCell","current","renderReadonlyCell","option","Badge","Check","renderCell","renderColumnHeader","matchingField","icon","fillPlan","canFillDown","fillHint","Tooltip","TooltipTrigger","Button","ArrowDownToLine","TooltipContent","groupableColumns","activeGroupField","grouped","totalRows","lastPage","selSize","totalColSpan","renderDataRow","isSelected","extra","TableRow","TableCell","toggleGroup","prev","groupHeaderLabel","ManifestFilterPopover","Layers","TooltipProvider","Table","TableHeader","TableHead","TableBody","group","isCollapsed","ChevronRight","ChevronDown"],"mappings":"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"}