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 +8 -0
- package/dist/index.cjs +49 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +49 -12
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/styles/twico-ui.css +7 -2
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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
|
-
|
|
8531
|
-
|
|
8532
|
-
.twc-
|
|
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-
|
|
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-
|
|
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-
|
|
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: [
|