@columenlabs/lumen-ui 0.1.1 → 0.1.2
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/README.md +1 -1
- package/dist/assistant-panel.js +1 -1
- package/dist/coverage-calendar-map.js +1 -1
- package/dist/coverage-cells.d.ts +2 -2
- package/dist/coverage-map.js +4 -10
- package/dist/details-table.js +1 -5
- package/dist/form-issues.js +1 -1
- package/dist/frame-script.js +1 -1
- package/dist/growth-chart.d.ts +9 -9
- package/dist/joins.d.ts +4 -3
- package/dist/joins.js +1 -1
- package/dist/lumen-code.js +1 -5
- package/dist/lumen-drawer.js +1 -3
- package/dist/lumen-filter.js +5 -13
- package/dist/lumen-grid.js +2 -4
- package/dist/lumen-layout.js +1 -1
- package/dist/lumen-links.d.ts +1 -1
- package/dist/lumen-selector.js +1 -1
- package/dist/lumen-source.js +2 -4
- package/dist/lumen-tab-drawer.js +1 -1
- package/dist/lumen-toast.d.ts +4 -4
- package/dist/lumen-view-card.js +1 -1
- package/dist/lumen-view.js +2 -4
- package/dist/lumen-widget.d.ts +170 -170
- package/dist/lumen-widget.js +4 -8
- package/dist/market/indicator-picker.js +1 -1
- package/dist/market/live.d.ts +1 -1
- package/dist/market/lumen-chart.js +1 -1
- package/dist/market/price-chart.d.ts +10 -10
- package/dist/nav.js +1 -1
- package/dist/notifications.js +1 -3
- package/dist/overview.js +1 -1
- package/dist/page.js +1 -1
- package/dist/pager.js +1 -1
- package/dist/prefs.d.ts +25 -25
- package/dist/schedules.js +1 -1
- package/dist/settings.js +1 -3
- package/dist/shell.js +1 -1
- package/dist/summary-cards.js +2 -6
- package/dist/symbol-sheet.js +1 -1
- package/dist/tasks.d.ts +1 -1
- package/dist/tasks.js +1 -1
- package/dist/tile.js +2 -4
- package/dist/ui/badge.d.ts +1 -1
- package/dist/ui/button.d.ts +2 -2
- package/dist/ui/chart.d.ts +2 -2
- package/dist/ui/chart.js +2 -5
- package/dist/ui/field.d.ts +1 -1
- package/dist/ui/input-group.d.ts +2 -2
- package/dist/ui/item.d.ts +3 -3
- package/dist/ui/sidebar.d.ts +1 -1
- package/dist/ui/sidebar.js +1 -1
- package/dist/ui/toggle.d.ts +1 -1
- package/dist/view-edit-cell.js +1 -4
- package/dist/view-editor.js +1 -1
- package/dist/view-formulas.d.ts +1 -1
- package/dist/view-model.d.ts +15 -15
- package/dist/whats-new.js +1 -1
- package/dist/widget-settings.d.ts +139 -139
- package/dist/widget-settings.js +4 -4
- package/dist/widget-thumbs.d.ts +1 -1
- package/dist/widget-thumbs.js +1 -1
- package/dist/workspace-keys.d.ts +1 -1
- package/dist/workspaces.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
|
|
3
3
|
Lumen's components: the app frame (`LumenShell`), pages and views (`LumenLayout`, `LumenView`, `LumenTable`, `LumenWidget`, `LumenCard`), charts (`LumenChart`), `LumenDrawer`, `LumenSelector`, the shadcn parts under `ui/*` and one `theme.css`. Its types are in `@columenlabs/lumen-ui-types`.
|
|
4
4
|
|
|
5
|
-
See the [Lumen README](https://github.com/columenlabs/lumen#readme) for install and use. MIT.
|
|
5
|
+
See the [Lumen README](https://github.com/columenlabs/lumen-ui#readme) for install and use. MIT.
|
package/dist/assistant-panel.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// LumenAssistant's frame (was the assistant panel's): what any app's AI assistant sits
|
|
3
3
|
// in, with nothing of the assistant itself. Docked right of the page on desktop (drag its left edge
|
|
4
4
|
// for ASSISTANT_WIDTH, never past half the window), a full-height sheet on phone; the header's ✦
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CalendarDaysIcon } from 'lucide-react';
|
|
3
3
|
import { useLayoutEffect, useMemo, useRef, useState } from 'react';
|
|
4
4
|
import { CoverageCell, CoverageLegend, CoverageTip } from './coverage-cells.js';
|
package/dist/coverage-cells.d.ts
CHANGED
|
@@ -27,7 +27,7 @@ export declare function CoverageLegend({ levels, hint }: {
|
|
|
27
27
|
* cell made a 100-row map 13,000 tooltips, seconds per render). `label` is the
|
|
28
28
|
* accessible name and the tooltip's first line; `tip` marks the cell for the shared tooltip.
|
|
29
29
|
*/
|
|
30
|
-
export declare const CoverageCell: import("react").
|
|
30
|
+
export declare const CoverageCell: import("react").MemoExoticComponent<({ level, label, tip, picked, disabled, pickable, onClick, className, }: {
|
|
31
31
|
level: CoverageLevel;
|
|
32
32
|
label: string;
|
|
33
33
|
/** What `CoverageTip` hands back to its `content` for this cell. */
|
|
@@ -38,7 +38,7 @@ export declare const CoverageCell: import("react").NamedExoticComponent<{
|
|
|
38
38
|
pickable?: boolean;
|
|
39
39
|
onClick?: (e: React.MouseEvent<HTMLButtonElement>) => void;
|
|
40
40
|
className?: string;
|
|
41
|
-
}>;
|
|
41
|
+
}) => import("react").JSX.Element>;
|
|
42
42
|
/**
|
|
43
43
|
* The one tooltip of a coverage map: it follows the cell under the pointer or keyboard focus inside
|
|
44
44
|
* `children` (any element with `data-cell`) and shows `content` for it. Hovering re-renders only
|
package/dist/coverage-map.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Link } from '@tanstack/react-router';
|
|
3
3
|
import { Grid3x3Icon, ListPlusIcon, XIcon } from 'lucide-react';
|
|
4
4
|
import { isValidElement, memo, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
@@ -148,9 +148,7 @@ const SUMMARY_WIDTH = {
|
|
|
148
148
|
};
|
|
149
149
|
/** A grid-shaped skeleton: label column plus empty cells, so nothing jumps when data lands. */
|
|
150
150
|
function GridSkeleton({ rows = 8 }) {
|
|
151
|
-
return (_jsx("div", { "aria-busy": "true", "aria-label": "Loading", className: "flex flex-col gap-[5px] py-1", children: Array.from({ length: rows }, (_, i) => (
|
|
152
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: static placeholders
|
|
153
|
-
_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-4 w-16 shrink-0" }), _jsx(Skeleton, { className: "h-[18px] flex-1" })] }, i))) }));
|
|
151
|
+
return (_jsx("div", { "aria-busy": "true", "aria-label": "Loading", className: "flex flex-col gap-[5px] py-1", children: Array.from({ length: rows }, (_, i) => (_jsxs("div", { className: "flex items-center gap-2", children: [_jsx(Skeleton, { className: "h-4 w-16 shrink-0" }), _jsx(Skeleton, { className: "h-[18px] flex-1" })] }, i))) }));
|
|
154
152
|
}
|
|
155
153
|
/** `symbols`, `series`: the row title as a count noun. */
|
|
156
154
|
/** The narrowest a block gets before the map scrolls sideways. */
|
|
@@ -321,9 +319,7 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
321
319
|
const grid = {
|
|
322
320
|
gridTemplateColumns: `${mobile ? '2.75rem' : '4rem'} repeat(12, minmax(${mobile ? '14px' : '18px'}, 1fr)) ${sumCols}`,
|
|
323
321
|
};
|
|
324
|
-
body = (
|
|
325
|
-
// biome-ignore lint/a11y/useKeyWithClickEvents: each cell is a button; this only routes its click.
|
|
326
|
-
_jsxs("div", { className: "grid items-center gap-[3px]", style: grid, onClick: onCellClick, children: [_jsx("span", { className: "text-xs text-muted-foreground", children: "Year" }), MON.map((m, i) => (_jsx("span", { className: "text-xs text-muted-foreground", children: mobile ? (i % 3 === 0 ? m : '') : m }, m))), sums.map((s) => (_jsx("span", { className: "pl-3 text-right text-xs text-muted-foreground", children: s === 'rows' ? rowsHead : SUMMARY_HEAD[s] }, s))), years.map((y) => {
|
|
322
|
+
body = (_jsxs("div", { className: "grid items-center gap-[3px]", style: grid, onClick: onCellClick, children: [_jsx("span", { className: "text-xs text-muted-foreground", children: "Year" }), MON.map((m, i) => (_jsx("span", { className: "text-xs text-muted-foreground", children: mobile ? (i % 3 === 0 ? m : '') : m }, m))), sums.map((s) => (_jsx("span", { className: "pl-3 text-right text-xs text-muted-foreground", children: s === 'rows' ? rowsHead : SUMMARY_HEAD[s] }, s))), years.map((y) => {
|
|
327
323
|
let have = 0;
|
|
328
324
|
let expected = 0;
|
|
329
325
|
return [
|
|
@@ -367,9 +363,7 @@ export function LumenCoverageMap({ source, title, icon = Grid3x3Icon, rows: rowS
|
|
|
367
363
|
}
|
|
368
364
|
const look = { mobile, groupBy, select, sums, drilled, link: rowSpec.link };
|
|
369
365
|
let group;
|
|
370
|
-
body = (
|
|
371
|
-
// biome-ignore lint/a11y/useKeyWithClickEvents: each cell is a button; this only routes its click.
|
|
372
|
-
_jsxs("div", { className: "grid min-w-min items-center gap-[3px]", style: grid, onClick: onCellClick, children: [_jsx("span", { className: "sticky left-0 z-1 bg-card text-xs text-muted-foreground", children: mobile ? '' : rowSpec.title }), cols.map((k) => (_jsx("span", { className: "num h-4 overflow-visible text-[11px] whitespace-nowrap text-muted-foreground", children: headLabel(k, block, cols.length) }, k))), sums.map((s) => (_jsx("span", { className: "pl-3 text-right text-xs text-muted-foreground", children: s === 'rows' ? rowsHead : SUMMARY_HEAD[s] }, s))), rowList.flatMap((r) => {
|
|
366
|
+
body = (_jsxs("div", { className: "grid min-w-min items-center gap-[3px]", style: grid, onClick: onCellClick, children: [_jsx("span", { className: "sticky left-0 z-1 bg-card text-xs text-muted-foreground", children: mobile ? '' : rowSpec.title }), cols.map((k) => (_jsx("span", { className: "num h-4 overflow-visible text-[11px] whitespace-nowrap text-muted-foreground", children: headLabel(k, block, cols.length) }, k))), sums.map((s) => (_jsx("span", { className: "pl-3 text-right text-xs text-muted-foreground", children: s === 'rows' ? rowsHead : SUMMARY_HEAD[s] }, s))), rowList.flatMap((r) => {
|
|
373
367
|
const out = [];
|
|
374
368
|
const shut = groupBy && folds.has(foldKey + (r.group ?? ''));
|
|
375
369
|
if (groupBy && r.group !== group) {
|
package/dist/details-table.js
CHANGED
|
@@ -5,11 +5,7 @@ export function DetailsTable({ head, rows, foot }) {
|
|
|
5
5
|
const marked = head.findIndex((h) => h.grow);
|
|
6
6
|
const grow = marked >= 0 ? marked : head.length - 1;
|
|
7
7
|
const cell = (i) => cn('num', head[i]?.right && 'text-right', i !== grow && 'w-px');
|
|
8
|
-
return (_jsx("div", { className: "-mx-1 overflow-x-auto overflow-y-hidden rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: head.map((h, i) => (_jsx(TableHead, { className: cn(h.right && 'text-right', i !== grow && 'w-px'), children: h.label }, h.label))) }) }), _jsx(TableBody, { children: rows.map((r) => (_jsx(TableRow, { children: r.cells.map((c, i) => (
|
|
9
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: cells are positional
|
|
10
|
-
_jsx(TableCell, { className: cell(i), children: c }, i))) }, r.key))) }), foot && (_jsx(TableFooter, { children: _jsx(TableRow, { children: foot.map((c, i) => (
|
|
11
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: cells are positional
|
|
12
|
-
_jsx(TableCell, { className: cell(i), children: c }, i))) }) }))] }) }));
|
|
8
|
+
return (_jsx("div", { className: "-mx-1 overflow-x-auto overflow-y-hidden rounded-md border", children: _jsxs(Table, { children: [_jsx(TableHeader, { children: _jsx(TableRow, { children: head.map((h, i) => (_jsx(TableHead, { className: cn(h.right && 'text-right', i !== grow && 'w-px'), children: h.label }, h.label))) }) }), _jsx(TableBody, { children: rows.map((r) => (_jsx(TableRow, { children: r.cells.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }, r.key))) }), foot && (_jsx(TableFooter, { children: _jsx(TableRow, { children: foot.map((c, i) => (_jsx(TableCell, { className: cell(i), children: c }, i))) }) }))] }) }));
|
|
13
9
|
}
|
|
14
10
|
/** Facts as a two-row table: the labels as the header, the values under them. */
|
|
15
11
|
export function FactsTable({ items }) {
|
package/dist/form-issues.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// Save with issues: a Save that cannot go yet says why. Beside it a chip
|
|
3
3
|
// counts what needs fixing and lists it; Save, and each line of the list, takes the person to the
|
|
4
4
|
// issue: the editor opens its section or tab (`reveal`), then the field scrolls into view, takes
|
package/dist/frame-script.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
|
3
3
|
import { PlayIcon, RotateCcwIcon, WrapTextIcon } from 'lucide-react';
|
|
4
4
|
import { useEffect, useMemo, useState } from 'react';
|
package/dist/growth-chart.d.ts
CHANGED
|
@@ -16,17 +16,17 @@ export type Series = {
|
|
|
16
16
|
points: [string, number][];
|
|
17
17
|
};
|
|
18
18
|
export declare const KEY_DATE_KINDS: readonly [{
|
|
19
|
-
readonly kind:
|
|
20
|
-
readonly label:
|
|
21
|
-
readonly color:
|
|
19
|
+
readonly kind: 'fomc';
|
|
20
|
+
readonly label: 'FOMC';
|
|
21
|
+
readonly color: 'var(--key-date-fomc)';
|
|
22
22
|
}, {
|
|
23
|
-
readonly kind:
|
|
24
|
-
readonly label:
|
|
25
|
-
readonly color:
|
|
23
|
+
readonly kind: 'cpi';
|
|
24
|
+
readonly label: 'CPI';
|
|
25
|
+
readonly color: 'var(--key-date-cpi)';
|
|
26
26
|
}, {
|
|
27
|
-
readonly kind:
|
|
28
|
-
readonly label:
|
|
29
|
-
readonly color:
|
|
27
|
+
readonly kind: 'jobs';
|
|
28
|
+
readonly label: 'Jobs';
|
|
29
|
+
readonly color: 'var(--key-date-jobs)';
|
|
30
30
|
}];
|
|
31
31
|
export type KeyDateKind = (typeof KEY_DATE_KINDS)[number]['kind'];
|
|
32
32
|
/** A thin vertical line on the chart; its label shows in the tooltip. */
|
package/dist/joins.d.ts
CHANGED
|
@@ -57,9 +57,10 @@ export interface JoinAction {
|
|
|
57
57
|
export declare const asOf: (at: string) => string;
|
|
58
58
|
/** Your data: the person's own columns. */
|
|
59
59
|
export declare const YOURS_COLOR = "var(--origin-yours)";
|
|
60
|
+
declare const recipeId: (id: string) => string;
|
|
60
61
|
/** A frame's group name on a card: `Assistant · Targets`, or `Yours · Notes` for the person's own. */
|
|
61
|
-
export declare const frameLabel: (meta: Pick<FrameMeta,
|
|
62
|
-
export declare const frameColor: (meta: Pick<FrameMeta,
|
|
62
|
+
export declare const frameLabel: (meta: Pick<FrameMeta, 'name' | 'origin'>, assistant?: string) => string;
|
|
63
|
+
export declare const frameColor: (meta: Pick<FrameMeta, 'origin'>) => "var(--origin-assistant)" | "var(--origin-yours)";
|
|
63
64
|
/** The hand-edited cells of a frame, as `column\u0000key` (or `column\u0000#row`). */
|
|
64
65
|
export declare function editedCells(data: FrameData | undefined): Set<string>;
|
|
65
66
|
export declare const editedKey: (column: string, key: string | number) => string;
|
|
@@ -79,7 +80,7 @@ export declare function useYourData(api: string | null): import("@tanstack/react
|
|
|
79
80
|
column: YourColumn;
|
|
80
81
|
}, unknown>;
|
|
81
82
|
/** A linked frame's group id in a card's field tree (`recipe:fr_…`). */
|
|
82
|
-
export declare const frameGroupId:
|
|
83
|
+
export declare const frameGroupId: typeof recipeId;
|
|
83
84
|
/**
|
|
84
85
|
* Edit widget's draft of `config.frames`: `domain` (the card's, joined with
|
|
85
86
|
* its saved frames) with the frames `ids` lists, reading the ones it lacks and dropping the rest.
|
package/dist/joins.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CATALOG, FRAME_LINK, catalogKeys, catalogTables, linkable, } from '@columenlabs/lumen-ui-types/catalog';
|
|
3
3
|
// Joins: the registry's
|
|
4
4
|
// join fields, attached to any card's rows by the keys they carry. A domain says how to read a
|
package/dist/lumen-code.js
CHANGED
|
@@ -71,9 +71,5 @@ export function LumenCode({ code, lang, wrap = false, lineNumbers = false, heade
|
|
|
71
71
|
setCopied(true);
|
|
72
72
|
setTimeout(() => setCopied(false), 1500);
|
|
73
73
|
}, () => toast.error("Couldn't copy the code"));
|
|
74
|
-
return (_jsxs("div", { "data-slot": "lumen-code", "data-highlighted": tokens ? 'true' : 'false', className: cn('lumen-code min-w-0 text-xs leading-relaxed', wrap && 'lumen-code-wrap', lineNumbers && 'lumen-code-numbers', header && 'rounded-lg border bg-muted/40', className), children: [header && (_jsxs("div", { className: "flex h-7 items-center justify-between border-b pr-1 pl-3", children: [_jsx("span", { className: "font-mono text-xs text-muted-foreground", children: lang || 'text' }), _jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, label: copied ? 'Copied' : 'Copy code', size: "icon-xs", onClick: copy })] })), _jsx("pre", { className: "overflow-x-auto", children: _jsx("code", { children: lines.map((line, i) => (
|
|
75
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: lines have no other identity
|
|
76
|
-
_jsxs("span", { className: "line", children: [line.map((t, j) => (
|
|
77
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: tokens have no other identity
|
|
78
|
-
_jsx("span", { style: t.htmlStyle, children: t.content }, j))), '\n'] }, i))) }) })] }));
|
|
74
|
+
return (_jsxs("div", { "data-slot": "lumen-code", "data-highlighted": tokens ? 'true' : 'false', className: cn('lumen-code min-w-0 text-xs leading-relaxed', wrap && 'lumen-code-wrap', lineNumbers && 'lumen-code-numbers', header && 'rounded-lg border bg-muted/40', className), children: [header && (_jsxs("div", { className: "flex h-7 items-center justify-between border-b pr-1 pl-3", children: [_jsx("span", { className: "font-mono text-xs text-muted-foreground", children: lang || 'text' }), _jsx(IconButton, { icon: copied ? CheckIcon : CopyIcon, label: copied ? 'Copied' : 'Copy code', size: "icon-xs", onClick: copy })] })), _jsx("pre", { className: "overflow-x-auto", children: _jsx("code", { children: lines.map((line, i) => (_jsxs("span", { className: "line", children: [line.map((t, j) => (_jsx("span", { style: t.htmlStyle, children: t.content }, j))), '\n'] }, i))) }) })] }));
|
|
79
75
|
}
|
package/dist/lumen-drawer.js
CHANGED
|
@@ -20,9 +20,7 @@ export function LumenDrawer({ open, onClose, title, description, children, foote
|
|
|
20
20
|
// Every drawer has a footer, styled like a dialog's: the body scrolls above
|
|
21
21
|
// it and always ends on a clear edge. Without actions of its own it offers Close.
|
|
22
22
|
const foot = (_jsxs("footer", { "data-slot": "drawer-footer", className: "flex shrink-0 items-center gap-2 border-t bg-muted/50 px-4 py-2.5", children: [footerStart && (_jsx("div", { className: "min-w-0 flex-1 truncate text-muted-foreground text-xs", children: footerStart })), _jsx("div", { className: "ml-auto flex items-center gap-2", children: footer ?? (_jsx(SheetClose, { asChild: true, children: _jsx(Button, { type: "button", size: "sm", variant: "outline", children: "Close" }) })) })] }));
|
|
23
|
-
return (
|
|
24
|
-
// Not modal on desktop: the assistant, docked beside it, stays usable while the drawer is open.
|
|
25
|
-
_jsx(Sheet, { open: open, onOpenChange: (o) => !o && onClose(), modal: isMobile, children: isMobile ? (_jsxs(SheetContent, { side: "bottom", className: "max-h-[85svh] gap-0 overflow-hidden", children: [_jsx(SheetHeader, { className: "shrink-0 border-b", children: head }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pt-2", children: body }), foot] })) : (_jsx(SheetContent, { side: "right", showCloseButton: false,
|
|
23
|
+
return (_jsx(Sheet, { open: open, onOpenChange: (o) => !o && onClose(), modal: isMobile, children: isMobile ? (_jsxs(SheetContent, { side: "bottom", className: "max-h-[85svh] gap-0 overflow-hidden", children: [_jsx(SheetHeader, { className: "shrink-0 border-b", children: head }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pt-2", children: body }), foot] })) : (_jsx(SheetContent, { side: "right", showCloseButton: false,
|
|
26
24
|
// The resize handle's grab zone is wider than the handle, so a drag can start on the
|
|
27
25
|
// overlay; the panels library marks that pointerdown handled, and then it doesn't close.
|
|
28
26
|
onPointerDownOutside: (e) => e.detail.originalEvent.defaultPrevented && e.preventDefault(), className: "pointer-events-none! gap-0 border-0 bg-transparent shadow-none data-[side=right]:left-0 data-[side=right]:w-auto data-[side=right]:border-l-0 data-[side=right]:sm:max-w-none", children: _jsxs(ResizablePanelGroup, { orientation: "horizontal", children: [_jsx(ResizablePanel, { minSize: "40%" }), _jsx(ResizableHandle, { withHandle: true, className: "pointer-events-auto" }), _jsx(ResizablePanel, { defaultSize: defaultSize, minSize: minSize, maxSize: maxSize, "data-slot": "lumen-drawer", className: "pointer-events-auto bg-popover shadow-lg", children: _jsxs("section", { className: "flex h-full flex-col overflow-hidden", children: [_jsxs("header", { className: "flex shrink-0 items-center gap-2 border-b px-4 py-3", children: [head, _jsx(SheetClose, { asChild: true, children: _jsx(IconButton, { icon: XIcon, label: "Close", className: "ml-auto" }) })] }), _jsx("div", { className: "min-h-0 flex-1 overflow-y-auto pt-2", children: body }), foot] }) })] }) })) }));
|
package/dist/lumen-filter.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { CONTAINS_KEY, meetsNumber } from '@columenlabs/lumen-ui-types/views';
|
|
3
3
|
// The one filter box every view uses, redone after p2e's:
|
|
4
4
|
// one chip per field in the sans face, `Account IRA, Roth ×`, included or excluded as a whole
|
|
@@ -217,9 +217,7 @@ function NumberCondition({ label, current, tall, count, onSet, }) {
|
|
|
217
217
|
};
|
|
218
218
|
const box = cn('min-w-0 flex-1 px-2 tabular-nums [appearance:textfield] [&::-webkit-inner-spin-button]:appearance-none', tall ? 'h-10 text-base' : 'h-8 text-sm');
|
|
219
219
|
const ok = isNumber(a) && (op !== 'between' || isNumber(b));
|
|
220
|
-
return (
|
|
221
|
-
// Keys stay here: the menu would take Enter and the arrows.
|
|
222
|
-
_jsxs("div", { className: "flex flex-col gap-1.5 px-2 py-1", onKeyDown: (e) => {
|
|
220
|
+
return (_jsxs("div", { className: "flex flex-col gap-1.5 px-2 py-1", onKeyDown: (e) => {
|
|
223
221
|
e.stopPropagation();
|
|
224
222
|
if (e.key === 'Enter')
|
|
225
223
|
e.preventDefault();
|
|
@@ -466,17 +464,13 @@ export function LumenTokenizedFilter({ filter, placeholder = 'Filter…', label
|
|
|
466
464
|
};
|
|
467
465
|
const activeField = active ? fieldOf(active) : undefined;
|
|
468
466
|
const activeChip = active ? chipOf(active) : undefined;
|
|
469
|
-
const menu = activeField ? (
|
|
470
|
-
// One field: Include or Exclude, then its values ticked.
|
|
471
|
-
_jsxs(_Fragment, { children: [_jsxs(CommandGroup, { className: "px-1 py-0.5", children: [_jsxs("div", { className: "flex items-center gap-1 px-1 py-1", children: [_jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "All filters", onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
467
|
+
const menu = activeField ? (_jsxs(_Fragment, { children: [_jsxs(CommandGroup, { className: "px-1 py-0.5", children: [_jsxs("div", { className: "flex items-center gap-1 px-1 py-1", children: [_jsx(Button, { variant: "ghost", size: "icon-xs", "aria-label": "All filters", onMouseDown: (e) => e.preventDefault(), onClick: () => {
|
|
472
468
|
setField(null);
|
|
473
469
|
setText('');
|
|
474
470
|
focus();
|
|
475
471
|
}, children: _jsx(ChevronLeftIcon, {}) }), _jsx(activeField.icon, { className: "size-4 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: activeField.label }), !activeField.number && (_jsxs(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, className: "ml-auto", value: notFor(activeField.key) ? 'exclude' : 'include', onValueChange: (v) => v && setNot(activeField.key, v === 'exclude'), "aria-label": `${activeField.label}: include or exclude`, children: [_jsx(ToggleGroupItem, { value: "include", className: "h-7 px-2 text-xs font-normal", children: "Include" }), _jsx(ToggleGroupItem, { value: "exclude", className: "h-7 px-2 text-xs font-normal", children: "Exclude" })] }))] }), activeField.number && (_jsx(NumberCondition, { label: activeField.label, current: tokens.find((t) => t.key === activeField.key), tall: mobile, count: (op, value) => numberCount(activeField.key, op, value), onSet: (op, value) => setCondition(activeField.key, op, value) }, activeField.key))] }), active === CONTAINS_KEY ? (_jsxs(CommandGroup, { className: "px-1 py-0.5", children: [containsWord && !picked(CONTAINS_KEY, containsWord) && (_jsxs(CommandItem, { value: `${CONTAINS_KEY}:${containsWord}`, onSelect: () => toggle(CONTAINS_KEY, containsWord), className: tall, children: [_jsx(TextSearchIcon, { className: "text-muted-foreground" }), _jsxs("span", { className: "min-w-0 truncate", children: ["\u201C", containsWord, "\u201D"] }), _jsx(CommandShortcut, { className: shortcut, children: wordOf(containsWord, notFor(CONTAINS_KEY)) })] })), tokens
|
|
476
472
|
.filter((t) => t.key === CONTAINS_KEY)
|
|
477
|
-
.map((t) => valueRow(CONTAINS_KEY, t.value, wordOf(t.value, !!t.not)))] })) : (!activeField.number && (_jsx(CommandGroup, { className: "px-1 py-0.5", children: valuesOf(activeField.key, needle, 200).map(([v, n]) => valueRow(activeField.key, v, n)) }))), _jsx(CommandEmpty, { children: "No matching values." })] })) : q ? (
|
|
478
|
-
// Typing: free text, the fields it names, and values from every field.
|
|
479
|
-
_jsxs(_Fragment, { children: [_jsx(CommandEmpty, { children: "No matching values." }), word && (_jsx(CommandGroup, { className: "px-1 py-0.5", children: _jsxs(CommandItem, { value: `${CONTAINS_KEY}:${word}`, onSelect: () => {
|
|
473
|
+
.map((t) => valueRow(CONTAINS_KEY, t.value, wordOf(t.value, !!t.not)))] })) : (!activeField.number && (_jsx(CommandGroup, { className: "px-1 py-0.5", children: valuesOf(activeField.key, needle, 200).map(([v, n]) => valueRow(activeField.key, v, n)) }))), _jsx(CommandEmpty, { children: "No matching values." })] })) : q ? (_jsxs(_Fragment, { children: [_jsx(CommandEmpty, { children: "No matching values." }), word && (_jsx(CommandGroup, { className: "px-1 py-0.5", children: _jsxs(CommandItem, { value: `${CONTAINS_KEY}:${word}`, onSelect: () => {
|
|
480
474
|
setTokens([
|
|
481
475
|
...tokens.filter((t) => !same(t, { key: CONTAINS_KEY, value: word })),
|
|
482
476
|
token(CONTAINS_KEY, word, chipOf(CONTAINS_KEY)?.not ?? negate),
|
|
@@ -489,9 +483,7 @@ export function LumenTokenizedFilter({ filter, placeholder = 'Filter…', label
|
|
|
489
483
|
.map((f) => {
|
|
490
484
|
const vs = valuesOf(f.key, q, PER_FIELD);
|
|
491
485
|
return (vs.length > 0 && (_jsx(CommandGroup, { heading: f.label, className: "px-1 py-0.5", children: vs.map(([v, n]) => valueRow(f.key, v, n)) }, f.key)));
|
|
492
|
-
})] })) : (
|
|
493
|
-
// At rest: every filter on, then the fields to add.
|
|
494
|
-
_jsxs(_Fragment, { children: [chips.length > 0 && (_jsx(CommandGroup, { heading: "Filters", className: "px-1 py-0.5", children: chips.map((c) => {
|
|
486
|
+
})] })) : (_jsxs(_Fragment, { children: [chips.length > 0 && (_jsx(CommandGroup, { heading: "Filters", className: "px-1 py-0.5", children: chips.map((c) => {
|
|
495
487
|
const f = fieldOf(c.key);
|
|
496
488
|
return (_jsxs(CommandItem, { value: `chip:${c.key}`, onSelect: () => openField(c.key), className: tall, children: [link?.color ? (_jsx(LinkDot, { color: link.color })) : (f && _jsx(f.icon, { className: "text-muted-foreground" })), _jsx("span", { className: "shrink-0", children: f?.label ?? c.key }), summary(c), _jsx(Button, { variant: "ghost", size: "icon-xs", className: "-my-1 shrink-0 text-muted-foreground", "aria-label": `Remove ${f?.label ?? c.key} filter`, onMouseDown: (e) => e.preventDefault(), onClick: (e) => {
|
|
497
489
|
e.stopPropagation();
|
package/dist/lumen-grid.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// LumenGrid: an
|
|
3
3
|
// LumenLayout's cards on a real grid, react-grid-layout underneath. A desktop has 6 columns, a phone
|
|
4
4
|
// 2; rows are 8px. A card is placed at x, y and sized w by h; a card with no h is as tall as what it
|
|
@@ -193,9 +193,7 @@ export function LumenGrid({ lead = [], cards, tail = [], editing, onPlace, }) {
|
|
|
193
193
|
parts.map((p) => Array.isArray(p) ? (_jsx(GridRun, { items: p, phone: phone, width: width, cell: (id) => {
|
|
194
194
|
const c = byId.get(id);
|
|
195
195
|
return c ? cell(c) : null;
|
|
196
|
-
} }, p.map((it) => it.i).join())) : (
|
|
197
|
-
// A full-width card that is no table (a note, a chart) stays put while a table scrolls.
|
|
198
|
-
_jsx("div", { className: "not-has-[table]:sticky not-has-[table]:left-0 not-has-[table]:w-(--view-w)", children: p.node }, p.id)))] }));
|
|
196
|
+
} }, p.map((it) => it.i).join())) : (_jsx("div", { className: "not-has-[table]:sticky not-has-[table]:left-0 not-has-[table]:w-(--view-w)", children: p.node }, p.id)))] }));
|
|
199
197
|
}
|
|
200
198
|
/** Cards between two full-width tables: their own grid, from the row the first starts on. */
|
|
201
199
|
function GridRun({ items, phone, width, cell, }) {
|
package/dist/lumen-layout.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// LumenLayout: the page
|
|
3
3
|
// every app shows. Crumbs and actions in the header, then the filter and Group by switch every
|
|
4
4
|
// card on the page shares, then an ordered list of cards, each a third, half, two thirds or the full width:
|
package/dist/lumen-links.d.ts
CHANGED
|
@@ -25,7 +25,7 @@ export declare function useLinkState(saved: Record<string, LinkColor | null>, ke
|
|
|
25
25
|
ids: string[];
|
|
26
26
|
}): {
|
|
27
27
|
links: Links;
|
|
28
|
-
colors: Record<string, "
|
|
28
|
+
colors: Record<string, "amber" | "blue" | "lime" | "pink" | "teal" | null>;
|
|
29
29
|
};
|
|
30
30
|
export declare const useCardId: () => string | null;
|
|
31
31
|
export declare function CardIdProvider({ id, children }: {
|
package/dist/lumen-selector.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// LumenSelector: the one
|
|
3
3
|
// picker for every "pick one or more things from a list", on the shell's base-ui Combobox.
|
|
4
4
|
//
|
package/dist/lumen-source.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// The shared loading contract.
|
|
3
3
|
// Every card and view loads its own data and says so the same way: a skeleton on first load, a thin
|
|
4
4
|
// bar while a view's query runs, the old data on screen (dimmed) while a refresh someone asked for
|
|
@@ -181,9 +181,7 @@ export function LumenError({ error, onRetry }) {
|
|
|
181
181
|
}
|
|
182
182
|
/** Rows of skeleton the height of a table, so nothing jumps when the data lands. */
|
|
183
183
|
export function LumenSkeleton({ rows = 6, className }) {
|
|
184
|
-
return (_jsx("div", { "aria-busy": "true", "aria-label": "Loading", className: cn('flex flex-col gap-2 p-3', className), children: Array.from({ length: rows }, (_, i) => (
|
|
185
|
-
// biome-ignore lint/suspicious/noArrayIndexKey: static placeholders
|
|
186
|
-
_jsx(Skeleton, { className: "h-7 w-full" }, i))) }));
|
|
184
|
+
return (_jsx("div", { "aria-busy": "true", "aria-label": "Loading", className: cn('flex flex-col gap-2 p-3', className), children: Array.from({ length: rows }, (_, i) => (_jsx(Skeleton, { className: "h-7 w-full" }, i))) }));
|
|
187
185
|
}
|
|
188
186
|
/** One component's states from its load: bar (views), skeleton, error with Retry, empty, then the
|
|
189
187
|
* content, dimmed while it refreshes. Place it at the top of a `relative` card body. */
|
package/dist/lumen-tab-drawer.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Trash2Icon } from 'lucide-react';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
import { LumenConfirm } from './confirm.js';
|
package/dist/lumen-toast.d.ts
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
2
|
import { type ExternalToast } from 'sonner';
|
|
3
3
|
export declare const lumenToast: ((message: ReactNode, options?: ExternalToast) => string | number) & {
|
|
4
|
-
success: (message: (
|
|
5
|
-
error: (message: (
|
|
6
|
-
warning: (message: (
|
|
7
|
-
info: (message: (
|
|
4
|
+
success: (message: ((() => React.ReactNode) | ReactNode) | React.ReactNode, data?: ExternalToast) => string | number;
|
|
5
|
+
error: (message: ((() => React.ReactNode) | ReactNode) | React.ReactNode, data?: ExternalToast) => string | number;
|
|
6
|
+
warning: (message: ((() => React.ReactNode) | ReactNode) | React.ReactNode, data?: ExternalToast) => string | number;
|
|
7
|
+
info: (message: ((() => React.ReactNode) | ReactNode) | React.ReactNode, data?: ExternalToast) => string | number;
|
|
8
8
|
dismiss: (id?: number | string) => string | number;
|
|
9
9
|
/** A change done, with Undo that puts it back. */
|
|
10
10
|
undo: (message: ReactNode, onUndo: () => void, options?: ExternalToast) => string | number;
|
package/dist/lumen-view-card.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { controlOn } from '@columenlabs/lumen-ui-types/views';
|
|
3
3
|
import { useEffect, useMemo, useState } from 'react';
|
|
4
4
|
import { useGroup } from './group-button.js';
|
package/dist/lumen-view.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { controlOn, isCountAgg, isDollarFormat, viewPageSizes, viewPaginationSchema, } from '@columenlabs/lumen-ui-types/views';
|
|
3
3
|
// Custom views: any number of views on any app, one page for all of them.
|
|
4
4
|
// A data domain (holdings, chains, bars, series, research results) describes its fields once in a
|
|
@@ -603,9 +603,7 @@ function LumenTableRows({ domain, columns = domain.fields, rows, groupBy = null,
|
|
|
603
603
|
? 'ascending'
|
|
604
604
|
: h.column.getIsSorted() === 'desc'
|
|
605
605
|
? 'descending'
|
|
606
|
-
: undefined, children: [i === 0 && groups && (
|
|
607
|
-
// Expand or collapse every group at once.
|
|
608
|
-
_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.getToggleSortingHandler(), 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
|
|
606
|
+
: 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.getToggleSortingHandler(), 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
|
|
609
607
|
? groups.map(([key, members], gi) => {
|
|
610
608
|
const open = isOpen(key, gi);
|
|
611
609
|
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)))
|