twico-ui 1.44.0 → 1.45.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
@@ -1951,6 +1951,65 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
1951
1951
  * This prop is the initial state — when enabled, users can hide/show the column from the toolbar's
1952
1952
  * **Columns** panel ("Row number"). @default false */
1953
1953
  rowNumbers?: boolean;
1954
+ /**
1955
+ * #481: style a whole row from its own state — the row-level counterpart to a column's `cellStyle`.
1956
+ * Without it, marking a row meant assigning `cellStyle` to **every** column: O(columns) for a
1957
+ * row-level fact, hand-composed against whatever else already used `cellStyle`, and with no fixed
1958
+ * column list to decorate at all when the columns come from a schema.
1959
+ *
1960
+ * Called `(row, index)`, the same shape as `rowKey`. **`index` is the row's 0-based position among
1961
+ * the rows currently rendered** — after sorting and filtering, and **within the current page**. It is
1962
+ * therefore *not* the number the `rowNumbers` column shows, which continues across pages; if you need
1963
+ * an absolute position, read it off `row` rather than from this argument.
1964
+ *
1965
+ * A `background` (or `backgroundColor`) is forwarded to the row's CELLS through the `--twc-dt-row-bg`
1966
+ * custom property, because `.twc-dt__td` paints an opaque surface of its own — without that it would
1967
+ * be invisible — and is **removed** from what reaches the `<tr>`, since a row box paints below its
1968
+ * cells and a leftover copy there would composite with the tint rather than hide behind it. Every
1969
+ * other declaration lands on the `<tr>`, except `border` (ignored on row boxes under
1970
+ * `border-collapse: separate`) and `backgroundImage` (painted under the cells' opaque surface) — both
1971
+ * need {@link getRowClassName} and a `… .twc-dt__td` rule. Sticky positioning and measured row height
1972
+ * are applied after yours, so a hook cannot break row pinning or row resizing.
1973
+ *
1974
+ * **Layering — one rule, not a bespoke order:** the row tint is the **bottom** layer above the
1975
+ * cell's plain surface, and **every** built-in state background covers it. The base `.twc-dt__td`
1976
+ * rule is the lowest-specificity background in the component, so hover, row selection,
1977
+ * `activeRowId`, a pinned row, a grabbed row, the diff add/remove/modify washes, cell
1978
+ * selection/active and inline editing all outrank it — and an inline per-cell `cellStyle` outranks
1979
+ * those. A row tint is a *data-derived* wash; nothing data-derived should be able to hide an
1980
+ * interaction state. So selection still reads on a tinted row, hover feedback is never lost, and a
1981
+ * per-cell state wins with nothing to compose on your side.
1982
+ *
1983
+ * Need a tint that survives hover? Use {@link getRowClassName} with a rule outranking `(0,3,0)` —
1984
+ * note `.twc-dt__row.my-row .twc-dt__td` is itself `(0,3,0)`, a tie decided by source order, so add
1985
+ * an element: `tr.twc-dt__row.my-row .twc-dt__td` is `(0,3,1)`, and `… .twc-dt__td[data-pin]` is
1986
+ * `(0,4,1)` for the pinned-column twins. You are then choosing to cover the hover cue on those rows.
1987
+ *
1988
+ * **Stripes:** there are none to layer against. Datatable does not zebra-stripe its data rows —
1989
+ * the only `data-zebra` rules in the component style the PIVOT grid's cells, and the hook does not
1990
+ * apply to pivot rows. So a row tint never has to compete with a stripe.
1991
+ *
1992
+ * **Which rows:** every data row. That includes rows pinned with the row ⋮ menu (the hook runs and
1993
+ * the class/non-background declarations apply, though the pinned-row highlight covers a background
1994
+ * tint for as long as the row is pinned, exactly like selection), and cells in a pinned COLUMN pick
1995
+ * the tint up, so a tinted row shows no hole where a frozen column scrolls over it. NOT group-header
1996
+ * rows or the pivot grid's aggregate rows: those have no `row` object to pass. Skeleton rows shown
1997
+ * while `loading` are untouched.
1998
+ */
1999
+ getRowStyle?: (row: T, index: number) => React.CSSProperties | undefined;
2000
+ /**
2001
+ * #481: a class on the row's `<tr>`, appended to `twc-dt__row` (never replacing it). Same
2002
+ * `(row, index)` signature as {@link getRowStyle}.
2003
+ *
2004
+ * **Which to reach for.** `getRowStyle` is the default: its *background* does not land inline on the
2005
+ * cells — it is routed through `--twc-dt-row-bg` and read by the `(0,1,0)` base rule, so it is the
2006
+ * **lowest** layer and every built-in state covers it, which is almost always what a row tint should
2007
+ * do. (Its *non-background* declarations — opacity, font-weight, text-decoration — are ordinary
2008
+ * inline styles on the `<tr>` and do win.) Reach for `getRowClassName` when you deliberately want the
2009
+ * tint to **outrank** those cues, since your own rule picks its specificity: beat `(0,3,0)`, e.g.
2010
+ * `tr.twc-dt__row.my-row .twc-dt__td`. You are then choosing to cover the hover cue on those rows.
2011
+ */
2012
+ getRowClassName?: (row: T, index: number) => string | undefined;
1954
2013
  /** Restrict the toolbar quick-search to these column `field`s (client mode); defaults to every
1955
2014
  * visible column. Mirrors `runDatatableQuery`'s `options.searchFields`. */
1956
2015
  searchFields?: string[];
package/dist/index.d.ts CHANGED
@@ -1951,6 +1951,65 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
1951
1951
  * This prop is the initial state — when enabled, users can hide/show the column from the toolbar's
1952
1952
  * **Columns** panel ("Row number"). @default false */
1953
1953
  rowNumbers?: boolean;
1954
+ /**
1955
+ * #481: style a whole row from its own state — the row-level counterpart to a column's `cellStyle`.
1956
+ * Without it, marking a row meant assigning `cellStyle` to **every** column: O(columns) for a
1957
+ * row-level fact, hand-composed against whatever else already used `cellStyle`, and with no fixed
1958
+ * column list to decorate at all when the columns come from a schema.
1959
+ *
1960
+ * Called `(row, index)`, the same shape as `rowKey`. **`index` is the row's 0-based position among
1961
+ * the rows currently rendered** — after sorting and filtering, and **within the current page**. It is
1962
+ * therefore *not* the number the `rowNumbers` column shows, which continues across pages; if you need
1963
+ * an absolute position, read it off `row` rather than from this argument.
1964
+ *
1965
+ * A `background` (or `backgroundColor`) is forwarded to the row's CELLS through the `--twc-dt-row-bg`
1966
+ * custom property, because `.twc-dt__td` paints an opaque surface of its own — without that it would
1967
+ * be invisible — and is **removed** from what reaches the `<tr>`, since a row box paints below its
1968
+ * cells and a leftover copy there would composite with the tint rather than hide behind it. Every
1969
+ * other declaration lands on the `<tr>`, except `border` (ignored on row boxes under
1970
+ * `border-collapse: separate`) and `backgroundImage` (painted under the cells' opaque surface) — both
1971
+ * need {@link getRowClassName} and a `… .twc-dt__td` rule. Sticky positioning and measured row height
1972
+ * are applied after yours, so a hook cannot break row pinning or row resizing.
1973
+ *
1974
+ * **Layering — one rule, not a bespoke order:** the row tint is the **bottom** layer above the
1975
+ * cell's plain surface, and **every** built-in state background covers it. The base `.twc-dt__td`
1976
+ * rule is the lowest-specificity background in the component, so hover, row selection,
1977
+ * `activeRowId`, a pinned row, a grabbed row, the diff add/remove/modify washes, cell
1978
+ * selection/active and inline editing all outrank it — and an inline per-cell `cellStyle` outranks
1979
+ * those. A row tint is a *data-derived* wash; nothing data-derived should be able to hide an
1980
+ * interaction state. So selection still reads on a tinted row, hover feedback is never lost, and a
1981
+ * per-cell state wins with nothing to compose on your side.
1982
+ *
1983
+ * Need a tint that survives hover? Use {@link getRowClassName} with a rule outranking `(0,3,0)` —
1984
+ * note `.twc-dt__row.my-row .twc-dt__td` is itself `(0,3,0)`, a tie decided by source order, so add
1985
+ * an element: `tr.twc-dt__row.my-row .twc-dt__td` is `(0,3,1)`, and `… .twc-dt__td[data-pin]` is
1986
+ * `(0,4,1)` for the pinned-column twins. You are then choosing to cover the hover cue on those rows.
1987
+ *
1988
+ * **Stripes:** there are none to layer against. Datatable does not zebra-stripe its data rows —
1989
+ * the only `data-zebra` rules in the component style the PIVOT grid's cells, and the hook does not
1990
+ * apply to pivot rows. So a row tint never has to compete with a stripe.
1991
+ *
1992
+ * **Which rows:** every data row. That includes rows pinned with the row ⋮ menu (the hook runs and
1993
+ * the class/non-background declarations apply, though the pinned-row highlight covers a background
1994
+ * tint for as long as the row is pinned, exactly like selection), and cells in a pinned COLUMN pick
1995
+ * the tint up, so a tinted row shows no hole where a frozen column scrolls over it. NOT group-header
1996
+ * rows or the pivot grid's aggregate rows: those have no `row` object to pass. Skeleton rows shown
1997
+ * while `loading` are untouched.
1998
+ */
1999
+ getRowStyle?: (row: T, index: number) => React.CSSProperties | undefined;
2000
+ /**
2001
+ * #481: a class on the row's `<tr>`, appended to `twc-dt__row` (never replacing it). Same
2002
+ * `(row, index)` signature as {@link getRowStyle}.
2003
+ *
2004
+ * **Which to reach for.** `getRowStyle` is the default: its *background* does not land inline on the
2005
+ * cells — it is routed through `--twc-dt-row-bg` and read by the `(0,1,0)` base rule, so it is the
2006
+ * **lowest** layer and every built-in state covers it, which is almost always what a row tint should
2007
+ * do. (Its *non-background* declarations — opacity, font-weight, text-decoration — are ordinary
2008
+ * inline styles on the `<tr>` and do win.) Reach for `getRowClassName` when you deliberately want the
2009
+ * tint to **outrank** those cues, since your own rule picks its specificity: beat `(0,3,0)`, e.g.
2010
+ * `tr.twc-dt__row.my-row .twc-dt__td`. You are then choosing to cover the hover cue on those rows.
2011
+ */
2012
+ getRowClassName?: (row: T, index: number) => string | undefined;
1954
2013
  /** Restrict the toolbar quick-search to these column `field`s (client mode); defaults to every
1955
2014
  * visible column. Mirrors `runDatatableQuery`'s `options.searchFields`. */
1956
2015
  searchFields?: string[];
package/dist/index.mjs CHANGED
@@ -9231,8 +9231,22 @@ var DT_CSS = `
9231
9231
  .twc-dt__row:hover .twc-dt__row-resizer::after { background: var(--color-border-strong); }
9232
9232
  .twc-dt__row-resizer:hover::after { background: var(--color-primary); }
9233
9233
 
9234
+ /* #481: the cell background reads --twc-dt-row-bg, which getRowStyle sets on the <tr>. It has to come
9235
+ through a custom property rather than straight off the row, because this rule paints an OPAQUE
9236
+ --color-surface on every cell: a background set on the <tr> would sit behind it and never show,
9237
+ which would make the commonest use of a row-style hook silently do nothing. Cells in a pinned
9238
+ COLUMN inherit it too, so a tinted row does not develop a hole where a sticky column scrolls over
9239
+ it.
9240
+ Layering: this rule is (0,1,0), the LOWEST specificity of any background in this sheet, so the
9241
+ row tint is the bottom layer above the plain surface and every built-in state covers it - hover,
9242
+ row selection, data-active, data-pinned-row, data-row-grabbed, the diff data-op washes, cell
9243
+ selection/active, inline editing (each (0,3,0), (0,4,0) for the pinned-column twins, or (0,2,0)
9244
+ for the cell-level ones) - and an inline per-cell cellStyle
9245
+ covers them all. That is the intended rule, not an accident of ordering: a row tint is a
9246
+ data-derived wash, and no data wash should be able to hide an interaction state. Consumers who
9247
+ need a tint that outranks those use getRowClassName and a rule of their own. */
9234
9248
  .twc-dt__td { padding: 0 12px; height: var(--_rowh, 44px); border-bottom: var(--border-thin) solid var(--color-divider);
9235
- font-size: var(--text-sm); color: var(--color-text); background: var(--color-surface);
9249
+ font-size: var(--text-sm); color: var(--color-text); background: var(--twc-dt-row-bg, var(--color-surface));
9236
9250
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; max-width: 0; }
9237
9251
  /* Wrap-text columns: content flows onto multiple lines (the row grows down) instead of
9238
9252
  clipping to one line. height stays a per-row minimum, so single-line cells are unchanged. */
@@ -9999,6 +10013,8 @@ function Datatable({
9999
10013
  onColumnVisibilityChange,
10000
10014
  batchActions = [],
10001
10015
  onRowSelectionChange,
10016
+ getRowStyle,
10017
+ getRowClassName,
10002
10018
  showExport = false,
10003
10019
  showDensity = false,
10004
10020
  showPivot = false,
@@ -12574,7 +12590,17 @@ function Datatable({
12574
12590
  const rowActive = selectionMode === "row" && activeRowVal === k;
12575
12591
  const stickyStyle = pinSide === "top" ? { position: "sticky", top: headH, zIndex: 5 } : pinSide === "bottom" ? { position: "sticky", bottom: 0, zIndex: 5 } : void 0;
12576
12592
  const h = rowHeights[k];
12577
- const rowStyle = { ...stickyStyle || {}, ...h ? { height: h } : {} };
12593
+ const userRowStyle = getRowStyle ? getRowStyle(row, ri) : void 0;
12594
+ const userRowClass = getRowClassName ? getRowClassName(row, ri) : void 0;
12595
+ const { background: _rowBgShorthand, backgroundColor: _rowBgColor, ...restRowStyle } = userRowStyle || {};
12596
+ const usable = (v) => typeof v === "string" && v.trim() !== "" ? v : void 0;
12597
+ const rowBg = usable(_rowBgShorthand) ?? usable(_rowBgColor);
12598
+ const rowStyle = {
12599
+ ...restRowStyle,
12600
+ ...rowBg != null ? { "--twc-dt-row-bg": rowBg } : {},
12601
+ ...stickyStyle || {},
12602
+ ...h ? { height: h } : {}
12603
+ };
12578
12604
  const reorderable = canReorderRows && !pinSide;
12579
12605
  const grabbed = rowGrab && rowGrab.key === k;
12580
12606
  const grabTarget = rowGrab && !grabbed && midIdx != null && rowGrab.index === midIdx ? rowGrab.index >= keyIndexMid.get(rowGrab.key) ? "after" : "before" : void 0;
@@ -12582,7 +12608,7 @@ function Datatable({
12582
12608
  /* @__PURE__ */ jsxs(
12583
12609
  "tr",
12584
12610
  {
12585
- className: "twc-dt__row",
12611
+ className: userRowClass ? `twc-dt__row ${userRowClass}` : "twc-dt__row",
12586
12612
  role: "row",
12587
12613
  "aria-rowindex": treeSeqByKey ? treeSeqByKey.get(k) + 2 : (paginated && !serverMode ? pageVal * sizeVal : 0) + ri + 2,
12588
12614
  "aria-selected": (checkboxSelection ? sel : rowActive) || void 0,