@columenlabs/lumen-ui 0.1.43 → 0.1.44
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.d.ts +1 -1
- package/dist/lumen-layout.js +3 -2
- package/dist/lumen-view.d.ts +31 -2
- package/dist/lumen-view.js +46 -17
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { type CustomViewConfig, LumenTable, type LumenTableProps, LumenView, type LumenViewProps, type ServerPaging, type ViewCellValue, type ViewChipTone, type ViewDomain, type ViewField, type ViewFieldGroup, type ViewSource, CHIP_TONE, RUN_STATE_TONE, FORMULAS_GROUP, ViewValueCell, rollUp, } from './lumen-view.js';
|
|
1
|
+
export { type CustomViewConfig, LumenTable, type LumenTableProps, LumenView, type LumenViewProps, type ServerGroup, type ServerGroups, type ServerPaging, type ViewCellValue, type ViewChipTone, type ViewDomain, type ViewField, type ViewFieldGroup, type ViewSource, CHIP_TONE, RUN_STATE_TONE, FORMULAS_GROUP, ViewValueCell, rollUp, } from './lumen-view.js';
|
|
2
2
|
export { LumenLayout, type LumenLayoutCard, type LumenLayoutProps, type LumenLayoutViewProps, domainKeys, followRows, } from './lumen-layout.js';
|
|
3
3
|
export { LumenViewCard, type LumenViewCardProps } from './lumen-view-card.js';
|
|
4
4
|
export { LumenSelector, LumenSelectorList, type LumenSelectorListHandle, type LumenSelectorProps, type LumenOption, type LumenOptionGroup, SelectorRowContent, } from './lumen-selector.js';
|
package/dist/lumen-layout.js
CHANGED
|
@@ -496,8 +496,9 @@ function ViewLayout({ crumbs, actions, meta, status, intro, cards: extra, lead,
|
|
|
496
496
|
const viewCard = mainTableOf(cards);
|
|
497
497
|
const viewOn = (k) => !viewCard || controlOn(viewCard, k);
|
|
498
498
|
const showBox = !hideFilter && viewOn('filter');
|
|
499
|
-
// A server's page cannot be grouped
|
|
500
|
-
|
|
499
|
+
// A server's page cannot be grouped (a group would bucket the one page only), unless the
|
|
500
|
+
// server groups it.
|
|
501
|
+
const groupButton = viewOn('group') && (!paging || paging.groups) ? group.button : null;
|
|
501
502
|
const viewFilter = !showBox && !groupButton ? undefined : (_jsxs(_Fragment, { children: [showBox && (_jsx(LumenTokenizedFilter, { filter: filter, label: `Filter ${config.name}`, className: "min-w-0 flex-1", saved: config.filters.default, link: {
|
|
502
503
|
color: viewColor,
|
|
503
504
|
onPick: (color) => links.setColor(viewCardId, color),
|
package/dist/lumen-view.d.ts
CHANGED
|
@@ -57,11 +57,37 @@ export interface ServerPaging {
|
|
|
57
57
|
onPage: (page: number) => void;
|
|
58
58
|
onSize?: (size: number) => void;
|
|
59
59
|
sizes?: readonly number[];
|
|
60
|
-
/** The columns the server sorts by; the rest take no header sort, and the view groups nothing
|
|
61
|
-
* since either would order or bucket one page only. */
|
|
60
|
+
/** The columns the server sorts by; the rest take no header sort, and the view groups nothing
|
|
61
|
+
* (unless `groups`), since either would order or bucket one page only. */
|
|
62
62
|
sorts?: readonly string[];
|
|
63
63
|
/** Told the sort held (a header click, a revert), to fetch the rows in that order. */
|
|
64
64
|
onSort?: (sort: CustomViewConfig['sort']) => void;
|
|
65
|
+
/** The server groups the rows: the Group button offers the domain's groupable fields, and a
|
|
66
|
+
* group's rows load when it opens. Without it a server's page groups nothing. */
|
|
67
|
+
groups?: ServerGroups;
|
|
68
|
+
}
|
|
69
|
+
/** One group a server counted: its key (the group field's value as the view shows it), its row
|
|
70
|
+
* count (null: not counted), and, once open, the rows loaded so far. */
|
|
71
|
+
export interface ServerGroup {
|
|
72
|
+
key: string;
|
|
73
|
+
n: number | null;
|
|
74
|
+
open: boolean;
|
|
75
|
+
/** The rows loaded for an open group, in the server's order. */
|
|
76
|
+
rows: unknown[];
|
|
77
|
+
/** The group has rows past those loaded: its Show more row loads the next. */
|
|
78
|
+
more?: () => void;
|
|
79
|
+
/** Its rows are loading. */
|
|
80
|
+
loading?: boolean;
|
|
81
|
+
}
|
|
82
|
+
export interface ServerGroups {
|
|
83
|
+
/** Told the field the person groups by (null: none), to fetch that field's groups. */
|
|
84
|
+
onGroup: (key: string | null) => void;
|
|
85
|
+
/** The picked field's groups, in order; null while they load. */
|
|
86
|
+
list: ServerGroup[] | null;
|
|
87
|
+
/** Groups past those listed: a More groups row asks for them. */
|
|
88
|
+
more?: () => void;
|
|
89
|
+
/** A group header's click: open or close it. */
|
|
90
|
+
onToggle: (key: string) => void;
|
|
65
91
|
}
|
|
66
92
|
export interface LumenViewProps<T> {
|
|
67
93
|
/** The view's domain, its formula columns included (`withViewFields`). */
|
|
@@ -195,4 +221,7 @@ export interface LumenTableProps<T> {
|
|
|
195
221
|
total?: boolean;
|
|
196
222
|
/** What each row opens under it (`subgroupOf`); null: rows open nothing but their panel. */
|
|
197
223
|
subgroup?: ViewSubgroup<T> | null;
|
|
224
|
+
/** The groups come from a server (`ServerPaging.groups`): their order, counts and open state,
|
|
225
|
+
* and each open group's rows. */
|
|
226
|
+
serverGroups?: ServerGroups | null;
|
|
198
227
|
}
|
package/dist/lumen-view.js
CHANGED
|
@@ -234,8 +234,12 @@ export function LumenView({ domain, config, rows, total = rows.length, paging: s
|
|
|
234
234
|
// scrolls with the page.
|
|
235
235
|
const inLayout = inScroller && !cell;
|
|
236
236
|
const columns = pick(domain.fields, config.columns);
|
|
237
|
-
// A server's page groups and pivots nothing
|
|
238
|
-
|
|
237
|
+
// A server's page groups and pivots nothing (either would cover the one page only), unless the
|
|
238
|
+
// server groups it.
|
|
239
|
+
const groupBy = server && !server.groups ? null : pickedGroup;
|
|
240
|
+
const served = server?.groups && groupBy ? server.groups : null;
|
|
241
|
+
const onGroup = server?.groups?.onGroup;
|
|
242
|
+
useEffect(() => onGroup?.(groupBy?.key ?? null), [onGroup, groupBy?.key]);
|
|
239
243
|
const pivot = server ? false : pickedPivot;
|
|
240
244
|
// Live columns on screen keep their source reading while the market trades (#861).
|
|
241
245
|
const load = useLiveLoad(sourceLoad, columns.some((c) => {
|
|
@@ -243,7 +247,9 @@ export function LumenView({ domain, config, rows, total = rows.length, paging: s
|
|
|
243
247
|
return r === 'live' || r === 'calc';
|
|
244
248
|
}));
|
|
245
249
|
const chips = chipsOf(config);
|
|
246
|
-
|
|
250
|
+
// Server groups: the open groups' rows, each object once (a row in two groups shows in both).
|
|
251
|
+
const groupRows = useMemo(() => served ? [...new Set((served.list ?? []).flatMap((g) => (g.open ? g.rows : [])))] : null, [served]);
|
|
252
|
+
const tableRows = useMemo(() => groupRows ?? mergeRows(domain, rows, groupBy), [groupRows, domain, rows, groupBy]);
|
|
247
253
|
const amountsHidden = useAmountsHidden();
|
|
248
254
|
// Flat tables page their rows, 25 a page unless the view says otherwise; the size picker and
|
|
249
255
|
// the page buttons sit in the card's header. Views saved before then
|
|
@@ -281,9 +287,10 @@ export function LumenView({ domain, config, rows, total = rows.length, paging: s
|
|
|
281
287
|
return [...out].slice(0, MAX_COMPARE);
|
|
282
288
|
}, [selection, chartField, rows, domain]);
|
|
283
289
|
const compare = openChart && picked.length > 1 ? (_jsx(IconButton, { icon: ChartSpline, label: `Compare ${picked.join(', ')}`, variant: "outline", onClick: () => openChart(picked) })) : null;
|
|
284
|
-
// A server's page: the pager counts from the server's total, or the rows seen so far.
|
|
285
|
-
|
|
286
|
-
const
|
|
290
|
+
// A server's page: the pager counts from the server's total, or the rows seen so far. Server
|
|
291
|
+
// groups page themselves: the header counts them.
|
|
292
|
+
const pager = served ? (_jsx("span", { className: "num px-2 text-xs text-muted-foreground", children: served.list ? `${served.list.length.toLocaleString()}${served.more ? '+' : ''} groups` : '' })) : server ? (_jsx(LumenPager, { total: server.total ?? server.page * server.size + rows.length, page: server.page, size: server.size, onPage: server.onPage, onSize: server.onSize ?? (() => { }), sizes: server.sizes ?? [server.size], more: server.total === null && server.more })) : paging ? (_jsx(LumenPager, { total: tableRows.length, page: page, size: pageSize, onPage: setPageIndex, onSize: setPageSize, noun: rows.length === total ? 'rows' : `of ${total} rows` })) : (_jsx("span", { className: "num px-2 text-xs text-muted-foreground", children: count }));
|
|
293
|
+
const table = pivot && config.pivot ? (_jsx(PivotTable, { domain: domain, rows: rows, pivot: config.pivot })) : (_jsx(LumenTable, { domain: domain, columns: columns, rows: tableRows, groupBy: groupBy, subgroup: sub, chips: chips, page: paging ? { index: page, size: pageSize } : null, inView: inLayout, fit: fit, onDetails: onDetails, tapped: tapped, selection: selection, groupActions: groupActions, sort: sort, onSort: onSort, serverSorts: server ? (server.sorts ?? []) : undefined, serverGroups: served, total: config.total !== false, add: onAddColumn || onColumns
|
|
287
294
|
? { ...onAddColumn, field: onColumns && { domain, columns, onColumns } }
|
|
288
295
|
: undefined }));
|
|
289
296
|
return (_jsx(LumenWidget, { id: cardId, kind: "table", style: "table", title: title, controls: controls, tools: state ? (tools) : (_jsxs(_Fragment, { children: [tools, compare, pager, onColumns && !onAddColumn && on('columns') && (_jsx(ColumnPicker, { domain: domain, columns: columns, onColumns: onColumns })), !pivot && on('download') && (_jsx(IconButton, { icon: DownloadIcon, label: "Download CSV", onClick: () => downloadCsv({
|
|
@@ -359,7 +366,7 @@ function sortingOf(sort, columns, serverSorts) {
|
|
|
359
366
|
return [];
|
|
360
367
|
return columns.some((f) => f.key === sort.key) ? [{ id: sort.key, desc: sort.desc }] : [];
|
|
361
368
|
}
|
|
362
|
-
function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null, chips = [], page = null, inView = false, fit = false, onDetails, tapped, selection, groupActions, sort, onSort, serverSorts, total = true, subgroup = null, add, }) {
|
|
369
|
+
function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null, chips = [], page = null, inView = false, fit = false, onDetails, tapped, selection, groupActions, sort, onSort, serverSorts, total = true, subgroup = null, add, serverGroups = null, }) {
|
|
363
370
|
const [sorting, setSorting] = useState(() => sortingOf(sort, columns, serverSorts));
|
|
364
371
|
// A saved sort patched while the table is open (the assistant's card move) applies at once.
|
|
365
372
|
const savedSort = JSON.stringify(sort ?? null);
|
|
@@ -507,6 +514,10 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
507
514
|
const groups = useMemo(() => {
|
|
508
515
|
if (!groupBy)
|
|
509
516
|
return null;
|
|
517
|
+
if (serverGroups) {
|
|
518
|
+
const byRow = new Map(sorted.map((r) => [r.original, r]));
|
|
519
|
+
return (serverGroups.list ?? []).map((g) => [g.key, g.rows.flatMap((o) => byRow.get(o) ?? [])]);
|
|
520
|
+
}
|
|
510
521
|
const m = new Map();
|
|
511
522
|
for (const r of sorted) {
|
|
512
523
|
const k = label(groupBy.value(r.original));
|
|
@@ -514,10 +525,11 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
514
525
|
b ? b.push(r) : m.set(k, [r]);
|
|
515
526
|
}
|
|
516
527
|
return [...m];
|
|
517
|
-
}, [groupBy, sorted]);
|
|
528
|
+
}, [groupBy, sorted, serverGroups]);
|
|
518
529
|
const span = shown.length + (selection ? 1 : 0);
|
|
530
|
+
const served = new Map((serverGroups?.list ?? []).map((g) => [g.key, g]));
|
|
519
531
|
const startsOpen = (i) => rows.length <= OPEN_ALL || i === 0;
|
|
520
|
-
const isOpen = (key, i) => startsOpen(i) !== flipped.has(key);
|
|
532
|
+
const isOpen = (key, i) => serverGroups ? !!served.get(key)?.open : startsOpen(i) !== flipped.has(key);
|
|
521
533
|
const anyClosed = !!groups?.some(([k], i) => !isOpen(k, i));
|
|
522
534
|
const setAll = (open) => setFlipped(new Set((groups ?? []).filter((_, i) => startsOpen(i) !== open).map(([k]) => k)));
|
|
523
535
|
const keyOf = domain.rowKey;
|
|
@@ -534,7 +546,8 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
534
546
|
const someOn = allKeys.some((k) => selection?.keys.has(k));
|
|
535
547
|
const selectCell = (key, name) => selection && (_jsx(TableCell, { className: "w-8 pr-0", onClick: (e) => e.stopPropagation(), children: _jsx(Checkbox, { checked: selection.keys.has(key), onCheckedChange: (on) => toggle([key], on === true), "aria-label": `Select ${name}` }) }));
|
|
536
548
|
const [openParts, setOpenParts] = useState(new Set());
|
|
537
|
-
|
|
549
|
+
// A server group's roll-ups would add up its loaded rows only, so they and the Total stay off.
|
|
550
|
+
const hasTotal = total && !serverGroups && shown.some(rollsUp);
|
|
538
551
|
// A group row's label spans the leading columns that roll nothing up.
|
|
539
552
|
const rolls = (f) => !f.noRollup && (!!f.aggregate || !!f.rollFormula || !!f.share);
|
|
540
553
|
const lead = Math.max(1, shown.findIndex((f, i) => i > 0 && rolls(f)) < 0
|
|
@@ -608,6 +621,17 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
608
621
|
_jsx(TableRow, { "data-more": true, children: _jsx(TableCell, { colSpan: span, className: "py-1", children: _jsxs(Button, { variant: "ghost", size: "xs", onClick: () => setMore((m) => new Map(m).set(scope, limit + DRAW_STEP)), children: [_jsx(ChevronsDownIcon, {}), "Show ", Math.min(left, DRAW_STEP).toLocaleString(), " more", _jsxs("span", { className: "num font-normal text-muted-foreground", children: ["of ", left.toLocaleString()] })] }) }) }, `${scope}:more`),
|
|
609
622
|
];
|
|
610
623
|
};
|
|
624
|
+
// A server group's rows as loaded, then its Show more (the server's next rows) or loading row.
|
|
625
|
+
const servedRows = (list, key) => {
|
|
626
|
+
const g = served.get(key);
|
|
627
|
+
const out = rowsOf(list, key);
|
|
628
|
+
if (!g?.more && !g?.loading)
|
|
629
|
+
return out;
|
|
630
|
+
return [
|
|
631
|
+
...out,
|
|
632
|
+
_jsx(TableRow, { "data-more": true, children: _jsx(TableCell, { colSpan: span, className: "py-1", children: g.loading ? (_jsx("span", { className: "px-2 text-xs text-muted-foreground", children: "Loading\u2026" })) : (_jsxs(Button, { variant: "ghost", size: "xs", onClick: g.more, children: [_jsx(ChevronsDownIcon, {}), "Show more", g.n !== null && (_jsxs("span", { className: "num font-normal text-muted-foreground", children: ["of ", (g.n - list.length).toLocaleString()] }))] })) }) }, `${key}:more`),
|
|
633
|
+
];
|
|
634
|
+
};
|
|
611
635
|
const box = useRef(null);
|
|
612
636
|
useFloatingHead(box, !inView);
|
|
613
637
|
return (_jsx("div", { ref: box, className: cn(inView ? IN_VIEW : 'overflow-x-auto overflow-y-hidden [--pin-top:0px]', fit && FIT), children: _jsxs(Table, { children: [_jsx(TableHeader, { children: table.getHeaderGroups().map((hg) => (_jsxs(TableRow, { children: [selection && (_jsx(TableHead, { className: cn('w-8 pr-0', PINNED_HEAD), children: _jsx(Checkbox, { checked: allOn ? true : someOn ? 'indeterminate' : false, onCheckedChange: (on) => toggle(allKeys, on === true), "aria-label": "Select every row" }) })), hg.headers.map((h, i) => (_jsxs(TableHead, { className: cn(colOf(shown[i]), PINNED_HEAD), style: ruleOf(colorOf(domain, shown[i])), onPointerDown: pressStart, onPointerUp: pressEnd, onPointerLeave: pressEnd, onPointerCancel: pressEnd, onContextMenu: (e) => {
|
|
@@ -617,20 +641,25 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
617
641
|
? 'ascending'
|
|
618
642
|
: h.column.getIsSorted() === 'desc'
|
|
619
643
|
? 'descending'
|
|
620
|
-
: undefined, children: [i === 0 && groups && (_jsx(IconButton, { icon: anyClosed ? ChevronsUpDownIcon : ChevronsDownUpIcon, size: "icon-xs", className: "-ml-2 mr-1 align-middle", label: anyClosed ? 'Expand all groups' : 'Collapse all groups', onClick: () => setAll(anyClosed) })), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "xs", className: cn('font-medium', !(i === 0 && groups) && '-mx-2'), style: { color: colorOf(domain, shown[i]) ?? undefined }, onClick: h.column.getCanSort() ? h.column.getToggleSortingHandler() : undefined, children: [shown[i] ? _jsx(FreshnessMark, { domain: domain, field: shown[i] }) : null, flexRender(h.column.columnDef.header, h.getContext()), _jsx(SortIcon, { dir: h.column.getIsSorted() })] }) }), shown[i] && (domain.groups?.length || freshnessOf(domain, shown[i])) ? (_jsxs(TooltipContent, { children: [domain.groups?.length ? _jsx("div", { children: pathOf(domain, shown[i]) }) : null, freshnessLine(domain, shown[i]) ? (_jsx("div", { children: freshnessLine(domain, shown[i]) })) : null] })) : null] })] }, h.id))), add && (_jsx(TableHead, { className: cn('w-8 pl-1', PINNED_HEAD), children: _jsx(AddColumnMenu, { add: add, fieldOpen: fieldOpen, onFieldOpen: setFieldOpen }) }))] }, hg.id))) }), _jsxs(TableBody, { children: [!rows.length && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: span, className: "py-6 text-center text-muted-foreground", children: "No rows match." }) })), groups && groupBy
|
|
644
|
+
: undefined, children: [i === 0 && groups && !serverGroups && (_jsx(IconButton, { icon: anyClosed ? ChevronsUpDownIcon : ChevronsDownUpIcon, size: "icon-xs", className: "-ml-2 mr-1 align-middle", label: anyClosed ? 'Expand all groups' : 'Collapse all groups', onClick: () => setAll(anyClosed) })), _jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { asChild: true, children: _jsxs(Button, { variant: "ghost", size: "xs", className: cn('font-medium', !(i === 0 && groups) && '-mx-2'), style: { color: colorOf(domain, shown[i]) ?? undefined }, onClick: h.column.getCanSort() ? h.column.getToggleSortingHandler() : undefined, children: [shown[i] ? _jsx(FreshnessMark, { domain: domain, field: shown[i] }) : null, flexRender(h.column.columnDef.header, h.getContext()), _jsx(SortIcon, { dir: h.column.getIsSorted() })] }) }), shown[i] && (domain.groups?.length || freshnessOf(domain, shown[i])) ? (_jsxs(TooltipContent, { children: [domain.groups?.length ? _jsx("div", { children: pathOf(domain, shown[i]) }) : null, freshnessLine(domain, shown[i]) ? (_jsx("div", { children: freshnessLine(domain, shown[i]) })) : null] })) : null] })] }, h.id))), add && (_jsx(TableHead, { className: cn('w-8 pl-1', PINNED_HEAD), children: _jsx(AddColumnMenu, { add: add, fieldOpen: fieldOpen, onFieldOpen: setFieldOpen }) }))] }, hg.id))) }), _jsxs(TableBody, { children: [!rows.length && (_jsx(TableRow, { children: _jsx(TableCell, { colSpan: span, className: "py-6 text-center text-muted-foreground", children: "No rows match." }) })), groups && groupBy
|
|
621
645
|
? groups.map(([key, members], gi) => {
|
|
622
646
|
const open = isOpen(key, gi);
|
|
623
647
|
return (_jsxs(Fragment, { children: [_jsxs(TableRow, { className: ROLLUP, "data-group": key, children: [selection && (_jsx(TableCell, { className: cn('w-8 pr-0', PINNED_GROUP), children: _jsx(Checkbox, { checked: members.every((m) => selection.keys.has(keyOf(m.original)))
|
|
624
648
|
? true
|
|
625
649
|
: members.some((m) => selection.keys.has(keyOf(m.original)))
|
|
626
650
|
? 'indeterminate'
|
|
627
|
-
: false, onCheckedChange: (on) => toggle(members.map((m) => keyOf(m.original)), on === true), "aria-label": `Select every row of ${key}` }) })), shown.slice(lead - 1).map((f, i) => i === 0 ? (_jsxs(TableCell, { colSpan: lead, className: PINNED_GROUP, children: [_jsxs(Button, { variant: "ghost", size: "xs", className: "-mx-2 hover:bg-transparent aria-expanded:bg-transparent", "aria-expanded": open, "aria-label": `${open ? 'Collapse' : 'Expand'} ${key}`, onClick: () =>
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
651
|
+
: false, onCheckedChange: (on) => toggle(members.map((m) => keyOf(m.original)), on === true), "aria-label": `Select every row of ${key}` }) })), shown.slice(lead - 1).map((f, i) => i === 0 ? (_jsxs(TableCell, { colSpan: lead, className: PINNED_GROUP, children: [_jsxs(Button, { variant: "ghost", size: "xs", className: "-mx-2 hover:bg-transparent aria-expanded:bg-transparent", "aria-expanded": open, "aria-label": `${open ? 'Collapse' : 'Expand'} ${key}`, onClick: () => serverGroups
|
|
652
|
+
? serverGroups.onToggle(key)
|
|
653
|
+
: setFlipped((c) => {
|
|
654
|
+
const n = new Set(c);
|
|
655
|
+
n.has(key) ? n.delete(key) : n.add(key);
|
|
656
|
+
return n;
|
|
657
|
+
}), children: [_jsx(ChevronRightIcon, { className: cn('transition-transform', open && 'rotate-90') }), _jsx(groupBy.icon, {}), key, _jsx("span", { className: "num font-normal text-muted-foreground", children: serverGroups
|
|
658
|
+
? (served.get(key)?.n?.toLocaleString() ?? '')
|
|
659
|
+
: members.length })] }), groupActions?.(key, members.map((m) => m.original))] }, f.key)) : (_jsx(TableCell, { className: cn(colOf(f), PINNED_GROUP), children: !serverGroups &&
|
|
660
|
+
rollCell(f, members.map((m) => m.original)) }, f.key)))] }), open && (serverGroups ? servedRows(members, key) : drawn(members, key))] }, key));
|
|
632
661
|
})
|
|
633
|
-
: drawn(sorted, ''), hasTotal && rows.length > 0 && (_jsxs(TableRow, { className: cn(ROLLUP, 'border-t-2'), "data-total": true, children: [selection && _jsx(TableCell, {}), rollCells(rows).map((cell, i) => i === 0 && !(shown[0] && rollsUp(shown[0])) ? (_jsx(TableCell, { children: "Total" }, "total")) : (cell))] }))] })] }) }));
|
|
662
|
+
: drawn(sorted, ''), serverGroups?.more && (_jsx(TableRow, { "data-more": true, children: _jsx(TableCell, { colSpan: span, className: "py-1", children: _jsxs(Button, { variant: "ghost", size: "xs", onClick: serverGroups.more, children: [_jsx(ChevronsDownIcon, {}), "More groups"] }) }) })), hasTotal && rows.length > 0 && (_jsxs(TableRow, { className: cn(ROLLUP, 'border-t-2'), "data-total": true, children: [selection && _jsx(TableCell, {}), rollCells(rows).map((cell, i) => i === 0 && !(shown[0] && rollsUp(shown[0])) ? (_jsx(TableCell, { children: "Total" }, "total")) : (cell))] }))] })] }) }));
|
|
634
663
|
}
|
|
635
664
|
/** One value rolled up into a rows × columns grid, with totals where the roll-up adds. */
|
|
636
665
|
function PivotTable({ domain, rows, pivot, }) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.44",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"@codemirror/lang-javascript": "6.2.5",
|
|
42
42
|
"@codemirror/lang-json": "6.0.2",
|
|
43
43
|
"@codemirror/lang-sql": "6.10.0",
|
|
44
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
44
|
+
"@columenlabs/lumen-ui-types": "0.1.44",
|
|
45
45
|
"@dnd-kit/core": "6.3.1",
|
|
46
46
|
"@dnd-kit/sortable": "10.0.0",
|
|
47
47
|
"@dnd-kit/utilities": "3.2.2",
|