twico-ui 1.17.0 → 1.17.2

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 CHANGED
@@ -2,6 +2,20 @@
2
2
 
3
3
  All notable changes to Twico UI are documented here (newest first). This file is generated automatically on each release by [semantic-release](https://semantic-release.gitbook.io/) from [Conventional Commits](https://www.conventionalcommits.org/) — do not edit it by hand. The same notes appear on each [GitHub Release](https://github.com/EncryptionL/twico-ui/releases).
4
4
 
5
+ ## [1.17.2](https://github.com/EncryptionL/twico-ui/compare/v1.17.1...v1.17.2) (2026-07-17)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **datatable:** clamp footer range + title on truncated cells/headers ([#252](https://github.com/EncryptionL/twico-ui/issues/252), [#253](https://github.com/EncryptionL/twico-ui/issues/253)) ([21a023e](https://github.com/EncryptionL/twico-ui/commit/21a023eb20aa8d05b5413ea752c18e32e15a03dc))
11
+
12
+ ## [1.17.1](https://github.com/EncryptionL/twico-ui/compare/v1.17.0...v1.17.1) (2026-07-15)
13
+
14
+
15
+ ### Bug Fixes
16
+
17
+ * **datatable:** batch editor survives portaled dropdowns + stands alone ([#249](https://github.com/EncryptionL/twico-ui/issues/249), [#250](https://github.com/EncryptionL/twico-ui/issues/250)) ([1b5ad91](https://github.com/EncryptionL/twico-ui/commit/1b5ad916f3a61e34f339a5a51e21bff06680cf62)), closes [#244](https://github.com/EncryptionL/twico-ui/issues/244) [#247](https://github.com/EncryptionL/twico-ui/issues/247) [#244](https://github.com/EncryptionL/twico-ui/issues/244)
18
+
5
19
  # [1.17.0](https://github.com/EncryptionL/twico-ui/compare/v1.16.0...v1.17.0) (2026-07-15)
6
20
 
7
21
 
package/dist/index.cjs CHANGED
@@ -10059,6 +10059,7 @@ function Datatable({
10059
10059
  [cols, editMode, batchEditKey]
10060
10060
  // eslint-disable-line react-hooks/exhaustive-deps
10061
10061
  );
10062
+ const hasBatchEditor = showBatchEdit && batchEditableCols.length > 0;
10062
10063
  const [batchEdit, setBatchEdit] = React51__namespace.default.useState(null);
10063
10064
  const [batchEditPos, openBatchEdit, closeBatchEdit] = useFloating();
10064
10065
  function openBatchEditor(el) {
@@ -10072,7 +10073,7 @@ function Datatable({
10072
10073
  closeBatchEdit();
10073
10074
  };
10074
10075
  const onDown = (e) => {
10075
- if (!e.target.closest(".twc-dt__pop") && !e.target.closest(".twc-dt__batch")) close();
10076
+ if (!e.target.closest(".twc-dt__pop") && !e.target.closest(".twc-dt__batch") && !e.target.closest(".twc-pop")) close();
10076
10077
  };
10077
10078
  const onKey = (e) => {
10078
10079
  if (e.key === "Escape") close();
@@ -10327,6 +10328,8 @@ function Datatable({
10327
10328
  const editable = isColEditable(c);
10328
10329
  const isEditing = editing && editing.key === k && editing.field === c.field;
10329
10330
  const cellActive = selectionMode === "cell" && activeCell && activeCell.key === k && activeCell.field === c.field;
10331
+ const display = c.valueFormatter ? c.valueFormatter(val, row) : val;
10332
+ const cellTitle = !isActions && !c.renderCell && !isEditing && (typeof display === "string" || typeof display === "number") ? String(display) : void 0;
10330
10333
  return /* @__PURE__ */ jsxRuntime.jsxs(
10331
10334
  "td",
10332
10335
  {
@@ -10345,14 +10348,14 @@ function Datatable({
10345
10348
  "data-pin": st.pin,
10346
10349
  "data-pin-edge": st.edge,
10347
10350
  style: { width: widthOf(c), ...st.style },
10348
- title: isActions || c.renderCell || editable ? void 0 : String(val ?? ""),
10351
+ title: cellTitle,
10349
10352
  onClick: selectionMode === "cell" ? (e) => handleCellClick(e, k, row, c) : void 0,
10350
10353
  onFocus: () => setFocus((f) => f.r === ri && f.c === ci ? f : { r: ri, c: ci }),
10351
10354
  onDoubleClick: editable ? () => beginEdit(k, c, row) : void 0,
10352
10355
  children: [
10353
10356
  !checkboxSelection && reorderable && ci === 0 && !isEditing ? /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { display: "inline-flex", alignItems: "center", gap: 6, maxWidth: "100%" }, children: [
10354
10357
  rowHandle(k, midIdx, row),
10355
- /* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : c.valueFormatter ? c.valueFormatter(val, row) : val })
10358
+ /* @__PURE__ */ jsxRuntime.jsx("span", { style: { overflow: "hidden", textOverflow: "ellipsis" }, children: isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display })
10356
10359
  ] }) : isEditing ? c.renderEditCell ? (
10357
10360
  // #236: full escape hatch — the host drops in its own editor (searchable/creatable/
10358
10361
  // async Combobox, …) and drives the lifecycle via commit/cancel. Wrapped in
@@ -10371,7 +10374,7 @@ function Datatable({
10371
10374
  onCancel: cancelEdit,
10372
10375
  onKeyDown: onEditKey
10373
10376
  }
10374
- ) : isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : c.valueFormatter ? c.valueFormatter(val, row) : val,
10377
+ ) : isActions ? renderActions(c, row) : c.renderCell ? c.renderCell(val, row) : display,
10375
10378
  editable && !isEditing ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__edit-hint", "aria-hidden": "true", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.pencil }) }) : null
10376
10379
  ]
10377
10380
  },
@@ -10485,14 +10488,14 @@ function Datatable({
10485
10488
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `twc-dt ${className}`, ref: rootRef, "data-density": density, "data-resizing": resizing || void 0, ...rest, children: [
10486
10489
  __twcStyles,
10487
10490
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__toolbar", "data-compact": compact || void 0, children: [
10488
- batchActions.length && selected.size > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__batch", children: [
10491
+ (batchActions.length || hasBatchEditor) && selected.size > 0 ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__batch", children: [
10489
10492
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__batch-x", onClick: clearSelection, "aria-label": "Clear selection", children: /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.x }) }),
10490
10493
  /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "twc-dt__batch-count", children: [
10491
10494
  selected.size,
10492
10495
  " selected"
10493
10496
  ] }),
10494
10497
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__batch-actions", children: [
10495
- showBatchEdit && batchEditableCols.length ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-dt__batch-btn", onClick: (e) => openBatchEditor(e.currentTarget), children: [
10498
+ hasBatchEditor ? /* @__PURE__ */ jsxRuntime.jsxs("button", { type: "button", className: "twc-dt__batch-btn", onClick: (e) => openBatchEditor(e.currentTarget), children: [
10496
10499
  /* @__PURE__ */ jsxRuntime.jsx(Svg, { d: I.pencil }),
10497
10500
  "Edit"
10498
10501
  ] }) : null,
@@ -10787,6 +10790,7 @@ function Datatable({
10787
10790
  className: "twc-dt__th-label",
10788
10791
  role: c.sortable ? "button" : void 0,
10789
10792
  tabIndex: c.sortable ? 0 : void 0,
10793
+ title: typeof c.headerName === "string" ? c.headerName : void 0,
10790
10794
  "aria-label": c.sortable ? `${c.headerName}, sort` : void 0,
10791
10795
  draggable: reorderable || void 0,
10792
10796
  onDragStart: reorderable ? (e) => {
@@ -10918,8 +10922,8 @@ function Datatable({
10918
10922
  const nf = (n) => n.toLocaleString();
10919
10923
  if (totalRows === 0) return "No rows";
10920
10924
  const shown = paged.length;
10921
- const start = paginated ? pageVal * sizeVal + 1 : 1;
10922
- const end = paginated ? start + shown - 1 : shown;
10925
+ const start = paginated ? Math.min(pageVal * sizeVal + 1, totalRows) : 1;
10926
+ const end = paginated ? Math.min(start + shown - 1, totalRows) : shown;
10923
10927
  return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10924
10928
  paginated ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
10925
10929
  "Showing ",