@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
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
|
73
|
-
*
|
|
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
|
|
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
|
|
85
|
+
/** What `#` lists. */
|
|
86
86
|
tiers?: {
|
|
87
87
|
id: string;
|
|
88
88
|
label: string;
|
|
89
89
|
model_label?: string;
|
|
90
90
|
}[];
|
|
91
|
-
/** What
|
|
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
|
|
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:
|
|
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
|
-
/**
|
|
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
|
|
468
|
-
*
|
|
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
|
|
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 ===
|
|
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
|
|
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 &&
|
|
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 === '
|
|
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 === '
|
|
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:
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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",
|