twico-ui 1.19.0 → 1.20.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/CHANGELOG.md +14 -0
- package/dist/index.cjs +24 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +7 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +24 -11
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
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.20.0](https://github.com/EncryptionL/twico-ui/compare/v1.19.1...v1.20.0) (2026-07-23)
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
### Features
|
|
9
|
+
|
|
10
|
+
* **datatable:** add column filterType, decoupling filter operators from the edit type ([68dbb6e](https://github.com/EncryptionL/twico-ui/commit/68dbb6e80cc3e50fd1072eff5fa8cf2415259ef0)), closes [#271](https://github.com/EncryptionL/twico-ui/issues/271) [263/#267](https://github.com/EncryptionL/twico-ui/issues/267) [#269](https://github.com/EncryptionL/twico-ui/issues/269) [#269](https://github.com/EncryptionL/twico-ui/issues/269) [#270](https://github.com/EncryptionL/twico-ui/issues/270) [#271](https://github.com/EncryptionL/twico-ui/issues/271)
|
|
11
|
+
|
|
12
|
+
## [1.19.1](https://github.com/EncryptionL/twico-ui/compare/v1.19.0...v1.19.1) (2026-07-23)
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
### Bug Fixes
|
|
16
|
+
|
|
17
|
+
* **datatable:** scope the column-reorder grab cursor to the header grip ([666401e](https://github.com/EncryptionL/twico-ui/commit/666401e617050700af531af7abbfd0f5d41bf644)), closes [#267](https://github.com/EncryptionL/twico-ui/issues/267)
|
|
18
|
+
|
|
5
19
|
# [1.19.0](https://github.com/EncryptionL/twico-ui/compare/v1.18.2...v1.19.0) (2026-07-23)
|
|
6
20
|
|
|
7
21
|
|
package/dist/index.cjs
CHANGED
|
@@ -6769,6 +6769,7 @@ function Select({
|
|
|
6769
6769
|
"data-disabled": o.disabled || void 0,
|
|
6770
6770
|
"data-selected": isSel || void 0,
|
|
6771
6771
|
"data-active": idx === active || void 0,
|
|
6772
|
+
title: typeof o.label === "string" ? o.label : void 0,
|
|
6772
6773
|
onMouseEnter: () => {
|
|
6773
6774
|
if (!o.disabled) setActive(idx);
|
|
6774
6775
|
},
|
|
@@ -8223,14 +8224,16 @@ var DT_CSS = `
|
|
|
8223
8224
|
.twc-dt__resizer:focus-visible::after { background: var(--color-primary); }
|
|
8224
8225
|
.twc-dt[data-resizing="true"] { cursor: col-resize; user-select: none; }
|
|
8225
8226
|
|
|
8226
|
-
/* Column reorder (drag)
|
|
8227
|
-
|
|
8227
|
+
/* Column reorder (drag) \u2014 the grab affordance lives on the header grip only (#267, the column analog
|
|
8228
|
+
of #263), not the whole header, so a plain hover to read/sort/open the \u22EE menu isn't shown as
|
|
8229
|
+
draggable (the header stays a drag source for the mouse). */
|
|
8228
8230
|
.twc-dt__th[data-dragging="true"] { opacity: 0.45; }
|
|
8229
8231
|
.twc-dt__th[data-dropbefore="true"] .twc-dt__th-inner { box-shadow: inset 3px 0 0 var(--color-primary); }
|
|
8230
8232
|
.twc-dt__th[data-dropafter="true"] .twc-dt__th-inner { box-shadow: inset -3px 0 0 var(--color-primary); }
|
|
8231
|
-
.twc-dt__grip { display: inline-flex; color: var(--color-text-subtle); opacity: 0; margin-inline-end: -2px; transition: opacity var(--duration-fast); flex: none; }
|
|
8233
|
+
.twc-dt__grip { display: inline-flex; color: var(--color-text-subtle); opacity: 0; margin-inline-end: -2px; transition: opacity var(--duration-fast); flex: none; cursor: grab; }
|
|
8232
8234
|
.twc-dt__grip svg { width: 13px; height: 13px; }
|
|
8233
8235
|
.twc-dt__th:hover .twc-dt__grip { opacity: 0.5; }
|
|
8236
|
+
.twc-dt__grip:active, .twc-dt__th[data-dragging="true"] .twc-dt__grip { cursor: grabbing; }
|
|
8234
8237
|
|
|
8235
8238
|
/* Summary / aggregation footer row */
|
|
8236
8239
|
.twc-dt__table tfoot td { position: sticky; bottom: 0; z-index: 3; background: var(--color-surface-sunken);
|
|
@@ -8493,13 +8496,15 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
|
|
|
8493
8496
|
.twc-dt__col-list { max-height: 230px; overflow-y: auto; }
|
|
8494
8497
|
.twc-dt__col-row { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: var(--radius-md); cursor: pointer; }
|
|
8495
8498
|
.twc-dt__col-row:hover { background: var(--color-surface-sunken); }
|
|
8496
|
-
|
|
8499
|
+
/* #271 (columns-panel analog of #263/#267): grab lives on the grip only, not the whole row \u2014 the row
|
|
8500
|
+
keeps its 'cursor: pointer' (toggles visibility) and stays a drag source for the mouse. */
|
|
8497
8501
|
.twc-dt__col-row[data-dragging="true"] { opacity: 0.5; }
|
|
8498
8502
|
.twc-dt__col-row[data-dropbefore="true"] { box-shadow: inset 0 3px 0 var(--color-primary); }
|
|
8499
8503
|
.twc-dt__col-row[data-dropafter="true"] { box-shadow: inset 0 -3px 0 var(--color-primary); }
|
|
8500
|
-
.twc-dt__col-grip { display: inline-flex; color: var(--color-text-subtle); flex: none; opacity: 0.45; }
|
|
8504
|
+
.twc-dt__col-grip { display: inline-flex; color: var(--color-text-subtle); flex: none; opacity: 0.45; cursor: grab; }
|
|
8501
8505
|
.twc-dt__col-row:hover .twc-dt__col-grip { opacity: 0.8; }
|
|
8502
8506
|
.twc-dt__col-grip svg { width: 14px; height: 14px; }
|
|
8507
|
+
.twc-dt__col-grip:active, .twc-dt__col-row[data-dragging="true"] .twc-dt__col-grip { cursor: grabbing; }
|
|
8503
8508
|
.twc-dt__col-name { flex: 1; font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
8504
8509
|
.twc-dt__col-pins { display: inline-flex; gap: 2px; flex: none; }
|
|
8505
8510
|
.twc-dt__col-pin { display: inline-grid; place-items: center; width: 24px; height: 24px; border: none; padding: 0; background: transparent; color: var(--color-text-subtle); cursor: pointer; border-radius: var(--radius-sm); transition: background-color var(--duration-fast), color var(--duration-fast); }
|
|
@@ -8637,6 +8642,11 @@ var NUM_OPS = [
|
|
|
8637
8642
|
];
|
|
8638
8643
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8639
8644
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8645
|
+
var filterTypeOf = (col) => {
|
|
8646
|
+
const ft = col && col.filterType;
|
|
8647
|
+
if (ft === "number" || ft === "string") return ft;
|
|
8648
|
+
return col && col.type === "number" ? "number" : "string";
|
|
8649
|
+
};
|
|
8640
8650
|
var getColVal = (col, row) => col && col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col && col.field];
|
|
8641
8651
|
var diffValueNode = (col, v, row) => col.renderCell ? col.renderCell(v, row) : col.valueFormatter ? col.valueFormatter(v, row) : v == null ? "" : v;
|
|
8642
8652
|
function renderDiffCell(col, val, row) {
|
|
@@ -8719,7 +8729,10 @@ function runDatatableQuery(rows, query, options = {}) {
|
|
|
8719
8729
|
let out = Array.isArray(rows) ? rows : [];
|
|
8720
8730
|
const quick = String(q.quickFilter || "").trim().toLowerCase();
|
|
8721
8731
|
if (quick) out = out.filter((r2) => searchFields.some((f) => String(gv(f, r2) ?? "").toLowerCase().includes(quick)));
|
|
8722
|
-
for (const f of q.filters || [])
|
|
8732
|
+
for (const f of q.filters || []) {
|
|
8733
|
+
const fc = cols.find((c) => c.field === f.field);
|
|
8734
|
+
out = out.filter((r2) => testFilter(gv(f.field, r2), f.op, f.value, filterTypeOf(fc)));
|
|
8735
|
+
}
|
|
8723
8736
|
if (q.sort && q.sort.field) {
|
|
8724
8737
|
const { field, dir } = q.sort, numeric = typeOf(field) === "number";
|
|
8725
8738
|
out = [...out].sort((a, b) => {
|
|
@@ -9537,7 +9550,7 @@ function Datatable({
|
|
|
9537
9550
|
for (const f of filters) {
|
|
9538
9551
|
const col = colByField[f.field];
|
|
9539
9552
|
if (!col) continue;
|
|
9540
|
-
out = out.filter((r2) => testFilter(getColVal(col, r2), f.op, f.value, col
|
|
9553
|
+
out = out.filter((r2) => testFilter(getColVal(col, r2), f.op, f.value, filterTypeOf(col)));
|
|
9541
9554
|
}
|
|
9542
9555
|
if (sort) {
|
|
9543
9556
|
const col = colByField[sort.field];
|
|
@@ -9855,7 +9868,7 @@ function Datatable({
|
|
|
9855
9868
|
}
|
|
9856
9869
|
function addFilter(field) {
|
|
9857
9870
|
const col = colByField[field] || cols[0];
|
|
9858
|
-
setFilters((f) => [...f, { id: Date.now() + Math.random(), field: col.field, op: opsFor(col
|
|
9871
|
+
setFilters((f) => [...f, { id: Date.now() + Math.random(), field: col.field, op: opsFor(filterTypeOf(col))[0].value, value: "" }]);
|
|
9859
9872
|
}
|
|
9860
9873
|
function setPin(field, side) {
|
|
9861
9874
|
setPins((p) => {
|
|
@@ -11670,7 +11683,7 @@ function Datatable({
|
|
|
11670
11683
|
] }),
|
|
11671
11684
|
filters.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__empty", style: { padding: "16px 12px" }, children: "No filters applied" }) : filters.map((f) => {
|
|
11672
11685
|
const col = colByField[f.field] || cols[0];
|
|
11673
|
-
const ops = opsFor(col
|
|
11686
|
+
const ops = opsFor(filterTypeOf(col));
|
|
11674
11687
|
const op = ops.find((o) => o.value === f.op) || ops[0];
|
|
11675
11688
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "twc-dt__frow", children: [
|
|
11676
11689
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "twc-dt__f-col", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -11682,7 +11695,7 @@ function Datatable({
|
|
|
11682
11695
|
options: filterableCols.map((c) => ({ value: c.field, label: c.headerName })),
|
|
11683
11696
|
onChange: (v) => {
|
|
11684
11697
|
const nc = colByField[v];
|
|
11685
|
-
setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, field: v, op: opsFor(nc
|
|
11698
|
+
setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, field: v, op: opsFor(filterTypeOf(nc))[0].value, value: "" } : x));
|
|
11686
11699
|
}
|
|
11687
11700
|
}
|
|
11688
11701
|
) }),
|
|
@@ -11721,7 +11734,7 @@ function Datatable({
|
|
|
11721
11734
|
Input,
|
|
11722
11735
|
{
|
|
11723
11736
|
size: "sm",
|
|
11724
|
-
type: col
|
|
11737
|
+
type: filterTypeOf(col) === "number" ? "number" : "text",
|
|
11725
11738
|
placeholder: "Value",
|
|
11726
11739
|
value: f.value,
|
|
11727
11740
|
onChange: (e) => setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, value: e.target.value } : x))
|