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/dist/index.d.cts
CHANGED
|
@@ -2046,6 +2046,13 @@ interface DatatableColumn<T = any> {
|
|
|
2046
2046
|
headerName?: string;
|
|
2047
2047
|
/** Data type. "actions" renders per-row action buttons via getActions. @default "string" */
|
|
2048
2048
|
type?: "string" | "number" | "actions";
|
|
2049
|
+
/** Filter operators + value comparison for this column, **decoupled from the edit `type`** (#270).
|
|
2050
|
+
* A `"number"` column edits by coercing its commit with `Number()`, which would wipe a custom value
|
|
2051
|
+
* (e.g. a value+unit measurement edited via `renderEditCell`) — so such a column must edit as
|
|
2052
|
+
* `type: "string"`, yet may still want **numeric** filter operators (`=` `≠` `>` `≥` `<` `≤`).
|
|
2053
|
+
* Set `filterType: "number"` to offer them (provide a `valueGetter` returning the numeric value so
|
|
2054
|
+
* the comparison is numeric). Falls back to `type`. Sorting still uses `type`. @default type */
|
|
2055
|
+
filterType?: "string" | "number";
|
|
2049
2056
|
/** Column width: a px number, or `"auto"` to size to the header's intrinsic width (chrome + label) so a short column fits without truncating or wasting the 160px default. @default 160 (120 for actions) */
|
|
2050
2057
|
width?: number | "auto";
|
|
2051
2058
|
/** Lower bound (px) for the resolved width, incl. `"auto"` and user resizes. */
|
package/dist/index.d.ts
CHANGED
|
@@ -2046,6 +2046,13 @@ interface DatatableColumn<T = any> {
|
|
|
2046
2046
|
headerName?: string;
|
|
2047
2047
|
/** Data type. "actions" renders per-row action buttons via getActions. @default "string" */
|
|
2048
2048
|
type?: "string" | "number" | "actions";
|
|
2049
|
+
/** Filter operators + value comparison for this column, **decoupled from the edit `type`** (#270).
|
|
2050
|
+
* A `"number"` column edits by coercing its commit with `Number()`, which would wipe a custom value
|
|
2051
|
+
* (e.g. a value+unit measurement edited via `renderEditCell`) — so such a column must edit as
|
|
2052
|
+
* `type: "string"`, yet may still want **numeric** filter operators (`=` `≠` `>` `≥` `<` `≤`).
|
|
2053
|
+
* Set `filterType: "number"` to offer them (provide a `valueGetter` returning the numeric value so
|
|
2054
|
+
* the comparison is numeric). Falls back to `type`. Sorting still uses `type`. @default type */
|
|
2055
|
+
filterType?: "string" | "number";
|
|
2049
2056
|
/** Column width: a px number, or `"auto"` to size to the header's intrinsic width (chrome + label) so a short column fits without truncating or wasting the 160px default. @default 160 (120 for actions) */
|
|
2050
2057
|
width?: number | "auto";
|
|
2051
2058
|
/** Lower bound (px) for the resolved width, incl. `"auto"` and user resizes. */
|
package/dist/index.mjs
CHANGED
|
@@ -6748,6 +6748,7 @@ function Select({
|
|
|
6748
6748
|
"data-disabled": o.disabled || void 0,
|
|
6749
6749
|
"data-selected": isSel || void 0,
|
|
6750
6750
|
"data-active": idx === active || void 0,
|
|
6751
|
+
title: typeof o.label === "string" ? o.label : void 0,
|
|
6751
6752
|
onMouseEnter: () => {
|
|
6752
6753
|
if (!o.disabled) setActive(idx);
|
|
6753
6754
|
},
|
|
@@ -8202,14 +8203,16 @@ var DT_CSS = `
|
|
|
8202
8203
|
.twc-dt__resizer:focus-visible::after { background: var(--color-primary); }
|
|
8203
8204
|
.twc-dt[data-resizing="true"] { cursor: col-resize; user-select: none; }
|
|
8204
8205
|
|
|
8205
|
-
/* Column reorder (drag)
|
|
8206
|
-
|
|
8206
|
+
/* Column reorder (drag) \u2014 the grab affordance lives on the header grip only (#267, the column analog
|
|
8207
|
+
of #263), not the whole header, so a plain hover to read/sort/open the \u22EE menu isn't shown as
|
|
8208
|
+
draggable (the header stays a drag source for the mouse). */
|
|
8207
8209
|
.twc-dt__th[data-dragging="true"] { opacity: 0.45; }
|
|
8208
8210
|
.twc-dt__th[data-dropbefore="true"] .twc-dt__th-inner { box-shadow: inset 3px 0 0 var(--color-primary); }
|
|
8209
8211
|
.twc-dt__th[data-dropafter="true"] .twc-dt__th-inner { box-shadow: inset -3px 0 0 var(--color-primary); }
|
|
8210
|
-
.twc-dt__grip { display: inline-flex; color: var(--color-text-subtle); opacity: 0; margin-inline-end: -2px; transition: opacity var(--duration-fast); flex: none; }
|
|
8212
|
+
.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; }
|
|
8211
8213
|
.twc-dt__grip svg { width: 13px; height: 13px; }
|
|
8212
8214
|
.twc-dt__th:hover .twc-dt__grip { opacity: 0.5; }
|
|
8215
|
+
.twc-dt__grip:active, .twc-dt__th[data-dragging="true"] .twc-dt__grip { cursor: grabbing; }
|
|
8213
8216
|
|
|
8214
8217
|
/* Summary / aggregation footer row */
|
|
8215
8218
|
.twc-dt__table tfoot td { position: sticky; bottom: 0; z-index: 3; background: var(--color-surface-sunken);
|
|
@@ -8472,13 +8475,15 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
|
|
|
8472
8475
|
.twc-dt__col-list { max-height: 230px; overflow-y: auto; }
|
|
8473
8476
|
.twc-dt__col-row { display: flex; align-items: center; gap: 10px; padding: 7px 8px; border-radius: var(--radius-md); cursor: pointer; }
|
|
8474
8477
|
.twc-dt__col-row:hover { background: var(--color-surface-sunken); }
|
|
8475
|
-
|
|
8478
|
+
/* #271 (columns-panel analog of #263/#267): grab lives on the grip only, not the whole row \u2014 the row
|
|
8479
|
+
keeps its 'cursor: pointer' (toggles visibility) and stays a drag source for the mouse. */
|
|
8476
8480
|
.twc-dt__col-row[data-dragging="true"] { opacity: 0.5; }
|
|
8477
8481
|
.twc-dt__col-row[data-dropbefore="true"] { box-shadow: inset 0 3px 0 var(--color-primary); }
|
|
8478
8482
|
.twc-dt__col-row[data-dropafter="true"] { box-shadow: inset 0 -3px 0 var(--color-primary); }
|
|
8479
|
-
.twc-dt__col-grip { display: inline-flex; color: var(--color-text-subtle); flex: none; opacity: 0.45; }
|
|
8483
|
+
.twc-dt__col-grip { display: inline-flex; color: var(--color-text-subtle); flex: none; opacity: 0.45; cursor: grab; }
|
|
8480
8484
|
.twc-dt__col-row:hover .twc-dt__col-grip { opacity: 0.8; }
|
|
8481
8485
|
.twc-dt__col-grip svg { width: 14px; height: 14px; }
|
|
8486
|
+
.twc-dt__col-grip:active, .twc-dt__col-row[data-dragging="true"] .twc-dt__col-grip { cursor: grabbing; }
|
|
8482
8487
|
.twc-dt__col-name { flex: 1; font-size: var(--text-sm); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
|
|
8483
8488
|
.twc-dt__col-pins { display: inline-flex; gap: 2px; flex: none; }
|
|
8484
8489
|
.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); }
|
|
@@ -8616,6 +8621,11 @@ var NUM_OPS = [
|
|
|
8616
8621
|
];
|
|
8617
8622
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8618
8623
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8624
|
+
var filterTypeOf = (col) => {
|
|
8625
|
+
const ft = col && col.filterType;
|
|
8626
|
+
if (ft === "number" || ft === "string") return ft;
|
|
8627
|
+
return col && col.type === "number" ? "number" : "string";
|
|
8628
|
+
};
|
|
8619
8629
|
var getColVal = (col, row) => col && col.valueGetter ? col.valueGetter(row) : row == null ? void 0 : row[col && col.field];
|
|
8620
8630
|
var diffValueNode = (col, v, row) => col.renderCell ? col.renderCell(v, row) : col.valueFormatter ? col.valueFormatter(v, row) : v == null ? "" : v;
|
|
8621
8631
|
function renderDiffCell(col, val, row) {
|
|
@@ -8698,7 +8708,10 @@ function runDatatableQuery(rows, query, options = {}) {
|
|
|
8698
8708
|
let out = Array.isArray(rows) ? rows : [];
|
|
8699
8709
|
const quick = String(q.quickFilter || "").trim().toLowerCase();
|
|
8700
8710
|
if (quick) out = out.filter((r2) => searchFields.some((f) => String(gv(f, r2) ?? "").toLowerCase().includes(quick)));
|
|
8701
|
-
for (const f of q.filters || [])
|
|
8711
|
+
for (const f of q.filters || []) {
|
|
8712
|
+
const fc = cols.find((c) => c.field === f.field);
|
|
8713
|
+
out = out.filter((r2) => testFilter(gv(f.field, r2), f.op, f.value, filterTypeOf(fc)));
|
|
8714
|
+
}
|
|
8702
8715
|
if (q.sort && q.sort.field) {
|
|
8703
8716
|
const { field, dir } = q.sort, numeric = typeOf(field) === "number";
|
|
8704
8717
|
out = [...out].sort((a, b) => {
|
|
@@ -9516,7 +9529,7 @@ function Datatable({
|
|
|
9516
9529
|
for (const f of filters) {
|
|
9517
9530
|
const col = colByField[f.field];
|
|
9518
9531
|
if (!col) continue;
|
|
9519
|
-
out = out.filter((r2) => testFilter(getColVal(col, r2), f.op, f.value, col
|
|
9532
|
+
out = out.filter((r2) => testFilter(getColVal(col, r2), f.op, f.value, filterTypeOf(col)));
|
|
9520
9533
|
}
|
|
9521
9534
|
if (sort) {
|
|
9522
9535
|
const col = colByField[sort.field];
|
|
@@ -9834,7 +9847,7 @@ function Datatable({
|
|
|
9834
9847
|
}
|
|
9835
9848
|
function addFilter(field) {
|
|
9836
9849
|
const col = colByField[field] || cols[0];
|
|
9837
|
-
setFilters((f) => [...f, { id: Date.now() + Math.random(), field: col.field, op: opsFor(col
|
|
9850
|
+
setFilters((f) => [...f, { id: Date.now() + Math.random(), field: col.field, op: opsFor(filterTypeOf(col))[0].value, value: "" }]);
|
|
9838
9851
|
}
|
|
9839
9852
|
function setPin(field, side) {
|
|
9840
9853
|
setPins((p) => {
|
|
@@ -11649,7 +11662,7 @@ function Datatable({
|
|
|
11649
11662
|
] }),
|
|
11650
11663
|
filters.length === 0 ? /* @__PURE__ */ jsx("div", { className: "twc-dt__empty", style: { padding: "16px 12px" }, children: "No filters applied" }) : filters.map((f) => {
|
|
11651
11664
|
const col = colByField[f.field] || cols[0];
|
|
11652
|
-
const ops = opsFor(col
|
|
11665
|
+
const ops = opsFor(filterTypeOf(col));
|
|
11653
11666
|
const op = ops.find((o) => o.value === f.op) || ops[0];
|
|
11654
11667
|
return /* @__PURE__ */ jsxs("div", { className: "twc-dt__frow", children: [
|
|
11655
11668
|
/* @__PURE__ */ jsx("div", { className: "twc-dt__f-col", children: /* @__PURE__ */ jsx(
|
|
@@ -11661,7 +11674,7 @@ function Datatable({
|
|
|
11661
11674
|
options: filterableCols.map((c) => ({ value: c.field, label: c.headerName })),
|
|
11662
11675
|
onChange: (v) => {
|
|
11663
11676
|
const nc = colByField[v];
|
|
11664
|
-
setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, field: v, op: opsFor(nc
|
|
11677
|
+
setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, field: v, op: opsFor(filterTypeOf(nc))[0].value, value: "" } : x));
|
|
11665
11678
|
}
|
|
11666
11679
|
}
|
|
11667
11680
|
) }),
|
|
@@ -11700,7 +11713,7 @@ function Datatable({
|
|
|
11700
11713
|
Input,
|
|
11701
11714
|
{
|
|
11702
11715
|
size: "sm",
|
|
11703
|
-
type: col
|
|
11716
|
+
type: filterTypeOf(col) === "number" ? "number" : "text",
|
|
11704
11717
|
placeholder: "Value",
|
|
11705
11718
|
value: f.value,
|
|
11706
11719
|
onChange: (e) => setFilters((arr) => arr.map((x) => x.id === f.id ? { ...x, value: e.target.value } : x))
|