twico-ui 1.32.0 → 1.33.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 +17 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +18 -0
- package/dist/index.d.ts +18 -0
- package/dist/index.mjs +17 -8
- package/dist/index.mjs.map +1 -1
- package/llms.txt +2 -0
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -2235,6 +2235,24 @@ interface DatatableColumn<T = any> {
|
|
|
2235
2235
|
copyType?: string;
|
|
2236
2236
|
/** Fully custom cell renderer (badges, avatars, etc.). */
|
|
2237
2237
|
renderCell?: (value: any, row: T) => React.ReactNode;
|
|
2238
|
+
/** #345: per-cell class hook — return a class name applied to the whole cell (`.twc-dt__td`, pinned cells
|
|
2239
|
+
* included), not just its content. Use for value/row-based tinting (e.g. a "changed" cell) via your own
|
|
2240
|
+
* stylesheet, without coupling to the internal class name. Because it participates in the CSS cascade, a
|
|
2241
|
+
* `cellClassName` tint co-exists with the built-in hover/selection/diff backgrounds (a plain class may even
|
|
2242
|
+
* lose to them by specificity — use a more specific selector, or `cellStyle`, to always win). Prefer this
|
|
2243
|
+
* over `cellStyle` when those state cues must stay visible on a tinted cell. Called `(value, row)` to match
|
|
2244
|
+
* `renderCell`/`valueFormatter`. */
|
|
2245
|
+
cellClassName?: (value: any, row: T) => string | undefined;
|
|
2246
|
+
/** #345: per-cell inline-style hook — return a style object applied to the whole cell (`.twc-dt__td`,
|
|
2247
|
+
* pinned cells included). The simplest way to tint an entire cell from the value/row with no stylesheet.
|
|
2248
|
+
* Pin positioning **and** stickiness are always preserved (don't set `position`/`inset-*`). Two caveats,
|
|
2249
|
+
* because an inline style wins over every built-in background: (1) on a **pinned** column the background
|
|
2250
|
+
* must be **opaque** — a translucent value lets the cells scrolling underneath the sticky cell bleed
|
|
2251
|
+
* through; composite over the surface, e.g. `color-mix(in srgb, var(--color-danger) 14%, var(--color-surface))`
|
|
2252
|
+
* rather than `…, transparent`. (2) it also overrides the hover / range-selection / edit-mode / diff
|
|
2253
|
+
* backgrounds on that cell — use `cellClassName` instead if those cues must remain visible. Called
|
|
2254
|
+
* `(value, row)` to match `renderCell`/`valueFormatter`. */
|
|
2255
|
+
cellStyle?: (value: any, row: T) => React.CSSProperties | undefined;
|
|
2238
2256
|
/** Diff-mode (#239) per-column equality override — return true when the two values are equal.
|
|
2239
2257
|
* Precedence: column.compare → diff.compare → valueGetter/=== → JSON compare. */
|
|
2240
2258
|
compare?: (a: any, b: any) => boolean;
|
package/dist/index.d.ts
CHANGED
|
@@ -2235,6 +2235,24 @@ interface DatatableColumn<T = any> {
|
|
|
2235
2235
|
copyType?: string;
|
|
2236
2236
|
/** Fully custom cell renderer (badges, avatars, etc.). */
|
|
2237
2237
|
renderCell?: (value: any, row: T) => React.ReactNode;
|
|
2238
|
+
/** #345: per-cell class hook — return a class name applied to the whole cell (`.twc-dt__td`, pinned cells
|
|
2239
|
+
* included), not just its content. Use for value/row-based tinting (e.g. a "changed" cell) via your own
|
|
2240
|
+
* stylesheet, without coupling to the internal class name. Because it participates in the CSS cascade, a
|
|
2241
|
+
* `cellClassName` tint co-exists with the built-in hover/selection/diff backgrounds (a plain class may even
|
|
2242
|
+
* lose to them by specificity — use a more specific selector, or `cellStyle`, to always win). Prefer this
|
|
2243
|
+
* over `cellStyle` when those state cues must stay visible on a tinted cell. Called `(value, row)` to match
|
|
2244
|
+
* `renderCell`/`valueFormatter`. */
|
|
2245
|
+
cellClassName?: (value: any, row: T) => string | undefined;
|
|
2246
|
+
/** #345: per-cell inline-style hook — return a style object applied to the whole cell (`.twc-dt__td`,
|
|
2247
|
+
* pinned cells included). The simplest way to tint an entire cell from the value/row with no stylesheet.
|
|
2248
|
+
* Pin positioning **and** stickiness are always preserved (don't set `position`/`inset-*`). Two caveats,
|
|
2249
|
+
* because an inline style wins over every built-in background: (1) on a **pinned** column the background
|
|
2250
|
+
* must be **opaque** — a translucent value lets the cells scrolling underneath the sticky cell bleed
|
|
2251
|
+
* through; composite over the surface, e.g. `color-mix(in srgb, var(--color-danger) 14%, var(--color-surface))`
|
|
2252
|
+
* rather than `…, transparent`. (2) it also overrides the hover / range-selection / edit-mode / diff
|
|
2253
|
+
* backgrounds on that cell — use `cellClassName` instead if those cues must remain visible. Called
|
|
2254
|
+
* `(value, row)` to match `renderCell`/`valueFormatter`. */
|
|
2255
|
+
cellStyle?: (value: any, row: T) => React.CSSProperties | undefined;
|
|
2238
2256
|
/** Diff-mode (#239) per-column equality override — return true when the two values are equal.
|
|
2239
2257
|
* Precedence: column.compare → diff.compare → valueGetter/=== → JSON compare. */
|
|
2240
2258
|
compare?: (a: any, b: any) => boolean;
|
package/dist/index.mjs
CHANGED
|
@@ -5867,6 +5867,7 @@ function Combobox({
|
|
|
5867
5867
|
setQuery("");
|
|
5868
5868
|
}
|
|
5869
5869
|
function commit(v) {
|
|
5870
|
+
if (disabled) return;
|
|
5870
5871
|
const o = flat.find((x) => x.value === v);
|
|
5871
5872
|
if (o && o.disabled) return;
|
|
5872
5873
|
if (value === void 0) setInternal(v);
|
|
@@ -6043,7 +6044,7 @@ function Combobox({
|
|
|
6043
6044
|
...rest
|
|
6044
6045
|
}
|
|
6045
6046
|
),
|
|
6046
|
-
clearable && selected && !open ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-cb__clear", "aria-label": "Clear", onClick: (e) => {
|
|
6047
|
+
clearable && selected && !open && !disabled ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-cb__clear", "aria-label": "Clear", onClick: (e) => {
|
|
6047
6048
|
e.stopPropagation();
|
|
6048
6049
|
commit(null);
|
|
6049
6050
|
}, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null,
|
|
@@ -7333,6 +7334,7 @@ var MULTI_CSS = `
|
|
|
7333
7334
|
background: var(--_accent-subtle); color: var(--_accent-subtle-fg);
|
|
7334
7335
|
border-radius: var(--radius-full); font-size: var(--text-xs); font-weight: var(--font-semibold);
|
|
7335
7336
|
}
|
|
7337
|
+
.twc-ms__control[data-disabled="true"] .twc-ms__chip { padding-inline-end: 9px; } /* #342: no \u2715 \u2192 symmetric pad */
|
|
7336
7338
|
.twc-ms__chip-x { display: inline-grid; place-items: center; width: 16px; height: 16px; border: none; padding: 0; background: transparent; color: inherit; cursor: pointer; border-radius: var(--radius-full); opacity: 0.7; }
|
|
7337
7339
|
.twc-ms__chip-x:hover { opacity: 1; background: color-mix(in srgb, currentColor 18%, transparent); }
|
|
7338
7340
|
.twc-ms__chip-x svg { width: 12px; height: 12px; }
|
|
@@ -7575,6 +7577,7 @@ function MultiSelect({
|
|
|
7575
7577
|
setScrollTop(next);
|
|
7576
7578
|
}, [active, open, virtualized, rows, listH]);
|
|
7577
7579
|
function commit(next) {
|
|
7580
|
+
if (disabled) return;
|
|
7578
7581
|
if (value === void 0) setInternal(next);
|
|
7579
7582
|
onChange?.(next);
|
|
7580
7583
|
}
|
|
@@ -7731,10 +7734,10 @@ function MultiSelect({
|
|
|
7731
7734
|
children: [
|
|
7732
7735
|
(maxTagCount != null ? selectedOpts.slice(0, maxTagCount) : selectedOpts).map((o) => /* @__PURE__ */ jsxs("span", { className: "twc-ms__chip", children: [
|
|
7733
7736
|
o.label,
|
|
7734
|
-
/* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
7737
|
+
!disabled ? /* @__PURE__ */ jsx("button", { type: "button", tabIndex: -1, className: "twc-ms__chip-x", "aria-label": `Remove ${o.label}`, onClick: (e) => {
|
|
7735
7738
|
e.stopPropagation();
|
|
7736
7739
|
toggle(o.value);
|
|
7737
|
-
}, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
|
|
7740
|
+
}, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.6", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
7738
7741
|
] }, o.value)),
|
|
7739
7742
|
maxTagCount != null && selectedOpts.length > maxTagCount ? /* @__PURE__ */ jsxs("span", { className: "twc-ms__more", title: selectedOpts.slice(maxTagCount).map((o) => o.label).join(", "), children: [
|
|
7740
7743
|
"+",
|
|
@@ -7787,8 +7790,10 @@ function MultiSelect({
|
|
|
7787
7790
|
tabIndex: -1,
|
|
7788
7791
|
onClick: (e) => {
|
|
7789
7792
|
e.stopPropagation();
|
|
7790
|
-
|
|
7791
|
-
|
|
7793
|
+
if (!disabled) {
|
|
7794
|
+
setOpen((o) => !o);
|
|
7795
|
+
inputRef.current?.focus();
|
|
7796
|
+
}
|
|
7792
7797
|
},
|
|
7793
7798
|
children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" }) })
|
|
7794
7799
|
}
|
|
@@ -10533,6 +10538,7 @@ function Datatable({
|
|
|
10533
10538
|
if (el) el.focus();
|
|
10534
10539
|
}
|
|
10535
10540
|
function onGridKeyDown(e) {
|
|
10541
|
+
if (e.target.closest("input, textarea, select, [contenteditable='true']")) return;
|
|
10536
10542
|
if (editing) return;
|
|
10537
10543
|
const td = e.target.closest(".twc-dt__td[data-r]");
|
|
10538
10544
|
if (!td) return;
|
|
@@ -11492,11 +11498,13 @@ function Datatable({
|
|
|
11492
11498
|
const cellId = selectionMode === "cell" ? `${gridId}-${ri}-${ci}` : void 0;
|
|
11493
11499
|
const display = c.valueFormatter ? c.valueFormatter(val, row) : val;
|
|
11494
11500
|
const cellTitle = !isActions && !c.renderCell && !isEditing && (typeof display === "string" || typeof display === "number") ? String(display) : void 0;
|
|
11501
|
+
const cellClass = c.cellClassName ? c.cellClassName(val, row) : void 0;
|
|
11502
|
+
const cellSty = c.cellStyle ? c.cellStyle(val, row) : void 0;
|
|
11495
11503
|
return /* @__PURE__ */ jsxs(
|
|
11496
11504
|
"td",
|
|
11497
11505
|
{
|
|
11498
11506
|
id: cellId,
|
|
11499
|
-
className: "twc-dt__td",
|
|
11507
|
+
className: cellClass ? `twc-dt__td ${cellClass}` : "twc-dt__td",
|
|
11500
11508
|
role: "gridcell",
|
|
11501
11509
|
"data-r": ri,
|
|
11502
11510
|
"data-c": ci,
|
|
@@ -11513,7 +11521,7 @@ function Datatable({
|
|
|
11513
11521
|
"data-wrap": effectiveWrapped.has(c.field) || void 0,
|
|
11514
11522
|
"data-pin": st.pin,
|
|
11515
11523
|
"data-pin-edge": st.edge,
|
|
11516
|
-
style: { width: widthOf(c), ...st.style },
|
|
11524
|
+
style: { width: widthOf(c), ...cellSty, ...st.style, ...st.pin ? { position: "sticky", zIndex: 2 } : null },
|
|
11517
11525
|
"data-ovtext": cellTitle,
|
|
11518
11526
|
onClick: selectionMode === "cell" ? (e) => handleCellClick(e, k, row, c) : void 0,
|
|
11519
11527
|
onFocus: () => setFocus((f) => f.r === ri && f.c === ci ? f : { r: ri, c: ci }),
|
|
@@ -15728,6 +15736,7 @@ function FileUpload({
|
|
|
15728
15736
|
} else if (accepted.length) set(accepted.slice(0, 1));
|
|
15729
15737
|
}
|
|
15730
15738
|
function remove(i) {
|
|
15739
|
+
if (disabled) return;
|
|
15731
15740
|
set(files.filter((_, idx) => idx !== i));
|
|
15732
15741
|
}
|
|
15733
15742
|
return /* @__PURE__ */ jsxs("div", { className: `twc-upload ${className}`, "data-size": size, ...rest, children: [
|
|
@@ -15798,7 +15807,7 @@ function FileUpload({
|
|
|
15798
15807
|
/* @__PURE__ */ jsx("span", { className: "twc-upload__file-name", children: f.name }),
|
|
15799
15808
|
/* @__PURE__ */ jsx("span", { className: "twc-upload__file-size", children: fmtSize(f.size) })
|
|
15800
15809
|
] }),
|
|
15801
|
-
/* @__PURE__ */ jsx("button", { className: "twc-upload__file-x", "aria-label": `Remove ${f.name}`, onClick: () => remove(i), type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) })
|
|
15810
|
+
!disabled ? /* @__PURE__ */ jsx("button", { className: "twc-upload__file-x", "aria-label": `Remove ${f.name}`, onClick: () => remove(i), type: "button", children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.4", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M18 6 6 18M6 6l12 12" }) }) }) : null
|
|
15802
15811
|
] }, fileKey(f))) }) : null,
|
|
15803
15812
|
error ? /* @__PURE__ */ jsx("span", { id: descId, className: "twc-field__error", children: error }) : null
|
|
15804
15813
|
] });
|