@columenlabs/lumen-ui 0.1.237 → 0.1.238
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.
|
@@ -19,7 +19,7 @@ import { Empty, EmptyContent, EmptyDescription, EmptyHeader, EmptyMedia, EmptyTi
|
|
|
19
19
|
import { InviteDrawer } from './invite-drawer.js';
|
|
20
20
|
import { PersonDrawer } from './person-drawer.js';
|
|
21
21
|
import { AuditSection, InvitesSection, PermissionsSection } from './sections.js';
|
|
22
|
-
import { LevelPicker, STATUS_LABEL, fromNow, peopleView, scopeKey, statusTone, topScopes, usePeopleAction, usePeopleQuery, useVisitView, when, withGrant, } from './shared.js';
|
|
22
|
+
import { LevelPicker, STATUS_LABEL, fromNow, peopleView, scopeKey, statusTone, syncText, topScopes, usePeopleAction, usePeopleQuery, useVisitView, when, withGrant, } from './shared.js';
|
|
23
23
|
export function LumenPeople({ adapter, crumbs = [], section: given, onSection, onSetUpMail, fields = [], }) {
|
|
24
24
|
const [own, setOwn] = useState('people');
|
|
25
25
|
const section = given ?? own;
|
|
@@ -167,8 +167,13 @@ function PeopleList({ frame, fields, onInvite, }) {
|
|
|
167
167
|
const invited = people.filter((p) => p.status === 'invited').length;
|
|
168
168
|
const active = people.filter((p) => p.status === 'active').length;
|
|
169
169
|
const disabled = people.filter((p) => p.status === 'disabled').length;
|
|
170
|
-
|
|
171
|
-
|
|
170
|
+
// The first-run note stands in for the table only when it has no row; a lone admin is a row.
|
|
171
|
+
const none = people.length === 0;
|
|
172
|
+
return (_jsxs(_Fragment, { children: [_jsx(LumenLayout, { crumbs: frame.crumbs, actions: frame.invite, intro: _jsxs("div", { className: "flex flex-col gap-3", children: [frame.tabs, _jsxs(TileRow, { fill: true, "aria-label": "People at a glance", children: [_jsx(Tile, { label: "People", value: people.length, caption: `${active} active${disabled ? ` · ${disabled} disabled` : ''}` }), _jsx(Tile, { label: "Admins", value: admins.length, caption: "Can\u2019t remove the last admin" }), _jsx(Tile, { label: "Invites pending", value: invited, caption: expired ? `${expired} expired` : 'none expired' }), view.sync ? (_jsx(Tile, { label: "Sign-in sync", value: syncText(view.sync), caption: !view.sync.configured
|
|
173
|
+
? 'Invites don’t reach sign-in'
|
|
174
|
+
: view.sync.at
|
|
175
|
+
? when(view.sync.at)
|
|
176
|
+
: view.sync.detail, valueClassName: !view.sync.configured || view.sync.ok ? undefined : 'text-loss' })) : (_jsx(Tile, { label: "Email", value: view.mail.configured ? 'Working' : 'Not set up', caption: view.mail.from ?? 'links only' }))] }), frame.mailNote, picked.size > 0 && (_jsx(BulkBar, { frame: frame, ids: [...picked], onClear: () => setPicked(new Set()) }))] }), domain: domain, ...layout, rows: people, load: load, state: none ? _jsx(FirstRun, { mail: view.mail.configured, onInvite: onInvite }) : undefined, selection: { keys: picked, onChange: setPicked }, rowTitle: (p) => p.name || p.email, onOpen: (p) => setOpenId(p.id) }), _jsx(LumenBoundary, { where: "people-person", what: "panel", children: _jsx(PersonDrawer, { adapter: adapter, view: view, person: open, onClose: () => setOpenId(null) }) })] }));
|
|
172
177
|
}
|
|
173
178
|
/** One change over the ticked people. Apply clears the selection; Undo puts the change back. */
|
|
174
179
|
function BulkBar({ frame, ids, onClear, }) {
|
|
@@ -14,7 +14,7 @@ import { LumenSelector } from '../lumen-selector.js';
|
|
|
14
14
|
import { NoteLine } from '../note-line.js';
|
|
15
15
|
import { Badge } from '../ui/badge.js';
|
|
16
16
|
import { Button } from '../ui/button.js';
|
|
17
|
-
import { LevelPicker, STATUS_LABEL, adminGuard, fromNow, topScopes, usePeopleAction, when, withGrant, } from './shared.js';
|
|
17
|
+
import { LevelPicker, STATUS_LABEL, adminGuard, fromNow, syncText, topScopes, usePeopleAction, when, withGrant, } from './shared.js';
|
|
18
18
|
const ROLES = [
|
|
19
19
|
{ value: 'member', label: 'Member', description: 'Only the levels set per scope' },
|
|
20
20
|
{ value: 'admin', label: 'Admin', description: 'Top level everywhere, and manages People' },
|
|
@@ -47,7 +47,9 @@ export function PersonDrawer({ adapter, view, person, onClose, }) {
|
|
|
47
47
|
},
|
|
48
48
|
view.sync && {
|
|
49
49
|
label: 'Sign-in provider',
|
|
50
|
-
value:
|
|
50
|
+
value: view.sync.at
|
|
51
|
+
? `${syncText(view.sync)} · ${when(view.sync.at)}`
|
|
52
|
+
: syncText(view.sync),
|
|
51
53
|
},
|
|
52
54
|
] }) }), adapter.audit && _jsx(ActivitySection, { adapter: adapter, person: p }), _jsx(DangerSection, { adapter: adapter, person: p, guard: guard, onGone: onClose })] })) }));
|
|
53
55
|
}
|
package/dist/people/shared.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Grant, type PeopleView, type Person, type PersonStatus, type Scope } from '@columenlabs/lumen-ui-types/people';
|
|
1
|
+
import { type Grant, type PeopleView, type Person, type PersonStatus, type Scope, type SyncStatus } from '@columenlabs/lumen-ui-types/people';
|
|
2
2
|
import { type CustomViewConfig } from '@columenlabs/lumen-ui-types/views';
|
|
3
3
|
import { type ReactNode } from 'react';
|
|
4
4
|
import type { Crumb } from '../page.js';
|
|
@@ -12,6 +12,8 @@ export declare const statusTone: (p: Pick<Person, 'status'>) => ViewChipTone | u
|
|
|
12
12
|
*/
|
|
13
13
|
export declare function when(ts: number | null | undefined, now?: number): string;
|
|
14
14
|
/** `in 5 d`, `in 3 h`, `2 d ago`: how far a time is from now. */
|
|
15
|
+
/** A sign-in sync's one-word state: never set up is not a failed sync. */
|
|
16
|
+
export declare const syncText: (s: Pick<SyncStatus, 'configured' | 'ok'>) => "Not set up" | "Out of step" | "Synced";
|
|
15
17
|
export declare function fromNow(ts: number | null | undefined, now?: number): string;
|
|
16
18
|
/** The top scopes (apps), in order; constructs inside one have a `parent`. */
|
|
17
19
|
export declare const topScopes: (scopes: readonly Scope[]) => Scope[];
|
package/dist/people/shared.js
CHANGED
|
@@ -53,6 +53,8 @@ export function when(ts, now = Date.now()) {
|
|
|
53
53
|
}));
|
|
54
54
|
}
|
|
55
55
|
/** `in 5 d`, `in 3 h`, `2 d ago`: how far a time is from now. */
|
|
56
|
+
/** A sign-in sync's one-word state: never set up is not a failed sync. */
|
|
57
|
+
export const syncText = (s) => !s.configured ? 'Not set up' : s.ok ? 'Synced' : 'Out of step';
|
|
56
58
|
export function fromNow(ts, now = Date.now()) {
|
|
57
59
|
if (!ts)
|
|
58
60
|
return '—';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@columenlabs/lumen-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.238",
|
|
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.238",
|
|
53
53
|
"@dnd-kit/core": "6.3.1",
|
|
54
54
|
"@dnd-kit/sortable": "10.0.0",
|
|
55
55
|
"@dnd-kit/utilities": "3.2.2",
|