twico-ui 1.20.2 → 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 +15 -0
- package/dist/index.cjs +53 -12
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +53 -12
- package/dist/index.mjs.map +1 -1
- package/llms.txt +1 -0
- package/package.json +1 -1
- package/styles/twico-ui.css +7 -2
package/dist/index.d.cts
CHANGED
|
@@ -1810,6 +1810,10 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
1810
1810
|
quickFilter?: string;
|
|
1811
1811
|
/** Fires with the new quick-search string as the user types (and when a host sets it). */
|
|
1812
1812
|
onQuickFilterChange?: (value: string) => void;
|
|
1813
|
+
/** Custom node rendered in a **leading slot** of the toolbar row, before the built-in Columns/Filters
|
|
1814
|
+
* cluster (#286) — for host controls like an "Add row" button or bulk actions. Mirrors `CardGrid`'s
|
|
1815
|
+
* `toolbar` prop, so no internal-class/absolute-position hacks are needed. */
|
|
1816
|
+
toolbarActions?: React.ReactNode;
|
|
1813
1817
|
/**
|
|
1814
1818
|
* Actions shown in the toolbar when one or more rows are selected (requires
|
|
1815
1819
|
* `checkboxSelection`). Each handler receives the selected keys, the resolved
|
package/dist/index.d.ts
CHANGED
|
@@ -1810,6 +1810,10 @@ interface DatatableProps<T = any> extends Omit<React.HTMLAttributes<HTMLDivEleme
|
|
|
1810
1810
|
quickFilter?: string;
|
|
1811
1811
|
/** Fires with the new quick-search string as the user types (and when a host sets it). */
|
|
1812
1812
|
onQuickFilterChange?: (value: string) => void;
|
|
1813
|
+
/** Custom node rendered in a **leading slot** of the toolbar row, before the built-in Columns/Filters
|
|
1814
|
+
* cluster (#286) — for host controls like an "Add row" button or bulk actions. Mirrors `CardGrid`'s
|
|
1815
|
+
* `toolbar` prop, so no internal-class/absolute-position hacks are needed. */
|
|
1816
|
+
toolbarActions?: React.ReactNode;
|
|
1813
1817
|
/**
|
|
1814
1818
|
* Actions shown in the toolbar when one or more rows are selected (requires
|
|
1815
1819
|
* `checkboxSelection`). Each handler receives the selected keys, the resolved
|
package/dist/index.mjs
CHANGED
|
@@ -5467,7 +5467,7 @@ function ColorPicker({
|
|
|
5467
5467
|
role: "dialog",
|
|
5468
5468
|
"aria-modal": "true",
|
|
5469
5469
|
"aria-label": "Color picker",
|
|
5470
|
-
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-
|
|
5470
|
+
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
|
|
5471
5471
|
children: [
|
|
5472
5472
|
/* @__PURE__ */ jsxs(
|
|
5473
5473
|
"div",
|
|
@@ -5945,7 +5945,7 @@ function Combobox({
|
|
|
5945
5945
|
role: "listbox",
|
|
5946
5946
|
ref: popRef,
|
|
5947
5947
|
"data-placement": coords.flip ? "top" : "bottom",
|
|
5948
|
-
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-
|
|
5948
|
+
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-floating)" },
|
|
5949
5949
|
children: popInner
|
|
5950
5950
|
}
|
|
5951
5951
|
),
|
|
@@ -6832,7 +6832,7 @@ function Select({
|
|
|
6832
6832
|
ref: popRef,
|
|
6833
6833
|
"data-state": popState,
|
|
6834
6834
|
"data-placement": coords.flip ? "top" : "bottom",
|
|
6835
|
-
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-
|
|
6835
|
+
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)" },
|
|
6836
6836
|
children: popInner
|
|
6837
6837
|
}
|
|
6838
6838
|
),
|
|
@@ -7599,7 +7599,7 @@ function MultiSelect({
|
|
|
7599
7599
|
className: "twc-pop twc-pop--portal",
|
|
7600
7600
|
ref: popRef,
|
|
7601
7601
|
"data-placement": coords.flip ? "top" : "bottom",
|
|
7602
|
-
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-
|
|
7602
|
+
style: { position: "fixed", left: coords.left, top: coords.top, bottom: coords.bottom, width: coords.width, right: "auto", zIndex: "var(--z-floating)" },
|
|
7603
7603
|
children: popInner
|
|
7604
7604
|
}
|
|
7605
7605
|
),
|
|
@@ -8107,6 +8107,8 @@ var DT_CSS = `
|
|
|
8107
8107
|
/* Toolbar */
|
|
8108
8108
|
.twc-dt__toolbar { position: relative; z-index: 10; display: flex; align-items: center; gap: 6px; padding: 8px 10px;
|
|
8109
8109
|
border-bottom: var(--border-thin) solid var(--color-divider); flex-wrap: wrap; }
|
|
8110
|
+
/* #286: host-supplied leading toolbar slot \u2014 a flex cluster so multiple buttons align with the built-ins. */
|
|
8111
|
+
.twc-dt__toolbar-actions { display: inline-flex; align-items: center; gap: 6px; }
|
|
8110
8112
|
/* z-index above the scroll area's sticky header (z:3) so a toolbar button's
|
|
8111
8113
|
hover tooltip (a ::after that hangs below the bar) paints over the table
|
|
8112
8114
|
instead of being covered by the header/first rows. */
|
|
@@ -8504,9 +8506,14 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
|
|
|
8504
8506
|
|
|
8505
8507
|
/* Filter panel */
|
|
8506
8508
|
.twc-dt__filters { width: 580px; max-width: calc(100vw - 32px); }
|
|
8507
|
-
|
|
8508
|
-
|
|
8509
|
-
.twc-
|
|
8509
|
+
/* #289: wrap is a safety net \u2014 a beyond-cap label or the narrow responsive panel drops the value input
|
|
8510
|
+
to its own line instead of clipping the remove button; no effect in the normal (capped) case. */
|
|
8511
|
+
.twc-dt__frow { display: flex; align-items: center; gap: 6px; padding: 5px 4px; flex-wrap: wrap; }
|
|
8512
|
+
/* #289: column-field auto-fits the widest header label \u2014 JS writes --twc-dt-fcol-w (measured, clamped),
|
|
8513
|
+
the max-width is the hard backstop that keeps the value input above its 140px floor inside the 580px
|
|
8514
|
+
panel even if the var is stale/too large. Fallback 118px = the previous fixed behavior. */
|
|
8515
|
+
.twc-dt__f-col { flex: none; width: var(--twc-dt-fcol-w, 118px); min-width: 118px; max-width: 210px; }
|
|
8516
|
+
.twc-dt__f-op { flex: none; width: var(--twc-dt-fop-w, 118px); min-width: 118px; max-width: 170px; }
|
|
8510
8517
|
.twc-dt__f-val { flex: 1; min-width: 140px; }
|
|
8511
8518
|
.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; }
|
|
8512
8519
|
.twc-dt__frm-x:hover { background: var(--color-danger-subtle); color: var(--color-danger-subtle-fg); }
|
|
@@ -8621,6 +8628,7 @@ var NUM_OPS = [
|
|
|
8621
8628
|
];
|
|
8622
8629
|
var opsFor = (type) => type === "number" ? NUM_OPS : STR_OPS;
|
|
8623
8630
|
var isMultiOp = (op) => op === "isAnyOf";
|
|
8631
|
+
var ALL_OP_LABELS = [...new Set([...STR_OPS, ...NUM_OPS].map((o) => o.label))];
|
|
8624
8632
|
var filterTypeOf = (col) => {
|
|
8625
8633
|
const ft = col && col.filterType;
|
|
8626
8634
|
if (ft === "number" || ft === "string") return ft;
|
|
@@ -9061,6 +9069,7 @@ function Datatable({
|
|
|
9061
9069
|
searchable = true,
|
|
9062
9070
|
quickFilter,
|
|
9063
9071
|
onQuickFilterChange,
|
|
9072
|
+
toolbarActions,
|
|
9064
9073
|
rowPinning = false,
|
|
9065
9074
|
rowReorder = false,
|
|
9066
9075
|
rowResize = false,
|
|
@@ -9292,6 +9301,8 @@ function Datatable({
|
|
|
9292
9301
|
};
|
|
9293
9302
|
}, []);
|
|
9294
9303
|
const scrollRef = React51__default.useRef(null);
|
|
9304
|
+
const filterPanelRef = React51__default.useRef(null);
|
|
9305
|
+
const measureCanvas = React51__default.useRef(null);
|
|
9295
9306
|
const [scrollTop, setScrollTop] = React51__default.useState(0);
|
|
9296
9307
|
const [viewportH, setViewportH] = React51__default.useState(0);
|
|
9297
9308
|
const [ovTip, setOvTip] = React51__default.useState(null);
|
|
@@ -10325,7 +10336,36 @@ function Datatable({
|
|
|
10325
10336
|
] });
|
|
10326
10337
|
}
|
|
10327
10338
|
const tableMinWidth = leadW + ordered.reduce((a, c) => a + widthOf(c), 0);
|
|
10328
|
-
const filterableCols = cols.filter((c) => c.filterable);
|
|
10339
|
+
const filterableCols = React51__default.useMemo(() => cols.filter((c) => c.filterable), [cols]);
|
|
10340
|
+
React51__default.useEffect(() => {
|
|
10341
|
+
const el = filterPanelRef.current;
|
|
10342
|
+
if (panel !== "filters" || !el || typeof document === "undefined") return void 0;
|
|
10343
|
+
const measure = () => {
|
|
10344
|
+
if (!el.isConnected) return;
|
|
10345
|
+
const trigger = el.querySelector(".twc-sel__trigger");
|
|
10346
|
+
const cs = getComputedStyle(trigger || el);
|
|
10347
|
+
const ctx = (measureCanvas.current || (measureCanvas.current = document.createElement("canvas"))).getContext("2d");
|
|
10348
|
+
if (!ctx) return;
|
|
10349
|
+
ctx.font = cs.font || `${cs.fontStyle} ${cs.fontWeight} ${cs.fontSize}/${cs.lineHeight} ${cs.fontFamily}`;
|
|
10350
|
+
const pad2 = trigger ? (parseFloat(cs.paddingLeft) || 0) + (parseFloat(cs.paddingRight) || 0) : 24;
|
|
10351
|
+
const chrome = pad2 + 8 + 16 + 4;
|
|
10352
|
+
const widest = (labels) => labels.reduce((m, l) => Math.max(m, ctx.measureText(String(l)).width), 0);
|
|
10353
|
+
const colCap = Math.max(118, Math.min(210, el.clientWidth - 118 - 30 - 140 - 3 * 6 - 2 * 4));
|
|
10354
|
+
const colW = Math.min(colCap, Math.max(118, Math.ceil(widest(filterableCols.map((c) => c.headerName ?? c.field)) + chrome)));
|
|
10355
|
+
const opW = Math.min(170, Math.max(118, Math.ceil(widest(ALL_OP_LABELS) + chrome)));
|
|
10356
|
+
if (Number.isFinite(colW)) el.style.setProperty("--twc-dt-fcol-w", `${colW}px`);
|
|
10357
|
+
if (Number.isFinite(opW)) el.style.setProperty("--twc-dt-fop-w", `${opW}px`);
|
|
10358
|
+
};
|
|
10359
|
+
measure();
|
|
10360
|
+
document.fonts?.ready?.then?.(measure).catch?.(() => {
|
|
10361
|
+
});
|
|
10362
|
+
let ro;
|
|
10363
|
+
if (typeof ResizeObserver !== "undefined") {
|
|
10364
|
+
ro = new ResizeObserver(measure);
|
|
10365
|
+
ro.observe(el);
|
|
10366
|
+
}
|
|
10367
|
+
return () => ro?.disconnect();
|
|
10368
|
+
}, [panel, filterableCols, filters.length]);
|
|
10329
10369
|
const orderIdxOf = (f) => {
|
|
10330
10370
|
const i = order.indexOf(f);
|
|
10331
10371
|
return i === -1 ? 9999 : i;
|
|
@@ -10643,6 +10683,7 @@ function Datatable({
|
|
|
10643
10683
|
return /* @__PURE__ */ jsxs("div", { className: `twc-dt ${className}`, ref: rootRef, "data-density": density, "data-resizing": resizing || void 0, ...rest, children: [
|
|
10644
10684
|
__twcStyles,
|
|
10645
10685
|
/* @__PURE__ */ jsxs("div", { className: "twc-dt__toolbar", "data-compact": compact || void 0, children: [
|
|
10686
|
+
toolbarActions != null ? /* @__PURE__ */ jsx("div", { className: "twc-dt__toolbar-actions", children: toolbarActions }) : null,
|
|
10646
10687
|
(batchActions.length || hasBatchEditor) && selected.size > 0 ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__batch", children: [
|
|
10647
10688
|
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__batch-x", onClick: clearSelection, "aria-label": "Clear selection", children: /* @__PURE__ */ jsx(Svg, { d: I.x }) }),
|
|
10648
10689
|
/* @__PURE__ */ jsxs("span", { className: "twc-dt__batch-count", children: [
|
|
@@ -11694,7 +11735,7 @@ function Datatable({
|
|
|
11694
11735
|
] })
|
|
11695
11736
|
] });
|
|
11696
11737
|
})() : null,
|
|
11697
|
-
panel === "filters" && panelPos ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__pop twc-dt__filters", style: { top: panelPos.top, left: panelPos.left }, children: [
|
|
11738
|
+
panel === "filters" && panelPos ? /* @__PURE__ */ jsxs("div", { ref: filterPanelRef, className: "twc-dt__pop twc-dt__filters", style: { top: panelPos.top, left: panelPos.left }, children: [
|
|
11698
11739
|
/* @__PURE__ */ jsxs("div", { className: "twc-dt__panel-head", children: [
|
|
11699
11740
|
/* @__PURE__ */ jsx("span", { className: "twc-dt__panel-title", children: "Filters" }),
|
|
11700
11741
|
filters.length ? /* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setFilters([]), children: "Clear all" }) : null
|
|
@@ -12567,7 +12608,7 @@ function DatePicker({
|
|
|
12567
12608
|
role: "dialog",
|
|
12568
12609
|
"aria-modal": "true",
|
|
12569
12610
|
"aria-label": "Choose date",
|
|
12570
|
-
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-
|
|
12611
|
+
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
|
|
12571
12612
|
children: [
|
|
12572
12613
|
/* @__PURE__ */ jsxs("div", { className: "twc-dp__head", children: [
|
|
12573
12614
|
/* @__PURE__ */ 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__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "m15 18-6-6 6-6" }) }) }),
|
|
@@ -13144,7 +13185,7 @@ function DateRangePicker({
|
|
|
13144
13185
|
role: "dialog",
|
|
13145
13186
|
"aria-modal": "true",
|
|
13146
13187
|
"aria-label": "Choose date range",
|
|
13147
|
-
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-
|
|
13188
|
+
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
|
|
13148
13189
|
children: [
|
|
13149
13190
|
presetItems.length ? /* @__PURE__ */ jsx("div", { className: "twc-drp__presets", children: presetItems.map((p, i) => /* @__PURE__ */ jsx("button", { type: "button", className: "twc-drp__preset", onClick: () => applyPreset(p), children: p.label }, i)) }) : null,
|
|
13150
13191
|
/* @__PURE__ */ jsxs("div", { className: "twc-drp__cal", children: [
|
|
@@ -13673,7 +13714,7 @@ function TimePicker({
|
|
|
13673
13714
|
role: "dialog",
|
|
13674
13715
|
"aria-modal": "true",
|
|
13675
13716
|
"aria-label": "Choose time",
|
|
13676
|
-
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-
|
|
13717
|
+
style: { position: "fixed", left: coords.left, right: "auto", top: coords.top, bottom: coords.bottom, zIndex: "var(--z-floating)" },
|
|
13677
13718
|
children: /* @__PURE__ */ jsx("div", { className: "twc-tp__cols", children: columns.map((col) => {
|
|
13678
13719
|
const firstTab = col.items.find((it) => it.selected) || col.items.find((it) => !it.disabled);
|
|
13679
13720
|
return /* @__PURE__ */ jsxs("div", { className: "twc-tp__col", role: "listbox", "aria-label": col.aria, "data-col": col.key, children: [
|