@hanzo/rooms 0.1.62 → 0.1.64
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 +3 -3
- package/dist/Orgs.js +40 -37
- package/dist/Room.js +3 -2
- package/package.json +1 -1
package/dist/App.js
CHANGED
|
@@ -24,9 +24,9 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
24
24
|
// stranger sees is the host's.
|
|
25
25
|
//
|
|
26
26
|
// THE ORGANIZATION COMES FIRST (Orgs.tsx), and the app mounts it itself, so no
|
|
27
|
-
// host draws the app without it: a reader with none makes one
|
|
28
|
-
// several picks one
|
|
29
|
-
//
|
|
27
|
+
// host draws the app without it: a reader with none makes one and a reader
|
|
28
|
+
// with several picks one. No plan is asked for here: that is the workspace's,
|
|
29
|
+
// on its own host (hanzo.team) and behind its front door.
|
|
30
30
|
//
|
|
31
31
|
// THE SIDEBAR'S TOGGLE IS AT THE WINDOW'S TOP-LEFT. In a browser tab it leads
|
|
32
32
|
// the rail. A host that is a window of its own (`bar`) has no browser around
|
package/dist/Orgs.js
CHANGED
|
@@ -4,26 +4,29 @@ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-run
|
|
|
4
4
|
//
|
|
5
5
|
// An organization owns every agent, credit and member. A signed-in reader who
|
|
6
6
|
// has none is shown one thing: make one. A reader with several picks the one
|
|
7
|
-
// they are working in when they arrive.
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
// (lib/auth/session.ts `scope`, hooks/useAi.ts).
|
|
7
|
+
// they are working in when they arrive. Past both the app renders, and every
|
|
8
|
+
// request under it then carries that organization (lib/auth/session.ts
|
|
9
|
+
// `scope`, hooks/useAi.ts).
|
|
11
10
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
//
|
|
18
|
-
//
|
|
11
|
+
// NO PLAN STANDS IN FRONT OF CHAT OR DEV. Off the workspace every
|
|
12
|
+
// organization opens, whatever its plan: what it may spend is the API's to
|
|
13
|
+
// meter, per plan, on every call. The per-seat Team plan is the workspace's to
|
|
14
|
+
// ask for, on its host (hanzo.team) and behind its front door, and nowhere
|
|
15
|
+
// else. It used to be asked of every organization that was not personal and
|
|
16
|
+
// not on a live plan, on every host, which put each member of a team on Free,
|
|
17
|
+
// and every account filed in the shared sign-up organization, in front of a
|
|
18
|
+
// wall at hanzo.ai/chat. Plans are
|
|
19
|
+
// the catalog's, read live and seeded from @hanzo/plans for first paint.
|
|
20
|
+
// Checkout is hanzo.ai/pay in this tab; it returns here, and the tier is read
|
|
21
|
+
// again on return.
|
|
19
22
|
//
|
|
20
23
|
// THE FRONT DOOR. A workspace rooted at `/` (hanzo.team) draws its host's
|
|
21
24
|
// Landing for a stranger at Home (`front`) and its host's Signup at /start
|
|
22
25
|
// (`signup`). Behind either, a reader with no team names one, invites people
|
|
23
|
-
// and takes the per-seat plan (`Start`, `Plan`) instead of the create dialog
|
|
24
|
-
//
|
|
25
|
-
// and an open one is sent on (`forward`).
|
|
26
|
-
//
|
|
26
|
+
// and takes the per-seat plan (`Start`, `Plan`) instead of the create dialog;
|
|
27
|
+
// a team without a live plan is offered that plan, a personal organization on
|
|
28
|
+
// Free is offered a team, and an open one is sent on (`forward`). Behind the
|
|
29
|
+
// door, and only there, nothing opens without a live plan.
|
|
27
30
|
import { dev } from './lib/host.js';
|
|
28
31
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
29
32
|
import { useIam } from '@hanzo/iam/react';
|
|
@@ -78,21 +81,22 @@ export function Orgs({ children, front = false, forward, signup = false, }) {
|
|
|
78
81
|
// The team being set up in this page. Once its name is taken the setup owns
|
|
79
82
|
// the screen until checkout, whatever `Orgs` reads of the new organization.
|
|
80
83
|
const [founding, setFounding] = useState(null);
|
|
81
|
-
|
|
84
|
+
// The workspace asks for the plan, on its host and behind its front door, and
|
|
85
|
+
// only there is it read: nowhere else does it decide anything.
|
|
86
|
+
const onTeam = workspace(useHost());
|
|
87
|
+
const asks = door || onTeam;
|
|
88
|
+
const { tier, wrong, reload } = useTier(Boolean(asks && isAuthenticated && current), current);
|
|
82
89
|
// A plan is live when billing READ one for this organization and it is not the free rung.
|
|
83
90
|
const live = Boolean(tier?.tier && tier.tier.name !== FREE_TIER);
|
|
84
|
-
//
|
|
85
|
-
//
|
|
86
|
-
|
|
87
|
-
// a team is offered the plan, a personal one is offered a team.
|
|
88
|
-
const onTeam = workspace(useHost());
|
|
89
|
-
const free = door ? Boolean(tier) && !live : !live && !onTeam && tier?.tier?.name === FREE_TIER;
|
|
91
|
+
// Behind the front door every organization without a live plan is read for
|
|
92
|
+
// its kind: a team is offered the plan, a personal one is offered a team.
|
|
93
|
+
const free = door && Boolean(tier) && !live;
|
|
90
94
|
const personal = usePersonal(current, free);
|
|
91
95
|
// A SuperAdmin IAM stepped into this organization sees its rooms whatever its
|
|
92
96
|
// plan: support is there to see what the organization has, and what it spends
|
|
93
97
|
// is billed to the operator's own books, never the organization's.
|
|
94
98
|
const supporting = Boolean(current) && assumed() === current;
|
|
95
|
-
const open =
|
|
99
|
+
const open = !asks || live || supporting;
|
|
96
100
|
const { client } = useAi();
|
|
97
101
|
useEffect(() => {
|
|
98
102
|
try {
|
|
@@ -195,19 +199,18 @@ export function Orgs({ children, front = false, forward, signup = false, }) {
|
|
|
195
199
|
}
|
|
196
200
|
if (!current || (members.length > 1 && !picked))
|
|
197
201
|
return _jsx(Pick, { members: members, onPick: choose });
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
//
|
|
201
|
-
//
|
|
202
|
-
//
|
|
203
|
-
//
|
|
204
|
-
//
|
|
202
|
+
if (open)
|
|
203
|
+
return forward ? _jsx(Forward, { to: forward }) : _jsx(_Fragment, { children: _jsx(Held, { veiled: false, children: children }) });
|
|
204
|
+
// IN THE WORKSPACE NOTHING OPENS WITHOUT A LIVE PLAN. Every branch here
|
|
205
|
+
// used to hand the room over when the answer was anything but a plain
|
|
206
|
+
// "free": an error of any kind, a read still in flight, a document with no
|
|
207
|
+
// plan in it. Each was a way in without paying — a refusal, a slow network,
|
|
208
|
+
// or devtools blocking one request all read as permission. The default is the
|
|
209
|
+
// ask, and the room is the exception rather than the fallback.
|
|
205
210
|
if (!tier && !wrong)
|
|
206
211
|
return _jsxs(_Fragment, { children: [_jsx(Held, { veiled: true, children: children }), _jsx(Veil, {})] });
|
|
207
212
|
if (free && personal === null)
|
|
208
213
|
return _jsxs(_Fragment, { children: [_jsx(Held, { veiled: true, children: children }), _jsx(Veil, {})] });
|
|
209
|
-
if (open)
|
|
210
|
-
return forward ? _jsx(Forward, { to: forward }) : _jsx(_Fragment, { children: _jsx(Held, { veiled: false, children: children }) });
|
|
211
214
|
const swap = () => setPicked(false);
|
|
212
215
|
if (door) {
|
|
213
216
|
// A billing OUTAGE is ours; the plan is still the condition.
|
|
@@ -220,9 +223,9 @@ export function Orgs({ children, front = false, forward, signup = false, }) {
|
|
|
220
223
|
}
|
|
221
224
|
return _jsx(Plan, { org: current, members: members, onSwitch: swap });
|
|
222
225
|
}
|
|
223
|
-
//
|
|
224
|
-
//
|
|
225
|
-
return _jsx(Subscribe, { org: current, members: members, onSwitch: swap
|
|
226
|
+
// The workspace's host off its front door: no live plan, or none read, does
|
|
227
|
+
// not open the room.
|
|
228
|
+
return _jsx(Subscribe, { org: current, members: members, onSwitch: swap });
|
|
226
229
|
}
|
|
227
230
|
/**
|
|
228
231
|
* A link that asks to arrive signed in.
|
|
@@ -459,8 +462,8 @@ function CreateDialog({ onClose }) {
|
|
|
459
462
|
function Pick({ members, onPick }) {
|
|
460
463
|
return (_jsx(Page, { label: "Choose an organization", children: _jsxs(Column, { children: [_jsx(Brand, {}), _jsx(Heading, { title: "Choose an organization", lede: _jsx(_Fragment, { children: "Everything you open \u2014 chats, agents, credit \u2014 is this one's." }) }), _jsx(Rule, {}), _jsx(View, { display: "grid", gap: 10, children: members.map((o) => (_jsx(View, { render: "button", onClick: () => onPick(o), items: "flex-start", px: 16, py: 14, rounded: 12, borderWidth: 1, borderColor: "var(--border)", bg: "transparent", cursor: "pointer", children: _jsx(Text, { fontSize: "$4", color: "var(--foreground)", text: "left", children: o }) }, o))) })] }) }));
|
|
461
464
|
}
|
|
462
|
-
/**
|
|
463
|
-
function Subscribe({ org, members, onSwitch,
|
|
465
|
+
/** On the workspace's host, an organization whose plan is not live: it is offered the per-seat Team plan. */
|
|
466
|
+
function Subscribe({ org, members, onSwitch, }) {
|
|
464
467
|
const { plan, price } = usePlan('team');
|
|
465
468
|
const seat = plan?.pricePerUser ? ' / seat' : '';
|
|
466
469
|
return (_jsx(Page, { label: "Subscribe", children: _jsxs(Column, { children: [_jsx(Brand, {}), _jsx(Heading, { title: org, lead: 22.5, lede: plan ? `This organization runs on the ${plan.name} plan at ${price}${seat} / month, and nothing in it works until that plan is live.` : 'Its plan is not live yet.' }), _jsx(Rule, {}), _jsxs(XStack, { gap: 10, flexWrap: "wrap", children: [plan ? (_jsx(Button, { asChild: true, variant: "primary", size: "lg", children: _jsx("a", { href: checkout(plan), children: `Subscribe — ${price}${seat} / month` }) })) : null, members.length > 1 ? (_jsx(Button, { size: "lg", onClick: onSwitch, children: "Switch organization" })) : null] })] }) }));
|
package/dist/Room.js
CHANGED
|
@@ -33,8 +33,9 @@ export function Room({ mode, front = false, children, }) {
|
|
|
33
33
|
if (to)
|
|
34
34
|
return null;
|
|
35
35
|
// A session comes first, then the organization: nothing of the workspace is
|
|
36
|
-
// drawn until the reader has signed in at hanzo.id
|
|
37
|
-
// organization
|
|
36
|
+
// drawn until the reader has signed in at hanzo.id and picked the
|
|
37
|
+
// organization they are working in, and on the workspace's own host until
|
|
38
|
+
// that organization's plan is live (`Orgs`).
|
|
38
39
|
// Going to a room from the apex is going to hanzo.team, in this tab.
|
|
39
40
|
return (_jsx(Orgs, { front: front, children: _jsx(Workspace, { mode: mode, navigate: (route) => {
|
|
40
41
|
// A page of another origin — hanzo.ai's from hanzo.team — is a
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.64",
|
|
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",
|