@columenlabs/lumen-ui 0.1.165 → 0.1.167
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/market/market-widget.js +38 -5
- package/dist/summary-cards.js +13 -5
- package/dist/theme.css +5 -1
- package/dist/tile.js +1 -1
- package/package.json +2 -2
|
@@ -34,6 +34,10 @@ import { useSymbolChart } from './lumen-chart.js';
|
|
|
34
34
|
import { faint } from './price-chart.js';
|
|
35
35
|
const LINE_TOKENS = ['--chart-1', '--chart-3', '--chart-4', '--chart-6', '--chart-2', '--chart-5'];
|
|
36
36
|
const MINUS = '−';
|
|
37
|
+
/** A signed percent on the chart's price axis. */
|
|
38
|
+
const pct = (p) => `${p >= 0 ? '+' : MINUS}${Math.abs(p).toFixed(2)}%`;
|
|
39
|
+
/** How near (px) a tick may sit to a line's value tag before it is left blank: one tag's height. */
|
|
40
|
+
const TAG_PX = 16;
|
|
37
41
|
export function fmtValue(s, v) {
|
|
38
42
|
return `${s.prefix}${v
|
|
39
43
|
.toLocaleString('en-US', {
|
|
@@ -143,7 +147,25 @@ export function MarketLines({ symbols: all }) {
|
|
|
143
147
|
},
|
|
144
148
|
localization: {
|
|
145
149
|
timeFormatter: (t) => clock(t, timeZone),
|
|
146
|
-
priceFormatter:
|
|
150
|
+
priceFormatter: pct,
|
|
151
|
+
// A tick a line's value tag would cover is left blank, so the two never overlap.
|
|
152
|
+
tickmarksPriceFormatter: (prices) => {
|
|
153
|
+
const ref = [...lines.current.values()][0];
|
|
154
|
+
const tags = [...lines.current.values(), ...extLines.current.values()]
|
|
155
|
+
.filter((s) => s.options().lastValueVisible)
|
|
156
|
+
.map((s) => s.data().at(-1))
|
|
157
|
+
.flatMap((d) => (d?.value === undefined ? [] : [d.value]));
|
|
158
|
+
const y = (p) => ref?.priceToCoordinate(p) ?? null;
|
|
159
|
+
return prices.map((p) => {
|
|
160
|
+
const at = y(p);
|
|
161
|
+
const covered = at !== null &&
|
|
162
|
+
tags.some((t) => {
|
|
163
|
+
const ty = y(t);
|
|
164
|
+
return ty !== null && Math.abs(ty - at) < TAG_PX;
|
|
165
|
+
});
|
|
166
|
+
return covered ? '' : pct(p);
|
|
167
|
+
});
|
|
168
|
+
},
|
|
147
169
|
},
|
|
148
170
|
crosshair: { mode: CrosshairMode.Normal },
|
|
149
171
|
handleScale: false,
|
|
@@ -234,7 +256,7 @@ export function MarketLines({ symbols: all }) {
|
|
|
234
256
|
return (_jsx("p", { className: "py-6 text-center text-sm text-muted-foreground", children: "No bars for this session yet." }));
|
|
235
257
|
if (!ready)
|
|
236
258
|
return _jsx(Skeleton, { "aria-busy": true, className: "h-72 w-full sm:h-80" });
|
|
237
|
-
return (_jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [_jsx("div", { className: "flex flex-
|
|
259
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-col gap-2", children: [_jsx("div", { className: "flex flex-wrap justify-between gap-x-1 sm:justify-start sm:gap-x-3", children: shown.map((s, i) => {
|
|
238
260
|
const ch = hover?.[s.key] ?? changeOf(s);
|
|
239
261
|
const last = s.bars.at(-1)?.c;
|
|
240
262
|
const ext = extendedOf(s);
|
|
@@ -248,7 +270,11 @@ export function MarketLines({ symbols: all }) {
|
|
|
248
270
|
const CHIP = 'h-4 px-1.5 text-[10px]';
|
|
249
271
|
/** "≈ SPY": the row is priced from that ETF. Purple, so it never reads as a warning. */
|
|
250
272
|
const ProxyChip = ({ text, title }) => (_jsx(Badge, { variant: "outline", title: title, className: cn(CHIP, 'num shrink-0 border-proxy/40 bg-proxy/10 text-proxy'), children: text }));
|
|
251
|
-
|
|
273
|
+
/** "Delayed", and the time of the value shown when it is known. */
|
|
274
|
+
const DelayedChip = ({ at }) => {
|
|
275
|
+
const { timeZone } = usePrefs();
|
|
276
|
+
return (_jsxs(Badge, { variant: "outline", className: cn(CHIP, 'border-warning/50 bg-warning/10 text-warning'), children: ["Delayed", at !== undefined ? ` · ${clock(at, timeZone).replace(/ [A-Z]{2,5}$/, '')}` : ''] }));
|
|
277
|
+
};
|
|
252
278
|
/** One widget per symbol: change, sparkline over the prior close, value, and its source chip. */
|
|
253
279
|
export function MarketTiles({ symbols }) {
|
|
254
280
|
const liveKeys = useMemo(() => symbols.filter((k) => !isDailyMarketKey(k)), [symbols]);
|
|
@@ -281,7 +307,14 @@ export function MarketTiles({ symbols }) {
|
|
|
281
307
|
function TileState({ label, text, tone, loading, children, }) {
|
|
282
308
|
return (_jsxs("div", { "aria-busy": loading || undefined, className: "flex h-[7.5rem] min-w-0 flex-col gap-1 rounded-lg border bg-card p-2.5", children: [_jsx("span", { className: "truncate font-semibold", children: label }), loading ? (_jsx(Skeleton, { className: "h-14 w-full" })) : (_jsxs("span", { className: "flex h-14 items-center gap-1.5 text-xs text-muted-foreground", children: [tone === 'error' ? (_jsx(CircleAlert, { className: "size-3.5 shrink-0 text-loss" })) : (_jsx(CircleSlash, { className: "size-3.5 shrink-0" })), _jsx("span", { className: "line-clamp-3", children: text })] })), _jsxs("span", { className: "flex items-center justify-between gap-2 text-[10px] text-muted-foreground", children: [loading ? (_jsxs("span", { className: "flex items-center gap-1", children: [_jsx(LoaderCircle, { className: "size-3 animate-spin" }), text] })) : (_jsx("span", {})), children] })] }));
|
|
283
309
|
}
|
|
310
|
+
/** How long a widget shows its first bars as on the way before it says there are none. */
|
|
311
|
+
const FIRST_BARS_MS = 90_000;
|
|
284
312
|
function Widget({ s, onOpen, live }) {
|
|
313
|
+
const [waited, setWaited] = useState(false);
|
|
314
|
+
useEffect(() => {
|
|
315
|
+
const t = setTimeout(() => setWaited(true), FIRST_BARS_MS);
|
|
316
|
+
return () => clearTimeout(t);
|
|
317
|
+
}, []);
|
|
285
318
|
const last = s.bars.at(-1)?.c;
|
|
286
319
|
const ch = s.daily?.points && last !== undefined && s.prevClose !== null
|
|
287
320
|
? last - s.prevClose
|
|
@@ -306,7 +339,7 @@ function Widget({ s, onOpen, live }) {
|
|
|
306
339
|
const hi = Math.max(...values, s.prevClose ?? Number.NEGATIVE_INFINITY);
|
|
307
340
|
const pad = (hi - lo) * 0.12 || 1;
|
|
308
341
|
const tone = up ? 'var(--gain)' : 'var(--loss)';
|
|
309
|
-
return (_jsxs("button", { type: "button", onClick: onOpen, disabled: !onOpen, "aria-label": `${s.label} ${ch === null ? '' : fmtCh(ch)}, open chart`, className: "flex min-w-0 flex-col gap-1 rounded-lg border bg-card p-2.5 text-left transition-colors hover:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-default", children: [_jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [_jsx("span", { className: "min-w-0 truncate font-semibold", children: s.label }), ch !== null && (_jsx("span", { className: cn('num shrink-0 text-xs whitespace-nowrap', up ? 'text-gain' : 'text-loss'), children: fmtCh(ch) }))] }), ext ? (_jsxs("span", { className: "num truncate text-xs text-muted-foreground", children: [ext.label, ' ', _jsx("span", { className: ext.change >= 0 ? 'text-gain' : 'text-loss', children: fmtPct(ext.change).slice(0, -2) })] })) : (_jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: s.name })), data.length > 1 ? (_jsx(ChartContainer, { config: { c: { label: s.label, color: tone } }, className: "aspect-auto h-14 w-full", children: _jsxs(AreaChart, { data: data, margin: { top: 2, bottom: 2, left: 0, right: 0 }, children: [_jsx(YAxis, { hide: true, domain: [lo - pad, hi + pad] }), s.prevClose !== null && !s.daily && (_jsx(ReferenceLine, { y: s.prevClose, stroke: "var(--muted-foreground)", strokeDasharray: "3 3" })), _jsx(Area, { dataKey: "c", type: "linear", stroke: tone, strokeWidth: 1.5, fill: tone, fillOpacity: 0.1, isAnimationActive: false, dot: false }), ext && (_jsx(Area, { dataKey: "e", type: "linear", stroke: ext.change >= 0 ? 'var(--gain)' : 'var(--loss)', strokeWidth: 1.5, strokeDasharray: "3 2", fill: "none", isAnimationActive: false, dot: false }))] }) })) : (_jsx("span", { className: "grid h-14 place-items-center text-xs text-muted-foreground", children: s.error
|
|
342
|
+
return (_jsxs("button", { type: "button", onClick: onOpen, disabled: !onOpen, "aria-label": `${s.label} ${ch === null ? '' : fmtCh(ch)}, open chart`, className: "flex min-w-0 flex-col gap-1 rounded-lg border bg-card p-2.5 text-left transition-colors hover:bg-muted/40 focus-visible:ring-2 focus-visible:ring-ring focus-visible:outline-none disabled:cursor-default", children: [_jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [_jsx("span", { className: "min-w-0 truncate font-semibold", children: s.label }), ch !== null && (_jsx("span", { className: cn('num shrink-0 text-xs whitespace-nowrap', up ? 'text-gain' : 'text-loss'), children: fmtCh(ch) }))] }), ext ? (_jsxs("span", { className: "num truncate text-xs text-muted-foreground", children: [ext.label, ' ', _jsx("span", { className: ext.change >= 0 ? 'text-gain' : 'text-loss', children: fmtPct(ext.change).slice(0, -2) })] })) : (_jsx("span", { className: "truncate text-[11px] text-muted-foreground", children: s.name })), data.length > 1 ? (_jsx(ChartContainer, { config: { c: { label: s.label, color: tone } }, className: "aspect-auto h-14 w-full", children: _jsxs(AreaChart, { data: data, margin: { top: 2, bottom: 2, left: 0, right: 0 }, children: [_jsx(YAxis, { hide: true, domain: [lo - pad, hi + pad] }), s.prevClose !== null && !s.daily && (_jsx(ReferenceLine, { y: s.prevClose, stroke: "var(--muted-foreground)", strokeDasharray: "3 3" })), _jsx(Area, { dataKey: "c", type: "linear", stroke: tone, strokeWidth: 1.5, fill: tone, fillOpacity: 0.1, isAnimationActive: false, dot: false }), ext && (_jsx(Area, { dataKey: "e", type: "linear", stroke: ext.change >= 0 ? 'var(--gain)' : 'var(--loss)', strokeWidth: 1.5, strokeDasharray: "3 2", fill: "none", isAnimationActive: false, dot: false }))] }) })) : s.error ? (_jsx("span", { className: "grid h-14 place-items-center text-xs text-muted-foreground", children: s.error })) : waited ? (_jsx("span", { className: "grid h-14 place-items-center text-xs text-muted-foreground", children: "No bars yet" })) : (_jsx(Skeleton, { "aria-busy": true, className: "h-14 w-full" })), _jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [last !== undefined ? (_jsx("span", { className: "num text-sm", children: fmtValue(s, last) })) : (_jsx(Skeleton, { className: "h-5 w-14" })), s.daily ? (_jsxs("span", { className: "text-[10px] text-muted-foreground", children: ["Daily \u00B7 ", day(s.daily.asOf)] })) : s.delayed ? (last !== undefined && _jsx(DelayedChip, { at: s.bars.at(-1)?.t })) : s.via ? (_jsxs("span", { className: "text-[10px] text-muted-foreground", children: ["via ", s.via] })) : live ? (_jsx("span", { className: "text-[10px] text-muted-foreground", children: "Live" })) : null] })] }));
|
|
310
343
|
}
|
|
311
344
|
/**
|
|
312
345
|
* Up or down today: one row per symbol with its price now and its change today,
|
|
@@ -339,7 +372,7 @@ export function MarketToday({ symbols: all }) {
|
|
|
339
372
|
return (_jsxs("div", { className: "flex flex-col gap-1", children: [_jsxs("p", { className: "num flex items-center gap-2 text-xs text-muted-foreground", children: [_jsxs("span", { className: "text-gain", children: ["\u25B2 ", up, " up"] }), _jsxs("span", { className: "text-loss", children: ["\u25BC ", down, " down"] }), session && _jsx("span", { className: "ml-auto font-sans", children: session })] }), _jsx("div", { className: "flex flex-col", children: rows.map(({ s, today, proxy }) => {
|
|
340
373
|
const ch = today?.change ?? null;
|
|
341
374
|
const tone = ch === null ? 'text-muted-foreground' : ch >= 0 ? 'text-gain' : 'text-loss';
|
|
342
|
-
return (_jsxs(Button, { variant: "ghost", className: "h-auto min-w-0 justify-between gap-3 px-2 py-1.5 font-normal", disabled: !open, onClick: () => open?.(s.key), title: `Open ${s.label}'s chart`, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: "truncate font-semibold", children: s.label }), proxy && (_jsx(ProxyChip, { text: `≈ ${proxy}`, title: `${s.label} is priced from ${proxy}'s move${today?.label ? ` ${today.label.toLowerCase()}` : ''}.` })), s.delayed && !today
|
|
375
|
+
return (_jsxs(Button, { variant: "ghost", className: "h-auto min-w-0 justify-between gap-3 px-2 py-1.5 font-normal", disabled: !open, onClick: () => open?.(s.key), title: `Open ${s.label}'s chart`, children: [_jsxs("span", { className: "flex min-w-0 items-center gap-2", children: [_jsx("span", { className: "truncate font-semibold", children: s.label }), proxy && (_jsx(ProxyChip, { text: `≈ ${proxy}`, title: `${s.label} is priced from ${proxy}'s move${today?.label ? ` ${today.label.toLowerCase()}` : ''}.` })), s.delayed && today && !today.label && _jsx(DelayedChip, {})] }), today ? (_jsxs("span", { className: "flex shrink-0 items-center gap-3", children: [_jsx("span", { className: "num text-xs text-muted-foreground", children: fmtValue(s, today.value) }), _jsx("span", { className: cn('num w-16 text-right text-sm font-semibold', tone), children: ch === null ? '—' : fmtPct(ch) })] })) : (_jsx(Skeleton, { className: "h-4 w-28 shrink-0" }))] }, s.key));
|
|
343
376
|
}) }), proxied.length > 0 && (_jsxs("p", { className: "flex items-start gap-2 border-t px-2 pt-2 text-xs text-muted-foreground", children: [_jsx(ProxyChip, { text: "\u2248" }), _jsx("span", { children: proxied.length === 1
|
|
344
377
|
? `Proxy: ${proxied[0]?.s.label} moves with ${proxied[0]?.proxy}.`
|
|
345
378
|
: "Proxy: these don't trade now, so each moves with its ETF." })] }))] }));
|
package/dist/summary-cards.js
CHANGED
|
@@ -19,7 +19,9 @@ export function figuresOf(domain, t, rows, fields) {
|
|
|
19
19
|
if (!f)
|
|
20
20
|
return null;
|
|
21
21
|
const count = isCountAgg(t.agg);
|
|
22
|
-
const
|
|
22
|
+
const own = filterByTokens(rows, fields, t.filter);
|
|
23
|
+
// A sum over no rows is nothing yet: $0, never a dash.
|
|
24
|
+
const value = roll(f, t.agg, own) ?? (t.agg === 'sum' && !own.length ? 0 : null);
|
|
23
25
|
const main = {
|
|
24
26
|
kind: 'value',
|
|
25
27
|
value,
|
|
@@ -36,15 +38,21 @@ export function figuresOf(domain, t, rows, fields) {
|
|
|
36
38
|
if (l.kind === 'pct') {
|
|
37
39
|
const of = roll(lf, l.agg, rows);
|
|
38
40
|
const pct = typeof value === 'number' && typeof of === 'number' && of !== 0 ? (value / of) * 100 : null;
|
|
41
|
+
// A line with nothing to say is left out, never a dash in a sentence.
|
|
42
|
+
if (pct === null)
|
|
43
|
+
return [];
|
|
39
44
|
return [
|
|
40
45
|
{ kind: 'value', value: pct, format: 'weight', amount: false, suffix: `of ${lf.label}` },
|
|
41
46
|
];
|
|
42
47
|
}
|
|
43
48
|
const c = isCountAgg(l.agg);
|
|
49
|
+
const lv = roll(lf, l.agg, filterByTokens(rows, fields, l.filter));
|
|
50
|
+
if (lv === null)
|
|
51
|
+
return [];
|
|
44
52
|
return [
|
|
45
53
|
{
|
|
46
54
|
kind: 'value',
|
|
47
|
-
value:
|
|
55
|
+
value: lv,
|
|
48
56
|
format: c ? 'rounded' : lf.format,
|
|
49
57
|
amount: !c && !!lf.amount,
|
|
50
58
|
suffix: l.suffix || undefined,
|
|
@@ -85,8 +93,8 @@ export function LumenCard({ domain, tile: t, rows, fields, drawn, loading, style
|
|
|
85
93
|
const tone = meterTone(meter, share, bands ?? (meter ? kitBands(meter) : undefined));
|
|
86
94
|
const of = target ? (_jsx(ViewValueCell, { value: target, format: figs.main.format, amount: figs.main.amount })) : null;
|
|
87
95
|
if (style === 'progress_circle')
|
|
88
|
-
return (_jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx(ProgressRing, { value: share, tone: tone }), _jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx("span", { className: "num truncate text-xl leading-7 font-semibold", children: _jsx(FigureText, { f: figs.main }) }), _jsx("span", { className: "
|
|
89
|
-
return (_jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx("span", { className: cn('num truncate text-2xl leading-8 font-semibold', t.sign && typeof v === 'number' && (v > 0 ? 'text-gain' : v < 0 ? 'text-loss' : '')), children: _jsx(FigureText, { f: figs.main }) }), style === 'progress_bar' && (_jsxs("div", { className: "flex flex-col gap-1 pt-1", children: [_jsx(Progress, { value: share ?? 0, className: cn('h-2', tone && TONE_BAR[tone]), "aria-label": "Progress to target" }), _jsx("span", { className: "
|
|
96
|
+
return (_jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [_jsx(ProgressRing, { value: share, tone: tone }), _jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx("span", { className: "num truncate text-xl leading-7 font-semibold", children: _jsx(FigureText, { f: figs.main }) }), _jsx("span", { className: "truncate text-xs text-muted-foreground tabular-nums", children: of ? _jsxs(_Fragment, { children: ["of ", of] }) : 'Set a target in Edit widget' })] })] }));
|
|
97
|
+
return (_jsxs("div", { className: "flex min-w-0 flex-col gap-0.5", children: [_jsx("span", { className: cn('num truncate text-2xl leading-8 font-semibold', t.sign && typeof v === 'number' && (v > 0 ? 'text-gain' : v < 0 ? 'text-loss' : '')), children: _jsx(FigureText, { f: figs.main }) }), style === 'progress_bar' && (_jsxs("div", { className: "flex flex-col gap-1 pt-1", children: [_jsx(Progress, { value: share ?? 0, className: cn('h-2', tone && TONE_BAR[tone]), "aria-label": "Progress to target" }), _jsx("span", { className: "text-xs text-muted-foreground tabular-nums", children: of ? (_jsxs(_Fragment, { children: [share === null ? '—' : `${share.toFixed(0)}%`, " of ", of] })) : ('Set a target in Edit widget') })] })), figs.lines.map((l, i) => (_jsx("span", { className: "line-clamp-2 text-xs text-muted-foreground tabular-nums", children: _jsx(FigureText, { f: l }) }, i)))] }));
|
|
90
98
|
}
|
|
91
99
|
/** A meter's bands from the app's `meterLevels` or `healthLevels`, in %. */
|
|
92
100
|
const kitBands = (meter) => {
|
|
@@ -108,7 +116,7 @@ export function SummaryTiles({ domain, tiles, rows, fields, tile, loading, }) {
|
|
|
108
116
|
if (!shown.length)
|
|
109
117
|
return null;
|
|
110
118
|
// Each card fills its column, as a header's metric cards do (`TileRow fill`), not the fixed tile width.
|
|
111
|
-
const grid = 'grid grid-cols-2 gap-(--shell-section-gap) md:auto-cols-
|
|
119
|
+
const grid = 'grid grid-cols-2 gap-(--shell-section-gap) md:auto-cols-[minmax(0,1fr)] md:grid-flow-col lg:*:*:w-auto';
|
|
112
120
|
if (loading)
|
|
113
121
|
return (_jsx("div", { "data-slot": "view-tiles", "aria-busy": "true", className: grid, children: shown.map((t) => (_jsx(Skeleton, { className: "h-[4.5rem] w-full rounded-xl" }, t.key))) }));
|
|
114
122
|
return (_jsx("div", { "data-slot": "view-tiles", className: cn(grid,
|
package/dist/theme.css
CHANGED
|
@@ -740,11 +740,15 @@ body[data-spotlight="nav"] [data-spotlit] {
|
|
|
740
740
|
}
|
|
741
741
|
|
|
742
742
|
/* LumenGrid: react-grid-layout's own rules, in the shell's tokens. */
|
|
743
|
+
/* Cards glide only while a person moves them in Edit layout. On a page that loads they take their
|
|
744
|
+
measured place at once, so a card that settles never leaves a gap sliding shut behind it. */
|
|
743
745
|
.lumen-grid {
|
|
744
746
|
position: relative;
|
|
747
|
+
}
|
|
748
|
+
.lumen-grid-edit {
|
|
745
749
|
transition: height 200ms ease;
|
|
746
750
|
}
|
|
747
|
-
.lumen-grid > .react-grid-item {
|
|
751
|
+
.lumen-grid-edit > .react-grid-item {
|
|
748
752
|
transition: transform 200ms ease, width 200ms ease, height 200ms ease;
|
|
749
753
|
}
|
|
750
754
|
.lumen-grid > .react-grid-item.resizing,
|
package/dist/tile.js
CHANGED
|
@@ -18,7 +18,7 @@ export function TileSpark({ values, color = 'var(--chart-1)', className, }) {
|
|
|
18
18
|
/** A value with no digit in it ("Workers Paid", "Healthy") is a word, not a number. */
|
|
19
19
|
const isWord = (v) => typeof v === 'string' && !/\d/.test(v);
|
|
20
20
|
function TileBody({ label, value, caption, lines, valueClassName, spark, sparkColor, }) {
|
|
21
|
-
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-full truncate text-xs text-muted-foreground", children: label }), _jsx("span", { className: cn(!isWord(value) && 'num', 'truncate text-xl leading-7 font-semibold', valueClassName), children: value }), caption ? (_jsx("span", { className: "line-clamp-2 text-xs text-muted-foreground tabular-nums", children: caption })) : null, lines?.map((l, i) => (_jsx("span", { className: "
|
|
21
|
+
return (_jsxs(_Fragment, { children: [_jsx("span", { className: "w-full truncate text-xs text-muted-foreground", children: label }), _jsx("span", { className: cn(!isWord(value) && 'num', 'truncate text-xl leading-7 font-semibold', valueClassName), children: value }), caption ? (_jsx("span", { className: "line-clamp-2 text-xs text-muted-foreground tabular-nums", children: caption })) : null, lines?.map((l, i) => (_jsx("span", { className: "line-clamp-2 text-xs text-muted-foreground tabular-nums", children: l }, i))), spark ? _jsx(TileSpark, { values: spark, color: sparkColor, className: "mt-1 self-stretch" }) : null] }));
|
|
22
22
|
}
|
|
23
23
|
export function Tile({ label, value, caption, lines, className, valueClassName, spark, sparkColor, }) {
|
|
24
24
|
return (_jsx(Card, { size: "sm", className: cn('min-w-0 flex-1 basis-2/5 gap-0.5 px-3 lg:basis-auto', TILE_WIDTH, className), children: _jsx(TileBody, { label: label, value: value, caption: caption, lines: lines, valueClassName: valueClassName, spark: spark, sparkColor: sparkColor }) }));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.167",
|
|
4
4
|
"description": "Lumen: shared React components (frame, views, widgets, charts, drawers).",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"@codemirror/lang-javascript": "6.2.5",
|
|
50
50
|
"@codemirror/lang-json": "6.0.2",
|
|
51
51
|
"@codemirror/lang-sql": "6.10.0",
|
|
52
|
-
"@columenlabs/lumen-ui-types": "0.1.
|
|
52
|
+
"@columenlabs/lumen-ui-types": "0.1.167",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|