@tetrascience-npm/tetrascience-react-ui 1.0.0-beta.156.1 → 1.0.0-beta.158.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.
- package/README.md +113 -0
- package/dist/components/composed/DataAppShell/RightPanel.cjs +1 -1
- package/dist/components/composed/DataAppShell/RightPanel.cjs.map +1 -1
- package/dist/components/composed/DataAppShell/RightPanel.d.ts +11 -1
- package/dist/components/composed/DataAppShell/RightPanel.js +128 -126
- package/dist/components/composed/DataAppShell/RightPanel.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.d.ts +5 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +32 -30
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.d.ts +269 -13
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.js +392 -310
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.d.ts +5 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.js +19 -15
- package/dist/components/composed/PlateMapEditor/PlateMapForm.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.d.ts +12 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +69 -63
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.d.ts +13 -4
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.js +38 -29
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.d.ts +6 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +490 -275
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.d.ts +8 -2
- package/dist/components/composed/PlateMapEditor/WellLegend.js +8 -7
- package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.d.ts +6 -2
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js +288 -256
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.d.ts +5 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.js +61 -66
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellQuickPaint.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/WellQuickPaint.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellQuickPaint.d.ts +23 -0
- package/dist/components/composed/PlateMapEditor/WellQuickPaint.js +75 -0
- package/dist/components/composed/PlateMapEditor/WellQuickPaint.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/index.d.ts +6 -2
- package/dist/components/composed/PlateMapEditor/types.d.ts +65 -0
- package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.d.ts +109 -0
- package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.js +246 -0
- package/dist/components/composed/PlateMapEditor/usePlateMapEditorState.js.map +1 -0
- package/dist/composed/PlateMapEditor.cjs +1 -1
- package/dist/composed/PlateMapEditor.js +48 -42
- package/dist/composed/PlateMapEditor.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +701 -695
- package/dist/index.js.map +1 -1
- package/dist/index.scoped.css +1 -1
- package/dist/index.tailwind.css +1 -1
- package/package.json +1 -1
|
@@ -1,59 +1,63 @@
|
|
|
1
|
-
import { jsxs as o, jsx as l, Fragment as
|
|
2
|
-
import * as
|
|
3
|
-
import { PlatePaintGrid as
|
|
4
|
-
import { allPositions as
|
|
5
|
-
import { Separator as
|
|
1
|
+
import { jsxs as o, jsx as l, Fragment as $ } from "react/jsx-runtime";
|
|
2
|
+
import * as ee from "react";
|
|
3
|
+
import { PlatePaintGrid as te } from "./PlatePaintGrid.js";
|
|
4
|
+
import { allPositions as ne, resolveDimensions as le } from "./wellGrid.js";
|
|
5
|
+
import { Separator as re } from "../../../ui/separator.js";
|
|
6
6
|
import { cn as y } from "../../../lib/utils.js";
|
|
7
|
-
function
|
|
8
|
-
return
|
|
7
|
+
function oe(a, c) {
|
|
8
|
+
return c.map((n) => {
|
|
9
9
|
const t = a[n.key];
|
|
10
10
|
if (t == null || t === "") return null;
|
|
11
11
|
if (n.kind === "select")
|
|
12
12
|
return (n.options ?? []).find((r) => r.value === t)?.label ?? String(t);
|
|
13
13
|
if (n.kind === "multiselect") {
|
|
14
14
|
const i = Array.isArray(t) ? t : [];
|
|
15
|
-
return i.length === 0 ? null : i.map((r) => (n.options ?? []).find((
|
|
15
|
+
return i.length === 0 ? null : i.map((r) => (n.options ?? []).find((d) => d.value === r)?.label ?? r).join(", ");
|
|
16
16
|
}
|
|
17
17
|
return n.kind === "boolean" ? t ? n.label : null : String(t);
|
|
18
18
|
}).filter(Boolean);
|
|
19
19
|
}
|
|
20
|
-
function
|
|
20
|
+
function me({
|
|
21
21
|
format: a,
|
|
22
|
-
rows:
|
|
22
|
+
rows: c,
|
|
23
23
|
columns: n,
|
|
24
24
|
values: t,
|
|
25
25
|
selection: i,
|
|
26
26
|
onSelectionChange: r,
|
|
27
|
-
colorForWell:
|
|
27
|
+
colorForWell: d,
|
|
28
28
|
fields: f,
|
|
29
29
|
renderHoverSummary: N,
|
|
30
|
-
onHoveredWellChange:
|
|
30
|
+
onHoveredWellChange: w,
|
|
31
31
|
hoveredWellId: x,
|
|
32
|
+
banner: g,
|
|
32
33
|
toolbar: p,
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
34
|
+
footer: k,
|
|
35
|
+
hideSelectionControls: P = !1,
|
|
36
|
+
selectAllLabel: S = "Select all",
|
|
37
|
+
deselectAllLabel: C = "Deselect all",
|
|
38
|
+
emptyWellFillColor: j,
|
|
39
|
+
wellShape: A,
|
|
40
|
+
framed: H,
|
|
41
|
+
wrapWell: F,
|
|
42
|
+
quickPaint: D,
|
|
43
|
+
highlightedWellIds: G,
|
|
44
|
+
onWellDoubleClick: R,
|
|
45
|
+
selectionFillMode: z,
|
|
46
|
+
flashWellId: B,
|
|
47
|
+
flashWellKey: E,
|
|
48
|
+
cellSize: M,
|
|
49
|
+
autoScale: T,
|
|
50
|
+
minCellSize: q,
|
|
51
|
+
maxCellSize: I,
|
|
49
52
|
groups: m,
|
|
50
|
-
activeGroupId:
|
|
51
|
-
onGroupClick:
|
|
52
|
-
className:
|
|
53
|
+
activeGroupId: J,
|
|
54
|
+
onGroupClick: K,
|
|
55
|
+
className: L
|
|
53
56
|
}) {
|
|
54
|
-
const
|
|
55
|
-
return /* @__PURE__ */ o("div", { "data-slot": "plate-map-grid", className: y("flex flex-col gap-1.5",
|
|
56
|
-
|
|
57
|
+
const O = le(a, c, n), [Q, U] = ee.useState(null), v = x !== void 0, s = v ? x : Q, V = () => r(new Set(ne(O))), W = () => r(/* @__PURE__ */ new Set()), u = s ? t.get(s) : void 0, X = u && f ? oe(u, f) : [], Y = s ? N?.(u, s) ?? [s, ...X].join(" • ") : " ", h = !P, Z = !!p || h;
|
|
58
|
+
return /* @__PURE__ */ o("div", { "data-slot": "plate-map-grid", className: y("flex w-full min-w-0 flex-col gap-1.5", L), children: [
|
|
59
|
+
g,
|
|
60
|
+
Z ? /* @__PURE__ */ o("div", { className: "flex flex-wrap items-center justify-start gap-3", children: [
|
|
57
61
|
p,
|
|
58
62
|
h ? /* @__PURE__ */ o("div", { className: "flex items-center gap-2 text-xs", children: [
|
|
59
63
|
/* @__PURE__ */ l(
|
|
@@ -61,8 +65,8 @@ function ae({
|
|
|
61
65
|
{
|
|
62
66
|
type: "button",
|
|
63
67
|
className: "font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline",
|
|
64
|
-
onClick:
|
|
65
|
-
children:
|
|
68
|
+
onClick: V,
|
|
69
|
+
children: S
|
|
66
70
|
}
|
|
67
71
|
),
|
|
68
72
|
/* @__PURE__ */ l("span", { className: "text-muted-foreground/60", children: "·" }),
|
|
@@ -71,55 +75,56 @@ function ae({
|
|
|
71
75
|
{
|
|
72
76
|
type: "button",
|
|
73
77
|
className: "font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline",
|
|
74
|
-
onClick:
|
|
75
|
-
children:
|
|
78
|
+
onClick: W,
|
|
79
|
+
children: C
|
|
76
80
|
}
|
|
77
81
|
)
|
|
78
82
|
] }) : null
|
|
79
83
|
] }) : null,
|
|
80
|
-
/* @__PURE__ */ l("div", { className: "h-5 text-xs text-muted-foreground", children:
|
|
84
|
+
/* @__PURE__ */ l("div", { className: "h-5 truncate text-xs text-muted-foreground", children: Y }),
|
|
81
85
|
/* @__PURE__ */ l(
|
|
82
|
-
|
|
86
|
+
te,
|
|
83
87
|
{
|
|
84
88
|
format: a,
|
|
85
|
-
rows:
|
|
89
|
+
rows: c,
|
|
86
90
|
columns: n,
|
|
87
91
|
values: t,
|
|
88
92
|
selection: i,
|
|
89
93
|
onSelectionChange: r,
|
|
90
|
-
colorForWell:
|
|
91
|
-
emptyWellFillColor:
|
|
92
|
-
wellShape:
|
|
93
|
-
framed:
|
|
94
|
-
wrapWell:
|
|
95
|
-
|
|
94
|
+
colorForWell: d,
|
|
95
|
+
emptyWellFillColor: j,
|
|
96
|
+
wellShape: A,
|
|
97
|
+
framed: H,
|
|
98
|
+
wrapWell: F,
|
|
99
|
+
quickPaint: D,
|
|
100
|
+
highlightedWellIds: G,
|
|
96
101
|
onWellHover: (e) => {
|
|
97
|
-
v ||
|
|
102
|
+
v || U(e), w?.(e);
|
|
98
103
|
},
|
|
99
|
-
onWellDoubleClick:
|
|
100
|
-
selectionFillMode:
|
|
101
|
-
flashWellId:
|
|
102
|
-
flashWellKey:
|
|
103
|
-
cellSize:
|
|
104
|
-
autoScale:
|
|
105
|
-
minCellSize:
|
|
106
|
-
maxCellSize:
|
|
104
|
+
onWellDoubleClick: R,
|
|
105
|
+
selectionFillMode: z,
|
|
106
|
+
flashWellId: B,
|
|
107
|
+
flashWellKey: E,
|
|
108
|
+
cellSize: M,
|
|
109
|
+
autoScale: T,
|
|
110
|
+
minCellSize: q,
|
|
111
|
+
maxCellSize: I
|
|
107
112
|
}
|
|
108
113
|
),
|
|
109
|
-
m && m.length > 0 ? /* @__PURE__ */ o(
|
|
110
|
-
/* @__PURE__ */ l(
|
|
114
|
+
m && m.length > 0 ? /* @__PURE__ */ o($, { children: [
|
|
115
|
+
/* @__PURE__ */ l(re, { className: "mt-2" }),
|
|
111
116
|
/* @__PURE__ */ l("div", { className: "flex max-h-28 flex-wrap gap-3 overflow-y-auto pt-1", children: m.map((e) => {
|
|
112
|
-
const
|
|
117
|
+
const _ = e.id === J, b = e.count ?? e.wellIds?.length;
|
|
113
118
|
return /* @__PURE__ */ o(
|
|
114
119
|
"button",
|
|
115
120
|
{
|
|
116
121
|
type: "button",
|
|
117
122
|
disabled: e.disabled,
|
|
118
|
-
onClick: () =>
|
|
123
|
+
onClick: () => K?.(e),
|
|
119
124
|
className: y(
|
|
120
125
|
"flex w-16 flex-col items-center gap-1 rounded-md px-1 py-1 text-center text-xs transition-colors",
|
|
121
126
|
"text-muted-foreground hover:bg-accent/60",
|
|
122
|
-
|
|
127
|
+
_ && "bg-muted text-foreground ring-1 ring-primary/40",
|
|
123
128
|
e.disabled && "pointer-events-none opacity-50"
|
|
124
129
|
),
|
|
125
130
|
title: e.label,
|
|
@@ -145,10 +150,11 @@ function ae({
|
|
|
145
150
|
e.id
|
|
146
151
|
);
|
|
147
152
|
}) })
|
|
148
|
-
] }) : null
|
|
153
|
+
] }) : null,
|
|
154
|
+
k
|
|
149
155
|
] });
|
|
150
156
|
}
|
|
151
157
|
export {
|
|
152
|
-
|
|
158
|
+
me as PlateMapGrid
|
|
153
159
|
};
|
|
154
160
|
//# sourceMappingURL=PlateMapGrid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlateMapGrid.js","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapGrid.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { PlatePaintGrid } from \"./PlatePaintGrid\";\nimport { allPositions, resolveDimensions } from \"./wellGrid\";\n\nimport type { WellShape } from \"./PlatePaintGrid\";\nimport type { PlateFormat, PlateMapGroupOption, WellField, WellId, WellRecord } from \"./types\";\n\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\nfunction formatHoverFields<T extends WellRecord>(entry: T, fields: WellField<T>[]): string[] {\n return fields\n .map((f) => {\n const v = entry[f.key];\n if (v === undefined || v === null || v === \"\") return null;\n if (f.kind === \"select\") {\n const opt = (f.options ?? []).find((o) => o.value === v);\n return opt?.label ?? String(v);\n }\n if (f.kind === \"multiselect\") {\n const arr = Array.isArray(v) ? (v as string[]) : [];\n if (arr.length === 0) return null;\n return arr.map((item) => (f.options ?? []).find((o) => o.value === item)?.label ?? item).join(\", \");\n }\n if (f.kind === \"boolean\") {\n return v ? f.label : null;\n }\n return String(v);\n })\n .filter(Boolean) as string[];\n}\n\nexport interface PlateMapGridProps<T extends WellRecord = WellRecord> {\n format: PlateFormat;\n rows?: number;\n columns?: number;\n values: Map<WellId, T>;\n selection: Set<WellId>;\n onSelectionChange: (next: Set<WellId>) => void;\n /** Resolves the SVG fill color for a well. */\n colorForWell: (well: T | undefined, wellId: WellId) => string;\n /** Field schema used to build the default hover summary string. */\n fields?: WellField<T>[];\n /** Custom hover summary for the strip above the grid. */\n renderHoverSummary?: (well: T | undefined, wellId: WellId) => React.ReactNode;\n /** Fires whenever the currently hovered well changes (null on leave). */\n onHoveredWellChange?: (wellId: WellId | null) => void;\n /**\n * Controlled hovered well id. When provided, the panel reflects this value\n * instead of tracking hover internally — useful for syncing the hover\n * summary with external state (e.g. resetting it on a plate switch).\n */\n hoveredWellId?: WellId | null;\n /** Controls rendered to the left of the built-in select/deselect links. */\n toolbar?: React.ReactNode;\n /** Hide the built-in \"Select all\" / \"Deselect all\" links. */\n hideSelectionControls?: boolean;\n selectAllLabel?: string;\n deselectAllLabel?: string;\n /** Fill color for empty wells. Pass `null` to delegate empty wells to `colorForWell`. */\n emptyWellFillColor?: string | null;\n /** Well shape forwarded to `PlatePaintGrid`. Defaults to `\"rect\"`. */\n wellShape?: WellShape;\n /** When true, wraps the grid in a card-like plate frame (rounded + border + soft shadow). */\n framed?: boolean;\n /** Render-prop that places a node inside each absolute-positioned well cell. */\n wrapWell?: (wellId: WellId, cellSize: number) => React.ReactNode;\n /** Wells to highlight (e.g. when hovering a legend item externally). */\n highlightedWellIds?: ReadonlySet<WellId>;\n onWellDoubleClick?: (wellId: WellId) => void;\n selectionFillMode?: \"selection\" | \"well\";\n flashWellId?: WellId;\n flashWellKey?: number;\n /** Fixed well size. When unset, the grid grows with the available width. */\n cellSize?: number;\n autoScale?: boolean;\n minCellSize?: number;\n maxCellSize?: number;\n /** Optional grouped well shortcuts rendered under the grid. */\n groups?: PlateMapGroupOption[];\n activeGroupId?: string;\n onGroupClick?: (group: PlateMapGroupOption) => void;\n className?: string;\n}\n\n/**\n * Card-agnostic plate grid panel. Renders the selection toolbar, hover\n * summary, the interactive `PlatePaintGrid`, and optional group shortcuts —\n * and owns the ephemeral hover state internally. The plate title, plate\n * selector, and actions menu are intentionally NOT part of this panel; compose\n * `PlateMapPlateSelector` and `PlateMapActionsMenu` around it for full layout\n * freedom.\n */\nexport function PlateMapGrid<T extends WellRecord = WellRecord>({\n format,\n rows,\n columns,\n values,\n selection,\n onSelectionChange,\n colorForWell,\n fields,\n renderHoverSummary,\n onHoveredWellChange,\n hoveredWellId,\n toolbar,\n hideSelectionControls = false,\n selectAllLabel = \"Select all\",\n deselectAllLabel = \"Deselect all\",\n emptyWellFillColor,\n wellShape,\n framed,\n wrapWell,\n highlightedWellIds,\n onWellDoubleClick,\n selectionFillMode,\n flashWellId,\n flashWellKey,\n cellSize,\n autoScale,\n minCellSize,\n maxCellSize,\n groups,\n activeGroupId,\n onGroupClick,\n className,\n}: PlateMapGridProps<T>) {\n const dims = resolveDimensions(format, rows, columns);\n const [internalHoverPos, setInternalHoverPos] = React.useState<WellId | null>(null);\n const isHoverControlled = hoveredWellId !== undefined;\n const hoverPos = isHoverControlled ? hoveredWellId : internalHoverPos;\n\n const selectAll = () => onSelectionChange(new Set(allPositions(dims)));\n const deselectAll = () => onSelectionChange(new Set());\n\n const hoverEntry = hoverPos ? values.get(hoverPos) : undefined;\n const hoverFields = hoverEntry && fields ? formatHoverFields(hoverEntry, fields) : [];\n const hoverSummary = hoverPos\n ? (renderHoverSummary?.(hoverEntry, hoverPos) ?? [hoverPos, ...hoverFields].join(\" • \"))\n : \" \";\n\n const showSelectionControls = !hideSelectionControls;\n const showToolbarRow = !!toolbar || showSelectionControls;\n\n return (\n <div data-slot=\"plate-map-grid\" className={cn(\"flex flex-col gap-1.5\", className)}>\n {showToolbarRow ? (\n <div className=\"flex flex-wrap items-center justify-start gap-3\">\n {toolbar}\n {showSelectionControls ? (\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n type=\"button\"\n className=\"font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline\"\n onClick={selectAll}\n >\n {selectAllLabel}\n </button>\n <span className=\"text-muted-foreground/60\">·</span>\n <button\n type=\"button\"\n className=\"font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline\"\n onClick={deselectAll}\n >\n {deselectAllLabel}\n </button>\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"h-5 text-xs text-muted-foreground\">{hoverSummary}</div>\n <PlatePaintGrid\n format={format}\n rows={rows}\n columns={columns}\n values={values}\n selection={selection}\n onSelectionChange={onSelectionChange}\n colorForWell={colorForWell}\n emptyWellFillColor={emptyWellFillColor}\n wellShape={wellShape}\n framed={framed}\n wrapWell={wrapWell}\n highlightedWellIds={highlightedWellIds}\n onWellHover={(wellId) => {\n if (!isHoverControlled) setInternalHoverPos(wellId);\n onHoveredWellChange?.(wellId);\n }}\n onWellDoubleClick={onWellDoubleClick}\n selectionFillMode={selectionFillMode}\n flashWellId={flashWellId}\n flashWellKey={flashWellKey}\n cellSize={cellSize}\n autoScale={autoScale}\n minCellSize={minCellSize}\n maxCellSize={maxCellSize}\n />\n {groups && groups.length > 0 ? (\n <>\n <Separator className=\"mt-2\" />\n <div className=\"flex max-h-28 flex-wrap gap-3 overflow-y-auto pt-1\">\n {groups.map((group) => {\n const isActive = group.id === activeGroupId;\n const count = group.count ?? group.wellIds?.length;\n return (\n <button\n key={group.id}\n type=\"button\"\n disabled={group.disabled}\n onClick={() => onGroupClick?.(group)}\n className={cn(\n \"flex w-16 flex-col items-center gap-1 rounded-md px-1 py-1 text-center text-xs transition-colors\",\n \"text-muted-foreground hover:bg-accent/60\",\n isActive && \"bg-muted text-foreground ring-1 ring-primary/40\",\n group.disabled && \"pointer-events-none opacity-50\",\n )}\n title={group.label}\n >\n <span\n className=\"size-7 rounded-full border\"\n style={{\n backgroundColor: group.color,\n borderColor: group.borderColor,\n }}\n aria-hidden\n />\n <span className=\"w-full truncate text-foreground\">{group.label}</span>\n {count === undefined ? null : (\n <span className=\"text-[0.7rem] leading-none text-muted-foreground\">{count} wells</span>\n )}\n </button>\n );\n })}\n </div>\n </>\n ) : null}\n </div>\n );\n}\n"],"names":["formatHoverFields","entry","fields","f","v","o","arr","item","PlateMapGrid","format","rows","columns","values","selection","onSelectionChange","colorForWell","renderHoverSummary","onHoveredWellChange","hoveredWellId","toolbar","hideSelectionControls","selectAllLabel","deselectAllLabel","emptyWellFillColor","wellShape","framed","wrapWell","highlightedWellIds","onWellDoubleClick","selectionFillMode","flashWellId","flashWellKey","cellSize","autoScale","minCellSize","maxCellSize","groups","activeGroupId","onGroupClick","className","dims","resolveDimensions","internalHoverPos","setInternalHoverPos","React","isHoverControlled","hoverPos","selectAll","allPositions","deselectAll","hoverEntry","hoverFields","hoverSummary","showSelectionControls","showToolbarRow","jsxs","cn","jsx","PlatePaintGrid","wellId","Fragment","Separator","group","isActive","count"],"mappings":";;;;;;AAWA,SAASA,GAAwCC,GAAUC,GAAkC;AAC3F,SAAOA,EACJ,IAAI,CAACC,MAAM;AACV,UAAMC,IAAIH,EAAME,EAAE,GAAG;AACrB,QAAuBC,KAAM,QAAQA,MAAM,GAAI,QAAO;AACtD,QAAID,EAAE,SAAS;AAEb,cADaA,EAAE,WAAW,CAAA,GAAI,KAAK,CAACE,MAAMA,EAAE,UAAUD,CAAC,GAC3C,SAAS,OAAOA,CAAC;AAE/B,QAAID,EAAE,SAAS,eAAe;AAC5B,YAAMG,IAAM,MAAM,QAAQF,CAAC,IAAKA,IAAiB,CAAA;AACjD,aAAIE,EAAI,WAAW,IAAU,OACtBA,EAAI,IAAI,CAACC,OAAUJ,EAAE,WAAW,CAAA,GAAI,KAAK,CAACE,MAAMA,EAAE,UAAUE,CAAI,GAAG,SAASA,CAAI,EAAE,KAAK,IAAI;AAAA,IACpG;AACA,WAAIJ,EAAE,SAAS,YACNC,IAAID,EAAE,QAAQ,OAEhB,OAAOC,CAAC;AAAA,EACjB,CAAC,EACA,OAAO,OAAO;AACnB;AA+DO,SAASI,GAAgD;AAAA,EAC9D,QAAAC;AAAA,EACA,MAAAC;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,cAAAC;AAAA,EACA,QAAAb;AAAA,EACA,oBAAAc;AAAA,EACA,qBAAAC;AAAA,EACA,eAAAC;AAAA,EACA,SAAAC;AAAA,EACA,uBAAAC,IAAwB;AAAA,EACxB,gBAAAC,IAAiB;AAAA,EACjB,kBAAAC,IAAmB;AAAA,EACnB,oBAAAC;AAAA,EACA,WAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,oBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,aAAAC;AAAA,EACA,cAAAC;AAAA,EACA,UAAAC;AAAA,EACA,WAAAC;AAAA,EACA,aAAAC;AAAA,EACA,aAAAC;AAAA,EACA,QAAAC;AAAA,EACA,eAAAC;AAAA,EACA,cAAAC;AAAA,EACA,WAAAC;AACF,GAAyB;AACvB,QAAMC,IAAOC,GAAkBhC,GAAQC,GAAMC,CAAO,GAC9C,CAAC+B,GAAkBC,CAAmB,IAAIC,EAAM,SAAwB,IAAI,GAC5EC,IAAoB3B,MAAkB,QACtC4B,IAAWD,IAAoB3B,IAAgBwB,GAE/CK,IAAY,MAAMjC,EAAkB,IAAI,IAAIkC,EAAaR,CAAI,CAAC,CAAC,GAC/DS,IAAc,MAAMnC,EAAkB,oBAAI,KAAK,GAE/CoC,IAAaJ,IAAWlC,EAAO,IAAIkC,CAAQ,IAAI,QAC/CK,IAAcD,KAAchD,IAASF,GAAkBkD,GAAYhD,CAAM,IAAI,CAAA,GAC7EkD,IAAeN,IAChB9B,IAAqBkC,GAAYJ,CAAQ,KAAK,CAACA,GAAU,GAAGK,CAAW,EAAE,KAAK,KAAK,IACpF,KAEEE,IAAwB,CAACjC,GACzBkC,IAAiB,CAAC,CAACnC,KAAWkC;AAEpC,SACE,gBAAAE,EAAC,SAAI,aAAU,kBAAiB,WAAWC,EAAG,yBAAyBjB,CAAS,GAC7E,UAAA;AAAA,IAAAe,IACC,gBAAAC,EAAC,OAAA,EAAI,WAAU,mDACZ,UAAA;AAAA,MAAApC;AAAA,MACAkC,IACC,gBAAAE,EAAC,OAAA,EAAI,WAAU,mCACb,UAAA;AAAA,QAAA,gBAAAE;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAASV;AAAA,YAER,UAAA1B;AAAA,UAAA;AAAA,QAAA;AAAA,QAEH,gBAAAoC,EAAC,QAAA,EAAK,WAAU,4BAA2B,UAAA,KAAC;AAAA,QAC5C,gBAAAA;AAAA,UAAC;AAAA,UAAA;AAAA,YACC,MAAK;AAAA,YACL,WAAU;AAAA,YACV,SAASR;AAAA,YAER,UAAA3B;AAAA,UAAA;AAAA,QAAA;AAAA,MACH,EAAA,CACF,IACE;AAAA,IAAA,EAAA,CACN,IACE;AAAA,IACJ,gBAAAmC,EAAC,OAAA,EAAI,WAAU,qCAAqC,UAAAL,GAAa;AAAA,IACjE,gBAAAK;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,QAAAjD;AAAA,QACA,MAAAC;AAAA,QACA,SAAAC;AAAA,QACA,QAAAC;AAAA,QACA,WAAAC;AAAA,QACA,mBAAAC;AAAA,QACA,cAAAC;AAAA,QACA,oBAAAQ;AAAA,QACA,WAAAC;AAAA,QACA,QAAAC;AAAA,QACA,UAAAC;AAAA,QACA,oBAAAC;AAAA,QACA,aAAa,CAACgC,MAAW;AACvB,UAAKd,KAAmBF,EAAoBgB,CAAM,GAClD1C,IAAsB0C,CAAM;AAAA,QAC9B;AAAA,QACA,mBAAA/B;AAAA,QACA,mBAAAC;AAAA,QACA,aAAAC;AAAA,QACA,cAAAC;AAAA,QACA,UAAAC;AAAA,QACA,WAAAC;AAAA,QACA,aAAAC;AAAA,QACA,aAAAC;AAAA,MAAA;AAAA,IAAA;AAAA,IAEDC,KAAUA,EAAO,SAAS,IACzB,gBAAAmB,EAAAK,GAAA,EACE,UAAA;AAAA,MAAA,gBAAAH,EAACI,IAAA,EAAU,WAAU,OAAA,CAAO;AAAA,wBAC3B,OAAA,EAAI,WAAU,sDACZ,UAAAzB,EAAO,IAAI,CAAC0B,MAAU;AACrB,cAAMC,IAAWD,EAAM,OAAOzB,GACxB2B,IAAQF,EAAM,SAASA,EAAM,SAAS;AAC5C,eACE,gBAAAP;AAAA,UAAC;AAAA,UAAA;AAAA,YAEC,MAAK;AAAA,YACL,UAAUO,EAAM;AAAA,YAChB,SAAS,MAAMxB,IAAewB,CAAK;AAAA,YACnC,WAAWN;AAAA,cACT;AAAA,cACA;AAAA,cACAO,KAAY;AAAA,cACZD,EAAM,YAAY;AAAA,YAAA;AAAA,YAEpB,OAAOA,EAAM;AAAA,YAEb,UAAA;AAAA,cAAA,gBAAAL;AAAA,gBAAC;AAAA,gBAAA;AAAA,kBACC,WAAU;AAAA,kBACV,OAAO;AAAA,oBACL,iBAAiBK,EAAM;AAAA,oBACvB,aAAaA,EAAM;AAAA,kBAAA;AAAA,kBAErB,eAAW;AAAA,gBAAA;AAAA,cAAA;AAAA,cAEb,gBAAAL,EAAC,QAAA,EAAK,WAAU,mCAAmC,YAAM,OAAM;AAAA,cAC9DO,MAAU,SAAY,OACrB,gBAAAT,EAAC,QAAA,EAAK,WAAU,oDAAoD,UAAA;AAAA,gBAAAS;AAAA,gBAAM;AAAA,cAAA,EAAA,CAAM;AAAA,YAAA;AAAA,UAAA;AAAA,UAtB7EF,EAAM;AAAA,QAAA;AAAA,MA0BjB,CAAC,EAAA,CACH;AAAA,IAAA,EAAA,CACF,IACE;AAAA,EAAA,GACN;AAEJ;"}
|
|
1
|
+
{"version":3,"file":"PlateMapGrid.js","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapGrid.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { PlatePaintGrid } from \"./PlatePaintGrid\";\nimport { allPositions, resolveDimensions } from \"./wellGrid\";\n\nimport type { WellShape } from \"./PlatePaintGrid\";\nimport type { PlateFormat, PlateMapGroupOption, WellField, WellId, WellRecord } from \"./types\";\n\nimport { Separator } from \"@/components/ui/separator\";\nimport { cn } from \"@/lib/utils\";\n\nfunction formatHoverFields<T extends WellRecord>(entry: T, fields: WellField<T>[]): string[] {\n return fields\n .map((f) => {\n const v = entry[f.key];\n if (v === undefined || v === null || v === \"\") return null;\n if (f.kind === \"select\") {\n const opt = (f.options ?? []).find((o) => o.value === v);\n return opt?.label ?? String(v);\n }\n if (f.kind === \"multiselect\") {\n const arr = Array.isArray(v) ? (v as string[]) : [];\n if (arr.length === 0) return null;\n return arr.map((item) => (f.options ?? []).find((o) => o.value === item)?.label ?? item).join(\", \");\n }\n if (f.kind === \"boolean\") {\n return v ? f.label : null;\n }\n return String(v);\n })\n .filter(Boolean) as string[];\n}\n\nexport interface PlateMapGridProps<T extends WellRecord = WellRecord> {\n format: PlateFormat;\n rows?: number;\n columns?: number;\n values: Map<WellId, T>;\n selection: Set<WellId>;\n onSelectionChange: (next: Set<WellId>) => void;\n /** Resolves the SVG fill color for a well. */\n colorForWell: (well: T | undefined, wellId: WellId) => string;\n /** Field schema used to build the default hover summary string. */\n fields?: WellField<T>[];\n /** Custom hover summary for the strip above the grid. */\n renderHoverSummary?: (well: T | undefined, wellId: WellId) => React.ReactNode;\n /** Fires whenever the currently hovered well changes (null on leave). */\n onHoveredWellChange?: (wellId: WellId | null) => void;\n /**\n * Controlled hovered well id. When provided, the panel reflects this value\n * instead of tracking hover internally — useful for syncing the hover\n * summary with external state (e.g. resetting it on a plate switch).\n */\n hoveredWellId?: WellId | null;\n /** Slot rendered above the toolbar row, inside the grid panel. */\n banner?: React.ReactNode;\n /** Controls rendered to the left of the built-in select/deselect links. */\n toolbar?: React.ReactNode;\n /** Slot rendered below the grid (and below any group shortcuts). */\n footer?: React.ReactNode;\n /** Hide the built-in \"Select all\" / \"Deselect all\" links. */\n hideSelectionControls?: boolean;\n selectAllLabel?: string;\n deselectAllLabel?: string;\n /** Fill color for empty wells. Pass `null` to delegate empty wells to `colorForWell`. */\n emptyWellFillColor?: string | null;\n /** Well shape forwarded to `PlatePaintGrid`. Defaults to `\"rect\"`. */\n wellShape?: WellShape;\n /** When true, wraps the grid in a card-like plate frame (rounded + border + soft shadow). */\n framed?: boolean;\n /** Render-prop that places a node inside each absolute-positioned well cell. */\n wrapWell?: (wellId: WellId, cellSize: number) => React.ReactNode;\n /** Swatch strip anchored above the selection for one-click painting. */\n quickPaint?: React.ReactNode;\n /** Wells to highlight (e.g. when hovering a legend item externally). */\n highlightedWellIds?: ReadonlySet<WellId>;\n onWellDoubleClick?: (wellId: WellId) => void;\n /**\n * How a selected well is filled. `\"well\"` (default) keeps the well's own\n * colour and shows selection via the ring, so an applied edit is visible\n * immediately. `\"selection\"` replaces the fill with the selection tint.\n */\n selectionFillMode?: \"selection\" | \"well\";\n flashWellId?: WellId;\n flashWellKey?: number;\n /** Fixed well size. When unset, the grid grows with the available width. */\n cellSize?: number;\n autoScale?: boolean;\n minCellSize?: number;\n maxCellSize?: number;\n /** Optional grouped well shortcuts rendered under the grid. */\n groups?: PlateMapGroupOption[];\n activeGroupId?: string;\n onGroupClick?: (group: PlateMapGroupOption) => void;\n className?: string;\n}\n\n/**\n * Card-agnostic plate grid panel. Renders the selection toolbar, hover\n * summary, the interactive `PlatePaintGrid`, and optional group shortcuts —\n * and owns the ephemeral hover state internally. The plate title, plate\n * selector, and actions menu are intentionally NOT part of this panel; compose\n * `PlateMapPlateSelector` and `PlateMapActionsMenu` around it for full layout\n * freedom.\n */\nexport function PlateMapGrid<T extends WellRecord = WellRecord>({\n format,\n rows,\n columns,\n values,\n selection,\n onSelectionChange,\n colorForWell,\n fields,\n renderHoverSummary,\n onHoveredWellChange,\n hoveredWellId,\n banner,\n toolbar,\n footer,\n hideSelectionControls = false,\n selectAllLabel = \"Select all\",\n deselectAllLabel = \"Deselect all\",\n emptyWellFillColor,\n wellShape,\n framed,\n wrapWell,\n quickPaint,\n highlightedWellIds,\n onWellDoubleClick,\n selectionFillMode,\n flashWellId,\n flashWellKey,\n cellSize,\n autoScale,\n minCellSize,\n maxCellSize,\n groups,\n activeGroupId,\n onGroupClick,\n className,\n}: PlateMapGridProps<T>) {\n const dims = resolveDimensions(format, rows, columns);\n const [internalHoverPos, setInternalHoverPos] = React.useState<WellId | null>(null);\n const isHoverControlled = hoveredWellId !== undefined;\n const hoverPos = isHoverControlled ? hoveredWellId : internalHoverPos;\n\n const selectAll = () => onSelectionChange(new Set(allPositions(dims)));\n const deselectAll = () => onSelectionChange(new Set());\n\n const hoverEntry = hoverPos ? values.get(hoverPos) : undefined;\n const hoverFields = hoverEntry && fields ? formatHoverFields(hoverEntry, fields) : [];\n const hoverSummary = hoverPos\n ? (renderHoverSummary?.(hoverEntry, hoverPos) ?? [hoverPos, ...hoverFields].join(\" • \"))\n : \" \";\n\n const showSelectionControls = !hideSelectionControls;\n const showToolbarRow = !!toolbar || showSelectionControls;\n\n return (\n <div data-slot=\"plate-map-grid\" className={cn(\"flex w-full min-w-0 flex-col gap-1.5\", className)}>\n {banner}\n {showToolbarRow ? (\n <div className=\"flex flex-wrap items-center justify-start gap-3\">\n {toolbar}\n {showSelectionControls ? (\n <div className=\"flex items-center gap-2 text-xs\">\n <button\n type=\"button\"\n className=\"font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline\"\n onClick={selectAll}\n >\n {selectAllLabel}\n </button>\n <span className=\"text-muted-foreground/60\">·</span>\n <button\n type=\"button\"\n className=\"font-medium text-primary underline-offset-2 hover:text-primary/80 hover:underline\"\n onClick={deselectAll}\n >\n {deselectAllLabel}\n </button>\n </div>\n ) : null}\n </div>\n ) : null}\n <div className=\"h-5 truncate text-xs text-muted-foreground\">{hoverSummary}</div>\n <PlatePaintGrid\n format={format}\n rows={rows}\n columns={columns}\n values={values}\n selection={selection}\n onSelectionChange={onSelectionChange}\n colorForWell={colorForWell}\n emptyWellFillColor={emptyWellFillColor}\n wellShape={wellShape}\n framed={framed}\n wrapWell={wrapWell}\n quickPaint={quickPaint}\n highlightedWellIds={highlightedWellIds}\n onWellHover={(wellId) => {\n if (!isHoverControlled) setInternalHoverPos(wellId);\n onHoveredWellChange?.(wellId);\n }}\n onWellDoubleClick={onWellDoubleClick}\n selectionFillMode={selectionFillMode}\n flashWellId={flashWellId}\n flashWellKey={flashWellKey}\n cellSize={cellSize}\n autoScale={autoScale}\n minCellSize={minCellSize}\n maxCellSize={maxCellSize}\n />\n {groups && groups.length > 0 ? (\n <>\n <Separator className=\"mt-2\" />\n <div className=\"flex max-h-28 flex-wrap gap-3 overflow-y-auto pt-1\">\n {groups.map((group) => {\n const isActive = group.id === activeGroupId;\n const count = group.count ?? group.wellIds?.length;\n return (\n <button\n key={group.id}\n type=\"button\"\n disabled={group.disabled}\n onClick={() => onGroupClick?.(group)}\n className={cn(\n \"flex w-16 flex-col items-center gap-1 rounded-md px-1 py-1 text-center text-xs transition-colors\",\n \"text-muted-foreground hover:bg-accent/60\",\n isActive && \"bg-muted text-foreground ring-1 ring-primary/40\",\n group.disabled && \"pointer-events-none opacity-50\",\n )}\n title={group.label}\n >\n <span\n className=\"size-7 rounded-full border\"\n style={{\n backgroundColor: group.color,\n borderColor: group.borderColor,\n }}\n aria-hidden\n />\n <span className=\"w-full truncate text-foreground\">{group.label}</span>\n {count === undefined ? null : (\n <span className=\"text-[0.7rem] leading-none text-muted-foreground\">{count} wells</span>\n )}\n </button>\n );\n })}\n </div>\n </>\n ) : null}\n {footer}\n </div>\n );\n}\n"],"names":["formatHoverFields","entry","fields","f","v","o","arr","item","PlateMapGrid","format","rows","columns","values","selection","onSelectionChange","colorForWell","renderHoverSummary","onHoveredWellChange","hoveredWellId","banner","toolbar","footer","hideSelectionControls","selectAllLabel","deselectAllLabel","emptyWellFillColor","wellShape","framed","wrapWell","quickPaint","highlightedWellIds","onWellDoubleClick","selectionFillMode","flashWellId","flashWellKey","cellSize","autoScale","minCellSize","maxCellSize","groups","activeGroupId","onGroupClick","className","dims","resolveDimensions","internalHoverPos","setInternalHoverPos","React","isHoverControlled","hoverPos","selectAll","allPositions","deselectAll","hoverEntry","hoverFields","hoverSummary","showSelectionControls","showToolbarRow","jsxs","cn","jsx","PlatePaintGrid","wellId","Fragment","Separator","group","isActive","count"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),j=require("./usePlateMapEditorState.cjs"),q=require("./WellManifestTable.cjs"),y=require("../../../lib/utils.cjs");function P({values:a,onChange:l,columns:s,fields:n,selection:i,onSelectionChange:r,emptyEntry:u=j.defaultEmptyEntry,isPopulated:c,filterable:o,filterColumns:d,groupable:f,defaultGroupBy:m,enableFillDown:p,labels:M,pageSize:x,pageSizeOptions:b,title:t,className:g}){return e.jsxs("div",{"data-slot":"plate-map-manifest",className:y.cn("flex flex-col gap-3",g),children:[t?e.jsx("div",{className:"text-base leading-snug font-medium",children:t}):null,e.jsx(q.WellManifestTable,{values:a,onChange:l,columns:s,fields:n,selection:i,onSelectionChange:r,emptyEntry:u,isPopulated:c,filterable:o,filterColumns:d,groupable:f,defaultGroupBy:m,enableFillDown:p,labels:M,pageSize:x,pageSizeOptions:b})]})}exports.PlateMapManifest=P;
|
|
2
2
|
//# sourceMappingURL=PlateMapManifest.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlateMapManifest.cjs","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapManifest.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { WellManifestTable } from \"./WellManifestTable\";\n\nimport type { WellColumn, WellField, WellId, WellRecord } from \"./types\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface PlateMapManifestProps<T extends WellRecord = WellRecord> {\n values: Map<WellId, T>;\n onChange: (next: Map<WellId, T>) => void;\n columns: WellColumn<T>[];\n fields?: WellField<T>[];\n selection?: Set<WellId>;\n onSelectionChange?: (next: Set<WellId>) => void;\n /** Builds an empty record when a manifest row is freshly created. */\n emptyEntry
|
|
1
|
+
{"version":3,"file":"PlateMapManifest.cjs","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapManifest.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { defaultEmptyEntry } from \"./usePlateMapEditorState\";\nimport { WellManifestTable } from \"./WellManifestTable\";\n\nimport type { WellColumn, WellField, WellId, WellManifestTableLabels, WellRecord } from \"./types\";\nimport type { FilterColumnConfig } from \"@/components/ui/data-table/data-table\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface PlateMapManifestProps<T extends WellRecord = WellRecord> {\n values: Map<WellId, T>;\n onChange: (next: Map<WellId, T>) => void;\n columns: WellColumn<T>[];\n fields?: WellField<T>[];\n selection?: Set<WellId>;\n onSelectionChange?: (next: Set<WellId>) => void;\n /** Builds an empty record when a manifest row is freshly created. Defaults to `{}`. */\n emptyEntry?: (id: WellId) => T;\n /** Filter for the manifest's \"hide empty\" mode. */\n isPopulated?: (row: T) => boolean;\n /** Enables the filter popover on the manifest table. */\n filterable?: boolean;\n /** Overrides which columns are filterable and how. */\n filterColumns?: FilterColumnConfig[];\n /** Enables the group-by selector on the manifest table. */\n groupable?: boolean;\n /** Field grouped by on first render. Requires `groupable`. */\n defaultGroupBy?: string;\n /** Adds the copy-first-value-downward column action. Defaults to true. */\n enableFillDown?: boolean;\n /** Overrides any user-facing string in the table. */\n labels?: WellManifestTableLabels;\n pageSize?: number;\n pageSizeOptions?: number[];\n /** Optional heading rendered above the table. Omit for a bare table. */\n title?: React.ReactNode;\n className?: string;\n}\n\n/**\n * Card-agnostic sample-manifest panel. A thin wrapper over `WellManifestTable`\n * with an optional heading and no width constraint of its own, so it can span\n * the full screen width or sit inside any container the caller chooses.\n */\nexport function PlateMapManifest<T extends WellRecord = WellRecord>({\n values,\n onChange,\n columns,\n fields,\n selection,\n onSelectionChange,\n emptyEntry = defaultEmptyEntry,\n isPopulated,\n filterable,\n filterColumns,\n groupable,\n defaultGroupBy,\n enableFillDown,\n labels,\n pageSize,\n pageSizeOptions,\n title,\n className,\n}: PlateMapManifestProps<T>) {\n return (\n <div data-slot=\"plate-map-manifest\" className={cn(\"flex flex-col gap-3\", className)}>\n {title ? <div className=\"text-base leading-snug font-medium\">{title}</div> : null}\n <WellManifestTable<T>\n values={values}\n onChange={onChange}\n columns={columns}\n fields={fields}\n selection={selection}\n onSelectionChange={onSelectionChange}\n emptyEntry={emptyEntry}\n isPopulated={isPopulated}\n filterable={filterable}\n filterColumns={filterColumns}\n groupable={groupable}\n defaultGroupBy={defaultGroupBy}\n enableFillDown={enableFillDown}\n labels={labels}\n pageSize={pageSize}\n pageSizeOptions={pageSizeOptions}\n />\n </div>\n );\n}\n"],"names":["PlateMapManifest","values","onChange","columns","fields","selection","onSelectionChange","emptyEntry","defaultEmptyEntry","isPopulated","filterable","filterColumns","groupable","defaultGroupBy","enableFillDown","labels","pageSize","pageSizeOptions","title","className","jsxs","cn","jsx","WellManifestTable"],"mappings":"wOA6CO,SAASA,EAAoD,CAClE,OAAAC,EACA,SAAAC,EACA,QAAAC,EACA,OAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,WAAAC,EAAaC,EAAAA,kBACb,YAAAC,EACA,WAAAC,EACA,cAAAC,EACA,UAAAC,EACA,eAAAC,EACA,eAAAC,EACA,OAAAC,EACA,SAAAC,EACA,gBAAAC,EACA,MAAAC,EACA,UAAAC,CACF,EAA6B,CAC3B,OACEC,OAAC,OAAI,YAAU,qBAAqB,UAAWC,EAAAA,GAAG,sBAAuBF,CAAS,EAC/E,SAAA,CAAAD,EAAQI,EAAAA,IAAC,MAAA,CAAI,UAAU,qCAAsC,WAAM,EAAS,KAC7EA,EAAAA,IAACC,EAAAA,kBAAA,CACC,OAAAtB,EACA,SAAAC,EACA,QAAAC,EACA,OAAAC,EACA,UAAAC,EACA,kBAAAC,EACA,WAAAC,EACA,YAAAE,EACA,WAAAC,EACA,cAAAC,EACA,UAAAC,EACA,eAAAC,EACA,eAAAC,EACA,OAAAC,EACA,SAAAC,EACA,gBAAAC,CAAA,CAAA,CACF,EACF,CAEJ"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { WellColumn, WellField, WellId, WellRecord } from './types';
|
|
1
|
+
import { WellColumn, WellField, WellId, WellManifestTableLabels, WellRecord } from './types';
|
|
2
|
+
import { FilterColumnConfig } from '../../ui/data-table/data-table';
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
export interface PlateMapManifestProps<T extends WellRecord = WellRecord> {
|
|
4
5
|
values: Map<WellId, T>;
|
|
@@ -7,14 +8,22 @@ export interface PlateMapManifestProps<T extends WellRecord = WellRecord> {
|
|
|
7
8
|
fields?: WellField<T>[];
|
|
8
9
|
selection?: Set<WellId>;
|
|
9
10
|
onSelectionChange?: (next: Set<WellId>) => void;
|
|
10
|
-
/** Builds an empty record when a manifest row is freshly created. */
|
|
11
|
-
emptyEntry
|
|
11
|
+
/** Builds an empty record when a manifest row is freshly created. Defaults to `{}`. */
|
|
12
|
+
emptyEntry?: (id: WellId) => T;
|
|
12
13
|
/** Filter for the manifest's "hide empty" mode. */
|
|
13
14
|
isPopulated?: (row: T) => boolean;
|
|
14
15
|
/** Enables the filter popover on the manifest table. */
|
|
15
16
|
filterable?: boolean;
|
|
17
|
+
/** Overrides which columns are filterable and how. */
|
|
18
|
+
filterColumns?: FilterColumnConfig[];
|
|
16
19
|
/** Enables the group-by selector on the manifest table. */
|
|
17
20
|
groupable?: boolean;
|
|
21
|
+
/** Field grouped by on first render. Requires `groupable`. */
|
|
22
|
+
defaultGroupBy?: string;
|
|
23
|
+
/** Adds the copy-first-value-downward column action. Defaults to true. */
|
|
24
|
+
enableFillDown?: boolean;
|
|
25
|
+
/** Overrides any user-facing string in the table. */
|
|
26
|
+
labels?: WellManifestTableLabels;
|
|
18
27
|
pageSize?: number;
|
|
19
28
|
pageSizeOptions?: number[];
|
|
20
29
|
/** Optional heading rendered above the table. Omit for a bare table. */
|
|
@@ -26,4 +35,4 @@ export interface PlateMapManifestProps<T extends WellRecord = WellRecord> {
|
|
|
26
35
|
* with an optional heading and no width constraint of its own, so it can span
|
|
27
36
|
* the full screen width or sit inside any container the caller chooses.
|
|
28
37
|
*/
|
|
29
|
-
export declare function PlateMapManifest<T extends WellRecord = WellRecord>({ values, onChange, columns, fields, selection, onSelectionChange, emptyEntry, isPopulated, filterable, groupable, pageSize, pageSizeOptions, title, className, }: PlateMapManifestProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
38
|
+
export declare function PlateMapManifest<T extends WellRecord = WellRecord>({ values, onChange, columns, fields, selection, onSelectionChange, emptyEntry, isPopulated, filterable, filterColumns, groupable, defaultGroupBy, enableFillDown, labels, pageSize, pageSizeOptions, title, className, }: PlateMapManifestProps<T>): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,44 +1,53 @@
|
|
|
1
|
-
import { jsxs as
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
1
|
+
import { jsxs as h, jsx as a } from "react/jsx-runtime";
|
|
2
|
+
import { defaultEmptyEntry as j } from "./usePlateMapEditorState.js";
|
|
3
|
+
import { WellManifestTable as v } from "./WellManifestTable.js";
|
|
4
|
+
import { cn as y } from "../../../lib/utils.js";
|
|
5
|
+
function W({
|
|
6
|
+
values: t,
|
|
7
|
+
onChange: l,
|
|
8
|
+
columns: m,
|
|
9
|
+
fields: n,
|
|
10
|
+
selection: r,
|
|
11
|
+
onSelectionChange: i,
|
|
12
|
+
emptyEntry: o = j,
|
|
13
|
+
isPopulated: s,
|
|
13
14
|
filterable: f,
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
15
|
+
filterColumns: p,
|
|
16
|
+
groupable: d,
|
|
17
|
+
defaultGroupBy: c,
|
|
18
|
+
enableFillDown: u,
|
|
19
|
+
labels: x,
|
|
20
|
+
pageSize: g,
|
|
21
|
+
pageSizeOptions: M,
|
|
17
22
|
title: e,
|
|
18
|
-
className:
|
|
23
|
+
className: b
|
|
19
24
|
}) {
|
|
20
|
-
return /* @__PURE__ */
|
|
25
|
+
return /* @__PURE__ */ h("div", { "data-slot": "plate-map-manifest", className: y("flex flex-col gap-3", b), children: [
|
|
21
26
|
e ? /* @__PURE__ */ a("div", { className: "text-base leading-snug font-medium", children: e }) : null,
|
|
22
27
|
/* @__PURE__ */ a(
|
|
23
|
-
|
|
28
|
+
v,
|
|
24
29
|
{
|
|
25
|
-
values:
|
|
26
|
-
onChange:
|
|
27
|
-
columns:
|
|
28
|
-
fields:
|
|
29
|
-
selection:
|
|
30
|
-
onSelectionChange:
|
|
30
|
+
values: t,
|
|
31
|
+
onChange: l,
|
|
32
|
+
columns: m,
|
|
33
|
+
fields: n,
|
|
34
|
+
selection: r,
|
|
35
|
+
onSelectionChange: i,
|
|
31
36
|
emptyEntry: o,
|
|
32
|
-
isPopulated:
|
|
37
|
+
isPopulated: s,
|
|
33
38
|
filterable: f,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
filterColumns: p,
|
|
40
|
+
groupable: d,
|
|
41
|
+
defaultGroupBy: c,
|
|
42
|
+
enableFillDown: u,
|
|
43
|
+
labels: x,
|
|
44
|
+
pageSize: g,
|
|
45
|
+
pageSizeOptions: M
|
|
37
46
|
}
|
|
38
47
|
)
|
|
39
48
|
] });
|
|
40
49
|
}
|
|
41
50
|
export {
|
|
42
|
-
|
|
51
|
+
W as PlateMapManifest
|
|
43
52
|
};
|
|
44
53
|
//# sourceMappingURL=PlateMapManifest.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PlateMapManifest.js","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapManifest.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { WellManifestTable } from \"./WellManifestTable\";\n\nimport type { WellColumn, WellField, WellId, WellRecord } from \"./types\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface PlateMapManifestProps<T extends WellRecord = WellRecord> {\n values: Map<WellId, T>;\n onChange: (next: Map<WellId, T>) => void;\n columns: WellColumn<T>[];\n fields?: WellField<T>[];\n selection?: Set<WellId>;\n onSelectionChange?: (next: Set<WellId>) => void;\n /** Builds an empty record when a manifest row is freshly created. */\n emptyEntry
|
|
1
|
+
{"version":3,"file":"PlateMapManifest.js","sources":["../../../../src/components/composed/PlateMapEditor/PlateMapManifest.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport { defaultEmptyEntry } from \"./usePlateMapEditorState\";\nimport { WellManifestTable } from \"./WellManifestTable\";\n\nimport type { WellColumn, WellField, WellId, WellManifestTableLabels, WellRecord } from \"./types\";\nimport type { FilterColumnConfig } from \"@/components/ui/data-table/data-table\";\n\nimport { cn } from \"@/lib/utils\";\n\nexport interface PlateMapManifestProps<T extends WellRecord = WellRecord> {\n values: Map<WellId, T>;\n onChange: (next: Map<WellId, T>) => void;\n columns: WellColumn<T>[];\n fields?: WellField<T>[];\n selection?: Set<WellId>;\n onSelectionChange?: (next: Set<WellId>) => void;\n /** Builds an empty record when a manifest row is freshly created. Defaults to `{}`. */\n emptyEntry?: (id: WellId) => T;\n /** Filter for the manifest's \"hide empty\" mode. */\n isPopulated?: (row: T) => boolean;\n /** Enables the filter popover on the manifest table. */\n filterable?: boolean;\n /** Overrides which columns are filterable and how. */\n filterColumns?: FilterColumnConfig[];\n /** Enables the group-by selector on the manifest table. */\n groupable?: boolean;\n /** Field grouped by on first render. Requires `groupable`. */\n defaultGroupBy?: string;\n /** Adds the copy-first-value-downward column action. Defaults to true. */\n enableFillDown?: boolean;\n /** Overrides any user-facing string in the table. */\n labels?: WellManifestTableLabels;\n pageSize?: number;\n pageSizeOptions?: number[];\n /** Optional heading rendered above the table. Omit for a bare table. */\n title?: React.ReactNode;\n className?: string;\n}\n\n/**\n * Card-agnostic sample-manifest panel. A thin wrapper over `WellManifestTable`\n * with an optional heading and no width constraint of its own, so it can span\n * the full screen width or sit inside any container the caller chooses.\n */\nexport function PlateMapManifest<T extends WellRecord = WellRecord>({\n values,\n onChange,\n columns,\n fields,\n selection,\n onSelectionChange,\n emptyEntry = defaultEmptyEntry,\n isPopulated,\n filterable,\n filterColumns,\n groupable,\n defaultGroupBy,\n enableFillDown,\n labels,\n pageSize,\n pageSizeOptions,\n title,\n className,\n}: PlateMapManifestProps<T>) {\n return (\n <div data-slot=\"plate-map-manifest\" className={cn(\"flex flex-col gap-3\", className)}>\n {title ? <div className=\"text-base leading-snug font-medium\">{title}</div> : null}\n <WellManifestTable<T>\n values={values}\n onChange={onChange}\n columns={columns}\n fields={fields}\n selection={selection}\n onSelectionChange={onSelectionChange}\n emptyEntry={emptyEntry}\n isPopulated={isPopulated}\n filterable={filterable}\n filterColumns={filterColumns}\n groupable={groupable}\n defaultGroupBy={defaultGroupBy}\n enableFillDown={enableFillDown}\n labels={labels}\n pageSize={pageSize}\n pageSizeOptions={pageSizeOptions}\n />\n </div>\n );\n}\n"],"names":["PlateMapManifest","values","onChange","columns","fields","selection","onSelectionChange","emptyEntry","defaultEmptyEntry","isPopulated","filterable","filterColumns","groupable","defaultGroupBy","enableFillDown","labels","pageSize","pageSizeOptions","title","className","jsxs","cn","jsx","WellManifestTable"],"mappings":";;;;AA6CO,SAASA,EAAoD;AAAA,EAClE,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,SAAAC;AAAA,EACA,QAAAC;AAAA,EACA,WAAAC;AAAA,EACA,mBAAAC;AAAA,EACA,YAAAC,IAAaC;AAAA,EACb,aAAAC;AAAA,EACA,YAAAC;AAAA,EACA,eAAAC;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,gBAAAC;AAAA,EACA,QAAAC;AAAA,EACA,UAAAC;AAAA,EACA,iBAAAC;AAAA,EACA,OAAAC;AAAA,EACA,WAAAC;AACF,GAA6B;AAC3B,SACE,gBAAAC,EAAC,SAAI,aAAU,sBAAqB,WAAWC,EAAG,uBAAuBF,CAAS,GAC/E,UAAA;AAAA,IAAAD,IAAQ,gBAAAI,EAAC,OAAA,EAAI,WAAU,sCAAsC,aAAM,IAAS;AAAA,IAC7E,gBAAAA;AAAA,MAACC;AAAA,MAAA;AAAA,QACC,QAAAtB;AAAA,QACA,UAAAC;AAAA,QACA,SAAAC;AAAA,QACA,QAAAC;AAAA,QACA,WAAAC;AAAA,QACA,mBAAAC;AAAA,QACA,YAAAC;AAAA,QACA,aAAAE;AAAA,QACA,YAAAC;AAAA,QACA,eAAAC;AAAA,QACA,WAAAC;AAAA,QACA,gBAAAC;AAAA,QACA,gBAAAC;AAAA,QACA,QAAAC;AAAA,QACA,UAAAC;AAAA,QACA,iBAAAC;AAAA,MAAA;AAAA,IAAA;AAAA,EACF,GACF;AAEJ;"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const u=require("react/jsx-runtime"),_e=require("react"),v=require("./wellGrid.cjs"),ee=require("../../../lib/utils.cjs");function ye(n){const l=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(n){for(const o in n)if(o!=="default"){const s=Object.getOwnPropertyDescriptor(n,o);Object.defineProperty(l,o,s.get?s:{enumerable:!0,get:()=>n[o]})}}return l.default=n,Object.freeze(l)}const L=ye(_e),we=34,be=24,xe=72,Ae=36,c=26,X=12,Me=1,oe=16,Pe=9,Te=5,N=1,z=4,te=4,Oe=3,se=5,q=650,ne="var(--surface-container)",le="var(--border)";function Re(n,l){const o=[];for(let s=0;s<n;s++)o.push(u.jsx("text",{x:c+s*l+l/2,y:c/2,textAnchor:"middle",fontSize:oe,className:"fill-muted-foreground",children:s+1},`c${s}`));return o}function je(n,l){const o=[];for(let s=0;s<n;s++)o.push(u.jsx("text",{x:c-Pe,y:c+s*l+l/2+Te,textAnchor:"end",fontSize:oe,className:"fill-muted-foreground",children:v.rowLabel(s)},`r${s}`));return o}function ke(n,l,o){const{dims:s,cellSize:e,values:E,selection:P,dragPositions:_,colorForWell:d,emptyWellFillColor:h,selectedFillColor:y,selectedFillOpacity:b,selectionFillMode:O,wellShape:m}=n,p=v.pos(l,o,s.columns),x=E.get(p),w=P.has(p)||_.has(p),k=x===void 0&&h!==null?h:d(x,p),T=w&&!(w&&O==="well"&&x!==void 0),R=T?y:k,j=T?b:void 0;if(m==="circle"){const F=c+o*e+e/2,A=c+l*e+e/2,S=e/2-N;return u.jsx("circle",{cx:F,cy:A,r:S,fill:R,fillOpacity:j,stroke:"none","data-well":p,"data-selected":w?"true":void 0},p)}return u.jsx("rect",{x:c+o*e,y:c+l*e,width:e,height:e,fill:R,fillOpacity:j,stroke:"none","data-well":p,"data-selected":w?"true":void 0},p)}function Fe({dims:n,...l}){const o=[];for(let s=0;s<n.rows;s++)for(let e=0;e<n.columns;e++)o.push(ke({dims:n,...l},s,e));return o}function Se(n,l,o){const s=[],e=c,E=c,P=c+n.columns*l,_=c+n.rows*l;for(let d=0;d<=n.columns;d++){const h=c+d*l;s.push(u.jsx("line",{x1:h,y1:E,x2:h,y2:_,stroke:o,strokeWidth:z,vectorEffect:"non-scaling-stroke",shapeRendering:"crispEdges",pointerEvents:"none","data-plate-grid-line":`column-${d}`},`grid-col-${d}`))}for(let d=0;d<=n.rows;d++){const h=c+d*l;s.push(u.jsx("line",{x1:e,y1:h,x2:P,y2:h,stroke:o,strokeWidth:z,vectorEffect:"non-scaling-stroke",shapeRendering:"crispEdges",pointerEvents:"none","data-plate-grid-line":`row-${d}`},`grid-row-${d}`))}return s}function De(n,l,o){const{dims:s,cellSize:e,selection:E,dragPositions:P,selectedBorderColor:_,flashWellId:d,flashWellKey:h,wellShape:y,highlightedWellIds:b,highlightBorderColor:O}=n,m=v.pos(l,o,s.columns),p=E.has(m)||P.has(m),x=d===m,w=!p&&b.has(m);if(!p&&!x&&!w)return null;const k=c+o*e+N,I=c+l*e+N,T=e-N*2,R=c+o*e+e/2,j=c+l*e+e/2,F=e/2-N,A=y==="circle",S=A?{cx:R,cy:j,r:F}:{x:k,y:I,width:T,height:T},M=(r,D,C)=>{const a={...S,...r,pointerEvents:"none"};return A?u.jsx("circle",{...a,children:D},C):u.jsx("rect",{...a,children:D},C)},$=u.jsxs(u.Fragment,{children:[u.jsx("animate",{attributeName:"fill-opacity",values:"0.24;0.1;0",dur:`${q}ms`,fill:"freeze"}),u.jsx("animate",{attributeName:"stroke-opacity",values:"0.92;0.42;0",dur:`${q}ms`,fill:"freeze"}),u.jsx("animate",{attributeName:"stroke-width",values:`${se};${te}`,dur:`${q}ms`,fill:"freeze"})]});return u.jsxs("g",{children:[p?M({fill:"none",stroke:_,strokeWidth:te,"data-well-selection":m}):null,w?M({fill:"none",stroke:O,strokeWidth:Oe,"data-well-highlight":m}):null,x?M({fill:_,fillOpacity:.24,stroke:_,strokeOpacity:.92,strokeWidth:se,"data-well-flash":m},$,`${m}-${h}`):null]},`overlay-${m}`)}function Ce({dims:n,...l}){const o=[];for(let s=0;s<n.rows;s++)for(let e=0;e<n.columns;e++){const E=De({dims:n,...l},s,e);E&&o.push(E)}return o}function We({format:n,rows:l,columns:o,values:s,selection:e,onSelectionChange:E,colorForWell:P,emptyWellFillColor:_=ne,wellShape:d="rect",framed:h=!1,cellSize:y,autoScale:b=!0,minCellSize:O=be,maxCellSize:m,borderColor:p=le,selectedBorderColor:x="var(--color-primary)",selectedFillColor:w="var(--color-primary)",selectedFillOpacity:k=.18,selectionFillMode:I="selection",flashWellId:T,flashWellKey:R,highlightedWellIds:j,highlightBorderColor:F="var(--color-primary)",onWellHover:A,onWellDoubleClick:S,wrapWell:M,className:$}){const r=v.resolveDimensions(n,l,o),D=L.useRef(null),C=L.useRef(null),[a,B]=L.useState(null),[U,re]=L.useState();L.useLayoutEffect(()=>{const i=D.current;if(!i||!b||y!==void 0)return;const t=()=>re(i.clientWidth);if(t(),typeof ResizeObserver>"u")return;const f=new ResizeObserver(t);return f.observe(i),()=>f.disconnect()},[b,y]);const g=L.useMemo(()=>{if(!b||y!==void 0||!U)return y??we;const i=m??(r.columns>12?Ae:xe),t=h?(X+Me)*2:0,f=Math.floor((U-c-t)/r.columns);return Math.max(O,Math.min(i,f))},[b,y,U,r.columns,h,m,O]),G=L.useCallback(i=>{const t=C.current;if(!t)return null;const f=t.getBoundingClientRect(),W=i.clientX-f.left-c,ve=i.clientY-f.top-c,H=Math.floor(W/g),K=Math.floor(ve/g);return K<0||K>=r.rows||H<0||H>=r.columns?null:{r:K,c:H}},[g,r.rows,r.columns]),ce=i=>{const t=G(i);if(!t)return;const f=i.shiftKey?"add":i.altKey?"remove":"replace";B({start:t,cur:t,mode:f})},ie=i=>{const t=G(i);t&&A&&A(v.pos(t.r,t.c,r.columns)),!(!a||!t)&&B({...a,cur:t})},Y=L.useCallback(()=>{if(!a)return;const i=v.rectPositions(a.start.r,a.start.c,a.cur.r,a.cur.c,r.columns);let t;a.mode==="replace"?t=new Set(i):a.mode==="add"?(t=new Set(e),i.forEach(f=>t.add(f))):(t=new Set(e),i.forEach(f=>t.delete(f))),E(t),B(null)},[a,r.columns,E,e]),ae=()=>Y(),ue=()=>{Y(),A?.(null)},de=i=>{const t=G(i);t&&S?.(v.pos(t.r,t.c,r.columns))},fe=L.useMemo(()=>a?new Set(v.rectPositions(a.start.r,a.start.c,a.cur.r,a.cur.c,r.columns)):new Set,[a,r.columns]),Z=z,J=r.columns*g+c+Z,Q=r.rows*g+c+Z,he=Re(r.columns,g),pe=je(r.rows,g),V={dims:r,cellSize:g,values:s,selection:e,dragPositions:fe,colorForWell:P,emptyWellFillColor:_,borderColor:p,selectedBorderColor:x,selectedFillColor:w,selectedFillOpacity:k,selectionFillMode:I,wellShape:d,highlightedWellIds:j??new Set,highlightBorderColor:F,flashWellId:T,flashWellKey:R},ge=Fe(V),me=d==="circle"?[]:Se(r,g,p),Ee=Ce(V),Le=L.useMemo(()=>{if(!M)return[];const i=[];for(let t=0;t<r.rows;t++)for(let f=0;f<r.columns;f++){const W=v.pos(t,f,r.columns);i.push(u.jsx("div",{style:{position:"absolute",left:c+f*g,top:c+t*g,width:g,height:g},"data-well-id":W,children:M(W,g)},W))}return i},[M,r.rows,r.columns,g]);return u.jsx("div",{ref:D,className:ee.cn("relative w-full select-none",$),"data-slot":"plate-paint-grid",children:u.jsxs("div",{className:ee.cn("relative inline-block",h&&"rounded-xl border bg-card p-3 shadow-elevation-3"),"data-slot":"plate-paint-grid-frame",children:[u.jsxs("svg",{ref:C,width:J,height:Q,className:"block cursor-crosshair",onMouseDown:ce,onMouseMove:ie,onMouseUp:ae,onMouseLeave:ue,onDoubleClick:de,role:"group","aria-label":`${r.rows} row by ${r.columns} column plate map. Drag to select wells.`,children:[he,pe,ge,me,Ee]}),M?u.jsx("div",{className:"pointer-events-none absolute",style:{top:h?X:0,left:h?X:0,width:J,height:Q},"aria-hidden":!0,"data-slot":"plate-well-overlay",children:Le}):null]})})}exports.parsePos=v.parsePos;exports.PLATE_MAP_CELL_BORDER=le;exports.PLATE_MAP_EMPTY_WELL_FILL=ne;exports.PlatePaintGrid=We;
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const h=require("react/jsx-runtime"),Ue=require("react"),g=require("./wellGrid.cjs"),se=require("../../../lib/utils.cjs");function Ke(t){const c=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const o in t)if(o!=="default"){const r=Object.getOwnPropertyDescriptor(t,o);Object.defineProperty(c,o,r.get?r:{enumerable:!0,get:()=>t[o]})}}return c.default=t,Object.freeze(c)}const u=Ke(Ue),Be=34,Xe=24,qe=72,Ye=36,a=26,Q=12,we=1,Ee=16,Ge=9,He=5,q=1,oe=4,be=4,ge=8,te=10,Qe=3,ye=5,ne=650,Le="var(--surface-container)",Ze=new Set;function re(t,c,o){return`${t}-well-${c}-${o}`}const xe="var(--border)";function Je(t,c){const o=[];for(let r=0;r<t;r++)o.push(h.jsx("text",{x:a+r*c+c/2,y:a/2,textAnchor:"middle",fontSize:Ee,className:"fill-muted-foreground",children:r+1},`c${r}`));return o}function Ve(t,c){const o=[];for(let r=0;r<t;r++)o.push(h.jsx("text",{x:a-Ge,y:a+r*c+c/2+He,textAnchor:"end",fontSize:Ee,className:"fill-muted-foreground",children:g.rowLabel(r)},`r${r}`));return o}function et(t,c,o){const{dims:r,cellSize:l,values:d,selection:L,dragPositions:E,colorForWell:m,emptyWellFillColor:p,selectedFillColor:T,selectedFillOpacity:j,selectionFillMode:D,wellShape:y,instanceId:x}=t,v=g.pos(c,o,r.columns),M=d.get(v),_=L.has(v)||E.has(v),F=M===void 0&&p!==null?p:m(M,v),R=_&&!(_&&D==="well"&&M!==void 0),$=R?T:F,I=R?j:void 0;if(y==="circle"){const P=a+o*l+l/2,z=a+c*l+l/2,k=l/2-q;return h.jsx("circle",{id:re(x,c,o),cx:P,cy:z,r:k,fill:$,fillOpacity:I,stroke:"none",role:"gridcell","aria-colindex":o+1,"aria-label":v,"aria-selected":_,"data-well":v,"data-selected":_?"true":void 0},v)}return h.jsx("rect",{id:re(x,c,o),x:a+o*l,y:a+c*l,width:l,height:l,fill:$,fillOpacity:I,stroke:"none",role:"gridcell","aria-colindex":o+1,"aria-label":v,"aria-selected":_,"data-well":v,"data-selected":_?"true":void 0},v)}function tt(t,c){const o=t.shiftKey;switch(t.key){case"ArrowUp":return{kind:"move",dr:-1,dc:0,extend:o};case"ArrowDown":return{kind:"move",dr:1,dc:0,extend:o};case"ArrowLeft":return{kind:"move",dr:0,dc:-1,extend:o};case"ArrowRight":return{kind:"move",dr:0,dc:1,extend:o};case"Home":return{kind:"move",dr:0,dc:-c,extend:o};case"End":return{kind:"move",dr:0,dc:c,extend:o};case" ":case"Enter":return{kind:"toggle"};case"Escape":return{kind:"clear"};case"a":case"A":return t.metaKey||t.ctrlKey?{kind:"selectAll"}:null;default:return null}}function nt(t,c,o){if(!t)return null;const{w:r,h:l}=c??{w:0,h:0},d=l+ge,L=t.topY<d,E=L?t.bottomY+ge:t.topY-d;if(r===0)return{left:t.anchorX,top:E,below:L,tailOffset:0,ready:!1};const m=Math.min(Math.max(t.anchorX-r/2,0),Math.max(0,o-r)),p=Math.min(Math.max(t.anchorX-m,te),Math.max(te,r-te));return{left:m,top:E,below:L,tailOffset:p,ready:!0}}function st({placement:t,children:c,layerRef:o}){return t?h.jsx("div",{ref:o,"data-slot":"plate-quick-paint-anchor","data-placement":t.below?"below":"above",className:"pointer-events-none absolute z-10 w-max",style:{left:t.left,top:t.top,visibility:t.ready?void 0:"hidden"},children:h.jsxs("div",{className:"pointer-events-auto relative",children:[c,h.jsx("span",{"aria-hidden":!0,"data-slot":"plate-quick-paint-tail",className:se.cn("absolute size-2 rotate-45 bg-popover",t.below?"-top-1 border-t border-l":"-bottom-1 border-r border-b"),style:{left:t.tailOffset-4}})]})}):null}function ot({dims:t,...c}){const o=[];for(let r=0;r<t.rows;r++){const l=[];for(let d=0;d<t.columns;d++)l.push(et({dims:t,...c},r,d));o.push(h.jsx("g",{role:"row","aria-rowindex":r+1,children:l},`row-${r}`))}return o}function rt(t,c,o){const r=[],l=a,d=a,L=a+t.columns*c,E=a+t.rows*c;for(let m=0;m<=t.columns;m++){const p=a+m*c;r.push(h.jsx("line",{x1:p,y1:d,x2:p,y2:E,stroke:o,strokeWidth:oe,vectorEffect:"non-scaling-stroke",shapeRendering:"crispEdges",pointerEvents:"none","data-plate-grid-line":`column-${m}`},`grid-col-${m}`))}for(let m=0;m<=t.rows;m++){const p=a+m*c;r.push(h.jsx("line",{x1:l,y1:p,x2:L,y2:p,stroke:o,strokeWidth:oe,vectorEffect:"non-scaling-stroke",shapeRendering:"crispEdges",pointerEvents:"none","data-plate-grid-line":`row-${m}`},`grid-row-${m}`))}return r}function lt(t,c,o){const{dims:r,cellSize:l,selection:d,dragPositions:L,selectedBorderColor:E,flashWellId:m,flashWellKey:p,wellShape:T,highlightedWellIds:j,highlightBorderColor:D}=t,y=g.pos(c,o,r.columns),x=d.has(y)||L.has(y),v=m===y,M=!x&&j.has(y);if(!x&&!v&&!M)return null;const _=a+o*l+q,F=a+c*l+q,N=l-q*2,R=a+o*l+l/2,$=a+c*l+l/2,I=l/2-q,P=T==="circle",z=P?{cx:R,cy:$,r:I}:{x:_,y:F,width:N,height:N},k=(Z,n,W)=>{const U={...z,...Z,pointerEvents:"none"};return P?h.jsx("circle",{...U,children:n},W):h.jsx("rect",{...U,children:n},W)},C=h.jsxs(h.Fragment,{children:[h.jsx("animate",{attributeName:"fill-opacity",values:"0.24;0.1;0",dur:`${ne}ms`,fill:"freeze"}),h.jsx("animate",{attributeName:"stroke-opacity",values:"0.92;0.42;0",dur:`${ne}ms`,fill:"freeze"}),h.jsx("animate",{attributeName:"stroke-width",values:`${ye};${be}`,dur:`${ne}ms`,fill:"freeze"})]});return h.jsxs("g",{children:[x?k({fill:"none",stroke:E,strokeWidth:be,"data-well-selection":y}):null,M?k({fill:"none",stroke:D,strokeWidth:Qe,"data-well-highlight":y}):null,v?k({fill:E,fillOpacity:.24,stroke:E,strokeOpacity:.92,strokeWidth:ye,"data-well-flash":y},C,`${y}-${p}`):null]},`overlay-${y}`)}function ct({dims:t,...c}){const o=[];for(let r=0;r<t.rows;r++)for(let l=0;l<t.columns;l++){const d=lt({dims:t,...c},r,l);d&&o.push(d)}return o}function it({format:t,rows:c,columns:o,values:r,selection:l,onSelectionChange:d,colorForWell:L,emptyWellFillColor:E=Le,wellShape:m="rect",framed:p=!1,cellSize:T,autoScale:j=!0,minCellSize:D=Xe,maxCellSize:y,borderColor:x=xe,selectedBorderColor:v="var(--color-chart-seq-blue-06)",selectedFillColor:M="var(--color-chart-seq-blue-06)",selectedFillOpacity:_=.26,selectionFillMode:F="well",flashWellId:N,flashWellKey:R,highlightedWellIds:$,highlightBorderColor:I="var(--color-primary)",onWellHover:P,onWellDoubleClick:z,wrapWell:k,quickPaint:C,className:Z}){const n=g.resolveDimensions(t,c,o),W=u.useId(),U=u.useRef(null),le=u.useRef(null),[w,J]=u.useState(null),[K,_e]=u.useState();u.useLayoutEffect(()=>{const s=U.current;if(!s)return;const e=()=>_e(s.clientWidth);if(e(),typeof ResizeObserver>"u")return;const i=new ResizeObserver(e);return i.observe(s),()=>i.disconnect()},[]);const f=u.useMemo(()=>{if(!j||T!==void 0||!K)return T??Be;const s=y??(n.columns>12?Ye:qe),e=p?(Q+we)*2:0,i=Math.floor((K-a-e)/n.columns);return Math.max(D,Math.min(s,i))},[j,T,K,n.columns,p,y,D]),V=u.useCallback(s=>{const e=le.current;if(!e)return null;const i=e.getBoundingClientRect(),A=s.clientX-i.left-a,b=s.clientY-i.top-a,S=Math.floor(A/f),ee=Math.floor(b/f);return ee<0||ee>=n.rows||S<0||S>=n.columns?null:{r:ee,c:S}},[f,n.rows,n.columns]),Ae=s=>{const e=V(s);if(!e)return;try{s.currentTarget.setPointerCapture?.(s.pointerId)}catch{}const i=s.shiftKey?"add":s.altKey?"remove":"replace";J({start:e,cur:e,mode:i}),Y(e)},Pe=s=>{const e=V(s);e&&P&&P(g.pos(e.r,e.c,n.columns)),!(!w||!e)&&J({...w,cur:e})},[O,Y]=u.useState(null),G=u.useRef(null),ke=u.useCallback((s,e,i)=>{const A=O??{r:0,c:0},b={r:Math.min(n.rows-1,Math.max(0,A.r+s)),c:Math.min(n.columns-1,Math.max(0,A.c+e))};if(i){const S=G.current??A;G.current=S,d(new Set(g.rectPositions(S.r,S.c,b.r,b.c,n.columns)))}else G.current=b;Y(b),P?.(g.pos(b.r,b.c,n.columns))},[n.columns,n.rows,O,d,P]),Me=u.useCallback(()=>{const s=O??{r:0,c:0},e=g.pos(s.r,s.c,n.columns),i=new Set(l);i.has(e)?i.delete(e):i.add(e),Y(s),d(i)},[n.columns,O,d,l]),Te=s=>{const e=tt(s,n.columns);e&&(s.preventDefault(),e.kind==="move"?ke(e.dr,e.dc,e.extend):e.kind==="toggle"?Me():e.kind==="selectAll"?d(new Set(g.allPositions(n))):(G.current=null,d(new Set)))},ce=u.useCallback(()=>{if(!w)return;const s=g.rectPositions(w.start.r,w.start.c,w.cur.r,w.cur.c,n.columns);let e;w.mode==="replace"?e=new Set(s):w.mode==="add"?(e=new Set(l),s.forEach(i=>e.add(i))):(e=new Set(l),s.forEach(i=>e.delete(i))),d(e),J(null)},[w,n.columns,d,l]),ie=s=>{try{s.currentTarget.releasePointerCapture?.(s.pointerId)}catch{}ce()},Re=()=>{ce(),P?.(null)},Ie=s=>{const e=V(s);e&&z?.(g.pos(e.r,e.c,n.columns))},ae=u.useMemo(()=>w?new Set(g.rectPositions(w.start.r,w.start.c,w.cur.r,w.cur.c,n.columns)):new Set,[w,n.columns]),ue=oe,B=n.columns*f+a+ue,de=n.rows*f+a+ue,Oe=B+(p?(Q+we)*2:0),X=K!==void 0&&Oe>K+1,Se=`${n.rows} by ${n.columns} plate map, horizontally scrollable.`,fe=u.useMemo(()=>{if(!C||l.size===0)return null;let s=1/0,e=-1/0,i=1/0;for(const A of l){const b=g.parsePos(A,n);b&&(b.row<s&&(s=b.row),b.row>e&&(e=b.row),b.col<i&&(i=b.col))}return!Number.isFinite(s)||!Number.isFinite(i)?null:{anchorX:a+i*f+f/2,topY:a+s*f,bottomY:a+(e+1)*f}},[n,C,l,f]),he=u.useRef(null),[me,pe]=u.useState();u.useLayoutEffect(()=>{const s=he.current;if(!s){pe(void 0);return}const e=()=>pe({w:s.offsetWidth,h:s.offsetHeight});if(e(),typeof ResizeObserver>"u")return;const i=new ResizeObserver(e);return i.observe(s),()=>i.disconnect()},[C]);const je=u.useMemo(()=>nt(fe,me,B),[fe,me,B]),De=`${n.rows} row by ${n.columns} column plate map. Drag to select wells, or use arrow keys to move and Space to toggle a well.`,Fe=u.useMemo(()=>Je(n.columns,f),[n.columns,f]),Ne=u.useMemo(()=>Ve(n.rows,f),[n.rows,f]),ve=$??Ze,H=u.useMemo(()=>({dims:n,cellSize:f,values:r,selection:l,dragPositions:ae,colorForWell:L,emptyWellFillColor:E,borderColor:x,selectedBorderColor:v,selectedFillColor:M,selectedFillOpacity:_,selectionFillMode:F,wellShape:m,highlightedWellIds:ve,highlightBorderColor:I,flashWellId:N,flashWellKey:R,instanceId:W}),[W,x,L,n,ae,E,N,R,I,f,ve,v,M,_,l,F,r,m]),$e=u.useMemo(()=>ot(H),[H]),Ce=u.useMemo(()=>m==="circle"?[]:rt(n,f,x),[m,n,f,x]),We=u.useMemo(()=>ct(H),[H]),ze=u.useMemo(()=>{if(!k)return[];const s=[];for(let e=0;e<n.rows;e++)for(let i=0;i<n.columns;i++){const A=g.pos(e,i,n.columns);s.push(h.jsx("div",{style:{position:"absolute",left:a+i*f,top:a+e*f,width:f,height:f},"data-well-id":A,children:k(A,f)},A))}return s},[k,n.rows,n.columns,f]);return h.jsx("div",{ref:U,className:se.cn("relative w-full max-w-full select-none overflow-x-auto",X&&"focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none",Z),"data-slot":"plate-paint-grid","data-scrollable":X||void 0,tabIndex:X?0:void 0,role:X?"group":void 0,"aria-label":X?Se:void 0,children:h.jsxs("div",{className:se.cn("relative inline-block",p&&"rounded-xl border bg-card p-3 shadow-elevation-3"),"data-slot":"plate-paint-grid-frame",children:[h.jsxs("svg",{ref:le,width:B,height:de,className:"block cursor-crosshair",onPointerDown:Ae,onPointerMove:Pe,onPointerUp:ie,onPointerCancel:ie,onPointerLeave:Re,onDoubleClick:Ie,onKeyDown:Te,onFocus:()=>Y(s=>s??{r:0,c:0}),style:{touchAction:"none"},tabIndex:0,role:"grid","aria-label":De,"aria-rowcount":n.rows,"aria-colcount":n.columns,"aria-activedescendant":O?re(W,O.r,O.c):void 0,children:[Fe,Ne,$e,Ce,We]}),h.jsx(st,{placement:je,layerRef:he,children:C}),k?h.jsx("div",{className:"pointer-events-none absolute",style:{top:p?Q:0,left:p?Q:0,width:B,height:de},"aria-hidden":!0,"data-slot":"plate-well-overlay",children:ze}):null]})})}exports.parsePos=g.parsePos;exports.PLATE_MAP_CELL_BORDER=xe;exports.PLATE_MAP_EMPTY_WELL_FILL=Le;exports.PlatePaintGrid=it;
|
|
2
2
|
//# sourceMappingURL=PlatePaintGrid.cjs.map
|