twico-ui 1.40.0 → 1.41.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/index.cjs +63 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +20 -4
- package/dist/index.d.ts +20 -4
- package/dist/index.mjs +63 -17
- package/dist/index.mjs.map +1 -1
- package/llms.txt +3 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1665,6 +1665,11 @@ interface ComboboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>
|
|
|
1665
1665
|
value?: string | null;
|
|
1666
1666
|
/** Uncontrolled initial value. */
|
|
1667
1667
|
defaultValue?: string | null;
|
|
1668
|
+
/** Seed the search *text* with this string each time the menu opens (caret placed at the end), without emitting it as
|
|
1669
|
+
* an `onInputChange`. It is matched against option labels/descriptions like any typed query — not the option
|
|
1670
|
+
* `value` — so to open a cell editor pre-filled on the current selection, pass its **label** (e.g. `"Japan"`),
|
|
1671
|
+
* not its value (`"jp"`). */
|
|
1672
|
+
defaultQuery?: string;
|
|
1668
1673
|
/** Called with the chosen option's value, or `null` when cleared via `clearable`. */
|
|
1669
1674
|
onChange?: (value: string | null) => void;
|
|
1670
1675
|
/** Show a clear (×) affix when a value is selected. */
|
|
@@ -1680,6 +1685,9 @@ interface ComboboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>
|
|
|
1680
1685
|
minWidth?: number;
|
|
1681
1686
|
/** Called with the raw query on every keystroke — drive a debounced remote fetch (with `loading` + `filter={false}`). */
|
|
1682
1687
|
onInputChange?: (query: string) => void;
|
|
1688
|
+
/** Called with `true` when the menu opens and `false` when it closes (including when `close()` silently resets the
|
|
1689
|
+
* typed query) — a host staging that query (e.g. a cell editor) can withdraw it on close. */
|
|
1690
|
+
onOpenChange?: (open: boolean) => void;
|
|
1683
1691
|
/** Client-side filtering: `false` shows options as-is (server-ranked); a function replaces the default label/description match. */
|
|
1684
1692
|
filter?: boolean | ((option: ComboboxOption, query: string) => boolean);
|
|
1685
1693
|
/** Show a loading row instead of the option list / empty state. @default false */
|
|
@@ -2043,10 +2051,18 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
2043
2051
|
/** Controlled-rows callback: receives the full next rows array after an edit (client mode). */
|
|
2044
2052
|
onRowsChange?: (rows: T[]) => void;
|
|
2045
2053
|
/** Fired when the built-in batch editor applies columns across selected rows:
|
|
2046
|
-
* (changedRows, patch, selectedKeys)
|
|
2047
|
-
* automatically when there are editable columns.
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2054
|
+
* `(changedRows, patch, selectedKeys)`. The selection-toolbar "Edit" button appears
|
|
2055
|
+
* automatically when there are editable columns.
|
|
2056
|
+
* - `changedRows` is **authoritative**: each row carries exactly the fields it may change
|
|
2057
|
+
* (a per-row `editable` predicate (#424/#428) is applied per cell). Persist these for a
|
|
2058
|
+
* complete, cell-precise write of the loaded page.
|
|
2059
|
+
* - `patch` is the column-uniform union of the picked field values.
|
|
2060
|
+
* - `selectedKeys` are the keys a `keys × patch` write can safely apply the **whole** patch
|
|
2061
|
+
* to — loaded rows on which **every** picked column is editable (so it never touches a
|
|
2062
|
+
* locked cell), plus any selected key on an **unloaded** page (which can't be predicate-
|
|
2063
|
+
* tested client-side — you apply and enforce the predicate server-side). For a mixed
|
|
2064
|
+
* batch where a row is editable on only some picked columns, that row is in `changedRows`
|
|
2065
|
+
* but not `selectedKeys`; use `changedRows` for the exact per-cell result. */
|
|
2050
2066
|
onBatchUpdate?: (changedRows: T[], patch: Record<string, any>, selectedKeys: Array<string | number>) => void;
|
|
2051
2067
|
/** Render the built-in "Edit" button in the selection toolbar (the batch editor). Set `false` to
|
|
2052
2068
|
* suppress it and ship your own batch-edit action via `batchActions` — otherwise you'd get two
|
package/dist/index.d.ts
CHANGED
|
@@ -1665,6 +1665,11 @@ interface ComboboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>
|
|
|
1665
1665
|
value?: string | null;
|
|
1666
1666
|
/** Uncontrolled initial value. */
|
|
1667
1667
|
defaultValue?: string | null;
|
|
1668
|
+
/** Seed the search *text* with this string each time the menu opens (caret placed at the end), without emitting it as
|
|
1669
|
+
* an `onInputChange`. It is matched against option labels/descriptions like any typed query — not the option
|
|
1670
|
+
* `value` — so to open a cell editor pre-filled on the current selection, pass its **label** (e.g. `"Japan"`),
|
|
1671
|
+
* not its value (`"jp"`). */
|
|
1672
|
+
defaultQuery?: string;
|
|
1668
1673
|
/** Called with the chosen option's value, or `null` when cleared via `clearable`. */
|
|
1669
1674
|
onChange?: (value: string | null) => void;
|
|
1670
1675
|
/** Show a clear (×) affix when a value is selected. */
|
|
@@ -1680,6 +1685,9 @@ interface ComboboxProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>
|
|
|
1680
1685
|
minWidth?: number;
|
|
1681
1686
|
/** Called with the raw query on every keystroke — drive a debounced remote fetch (with `loading` + `filter={false}`). */
|
|
1682
1687
|
onInputChange?: (query: string) => void;
|
|
1688
|
+
/** Called with `true` when the menu opens and `false` when it closes (including when `close()` silently resets the
|
|
1689
|
+
* typed query) — a host staging that query (e.g. a cell editor) can withdraw it on close. */
|
|
1690
|
+
onOpenChange?: (open: boolean) => void;
|
|
1683
1691
|
/** Client-side filtering: `false` shows options as-is (server-ranked); a function replaces the default label/description match. */
|
|
1684
1692
|
filter?: boolean | ((option: ComboboxOption, query: string) => boolean);
|
|
1685
1693
|
/** Show a loading row instead of the option list / empty state. @default false */
|
|
@@ -2043,10 +2051,18 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
2043
2051
|
/** Controlled-rows callback: receives the full next rows array after an edit (client mode). */
|
|
2044
2052
|
onRowsChange?: (rows: T[]) => void;
|
|
2045
2053
|
/** Fired when the built-in batch editor applies columns across selected rows:
|
|
2046
|
-
* (changedRows, patch, selectedKeys)
|
|
2047
|
-
* automatically when there are editable columns.
|
|
2048
|
-
*
|
|
2049
|
-
*
|
|
2054
|
+
* `(changedRows, patch, selectedKeys)`. The selection-toolbar "Edit" button appears
|
|
2055
|
+
* automatically when there are editable columns.
|
|
2056
|
+
* - `changedRows` is **authoritative**: each row carries exactly the fields it may change
|
|
2057
|
+
* (a per-row `editable` predicate (#424/#428) is applied per cell). Persist these for a
|
|
2058
|
+
* complete, cell-precise write of the loaded page.
|
|
2059
|
+
* - `patch` is the column-uniform union of the picked field values.
|
|
2060
|
+
* - `selectedKeys` are the keys a `keys × patch` write can safely apply the **whole** patch
|
|
2061
|
+
* to — loaded rows on which **every** picked column is editable (so it never touches a
|
|
2062
|
+
* locked cell), plus any selected key on an **unloaded** page (which can't be predicate-
|
|
2063
|
+
* tested client-side — you apply and enforce the predicate server-side). For a mixed
|
|
2064
|
+
* batch where a row is editable on only some picked columns, that row is in `changedRows`
|
|
2065
|
+
* but not `selectedKeys`; use `changedRows` for the exact per-cell result. */
|
|
2050
2066
|
onBatchUpdate?: (changedRows: T[], patch: Record<string, any>, selectedKeys: Array<string | number>) => void;
|
|
2051
2067
|
/** Render the built-in "Edit" button in the selection toolbar (the batch editor). Set `false` to
|
|
2052
2068
|
* suppress it and ship your own batch-edit action via `batchActions` — otherwise you'd get two
|
package/dist/index.mjs
CHANGED
|
@@ -420,7 +420,10 @@ var ICONBTN_CSS = `
|
|
|
420
420
|
.twc-iconbtn[aria-pressed="true"][data-pressed-tone="warning"] { --_accent: var(--color-warning); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg); }
|
|
421
421
|
.twc-iconbtn[aria-pressed="true"][data-pressed-tone="info"] { --_accent: var(--color-info); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg); }
|
|
422
422
|
.twc-iconbtn[aria-pressed="true"][data-pressed-tone="danger"] { --_accent: var(--color-danger); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg); }
|
|
423
|
-
|
|
423
|
+
/* #430: color-surface-sunken steps toward the page background in dark mode, so a neutral pressed fill was
|
|
424
|
+
invisible on a surface panel. Fill with color-border (steps away from the background in both themes) + a
|
|
425
|
+
stronger color-text-subtle edge so the outline also carries the "on" state. Mirrors Button. */
|
|
426
|
+
.twc-iconbtn[aria-pressed="true"][data-pressed-tone="neutral"] { --_accent: var(--color-text-subtle); --_accent-subtle: var(--color-border); --_accent-subtle-fg: var(--color-text); }
|
|
424
427
|
/* #418: keep the pressed look on hover (matching-specificity, after the variant hover rules). */
|
|
425
428
|
.twc-iconbtn[aria-pressed="true"]:hover:not(:disabled) { background: var(--_accent-subtle); color: var(--_accent-subtle-fg); border-color: var(--_accent); filter: brightness(0.97); }
|
|
426
429
|
.dark .twc-iconbtn[aria-pressed="true"]:hover:not(:disabled) { filter: brightness(1.25); }
|
|
@@ -1718,7 +1721,11 @@ var CSS2 = `
|
|
|
1718
1721
|
.twc-btn[aria-pressed="true"][data-pressed-tone="warning"] { --_accent: var(--color-warning); --_accent-subtle: var(--color-warning-subtle); --_accent-subtle-fg: var(--color-warning-subtle-fg); }
|
|
1719
1722
|
.twc-btn[aria-pressed="true"][data-pressed-tone="info"] { --_accent: var(--color-info); --_accent-subtle: var(--color-info-subtle); --_accent-subtle-fg: var(--color-info-subtle-fg); }
|
|
1720
1723
|
.twc-btn[aria-pressed="true"][data-pressed-tone="danger"] { --_accent: var(--color-danger); --_accent-subtle: var(--color-danger-subtle); --_accent-subtle-fg: var(--color-danger-subtle-fg); }
|
|
1721
|
-
|
|
1724
|
+
/* #430: color-surface-sunken steps TOWARD the page background in dark mode (0b1222 under 0f172a), so a neutral
|
|
1725
|
+
pressed fill was invisible on a surface panel. Fill with color-border instead \u2014 it steps AWAY from the
|
|
1726
|
+
background in both themes (lighter in dark, darker in light) \u2014 and strengthen the edge with color-text-subtle
|
|
1727
|
+
so the outline carries the "on" state too (neutral has no meaning-colour to recolour the label). */
|
|
1728
|
+
.twc-btn[aria-pressed="true"][data-pressed-tone="neutral"] { --_accent: var(--color-text-subtle); --_accent-subtle: var(--color-border); --_accent-subtle-fg: var(--color-text); }
|
|
1722
1729
|
/* #418: keep the pressed look under the pointer \u2014 the variant hover rules (0,4,0) otherwise beat the base
|
|
1723
1730
|
pressed rule (0,2,0). This matching-specificity rule, source-ordered after them, restores the fill/fg/border
|
|
1724
1731
|
(resetting the text colour too, so solid stays legible \u2014 incl. tone="danger"). */
|
|
@@ -6328,6 +6335,7 @@ function Combobox({
|
|
|
6328
6335
|
options,
|
|
6329
6336
|
value,
|
|
6330
6337
|
defaultValue = null,
|
|
6338
|
+
defaultQuery,
|
|
6331
6339
|
onChange,
|
|
6332
6340
|
clearable = false,
|
|
6333
6341
|
disabled = false,
|
|
@@ -6335,6 +6343,7 @@ function Combobox({
|
|
|
6335
6343
|
portal = true,
|
|
6336
6344
|
minWidth = 0,
|
|
6337
6345
|
onInputChange,
|
|
6346
|
+
onOpenChange,
|
|
6338
6347
|
filter,
|
|
6339
6348
|
loading = false,
|
|
6340
6349
|
emptyText = "No results found",
|
|
@@ -6451,9 +6460,18 @@ function Combobox({
|
|
|
6451
6460
|
React53__default.useEffect(() => {
|
|
6452
6461
|
setActive(0);
|
|
6453
6462
|
}, [query]);
|
|
6463
|
+
const onOpenChangeRef = React53__default.useRef(onOpenChange);
|
|
6464
|
+
onOpenChangeRef.current = onOpenChange;
|
|
6465
|
+
const prevOpenRef = React53__default.useRef(open);
|
|
6466
|
+
React53__default.useEffect(() => {
|
|
6467
|
+
if (prevOpenRef.current !== open) {
|
|
6468
|
+
prevOpenRef.current = open;
|
|
6469
|
+
onOpenChangeRef.current?.(open);
|
|
6470
|
+
}
|
|
6471
|
+
}, [open]);
|
|
6454
6472
|
React53__default.useEffect(() => {
|
|
6455
6473
|
if (!open) return;
|
|
6456
|
-
const idx =
|
|
6474
|
+
const idx = visible.findIndex((o) => o.value === current);
|
|
6457
6475
|
setActive(idx >= 0 ? idx : 0);
|
|
6458
6476
|
}, [open]);
|
|
6459
6477
|
React53__default.useEffect(() => {
|
|
@@ -6480,8 +6498,13 @@ function Combobox({
|
|
|
6480
6498
|
}, [active, open, virtualized, rows, listH]);
|
|
6481
6499
|
function openMenu() {
|
|
6482
6500
|
if (disabled) return;
|
|
6483
|
-
|
|
6501
|
+
const seed = defaultQuery || "";
|
|
6502
|
+
setQuery(seed);
|
|
6484
6503
|
setOpen(true);
|
|
6504
|
+
if (seed) requestAnimationFrame(() => {
|
|
6505
|
+
const el = inputRef.current;
|
|
6506
|
+
if (el) el.setSelectionRange(seed.length, seed.length);
|
|
6507
|
+
});
|
|
6485
6508
|
}
|
|
6486
6509
|
function close() {
|
|
6487
6510
|
setOpen(false);
|
|
@@ -10446,7 +10469,7 @@ function Datatable({
|
|
|
10446
10469
|
);
|
|
10447
10470
|
const effectiveHidden = React53__default.useMemo(() => combineSources.size ? /* @__PURE__ */ new Set([...hidden, ...combineSources]) : hidden, [hidden, combineSources]);
|
|
10448
10471
|
const effectiveWrapped = React53__default.useMemo(() => stackCombineTargets.size ? /* @__PURE__ */ new Set([...wrapped, ...stackCombineTargets]) : wrapped, [wrapped, stackCombineTargets]);
|
|
10449
|
-
const visibleCols = cols.filter((c) => !effectiveHidden.has(c.field));
|
|
10472
|
+
const visibleCols = React53__default.useMemo(() => cols.filter((c) => !effectiveHidden.has(c.field)), [cols, effectiveHidden]);
|
|
10450
10473
|
const colFieldsKey = JSON.stringify(
|
|
10451
10474
|
cols.filter((c) => typeof c.field === "string" && c.type !== "actions").map((c) => c.field)
|
|
10452
10475
|
);
|
|
@@ -11321,12 +11344,18 @@ function Datatable({
|
|
|
11321
11344
|
const revealOn = !!scrollActiveCellIntoView;
|
|
11322
11345
|
const revealBlock = scrollActiveCellIntoView && typeof scrollActiveCellIntoView === "object" && scrollActiveCellIntoView.block === "center" ? "center" : "nearest";
|
|
11323
11346
|
const revealInline = scrollActiveCellIntoView && typeof scrollActiveCellIntoView === "object" && scrollActiveCellIntoView.inline === "center" ? "center" : "nearest";
|
|
11347
|
+
const revealRi = activeCellVal ? keyIndex.get(activeCellVal.key) : void 0;
|
|
11348
|
+
const revealCi = activeCellVal ? cellColIndex(activeCellVal.field) : -1;
|
|
11349
|
+
const revealOffsetsRef = React53__default.useRef(offsets);
|
|
11350
|
+
revealOffsetsRef.current = offsets;
|
|
11351
|
+
const revealMidRef = React53__default.useRef(keyIndexMid);
|
|
11352
|
+
revealMidRef.current = keyIndexMid;
|
|
11324
11353
|
React53__default.useEffect(() => {
|
|
11325
11354
|
if (!revealOn || !activeCellVal) return void 0;
|
|
11326
11355
|
const block = revealBlock, inline = revealInline;
|
|
11327
|
-
const ri =
|
|
11356
|
+
const ri = revealRi, ci = revealCi;
|
|
11328
11357
|
if (ri == null || ci < 0) return void 0;
|
|
11329
|
-
let raf = 0;
|
|
11358
|
+
let raf = 0, tries = 0;
|
|
11330
11359
|
const reveal = () => {
|
|
11331
11360
|
const sc = scrollRef.current;
|
|
11332
11361
|
if (!sc) return;
|
|
@@ -11352,10 +11381,12 @@ function Datatable({
|
|
|
11352
11381
|
} else if (tR.left < scR.left + leftInset) sc.scrollLeft -= scR.left + leftInset - tR.left;
|
|
11353
11382
|
else if (tR.right > scR.right - rightInset) sc.scrollLeft += tR.right - (scR.right - rightInset);
|
|
11354
11383
|
}
|
|
11355
|
-
} else if (virtualizing &&
|
|
11356
|
-
const
|
|
11357
|
-
|
|
11358
|
-
|
|
11384
|
+
} else if (virtualizing && revealOffsetsRef.current) {
|
|
11385
|
+
const off = revealOffsetsRef.current;
|
|
11386
|
+
const mi = revealMidRef.current.get(activeCellVal.key);
|
|
11387
|
+
if (mi != null && off[mi] != null && tries < 30) {
|
|
11388
|
+
tries += 1;
|
|
11389
|
+
sc.scrollTop = Math.max(0, off[mi] - (block === "center" ? sc.clientHeight / 2 : headH));
|
|
11359
11390
|
raf = requestAnimationFrame(reveal);
|
|
11360
11391
|
}
|
|
11361
11392
|
}
|
|
@@ -11364,7 +11395,7 @@ function Datatable({
|
|
|
11364
11395
|
return () => {
|
|
11365
11396
|
if (raf) cancelAnimationFrame(raf);
|
|
11366
11397
|
};
|
|
11367
|
-
}, [activeCellVal?.key, activeCellVal?.field, revealOn, revealBlock, revealInline,
|
|
11398
|
+
}, [activeCellVal?.key, activeCellVal?.field, revealOn, revealBlock, revealInline, revealRi, revealCi, virtualizing, headH]);
|
|
11368
11399
|
React53__default.useEffect(() => {
|
|
11369
11400
|
if (!activeCellControlled || !activeCellVal) {
|
|
11370
11401
|
jumpAppliedRef.current = null;
|
|
@@ -11456,6 +11487,10 @@ function Datatable({
|
|
|
11456
11487
|
[cols, editMode, batchEditKey]
|
|
11457
11488
|
// eslint-disable-line react-hooks/exhaustive-deps
|
|
11458
11489
|
);
|
|
11490
|
+
const batchEditableColsSel = React53__default.useMemo(
|
|
11491
|
+
() => batchEditableCols.filter((c) => typeof c.editable !== "function" || selectedRows.some((r2) => c.editable(r2, { field: c.field }))),
|
|
11492
|
+
[batchEditableCols, selectedRows]
|
|
11493
|
+
);
|
|
11459
11494
|
const hasBatchEditor = showBatchEdit && batchEditableCols.length > 0;
|
|
11460
11495
|
const [batchEdit, setBatchEdit] = React53__default.useState(null);
|
|
11461
11496
|
const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
|
|
@@ -11490,7 +11525,7 @@ function Datatable({
|
|
|
11490
11525
|
}, [batchEdit, selected.size, closeBatchEdit]);
|
|
11491
11526
|
function applyBatchEdit() {
|
|
11492
11527
|
if (!batchEdit) return;
|
|
11493
|
-
const active =
|
|
11528
|
+
const active = batchEditableColsSel.filter((c) => batchEdit.fields[c.field]);
|
|
11494
11529
|
if (!active.length) {
|
|
11495
11530
|
setBatchEdit(null);
|
|
11496
11531
|
closeBatchEdit();
|
|
@@ -11506,20 +11541,27 @@ function Datatable({
|
|
|
11506
11541
|
patch[c.field] = v;
|
|
11507
11542
|
});
|
|
11508
11543
|
const selKeys2 = new Set(selected);
|
|
11544
|
+
const loadedSel = /* @__PURE__ */ new Set();
|
|
11509
11545
|
const changedRows = [];
|
|
11546
|
+
const safeKeys = [];
|
|
11510
11547
|
const nextAll = rows.map((r2, i) => {
|
|
11511
11548
|
const k = keyOf(r2, i);
|
|
11512
11549
|
if (!selKeys2.has(k)) return r2;
|
|
11550
|
+
loadedSel.add(k);
|
|
11513
11551
|
const rowPatch = {};
|
|
11552
|
+
let allEditable = true;
|
|
11514
11553
|
for (const c of active) {
|
|
11515
11554
|
if (typeof c.editable !== "function" || c.editable(r2, { field: c.field })) rowPatch[c.field] = patch[c.field];
|
|
11555
|
+
else allEditable = false;
|
|
11516
11556
|
}
|
|
11557
|
+
if (allEditable) safeKeys.push(k);
|
|
11517
11558
|
if (!Object.keys(rowPatch).length) return r2;
|
|
11518
11559
|
const updated = { ...r2, ...rowPatch };
|
|
11519
11560
|
changedRows.push(updated);
|
|
11520
11561
|
return updated;
|
|
11521
11562
|
});
|
|
11522
|
-
|
|
11563
|
+
for (const k of selKeys2) if (!loadedSel.has(k)) safeKeys.push(k);
|
|
11564
|
+
onBatchUpdate?.(changedRows, patch, safeKeys);
|
|
11523
11565
|
onRowsChange?.(nextAll);
|
|
11524
11566
|
setBatchEdit(null);
|
|
11525
11567
|
closeBatchEdit();
|
|
@@ -13062,8 +13104,8 @@ function Datatable({
|
|
|
13062
13104
|
}
|
|
13063
13105
|
) : null,
|
|
13064
13106
|
batchEdit && batchEditPos ? (() => {
|
|
13065
|
-
const pickedCols = Object.keys(batchEdit.fields).filter((f) => batchEdit.fields[f]).map((f) =>
|
|
13066
|
-
const unpicked =
|
|
13107
|
+
const pickedCols = Object.keys(batchEdit.fields).filter((f) => batchEdit.fields[f]).map((f) => batchEditableColsSel.find((c) => c.field === f)).filter(Boolean);
|
|
13108
|
+
const unpicked = batchEditableColsSel.filter((c) => !batchEdit.fields[c.field]);
|
|
13067
13109
|
const addField = (f) => {
|
|
13068
13110
|
if (f) setBatchEdit((b) => ({ ...b, fields: { ...b.fields, [f]: true }, values: { ...b.values, [f]: b.values[f] ?? "" } }));
|
|
13069
13111
|
};
|
|
@@ -13095,7 +13137,11 @@ function Datatable({
|
|
|
13095
13137
|
onChange: addField
|
|
13096
13138
|
}
|
|
13097
13139
|
) }) : null,
|
|
13098
|
-
/* @__PURE__ */ jsx("div", { className: "twc-dt__cfg-list", children: pickedCols.length === 0 ?
|
|
13140
|
+
/* @__PURE__ */ jsx("div", { className: "twc-dt__cfg-list", children: pickedCols.length === 0 ? (
|
|
13141
|
+
// #428: when a predicate leaves no column editable for the current selection, say so instead of
|
|
13142
|
+
// inviting a pick that can't be made (the "Add a column…" picker is hidden when unpicked is empty).
|
|
13143
|
+
/* @__PURE__ */ jsx("div", { className: "twc-dt__be-empty", children: unpicked.length ? "Pick a column to set its value on all selected rows." : "No columns are editable for the current selection." })
|
|
13144
|
+
) : pickedCols.map((c, i) => {
|
|
13099
13145
|
const opts = c.valueOptions ? c.valueOptions.map((o) => typeof o === "string" ? { value: o, label: o } : o) : null;
|
|
13100
13146
|
return /* @__PURE__ */ jsxs("div", { className: "twc-dt__be-row", children: [
|
|
13101
13147
|
/* @__PURE__ */ jsxs("span", { className: "twc-dt__be-name", title: colLabel(c), children: [
|