twico-ui 1.31.0 → 1.31.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 CHANGED
@@ -2,6 +2,13 @@
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.31.1](https://github.com/EncryptionL/twico-ui/compare/v1.31.0...v1.31.1) (2026-08-04)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **datatable:** make the filter And/Or connector a resizable field (no more truncation) ([15698fd](https://github.com/EncryptionL/twico-ui/commit/15698fdee0191e178cfb0a65cb08775c25d20b91)), closes [#289](https://github.com/EncryptionL/twico-ui/issues/289) [#292](https://github.com/EncryptionL/twico-ui/issues/292)
11
+
5
12
  # [1.31.0](https://github.com/EncryptionL/twico-ui/compare/v1.30.0...v1.31.0) (2026-08-04)
6
13
 
7
14
 
package/dist/index.cjs CHANGED
@@ -8212,7 +8212,6 @@ function classifyDiff(from = [], to = [], columns = [], rowKey, opts = {}) {
8212
8212
  return { rows, counts };
8213
8213
  }
8214
8214
  var DT_FILTER_PANEL_W = 620;
8215
- var DT_FILTER_LOGIC_W = 68;
8216
8215
  var DT_CSS = `
8217
8216
  .twc-dt { display: flex; flex-direction: column; font-family: var(--font-sans); color: var(--color-text);
8218
8217
  border: var(--border-thin) solid var(--color-border); border-radius: var(--radius-lg);
@@ -8637,8 +8636,11 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
8637
8636
  .twc-dt__link:hover { background: var(--color-primary-subtle); }
8638
8637
  /* #330: MUI DataGrid-style per-row And/Or connector. Row 1 shows a static "Where"; the first connector
8639
8638
  row (row 2) hosts an editable And/Or Select bound to the single filterLogic; rows 3+ echo it as static
8640
- text. Fixed-width leading cell so the Column/Operator/Value cells stay aligned across rows. */
8641
- .twc-dt__f-logic { position: relative; flex: none; width: 68px; }
8639
+ text. Leading cell aligns the Column/Operator/Value cells across rows. It is a first-class resizable
8640
+ filter field like col/op: auto-fit to its content (-fit, from the #289 measurer) with a user drag tier
8641
+ (-usr) winning in the clamp cascade, so it no longer truncates and the width can be adjusted manually. */
8642
+ .twc-dt__f-logic { position: relative; flex: none; min-width: 84px;
8643
+ width: clamp(84px, var(--twc-dt-flogic-usr, var(--twc-dt-flogic-fit, 84px)), var(--twc-dt-flogic-cap, 180px)); }
8642
8644
  .twc-dt__f-where { display: inline-flex; align-items: center; height: 38px; padding-inline: 6px; color: var(--color-text-muted); font-size: var(--text-sm); font-weight: var(--font-medium); }
8643
8645
 
8644
8646
  /* Filter panel \u2014 user-resizable (#292): panel size + per-field widths resolve through a two-tier CSS var
@@ -9452,7 +9454,7 @@ function Datatable({
9452
9454
  density,
9453
9455
  // #292: additive, optional — user-resized filter panel + field widths (panel-global, not per column).
9454
9456
  filterPanelSize: fPanelSize || void 0,
9455
- filterFieldWidths: fWidths.col != null || fWidths.op != null || fWidths.val != null ? fWidths : void 0,
9457
+ filterFieldWidths: fWidths.col != null || fWidths.op != null || fWidths.val != null || fWidths.logic != null ? fWidths : void 0,
9456
9458
  // #304: additive, optional — user-resized sizes of the other toolbar popovers, keyed by popover id.
9457
9459
  popoverSizes: Object.keys(popSizes).length ? popSizes : void 0
9458
9460
  });
@@ -9482,7 +9484,7 @@ function Datatable({
9482
9484
  if (s.density === "compact" || s.density === "standard" || s.density === "comfortable") setDensity(s.density);
9483
9485
  if (s.filterFieldWidths && typeof s.filterFieldWidths === "object") {
9484
9486
  const fw = {};
9485
- for (const k of ["col", "op", "val"]) if (typeof s.filterFieldWidths[k] === "number") fw[k] = s.filterFieldWidths[k];
9487
+ for (const k of ["col", "op", "val", "logic"]) if (typeof s.filterFieldWidths[k] === "number") fw[k] = s.filterFieldWidths[k];
9486
9488
  if (Object.keys(fw).length) setFWidths(fw);
9487
9489
  }
9488
9490
  if (s.filterPanelSize && typeof s.filterPanelSize === "object") {
@@ -10853,9 +10855,11 @@ function Datatable({
10853
10855
  const pad2 = trigger ? (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0) : 24;
10854
10856
  const chrome = pad2 + 8 + 16 + 4;
10855
10857
  const widest = (labels) => labels.reduce((m, l) => Math.max(m, ctx.measureText(String(l)).width), 0);
10856
- const colCap = Math.max(118, Math.min(210, el.clientWidth - DT_FILTER_LOGIC_W - 118 - 30 - 30 - 140 - 5 * 6 - 2 * 4));
10858
+ const logicW = Math.min(180, Math.max(84, Math.ceil(widest(["And", "Or"]) + chrome)));
10859
+ const colCap = Math.max(118, Math.min(210, el.clientWidth - logicW - 118 - 30 - 30 - 140 - 5 * 6 - 2 * 4));
10857
10860
  const colW = Math.min(colCap, Math.max(118, Math.ceil(widest(filterableCols.map((c) => c.headerName ?? c.field)) + chrome)));
10858
10861
  const opW = Math.min(170, Math.max(118, Math.ceil(widest(ALL_OP_LABELS) + chrome)));
10862
+ if (Number.isFinite(logicW)) el.style.setProperty("--twc-dt-flogic-fit", `${logicW}px`);
10859
10863
  if (Number.isFinite(colW)) el.style.setProperty("--twc-dt-fcol-fit", `${colW}px`);
10860
10864
  if (Number.isFinite(opW)) el.style.setProperty("--twc-dt-fop-fit", `${opW}px`);
10861
10865
  };
@@ -10869,10 +10873,10 @@ function Datatable({
10869
10873
  }
10870
10874
  return () => ro?.disconnect();
10871
10875
  }, [panel, filterableCols, filters.length]);
10872
- const F_MIN = { col: 118, op: 118, val: 140 };
10873
- const F_VAR = { col: "--twc-dt-fcol-usr", op: "--twc-dt-fop-usr", val: "--twc-dt-fval-usr" };
10874
- const F_SEL = { col: ".twc-dt__f-col", op: ".twc-dt__f-op", val: ".twc-dt__f-val" };
10875
- const F_LABEL = { col: "column", op: "operator", val: "value" };
10876
+ const F_MIN = { col: 118, op: 118, val: 140, logic: 84 };
10877
+ const F_VAR = { col: "--twc-dt-fcol-usr", op: "--twc-dt-fop-usr", val: "--twc-dt-fval-usr", logic: "--twc-dt-flogic-usr" };
10878
+ const F_SEL = { col: ".twc-dt__f-col", op: ".twc-dt__f-op", val: ".twc-dt__f-val", logic: ".twc-dt__f-logic" };
10879
+ const F_LABEL = { col: "column", op: "operator", val: "value", logic: "connector" };
10876
10880
  const fMaxW = () => typeof window === "undefined" ? 9999 : window.innerWidth - 32;
10877
10881
  const fMaxH = () => typeof window === "undefined" ? 9999 : window.innerHeight - 32;
10878
10882
  const clampNum = (v, lo, hi) => Math.max(lo, Math.min(hi, Math.round(v)));
@@ -10881,11 +10885,12 @@ function Datatable({
10881
10885
  return el ? el.getBoundingClientRect().width : F_MIN[field];
10882
10886
  };
10883
10887
  const fCap = (field) => {
10888
+ if (field === "logic") return 180;
10884
10889
  if (field === "col") return filterFieldMaxWidth || 360;
10885
10890
  if (field === "op") return filterFieldMaxWidth || 260;
10886
10891
  const p = filterPanelRef.current;
10887
10892
  if (!p) return 640;
10888
- return clampNum(p.clientWidth - DT_FILTER_LOGIC_W - fLiveW("col") - fLiveW("op") - 30 - 30 - 5 * 6 - 2 * 4, F_MIN.val, 640);
10893
+ return clampNum(p.clientWidth - fLiveW("logic") - fLiveW("col") - fLiveW("op") - 30 - 30 - 5 * 6 - 2 * 4, F_MIN.val, 640);
10889
10894
  };
10890
10895
  const isRtl = () => {
10891
10896
  const p = filterPanelRef.current;
@@ -11018,12 +11023,12 @@ function Datatable({
11018
11023
  setFPanelSize(null);
11019
11024
  const p = filterPanelRef.current;
11020
11025
  if (p) {
11021
- ["--twc-dt-fcol-usr", "--twc-dt-fop-usr", "--twc-dt-fval-usr", "--twc-dt-panel-w", "--twc-dt-panel-h"].forEach((v) => p.style.removeProperty(v));
11026
+ ["--twc-dt-fcol-usr", "--twc-dt-fop-usr", "--twc-dt-fval-usr", "--twc-dt-flogic-usr", "--twc-dt-panel-w", "--twc-dt-panel-h"].forEach((v) => p.style.removeProperty(v));
11022
11027
  p.removeAttribute("data-val-fixed");
11023
11028
  p.removeAttribute("data-panel-sized");
11024
11029
  }
11025
11030
  };
11026
- const hasFilterSizeOverride = fWidths.col != null || fWidths.op != null || fWidths.val != null || fPanelSize != null;
11031
+ const hasFilterSizeOverride = fWidths.col != null || fWidths.op != null || fWidths.val != null || fWidths.logic != null || fPanelSize != null;
11027
11032
  const POP_MIN_W = { columns: 240, agg: 240, pivot: 260, batchedit: 260 };
11028
11033
  const popMinW = (id) => POP_MIN_W[id] || 200;
11029
11034
  const clearPop = (id, node) => {
@@ -12573,6 +12578,7 @@ function Datatable({
12573
12578
  "--twc-dt-fcol-usr": fWidths.col != null ? `${fWidths.col}px` : void 0,
12574
12579
  "--twc-dt-fop-usr": fWidths.op != null ? `${fWidths.op}px` : void 0,
12575
12580
  "--twc-dt-fval-usr": fWidths.val != null ? `${fWidths.val}px` : void 0,
12581
+ "--twc-dt-flogic-usr": fWidths.logic != null ? `${fWidths.logic}px` : void 0,
12576
12582
  "--twc-dt-panel-w": fPanelSize?.w != null ? `${fPanelSize.w}px` : void 0,
12577
12583
  "--twc-dt-panel-h": fPanelSize?.h != null ? `${fPanelSize.h}px` : void 0,
12578
12584
  "--twc-dt-fcol-cap": filterFieldMaxWidth ? `${filterFieldMaxWidth}px` : void 0,
@@ -12593,17 +12599,20 @@ function Datatable({
12593
12599
  const ops = opsFor(filterTypeOf(col));
12594
12600
  const op = ops.find((o) => o.value === f.op) || ops[0];
12595
12601
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__frow", children: [
12596
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__f-logic", children: i === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__f-where", children: "Where" }) : i === 1 ? /* @__PURE__ */ jsxRuntime.jsx(
12597
- Select,
12598
- {
12599
- size: "sm",
12600
- portal: true,
12601
- "aria-label": "Combine with the other filters",
12602
- value: filterLogic,
12603
- options: [{ value: "and", label: "And" }, { value: "or", label: "Or" }],
12604
- onChange: (v) => setFilterLogic(v)
12605
- }
12606
- ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__f-where", children: filterLogic === "or" ? "Or" : "And" }) }),
12602
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__f-logic", children: [
12603
+ i === 0 ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__f-where", children: "Where" }) : i === 1 ? /* @__PURE__ */ jsxRuntime.jsx(
12604
+ Select,
12605
+ {
12606
+ size: "sm",
12607
+ portal: true,
12608
+ "aria-label": "Combine with the other filters",
12609
+ value: filterLogic,
12610
+ options: [{ value: "and", label: "And" }, { value: "or", label: "Or" }],
12611
+ onChange: (v) => setFilterLogic(v)
12612
+ }
12613
+ ) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__f-where", children: filterLogic === "or" ? "Or" : "And" }),
12614
+ fieldHandle("logic", i)
12615
+ ] }),
12607
12616
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__f-col", children: [
12608
12617
  /* @__PURE__ */ jsxRuntime.jsx(
12609
12618
  Select,