twico-ui 1.3.1 → 1.4.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/dist/index.cjs +30 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -6
- package/dist/index.d.ts +13 -6
- package/dist/index.mjs +30 -14
- package/dist/index.mjs.map +1 -1
- package/llms.txt +8 -4
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -541,9 +541,9 @@ declare function CurrencyField(props: CurrencyFieldProps): React.JSX.Element;
|
|
|
541
541
|
* Advanced data table (Material UI Data Grid Premium style): sortable, filterable
|
|
542
542
|
* (per-column operators + quick search), hideable (with a searchable column list),
|
|
543
543
|
* and pinnable (left/right, sticky) columns, drag-to-reorder and drag-to-resize
|
|
544
|
-
* columns, a column-management + filter toolbar
|
|
545
|
-
* an optional aggregation/summary footer, optional
|
|
546
|
-
* batch-action toolbar, an actions column (per-row icon buttons + overflow menu),
|
|
544
|
+
* columns, a column-management + filter toolbar (with opt-in density / aggregation /
|
|
545
|
+
* pivot / CSV-export tools), an optional aggregation/summary footer, optional
|
|
546
|
+
* checkbox selection with a batch-action toolbar, an actions column (per-row icon buttons + overflow menu),
|
|
547
547
|
* page-number pagination with a configurable rows-per-page selector, a skeleton
|
|
548
548
|
* loading state, and an optional server-side mode (sort/filter/paginate on the
|
|
549
549
|
* backend — only the current page is loaded). Filter controls and the pager are
|
|
@@ -579,7 +579,7 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
579
579
|
* full row objects server-side rather than relying on `selectedRows`.
|
|
580
580
|
*/
|
|
581
581
|
batchActions?: DatatableBatchAction[];
|
|
582
|
-
/** Row height preset.
|
|
582
|
+
/** Row height preset. With `showDensity`, the toolbar density button cycles it locally; changing this prop re-applies it. @default "comfortable" */
|
|
583
583
|
density?: "compact" | "standard" | "comfortable";
|
|
584
584
|
/** Initial rows per page. 0 disables pagination. @default 10 */
|
|
585
585
|
pageSize?: number;
|
|
@@ -598,8 +598,13 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
598
598
|
rowCount?: number;
|
|
599
599
|
/** Server-mode callback fired (debounced) whenever the query changes. */
|
|
600
600
|
onServerChange?: (state: DatatableQuery) => void;
|
|
601
|
-
/** Show the Export toolbar button (split button: click = CSV, chevron = format menu). @default
|
|
601
|
+
/** Show the Export toolbar button (split button: click = CSV, chevron = format menu). @default false */
|
|
602
602
|
showExport?: boolean;
|
|
603
|
+
/** Show the row-density toolbar button (cycles compact / standard / comfortable). The `density` prop
|
|
604
|
+
* still sets the row height even when this button is hidden. @default false */
|
|
605
|
+
showDensity?: boolean;
|
|
606
|
+
/** Show the Pivot toolbar button. Also shown automatically when `pivot` or `pivotMode` is set. @default false */
|
|
607
|
+
showPivot?: boolean;
|
|
603
608
|
/** Filename (without extension) for exports (CSV / Excel). @default "export" */
|
|
604
609
|
exportFilename?: string;
|
|
605
610
|
/** Server-mode precomputed aggregation. Per field, either a scalar/node (used as-is) or a per-function map
|
|
@@ -637,7 +642,9 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
637
642
|
onCellClick?: (value: any, row: any, field: string) => void;
|
|
638
643
|
/** Fired when the active cell changes: ({ key, field } | null). */
|
|
639
644
|
onActiveCellChange?: (cell: { key: string | number; field: string } | null) => void;
|
|
640
|
-
/**
|
|
645
|
+
/** Show the **Aggregation** toolbar button and start with the totals row on. From that panel the user
|
|
646
|
+
* toggles totals and picks columns + functions (a column's `aggregation` prop seeds the initial choice);
|
|
647
|
+
* changing the prop re-applies it. When false (the default) the Aggregation button is hidden. @default false */
|
|
641
648
|
showAggregation?: boolean;
|
|
642
649
|
/** Accessible label for the grid (role="grid"). A standard `aria-label` prop takes precedence. @default "Data table" */
|
|
643
650
|
ariaLabel?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -541,9 +541,9 @@ declare function CurrencyField(props: CurrencyFieldProps): React.JSX.Element;
|
|
|
541
541
|
* Advanced data table (Material UI Data Grid Premium style): sortable, filterable
|
|
542
542
|
* (per-column operators + quick search), hideable (with a searchable column list),
|
|
543
543
|
* and pinnable (left/right, sticky) columns, drag-to-reorder and drag-to-resize
|
|
544
|
-
* columns, a column-management + filter toolbar
|
|
545
|
-
* an optional aggregation/summary footer, optional
|
|
546
|
-
* batch-action toolbar, an actions column (per-row icon buttons + overflow menu),
|
|
544
|
+
* columns, a column-management + filter toolbar (with opt-in density / aggregation /
|
|
545
|
+
* pivot / CSV-export tools), an optional aggregation/summary footer, optional
|
|
546
|
+
* checkbox selection with a batch-action toolbar, an actions column (per-row icon buttons + overflow menu),
|
|
547
547
|
* page-number pagination with a configurable rows-per-page selector, a skeleton
|
|
548
548
|
* loading state, and an optional server-side mode (sort/filter/paginate on the
|
|
549
549
|
* backend — only the current page is loaded). Filter controls and the pager are
|
|
@@ -579,7 +579,7 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
579
579
|
* full row objects server-side rather than relying on `selectedRows`.
|
|
580
580
|
*/
|
|
581
581
|
batchActions?: DatatableBatchAction[];
|
|
582
|
-
/** Row height preset.
|
|
582
|
+
/** Row height preset. With `showDensity`, the toolbar density button cycles it locally; changing this prop re-applies it. @default "comfortable" */
|
|
583
583
|
density?: "compact" | "standard" | "comfortable";
|
|
584
584
|
/** Initial rows per page. 0 disables pagination. @default 10 */
|
|
585
585
|
pageSize?: number;
|
|
@@ -598,8 +598,13 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
598
598
|
rowCount?: number;
|
|
599
599
|
/** Server-mode callback fired (debounced) whenever the query changes. */
|
|
600
600
|
onServerChange?: (state: DatatableQuery) => void;
|
|
601
|
-
/** Show the Export toolbar button (split button: click = CSV, chevron = format menu). @default
|
|
601
|
+
/** Show the Export toolbar button (split button: click = CSV, chevron = format menu). @default false */
|
|
602
602
|
showExport?: boolean;
|
|
603
|
+
/** Show the row-density toolbar button (cycles compact / standard / comfortable). The `density` prop
|
|
604
|
+
* still sets the row height even when this button is hidden. @default false */
|
|
605
|
+
showDensity?: boolean;
|
|
606
|
+
/** Show the Pivot toolbar button. Also shown automatically when `pivot` or `pivotMode` is set. @default false */
|
|
607
|
+
showPivot?: boolean;
|
|
603
608
|
/** Filename (without extension) for exports (CSV / Excel). @default "export" */
|
|
604
609
|
exportFilename?: string;
|
|
605
610
|
/** Server-mode precomputed aggregation. Per field, either a scalar/node (used as-is) or a per-function map
|
|
@@ -637,7 +642,9 @@ interface DatatableProps extends Omit<React.HTMLAttributes<HTMLDivElement>, "row
|
|
|
637
642
|
onCellClick?: (value: any, row: any, field: string) => void;
|
|
638
643
|
/** Fired when the active cell changes: ({ key, field } | null). */
|
|
639
644
|
onActiveCellChange?: (cell: { key: string | number; field: string } | null) => void;
|
|
640
|
-
/**
|
|
645
|
+
/** Show the **Aggregation** toolbar button and start with the totals row on. From that panel the user
|
|
646
|
+
* toggles totals and picks columns + functions (a column's `aggregation` prop seeds the initial choice);
|
|
647
|
+
* changing the prop re-applies it. When false (the default) the Aggregation button is hidden. @default false */
|
|
641
648
|
showAggregation?: boolean;
|
|
642
649
|
/** Accessible label for the grid (role="grid"). A standard `aria-label` prop takes precedence. @default "Data table" */
|
|
643
650
|
ariaLabel?: string;
|
package/dist/index.mjs
CHANGED
|
@@ -187,7 +187,9 @@ function initials(name) {
|
|
|
187
187
|
function safeSrc(url) {
|
|
188
188
|
if (url == null) return void 0;
|
|
189
189
|
const s = String(url).replace(/[\x00-\x20]+/g, "").toLowerCase();
|
|
190
|
-
|
|
190
|
+
if (s.startsWith("javascript:") || s.startsWith("vbscript:")) return void 0;
|
|
191
|
+
if (s.startsWith("data:") && !s.startsWith("data:image/")) return void 0;
|
|
192
|
+
return url;
|
|
191
193
|
}
|
|
192
194
|
function Avatar({
|
|
193
195
|
src,
|
|
@@ -3780,6 +3782,7 @@ th.twc-dt__rownum .twc-dt__th-inner { padding-inline: 8px; gap: 2px; justify-con
|
|
|
3780
3782
|
.twc-dt__sw[data-on="true"]::after { transform: translateX(14px); }
|
|
3781
3783
|
.twc-dt__panel-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 8px 8px; }
|
|
3782
3784
|
.twc-dt__panel-title { font-size: var(--text-xs); font-weight: 700; letter-spacing: var(--tracking-wide); text-transform: uppercase; color: var(--color-text-subtle); }
|
|
3785
|
+
.twc-dt__panel-count { font-weight: 600; color: var(--color-text-muted); text-transform: none; letter-spacing: 0; margin-inline-start: 6px; font-variant-numeric: tabular-nums; }
|
|
3783
3786
|
.twc-dt__link { border: none; background: transparent; color: var(--color-primary); font-family: inherit; font-size: var(--text-xs); font-weight: 600; cursor: pointer; padding: 2px 4px; border-radius: var(--radius-sm); }
|
|
3784
3787
|
.twc-dt__link:hover { background: var(--color-primary-subtle); }
|
|
3785
3788
|
|
|
@@ -4177,7 +4180,7 @@ function Datatable({
|
|
|
4177
4180
|
loading = false,
|
|
4178
4181
|
rowKey,
|
|
4179
4182
|
checkboxSelection = false,
|
|
4180
|
-
density: densityProp = "
|
|
4183
|
+
density: densityProp = "comfortable",
|
|
4181
4184
|
pageSize = 10,
|
|
4182
4185
|
pageSizeOptions = [5, 10, 25, 50],
|
|
4183
4186
|
height = 440,
|
|
@@ -4185,7 +4188,9 @@ function Datatable({
|
|
|
4185
4188
|
rowCount,
|
|
4186
4189
|
onServerChange,
|
|
4187
4190
|
batchActions = [],
|
|
4188
|
-
showExport =
|
|
4191
|
+
showExport = false,
|
|
4192
|
+
showDensity = false,
|
|
4193
|
+
showPivot = false,
|
|
4189
4194
|
exportFilename = "export",
|
|
4190
4195
|
aggregationValues = null,
|
|
4191
4196
|
disableColumnReorder = false,
|
|
@@ -4724,7 +4729,7 @@ function Datatable({
|
|
|
4724
4729
|
rowFocusRef.current = null;
|
|
4725
4730
|
const root = gridRef.current;
|
|
4726
4731
|
if (!root) return;
|
|
4727
|
-
const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/"/g,
|
|
4732
|
+
const sel = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(String(key)) : String(key).replace(/[\\"]/g, "\\$&");
|
|
4728
4733
|
const el = root.querySelector(`.twc-dt__row-handle[data-row-key="${sel}"]`);
|
|
4729
4734
|
if (el) el.focus();
|
|
4730
4735
|
});
|
|
@@ -5274,6 +5279,8 @@ function Datatable({
|
|
|
5274
5279
|
};
|
|
5275
5280
|
const shownColRows = cols.filter((c) => c.field !== "__pinactions__" && c.headerName.toLowerCase().includes(colQuery.trim().toLowerCase())).sort((a, b) => orderIdxOf(a.field) - orderIdxOf(b.field));
|
|
5276
5281
|
const rowNumMatch = rowNumbers && "row number".includes(colQuery.trim().toLowerCase());
|
|
5282
|
+
const manageableCols = cols.filter((c) => c.field !== "__pinactions__");
|
|
5283
|
+
const visibleColCount = manageableCols.filter((c) => !hidden.has(c.field)).length;
|
|
5277
5284
|
const rppOptions = Array.from(new Set([...pageSizeOptions || [], pageSize].filter((n) => n > 0))).sort((a, b) => a - b).map((n) => ({ value: String(n), label: String(n) }));
|
|
5278
5285
|
const totalCols = ordered.length + (checkboxSelection ? 1 : 0) + (showRowNum ? 1 : 0);
|
|
5279
5286
|
function renderGroupRow(item) {
|
|
@@ -5636,11 +5643,11 @@ function Datatable({
|
|
|
5636
5643
|
]
|
|
5637
5644
|
}
|
|
5638
5645
|
),
|
|
5639
|
-
/* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
|
|
5646
|
+
showDensity ? /* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__tbtn", "data-tip": "Change row density", onClick: () => setDensity((d) => d === "compact" ? "standard" : d === "standard" ? "comfortable" : "compact"), children: [
|
|
5640
5647
|
/* @__PURE__ */ jsx(Svg, { d: I.density }),
|
|
5641
5648
|
/* @__PURE__ */ jsx("span", { className: "twc-dt__tlabel", children: density[0].toUpperCase() + density.slice(1) })
|
|
5642
|
-
] }),
|
|
5643
|
-
/* @__PURE__ */ jsxs(
|
|
5649
|
+
] }) : null,
|
|
5650
|
+
showAggregation ? /* @__PURE__ */ jsxs(
|
|
5644
5651
|
"button",
|
|
5645
5652
|
{
|
|
5646
5653
|
type: "button",
|
|
@@ -5665,8 +5672,8 @@ function Datatable({
|
|
|
5665
5672
|
aggOn && hasAggregation ? /* @__PURE__ */ jsx("span", { className: "twc-dt__tbadge", children: ordered.filter((c) => aggOf(c)).length }) : null
|
|
5666
5673
|
]
|
|
5667
5674
|
}
|
|
5668
|
-
),
|
|
5669
|
-
/* @__PURE__ */ jsxs(
|
|
5675
|
+
) : null,
|
|
5676
|
+
showPivot || pivotMode || pivot != null || pivotActive ? /* @__PURE__ */ jsxs(
|
|
5670
5677
|
"button",
|
|
5671
5678
|
{
|
|
5672
5679
|
type: "button",
|
|
@@ -5691,7 +5698,7 @@ function Datatable({
|
|
|
5691
5698
|
pivotActive ? /* @__PURE__ */ jsx("span", { className: "twc-dt__tdot", "aria-label": "on", role: "img" }) : null
|
|
5692
5699
|
]
|
|
5693
5700
|
}
|
|
5694
|
-
),
|
|
5701
|
+
) : null,
|
|
5695
5702
|
showExport ? /* @__PURE__ */ jsxs("span", { className: "twc-dt__export", children: [
|
|
5696
5703
|
/* @__PURE__ */ jsxs("button", { type: "button", className: "twc-dt__export-main", "data-tip": "Export to CSV", onClick: () => exportData("csv"), "aria-label": "Export to CSV", children: [
|
|
5697
5704
|
/* @__PURE__ */ jsx(Svg, { d: I.download }),
|
|
@@ -6260,7 +6267,14 @@ function Datatable({
|
|
|
6260
6267
|
) : null,
|
|
6261
6268
|
panel === "columns" && panelPos ? /* @__PURE__ */ jsxs("div", { className: "twc-dt__pop twc-dt__cols", style: { top: panelPos.top, left: panelPos.left }, role: "dialog", "aria-label": "Column settings", children: [
|
|
6262
6269
|
/* @__PURE__ */ jsxs("div", { className: "twc-dt__panel-head", children: [
|
|
6263
|
-
/* @__PURE__ */
|
|
6270
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-dt__panel-title", children: [
|
|
6271
|
+
"Columns ",
|
|
6272
|
+
/* @__PURE__ */ jsxs("span", { className: "twc-dt__panel-count", title: `${visibleColCount} of ${manageableCols.length} columns shown`, children: [
|
|
6273
|
+
visibleColCount,
|
|
6274
|
+
"/",
|
|
6275
|
+
manageableCols.length
|
|
6276
|
+
] })
|
|
6277
|
+
] }),
|
|
6264
6278
|
/* @__PURE__ */ jsxs("div", { children: [
|
|
6265
6279
|
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(/* @__PURE__ */ new Set()), children: "Show all" }),
|
|
6266
6280
|
/* @__PURE__ */ jsx("button", { type: "button", className: "twc-dt__link", onClick: () => setHidden(new Set(cols.filter((c) => c.hideable).map((c) => c.field))), children: "Hide all" })
|
|
@@ -8836,8 +8850,10 @@ var SIDEBAR_CSS = `
|
|
|
8836
8850
|
.twc-sidebar__badge { flex: none; font-size: 11px; font-weight: var(--font-bold); padding: 1px 7px; border-radius: var(--radius-full); background: var(--color-primary); color: var(--color-primary-fg); opacity: 1; visibility: visible;
|
|
8837
8851
|
transition: opacity var(--duration-fast) var(--ease-standard) var(--duration-fast), visibility 0s; }
|
|
8838
8852
|
.twc-sidebar[data-collapsed="true"] .twc-sidebar__badge { opacity: 0; visibility: hidden; transition: opacity var(--duration-instant) var(--ease-standard), visibility 0s var(--duration-instant); }
|
|
8839
|
-
/* Collapsed:
|
|
8840
|
-
|
|
8853
|
+
/* Collapsed: centre the brand mark in the 68px rail (\u2248 the nav icon column) with no
|
|
8854
|
+
right padding, so a mark wider than the icons isn't clipped. flex-start (not
|
|
8855
|
+
justify-content) keeps it from jolting to centre while the rail is still wide. */
|
|
8856
|
+
.twc-sidebar[data-collapsed="true"] .twc-sidebar__head { padding-inline: 18px 0; }
|
|
8841
8857
|
.twc-sidebar[data-collapsed="true"] .twc-sidebar__brand, .twc-sidebar[data-collapsed="true"] .twc-sidebar__foot-user { font-size: 0; gap: 0; }
|
|
8842
8858
|
.twc-sidebar[data-collapsed="true"] .twc-sidebar__foot-user { justify-content: center; }
|
|
8843
8859
|
.twc-sidebar__brand > :not(:first-child) { visibility: visible; transition: opacity var(--duration-fast) var(--ease-standard) var(--duration-fast), visibility 0s; }
|
|
@@ -9066,7 +9082,7 @@ function Slider({
|
|
|
9066
9082
|
}
|
|
9067
9083
|
function onKeyDown(e) {
|
|
9068
9084
|
if (disabled) return;
|
|
9069
|
-
let next
|
|
9085
|
+
let next;
|
|
9070
9086
|
if (e.key === "ArrowRight" || e.key === "ArrowUp") next = clampSnap(val + step);
|
|
9071
9087
|
else if (e.key === "ArrowLeft" || e.key === "ArrowDown") next = clampSnap(val - step);
|
|
9072
9088
|
else if (e.key === "Home") next = min;
|