@columenlabs/lumen-ui 0.1.242 → 0.1.244
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/assistant/settings.js +15 -1
- package/dist/assistant/usage-history.js +32 -10
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lumen-finder.d.ts +5 -1
- package/dist/lumen-finder.js +10 -4
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -59,7 +59,7 @@ Use `createDeskQueryClient()` for the app's TanStack Query client: data stays fr
|
|
|
59
59
|
|
|
60
60
|
## What's inside
|
|
61
61
|
|
|
62
|
-
**Frame.** `LumenShell` (sidebar with icons-only collapse and a drawer on phone, header, status bar, Settings, profile menu, ⌘K Find), `LumenAppSwitcher` and `LumenSuiteSwitcher` (groups, apps on other sites, a list read from an address), `WhatsNew` (release notes in a drawer), `TasksButton` and `TasksProvider` (background work in the header), `NotificationsSettings`, `McpSettings`, sign-in screens (`LumenAuthStage`, `LumenSecondStep`, `LumenSignInMethods`, `LumenBackupCodes`, `LumenBotCheck` for Cloudflare Turnstile, `authErrorText` for errors in plain words), `StatusHealth`, `LumenBoundary` (keeps a crash inside its card), `LumenPageState` (loading, empty and error), `lumenToast`.
|
|
62
|
+
**Frame.** `LumenShell` (sidebar with icons-only collapse and a drawer on phone, header, status bar, Settings, profile menu, ⌘K Find; `LumenFinder` mounts Find on its own for an app that draws its own frame, with commands from `useLumenFinderRows`), `LumenAppSwitcher` and `LumenSuiteSwitcher` (groups, apps on other sites, a list read from an address), `WhatsNew` (release notes in a drawer), `TasksButton` and `TasksProvider` (background work in the header), `NotificationsSettings`, `McpSettings`, sign-in screens (`LumenAuthStage`, `LumenSecondStep`, `LumenSignInMethods`, `LumenBackupCodes`, `LumenBotCheck` for Cloudflare Turnstile, `authErrorText` for errors in plain words), `StatusHealth`, `LumenBoundary` (keeps a crash inside its card), `LumenPageState` (loading, empty and error), `lumenToast`.
|
|
63
63
|
|
|
64
64
|
**Pages and views.** `LumenLayout` (a page of cards from one view config: filter, tiles, widgets; Edit layout and Edit widget when you pass `onConfigChange`; a card with `header: false` is its body alone), `LumenGrid` (the 6-column grid under it), `LumenView` and `LumenViewCard` (a table that filters, groups, pivots and totals the rows you load), `LumenTable`, `LumenTokenizedFilter`, `LumenWidget` and `LumenSavedWidget` (the frame every card sits in, with its link square and controls), `LumenCard` (one number and its lines), `LumenPager`, `DetailsTable`, `LumenTree`, `LumenCalendar` (events by month, week or agenda, in a time zone), `LumenBoard` (items in columns by stage), `useAppView` (a page whose layout each person can change and reset).
|
|
65
65
|
|
|
@@ -174,9 +174,23 @@ function Providers({ client }) {
|
|
|
174
174
|
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: _jsx(LumenSelector, { label: "Answers run on", size: "sm", className: "w-44", value: s.pay, options: [
|
|
175
175
|
{ value: 'own', label: 'Your own first' },
|
|
176
176
|
{ value: 'app', label: 'Shared credits first' },
|
|
177
|
-
], onChange: (pay) => void apply('pay', () => client.settings({ pay: pay })) }) })), 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)) }) })), _jsx(OwnKeyUsage, { client: client, always: ownSet })] }));
|
|
177
|
+
], onChange: (pay) => void apply('pay', () => client.settings({ pay: pay })) }) })), 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 })] }));
|
|
178
178
|
} }));
|
|
179
179
|
}
|
|
180
|
+
/**
|
|
181
|
+
* How much of the person's own monthly cap is used: the same spend rows the cap is checked
|
|
182
|
+
* against, so this and the switch to shared credits never disagree.
|
|
183
|
+
*/
|
|
184
|
+
function OwnCapUse({ s }) {
|
|
185
|
+
const used = s.spend.rows
|
|
186
|
+
.filter((r) => r.payer === 'own' && !r.free)
|
|
187
|
+
.reduce((a, r) => a + r.usd, 0);
|
|
188
|
+
const cap = s.caps.own;
|
|
189
|
+
const full = cap > 0 && used >= cap;
|
|
190
|
+
return (_jsx(SettingField, { label: "Used this month", info: full
|
|
191
|
+
? 'Your cap is used up, so the shared credits pay until next month or until you raise the cap.'
|
|
192
|
+
: '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" })] }) }));
|
|
193
|
+
}
|
|
180
194
|
/** One provider's shared key, which an admin sets for everyone. */
|
|
181
195
|
function SharedProviderKey({ client, p }) {
|
|
182
196
|
const { apply, refresh } = useApply(client);
|
|
@@ -119,17 +119,39 @@ export function OwnKeyUsage({ client, always }) {
|
|
|
119
119
|
const sessions = all
|
|
120
120
|
.filter((e) => e.at >= since && !seen.has(e.id) && seen.add(e.id))
|
|
121
121
|
.sort((a, b) => b.at - a.at);
|
|
122
|
-
|
|
123
|
-
|
|
122
|
+
// This month's own spend that no chat or run carries (spent before per-chat tracking), so the
|
|
123
|
+
// table never reads "nothing" while the cap's own numbers say otherwise.
|
|
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;
|
|
130
|
+
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: [
|
|
124
132
|
{ label: 'Session', grow: true },
|
|
125
133
|
{ label: 'Date', hideOnPhone: true },
|
|
126
134
|
{ label: 'Amount', right: true },
|
|
127
|
-
], rows:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
+
], rows: [
|
|
136
|
+
...sessions.map((e) => ({
|
|
137
|
+
key: e.id,
|
|
138
|
+
cells: [
|
|
139
|
+
_jsx("span", { className: "block truncate", title: e.title, children: e.title }, "n"),
|
|
140
|
+
_jsx("time", { dateTime: new Date(e.at).toISOString(), title: new Date(e.at).toLocaleString(), children: when(e.at) }, "t"),
|
|
141
|
+
usd(e.own_usd ?? 0),
|
|
142
|
+
],
|
|
143
|
+
})),
|
|
144
|
+
...(untracked
|
|
145
|
+
? [
|
|
146
|
+
{
|
|
147
|
+
key: 'earlier',
|
|
148
|
+
cells: [
|
|
149
|
+
_jsx("span", { className: "block truncate text-muted-foreground", title: earlier, children: earlier }, "n"),
|
|
150
|
+
_jsx("span", {}, "t"),
|
|
151
|
+
usd(untracked),
|
|
152
|
+
],
|
|
153
|
+
},
|
|
154
|
+
]
|
|
155
|
+
: []),
|
|
156
|
+
], 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, "."] }))] }));
|
|
135
157
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -117,6 +117,6 @@ export { LumenChart, type LumenChartOptions, type MineIndicators, SymbolChartPro
|
|
|
117
117
|
export { SymbolSheetProvider } from './symbol-sheet.js';
|
|
118
118
|
export { useSymbolSheet } from './symbol-sheet-context.js';
|
|
119
119
|
export { NoteLine, type NoteLineProps } from './note-line.js';
|
|
120
|
-
export { type LumenFinderConfig, type LumenFinderPageType, type LumenFinderRow, type LumenFinderScope, LumenFinderButton, useLumenFinder, useLumenFinderRows, useOpenLumenFinder, } from './lumen-finder.js';
|
|
120
|
+
export { type LumenFinderConfig, type LumenFinderPageType, type LumenFinderRow, type LumenFinderScope, LumenFinder, LumenFinderButton, useLumenFinder, useLumenFinderRows, useOpenLumenFinder, } from './lumen-finder.js';
|
|
121
121
|
export { type AssistantChat, LumenAssistantButton, LumenAssistantChats, LumenAssistantPanel, assistantOpen, tabState, useAssistantHotkey, } from './assistant-panel.js';
|
|
122
122
|
export { LumenTree, LumenTreeItem, type LumenTreeItemProps, type LumenTreeProps, useLumenTree, } from './lumen-tree.js';
|
package/dist/index.js
CHANGED
|
@@ -124,6 +124,6 @@ export { LumenChart, SymbolChartProvider, useLumenChart, useSymbolChart, } from
|
|
|
124
124
|
export { SymbolSheetProvider } from './symbol-sheet.js';
|
|
125
125
|
export { useSymbolSheet } from './symbol-sheet-context.js';
|
|
126
126
|
export { NoteLine } from './note-line.js';
|
|
127
|
-
export { LumenFinderButton, useLumenFinder, useLumenFinderRows, useOpenLumenFinder, } from './lumen-finder.js';
|
|
127
|
+
export { LumenFinder, LumenFinderButton, useLumenFinder, useLumenFinderRows, useOpenLumenFinder, } from './lumen-finder.js';
|
|
128
128
|
export { LumenAssistantButton, LumenAssistantChats, LumenAssistantPanel, assistantOpen, tabState, useAssistantHotkey, } from './assistant-panel.js';
|
|
129
129
|
export { LumenTree, LumenTreeItem, useLumenTree, } from './lumen-tree.js';
|
package/dist/lumen-finder.d.ts
CHANGED
|
@@ -46,7 +46,11 @@ export declare function useLumenFinderRows(rows: LumenFinderRow[] | null): void;
|
|
|
46
46
|
type Icon = ComponentType<{
|
|
47
47
|
className?: string;
|
|
48
48
|
}>;
|
|
49
|
-
/**
|
|
49
|
+
/**
|
|
50
|
+
* Find: ⌘K, the rows apps add and the dialog. LumenShell mounts it; an app that draws its own frame
|
|
51
|
+
* (a full-screen editor) mounts it around its screen instead and adds its commands with
|
|
52
|
+
* `useLumenFinderRows`. No router is needed there: rows run, or follow plain links.
|
|
53
|
+
*/
|
|
50
54
|
export declare function LumenFinder({ app, settings, openSettings, config, children, }: {
|
|
51
55
|
app: string;
|
|
52
56
|
settings: {
|
package/dist/lumen-finder.js
CHANGED
|
@@ -162,7 +162,11 @@ function useShellRows(open, query, settings, openSettings, app, pageTypes, setti
|
|
|
162
162
|
]
|
|
163
163
|
: base, [base, assistant, q]);
|
|
164
164
|
}
|
|
165
|
-
/**
|
|
165
|
+
/**
|
|
166
|
+
* Find: ⌘K, the rows apps add and the dialog. LumenShell mounts it; an app that draws its own frame
|
|
167
|
+
* (a full-screen editor) mounts it around its screen instead and adds its commands with
|
|
168
|
+
* `useLumenFinderRows`. No router is needed there: rows run, or follow plain links.
|
|
169
|
+
*/
|
|
166
170
|
export function LumenFinder({ app, settings, openSettings, config, children, }) {
|
|
167
171
|
const pageTypes = config?.pageTypes ?? NO_TYPES;
|
|
168
172
|
const settingsScope = config?.settingsScope ?? 'Settings';
|
|
@@ -218,7 +222,9 @@ export function LumenFinder({ app, settings, openSettings, config, children, })
|
|
|
218
222
|
}
|
|
219
223
|
function FinderDialog({ app, open, onOpenChange, query, onQuery, scope, onScope, scopes, placeholder, groups, }) {
|
|
220
224
|
const mobile = useIsMobile();
|
|
221
|
-
|
|
225
|
+
// Optional: an app without TanStack Router (a single-screen tool) still gets Find; its rows run or
|
|
226
|
+
// go by plain links.
|
|
227
|
+
const router = useRouter({ warn: false });
|
|
222
228
|
const list = useRef(null);
|
|
223
229
|
const input = useRef(null);
|
|
224
230
|
// Focus without scrolling: on a phone iOS pans the page to a focused field as the keyboard opens,
|
|
@@ -241,8 +247,8 @@ function FinderDialog({ app, open, onOpenChange, query, onQuery, scope, onScope,
|
|
|
241
247
|
return;
|
|
242
248
|
const outside = /^https?:/.test(r.href);
|
|
243
249
|
if (tab)
|
|
244
|
-
window.open(outside ? r.href : router.history.createHref(r.href), '_blank');
|
|
245
|
-
else if (outside)
|
|
250
|
+
window.open(outside || !router ? r.href : router.history.createHref(r.href), '_blank');
|
|
251
|
+
else if (outside || !router)
|
|
246
252
|
window.location.assign(r.href);
|
|
247
253
|
else
|
|
248
254
|
void router.navigate({ href: r.href });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.244",
|
|
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.244",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|