@adapttable/unstyled 0.1.0 → 0.2.0

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/index.cjs CHANGED
@@ -1,2473 +1,1982 @@
1
- 'use strict';
2
-
3
- var core = require('@adapttable/core');
4
- var react = require('react');
5
- var jsxRuntime = require('react/jsx-runtime');
6
- var reactDom = require('react-dom');
7
-
8
- // src/components/AutoFilterForm.tsx
9
- var FIELD_PART = "filter-field";
10
- var LABEL_PART = "filter-label";
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _adapttable_core = require("@adapttable/core");
3
+ let react = require("react");
4
+ let react_jsx_runtime = require("react/jsx-runtime");
5
+ let react_dom = require("react-dom");
6
+ //#region src/components/AutoFilterForm.tsx
7
+ const FIELD_PART = "filter-field";
8
+ const LABEL_PART = "filter-label";
9
+ /** A filter-bag value as input text (`undefined` renders empty). */
11
10
  function asText(value) {
12
- return String(value ?? "");
11
+ return String(value ?? "");
13
12
  }
13
+ /** A `multiSelect` bag value as an array, tolerating a scalar from the URL. */
14
14
  function selectedValues(value) {
15
- if (Array.isArray(value)) return value;
16
- if (value == null || value === "") return [];
17
- return [String(value)];
15
+ if (Array.isArray(value)) return value;
16
+ if (value == null || value === "") return [];
17
+ return [String(value)];
18
18
  }
19
- function GroupField({
20
- caption,
21
- classNames,
22
- children
23
- }) {
24
- return /* @__PURE__ */ jsxRuntime.jsxs(
25
- "fieldset",
26
- {
27
- "data-adapttable-part": FIELD_PART,
28
- className: classNames.filterField,
29
- children: [
30
- /* @__PURE__ */ jsxRuntime.jsx(
31
- "legend",
32
- {
33
- "data-adapttable-part": LABEL_PART,
34
- className: classNames.filterLabel,
35
- children: caption
36
- }
37
- ),
38
- children
39
- ]
40
- }
41
- );
19
+ /** `<fieldset>` + `<legend>` wrapper for multi-control fields. */
20
+ function GroupField({ caption, classNames, children }) {
21
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
22
+ "data-adapttable-part": FIELD_PART,
23
+ className: classNames.filterField,
24
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("legend", {
25
+ "data-adapttable-part": LABEL_PART,
26
+ className: classNames.filterLabel,
27
+ children: caption
28
+ }), children]
29
+ });
42
30
  }
43
- function BagInput({
44
- source,
45
- stateKey,
46
- type,
47
- placeholder,
48
- classNames
49
- }) {
50
- return /* @__PURE__ */ jsxRuntime.jsx(
51
- "input",
52
- {
53
- type,
54
- placeholder,
55
- "data-adapttable-part": "filter-input",
56
- className: classNames.filterInput,
57
- value: asText(source.extra[stateKey]),
58
- onChange: (e) => source.setExtra(stateKey, e.currentTarget.value)
59
- }
60
- );
31
+ /** One input bound to a filter-bag state key (empty text clears it). */
32
+ function BagInput({ source, stateKey, type, placeholder, classNames }) {
33
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
34
+ type,
35
+ placeholder,
36
+ "data-adapttable-part": "filter-input",
37
+ className: classNames.filterInput,
38
+ value: asText(source.extra[stateKey]),
39
+ onChange: (e) => source.setExtra(stateKey, e.currentTarget.value)
40
+ });
61
41
  }
62
- function TextField({
63
- def,
64
- source,
65
- classNames
66
- }) {
67
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { "data-adapttable-part": FIELD_PART, className: classNames.filterField, children: [
68
- /* @__PURE__ */ jsxRuntime.jsx(
69
- "span",
70
- {
71
- "data-adapttable-part": LABEL_PART,
72
- className: classNames.filterLabel,
73
- children: core.filterLabel(def)
74
- }
75
- ),
76
- " ",
77
- /* @__PURE__ */ jsxRuntime.jsx(
78
- BagInput,
79
- {
80
- source,
81
- stateKey: def.key,
82
- type: "text",
83
- placeholder: def.placeholder,
84
- classNames
85
- }
86
- )
87
- ] });
42
+ function TextField({ def, source, classNames }) {
43
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
44
+ "data-adapttable-part": FIELD_PART,
45
+ className: classNames.filterField,
46
+ children: [
47
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
48
+ "data-adapttable-part": LABEL_PART,
49
+ className: classNames.filterLabel,
50
+ children: (0, _adapttable_core.filterLabel)(def)
51
+ }),
52
+ " ",
53
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BagInput, {
54
+ source,
55
+ stateKey: def.key,
56
+ type: "text",
57
+ placeholder: def.placeholder,
58
+ classNames
59
+ })
60
+ ]
61
+ });
88
62
  }
89
- function SelectField({
90
- def,
91
- source,
92
- classNames
93
- }) {
94
- const { options, loading } = core.useFilterOptions(def);
95
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { "data-adapttable-part": FIELD_PART, className: classNames.filterField, children: [
96
- /* @__PURE__ */ jsxRuntime.jsx(
97
- "span",
98
- {
99
- "data-adapttable-part": LABEL_PART,
100
- className: classNames.filterLabel,
101
- children: core.filterLabel(def)
102
- }
103
- ),
104
- " ",
105
- /* @__PURE__ */ jsxRuntime.jsx(
106
- "select",
107
- {
108
- "data-adapttable-part": "filter-select",
109
- className: classNames.filterSelect,
110
- value: asText(source.extra[def.key]),
111
- onChange: (e) => source.setExtra(def.key, e.currentTarget.value),
112
- children: loading ? /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "\u2026" }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
113
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "All" }),
114
- options.map((option) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: option.value, children: option.label }, option.value))
115
- ] })
116
- }
117
- )
118
- ] });
63
+ function SelectField({ def, source, classNames }) {
64
+ const { options, loading } = (0, _adapttable_core.useFilterOptions)(def);
65
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
66
+ "data-adapttable-part": FIELD_PART,
67
+ className: classNames.filterField,
68
+ children: [
69
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
70
+ "data-adapttable-part": LABEL_PART,
71
+ className: classNames.filterLabel,
72
+ children: (0, _adapttable_core.filterLabel)(def)
73
+ }),
74
+ " ",
75
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
76
+ "data-adapttable-part": "filter-select",
77
+ className: classNames.filterSelect,
78
+ value: asText(source.extra[def.key]),
79
+ onChange: (e) => source.setExtra(def.key, e.currentTarget.value),
80
+ children: loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
81
+ value: "",
82
+ disabled: true,
83
+ children: "…"
84
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
85
+ value: "",
86
+ children: "All"
87
+ }), options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
88
+ value: option.value,
89
+ children: option.label
90
+ }, option.value))] })
91
+ })
92
+ ]
93
+ });
119
94
  }
120
- function MultiSelectField({
121
- def,
122
- source,
123
- classNames
124
- }) {
125
- const selected = selectedValues(source.extra[def.key]);
126
- const { options, loading } = core.useFilterOptions(def);
127
- return /* @__PURE__ */ jsxRuntime.jsx(GroupField, { caption: core.filterLabel(def), classNames, children: /* @__PURE__ */ jsxRuntime.jsx(
128
- "div",
129
- {
130
- "data-adapttable-part": "filter-checkbox-group",
131
- className: classNames.filterCheckboxGroup,
132
- children: loading ? /* @__PURE__ */ jsxRuntime.jsx(
133
- "span",
134
- {
135
- "data-adapttable-part": "filter-options-loading",
136
- className: classNames.filterOptionsLoading,
137
- children: "\u2026"
138
- }
139
- ) : options.map((option) => /* @__PURE__ */ jsxRuntime.jsxs(
140
- "label",
141
- {
142
- "data-adapttable-part": "filter-checkbox",
143
- className: classNames.filterCheckbox,
144
- children: [
145
- /* @__PURE__ */ jsxRuntime.jsx(
146
- "input",
147
- {
148
- type: "checkbox",
149
- checked: selected.includes(option.value),
150
- onChange: (e) => source.setExtra(
151
- def.key,
152
- e.currentTarget.checked ? [...selected, option.value] : selected.filter((v) => v !== option.value)
153
- )
154
- }
155
- ),
156
- " ",
157
- option.label
158
- ]
159
- },
160
- option.value
161
- ))
162
- }
163
- ) });
95
+ function MultiSelectField({ def, source, classNames }) {
96
+ const selected = selectedValues(source.extra[def.key]);
97
+ const { options, loading } = (0, _adapttable_core.useFilterOptions)(def);
98
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupField, {
99
+ caption: (0, _adapttable_core.filterLabel)(def),
100
+ classNames,
101
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
102
+ "data-adapttable-part": "filter-checkbox-group",
103
+ className: classNames.filterCheckboxGroup,
104
+ children: loading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
105
+ "data-adapttable-part": "filter-options-loading",
106
+ className: classNames.filterOptionsLoading,
107
+ children: "…"
108
+ }) : options.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", {
109
+ "data-adapttable-part": "filter-checkbox",
110
+ className: classNames.filterCheckbox,
111
+ children: [
112
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
113
+ type: "checkbox",
114
+ checked: selected.includes(option.value),
115
+ onChange: (e) => source.setExtra(def.key, e.currentTarget.checked ? [...selected, option.value] : selected.filter((v) => v !== option.value))
116
+ }),
117
+ " ",
118
+ option.label
119
+ ]
120
+ }, option.value))
121
+ })
122
+ });
164
123
  }
165
- function RangeValueInput({
166
- type,
167
- label,
168
- value,
169
- onValue,
170
- classNames
171
- }) {
172
- return /* @__PURE__ */ jsxRuntime.jsx(
173
- "input",
174
- {
175
- type,
176
- style: { flex: "1 1 7rem", minWidth: "7rem" },
177
- placeholder: label,
178
- "aria-label": label,
179
- "data-adapttable-part": "filter-input",
180
- className: classNames.filterInput,
181
- value,
182
- onChange: (e) => onValue(e.currentTarget.value)
183
- }
184
- );
124
+ /** One bound of a range widget; the parent owns the write-through. */
125
+ function RangeValueInput({ type, label, value, onValue, classNames }) {
126
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
127
+ type,
128
+ style: {
129
+ flex: "1 1 7rem",
130
+ minWidth: "7rem"
131
+ },
132
+ placeholder: label,
133
+ "aria-label": label,
134
+ "data-adapttable-part": "filter-input",
135
+ className: classNames.filterInput,
136
+ value,
137
+ onChange: (e) => onValue(e.currentTarget.value)
138
+ });
185
139
  }
186
- function RangeField({
187
- def,
188
- source,
189
- classNames,
190
- inputType,
191
- suffixes,
192
- labels
193
- }) {
194
- const lowKey = def.key + suffixes.start;
195
- const highKey = def.key + suffixes.end;
196
- const [op, setOp] = react.useState(
197
- () => core.readRangeWidget(source.extra, lowKey, highKey).op
198
- );
199
- const a = asText(source.extra[op === "lte" ? highKey : lowKey]);
200
- const b = asText(source.extra[highKey]);
201
- const write = (nextOp, nextA, nextB) => source.setExtras(core.writeRangeWidget(nextOp, nextA, nextB, lowKey, highKey));
202
- const opLabelKeys = core.RANGE_OP_LABEL_KEYS[inputType];
203
- return /* @__PURE__ */ jsxRuntime.jsx(GroupField, { caption: core.filterLabel(def), classNames, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", flexWrap: "wrap", gap: 8 }, children: [
204
- /* @__PURE__ */ jsxRuntime.jsxs(
205
- "select",
206
- {
207
- style: { flex: "0 0 8.5rem", width: "8.5rem" },
208
- "aria-label": labels.operator,
209
- "data-adapttable-part": "filter-operator",
210
- className: classNames.filterOperator,
211
- value: op ?? "",
212
- onChange: (e) => {
213
- const next = core.RANGE_OPS.find((o) => o === e.currentTarget.value);
214
- setOp(next);
215
- write(next, a, b);
216
- },
217
- children: [
218
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: labels.operator }),
219
- core.RANGE_OPS.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o, children: labels[opLabelKeys[o]] }, o))
220
- ]
221
- }
222
- ),
223
- op === "between" && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
224
- /* @__PURE__ */ jsxRuntime.jsx(
225
- RangeValueInput,
226
- {
227
- type: inputType,
228
- label: labels.from,
229
- value: a,
230
- onValue: (next) => write(op, next, b),
231
- classNames
232
- }
233
- ),
234
- /* @__PURE__ */ jsxRuntime.jsx(
235
- RangeValueInput,
236
- {
237
- type: inputType,
238
- label: labels.to,
239
- value: b,
240
- onValue: (next) => write(op, a, next),
241
- classNames
242
- }
243
- )
244
- ] }),
245
- op !== void 0 && op !== "between" && /* @__PURE__ */ jsxRuntime.jsx(
246
- RangeValueInput,
247
- {
248
- type: inputType,
249
- label: labels.value,
250
- value: a,
251
- onValue: (next) => write(op, next, ""),
252
- classNames
253
- }
254
- )
255
- ] }) });
140
+ /**
141
+ * Operator-first range field: a comparison `<select>` (its placeholder
142
+ * option clears the pair), then ONE value input — or a labeled From/To
143
+ * pair for `between`. The persisted state stays the inclusive
144
+ * `<key><start>` / `<key><end>` pair, written through `setExtras`.
145
+ */
146
+ function RangeField({ def, source, classNames, inputType, suffixes, labels }) {
147
+ const lowKey = def.key + suffixes.start;
148
+ const highKey = def.key + suffixes.end;
149
+ const [op, setOp] = (0, react.useState)(() => (0, _adapttable_core.readRangeWidget)(source.extra, lowKey, highKey).op);
150
+ const a = asText(source.extra[op === "lte" ? highKey : lowKey]);
151
+ const b = asText(source.extra[highKey]);
152
+ const write = (nextOp, nextA, nextB) => source.setExtras((0, _adapttable_core.writeRangeWidget)(nextOp, nextA, nextB, lowKey, highKey));
153
+ const opLabelKeys = _adapttable_core.RANGE_OP_LABEL_KEYS[inputType];
154
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(GroupField, {
155
+ caption: (0, _adapttable_core.filterLabel)(def),
156
+ classNames,
157
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
158
+ style: {
159
+ display: "flex",
160
+ flexWrap: "wrap",
161
+ gap: 8
162
+ },
163
+ children: [
164
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
165
+ style: {
166
+ flex: "0 0 8.5rem",
167
+ width: "8.5rem"
168
+ },
169
+ "aria-label": labels.operator,
170
+ "data-adapttable-part": "filter-operator",
171
+ className: classNames.filterOperator,
172
+ value: op ?? "",
173
+ onChange: (e) => {
174
+ const next = _adapttable_core.RANGE_OPS.find((o) => o === e.currentTarget.value);
175
+ setOp(next);
176
+ write(next, a, b);
177
+ },
178
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
179
+ value: "",
180
+ children: labels.operator
181
+ }), _adapttable_core.RANGE_OPS.map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
182
+ value: o,
183
+ children: labels[opLabelKeys[o]]
184
+ }, o))]
185
+ }),
186
+ op === "between" && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(RangeValueInput, {
187
+ type: inputType,
188
+ label: labels.from,
189
+ value: a,
190
+ onValue: (next) => write(op, next, b),
191
+ classNames
192
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RangeValueInput, {
193
+ type: inputType,
194
+ label: labels.to,
195
+ value: b,
196
+ onValue: (next) => write(op, a, next),
197
+ classNames
198
+ })] }),
199
+ op !== void 0 && op !== "between" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RangeValueInput, {
200
+ type: inputType,
201
+ label: labels.value,
202
+ value: a,
203
+ onValue: (next) => write(op, next, ""),
204
+ classNames
205
+ })
206
+ ]
207
+ })
208
+ });
256
209
  }
257
- function FilterField({
258
- def,
259
- source,
260
- classNames,
261
- labels
262
- }) {
263
- switch (def.type) {
264
- case "text":
265
- return /* @__PURE__ */ jsxRuntime.jsx(TextField, { def, source, classNames });
266
- case "select":
267
- return /* @__PURE__ */ jsxRuntime.jsx(SelectField, { def, source, classNames });
268
- case "multiSelect":
269
- return /* @__PURE__ */ jsxRuntime.jsx(MultiSelectField, { def, source, classNames });
270
- case "dateRange":
271
- return /* @__PURE__ */ jsxRuntime.jsx(
272
- RangeField,
273
- {
274
- def,
275
- source,
276
- classNames,
277
- inputType: "date",
278
- suffixes: core.RANGE_SUFFIXES.dateRange,
279
- labels
280
- }
281
- );
282
- case "numberRange":
283
- return /* @__PURE__ */ jsxRuntime.jsx(
284
- RangeField,
285
- {
286
- def,
287
- source,
288
- classNames,
289
- inputType: "number",
290
- suffixes: core.RANGE_SUFFIXES.numberRange,
291
- labels
292
- }
293
- );
294
- }
210
+ function FilterField({ def, source, classNames, labels }) {
211
+ switch (def.type) {
212
+ case "text": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TextField, {
213
+ def,
214
+ source,
215
+ classNames
216
+ });
217
+ case "select": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SelectField, {
218
+ def,
219
+ source,
220
+ classNames
221
+ });
222
+ case "multiSelect": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MultiSelectField, {
223
+ def,
224
+ source,
225
+ classNames
226
+ });
227
+ case "dateRange": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RangeField, {
228
+ def,
229
+ source,
230
+ classNames,
231
+ inputType: "date",
232
+ suffixes: _adapttable_core.RANGE_SUFFIXES.dateRange,
233
+ labels
234
+ });
235
+ case "numberRange": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RangeField, {
236
+ def,
237
+ source,
238
+ classNames,
239
+ inputType: "number",
240
+ suffixes: _adapttable_core.RANGE_SUFFIXES.numberRange,
241
+ labels
242
+ });
243
+ }
295
244
  }
296
- function AutoFilterForm({
297
- defs,
298
- source,
299
- classNames = {},
300
- labels
301
- }) {
302
- const resolvedLabels = core.resolveLabels(labels);
303
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: defs.map((def) => /* @__PURE__ */ jsxRuntime.jsx(
304
- FilterField,
305
- {
306
- def,
307
- source,
308
- classNames,
309
- labels: resolvedLabels
310
- },
311
- def.key
312
- )) });
245
+ /**
246
+ * The auto-built filter form for the declarative `filters` array: one
247
+ * semantic field per definition (`text` input, `select` with an "All"
248
+ * option, `multiSelect` checkbox list, operator-first `dateRange` /
249
+ * `numberRange` widgets), each carrying `data-adapttable-part` hooks and
250
+ * `classNames` overrides. Controls read `source.extra` and write through
251
+ * `source.setExtra` / `source.setExtras` — an empty value clears its key.
252
+ *
253
+ * @typeParam TRow - The row type.
254
+ */
255
+ function AutoFilterForm({ defs, source, classNames = {}, labels }) {
256
+ const resolvedLabels = (0, _adapttable_core.resolveLabels)(labels);
257
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: defs.map((def) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterField, {
258
+ def,
259
+ source,
260
+ classNames,
261
+ labels: resolvedLabels
262
+ }, def.key)) });
313
263
  }
314
-
315
- // src/cx.ts
264
+ //#endregion
265
+ //#region src/cx.ts
266
+ /**
267
+ * Join class-name parts, dropping falsy values. Tiny `clsx`-style helper
268
+ * so the unstyled adapter has no runtime dependencies.
269
+ *
270
+ * @param parts - Class names or falsy values.
271
+ * @returns The space-joined class string.
272
+ */
316
273
  function cx(...parts) {
317
- return parts.filter(Boolean).join(" ");
274
+ return parts.filter(Boolean).join(" ");
318
275
  }
319
- function FilterPanel({
320
- open,
321
- onClose,
322
- filters,
323
- activeFilterCount,
324
- onClearFilters,
325
- labels,
326
- dir = "ltr",
327
- classNames
328
- }) {
329
- const panelRef = react.useRef(null);
330
- const onCloseRef = react.useRef(onClose);
331
- onCloseRef.current = onClose;
332
- react.useEffect(() => {
333
- if (!open) return;
334
- const trigger = document.activeElement;
335
- panelRef.current?.focus();
336
- const onKeyDown = (event) => {
337
- if (event.key === "Escape") onCloseRef.current();
338
- };
339
- document.addEventListener("keydown", onKeyDown);
340
- return () => {
341
- document.removeEventListener("keydown", onKeyDown);
342
- trigger?.focus?.();
343
- };
344
- }, [open]);
345
- if (!open) return null;
346
- return reactDom.createPortal(
347
- /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
348
- /* @__PURE__ */ jsxRuntime.jsx(
349
- "button",
350
- {
351
- type: "button",
352
- "aria-label": labels.cancel,
353
- "data-adapttable-part": "filters-backdrop",
354
- className: cx(
355
- "adapttable-filters-backdrop",
356
- classNames.filtersBackdrop
357
- ),
358
- onClick: onClose
359
- }
360
- ),
361
- /* @__PURE__ */ jsxRuntime.jsxs(
362
- "dialog",
363
- {
364
- ref: panelRef,
365
- open: true,
366
- tabIndex: -1,
367
- "aria-modal": "true",
368
- "aria-label": labels.filters,
369
- "data-adapttable-part": "filters-panel",
370
- dir,
371
- "data-dir": dir,
372
- className: cx("adapttable-filters-panel", classNames.filtersPanel),
373
- style: {
374
- position: "fixed",
375
- insetBlock: 0,
376
- insetInlineEnd: 0,
377
- insetInlineStart: "auto",
378
- margin: 0,
379
- maxHeight: "none",
380
- maxWidth: "none",
381
- height: "100%",
382
- zIndex: 200
383
- },
384
- children: [
385
- /* @__PURE__ */ jsxRuntime.jsxs(
386
- "header",
387
- {
388
- "data-adapttable-part": "filters-header",
389
- className: classNames.filtersHeader,
390
- children: [
391
- /* @__PURE__ */ jsxRuntime.jsxs(
392
- "h3",
393
- {
394
- "data-adapttable-part": "filters-title",
395
- className: classNames.filtersTitle,
396
- children: [
397
- labels.filters,
398
- activeFilterCount > 0 ? ` (${activeFilterCount})` : ""
399
- ]
400
- }
401
- ),
402
- /* @__PURE__ */ jsxRuntime.jsx(
403
- "button",
404
- {
405
- type: "button",
406
- "aria-label": labels.cancel,
407
- "data-adapttable-part": "filters-close",
408
- className: classNames.filtersClose,
409
- onClick: onClose,
410
- children: "\xD7"
411
- }
412
- )
413
- ]
414
- }
415
- ),
416
- /* @__PURE__ */ jsxRuntime.jsx(
417
- "div",
418
- {
419
- "data-adapttable-part": "filters-body",
420
- className: classNames.filtersBody,
421
- children: filters
422
- }
423
- ),
424
- /* @__PURE__ */ jsxRuntime.jsxs(
425
- "footer",
426
- {
427
- "data-adapttable-part": "filters-footer",
428
- className: classNames.filtersFooter,
429
- children: [
430
- /* @__PURE__ */ jsxRuntime.jsx(
431
- "button",
432
- {
433
- type: "button",
434
- onClick: () => onClearFilters?.(),
435
- disabled: activeFilterCount === 0,
436
- "data-adapttable-part": "filters-clear",
437
- className: classNames.filtersClear,
438
- children: labels.clearAll
439
- }
440
- ),
441
- /* @__PURE__ */ jsxRuntime.jsx(
442
- "button",
443
- {
444
- type: "button",
445
- onClick: onClose,
446
- "data-adapttable-part": "filters-done",
447
- className: classNames.filtersDone,
448
- children: labels.applyFilters
449
- }
450
- )
451
- ]
452
- }
453
- )
454
- ]
455
- }
456
- )
457
- ] }),
458
- document.body
459
- );
276
+ //#endregion
277
+ //#region src/components/FilterPanel.tsx
278
+ /** Backdrop + side drawer for caller-provided filter widgets. */
279
+ function FilterPanel({ open, onClose, filters, activeFilterCount, onClearFilters, labels, dir = "ltr", classNames }) {
280
+ const panelRef = (0, react.useRef)(null);
281
+ const onCloseRef = (0, react.useRef)(onClose);
282
+ onCloseRef.current = onClose;
283
+ (0, react.useEffect)(() => {
284
+ if (!open) return;
285
+ const trigger = document.activeElement;
286
+ panelRef.current?.focus();
287
+ const onKeyDown = (event) => {
288
+ if (event.key === "Escape") onCloseRef.current();
289
+ };
290
+ document.addEventListener("keydown", onKeyDown);
291
+ return () => {
292
+ document.removeEventListener("keydown", onKeyDown);
293
+ trigger?.focus?.();
294
+ };
295
+ }, [open]);
296
+ if (!open) return null;
297
+ return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
298
+ type: "button",
299
+ "aria-label": labels.cancel,
300
+ "data-adapttable-part": "filters-backdrop",
301
+ className: cx("adapttable-filters-backdrop", classNames.filtersBackdrop),
302
+ onClick: onClose
303
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("dialog", {
304
+ ref: panelRef,
305
+ open: true,
306
+ tabIndex: -1,
307
+ "aria-modal": "true",
308
+ "aria-label": labels.filters,
309
+ "data-adapttable-part": "filters-panel",
310
+ dir,
311
+ "data-dir": dir,
312
+ className: cx("adapttable-filters-panel", classNames.filtersPanel),
313
+ style: {
314
+ position: "fixed",
315
+ insetBlock: 0,
316
+ insetInlineEnd: 0,
317
+ insetInlineStart: "auto",
318
+ margin: 0,
319
+ maxHeight: "none",
320
+ maxWidth: "none",
321
+ height: "100%",
322
+ zIndex: 200
323
+ },
324
+ children: [
325
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
326
+ "data-adapttable-part": "filters-header",
327
+ className: classNames.filtersHeader,
328
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
329
+ "data-adapttable-part": "filters-title",
330
+ className: classNames.filtersTitle,
331
+ children: [labels.filters, activeFilterCount > 0 ? ` (${activeFilterCount})` : ""]
332
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
333
+ type: "button",
334
+ "aria-label": labels.cancel,
335
+ "data-adapttable-part": "filters-close",
336
+ className: classNames.filtersClose,
337
+ onClick: onClose,
338
+ children: "×"
339
+ })]
340
+ }),
341
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
342
+ "data-adapttable-part": "filters-body",
343
+ className: classNames.filtersBody,
344
+ children: filters
345
+ }),
346
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("footer", {
347
+ "data-adapttable-part": "filters-footer",
348
+ className: classNames.filtersFooter,
349
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
350
+ type: "button",
351
+ onClick: () => onClearFilters?.(),
352
+ disabled: activeFilterCount === 0,
353
+ "data-adapttable-part": "filters-clear",
354
+ className: classNames.filtersClear,
355
+ children: labels.clearAll
356
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
357
+ type: "button",
358
+ onClick: onClose,
359
+ "data-adapttable-part": "filters-done",
360
+ className: classNames.filtersDone,
361
+ children: labels.applyFilters
362
+ })]
363
+ })
364
+ ]
365
+ })] }), document.body);
460
366
  }
461
- function FilterPopover({
462
- open,
463
- onClose,
464
- filters,
465
- activeFilterCount,
466
- onClearFilters,
467
- labels,
468
- dir = "ltr",
469
- classNames,
470
- children
471
- }) {
472
- const onCloseRef = react.useRef(onClose);
473
- onCloseRef.current = onClose;
474
- const rootRef = react.useRef(null);
475
- const cardRef = react.useRef(null);
476
- react.useEffect(() => {
477
- if (!open) return;
478
- const onClick = (event) => {
479
- const root = rootRef.current;
480
- if (root.contains(event.target)) return;
481
- if (cardRef.current?.contains(document.activeElement)) return;
482
- onCloseRef.current();
483
- };
484
- const onKeyDown = (event) => {
485
- if (event.key !== "Escape") return;
486
- onCloseRef.current();
487
- rootRef.current?.querySelector("button")?.focus();
488
- };
489
- document.addEventListener("click", onClick);
490
- document.addEventListener("keydown", onKeyDown);
491
- return () => {
492
- document.removeEventListener("click", onClick);
493
- document.removeEventListener("keydown", onKeyDown);
494
- };
495
- }, [open]);
496
- const side = dir === "rtl" ? { left: 0 } : { right: 0 };
497
- return /* @__PURE__ */ jsxRuntime.jsxs(
498
- "span",
499
- {
500
- ref: rootRef,
501
- "data-adapttable-part": "filters-anchor",
502
- className: cx("adapttable-filters-anchor", classNames.filtersAnchor),
503
- style: { position: "relative", display: "inline-flex" },
504
- children: [
505
- children,
506
- open && /* @__PURE__ */ jsxRuntime.jsxs(
507
- "div",
508
- {
509
- ref: cardRef,
510
- "data-adapttable-part": "filters-popover",
511
- "data-dir": dir,
512
- className: cx(
513
- "adapttable-filters-popover",
514
- classNames.filtersPopover
515
- ),
516
- style: { position: "absolute", top: "100%", zIndex: 200, ...side },
517
- children: [
518
- /* @__PURE__ */ jsxRuntime.jsxs(
519
- "header",
520
- {
521
- "data-adapttable-part": "filters-header",
522
- className: classNames.filtersHeader,
523
- children: [
524
- /* @__PURE__ */ jsxRuntime.jsxs(
525
- "h3",
526
- {
527
- "data-adapttable-part": "filters-title",
528
- className: classNames.filtersTitle,
529
- children: [
530
- labels.filters,
531
- activeFilterCount > 0 ? ` (${activeFilterCount})` : ""
532
- ]
533
- }
534
- ),
535
- /* @__PURE__ */ jsxRuntime.jsx(
536
- "button",
537
- {
538
- type: "button",
539
- onClick: () => onClearFilters?.(),
540
- disabled: activeFilterCount === 0,
541
- "data-adapttable-part": "filters-clear",
542
- className: classNames.filtersClear,
543
- children: labels.clearAll
544
- }
545
- )
546
- ]
547
- }
548
- ),
549
- /* @__PURE__ */ jsxRuntime.jsx(
550
- "div",
551
- {
552
- "data-adapttable-part": "filters-body",
553
- className: classNames.filtersBody,
554
- children: filters
555
- }
556
- )
557
- ]
558
- }
559
- )
560
- ]
561
- }
562
- );
367
+ //#endregion
368
+ //#region src/components/FilterPopover.tsx
369
+ /**
370
+ * Anchored filter card (the default filter container). Opens beneath the
371
+ * Filters button with NO backdrop — the background stays visible and
372
+ * interactive; clicking outside the popover/anchor or pressing Escape closes
373
+ * it. This is the plain-DOM mirror of the Mantine reference; pair with
374
+ * `filtersMode="drawer"` for the slide-in panel (`FilterPanel`) instead.
375
+ */
376
+ function FilterPopover({ open, onClose, filters, activeFilterCount, onClearFilters, labels, dir = "ltr", classNames, children }) {
377
+ const onCloseRef = (0, react.useRef)(onClose);
378
+ onCloseRef.current = onClose;
379
+ const rootRef = (0, react.useRef)(null);
380
+ const cardRef = (0, react.useRef)(null);
381
+ (0, react.useEffect)(() => {
382
+ if (!open) return;
383
+ const onClick = (event) => {
384
+ if (rootRef.current.contains(event.target)) return;
385
+ if (cardRef.current?.contains(document.activeElement)) return;
386
+ onCloseRef.current();
387
+ };
388
+ const onKeyDown = (event) => {
389
+ if (event.key !== "Escape") return;
390
+ onCloseRef.current();
391
+ rootRef.current?.querySelector("button")?.focus();
392
+ };
393
+ document.addEventListener("click", onClick);
394
+ document.addEventListener("keydown", onKeyDown);
395
+ return () => {
396
+ document.removeEventListener("click", onClick);
397
+ document.removeEventListener("keydown", onKeyDown);
398
+ };
399
+ }, [open]);
400
+ const side = dir === "rtl" ? { left: 0 } : { right: 0 };
401
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
402
+ ref: rootRef,
403
+ "data-adapttable-part": "filters-anchor",
404
+ className: cx("adapttable-filters-anchor", classNames.filtersAnchor),
405
+ style: {
406
+ position: "relative",
407
+ display: "inline-flex"
408
+ },
409
+ children: [children, open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
410
+ ref: cardRef,
411
+ "data-adapttable-part": "filters-popover",
412
+ "data-dir": dir,
413
+ className: cx("adapttable-filters-popover", classNames.filtersPopover),
414
+ style: {
415
+ position: "absolute",
416
+ top: "100%",
417
+ zIndex: 200,
418
+ ...side
419
+ },
420
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("header", {
421
+ "data-adapttable-part": "filters-header",
422
+ className: classNames.filtersHeader,
423
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("h3", {
424
+ "data-adapttable-part": "filters-title",
425
+ className: classNames.filtersTitle,
426
+ children: [labels.filters, activeFilterCount > 0 ? ` (${activeFilterCount})` : ""]
427
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
428
+ type: "button",
429
+ onClick: () => onClearFilters?.(),
430
+ disabled: activeFilterCount === 0,
431
+ "data-adapttable-part": "filters-clear",
432
+ className: classNames.filtersClear,
433
+ children: labels.clearAll
434
+ })]
435
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
436
+ "data-adapttable-part": "filters-body",
437
+ className: classNames.filtersBody,
438
+ children: filters
439
+ })]
440
+ })]
441
+ });
563
442
  }
564
- function Svg({
565
- size = 16,
566
- className,
567
- children
568
- }) {
569
- return /* @__PURE__ */ jsxRuntime.jsx(
570
- "svg",
571
- {
572
- width: size,
573
- height: size,
574
- viewBox: "0 0 24 24",
575
- fill: "none",
576
- stroke: "currentColor",
577
- strokeWidth: 2,
578
- strokeLinecap: "round",
579
- strokeLinejoin: "round",
580
- className,
581
- "aria-hidden": "true",
582
- focusable: "false",
583
- children
584
- }
585
- );
443
+ //#endregion
444
+ //#region src/components/icons.tsx
445
+ function Svg({ size = 16, className, children }) {
446
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
447
+ width: size,
448
+ height: size,
449
+ viewBox: "0 0 24 24",
450
+ fill: "none",
451
+ stroke: "currentColor",
452
+ strokeWidth: 2,
453
+ strokeLinecap: "round",
454
+ strokeLinejoin: "round",
455
+ className,
456
+ "aria-hidden": "true",
457
+ focusable: "false",
458
+ children
459
+ });
586
460
  }
587
- var SearchIcon = (p) => /* @__PURE__ */ jsxRuntime.jsxs(Svg, { ...p, children: [
588
- /* @__PURE__ */ jsxRuntime.jsx("circle", { cx: "11", cy: "11", r: "7" }),
589
- /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m21 21-4.3-4.3" })
590
- ] });
591
- var FiltersIcon = (p) => /* @__PURE__ */ jsxRuntime.jsx(Svg, { ...p, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M3 4h18l-7 8v6l-4 2v-8L3 4Z" }) });
592
- var ChevronIcon = (p) => /* @__PURE__ */ jsxRuntime.jsx(Svg, { ...p, children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m9 6 6 6-6 6" }) });
593
- var MENU_PANEL_STYLE = {
594
- position: "absolute",
595
- zIndex: 200,
596
- insetInlineEnd: 0,
597
- margin: 0,
598
- border: 0,
599
- padding: 0,
600
- minInlineSize: 0
461
+ /** Magnifying-glass search glyph (inline SVG, `currentColor`). */
462
+ const SearchIcon = (p) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Svg, {
463
+ ...p,
464
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
465
+ cx: "11",
466
+ cy: "11",
467
+ r: "7"
468
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m21 21-4.3-4.3" })]
469
+ });
470
+ /** Funnel glyph for the Filters button (inline SVG, `currentColor`). */
471
+ const FiltersIcon = (p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Svg, {
472
+ ...p,
473
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "M3 4h18l-7 8v6l-4 2v-8L3 4Z" })
474
+ });
475
+ /**
476
+ * Right-pointing chevron (▸) for the expand-row button. The button carries a
477
+ * `data-expanded` attribute so consumers rotate the glyph with their own CSS
478
+ * (e.g. `[data-expanded] svg { transform: rotate(90deg) }`).
479
+ */
480
+ const ChevronIcon = (p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Svg, {
481
+ ...p,
482
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", { d: "m9 6 6 6-6 6" })
483
+ });
484
+ //#endregion
485
+ //#region src/components/menuPopover.ts
486
+ /**
487
+ * Inline style for an absolutely-positioned toolbar menu panel. The extra
488
+ * `margin`/`border`/`padding`/`minInlineSize` zeros neutralise `<fieldset>`
489
+ * defaults so the same style works for any panel element.
490
+ */
491
+ const MENU_PANEL_STYLE = {
492
+ position: "absolute",
493
+ zIndex: 200,
494
+ insetInlineEnd: 0,
495
+ margin: 0,
496
+ border: 0,
497
+ padding: 0,
498
+ minInlineSize: 0
601
499
  };
500
+ /**
501
+ * Disclosure behaviour for the toolbar menus (ColumnMenu, SavedViewsMenu):
502
+ * open/close state that also closes on outside mousedown or Escape, with
503
+ * Escape restoring focus to the trigger.
504
+ */
602
505
  function useMenuPopover() {
603
- const [open, setOpen] = react.useState(false);
604
- const rootRef = react.useRef(null);
605
- const triggerRef = react.useRef(null);
606
- react.useEffect(() => {
607
- if (!open) return;
608
- const onDown = (event) => {
609
- if (!rootRef.current?.contains(event.target)) setOpen(false);
610
- };
611
- const onKey = (event) => {
612
- if (event.key !== "Escape") return;
613
- setOpen(false);
614
- triggerRef.current?.focus();
615
- };
616
- document.addEventListener("mousedown", onDown);
617
- document.addEventListener("keydown", onKey);
618
- return () => {
619
- document.removeEventListener("mousedown", onDown);
620
- document.removeEventListener("keydown", onKey);
621
- };
622
- }, [open]);
623
- return { open, setOpen, rootRef, triggerRef };
506
+ const [open, setOpen] = (0, react.useState)(false);
507
+ const rootRef = (0, react.useRef)(null);
508
+ const triggerRef = (0, react.useRef)(null);
509
+ (0, react.useEffect)(() => {
510
+ if (!open) return;
511
+ const onDown = (event) => {
512
+ if (!rootRef.current?.contains(event.target)) setOpen(false);
513
+ };
514
+ const onKey = (event) => {
515
+ if (event.key !== "Escape") return;
516
+ setOpen(false);
517
+ triggerRef.current?.focus();
518
+ };
519
+ document.addEventListener("mousedown", onDown);
520
+ document.addEventListener("keydown", onKey);
521
+ return () => {
522
+ document.removeEventListener("mousedown", onDown);
523
+ document.removeEventListener("keydown", onKey);
524
+ };
525
+ }, [open]);
526
+ return {
527
+ open,
528
+ setOpen,
529
+ rootRef,
530
+ triggerRef
531
+ };
624
532
  }
625
- function SavedViewsMenu({
626
- options,
627
- labels,
628
- classNames
629
- }) {
630
- const { views, save, apply, remove } = core.useSavedViews(options);
631
- const { open, setOpen, rootRef, triggerRef } = useMenuPopover();
632
- const [name, setName] = react.useState("");
633
- const trimmed = name.trim();
634
- return /* @__PURE__ */ jsxRuntime.jsxs(
635
- "div",
636
- {
637
- ref: rootRef,
638
- "data-adapttable-part": "views-menu",
639
- style: { position: "relative" },
640
- children: [
641
- /* @__PURE__ */ jsxRuntime.jsx(
642
- "button",
643
- {
644
- ref: triggerRef,
645
- type: "button",
646
- "aria-expanded": open,
647
- "aria-haspopup": "true",
648
- "data-adapttable-part": "views-button",
649
- "data-active": open || void 0,
650
- className: classNames.viewsButton,
651
- style: { flexShrink: 0, whiteSpace: "nowrap" },
652
- onClick: () => setOpen((v) => !v),
653
- children: labels.savedViews
654
- }
655
- ),
656
- open && /* @__PURE__ */ jsxRuntime.jsxs(
657
- "div",
658
- {
659
- "data-adapttable-part": "views-panel",
660
- className: classNames.viewsPanel,
661
- style: MENU_PANEL_STYLE,
662
- children: [
663
- views.map((view) => /* @__PURE__ */ jsxRuntime.jsxs(
664
- "div",
665
- {
666
- style: { display: "flex", alignItems: "center" },
667
- children: [
668
- /* @__PURE__ */ jsxRuntime.jsx(
669
- "button",
670
- {
671
- type: "button",
672
- "data-adapttable-part": "views-item",
673
- className: classNames.viewsItem,
674
- onClick: () => {
675
- apply(view.name);
676
- setOpen(false);
677
- },
678
- children: view.name
679
- }
680
- ),
681
- /* @__PURE__ */ jsxRuntime.jsx(
682
- "button",
683
- {
684
- type: "button",
685
- "aria-label": `${labels.deleteView}: ${view.name}`,
686
- "data-adapttable-part": "views-delete",
687
- className: classNames.viewsDelete,
688
- onClick: () => remove(view.name),
689
- children: "\xD7"
690
- }
691
- )
692
- ]
693
- },
694
- view.name
695
- )),
696
- /* @__PURE__ */ jsxRuntime.jsx("hr", { "data-adapttable-part": "views-divider" }),
697
- /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { display: "flex", alignItems: "center" }, children: [
698
- /* @__PURE__ */ jsxRuntime.jsx(
699
- "input",
700
- {
701
- "aria-label": labels.viewName,
702
- placeholder: labels.viewName,
703
- "data-adapttable-part": "views-input",
704
- className: classNames.viewsInput,
705
- value: name,
706
- onChange: (e) => setName(e.currentTarget.value)
707
- }
708
- ),
709
- /* @__PURE__ */ jsxRuntime.jsx(
710
- "button",
711
- {
712
- type: "button",
713
- disabled: trimmed === "",
714
- "data-adapttable-part": "views-save",
715
- className: classNames.viewsSave,
716
- onClick: () => {
717
- save(trimmed);
718
- setName("");
719
- },
720
- children: labels.saveView
721
- }
722
- )
723
- ] })
724
- ]
725
- }
726
- )
727
- ]
728
- }
729
- );
533
+ //#endregion
534
+ //#region src/components/SavedViewsMenu.tsx
535
+ /**
536
+ * Saved-views popover: a disclosure button + a panel listing the saved views
537
+ * (click applies one; each has a delete button) above a save row that
538
+ * captures the table's CURRENT state under a typed name. Built on core's
539
+ * `useSavedViews`; closes on outside-click or Escape. Ships no styles —
540
+ * target the `data-adapttable-part` hooks or the `views*` className slots.
541
+ */
542
+ function SavedViewsMenu({ options, labels, classNames }) {
543
+ const { views, save, apply, remove } = (0, _adapttable_core.useSavedViews)(options);
544
+ const { open, setOpen, rootRef, triggerRef } = useMenuPopover();
545
+ const [name, setName] = (0, react.useState)("");
546
+ const trimmed = name.trim();
547
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
548
+ ref: rootRef,
549
+ "data-adapttable-part": "views-menu",
550
+ style: { position: "relative" },
551
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
552
+ ref: triggerRef,
553
+ type: "button",
554
+ "aria-expanded": open,
555
+ "aria-haspopup": "true",
556
+ "data-adapttable-part": "views-button",
557
+ "data-active": open || void 0,
558
+ className: classNames.viewsButton,
559
+ style: {
560
+ flexShrink: 0,
561
+ whiteSpace: "nowrap"
562
+ },
563
+ onClick: () => setOpen((v) => !v),
564
+ children: labels.savedViews
565
+ }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
566
+ "data-adapttable-part": "views-panel",
567
+ className: classNames.viewsPanel,
568
+ style: MENU_PANEL_STYLE,
569
+ children: [
570
+ views.map((view) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
571
+ style: {
572
+ display: "flex",
573
+ alignItems: "center"
574
+ },
575
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
576
+ type: "button",
577
+ "data-adapttable-part": "views-item",
578
+ className: classNames.viewsItem,
579
+ onClick: () => {
580
+ apply(view.name);
581
+ setOpen(false);
582
+ },
583
+ children: view.name
584
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
585
+ type: "button",
586
+ "aria-label": `${labels.deleteView}: ${view.name}`,
587
+ "data-adapttable-part": "views-delete",
588
+ className: classNames.viewsDelete,
589
+ onClick: () => remove(view.name),
590
+ children: "×"
591
+ })]
592
+ }, view.name)),
593
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("hr", { "data-adapttable-part": "views-divider" }),
594
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
595
+ style: {
596
+ display: "flex",
597
+ alignItems: "center"
598
+ },
599
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
600
+ "aria-label": labels.viewName,
601
+ placeholder: labels.viewName,
602
+ "data-adapttable-part": "views-input",
603
+ className: classNames.viewsInput,
604
+ value: name,
605
+ onChange: (e) => setName(e.currentTarget.value)
606
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
607
+ type: "button",
608
+ disabled: trimmed === "",
609
+ "data-adapttable-part": "views-save",
610
+ className: classNames.viewsSave,
611
+ onClick: () => {
612
+ save(trimmed);
613
+ setName("");
614
+ },
615
+ children: labels.saveView
616
+ })]
617
+ })
618
+ ]
619
+ })]
620
+ });
730
621
  }
731
- function Chips({
732
- chips,
733
- onClearAll,
734
- labels,
735
- classNames
736
- }) {
737
- if (chips.length === 0) return null;
738
- return /* @__PURE__ */ jsxRuntime.jsxs(
739
- "ul",
740
- {
741
- "aria-label": labels.filters,
742
- "data-adapttable-part": "chips",
743
- className: classNames.chips,
744
- children: [
745
- chips.map((chip) => /* @__PURE__ */ jsxRuntime.jsxs(
746
- "li",
747
- {
748
- "data-adapttable-part": "chip",
749
- className: classNames.chip,
750
- children: [
751
- chip.label,
752
- /* @__PURE__ */ jsxRuntime.jsx(
753
- "button",
754
- {
755
- type: "button",
756
- "aria-label": `${labels.clearAll}: ${chip.label}`,
757
- "data-adapttable-part": "chip-remove",
758
- className: classNames.chipRemove,
759
- onClick: chip.onRemove,
760
- children: "\xD7"
761
- }
762
- )
763
- ]
764
- },
765
- chip.key
766
- )),
767
- /* @__PURE__ */ jsxRuntime.jsx("li", { children: /* @__PURE__ */ jsxRuntime.jsx(
768
- "button",
769
- {
770
- type: "button",
771
- onClick: onClearAll,
772
- className: classNames.chipRemove,
773
- children: labels.clearAll
774
- }
775
- ) })
776
- ]
777
- }
778
- );
622
+ //#endregion
623
+ //#region src/components/chrome.tsx
624
+ /** Removable filter-chip strip. Renders nothing when empty. */
625
+ function Chips({ chips, onClearAll, labels, classNames }) {
626
+ if (chips.length === 0) return null;
627
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
628
+ "aria-label": labels.filters,
629
+ "data-adapttable-part": "chips",
630
+ className: classNames.chips,
631
+ children: [chips.map((chip) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
632
+ "data-adapttable-part": "chip",
633
+ className: classNames.chip,
634
+ children: [chip.label, /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
635
+ type: "button",
636
+ "aria-label": `${labels.clearAll}: ${chip.label}`,
637
+ "data-adapttable-part": "chip-remove",
638
+ className: classNames.chipRemove,
639
+ onClick: chip.onRemove,
640
+ children: "×"
641
+ })]
642
+ }, chip.key)), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
643
+ "data-adapttable-part": "chip",
644
+ className: classNames.chip,
645
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
646
+ type: "button",
647
+ "data-adapttable-part": "chip-remove",
648
+ className: classNames.chipRemove,
649
+ onClick: onClearAll,
650
+ children: labels.clearAll
651
+ })
652
+ })]
653
+ });
779
654
  }
780
- function BulkBar({
781
- selection,
782
- total,
783
- bulkActions,
784
- confirm,
785
- labels,
786
- classNames
787
- }) {
788
- const {
789
- selectedIds,
790
- selectedCount,
791
- clear,
792
- headerState,
793
- visibleIds,
794
- allMatching,
795
- selectAllMatching
796
- } = selection;
797
- const { pending, run } = core.useBulkActionRunner({
798
- confirm,
799
- cancelLabel: labels.cancel,
800
- onComplete: clear
801
- });
802
- if (selectedCount === 0) return null;
803
- const ids = [...selectedIds];
804
- const showBanner = headerState === "all" && total > visibleIds.length;
805
- const scope = allMatching ? { allMatching: true, total } : void 0;
806
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-adapttable-part": "bulk-bar", className: classNames.bulkBar, children: [
807
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.selectedCount(selectedCount) }),
808
- showBanner && /* @__PURE__ */ jsxRuntime.jsxs(
809
- "div",
810
- {
811
- "data-adapttable-part": "select-all-banner",
812
- className: classNames.selectAllBanner,
813
- children: [
814
- /* @__PURE__ */ jsxRuntime.jsx(
815
- "span",
816
- {
817
- "data-adapttable-part": "select-all-text",
818
- className: classNames.selectAllText,
819
- children: allMatching ? labels.allMatchingSelected(total) : labels.pageSelected(visibleIds.length)
820
- }
821
- ),
822
- /* @__PURE__ */ jsxRuntime.jsx(
823
- "button",
824
- {
825
- type: "button",
826
- "data-adapttable-part": "select-all-button",
827
- className: classNames.selectAllButton,
828
- onClick: allMatching ? clear : selectAllMatching,
829
- children: allMatching ? labels.clearAll : labels.selectAllMatching(total)
830
- }
831
- )
832
- ]
833
- }
834
- ),
835
- /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: clear, disabled: pending !== null, children: labels.clearAll }),
836
- bulkActions.map((action) => {
837
- const reason = core.resolveDisabledReason(action.disabledReason?.(ids));
838
- return /* @__PURE__ */ jsxRuntime.jsxs(
839
- "button",
840
- {
841
- type: "button",
842
- title: reason,
843
- disabled: reason !== void 0 || pending !== null,
844
- "data-adapttable-part": "bulk-button",
845
- "data-color": action.color,
846
- className: classNames.bulkButton,
847
- onClick: () => run(action, ids, scope),
848
- children: [
849
- action.icon,
850
- action.label
851
- ]
852
- },
853
- action.key
854
- );
855
- })
856
- ] });
655
+ /** Selection toolbar with bulk-action buttons. */
656
+ function BulkBar({ selection, total, bulkActions, confirm, labels, classNames }) {
657
+ const { selectedIds, selectedCount, clear, headerState, visibleIds, allMatching, selectAllMatching } = selection;
658
+ const { pending, run } = (0, _adapttable_core.useBulkActionRunner)({
659
+ confirm,
660
+ cancelLabel: labels.cancel,
661
+ onComplete: clear
662
+ });
663
+ if (selectedCount === 0) return null;
664
+ const ids = [...selectedIds];
665
+ const showBanner = headerState === "all" && total > visibleIds.length;
666
+ const scope = allMatching ? {
667
+ allMatching: true,
668
+ total
669
+ } : void 0;
670
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
671
+ "data-adapttable-part": "bulk-bar",
672
+ className: classNames.bulkBar,
673
+ children: [
674
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.selectedCount(selectedCount) }),
675
+ showBanner && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
676
+ "data-adapttable-part": "select-all-banner",
677
+ className: classNames.selectAllBanner,
678
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
679
+ "data-adapttable-part": "select-all-text",
680
+ className: classNames.selectAllText,
681
+ children: allMatching ? labels.allMatchingSelected(total) : labels.pageSelected(visibleIds.length)
682
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
683
+ type: "button",
684
+ "data-adapttable-part": "select-all-button",
685
+ className: classNames.selectAllButton,
686
+ onClick: allMatching ? clear : selectAllMatching,
687
+ children: allMatching ? labels.clearAll : labels.selectAllMatching(total)
688
+ })]
689
+ }),
690
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
691
+ type: "button",
692
+ onClick: clear,
693
+ disabled: pending !== null,
694
+ children: labels.clearAll
695
+ }),
696
+ bulkActions.map((action) => {
697
+ const reason = (0, _adapttable_core.resolveDisabledReason)(action.disabledReason?.(ids));
698
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
699
+ type: "button",
700
+ title: reason,
701
+ disabled: reason !== void 0 || pending !== null,
702
+ "data-adapttable-part": "bulk-button",
703
+ "data-color": action.color,
704
+ className: classNames.bulkButton,
705
+ onClick: () => run(action, ids, scope),
706
+ children: [action.icon, action.label]
707
+ }, action.key);
708
+ })
709
+ ]
710
+ });
857
711
  }
858
- function RowsPerPageSelect({
859
- source,
860
- labels,
861
- classNames
862
- }) {
863
- return /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
864
- labels.rowsPerPage,
865
- " ",
866
- /* @__PURE__ */ jsxRuntime.jsx(
867
- "select",
868
- {
869
- "aria-label": labels.rowsPerPage,
870
- "data-adapttable-part": "rows-per-page",
871
- className: classNames.rowsPerPageSelect,
872
- value: source.limit,
873
- onChange: (e) => source.setLimit(Number(e.currentTarget.value)),
874
- children: core.pageSizeOptions(source.limit).map((n) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: n, children: n }, n))
875
- }
876
- )
877
- ] });
712
+ /** The rows-per-page selector shared by the toolbar (infinite) and footer. */
713
+ function RowsPerPageSelect({ source, labels, classNames }) {
714
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
715
+ labels.rowsPerPage,
716
+ " ",
717
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("select", {
718
+ "aria-label": labels.rowsPerPage,
719
+ "data-adapttable-part": "rows-per-page",
720
+ className: classNames.rowsPerPageSelect,
721
+ value: source.limit,
722
+ onChange: (e) => source.setLimit(Number(e.currentTarget.value)),
723
+ children: (0, _adapttable_core.pageSizeOptions)(source.limit).map((n) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
724
+ value: n,
725
+ children: n
726
+ }, n))
727
+ })
728
+ ] });
878
729
  }
879
- function Footer({
880
- pagination,
881
- source,
882
- labels,
883
- classNames
884
- }) {
885
- const { safePage, totalPages, fromIndex, toIndex } = pagination;
886
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-adapttable-part": "footer", className: classNames.footer, children: [
887
- /* @__PURE__ */ jsxRuntime.jsx(
888
- RowsPerPageSelect,
889
- {
890
- source,
891
- labels,
892
- classNames
893
- }
894
- ),
895
- source.total > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.showing({
896
- from: fromIndex,
897
- to: toIndex,
898
- total: source.total
899
- }) }),
900
- /* @__PURE__ */ jsxRuntime.jsx("span", { children: labels.pageOf({ page: safePage, total: totalPages }) }),
901
- /* @__PURE__ */ jsxRuntime.jsx(
902
- "button",
903
- {
904
- type: "button",
905
- "aria-label": labels.previousPage,
906
- "data-adapttable-part": "page-prev",
907
- className: classNames.pageButton,
908
- disabled: safePage <= 1,
909
- onClick: () => source.setPage(safePage - 1),
910
- children: "\u2039"
911
- }
912
- ),
913
- /* @__PURE__ */ jsxRuntime.jsx(
914
- "button",
915
- {
916
- type: "button",
917
- "aria-label": labels.nextPage,
918
- "data-adapttable-part": "page-next",
919
- className: classNames.pageButton,
920
- disabled: safePage >= totalPages,
921
- onClick: () => source.setPage(safePage + 1),
922
- children: "\u203A"
923
- }
924
- )
925
- ] });
730
+ /** Prev/next pager with a rows-per-page select. */
731
+ function Footer({ pagination, source, labels, classNames }) {
732
+ const { safePage, totalPages, fromIndex, toIndex } = pagination;
733
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
734
+ "data-adapttable-part": "footer",
735
+ className: classNames.footer,
736
+ children: [
737
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowsPerPageSelect, {
738
+ source,
739
+ labels,
740
+ classNames
741
+ }),
742
+ source.total > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.showing({
743
+ from: fromIndex,
744
+ to: toIndex,
745
+ total: source.total
746
+ }) }),
747
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: labels.pageOf({
748
+ page: safePage,
749
+ total: totalPages
750
+ }) }),
751
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
752
+ type: "button",
753
+ "aria-label": labels.previousPage,
754
+ "data-adapttable-part": "page-prev",
755
+ className: classNames.pageButton,
756
+ disabled: safePage <= 1,
757
+ onClick: () => source.setPage(safePage - 1),
758
+ children: "‹"
759
+ }),
760
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
761
+ type: "button",
762
+ "aria-label": labels.nextPage,
763
+ "data-adapttable-part": "page-next",
764
+ className: classNames.pageButton,
765
+ disabled: safePage >= totalPages,
766
+ onClick: () => source.setPage(safePage + 1),
767
+ children: ""
768
+ })
769
+ ]
770
+ });
926
771
  }
927
- function ErrorState({
928
- error,
929
- labels,
930
- onRetry,
931
- classNames
932
- }) {
933
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "alert", "data-adapttable-part": "error", className: classNames.error, children: [
934
- /* @__PURE__ */ jsxRuntime.jsx("strong", { children: labels.errorTitle }),
935
- /* @__PURE__ */ jsxRuntime.jsx("p", { children: labels.errorMessage }),
936
- /* @__PURE__ */ jsxRuntime.jsx("small", { children: error.message }),
937
- onRetry && /* @__PURE__ */ jsxRuntime.jsx(
938
- "button",
939
- {
940
- type: "button",
941
- onClick: onRetry,
942
- "data-adapttable-part": "retry",
943
- className: classNames.retryButton,
944
- children: labels.retry
945
- }
946
- )
947
- ] });
772
+ /** Inline error with optional retry. */
773
+ function ErrorState({ error, labels, onRetry, classNames }) {
774
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
775
+ role: "alert",
776
+ "data-adapttable-part": "error",
777
+ className: classNames.error,
778
+ children: [
779
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: labels.errorTitle }),
780
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", { children: labels.errorMessage }),
781
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("small", { children: error.message }),
782
+ onRetry && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
783
+ type: "button",
784
+ onClick: onRetry,
785
+ "data-adapttable-part": "retry",
786
+ className: classNames.retryButton,
787
+ children: labels.retry
788
+ })
789
+ ]
790
+ });
948
791
  }
949
792
  function loadingLineWidth(column, total) {
950
- if (column === 0) return "70%";
951
- if (column === total - 1) return "42%";
952
- return "55%";
793
+ if (column === 0) return "70%";
794
+ if (column === total - 1) return "42%";
795
+ return "55%";
953
796
  }
954
- function LoadingState({
955
- rows,
956
- columns,
957
- variant,
958
- labels,
959
- classNames,
960
- hasActions = false
961
- }) {
962
- const rowKeys = Array.from({ length: rows }, (_, i) => i);
963
- const dataColumns = Math.max(columns, 1);
964
- const columnCount = dataColumns + (hasActions ? 1 : 0);
965
- const columnKeys = Array.from({ length: columnCount }, (_, i) => i);
966
- return /* @__PURE__ */ jsxRuntime.jsxs(
967
- "div",
968
- {
969
- role: "status",
970
- "aria-busy": "true",
971
- "aria-live": "polite",
972
- "data-adapttable-part": "loading",
973
- className: cx(classNames.loading),
974
- children: [
975
- variant === "table" ? /* @__PURE__ */ jsxRuntime.jsxs("table", { "data-adapttable-part": "loading-table", children: [
976
- /* @__PURE__ */ jsxRuntime.jsx("thead", { children: /* @__PURE__ */ jsxRuntime.jsx("tr", { "data-adapttable-part": "loading-header-row", children: columnKeys.map((column) => /* @__PURE__ */ jsxRuntime.jsx("th", { "data-adapttable-part": "loading-header-cell", children: /* @__PURE__ */ jsxRuntime.jsx(
977
- "span",
978
- {
979
- "data-adapttable-part": "loading-line",
980
- style: { width: loadingLineWidth(column, columnCount) }
981
- }
982
- ) }, column)) }) }),
983
- /* @__PURE__ */ jsxRuntime.jsx("tbody", { children: rowKeys.map((row) => /* @__PURE__ */ jsxRuntime.jsx("tr", { "data-adapttable-part": "loading-row", children: columnKeys.map((column) => /* @__PURE__ */ jsxRuntime.jsx("td", { "data-adapttable-part": "loading-cell", children: /* @__PURE__ */ jsxRuntime.jsx(
984
- "span",
985
- {
986
- "data-adapttable-part": "loading-line",
987
- style: {
988
- width: loadingLineWidth(column, columnCount)
989
- }
990
- }
991
- ) }, column)) }, row)) })
992
- ] }) : /* @__PURE__ */ jsxRuntime.jsx("div", { "data-adapttable-part": "loading-cards", children: rowKeys.map((row) => /* @__PURE__ */ jsxRuntime.jsx("div", { "data-adapttable-part": "loading-card", children: columnKeys.slice(0, Math.min(4, columnKeys.length)).map((column) => /* @__PURE__ */ jsxRuntime.jsx(
993
- "span",
994
- {
995
- "data-adapttable-part": "loading-line",
996
- style: {
997
- width: loadingLineWidth(column, columnKeys.length)
998
- }
999
- },
1000
- column
1001
- )) }, row)) }),
1002
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "adapttable-sr-only", children: labels.loading })
1003
- ]
1004
- }
1005
- );
797
+ /** Skeleton-ish loading placeholder (semantic, unstyled). */
798
+ function LoadingState({ rows, columns, variant, labels, classNames, hasActions = false }) {
799
+ const rowKeys = Array.from({ length: rows }, (_, i) => i);
800
+ const columnCount = Math.max(columns, 1) + (hasActions ? 1 : 0);
801
+ const columnKeys = Array.from({ length: columnCount }, (_, i) => i);
802
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
803
+ role: "status",
804
+ "aria-busy": "true",
805
+ "aria-live": "polite",
806
+ "data-adapttable-part": "loading",
807
+ className: cx(classNames.loading),
808
+ children: [variant === "table" ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
809
+ "data-adapttable-part": "loading-table",
810
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("thead", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
811
+ "data-adapttable-part": "loading-header-row",
812
+ children: columnKeys.map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
813
+ "data-adapttable-part": "loading-header-cell",
814
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
815
+ "data-adapttable-part": "loading-line",
816
+ style: { width: loadingLineWidth(column, columnCount) }
817
+ })
818
+ }, column))
819
+ }) }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tbody", { children: rowKeys.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
820
+ "data-adapttable-part": "loading-row",
821
+ children: columnKeys.map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
822
+ "data-adapttable-part": "loading-cell",
823
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
824
+ "data-adapttable-part": "loading-line",
825
+ style: { width: loadingLineWidth(column, columnCount) }
826
+ })
827
+ }, column))
828
+ }, row)) })]
829
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
830
+ "data-adapttable-part": "loading-cards",
831
+ children: rowKeys.map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
832
+ "data-adapttable-part": "loading-card",
833
+ children: columnKeys.slice(0, Math.min(4, columnKeys.length)).map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
834
+ "data-adapttable-part": "loading-line",
835
+ style: { width: loadingLineWidth(column, columnKeys.length) }
836
+ }, column))
837
+ }, row))
838
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
839
+ className: "adapttable-sr-only",
840
+ children: labels.loading
841
+ })]
842
+ });
1006
843
  }
1007
- function VisibilityToggle({
1008
- hidden,
1009
- name,
1010
- labels,
1011
- classNames,
1012
- onToggle
1013
- }) {
1014
- return /* @__PURE__ */ jsxRuntime.jsx(
1015
- "button",
1016
- {
1017
- type: "button",
1018
- "data-adapttable-part": "column-menu-visibility",
1019
- "data-active": !hidden || void 0,
1020
- "aria-pressed": !hidden,
1021
- "aria-label": `${hidden ? labels.showColumn : labels.hideColumn}: ${name}`,
1022
- className: classNames.columnMenuVisibility,
1023
- onClick: onToggle,
1024
- children: /* @__PURE__ */ jsxRuntime.jsx(core.EyeIcon, { off: hidden })
1025
- }
1026
- );
844
+ //#endregion
845
+ //#region src/components/ColumnMenu.tsx
846
+ /** The eye toggle shared by data-column rows and the actions row. */
847
+ function VisibilityToggle({ hidden, name, labels, classNames, onToggle }) {
848
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
849
+ type: "button",
850
+ "data-adapttable-part": "column-menu-visibility",
851
+ "data-active": !hidden || void 0,
852
+ "aria-pressed": !hidden,
853
+ "aria-label": `${hidden ? labels.showColumn : labels.hideColumn}: ${name}`,
854
+ className: classNames.columnMenuVisibility,
855
+ onClick: onToggle,
856
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_adapttable_core.EyeIcon, { off: hidden })
857
+ });
1027
858
  }
1028
- function RowName({
1029
- hidden,
1030
- name,
1031
- classNames
1032
- }) {
1033
- return /* @__PURE__ */ jsxRuntime.jsx(
1034
- "span",
1035
- {
1036
- "data-adapttable-part": "column-menu-label",
1037
- "data-hidden": hidden || void 0,
1038
- className: classNames.columnMenuLabel,
1039
- children: name
1040
- }
1041
- );
859
+ /** The row's name caption, shared by data-column rows and the actions row. */
860
+ function RowName({ hidden, name, classNames }) {
861
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
862
+ "data-adapttable-part": "column-menu-label",
863
+ "data-hidden": hidden || void 0,
864
+ className: classNames.columnMenuLabel,
865
+ children: name
866
+ });
1042
867
  }
1043
- function PinToggle({
1044
- active,
1045
- actionLabel,
1046
- classNames,
1047
- onClick
1048
- }) {
1049
- return /* @__PURE__ */ jsxRuntime.jsx(
1050
- "button",
1051
- {
1052
- type: "button",
1053
- "data-adapttable-part": "column-menu-pin",
1054
- "data-active": active || void 0,
1055
- "aria-pressed": active,
1056
- "aria-label": actionLabel,
1057
- className: classNames.columnMenuPin,
1058
- onClick,
1059
- children: /* @__PURE__ */ jsxRuntime.jsx(core.PinIcon, {})
1060
- }
1061
- );
868
+ /** The pin toggle shared by data-column rows and the actions row. */
869
+ function PinToggle({ active, actionLabel, classNames, onClick }) {
870
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
871
+ type: "button",
872
+ "data-adapttable-part": "column-menu-pin",
873
+ "data-active": active || void 0,
874
+ "aria-pressed": active,
875
+ "aria-label": actionLabel,
876
+ className: classNames.columnMenuPin,
877
+ onClick,
878
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_adapttable_core.PinIcon, {})
879
+ });
1062
880
  }
1063
- function ColumnMenuRowItem({
1064
- row,
1065
- layout,
1066
- labels,
1067
- classNames,
1068
- drag
1069
- }) {
1070
- const { key, name, hidden, pinned, index } = row;
1071
- return /* @__PURE__ */ jsxRuntime.jsxs(
1072
- "div",
1073
- {
1074
- "data-adapttable-part": "column-menu-item",
1075
- "data-hidden": hidden || void 0,
1076
- "data-pinned": pinned,
1077
- className: classNames.columnMenuItem,
1078
- style: { cursor: "grab" },
1079
- ...drag.rowDragProps(key, index),
1080
- ...drag.dropProps(index, layout.move),
1081
- ...drag.rowAttrs(key, index),
1082
- children: [
1083
- /* @__PURE__ */ jsxRuntime.jsx(
1084
- "span",
1085
- {
1086
- "data-adapttable-part": "column-menu-grip",
1087
- className: classNames.columnMenuGrip,
1088
- ...core.columnReorderKeyProps(
1089
- key,
1090
- index,
1091
- layout.move,
1092
- `${labels.moveLeft} / ${labels.moveRight}: ${name}`
1093
- ),
1094
- children: /* @__PURE__ */ jsxRuntime.jsx(core.GripIcon, {})
1095
- }
1096
- ),
1097
- /* @__PURE__ */ jsxRuntime.jsx(
1098
- VisibilityToggle,
1099
- {
1100
- hidden,
1101
- name,
1102
- labels,
1103
- classNames,
1104
- onToggle: () => layout.toggleVisible(key)
1105
- }
1106
- ),
1107
- /* @__PURE__ */ jsxRuntime.jsx(RowName, { hidden, name, classNames }),
1108
- /* @__PURE__ */ jsxRuntime.jsx(
1109
- PinToggle,
1110
- {
1111
- active: pinned !== void 0,
1112
- actionLabel: `${core.pinActionLabel(pinned, labels)}: ${name}`,
1113
- classNames,
1114
- onClick: () => layout.setPinned(key, core.nextPinSide(pinned))
1115
- }
1116
- )
1117
- ]
1118
- }
1119
- );
881
+ function ColumnMenuRowItem({ row, layout, labels, classNames, drag }) {
882
+ const { key, name, hidden, pinned, index } = row;
883
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
884
+ "data-adapttable-part": "column-menu-item",
885
+ "data-hidden": hidden || void 0,
886
+ "data-pinned": pinned,
887
+ className: classNames.columnMenuItem,
888
+ style: { cursor: "grab" },
889
+ ...drag.rowDragProps(key, index),
890
+ ...drag.dropProps(index, layout.move),
891
+ ...drag.rowAttrs(key, index),
892
+ children: [
893
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
894
+ "data-adapttable-part": "column-menu-grip",
895
+ className: classNames.columnMenuGrip,
896
+ ...(0, _adapttable_core.columnReorderKeyProps)(key, index, layout.move, `${labels.moveLeft} / ${labels.moveRight}: ${name}`),
897
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_adapttable_core.GripIcon, {})
898
+ }),
899
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VisibilityToggle, {
900
+ hidden,
901
+ name,
902
+ labels,
903
+ classNames,
904
+ onToggle: () => layout.toggleVisible(key)
905
+ }),
906
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowName, {
907
+ hidden,
908
+ name,
909
+ classNames
910
+ }),
911
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinToggle, {
912
+ active: pinned !== void 0,
913
+ actionLabel: `${(0, _adapttable_core.pinActionLabel)(pinned, labels)}: ${name}`,
914
+ classNames,
915
+ onClick: () => layout.setPinned(key, (0, _adapttable_core.nextPinSide)(pinned))
916
+ })
917
+ ]
918
+ });
1120
919
  }
1121
- function ActionsMenuRowItem({
1122
- layout,
1123
- labels,
1124
- classNames
1125
- }) {
1126
- const hidden = layout.isHidden(core.ACTIONS_COLUMN_KEY);
1127
- const pinned = layout.state.pinned[core.ACTIONS_COLUMN_KEY] !== void 0;
1128
- const name = labels.actions;
1129
- return /* @__PURE__ */ jsxRuntime.jsxs(
1130
- "div",
1131
- {
1132
- "data-adapttable-part": "column-menu-item",
1133
- "data-actions": "",
1134
- "data-hidden": hidden || void 0,
1135
- "data-pinned": pinned ? "right" : void 0,
1136
- className: classNames.columnMenuItem,
1137
- children: [
1138
- /* @__PURE__ */ jsxRuntime.jsx(
1139
- VisibilityToggle,
1140
- {
1141
- hidden,
1142
- name,
1143
- labels,
1144
- classNames,
1145
- onToggle: () => layout.toggleVisible(core.ACTIONS_COLUMN_KEY)
1146
- }
1147
- ),
1148
- /* @__PURE__ */ jsxRuntime.jsx(RowName, { hidden, name, classNames }),
1149
- /* @__PURE__ */ jsxRuntime.jsx(
1150
- PinToggle,
1151
- {
1152
- active: pinned,
1153
- actionLabel: `${pinned ? labels.unpin : labels.pinRight}: ${name}`,
1154
- classNames,
1155
- onClick: () => layout.setPinned(core.ACTIONS_COLUMN_KEY, pinned ? void 0 : "right")
1156
- }
1157
- )
1158
- ]
1159
- }
1160
- );
920
+ /**
921
+ * The injected row-actions column as a first-class menu row: the same eye
922
+ * toggle as a data column plus a ONE-CLICK end-pin toggle (right ↔ unpinned).
923
+ * The column always trails, so there is no left pin and no reorder grip.
924
+ */
925
+ function ActionsMenuRowItem({ layout, labels, classNames }) {
926
+ const hidden = layout.isHidden(_adapttable_core.ACTIONS_COLUMN_KEY);
927
+ const pinned = layout.state.pinned[_adapttable_core.ACTIONS_COLUMN_KEY] !== void 0;
928
+ const name = labels.actions;
929
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
930
+ "data-adapttable-part": "column-menu-item",
931
+ "data-actions": "",
932
+ "data-hidden": hidden || void 0,
933
+ "data-pinned": pinned ? "right" : void 0,
934
+ className: classNames.columnMenuItem,
935
+ children: [
936
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VisibilityToggle, {
937
+ hidden,
938
+ name,
939
+ labels,
940
+ classNames,
941
+ onToggle: () => layout.toggleVisible(_adapttable_core.ACTIONS_COLUMN_KEY)
942
+ }),
943
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowName, {
944
+ hidden,
945
+ name,
946
+ classNames
947
+ }),
948
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinToggle, {
949
+ active: pinned,
950
+ actionLabel: `${pinned ? labels.unpin : labels.pinRight}: ${name}`,
951
+ classNames,
952
+ onClick: () => layout.setPinned(_adapttable_core.ACTIONS_COLUMN_KEY, pinned ? void 0 : "right")
953
+ })
954
+ ]
955
+ });
1161
956
  }
1162
- function ColumnMenu({
1163
- allColumns,
1164
- layout,
1165
- labels,
1166
- classNames,
1167
- hasRowActions
1168
- }) {
1169
- const drag = core.useColumnDragState();
1170
- const { open, setOpen, rootRef, triggerRef } = useMenuPopover();
1171
- return /* @__PURE__ */ jsxRuntime.jsxs(
1172
- "div",
1173
- {
1174
- ref: rootRef,
1175
- "data-adapttable-part": "column-menu",
1176
- className: classNames.columnMenu,
1177
- style: { position: "relative" },
1178
- children: [
1179
- /* @__PURE__ */ jsxRuntime.jsx(
1180
- "button",
1181
- {
1182
- ref: triggerRef,
1183
- type: "button",
1184
- "aria-expanded": open,
1185
- "aria-haspopup": "true",
1186
- "data-adapttable-part": "column-menu-button",
1187
- "data-active": open || void 0,
1188
- className: classNames.columnMenuButton,
1189
- style: { flexShrink: 0, whiteSpace: "nowrap" },
1190
- onClick: () => setOpen((v) => !v),
1191
- children: labels.columns
1192
- }
1193
- ),
1194
- open && /* @__PURE__ */ jsxRuntime.jsxs(
1195
- "fieldset",
1196
- {
1197
- "aria-label": labels.columns,
1198
- "data-adapttable-part": "column-menu-panel",
1199
- className: classNames.columnMenuPanel,
1200
- style: MENU_PANEL_STYLE,
1201
- children: [
1202
- /* @__PURE__ */ jsxRuntime.jsx(
1203
- "div",
1204
- {
1205
- "data-adapttable-part": "column-menu-header",
1206
- className: classNames.columnMenuHeader,
1207
- children: /* @__PURE__ */ jsxRuntime.jsx(
1208
- "span",
1209
- {
1210
- "data-adapttable-part": "column-menu-title",
1211
- className: classNames.columnMenuTitle,
1212
- children: labels.columns
1213
- }
1214
- )
1215
- }
1216
- ),
1217
- core.columnMenuRows(allColumns, layout).map((row) => /* @__PURE__ */ jsxRuntime.jsx(
1218
- ColumnMenuRowItem,
1219
- {
1220
- row,
1221
- layout,
1222
- labels,
1223
- classNames,
1224
- drag
1225
- },
1226
- row.key
1227
- )),
1228
- hasRowActions && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1229
- /* @__PURE__ */ jsxRuntime.jsx(
1230
- "hr",
1231
- {
1232
- "data-adapttable-part": "column-menu-separator",
1233
- className: classNames.columnMenuSeparator
1234
- }
1235
- ),
1236
- /* @__PURE__ */ jsxRuntime.jsx(
1237
- ActionsMenuRowItem,
1238
- {
1239
- layout,
1240
- labels,
1241
- classNames
1242
- }
1243
- )
1244
- ] }),
1245
- /* @__PURE__ */ jsxRuntime.jsx(
1246
- "button",
1247
- {
1248
- type: "button",
1249
- "data-adapttable-part": "column-menu-reset",
1250
- className: cx(classNames.columnMenuReset),
1251
- onClick: () => layout.reset(),
1252
- children: labels.resetColumns
1253
- }
1254
- )
1255
- ]
1256
- }
1257
- )
1258
- ]
1259
- }
1260
- );
957
+ /**
958
+ * Column-management popover: a disclosure button + a panel where each column
959
+ * has a drag grip (reorder), an eye toggle (show/hide), and a pin toggle.
960
+ * Closes on outside-click or Escape. Ships no styles — target the
961
+ * `data-adapttable-part` hooks or the `columnMenu*` className slots.
962
+ */
963
+ function ColumnMenu({ allColumns, layout, labels, classNames, hasRowActions }) {
964
+ const drag = (0, _adapttable_core.useColumnDragState)();
965
+ const { open, setOpen, rootRef, triggerRef } = useMenuPopover();
966
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
967
+ ref: rootRef,
968
+ "data-adapttable-part": "column-menu",
969
+ className: classNames.columnMenu,
970
+ style: { position: "relative" },
971
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
972
+ ref: triggerRef,
973
+ type: "button",
974
+ "aria-expanded": open,
975
+ "aria-haspopup": "true",
976
+ "data-adapttable-part": "column-menu-button",
977
+ "data-active": open || void 0,
978
+ className: classNames.columnMenuButton,
979
+ style: {
980
+ flexShrink: 0,
981
+ whiteSpace: "nowrap"
982
+ },
983
+ onClick: () => setOpen((v) => !v),
984
+ children: labels.columns
985
+ }), open && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("fieldset", {
986
+ "aria-label": labels.columns,
987
+ "data-adapttable-part": "column-menu-panel",
988
+ className: classNames.columnMenuPanel,
989
+ style: MENU_PANEL_STYLE,
990
+ children: [
991
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
992
+ "data-adapttable-part": "column-menu-header",
993
+ className: classNames.columnMenuHeader,
994
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
995
+ "data-adapttable-part": "column-menu-title",
996
+ className: classNames.columnMenuTitle,
997
+ children: labels.columns
998
+ })
999
+ }),
1000
+ (0, _adapttable_core.columnMenuRows)(allColumns, layout).map((row) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColumnMenuRowItem, {
1001
+ row,
1002
+ layout,
1003
+ labels,
1004
+ classNames,
1005
+ drag
1006
+ }, row.key)),
1007
+ hasRowActions && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("hr", {
1008
+ "data-adapttable-part": "column-menu-separator",
1009
+ className: classNames.columnMenuSeparator
1010
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActionsMenuRowItem, {
1011
+ layout,
1012
+ labels,
1013
+ classNames
1014
+ })] }),
1015
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1016
+ type: "button",
1017
+ "data-adapttable-part": "column-menu-reset",
1018
+ className: cx(classNames.columnMenuReset),
1019
+ onClick: () => layout.reset(),
1020
+ children: labels.resetColumns
1021
+ })
1022
+ ]
1023
+ })]
1024
+ });
1261
1025
  }
1262
- var RESIZE_HANDLE_STYLE = {
1263
- position: "absolute",
1264
- insetInlineEnd: 0,
1265
- top: 0,
1266
- height: "100%",
1267
- width: 8,
1268
- cursor: "col-resize",
1269
- touchAction: "none",
1270
- userSelect: "none"
1026
+ //#endregion
1027
+ //#region src/components/tables.tsx
1028
+ /** Inline style for an absolutely-positioned column-resize handle. */
1029
+ const RESIZE_HANDLE_STYLE = {
1030
+ position: "absolute",
1031
+ insetInlineEnd: 0,
1032
+ top: 0,
1033
+ height: "100%",
1034
+ width: 8,
1035
+ cursor: "col-resize",
1036
+ touchAction: "none",
1037
+ userSelect: "none"
1271
1038
  };
1272
- var SELECTION_WIDTH = 44;
1273
- var ACTIONS_WIDTH = 120;
1039
+ const SELECTION_WIDTH = 44;
1040
+ const ACTIONS_WIDTH = 120;
1041
+ /**
1042
+ * Scroll-box style: a `maxHeight`-bounded box scrolls on both axes; otherwise
1043
+ * the wrapper scrolls sideways only when something needs it (a pinned column,
1044
+ * or measured horizontal overflow). When the table fits, the wrapper carries
1045
+ * NO overflow style — `overflow-x: auto` makes `overflow-y` compute to `auto`
1046
+ * too, which would trap a page-scroll sticky header inside the box.
1047
+ */
1274
1048
  function scrollBoxStyle(maxHeight, scrollX) {
1275
- if (maxHeight != null) {
1276
- return { maxHeight, overflowX: "auto", overflowY: "auto" };
1277
- }
1278
- return scrollX ? { overflowX: "auto" } : void 0;
1049
+ if (maxHeight != null) return {
1050
+ maxHeight,
1051
+ overflowX: "auto",
1052
+ overflowY: "auto"
1053
+ };
1054
+ return scrollX ? { overflowX: "auto" } : void 0;
1279
1055
  }
1280
- function RowActionButtons({
1281
- row,
1282
- actions,
1283
- confirm,
1284
- cancelLabel,
1285
- classNames
1286
- }) {
1287
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: actions.map((action) => {
1288
- if (action.isHidden?.(row)) return null;
1289
- const reason = core.resolveDisabledReason(action.disabledReason?.(row));
1290
- const disabled = reason !== void 0 || (action.isDisabled?.(row) ?? false);
1291
- const handleClick = disabled ? void 0 : (e) => {
1292
- e.stopPropagation();
1293
- core.runRowAction(action, row, confirm, cancelLabel);
1294
- };
1295
- return /* @__PURE__ */ jsxRuntime.jsx(
1296
- "button",
1297
- {
1298
- type: "button",
1299
- disabled,
1300
- title: reason,
1301
- "aria-label": action.label,
1302
- "data-adapttable-part": "action-button",
1303
- "data-color": action.color,
1304
- className: classNames.actionButton,
1305
- onClick: handleClick,
1306
- children: action.icon ?? action.label
1307
- },
1308
- action.key
1309
- );
1310
- }) });
1056
+ function RowActionButtons({ row, actions, confirm, cancelLabel, classNames }) {
1057
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: actions.map((action) => {
1058
+ if (action.isHidden?.(row)) return null;
1059
+ const reason = (0, _adapttable_core.resolveDisabledReason)(action.disabledReason?.(row));
1060
+ const disabled = reason !== void 0 || (action.isDisabled?.(row) ?? false);
1061
+ const handleClick = disabled ? void 0 : (e) => {
1062
+ e.stopPropagation();
1063
+ (0, _adapttable_core.runRowAction)(action, row, confirm, cancelLabel);
1064
+ };
1065
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1066
+ type: "button",
1067
+ disabled,
1068
+ title: reason,
1069
+ "aria-label": action.label,
1070
+ "data-adapttable-part": "action-button",
1071
+ "data-color": action.color,
1072
+ className: classNames.actionButton,
1073
+ onClick: handleClick,
1074
+ children: action.icon ?? action.label
1075
+ }, action.key);
1076
+ }) });
1311
1077
  }
1312
- function ExpandButton({
1313
- expanded,
1314
- labels,
1315
- classNames,
1316
- onToggle
1317
- }) {
1318
- return /* @__PURE__ */ jsxRuntime.jsx(
1319
- "button",
1320
- {
1321
- type: "button",
1322
- "data-adapttable-part": "expand-button",
1323
- "data-expanded": expanded ? "" : void 0,
1324
- className: classNames.expandButton,
1325
- "aria-expanded": expanded,
1326
- "aria-label": expanded ? labels.collapseRow : labels.expandRow,
1327
- onClick: onToggle,
1328
- children: /* @__PURE__ */ jsxRuntime.jsx(ChevronIcon, { size: 14 })
1329
- }
1330
- );
1078
+ /**
1079
+ * The expand/collapse chevron, shared by desktop rows and mobile cards. The
1080
+ * `data-expanded` attribute is the styling hook for rotating the glyph
1081
+ * (`rowClickProps`' interactive-child guard keeps the click off the row).
1082
+ */
1083
+ function ExpandButton({ expanded, labels, classNames, onToggle }) {
1084
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1085
+ type: "button",
1086
+ "data-adapttable-part": "expand-button",
1087
+ "data-expanded": expanded ? "" : void 0,
1088
+ className: classNames.expandButton,
1089
+ "aria-expanded": expanded,
1090
+ "aria-label": expanded ? labels.collapseRow : labels.expandRow,
1091
+ onClick: onToggle,
1092
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ChevronIcon, { size: 14 })
1093
+ });
1331
1094
  }
1095
+ /**
1096
+ * `React.memo` comparator: re-render a row only when one of its VISUAL
1097
+ * inputs changes. A search keystroke or another row's checkbox re-renders
1098
+ * the table shell, but every unchanged row bails out here (accessors and
1099
+ * Cell render-props are not re-invoked).
1100
+ */
1332
1101
  function desktopRowPropsEqual(prev, next) {
1333
- return prev.row === next.row && prev.index === next.index && prev.id === next.id && prev.selected === next.selected && prev.expanded === next.expanded && prev.columns === next.columns && prev.labels === next.labels && prev.classNames === next.classNames && prev.showActions === next.showActions && prev.rowActions === next.rowActions && prev.columnSpan === next.columnSpan && prev.columnWidths === next.columnWidths && prev.pinSignature === next.pinSignature && prev.hasLeftPin === next.hasLeftPin && prev.hasRightPin === next.hasRightPin && prev.actionsPinned === next.actionsPinned && prev.rowClass === next.rowClass && prev.clickable === next.clickable && prev.hasPrefetch === next.hasPrefetch;
1102
+ return prev.row === next.row && prev.index === next.index && prev.id === next.id && prev.selected === next.selected && prev.expanded === next.expanded && prev.columns === next.columns && prev.labels === next.labels && prev.classNames === next.classNames && prev.showActions === next.showActions && prev.rowActions === next.rowActions && prev.columnSpan === next.columnSpan && prev.columnWidths === next.columnWidths && prev.pinSignature === next.pinSignature && prev.hasLeftPin === next.hasLeftPin && prev.hasRightPin === next.hasRightPin && prev.actionsPinned === next.actionsPinned && prev.rowClass === next.rowClass && prev.clickable === next.clickable && prev.hasPrefetch === next.hasPrefetch;
1334
1103
  }
1335
1104
  function DesktopRowBase(props) {
1336
- const {
1337
- row,
1338
- index,
1339
- id,
1340
- table,
1341
- columns,
1342
- labels,
1343
- classNames,
1344
- selected,
1345
- expanded,
1346
- showActions,
1347
- rowActions,
1348
- confirm,
1349
- columnSpan,
1350
- pinOffset,
1351
- hasLeftPin,
1352
- hasRightPin,
1353
- actionsPinned,
1354
- rowClass,
1355
- clickable,
1356
- hasPrefetch,
1357
- onRowClick,
1358
- onPrefetch,
1359
- onToggleSelect,
1360
- onToggleExpand,
1361
- renderDetail,
1362
- measureElement
1363
- } = props;
1364
- const expandable = expanded !== void 0;
1365
- const leads = {
1366
- left: selected === void 0 ? 0 : SELECTION_WIDTH,
1367
- right: showActions ? ACTIONS_WIDTH : 0
1368
- };
1369
- const bodyPinStyle = (key) => core.pinnedCellStyle(pinOffset?.(key), core.PIN_Z.body, leads);
1370
- const rowProps = { ...table.getRowProps(row, index) };
1371
- delete rowProps.key;
1372
- return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1373
- /* @__PURE__ */ jsxRuntime.jsxs(
1374
- "tr",
1375
- {
1376
- ...rowProps,
1377
- ...core.rowClickProps(row, clickable ? onRowClick : void 0),
1378
- ref: measureElement,
1379
- "data-adapttable-part": "row",
1380
- "data-selected": selected ? "" : void 0,
1381
- "data-clickable": clickable ? "" : void 0,
1382
- className: cx(classNames.row, rowClass),
1383
- onMouseEnter: hasPrefetch ? () => onPrefetch(row) : void 0,
1384
- children: [
1385
- expandable && /* @__PURE__ */ jsxRuntime.jsx(
1386
- "td",
1387
- {
1388
- "data-adapttable-part": "expand-cell",
1389
- className: classNames.expandCell,
1390
- children: /* @__PURE__ */ jsxRuntime.jsx(
1391
- ExpandButton,
1392
- {
1393
- expanded,
1394
- labels,
1395
- classNames,
1396
- onToggle: () => onToggleExpand(id)
1397
- }
1398
- )
1399
- }
1400
- ),
1401
- selected !== void 0 && /* @__PURE__ */ jsxRuntime.jsx(
1402
- "td",
1403
- {
1404
- "data-adapttable-part": "selection-cell",
1405
- "data-pinned": hasLeftPin ? "left" : void 0,
1406
- style: core.edgePinStyle("left", hasLeftPin, core.PIN_Z.body),
1407
- className: cx(classNames.cell, classNames.selectionCell),
1408
- children: /* @__PURE__ */ jsxRuntime.jsx(
1409
- "input",
1410
- {
1411
- type: "checkbox",
1412
- "aria-label": labels.selectRow,
1413
- checked: selected,
1414
- onChange: () => onToggleSelect(id),
1415
- className: classNames.checkbox
1416
- }
1417
- )
1418
- }
1419
- ),
1420
- columns.map((column) => {
1421
- const pinStyle = bodyPinStyle(column.key);
1422
- return /* @__PURE__ */ jsxRuntime.jsx(
1423
- "td",
1424
- {
1425
- ...table.getCellProps(column, pinStyle && { style: pinStyle }),
1426
- "data-adapttable-part": "cell",
1427
- "data-pinned": pinOffset?.(column.key)?.side,
1428
- className: classNames.cell,
1429
- children: column.Cell ? /* @__PURE__ */ jsxRuntime.jsx(column.Cell, { row, rowIndex: index }) : column.accessor?.(row)
1430
- },
1431
- column.key
1432
- );
1433
- }),
1434
- showActions && /* @__PURE__ */ jsxRuntime.jsx(
1435
- "td",
1436
- {
1437
- "data-adapttable-part": "actions-cell",
1438
- "data-pinned": hasRightPin || actionsPinned ? "right" : void 0,
1439
- style: core.edgePinStyle(
1440
- "right",
1441
- hasRightPin || actionsPinned,
1442
- core.PIN_Z.body
1443
- ),
1444
- className: cx(classNames.cell, classNames.actionsCell),
1445
- children: /* @__PURE__ */ jsxRuntime.jsx(
1446
- RowActionButtons,
1447
- {
1448
- row,
1449
- actions: rowActions,
1450
- confirm,
1451
- cancelLabel: labels.cancel,
1452
- classNames
1453
- }
1454
- )
1455
- }
1456
- )
1457
- ]
1458
- }
1459
- ),
1460
- expandable && expanded && /* @__PURE__ */ jsxRuntime.jsx("tr", { "data-adapttable-part": "detail-row", className: classNames.detailRow, children: /* @__PURE__ */ jsxRuntime.jsx(
1461
- "td",
1462
- {
1463
- colSpan: columnSpan,
1464
- "data-adapttable-part": "detail-cell",
1465
- className: classNames.detailCell,
1466
- children: renderDetail(row)
1467
- }
1468
- ) })
1469
- ] });
1105
+ const { row, index, id, table, columns, labels, classNames, selected, expanded, showActions, rowActions, confirm, columnSpan, pinOffset, hasLeftPin, hasRightPin, actionsPinned, rowClass, clickable, hasPrefetch, onRowClick, onPrefetch, onToggleSelect, onToggleExpand, renderDetail, measureElement } = props;
1106
+ const expandable = expanded !== void 0;
1107
+ const leads = {
1108
+ left: selected === void 0 ? 0 : SELECTION_WIDTH,
1109
+ right: showActions ? ACTIONS_WIDTH : 0
1110
+ };
1111
+ const bodyPinStyle = (key) => (0, _adapttable_core.pinnedCellStyle)(pinOffset?.(key), _adapttable_core.PIN_Z.body, leads);
1112
+ const rowProps = { ...table.getRowProps(row, index) };
1113
+ delete rowProps.key;
1114
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
1115
+ ...rowProps,
1116
+ ...(0, _adapttable_core.rowClickProps)(row, clickable ? onRowClick : void 0),
1117
+ ref: measureElement,
1118
+ "data-adapttable-part": "row",
1119
+ "data-selected": selected ? "" : void 0,
1120
+ "data-clickable": clickable ? "" : void 0,
1121
+ className: cx(classNames.row, rowClass),
1122
+ onMouseEnter: hasPrefetch ? () => onPrefetch(row) : void 0,
1123
+ children: [
1124
+ expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1125
+ "data-adapttable-part": "expand-cell",
1126
+ className: classNames.expandCell,
1127
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandButton, {
1128
+ expanded,
1129
+ labels,
1130
+ classNames,
1131
+ onToggle: () => onToggleExpand(id)
1132
+ })
1133
+ }),
1134
+ selected !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1135
+ "data-adapttable-part": "selection-cell",
1136
+ "data-pinned": hasLeftPin ? "left" : void 0,
1137
+ style: (0, _adapttable_core.edgePinStyle)("left", hasLeftPin, _adapttable_core.PIN_Z.body),
1138
+ className: cx(classNames.cell, classNames.selectionCell),
1139
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1140
+ type: "checkbox",
1141
+ "aria-label": labels.selectRow,
1142
+ checked: selected,
1143
+ onChange: () => onToggleSelect(id),
1144
+ className: classNames.checkbox
1145
+ })
1146
+ }),
1147
+ columns.map((column) => {
1148
+ const pinStyle = bodyPinStyle(column.key);
1149
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1150
+ ...table.getCellProps(column, pinStyle && { style: pinStyle }),
1151
+ "data-adapttable-part": "cell",
1152
+ "data-pinned": pinOffset?.(column.key)?.side,
1153
+ className: classNames.cell,
1154
+ children: column.Cell ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(column.Cell, {
1155
+ row,
1156
+ rowIndex: index
1157
+ }) : column.accessor?.(row)
1158
+ }, column.key);
1159
+ }),
1160
+ showActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1161
+ "data-adapttable-part": "actions-cell",
1162
+ "data-pinned": hasRightPin || actionsPinned ? "right" : void 0,
1163
+ style: (0, _adapttable_core.edgePinStyle)("right", hasRightPin || actionsPinned, _adapttable_core.PIN_Z.body),
1164
+ className: cx(classNames.cell, classNames.actionsCell),
1165
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowActionButtons, {
1166
+ row,
1167
+ actions: rowActions,
1168
+ confirm,
1169
+ cancelLabel: labels.cancel,
1170
+ classNames
1171
+ })
1172
+ })
1173
+ ]
1174
+ }), expandable && expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", {
1175
+ "data-adapttable-part": "detail-row",
1176
+ className: classNames.detailRow,
1177
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1178
+ colSpan: columnSpan,
1179
+ "data-adapttable-part": "detail-cell",
1180
+ className: classNames.detailCell,
1181
+ children: renderDetail(row)
1182
+ })
1183
+ })] });
1470
1184
  }
1185
+ /**
1186
+ * One memoized row component per `DesktopTable` instantiation. A factory
1187
+ * (called once through `useMemo`) instead of a module-level `memo(...)`
1188
+ * because `React.memo` erases a generic component's type parameter — the
1189
+ * factory keeps `TRow` without a type cast.
1190
+ */
1471
1191
  function createDesktopRow() {
1472
- return react.memo(DesktopRowBase, desktopRowPropsEqual);
1192
+ return (0, react.memo)(DesktopRowBase, desktopRowPropsEqual);
1473
1193
  }
1474
- function DesktopTable({
1475
- table,
1476
- rows,
1477
- rowActions,
1478
- confirm,
1479
- getRowId,
1480
- classNames,
1481
- prefetch,
1482
- onRowClick,
1483
- rowClassName,
1484
- renderRowDetail,
1485
- summaryRow,
1486
- expansion,
1487
- rowEntries,
1488
- paddingTop = 0,
1489
- paddingBottom = 0,
1490
- measureElement,
1491
- stickyHeader = false,
1492
- stickyTop = 0,
1493
- pinOffset,
1494
- maxHeight,
1495
- virtualScrollRef,
1496
- setWidth,
1497
- columnWidths,
1498
- resizeLabel = "Resize column",
1499
- actionsPinned = false
1500
- }) {
1501
- const { columns, selection, labels, showActions, entries, columnSpan } = core.tableRenderModel({
1502
- table,
1503
- rows,
1504
- rowActions,
1505
- getRowId,
1506
- rowEntries,
1507
- renderRowDetail,
1508
- expansion
1509
- });
1510
- const stickActions = showActions && actionsPinned;
1511
- const expansionState = renderRowDetail ? expansion : void 0;
1512
- const expandable = expansionState !== void 0;
1513
- const live = react.useRef({
1514
- selection,
1515
- expansion: expansionState,
1516
- onRowClick,
1517
- prefetch,
1518
- renderRowDetail
1519
- });
1520
- live.current = {
1521
- selection,
1522
- expansion: expansionState,
1523
- onRowClick,
1524
- prefetch,
1525
- renderRowDetail
1526
- };
1527
- const onToggleSelect = react.useCallback(
1528
- (id) => live.current.selection?.toggle(id),
1529
- []
1530
- );
1531
- const onToggleExpand = react.useCallback(
1532
- (id) => live.current.expansion?.toggle(id),
1533
- []
1534
- );
1535
- const handleRowClick = react.useCallback(
1536
- (row) => live.current.onRowClick?.(row),
1537
- []
1538
- );
1539
- const handlePrefetch = react.useCallback(
1540
- (row) => live.current.prefetch?.(row),
1541
- []
1542
- );
1543
- const renderDetail = react.useCallback(
1544
- (row) => live.current.renderRowDetail?.(row),
1545
- []
1546
- );
1547
- const Row = react.useMemo(() => createDesktopRow(), []);
1548
- const { ref: overflowRef, overflowing } = core.useHorizontalOverflow();
1549
- const hasPinned = columns.some((c) => pinOffset?.(c.key) != null) || stickActions;
1550
- const inScrollBox = maxHeight != null || hasPinned || overflowing;
1551
- const stickyStyle = stickyHeader ? {
1552
- position: "sticky",
1553
- top: inScrollBox ? 0 : stickyTop,
1554
- zIndex: core.PIN_Z.header
1555
- } : void 0;
1556
- const stickyAttr = stickyHeader || void 0;
1557
- const leads = {
1558
- left: selection ? SELECTION_WIDTH : 0,
1559
- right: showActions ? ACTIONS_WIDTH : 0
1560
- };
1561
- const hasLeftPin = columns.some((c) => pinOffset?.(c.key)?.side === "left");
1562
- const hasRightPin = columns.some((c) => pinOffset?.(c.key)?.side === "right");
1563
- const pinSignature = columns.map((c) => {
1564
- const pin = pinOffset?.(c.key);
1565
- return pin ? `${c.key}:${pin.side}:${pin.inset}` : "";
1566
- }).join("|");
1567
- const headPinStyle = (key) => core.pinnedCellStyle(pinOffset?.(key), core.PIN_Z.headerPinned, leads);
1568
- const headStyle = (column) => {
1569
- const key = column.key;
1570
- const pin = headPinStyle(key);
1571
- const width = pin ? core.pinnedColumnWidth(column, columnWidths) : columnWidths?.[key];
1572
- if (!stickyStyle && !pin && width == null && !setWidth) return void 0;
1573
- const merged = {
1574
- ...stickyStyle,
1575
- ...pin,
1576
- ...width != null && { width }
1577
- };
1578
- if (setWidth && !merged.position) merged.position = "relative";
1579
- return merged;
1580
- };
1581
- const edgeHeadStyle = (side, active) => {
1582
- const edge = core.edgePinStyle(side, active, core.PIN_Z.headerPinned);
1583
- if (!stickyStyle && !edge) return void 0;
1584
- return { ...stickyStyle, ...edge };
1585
- };
1586
- const columnName = (column) => typeof column.header === "string" ? column.header : column.key;
1587
- const minWidth = core.tableMinWidth(columns, {
1588
- widths: columnWidths,
1589
- extra: (selection ? SELECTION_WIDTH : 0) + (showActions ? ACTIONS_WIDTH : 0)
1590
- });
1591
- const groups = core.headerGroupRow(columns);
1592
- const summary = summaryRow?.(rows);
1593
- const groupPad = /* @__PURE__ */ jsxRuntime.jsx("th", { "data-adapttable-part": "group-cell", className: classNames.groupCell });
1594
- const summaryPad = /* @__PURE__ */ jsxRuntime.jsx(
1595
- "td",
1596
- {
1597
- "data-adapttable-part": "summary-cell",
1598
- className: classNames.summaryCell
1599
- }
1600
- );
1601
- const tableEl = /* @__PURE__ */ jsxRuntime.jsxs(
1602
- "table",
1603
- {
1604
- ...table.getTableProps(),
1605
- "data-adapttable-part": "table",
1606
- className: classNames.table,
1607
- style: minWidth > 0 ? { minWidth } : void 0,
1608
- children: [
1609
- /* @__PURE__ */ jsxRuntime.jsxs("thead", { "data-adapttable-part": "thead", className: classNames.thead, children: [
1610
- groups && /* @__PURE__ */ jsxRuntime.jsxs("tr", { "data-adapttable-part": "group-row", className: classNames.groupRow, children: [
1611
- expandable && groupPad,
1612
- selection && groupPad,
1613
- groups.map((group) => /* @__PURE__ */ jsxRuntime.jsx(
1614
- "th",
1615
- {
1616
- colSpan: group.span,
1617
- "data-adapttable-part": "group-cell",
1618
- className: classNames.groupCell,
1619
- children: group.label
1620
- },
1621
- group.key
1622
- )),
1623
- showActions && groupPad
1624
- ] }),
1625
- /* @__PURE__ */ jsxRuntime.jsxs(
1626
- "tr",
1627
- {
1628
- ...table.getHeaderRowProps(),
1629
- "data-adapttable-part": "header-row",
1630
- className: classNames.headerRow,
1631
- children: [
1632
- expandable && /* @__PURE__ */ jsxRuntime.jsx(
1633
- "th",
1634
- {
1635
- "aria-label": labels.expandRow,
1636
- "data-adapttable-part": "expand-header",
1637
- "data-sticky": stickyAttr,
1638
- style: stickyStyle,
1639
- className: cx(classNames.headerCell, classNames.expandHeader)
1640
- }
1641
- ),
1642
- selection && /* @__PURE__ */ jsxRuntime.jsx(
1643
- "th",
1644
- {
1645
- "data-adapttable-part": "selection-header",
1646
- "data-sticky": stickyAttr,
1647
- "data-pinned": hasLeftPin ? "left" : void 0,
1648
- style: edgeHeadStyle("left", hasLeftPin),
1649
- className: cx(classNames.headerCell, classNames.selectionCell),
1650
- children: /* @__PURE__ */ jsxRuntime.jsx(
1651
- "input",
1652
- {
1653
- type: "checkbox",
1654
- "aria-label": labels.selectAll,
1655
- checked: selection.headerState === "all",
1656
- ref: (el) => {
1657
- if (el) el.indeterminate = selection.headerState === "some";
1658
- },
1659
- onChange: selection.toggleAll,
1660
- className: classNames.checkbox
1661
- }
1662
- )
1663
- }
1664
- ),
1665
- columns.map((column) => {
1666
- const localStyle = headStyle(column);
1667
- const headerProps = table.getHeaderCellProps(
1668
- column,
1669
- localStyle && { style: localStyle }
1670
- );
1671
- const active = table.sortBy === column.key;
1672
- const sortButtonProps = table.getSortButtonProps(column);
1673
- const sortIndex = sortButtonProps["data-sort-index"];
1674
- return /* @__PURE__ */ jsxRuntime.jsxs(
1675
- "th",
1676
- {
1677
- ...headerProps,
1678
- "data-adapttable-part": "header-cell",
1679
- "data-sorted": active ? table.sortDir : void 0,
1680
- "data-sticky": stickyAttr,
1681
- "data-pinned": pinOffset?.(column.key)?.side,
1682
- className: classNames.headerCell,
1683
- children: [
1684
- column.sortable ? /* @__PURE__ */ jsxRuntime.jsxs(
1685
- "button",
1686
- {
1687
- ...sortButtonProps,
1688
- "data-adapttable-part": "sort-button",
1689
- className: classNames.sortButton,
1690
- children: [
1691
- column.header,
1692
- typeof sortIndex === "number" && /* @__PURE__ */ jsxRuntime.jsx(
1693
- "span",
1694
- {
1695
- "data-adapttable-part": "sort-index",
1696
- className: classNames.sortIndex,
1697
- children: sortIndex
1698
- }
1699
- ),
1700
- /* @__PURE__ */ jsxRuntime.jsxs("span", { "aria-hidden": true, children: [
1701
- " ",
1702
- sortGlyph(active, table.sortDir)
1703
- ] })
1704
- ]
1705
- }
1706
- ) : column.header,
1707
- setWidth && /* @__PURE__ */ jsxRuntime.jsx(
1708
- "span",
1709
- {
1710
- ...core.columnResizeHandleProps(
1711
- column.key,
1712
- setWidth,
1713
- `${resizeLabel}: ${columnName(column)}`
1714
- ),
1715
- "data-adapttable-part": "resize-handle",
1716
- className: classNames.resizeHandle,
1717
- style: RESIZE_HANDLE_STYLE
1718
- }
1719
- )
1720
- ]
1721
- },
1722
- column.key
1723
- );
1724
- }),
1725
- showActions && /* @__PURE__ */ jsxRuntime.jsx(
1726
- "th",
1727
- {
1728
- "data-adapttable-part": "actions-header",
1729
- "data-sticky": stickyAttr,
1730
- "data-pinned": hasRightPin || stickActions ? "right" : void 0,
1731
- style: edgeHeadStyle("right", hasRightPin || stickActions),
1732
- className: cx(classNames.headerCell, classNames.actionsCell),
1733
- children: labels.actions
1734
- }
1735
- )
1736
- ]
1737
- }
1738
- )
1739
- ] }),
1740
- /* @__PURE__ */ jsxRuntime.jsxs("tbody", { "data-adapttable-part": "tbody", className: classNames.tbody, children: [
1741
- paddingTop > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1742
- "td",
1743
- {
1744
- colSpan: columnSpan,
1745
- style: { height: paddingTop, padding: 0 }
1746
- }
1747
- ) }),
1748
- entries.map(({ row, index, key }) => {
1749
- const id = getRowId(row);
1750
- return /* @__PURE__ */ jsxRuntime.jsx(
1751
- Row,
1752
- {
1753
- row,
1754
- index,
1755
- id,
1756
- table,
1757
- columns,
1758
- labels,
1759
- classNames,
1760
- selected: selection ? selection.isSelected(id) : void 0,
1761
- expanded: expansionState ? expansionState.isExpanded(id) : void 0,
1762
- showActions,
1763
- rowActions,
1764
- confirm,
1765
- columnSpan,
1766
- columnWidths,
1767
- pinOffset,
1768
- pinSignature,
1769
- hasLeftPin,
1770
- hasRightPin,
1771
- actionsPinned: stickActions,
1772
- rowClass: rowClassName?.(row, index),
1773
- clickable: Boolean(onRowClick),
1774
- hasPrefetch: Boolean(prefetch),
1775
- onRowClick: handleRowClick,
1776
- onPrefetch: handlePrefetch,
1777
- onToggleSelect,
1778
- onToggleExpand,
1779
- renderDetail,
1780
- measureElement
1781
- },
1782
- key
1783
- );
1784
- }),
1785
- paddingBottom > 0 && /* @__PURE__ */ jsxRuntime.jsx("tr", { children: /* @__PURE__ */ jsxRuntime.jsx(
1786
- "td",
1787
- {
1788
- colSpan: columnSpan,
1789
- style: { height: paddingBottom, padding: 0 }
1790
- }
1791
- ) })
1792
- ] }),
1793
- summary && /* @__PURE__ */ jsxRuntime.jsx("tfoot", { "data-adapttable-part": "summary", className: classNames.summary, children: /* @__PURE__ */ jsxRuntime.jsxs(
1794
- "tr",
1795
- {
1796
- "data-adapttable-part": "summary-row",
1797
- className: classNames.summaryRow,
1798
- children: [
1799
- expandable && summaryPad,
1800
- selection && summaryPad,
1801
- columns.map((column) => /* @__PURE__ */ jsxRuntime.jsx(
1802
- "td",
1803
- {
1804
- "data-adapttable-part": "summary-cell",
1805
- className: classNames.summaryCell,
1806
- children: summary[column.key]
1807
- },
1808
- column.key
1809
- )),
1810
- showActions && summaryPad
1811
- ]
1812
- }
1813
- ) })
1814
- ]
1815
- }
1816
- );
1817
- return /* @__PURE__ */ jsxRuntime.jsx(
1818
- "div",
1819
- {
1820
- ref: (node) => {
1821
- overflowRef(node);
1822
- virtualScrollRef?.(node);
1823
- },
1824
- "data-adapttable-part": "scroll-box",
1825
- style: scrollBoxStyle(maxHeight, hasPinned || overflowing),
1826
- children: tableEl
1827
- }
1828
- );
1194
+ /** Desktop semantic `<table>` rendering. */
1195
+ function DesktopTable({ table, rows, rowActions, confirm, getRowId, classNames, prefetch, onRowClick, rowClassName, renderRowDetail, summaryRow, expansion, rowEntries, paddingTop = 0, paddingBottom = 0, measureElement, stickyHeader = false, stickyTop = 0, pinOffset, maxHeight, virtualScrollRef, setWidth, columnWidths, resizeLabel = "Resize column", actionsPinned = false }) {
1196
+ const { columns, selection, labels, showActions, entries, columnSpan } = (0, _adapttable_core.tableRenderModel)({
1197
+ table,
1198
+ rows,
1199
+ rowActions,
1200
+ getRowId,
1201
+ rowEntries,
1202
+ renderRowDetail,
1203
+ expansion
1204
+ });
1205
+ const stickActions = showActions && actionsPinned;
1206
+ const expansionState = renderRowDetail ? expansion : void 0;
1207
+ const expandable = expansionState !== void 0;
1208
+ const live = (0, react.useRef)({
1209
+ selection,
1210
+ expansion: expansionState,
1211
+ onRowClick,
1212
+ prefetch,
1213
+ renderRowDetail
1214
+ });
1215
+ live.current = {
1216
+ selection,
1217
+ expansion: expansionState,
1218
+ onRowClick,
1219
+ prefetch,
1220
+ renderRowDetail
1221
+ };
1222
+ const onToggleSelect = (0, react.useCallback)((id) => live.current.selection?.toggle(id), []);
1223
+ const onToggleExpand = (0, react.useCallback)((id) => live.current.expansion?.toggle(id), []);
1224
+ const handleRowClick = (0, react.useCallback)((row) => live.current.onRowClick?.(row), []);
1225
+ const handlePrefetch = (0, react.useCallback)((row) => live.current.prefetch?.(row), []);
1226
+ const renderDetail = (0, react.useCallback)((row) => live.current.renderRowDetail?.(row), []);
1227
+ const Row = (0, react.useMemo)(() => createDesktopRow(), []);
1228
+ const { ref: overflowRef, overflowing } = (0, _adapttable_core.useHorizontalOverflow)();
1229
+ const hasPinned = columns.some((c) => pinOffset?.(c.key) != null) || stickActions;
1230
+ const stickyStyle = stickyHeader ? {
1231
+ position: "sticky",
1232
+ top: maxHeight != null || hasPinned || overflowing ? 0 : stickyTop,
1233
+ zIndex: _adapttable_core.PIN_Z.header
1234
+ } : void 0;
1235
+ const stickyAttr = stickyHeader || void 0;
1236
+ const leads = {
1237
+ left: selection ? SELECTION_WIDTH : 0,
1238
+ right: showActions ? ACTIONS_WIDTH : 0
1239
+ };
1240
+ const hasLeftPin = columns.some((c) => pinOffset?.(c.key)?.side === "left");
1241
+ const hasRightPin = columns.some((c) => pinOffset?.(c.key)?.side === "right");
1242
+ const pinSignature = columns.map((c) => {
1243
+ const pin = pinOffset?.(c.key);
1244
+ return pin ? `${c.key}:${pin.side}:${pin.inset}` : "";
1245
+ }).join("|");
1246
+ const headPinStyle = (key) => (0, _adapttable_core.pinnedCellStyle)(pinOffset?.(key), _adapttable_core.PIN_Z.headerPinned, leads);
1247
+ const headStyle = (column) => {
1248
+ const key = column.key;
1249
+ const pin = headPinStyle(key);
1250
+ const width = pin ? (0, _adapttable_core.pinnedColumnWidth)(column, columnWidths) : columnWidths?.[key];
1251
+ if (!stickyStyle && !pin && width == null && !setWidth) return void 0;
1252
+ const merged = {
1253
+ ...stickyStyle,
1254
+ ...pin,
1255
+ ...width != null && { width }
1256
+ };
1257
+ if (setWidth && !merged.position) merged.position = "relative";
1258
+ return merged;
1259
+ };
1260
+ const edgeHeadStyle = (side, active) => {
1261
+ const edge = (0, _adapttable_core.edgePinStyle)(side, active, _adapttable_core.PIN_Z.headerPinned);
1262
+ if (!stickyStyle && !edge) return void 0;
1263
+ return {
1264
+ ...stickyStyle,
1265
+ ...edge
1266
+ };
1267
+ };
1268
+ const columnName = (column) => typeof column.header === "string" ? column.header : column.key;
1269
+ const minWidth = (0, _adapttable_core.tableMinWidth)(columns, {
1270
+ widths: columnWidths,
1271
+ extra: (selection ? SELECTION_WIDTH : 0) + (showActions ? ACTIONS_WIDTH : 0)
1272
+ });
1273
+ const groups = (0, _adapttable_core.headerGroupRow)(columns);
1274
+ const summary = summaryRow?.(rows);
1275
+ const groupPad = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1276
+ "data-adapttable-part": "group-cell",
1277
+ className: classNames.groupCell
1278
+ });
1279
+ const summaryPad = /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1280
+ "data-adapttable-part": "summary-cell",
1281
+ className: classNames.summaryCell
1282
+ });
1283
+ const tableEl = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("table", {
1284
+ ...table.getTableProps(),
1285
+ "data-adapttable-part": "table",
1286
+ className: classNames.table,
1287
+ style: minWidth > 0 ? { minWidth } : void 0,
1288
+ children: [
1289
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("thead", {
1290
+ "data-adapttable-part": "thead",
1291
+ className: classNames.thead,
1292
+ children: [groups && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
1293
+ "data-adapttable-part": "group-row",
1294
+ className: classNames.groupRow,
1295
+ children: [
1296
+ expandable && groupPad,
1297
+ selection && groupPad,
1298
+ groups.map((group) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1299
+ colSpan: group.span,
1300
+ "data-adapttable-part": "group-cell",
1301
+ className: classNames.groupCell,
1302
+ children: group.label
1303
+ }, group.key)),
1304
+ showActions && groupPad
1305
+ ]
1306
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
1307
+ ...table.getHeaderRowProps(),
1308
+ "data-adapttable-part": "header-row",
1309
+ className: classNames.headerRow,
1310
+ children: [
1311
+ expandable && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1312
+ "aria-label": labels.expandRow,
1313
+ "data-adapttable-part": "expand-header",
1314
+ "data-sticky": stickyAttr,
1315
+ style: stickyStyle,
1316
+ className: cx(classNames.headerCell, classNames.expandHeader)
1317
+ }),
1318
+ selection && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1319
+ "data-adapttable-part": "selection-header",
1320
+ "data-sticky": stickyAttr,
1321
+ "data-pinned": hasLeftPin ? "left" : void 0,
1322
+ style: edgeHeadStyle("left", hasLeftPin),
1323
+ className: cx(classNames.headerCell, classNames.selectionCell),
1324
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1325
+ type: "checkbox",
1326
+ "aria-label": labels.selectAll,
1327
+ checked: selection.headerState === "all",
1328
+ ref: (el) => {
1329
+ if (el) el.indeterminate = selection.headerState === "some";
1330
+ },
1331
+ onChange: selection.toggleAll,
1332
+ className: classNames.checkbox
1333
+ })
1334
+ }),
1335
+ columns.map((column) => {
1336
+ const localStyle = headStyle(column);
1337
+ const headerProps = table.getHeaderCellProps(column, localStyle && { style: localStyle });
1338
+ const active = table.sortBy === column.key;
1339
+ const sortButtonProps = table.getSortButtonProps(column);
1340
+ const sortIndex = sortButtonProps["data-sort-index"];
1341
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("th", {
1342
+ ...headerProps,
1343
+ "data-adapttable-part": "header-cell",
1344
+ "data-sorted": active ? table.sortDir : void 0,
1345
+ "data-sticky": stickyAttr,
1346
+ "data-pinned": pinOffset?.(column.key)?.side,
1347
+ className: classNames.headerCell,
1348
+ children: [column.sortable ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1349
+ ...sortButtonProps,
1350
+ "data-adapttable-part": "sort-button",
1351
+ className: classNames.sortButton,
1352
+ children: [
1353
+ column.header,
1354
+ typeof sortIndex === "number" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1355
+ "data-adapttable-part": "sort-index",
1356
+ className: classNames.sortIndex,
1357
+ children: sortIndex
1358
+ }),
1359
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1360
+ "aria-hidden": true,
1361
+ children: [" ", sortGlyph(active, table.sortDir)]
1362
+ })
1363
+ ]
1364
+ }) : column.header, setWidth && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1365
+ ...(0, _adapttable_core.columnResizeHandleProps)(column.key, setWidth, `${resizeLabel}: ${columnName(column)}`),
1366
+ "data-adapttable-part": "resize-handle",
1367
+ className: classNames.resizeHandle,
1368
+ style: RESIZE_HANDLE_STYLE
1369
+ })]
1370
+ }, column.key);
1371
+ }),
1372
+ showActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("th", {
1373
+ "data-adapttable-part": "actions-header",
1374
+ "data-sticky": stickyAttr,
1375
+ "data-pinned": hasRightPin || stickActions ? "right" : void 0,
1376
+ style: edgeHeadStyle("right", hasRightPin || stickActions),
1377
+ className: cx(classNames.headerCell, classNames.actionsCell),
1378
+ children: labels.actions
1379
+ })
1380
+ ]
1381
+ })]
1382
+ }),
1383
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tbody", {
1384
+ "data-adapttable-part": "tbody",
1385
+ className: classNames.tbody,
1386
+ children: [
1387
+ paddingTop > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1388
+ colSpan: columnSpan,
1389
+ style: {
1390
+ height: paddingTop,
1391
+ padding: 0
1392
+ }
1393
+ }) }),
1394
+ entries.map(({ row, index, key }) => {
1395
+ const id = getRowId(row);
1396
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Row, {
1397
+ row,
1398
+ index,
1399
+ id,
1400
+ table,
1401
+ columns,
1402
+ labels,
1403
+ classNames,
1404
+ selected: selection ? selection.isSelected(id) : void 0,
1405
+ expanded: expansionState ? expansionState.isExpanded(id) : void 0,
1406
+ showActions,
1407
+ rowActions,
1408
+ confirm,
1409
+ columnSpan,
1410
+ columnWidths,
1411
+ pinOffset,
1412
+ pinSignature,
1413
+ hasLeftPin,
1414
+ hasRightPin,
1415
+ actionsPinned: stickActions,
1416
+ rowClass: rowClassName?.(row, index),
1417
+ clickable: Boolean(onRowClick),
1418
+ hasPrefetch: Boolean(prefetch),
1419
+ onRowClick: handleRowClick,
1420
+ onPrefetch: handlePrefetch,
1421
+ onToggleSelect,
1422
+ onToggleExpand,
1423
+ renderDetail,
1424
+ measureElement
1425
+ }, key);
1426
+ }),
1427
+ paddingBottom > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tr", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1428
+ colSpan: columnSpan,
1429
+ style: {
1430
+ height: paddingBottom,
1431
+ padding: 0
1432
+ }
1433
+ }) })
1434
+ ]
1435
+ }),
1436
+ summary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("tfoot", {
1437
+ "data-adapttable-part": "summary",
1438
+ className: classNames.summary,
1439
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("tr", {
1440
+ "data-adapttable-part": "summary-row",
1441
+ className: classNames.summaryRow,
1442
+ children: [
1443
+ expandable && summaryPad,
1444
+ selection && summaryPad,
1445
+ columns.map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("td", {
1446
+ "data-adapttable-part": "summary-cell",
1447
+ className: classNames.summaryCell,
1448
+ children: summary[column.key]
1449
+ }, column.key)),
1450
+ showActions && summaryPad
1451
+ ]
1452
+ })
1453
+ })
1454
+ ]
1455
+ });
1456
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1457
+ ref: (node) => {
1458
+ overflowRef(node);
1459
+ virtualScrollRef?.(node);
1460
+ },
1461
+ "data-adapttable-part": "scroll-box",
1462
+ style: scrollBoxStyle(maxHeight, hasPinned || overflowing),
1463
+ children: tableEl
1464
+ });
1829
1465
  }
1830
- function MobileCards({
1831
- table,
1832
- rows,
1833
- rowActions,
1834
- confirm,
1835
- getRowId,
1836
- classNames,
1837
- onRowClick,
1838
- rowClassName,
1839
- renderRowDetail,
1840
- summaryRow,
1841
- expansion,
1842
- rowEntries,
1843
- paddingTop = 0,
1844
- paddingBottom = 0,
1845
- measureElement
1846
- }) {
1847
- const { columns, selection, labels } = table;
1848
- const entries = core.resolveVirtualRows(rows, getRowId, rowEntries);
1849
- const expansionState = renderRowDetail ? expansion : void 0;
1850
- const summary = summaryRow?.(rows);
1851
- return /* @__PURE__ */ jsxRuntime.jsxs(
1852
- "ul",
1853
- {
1854
- ...table.getTableProps({ role: void 0 }),
1855
- "data-adapttable-part": "cards",
1856
- className: classNames.cards,
1857
- style: { listStyle: "none", margin: 0, padding: 0 },
1858
- children: [
1859
- paddingTop > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1860
- "li",
1861
- {
1862
- "aria-hidden": true,
1863
- "data-adapttable-part": "virtual-spacer",
1864
- style: { height: paddingTop }
1865
- }
1866
- ),
1867
- entries.map(({ row, index, key }) => {
1868
- const id = getRowId(row);
1869
- const expanded = expansionState?.isExpanded(id) ?? false;
1870
- return /* @__PURE__ */ jsxRuntime.jsxs(
1871
- "li",
1872
- {
1873
- ...core.rowClickProps(row, onRowClick),
1874
- ref: measureElement,
1875
- "data-index": index,
1876
- "data-adapttable-part": "card",
1877
- "data-selected": selection?.isSelected(id) ? "" : void 0,
1878
- "data-clickable": onRowClick ? "" : void 0,
1879
- className: cx(classNames.card, rowClassName?.(row, index)),
1880
- children: [
1881
- selection && /* @__PURE__ */ jsxRuntime.jsx(
1882
- "input",
1883
- {
1884
- type: "checkbox",
1885
- "aria-label": labels.selectRow,
1886
- checked: selection.isSelected(id),
1887
- onChange: () => selection.toggle(id),
1888
- className: classNames.checkbox
1889
- }
1890
- ),
1891
- expansionState && /* @__PURE__ */ jsxRuntime.jsx(
1892
- ExpandButton,
1893
- {
1894
- expanded,
1895
- labels,
1896
- classNames,
1897
- onToggle: () => expansionState.toggle(id)
1898
- }
1899
- ),
1900
- columns.map((column) => /* @__PURE__ */ jsxRuntime.jsxs(
1901
- "div",
1902
- {
1903
- "data-adapttable-part": "card-row",
1904
- className: classNames.cardRow,
1905
- children: [
1906
- /* @__PURE__ */ jsxRuntime.jsx(
1907
- "span",
1908
- {
1909
- "data-adapttable-part": "card-label",
1910
- className: classNames.cardLabel,
1911
- children: cardLabel(column)
1912
- }
1913
- ),
1914
- /* @__PURE__ */ jsxRuntime.jsx(
1915
- "span",
1916
- {
1917
- "data-adapttable-part": "card-value",
1918
- className: classNames.cardValue,
1919
- children: column.Cell ? /* @__PURE__ */ jsxRuntime.jsx(column.Cell, { row, rowIndex: index }) : column.accessor?.(row)
1920
- }
1921
- )
1922
- ]
1923
- },
1924
- column.key
1925
- )),
1926
- rowActions && rowActions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1927
- "div",
1928
- {
1929
- "data-adapttable-part": "card-actions",
1930
- className: classNames.actionsCell,
1931
- children: /* @__PURE__ */ jsxRuntime.jsx(
1932
- RowActionButtons,
1933
- {
1934
- row,
1935
- actions: rowActions,
1936
- confirm,
1937
- cancelLabel: labels.cancel,
1938
- classNames
1939
- }
1940
- )
1941
- }
1942
- ),
1943
- expanded && // Inside the measured card `<li>`, so the virtualizer's size
1944
- // measurement tracks the open detail panel.
1945
- /* @__PURE__ */ jsxRuntime.jsx(
1946
- "div",
1947
- {
1948
- "data-adapttable-part": "card-detail",
1949
- className: classNames.cardDetail,
1950
- children: renderRowDetail(row)
1951
- }
1952
- )
1953
- ]
1954
- },
1955
- key
1956
- );
1957
- }),
1958
- paddingBottom > 0 && /* @__PURE__ */ jsxRuntime.jsx(
1959
- "li",
1960
- {
1961
- "aria-hidden": true,
1962
- "data-adapttable-part": "virtual-spacer",
1963
- style: { height: paddingBottom }
1964
- }
1965
- ),
1966
- summary && /* @__PURE__ */ jsxRuntime.jsx(
1967
- "li",
1968
- {
1969
- "data-adapttable-part": "summary-card",
1970
- className: classNames.summaryCard,
1971
- children: columns.filter((column) => summary[column.key] !== void 0).map((column) => /* @__PURE__ */ jsxRuntime.jsxs(
1972
- "div",
1973
- {
1974
- "data-adapttable-part": "card-row",
1975
- className: classNames.cardRow,
1976
- children: [
1977
- /* @__PURE__ */ jsxRuntime.jsx(
1978
- "span",
1979
- {
1980
- "data-adapttable-part": "card-label",
1981
- className: classNames.cardLabel,
1982
- children: cardLabel(column)
1983
- }
1984
- ),
1985
- /* @__PURE__ */ jsxRuntime.jsx(
1986
- "span",
1987
- {
1988
- "data-adapttable-part": "card-value",
1989
- className: classNames.cardValue,
1990
- children: summary[column.key]
1991
- }
1992
- )
1993
- ]
1994
- },
1995
- column.key
1996
- ))
1997
- }
1998
- )
1999
- ]
2000
- }
2001
- );
1466
+ /** Mobile card-list rendering. */
1467
+ function MobileCards({ table, rows, rowActions, confirm, getRowId, classNames, onRowClick, rowClassName, renderRowDetail, summaryRow, expansion, rowEntries, paddingTop = 0, paddingBottom = 0, measureElement }) {
1468
+ const { columns, selection, labels } = table;
1469
+ const entries = (0, _adapttable_core.resolveVirtualRows)(rows, getRowId, rowEntries);
1470
+ const expansionState = renderRowDetail ? expansion : void 0;
1471
+ const summary = summaryRow?.(rows);
1472
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("ul", {
1473
+ ...table.getTableProps({ role: void 0 }),
1474
+ "data-adapttable-part": "cards",
1475
+ className: classNames.cards,
1476
+ style: {
1477
+ listStyle: "none",
1478
+ margin: 0,
1479
+ padding: 0
1480
+ },
1481
+ children: [
1482
+ paddingTop > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1483
+ "aria-hidden": true,
1484
+ "data-adapttable-part": "virtual-spacer",
1485
+ style: { height: paddingTop }
1486
+ }),
1487
+ entries.map(({ row, index, key }) => {
1488
+ const id = getRowId(row);
1489
+ const expanded = expansionState?.isExpanded(id) ?? false;
1490
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("li", {
1491
+ ...(0, _adapttable_core.rowClickProps)(row, onRowClick),
1492
+ ref: measureElement,
1493
+ "data-index": index,
1494
+ "data-adapttable-part": "card",
1495
+ "data-selected": selection?.isSelected(id) ? "" : void 0,
1496
+ "data-clickable": onRowClick ? "" : void 0,
1497
+ className: cx(classNames.card, rowClassName?.(row, index)),
1498
+ children: [
1499
+ selection && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1500
+ type: "checkbox",
1501
+ "aria-label": labels.selectRow,
1502
+ checked: selection.isSelected(id),
1503
+ onChange: () => selection.toggle(id),
1504
+ className: classNames.checkbox
1505
+ }),
1506
+ expansionState && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ExpandButton, {
1507
+ expanded,
1508
+ labels,
1509
+ classNames,
1510
+ onToggle: () => expansionState.toggle(id)
1511
+ }),
1512
+ columns.map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1513
+ "data-adapttable-part": "card-row",
1514
+ className: classNames.cardRow,
1515
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1516
+ "data-adapttable-part": "card-label",
1517
+ className: classNames.cardLabel,
1518
+ children: cardLabel(column)
1519
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1520
+ "data-adapttable-part": "card-value",
1521
+ className: classNames.cardValue,
1522
+ children: column.Cell ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(column.Cell, {
1523
+ row,
1524
+ rowIndex: index
1525
+ }) : column.accessor?.(row)
1526
+ })]
1527
+ }, column.key)),
1528
+ rowActions && rowActions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1529
+ "data-adapttable-part": "card-actions",
1530
+ className: classNames.actionsCell,
1531
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowActionButtons, {
1532
+ row,
1533
+ actions: rowActions,
1534
+ confirm,
1535
+ cancelLabel: labels.cancel,
1536
+ classNames
1537
+ })
1538
+ }),
1539
+ expanded && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1540
+ "data-adapttable-part": "card-detail",
1541
+ className: classNames.cardDetail,
1542
+ children: renderRowDetail(row)
1543
+ })
1544
+ ]
1545
+ }, key);
1546
+ }),
1547
+ paddingBottom > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1548
+ "aria-hidden": true,
1549
+ "data-adapttable-part": "virtual-spacer",
1550
+ style: { height: paddingBottom }
1551
+ }),
1552
+ summary && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", {
1553
+ "data-adapttable-part": "summary-card",
1554
+ className: classNames.summaryCard,
1555
+ children: columns.filter((column) => summary[column.key] !== void 0).map((column) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1556
+ "data-adapttable-part": "card-row",
1557
+ className: classNames.cardRow,
1558
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1559
+ "data-adapttable-part": "card-label",
1560
+ className: classNames.cardLabel,
1561
+ children: cardLabel(column)
1562
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1563
+ "data-adapttable-part": "card-value",
1564
+ className: classNames.cardValue,
1565
+ children: summary[column.key]
1566
+ })]
1567
+ }, column.key))
1568
+ })
1569
+ ]
1570
+ });
2002
1571
  }
2003
1572
  function sortGlyph(active, dir) {
2004
- if (!active) return "\u2195";
2005
- return dir === "asc" ? "\u2191" : "\u2193";
1573
+ if (!active) return "";
1574
+ return dir === "asc" ? "" : "";
2006
1575
  }
2007
1576
  function cardLabel(column) {
2008
- return column.mobileLabel ?? (typeof column.header === "string" ? column.header : column.key);
1577
+ return column.mobileLabel ?? (typeof column.header === "string" ? column.header : column.key);
2009
1578
  }
2010
- var NO_CLASSNAMES = {};
2011
- function DataTableBody({
2012
- chrome,
2013
- props,
2014
- classNames,
2015
- confirm,
2016
- getRowId,
2017
- virtualization,
2018
- virtualScrollRef,
2019
- labels
2020
- }) {
2021
- const rowActions = chrome.columnLayout.isHidden(core.ACTIONS_COLUMN_KEY) ? void 0 : props.rowActions;
2022
- const actionsPinned = (rowActions?.length ?? 0) > 0 && chrome.columnLayout.state.pinned[core.ACTIONS_COLUMN_KEY] !== void 0;
2023
- if (chrome.body === "skeleton") {
2024
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.slots?.skeleton ?? props.loadingState ?? /* @__PURE__ */ jsxRuntime.jsx(
2025
- LoadingState,
2026
- {
2027
- rows: props.skeletonRows ?? props.source.limit,
2028
- columns: chrome.table.columns.length,
2029
- variant: chrome.isMobile ? "cards" : "table",
2030
- labels,
2031
- classNames,
2032
- hasActions: (rowActions?.length ?? 0) > 0
2033
- }
2034
- ) });
2035
- }
2036
- if (chrome.body === "empty") {
2037
- const noResults = chrome.emptyVariant === "noResults";
2038
- return /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: props.slots?.empty ?? props.emptyState ?? /* @__PURE__ */ jsxRuntime.jsxs("output", { "data-adapttable-part": "empty", className: classNames.empty, children: [
2039
- noResults ? labels.noResults : labels.noData,
2040
- noResults && /* @__PURE__ */ jsxRuntime.jsx(
2041
- "button",
2042
- {
2043
- type: "button",
2044
- "data-adapttable-part": "empty-clear",
2045
- className: classNames.emptyClear,
2046
- onClick: chrome.clearFilters,
2047
- children: labels.clearAll
2048
- }
2049
- )
2050
- ] }) });
2051
- }
2052
- const Renderer = chrome.isMobile ? MobileCards : DesktopTable;
2053
- return /* @__PURE__ */ jsxRuntime.jsx(
2054
- Renderer,
2055
- {
2056
- table: chrome.table,
2057
- rows: props.source.rows,
2058
- rowActions,
2059
- actionsPinned,
2060
- confirm,
2061
- getRowId,
2062
- classNames,
2063
- prefetch: props.prefetch,
2064
- onRowClick: props.onRowClick,
2065
- rowClassName: props.rowClassName,
2066
- renderRowDetail: props.renderRowDetail,
2067
- summaryRow: props.summaryRow,
2068
- expansion: chrome.detail?.expansion,
2069
- rowEntries: virtualization.enabled ? virtualization.rows : void 0,
2070
- paddingTop: virtualization.paddingTop,
2071
- paddingBottom: virtualization.paddingBottom,
2072
- measureElement: virtualization.measureElement,
2073
- stickyHeader: props.stickyHeader,
2074
- stickyTop: props.stickyTop,
2075
- pinOffset: chrome.columnLayout.pinOffset,
2076
- maxHeight: props.maxHeight,
2077
- virtualScrollRef,
2078
- setWidth: props.resizableColumns ? chrome.columnLayout.setWidth : void 0,
2079
- columnWidths: chrome.columnLayout.state.widths,
2080
- resizeLabel: labels.resizeColumn
2081
- }
2082
- );
1579
+ //#endregion
1580
+ //#region src/DataTable.tsx
1581
+ const NO_CLASSNAMES = {};
1582
+ function DataTableBody({ chrome, props, classNames, confirm, getRowId, virtualization, virtualScrollRef, labels }) {
1583
+ const rowActions = chrome.columnLayout.isHidden(_adapttable_core.ACTIONS_COLUMN_KEY) ? void 0 : props.rowActions;
1584
+ const actionsPinned = (rowActions?.length ?? 0) > 0 && chrome.columnLayout.state.pinned[_adapttable_core.ACTIONS_COLUMN_KEY] !== void 0;
1585
+ if (chrome.body === "skeleton") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.slots?.skeleton ?? props.loadingState ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LoadingState, {
1586
+ rows: props.skeletonRows ?? props.source.limit,
1587
+ columns: chrome.table.columns.length,
1588
+ variant: chrome.isMobile ? "cards" : "table",
1589
+ labels,
1590
+ classNames,
1591
+ hasActions: (rowActions?.length ?? 0) > 0
1592
+ }) });
1593
+ if (chrome.body === "empty") {
1594
+ const noResults = chrome.emptyVariant === "noResults";
1595
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children: props.slots?.empty ?? props.emptyState ?? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("output", {
1596
+ "data-adapttable-part": "empty",
1597
+ className: classNames.empty,
1598
+ children: [noResults ? labels.noResults : labels.noData, noResults && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1599
+ type: "button",
1600
+ "data-adapttable-part": "empty-clear",
1601
+ className: classNames.emptyClear,
1602
+ onClick: chrome.clearFilters,
1603
+ children: labels.clearAll
1604
+ })]
1605
+ }) });
1606
+ }
1607
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(chrome.isMobile ? MobileCards : DesktopTable, {
1608
+ table: chrome.table,
1609
+ rows: props.source.rows,
1610
+ rowActions,
1611
+ actionsPinned,
1612
+ confirm,
1613
+ getRowId,
1614
+ classNames,
1615
+ prefetch: props.prefetch,
1616
+ onRowClick: props.onRowClick,
1617
+ rowClassName: props.rowClassName,
1618
+ renderRowDetail: props.renderRowDetail,
1619
+ summaryRow: props.summaryRow,
1620
+ expansion: chrome.detail?.expansion,
1621
+ rowEntries: virtualization.enabled ? virtualization.rows : void 0,
1622
+ paddingTop: virtualization.paddingTop,
1623
+ paddingBottom: virtualization.paddingBottom,
1624
+ measureElement: virtualization.measureElement,
1625
+ stickyHeader: props.stickyHeader,
1626
+ stickyTop: props.stickyTop,
1627
+ pinOffset: chrome.columnLayout.pinOffset,
1628
+ maxHeight: props.maxHeight,
1629
+ virtualScrollRef,
1630
+ setWidth: props.resizableColumns ? chrome.columnLayout.setWidth : void 0,
1631
+ columnWidths: chrome.columnLayout.state.widths,
1632
+ resizeLabel: labels.resizeColumn
1633
+ });
2083
1634
  }
1635
+ /**
1636
+ * Headless, unstyled AdaptTable for Tailwind / shadcn / custom CSS. Renders
1637
+ * semantic HTML with `data-adapttable-part` hooks and `className` overrides;
1638
+ * ships no styles of its own. Built on the `@adapttable/core` prop-getters.
1639
+ *
1640
+ * @typeParam TRow - The row type.
1641
+ */
2084
1642
  function DataTable(props) {
2085
- const {
2086
- data,
2087
- total,
2088
- loading,
2089
- onQueryChange,
2090
- urlAdapter,
2091
- urlKey,
2092
- searchPlaceholder,
2093
- sortByOptions,
2094
- dir,
2095
- hideSearch,
2096
- filtersMode = "popover",
2097
- bulkActions,
2098
- classNames = NO_CLASSNAMES,
2099
- toolbar: customToolbar
2100
- } = props;
2101
- const density = props.density ?? "comfortable";
2102
- const { source, runtime } = core.useTableData({
2103
- locale: props.locale,
2104
- source: props.source,
2105
- data,
2106
- total,
2107
- loading,
2108
- onQueryChange,
2109
- adapter: props.urlSync === false ? void 0 : urlAdapter,
2110
- enabled: props.urlSync,
2111
- urlKey,
2112
- columns: props.columns,
2113
- filters: props.filters
2114
- });
2115
- const autoForm = runtime.defs.length > 0 ? /* @__PURE__ */ jsxRuntime.jsx(
2116
- AutoFilterForm,
2117
- {
2118
- defs: runtime.defs,
2119
- source,
2120
- classNames,
2121
- labels: props.labels
2122
- }
2123
- ) : void 0;
2124
- const filters = core.isDeclarativeFilters(props.filters) || props.filters === void 0 ? autoForm : props.filters;
2125
- const chromeProps = {
2126
- ...props,
2127
- source,
2128
- filters,
2129
- filterLabels: { ...runtime.filterLabels, ...props.filterLabels }
2130
- };
2131
- const chrome = core.useTableChrome(chromeProps);
2132
- const { table, confirm, getRowId } = chrome;
2133
- const { labels } = table;
2134
- const [filtersOpen, setFiltersOpen] = react.useState(false);
2135
- const filtersTrigger = core.useFilterTriggerToggle(filtersOpen, setFiltersOpen);
2136
- const rootRef = react.useRef(null);
2137
- core.useChromeScrollReset(rootRef, chrome, chromeProps);
2138
- const bodyData = core.useChromeBodyData(chrome, chromeProps);
2139
- const { virtualization, canLoadMore } = bodyData;
2140
- const loadMoreRef = bodyData.loadMoreRef;
2141
- const searchProps = table.getSearchInputProps(
2142
- searchPlaceholder ? { placeholder: searchPlaceholder } : void 0
2143
- );
2144
- const sortOptions = sortByOptions ?? (chrome.isMobile ? table.sortByOptions : void 0);
2145
- const filtersButton = /* @__PURE__ */ jsxRuntime.jsxs(
2146
- "button",
2147
- {
2148
- type: "button",
2149
- "aria-expanded": filtersMode === "popover" ? filtersOpen : void 0,
2150
- "data-active": filtersOpen || void 0,
2151
- "data-adapttable-part": "filters-button",
2152
- className: classNames.filtersButton,
2153
- style: { flexShrink: 0, whiteSpace: "nowrap" },
2154
- onPointerDown: filtersTrigger.onPointerDown,
2155
- onClick: filtersTrigger.onClick,
2156
- children: [
2157
- /* @__PURE__ */ jsxRuntime.jsx(
2158
- "span",
2159
- {
2160
- "data-adapttable-part": "filters-icon",
2161
- className: classNames.filtersIcon,
2162
- style: { display: "inline-flex" },
2163
- children: /* @__PURE__ */ jsxRuntime.jsx(FiltersIcon, {})
2164
- }
2165
- ),
2166
- labels.filters,
2167
- chrome.activeFilterCount > 0 && /* @__PURE__ */ jsxRuntime.jsx(
2168
- "span",
2169
- {
2170
- "data-adapttable-part": "filters-count",
2171
- className: classNames.filtersCount,
2172
- children: chrome.activeFilterCount
2173
- }
2174
- )
2175
- ]
2176
- }
2177
- );
2178
- return /* @__PURE__ */ jsxRuntime.jsxs(
2179
- "div",
2180
- {
2181
- ref: rootRef,
2182
- dir,
2183
- "data-adapttable-part": "root",
2184
- "data-mobile": chrome.isMobile || void 0,
2185
- "data-density": density,
2186
- "data-refreshing": chrome.isRefreshing || void 0,
2187
- "aria-busy": chrome.isRefreshing || void 0,
2188
- className: cx("adapttable", classNames.root),
2189
- children: [
2190
- /* @__PURE__ */ jsxRuntime.jsxs(
2191
- "div",
2192
- {
2193
- "data-adapttable-part": "toolbar",
2194
- className: classNames.toolbar,
2195
- style: {
2196
- display: "flex",
2197
- flexWrap: "wrap",
2198
- alignItems: "center",
2199
- rowGap: 8
2200
- },
2201
- children: [
2202
- !hideSearch && /* @__PURE__ */ jsxRuntime.jsxs(
2203
- "span",
2204
- {
2205
- "data-adapttable-part": "search-field",
2206
- className: classNames.searchField,
2207
- style: {
2208
- flex: 1,
2209
- minWidth: 0,
2210
- display: "inline-flex",
2211
- alignItems: "center"
2212
- },
2213
- children: [
2214
- /* @__PURE__ */ jsxRuntime.jsx(
2215
- "span",
2216
- {
2217
- "data-adapttable-part": "search-icon",
2218
- className: classNames.searchIcon,
2219
- style: { display: "inline-flex" },
2220
- children: /* @__PURE__ */ jsxRuntime.jsx(SearchIcon, { size: 14 })
2221
- }
2222
- ),
2223
- /* @__PURE__ */ jsxRuntime.jsx(
2224
- "input",
2225
- {
2226
- ...searchProps,
2227
- "data-adapttable-part": "search",
2228
- className: classNames.search,
2229
- style: { flex: 1, minWidth: 0 }
2230
- }
2231
- )
2232
- ]
2233
- }
2234
- ),
2235
- sortOptions && sortOptions.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
2236
- labels.sortBy,
2237
- " ",
2238
- /* @__PURE__ */ jsxRuntime.jsxs(
2239
- "select",
2240
- {
2241
- "aria-label": labels.sortBy,
2242
- "data-adapttable-part": "sort-select",
2243
- className: classNames.sortSelect,
2244
- value: source.sortBy ?? "",
2245
- onChange: (e) => source.setSort(
2246
- e.currentTarget.value || void 0,
2247
- source.sortDir ?? "asc"
2248
- ),
2249
- children: [
2250
- /* @__PURE__ */ jsxRuntime.jsx("option", { value: "", children: "\u2014" }),
2251
- sortOptions.map((o) => /* @__PURE__ */ jsxRuntime.jsx("option", { value: o.value, children: o.label }, o.value))
2252
- ]
2253
- }
2254
- )
2255
- ] }),
2256
- customToolbar,
2257
- filters && (filtersMode === "popover" ? /* @__PURE__ */ jsxRuntime.jsx(
2258
- FilterPopover,
2259
- {
2260
- open: filtersOpen,
2261
- onClose: () => setFiltersOpen(false),
2262
- filters,
2263
- activeFilterCount: chrome.activeFilterCount,
2264
- onClearFilters: chrome.clearFilters,
2265
- labels,
2266
- dir,
2267
- classNames,
2268
- children: filtersButton
2269
- }
2270
- ) : filtersButton),
2271
- props.enableColumnMenu && !chrome.isMobile && /* @__PURE__ */ jsxRuntime.jsx(
2272
- ColumnMenu,
2273
- {
2274
- allColumns: chrome.allColumns,
2275
- layout: chrome.columnLayout,
2276
- labels,
2277
- classNames,
2278
- hasRowActions: (props.rowActions?.length ?? 0) > 0
2279
- }
2280
- ),
2281
- props.savedViews && // The menu must capture/apply through the SAME URL backend and
2282
- // namespace the table reads, so those default from the table's
2283
- // own props (explicit option values still win).
2284
- /* @__PURE__ */ jsxRuntime.jsx(
2285
- SavedViewsMenu,
2286
- {
2287
- options: { adapter: urlAdapter, urlKey, ...props.savedViews },
2288
- labels,
2289
- classNames
2290
- }
2291
- ),
2292
- canLoadMore && /* @__PURE__ */ jsxRuntime.jsx(
2293
- RowsPerPageSelect,
2294
- {
2295
- source,
2296
- labels,
2297
- classNames
2298
- }
2299
- )
2300
- ]
2301
- }
2302
- ),
2303
- filters && filtersMode === "drawer" && /* @__PURE__ */ jsxRuntime.jsx(
2304
- FilterPanel,
2305
- {
2306
- open: filtersOpen,
2307
- onClose: () => setFiltersOpen(false),
2308
- filters,
2309
- activeFilterCount: chrome.activeFilterCount,
2310
- onClearFilters: chrome.clearFilters,
2311
- labels,
2312
- dir,
2313
- classNames
2314
- }
2315
- ),
2316
- /* @__PURE__ */ jsxRuntime.jsx(
2317
- Chips,
2318
- {
2319
- chips: chrome.mergedChips,
2320
- onClearAll: chrome.clearFilters,
2321
- labels,
2322
- classNames
2323
- }
2324
- ),
2325
- table.selection && bulkActions && /* @__PURE__ */ jsxRuntime.jsx(
2326
- BulkBar,
2327
- {
2328
- selection: table.selection,
2329
- total: source.total,
2330
- bulkActions,
2331
- confirm,
2332
- labels,
2333
- classNames
2334
- }
2335
- ),
2336
- chrome.isRefreshing && // Native indeterminate progress (no `value`) — implicit progressbar
2337
- // role with correct semantics on every device.
2338
- /* @__PURE__ */ jsxRuntime.jsx(
2339
- "progress",
2340
- {
2341
- "aria-label": labels.loading,
2342
- "data-adapttable-part": "refresh-indicator",
2343
- className: classNames.refreshIndicator
2344
- }
2345
- ),
2346
- source.error ? /* @__PURE__ */ jsxRuntime.jsx(
2347
- ErrorState,
2348
- {
2349
- error: source.error,
2350
- labels,
2351
- onRetry: source.refetch ? () => void source.refetch?.() : void 0,
2352
- classNames
2353
- }
2354
- ) : /* @__PURE__ */ jsxRuntime.jsx(
2355
- DataTableBody,
2356
- {
2357
- chrome,
2358
- props: chromeProps,
2359
- classNames,
2360
- confirm,
2361
- getRowId,
2362
- virtualization,
2363
- virtualScrollRef: bodyData.virtualScrollRef,
2364
- labels
2365
- }
2366
- ),
2367
- canLoadMore && source.hasNextPage && /* @__PURE__ */ jsxRuntime.jsx(
2368
- "div",
2369
- {
2370
- ref: loadMoreRef,
2371
- "data-adapttable-part": "load-more",
2372
- className: classNames.loadMore,
2373
- children: /* @__PURE__ */ jsxRuntime.jsx(
2374
- "button",
2375
- {
2376
- type: "button",
2377
- disabled: source.isFetchingNextPage,
2378
- "data-adapttable-part": "load-more-button",
2379
- className: classNames.loadMoreButton,
2380
- onClick: () => source.fetchNextPage(),
2381
- children: labels.loadMore
2382
- }
2383
- )
2384
- }
2385
- ),
2386
- chrome.showFooter && /* @__PURE__ */ jsxRuntime.jsx(
2387
- Footer,
2388
- {
2389
- pagination: table.pagination,
2390
- source,
2391
- labels,
2392
- classNames
2393
- }
2394
- )
2395
- ]
2396
- }
2397
- );
1643
+ const { data, total, loading, onQueryChange, urlAdapter, urlKey, searchPlaceholder, sortByOptions, dir, hideSearch, filtersMode = "popover", bulkActions, classNames = NO_CLASSNAMES, toolbar: customToolbar } = props;
1644
+ const density = props.density ?? "comfortable";
1645
+ const { source, runtime } = (0, _adapttable_core.useTableData)({
1646
+ locale: props.locale,
1647
+ source: props.source,
1648
+ data,
1649
+ total,
1650
+ loading,
1651
+ onQueryChange,
1652
+ adapter: props.urlSync === false ? void 0 : urlAdapter,
1653
+ enabled: props.urlSync,
1654
+ urlKey,
1655
+ columns: props.columns,
1656
+ filters: props.filters
1657
+ });
1658
+ const autoForm = runtime.defs.length > 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AutoFilterForm, {
1659
+ defs: runtime.defs,
1660
+ source,
1661
+ classNames,
1662
+ labels: props.labels
1663
+ }) : void 0;
1664
+ const filters = (0, _adapttable_core.isDeclarativeFilters)(props.filters) || props.filters === void 0 ? autoForm : props.filters;
1665
+ const chromeProps = {
1666
+ ...props,
1667
+ source,
1668
+ filters,
1669
+ filterLabels: {
1670
+ ...runtime.filterLabels,
1671
+ ...props.filterLabels
1672
+ }
1673
+ };
1674
+ const chrome = (0, _adapttable_core.useTableChrome)(chromeProps);
1675
+ const { table, confirm, getRowId } = chrome;
1676
+ const { labels } = table;
1677
+ const [filtersOpen, setFiltersOpen] = (0, react.useState)(false);
1678
+ const filtersTrigger = (0, _adapttable_core.useFilterTriggerToggle)(filtersOpen, setFiltersOpen);
1679
+ const rootRef = (0, react.useRef)(null);
1680
+ (0, _adapttable_core.useChromeScrollReset)(rootRef, chrome, chromeProps);
1681
+ const bodyData = (0, _adapttable_core.useChromeBodyData)(chrome, chromeProps);
1682
+ const { virtualization, canLoadMore } = bodyData;
1683
+ const loadMoreRef = bodyData.loadMoreRef;
1684
+ const searchProps = table.getSearchInputProps(searchPlaceholder ? { placeholder: searchPlaceholder } : void 0);
1685
+ const sortOptions = sortByOptions ?? (chrome.isMobile ? table.sortByOptions : void 0);
1686
+ const filtersButton = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
1687
+ type: "button",
1688
+ "aria-expanded": filtersMode === "popover" ? filtersOpen : void 0,
1689
+ "data-active": filtersOpen || void 0,
1690
+ "data-adapttable-part": "filters-button",
1691
+ className: classNames.filtersButton,
1692
+ style: {
1693
+ flexShrink: 0,
1694
+ whiteSpace: "nowrap"
1695
+ },
1696
+ onPointerDown: filtersTrigger.onPointerDown,
1697
+ onClick: filtersTrigger.onClick,
1698
+ children: [
1699
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1700
+ "data-adapttable-part": "filters-icon",
1701
+ className: classNames.filtersIcon,
1702
+ style: { display: "inline-flex" },
1703
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FiltersIcon, {})
1704
+ }),
1705
+ labels.filters,
1706
+ chrome.activeFilterCount > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1707
+ "data-adapttable-part": "filters-count",
1708
+ className: classNames.filtersCount,
1709
+ children: chrome.activeFilterCount
1710
+ })
1711
+ ]
1712
+ });
1713
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1714
+ ref: rootRef,
1715
+ dir,
1716
+ "data-adapttable-part": "root",
1717
+ "data-mobile": chrome.isMobile || void 0,
1718
+ "data-density": density,
1719
+ "data-refreshing": chrome.isRefreshing || void 0,
1720
+ "aria-busy": chrome.isRefreshing || void 0,
1721
+ className: cx("adapttable", classNames.root),
1722
+ children: [
1723
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1724
+ "data-adapttable-part": "toolbar",
1725
+ className: classNames.toolbar,
1726
+ style: {
1727
+ display: "flex",
1728
+ flexWrap: "wrap",
1729
+ alignItems: "center",
1730
+ rowGap: 8
1731
+ },
1732
+ children: [
1733
+ !hideSearch && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1734
+ "data-adapttable-part": "search-field",
1735
+ className: classNames.searchField,
1736
+ style: {
1737
+ flex: 1,
1738
+ minWidth: 0,
1739
+ display: "inline-flex",
1740
+ alignItems: "center"
1741
+ },
1742
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1743
+ "data-adapttable-part": "search-icon",
1744
+ className: classNames.searchIcon,
1745
+ style: { display: "inline-flex" },
1746
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SearchIcon, { size: 14 })
1747
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
1748
+ ...searchProps,
1749
+ "data-adapttable-part": "search",
1750
+ className: classNames.search,
1751
+ style: {
1752
+ flex: 1,
1753
+ minWidth: 0
1754
+ }
1755
+ })]
1756
+ }),
1757
+ sortOptions && sortOptions.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("label", { children: [
1758
+ labels.sortBy,
1759
+ " ",
1760
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("select", {
1761
+ "aria-label": labels.sortBy,
1762
+ "data-adapttable-part": "sort-select",
1763
+ className: classNames.sortSelect,
1764
+ value: source.sortBy ?? "",
1765
+ onChange: (e) => source.setSort(e.currentTarget.value || void 0, source.sortDir ?? "asc"),
1766
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1767
+ value: "",
1768
+ children: ""
1769
+ }), sortOptions.map((o) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("option", {
1770
+ value: o.value,
1771
+ children: o.label
1772
+ }, o.value))]
1773
+ })
1774
+ ] }),
1775
+ customToolbar,
1776
+ filters && (filtersMode === "popover" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterPopover, {
1777
+ open: filtersOpen,
1778
+ onClose: () => setFiltersOpen(false),
1779
+ filters,
1780
+ activeFilterCount: chrome.activeFilterCount,
1781
+ onClearFilters: chrome.clearFilters,
1782
+ labels,
1783
+ dir,
1784
+ classNames,
1785
+ children: filtersButton
1786
+ }) : filtersButton),
1787
+ props.enableColumnMenu && !chrome.isMobile && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ColumnMenu, {
1788
+ allColumns: chrome.allColumns,
1789
+ layout: chrome.columnLayout,
1790
+ labels,
1791
+ classNames,
1792
+ hasRowActions: (props.rowActions?.length ?? 0) > 0
1793
+ }),
1794
+ props.savedViews && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SavedViewsMenu, {
1795
+ options: {
1796
+ adapter: urlAdapter,
1797
+ urlKey,
1798
+ ...props.savedViews
1799
+ },
1800
+ labels,
1801
+ classNames
1802
+ }),
1803
+ canLoadMore && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowsPerPageSelect, {
1804
+ source,
1805
+ labels,
1806
+ classNames
1807
+ })
1808
+ ]
1809
+ }),
1810
+ filters && filtersMode === "drawer" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FilterPanel, {
1811
+ open: filtersOpen,
1812
+ onClose: () => setFiltersOpen(false),
1813
+ filters,
1814
+ activeFilterCount: chrome.activeFilterCount,
1815
+ onClearFilters: chrome.clearFilters,
1816
+ labels,
1817
+ dir,
1818
+ classNames
1819
+ }),
1820
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chips, {
1821
+ chips: chrome.mergedChips,
1822
+ onClearAll: chrome.clearFilters,
1823
+ labels,
1824
+ classNames
1825
+ }),
1826
+ table.selection && bulkActions && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BulkBar, {
1827
+ selection: table.selection,
1828
+ total: source.total,
1829
+ bulkActions,
1830
+ confirm,
1831
+ labels,
1832
+ classNames
1833
+ }),
1834
+ chrome.isRefreshing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("progress", {
1835
+ "aria-label": labels.loading,
1836
+ "data-adapttable-part": "refresh-indicator",
1837
+ className: classNames.refreshIndicator
1838
+ }),
1839
+ source.error ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ErrorState, {
1840
+ error: source.error,
1841
+ labels,
1842
+ onRetry: source.refetch ? () => void source.refetch?.() : void 0,
1843
+ classNames
1844
+ }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DataTableBody, {
1845
+ chrome,
1846
+ props: chromeProps,
1847
+ classNames,
1848
+ confirm,
1849
+ getRowId,
1850
+ virtualization,
1851
+ virtualScrollRef: bodyData.virtualScrollRef,
1852
+ labels
1853
+ }),
1854
+ canLoadMore && source.hasNextPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1855
+ ref: loadMoreRef,
1856
+ "data-adapttable-part": "load-more",
1857
+ className: classNames.loadMore,
1858
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1859
+ type: "button",
1860
+ disabled: source.isFetchingNextPage,
1861
+ "data-adapttable-part": "load-more-button",
1862
+ className: classNames.loadMoreButton,
1863
+ onClick: () => source.fetchNextPage(),
1864
+ children: labels.loadMore
1865
+ })
1866
+ }),
1867
+ chrome.showFooter && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Footer, {
1868
+ pagination: table.pagination,
1869
+ source,
1870
+ labels,
1871
+ classNames
1872
+ })
1873
+ ]
1874
+ });
2398
1875
  }
2399
-
1876
+ //#endregion
1877
+ exports.AutoFilterForm = AutoFilterForm;
1878
+ exports.DataTable = DataTable;
2400
1879
  Object.defineProperty(exports, "FILTER_TYPES", {
2401
- enumerable: true,
2402
- get: function () { return core.FILTER_TYPES; }
1880
+ enumerable: true,
1881
+ get: function() {
1882
+ return _adapttable_core.FILTER_TYPES;
1883
+ }
2403
1884
  });
1885
+ exports.FilterPanel = FilterPanel;
1886
+ exports.FilterPopover = FilterPopover;
1887
+ exports.FiltersIcon = FiltersIcon;
1888
+ exports.SavedViewsMenu = SavedViewsMenu;
1889
+ exports.SearchIcon = SearchIcon;
2404
1890
  Object.defineProperty(exports, "createHistoryAdapter", {
2405
- enumerable: true,
2406
- get: function () { return core.createHistoryAdapter; }
1891
+ enumerable: true,
1892
+ get: function() {
1893
+ return _adapttable_core.createHistoryAdapter;
1894
+ }
2407
1895
  });
2408
1896
  Object.defineProperty(exports, "createMemoryAdapter", {
2409
- enumerable: true,
2410
- get: function () { return core.createMemoryAdapter; }
1897
+ enumerable: true,
1898
+ get: function() {
1899
+ return _adapttable_core.createMemoryAdapter;
1900
+ }
2411
1901
  });
1902
+ exports.cx = cx;
2412
1903
  Object.defineProperty(exports, "defaultConfirm", {
2413
- enumerable: true,
2414
- get: function () { return core.defaultConfirm; }
1904
+ enumerable: true,
1905
+ get: function() {
1906
+ return _adapttable_core.defaultConfirm;
1907
+ }
2415
1908
  });
2416
1909
  Object.defineProperty(exports, "defaultLabels", {
2417
- enumerable: true,
2418
- get: function () { return core.defaultLabels; }
1910
+ enumerable: true,
1911
+ get: function() {
1912
+ return _adapttable_core.defaultLabels;
1913
+ }
2419
1914
  });
2420
1915
  Object.defineProperty(exports, "deriveSortByOptions", {
2421
- enumerable: true,
2422
- get: function () { return core.deriveSortByOptions; }
1916
+ enumerable: true,
1917
+ get: function() {
1918
+ return _adapttable_core.deriveSortByOptions;
1919
+ }
2423
1920
  });
2424
1921
  Object.defineProperty(exports, "filterLabel", {
2425
- enumerable: true,
2426
- get: function () { return core.filterLabel; }
1922
+ enumerable: true,
1923
+ get: function() {
1924
+ return _adapttable_core.filterLabel;
1925
+ }
2427
1926
  });
2428
1927
  Object.defineProperty(exports, "filterStateKeys", {
2429
- enumerable: true,
2430
- get: function () { return core.filterStateKeys; }
1928
+ enumerable: true,
1929
+ get: function() {
1930
+ return _adapttable_core.filterStateKeys;
1931
+ }
2431
1932
  });
2432
1933
  Object.defineProperty(exports, "getHistoryAdapter", {
2433
- enumerable: true,
2434
- get: function () { return core.getHistoryAdapter; }
1934
+ enumerable: true,
1935
+ get: function() {
1936
+ return _adapttable_core.getHistoryAdapter;
1937
+ }
2435
1938
  });
2436
1939
  Object.defineProperty(exports, "useBackendData", {
2437
- enumerable: true,
2438
- get: function () { return core.useBackendData; }
1940
+ enumerable: true,
1941
+ get: function() {
1942
+ return _adapttable_core.useBackendData;
1943
+ }
2439
1944
  });
2440
1945
  Object.defineProperty(exports, "useDataTable", {
2441
- enumerable: true,
2442
- get: function () { return core.useDataTable; }
1946
+ enumerable: true,
1947
+ get: function() {
1948
+ return _adapttable_core.useDataTable;
1949
+ }
2443
1950
  });
2444
1951
  Object.defineProperty(exports, "useFrontendData", {
2445
- enumerable: true,
2446
- get: function () { return core.useFrontendData; }
1952
+ enumerable: true,
1953
+ get: function() {
1954
+ return _adapttable_core.useFrontendData;
1955
+ }
2447
1956
  });
2448
1957
  Object.defineProperty(exports, "useSavedViews", {
2449
- enumerable: true,
2450
- get: function () { return core.useSavedViews; }
1958
+ enumerable: true,
1959
+ get: function() {
1960
+ return _adapttable_core.useSavedViews;
1961
+ }
2451
1962
  });
2452
1963
  Object.defineProperty(exports, "useServerData", {
2453
- enumerable: true,
2454
- get: function () { return core.useServerData; }
1964
+ enumerable: true,
1965
+ get: function() {
1966
+ return _adapttable_core.useServerData;
1967
+ }
2455
1968
  });
2456
1969
  Object.defineProperty(exports, "useTableData", {
2457
- enumerable: true,
2458
- get: function () { return core.useTableData; }
1970
+ enumerable: true,
1971
+ get: function() {
1972
+ return _adapttable_core.useTableData;
1973
+ }
2459
1974
  });
2460
1975
  Object.defineProperty(exports, "useTableUrlState", {
2461
- enumerable: true,
2462
- get: function () { return core.useTableUrlState; }
1976
+ enumerable: true,
1977
+ get: function() {
1978
+ return _adapttable_core.useTableUrlState;
1979
+ }
2463
1980
  });
2464
- exports.AutoFilterForm = AutoFilterForm;
2465
- exports.DataTable = DataTable;
2466
- exports.FilterPanel = FilterPanel;
2467
- exports.FilterPopover = FilterPopover;
2468
- exports.FiltersIcon = FiltersIcon;
2469
- exports.SavedViewsMenu = SavedViewsMenu;
2470
- exports.SearchIcon = SearchIcon;
2471
- exports.cx = cx;
2472
- //# sourceMappingURL=index.cjs.map
1981
+
2473
1982
  //# sourceMappingURL=index.cjs.map