twico-ui 1.21.0 → 1.21.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,14 @@
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.21.1](https://github.com/EncryptionL/twico-ui/compare/v1.21.0...v1.21.1) (2026-07-29)
6
+
7
+
8
+ ### Bug Fixes
9
+
10
+ * **datatable:** auto-fit filter panel field widths to the widest label ([29ca74c](https://github.com/EncryptionL/twico-ui/commit/29ca74cd89fde500ca024f574488a59feaa87ee0)), closes [#289](https://github.com/EncryptionL/twico-ui/issues/289)
11
+ * **overlay:** stack tooltips below toasts, and dropdowns above ([7236003](https://github.com/EncryptionL/twico-ui/commit/7236003bbf97f73b7440abd89b39aa846b02edc1)), closes [#288](https://github.com/EncryptionL/twico-ui/issues/288)
12
+
5
13
  # [1.21.0](https://github.com/EncryptionL/twico-ui/compare/v1.20.2...v1.21.0) (2026-07-28)
6
14
 
7
15
 
package/dist/index.cjs CHANGED
@@ -5488,7 +5488,7 @@ function ColorPicker({
5488
5488
  role: "dialog",
5489
5489
  "aria-modal": "true",
5490
5490
  "aria-label": "Color picker",
5491
- style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
5491
+ style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
5492
5492
  children: [
5493
5493
  /* @__PURE__ */ jsxRuntime.jsxs(
5494
5494
  "div",
@@ -5966,7 +5966,7 @@ function Combobox({
5966
5966
  role: "listbox",
5967
5967
  ref: popRef,
5968
5968
  "data-placement": coords.flip ? "top" : "bottom",
5969
- style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
5969
+ style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-floating)" },
5970
5970
  children: popInner
5971
5971
  }
5972
5972
  ),
@@ -6853,7 +6853,7 @@ function Select({
6853
6853
  ref: popRef,
6854
6854
  "data-state": popState,
6855
6855
  "data-placement": coords.flip ? "top" : "bottom",
6856
- style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, minWidth: coords.minWidth, maxWidth: coords.maxWidth, right: "auto", zIndex: "var(--z-tooltip)" },
6856
+ style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, minWidth: coords.minWidth, maxWidth: coords.maxWidth, right: "auto", zIndex: "var(--z-floating)" },
6857
6857
  children: popInner
6858
6858
  }
6859
6859
  ),
@@ -7620,7 +7620,7 @@ function MultiSelect({
7620
7620
  className: "twc-pop twc-pop--portal",
7621
7621
  ref: popRef,
7622
7622
  "data-placement": coords.flip ? "top" : "bottom",
7623
- style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-tooltip)" },
7623
+ style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-floating)" },
7624
7624
  children: popInner
7625
7625
  }
7626
7626
  ),
@@ -8527,9 +8527,14 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
8527
8527
 
8528
8528
  /* Filter panel */
8529
8529
  .twc-dt__filters { width: 580px; max-width: calc(100vw - 32px); }
8530
- .twc-dt__frow { display: flex; align-items: center; gap: 6px; padding: 5px 4px; }
8531
- .twc-dt__f-col { width: 118px; flex: none; }
8532
- .twc-dt__f-op { width: 118px; flex: none; }
8530
+ /* #289: wrap is a safety net \u2014 a beyond-cap label or the narrow responsive panel drops the value input
8531
+ to its own line instead of clipping the remove button; no effect in the normal (capped) case. */
8532
+ .twc-dt__frow { display: flex; align-items: center; gap: 6px; padding: 5px 4px; flex-wrap: wrap; }
8533
+ /* #289: column-field auto-fits the widest header label \u2014 JS writes --twc-dt-fcol-w (measured, clamped),
8534
+ the max-width is the hard backstop that keeps the value input above its 140px floor inside the 580px
8535
+ panel even if the var is stale/too large. Fallback 118px = the previous fixed behavior. */
8536
+ .twc-dt__f-col { flex: none; width: var(--twc-dt-fcol-w, 118px); min-width: 118px; max-width: 210px; }
8537
+ .twc-dt__f-op { flex: none; width: var(--twc-dt-fop-w, 118px); min-width: 118px; max-width: 170px; }
8533
8538
  .twc-dt__f-val { flex: 1; min-width: 140px; }
8534
8539
  .twc-dt__frm-x { display: inline-grid; place-items: center; width: 30px; height: 38px; border: none; background: transparent; color: var(--color-text-subtle); border-radius: var(--radius-md); cursor: pointer; flex: none; align-self: flex-start; }
8535
8540
  .twc-dt__frm-x:hover { background: var(--color-danger-subtle); color: var(--color-danger-subtle-fg); }
@@ -8644,6 +8649,7 @@ var NUM_OPS = [
8644
8649
  ];
8645
8650
  var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
8646
8651
  var isMultiOp = (op) => op === "isAnyOf";
8652
+ var ALL_OP_LABELS = [...new Set([...STR_OPS, ...NUM_OPS].map((o) => o.label))];
8647
8653
  var filterTypeOf = (col) => {
8648
8654
  const ft = col && col.filterType;
8649
8655
  if (ft === "number" || ft === "string") return ft;
@@ -9316,6 +9322,8 @@ function Datatable({
9316
9322
  };
9317
9323
  }, []);
9318
9324
  const scrollRef = React51__namespace.default.useRef(null);
9325
+ const filterPanelRef = React51__namespace.default.useRef(null);
9326
+ const measureCanvas = React51__namespace.default.useRef(null);
9319
9327
  const [scrollTop, setScrollTop] = React51__namespace.default.useState(0);
9320
9328
  const [viewportH, setViewportH] = React51__namespace.default.useState(0);
9321
9329
  const [ovTip, setOvTip] = React51__namespace.default.useState(null);
@@ -10349,7 +10357,36 @@ function Datatable({
10349
10357
  ] });
10350
10358
  }
10351
10359
  const tableMinWidth = leadW + ordered.reduce((a, c) => a + widthOf(c), 0);
10352
- const filterableCols = cols.filter((c) => c.filterable);
10360
+ const filterableCols = React51__namespace.default.useMemo(() => cols.filter((c) => c.filterable), [cols]);
10361
+ React51__namespace.default.useEffect(() => {
10362
+ const el = filterPanelRef.current;
10363
+ if (panel !== "filters" || !el || typeof document === "undefined") return void 0;
10364
+ const measure = () => {
10365
+ if (!el.isConnected) return;
10366
+ const trigger = el.querySelector(".twc-sel__trigger");
10367
+ const cs = getComputedStyle(trigger || el);
10368
+ const ctx = (measureCanvas.current || (measureCanvas.current = document.createElement("canvas"))).getContext("2d");
10369
+ if (!ctx) return;
10370
+ ctx.font = cs.font || `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize}/${cs.lineHeight} ${cs.fontFamily}`;
10371
+ const pad2 = trigger ? (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0) : 24;
10372
+ const chrome = pad2 + 8 + 16 + 4;
10373
+ const widest = (labels) => labels.reduce((m, l) => Math.max(m, ctx.measureText(String(l)).width), 0);
10374
+ const colCap = Math.max(118, Math.min(210, el.clientWidth - 118 - 30 - 140 - 3 * 6 - 2 * 4));
10375
+ const colW = Math.min(colCap, Math.max(118, Math.ceil(widest(filterableCols.map((c) => c.headerName ?? c.field)) + chrome)));
10376
+ const opW = Math.min(170, Math.max(118, Math.ceil(widest(ALL_OP_LABELS) + chrome)));
10377
+ if (Number.isFinite(colW)) el.style.setProperty("--twc-dt-fcol-w", `${colW}px`);
10378
+ if (Number.isFinite(opW)) el.style.setProperty("--twc-dt-fop-w", `${opW}px`);
10379
+ };
10380
+ measure();
10381
+ document.fonts?.ready?.then?.(measure).catch?.(() => {
10382
+ });
10383
+ let ro;
10384
+ if (typeof ResizeObserver !== "undefined") {
10385
+ ro = new ResizeObserver(measure);
10386
+ ro.observe(el);
10387
+ }
10388
+ return () => ro?.disconnect();
10389
+ }, [panel, filterableCols, filters.length]);
10353
10390
  const orderIdxOf = (f) => {
10354
10391
  const i = order.indexOf(f);
10355
10392
  return i === -1 ? 9999 : i;
@@ -11719,7 +11756,7 @@ function Datatable({
11719
11756
  ] })
11720
11757
  ] });
11721
11758
  })() : null,
11722
- panel === "filters" && panelPos ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__pop twc-dt__filters", style: { top: panelPos.top, left: panelPos.left }, children: [
11759
+ panel === "filters" && panelPos ? /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: filterPanelRef, className: "twc-dt__pop twc-dt__filters", style: { top: panelPos.top, left: panelPos.left }, children: [
11723
11760
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__panel-head", children: [
11724
11761
  /* @__PURE__ */ jsxRuntime.jsx("span", { className: "twc-dt__panel-title", children: "Filters" }),
11725
11762
  filters.length ? /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setFilters([]), children: "Clear all" }) : null
@@ -12592,7 +12629,7 @@ function DatePicker({
12592
12629
  role: "dialog",
12593
12630
  "aria-modal": "true",
12594
12631
  "aria-label": "Choose date",
12595
- style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
12632
+ style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
12596
12633
  children: [
12597
12634
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dp__head", children: [
12598
12635
  /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-dp__nav", "aria-label": mode === "years" ? "Previous decade" : mode === "months" ? "Previous year" : "Previous month", onClick: () => setView(mode === "years" ? new Date(y - 10, m, 1) : mode === "months" ? new Date(y - 1, m, 1) : new Date(y, m - 1, 1)), children: /* @__PURE__ */ jsxRuntime.jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
@@ -13169,7 +13206,7 @@ function DateRangePicker({
13169
13206
  role: "dialog",
13170
13207
  "aria-modal": "true",
13171
13208
  "aria-label": "Choose date range",
13172
- style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
13209
+ style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
13173
13210
  children: [
13174
13211
  presetItems.length ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-drp__presets", children: presetItems.map((p, i) => /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: "twc-drp__preset", onClick: () => applyPreset(p), children: p.label }, i)) }) : null,
13175
13212
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-drp__cal", children: [
@@ -13698,7 +13735,7 @@ function TimePicker({
13698
13735
  role: "dialog",
13699
13736
  "aria-modal": "true",
13700
13737
  "aria-label": "Choose time",
13701
- style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-tooltip)" },
13738
+ style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
13702
13739
  children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-tp__cols", children: columns.map((col) => {
13703
13740
  const firstTab = col.items.find((it) => it.selected) || col.items.find((it) => !it.disabled);
13704
13741
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-tp__col", role: "listbox", "aria-label": col.aria, "data-col": col.key, children: [