@columenlabs/lumen-ui 0.1.213 → 0.1.215

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.
@@ -1,6 +1,6 @@
1
1
  import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  // ChatImage: an image in a chat message. A thumbnail until clicked; then it opens full width in place,
3
- // where the wheel or a pinch zooms at the pointer, a drag or two fingers pan and a double-click
3
+ // where a pinch (or Ctrl + wheel) zooms at the pointer, a drag or two fingers pan and a double-click
4
4
  // toggles fit and 2× (react-zoom-pan-pinch). Its toolbar zooms, resets, opens the image in a 90%
5
5
  // lightbox with the same controls (the kit's Dialog: Esc, × or a click outside closes it) and
6
6
  // shrinks it back to the thumbnail.
@@ -20,8 +20,11 @@ function ZoomBar({ children }) {
20
20
  return (_jsxs("div", { className: "absolute top-2 right-2 z-10 flex items-center gap-0.5 rounded-lg border bg-popover/90 p-0.5 text-popover-foreground shadow-sm backdrop-blur-sm", "data-slot": "image-zoom-bar", children: [_jsx(IconButton, { icon: ZoomOutIcon, label: "Zoom out", disabled: scale <= 1.001, onClick: () => zoomOut() }), _jsxs("span", { className: "num min-w-10 text-center text-muted-foreground text-xs", "aria-live": "polite", children: [Math.round(scale * 100), "%"] }), _jsx(IconButton, { icon: ZoomInIcon, label: "Zoom in", disabled: scale >= MAX_SCALE - 0.001, onClick: () => zoomIn() }), _jsx(IconButton, { icon: RotateCcwIcon, label: "Reset zoom", onClick: () => resetTransform() }), _jsx("span", { className: "mx-0.5 h-4 w-px bg-border", "aria-hidden": true }), children] }));
21
21
  }
22
22
  /** The image at fit (scale 1), with zoom and pan; the wrapper takes the box its parent gives it. */
23
- function Zoomable({ src, alt, children, }) {
24
- return (_jsxs(TransformWrapper, { minScale: 1, maxScale: MAX_SCALE, centerZoomedOut: true, wheel: { step: 0.004 }, doubleClick: { mode: 'toggle', step: 1 }, children: [_jsx(ZoomBar, { children: children }), _jsx(TransformComponent, { wrapperClass: "!size-full cursor-grab active:cursor-grabbing", contentClass: "!size-full", children: _jsx("img", { src: src, alt: alt, draggable: false, className: "size-full object-contain" }) })] }));
23
+ function Zoomable({ src, alt, panAtFit = false, children, }) {
24
+ const [zoomed, setZoomed] = useState(false);
25
+ return (_jsxs(TransformWrapper, { minScale: 1, maxScale: MAX_SCALE, centerZoomedOut: true,
26
+ // A pinch (a wheel with ctrlKey) zooms; two fingers or a plain wheel pan.
27
+ wheel: { step: 0.01, wheelDisabled: true }, trackPadPanning: { disabled: !panAtFit && !zoomed, velocityDisabled: true }, onTransform: (_, { scale }) => setZoomed(scale > 1.001), doubleClick: { mode: 'toggle', step: 1 }, children: [_jsx(ZoomBar, { children: children }), _jsx(TransformComponent, { wrapperClass: "!size-full cursor-grab active:cursor-grabbing", contentClass: "!size-full", children: _jsx("img", { src: src, alt: alt, draggable: false, className: "size-full object-contain" }) })] }));
25
28
  }
26
29
  export function ChatImage({ src, alt }) {
27
30
  const [open, setOpen] = useState(false);
@@ -43,5 +46,5 @@ export function ChatImage({ src, alt }) {
43
46
  onOpenAutoFocus: (e) => {
44
47
  e.preventDefault();
45
48
  e.currentTarget.focus();
46
- }, className: cn('h-[90vh] w-[90vw] max-w-none overflow-hidden p-0 sm:max-w-none', 'max-md:h-full max-md:w-full'), children: [_jsx(DialogTitle, { className: "sr-only", children: alt }), _jsx("div", { className: "relative size-full", children: _jsx(Zoomable, { src: src, alt: alt, children: _jsx(DialogClose, { asChild: true, children: _jsx(IconButton, { icon: XIcon, label: "Close" }) }) }) })] }) })] }));
49
+ }, className: cn('h-[90vh] w-[90vw] max-w-none overflow-hidden p-0 sm:max-w-none', 'max-md:h-full max-md:w-full'), children: [_jsx(DialogTitle, { className: "sr-only", children: alt }), _jsx("div", { className: "relative size-full", children: _jsx(Zoomable, { src: src, alt: alt, panAtFit: true, children: _jsx(DialogClose, { asChild: true, children: _jsx(IconButton, { icon: XIcon, label: "Close" }) }) }) })] }) })] }));
47
50
  }
@@ -36,7 +36,7 @@ export interface LumenAssistantProps {
36
36
  * kit's: /compact, /clear, /model and /escalate.
37
37
  */
38
38
  commands?: AssistantCommand[];
39
- /** What `#` lists everywhere; a page adds its own with `useAssistantSource`. */
39
+ /** What `@` lists everywhere; a page adds its own with `useAssistantSource`. */
40
40
  sources?: readonly AssistantSource[];
41
41
  /**
42
42
  * Images can go with a message: pasted (Cmd+V / Ctrl+V) or dropped on the box, shown as chips
@@ -61,7 +61,7 @@ export interface AssistantCommand {
61
61
  export declare function LumenAssistant({ client, context, onSettings, keepDays, chatScope, onClose, chat: outside, commands, sources, images, }: LumenAssistantProps): import("react").JSX.Element;
62
62
  /** An allowance in its unit: `$4.20`, or `350 credits`. */
63
63
  export declare const allowanceAmount: (u: AllowanceUnit, n: number) => string;
64
- /** What the composer sends with the text: the tier picked with `@` and the things pointed at with `#`. */
64
+ /** What the composer sends with the text: the tier picked with `#` and the things pointed at with `@`. */
65
65
  export interface ComposerExtra {
66
66
  tier?: string;
67
67
  refs?: AssistantRefNote[];
@@ -69,26 +69,26 @@ export interface ComposerExtra {
69
69
  }
70
70
  /**
71
71
  * The message box: Enter sends, Shift+Enter breaks a line; Stop while an answer runs. Three
72
- * triggers list what can follow them as it is typed: `/` at the start a command, `@` a tier for
73
- * this message, `#` a thing to point at (the `sources`); a picked tier or thing shows as a chip.
72
+ * triggers list what can follow them as it is typed: `/` at the start a command, `@` a thing to
73
+ * point at (the `sources`), `#` a tier for this message; a picked tier or thing shows as a chip.
74
74
  */
75
75
  export declare function LumenComposer({ name, busy, queued, disabled, commands, tiers, sources, page, images: canAttach, onSend, onStop, }: {
76
76
  name: string;
77
77
  /** Images can be pasted or dropped on the box (`LumenAssistant` `images`). */
78
78
  images?: boolean;
79
- /** The page's name for `#` This page; the document's title by default. */
79
+ /** The page's name for `@` This page; the document's title by default. */
80
80
  page?: string;
81
81
  busy: boolean;
82
82
  queued: string | null;
83
83
  disabled?: boolean;
84
84
  commands?: AssistantCommand[];
85
- /** What `@` lists. */
85
+ /** What `#` lists. */
86
86
  tiers?: {
87
87
  id: string;
88
88
  label: string;
89
89
  model_label?: string;
90
90
  }[];
91
- /** What `#` lists, a group each. */
91
+ /** What `@` lists, a group each. */
92
92
  sources?: readonly AssistantSource[];
93
93
  onSend: (text: string, extra: ComposerExtra) => void;
94
94
  onStop: () => void;
@@ -233,7 +233,7 @@ function allowanceWait(a) {
233
233
  }
234
234
  /** The assistant's name, for a copied turn's headings. */
235
235
  const AssistantName = createContext('Assistant');
236
- /** A tier's name for a message's `@` chip. */
236
+ /** A tier's name for a message's `#` chip. */
237
237
  const TierNames = createContext((id) => id);
238
238
  /** Takes back a change made at once (Undo on its line). */
239
239
  const UndoWrite = createContext(null);
@@ -264,7 +264,7 @@ function Item({ item, onSettle, busy, }) {
264
264
  const tierName = useContext(TierNames);
265
265
  switch (item.kind) {
266
266
  case 'user':
267
- return (_jsxs("div", { className: "ml-8 self-end rounded-lg bg-muted px-3 py-2 text-sm whitespace-pre-wrap has-[[data-slot=chat-image]]:ml-0 has-[[data-slot=chat-image]]:w-full", children: [(item.tier || item.refs?.length) && (_jsxs("span", { className: "mb-1 flex flex-wrap gap-1", children: [item.tier && _jsx(ComposerChip, { sign: "@", label: tierName(item.tier) }), item.refs?.map((r, i) => (_jsx(ComposerChip, { sign: "#", label: r.label }, `${r.kind}:${r.label}:${i}`)))] })), item.images?.length ? (_jsx("span", { className: "mb-1 flex flex-wrap gap-1.5", children: item.images.map((src, i) => (_jsx(ChatImage, { src: src, alt: `Pasted ${i + 1}` }, `${i}:${src.length}`))) })) : null, item.text, item.context && (_jsxs("span", { className: "mt-1 block text-muted-foreground text-xs", children: ["on ", item.context] }))] }));
267
+ return (_jsxs("div", { className: "ml-8 self-end rounded-lg bg-muted px-3 py-2 text-sm whitespace-pre-wrap has-[[data-slot=chat-image]]:ml-0 has-[[data-slot=chat-image]]:w-full", children: [(item.tier || item.refs?.length) && (_jsxs("span", { className: "mb-1 flex flex-wrap gap-1", children: [item.tier && _jsx(ComposerChip, { sign: TIER, label: tierName(item.tier) }), item.refs?.map((r, i) => (_jsx(ComposerChip, { sign: POINT, label: r.label }, `${r.kind}:${r.label}:${i}`)))] })), item.images?.length ? (_jsx("span", { className: "mb-1 flex flex-wrap gap-1.5", children: item.images.map((src, i) => (_jsx(ChatImage, { src: src, alt: `Pasted ${i + 1}` }, `${i}:${src.length}`))) })) : null, item.text, item.context && (_jsxs("span", { className: "mt-1 block text-muted-foreground text-xs", children: ["on ", item.context] }))] }));
268
268
  case 'text':
269
269
  return (_jsxs("div", { className: "prose-sm text-sm leading-relaxed [&_code]:font-code [&_code]:text-xs [&_li]:ml-4 [&_ol]:list-decimal [&_p]:my-1.5 [&_ul]:list-disc", children: [_jsx(ChatMarkdown, { children: item.text }), item.live && (_jsx("span", { className: "ml-0.5 inline-block h-3.5 w-1.5 animate-pulse bg-foreground/60 align-middle" }))] }));
270
270
  case 'step':
@@ -427,7 +427,10 @@ const WHY = {
427
427
  function HandOff({ item, onSettle, busy, }) {
428
428
  return (_jsxs("section", { className: "flex flex-col gap-2 border-l-2 border-primary/40 pl-3", children: [_jsxs("p", { className: "flex items-center gap-1.5 text-xs", children: [_jsx(CornerDownRightIcon, { className: "size-3.5 text-muted-foreground" }), _jsx("span", { className: "font-medium", children: item.label }), _jsxs("span", { className: "text-muted-foreground", children: ["\u00B7 ", WHY[item.why]] }), item.usage && (_jsx("span", { className: "ml-auto text-muted-foreground tabular-nums", children: usd(item.usage.usd) }))] }), _jsx("p", { className: "text-muted-foreground text-xs", children: item.task }), _jsx(Items, { items: item.items, onSettle: onSettle, busy: busy })] }));
429
429
  }
430
- /** A chip over the message box: a tier picked with `@` or a thing pointed at with `#`. */
430
+ /** The composer's triggers: `@` points at a thing (the `sources`), `#` picks the tier for one message. */
431
+ const POINT = '@';
432
+ const TIER = '#';
433
+ /** A chip over the message box: a tier picked with `#` or a thing pointed at with `@`. */
431
434
  function ComposerChip({ sign, label, onRemove, }) {
432
435
  return (_jsxs("span", { className: "inline-flex max-w-full items-center gap-1 rounded-md border bg-background px-1.5 py-0.5 text-xs", children: [_jsx("span", { className: "text-muted-foreground", children: sign }), _jsx("span", { className: "truncate", children: label }), onRemove && (_jsx("button", { type: "button", "aria-label": `Remove ${label}`, className: "text-muted-foreground hover:text-foreground", onClick: onRemove, children: _jsx(XIcon, { className: "size-3" }) }))] }));
433
436
  }
@@ -464,8 +467,8 @@ async function readImage(file) {
464
467
  const imageUrl = (i) => `data:${i.media_type};base64,${i.data}`;
465
468
  /**
466
469
  * The message box: Enter sends, Shift+Enter breaks a line; Stop while an answer runs. Three
467
- * triggers list what can follow them as it is typed: `/` at the start a command, `@` a tier for
468
- * this message, `#` a thing to point at (the `sources`); a picked tier or thing shows as a chip.
470
+ * triggers list what can follow them as it is typed: `/` at the start a command, `@` a thing to
471
+ * point at (the `sources`), `#` a tier for this message; a picked tier or thing shows as a chip.
469
472
  */
470
473
  export function LumenComposer({ name, busy, queued, disabled, commands = [], tiers = [], sources = [], page, images: canAttach = false, onSend, onStop, }) {
471
474
  const [text, setText] = useState('');
@@ -496,13 +499,13 @@ export function LumenComposer({ name, busy, queued, disabled, commands = [], tie
496
499
  }, [request]);
497
500
  const m = /^\/(\S*)(?:\s(.*))?$/s.exec(text);
498
501
  const cmd = m && m[2] !== undefined ? commands.find((c) => c.name === m[1]) : undefined;
499
- // `@` or `#` as the word the caret is in: `pick #sto|` lists the sources' items matching "sto".
502
+ // `@` or `#` as the word the caret is in: `pick @sto|` lists the sources' items matching "sto".
500
503
  const word = /(^|\s)([@#])([^\s@#]*)$/.exec(text.slice(0, caret));
501
504
  const trigger = word ? word[2] : null;
502
505
  const asked = word?.[3] ?? '';
503
506
  const open = closed !== `${text}|${caret}`;
504
507
  const slash = m && commands.length ? (m[2] === undefined ? 'command' : cmd?.options ? 'arg' : null) : null;
505
- const at = trigger === '@' && tiers.length > 1 ? '@' : trigger === '#' ? '#' : null;
508
+ const at = trigger === TIER && tiers.length > 1 ? 'tier' : trigger === POINT ? 'point' : null;
506
509
  const picking = open ? (slash ?? at) : null;
507
510
  const extra = () => ({
508
511
  ...(tier ? { tier } : {}),
@@ -590,12 +593,12 @@ export function LumenComposer({ name, busy, queued, disabled, commands = [], tie
590
593
  box.current?.setSelectionRange(start, start);
591
594
  });
592
595
  };
593
- // Each `#` row makes its chip when picked, so what it carries (a card's words) is read then.
596
+ // Each `@` row makes its chip when picked, so what it carries (a card's words) is read then.
594
597
  const sourceItems = new Map();
595
598
  const picked = selection ? selectionRef(selection) : null;
596
599
  const added = (r) => refs.some((x) => sameRef(x, r)) ? { disabled: 'Added' } : {};
597
600
  const onPage = [];
598
- if (picking === '#') {
601
+ if (picking === 'point') {
599
602
  const pageRef = () => ({
600
603
  kind: 'page',
601
604
  label: page || document.title || 'This page',
@@ -654,7 +657,7 @@ export function LumenComposer({ name, busy, queued, disabled, commands = [], tie
654
657
  }
655
658
  if (picked)
656
659
  sourceItems.set('selection', () => picked);
657
- const sourceOptions = picking === '#'
660
+ const sourceOptions = picking === 'point'
658
661
  ? [
659
662
  ...(picked
660
663
  ? [
@@ -703,20 +706,20 @@ export function LumenComposer({ name, busy, queued, disabled, commands = [], tie
703
706
  requestAnimationFrame(() => box.current?.focus());
704
707
  };
705
708
  const tierLabel = tiers.find((t) => t.id === tier)?.label;
706
- const hints = [commands.length && '/', tiers.length > 1 && '@', '#'].filter(Boolean);
709
+ const hints = [commands.length && '/', POINT, tiers.length > 1 && TIER].filter(Boolean);
707
710
  return (_jsxs("div", { className: "shrink-0 border-t p-3", children: [queued && (_jsxs("p", { className: "mb-2 truncate text-muted-foreground text-xs", children: ["Queued: ", _jsx("span", { className: "text-foreground", children: queued })] })), picking === 'command' && (_jsx(LumenSelectorList, { handle: list, label: "Commands", className: "mb-2", fuzzy: true, query: m?.[1] ?? '', options: commands.map((c) => ({
708
711
  value: c.name,
709
712
  label: `/${c.name}`,
710
713
  ...(c.args ? { detail: c.args } : {}),
711
714
  description: c.about,
712
- })), empty: "No command matches", onPick: pickCommand, onClose: () => setClosed(`${text}|${caret}`) })), picking === 'arg' && cmd?.options && (_jsx(LumenSelectorList, { handle: list, label: `/${cmd.name}`, className: "mb-2", fuzzy: true, query: m?.[2] ?? '', options: cmd.options(), onPick: (o) => void run(cmd, o.value), onClose: () => setClosed(`${text}|${caret}`) })), picking === '@' && (_jsx(LumenSelectorList, { handle: list, label: "Answer this message on", className: "mb-2", fuzzy: true, query: asked, options: tiers.map((t) => ({
715
+ })), empty: "No command matches", onPick: pickCommand, onClose: () => setClosed(`${text}|${caret}`) })), picking === 'arg' && cmd?.options && (_jsx(LumenSelectorList, { handle: list, label: `/${cmd.name}`, className: "mb-2", fuzzy: true, query: m?.[2] ?? '', options: cmd.options(), onPick: (o) => void run(cmd, o.value), onClose: () => setClosed(`${text}|${caret}`) })), picking === 'tier' && (_jsx(LumenSelectorList, { handle: list, label: "Answer this message on", className: "mb-2", fuzzy: true, query: asked, options: tiers.map((t) => ({
713
716
  value: t.id,
714
717
  label: t.label,
715
718
  ...(t.model_label ? { detail: t.model_label } : {}),
716
719
  })), empty: "No tier matches", onPick: (o) => {
717
720
  setTier(o.value);
718
721
  dropWord();
719
- }, onClose: () => setClosed(`${text}|${caret}`) })), picking === '#' && (_jsx(LumenSelectorList, { handle: list, label: "Point at", className: "mb-2", query: asked, options: sourceOptions, empty: "Nothing matches", onPick: (o) => {
722
+ }, onClose: () => setClosed(`${text}|${caret}`) })), picking === 'point' && (_jsx(LumenSelectorList, { handle: list, label: "Point at", className: "mb-2", query: asked, options: sourceOptions, empty: "Nothing matches", onPick: (o) => {
720
723
  dropWord();
721
724
  if (o.value === 'point') {
722
725
  void point();
@@ -725,7 +728,7 @@ export function LumenComposer({ name, busy, queued, disabled, commands = [], tie
725
728
  const r = sourceItems.get(o.value)?.();
726
729
  if (r)
727
730
  setRefs((p) => [...p, r]);
728
- }, onClose: () => setClosed(`${text}|${caret}`) })), 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: "@", label: tierLabel, onRemove: () => setTier(null) }), refs.map((r, i) => (_jsx(ComposerChip, { sign: "#", 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: "max-h-48 min-h-11 resize-none pr-11", value: text, disabled: disabled, onChange: (e) => {
731
+ }, onClose: () => setClosed(`${text}|${caret}`) })), 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: "max-h-48 min-h-11 resize-none pr-11", value: text, disabled: disabled, onChange: (e) => {
729
732
  setText(e.target.value);
730
733
  setCaret(e.target.selectionStart);
731
734
  }, onSelect: (e) => setCaret(e.currentTarget.selectionStart), onPaste: (e) => {
@@ -1,6 +1,6 @@
1
1
  import type { AssistantRefNote } from '@columenlabs/lumen-ui-types/assistant';
2
2
  import { type ComponentType } from 'react';
3
- /** One thing a source holds: a row in the `#` list, sent with the message as `ref`. */
3
+ /** One thing a source holds: a row in the `@` list, sent with the message as `ref`. */
4
4
  export interface AssistantSourceItem {
5
5
  /** Unique within its source. */
6
6
  id: string;
@@ -14,7 +14,7 @@ export interface AssistantSourceItem {
14
14
  /** What goes to the model: its kind, its label and whatever finds it (an id, a path). */
15
15
  ref: AssistantRefNote;
16
16
  }
17
- /** A group of things in the `#` list. */
17
+ /** A group of things in the `@` list. */
18
18
  export interface AssistantSource {
19
19
  /** Unique: a page's source replaces an app source of the same id. */
20
20
  id: string;
@@ -23,10 +23,10 @@ export interface AssistantSource {
23
23
  icon?: ComponentType<{
24
24
  className?: string;
25
25
  }>;
26
- /** What it holds now; `query` is what follows the `#`, for a source that searches. */
26
+ /** What it holds now; `query` is what follows the `@`, for a source that searches. */
27
27
  items: (query: string) => readonly AssistantSourceItem[];
28
28
  }
29
- /** Adds a source to the `#` list while the calling page is shown. */
29
+ /** Adds a source to the `@` list while the calling page is shown. */
30
30
  export declare function useAssistantSource(source: AssistantSource | null | undefined): void;
31
31
  /** The sources pages have added, newest page last. */
32
32
  export declare function useShownAssistantSources(): readonly AssistantSource[];
@@ -50,5 +50,5 @@ export interface PageSelection {
50
50
  }
51
51
  /** What the person last highlighted on the page outside the assistant, or null. */
52
52
  export declare function usePageSelection(): PageSelection | null;
53
- /** A highlight as a `#` chip: its first words, the whole text and where it sits go to the model. */
53
+ /** A highlight as an `@` chip: its first words, the whole text and where it sits go to the model. */
54
54
  export declare const selectionRef: (s: PageSelection) => AssistantRefNote;
@@ -11,7 +11,7 @@ const subscribe = (l) => {
11
11
  listeners.add(l);
12
12
  return () => listeners.delete(l);
13
13
  };
14
- /** Adds a source to the `#` list while the calling page is shown. */
14
+ /** Adds a source to the `@` list while the calling page is shown. */
15
15
  export function useAssistantSource(source) {
16
16
  const latest = useRef(source);
17
17
  latest.current = source;
@@ -105,7 +105,7 @@ export function usePageSelection() {
105
105
  };
106
106
  }, () => selected, () => null);
107
107
  }
108
- /** A highlight as a `#` chip: its first words, the whole text and where it sits go to the model. */
108
+ /** A highlight as an `@` chip: its first words, the whole text and where it sits go to the model. */
109
109
  export const selectionRef = (s) => ({
110
110
  kind: 'selection',
111
111
  label: `“${s.text.length > 40 ? `${s.text.slice(0, 40)}…` : s.text}”`,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@columenlabs/lumen-ui",
3
- "version": "0.1.213",
3
+ "version": "0.1.215",
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.213",
52
+ "@columenlabs/lumen-ui-types": "0.1.215",
53
53
  "@dnd-kit/core": "6.3.1",
54
54
  "@dnd-kit/sortable": "10.0.0",
55
55
  "@dnd-kit/utilities": "3.2.2",