@hanzo/rooms 0.1.0

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.
Files changed (235) hide show
  1. package/LICENSE-APACHE +205 -0
  2. package/LICENSE-MIT +21 -0
  3. package/README.md +23 -0
  4. package/dist/Account.d.ts +8 -0
  5. package/dist/Account.js +58 -0
  6. package/dist/Beluga.d.ts +12 -0
  7. package/dist/Beluga.js +152 -0
  8. package/dist/Billing.d.ts +1 -0
  9. package/dist/Billing.js +31 -0
  10. package/dist/Board.d.ts +9 -0
  11. package/dist/Board.js +447 -0
  12. package/dist/Boxes.d.ts +1 -0
  13. package/dist/Boxes.js +173 -0
  14. package/dist/CalScheduler.d.ts +15 -0
  15. package/dist/CalScheduler.js +196 -0
  16. package/dist/Chat.d.ts +35 -0
  17. package/dist/Chat.js +1049 -0
  18. package/dist/Column.d.ts +15 -0
  19. package/dist/Column.js +88 -0
  20. package/dist/Contacts.d.ts +1 -0
  21. package/dist/Contacts.js +301 -0
  22. package/dist/Directory.d.ts +24 -0
  23. package/dist/Directory.js +356 -0
  24. package/dist/Drive.d.ts +2 -0
  25. package/dist/Drive.js +466 -0
  26. package/dist/Find.d.ts +7 -0
  27. package/dist/Find.js +82 -0
  28. package/dist/Guide.d.ts +6 -0
  29. package/dist/Guide.js +272 -0
  30. package/dist/Home.d.ts +39 -0
  31. package/dist/Home.js +306 -0
  32. package/dist/Inbox.d.ts +9 -0
  33. package/dist/Inbox.js +193 -0
  34. package/dist/Market.d.ts +3 -0
  35. package/dist/Market.js +149 -0
  36. package/dist/Me.d.ts +27 -0
  37. package/dist/Me.js +251 -0
  38. package/dist/Meet.d.ts +9 -0
  39. package/dist/Meet.js +370 -0
  40. package/dist/ModeMark.d.ts +8 -0
  41. package/dist/ModeMark.js +18 -0
  42. package/dist/OrgSwitcher.d.ts +31 -0
  43. package/dist/OrgSwitcher.js +120 -0
  44. package/dist/Orgs.d.ts +10 -0
  45. package/dist/Orgs.js +582 -0
  46. package/dist/Profile.d.ts +4 -0
  47. package/dist/Profile.js +67 -0
  48. package/dist/Prose.d.ts +5 -0
  49. package/dist/Prose.js +111 -0
  50. package/dist/ProviderMark.d.ts +17 -0
  51. package/dist/ProviderMark.js +277 -0
  52. package/dist/Recents.d.ts +10 -0
  53. package/dist/Recents.js +91 -0
  54. package/dist/RightPane.d.ts +13 -0
  55. package/dist/RightPane.js +426 -0
  56. package/dist/Room.d.ts +8 -0
  57. package/dist/Room.js +50 -0
  58. package/dist/Scene.d.ts +12 -0
  59. package/dist/Scene.js +105 -0
  60. package/dist/Settings.d.ts +46 -0
  61. package/dist/Settings.js +321 -0
  62. package/dist/Setup.d.ts +1 -0
  63. package/dist/Setup.js +36 -0
  64. package/dist/Share.d.ts +3 -0
  65. package/dist/Share.js +130 -0
  66. package/dist/Shared.d.ts +1 -0
  67. package/dist/Shared.js +113 -0
  68. package/dist/Shell.d.ts +63 -0
  69. package/dist/Shell.js +1225 -0
  70. package/dist/Start.d.ts +1 -0
  71. package/dist/Start.js +96 -0
  72. package/dist/Support.d.ts +14 -0
  73. package/dist/Support.js +122 -0
  74. package/dist/Talk.d.ts +4 -0
  75. package/dist/Talk.js +107 -0
  76. package/dist/Upgrade.d.ts +11 -0
  77. package/dist/Upgrade.js +75 -0
  78. package/dist/Usage.d.ts +1 -0
  79. package/dist/Usage.js +21 -0
  80. package/dist/Vibe.d.ts +2 -0
  81. package/dist/Vibe.js +188 -0
  82. package/dist/Work.d.ts +12 -0
  83. package/dist/Work.js +256 -0
  84. package/dist/bots/Bots.d.ts +2 -0
  85. package/dist/bots/Bots.js +456 -0
  86. package/dist/bots/Lights.d.ts +8 -0
  87. package/dist/bots/Lights.js +13 -0
  88. package/dist/bots/api.d.ts +120 -0
  89. package/dist/bots/api.js +75 -0
  90. package/dist/bots/face.d.ts +5 -0
  91. package/dist/bots/face.js +13 -0
  92. package/dist/bots/ink.d.ts +7 -0
  93. package/dist/bots/ink.js +29 -0
  94. package/dist/bots/kit.d.ts +113 -0
  95. package/dist/bots/kit.js +43 -0
  96. package/dist/bots/runtime.d.ts +4 -0
  97. package/dist/bots/runtime.js +326 -0
  98. package/dist/card.d.ts +52 -0
  99. package/dist/card.js +52 -0
  100. package/dist/cast.d.ts +143 -0
  101. package/dist/cast.js +251 -0
  102. package/dist/connect.d.ts +29 -0
  103. package/dist/connect.js +64 -0
  104. package/dist/contacts-store.d.ts +111 -0
  105. package/dist/contacts-store.js +276 -0
  106. package/dist/conversations.d.ts +54 -0
  107. package/dist/conversations.js +98 -0
  108. package/dist/copy.d.ts +23 -0
  109. package/dist/copy.js +39 -0
  110. package/dist/crew.d.ts +36 -0
  111. package/dist/crew.js +304 -0
  112. package/dist/dev.d.ts +3 -0
  113. package/dist/dev.js +102 -0
  114. package/dist/enso.d.ts +70 -0
  115. package/dist/enso.js +112 -0
  116. package/dist/failure.d.ts +57 -0
  117. package/dist/failure.js +143 -0
  118. package/dist/ground.d.ts +32 -0
  119. package/dist/ground.js +32 -0
  120. package/dist/host.d.ts +76 -0
  121. package/dist/host.js +76 -0
  122. package/dist/index.d.ts +14 -0
  123. package/dist/index.js +12 -0
  124. package/dist/kept.d.ts +5 -0
  125. package/dist/kept.js +27 -0
  126. package/dist/lib/account.d.ts +49 -0
  127. package/dist/lib/account.js +229 -0
  128. package/dist/lib/ai.d.ts +46 -0
  129. package/dist/lib/ai.js +140 -0
  130. package/dist/lib/api.d.ts +43 -0
  131. package/dist/lib/api.js +62 -0
  132. package/dist/lib/bare.d.ts +9 -0
  133. package/dist/lib/bare.js +7 -0
  134. package/dist/lib/coding.d.ts +105 -0
  135. package/dist/lib/coding.js +87 -0
  136. package/dist/lib/destination.d.ts +102 -0
  137. package/dist/lib/destination.js +260 -0
  138. package/dist/lib/durable.d.ts +66 -0
  139. package/dist/lib/durable.js +107 -0
  140. package/dist/lib/first.d.ts +11 -0
  141. package/dist/lib/first.js +23 -0
  142. package/dist/lib/home.d.ts +61 -0
  143. package/dist/lib/home.js +54 -0
  144. package/dist/lib/host.d.ts +104 -0
  145. package/dist/lib/host.js +132 -0
  146. package/dist/lib/hostname.d.ts +1 -0
  147. package/dist/lib/hostname.js +14 -0
  148. package/dist/lib/hydrated.d.ts +1 -0
  149. package/dist/lib/hydrated.js +20 -0
  150. package/dist/lib/integrations.d.ts +21 -0
  151. package/dist/lib/integrations.js +1 -0
  152. package/dist/lib/intent.d.ts +6 -0
  153. package/dist/lib/intent.js +71 -0
  154. package/dist/lib/invite.d.ts +155 -0
  155. package/dist/lib/invite.js +245 -0
  156. package/dist/lib/limits.d.ts +55 -0
  157. package/dist/lib/limits.js +119 -0
  158. package/dist/lib/list.d.ts +9 -0
  159. package/dist/lib/list.js +11 -0
  160. package/dist/lib/mark.d.ts +13 -0
  161. package/dist/lib/mark.js +85 -0
  162. package/dist/lib/mix.d.ts +22 -0
  163. package/dist/lib/mix.js +22 -0
  164. package/dist/lib/models.d.ts +27 -0
  165. package/dist/lib/models.js +106 -0
  166. package/dist/lib/org.d.ts +109 -0
  167. package/dist/lib/org.js +140 -0
  168. package/dist/lib/path.d.ts +9 -0
  169. package/dist/lib/path.js +29 -0
  170. package/dist/lib/plans.d.ts +193 -0
  171. package/dist/lib/plans.js +310 -0
  172. package/dist/lib/prose.d.ts +13 -0
  173. package/dist/lib/prose.js +62 -0
  174. package/dist/lib/reach.d.ts +17 -0
  175. package/dist/lib/reach.js +70 -0
  176. package/dist/lib/rooms.json +23 -0
  177. package/dist/lib/served.d.ts +20 -0
  178. package/dist/lib/served.js +92 -0
  179. package/dist/lib/session.d.ts +211 -0
  180. package/dist/lib/session.js +493 -0
  181. package/dist/lib/share.d.ts +131 -0
  182. package/dist/lib/share.js +216 -0
  183. package/dist/lib/signout.d.ts +14 -0
  184. package/dist/lib/signout.js +40 -0
  185. package/dist/lib/tags.d.ts +27 -0
  186. package/dist/lib/tags.js +46 -0
  187. package/dist/lib/tap.d.ts +17 -0
  188. package/dist/lib/tap.js +9 -0
  189. package/dist/lib/tier.d.ts +115 -0
  190. package/dist/lib/tier.js +207 -0
  191. package/dist/lib/tiers.d.ts +9 -0
  192. package/dist/lib/tiers.js +141 -0
  193. package/dist/lib/todo.d.ts +125 -0
  194. package/dist/lib/todo.js +379 -0
  195. package/dist/look.d.ts +1 -0
  196. package/dist/look.js +21 -0
  197. package/dist/meters.d.ts +8 -0
  198. package/dist/meters.js +31 -0
  199. package/dist/model.d.ts +4 -0
  200. package/dist/model.js +44 -0
  201. package/dist/network.d.ts +64 -0
  202. package/dist/network.js +216 -0
  203. package/dist/open.d.ts +81 -0
  204. package/dist/open.js +149 -0
  205. package/dist/pane.d.ts +92 -0
  206. package/dist/pane.js +231 -0
  207. package/dist/progress.d.ts +46 -0
  208. package/dist/progress.js +51 -0
  209. package/dist/recent.d.ts +67 -0
  210. package/dist/recent.js +161 -0
  211. package/dist/rooms.d.ts +131 -0
  212. package/dist/rooms.js +195 -0
  213. package/dist/roster.d.ts +28 -0
  214. package/dist/roster.js +70 -0
  215. package/dist/span.d.ts +14 -0
  216. package/dist/span.js +50 -0
  217. package/dist/speech.d.ts +44 -0
  218. package/dist/speech.js +229 -0
  219. package/dist/stars.d.ts +16 -0
  220. package/dist/stars.js +75 -0
  221. package/dist/tabs.d.ts +26 -0
  222. package/dist/tabs.js +25 -0
  223. package/dist/team.d.ts +11 -0
  224. package/dist/team.gen.d.ts +10 -0
  225. package/dist/team.gen.js +11 -0
  226. package/dist/team.js +30 -0
  227. package/dist/tools.d.ts +35 -0
  228. package/dist/tools.js +143 -0
  229. package/dist/tours.d.ts +24 -0
  230. package/dist/tours.js +311 -0
  231. package/dist/waiting.d.ts +15 -0
  232. package/dist/waiting.js +17 -0
  233. package/dist/where.d.ts +54 -0
  234. package/dist/where.js +14 -0
  235. package/package.json +108 -0
@@ -0,0 +1,57 @@
1
+ /** Whether the store answered and the answer was no — exported so a surface can
2
+ * offer the way past a refusal rather than only describing it. */
3
+ export declare const refused: (error: unknown) => boolean;
4
+ /**
5
+ * A sentence about `subject` — "your drive", "this board" — naming what a
6
+ * reader can do next. Never the caught text: an error written for an operator
7
+ * is not an answer for a reader.
8
+ */
9
+ export declare function say(error: unknown, subject: string, act?: 'read' | 'save'): string;
10
+ /**
11
+ * The reader's version of a failure, keeping what the store said when that is
12
+ * an answer.
13
+ *
14
+ * A gateway that refuses over credit, a context that ran long, a model nobody
15
+ * serves — each of those is the reader's own situation, stated by the only
16
+ * thing that knows it, and translating them away would leave a room saying
17
+ * nothing where it could have said the one useful thing. A gateway that is not
18
+ * there, or one that refused the account, is the estate talking to itself; that
19
+ * half is replaced.
20
+ */
21
+ export declare function plainly(error: unknown, subject: string): string;
22
+ /**
23
+ * Whether a refusal asks for a plan, and the checkout it names.
24
+ *
25
+ * The gateway refuses a model the plan does not include with 402
26
+ * `plan_required`, a Free caller whose share is spent with 402
27
+ * `allowance_spent`, and a free request the shared pool cannot serve with 429
28
+ * `pool_busy` or `pool_exhausted`, each with an `upgrade_url`. The code decides,
29
+ * never the sentence. The address is kept only when it is an https page on
30
+ * hanzo.ai or one of its hosts; any other leaves `href` empty and the caller
31
+ * builds its own.
32
+ */
33
+ export declare function planRequired(error: unknown): {
34
+ href?: string;
35
+ } | null;
36
+ /** A plan holder's spent window. */
37
+ export interface Cap {
38
+ limit: 'session' | 'day';
39
+ /** When it opens again, RFC 3339. */
40
+ resets: string | null;
41
+ /** The next plan's checkout, on hanzo.ai only. Absent at the top plan. */
42
+ href?: string;
43
+ }
44
+ /**
45
+ * Whether a refusal is a plan's usage limit, and which window.
46
+ *
47
+ * A paid plan is a subscription with limits: a spent session or day comes back
48
+ * 429 `usage_cap_exceeded` naming the window, its reset and, below the top
49
+ * plan, an `upgrade_url`. The month refuses nothing — Enso and Zen keep
50
+ * answering — so no other window is a cap. The code decides, never the
51
+ * sentence, and the address is kept by the rule `planRequired` keeps.
52
+ */
53
+ export declare function capped(error: unknown): Cap | null;
54
+ /** The family a model id belongs to, as a reader knows it, or '' for one outside them. */
55
+ export declare const familyOf: (id: string) => string;
56
+ /** What the server said about a failure, for the detail folded under the plain line. */
57
+ export declare const detail: (error: unknown) => string;
@@ -0,0 +1,143 @@
1
+ 'use client';
2
+ // What to tell a reader when a room's store does not answer.
3
+ //
4
+ // The rooms used to print the error they caught, which on a store that is down
5
+ // reads "mount /v1/s3: no instance running". That says nothing a reader can act
6
+ // on — it names a mount and an instance, neither of which is theirs — and it
7
+ // puts the shape of the estate on a public page. The detail is still in the
8
+ // network tab, where the person who can act on it is looking.
9
+ //
10
+ // ONE FUNCTION, because every room owes the same three answers and three copies
11
+ // would drift into three vocabularies for one event.
12
+ import { told } from './lib/reach.js';
13
+ /**
14
+ * THE STATUS, WHERE THE FAILURE CARRIES ONE.
15
+ *
16
+ * `@hanzo/ai`'s APIError publishes `status` as a number, and a number is a fact
17
+ * — while the message beside it is prose the SDK is free to improve. It did:
18
+ * 0.6.16 added a table answering 503 with "The service is not running right
19
+ * now.", which reads the same to a person and matches none of the patterns
20
+ * below, so every downed store fell through to the flat "Could not read" and
21
+ * the rooms stopped saying that nothing had been lost. Reading the status first
22
+ * is what makes this survive the next rewording.
23
+ */
24
+ const status = (e) => {
25
+ const s = e?.status;
26
+ return typeof s === 'number' && Number.isFinite(s) ? s : null;
27
+ };
28
+ /** True where a failure is the store being absent rather than the reader. The
29
+ * text is still read, because a network failure raises before any status. */
30
+ const absent = (text) => /no instance running|not running|service unavailable|503|econnrefused|failed to fetch|network/i.test(text);
31
+ /**
32
+ * True where the answer was no, whoever said it.
33
+ *
34
+ * Three vocabularies for one event. The gateway says 401 "authentication
35
+ * required" on a turn and 403 "a validated principal is required" on a read,
36
+ * and the SDK raises before sending at all when it has no credential to send
37
+ * with. A reader meets the same wall in every case, so all three read as one.
38
+ */
39
+ const barred = (text) => /401|403|forbidden|unauthori[sz]ed|not authori[sz]ed|authentication required|validated principal|permission|serve anonymous|anonymous completions/i.test(text);
40
+ /** Whether the store answered and the answer was no — exported so a surface can
41
+ * offer the way past a refusal rather than only describing it. */
42
+ export const refused = (error) => {
43
+ const code = status(error);
44
+ if (code === 401 || code === 403)
45
+ return true;
46
+ return barred(error instanceof Error ? error.message : String(error ?? ''));
47
+ };
48
+ /**
49
+ * A sentence about `subject` — "your drive", "this board" — naming what a
50
+ * reader can do next. Never the caught text: an error written for an operator
51
+ * is not an answer for a reader.
52
+ */
53
+ export function say(error, subject, act = 'read') {
54
+ const text = error instanceof Error ? error.message : String(error ?? '');
55
+ const code = status(error);
56
+ // VERB FIRST, so the subject's number never has to agree with anything. Said
57
+ // subject-first, "your projects is not answering" is what a plural name gets,
58
+ // and every caller then has to remember to phrase its subject singular.
59
+ if (code === 502 || code === 503 || code === 504 || absent(text))
60
+ return `Could not reach ${subject}. Nothing has been lost — try again shortly.`;
61
+ if (code === 401 || code === 403 || barred(text))
62
+ return act === 'save'
63
+ ? `This account cannot change ${subject}.`
64
+ : `This account cannot open ${subject}.`;
65
+ return act === 'save' ? `Could not save ${subject}.` : `Could not read ${subject}.`;
66
+ }
67
+ /**
68
+ * The reader's version of a failure, keeping what the store said when that is
69
+ * an answer.
70
+ *
71
+ * A gateway that refuses over credit, a context that ran long, a model nobody
72
+ * serves — each of those is the reader's own situation, stated by the only
73
+ * thing that knows it, and translating them away would leave a room saying
74
+ * nothing where it could have said the one useful thing. A gateway that is not
75
+ * there, or one that refused the account, is the estate talking to itself; that
76
+ * half is replaced.
77
+ */
78
+ export function plainly(error, subject) {
79
+ const text = error instanceof Error ? error.message : String(error ?? '');
80
+ return absent(text) || barred(text) ? say(error, subject) : told(error) ?? text;
81
+ }
82
+ /**
83
+ * The refusals a plan lifts, by the status each arrives with: a model the plan
84
+ * does not include, and the Free plan's two limits — a person's own share of
85
+ * the pool spent for the window, and the pool every free user shares used up.
86
+ */
87
+ const LIFTED = {
88
+ plan_required: 402,
89
+ allowance_spent: 402,
90
+ pool_busy: 429,
91
+ pool_exhausted: 429,
92
+ };
93
+ /**
94
+ * Whether a refusal asks for a plan, and the checkout it names.
95
+ *
96
+ * The gateway refuses a model the plan does not include with 402
97
+ * `plan_required`, a Free caller whose share is spent with 402
98
+ * `allowance_spent`, and a free request the shared pool cannot serve with 429
99
+ * `pool_busy` or `pool_exhausted`, each with an `upgrade_url`. The code decides,
100
+ * never the sentence. The address is kept only when it is an https page on
101
+ * hanzo.ai or one of its hosts; any other leaves `href` empty and the caller
102
+ * builds its own.
103
+ */
104
+ export function planRequired(error) {
105
+ const said = error?.body?.error;
106
+ const code = typeof said?.code === 'string' ? said.code : '';
107
+ if (!LIFTED[code] || status(error) !== LIFTED[code])
108
+ return null;
109
+ return { href: ours(said?.upgrade_url) };
110
+ }
111
+ /**
112
+ * Whether a refusal is a plan's usage limit, and which window.
113
+ *
114
+ * A paid plan is a subscription with limits: a spent session or day comes back
115
+ * 429 `usage_cap_exceeded` naming the window, its reset and, below the top
116
+ * plan, an `upgrade_url`. The month refuses nothing — Enso and Zen keep
117
+ * answering — so no other window is a cap. The code decides, never the
118
+ * sentence, and the address is kept by the rule `planRequired` keeps.
119
+ */
120
+ export function capped(error) {
121
+ const said = error?.body?.error;
122
+ if (said?.code !== 'usage_cap_exceeded' || status(error) !== 429)
123
+ return null;
124
+ if (said.limit !== 'session' && said.limit !== 'day')
125
+ return null;
126
+ return { limit: said.limit, resets: typeof said.resets_at === 'string' ? said.resets_at : null, href: ours(said.upgrade_url) };
127
+ }
128
+ function ours(href) {
129
+ if (typeof href !== 'string')
130
+ return undefined;
131
+ try {
132
+ const url = new URL(href);
133
+ const host = url.hostname;
134
+ return url.protocol === 'https:' && (host === 'hanzo.ai' || host.endsWith('.hanzo.ai')) ? url.toString() : undefined;
135
+ }
136
+ catch {
137
+ return undefined;
138
+ }
139
+ }
140
+ /** The family a model id belongs to, as a reader knows it, or '' for one outside them. */
141
+ export const familyOf = (id) => /^(hanzo\/)?enso/i.test(id) ? 'Enso' : /^(hanzo\/)?zen/i.test(id) ? 'Zen' : '';
142
+ /** What the server said about a failure, for the detail folded under the plain line. */
143
+ export const detail = (error) => told(error) ?? (error instanceof Error ? error.message : String(error ?? ''));
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The ground the workspace's cards stand on, and how each card is cut.
3
+ *
4
+ * A PANE is a card floating on the ground, cut by the `--pane-*` tokens
5
+ * (app/globals.css): a corner, an edge, the lens behind it, and the second
6
+ * paper rung's lit edge and drop. The fill is the caller's rung: `--pane-fill`
7
+ * in the app's frame, `sheet(1)`/`sheet(2)` where a pane lies in a room.
8
+ *
9
+ * The drop is a prop and not `sheet(2)`'s `elevation-2` class, whose shadow is
10
+ * `!important`: a Dev run's pane steps aside for the two panes inside it by
11
+ * slot (@hanzo/build's `run-split`), and an important shadow would stay behind.
12
+ */
13
+ export declare const pane: (fill?: string) => {
14
+ readonly backgroundColor: string;
15
+ readonly borderRadius: 'var(--pane-round)';
16
+ readonly borderWidth: 1;
17
+ readonly borderColor: 'var(--pane-edge)';
18
+ readonly backdropFilter: 'var(--pane-blur)';
19
+ readonly boxShadow: 'var(--shadow-sheet-2)';
20
+ };
21
+ /**
22
+ * THE FLOOR under the app's frame (app/_web.tsx, components/settings/Frame.tsx):
23
+ * design's top light falling off down the window over the faint lamps of
24
+ * `--pane-ground`. A straight fall rather than a radial glow, because at these
25
+ * alphas a circle quantises into rings a blur makes plainer.
26
+ */
27
+ export declare const floor: {
28
+ readonly backgroundColor: 'var(--pane-floor)';
29
+ readonly backgroundImage: 'linear-gradient(to bottom, var(--glass-strong), transparent), var(--pane-ground)';
30
+ readonly backgroundSize: '100% 70%, auto';
31
+ readonly backgroundRepeat: 'no-repeat';
32
+ };
package/dist/ground.js ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * The ground the workspace's cards stand on, and how each card is cut.
3
+ *
4
+ * A PANE is a card floating on the ground, cut by the `--pane-*` tokens
5
+ * (app/globals.css): a corner, an edge, the lens behind it, and the second
6
+ * paper rung's lit edge and drop. The fill is the caller's rung: `--pane-fill`
7
+ * in the app's frame, `sheet(1)`/`sheet(2)` where a pane lies in a room.
8
+ *
9
+ * The drop is a prop and not `sheet(2)`'s `elevation-2` class, whose shadow is
10
+ * `!important`: a Dev run's pane steps aside for the two panes inside it by
11
+ * slot (@hanzo/build's `run-split`), and an important shadow would stay behind.
12
+ */
13
+ export const pane = (fill = 'var(--pane-fill)') => ({
14
+ backgroundColor: fill,
15
+ borderRadius: 'var(--pane-round)',
16
+ borderWidth: 1,
17
+ borderColor: 'var(--pane-edge)',
18
+ backdropFilter: 'var(--pane-blur)',
19
+ boxShadow: 'var(--shadow-sheet-2)',
20
+ });
21
+ /**
22
+ * THE FLOOR under the app's frame (app/_web.tsx, components/settings/Frame.tsx):
23
+ * design's top light falling off down the window over the faint lamps of
24
+ * `--pane-ground`. A straight fall rather than a radial glow, because at these
25
+ * alphas a circle quantises into rings a blur makes plainer.
26
+ */
27
+ export const floor = {
28
+ backgroundColor: 'var(--pane-floor)',
29
+ backgroundImage: 'linear-gradient(to bottom, var(--glass-strong), transparent), var(--pane-ground)',
30
+ backgroundSize: '100% 70%, auto',
31
+ backgroundRepeat: 'no-repeat',
32
+ };
package/dist/host.d.ts ADDED
@@ -0,0 +1,76 @@
1
+ /**
2
+ * What a host tells the rooms.
3
+ *
4
+ * The rooms name no framework and no site. Everything that differs between the
5
+ * surfaces that mount them arrives here, in two halves, because two kinds of
6
+ * caller read them:
7
+ *
8
+ * configure({ site: 'https://hanzo.ai', home: '/', signUp: '/start' })
9
+ *
10
+ * <Rooms router={useRouter()} search={useSearchParams()} route={route} Link={Link}>
11
+ * <Room mode="cal" />
12
+ * </Rooms>
13
+ *
14
+ * The ADDRESSES — where the app's pages live, which gateway and IAM to talk to,
15
+ * the plan catalogue to paint first — do not change while the page is open, and
16
+ * plain modules (`api()`, `iam()`, `site()`, the plan reads) call them outside
17
+ * any component and on pages the rooms never draw. So the host states them once
18
+ * with `configure()`, in a module its root imports, before anything renders.
19
+ *
20
+ * The ROUTER, the query and the route change as the page moves, so they ride
21
+ * React context, and a room reads them with `useRooms()`.
22
+ */
23
+ import { type AnchorHTMLAttributes, type ComponentType, type ReactNode } from 'react';
24
+ /** A link the host's router owns: next/link under Next, an anchor elsewhere. */
25
+ export type Link = ComponentType<AnchorHTMLAttributes<HTMLAnchorElement> & {
26
+ href: string;
27
+ prefetch?: boolean;
28
+ }>;
29
+ export interface Router {
30
+ push(href: string): void;
31
+ replace(href: string): void;
32
+ back(): void;
33
+ forward(): void;
34
+ }
35
+ interface Moving {
36
+ router: Router;
37
+ /** The address's query, for the rooms that read one (Dev's `?at=`). */
38
+ search: URLSearchParams | null;
39
+ route: string;
40
+ Link: Link;
41
+ }
42
+ export interface RoomsProps extends Omit<Moving, 'search'> {
43
+ /** Absent where no mounted room reads the query, so a static export needs no Suspense for it. */
44
+ search?: URLSearchParams | null;
45
+ children?: ReactNode;
46
+ }
47
+ /** The router, the query, the route and the link the host mounted the rooms with. */
48
+ export declare const useRooms: () => Moving;
49
+ /** The org in scope, by the id the appearance layers are keyed on. */
50
+ export declare function useOrg(): {
51
+ id?: string;
52
+ name?: string;
53
+ };
54
+ /**
55
+ * The person's appearance — theme, type, spacing, corners, accent — resolved
56
+ * for the org in scope and kept with their IAM account, so a choice made here
57
+ * follows them to every Hanzo origin. Every control that changes how the rooms
58
+ * look goes through this, and only this.
59
+ */
60
+ export declare function useLook(): {
61
+ pref: import("@hanzo/appearance").Preference;
62
+ set: (patch: Partial<import("@hanzo/appearance").Preference>) => void;
63
+ reset: () => void;
64
+ scope: import("@hanzo/appearance").Scope;
65
+ setScope: (s: import("@hanzo/appearance").Scope) => import("@hanzo/appearance").Resolved;
66
+ from: Partial<Record<keyof import("@hanzo/appearance").Preference, "install" | "org" | "user" | "userOrg">>;
67
+ layer: "user" | "userOrg";
68
+ };
69
+ /**
70
+ * The look, applied: mounted once at the host's root, inside its IamProvider,
71
+ * so every page — a room or not — opens in the person's theme and accent and
72
+ * keeps their choice in step with IAM.
73
+ */
74
+ export declare function Look(): any;
75
+ export declare function Rooms({ router, search, route, Link, children }: RoomsProps): import("react").JSX.Element;
76
+ export {};
package/dist/host.js ADDED
@@ -0,0 +1,76 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ /**
4
+ * What a host tells the rooms.
5
+ *
6
+ * The rooms name no framework and no site. Everything that differs between the
7
+ * surfaces that mount them arrives here, in two halves, because two kinds of
8
+ * caller read them:
9
+ *
10
+ * configure({ site: 'https://hanzo.ai', home: '/', signUp: '/start' })
11
+ *
12
+ * <Rooms router={useRouter()} search={useSearchParams()} route={route} Link={Link}>
13
+ * <Room mode="cal" />
14
+ * </Rooms>
15
+ *
16
+ * The ADDRESSES — where the app's pages live, which gateway and IAM to talk to,
17
+ * the plan catalogue to paint first — do not change while the page is open, and
18
+ * plain modules (`api()`, `iam()`, `site()`, the plan reads) call them outside
19
+ * any component and on pages the rooms never draw. So the host states them once
20
+ * with `configure()`, in a module its root imports, before anything renders.
21
+ *
22
+ * The ROUTER, the query and the route change as the page moves, so they ride
23
+ * React context, and a room reads them with `useRooms()`.
24
+ */
25
+ import { createContext, useContext } from 'react';
26
+ import { useIam, useOrganizations } from '@hanzo/iam/react';
27
+ import { useAppearance } from '@hanzo/appearance';
28
+ import { where } from './where.js';
29
+ const Plain = ({ prefetch: _prefetch, ...rest }) => _jsx("a", { ...rest });
30
+ const Context = createContext({
31
+ router: {
32
+ push: (href) => window.location.assign(href),
33
+ replace: (href) => window.location.replace(href),
34
+ back: () => window.history.back(),
35
+ forward: () => window.history.forward(),
36
+ },
37
+ search: null,
38
+ route: '/',
39
+ Link: Plain,
40
+ });
41
+ /** The router, the query, the route and the link the host mounted the rooms with. */
42
+ export const useRooms = () => useContext(Context);
43
+ /** The org in scope, by the id the appearance layers are keyed on. */
44
+ export function useOrg() {
45
+ const { currentOrg } = useOrganizations();
46
+ const one = currentOrg;
47
+ return { id: one?.id || one?.name, name: one?.displayName || one?.name };
48
+ }
49
+ /**
50
+ * The person's appearance — theme, type, spacing, corners, accent — resolved
51
+ * for the org in scope and kept with their IAM account, so a choice made here
52
+ * follows them to every Hanzo origin. Every control that changes how the rooms
53
+ * look goes through this, and only this.
54
+ */
55
+ export function useLook() {
56
+ const { accessToken } = useIam();
57
+ const org = useOrg();
58
+ // Signed out there is no person to ask about, so IAM is not asked: a stranger
59
+ // passing through a room on the way to sign in sends nothing to the issuer.
60
+ return useAppearance({
61
+ org: org.id,
62
+ account: accessToken ? { base: (where().iam ?? 'https://hanzo.id').replace(/\/+$/, ''), token: accessToken } : undefined,
63
+ });
64
+ }
65
+ /**
66
+ * The look, applied: mounted once at the host's root, inside its IamProvider,
67
+ * so every page — a room or not — opens in the person's theme and accent and
68
+ * keeps their choice in step with IAM.
69
+ */
70
+ export function Look() {
71
+ useLook();
72
+ return null;
73
+ }
74
+ export function Rooms({ router, search = null, route, Link, children }) {
75
+ return _jsx(Context.Provider, { value: { router, search, route, Link }, children: children });
76
+ }
@@ -0,0 +1,14 @@
1
+ /**
2
+ * @hanzo/rooms — the workspace rooms, once, for every Hanzo surface.
3
+ *
4
+ * import { configure, Rooms } from '@hanzo/rooms'
5
+ * import { Room } from '@hanzo/rooms/Room'
6
+ * import { CalScheduler } from '@hanzo/rooms/CalScheduler'
7
+ *
8
+ * The root names what a host passes; each room is its own subpath, so a page
9
+ * loads the rooms it draws and no others.
10
+ */
11
+ export { configure, where, site } from './where.js';
12
+ export type { Addresses } from './where.js';
13
+ export { Rooms, Look, useRooms, useLook, useOrg } from './host.js';
14
+ export type { Router, Link, RoomsProps } from './host.js';
package/dist/index.js ADDED
@@ -0,0 +1,12 @@
1
+ /**
2
+ * @hanzo/rooms — the workspace rooms, once, for every Hanzo surface.
3
+ *
4
+ * import { configure, Rooms } from '@hanzo/rooms'
5
+ * import { Room } from '@hanzo/rooms/Room'
6
+ * import { CalScheduler } from '@hanzo/rooms/CalScheduler'
7
+ *
8
+ * The root names what a host passes; each room is its own subpath, so a page
9
+ * loads the rooms it draws and no others.
10
+ */
11
+ export { configure, where, site } from './where.js';
12
+ export { Rooms, Look, useRooms, useLook, useOrg } from './host.js';
package/dist/kept.d.ts ADDED
@@ -0,0 +1,5 @@
1
+ /**
2
+ * A value kept in this browser as JSON; storage that throws keeps it in memory.
3
+ * Read in the initializer: the app renders only in the browser (app/_apex.tsx).
4
+ */
5
+ export declare function useKept<T>(key: string, initial: T): [T, (v: T) => void];
package/dist/kept.js ADDED
@@ -0,0 +1,27 @@
1
+ 'use client';
2
+ import { useState } from 'react';
3
+ /**
4
+ * A value kept in this browser as JSON; storage that throws keeps it in memory.
5
+ * Read in the initializer: the app renders only in the browser (app/_apex.tsx).
6
+ */
7
+ export function useKept(key, initial) {
8
+ const [value, setValue] = useState(() => {
9
+ try {
10
+ const raw = localStorage.getItem(key);
11
+ return raw === null ? initial : JSON.parse(raw);
12
+ }
13
+ catch {
14
+ return initial;
15
+ }
16
+ });
17
+ const set = (v) => {
18
+ setValue(v);
19
+ try {
20
+ localStorage.setItem(key, JSON.stringify(v));
21
+ }
22
+ catch {
23
+ /* kept for this page only */
24
+ }
25
+ };
26
+ return [value, set];
27
+ }
@@ -0,0 +1,49 @@
1
+ import React, { ReactNode } from 'react';
2
+ export interface OrganizationMember {
3
+ id: string;
4
+ name: string;
5
+ email: string;
6
+ role: string;
7
+ avatar?: string;
8
+ }
9
+ export interface Organization {
10
+ id: string;
11
+ name: string;
12
+ /** The reader's role in it as the token's `orgs` claim states it: owner | admin | member. */
13
+ role: string;
14
+ avatar?: string;
15
+ plan?: string;
16
+ memberCount?: number;
17
+ members?: OrganizationMember[];
18
+ description?: string;
19
+ website?: string;
20
+ location?: string;
21
+ }
22
+ export interface User {
23
+ id: string;
24
+ name: string;
25
+ email: string;
26
+ avatar?: string;
27
+ bio?: string;
28
+ location?: string;
29
+ joinedDate?: string;
30
+ website?: string;
31
+ phone?: string;
32
+ }
33
+ interface AccountContextType {
34
+ user: User | null;
35
+ setUser: (user: User) => void;
36
+ organizations: Organization[];
37
+ currentOrganization: Organization | null;
38
+ isLoading: boolean;
39
+ switchOrganization: (orgId: string) => void;
40
+ /** Writes to IAM and resolves once the row is stored. Rejects with the
41
+ * reason where it is not — a caller that reports success does so on this. */
42
+ updateUserProfile: (userData: Partial<User>) => Promise<void>;
43
+ updateOrganization: (orgData: Partial<Organization>) => void;
44
+ }
45
+ export declare const AccountProvider: React.FC<{
46
+ children: ReactNode;
47
+ }>;
48
+ export declare const useAccount: () => AccountContextType;
49
+ export {};