@hanzo/rooms 0.1.7 → 0.1.8
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/Billing.js +2 -1
- package/dist/Chat.js +2 -1
- package/dist/Drive.js +1 -1
- package/dist/Me.js +2 -1
- package/dist/Orgs.js +2 -1
- package/dist/Settings.js +2 -1
- package/dist/Shell.js +1 -1
- package/dist/lib/pay.d.ts +45 -0
- package/dist/lib/pay.js +59 -0
- package/dist/lib/plans.d.ts +1 -23
- package/dist/lib/plans.js +9 -57
- package/dist/lib/tier.js +1 -1
- package/package.json +1 -1
package/dist/Billing.js
CHANGED
|
@@ -15,7 +15,8 @@ import { Box, Text, XStack } from '@hanzo/ui';
|
|
|
15
15
|
import { useIam } from '@hanzo/iam/react';
|
|
16
16
|
import { formatCents } from '@hanzo/usage';
|
|
17
17
|
import { renewal, useSubscription, useTier } from './lib/tier.js';
|
|
18
|
-
import { payPage
|
|
18
|
+
import { payPage } from './lib/pay.js';
|
|
19
|
+
import { planName } from './lib/plans.js';
|
|
19
20
|
export function Billing() {
|
|
20
21
|
const { isAuthenticated } = useIam();
|
|
21
22
|
const { tier } = useTier(isAuthenticated);
|
package/dist/Chat.js
CHANGED
|
@@ -60,7 +60,8 @@ import { Share } from "./Share.js";
|
|
|
60
60
|
import { useStarred } from "./stars.js";
|
|
61
61
|
import { useModel } from "./model.js";
|
|
62
62
|
import { Enso, nameOf, useEffort } from "./enso.js";
|
|
63
|
-
import { checkoutUrl
|
|
63
|
+
import { checkoutUrl } from './lib/pay.js';
|
|
64
|
+
import { onFree, planName } from './lib/plans.js';
|
|
64
65
|
import { Upgrade, useFree } from './Upgrade.js';
|
|
65
66
|
import { enter, LOGIN } from './lib/destination.js';
|
|
66
67
|
import { first } from './lib/first.js';
|
package/dist/Drive.js
CHANGED
|
@@ -6,7 +6,7 @@ import { Box, Button, Text, View, XStack, YStack } from '@hanzo/ui';
|
|
|
6
6
|
import { useIam, useOrganizations } from '@hanzo/iam/react';
|
|
7
7
|
import { useAi } from './lib/ai.js';
|
|
8
8
|
import { useOpen } from './open.js';
|
|
9
|
-
import { checkoutUrl } from './lib/
|
|
9
|
+
import { checkoutUrl } from './lib/pay.js';
|
|
10
10
|
import { BAD, mix } from './lib/mix.js';
|
|
11
11
|
const blame = (e) => {
|
|
12
12
|
const text = e instanceof Error ? e.message : String(e ?? '');
|
package/dist/Me.js
CHANGED
|
@@ -29,7 +29,8 @@ import { createOrg, say } from './lib/org.js';
|
|
|
29
29
|
import { useTier } from './lib/tier.js';
|
|
30
30
|
import { list } from './lib/list.js';
|
|
31
31
|
import { org as current, orgs, pick, renew, scope, superAdmin } from './lib/session.js';
|
|
32
|
-
import { payPage
|
|
32
|
+
import { payPage } from './lib/pay.js';
|
|
33
|
+
import { planName } from './lib/plans.js';
|
|
33
34
|
import { ENTRY } from './lib/host.js';
|
|
34
35
|
import { SupportPicker } from './Support.js';
|
|
35
36
|
import { BAD } from './lib/mix.js';
|
package/dist/Orgs.js
CHANGED
|
@@ -39,7 +39,8 @@ import { api } from './lib/api.js';
|
|
|
39
39
|
import { usePersonal, useTier } from './lib/tier.js';
|
|
40
40
|
import { ORG, PICKED, assumed, hasSession, org, orgs as claimed, pick, renew, scope } from './lib/session.js';
|
|
41
41
|
import { team as workspace } from './lib/host.js';
|
|
42
|
-
import {
|
|
42
|
+
import { checkoutUrl, money } from './lib/pay.js';
|
|
43
|
+
import { cartUrl, charge, priced, usePlan, usePlans } from './lib/plans.js';
|
|
43
44
|
import { createInvitation, inviteLink } from './lib/invite.js';
|
|
44
45
|
import { countSignup } from './lib/intent.js';
|
|
45
46
|
import { BAD, mix } from './lib/mix.js';
|
package/dist/Settings.js
CHANGED
|
@@ -34,7 +34,8 @@ import { ModelSelector, RESEARCH } from '@hanzo/ui/models';
|
|
|
34
34
|
import { UsagePanel } from '@hanzo/usage/panel';
|
|
35
35
|
import { Catalog } from './Directory.js';
|
|
36
36
|
import { useModel } from './model.js';
|
|
37
|
-
import { payPage
|
|
37
|
+
import { payPage } from './lib/pay.js';
|
|
38
|
+
import { planName } from './lib/plans.js';
|
|
38
39
|
import { api } from './lib/api.js';
|
|
39
40
|
import { renewal, useSubscription, useTier } from './lib/tier.js';
|
|
40
41
|
import { sku, spendShown, useLimits } from './lib/limits.js';
|
package/dist/Shell.js
CHANGED
|
@@ -74,7 +74,7 @@ import { Find } from "./Find.js";
|
|
|
74
74
|
import { Account } from "./Account.js";
|
|
75
75
|
import { ModeMark } from "./ModeMark.js";
|
|
76
76
|
import { called } from "./team.js";
|
|
77
|
-
import { checkoutUrl } from './lib/
|
|
77
|
+
import { checkoutUrl } from './lib/pay.js';
|
|
78
78
|
/** Tabs: the terminals, at their own host. */
|
|
79
79
|
const TABS = "https://tabs.hanzo.ai/app";
|
|
80
80
|
/** Where a plan is chosen. `lib/plans` owns the address; this is the door. */
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pay site's addresses and money as a sentence says it.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from `plans.ts`, which reads the bundled plan catalogue: a page
|
|
5
|
+
* that only links the pay page or prints a price carries none of it.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Where money changes hands: the checkout, mounted at hanzo.ai/pay so a buyer
|
|
9
|
+
* never leaves the site. It is hanzo-inc/pay, served from the same export
|
|
10
|
+
* pay.hanzo.ai was; that host now redirects here.
|
|
11
|
+
*
|
|
12
|
+
* billing.hanzo.ai has no route at the edge and answers 404, and /billing on
|
|
13
|
+
* this site is the Billing PRODUCT's page — a reader sent there to buy a plan
|
|
14
|
+
* lands on marketing. /pay takes `?plan=`, `?interval=`, `?returnUrl=` and
|
|
15
|
+
* `?org=`, and comes back. Every "add credit" and "billing" link reads this one
|
|
16
|
+
* address. Absolute, because this export also serves cloud.hanzo.ai and
|
|
17
|
+
* hanzo.bot, and the checkout lives on hanzo.ai.
|
|
18
|
+
*/
|
|
19
|
+
export declare const BILLING_URL = "https://hanzo.ai/pay";
|
|
20
|
+
/**
|
|
21
|
+
* The checkout address, opened on a plan when one is named, and returning to
|
|
22
|
+
* `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
|
|
23
|
+
* site's receipt with no way into what they bought.
|
|
24
|
+
*
|
|
25
|
+
* ONE writer for this address. It was spelled out in three places — the
|
|
26
|
+
* personal ladder, the business strip and the /account hand-off — and a plan id
|
|
27
|
+
* only selects the card a reader clicked if every writer spells the query the
|
|
28
|
+
* same way.
|
|
29
|
+
*/
|
|
30
|
+
export declare function checkoutUrl(id?: string, back?: string): string;
|
|
31
|
+
/**
|
|
32
|
+
* A page on the pay site, for the organization this browser works in.
|
|
33
|
+
*
|
|
34
|
+
* pay charges and reads the ledger it is named, and it can only offer the ones
|
|
35
|
+
* the token lists; which of them this workspace is in is a fact only this site
|
|
36
|
+
* holds. `?org=` carries it across, and pay honours it only while the token
|
|
37
|
+
* offers it. Call it at the moment of leaving: the organization lives in this
|
|
38
|
+
* browser and moves with the switcher.
|
|
39
|
+
*/
|
|
40
|
+
export declare function payPage(path?: string): string;
|
|
41
|
+
/** The pay address with its query, written in one place for both callers above. */
|
|
42
|
+
export declare function payUrl(path: string, query: Record<string, string | null | undefined>): string;
|
|
43
|
+
export declare const dollars: (n: number) => string;
|
|
44
|
+
/** Money as a sentence says it: whole dollars bare, anything else to the cent — $20, $16.67. */
|
|
45
|
+
export declare const money: (n: number) => string;
|
package/dist/lib/pay.js
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The pay site's addresses and money as a sentence says it.
|
|
3
|
+
*
|
|
4
|
+
* Kept apart from `plans.ts`, which reads the bundled plan catalogue: a page
|
|
5
|
+
* that only links the pay page or prints a price carries none of it.
|
|
6
|
+
*/
|
|
7
|
+
import { org } from "./session.js";
|
|
8
|
+
/**
|
|
9
|
+
* Where money changes hands: the checkout, mounted at hanzo.ai/pay so a buyer
|
|
10
|
+
* never leaves the site. It is hanzo-inc/pay, served from the same export
|
|
11
|
+
* pay.hanzo.ai was; that host now redirects here.
|
|
12
|
+
*
|
|
13
|
+
* billing.hanzo.ai has no route at the edge and answers 404, and /billing on
|
|
14
|
+
* this site is the Billing PRODUCT's page — a reader sent there to buy a plan
|
|
15
|
+
* lands on marketing. /pay takes `?plan=`, `?interval=`, `?returnUrl=` and
|
|
16
|
+
* `?org=`, and comes back. Every "add credit" and "billing" link reads this one
|
|
17
|
+
* address. Absolute, because this export also serves cloud.hanzo.ai and
|
|
18
|
+
* hanzo.bot, and the checkout lives on hanzo.ai.
|
|
19
|
+
*/
|
|
20
|
+
export const BILLING_URL = "https://hanzo.ai/pay";
|
|
21
|
+
/**
|
|
22
|
+
* The checkout address, opened on a plan when one is named, and returning to
|
|
23
|
+
* `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
|
|
24
|
+
* site's receipt with no way into what they bought.
|
|
25
|
+
*
|
|
26
|
+
* ONE writer for this address. It was spelled out in three places — the
|
|
27
|
+
* personal ladder, the business strip and the /account hand-off — and a plan id
|
|
28
|
+
* only selects the card a reader clicked if every writer spells the query the
|
|
29
|
+
* same way.
|
|
30
|
+
*/
|
|
31
|
+
export function checkoutUrl(id, back) {
|
|
32
|
+
return payUrl(id ? "/cart" : "/", { plan: id, returnUrl: back });
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* A page on the pay site, for the organization this browser works in.
|
|
36
|
+
*
|
|
37
|
+
* pay charges and reads the ledger it is named, and it can only offer the ones
|
|
38
|
+
* the token lists; which of them this workspace is in is a fact only this site
|
|
39
|
+
* holds. `?org=` carries it across, and pay honours it only while the token
|
|
40
|
+
* offers it. Call it at the moment of leaving: the organization lives in this
|
|
41
|
+
* browser and moves with the switcher.
|
|
42
|
+
*/
|
|
43
|
+
export function payPage(path = "/") {
|
|
44
|
+
return payUrl(path, { org: org() });
|
|
45
|
+
}
|
|
46
|
+
/** The pay address with its query, written in one place for both callers above. */
|
|
47
|
+
export function payUrl(path, query) {
|
|
48
|
+
const q = new URLSearchParams();
|
|
49
|
+
for (const [k, v] of Object.entries(query))
|
|
50
|
+
if (v)
|
|
51
|
+
q.set(k, v);
|
|
52
|
+
const s = q.toString();
|
|
53
|
+
if (path === "/" && !s)
|
|
54
|
+
return BILLING_URL;
|
|
55
|
+
return `${BILLING_URL}${path}${s ? `?${s}` : ""}`;
|
|
56
|
+
}
|
|
57
|
+
export const dollars = (n) => `$${n.toFixed(2)}`;
|
|
58
|
+
/** Money as a sentence says it: whole dollars bare, anything else to the cent — $20, $16.67. */
|
|
59
|
+
export const money = (n) => (Number.isInteger(n) ? `$${n.toLocaleString("en-US")}` : dollars(n));
|
package/dist/lib/plans.d.ts
CHANGED
|
@@ -69,27 +69,6 @@ export interface SubscriptionPlan {
|
|
|
69
69
|
checkoutUrl?: string;
|
|
70
70
|
checkoutId?: string;
|
|
71
71
|
}
|
|
72
|
-
/**
|
|
73
|
-
* The checkout address, opened on a plan when one is named, and returning to
|
|
74
|
-
* `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
|
|
75
|
-
* site's receipt with no way into what they bought.
|
|
76
|
-
*
|
|
77
|
-
* ONE writer for this address. It was spelled out in three places — the
|
|
78
|
-
* personal ladder, the business strip and the /account hand-off — and a plan id
|
|
79
|
-
* only selects the card a reader clicked if every writer spells the query the
|
|
80
|
-
* same way.
|
|
81
|
-
*/
|
|
82
|
-
export declare function checkoutUrl(id?: string, back?: string): string;
|
|
83
|
-
/**
|
|
84
|
-
* A page on the pay site, for the organization this browser works in.
|
|
85
|
-
*
|
|
86
|
-
* pay charges and reads the ledger it is named, and it can only offer the ones
|
|
87
|
-
* the token lists; which of them this workspace is in is a fact only this site
|
|
88
|
-
* holds. `?org=` carries it across, and pay honours it only while the token
|
|
89
|
-
* offers it. Call it at the moment of leaving: the organization lives in this
|
|
90
|
-
* browser and moves with the switcher.
|
|
91
|
-
*/
|
|
92
|
-
export declare function payPage(path?: string): string;
|
|
93
72
|
/**
|
|
94
73
|
* The checkout a plan's CTA opens.
|
|
95
74
|
*
|
|
@@ -122,6 +101,7 @@ export declare function fallbackPlans(category: string): SubscriptionPlan[];
|
|
|
122
101
|
* a reader with no build in between.
|
|
123
102
|
*/
|
|
124
103
|
export declare function useCatalog(): SubscriptionPlan[];
|
|
104
|
+
/** Dollars as a price is written: two places, always, so a card and a button agree. */
|
|
125
105
|
/** The row an organization runs on, priced. */
|
|
126
106
|
export interface OrgPlan {
|
|
127
107
|
plan: SubscriptionPlan | null;
|
|
@@ -156,8 +136,6 @@ export declare function usePlan(category?: string): OrgPlan;
|
|
|
156
136
|
export declare function usePlans(category: string): SubscriptionPlan[];
|
|
157
137
|
/** A row priced the way every surface writes it. */
|
|
158
138
|
export declare function priced(plan: SubscriptionPlan | null): OrgPlan;
|
|
159
|
-
/** Money as a sentence says it: whole dollars bare, anything else to the cent — $20, $16.67. */
|
|
160
|
-
export declare const money: (n: number) => string;
|
|
161
139
|
/**
|
|
162
140
|
* What one term of a plan charges, in dollars, or null where the catalog sells
|
|
163
141
|
* no such term. A month is `priceMonthly`. A year is the total the catalog
|
package/dist/lib/plans.js
CHANGED
|
@@ -33,56 +33,7 @@ import { useEffect, useMemo, useState } from "react";
|
|
|
33
33
|
import { subscriptionPlans } from "@hanzo/plans";
|
|
34
34
|
import { where } from "../where.js";
|
|
35
35
|
import { api } from "./api.js";
|
|
36
|
-
import {
|
|
37
|
-
/**
|
|
38
|
-
* Where money changes hands: the checkout, mounted at hanzo.ai/pay so a buyer
|
|
39
|
-
* never leaves the site. It is hanzo-inc/pay, served from the same export
|
|
40
|
-
* pay.hanzo.ai was; that host now redirects here.
|
|
41
|
-
*
|
|
42
|
-
* billing.hanzo.ai has no route at the edge and answers 404, and /billing on
|
|
43
|
-
* this site is the Billing PRODUCT's page — a reader sent there to buy a plan
|
|
44
|
-
* lands on marketing. /pay takes `?plan=`, `?interval=`, `?returnUrl=` and
|
|
45
|
-
* `?org=`, and comes back. Every "add credit" and "billing" link reads this one
|
|
46
|
-
* address. Absolute, because this export also serves cloud.hanzo.ai and
|
|
47
|
-
* hanzo.bot, and the checkout lives on hanzo.ai.
|
|
48
|
-
*/
|
|
49
|
-
const BILLING_URL = "https://hanzo.ai/pay";
|
|
50
|
-
/**
|
|
51
|
-
* The checkout address, opened on a plan when one is named, and returning to
|
|
52
|
-
* `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
|
|
53
|
-
* site's receipt with no way into what they bought.
|
|
54
|
-
*
|
|
55
|
-
* ONE writer for this address. It was spelled out in three places — the
|
|
56
|
-
* personal ladder, the business strip and the /account hand-off — and a plan id
|
|
57
|
-
* only selects the card a reader clicked if every writer spells the query the
|
|
58
|
-
* same way.
|
|
59
|
-
*/
|
|
60
|
-
export function checkoutUrl(id, back) {
|
|
61
|
-
return payUrl(id ? "/cart" : "/", { plan: id, returnUrl: back });
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* A page on the pay site, for the organization this browser works in.
|
|
65
|
-
*
|
|
66
|
-
* pay charges and reads the ledger it is named, and it can only offer the ones
|
|
67
|
-
* the token lists; which of them this workspace is in is a fact only this site
|
|
68
|
-
* holds. `?org=` carries it across, and pay honours it only while the token
|
|
69
|
-
* offers it. Call it at the moment of leaving: the organization lives in this
|
|
70
|
-
* browser and moves with the switcher.
|
|
71
|
-
*/
|
|
72
|
-
export function payPage(path = "/") {
|
|
73
|
-
return payUrl(path, { org: org() });
|
|
74
|
-
}
|
|
75
|
-
/** The pay address with its query, written in one place for both callers above. */
|
|
76
|
-
function payUrl(path, query) {
|
|
77
|
-
const q = new URLSearchParams();
|
|
78
|
-
for (const [k, v] of Object.entries(query))
|
|
79
|
-
if (v)
|
|
80
|
-
q.set(k, v);
|
|
81
|
-
const s = q.toString();
|
|
82
|
-
if (path === "/" && !s)
|
|
83
|
-
return BILLING_URL;
|
|
84
|
-
return `${BILLING_URL}${path}${s ? `?${s}` : ""}`;
|
|
85
|
-
}
|
|
36
|
+
import { BILLING_URL, checkoutUrl, dollars, money, payUrl } from "./pay.js";
|
|
86
37
|
/**
|
|
87
38
|
* The checkout a plan's CTA opens.
|
|
88
39
|
*
|
|
@@ -205,8 +156,6 @@ export function useCatalog() {
|
|
|
205
156
|
}, []);
|
|
206
157
|
return rows;
|
|
207
158
|
}
|
|
208
|
-
/** Dollars as a price is written: two places, always, so a card and a button agree. */
|
|
209
|
-
const dollars = (n) => `$${n.toFixed(2)}`;
|
|
210
159
|
/**
|
|
211
160
|
* Which plan an organization runs on, and what it costs. A plan is a
|
|
212
161
|
* subscription with usage limits; it mints no credit, so nothing here says it does.
|
|
@@ -242,8 +191,6 @@ export function usePlans(category) {
|
|
|
242
191
|
export function priced(plan) {
|
|
243
192
|
return { plan, price: plan ? dollars(plan.priceMonthly ?? 0) : "—" };
|
|
244
193
|
}
|
|
245
|
-
/** Money as a sentence says it: whole dollars bare, anything else to the cent — $20, $16.67. */
|
|
246
|
-
export const money = (n) => (Number.isInteger(n) ? `$${n.toLocaleString("en-US")}` : dollars(n));
|
|
247
194
|
/**
|
|
248
195
|
* What one term of a plan charges, in dollars, or null where the catalog sells
|
|
249
196
|
* no such term. A month is `priceMonthly`. A year is the total the catalog
|
|
@@ -275,11 +222,16 @@ export function saving(plan) {
|
|
|
275
222
|
return null;
|
|
276
223
|
return Math.round((1 - year / (12 * month)) * 100);
|
|
277
224
|
}
|
|
278
|
-
/**
|
|
279
|
-
|
|
225
|
+
/**
|
|
226
|
+
* The models the Free plan runs, as @hanzo/plans states them: `ai.models` on
|
|
227
|
+
* the `free` row. Read on first ask and not at import, so a page that only
|
|
228
|
+
* formats money or names the pay page carries none of the catalogue.
|
|
229
|
+
*/
|
|
230
|
+
let freeModels = null;
|
|
280
231
|
/** Whether the Free plan runs a model: one its row names, or any `:free` route. */
|
|
281
232
|
export function onFree(model) {
|
|
282
|
-
|
|
233
|
+
freeModels ??= new Set(subscriptionPlans.find((p) => p.id === "free")?.entitlements?.["ai.models"] ?? []);
|
|
234
|
+
return freeModels.has(model) || model.endsWith(":free");
|
|
283
235
|
}
|
|
284
236
|
/**
|
|
285
237
|
* The catalog's own name for a plan slug — "max-20x" reads as "Max 20x" —
|
package/dist/lib/tier.js
CHANGED
|
@@ -25,7 +25,7 @@ import { useCallback, useEffect, useState } from 'react';
|
|
|
25
25
|
import { api } from './api.js';
|
|
26
26
|
import { bearer, org, orgs, scope } from './session.js';
|
|
27
27
|
import { list } from './list.js';
|
|
28
|
-
import { money } from './
|
|
28
|
+
import { money } from './pay.js';
|
|
29
29
|
import { date } from './limits.js';
|
|
30
30
|
/** An error that names the status, for `say()` to turn into a sentence. */
|
|
31
31
|
const refusal = (status, message) => Object.assign(new Error(message), { status });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/rooms",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
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",
|