twico-ui 1.45.1 → 1.46.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.d.cts CHANGED
@@ -2087,6 +2087,26 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
2087
2087
  * full row objects server-side rather than relying on `selectedRows`.
2088
2088
  */
2089
2089
  batchActions?: DatatableBatchAction<T>[];
2090
+ /**
2091
+ * #492: extra node in the **selection** toolbar, rendered beside the "N selected" count and before
2092
+ * the batch actions — for the number the count does not carry.
2093
+ *
2094
+ * The count is not always what decides anything. A batch capped by total **size** refuses on
2095
+ * gigabytes, not on items: "12 selected" is not the number the user needs, "12 selected · 2.4 GB"
2096
+ * is. Before this there was nowhere to put it, so hosts lifted it into the main toolbar behind
2097
+ * their own `selected.length > 0` guard — putting it in a different row from the count it
2098
+ * qualifies, and re-deriving a selection this component already tracks.
2099
+ *
2100
+ * Prefer the **function form**: it receives the same `(keys, rows)` the batch actions get, so the
2101
+ * host supplies one pure function and keeps no selection state of its own. (With `retainSelectedRows`
2102
+ * the off-page rows resolve too; without it only the rows currently rendered do.) Pass a plain
2103
+ * node when the summary does not depend on the selection.
2104
+ *
2105
+ * Complements `disabledReason` (#479), which explains the refusal once a cap is exceeded: this is
2106
+ * the running total *before* that point, which is what lets someone stop at the right number
2107
+ * instead of discovering the cap by hitting it.
2108
+ */
2109
+ selectionSummary?: React.ReactNode | ((keys: Array<string | number>, rows: T[]) => React.ReactNode);
2090
2110
  /** #322: fired when the checkbox row selection changes — `(keys, rows)`. The row-mode analogue of
2091
2111
  * `onCellSelectionChange`, so a consumer can track the selection and drive a batch action's own
2092
2112
  * `disabled`/`hidden` (which also accept predicates). */
@@ -2879,6 +2899,26 @@ interface CardGridProps<Row = any> extends Omit<React.HTMLAttributes<HTMLDivElem
2879
2899
  * `ctx.anchorEl` so an action can anchor a popover to its own button.
2880
2900
  */
2881
2901
  batchActions?: CardGridBatchAction<Row>[];
2902
+ /**
2903
+ * #492: extra node in the **selection** toolbar, rendered beside the "N selected" count and before
2904
+ * the batch actions — for the number the count does not carry.
2905
+ *
2906
+ * The count is not always what decides anything. A batch capped by total **size** refuses on
2907
+ * gigabytes, not on items: "12 selected" is not the number the user needs, "12 selected · 2.4 GB"
2908
+ * is. Before this there was nowhere to put it, so hosts lifted it into the main toolbar behind
2909
+ * their own `selected.length > 0` guard — putting it in a different row from the count it
2910
+ * qualifies, and re-deriving a selection this component already tracks.
2911
+ *
2912
+ * Prefer the **function form**: it receives the same `(keys, rows)` the batch actions get, so the
2913
+ * host supplies one pure function and keeps no selection state of its own. (With `retainSelectedRows`
2914
+ * the off-page rows resolve too; without it only the rows currently rendered do.) Pass a plain
2915
+ * node when the summary does not depend on the selection.
2916
+ *
2917
+ * Complements `disabledReason` (#479), which explains the refusal once a cap is exceeded: this is
2918
+ * the running total *before* that point, which is what lets someone stop at the right number
2919
+ * instead of discovering the cap by hitting it.
2920
+ */
2921
+ selectionSummary?: React.ReactNode | ((keys: Array<string | number>, rows: Row[]) => React.ReactNode);
2882
2922
  /** Fired when the selection changes — `(keys, rows)`, matching `Datatable.onRowSelectionChange`. */
2883
2923
  onRowSelectionChange?: (keys: Array<string | number>, rows: Row[]) => void;
2884
2924
  /**
package/dist/index.d.ts CHANGED
@@ -2087,6 +2087,26 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
2087
2087
  * full row objects server-side rather than relying on `selectedRows`.
2088
2088
  */
2089
2089
  batchActions?: DatatableBatchAction<T>[];
2090
+ /**
2091
+ * #492: extra node in the **selection** toolbar, rendered beside the "N selected" count and before
2092
+ * the batch actions — for the number the count does not carry.
2093
+ *
2094
+ * The count is not always what decides anything. A batch capped by total **size** refuses on
2095
+ * gigabytes, not on items: "12 selected" is not the number the user needs, "12 selected · 2.4 GB"
2096
+ * is. Before this there was nowhere to put it, so hosts lifted it into the main toolbar behind
2097
+ * their own `selected.length > 0` guard — putting it in a different row from the count it
2098
+ * qualifies, and re-deriving a selection this component already tracks.
2099
+ *
2100
+ * Prefer the **function form**: it receives the same `(keys, rows)` the batch actions get, so the
2101
+ * host supplies one pure function and keeps no selection state of its own. (With `retainSelectedRows`
2102
+ * the off-page rows resolve too; without it only the rows currently rendered do.) Pass a plain
2103
+ * node when the summary does not depend on the selection.
2104
+ *
2105
+ * Complements `disabledReason` (#479), which explains the refusal once a cap is exceeded: this is
2106
+ * the running total *before* that point, which is what lets someone stop at the right number
2107
+ * instead of discovering the cap by hitting it.
2108
+ */
2109
+ selectionSummary?: React.ReactNode | ((keys: Array<string | number>, rows: T[]) => React.ReactNode);
2090
2110
  /** #322: fired when the checkbox row selection changes — `(keys, rows)`. The row-mode analogue of
2091
2111
  * `onCellSelectionChange`, so a consumer can track the selection and drive a batch action's own
2092
2112
  * `disabled`/`hidden` (which also accept predicates). */
@@ -2879,6 +2899,26 @@ interface CardGridProps<Row = any> extends Omit<React.HTMLAttributes<HTMLDivElem
2879
2899
  * `ctx.anchorEl` so an action can anchor a popover to its own button.
2880
2900
  */
2881
2901
  batchActions?: CardGridBatchAction<Row>[];
2902
+ /**
2903
+ * #492: extra node in the **selection** toolbar, rendered beside the "N selected" count and before
2904
+ * the batch actions — for the number the count does not carry.
2905
+ *
2906
+ * The count is not always what decides anything. A batch capped by total **size** refuses on
2907
+ * gigabytes, not on items: "12 selected" is not the number the user needs, "12 selected · 2.4 GB"
2908
+ * is. Before this there was nowhere to put it, so hosts lifted it into the main toolbar behind
2909
+ * their own `selected.length > 0` guard — putting it in a different row from the count it
2910
+ * qualifies, and re-deriving a selection this component already tracks.
2911
+ *
2912
+ * Prefer the **function form**: it receives the same `(keys, rows)` the batch actions get, so the
2913
+ * host supplies one pure function and keeps no selection state of its own. (With `retainSelectedRows`
2914
+ * the off-page rows resolve too; without it only the rows currently rendered do.) Pass a plain
2915
+ * node when the summary does not depend on the selection.
2916
+ *
2917
+ * Complements `disabledReason` (#479), which explains the refusal once a cap is exceeded: this is
2918
+ * the running total *before* that point, which is what lets someone stop at the right number
2919
+ * instead of discovering the cap by hitting it.
2920
+ */
2921
+ selectionSummary?: React.ReactNode | ((keys: Array<string | number>, rows: Row[]) => React.ReactNode);
2882
2922
  /** Fired when the selection changes — `(keys, rows)`, matching `Datatable.onRowSelectionChange`. */
2883
2923
  onRowSelectionChange?: (keys: Array<string | number>, rows: Row[]) => void;
2884
2924
  /**
package/dist/index.mjs CHANGED
@@ -9537,6 +9537,12 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
9537
9537
  .twc-dt__batch-x:hover { background: color-mix(in srgb, var(--color-primary) 20%, transparent); }
9538
9538
  .twc-dt__batch-x svg { width: 16px; height: 16px; }
9539
9539
  .twc-dt__batch-count { font-size: var(--text-sm); font-weight: var(--font-bold); color: var(--color-primary-subtle-fg); white-space: nowrap; }
9540
+ /* #492: the host's running total, sitting with the count it qualifies. Same colour as the count,
9541
+ differentiated by WEIGHT rather than by a lighter token: this bar is --color-primary-subtle, and
9542
+ --color-text-subtle on that is 4.26:1, under the 4.5:1 needed for normal text. */
9543
+ .twc-dt__batch-summary { display: inline-flex; align-items: center; gap: 6px; font-size: var(--text-sm);
9544
+ color: var(--color-primary-subtle-fg); white-space: nowrap; }
9545
+ .twc-dt__batch-summary::before { content: ""; width: var(--border-thin); height: 14px; background: currentColor; opacity: 0.35; }
9540
9546
  .twc-dt__batch-actions { margin-inline-start: auto; display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
9541
9547
  .twc-dt__batch-btn { display: inline-flex; align-items: center; gap: 6px; height: 32px; padding: 0 12px;
9542
9548
  border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-md); background: var(--color-surface);
@@ -10037,6 +10043,7 @@ function Datatable({
10037
10043
  onColumnVisibilityChange,
10038
10044
  batchActions = [],
10039
10045
  onRowSelectionChange,
10046
+ selectionSummary,
10040
10047
  getRowStyle,
10041
10048
  getRowClassName,
10042
10049
  showExport = false,
@@ -12906,13 +12913,13 @@ function Datatable({
12906
12913
  return /* @__PURE__ */ jsxs("div", { className: `twc-dt ${className}`, ref: rootRef, "data-density": density, "data-resizing": resizing || void 0, "data-editing": editing ? "" : void 0, ...rest, children: [
12907
12914
  __twcStyles,
12908
12915
  /* @__PURE__ */ jsxs("div", { className: "twc-dt__toolbar", "data-compact": compact || void 0, children: [
12909
- toolbarActions != null ? /* @__PURE__ */ jsx("div", { className: "twc-dt__toolbar-actions", children: toolbarActions }) : null,
12910
12916
  (batchActions.length || hasBatchEditor) && selected.size > 0 ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__batch", children: [
12911
12917
  /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__batch-x", onClick: clearSelection, "aria-label": "Clear selection", children: /* @__PURE__ */ jsx(Svg, { d: I.x }) }),
12912
12918
  /* @__PURE__ */ jsxs("span", { className: "twc-dt__batch-count", children: [
12913
12919
  selected.size,
12914
12920
  " selected"
12915
12921
  ] }),
12922
+ selectionSummary != null ? /* @__PURE__ */ jsx("span", { className: "twc-dt__batch-summary", children: typeof selectionSummary === "function" ? selectionSummary(selKeys, selectedRows) : selectionSummary }) : null,
12916
12923
  /* @__PURE__ */ jsxs("div", { className: "twc-dt__batch-actions", children: [
12917
12924
  hasBatchEditor ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__batch-btn", onClick: (e) => openBatchEditor(e.currentTarget), children: [
12918
12925
  /* @__PURE__ */ jsx(Svg, { d: I.pencil }),
@@ -13107,6 +13114,7 @@ function Datatable({
13107
13114
  }
13108
13115
  )
13109
13116
  ] }) : null,
13117
+ toolbarActions != null ? /* @__PURE__ */ jsx("div", { className: "twc-dt__toolbar-actions", children: toolbarActions }) : null,
13110
13118
  searchable ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__search", children: [
13111
13119
  /* @__PURE__ */ jsx(Svg, { d: I.search }),
13112
13120
  /* @__PURE__ */ jsx("input", { ref: quickSearchRef, placeholder: "Search\u2026", "aria-label": "Search rows", value: quick, onChange: (e) => commitQuick(e.target.value) }),
@@ -14395,6 +14403,11 @@ var CARDGRID_CSS = `
14395
14403
  padding: var(--space-2) var(--space-3); border: var(--border-thin) solid var(--color-primary-border);
14396
14404
  background: var(--color-primary-subtle); border-radius: var(--radius-md); }
14397
14405
  .twc-cardgrid__batch-count { font-size: var(--text-sm); font-weight: var(--font-semibold); color: var(--color-primary-subtle-fg); }
14406
+ /* #492: same slot, same contract as Datatable. Weight, not a lighter token - this bar is
14407
+ --color-primary-subtle, where --color-text-subtle is 4.26:1 and fails normal-text contrast. */
14408
+ .twc-cardgrid__batch-summary { display: inline-flex; align-items: center; gap: var(--space-2);
14409
+ font-size: var(--text-sm); color: var(--color-primary-subtle-fg); }
14410
+ .twc-cardgrid__batch-summary::before { content: ""; width: var(--border-thin); height: 14px; background: currentColor; opacity: 0.35; }
14398
14411
  .twc-cardgrid__batch-actions { display: inline-flex; flex-wrap: wrap; align-items: center; gap: var(--space-2); margin-inline-start: auto; }
14399
14412
  .twc-cardgrid__batch-btn { display: inline-flex; align-items: center; gap: var(--space-2); height: var(--control-h-sm);
14400
14413
  padding-inline: var(--space-3); border: var(--border-thin) solid var(--color-border); background: var(--color-surface);
@@ -14450,6 +14463,7 @@ function CardGrid({
14450
14463
  // the whole point, and it was the only Datatable affordance CardGrid lacked.
14451
14464
  checkboxSelection = false,
14452
14465
  batchActions = [],
14466
+ selectionSummary,
14453
14467
  onRowSelectionChange,
14454
14468
  selectionPlacement = "top-start",
14455
14469
  selectionLabel,
@@ -14657,6 +14671,7 @@ function CardGrid({
14657
14671
  selected.size,
14658
14672
  " selected"
14659
14673
  ] }),
14674
+ selectionSummary != null ? /* @__PURE__ */ jsx("span", { className: "twc-cardgrid__batch-summary", children: typeof selectionSummary === "function" ? selectionSummary(selKeys, selectedRows) : selectionSummary }) : null,
14660
14675
  showSelectAll && pageRows.length > 0 ? /* @__PURE__ */ jsxs("label", { className: "twc-cardgrid__selall", children: [
14661
14676
  /* @__PURE__ */ jsx(
14662
14677
  Checkbox,