@hanzo/rooms 0.1.34 → 0.1.35
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 +2 -2
- package/dist/dev.js +9 -9
- package/dist/host.d.ts +9 -5
- package/dist/host.js +5 -4
- package/dist/lib/host.d.ts +20 -15
- package/dist/lib/host.js +41 -26
- package/dist/lib/session.js +7 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -11,13 +11,13 @@ import { CalScheduler } from '@hanzo/rooms/CalScheduler'
|
|
|
11
11
|
|
|
12
12
|
configure({ site: '', home: '/home', signUp: '/signup' })
|
|
13
13
|
|
|
14
|
-
<Rooms router={router} search={search} route={route} Link={Link}>
|
|
14
|
+
<Rooms router={router} search={search} path={pathname} route={route} Link={Link}>
|
|
15
15
|
<Room mode="cal"><CalScheduler /></Room>
|
|
16
16
|
</Rooms>
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
`configure()` names the host's addresses (where its own pages live, the
|
|
20
20
|
gateway and IAM, the plan catalogue to paint first). `<Rooms>` carries what
|
|
21
|
-
moves: the router, the query, the route and the link component. The rooms
|
|
21
|
+
moves: the router, the query, the path, the route and the link component. The rooms
|
|
22
22
|
import nothing from a host, and their look comes from `@hanzo/appearance` and
|
|
23
23
|
`@hanzo/design` through `@hanzo/ui`.
|
package/dist/dev.js
CHANGED
|
@@ -7,12 +7,12 @@
|
|
|
7
7
|
// to leave. The name drawn at the top left is Hanzo Dev: this host is the
|
|
8
8
|
// dev agent. Chat, on the rooms shell, is Hanzo AI.
|
|
9
9
|
//
|
|
10
|
-
// THE ADDRESS IS THE
|
|
11
|
-
//
|
|
10
|
+
// THE ADDRESS IS THE PATH. Dev is `/dev`, and what it shows is the path under
|
|
11
|
+
// it in the builder's own grammar (lib/host.ts `app`, `under`), so a run, a
|
|
12
12
|
// screen, a Settings section, a Customize tab, the plans and a project all
|
|
13
13
|
// survive a reload, and Back steps through them. A move is a native history
|
|
14
|
-
// entry, which the Next router folds into `
|
|
15
|
-
//
|
|
14
|
+
// entry, which the Next router folds into `usePathname`, so reading the address
|
|
15
|
+
// and moving it are one path.
|
|
16
16
|
import { useMemo } from 'react';
|
|
17
17
|
import { useLook, useRooms } from './host.js';
|
|
18
18
|
import { useIam } from '@hanzo/iam/react';
|
|
@@ -21,7 +21,7 @@ import { administers, path, route } from '@hanzo/build';
|
|
|
21
21
|
import { bearer, named, org, orgs, pick } from './lib/session.js';
|
|
22
22
|
import { enter } from './lib/destination.js';
|
|
23
23
|
import { api } from './lib/api.js';
|
|
24
|
-
import { app,
|
|
24
|
+
import { app, under } from './lib/host.js';
|
|
25
25
|
import { link } from './lib/tags.js';
|
|
26
26
|
/** Where the builder links out: every one of them an address of this site. */
|
|
27
27
|
const LINKS = {
|
|
@@ -32,14 +32,14 @@ const LINKS = {
|
|
|
32
32
|
};
|
|
33
33
|
/** The person's theme, when they have chosen one the builder can name. */
|
|
34
34
|
const theme = (t) => (t === 'light' || t === 'dark' || t === 'system' ? t : undefined);
|
|
35
|
-
/** The app address a
|
|
35
|
+
/** The app address a builder path names, canonical; '' for anything that is not one. */
|
|
36
36
|
const canonical = (at) => path(route(at ?? ''));
|
|
37
37
|
/** The host for a signed-in reader. */
|
|
38
38
|
export function useDevHost() {
|
|
39
39
|
const { user, accessToken } = useIam();
|
|
40
40
|
const logout = useSignOut();
|
|
41
|
-
const { router,
|
|
42
|
-
const here = canonical(
|
|
41
|
+
const { router, path: pathname } = useRooms();
|
|
42
|
+
const here = canonical(under(pathname));
|
|
43
43
|
const look = useLook();
|
|
44
44
|
// The token's claims change only when the token does: a sign-in, a refresh.
|
|
45
45
|
const memberships = useMemo(() => orgs(), [accessToken]); // eslint-disable-line react-hooks/exhaustive-deps
|
|
@@ -70,7 +70,7 @@ export function useDevHost() {
|
|
|
70
70
|
path: here,
|
|
71
71
|
go: (to, how) => {
|
|
72
72
|
const next = app(canonical(to));
|
|
73
|
-
if (
|
|
73
|
+
if (window.location.pathname === next && !window.location.search)
|
|
74
74
|
return;
|
|
75
75
|
if (how?.replace)
|
|
76
76
|
window.history.replaceState(null, '', next);
|
package/dist/host.d.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* configure({ site: 'https://hanzo.ai', home: '/', signUp: '/start' })
|
|
9
9
|
*
|
|
10
|
-
* <Rooms router={useRouter()} search={useSearchParams()} route={route} Link={Link}>
|
|
10
|
+
* <Rooms router={useRouter()} search={useSearchParams()} path={usePathname()} route={route} Link={Link}>
|
|
11
11
|
* <Room mode="cal" />
|
|
12
12
|
* </Rooms>
|
|
13
13
|
*
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
* any component and on pages the rooms never draw. So the host states them once
|
|
18
18
|
* with `configure()`, in a module its root imports, before anything renders.
|
|
19
19
|
*
|
|
20
|
-
* The ROUTER, the query and the route change as the page moves, so they ride
|
|
20
|
+
* The ROUTER, the query, the path and the route change as the page moves, so they ride
|
|
21
21
|
* React context, and a room reads them with `useRooms()`.
|
|
22
22
|
*/
|
|
23
23
|
import { type AnchorHTMLAttributes, type ComponentType, type ReactNode } from 'react';
|
|
@@ -34,14 +34,18 @@ export interface Router {
|
|
|
34
34
|
}
|
|
35
35
|
interface Moving {
|
|
36
36
|
router: Router;
|
|
37
|
-
/** The address's query, for the rooms that read one (
|
|
37
|
+
/** The address's query, for the rooms that read one (Chat's `?chat=`). */
|
|
38
38
|
search: URLSearchParams | null;
|
|
39
|
+
/** The address's path, for the rooms that read one (Dev's, under `/dev`). */
|
|
40
|
+
path: string | null;
|
|
39
41
|
route: string;
|
|
40
42
|
Link: Link;
|
|
41
43
|
}
|
|
42
|
-
export interface RoomsProps extends Omit<Moving, 'search'> {
|
|
44
|
+
export interface RoomsProps extends Omit<Moving, 'search' | 'path'> {
|
|
43
45
|
/** Absent where no mounted room reads the query, so a static export needs no Suspense for it. */
|
|
44
46
|
search?: URLSearchParams | null;
|
|
47
|
+
/** Absent where no mounted room reads the path. */
|
|
48
|
+
path?: string | null;
|
|
45
49
|
children?: ReactNode;
|
|
46
50
|
}
|
|
47
51
|
/** The router, the query, the route and the link the host mounted the rooms with. */
|
|
@@ -72,5 +76,5 @@ export declare function useLook(): {
|
|
|
72
76
|
* keeps their choice in step with IAM.
|
|
73
77
|
*/
|
|
74
78
|
export declare function Look(): any;
|
|
75
|
-
export declare function Rooms({ router, search, route, Link, children }: RoomsProps): import("react").JSX.Element;
|
|
79
|
+
export declare function Rooms({ router, search, path, route, Link, children }: RoomsProps): import("react").JSX.Element;
|
|
76
80
|
export {};
|
package/dist/host.js
CHANGED
|
@@ -9,7 +9,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
9
9
|
*
|
|
10
10
|
* configure({ site: 'https://hanzo.ai', home: '/', signUp: '/start' })
|
|
11
11
|
*
|
|
12
|
-
* <Rooms router={useRouter()} search={useSearchParams()} route={route} Link={Link}>
|
|
12
|
+
* <Rooms router={useRouter()} search={useSearchParams()} path={usePathname()} route={route} Link={Link}>
|
|
13
13
|
* <Room mode="cal" />
|
|
14
14
|
* </Rooms>
|
|
15
15
|
*
|
|
@@ -19,7 +19,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
|
|
|
19
19
|
* any component and on pages the rooms never draw. So the host states them once
|
|
20
20
|
* with `configure()`, in a module its root imports, before anything renders.
|
|
21
21
|
*
|
|
22
|
-
* The ROUTER, the query and the route change as the page moves, so they ride
|
|
22
|
+
* The ROUTER, the query, the path and the route change as the page moves, so they ride
|
|
23
23
|
* React context, and a room reads them with `useRooms()`.
|
|
24
24
|
*/
|
|
25
25
|
import { createContext, useContext } from 'react';
|
|
@@ -35,6 +35,7 @@ const Context = createContext({
|
|
|
35
35
|
forward: () => window.history.forward(),
|
|
36
36
|
},
|
|
37
37
|
search: null,
|
|
38
|
+
path: null,
|
|
38
39
|
route: '/',
|
|
39
40
|
Link: Plain,
|
|
40
41
|
});
|
|
@@ -71,6 +72,6 @@ export function Look() {
|
|
|
71
72
|
useLook();
|
|
72
73
|
return null;
|
|
73
74
|
}
|
|
74
|
-
export function Rooms({ router, search = null, route, Link, children }) {
|
|
75
|
-
return _jsx(Context.Provider, { value: { router, search, route, Link }, children: children });
|
|
75
|
+
export function Rooms({ router, search = null, path = null, route, Link, children }) {
|
|
76
|
+
return _jsx(Context.Provider, { value: { router, search, path, route, Link }, children: children });
|
|
76
77
|
}
|
package/dist/lib/host.d.ts
CHANGED
|
@@ -30,30 +30,35 @@ export declare const ENTRY = "https://hanzo.team/?signin";
|
|
|
30
30
|
*/
|
|
31
31
|
export declare const START = "https://hanzo.team/start";
|
|
32
32
|
/**
|
|
33
|
-
* The web app,
|
|
34
|
-
* Dev is @hanzo/build's `<Builder
|
|
35
|
-
* in the builder's own grammar (`route` in @hanzo/build):
|
|
36
|
-
* run,
|
|
37
|
-
*
|
|
38
|
-
*
|
|
33
|
+
* The web app, for a signed-in reader, in two modes. Chat is the default, at
|
|
34
|
+
* `/`. Dev is @hanzo/build's `<Builder>` at `/dev`, and what it shows is the
|
|
35
|
+
* PATH under it, in the builder's own grammar (`route` in @hanzo/build): `/dev`
|
|
36
|
+
* New, `/dev/sess_<id>` a run, `/dev/<org>/<repo>` a project,
|
|
37
|
+
* `/dev/-/<screen>`, `/dev/-/settings[/<section>]`, `/dev/-/customize[/<tab>]`,
|
|
38
|
+
* `/dev/<slug>` a deployed site. The export holds one page for all of them,
|
|
39
|
+
* `/dev`, and the edge serves it for every path under it (hanzo.ai's
|
|
40
|
+
* lib/edge.ts `APP`).
|
|
39
41
|
*/
|
|
40
|
-
export declare const
|
|
41
|
-
/**
|
|
42
|
+
export declare const DEV = "/dev";
|
|
43
|
+
/** Dev at an app address; '' is Dev's New, `/dev` itself. */
|
|
42
44
|
export declare const app: (path: string) => string;
|
|
45
|
+
/** The app address a pathname names under `/dev`, or null for a pathname that is not Dev's. */
|
|
46
|
+
export declare const under: (pathname: string | null | undefined) => string | null;
|
|
43
47
|
/**
|
|
44
48
|
* Chat, the app's default mode: `/` is a new conversation and `?chat=<id>` one
|
|
45
|
-
* of the reader's. So the address says which mode the app is in —
|
|
46
|
-
* anything else Chat — and a reload keeps it.
|
|
49
|
+
* of the reader's. So the address says which mode the app is in — a path under
|
|
50
|
+
* `/dev` for Dev, anything else Chat — and a reload keeps it.
|
|
47
51
|
*/
|
|
48
52
|
export declare const TALK = "chat";
|
|
49
53
|
/** `/` in Chat, on a conversation, or `/` itself for a new one. */
|
|
50
54
|
export declare const talk: (id?: string | null) => string;
|
|
51
55
|
/**
|
|
52
|
-
*
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
*
|
|
56
|
+
* Dev opened on one run, project or site, from anywhere: every "Try Hanzo Dev"
|
|
57
|
+
* link, a room's Dev, the console's "open in the builder". It signs a stranger
|
|
58
|
+
* in on the way (app/(app)/dev/_door.tsx), and is reached through `site()`:
|
|
59
|
+
* here on hanzo.ai, across to hanzo.ai from hanzo.team. Only a value that is
|
|
60
|
+
* exactly a session id, a repository or a site's slug is carried; anything else
|
|
61
|
+
* opens /dev itself, so no caller can make this name another address.
|
|
57
62
|
*/
|
|
58
63
|
export declare const dev: (ref?: string | null) => string;
|
|
59
64
|
/**
|
package/dist/lib/host.js
CHANGED
|
@@ -32,44 +32,59 @@ export const ENTRY = `${WORKSPACE}/?signin`;
|
|
|
32
32
|
*/
|
|
33
33
|
export const START = `${WORKSPACE}/start`;
|
|
34
34
|
/**
|
|
35
|
-
* The web app,
|
|
36
|
-
* Dev is @hanzo/build's `<Builder
|
|
37
|
-
* in the builder's own grammar (`route` in @hanzo/build):
|
|
38
|
-
* run,
|
|
39
|
-
*
|
|
40
|
-
*
|
|
35
|
+
* The web app, for a signed-in reader, in two modes. Chat is the default, at
|
|
36
|
+
* `/`. Dev is @hanzo/build's `<Builder>` at `/dev`, and what it shows is the
|
|
37
|
+
* PATH under it, in the builder's own grammar (`route` in @hanzo/build): `/dev`
|
|
38
|
+
* New, `/dev/sess_<id>` a run, `/dev/<org>/<repo>` a project,
|
|
39
|
+
* `/dev/-/<screen>`, `/dev/-/settings[/<section>]`, `/dev/-/customize[/<tab>]`,
|
|
40
|
+
* `/dev/<slug>` a deployed site. The export holds one page for all of them,
|
|
41
|
+
* `/dev`, and the edge serves it for every path under it (hanzo.ai's
|
|
42
|
+
* lib/edge.ts `APP`).
|
|
41
43
|
*/
|
|
42
|
-
export const
|
|
43
|
-
/**
|
|
44
|
-
export const app = (path) =>
|
|
44
|
+
export const DEV = '/dev';
|
|
45
|
+
/** Dev at an app address; '' is Dev's New, `/dev` itself. */
|
|
46
|
+
export const app = (path) => {
|
|
47
|
+
const p = path.replace(/^\/+|\/+$/g, '');
|
|
48
|
+
return p ? `${DEV}/${p}` : DEV;
|
|
49
|
+
};
|
|
50
|
+
/** The app address a pathname names under `/dev`, or null for a pathname that is not Dev's. */
|
|
51
|
+
export const under = (pathname) => {
|
|
52
|
+
if (!pathname)
|
|
53
|
+
return null;
|
|
54
|
+
if (pathname === DEV || pathname === `${DEV}/`)
|
|
55
|
+
return '';
|
|
56
|
+
if (!pathname.startsWith(`${DEV}/`))
|
|
57
|
+
return null;
|
|
58
|
+
try {
|
|
59
|
+
return decodeURIComponent(pathname.slice(DEV.length + 1));
|
|
60
|
+
}
|
|
61
|
+
catch {
|
|
62
|
+
return '';
|
|
63
|
+
}
|
|
64
|
+
};
|
|
45
65
|
/**
|
|
46
66
|
* Chat, the app's default mode: `/` is a new conversation and `?chat=<id>` one
|
|
47
|
-
* of the reader's. So the address says which mode the app is in —
|
|
48
|
-
* anything else Chat — and a reload keeps it.
|
|
67
|
+
* of the reader's. So the address says which mode the app is in — a path under
|
|
68
|
+
* `/dev` for Dev, anything else Chat — and a reload keeps it.
|
|
49
69
|
*/
|
|
50
70
|
export const TALK = 'chat';
|
|
51
71
|
/** `/` in Chat, on a conversation, or `/` itself for a new one. */
|
|
52
72
|
export const talk = (id) => (id ? `/?${TALK}=${encodeURIComponent(id)}` : '/');
|
|
53
|
-
/**
|
|
54
|
-
* The door into the app: every "Try Hanzo Dev" link, the rail's Dev, the
|
|
55
|
-
* console's "open in the builder", dev.hanzo.ai. It signs a stranger in and
|
|
56
|
-
* forwards a member to Dev in the app, `/?at=` (app/(app)/dev/_door.tsx). It is
|
|
57
|
-
* the app's page, so it is reached through `site()`: here on hanzo.ai, across
|
|
58
|
-
* to hanzo.ai from hanzo.team.
|
|
59
|
-
*/
|
|
60
|
-
const DEV = '/dev';
|
|
61
73
|
/** A run, as the platform mints its id. */
|
|
62
74
|
const SESSION = /^sess_[0-9a-f]{32}$/;
|
|
63
|
-
/** A
|
|
75
|
+
/** A deployed site, as the Sites plane slugs it. */
|
|
64
76
|
const SLUG = /^[a-z0-9](?:[a-z0-9-]{0,38}[a-z0-9])?$/;
|
|
77
|
+
/** A repository on the forge, `<org>/<name>`. */
|
|
78
|
+
const REPO = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}\/[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
65
79
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
80
|
+
* Dev opened on one run, project or site, from anywhere: every "Try Hanzo Dev"
|
|
81
|
+
* link, a room's Dev, the console's "open in the builder". It signs a stranger
|
|
82
|
+
* in on the way (app/(app)/dev/_door.tsx), and is reached through `site()`:
|
|
83
|
+
* here on hanzo.ai, across to hanzo.ai from hanzo.team. Only a value that is
|
|
84
|
+
* exactly a session id, a repository or a site's slug is carried; anything else
|
|
85
|
+
* opens /dev itself, so no caller can make this name another address.
|
|
71
86
|
*/
|
|
72
|
-
export const dev = (ref) => site(
|
|
87
|
+
export const dev = (ref) => site(ref && (SESSION.test(ref) || REPO.test(ref) || SLUG.test(ref)) ? app(ref) : DEV);
|
|
73
88
|
/** The routes under app/(app) the apex keeps: the app — /chat, a chat shared by link, and /dev. */
|
|
74
89
|
const KEPT = new Set(['/chat', '/chat/shared', '/dev']);
|
|
75
90
|
/** Settings, and every page under it: the person's and the organization's, served wherever the app is. */
|
package/dist/lib/session.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
* who was signed in, which reads as a permissions problem rather than a typo.
|
|
15
15
|
* Two derivations of one name never agree; this is the one derivation.
|
|
16
16
|
*/
|
|
17
|
-
import {
|
|
17
|
+
import { TALK } from './host.js';
|
|
18
18
|
import { api } from './api.js';
|
|
19
19
|
/** The SDK's own keys, `hanzo_iam_`-prefixed. The far side of a boundary. */
|
|
20
20
|
const PREFIX = 'hanzo_iam_';
|
|
@@ -59,12 +59,13 @@ export function live() {
|
|
|
59
59
|
/** The attribute on `<html>` that says `/` is showing the app, not the landing. */
|
|
60
60
|
export const APP = 'data-app';
|
|
61
61
|
/**
|
|
62
|
-
* An address on `/` that names a place in the app — `?
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
62
|
+
* An address on `/` that names a place in the app — `?chat` in Chat
|
|
63
|
+
* (lib/host.ts `TALK`; Dev's places are paths under `/dev`, whose own page
|
|
64
|
+
* signs a stranger in). The app is signed-in only, so a reader nobody has
|
|
65
|
+
* signed in is sent to hanzo.id with it rather than shown the landing, and it
|
|
66
|
+
* comes back with them.
|
|
66
67
|
*/
|
|
67
|
-
const PLACE = new RegExp(`[?&]
|
|
68
|
+
const PLACE = new RegExp(`[?&]${TALK}(?:[=&]|$)`);
|
|
68
69
|
/** Whether `search` names a place in the app. */
|
|
69
70
|
export const place = (search) => PLACE.test(search);
|
|
70
71
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.35",
|
|
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",
|