@hanzo/rooms 0.1.56 → 0.1.58

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/Shell.js CHANGED
@@ -75,7 +75,6 @@ import { Profile } from "./Profile.js";
75
75
  import { SupportPicker } from "./Support.js";
76
76
  import { Find } from "./Find.js";
77
77
  import { Account } from "./Account.js";
78
- import { ModeMark } from "./ModeMark.js";
79
78
  import { called } from "./team.js";
80
79
  import { checkoutUrl } from './lib/pay.js';
81
80
  /** Tabs: the terminals, at their own host. */
@@ -116,7 +115,7 @@ const CONTROL = 28;
116
115
  import { getStoredPeople, getStoredAgents, getCustomThreads, createDirectChat, } from "./contacts-store.js";
117
116
  import { bare } from './lib/bare.js';
118
117
  import { BAD } from './lib/mix.js';
119
- import { brand, site, where } from './where.js';
118
+ import { brand, site, where, wordmark } from './where.js';
120
119
  /**
121
120
  * The destinations, in rail order.
122
121
  *
@@ -570,13 +569,13 @@ function Team({ filter = "", onPick, navigate, }) {
570
569
  // this app climbs (see Home's `Waiting`). "Reading." never resolves for a
571
570
  // reader nobody is going to answer, so the session is asked first.
572
571
  if (!signedIn)
573
- return _jsx(Note, { children: "Sign in to see your org's rooms." });
572
+ return _jsx(Note, { children: "Sign in to see your org's channels." });
574
573
  if (wrong)
575
- return _jsx(Note, { children: say(wrong, "your rooms") });
574
+ return _jsx(Note, { children: say(wrong, "your channels") });
576
575
  if (rooms === null)
577
- return _jsx(Note, { children: "Reading your rooms." });
576
+ return _jsx(Note, { children: "Reading your channels." });
578
577
  if (rooms.length === 0)
579
- return _jsx(Note, { children: "No rooms yet. Open one and the conversation has somewhere to live." });
578
+ return _jsx(Note, { children: "No channels yet." });
580
579
  if (shown.length === 0)
581
580
  return _jsxs(Note, { children: ["No room matches \u201C", filter, "\u201D."] });
582
581
  return (_jsxs(_Fragment, { children: [favourites.length > 0 ? (_jsx(SidebarFolder, { name: "Favorites", defaultOpen: true, children: favourites.map((one) => (_jsx(SidebarItem, { active: teamKey(one) === room, icon: _jsx(Star, { size: 13, "aria-hidden": true }), onPress: () => {
@@ -1181,7 +1180,7 @@ function Frame({ mode, children, navigate, back, forward, }) {
1181
1180
  // Drive names the company rather than the room.
1182
1181
  id: place.id,
1183
1182
  title: place.label,
1184
- category: "Rooms",
1183
+ category: "Apps",
1185
1184
  icon: _jsx(place.icon, { size: 15, "aria-hidden": true }),
1186
1185
  href: place.route,
1187
1186
  })),
@@ -1210,7 +1209,7 @@ function Frame({ mode, children, navigate, back, forward, }) {
1210
1209
  const list = (_jsxs(Sidebar, { ref: side.ref,
1211
1210
  // A phone's sheet is never wider than 280, whatever the laptop kept.
1212
1211
  // inline-style: `--span`, the width a drag rewrites on the element itself (span.ts); no prop sets a variable.
1213
- style: side.style, $md: { width: "var(--span)" }, "$max-md": { width: "100%", maxW: 280 }, ...sheet(0), borderRightWidth: 1, borderColor: "var(--edge, var(--white-06))", position: "relative", children: [_jsx(Grip, { side: "left", span: side.span, floor: FLOOR, ceil: CEIL, reset: SIDEBAR_WIDTH, onSpan: side.move, onKeep: side.keep, onShut: () => setAsked(false), label: "Resize sidebar" }), _jsx(XStack, { "data-slot": "mode-switch", items: "center", px: "$2", pt: "$2", minW: 0, children: _jsx(ModeMark, { mode: mode === "dev" ? "dev" : "chat", onChat: () => navigate?.("/chat"), onDev: () => navigate?.(dev()) }) }), _jsxs(XStack, { "data-slot": "workspace-switcher", items: "center", gap: "$2", px: "$2", pt: "$1", pb: "$1", minW: 0, children: [_jsx(Text, { render: _jsx("a", { href: "/", onClick: (e) => {
1212
+ style: side.style, $md: { width: "var(--span)" }, "$max-md": { width: "100%", maxW: 280 }, ...sheet(0), borderRightWidth: 1, borderColor: "var(--edge, var(--white-06))", position: "relative", children: [_jsx(Grip, { side: "left", span: side.span, floor: FLOOR, ceil: CEIL, reset: SIDEBAR_WIDTH, onSpan: side.move, onKeep: side.keep, onShut: () => setAsked(false), label: "Resize sidebar" }), _jsx(XStack, { "data-slot": "mode-name", items: "center", px: "$2", pt: "$2", minW: 0, children: _jsx(Text, { fontSize: "$4", fontWeight: "600", color: "$ink", numberOfLines: 1, children: wordmark(mode === "dev" ? "dev" : "chat") }) }), _jsxs(XStack, { "data-slot": "workspace-switcher", items: "center", gap: "$2", px: "$2", pt: "$1", pb: "$1", minW: 0, children: [_jsx(Text, { render: _jsx("a", { href: "/", onClick: (e) => {
1214
1213
  if (!navigate || e.metaKey || e.ctrlKey || e.shiftKey || e.button !== 0)
1215
1214
  return;
1216
1215
  e.preventDefault();
package/dist/Talk.js CHANGED
@@ -43,7 +43,7 @@ function when(ms) {
43
43
  * an empty header. The sigil is how a client DRAWS a room and is not stored, so
44
44
  * it is added here and only where there is a name to put it on.
45
45
  */
46
- const titleOf = (room) => room.name ? `#${room.name}` : room.direct ? 'Direct message' : 'Room';
46
+ const titleOf = (room) => room.name ? `#${room.name}` : room.direct ? 'Direct message' : 'Channel';
47
47
  /** Adds `@name ` to a draft, after a space where the draft needs one. */
48
48
  const mention = (draft, name) => `${draft && !/\s$/.test(draft) ? `${draft} ` : draft}@${name} `;
49
49
  export function Talk({ room }) {
@@ -70,14 +70,14 @@ export function Talk({ room }) {
70
70
  }
71
71
  catch (e) {
72
72
  setDraft(text);
73
- setRefused(say(e, 'this room', 'save'));
73
+ setRefused(say(e, 'this channel', 'save'));
74
74
  }
75
75
  finally {
76
76
  setPending((held) => held.filter((one) => one.key !== key));
77
77
  }
78
78
  };
79
79
  const name = (of) => setDraft((held) => mention(held, of));
80
- return (_jsxs(YStack, { flex: 1, minH: 0, children: [_jsxs(ChannelHeader, { name: titleOf(room), children: [room.topic ? (_jsx(Text, { fontSize: "$2", color: "$soft", numberOfLines: 1, children: room.topic })) : null, _jsx(Box, { render: "button", "aria-label": aside === 'roster' ? 'Hide directory & roster' : 'Show directory & roster', "aria-pressed": aside === 'roster', onClick: () => showAside(aside === 'roster' ? null : 'roster'), ml: "auto", p: "$2", rounded: "$3", hoverStyle: { bg: '$hover' }, children: _jsx(Users, { size: 16, "aria-hidden": true }) })] }), _jsxs(YStack, { flex: 1, minH: 0, overflowY: "auto", overflowX: "hidden", p: "$4", gap: "$3", children: [failed ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: say(failed, 'this room') })) : messages === null ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: "Reading the room." })) : messages.length === 0 && pending.length === 0 ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: "Nothing has been said here yet." })) : (messages.map((one) => (_jsx(Line, { member: memberOf(members, one.author), fallback: one.author, stamp: when(one.createdOn), text: one.text }, one.id)))), pending
80
+ return (_jsxs(YStack, { flex: 1, minH: 0, children: [_jsxs(ChannelHeader, { name: titleOf(room), children: [room.topic ? (_jsx(Text, { fontSize: "$2", color: "$soft", numberOfLines: 1, children: room.topic })) : null, _jsx(Box, { render: "button", "aria-label": aside === 'roster' ? 'Hide directory & roster' : 'Show directory & roster', "aria-pressed": aside === 'roster', onClick: () => showAside(aside === 'roster' ? null : 'roster'), ml: "auto", p: "$2", rounded: "$3", hoverStyle: { bg: '$hover' }, children: _jsx(Users, { size: 16, "aria-hidden": true }) })] }), _jsxs(YStack, { flex: 1, minH: 0, overflowY: "auto", overflowX: "hidden", p: "$4", gap: "$3", children: [failed ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: say(failed, 'this channel') })) : messages === null ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: "Reading the room." })) : messages.length === 0 && pending.length === 0 ? (_jsx(Text, { fontSize: "$3", color: "$soft", children: "Nothing has been said here yet." })) : (messages.map((one) => (_jsx(Line, { member: memberOf(members, one.author), fallback: one.author, stamp: when(one.createdOn), text: one.text }, one.id)))), pending
81
81
  .filter((one) => !messages?.some((said) => said.author === me && said.text === one.text))
82
82
  .map((one) => (_jsx(Line, { member: mine, fallback: "You", text: one.text, soft: true }, `pending-${one.key}`)))] }), _jsxs(YStack, { p: "$3", gap: "$2", borderTopWidth: 1, borderColor: "$borderColor", children: [_jsx(Composer, { value: draft, onChange: setDraft, onSend: () => void speak(), placeholder: `Message ${titleOf(room)}`, label: `Message ${titleOf(room)}`, hint: agents.length ? 'Mention an agent with @name and it answers.' : undefined, children: agents.length ? (_jsx(XStack, { gap: "$1", flexWrap: "wrap", shrink: 1, minW: 0, children: agents.map((one) => (_jsx(Box, { render: "button", "aria-label": `Mention ${one.name}`, onClick: () => name(one.name), px: "$2", py: "$1", rounded: "$10", hoverStyle: { bg: '$hover' }, children: _jsxs(Text, { fontSize: "$2", color: "$soft", children: ["@", one.name] }) }, one.id))) })) : null }), refused ? (_jsx(Text, { fontSize: "$2", color: BAD, children: refused })) : null] }), _jsx(Beside, { children: aside === 'roster' ? _jsx(Roster, { members: members, wrong: wrong, onMention: name }) : null })] }));
83
83
  }
package/dist/host.js CHANGED
@@ -25,7 +25,7 @@ import { jsx as _jsx } from "react/jsx-runtime";
25
25
  import { createContext, useContext } from 'react';
26
26
  import { useIam, useOrganizations } from '@hanzo/iam/react';
27
27
  import { useAppearance } from '@hanzo/appearance';
28
- import { where } from './where.js';
28
+ import { iam } from './lib/api.js';
29
29
  const Plain = ({ prefetch: _prefetch, ...rest }) => _jsx("a", { ...rest });
30
30
  const Context = createContext({
31
31
  router: {
@@ -59,7 +59,7 @@ export function useLook() {
59
59
  // passing through a room on the way to sign in sends nothing to the issuer.
60
60
  return useAppearance({
61
61
  org: org.id,
62
- account: accessToken ? { base: (where().iam ?? 'https://hanzo.id').replace(/\/+$/, ''), token: accessToken } : undefined,
62
+ account: accessToken ? { base: iam(), token: accessToken } : undefined,
63
63
  });
64
64
  }
65
65
  /**
package/dist/lib/host.js CHANGED
@@ -207,9 +207,11 @@ const DEVNET = '-dev.hanzo.ai';
207
207
  * either: it is hanzo.ai/dev's old address and redirects there.
208
208
  */
209
209
  export function devnet(hostname) {
210
- if (!hostname.endsWith(DEVNET))
210
+ // A fully qualified name (app-dev.hanzo.ai.) is the same host.
211
+ const host = hostname.endsWith('.') ? hostname.slice(0, -1) : hostname;
212
+ if (!host.endsWith(DEVNET))
211
213
  return false;
212
- const label = hostname.slice(0, -'.hanzo.ai'.length);
214
+ const label = host.slice(0, -'.hanzo.ai'.length);
213
215
  return label.length > '-dev'.length && !label.includes('.');
214
216
  }
215
217
  /**
package/dist/lib/pay.d.ts CHANGED
@@ -17,6 +17,14 @@
17
17
  * hanzo.bot, and the checkout lives on hanzo.ai.
18
18
  */
19
19
  export declare const BILLING_URL = "https://hanzo.ai/pay";
20
+ /**
21
+ * The devnet's checkout: the same /pay mount on the devnet's site host, which
22
+ * charges Square's sandbox through the devnet's cloud. A page on a devnet host
23
+ * sends a buyer here and never to production's checkout.
24
+ */
25
+ export declare const BILLING_DEV = "https://app-dev.hanzo.ai/pay";
26
+ /** The checkout for the page in front of us: the devnet's on a devnet host, hanzo.ai's everywhere else. */
27
+ export declare function billing(): string;
20
28
  /**
21
29
  * The checkout address, opened on a plan when one is named, and returning to
22
30
  * `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
package/dist/lib/pay.js CHANGED
@@ -4,6 +4,7 @@
4
4
  * Kept apart from `plans.ts`, which reads the bundled plan catalogue: a page
5
5
  * that only links the pay page or prints a price carries none of it.
6
6
  */
7
+ import { devnet } from "./host.js";
7
8
  import { org } from "./session.js";
8
9
  /**
9
10
  * Where money changes hands: the checkout, mounted at hanzo.ai/pay so a buyer
@@ -18,6 +19,16 @@ import { org } from "./session.js";
18
19
  * hanzo.bot, and the checkout lives on hanzo.ai.
19
20
  */
20
21
  export const BILLING_URL = "https://hanzo.ai/pay";
22
+ /**
23
+ * The devnet's checkout: the same /pay mount on the devnet's site host, which
24
+ * charges Square's sandbox through the devnet's cloud. A page on a devnet host
25
+ * sends a buyer here and never to production's checkout.
26
+ */
27
+ export const BILLING_DEV = "https://app-dev.hanzo.ai/pay";
28
+ /** The checkout for the page in front of us: the devnet's on a devnet host, hanzo.ai's everywhere else. */
29
+ export function billing() {
30
+ return typeof window !== "undefined" && devnet(window.location.hostname) ? BILLING_DEV : BILLING_URL;
31
+ }
21
32
  /**
22
33
  * The checkout address, opened on a plan when one is named, and returning to
23
34
  * `back` once the buyer has paid. Without `back` a paid buyer lands on the pay
@@ -50,9 +61,10 @@ export function payUrl(path, query) {
50
61
  if (v)
51
62
  q.set(k, v);
52
63
  const s = q.toString();
64
+ const at = billing();
53
65
  if (path === "/" && !s)
54
- return BILLING_URL;
55
- return `${BILLING_URL}${path}${s ? `?${s}` : ""}`;
66
+ return at;
67
+ return `${at}${path}${s ? `?${s}` : ""}`;
56
68
  }
57
69
  export const dollars = (n) => `$${n.toFixed(2)}`;
58
70
  /** Money as a sentence says it: whole dollars bare, anything else to the cent — $20, $16.67. */
package/dist/lib/plans.js CHANGED
@@ -32,7 +32,7 @@
32
32
  import { useEffect, useMemo, useState } from "react";
33
33
  import { where } from "../where.js";
34
34
  import { api } from "./api.js";
35
- import { BILLING_URL, checkoutUrl, dollars, money, payUrl } from "./pay.js";
35
+ import { billing, checkoutUrl, dollars, money, payUrl } from "./pay.js";
36
36
  /**
37
37
  * The checkout a plan's CTA opens.
38
38
  *
@@ -52,7 +52,7 @@ export function planCheckoutUrl(plan, back) {
52
52
  export function term(href, interval) {
53
53
  if (interval === "month")
54
54
  return href;
55
- const url = new URL(href, BILLING_URL);
55
+ const url = new URL(href, billing());
56
56
  url.searchParams.set("interval", "year");
57
57
  return url.toString();
58
58
  }
package/dist/recent.js CHANGED
@@ -1,6 +1,6 @@
1
1
  // The Recents list as data: each mode's rows, the views a menu offers, and the
2
2
  // list a view makes of them. No React, so a spec reads it as it is.
3
- export const PLAIN = { status: 'all', since: 'any', group: 'date', sort: 'activity' };
3
+ export const PLAIN = { status: 'all', since: 'any', group: 'none', sort: 'activity' };
4
4
  const STATUSES = [
5
5
  { id: 'all', label: 'All' },
6
6
  { id: 'running', label: 'Running' },
package/dist/rooms.js CHANGED
@@ -87,7 +87,7 @@ export function useTeamRooms() {
87
87
  }, [client, user, now]);
88
88
  const open = useCallback(async (room) => {
89
89
  if (!client)
90
- throw Object.assign(new Error('Sign in to open a room'), { status: 401 });
90
+ throw Object.assign(new Error('Sign in to open a channel'), { status: 401 });
91
91
  const made = await client.http.json({
92
92
  method: 'POST',
93
93
  path: '/v1/team/rooms',
@@ -180,7 +180,7 @@ export function useRoomMessages(room, space) {
180
180
  /** Says it and answers the stored row, or throws with the platform's status. */
181
181
  const send = useCallback(async (text) => {
182
182
  if (!client || !room || !space) {
183
- throw Object.assign(new Error('This room has no address to send to'), { status: 503 });
183
+ throw Object.assign(new Error('This channel has no address to send to'), { status: 503 });
184
184
  }
185
185
  const row = await client.http.json({
186
186
  method: 'POST',
package/dist/thread.d.ts CHANGED
@@ -55,3 +55,11 @@ export declare function ThreadRow({ t, active, aside, listed, children, }: {
55
55
  listed?: boolean;
56
56
  children: ReactElement;
57
57
  }): import("react").JSX.Element;
58
+ /**
59
+ * The ⋯ of the conversation a pane holds, in its header: the trigger of the
60
+ * menu its row opens, drawn inside a `ConversationMenu` of that one
61
+ * conversation, so the header and the row offer one menu.
62
+ */
63
+ export declare function ThreadMore({ t }: {
64
+ t: Thread;
65
+ }): import("react").JSX.Element;
package/dist/thread.js CHANGED
@@ -373,6 +373,21 @@ export function ThreadRow({ t, active = false, aside, listed = true, children, }
373
373
  // Before gui's own press handler, which opens the menu and stops there.
374
374
  onPointerDownCapture: aim, onKeyDownCapture: aim, onFocus: () => setFocused(true), onBlur: () => setFocused(false), children: _jsx(MoreHorizontal, { size: 15, "aria-hidden": true }) }) }) })] }));
375
375
  }
376
+ /**
377
+ * The ⋯ of the conversation a pane holds, in its header: the trigger of the
378
+ * menu its row opens, drawn inside a `ConversationMenu` of that one
379
+ * conversation, so the header and the row offer one menu.
380
+ */
381
+ export function ThreadMore({ t }) {
382
+ const menus = useContext(Rows);
383
+ if (!menus)
384
+ throw new Error('ThreadMore is drawn inside a ConversationMenu, which holds its menu.');
385
+ // gui types these handlers by React Native's event; on the web they carry the DOM's.
386
+ const aim = (e) => menus.aim(t, e.currentTarget);
387
+ return (_jsx(DropdownMenuTrigger, { asChild: true, children: _jsx(XStack, { render: "button", "aria-label": "Conversation options", ...{ title: 'More' }, "data-slot": "conversation-options", width: 32, height: 32, rounded: "$3", items: "center", justify: "center", cursor: "pointer", bg: menus.open === t.id ? '$hover' : 'transparent', hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' },
388
+ // Before gui's own press handler, which opens the menu and stops there.
389
+ onPointerDownCapture: aim, onKeyDownCapture: aim, children: _jsx(MoreHorizontal, { size: 16, "aria-hidden": true }) }) }));
390
+ }
376
391
  /** A conversation's title, written again: one line, never empty. */
377
392
  function Rename({ t, open, onOpenChange, onCloseAutoFocus, save, }) {
378
393
  const [words, setWords] = useState('');
package/dist/where.d.ts CHANGED
@@ -67,5 +67,7 @@ export declare function configure(given: Partial<Addresses>): void;
67
67
  export declare const where: () => Addresses;
68
68
  /** The product's name, as the host states it. Read at call time, like every address. */
69
69
  export declare const brand: () => string;
70
+ /** The product's name in each mode of the app: the host's brand in Chat (Hanzo AI, Hanzo Team), Hanzo Dev in Dev. */
71
+ export declare const wordmark: (mode: 'chat' | 'dev') => string;
70
72
  /** A page of the app's own, from wherever the rooms are mounted. */
71
73
  export declare const site: (path: string) => string;
package/dist/where.js CHANGED
@@ -11,5 +11,7 @@ export function configure(given) {
11
11
  export const where = () => addresses;
12
12
  /** The product's name, as the host states it. Read at call time, like every address. */
13
13
  export const brand = () => addresses.brand ?? 'Hanzo AI';
14
+ /** The product's name in each mode of the app: the host's brand in Chat (Hanzo AI, Hanzo Team), Hanzo Dev in Dev. */
15
+ export const wordmark = (mode) => (mode === 'dev' ? 'Hanzo Dev' : brand());
14
16
  /** A page of the app's own, from wherever the rooms are mounted. */
15
17
  export const site = (path) => `${addresses.site}${path}`;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hanzo/rooms",
3
- "version": "0.1.56",
3
+ "version": "0.1.58",
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",
@@ -1,8 +0,0 @@
1
- /** The product's name in each mode: the host's brand in Chat (Hanzo AI, Hanzo Team), Hanzo Dev in Dev. */
2
- export declare const wordmark: (mode: 'chat' | 'dev') => string;
3
- export declare function ModeMark({ mode, onChat, onDev, stacked, }: {
4
- mode: 'chat' | 'dev';
5
- onChat: () => void;
6
- onDev: () => void;
7
- stacked?: boolean;
8
- }): import("react").JSX.Element;
package/dist/ModeMark.js DELETED
@@ -1,19 +0,0 @@
1
- 'use client';
2
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import { MessageSquare, Code2 } from 'lucide-react';
4
- import { XStack, YStack, Text, Tooltip, TooltipContent, TooltipTrigger } from '@hanzo/ui';
5
- import { brand } from './where.js';
6
- /** The product's name in each mode: the host's brand in Chat (Hanzo AI, Hanzo Team), Hanzo Dev in Dev. */
7
- export const wordmark = (mode) => (mode === 'dev' ? 'Hanzo Dev' : brand());
8
- /** One side of the switch: an icon button named for its mode, with the name as its tooltip. */
9
- function Side({ name, on, onPress, children }) {
10
- return (_jsxs(Tooltip, { children: [_jsx(TooltipTrigger, { children: _jsx(XStack, { render: "button", "aria-label": name, "aria-pressed": on, onPress: onPress, width: 28, height: 24, rounded: 999, items: "center", justify: "center", bg: on ? '$hover' : 'transparent', hoverStyle: { bg: '$hover' }, cursor: "pointer", children: children }) }), _jsx(TooltipContent, { children: _jsx(Text, { fontSize: "$2", children: name }) })] }));
11
- }
12
- export function ModeMark({ mode, onChat, onDev, stacked = false, }) {
13
- const dev = mode === 'dev';
14
- const Group = stacked ? YStack : XStack;
15
- const toggle = (_jsxs(Group, { role: "group", "aria-label": "Switch Hanzo", items: "center", gap: 2, p: 2, rounded: 999, bg: "$edge", shrink: 0, children: [_jsx(Side, { name: "Chat", on: !dev, onPress: onChat, children: _jsx(MessageSquare, { size: 14, "aria-hidden": true }) }), _jsx(Side, { name: "Dev", on: dev, onPress: onDev, children: _jsx(Code2, { size: 14, "aria-hidden": true }) })] }));
16
- if (stacked)
17
- return toggle;
18
- return (_jsxs(XStack, { flex: 1, items: "center", justify: "space-between", gap: "$2", minW: 0, children: [_jsx(Text, { fontSize: "$4", fontWeight: "600", color: "$ink", numberOfLines: 1, children: wordmark(mode) }), toggle] }));
19
- }