@columenlabs/lumen-ui 0.1.245 → 0.1.247

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.
@@ -22,10 +22,10 @@ import { cardsOnScreen, kindName, pointAt, sectionsOnScreen, targetEl, textOf, }
22
22
  import { Alert, AlertDescription } from '../ui/alert.js';
23
23
  import { Button } from '../ui/button.js';
24
24
  import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '../ui/collapsible.js';
25
+ import { InputGroup, InputGroupAddon, InputGroupTextarea } from '../ui/input-group.js';
25
26
  import { Popover, PopoverContent, PopoverTrigger } from '../ui/popover.js';
26
27
  import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '../ui/sheet.js';
27
28
  import { Spinner } from '../ui/spinner.js';
28
- import { Textarea } from '../ui/textarea.js';
29
29
  import { ChatImage } from './chat-image.js';
30
30
  import { chatMarkdown, chatTurns, copyMarkdown, turnMarkdown } from './copy.js';
31
31
  import { ImageCard, ImagePending, toolIs } from './image-card.js';
@@ -880,7 +880,7 @@ export function LumenComposer({ name, busy, queued, queue, canSteer = false, onS
880
880
  const r = sourceItems.get(o.value)?.();
881
881
  if (r)
882
882
  setRefs((p) => [...p, r]);
883
- }, onClose: () => setClosed(`${text}|${caret}`) })), quote && _jsx(QuoteLine, { quote: quote, onRemove: () => setQuote(null) }), images.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-1.5", "aria-label": "Images going with your message", children: images.map((img, i) => (_jsxs("span", { className: "relative", children: [_jsx("img", { src: imageUrl(img), alt: `Pasted ${i + 1}`, className: "size-12 rounded-md border object-cover" }), _jsx("button", { type: "button", "aria-label": `Remove image ${i + 1}`, className: "absolute -top-1.5 -right-1.5 grid size-4 place-items-center rounded-full border bg-background text-muted-foreground hover:text-foreground", onClick: () => setImages((p) => p.filter((_, j) => j !== i)), children: _jsx(XIcon, { className: "size-3" }) })] }, `${i}:${img.data.length}`))) })), (tierLabel || refs.length > 0) && (_jsxs("div", { className: "mb-2 flex flex-wrap gap-1", children: [tierLabel && (_jsx(ComposerChip, { sign: TIER, label: tierLabel, onRemove: () => setTier(null) })), refs.map((r, i) => (_jsx(ComposerChip, { sign: POINT, label: r.label, onRemove: () => setRefs((p) => p.filter((_, j) => j !== i)) }, `${r.kind}:${r.label}:${i}`)))] })), _jsxs("div", { className: "relative", children: [_jsx(Textarea, { ref: box, "aria-label": `Message ${name}`, placeholder: `Ask ${name}…${hints.length ? ` (${hints.join(' ')})` : ''}`, className: cn('max-h-48 min-h-11 resize-none', busy && text.trim() && canSteer ? 'pr-18' : 'pr-11', (canAttach || modes.length > 0) && 'pb-9'), value: text, disabled: disabled, onChange: (e) => {
883
+ }, onClose: () => setClosed(`${text}|${caret}`) })), quote && _jsx(QuoteLine, { quote: quote, onRemove: () => setQuote(null) }), images.length > 0 && (_jsx("div", { className: "mb-2 flex flex-wrap gap-1.5", "aria-label": "Images going with your message", children: images.map((img, i) => (_jsxs("span", { className: "relative", children: [_jsx("img", { src: imageUrl(img), alt: `Pasted ${i + 1}`, className: "size-12 rounded-md border object-cover" }), _jsx("button", { type: "button", "aria-label": `Remove image ${i + 1}`, className: "absolute -top-1.5 -right-1.5 grid size-4 place-items-center rounded-full border bg-background text-muted-foreground hover:text-foreground", onClick: () => setImages((p) => p.filter((_, j) => j !== i)), children: _jsx(XIcon, { className: "size-3" }) })] }, `${i}:${img.data.length}`))) })), (tierLabel || refs.length > 0) && (_jsxs("div", { className: "mb-2 flex flex-wrap gap-1", children: [tierLabel && (_jsx(ComposerChip, { sign: TIER, label: tierLabel, onRemove: () => setTier(null) })), refs.map((r, i) => (_jsx(ComposerChip, { sign: POINT, label: r.label, onRemove: () => setRefs((p) => p.filter((_, j) => j !== i)) }, `${r.kind}:${r.label}:${i}`)))] })), _jsxs(InputGroup, { children: [_jsx(InputGroupTextarea, { ref: box, "aria-label": `Message ${name}`, placeholder: `Ask ${name}…${hints.length ? ` (${hints.join(' ')})` : ''}`, className: "max-h-48 min-h-11", value: text, disabled: disabled, onChange: (e) => {
884
884
  setText(e.target.value);
885
885
  setCaret(e.target.selectionStart);
886
886
  }, onSelect: (e) => setCaret(e.currentTarget.selectionStart), onPaste: (e) => {
@@ -900,11 +900,11 @@ export function LumenComposer({ name, busy, queued, queue, canSteer = false, onS
900
900
  e.preventDefault();
901
901
  send(e.altKey ? 'queue' : undefined);
902
902
  }
903
- } }), (canAttach || modes.length > 0) && (_jsxs("div", { className: "absolute bottom-1.5 left-1.5 flex items-center gap-0.5", children: [canAttach && (_jsxs(_Fragment, { children: [_jsx(IconButton, { icon: PaperclipIcon, label: "Attach images", size: "icon-xs", disabled: disabled, onClick: () => filePick.current?.click() }), _jsx("input", { ref: filePick, type: "file", accept: "image/*", multiple: true, hidden: true, onChange: (e) => {
903
+ } }), _jsxs(InputGroupAddon, { align: "block-end", className: "gap-0.5 px-1.5 pb-1.5", children: [canAttach && (_jsxs(_Fragment, { children: [_jsx(IconButton, { icon: PaperclipIcon, label: "Attach images", size: "icon-xs", disabled: disabled, onClick: () => filePick.current?.click() }), _jsx("input", { ref: filePick, type: "file", accept: "image/*", multiple: true, hidden: true, onChange: (e) => {
904
904
  if (e.target.files)
905
905
  attach(e.target.files);
906
906
  e.target.value = '';
907
- } })] })), modes.map((md) => (_jsx(IconButton, { icon: md.icon, label: md.label, size: "icon-xs", variant: use === md.id ? 'secondary' : 'ghost', "aria-pressed": use === md.id, className: cn(use === md.id && 'text-primary'), disabled: disabled, onClick: () => setUse((u) => (u === md.id ? null : md.id)) }, md.id)))] })), _jsx("div", { className: "absolute right-1.5 bottom-1.5", children: busy && !text.trim() ? (_jsx(IconButton, { icon: SquareIcon, label: "Stop", variant: "outline", size: "icon-xs", onClick: onStop })) : busy ? (_jsxs("span", { className: "flex gap-1", children: [_jsx(IconButton, { icon: ListPlusIcon, label: canSteer ? 'Queue for after (⌥↩)' : 'Queue for after (↩)', variant: canSteer ? 'outline' : 'default', size: "icon-xs", disabled: disabled, onClick: () => send('queue') }), canSteer && (_jsx(IconButton, { icon: CornerDownRightIcon, label: "Steer now (\u21A9)", variant: "default", size: "icon-xs", disabled: disabled, onClick: () => send('steer') }))] })) : (_jsx(IconButton, { icon: ArrowUpIcon, label: "Send", variant: "default", size: "icon-xs", disabled: !text.trim() || disabled, onClick: () => send() })) })] })] }));
907
+ } })] })), modes.map((md) => (_jsx(IconButton, { icon: md.icon, label: md.label, size: "icon-xs", variant: use === md.id ? 'secondary' : 'ghost', "aria-pressed": use === md.id, className: cn(use === md.id && 'text-primary'), disabled: disabled, onClick: () => setUse((u) => (u === md.id ? null : md.id)) }, md.id))), _jsx("div", { className: "ml-auto", children: busy && !text.trim() ? (_jsx(IconButton, { icon: SquareIcon, label: "Stop", variant: "outline", size: "icon-xs", onClick: onStop })) : busy ? (_jsxs("span", { className: "flex gap-1", children: [_jsx(IconButton, { icon: ListPlusIcon, label: canSteer ? 'Queue for after (⌥↩)' : 'Queue for after (↩)', variant: canSteer ? 'outline' : 'default', size: "icon-xs", disabled: disabled, onClick: () => send('queue') }), canSteer && (_jsx(IconButton, { icon: CornerDownRightIcon, label: "Steer now (\u21A9)", variant: "default", size: "icon-xs", disabled: disabled, onClick: () => send('steer') }))] })) : (_jsx(IconButton, { icon: ArrowUpIcon, label: "Send", variant: "default", size: "icon-xs", disabled: !text.trim() || disabled, onClick: () => send() })) })] })] })] }));
908
908
  }
909
909
  /**
910
910
  * What waits above the box while an answer runs: steering messages until the answer reads them,
@@ -170,7 +170,7 @@ function Providers({ client }) {
170
170
  // is exactly what the server may pay with.
171
171
  const rows = s.providers.filter((p) => !p.own_ways || p.own_ways.length > 0);
172
172
  const ownSet = rows.some(ownUsable);
173
- return (_jsxs("div", { className: "flex flex-col", children: [_jsx(LumenExpandList, { children: rows.map((p) => (_jsx(OwnProviderKey, { client: client, p: p }, p.id))) }), ownSet && (_jsx(SettingField, { label: "Answers run on", info: "Your own key or plan first, with the shared credits behind it; or the shared credits first.", children: _jsxs(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, value: s.pay, "aria-label": "Answers run on", onValueChange: (pay) => pay && void apply('pay', () => client.settings({ pay: pay })), children: [_jsx(ToggleGroupItem, { value: "own", children: "Your own first" }), _jsx(ToggleGroupItem, { value: "app", children: "Credits first" })] }) })), ownSet && (_jsx(SettingField, { label: "Your keys may spend", info: "On your keys, every provider together.", children: _jsx(CapInput, { label: "Your monthly cap", value: s.caps.own, onSave: (n) => void apply('own', () => client.ownCap(n)) }) })), ownSet && _jsx(OwnCapUse, { s: s }), _jsx(OwnKeyUsage, { client: client, always: ownSet })] }));
173
+ return (_jsxs("div", { className: "flex flex-col", children: [_jsx(LumenExpandList, { children: rows.map((p) => (_jsx(OwnProviderKey, { client: client, p: p }, p.id))) }), ownSet && (_jsx(SettingField, { label: "Answers run on", info: "Your own key or plan first, with the shared credits behind it; or the shared credits first.", children: _jsxs(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, value: s.pay, "aria-label": "Answers run on", onValueChange: (pay) => pay && void apply('pay', () => client.settings({ pay: pay })), children: [_jsx(ToggleGroupItem, { value: "own", children: "Your own first" }), _jsx(ToggleGroupItem, { value: "app", children: "Credits first" })] }) })), ownSet && (_jsx(SettingField, { label: "Your keys may spend", info: "On your keys, every provider together.", children: _jsx(CapInput, { label: "Your monthly cap", value: s.caps.own, onSave: (n) => void apply('own', () => client.ownCap(n)) }) })), ownSet && _jsx(OwnCapUse, { s: s }), _jsx(OwnKeyUsage, { client: client, always: ownSet, usable: rows.filter(ownUsable).map((p) => p.id) })] }));
174
174
  } }));
175
175
  }
176
176
  /**
@@ -178,14 +178,14 @@ function Providers({ client }) {
178
178
  * against, so this and the switch to shared credits never disagree.
179
179
  */
180
180
  function OwnCapUse({ s }) {
181
- const used = s.spend.rows
182
- .filter((r) => r.payer === 'own' && !r.free)
183
- .reduce((a, r) => a + r.usd, 0);
181
+ // The server's own count (key calls only, on providers still set); older servers sum own rows.
182
+ const used = s.spend.own_used ??
183
+ s.spend.rows.filter((r) => r.payer === 'own' && !r.free).reduce((a, r) => a + r.usd, 0);
184
184
  const cap = s.caps.own;
185
185
  const full = cap > 0 && used >= cap;
186
186
  return (_jsx(SettingField, { label: "Used this month", info: full
187
187
  ? 'Your cap is used up, so the shared credits pay until next month or until you raise the cap.'
188
- : 'What your own keys and plan have spent this month, against your cap.', children: _jsxs("div", { className: "flex w-56 min-w-0 flex-col gap-1", children: [_jsx(ShareMeter, { value: cap > 0 ? used / cap : 1, label: `${usd(used)} of ${usd(cap)}`, wide: true }), full && _jsx("span", { className: "text-muted-foreground text-xs", children: "Cap reached: credits pay" })] }) }));
188
+ : 'What your own API keys spent this month, against your cap. A plan sign-in counts nothing.', children: _jsxs("div", { className: "flex w-56 min-w-0 flex-col gap-1", children: [_jsx(ShareMeter, { value: cap > 0 ? used / cap : 1, wide: true, capped: true }), _jsxs("span", { className: "truncate text-muted-foreground text-xs", title: `${usd(used)} of ${usd(cap)}${full ? ' · Cap reached: credits pay' : ''}`, children: [_jsxs("span", { className: "num", children: [usd(used), " of ", usd(cap)] }), full && ' · Cap reached: credits pay'] })] }) }));
189
189
  }
190
190
  /** One provider's shared key, which an admin sets for everyone. */
191
191
  function SharedProviderKey({ client, p }) {
@@ -18,7 +18,9 @@ export declare function UsageHistoryView({ client, className, }: {
18
18
  * (Session, Date, Amount), newest first, and a Total of the rows. A session counts in the range its
19
19
  * last use falls in. Shown when `always` (an own key or plan is set) or any session was paid on one.
20
20
  */
21
- export declare function OwnKeyUsage({ client, always }: {
21
+ export declare function OwnKeyUsage({ client, always, usable, }: {
22
22
  client: AssistantAdapter;
23
23
  always?: boolean;
24
+ /** Providers the person can pay with now: earlier spend on any other is listed apart, uncounted. */
25
+ usable?: string[];
24
26
  }): import("react").JSX.Element | null;
@@ -102,7 +102,7 @@ const OWN_RANGES = [
102
102
  * (Session, Date, Amount), newest first, and a Total of the rows. A session counts in the range its
103
103
  * last use falls in. Shown when `always` (an own key or plan is set) or any session was paid on one.
104
104
  */
105
- export function OwnKeyUsage({ client, always }) {
105
+ export function OwnKeyUsage({ client, always, usable, }) {
106
106
  const [range, setRange] = useState('7d');
107
107
  const now = useAssistantUsage(client).data;
108
108
  // The month before, for a range that reaches back past this month's start.
@@ -122,13 +122,21 @@ export function OwnKeyUsage({ client, always }) {
122
122
  // This month's own spend that no chat or run carries (spent before per-chat tracking), so the
123
123
  // table never reads "nothing" while the cap's own numbers say otherwise.
124
124
  const tagged = now.entries.reduce((a, e) => a + (e.own_usd ?? 0), 0);
125
- const ownMonth = now.rows
126
- .filter((r) => r.payer === 'own' && !r.free)
127
- .reduce((a, r) => a + r.usd, 0);
128
- const untracked = ownMonth - tagged >= 0.01 ? ownMonth - tagged : 0;
129
- const total = sessions.reduce((a, e) => a + (e.own_usd ?? 0), 0) + untracked;
125
+ // A plan sign-in's calls cost nothing, so they are no one's spend.
126
+ const ownRows = now.rows.filter((r) => r.payer === 'own' && !r.free && r.way !== 'plan');
127
+ const removed = usable && ownRows.length
128
+ ? ownRows
129
+ .filter((r) => r.provider && !usable.includes(r.provider))
130
+ .reduce((a, r) => a + r.usd, 0)
131
+ : 0;
132
+ const ownMonth = ownRows.reduce((a, r) => a + r.usd, 0);
133
+ const left = ownMonth - tagged - removed;
134
+ const untracked = left >= 0.01 ? left : 0;
135
+ const gone = removed >= 0.01 ? removed : 0;
136
+ const total = sessions.reduce((a, e) => a + (e.own_usd ?? 0), 0) + untracked + gone;
130
137
  const earlier = 'Earlier this month, not per chat';
131
- return (_jsxs("div", { className: "flex flex-col gap-2 border-t border-border/60 pb-3 first:border-t-0", children: [_jsx(SettingField, { label: "Spent on your keys", info: "Each chat and run your own key or plan paid for, by its last use.", className: "border-t-0", end: _jsx(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, value: range, "aria-label": "Range", onValueChange: (v) => v && setRange(v), children: OWN_RANGES.map((r) => (_jsx(ToggleGroupItem, { value: r.id, "aria-label": `Last ${r.id}`, children: r.id }, r.id))) }) }), sessions.length || untracked ? (_jsx(DetailsTable, { head: [
138
+ const removedText = 'Key not in use now, not counted';
139
+ return (_jsxs("div", { className: "flex flex-col gap-2 border-t border-border/60 pb-3 first:border-t-0", children: [_jsx(SettingField, { label: "Spent on your keys", info: "Each chat and run your own key or plan paid for, by its last use.", className: "border-t-0", end: _jsx(ToggleGroup, { type: "single", variant: "outline", size: "sm", spacing: 0, value: range, "aria-label": "Range", onValueChange: (v) => v && setRange(v), children: OWN_RANGES.map((r) => (_jsx(ToggleGroupItem, { value: r.id, "aria-label": `Last ${r.id}`, children: r.id }, r.id))) }) }), sessions.length || untracked || gone ? (_jsx(DetailsTable, { head: [
132
140
  { label: 'Session', grow: true },
133
141
  { label: 'Date', hideOnPhone: true },
134
142
  { label: 'Amount', right: true },
@@ -153,5 +161,17 @@ export function OwnKeyUsage({ client, always }) {
153
161
  },
154
162
  ]
155
163
  : []),
164
+ ...(gone
165
+ ? [
166
+ {
167
+ key: 'removed',
168
+ cells: [
169
+ _jsx("span", { className: "block truncate text-muted-foreground", title: removedText, children: removedText }, "n"),
170
+ _jsx("span", {}, "t"),
171
+ usd(gone),
172
+ ],
173
+ },
174
+ ]
175
+ : []),
156
176
  ], foot: ['Total', _jsx("span", { className: "max-md:hidden" }, "d"), usd(total)] })) : (_jsxs("p", { className: "text-muted-foreground text-sm", children: ["Nothing spent on your keys in the last ", range, "."] }))] }));
157
177
  }
@@ -1,8 +1,12 @@
1
1
  import type { AssistantEvent, AssistantMessage, AssistantScreenOutcome, ChatItem, ChatUsage, DraftItem, StepItem } from '@columenlabs/lumen-ui-types/assistant';
2
2
  import type { AssistantAdapter } from './client.js';
3
- /** An item as the panel draws it: a text still streaming, a step still running. */
3
+ /**
4
+ * An item as the panel draws it: a text still streaming, a step still running. `writing` marks a
5
+ * running step whose tool makes a change at once, so an app can show what it changes as changing.
6
+ */
4
7
  export type LiveItem = ChatItem & {
5
8
  live?: boolean;
9
+ writing?: boolean;
6
10
  };
7
11
  type Extra = Omit<AssistantMessage, 'message' | 'chat_id'>;
8
12
  /** A message sent while an answer runs: waiting for it to end, or steered into it. */
@@ -83,6 +83,7 @@ export function applyEvent(prev, e) {
83
83
  ok: true,
84
84
  ms: 0,
85
85
  live: true,
86
+ ...(e.data.write ? { writing: true } : {}),
86
87
  });
87
88
  break;
88
89
  case 'step': {
@@ -157,7 +158,7 @@ const settled = (items) => items.map((i) => {
157
158
  return { ...i, items: settled(i.items) };
158
159
  if (!i.live || i.kind === 'screen')
159
160
  return i;
160
- const { live: _l, ...rest } = i;
161
+ const { live: _l, writing: _w, ...rest } = i;
161
162
  return rest;
162
163
  });
163
164
  export function useAssistantChat(client) {
@@ -8,7 +8,7 @@ export interface ShareSegment {
8
8
  /** Who it is, read out by screen readers and in the bar's hover (`web 122%`). */
9
9
  label?: string;
10
10
  }
11
- export declare function ShareMeter({ value, label, color, kind, levels, segments, wide, className, }: {
11
+ export declare function ShareMeter({ value, label, color, kind, levels, segments, wide, capped, className, }: {
12
12
  /** 0 to 1 fills the bar; past 1 it stays full and the overage spills past a tick at the cap. */
13
13
  value: number;
14
14
  /** The number beside the bar, e.g. `113%`; left out, the rounded percent. */
@@ -23,5 +23,7 @@ export declare function ShareMeter({ value, label, color, kind, levels, segments
23
23
  segments?: ShareSegment[];
24
24
  /** Fills its cell (a list row) instead of the fixed table width. */
25
25
  wide?: boolean;
26
+ /** A share that stops at its cap: no spill slot, so the bar takes the whole track. */
27
+ capped?: boolean;
26
28
  className?: string;
27
29
  }): import("react").JSX.Element;
@@ -4,16 +4,16 @@ import { METER_LEVEL_COLOR, meterLevel } from './meter-level.js';
4
4
  import { Progress } from './ui/progress.js';
5
5
  /** How far past the cap the spill stub can grow (a share of the cap). */
6
6
  const SPILL_MAX = 0.5;
7
- export function ShareMeter({ value, label, color, kind, levels, segments, wide, className, }) {
7
+ export function ShareMeter({ value, label, color, kind, levels, segments, wide, capped, className, }) {
8
8
  const said = segments
9
9
  ?.filter((s) => s.value > 0)
10
10
  .map((s) => `${s.label ?? ''} ${Math.round(s.value * 100)}%`.trim());
11
- const over = kind !== 'health' && value > 1;
11
+ const over = !capped && kind !== 'health' && value > 1;
12
12
  const spill = over ? Math.min(value - 1, SPILL_MAX) / SPILL_MAX : 0;
13
13
  return (_jsxs("span", { className: cn('inline-flex items-center gap-2', wide && 'w-full', className), title: said?.length ? said.join(' · ') : undefined, children: [_jsxs("span", { "data-slot": "share-meter", "data-over": over || undefined, className: cn('flex shrink-0 items-center', wide ? 'w-full shrink' : 'w-16'), style: {
14
14
  '--meter-color': color ?? METER_LEVEL_COLOR[meterLevel(value, levels, kind)],
15
- }, children: [_jsx(Progress, { value: Math.max(0, Math.min(value, 1)) * 100, "aria-label": said?.length ? said.join(', ') : undefined, className: cn('h-1.5 w-auto flex-2 [&>[data-slot=progress-indicator]]:bg-(--meter-color)', over && 'rounded-r-none') }), _jsx("span", { "aria-hidden": true, className: "flex h-1.5 flex-1", children: over && (_jsx("span", { "data-slot": "share-spill", className: "h-full min-w-1 rounded-r-full border-foreground/70 border-l-2", style: {
15
+ }, children: [_jsx(Progress, { value: Math.max(0, Math.min(value, 1)) * 100, "aria-label": said?.length ? said.join(', ') : undefined, className: cn('h-1.5 w-auto flex-2 [&>[data-slot=progress-indicator]]:bg-(--meter-color)', over && 'rounded-r-none') }), _jsx("span", { "aria-hidden": true, className: cn('flex h-1.5 flex-1', capped && 'hidden'), children: over && (_jsx("span", { "data-slot": "share-spill", className: "h-full min-w-1 rounded-r-full border-foreground/70 border-l-2", style: {
16
16
  width: `${spill * 100}%`,
17
17
  background: 'repeating-linear-gradient(135deg, var(--meter-color) 0 2px, transparent 2px 4px)',
18
- } })) })] }), _jsx("span", { className: "num w-11 shrink-0 text-right text-xs", children: label ?? `${Math.round(value * 100)}%` })] }));
18
+ } })) })] }), _jsx("span", { className: cn('num shrink-0 text-right text-xs', capped ? 'w-auto' : 'w-11'), children: label ?? `${Math.round(value * 100)}%` })] }));
19
19
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ui",
3
- "version": "0.1.245",
3
+ "version": "0.1.247",
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.245",
52
+ "@columenlabs/lumen-ui-types": "0.1.247",
53
53
  "@dnd-kit/core": "6.3.1",
54
54
  "@dnd-kit/sortable": "10.0.0",
55
55
  "@dnd-kit/utilities": "3.2.2",