@columenlabs/lumen-ui 0.1.32 → 0.1.34
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/coverage-cells.d.ts +10 -3
- package/dist/coverage-cells.js +27 -11
- package/dist/coverage-map.d.ts +4 -2
- package/dist/coverage-map.js +13 -7
- package/dist/theme.css +3 -0
- package/package.json +2 -2
package/dist/coverage-cells.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { type ReactNode } from 'react';
|
|
2
2
|
/** A backfill's state on a block it touches; it wins over coverage while the job runs. */
|
|
3
|
-
|
|
3
|
+
/** `indexing`: the block's copy is done and a follow-up step (an index, a rollup) is still running on it. */
|
|
4
|
+
export type CoverageJobState = 'queued' | 'running' | 'indexing' | 'failed' | 'canceled';
|
|
4
5
|
/** One cell's state. Done is not its own state: a finished block simply turns `full`. */
|
|
5
6
|
export type CoverageLevel = 'full' | 'high' | 'low' | 'gap' | 'current' | 'none' | CoverageJobState;
|
|
7
|
+
/** `swatch`: the legend's look when it differs from a cell's (a part-filled cell fills to its share). */
|
|
6
8
|
export declare const COVERAGE_LEVELS: {
|
|
7
9
|
level: CoverageLevel;
|
|
8
10
|
label: string;
|
|
9
11
|
className: string;
|
|
12
|
+
swatch?: string;
|
|
10
13
|
}[];
|
|
11
14
|
export declare const coverageLabel: (l: CoverageLevel) => string;
|
|
12
15
|
export declare const coverageClass: (l: CoverageLevel) => string;
|
|
@@ -18,18 +21,22 @@ export declare function coverageLevel(have: number, expected: number, { current,
|
|
|
18
21
|
/** The job state that shows when a block holds several. */
|
|
19
22
|
export declare const firstJobState: (a: CoverageJobState | null, b: CoverageJobState | undefined) => CoverageJobState | null;
|
|
20
23
|
/** The states on screen, in the legend's order, with a hint at the right. */
|
|
21
|
-
export declare function CoverageLegend({ levels, hint }: {
|
|
24
|
+
export declare function CoverageLegend({ levels, hint, labels, }: {
|
|
22
25
|
levels: Set<CoverageLevel>;
|
|
23
26
|
hint?: ReactNode;
|
|
27
|
+
/** An app's own words for some states (`running`: `Copying`). */
|
|
28
|
+
labels?: Partial<Record<CoverageLevel, string>>;
|
|
24
29
|
}): import("react").JSX.Element;
|
|
25
30
|
/**
|
|
26
31
|
* One cell: a plain button. Its tooltip is the map's one shared `CoverageTip` (a Radix tooltip per
|
|
27
32
|
* cell made a 100-row map 13,000 tooltips, seconds per render). `label` is the
|
|
28
33
|
* accessible name and the tooltip's first line; `tip` marks the cell for the shared tooltip.
|
|
29
34
|
*/
|
|
30
|
-
export declare const CoverageCell: import("react").MemoExoticComponent<({ level, label, tip, picked, disabled, pickable, onClick, className, }: {
|
|
35
|
+
export declare const CoverageCell: import("react").MemoExoticComponent<({ level, label, tip, picked, disabled, pickable, onClick, className, fill, }: {
|
|
31
36
|
level: CoverageLevel;
|
|
32
37
|
label: string;
|
|
38
|
+
/** The share in hand (0–1): a part-done block fills to it from the left, whatever its state. */
|
|
39
|
+
fill?: number;
|
|
33
40
|
/** What `CoverageTip` hands back to its `content` for this cell. */
|
|
34
41
|
tip: string;
|
|
35
42
|
picked?: boolean;
|
package/dist/coverage-cells.js
CHANGED
|
@@ -4,10 +4,21 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
import { memo, useRef, useState } from 'react';
|
|
5
5
|
import { cn } from './lib/utils.js';
|
|
6
6
|
import { Tooltip, TooltipContent, TooltipTrigger } from './ui/tooltip.js';
|
|
7
|
+
/** `swatch`: the legend's look when it differs from a cell's (a part-filled cell fills to its share). */
|
|
7
8
|
export const COVERAGE_LEVELS = [
|
|
8
9
|
{ level: 'full', label: 'Complete', className: 'bg-cov-full' },
|
|
9
|
-
{
|
|
10
|
-
|
|
10
|
+
{
|
|
11
|
+
level: 'high',
|
|
12
|
+
label: '95–99%',
|
|
13
|
+
className: 'ring-1 ring-inset ring-cov-full',
|
|
14
|
+
swatch: 'bg-[linear-gradient(90deg,var(--cov-full)_0_80%,transparent_80%)] ring-1 ring-inset ring-cov-full',
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
level: 'low',
|
|
18
|
+
label: 'Under 95%',
|
|
19
|
+
className: 'ring-1 ring-inset ring-cov-full',
|
|
20
|
+
swatch: 'bg-[linear-gradient(90deg,var(--cov-full)_0_40%,transparent_40%)] ring-1 ring-inset ring-cov-full',
|
|
21
|
+
},
|
|
11
22
|
{ level: 'gap', label: 'Missing', className: 'bg-gap-hatch' },
|
|
12
23
|
{
|
|
13
24
|
level: 'current',
|
|
@@ -21,13 +32,18 @@ export const COVERAGE_LEVELS = [
|
|
|
21
32
|
className: 'outline-1 outline-dashed -outline-offset-1 outline-primary',
|
|
22
33
|
},
|
|
23
34
|
{ level: 'running', label: 'Running', className: 'bg-cov-running' },
|
|
24
|
-
{ level: '
|
|
35
|
+
{ level: 'indexing', label: 'Indexing', className: 'bg-cov-indexing' },
|
|
36
|
+
{
|
|
37
|
+
level: 'failed',
|
|
38
|
+
label: 'Failed',
|
|
39
|
+
className: 'bg-destructive/15 outline-2 -outline-offset-2 outline-destructive',
|
|
40
|
+
},
|
|
25
41
|
{ level: 'canceled', label: 'Canceled', className: 'bg-cov-canceled' },
|
|
26
42
|
];
|
|
27
43
|
const BY_LEVEL = Object.fromEntries(COVERAGE_LEVELS.map((l) => [l.level, l]));
|
|
28
44
|
export const coverageLabel = (l) => BY_LEVEL[l].label;
|
|
29
45
|
export const coverageClass = (l) => BY_LEVEL[l].className;
|
|
30
|
-
const JOB_ORDER = ['running', 'queued', 'failed', 'canceled'];
|
|
46
|
+
const JOB_ORDER = ['running', 'indexing', 'queued', 'failed', 'canceled'];
|
|
31
47
|
/** The state of a block from its sums: a job state first, then coverage. */
|
|
32
48
|
export function coverageLevel(have, expected, { current = false, state } = {}) {
|
|
33
49
|
if (state)
|
|
@@ -43,22 +59,22 @@ export function coverageLevel(have, expected, { current = false, state } = {}) {
|
|
|
43
59
|
/** The job state that shows when a block holds several. */
|
|
44
60
|
export const firstJobState = (a, b) => !b ? a : !a || JOB_ORDER.indexOf(b) < JOB_ORDER.indexOf(a) ? b : a;
|
|
45
61
|
/** The states on screen, in the legend's order, with a hint at the right. */
|
|
46
|
-
export function CoverageLegend({ levels, hint }) {
|
|
47
|
-
return (_jsxs("div", { className: "flex flex-wrap items-center gap-x-5 gap-y-2 text-xs text-muted-foreground", children: [COVERAGE_LEVELS.filter((l) => levels.has(l.level)).map((l) => (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { "aria-hidden": true, className: cn('h-3 w-4 rounded-[3px]', l.className) }), l.label] }, l.level))), hint && _jsx("span", { className: "ml-auto hidden md:inline", children: hint })] }));
|
|
62
|
+
export function CoverageLegend({ levels, hint, labels, }) {
|
|
63
|
+
return (_jsxs("div", { className: "flex flex-wrap items-center gap-x-5 gap-y-2 text-xs text-muted-foreground", children: [COVERAGE_LEVELS.filter((l) => levels.has(l.level)).map((l) => (_jsxs("span", { className: "flex items-center gap-1.5", children: [_jsx("span", { "aria-hidden": true, className: cn('h-3 w-4 rounded-[3px]', l.swatch ?? l.className) }), labels?.[l.level] ?? l.label] }, l.level))), hint && _jsx("span", { className: "ml-auto hidden md:inline", children: hint })] }));
|
|
48
64
|
}
|
|
49
65
|
/**
|
|
50
66
|
* One cell: a plain button. Its tooltip is the map's one shared `CoverageTip` (a Radix tooltip per
|
|
51
67
|
* cell made a 100-row map 13,000 tooltips, seconds per render). `label` is the
|
|
52
68
|
* accessible name and the tooltip's first line; `tip` marks the cell for the shared tooltip.
|
|
53
69
|
*/
|
|
54
|
-
export const CoverageCell = memo(function CoverageCell({ level, label, tip, picked = false, disabled = false, pickable = false, onClick, className, }) {
|
|
55
|
-
return (_jsx("button", { type: "button", "data-cell": tip, "aria-label": `${label}: ${coverageLabel(level)}`, "aria-pressed": pickable && !disabled ? picked : undefined, disabled: disabled, onClick: onClick, className: cn('min-w-0 rounded-[3px] p-0 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default', coverageClass(level),
|
|
70
|
+
export const CoverageCell = memo(function CoverageCell({ level, label, tip, picked = false, disabled = false, pickable = false, onClick, className, fill, }) {
|
|
71
|
+
return (_jsx("button", { type: "button", "data-cell": tip, "aria-label": `${label}: ${coverageLabel(level)}`, "aria-pressed": pickable && !disabled ? picked : undefined, disabled: disabled, onClick: onClick, className: cn('min-w-0 rounded-[3px] p-0 focus-visible:ring-2 focus-visible:ring-ring disabled:cursor-default', coverageClass(level), 'relative overflow-hidden',
|
|
56
72
|
// outline-none would also hide the picked outline, so a picked cell must not carry it.
|
|
57
73
|
picked
|
|
58
74
|
? 'outline-2 outline-offset-1 outline-foreground'
|
|
59
|
-
: level === 'queued'
|
|
75
|
+
: level === 'queued' || level === 'failed'
|
|
60
76
|
? ''
|
|
61
|
-
: 'outline-none', pickable && !disabled && 'cursor-pointer', className) }));
|
|
77
|
+
: 'outline-none', pickable && !disabled && 'cursor-pointer', className), children: fill !== undefined && fill > 0 && fill < 1 && (_jsx("span", { "aria-hidden": true, className: "pointer-events-none absolute inset-y-0 left-0 bg-cov-full", style: { width: `${Math.round(fill * 100)}%` } })) }));
|
|
62
78
|
});
|
|
63
79
|
/**
|
|
64
80
|
* The one tooltip of a coverage map: it follows the cell under the pointer or keyboard focus inside
|
|
@@ -81,5 +97,5 @@ export function CoverageTip({ content, children, className, }) {
|
|
|
81
97
|
: { tip, x: r.left - o.left, y: r.top - o.top, w: r.width, h: r.height });
|
|
82
98
|
};
|
|
83
99
|
const body = at ? content(at.tip) : null;
|
|
84
|
-
return (_jsxs("div", { ref: box, className: cn('relative', className), onPointerOver: (e) => e.pointerType !== 'touch' && show(e.target), onPointerLeave: () => setAt(null), onFocus: (e) => show(e.target), onBlur: () => setAt(null), children: [children, at && body && (_jsxs(Tooltip, { open: true, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { "aria-hidden": true, className: "pointer-events-none absolute", style: { left: at.x, top: at.y, width: at.w, height: at.h } }) }),
|
|
100
|
+
return (_jsxs("div", { ref: box, className: cn('relative', className), onPointerOver: (e) => e.pointerType !== 'touch' && show(e.target), onPointerLeave: () => setAt(null), onFocus: (e) => show(e.target), onBlur: () => setAt(null), children: [children, at && body && (_jsxs(Tooltip, { open: true, children: [_jsx(TooltipTrigger, { asChild: true, children: _jsx("span", { "aria-hidden": true, className: "pointer-events-none absolute", style: { left: at.x, top: at.y, width: at.w, height: at.h } }) }), _jsx(TooltipContent, { className: "num max-w-72", children: _jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("div", { className: "font-medium", children: body.label }), body.detail] }) })] }, at.tip))] }));
|
|
85
101
|
}
|
package/dist/coverage-map.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { QueryKey, UseQueryOptions } from '@tanstack/react-query';
|
|
2
2
|
import { type LucideIcon } from 'lucide-react';
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
|
-
import { type CoverageJobState } from './coverage-cells.js';
|
|
4
|
+
import { type CoverageJobState, type CoverageLevel } from './coverage-cells.js';
|
|
5
5
|
/** One count at the finest grain a page has: a day (`2026-10-12`) or a month (`2026-10`). */
|
|
6
6
|
export interface CoverageFact {
|
|
7
7
|
row: string;
|
|
@@ -84,6 +84,8 @@ export interface LumenCoverageMapProps<TRaw = unknown, TKey extends QueryKey = Q
|
|
|
84
84
|
/** Months already queued that a pick can take back out, with the bar's Remove from queue. */
|
|
85
85
|
removable?: (row: string, month: string) => boolean;
|
|
86
86
|
onRemove?: (pick: CoveragePick) => Promise<unknown> | undefined;
|
|
87
|
+
/** An app's own words for some states, in the tooltip and legend (`{ running: 'Copying' }`). */
|
|
88
|
+
stateLabels?: Partial<Record<CoverageLevel, string>>;
|
|
87
89
|
/** Picks these months as if clicked (pass a new object each time); nothing is queued until the bar's button. */
|
|
88
90
|
preselect?: CoveragePick;
|
|
89
91
|
/** The drilled block (`2026-09`) and the click that changes it. */
|
|
@@ -119,4 +121,4 @@ export interface LumenCoverageMapProps<TRaw = unknown, TKey extends QueryKey = Q
|
|
|
119
121
|
export declare function blockOf(period: string, block: CoverageBlock): string;
|
|
120
122
|
/** `2026-09` → `Sep 2026`, `2026-Q3` → `2026 Q3`, days stay as they are. */
|
|
121
123
|
export declare function blockName(key: string): string;
|
|
122
|
-
export declare function LumenCoverageMap<TRaw, TKey extends QueryKey>({ source, title, icon, rows: rowSpec, layout, block: initialBlock, zoom, window, unit, summary, select, selectable, onQueue, queueLabel, pickNote, removable, onRemove, preselect, drilled, onDrill, groupBy, hint, pageSize: initialPageSize, pager, tools, filter, filterCount, empty, lazy, }: LumenCoverageMapProps<TRaw, TKey>): import("react").JSX.Element;
|
|
124
|
+
export declare function LumenCoverageMap<TRaw, TKey extends QueryKey>({ source, title, icon, rows: rowSpec, layout, block: initialBlock, zoom, window, unit, summary, select, selectable, onQueue, queueLabel, pickNote, removable, onRemove, preselect, stateLabels, drilled, onDrill, groupBy, hint, pageSize: initialPageSize, pager, tools, filter, filterCount, empty, lazy, }: LumenCoverageMapProps<TRaw, TKey>): import("react").JSX.Element;
|
package/dist/coverage-map.js
CHANGED
|
@@ -189,7 +189,7 @@ const MapRow = memo(function MapRow({ r, cols, marks, picks, total, look, }) {
|
|
|
189
189
|
const m = marks[i];
|
|
190
190
|
if (!m)
|
|
191
191
|
return _jsx("span", {}, k);
|
|
192
|
-
return (_jsx(CoverageCell, { level: m.level, label: `${text} · ${blockName(k)}`, tip: `${r.row}|${k}`, picked: picks.includes(k) || look.drilled === k, pickable: look.select === 'backfill' || look.select === 'drill', disabled: look.select === 'backfill' ? !m.canPick : look.select !== 'drill', className: "h-[18px]" }, k));
|
|
192
|
+
return (_jsx(CoverageCell, { level: m.level, fill: m.fill, label: `${text} · ${blockName(k)}`, tip: `${r.row}|${k}`, picked: picks.includes(k) || look.drilled === k, pickable: look.select === 'backfill' || look.select === 'drill', disabled: look.select === 'backfill' ? !m.canPick : look.select !== 'drill', className: "h-[18px]" }, k));
|
|
193
193
|
}), look.sums.map((s) => (_jsx("span", { className: cn('num pl-3 text-right text-xs whitespace-nowrap', s !== 'complete' && 'text-muted-foreground'), children: s === 'complete'
|
|
194
194
|
? fmtPct(total.have, total.expected)
|
|
195
195
|
: s === 'first'
|
|
@@ -200,7 +200,7 @@ const MapRow = memo(function MapRow({ r, cols, marks, picks, total, look, }) {
|
|
|
200
200
|
? fmtCounts(total.have, total.expected)
|
|
201
201
|
: fmtInt(total.have) }, s)))] }));
|
|
202
202
|
}, (a, b) => a.sig === b.sig && sameNode(a.r.badge, b.r.badge));
|
|
203
|
-
export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowSpec, layout = 'grid', block: initialBlock = 'month', zoom, window = 'all', unit = 'sessions', summary = ['complete', 'last'], select, selectable = () => true, onQueue, queueLabel = 'Queue backfill', pickNote, removable = () => false, onRemove, preselect, drilled = null, onDrill, groupBy = false, hint, pageSize: initialPageSize, pager, tools, filter, filterCount, empty, lazy = false, }) {
|
|
203
|
+
export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowSpec, layout = 'grid', block: initialBlock = 'month', zoom, window = 'all', unit = 'sessions', summary = ['complete', 'last'], select, selectable = () => true, onQueue, queueLabel = 'Queue backfill', pickNote, removable = () => false, onRemove, preselect, stateLabels, drilled = null, onDrill, groupBy = false, hint, pageSize: initialPageSize, pager, tools, filter, filterCount, empty, lazy = false, }) {
|
|
204
204
|
const { data, load: raw, ref } = useLumenSource(source, { lazy });
|
|
205
205
|
// A coverage map refreshes in place: any refresh, asked for or a poll, only spins its ↻; no bar or dimming over the cells.
|
|
206
206
|
const load = { ...raw, fetching: raw.fetching || raw.background };
|
|
@@ -295,7 +295,7 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
295
295
|
const text = data?.rows.find((r) => r.row === row)?.label ?? row;
|
|
296
296
|
return {
|
|
297
297
|
label: `${text} · ${blockName(k)}`,
|
|
298
|
-
detail: (_jsxs(_Fragment, { children: [_jsxs("div", { children: [unitLabel(c.have, c.expected), " \u00B7 ", coverageLabel(c.level)] }), c.notes.map((n) => (_jsx("div", { children: n }, n))), layout === 'months' && select === 'drill' && _jsx("div", { children: "Click to see its days" })] })),
|
|
298
|
+
detail: (_jsxs(_Fragment, { children: [_jsxs("div", { children: [unitLabel(c.have, c.expected), " \u00B7 ", stateLabels?.[c.level] ?? coverageLabel(c.level)] }), c.notes.map((n) => (_jsx("div", { children: n }, n))), layout === 'months' && select === 'drill' && _jsx("div", { children: "Click to see its days" })] })),
|
|
299
299
|
};
|
|
300
300
|
};
|
|
301
301
|
/** A block a pick can take: a month in it can be queued, or taken out of the queue. */
|
|
@@ -353,7 +353,7 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
353
353
|
levels.add(c.level);
|
|
354
354
|
have += c.have;
|
|
355
355
|
expected += c.expected;
|
|
356
|
-
return (_jsx(CoverageCell, { level: c.level, label: `${row} · ${blockName(key)}`, tip: `${row}|${key}`, picked: picked.has(`${row}|${key}`) || drilled === key, pickable: select === 'backfill' || select === 'drill', disabled: select === 'backfill' ? !canPick(row, key) : select !== 'drill', className: mobile ? 'h-4' : 'h-5' }, key));
|
|
356
|
+
return (_jsx(CoverageCell, { level: c.level, fill: c.expected > 0 ? c.have / c.expected : undefined, label: `${row} · ${blockName(key)}`, tip: `${row}|${key}`, picked: picked.has(`${row}|${key}`) || drilled === key, pickable: select === 'backfill' || select === 'drill', disabled: select === 'backfill' ? !canPick(row, key) : select !== 'drill', className: mobile ? 'h-4' : 'h-5' }, key));
|
|
357
357
|
}),
|
|
358
358
|
...sums.map((s) => (_jsx("span", { className: cn('num pl-3 text-right text-xs', s !== 'complete' && 'text-muted-foreground'), children: s === 'complete'
|
|
359
359
|
? fmtPct(have, expected)
|
|
@@ -407,7 +407,11 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
407
407
|
if (!c)
|
|
408
408
|
return null;
|
|
409
409
|
levels.add(c.level);
|
|
410
|
-
return {
|
|
410
|
+
return {
|
|
411
|
+
level: c.level,
|
|
412
|
+
canPick: select === 'backfill' && canPick(r.row, k),
|
|
413
|
+
fill: c.expected > 0 ? c.have / c.expected : undefined,
|
|
414
|
+
};
|
|
411
415
|
});
|
|
412
416
|
const picks = pickedBy.get(r.row) ?? [];
|
|
413
417
|
out.push(_jsx(MapRow, { r: r, cols: cols, marks: marks, picks: picks, total: folded.totals.get(r.row) ?? { have: 0, expected: 0 }, look: look, sig: [
|
|
@@ -425,7 +429,9 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
425
429
|
cols[0],
|
|
426
430
|
cols.at(-1),
|
|
427
431
|
picks.join(),
|
|
428
|
-
marks
|
|
432
|
+
marks
|
|
433
|
+
.map((m) => (m ? `${m.level}${m.canPick ? '+' : ''}${m.fill ?? ''}` : ''))
|
|
434
|
+
.join(),
|
|
429
435
|
JSON.stringify(folded.totals.get(r.row) ?? null),
|
|
430
436
|
].join('\u0001') }, r.row));
|
|
431
437
|
return out;
|
|
@@ -451,7 +457,7 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
451
457
|
setPageSize(n);
|
|
452
458
|
setPageIndex(0);
|
|
453
459
|
}, noun: plural(rowSpec.title) })))] }));
|
|
454
|
-
return (_jsx("div", { ref: ref, className: "min-w-0", children: _jsx(LumenWidget, { id: title, kind: null, icon: icon, title: title, tools: head, filter: filter, filterCount: filterCount, load: load, rows: data?.rows.length, pad: false, children: _jsx("div", { className: "flex flex-col gap-3 px-3 pt-3 pb-3", children: _jsxs(LumenStates, { load: cells, skeleton: _jsx(GridSkeleton, {}), empty: data && !data.rows.length && !data.facts.length ? empty : undefined, children: [_jsx("div", { ref: scroller, className: "overflow-x-auto overflow-y-hidden pb-1", children: _jsx(CoverageTip, { content: tipFor, className: "w-max min-w-full", children: body }) }), pickedCount > 0 && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-lg bg-muted px-3 py-2 text-sm", children: [_jsxs("span", { className: "min-w-0", children: [layout === 'grid' && (_jsx("span", { className: "num font-semibold", children: `${pickedRows.map(rowName).join(', ')} · ` })), `${months(pickedCount)} picked`, pickNote && queueCount > 0 ? ` · ${pickNote(pick)}` : ''] }), _jsx("span", { className: "flex-1" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setPicked(new Set()), children: "Clear" }), removeCount > 0 && (_jsxs(Button, { variant: "outline", size: "sm", disabled: queueing, onClick: () => void queue(true), children: [_jsx(ListXIcon, {}), " Remove from queue \u00B7 ", months(removeCount)] })), queueCount > 0 && (_jsxs(Button, { size: "sm", disabled: queueing || !onQueue, onClick: () => void queue(), children: [_jsx(ListPlusIcon, {}), " ", queueLabel, " \u00B7 ", months(queueCount)] }))] })), _jsx("div", { className: "border-t pt-3", children: _jsx(CoverageLegend, { levels: levels, hint: hint ??
|
|
460
|
+
return (_jsx("div", { ref: ref, className: "min-w-0", children: _jsx(LumenWidget, { id: title, kind: null, icon: icon, title: title, tools: head, filter: filter, filterCount: filterCount, load: load, rows: data?.rows.length, pad: false, children: _jsx("div", { className: "flex flex-col gap-3 px-3 pt-3 pb-3", children: _jsxs(LumenStates, { load: cells, skeleton: _jsx(GridSkeleton, {}), empty: data && !data.rows.length && !data.facts.length ? empty : undefined, children: [_jsx("div", { ref: scroller, className: "overflow-x-auto overflow-y-hidden pb-1", children: _jsx(CoverageTip, { content: tipFor, className: "w-max min-w-full", children: body }) }), pickedCount > 0 && (_jsxs("div", { className: "flex flex-wrap items-center gap-2 rounded-lg bg-muted px-3 py-2 text-sm", children: [_jsxs("span", { className: "min-w-0", children: [layout === 'grid' && (_jsx("span", { className: "num font-semibold", children: `${pickedRows.map(rowName).join(', ')} · ` })), `${months(pickedCount)} picked`, pickNote && queueCount > 0 ? ` · ${pickNote(pick)}` : ''] }), _jsx("span", { className: "flex-1" }), _jsx(Button, { variant: "ghost", size: "sm", onClick: () => setPicked(new Set()), children: "Clear" }), removeCount > 0 && (_jsxs(Button, { variant: "outline", size: "sm", disabled: queueing, onClick: () => void queue(true), children: [_jsx(ListXIcon, {}), " Remove from queue \u00B7 ", months(removeCount)] })), queueCount > 0 && (_jsxs(Button, { size: "sm", disabled: queueing || !onQueue, onClick: () => void queue(), children: [_jsx(ListPlusIcon, {}), " ", queueLabel, " \u00B7 ", months(queueCount)] }))] })), _jsx("div", { className: "border-t pt-3", children: _jsx(CoverageLegend, { levels: levels, labels: stateLabels, hint: hint ??
|
|
455
461
|
(select === 'backfill'
|
|
456
462
|
? 'Click a block, shift-click for a range'
|
|
457
463
|
: select === 'drill'
|
package/dist/theme.css
CHANGED
|
@@ -397,6 +397,9 @@
|
|
|
397
397
|
background-size: 11.3px 11.3px;
|
|
398
398
|
animation: lumen-cov-run 1s linear infinite;
|
|
399
399
|
}
|
|
400
|
+
.bg-cov-indexing {
|
|
401
|
+
background: repeating-linear-gradient(135deg, var(--cov-high) 0 4px, var(--cov-low) 4px 8px);
|
|
402
|
+
}
|
|
400
403
|
.bg-cov-canceled {
|
|
401
404
|
background: linear-gradient(
|
|
402
405
|
135deg,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.34",
|
|
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.34",
|
|
45
45
|
"@dnd-kit/core": "6.3.1",
|
|
46
46
|
"@dnd-kit/sortable": "10.0.0",
|
|
47
47
|
"@dnd-kit/utilities": "3.2.2",
|