@columenlabs/lumen-ui 0.1.90 → 0.1.92
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/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/lumen-bulk-bar.d.ts +14 -0
- package/dist/lumen-bulk-bar.js +13 -0
- package/dist/people/lumen-people.js +4 -3
- package/dist/tasks.d.ts +7 -0
- package/dist/tasks.js +22 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,7 @@ export { type CardOnScreen, cardsOnScreen, kindName, onScreen, pointAt, pointAtC
|
|
|
8
8
|
export { LinkDot, LinkPicker, type LinkColor, linkVar } from './lumen-links.js';
|
|
9
9
|
export { CardSegments, CardSwitch } from './card-switch.js';
|
|
10
10
|
export { PageInput, PageInputs } from './page-inputs.js';
|
|
11
|
+
export { LumenBulkBar } from './lumen-bulk-bar.js';
|
|
11
12
|
export { type LumenTab, LumenTabs } from './lumen-tabs.js';
|
|
12
13
|
export { LumenTabDrawer, TAB_NAME_MAX } from './lumen-tab-drawer.js';
|
|
13
14
|
export { IconPicker } from './icon-picker.js';
|
|
@@ -68,7 +69,7 @@ export { WhatsNew } from './whats-new.js';
|
|
|
68
69
|
export { type LumenApp, LumenAppSwitcher, LumenSuiteSwitcher, type SuiteApp, type SuiteList, suiteApps, } from './app-switcher.js';
|
|
69
70
|
export { type BriefActions, type BriefChange, type ScheduleChange, type ScheduleItem, type ScheduleRun, SchedulesSection, } from './schedules.js';
|
|
70
71
|
export { NotificationsSettings } from './notifications.js';
|
|
71
|
-
export { type TasksConfig, TasksButton, TasksProvider, useTasks } from './tasks.js';
|
|
72
|
+
export { type TasksConfig, TasksButton, TasksProvider, useTaskFor, useTasks } from './tasks.js';
|
|
72
73
|
export { type McpServer, McpSettings } from './mcp-settings.js';
|
|
73
74
|
export { lumenToast } from './lumen-toast.js';
|
|
74
75
|
export { LumenShell, type LumenShellProps, type ShellUser, StatusItem, firstName, initials, maskAmount, useAmountsHidden, useApp, useShell, } from './shell.js';
|
package/dist/index.js
CHANGED
|
@@ -15,6 +15,7 @@ export { cardsOnScreen, kindName, onScreen, pointAt, pointAtCard, sectionsOnScre
|
|
|
15
15
|
export { LinkDot, LinkPicker, linkVar } from './lumen-links.js';
|
|
16
16
|
export { CardSegments, CardSwitch } from './card-switch.js';
|
|
17
17
|
export { PageInput, PageInputs } from './page-inputs.js';
|
|
18
|
+
export { LumenBulkBar } from './lumen-bulk-bar.js';
|
|
18
19
|
export { LumenTabs } from './lumen-tabs.js';
|
|
19
20
|
export { LumenTabDrawer, TAB_NAME_MAX } from './lumen-tab-drawer.js';
|
|
20
21
|
export { IconPicker } from './icon-picker.js';
|
|
@@ -75,7 +76,7 @@ export { WhatsNew } from './whats-new.js';
|
|
|
75
76
|
export { LumenAppSwitcher, LumenSuiteSwitcher, suiteApps, } from './app-switcher.js';
|
|
76
77
|
export { SchedulesSection, } from './schedules.js';
|
|
77
78
|
export { NotificationsSettings } from './notifications.js';
|
|
78
|
-
export { TasksButton, TasksProvider, useTasks } from './tasks.js';
|
|
79
|
+
export { TasksButton, TasksProvider, useTaskFor, useTasks } from './tasks.js';
|
|
79
80
|
export { McpSettings } from './mcp-settings.js';
|
|
80
81
|
export { lumenToast } from './lumen-toast.js';
|
|
81
82
|
export { LumenShell, StatusItem, firstName, initials, maskAmount, useAmountsHidden, useApp, useShell, } from './shell.js';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* The bar over a table while rows are ticked: how many, the actions that apply to them, and a ✕
|
|
4
|
+
* that clears the ticks. Each action clears the selection when it applies and offers Undo in a
|
|
5
|
+
* toast (the change comes back, not the ticks). Pair it with LumenLayout's `selection`.
|
|
6
|
+
*/
|
|
7
|
+
export declare function LumenBulkBar({ count, label, onClear, children, }: {
|
|
8
|
+
count: number;
|
|
9
|
+
/** The toolbar's name for screen readers ("Change the ticked people"). */
|
|
10
|
+
label?: string;
|
|
11
|
+
onClear: () => void;
|
|
12
|
+
/** The actions, small outline buttons or a chip picker. */
|
|
13
|
+
children: ReactNode;
|
|
14
|
+
}): import("react").JSX.Element | null;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { XIcon } from 'lucide-react';
|
|
3
|
+
import { Button } from './ui/button.js';
|
|
4
|
+
/**
|
|
5
|
+
* The bar over a table while rows are ticked: how many, the actions that apply to them, and a ✕
|
|
6
|
+
* that clears the ticks. Each action clears the selection when it applies and offers Undo in a
|
|
7
|
+
* toast (the change comes back, not the ticks). Pair it with LumenLayout's `selection`.
|
|
8
|
+
*/
|
|
9
|
+
export function LumenBulkBar({ count, label = 'Change the ticked rows', onClear, children, }) {
|
|
10
|
+
if (count < 1)
|
|
11
|
+
return null;
|
|
12
|
+
return (_jsxs("div", { role: "toolbar", "aria-label": label, className: "flex flex-wrap items-center gap-2 rounded-lg border bg-muted px-3 py-2 text-sm", children: [_jsxs("span", { className: "num font-medium", children: [count, " selected"] }), children, _jsx(Button, { size: "icon-sm", variant: "ghost", "aria-label": "Clear the selection", className: "ml-auto", onClick: onClear, children: _jsx(XIcon, {}) })] }));
|
|
13
|
+
}
|
|
@@ -2,10 +2,11 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
2
2
|
// LumenPeople: who may sign in, what each person may open, invites and the audit log, as one block
|
|
3
3
|
// an app drops in with an adapter (`peopleClient(url)` over `@columenlabs/lumen-people`'s routes).
|
|
4
4
|
import { levelLabel, levelOf, levelsOf, } from '@columenlabs/lumen-ui-types/people';
|
|
5
|
-
import { AppWindowIcon, BanIcon, CircleDotIcon, ClockIcon, HistoryIcon, KeyRoundIcon, MailIcon, ShieldCheckIcon, Trash2Icon, TriangleAlertIcon, UserPlusIcon, UserRoundIcon, UsersIcon,
|
|
5
|
+
import { AppWindowIcon, BanIcon, CircleDotIcon, ClockIcon, HistoryIcon, KeyRoundIcon, MailIcon, ShieldCheckIcon, Trash2Icon, TriangleAlertIcon, UserPlusIcon, UserRoundIcon, UsersIcon, } from 'lucide-react';
|
|
6
6
|
import { useMemo, useState } from 'react';
|
|
7
7
|
import { LumenConfirm } from '../confirm.js';
|
|
8
8
|
import { LumenBoundary } from '../lumen-boundary.js';
|
|
9
|
+
import { LumenBulkBar } from '../lumen-bulk-bar.js';
|
|
9
10
|
import { LumenLayout } from '../lumen-layout.js';
|
|
10
11
|
import { LumenPageState } from '../lumen-page-state.js';
|
|
11
12
|
import { LumenSelector } from '../lumen-selector.js';
|
|
@@ -231,10 +232,10 @@ function BulkBar({ frame, ids, onClear, }) {
|
|
|
231
232
|
onClear();
|
|
232
233
|
void act(() => each({ op: 'status', status: 'disabled' }, list), `${many(list.length)} disabled`, () => each({ op: 'status', status: 'active' }, list));
|
|
233
234
|
};
|
|
234
|
-
return (_jsxs(
|
|
235
|
+
return (_jsxs(LumenBulkBar, { count: n, label: "Change the ticked people", onClear: onClear, children: [_jsx(LumenSelector, { trigger: "chip", size: "sm", label: "Set level on\u2026", placeholder: "Set level on\u2026", value: null, options: levelOptions, onChange: setLevel }), _jsxs(Button, { size: "sm", variant: "outline", onClick: () => setRole('admin'), children: [_jsx(ShieldCheckIcon, {}), " Make admin"] }), invites.length > 0 && (_jsxs(Button, { size: "sm", variant: "outline", onClick: () => {
|
|
235
236
|
onClear();
|
|
236
237
|
void act(() => each({ op: 'resend' }, invites), `New invites sent to ${many(invites.length)}`);
|
|
237
|
-
}, children: [_jsx(MailIcon, {}), " Resend invites"] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: disable, children: [_jsx(BanIcon, {}), " Disable"] }), _jsxs(Button, { size: "sm", variant: "outline", className: "text-destructive", onClick: () => setRemoving(true), children: [_jsx(Trash2Icon, {}), " Remove"] }), _jsx(
|
|
238
|
+
}, children: [_jsx(MailIcon, {}), " Resend invites"] })), _jsxs(Button, { size: "sm", variant: "outline", onClick: disable, children: [_jsx(BanIcon, {}), " Disable"] }), _jsxs(Button, { size: "sm", variant: "outline", className: "text-destructive", onClick: () => setRemoving(true), children: [_jsx(Trash2Icon, {}), " Remove"] }), _jsx(LumenConfirm, { open: removing, onOpenChange: setRemoving, title: `Remove ${many(n)}?`, description: "Each part of the app deletes their data first, then they leave People. This cannot be undone.", typeToConfirm: "REMOVE", action: "Remove for good", busyAction: "Removing\u2026", onConfirm: async () => {
|
|
238
239
|
const r = await act(() => each({ op: 'remove' }, chosen), `Removed ${many(n)}`);
|
|
239
240
|
if (!r)
|
|
240
241
|
throw new Error('Some people were not removed.');
|
package/dist/tasks.d.ts
CHANGED
|
@@ -15,11 +15,18 @@ interface TasksState {
|
|
|
15
15
|
/** Deletes one ended task, or every ended one; open tasks stay. */
|
|
16
16
|
clear: (id?: string) => Promise<void>;
|
|
17
17
|
open: (t: Task) => void;
|
|
18
|
+
/** Shows a task the app just started (its POST's answer) at once, before the next read, so its
|
|
19
|
+
* end toasts even when it finishes within one poll. */
|
|
20
|
+
track: (t: Task) => void;
|
|
18
21
|
/** `TasksConfig.apps`. */
|
|
19
22
|
apps?: Record<string, string>;
|
|
20
23
|
}
|
|
21
24
|
/** The Tasks list, or null where the app has none; `refresh()` after starting one shows it at once. */
|
|
22
25
|
export declare function useTasks(): TasksState | null;
|
|
26
|
+
/** The newest task for one piece of work (`kind` + the engine's `ref`, such as a saved search's
|
|
27
|
+
* id), so the button that starts it can show it running (`Running 1/3`) and come back when it
|
|
28
|
+
* ends. Null when there is none or the app has no Tasks. */
|
|
29
|
+
export declare function useTaskFor(kind: string, ref: string | null | undefined): Task | null;
|
|
23
30
|
export declare function TasksProvider({ config, children }: {
|
|
24
31
|
config?: TasksConfig;
|
|
25
32
|
children: ReactNode;
|
package/dist/tasks.js
CHANGED
|
@@ -30,6 +30,15 @@ const TasksCtx = createContext(null);
|
|
|
30
30
|
export function useTasks() {
|
|
31
31
|
return useContext(TasksCtx);
|
|
32
32
|
}
|
|
33
|
+
/** The newest task for one piece of work (`kind` + the engine's `ref`, such as a saved search's
|
|
34
|
+
* id), so the button that starts it can show it running (`Running 1/3`) and come back when it
|
|
35
|
+
* ends. Null when there is none or the app has no Tasks. */
|
|
36
|
+
export function useTaskFor(kind, ref) {
|
|
37
|
+
const tasks = useTasks();
|
|
38
|
+
if (!tasks?.list || !ref)
|
|
39
|
+
return null;
|
|
40
|
+
return tasks.list.tasks.find((t) => t.kind === kind && t.ref === ref) ?? null;
|
|
41
|
+
}
|
|
33
42
|
const POLL_MS = 3000;
|
|
34
43
|
export function TasksProvider({ config, children }) {
|
|
35
44
|
if (!config)
|
|
@@ -84,6 +93,18 @@ function TasksLive({ api, apps, children, }) {
|
|
|
84
93
|
activeIds.current = new Set(next.tasks.filter(isActive).map((t) => t.id));
|
|
85
94
|
setList(next);
|
|
86
95
|
}, [api, open, qc]);
|
|
96
|
+
const track = useCallback((t) => {
|
|
97
|
+
activeIds.current = new Set([...(activeIds.current ?? []), t.id]);
|
|
98
|
+
setList((l) => {
|
|
99
|
+
const tasks = [t, ...(l?.tasks ?? []).filter((x) => x.id !== t.id)];
|
|
100
|
+
return {
|
|
101
|
+
tasks,
|
|
102
|
+
active: tasks.filter(isActive).length,
|
|
103
|
+
unseen: tasks.filter((x) => x.finished_at && !x.seen_at).length,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
void refresh();
|
|
107
|
+
}, [refresh]);
|
|
87
108
|
const post = useCallback(async (path) => {
|
|
88
109
|
await fetch(`${api}${path}`, {
|
|
89
110
|
method: 'POST',
|
|
@@ -137,7 +158,7 @@ function TasksLive({ api, apps, children, }) {
|
|
|
137
158
|
}, POLL_MS);
|
|
138
159
|
return () => window.clearInterval(id);
|
|
139
160
|
}, [active, refresh]);
|
|
140
|
-
const value = useMemo(() => (gone ? null : { list, refresh, cancel, seen, clear, open, apps }), [gone, list, refresh, cancel, seen, clear, open, apps]);
|
|
161
|
+
const value = useMemo(() => (gone ? null : { list, refresh, cancel, seen, clear, open, track, apps }), [gone, list, refresh, cancel, seen, clear, open, track, apps]);
|
|
141
162
|
return _jsx(TasksCtx.Provider, { value: value, children: children });
|
|
142
163
|
}
|
|
143
164
|
function endedToast(t, open) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.92",
|
|
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.92",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|