@tetrascience-npm/tetrascience-react-ui 0.5.0-beta.55.1 → 0.5.0-beta.58.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/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +140 -0
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js +126 -0
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.js +422 -0
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js +136 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +389 -0
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.js +54 -0
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.js +96 -0
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellLegend.js +58 -0
- package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js +408 -0
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.js +177 -0
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/autoFill.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/autoFill.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/autoFill.js +41 -0
- package/dist/components/composed/PlateMapEditor/autoFill.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/csvPlateTriage.cjs +4 -0
- package/dist/components/composed/PlateMapEditor/csvPlateTriage.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/csvPlateTriage.js +103 -0
- package/dist/components/composed/PlateMapEditor/csvPlateTriage.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/helpers.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/helpers.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/helpers.js +11 -0
- package/dist/components/composed/PlateMapEditor/helpers.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/wellGrid.cjs +2 -0
- package/dist/components/composed/PlateMapEditor/wellGrid.cjs.map +1 -0
- package/dist/components/composed/PlateMapEditor/wellGrid.js +56 -0
- package/dist/components/composed/PlateMapEditor/wellGrid.js.map +1 -0
- package/dist/components/ui/data-table/data-table-filter.cjs +1 -1
- package/dist/components/ui/data-table/data-table-filter.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-filter.js +124 -139
- package/dist/components/ui/data-table/data-table-filter.js.map +1 -1
- package/dist/components/ui/data-table/data-table-group.cjs +2 -0
- package/dist/components/ui/data-table/data-table-group.cjs.map +1 -0
- package/dist/components/ui/data-table/data-table-group.js +118 -0
- package/dist/components/ui/data-table/data-table-group.js.map +1 -0
- package/dist/components/ui/data-table/data-table-pagination.cjs +1 -1
- package/dist/components/ui/data-table/data-table-pagination.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-pagination.js +22 -22
- package/dist/components/ui/data-table/data-table-pagination.js.map +1 -1
- package/dist/components/ui/data-table/data-table.cjs +1 -1
- package/dist/components/ui/data-table/data-table.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table.js +567 -316
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/popover.cjs +2 -0
- package/dist/components/ui/popover.cjs.map +1 -0
- package/dist/components/ui/popover.js +45 -0
- package/dist/components/ui/popover.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +580 -1
- package/dist/index.js +637 -593
- package/dist/index.js.map +1 -1
- package/dist/index.tailwind.css +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { jsxs as o, jsx as n } from "react/jsx-runtime";
|
|
2
|
+
import * as I from "react";
|
|
3
|
+
import { Button as x } from "../../ui/button.js";
|
|
4
|
+
import { Checkbox as S } from "../../ui/checkbox.js";
|
|
5
|
+
import { useComboboxAnchor as $, Combobox as F, ComboboxChips as V, ComboboxValue as A, ComboboxChip as M, ComboboxChipsInput as B, ComboboxContent as T, ComboboxEmpty as _, ComboboxList as j, ComboboxItem as E } from "../../ui/combobox.js";
|
|
6
|
+
import { Input as L } from "../../ui/input.js";
|
|
7
|
+
import { Label as P } from "../../ui/label.js";
|
|
8
|
+
import { Select as R, SelectTrigger as Y, SelectValue as D, SelectContent as K, SelectItem as U } from "../../ui/select.js";
|
|
9
|
+
import { Switch as W } from "../../ui/switch.js";
|
|
10
|
+
import { cn as q } from "../../../lib/utils.js";
|
|
11
|
+
function G({
|
|
12
|
+
id: i,
|
|
13
|
+
value: c,
|
|
14
|
+
options: a,
|
|
15
|
+
placeholder: m,
|
|
16
|
+
onChange: k
|
|
17
|
+
}) {
|
|
18
|
+
const p = $(), b = I.useMemo(() => {
|
|
19
|
+
const l = /* @__PURE__ */ new Map();
|
|
20
|
+
return a.forEach((s) => l.set(s.value, s.label)), l;
|
|
21
|
+
}, [a]);
|
|
22
|
+
return /* @__PURE__ */ o(F, { multiple: !0, items: a.map((l) => l.value), value: c, onValueChange: k, children: [
|
|
23
|
+
/* @__PURE__ */ o(V, { ref: p, className: "min-h-9 w-full", children: [
|
|
24
|
+
/* @__PURE__ */ n(A, { children: (l) => l.map((s) => /* @__PURE__ */ n(M, { children: b.get(s) ?? s }, s)) }),
|
|
25
|
+
/* @__PURE__ */ n(B, { id: i, placeholder: m ?? "Select…" })
|
|
26
|
+
] }),
|
|
27
|
+
/* @__PURE__ */ o(T, { anchor: p, children: [
|
|
28
|
+
/* @__PURE__ */ n(_, { children: "No options." }),
|
|
29
|
+
/* @__PURE__ */ n(j, { children: (l) => /* @__PURE__ */ n(E, { value: l, children: /* @__PURE__ */ o("span", { className: "inline-flex items-center gap-2", children: [
|
|
30
|
+
(() => {
|
|
31
|
+
const s = a.find((g) => g.value === l);
|
|
32
|
+
return s?.swatch ? /* @__PURE__ */ n(
|
|
33
|
+
"span",
|
|
34
|
+
{
|
|
35
|
+
className: "inline-block h-2.5 w-2.5 rounded-sm border border-foreground/20",
|
|
36
|
+
style: { backgroundColor: s.swatch },
|
|
37
|
+
"aria-hidden": !0
|
|
38
|
+
}
|
|
39
|
+
) : null;
|
|
40
|
+
})(),
|
|
41
|
+
b.get(l) ?? l
|
|
42
|
+
] }) }, l) })
|
|
43
|
+
] })
|
|
44
|
+
] });
|
|
45
|
+
}
|
|
46
|
+
const H = {
|
|
47
|
+
number: "number",
|
|
48
|
+
integer: "number",
|
|
49
|
+
date: "date",
|
|
50
|
+
datetime: "datetime-local",
|
|
51
|
+
time: "time"
|
|
52
|
+
};
|
|
53
|
+
function J(i) {
|
|
54
|
+
return H[i] ?? "text";
|
|
55
|
+
}
|
|
56
|
+
function O(i, c) {
|
|
57
|
+
if (c !== "") {
|
|
58
|
+
if (i === "number") {
|
|
59
|
+
const a = parseFloat(c);
|
|
60
|
+
return Number.isFinite(a) ? a : c;
|
|
61
|
+
}
|
|
62
|
+
if (i === "integer") {
|
|
63
|
+
const a = parseInt(c, 10);
|
|
64
|
+
return Number.isFinite(a) ? a : c;
|
|
65
|
+
}
|
|
66
|
+
return c;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function le({
|
|
70
|
+
fields: i,
|
|
71
|
+
value: c,
|
|
72
|
+
onChange: a,
|
|
73
|
+
selectionSize: m,
|
|
74
|
+
onApply: k,
|
|
75
|
+
onClear: p,
|
|
76
|
+
applyLabel: b = "Apply",
|
|
77
|
+
clearLabel: l = "Clear wells",
|
|
78
|
+
extras: s,
|
|
79
|
+
className: g
|
|
80
|
+
}) {
|
|
81
|
+
const u = (e, r) => {
|
|
82
|
+
a({ ...c, [e]: r });
|
|
83
|
+
}, d = (e) => /* @__PURE__ */ o(P, { htmlFor: `field-${e.key}`, className: "gap-1.5", children: [
|
|
84
|
+
e.icon ? /* @__PURE__ */ n("span", { className: "inline-flex text-muted-foreground [&_svg]:size-3.5", children: e.icon }) : null,
|
|
85
|
+
e.label
|
|
86
|
+
] }), C = (e, r) => /* @__PURE__ */ o("div", { className: "flex flex-col gap-1.5", children: [
|
|
87
|
+
d(e),
|
|
88
|
+
e.render({
|
|
89
|
+
value: r,
|
|
90
|
+
onChange: (t) => u(e.key, t),
|
|
91
|
+
selectionSize: m
|
|
92
|
+
})
|
|
93
|
+
] }, e.key), y = (e, r) => /* @__PURE__ */ o("div", { className: "flex flex-col gap-1.5", children: [
|
|
94
|
+
d(e),
|
|
95
|
+
/* @__PURE__ */ o(R, { value: r ?? "", onValueChange: (t) => u(e.key, t), children: [
|
|
96
|
+
/* @__PURE__ */ n(Y, { id: `field-${e.key}`, size: "sm", className: "w-full", children: /* @__PURE__ */ n(D, { placeholder: e.placeholder ?? "Select…" }) }),
|
|
97
|
+
/* @__PURE__ */ n(K, { children: (e.options ?? []).map((t) => /* @__PURE__ */ n(U, { value: t.value, children: /* @__PURE__ */ o("span", { className: "inline-flex items-center gap-2", children: [
|
|
98
|
+
t.swatch ? /* @__PURE__ */ n(
|
|
99
|
+
"span",
|
|
100
|
+
{
|
|
101
|
+
className: "inline-block h-2.5 w-2.5 rounded-sm border border-foreground/20",
|
|
102
|
+
style: { backgroundColor: t.swatch },
|
|
103
|
+
"aria-hidden": !0
|
|
104
|
+
}
|
|
105
|
+
) : null,
|
|
106
|
+
t.label
|
|
107
|
+
] }) }, t.value)) })
|
|
108
|
+
] })
|
|
109
|
+
] }, e.key), v = (e, r) => {
|
|
110
|
+
const t = Array.isArray(r) ? r : [];
|
|
111
|
+
return /* @__PURE__ */ o("div", { className: "flex flex-col gap-1.5", children: [
|
|
112
|
+
d(e),
|
|
113
|
+
/* @__PURE__ */ n(
|
|
114
|
+
G,
|
|
115
|
+
{
|
|
116
|
+
id: `field-${e.key}`,
|
|
117
|
+
value: t,
|
|
118
|
+
options: e.options ?? [],
|
|
119
|
+
placeholder: e.placeholder,
|
|
120
|
+
onChange: (h) => u(e.key, h.length === 0 ? void 0 : h)
|
|
121
|
+
}
|
|
122
|
+
)
|
|
123
|
+
] }, e.key);
|
|
124
|
+
}, N = (e, r) => {
|
|
125
|
+
const t = !!r;
|
|
126
|
+
return e.boolStyle === "switch" ? /* @__PURE__ */ o("div", { className: "flex items-center justify-between gap-2", children: [
|
|
127
|
+
d(e),
|
|
128
|
+
/* @__PURE__ */ n(
|
|
129
|
+
W,
|
|
130
|
+
{
|
|
131
|
+
id: `field-${e.key}`,
|
|
132
|
+
checked: t,
|
|
133
|
+
onCheckedChange: (h) => u(e.key, h)
|
|
134
|
+
}
|
|
135
|
+
)
|
|
136
|
+
] }, e.key) : /* @__PURE__ */ o("div", { className: "flex items-center gap-2", children: [
|
|
137
|
+
/* @__PURE__ */ n(
|
|
138
|
+
S,
|
|
139
|
+
{
|
|
140
|
+
id: `field-${e.key}`,
|
|
141
|
+
checked: t,
|
|
142
|
+
onCheckedChange: (h) => u(e.key, h === !0)
|
|
143
|
+
}
|
|
144
|
+
),
|
|
145
|
+
d(e)
|
|
146
|
+
] }, e.key);
|
|
147
|
+
}, f = (e, r) => /* @__PURE__ */ o("div", { className: "flex flex-col gap-1.5", children: [
|
|
148
|
+
d(e),
|
|
149
|
+
/* @__PURE__ */ n(
|
|
150
|
+
L,
|
|
151
|
+
{
|
|
152
|
+
id: `field-${e.key}`,
|
|
153
|
+
type: J(e.kind),
|
|
154
|
+
step: e.kind === "integer" ? 1 : void 0,
|
|
155
|
+
placeholder: e.placeholder,
|
|
156
|
+
value: r ?? "",
|
|
157
|
+
onChange: (t) => u(e.key, O(e.kind, t.target.value))
|
|
158
|
+
}
|
|
159
|
+
)
|
|
160
|
+
] }, e.key), w = (e) => {
|
|
161
|
+
const r = c[e.key];
|
|
162
|
+
return e.render ? C(e, r) : e.kind === "select" ? y(e, r) : e.kind === "multiselect" ? v(e, r) : e.kind === "boolean" ? N(e, r) : f(e, r);
|
|
163
|
+
};
|
|
164
|
+
return /* @__PURE__ */ o("div", { "data-slot": "well-metadata-form", className: q("flex flex-col gap-3", g), children: [
|
|
165
|
+
/* @__PURE__ */ n("div", { className: "text-sm font-medium", children: m > 0 ? `Apply to ${m} well${m === 1 ? "" : "s"}` : "Select wells to edit" }),
|
|
166
|
+
i.map(w),
|
|
167
|
+
s,
|
|
168
|
+
/* @__PURE__ */ o("div", { className: "mt-auto flex gap-2 pt-1", children: [
|
|
169
|
+
/* @__PURE__ */ n(x, { variant: "default", size: "sm", disabled: m === 0, onClick: k, children: b }),
|
|
170
|
+
/* @__PURE__ */ n(x, { variant: "outline", size: "sm", disabled: m === 0, onClick: p, children: l })
|
|
171
|
+
] })
|
|
172
|
+
] });
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
le as WellMetadataForm
|
|
176
|
+
};
|
|
177
|
+
//# sourceMappingURL=WellMetadataForm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WellMetadataForm.js","sources":["../../../../src/components/composed/PlateMapEditor/WellMetadataForm.tsx"],"sourcesContent":["import * as React from \"react\";\n\nimport type { WellField, WellRecord, WellSelectOption } from \"./types\";\n\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 { Input } from \"@/components/ui/input\";\nimport { Label } from \"@/components/ui/label\";\nimport { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from \"@/components/ui/select\";\nimport { Switch } from \"@/components/ui/switch\";\nimport { cn } from \"@/lib/utils\";\n\nfunction MultiSelectControl({\n id,\n value,\n options,\n placeholder,\n onChange,\n}: {\n id: 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=\"min-h-9 w-full\">\n <ComboboxValue>\n {(items: string[]) =>\n items.map((item) => <ComboboxChip key={item}>{labelByValue.get(item) ?? item}</ComboboxChip>)\n }\n </ComboboxValue>\n <ComboboxChipsInput id={id} 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 <span className=\"inline-flex items-center gap-2\">\n {(() => {\n const opt = options.find((o) => o.value === item);\n return 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 })()}\n {labelByValue.get(item) ?? item}\n </span>\n </ComboboxItem>\n )}\n </ComboboxList>\n </ComboboxContent>\n </Combobox>\n );\n}\n\nexport interface WellMetadataFormProps<T extends WellRecord = WellRecord> {\n fields: WellField<T>[];\n /** Staged values used to apply across the selection. */\n value: Partial<T>;\n onChange: (next: Partial<T>) => void;\n selectionSize: number;\n onApply: () => void;\n onClear: () => void;\n applyLabel?: string;\n clearLabel?: string;\n /** Optional extra slot rendered between fields and action row. */\n extras?: React.ReactNode;\n className?: string;\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 function WellMetadataForm<T extends WellRecord = WellRecord>({\n fields,\n value,\n onChange,\n selectionSize,\n onApply,\n onClear,\n applyLabel = \"Apply\",\n clearLabel = \"Clear wells\",\n extras,\n className,\n}: WellMetadataFormProps<T>) {\n const setField = (key: keyof T & string, next: unknown) => {\n onChange({ ...value, [key]: next } as Partial<T>);\n };\n\n const renderLabel = (field: WellField<T>) => (\n <Label htmlFor={`field-${field.key}`} className=\"gap-1.5\">\n {field.icon ? <span className=\"inline-flex text-muted-foreground [&_svg]:size-3.5\">{field.icon}</span> : null}\n {field.label}\n </Label>\n );\n\n const renderCustom = (field: WellField<T>, fieldValue: unknown) => (\n <div key={field.key} className=\"flex flex-col gap-1.5\">\n {renderLabel(field)}\n {field.render!({\n value: fieldValue,\n onChange: (next) => setField(field.key, next),\n selectionSize,\n })}\n </div>\n );\n\n const renderSelect = (field: WellField<T>, fieldValue: unknown) => (\n <div key={field.key} className=\"flex flex-col gap-1.5\">\n {renderLabel(field)}\n <Select value={(fieldValue as string | undefined) ?? \"\"} onValueChange={(v) => setField(field.key, v)}>\n <SelectTrigger id={`field-${field.key}`} size=\"sm\" className=\"w-full\">\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 </div>\n );\n\n const renderMultiSelect = (field: WellField<T>, fieldValue: unknown) => {\n const current = Array.isArray(fieldValue) ? (fieldValue as string[]) : [];\n return (\n <div key={field.key} className=\"flex flex-col gap-1.5\">\n {renderLabel(field)}\n <MultiSelectControl\n id={`field-${field.key}`}\n value={current}\n options={field.options ?? []}\n placeholder={field.placeholder}\n onChange={(next) => setField(field.key, next.length === 0 ? undefined : next)}\n />\n </div>\n );\n };\n\n const renderBoolean = (field: WellField<T>, fieldValue: unknown) => {\n const checked = !!fieldValue;\n if (field.boolStyle === \"switch\") {\n return (\n <div key={field.key} className=\"flex items-center justify-between gap-2\">\n {renderLabel(field)}\n <Switch\n id={`field-${field.key}`}\n checked={checked}\n onCheckedChange={(c) => setField(field.key, c)}\n />\n </div>\n );\n }\n return (\n <div key={field.key} className=\"flex items-center gap-2\">\n <Checkbox\n id={`field-${field.key}`}\n checked={checked}\n onCheckedChange={(c) => setField(field.key, c === true)}\n />\n {renderLabel(field)}\n </div>\n );\n };\n\n const renderInput = (field: WellField<T>, fieldValue: unknown) => (\n <div key={field.key} className=\"flex flex-col gap-1.5\">\n {renderLabel(field)}\n <Input\n id={`field-${field.key}`}\n type={resolveInputType(field.kind)}\n step={field.kind === \"integer\" ? 1 : undefined}\n placeholder={field.placeholder}\n value={(fieldValue as string | number | undefined) ?? \"\"}\n onChange={(e) => setField(field.key, parseInputValue(field.kind, e.target.value))}\n />\n </div>\n );\n\n const renderField = (field: WellField<T>) => {\n const fieldValue = value[field.key];\n if (field.render) return renderCustom(field, fieldValue);\n if (field.kind === \"select\") return renderSelect(field, fieldValue);\n if (field.kind === \"multiselect\") return renderMultiSelect(field, fieldValue);\n if (field.kind === \"boolean\") return renderBoolean(field, fieldValue);\n return renderInput(field, fieldValue);\n };\n\n return (\n <div data-slot=\"well-metadata-form\" className={cn(\"flex flex-col gap-3\", className)}>\n <div className=\"text-sm font-medium\">\n {selectionSize > 0 ? `Apply to ${selectionSize} well${selectionSize === 1 ? \"\" : \"s\"}` : \"Select wells to edit\"}\n </div>\n\n {fields.map(renderField)}\n\n {extras}\n\n <div className=\"mt-auto flex gap-2 pt-1\">\n <Button variant=\"default\" size=\"sm\" disabled={selectionSize === 0} onClick={onApply}>\n {applyLabel}\n </Button>\n <Button variant=\"outline\" size=\"sm\" disabled={selectionSize === 0} onClick={onClear}>\n {clearLabel}\n </Button>\n </div>\n </div>\n );\n}\n"],"names":["MultiSelectControl","id","value","options","placeholder","onChange","anchorRef","useComboboxAnchor","labelByValue","React","m","o","jsxs","Combobox","ComboboxChips","jsx","ComboboxValue","items","item","ComboboxChip","ComboboxChipsInput","ComboboxContent","ComboboxEmpty","ComboboxList","ComboboxItem","opt","INPUT_TYPE_BY_KIND","resolveInputType","kind","parseInputValue","raw","num","WellMetadataForm","fields","selectionSize","onApply","onClear","applyLabel","clearLabel","extras","className","setField","key","next","renderLabel","field","Label","renderCustom","fieldValue","renderSelect","Select","v","SelectTrigger","SelectValue","SelectContent","SelectItem","renderMultiSelect","current","renderBoolean","checked","Switch","c","Checkbox","renderInput","Input","e","renderField","cn","Button"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const f=require("./wellGrid.cjs");function p(s,n,o){const{rows:c,columns:t}=s;if(n==="row-major")return f.pos(Math.floor(o/t),o%t,t);if(n==="column-major")return f.pos(o%c,Math.floor(o/c),t);if(n==="row-snake"){const i=Math.floor(o/t),e=o%t,l=i%2===0?e:t-1-e;return f.pos(i,l,t)}const r=Math.floor(o/c),u=o%c,a=r%2===0?u:c-1-u;return f.pos(a,r,t)}function m(s,n,o){if(!o||!f.parsePos(o,s))return 0;const t=s.rows*s.columns;for(let r=0;r<t;r++)if(p(s,n,r)===o)return r;return 0}function h(s){const{dims:n,count:o,startWellId:c,strategy:t="row-major",replicates:r=1}=s;if(o<=0||r<=0)return[];const u=n.rows*n.columns,a=m(n,t,c),i=Math.min(u,a+o*r),e=[];for(let l=a;l<i;l++)e.push(p(n,t,l));return e}function M(s,n,o){const c=h({...o,count:s.length}),t=o.replicates??1,r=new Map;return c.forEach((u,a)=>{const i=Math.floor(a/t),e=s[i];e!==void 0&&r.set(u,n(e,i,u))}),r}exports.autoFillPositions=h;exports.autoFillRecords=M;
|
|
2
|
+
//# sourceMappingURL=autoFill.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoFill.cjs","sources":["../../../../src/components/composed/PlateMapEditor/autoFill.ts"],"sourcesContent":["import { parsePos, pos } from \"./wellGrid\";\n\nimport type { PlateDimensions, WellId } from \"./types\";\n\nexport type FillStrategy = \"row-major\" | \"column-major\" | \"row-snake\" | \"column-snake\";\n\nexport interface AutoFillOptions {\n dims: PlateDimensions;\n /** Number of distinct items to place. Each is repeated `replicates` times. */\n count: number;\n /** First well in fill order. Defaults to position (0,0). */\n startWellId?: WellId;\n /** Traversal strategy. Defaults to `\"row-major\"`. */\n strategy?: FillStrategy;\n /** Consecutive cells assigned per item. Defaults to 1. */\n replicates?: number;\n}\n\nfunction positionAtIndex(dims: PlateDimensions, strategy: FillStrategy, index: number): WellId {\n const { rows, columns } = dims;\n if (strategy === \"row-major\") {\n return pos(Math.floor(index / columns), index % columns, columns);\n }\n if (strategy === \"column-major\") {\n return pos(index % rows, Math.floor(index / rows), columns);\n }\n if (strategy === \"row-snake\") {\n const r = Math.floor(index / columns);\n const i = index % columns;\n const c = r % 2 === 0 ? i : columns - 1 - i;\n return pos(r, c, columns);\n }\n const c = Math.floor(index / rows);\n const i = index % rows;\n const r = c % 2 === 0 ? i : rows - 1 - i;\n return pos(r, c, columns);\n}\n\nfunction findStartIndex(dims: PlateDimensions, strategy: FillStrategy, startWellId: WellId | undefined): number {\n if (!startWellId) return 0;\n const parsed = parsePos(startWellId, dims);\n if (!parsed) return 0;\n const total = dims.rows * dims.columns;\n for (let i = 0; i < total; i++) {\n if (positionAtIndex(dims, strategy, i) === startWellId) return i;\n }\n return 0;\n}\n\n/**\n * Compute the ordered list of well ids to assign to `count` items (each\n * repeated `replicates` times) starting from `startWellId`. Returns at most\n * `dims.rows * dims.columns` ids — overflow is silently truncated so callers\n * can paginate onto multiple plates themselves.\n */\nexport function autoFillPositions(options: AutoFillOptions): WellId[] {\n const { dims, count, startWellId, strategy = \"row-major\", replicates = 1 } = options;\n if (count <= 0 || replicates <= 0) return [];\n\n const total = dims.rows * dims.columns;\n const startIdx = findStartIndex(dims, strategy, startWellId);\n const end = Math.min(total, startIdx + count * replicates);\n const out: WellId[] = [];\n for (let i = startIdx; i < end; i++) {\n out.push(positionAtIndex(dims, strategy, i));\n }\n return out;\n}\n\n/**\n * Convenience wrapper: assigns each input item to `replicates` consecutive\n * wells, returning a `Map<WellId, T>`. The mapper builds the record stored at\n * each well (e.g. stamp item-specific fields onto a base record).\n */\nexport function autoFillRecords<T>(\n items: T[],\n buildRecord: (item: T, index: number, wellId: WellId) => T,\n options: Omit<AutoFillOptions, \"count\">,\n): Map<WellId, T> {\n const positions = autoFillPositions({ ...options, count: items.length });\n const replicates = options.replicates ?? 1;\n const next = new Map<WellId, T>();\n positions.forEach((wellId, idx) => {\n const itemIndex = Math.floor(idx / replicates);\n const item = items[itemIndex];\n if (item === undefined) return;\n next.set(wellId, buildRecord(item, itemIndex, wellId));\n });\n return next;\n}\n"],"names":["positionAtIndex","dims","strategy","index","rows","columns","pos","r","i","c","findStartIndex","startWellId","parsePos","total","autoFillPositions","options","count","replicates","startIdx","end","out","autoFillRecords","items","buildRecord","positions","next","wellId","idx","itemIndex","item"],"mappings":"kHAkBA,SAASA,EAAgBC,EAAuBC,EAAwBC,EAAuB,CAC7F,KAAM,CAAE,KAAAC,EAAM,QAAAC,CAAA,EAAYJ,EAC1B,GAAIC,IAAa,YACf,OAAOI,EAAAA,IAAI,KAAK,MAAMH,EAAQE,CAAO,EAAGF,EAAQE,EAASA,CAAO,EAElE,GAAIH,IAAa,eACf,OAAOI,EAAAA,IAAIH,EAAQC,EAAM,KAAK,MAAMD,EAAQC,CAAI,EAAGC,CAAO,EAE5D,GAAIH,IAAa,YAAa,CAC5B,MAAMK,EAAI,KAAK,MAAMJ,EAAQE,CAAO,EAC9BG,EAAIL,EAAQE,EACZI,EAAIF,EAAI,IAAM,EAAIC,EAAIH,EAAU,EAAIG,EAC1C,OAAOF,MAAIC,EAAGE,EAAGJ,CAAO,CAC1B,CACA,MAAMI,EAAI,KAAK,MAAMN,EAAQC,CAAI,EAC3BI,EAAIL,EAAQC,EACZG,EAAIE,EAAI,IAAM,EAAID,EAAIJ,EAAO,EAAII,EACvC,OAAOF,MAAIC,EAAGE,EAAGJ,CAAO,CAC1B,CAEA,SAASK,EAAeT,EAAuBC,EAAwBS,EAAyC,CAG9G,GAFI,CAACA,GAED,CADWC,EAAAA,SAASD,EAAaV,CAAI,EAC5B,MAAO,GACpB,MAAMY,EAAQZ,EAAK,KAAOA,EAAK,QAC/B,QAASO,EAAI,EAAGA,EAAIK,EAAOL,IACzB,GAAIR,EAAgBC,EAAMC,EAAUM,CAAC,IAAMG,EAAa,OAAOH,EAEjE,MAAO,EACT,CAQO,SAASM,EAAkBC,EAAoC,CACpE,KAAM,CAAE,KAAAd,EAAM,MAAAe,EAAO,YAAAL,EAAa,SAAAT,EAAW,YAAa,WAAAe,EAAa,GAAMF,EAC7E,GAAIC,GAAS,GAAKC,GAAc,QAAU,CAAA,EAE1C,MAAMJ,EAAQZ,EAAK,KAAOA,EAAK,QACzBiB,EAAWR,EAAeT,EAAMC,EAAUS,CAAW,EACrDQ,EAAM,KAAK,IAAIN,EAAOK,EAAWF,EAAQC,CAAU,EACnDG,EAAgB,CAAA,EACtB,QAASZ,EAAIU,EAAUV,EAAIW,EAAKX,IAC9BY,EAAI,KAAKpB,EAAgBC,EAAMC,EAAUM,CAAC,CAAC,EAE7C,OAAOY,CACT,CAOO,SAASC,EACdC,EACAC,EACAR,EACgB,CAChB,MAAMS,EAAYV,EAAkB,CAAE,GAAGC,EAAS,MAAOO,EAAM,OAAQ,EACjEL,EAAaF,EAAQ,YAAc,EACnCU,MAAW,IACjB,OAAAD,EAAU,QAAQ,CAACE,EAAQC,IAAQ,CACjC,MAAMC,EAAY,KAAK,MAAMD,EAAMV,CAAU,EACvCY,EAAOP,EAAMM,CAAS,EACxBC,IAAS,QACbJ,EAAK,IAAIC,EAAQH,EAAYM,EAAMD,EAAWF,CAAM,CAAC,CACvD,CAAC,EACMD,CACT"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { parsePos as h, pos as l } from "./wellGrid.js";
|
|
2
|
+
function p(s, n, o) {
|
|
3
|
+
const { rows: c, columns: t } = s;
|
|
4
|
+
if (n === "row-major")
|
|
5
|
+
return l(Math.floor(o / t), o % t, t);
|
|
6
|
+
if (n === "column-major")
|
|
7
|
+
return l(o % c, Math.floor(o / c), t);
|
|
8
|
+
if (n === "row-snake") {
|
|
9
|
+
const a = Math.floor(o / t), u = o % t, i = a % 2 === 0 ? u : t - 1 - u;
|
|
10
|
+
return l(a, i, t);
|
|
11
|
+
}
|
|
12
|
+
const r = Math.floor(o / c), e = o % c, f = r % 2 === 0 ? e : c - 1 - e;
|
|
13
|
+
return l(f, r, t);
|
|
14
|
+
}
|
|
15
|
+
function m(s, n, o) {
|
|
16
|
+
if (!o || !h(o, s)) return 0;
|
|
17
|
+
const t = s.rows * s.columns;
|
|
18
|
+
for (let r = 0; r < t; r++)
|
|
19
|
+
if (p(s, n, r) === o) return r;
|
|
20
|
+
return 0;
|
|
21
|
+
}
|
|
22
|
+
function M(s) {
|
|
23
|
+
const { dims: n, count: o, startWellId: c, strategy: t = "row-major", replicates: r = 1 } = s;
|
|
24
|
+
if (o <= 0 || r <= 0) return [];
|
|
25
|
+
const e = n.rows * n.columns, f = m(n, t, c), a = Math.min(e, f + o * r), u = [];
|
|
26
|
+
for (let i = f; i < a; i++)
|
|
27
|
+
u.push(p(n, t, i));
|
|
28
|
+
return u;
|
|
29
|
+
}
|
|
30
|
+
function j(s, n, o) {
|
|
31
|
+
const c = M({ ...o, count: s.length }), t = o.replicates ?? 1, r = /* @__PURE__ */ new Map();
|
|
32
|
+
return c.forEach((e, f) => {
|
|
33
|
+
const a = Math.floor(f / t), u = s[a];
|
|
34
|
+
u !== void 0 && r.set(e, n(u, a, e));
|
|
35
|
+
}), r;
|
|
36
|
+
}
|
|
37
|
+
export {
|
|
38
|
+
M as autoFillPositions,
|
|
39
|
+
j as autoFillRecords
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=autoFill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"autoFill.js","sources":["../../../../src/components/composed/PlateMapEditor/autoFill.ts"],"sourcesContent":["import { parsePos, pos } from \"./wellGrid\";\n\nimport type { PlateDimensions, WellId } from \"./types\";\n\nexport type FillStrategy = \"row-major\" | \"column-major\" | \"row-snake\" | \"column-snake\";\n\nexport interface AutoFillOptions {\n dims: PlateDimensions;\n /** Number of distinct items to place. Each is repeated `replicates` times. */\n count: number;\n /** First well in fill order. Defaults to position (0,0). */\n startWellId?: WellId;\n /** Traversal strategy. Defaults to `\"row-major\"`. */\n strategy?: FillStrategy;\n /** Consecutive cells assigned per item. Defaults to 1. */\n replicates?: number;\n}\n\nfunction positionAtIndex(dims: PlateDimensions, strategy: FillStrategy, index: number): WellId {\n const { rows, columns } = dims;\n if (strategy === \"row-major\") {\n return pos(Math.floor(index / columns), index % columns, columns);\n }\n if (strategy === \"column-major\") {\n return pos(index % rows, Math.floor(index / rows), columns);\n }\n if (strategy === \"row-snake\") {\n const r = Math.floor(index / columns);\n const i = index % columns;\n const c = r % 2 === 0 ? i : columns - 1 - i;\n return pos(r, c, columns);\n }\n const c = Math.floor(index / rows);\n const i = index % rows;\n const r = c % 2 === 0 ? i : rows - 1 - i;\n return pos(r, c, columns);\n}\n\nfunction findStartIndex(dims: PlateDimensions, strategy: FillStrategy, startWellId: WellId | undefined): number {\n if (!startWellId) return 0;\n const parsed = parsePos(startWellId, dims);\n if (!parsed) return 0;\n const total = dims.rows * dims.columns;\n for (let i = 0; i < total; i++) {\n if (positionAtIndex(dims, strategy, i) === startWellId) return i;\n }\n return 0;\n}\n\n/**\n * Compute the ordered list of well ids to assign to `count` items (each\n * repeated `replicates` times) starting from `startWellId`. Returns at most\n * `dims.rows * dims.columns` ids — overflow is silently truncated so callers\n * can paginate onto multiple plates themselves.\n */\nexport function autoFillPositions(options: AutoFillOptions): WellId[] {\n const { dims, count, startWellId, strategy = \"row-major\", replicates = 1 } = options;\n if (count <= 0 || replicates <= 0) return [];\n\n const total = dims.rows * dims.columns;\n const startIdx = findStartIndex(dims, strategy, startWellId);\n const end = Math.min(total, startIdx + count * replicates);\n const out: WellId[] = [];\n for (let i = startIdx; i < end; i++) {\n out.push(positionAtIndex(dims, strategy, i));\n }\n return out;\n}\n\n/**\n * Convenience wrapper: assigns each input item to `replicates` consecutive\n * wells, returning a `Map<WellId, T>`. The mapper builds the record stored at\n * each well (e.g. stamp item-specific fields onto a base record).\n */\nexport function autoFillRecords<T>(\n items: T[],\n buildRecord: (item: T, index: number, wellId: WellId) => T,\n options: Omit<AutoFillOptions, \"count\">,\n): Map<WellId, T> {\n const positions = autoFillPositions({ ...options, count: items.length });\n const replicates = options.replicates ?? 1;\n const next = new Map<WellId, T>();\n positions.forEach((wellId, idx) => {\n const itemIndex = Math.floor(idx / replicates);\n const item = items[itemIndex];\n if (item === undefined) return;\n next.set(wellId, buildRecord(item, itemIndex, wellId));\n });\n return next;\n}\n"],"names":["positionAtIndex","dims","strategy","index","rows","columns","pos","r","i","c","findStartIndex","startWellId","parsePos","total","autoFillPositions","options","count","replicates","startIdx","end","out","autoFillRecords","items","buildRecord","positions","next","wellId","idx","itemIndex","item"],"mappings":";AAkBA,SAASA,EAAgBC,GAAuBC,GAAwBC,GAAuB;AAC7F,QAAM,EAAE,MAAAC,GAAM,SAAAC,EAAA,IAAYJ;AAC1B,MAAIC,MAAa;AACf,WAAOI,EAAI,KAAK,MAAMH,IAAQE,CAAO,GAAGF,IAAQE,GAASA,CAAO;AAElE,MAAIH,MAAa;AACf,WAAOI,EAAIH,IAAQC,GAAM,KAAK,MAAMD,IAAQC,CAAI,GAAGC,CAAO;AAE5D,MAAIH,MAAa,aAAa;AAC5B,UAAMK,IAAI,KAAK,MAAMJ,IAAQE,CAAO,GAC9BG,IAAIL,IAAQE,GACZI,IAAIF,IAAI,MAAM,IAAIC,IAAIH,IAAU,IAAIG;AAC1C,WAAOF,EAAIC,GAAGE,GAAGJ,CAAO;AAAA,EAC1B;AACA,QAAMI,IAAI,KAAK,MAAMN,IAAQC,CAAI,GAC3BI,IAAIL,IAAQC,GACZG,IAAIE,IAAI,MAAM,IAAID,IAAIJ,IAAO,IAAII;AACvC,SAAOF,EAAIC,GAAGE,GAAGJ,CAAO;AAC1B;AAEA,SAASK,EAAeT,GAAuBC,GAAwBS,GAAyC;AAG9G,MAFI,CAACA,KAED,CADWC,EAASD,GAAaV,CAAI,EAC5B,QAAO;AACpB,QAAMY,IAAQZ,EAAK,OAAOA,EAAK;AAC/B,WAASO,IAAI,GAAGA,IAAIK,GAAOL;AACzB,QAAIR,EAAgBC,GAAMC,GAAUM,CAAC,MAAMG,EAAa,QAAOH;AAEjE,SAAO;AACT;AAQO,SAASM,EAAkBC,GAAoC;AACpE,QAAM,EAAE,MAAAd,GAAM,OAAAe,GAAO,aAAAL,GAAa,UAAAT,IAAW,aAAa,YAAAe,IAAa,MAAMF;AAC7E,MAAIC,KAAS,KAAKC,KAAc,UAAU,CAAA;AAE1C,QAAMJ,IAAQZ,EAAK,OAAOA,EAAK,SACzBiB,IAAWR,EAAeT,GAAMC,GAAUS,CAAW,GACrDQ,IAAM,KAAK,IAAIN,GAAOK,IAAWF,IAAQC,CAAU,GACnDG,IAAgB,CAAA;AACtB,WAAS,IAAIF,GAAU,IAAIC,GAAK;AAC9B,IAAAC,EAAI,KAAKpB,EAAgBC,GAAMC,GAAU,CAAC,CAAC;AAE7C,SAAOkB;AACT;AAOO,SAASC,EACdC,GACAC,GACAR,GACgB;AAChB,QAAMS,IAAYV,EAAkB,EAAE,GAAGC,GAAS,OAAOO,EAAM,QAAQ,GACjEL,IAAaF,EAAQ,cAAc,GACnCU,wBAAW,IAAA;AACjB,SAAAD,EAAU,QAAQ,CAACE,GAAQC,MAAQ;AACjC,UAAMC,IAAY,KAAK,MAAMD,IAAMV,CAAU,GACvCY,IAAOP,EAAMM,CAAS;AAC5B,IAAIC,MAAS,UACbJ,EAAK,IAAIC,GAAQH,EAAYM,GAAMD,GAAWF,CAAM,CAAC;AAAA,EACvD,CAAC,GACMD;AACT;"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const C=["plate barcode","plate_barcode","plate-barcode","plateBarcode","plate id","plate_id","plateId"],v=new Set(["text/csv","application/vnd.ms-excel"]);function u(r){return r.trim().toLowerCase().replace(/[^a-z0-9]/g,"")}function p(r,e){return[...r,e]}function d(r,e,o){const t=p(e,o);return t.some(s=>s.trim()!=="")?{records:[...r,t],record:[]}:{records:r,record:[]}}function g(r,e,o){const t=r[e];return t!=='"'?{field:`${o}${t}`,quoted:!0,index:e}:r[e+1]==='"'?{field:`${o}"`,quoted:!0,index:e+1}:{field:o,quoted:!1,index:e}}function h(r){let e=[],o=[],t="",s=!1;for(let n=0;n<r.length;n+=1){const a=r[n];if(s){const c=g(r,n,t);t=c.field,s=c.quoted,n=c.index}else if(a==='"'&&t==="")s=!0;else if(a===",")o=p(o,t),t="";else if(a===`
|
|
2
|
+
`||a==="\r"){const c=d(e,o,t);e=c.records,o=c.record,t="",a==="\r"&&r[n+1]===`
|
|
3
|
+
`&&(n+=1)}else t=`${t}${a}`}return(t!==""||o.length>0)&&(e=d(e,o,t).records),e}function w(r,e){const o=[e?.plateBarcodeColumn,...e?.plateBarcodeColumnAliases??[],...C].filter(t=>!!t).map(u);return r.find(t=>o.includes(u(t)))}function B(r,e,o){const t=r.reduce((s,n,a)=>(s[n]=e[a]??"",s),{});return{line:o+2,values:t}}function M(r,e){const o=new Map,t=[];return r.forEach(s=>{const n=e?s.values[e]?.trim():"";if(!n){t.push(s);return}const a=o.get(n)??[];o.set(n,[...a,s])}),{plateRows:o,missingBarcodeRows:t}}function f(r,e){const o=h(r),t=o[0]?.map(i=>i.trim())??[],s=w(t,e),n=o.slice(1).map((i,l)=>B(t,i,l)),{plateRows:a,missingBarcodeRows:c}=M(n,s),m=[...a.entries()].map(([i,l])=>({id:i,barcode:i,rows:l,rowCount:l.length}));return{headers:t,plateBarcodeColumn:s,rows:n,plates:m,missingBarcodeRows:c}}function R(r){return r.plates.map(e=>({id:e.id,barcode:e.barcode,count:e.rowCount}))}async function P(r,e){if(r.name.toLowerCase().endsWith(".csv")||v.has(r.type))return f(await r.text(),e)}exports.plateOptionsFromCsvTriage=R;exports.triagePlateMapCsvByBarcode=f;exports.triagePlateMapCsvFile=P;
|
|
4
|
+
//# sourceMappingURL=csvPlateTriage.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csvPlateTriage.cjs","sources":["../../../../src/components/composed/PlateMapEditor/csvPlateTriage.ts"],"sourcesContent":["import type {\n PlateMapCsvPlate,\n PlateMapCsvRow,\n PlateMapCsvTriage,\n PlateMapCsvTriageOptions,\n PlateMapPlateOption,\n} from \"./types\";\n\nconst DEFAULT_PLATE_BARCODE_COLUMNS = [\n \"plate barcode\",\n \"plate_barcode\",\n \"plate-barcode\",\n \"plateBarcode\",\n \"plate id\",\n \"plate_id\",\n \"plateId\",\n];\n\nconst CSV_MIME_TYPES = new Set([\"text/csv\", \"application/vnd.ms-excel\"]);\n\nfunction normalizeColumnName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\");\n}\n\nfunction pushCsvField(record: string[], field: string): string[] {\n return [...record, field];\n}\n\nfunction pushCsvRecord(\n records: string[][],\n record: string[],\n field: string,\n): { records: string[][]; record: string[] } {\n const nextRecord = pushCsvField(record, field);\n if (nextRecord.some((cell) => cell.trim() !== \"\")) {\n return { records: [...records, nextRecord], record: [] };\n }\n return { records, record: [] };\n}\n\nfunction readQuotedCsvCharacter(text: string, index: number, field: string) {\n const char = text[index];\n if (char !== '\"') return { field: `${field}${char}`, quoted: true, index };\n if (text[index + 1] === '\"') return { field: `${field}\"`, quoted: true, index: index + 1 };\n return { field, quoted: false, index };\n}\n\nfunction parseCsvRecords(text: string): string[][] {\n let records: string[][] = [];\n let record: string[] = [];\n let field = \"\";\n let quoted = false;\n\n for (let index = 0; index < text.length; index += 1) {\n const char = text[index];\n\n if (quoted) {\n const next = readQuotedCsvCharacter(text, index, field);\n field = next.field;\n quoted = next.quoted;\n index = next.index;\n } else if (char === '\"' && field === \"\") {\n quoted = true;\n } else if (char === \",\") {\n record = pushCsvField(record, field);\n field = \"\";\n } else if (char === \"\\n\" || char === \"\\r\") {\n const next = pushCsvRecord(records, record, field);\n records = next.records;\n record = next.record;\n field = \"\";\n if (char === \"\\r\" && text[index + 1] === \"\\n\") index += 1;\n } else {\n field = `${field}${char}`;\n }\n }\n\n if (field !== \"\" || record.length > 0) {\n records = pushCsvRecord(records, record, field).records;\n }\n\n return records;\n}\n\nfunction resolvePlateBarcodeColumn(headers: string[], options?: PlateMapCsvTriageOptions): string | undefined {\n const candidates = [\n options?.plateBarcodeColumn,\n ...(options?.plateBarcodeColumnAliases ?? []),\n ...DEFAULT_PLATE_BARCODE_COLUMNS,\n ]\n .filter((candidate): candidate is string => !!candidate)\n .map(normalizeColumnName);\n\n return headers.find((header) => candidates.includes(normalizeColumnName(header)));\n}\n\nfunction recordToRow(headers: string[], record: string[], recordIndex: number): PlateMapCsvRow {\n const values = headers.reduce<Record<string, string>>((acc, header, headerIndex) => {\n acc[header] = record[headerIndex] ?? \"\";\n return acc;\n }, {});\n\n return {\n line: recordIndex + 2,\n values,\n };\n}\n\nfunction groupRowsByBarcode(rows: PlateMapCsvRow[], plateBarcodeColumn: string | undefined) {\n const plateRows = new Map<string, PlateMapCsvRow[]>();\n const missingBarcodeRows: PlateMapCsvRow[] = [];\n\n rows.forEach((row) => {\n const barcode = plateBarcodeColumn ? row.values[plateBarcodeColumn]?.trim() : \"\";\n if (!barcode) {\n missingBarcodeRows.push(row);\n return;\n }\n\n const rowsForBarcode = plateRows.get(barcode) ?? [];\n plateRows.set(barcode, [...rowsForBarcode, row]);\n });\n\n return { plateRows, missingBarcodeRows };\n}\n\nexport function triagePlateMapCsvByBarcode(text: string, options?: PlateMapCsvTriageOptions): PlateMapCsvTriage {\n const records = parseCsvRecords(text);\n const headers = records[0]?.map((header) => header.trim()) ?? [];\n const plateBarcodeColumn = resolvePlateBarcodeColumn(headers, options);\n const rows = records.slice(1).map((record, recordIndex) => recordToRow(headers, record, recordIndex));\n const { plateRows, missingBarcodeRows } = groupRowsByBarcode(rows, plateBarcodeColumn);\n const plates: PlateMapCsvPlate[] = [...plateRows.entries()].map(([barcode, plateRowsForBarcode]) => ({\n id: barcode,\n barcode,\n rows: plateRowsForBarcode,\n rowCount: plateRowsForBarcode.length,\n }));\n\n return {\n headers,\n plateBarcodeColumn,\n rows,\n plates,\n missingBarcodeRows,\n };\n}\n\nexport function plateOptionsFromCsvTriage(triage: PlateMapCsvTriage): PlateMapPlateOption[] {\n return triage.plates.map((plate) => ({\n id: plate.id,\n barcode: plate.barcode,\n count: plate.rowCount,\n }));\n}\n\nexport async function triagePlateMapCsvFile(\n file: File,\n options?: PlateMapCsvTriageOptions,\n): Promise<PlateMapCsvTriage | undefined> {\n const fileName = file.name.toLowerCase();\n const isCsv = fileName.endsWith(\".csv\") || CSV_MIME_TYPES.has(file.type);\n if (!isCsv) return undefined;\n\n return triagePlateMapCsvByBarcode(await file.text(), options);\n}\n"],"names":["DEFAULT_PLATE_BARCODE_COLUMNS","CSV_MIME_TYPES","normalizeColumnName","value","pushCsvField","record","field","pushCsvRecord","records","nextRecord","cell","readQuotedCsvCharacter","text","index","char","parseCsvRecords","quoted","next","resolvePlateBarcodeColumn","headers","options","candidates","candidate","header","recordToRow","recordIndex","values","acc","headerIndex","groupRowsByBarcode","rows","plateBarcodeColumn","plateRows","missingBarcodeRows","row","barcode","rowsForBarcode","triagePlateMapCsvByBarcode","plates","plateRowsForBarcode","plateOptionsFromCsvTriage","triage","plate","triagePlateMapCsvFile","file"],"mappings":"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"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
const m = [
|
|
2
|
+
"plate barcode",
|
|
3
|
+
"plate_barcode",
|
|
4
|
+
"plate-barcode",
|
|
5
|
+
"plateBarcode",
|
|
6
|
+
"plate id",
|
|
7
|
+
"plate_id",
|
|
8
|
+
"plateId"
|
|
9
|
+
], C = /* @__PURE__ */ new Set(["text/csv", "application/vnd.ms-excel"]);
|
|
10
|
+
function d(t) {
|
|
11
|
+
return t.trim().toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
12
|
+
}
|
|
13
|
+
function f(t, e) {
|
|
14
|
+
return [...t, e];
|
|
15
|
+
}
|
|
16
|
+
function l(t, e, o) {
|
|
17
|
+
const r = f(e, o);
|
|
18
|
+
return r.some((s) => s.trim() !== "") ? { records: [...t, r], record: [] } : { records: t, record: [] };
|
|
19
|
+
}
|
|
20
|
+
function v(t, e, o) {
|
|
21
|
+
const r = t[e];
|
|
22
|
+
return r !== '"' ? { field: `${o}${r}`, quoted: !0, index: e } : t[e + 1] === '"' ? { field: `${o}"`, quoted: !0, index: e + 1 } : { field: o, quoted: !1, index: e };
|
|
23
|
+
}
|
|
24
|
+
function h(t) {
|
|
25
|
+
let e = [], o = [], r = "", s = !1;
|
|
26
|
+
for (let n = 0; n < t.length; n += 1) {
|
|
27
|
+
const c = t[n];
|
|
28
|
+
if (s) {
|
|
29
|
+
const a = v(t, n, r);
|
|
30
|
+
r = a.field, s = a.quoted, n = a.index;
|
|
31
|
+
} else if (c === '"' && r === "")
|
|
32
|
+
s = !0;
|
|
33
|
+
else if (c === ",")
|
|
34
|
+
o = f(o, r), r = "";
|
|
35
|
+
else if (c === `
|
|
36
|
+
` || c === "\r") {
|
|
37
|
+
const a = l(e, o, r);
|
|
38
|
+
e = a.records, o = a.record, r = "", c === "\r" && t[n + 1] === `
|
|
39
|
+
` && (n += 1);
|
|
40
|
+
} else
|
|
41
|
+
r = `${r}${c}`;
|
|
42
|
+
}
|
|
43
|
+
return (r !== "" || o.length > 0) && (e = l(e, o, r).records), e;
|
|
44
|
+
}
|
|
45
|
+
function w(t, e) {
|
|
46
|
+
const o = [
|
|
47
|
+
e?.plateBarcodeColumn,
|
|
48
|
+
...e?.plateBarcodeColumnAliases ?? [],
|
|
49
|
+
...m
|
|
50
|
+
].filter((r) => !!r).map(d);
|
|
51
|
+
return t.find((r) => o.includes(d(r)));
|
|
52
|
+
}
|
|
53
|
+
function g(t, e, o) {
|
|
54
|
+
const r = t.reduce((s, n, c) => (s[n] = e[c] ?? "", s), {});
|
|
55
|
+
return {
|
|
56
|
+
line: o + 2,
|
|
57
|
+
values: r
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
function B(t, e) {
|
|
61
|
+
const o = /* @__PURE__ */ new Map(), r = [];
|
|
62
|
+
return t.forEach((s) => {
|
|
63
|
+
const n = e ? s.values[e]?.trim() : "";
|
|
64
|
+
if (!n) {
|
|
65
|
+
r.push(s);
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const c = o.get(n) ?? [];
|
|
69
|
+
o.set(n, [...c, s]);
|
|
70
|
+
}), { plateRows: o, missingBarcodeRows: r };
|
|
71
|
+
}
|
|
72
|
+
function R(t, e) {
|
|
73
|
+
const o = h(t), r = o[0]?.map((i) => i.trim()) ?? [], s = w(r, e), n = o.slice(1).map((i, u) => g(r, i, u)), { plateRows: c, missingBarcodeRows: a } = B(n, s), p = [...c.entries()].map(([i, u]) => ({
|
|
74
|
+
id: i,
|
|
75
|
+
barcode: i,
|
|
76
|
+
rows: u,
|
|
77
|
+
rowCount: u.length
|
|
78
|
+
}));
|
|
79
|
+
return {
|
|
80
|
+
headers: r,
|
|
81
|
+
plateBarcodeColumn: s,
|
|
82
|
+
rows: n,
|
|
83
|
+
plates: p,
|
|
84
|
+
missingBarcodeRows: a
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
function _(t) {
|
|
88
|
+
return t.plates.map((e) => ({
|
|
89
|
+
id: e.id,
|
|
90
|
+
barcode: e.barcode,
|
|
91
|
+
count: e.rowCount
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
async function E(t, e) {
|
|
95
|
+
if (t.name.toLowerCase().endsWith(".csv") || C.has(t.type))
|
|
96
|
+
return R(await t.text(), e);
|
|
97
|
+
}
|
|
98
|
+
export {
|
|
99
|
+
_ as plateOptionsFromCsvTriage,
|
|
100
|
+
R as triagePlateMapCsvByBarcode,
|
|
101
|
+
E as triagePlateMapCsvFile
|
|
102
|
+
};
|
|
103
|
+
//# sourceMappingURL=csvPlateTriage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"csvPlateTriage.js","sources":["../../../../src/components/composed/PlateMapEditor/csvPlateTriage.ts"],"sourcesContent":["import type {\n PlateMapCsvPlate,\n PlateMapCsvRow,\n PlateMapCsvTriage,\n PlateMapCsvTriageOptions,\n PlateMapPlateOption,\n} from \"./types\";\n\nconst DEFAULT_PLATE_BARCODE_COLUMNS = [\n \"plate barcode\",\n \"plate_barcode\",\n \"plate-barcode\",\n \"plateBarcode\",\n \"plate id\",\n \"plate_id\",\n \"plateId\",\n];\n\nconst CSV_MIME_TYPES = new Set([\"text/csv\", \"application/vnd.ms-excel\"]);\n\nfunction normalizeColumnName(value: string): string {\n return value\n .trim()\n .toLowerCase()\n .replace(/[^a-z0-9]/g, \"\");\n}\n\nfunction pushCsvField(record: string[], field: string): string[] {\n return [...record, field];\n}\n\nfunction pushCsvRecord(\n records: string[][],\n record: string[],\n field: string,\n): { records: string[][]; record: string[] } {\n const nextRecord = pushCsvField(record, field);\n if (nextRecord.some((cell) => cell.trim() !== \"\")) {\n return { records: [...records, nextRecord], record: [] };\n }\n return { records, record: [] };\n}\n\nfunction readQuotedCsvCharacter(text: string, index: number, field: string) {\n const char = text[index];\n if (char !== '\"') return { field: `${field}${char}`, quoted: true, index };\n if (text[index + 1] === '\"') return { field: `${field}\"`, quoted: true, index: index + 1 };\n return { field, quoted: false, index };\n}\n\nfunction parseCsvRecords(text: string): string[][] {\n let records: string[][] = [];\n let record: string[] = [];\n let field = \"\";\n let quoted = false;\n\n for (let index = 0; index < text.length; index += 1) {\n const char = text[index];\n\n if (quoted) {\n const next = readQuotedCsvCharacter(text, index, field);\n field = next.field;\n quoted = next.quoted;\n index = next.index;\n } else if (char === '\"' && field === \"\") {\n quoted = true;\n } else if (char === \",\") {\n record = pushCsvField(record, field);\n field = \"\";\n } else if (char === \"\\n\" || char === \"\\r\") {\n const next = pushCsvRecord(records, record, field);\n records = next.records;\n record = next.record;\n field = \"\";\n if (char === \"\\r\" && text[index + 1] === \"\\n\") index += 1;\n } else {\n field = `${field}${char}`;\n }\n }\n\n if (field !== \"\" || record.length > 0) {\n records = pushCsvRecord(records, record, field).records;\n }\n\n return records;\n}\n\nfunction resolvePlateBarcodeColumn(headers: string[], options?: PlateMapCsvTriageOptions): string | undefined {\n const candidates = [\n options?.plateBarcodeColumn,\n ...(options?.plateBarcodeColumnAliases ?? []),\n ...DEFAULT_PLATE_BARCODE_COLUMNS,\n ]\n .filter((candidate): candidate is string => !!candidate)\n .map(normalizeColumnName);\n\n return headers.find((header) => candidates.includes(normalizeColumnName(header)));\n}\n\nfunction recordToRow(headers: string[], record: string[], recordIndex: number): PlateMapCsvRow {\n const values = headers.reduce<Record<string, string>>((acc, header, headerIndex) => {\n acc[header] = record[headerIndex] ?? \"\";\n return acc;\n }, {});\n\n return {\n line: recordIndex + 2,\n values,\n };\n}\n\nfunction groupRowsByBarcode(rows: PlateMapCsvRow[], plateBarcodeColumn: string | undefined) {\n const plateRows = new Map<string, PlateMapCsvRow[]>();\n const missingBarcodeRows: PlateMapCsvRow[] = [];\n\n rows.forEach((row) => {\n const barcode = plateBarcodeColumn ? row.values[plateBarcodeColumn]?.trim() : \"\";\n if (!barcode) {\n missingBarcodeRows.push(row);\n return;\n }\n\n const rowsForBarcode = plateRows.get(barcode) ?? [];\n plateRows.set(barcode, [...rowsForBarcode, row]);\n });\n\n return { plateRows, missingBarcodeRows };\n}\n\nexport function triagePlateMapCsvByBarcode(text: string, options?: PlateMapCsvTriageOptions): PlateMapCsvTriage {\n const records = parseCsvRecords(text);\n const headers = records[0]?.map((header) => header.trim()) ?? [];\n const plateBarcodeColumn = resolvePlateBarcodeColumn(headers, options);\n const rows = records.slice(1).map((record, recordIndex) => recordToRow(headers, record, recordIndex));\n const { plateRows, missingBarcodeRows } = groupRowsByBarcode(rows, plateBarcodeColumn);\n const plates: PlateMapCsvPlate[] = [...plateRows.entries()].map(([barcode, plateRowsForBarcode]) => ({\n id: barcode,\n barcode,\n rows: plateRowsForBarcode,\n rowCount: plateRowsForBarcode.length,\n }));\n\n return {\n headers,\n plateBarcodeColumn,\n rows,\n plates,\n missingBarcodeRows,\n };\n}\n\nexport function plateOptionsFromCsvTriage(triage: PlateMapCsvTriage): PlateMapPlateOption[] {\n return triage.plates.map((plate) => ({\n id: plate.id,\n barcode: plate.barcode,\n count: plate.rowCount,\n }));\n}\n\nexport async function triagePlateMapCsvFile(\n file: File,\n options?: PlateMapCsvTriageOptions,\n): Promise<PlateMapCsvTriage | undefined> {\n const fileName = file.name.toLowerCase();\n const isCsv = fileName.endsWith(\".csv\") || CSV_MIME_TYPES.has(file.type);\n if (!isCsv) return undefined;\n\n return triagePlateMapCsvByBarcode(await file.text(), options);\n}\n"],"names":["DEFAULT_PLATE_BARCODE_COLUMNS","CSV_MIME_TYPES","normalizeColumnName","value","pushCsvField","record","field","pushCsvRecord","records","nextRecord","cell","readQuotedCsvCharacter","text","index","char","parseCsvRecords","quoted","next","resolvePlateBarcodeColumn","headers","options","candidates","candidate","header","recordToRow","recordIndex","values","acc","headerIndex","groupRowsByBarcode","rows","plateBarcodeColumn","plateRows","missingBarcodeRows","row","barcode","rowsForBarcode","triagePlateMapCsvByBarcode","plates","plateRowsForBarcode","plateOptionsFromCsvTriage","triage","plate","triagePlateMapCsvFile","file"],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function s(r){const t=new Map;return(r??[]).forEach(e=>{const o=e.group??"",n=t.get(o)??[];n.push(e),t.set(o,n)}),[...t.entries()]}exports.groupTemplateOptions=s;
|
|
2
|
+
//# sourceMappingURL=helpers.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.cjs","sources":["../../../../src/components/composed/PlateMapEditor/helpers.ts"],"sourcesContent":["import type { TemplateOption } from \"./types\";\n\nexport function groupTemplateOptions(templates: TemplateOption[] | undefined): [string, TemplateOption[]][] {\n const groups = new Map<string, TemplateOption[]>();\n (templates ?? []).forEach((template) => {\n const key = template.group ?? \"\";\n const list = groups.get(key) ?? [];\n list.push(template);\n groups.set(key, list);\n });\n return [...groups.entries()];\n}\n"],"names":["groupTemplateOptions","templates","groups","template","key","list"],"mappings":"gFAEO,SAASA,EAAqBC,EAAuE,CAC1G,MAAMC,MAAa,IACnB,OAACD,GAAa,CAAA,GAAI,QAASE,GAAa,CACtC,MAAMC,EAAMD,EAAS,OAAS,GACxBE,EAAOH,EAAO,IAAIE,CAAG,GAAK,CAAA,EAChCC,EAAK,KAAKF,CAAQ,EAClBD,EAAO,IAAIE,EAAKC,CAAI,CACtB,CAAC,EACM,CAAC,GAAGH,EAAO,SAAS,CAC7B"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
function r(e) {
|
|
2
|
+
const o = /* @__PURE__ */ new Map();
|
|
3
|
+
return (e ?? []).forEach((t) => {
|
|
4
|
+
const n = t.group ?? "", s = o.get(n) ?? [];
|
|
5
|
+
s.push(t), o.set(n, s);
|
|
6
|
+
}), [...o.entries()];
|
|
7
|
+
}
|
|
8
|
+
export {
|
|
9
|
+
r as groupTemplateOptions
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../../../src/components/composed/PlateMapEditor/helpers.ts"],"sourcesContent":["import type { TemplateOption } from \"./types\";\n\nexport function groupTemplateOptions(templates: TemplateOption[] | undefined): [string, TemplateOption[]][] {\n const groups = new Map<string, TemplateOption[]>();\n (templates ?? []).forEach((template) => {\n const key = template.group ?? \"\";\n const list = groups.get(key) ?? [];\n list.push(template);\n groups.set(key, list);\n });\n return [...groups.entries()];\n}\n"],"names":["groupTemplateOptions","templates","groups","template","key","list"],"mappings":"AAEO,SAASA,EAAqBC,GAAuE;AAC1G,QAAMC,wBAAa,IAAA;AACnB,UAACD,KAAa,CAAA,GAAI,QAAQ,CAACE,MAAa;AACtC,UAAMC,IAAMD,EAAS,SAAS,IACxBE,IAAOH,EAAO,IAAIE,CAAG,KAAK,CAAA;AAChC,IAAAC,EAAK,KAAKF,CAAQ,GAClBD,EAAO,IAAIE,GAAKC,CAAI;AAAA,EACtB,CAAC,GACM,CAAC,GAAGH,EAAO,SAAS;AAC7B;"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const I={96:{rows:8,columns:12},384:{rows:16,columns:24},1536:{rows:32,columns:48}},c=26,e=65,p=100,A=2,C=3;function D(o,t,n){return o==="custom"?{rows:t??8,columns:n??12}:I[o]}function m(o){if(o<c)return String.fromCharCode(e+o);const t=Math.floor(o/c)-1,n=o%c;return String.fromCharCode(e+t)+String.fromCharCode(e+n)}function P(o){return o.length===1?o.charCodeAt(0)-e:(o.charCodeAt(0)-e+1)*c+(o.charCodeAt(1)-e)}function S(o){return o>=p?C:A}function l(o,t,n){return`${m(o)}${String(t+1).padStart(S(n),"0")}`}function _(o,t){if(!o)return null;const n=/^([A-Z]{1,2})(\d+)$/.exec(o);if(!n)return null;const r=P(n[1]),s=parseInt(n[2],10)-1;return Number.isNaN(s)||r<0||r>=t.rows||s<0||s>=t.columns?null:{row:r,col:s}}function w(o,t,n,r,s){const a=[Math.min(o,n),Math.max(o,n)],f=[Math.min(t,r),Math.max(t,r)],h=[];for(let u=a[0];u<=a[1];u++)for(let i=f[0];i<=f[1];i++)h.push(l(u,i,s));return h}function L(o){const t=[];for(let n=0;n<o.rows;n++)for(let r=0;r<o.columns;r++)t.push(l(n,r,o.columns));return t}exports.allPositions=L;exports.parsePos=_;exports.parseRowLabel=P;exports.pos=l;exports.rectPositions=w;exports.resolveDimensions=D;exports.rowLabel=m;
|
|
2
|
+
//# sourceMappingURL=wellGrid.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wellGrid.cjs","sources":["../../../../src/components/composed/PlateMapEditor/wellGrid.ts"],"sourcesContent":["import type { PlateDimensions, PlateFormat, WellId } from \"./types\";\n\nconst FORMAT_DIMENSIONS: Record<Exclude<PlateFormat, \"custom\">, PlateDimensions> = {\n \"96\": { rows: 8, columns: 12 },\n \"384\": { rows: 16, columns: 24 },\n \"1536\": { rows: 32, columns: 48 },\n};\n\nconst ALPHABET_SIZE = 26;\nconst CHAR_CODE_A = 65;\nconst TRIPLE_DIGIT_THRESHOLD = 100;\nconst DOUBLE_DIGIT_PAD = 2;\nconst TRIPLE_DIGIT_PAD = 3;\n\nexport function resolveDimensions(\n format: PlateFormat,\n rows?: number,\n columns?: number,\n): PlateDimensions {\n if (format === \"custom\") {\n return {\n rows: rows ?? 8,\n columns: columns ?? 12,\n };\n }\n return FORMAT_DIMENSIONS[format];\n}\n\n/** Letter for a row index. Supports A-Z then AA-ZZ for 1536-format plates. */\nexport function rowLabel(row: number): string {\n if (row < ALPHABET_SIZE) return String.fromCharCode(CHAR_CODE_A + row);\n const high = Math.floor(row / ALPHABET_SIZE) - 1;\n const low = row % ALPHABET_SIZE;\n return (\n String.fromCharCode(CHAR_CODE_A + high) +\n String.fromCharCode(CHAR_CODE_A + low)\n );\n}\n\nexport function parseRowLabel(label: string): number {\n if (label.length === 1) return label.charCodeAt(0) - CHAR_CODE_A;\n return (\n (label.charCodeAt(0) - CHAR_CODE_A + 1) * ALPHABET_SIZE +\n (label.charCodeAt(1) - CHAR_CODE_A)\n );\n}\n\n/** Pad column number to a width that matches the plate's column count. */\nfunction colPadWidth(columns: number): number {\n return columns >= TRIPLE_DIGIT_THRESHOLD ? TRIPLE_DIGIT_PAD : DOUBLE_DIGIT_PAD;\n}\n\nexport function pos(row: number, col: number, columns: number): WellId {\n return `${rowLabel(row)}${String(col + 1).padStart(colPadWidth(columns), \"0\")}`;\n}\n\nexport function parsePos(\n id: WellId,\n dims: PlateDimensions,\n): { row: number; col: number } | null {\n if (!id) return null;\n const m = /^([A-Z]{1,2})(\\d+)$/.exec(id);\n if (!m) return null;\n const row = parseRowLabel(m[1]);\n const col = parseInt(m[2], 10) - 1;\n if (\n Number.isNaN(col) ||\n row < 0 ||\n row >= dims.rows ||\n col < 0 ||\n col >= dims.columns\n ) {\n return null;\n }\n return { row, col };\n}\n\nexport function rectPositions(\n r0: number,\n c0: number,\n r1: number,\n c1: number,\n columns: number,\n): WellId[] {\n const rs = [Math.min(r0, r1), Math.max(r0, r1)];\n const cs = [Math.min(c0, c1), Math.max(c0, c1)];\n const out: WellId[] = [];\n for (let r = rs[0]; r <= rs[1]; r++) {\n for (let c = cs[0]; c <= cs[1]; c++) {\n out.push(pos(r, c, columns));\n }\n }\n return out;\n}\n\nexport function allPositions(dims: PlateDimensions): WellId[] {\n const out: WellId[] = [];\n for (let r = 0; r < dims.rows; r++) {\n for (let c = 0; c < dims.columns; c++) {\n out.push(pos(r, c, dims.columns));\n }\n }\n return out;\n}\n"],"names":["FORMAT_DIMENSIONS","ALPHABET_SIZE","CHAR_CODE_A","TRIPLE_DIGIT_THRESHOLD","DOUBLE_DIGIT_PAD","TRIPLE_DIGIT_PAD","resolveDimensions","format","rows","columns","rowLabel","row","high","low","parseRowLabel","label","colPadWidth","pos","col","parsePos","id","dims","m","rectPositions","r0","c0","r1","c1","rs","cs","out","r","c","allPositions"],"mappings":"gFAEA,MAAMA,EAA6E,CACjF,GAAM,CAAE,KAAM,EAAG,QAAS,EAAA,EAC1B,IAAO,CAAE,KAAM,GAAI,QAAS,EAAA,EAC5B,KAAQ,CAAE,KAAM,GAAI,QAAS,EAAA,CAC/B,EAEMC,EAAgB,GAChBC,EAAc,GACdC,EAAyB,IACzBC,EAAmB,EACnBC,EAAmB,EAElB,SAASC,EACdC,EACAC,EACAC,EACiB,CACjB,OAAIF,IAAW,SACN,CACL,KAAMC,GAAQ,EACd,QAASC,GAAW,EAAA,EAGjBT,EAAkBO,CAAM,CACjC,CAGO,SAASG,EAASC,EAAqB,CAC5C,GAAIA,EAAMV,EAAe,OAAO,OAAO,aAAaC,EAAcS,CAAG,EACrE,MAAMC,EAAO,KAAK,MAAMD,EAAMV,CAAa,EAAI,EACzCY,EAAMF,EAAMV,EAClB,OACE,OAAO,aAAaC,EAAcU,CAAI,EACtC,OAAO,aAAaV,EAAcW,CAAG,CAEzC,CAEO,SAASC,EAAcC,EAAuB,CACnD,OAAIA,EAAM,SAAW,EAAUA,EAAM,WAAW,CAAC,EAAIb,GAElDa,EAAM,WAAW,CAAC,EAAIb,EAAc,GAAKD,GACzCc,EAAM,WAAW,CAAC,EAAIb,EAE3B,CAGA,SAASc,EAAYP,EAAyB,CAC5C,OAAOA,GAAWN,EAAyBE,EAAmBD,CAChE,CAEO,SAASa,EAAIN,EAAaO,EAAaT,EAAyB,CACrE,MAAO,GAAGC,EAASC,CAAG,CAAC,GAAG,OAAOO,EAAM,CAAC,EAAE,SAASF,EAAYP,CAAO,EAAG,GAAG,CAAC,EAC/E,CAEO,SAASU,EACdC,EACAC,EACqC,CACrC,GAAI,CAACD,EAAI,OAAO,KAChB,MAAME,EAAI,sBAAsB,KAAKF,CAAE,EACvC,GAAI,CAACE,EAAG,OAAO,KACf,MAAMX,EAAMG,EAAcQ,EAAE,CAAC,CAAC,EACxBJ,EAAM,SAASI,EAAE,CAAC,EAAG,EAAE,EAAI,EACjC,OACE,OAAO,MAAMJ,CAAG,GAChBP,EAAM,GACNA,GAAOU,EAAK,MACZH,EAAM,GACNA,GAAOG,EAAK,QAEL,KAEF,CAAE,IAAAV,EAAK,IAAAO,CAAA,CAChB,CAEO,SAASK,EACdC,EACAC,EACAC,EACAC,EACAlB,EACU,CACV,MAAMmB,EAAK,CAAC,KAAK,IAAIJ,EAAIE,CAAE,EAAG,KAAK,IAAIF,EAAIE,CAAE,CAAC,EACxCG,EAAK,CAAC,KAAK,IAAIJ,EAAIE,CAAE,EAAG,KAAK,IAAIF,EAAIE,CAAE,CAAC,EACxCG,EAAgB,CAAA,EACtB,QAASC,EAAIH,EAAG,CAAC,EAAGG,GAAKH,EAAG,CAAC,EAAGG,IAC9B,QAASC,EAAIH,EAAG,CAAC,EAAGG,GAAKH,EAAG,CAAC,EAAGG,IAC9BF,EAAI,KAAKb,EAAIc,EAAGC,EAAGvB,CAAO,CAAC,EAG/B,OAAOqB,CACT,CAEO,SAASG,EAAaZ,EAAiC,CAC5D,MAAMS,EAAgB,CAAA,EACtB,QAASC,EAAI,EAAGA,EAAIV,EAAK,KAAMU,IAC7B,QAASC,EAAI,EAAGA,EAAIX,EAAK,QAASW,IAChCF,EAAI,KAAKb,EAAIc,EAAGC,EAAGX,EAAK,OAAO,CAAC,EAGpC,OAAOS,CACT"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const m = {
|
|
2
|
+
96: { rows: 8, columns: 12 },
|
|
3
|
+
384: { rows: 16, columns: 24 },
|
|
4
|
+
1536: { rows: 32, columns: 48 }
|
|
5
|
+
}, u = 26, c = 65, I = 100, A = 2, C = 3;
|
|
6
|
+
function S(n, t, o) {
|
|
7
|
+
return n === "custom" ? {
|
|
8
|
+
rows: t ?? 8,
|
|
9
|
+
columns: o ?? 12
|
|
10
|
+
} : m[n];
|
|
11
|
+
}
|
|
12
|
+
function D(n) {
|
|
13
|
+
if (n < u) return String.fromCharCode(c + n);
|
|
14
|
+
const t = Math.floor(n / u) - 1, o = n % u;
|
|
15
|
+
return String.fromCharCode(c + t) + String.fromCharCode(c + o);
|
|
16
|
+
}
|
|
17
|
+
function _(n) {
|
|
18
|
+
return n.length === 1 ? n.charCodeAt(0) - c : (n.charCodeAt(0) - c + 1) * u + (n.charCodeAt(1) - c);
|
|
19
|
+
}
|
|
20
|
+
function P(n) {
|
|
21
|
+
return n >= I ? C : A;
|
|
22
|
+
}
|
|
23
|
+
function h(n, t, o) {
|
|
24
|
+
return `${D(n)}${String(t + 1).padStart(P(o), "0")}`;
|
|
25
|
+
}
|
|
26
|
+
function p(n, t) {
|
|
27
|
+
if (!n) return null;
|
|
28
|
+
const o = /^([A-Z]{1,2})(\d+)$/.exec(n);
|
|
29
|
+
if (!o) return null;
|
|
30
|
+
const r = _(o[1]), s = parseInt(o[2], 10) - 1;
|
|
31
|
+
return Number.isNaN(s) || r < 0 || r >= t.rows || s < 0 || s >= t.columns ? null : { row: r, col: s };
|
|
32
|
+
}
|
|
33
|
+
function E(n, t, o, r, s) {
|
|
34
|
+
const f = [Math.min(n, o), Math.max(n, o)], l = [Math.min(t, r), Math.max(t, r)], a = [];
|
|
35
|
+
for (let e = f[0]; e <= f[1]; e++)
|
|
36
|
+
for (let i = l[0]; i <= l[1]; i++)
|
|
37
|
+
a.push(h(e, i, s));
|
|
38
|
+
return a;
|
|
39
|
+
}
|
|
40
|
+
function T(n) {
|
|
41
|
+
const t = [];
|
|
42
|
+
for (let o = 0; o < n.rows; o++)
|
|
43
|
+
for (let r = 0; r < n.columns; r++)
|
|
44
|
+
t.push(h(o, r, n.columns));
|
|
45
|
+
return t;
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
T as allPositions,
|
|
49
|
+
p as parsePos,
|
|
50
|
+
_ as parseRowLabel,
|
|
51
|
+
h as pos,
|
|
52
|
+
E as rectPositions,
|
|
53
|
+
S as resolveDimensions,
|
|
54
|
+
D as rowLabel
|
|
55
|
+
};
|
|
56
|
+
//# sourceMappingURL=wellGrid.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wellGrid.js","sources":["../../../../src/components/composed/PlateMapEditor/wellGrid.ts"],"sourcesContent":["import type { PlateDimensions, PlateFormat, WellId } from \"./types\";\n\nconst FORMAT_DIMENSIONS: Record<Exclude<PlateFormat, \"custom\">, PlateDimensions> = {\n \"96\": { rows: 8, columns: 12 },\n \"384\": { rows: 16, columns: 24 },\n \"1536\": { rows: 32, columns: 48 },\n};\n\nconst ALPHABET_SIZE = 26;\nconst CHAR_CODE_A = 65;\nconst TRIPLE_DIGIT_THRESHOLD = 100;\nconst DOUBLE_DIGIT_PAD = 2;\nconst TRIPLE_DIGIT_PAD = 3;\n\nexport function resolveDimensions(\n format: PlateFormat,\n rows?: number,\n columns?: number,\n): PlateDimensions {\n if (format === \"custom\") {\n return {\n rows: rows ?? 8,\n columns: columns ?? 12,\n };\n }\n return FORMAT_DIMENSIONS[format];\n}\n\n/** Letter for a row index. Supports A-Z then AA-ZZ for 1536-format plates. */\nexport function rowLabel(row: number): string {\n if (row < ALPHABET_SIZE) return String.fromCharCode(CHAR_CODE_A + row);\n const high = Math.floor(row / ALPHABET_SIZE) - 1;\n const low = row % ALPHABET_SIZE;\n return (\n String.fromCharCode(CHAR_CODE_A + high) +\n String.fromCharCode(CHAR_CODE_A + low)\n );\n}\n\nexport function parseRowLabel(label: string): number {\n if (label.length === 1) return label.charCodeAt(0) - CHAR_CODE_A;\n return (\n (label.charCodeAt(0) - CHAR_CODE_A + 1) * ALPHABET_SIZE +\n (label.charCodeAt(1) - CHAR_CODE_A)\n );\n}\n\n/** Pad column number to a width that matches the plate's column count. */\nfunction colPadWidth(columns: number): number {\n return columns >= TRIPLE_DIGIT_THRESHOLD ? TRIPLE_DIGIT_PAD : DOUBLE_DIGIT_PAD;\n}\n\nexport function pos(row: number, col: number, columns: number): WellId {\n return `${rowLabel(row)}${String(col + 1).padStart(colPadWidth(columns), \"0\")}`;\n}\n\nexport function parsePos(\n id: WellId,\n dims: PlateDimensions,\n): { row: number; col: number } | null {\n if (!id) return null;\n const m = /^([A-Z]{1,2})(\\d+)$/.exec(id);\n if (!m) return null;\n const row = parseRowLabel(m[1]);\n const col = parseInt(m[2], 10) - 1;\n if (\n Number.isNaN(col) ||\n row < 0 ||\n row >= dims.rows ||\n col < 0 ||\n col >= dims.columns\n ) {\n return null;\n }\n return { row, col };\n}\n\nexport function rectPositions(\n r0: number,\n c0: number,\n r1: number,\n c1: number,\n columns: number,\n): WellId[] {\n const rs = [Math.min(r0, r1), Math.max(r0, r1)];\n const cs = [Math.min(c0, c1), Math.max(c0, c1)];\n const out: WellId[] = [];\n for (let r = rs[0]; r <= rs[1]; r++) {\n for (let c = cs[0]; c <= cs[1]; c++) {\n out.push(pos(r, c, columns));\n }\n }\n return out;\n}\n\nexport function allPositions(dims: PlateDimensions): WellId[] {\n const out: WellId[] = [];\n for (let r = 0; r < dims.rows; r++) {\n for (let c = 0; c < dims.columns; c++) {\n out.push(pos(r, c, dims.columns));\n }\n }\n return out;\n}\n"],"names":["FORMAT_DIMENSIONS","ALPHABET_SIZE","CHAR_CODE_A","TRIPLE_DIGIT_THRESHOLD","DOUBLE_DIGIT_PAD","TRIPLE_DIGIT_PAD","resolveDimensions","format","rows","columns","rowLabel","row","high","low","parseRowLabel","label","colPadWidth","pos","col","parsePos","id","dims","m","rectPositions","r0","c0","r1","c1","rs","cs","out","r","c","allPositions"],"mappings":"AAEA,MAAMA,IAA6E;AAAA,EACjF,IAAM,EAAE,MAAM,GAAG,SAAS,GAAA;AAAA,EAC1B,KAAO,EAAE,MAAM,IAAI,SAAS,GAAA;AAAA,EAC5B,MAAQ,EAAE,MAAM,IAAI,SAAS,GAAA;AAC/B,GAEMC,IAAgB,IAChBC,IAAc,IACdC,IAAyB,KACzBC,IAAmB,GACnBC,IAAmB;AAElB,SAASC,EACdC,GACAC,GACAC,GACiB;AACjB,SAAIF,MAAW,WACN;AAAA,IACL,MAAMC,KAAQ;AAAA,IACd,SAASC,KAAW;AAAA,EAAA,IAGjBT,EAAkBO,CAAM;AACjC;AAGO,SAASG,EAASC,GAAqB;AAC5C,MAAIA,IAAMV,EAAe,QAAO,OAAO,aAAaC,IAAcS,CAAG;AACrE,QAAMC,IAAO,KAAK,MAAMD,IAAMV,CAAa,IAAI,GACzCY,IAAMF,IAAMV;AAClB,SACE,OAAO,aAAaC,IAAcU,CAAI,IACtC,OAAO,aAAaV,IAAcW,CAAG;AAEzC;AAEO,SAASC,EAAcC,GAAuB;AACnD,SAAIA,EAAM,WAAW,IAAUA,EAAM,WAAW,CAAC,IAAIb,KAElDa,EAAM,WAAW,CAAC,IAAIb,IAAc,KAAKD,KACzCc,EAAM,WAAW,CAAC,IAAIb;AAE3B;AAGA,SAASc,EAAYP,GAAyB;AAC5C,SAAOA,KAAWN,IAAyBE,IAAmBD;AAChE;AAEO,SAASa,EAAIN,GAAaO,GAAaT,GAAyB;AACrE,SAAO,GAAGC,EAASC,CAAG,CAAC,GAAG,OAAOO,IAAM,CAAC,EAAE,SAASF,EAAYP,CAAO,GAAG,GAAG,CAAC;AAC/E;AAEO,SAASU,EACdC,GACAC,GACqC;AACrC,MAAI,CAACD,EAAI,QAAO;AAChB,QAAME,IAAI,sBAAsB,KAAKF,CAAE;AACvC,MAAI,CAACE,EAAG,QAAO;AACf,QAAMX,IAAMG,EAAcQ,EAAE,CAAC,CAAC,GACxBJ,IAAM,SAASI,EAAE,CAAC,GAAG,EAAE,IAAI;AACjC,SACE,OAAO,MAAMJ,CAAG,KAChBP,IAAM,KACNA,KAAOU,EAAK,QACZH,IAAM,KACNA,KAAOG,EAAK,UAEL,OAEF,EAAE,KAAAV,GAAK,KAAAO,EAAA;AAChB;AAEO,SAASK,EACdC,GACAC,GACAC,GACAC,GACAlB,GACU;AACV,QAAMmB,IAAK,CAAC,KAAK,IAAIJ,GAAIE,CAAE,GAAG,KAAK,IAAIF,GAAIE,CAAE,CAAC,GACxCG,IAAK,CAAC,KAAK,IAAIJ,GAAIE,CAAE,GAAG,KAAK,IAAIF,GAAIE,CAAE,CAAC,GACxCG,IAAgB,CAAA;AACtB,WAASC,IAAIH,EAAG,CAAC,GAAGG,KAAKH,EAAG,CAAC,GAAGG;AAC9B,aAASC,IAAIH,EAAG,CAAC,GAAGG,KAAKH,EAAG,CAAC,GAAGG;AAC9B,MAAAF,EAAI,KAAKb,EAAIc,GAAGC,GAAGvB,CAAO,CAAC;AAG/B,SAAOqB;AACT;AAEO,SAASG,EAAaZ,GAAiC;AAC5D,QAAMS,IAAgB,CAAA;AACtB,WAASC,IAAI,GAAGA,IAAIV,EAAK,MAAMU;AAC7B,aAASC,IAAI,GAAGA,IAAIX,EAAK,SAASW;AAChC,MAAAF,EAAI,KAAKb,EAAIc,GAAGC,GAAGX,EAAK,OAAO,CAAC;AAGpC,SAAOS;AACT;"}
|
|
@@ -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"),x=require("lucide-react"),D=require("./data-table.cjs"),f=require("../button.cjs"),R=require("../input.cjs"),g=require("../popover.cjs"),l=require("../select.cjs"),A=require("../../../lib/utils.cjs"),L={contains:"contains",equals:"equals",not_equals:"not equals",starts_with:"starts with",ends_with:"ends with",is_empty:"is empty",is_not_empty:"is not empty"},O=["is_empty","is_not_empty"],y=["contains","equals","not_equals","starts_with","ends_with","is_empty","is_not_empty"];function E(a,i,n){return i[a]??n?.columnDef?.meta?.label??(typeof n?.columnDef?.header=="string"?n.columnDef.header:void 0)??a}function P(a,i){const n=i?.[0]??"contains";return{id:crypto.randomUUID(),columnId:a,operator:n,value:""}}function _({className:a}){const{table:i,columnLabels:n,filters:r,setFilters:u,filterConfig:v,enableFiltering:I}=D.useDataTable();if(!I)return null;const j=i.getAllLeafColumns(),o=v.length>0?v:j.filter(t=>"accessorKey"in t.columnDef||"accessorFn"in t.columnDef).map(t=>({columnId:t.id})),b=o[0],F=b?.columnId??"";function N(){u([...r,P(F,b?.operators)])}function S(t){u(r.filter(m=>m.id!==t))}function h(t,m){u(r.map(c=>c.id===t?{...c,...m}:c))}function q(){u([])}const d=r.length;return e.jsxs(g.Popover,{children:[e.jsx(g.PopoverTrigger,{asChild:!0,children:e.jsxs(f.Button,{type:"button",variant:"outline",size:"sm","data-slot":"data-table-filter",className:A.cn(a),"aria-label":d>0?`Filter (${d} active)`:"Filter",children:[e.jsx(x.ListFilterIcon,{className:"size-3.5"}),"Filter",d>0&&e.jsx("span",{className:"flex size-4 items-center justify-center rounded-full bg-primary text-[10px] font-medium text-primary-foreground",children:d})]})}),e.jsx(g.PopoverContent,{"data-slot":"data-table-filter-panel",align:"end",className:"min-w-80",children:e.jsxs("div",{className:"flex flex-col gap-2",children:[r.map(t=>{const c=o.find(s=>s.columnId===t.columnId)?.operators??y,T=O.includes(t.operator);return e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l.Select,{value:t.columnId,onValueChange:s=>{const p=o.find(z=>z.columnId===s)?.operators??y,w=p.includes(t.operator)?t.operator:p[0]??"contains";h(t.id,{columnId:s,operator:w,value:""})},children:[e.jsx(l.SelectTrigger,{size:"sm",className:"w-36",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:o.map(s=>{const C=j.find(p=>p.id===s.columnId);return e.jsx(l.SelectItem,{value:s.columnId,children:s.label??E(s.columnId,n,C)},s.columnId)})})]}),e.jsxs(l.Select,{value:t.operator,onValueChange:s=>h(t.id,{operator:s,value:""}),children:[e.jsx(l.SelectTrigger,{size:"sm",className:"w-32",children:e.jsx(l.SelectValue,{})}),e.jsx(l.SelectContent,{children:c.map(s=>e.jsx(l.SelectItem,{value:s,children:L[s]},s))})]}),T?e.jsx("div",{className:"h-8 w-40","aria-hidden":!0}):e.jsx(R.Input,{className:"w-40",placeholder:"Value…",value:t.value,onChange:s=>h(t.id,{value:s.target.value})}),e.jsx(f.Button,{type:"button",variant:"ghost",size:"icon",className:"size-8 shrink-0 text-muted-foreground hover:text-foreground",onClick:()=>S(t.id),"aria-label":"Remove filter",children:e.jsx(x.XIcon,{className:"size-3.5"})})]},t.id)}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(f.Button,{type:"button",variant:"outline",size:"sm",onClick:N,disabled:o.length===0,children:[e.jsx(x.PlusIcon,{className:"size-3.5"}),"Add filter"]}),r.length>0&&e.jsx(f.Button,{type:"button",variant:"ghost",size:"sm",className:"text-muted-foreground",onClick:q,children:"Clear all"})]})]})})]})}_.displayName="DataTableFilter";exports.DataTableFilter=_;
|
|
2
2
|
//# sourceMappingURL=data-table-filter.cjs.map
|