@hanzo/rooms 0.1.96 → 0.1.98
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/App.js +33 -37
- package/dist/Chrome.js +3 -1
- package/dist/Column.d.ts +5 -3
- package/dist/Column.js +12 -19
- package/dist/Drawer.d.ts +55 -0
- package/dist/Drawer.js +334 -0
- package/dist/Me.d.ts +2 -2
- package/dist/Me.js +12 -5
- package/dist/Orgs.js +1 -1
- package/dist/Palette.js +1 -1
- package/dist/ProviderMark.js +5 -2
- package/dist/Rail.d.ts +3 -3
- package/dist/Rail.js +33 -16
- package/dist/Recents.js +4 -2
- package/dist/Settings.js +3 -1
- package/dist/Top.js +5 -2
- package/dist/dev.js +14 -6
- package/dist/index.js +0 -1
- package/dist/lib/signout.d.ts +5 -0
- package/dist/lib/signout.js +7 -1
- package/dist/slide.d.ts +24 -0
- package/dist/slide.js +48 -0
- package/package.json +5 -2
package/dist/Recents.js
CHANGED
|
@@ -73,7 +73,9 @@ function List({ mode, rows, view, keep, open, reading, error, onOpen, threads, h
|
|
|
73
73
|
// shows on hover and focus, a run's state is a dot at its end.
|
|
74
74
|
const row = (r) => {
|
|
75
75
|
const t = threads?.get(r.id);
|
|
76
|
-
const item = (_jsx(SidebarItem, { "data-kind": r.kind, active: open(r), rounded: "$4", minH: 31, px: "$2", pr: t || r.kind === 'dev' ? '$7' : '$2',
|
|
76
|
+
const item = (_jsx(SidebarItem, { "data-kind": r.kind, active: open(r), rounded: "$4", minH: 31, px: "$2", pr: t || r.kind === 'dev' ? '$7' : '$2',
|
|
77
|
+
// A thumb's 44 on a touch screen; a conversation's ⋯ is a thumb wide there and always there: the title stops short of it.
|
|
78
|
+
$touchable: t ? { minH: 44, pr: 52 } : { minH: 44 }, onKeyDown: (e) => {
|
|
77
79
|
if (e.key !== 'Enter' && e.key !== ' ')
|
|
78
80
|
return;
|
|
79
81
|
e.preventDefault?.();
|
|
@@ -98,5 +100,5 @@ function List({ mode, rows, view, keep, open, reading, error, onOpen, threads, h
|
|
|
98
100
|
: pinned
|
|
99
101
|
? null
|
|
100
102
|
: note;
|
|
101
|
-
return (_jsx(YStack, { "data-slot": "recents", flex: 1, minH: 0, children: _jsxs(ScrollView, { flex: 1, showsVerticalScrollIndicator: false, children: [error ? _jsx(Note, { children: error.message }) : null, _jsxs(YStack, { role: "list", "aria-labelledby": label, gap: 1, children: [pinned ? (_jsxs(YStack, { role: "listitem", gap: 1, children: [heading(PINNED), menus(_jsx(YStack, { role: "list", "aria-label": PINNED, gap: 1, children: pinned.rows.map(row) }))] })) : null, _jsxs(YStack, { role: "listitem", gap: 1, children: [heading('Recents', label, true), loose.length ? menus(rest) : rest] })] })] }) }));
|
|
103
|
+
return (_jsx(YStack, { "data-slot": "recents", flex: 1, minH: 0, children: _jsxs(ScrollView, { flex: 1, showsVerticalScrollIndicator: false, ...{ overscrollBehavior: 'contain' }, children: [error ? _jsx(Note, { children: error.message }) : null, _jsxs(YStack, { role: "list", "aria-labelledby": label, gap: 1, children: [pinned ? (_jsxs(YStack, { role: "listitem", gap: 1, children: [heading(PINNED), menus(_jsx(YStack, { role: "list", "aria-label": PINNED, gap: 1, children: pinned.rows.map(row) }))] })) : null, _jsxs(YStack, { role: "listitem", gap: 1, children: [heading('Recents', label, true), loose.length ? menus(rest) : rest] })] })] }) }));
|
|
102
104
|
}
|
package/dist/Settings.js
CHANGED
|
@@ -23,6 +23,7 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
23
23
|
//
|
|
24
24
|
// The panes that are not yet built say so in one sentence rather than pretending
|
|
25
25
|
// to a screen. An honest empty pane is a smaller lie than an invented one.
|
|
26
|
+
import { useI18n } from '@hanzo/i18n/react';
|
|
26
27
|
import { app, dev } from './lib/host.js';
|
|
27
28
|
import { ArrowLeft, ArrowUpRight } from 'lucide-react';
|
|
28
29
|
import { Text } from '@hanzo/ui';
|
|
@@ -104,11 +105,12 @@ export const FIRST = ROWS[0].id;
|
|
|
104
105
|
* the address never moves.
|
|
105
106
|
*/
|
|
106
107
|
export function SettingsList({ active, filter, onPick, onBack, }) {
|
|
108
|
+
const { t } = useI18n();
|
|
107
109
|
const q = filter.trim().toLowerCase();
|
|
108
110
|
const groups = q
|
|
109
111
|
? GROUPS.map((g) => ({ ...g, rows: g.rows.filter((r) => r.label.toLowerCase().includes(q)) })).filter((g) => g.rows.length > 0)
|
|
110
112
|
: GROUPS;
|
|
111
|
-
return (_jsxs(_Fragment, { children: [_jsx(SidebarItem, { icon: _jsx(ArrowLeft, { size: 15, "aria-hidden": true }), onPress: onBack, children: "Workspace" }), q && groups.length === 0 ? (_jsxs(Text, { px: "$3", py: "$2", fontSize: "$2", color: "$quiet", children: ["No matches for
|
|
113
|
+
return (_jsxs(_Fragment, { children: [_jsx(SidebarItem, { icon: _jsx(ArrowLeft, { size: 15, "aria-hidden": true }), onPress: onBack, children: t("Workspace") }), q && groups.length === 0 ? (_jsxs(Text, { px: "$3", py: "$2", fontSize: "$2", color: "$quiet", children: [t("No matches for “"), filter.trim(), "\u201D."] })) : null, groups.map((g) => (_jsx(SidebarSection, { label: g.label, children: g.rows.map((r) => (_jsx(SidebarItem, {
|
|
112
114
|
// The arrow says this row LEAVES. Without it a row that navigates
|
|
113
115
|
// away and one that draws a pane in place look identical until
|
|
114
116
|
// pressed.
|
package/dist/Top.js
CHANGED
|
@@ -16,6 +16,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
16
16
|
// was last). In Studio neither is lit. New is Chat's New chat, and elsewhere the
|
|
17
17
|
// mode's own New row (@hanzo/build's and @hanzo/studio's `nav`, `NEW`), so the
|
|
18
18
|
// bar names it as the sidebar does.
|
|
19
|
+
import { useI18n } from '@hanzo/i18n/react';
|
|
19
20
|
import { SquarePen } from 'lucide-react';
|
|
20
21
|
import { Text, XStack } from '@hanzo/gui';
|
|
21
22
|
import { nav, NEW } from '@hanzo/build';
|
|
@@ -33,7 +34,8 @@ const SEGMENT = 73;
|
|
|
33
34
|
const GLASS = { ...pane(), borderColor: 'var(--border-strong)', borderRadius: 9999 };
|
|
34
35
|
/** A round glass button named for what it does. */
|
|
35
36
|
function Round({ label, onPress, children, ...rest }) {
|
|
36
|
-
|
|
37
|
+
const { t } = useI18n();
|
|
38
|
+
return (_jsx(XStack, { render: "button", "aria-label": t(label), onPress: onPress, ...GLASS, width: ROUND, height: ROUND, items: "center", justify: "center", shrink: 0, cursor: "pointer", pressStyle: { bg: '$raised' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, ...rest, children: children }));
|
|
37
39
|
}
|
|
38
40
|
/** The drawer's mark: two strokes, the lower one shorter, 19×11 as the reference draws it. */
|
|
39
41
|
function Lines() {
|
|
@@ -44,6 +46,7 @@ function Side({ value, children }) {
|
|
|
44
46
|
return (_jsx(ToggleGroupItem, { value: value, size: "lg", width: SEGMENT, rounded: 9999, bg: "transparent", borderColor: "transparent", hoverStyle: { bg: '$hover' }, activeStyle: { bg: '$raised', borderColor: 'transparent' }, children: _jsx(Text, { fontSize: "$4", fontWeight: "500", color: "$ink", numberOfLines: 1, children: children }) }));
|
|
45
47
|
}
|
|
46
48
|
export function Top({ host, mode, places, go, onMenu, onChat, onDev, }) {
|
|
49
|
+
const { t } = useI18n();
|
|
47
50
|
const made = mode === 'chat' ? null : (places ?? nav(host, (p) => host.go(p))).flatMap((g) => g.links).find((l) => l.id === NEW);
|
|
48
51
|
const fresh = mode === 'chat'
|
|
49
52
|
? {
|
|
@@ -54,5 +57,5 @@ export function Top({ host, mode, places, go, onMenu, onChat, onDev, }) {
|
|
|
54
57
|
},
|
|
55
58
|
}
|
|
56
59
|
: { label: made?.label ?? 'New', onPress: made?.onPress };
|
|
57
|
-
return (_jsxs(XStack, { "data-slot": "app-bar", height: `calc(${LINE}px + var(--safe-top))`, pt: "var(--safe-top)", px: "$4.5", items: "center", justify: "space-between", shrink: 0, $md: { display: 'none' }, children: [_jsx(Round, { label: "Open sidebar", "data-slot": "bar-menu", onPress: onMenu, children: _jsx(Lines, {}) }), _jsx(XStack, { "data-slot": "bar-mode", ...GLASS, height: LINE, p: "$1", items: "center", children: _jsxs(ToggleGroup, { type: "single", "aria-label": "App", value: mode === 'chat' || mode === 'dev' ? mode : '', disableDeactivation: true, onValueChange: (v) => (v === 'chat' ? onChat() : v === 'dev' ? onDev() : undefined), children: [_jsx(Side, { value: "chat", children: "Chat" }), _jsx(Side, { value: "dev", children: "Dev" })] }) }), _jsx(Round, { label: fresh.label, "data-slot": "bar-new", onPress: fresh.onPress, children: _jsx(SquarePen, { size: 20, "aria-hidden": true }) })] }));
|
|
60
|
+
return (_jsxs(XStack, { "data-slot": "app-bar", height: `calc(${LINE}px + var(--safe-top))`, pt: "var(--safe-top)", px: "$4.5", items: "center", justify: "space-between", shrink: 0, $md: { display: 'none' }, children: [_jsx(Round, { label: t("Open sidebar"), "data-slot": "bar-menu", onPress: onMenu, children: _jsx(Lines, {}) }), _jsx(XStack, { "data-slot": "bar-mode", ...GLASS, height: LINE, p: "$1", items: "center", children: _jsxs(ToggleGroup, { type: "single", "aria-label": t("App"), value: mode === 'chat' || mode === 'dev' ? mode : '', disableDeactivation: true, onValueChange: (v) => (v === 'chat' ? onChat() : v === 'dev' ? onDev() : undefined), children: [_jsx(Side, { value: "chat", children: t("Chat") }), _jsx(Side, { value: "dev", children: t("Dev") })] }) }), _jsx(Round, { label: fresh.label, "data-slot": "bar-new", onPress: fresh.onPress, children: _jsx(SquarePen, { size: 20, "aria-hidden": true }) })] }));
|
|
58
61
|
}
|
package/dist/dev.js
CHANGED
|
@@ -44,7 +44,7 @@ import { showSettings, useOpen } from './open.js';
|
|
|
44
44
|
const LINKS = {
|
|
45
45
|
github: app('-/sync'),
|
|
46
46
|
customize: app('-/customize'),
|
|
47
|
-
settings:
|
|
47
|
+
settings: '/settings',
|
|
48
48
|
home: '/',
|
|
49
49
|
};
|
|
50
50
|
/** The builder's address for the plans. */
|
|
@@ -80,15 +80,23 @@ export function useDevHost() {
|
|
|
80
80
|
const here = path(route(at(pathname)));
|
|
81
81
|
const look = useLook();
|
|
82
82
|
const { settings } = useOpen();
|
|
83
|
-
//
|
|
84
|
-
// one it does not have opens Settings itself.
|
|
83
|
+
// Settings is top-level /settings; organization settings are at /settings/organization.
|
|
85
84
|
useEffect(() => {
|
|
86
85
|
if (!settings)
|
|
87
86
|
return;
|
|
88
87
|
showSettings(null);
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const s = settings.toLowerCase();
|
|
89
|
+
if (s.includes('member'))
|
|
90
|
+
router.push('/settings/organization/members');
|
|
91
|
+
else if (s.includes('billing'))
|
|
92
|
+
router.push('/settings/organization/billing');
|
|
93
|
+
else if (s.includes('usage'))
|
|
94
|
+
router.push('/settings/organization/usage');
|
|
95
|
+
else if (s.includes('org'))
|
|
96
|
+
router.push('/settings/organization');
|
|
97
|
+
else
|
|
98
|
+
router.push('/settings');
|
|
99
|
+
}, [settings, router]);
|
|
92
100
|
// The token's claims change only when the token does: a sign-in, a refresh.
|
|
93
101
|
const memberships = useMemo(() => orgs(), [accessToken]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
94
102
|
const scoped = useMemo(() => org(), [accessToken]); // eslint-disable-line react-hooks/exhaustive-deps
|
package/dist/index.js
CHANGED
package/dist/lib/signout.d.ts
CHANGED
|
@@ -10,5 +10,10 @@ export declare const OUT = "/login?from=logout";
|
|
|
10
10
|
* IAM's /v1/iam routes, IAM's session here ended, the local session cleared —
|
|
11
11
|
* counted as logout_completed, and then /login?from=logout, where the person can
|
|
12
12
|
* sign straight back in. IAM's own logout page is never visited.
|
|
13
|
+
*
|
|
14
|
+
* EVERY HANZO SITE AT ONCE (`everywhere`). hanzo.ai and platform.hanzo.ai sign in
|
|
15
|
+
* from one session, so leaving one of them must leave the other: IAM retires the
|
|
16
|
+
* person's grant to every application of this client's organization along with
|
|
17
|
+
* the session. A third-party app the person signed into keeps its own.
|
|
13
18
|
*/
|
|
14
19
|
export declare function useSignOut(): () => Promise<void>;
|
package/dist/lib/signout.js
CHANGED
|
@@ -28,7 +28,13 @@ export const OUT = '/login?from=logout';
|
|
|
28
28
|
* IAM's /v1/iam routes, IAM's session here ended, the local session cleared —
|
|
29
29
|
* counted as logout_completed, and then /login?from=logout, where the person can
|
|
30
30
|
* sign straight back in. IAM's own logout page is never visited.
|
|
31
|
+
*
|
|
32
|
+
* EVERY HANZO SITE AT ONCE (`everywhere`). hanzo.ai and platform.hanzo.ai sign in
|
|
33
|
+
* from one session, so leaving one of them must leave the other: IAM retires the
|
|
34
|
+
* person's grant to every application of this client's organization along with
|
|
35
|
+
* the session. A third-party app the person signed into keeps its own.
|
|
31
36
|
*/
|
|
32
37
|
export function useSignOut() {
|
|
33
|
-
|
|
38
|
+
// @ts-expect-error everywhere option added in @hanzo/ui / IAM shared sign-out
|
|
39
|
+
return useUiSignOut({ to: OUT, track, everywhere: true });
|
|
34
40
|
}
|
package/dist/slide.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/** The pane left in sight at the end edge while the menu is open, px: a thumb's 44 and room around it. */
|
|
2
|
+
export declare const STRIP = 64;
|
|
3
|
+
/** The menu's widest, px: a phone held sideways, or a small tablet, keeps the menu a menu. */
|
|
4
|
+
export declare const REACH = 360;
|
|
5
|
+
/** How far the pane slides, as CSS: the window less the strip, up to `REACH`. `%` is the window's width wherever it is read. */
|
|
6
|
+
export declare const OPEN = "min(100% - 64px, 360px)";
|
|
7
|
+
/** Shut (no menu), open, or sliding home before the menu goes. */
|
|
8
|
+
export type State = 'shut' | 'open' | 'closing';
|
|
9
|
+
/** Which way the end side is, as a sign on the x axis. */
|
|
10
|
+
export declare const sign: (direction: string) => 1 | -1;
|
|
11
|
+
/** px a finger moves before a drag is a drag, and not a tap or a scroll. */
|
|
12
|
+
export declare const SLOP = 8;
|
|
13
|
+
/**
|
|
14
|
+
* What a finger's first movement is: a pull along the line (`x`), a scroll
|
|
15
|
+
* (`y`), or nothing yet. Along the line has to win clearly: a list scrolls on a
|
|
16
|
+
* slant.
|
|
17
|
+
*/
|
|
18
|
+
export declare function axis(dx: number, dy: number): 'x' | 'y' | null;
|
|
19
|
+
/** Where the pane stands while a finger holds it, px from home: where it was, moved along the line, never past home or open. */
|
|
20
|
+
export declare function pull(from: number, dx: number, way: 1 | -1, reach: number): number;
|
|
21
|
+
/** A flick, px per ms along the line: faster than this decides by its way, whatever the distance. */
|
|
22
|
+
export declare const FLICK = 0.4;
|
|
23
|
+
/** Whether a pane let go at `at` px from home, moving `speed` px/ms along the line, stays open. */
|
|
24
|
+
export declare function settle(at: number, reach: number, speed: number): boolean;
|
package/dist/slide.js
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// The phone's drawer as numbers (Drawer.tsx draws it): how far the pane slides,
|
|
2
|
+
// which way, and where a drag lets it go.
|
|
3
|
+
//
|
|
4
|
+
// The pane slides toward the END side of the line: right where text runs left to
|
|
5
|
+
// right, left under `dir="rtl"`. A transform has no logical form, so its sign is
|
|
6
|
+
// the one physical fact in the drawer, and it is read off the page
|
|
7
|
+
// (`getComputedStyle(…).direction`), never assumed. Everything else is logical:
|
|
8
|
+
// the menu stands at the start, the strip of pane left in sight at the end.
|
|
9
|
+
//
|
|
10
|
+
// A drag is measured ALONG the line: positive toward the end, whichever way the
|
|
11
|
+
// line runs, so the same numbers close an LTR drawer pulled left and an RTL one
|
|
12
|
+
// pulled right.
|
|
13
|
+
/** The pane left in sight at the end edge while the menu is open, px: a thumb's 44 and room around it. */
|
|
14
|
+
export const STRIP = 64;
|
|
15
|
+
/** The menu's widest, px: a phone held sideways, or a small tablet, keeps the menu a menu. */
|
|
16
|
+
export const REACH = 360;
|
|
17
|
+
/** How far the pane slides, as CSS: the window less the strip, up to `REACH`. `%` is the window's width wherever it is read. */
|
|
18
|
+
export const OPEN = `min(100% - ${STRIP}px, ${REACH}px)`;
|
|
19
|
+
/** Which way the end side is, as a sign on the x axis. */
|
|
20
|
+
export const sign = (direction) => (direction === 'rtl' ? -1 : 1);
|
|
21
|
+
/** px a finger moves before a drag is a drag, and not a tap or a scroll. */
|
|
22
|
+
export const SLOP = 8;
|
|
23
|
+
/**
|
|
24
|
+
* What a finger's first movement is: a pull along the line (`x`), a scroll
|
|
25
|
+
* (`y`), or nothing yet. Along the line has to win clearly: a list scrolls on a
|
|
26
|
+
* slant.
|
|
27
|
+
*/
|
|
28
|
+
export function axis(dx, dy) {
|
|
29
|
+
const x = Math.abs(dx);
|
|
30
|
+
const y = Math.abs(dy);
|
|
31
|
+
if (x < SLOP && y < SLOP)
|
|
32
|
+
return null;
|
|
33
|
+
return x > y * 1.2 ? 'x' : 'y';
|
|
34
|
+
}
|
|
35
|
+
/** Where the pane stands while a finger holds it, px from home: where it was, moved along the line, never past home or open. */
|
|
36
|
+
export function pull(from, dx, way, reach) {
|
|
37
|
+
return Math.min(reach, Math.max(0, from + dx * way));
|
|
38
|
+
}
|
|
39
|
+
/** A flick, px per ms along the line: faster than this decides by its way, whatever the distance. */
|
|
40
|
+
export const FLICK = 0.4;
|
|
41
|
+
/** Whether a pane let go at `at` px from home, moving `speed` px/ms along the line, stays open. */
|
|
42
|
+
export function settle(at, reach, speed) {
|
|
43
|
+
if (speed <= -FLICK)
|
|
44
|
+
return false;
|
|
45
|
+
if (speed >= FLICK)
|
|
46
|
+
return true;
|
|
47
|
+
return at > reach / 2;
|
|
48
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.98",
|
|
4
4
|
"description": "The workspace rooms — Home, Chat, Inbox, Contacts, Meet, Cal, Drive, Board, Work, Bots — and the frame that holds them, once, for every Hanzo surface.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"@hanzo/composer": ">=0.2.0",
|
|
54
54
|
"@hanzo/event": ">=0.3.56",
|
|
55
55
|
"@hanzo/gui": "^8.3.5",
|
|
56
|
+
"@hanzo/i18n": ">=0.2.0",
|
|
56
57
|
"@hanzo/iam": ">=0.21.35",
|
|
57
58
|
"@hanzo/logo": ">=1.0.26",
|
|
58
59
|
"@hanzo/studio": ">=0.1.0",
|
|
@@ -73,10 +74,11 @@
|
|
|
73
74
|
"@hanzo/design": "0.5.34",
|
|
74
75
|
"@hanzo/event": "0.3.56",
|
|
75
76
|
"@hanzo/gui": "8.3.5",
|
|
77
|
+
"@hanzo/i18n": "0.2.0",
|
|
76
78
|
"@hanzo/iam": "0.21.35",
|
|
77
79
|
"@hanzo/logo": "1.0.26",
|
|
78
80
|
"@hanzo/studio": "0.1.0",
|
|
79
|
-
"@hanzo/tabs": "github:hanzo-
|
|
81
|
+
"@hanzo/tabs": "github:hanzo-inc/tabs",
|
|
80
82
|
"@hanzo/ui": "8.29.0",
|
|
81
83
|
"@hanzo/usage": "0.1.18",
|
|
82
84
|
"@hanzo/voice": "0.1.19",
|
|
@@ -88,6 +90,7 @@
|
|
|
88
90
|
"@types/node": "26.5.0",
|
|
89
91
|
"@types/react": "19.2.18",
|
|
90
92
|
"@types/react-dom": "19.2.7",
|
|
93
|
+
"happy-dom": "20.14.6",
|
|
91
94
|
"lucide-react": "1.42.0",
|
|
92
95
|
"react": "19.2.8",
|
|
93
96
|
"react-dom": "19.2.8",
|