@hanzo/build 0.2.7 → 0.2.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/README.md +7 -5
- package/lib/account.js +2 -13
- package/lib/builder.js +3 -26
- package/lib/forge.js +1 -12
- package/lib/host.d.ts +4 -0
- package/lib/switch.d.ts +1 -0
- package/lib/switch.js +40 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -84,11 +84,13 @@ collide.
|
|
|
84
84
|
|
|
85
85
|
## What is on the screen
|
|
86
86
|
|
|
87
|
-
**The rail** (hanzo.build).
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
87
|
+
**The rail** (hanzo.build). At the top, the mark. Signed in to an organization,
|
|
88
|
+
that spot is the organization switcher: the org, and the projects under it.
|
|
89
|
+
New, then Automations, then the forge — Codebase, Projects, Issues — then MCP,
|
|
90
|
+
Artifacts, More (Templates, Machines, Docs), then the org's coding runs newest
|
|
91
|
+
first with a live status dot. The account stays at the foot. Settings opens
|
|
92
|
+
that account on this page. Collapse is an explicit toggle kept in this browser.
|
|
93
|
+
A host with its own rail draws `DevSection` there instead.
|
|
92
94
|
|
|
93
95
|
**MCP.** The native servers `POST /v1/mcp` lists, each with the operations it
|
|
94
96
|
names. A run starts a server when it calls it, and the server stays up afterwards.
|
package/lib/account.js
CHANGED
|
@@ -4,7 +4,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
|
4
4
|
* finding a run by name (the search icon).
|
|
5
5
|
*/
|
|
6
6
|
import { SizableText, XStack, YStack } from '@hanzo/gui';
|
|
7
|
-
import { LogOut
|
|
7
|
+
import { LogOut } from '@hanzogui/lucide-icons-2';
|
|
8
8
|
import { Button, Dialog, DialogContent, DialogTitle, Input } from '@hanzo/ui';
|
|
9
9
|
import { useMemo, useState } from 'react';
|
|
10
10
|
import { useHost } from './host.js';
|
|
@@ -20,21 +20,10 @@ export function onAccount(fn) {
|
|
|
20
20
|
export function revealAccount() {
|
|
21
21
|
reveal?.();
|
|
22
22
|
}
|
|
23
|
-
/** A settings address on another host. This page's own account is the dialog itself. */
|
|
24
|
-
function accountSettings(href) {
|
|
25
|
-
if (typeof window === 'undefined')
|
|
26
|
-
return false;
|
|
27
|
-
try {
|
|
28
|
-
return new URL(href, window.location.origin).origin !== window.location.origin;
|
|
29
|
-
}
|
|
30
|
-
catch {
|
|
31
|
-
return false;
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
23
|
export function Account({ open, onOpenChange }) {
|
|
35
24
|
const host = useHost();
|
|
36
25
|
const who = host.person;
|
|
37
|
-
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { maxW: 360, children: [_jsx(DialogTitle, { children: "Account" }), _jsxs(YStack, { gap: "$1", children: [_jsx(SizableText, { size: "$3", color: "$ink", numberOfLines: 1, children: who?.name || who?.email || 'Signed out' }), who?.email && who.name ? (_jsx(SizableText, { size: "$2", color: "$soft", numberOfLines: 1, children: who.email })) : null, host.org ? (_jsxs(SizableText, { size: "$1", color: "$soft", children: ["Organization: ", host.org] })) : null] }),
|
|
26
|
+
return (_jsx(Dialog, { open: open, onOpenChange: onOpenChange, children: _jsxs(DialogContent, { maxW: 360, children: [_jsx(DialogTitle, { children: "Account" }), _jsxs(YStack, { gap: "$1", children: [_jsx(SizableText, { size: "$3", color: "$ink", numberOfLines: 1, children: who?.name || who?.email || 'Signed out' }), who?.email && who.name ? (_jsx(SizableText, { size: "$2", color: "$soft", numberOfLines: 1, children: who.email })) : null, host.org ? (_jsxs(SizableText, { size: "$1", color: "$soft", children: ["Organization: ", host.org] })) : null] }), _jsx(XStack, { gap: "$2", justify: "flex-end", flexWrap: "wrap", children: host.signOut ? (_jsxs(Button, { variant: "outline", size: "sm", onPress: () => host.signOut?.(), children: [_jsx(LogOut, { size: 14 }), " Sign out"] })) : null })] }) }));
|
|
38
27
|
}
|
|
39
28
|
export function Find({ open, onOpenChange, recents, onOpen, }) {
|
|
40
29
|
const [q, setQ] = useState('');
|
package/lib/builder.js
CHANGED
|
@@ -42,6 +42,7 @@ import { Run } from './run.js';
|
|
|
42
42
|
import { DOTS } from './section.js';
|
|
43
43
|
import { Artifacts, Templates } from './shelf.js';
|
|
44
44
|
import { Account, Find, onAccount } from './account.js';
|
|
45
|
+
import { Where } from './switch.js';
|
|
45
46
|
function Shell() {
|
|
46
47
|
const host = useHost();
|
|
47
48
|
const t = useTarget();
|
|
@@ -87,37 +88,13 @@ function Shell() {
|
|
|
87
88
|
id: 'machines',
|
|
88
89
|
label: 'Machines',
|
|
89
90
|
icon: _jsx(Cpu, { size: 16 }),
|
|
90
|
-
onPress: () =>
|
|
91
|
-
const home = host.links.home.replace(/\/+$/, '');
|
|
92
|
-
const computers = `${home}/platform/computers`;
|
|
93
|
-
try {
|
|
94
|
-
if (new URL(computers, window.location.origin).origin === window.location.origin) {
|
|
95
|
-
host.go('');
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
return;
|
|
101
|
-
}
|
|
102
|
-
host.open(computers);
|
|
103
|
-
},
|
|
91
|
+
onPress: () => host.go(''),
|
|
104
92
|
},
|
|
105
93
|
{ id: 'docs', label: 'Docs', icon: _jsx(BookOpen, { size: 16 }), onPress: () => window.open('https://docs.hanzo.ai/docs/dev', '_blank', 'noopener,noreferrer') },
|
|
106
94
|
];
|
|
107
95
|
return (_jsxs(XStack, { flex: 1, minH: 0, minW: 0, bg: "$background", children: [_jsxs(YStack, { position: "relative", shrink: 0, children: [_jsx(SessionRail, { onNew: () => go(''), fresh: r.kind === 'new', links: links, more: more, recents: rows, active: r.kind === 'run' ? r.id : null, onOpen: (id) => go(id), onSort: () => setOrder(order === 'newest' ? 'running' : 'newest'), sortLabel: order === 'newest' ? 'Show running first' : 'Show newest first', empty: _jsx(SizableText, { size: "$1", color: "$soft", px: "$2", children: !host.person ? 'Sign in to see your runs.' : recents.error ? recents.error.message : recents.loading ? 'Reading…' : 'No runs yet.' }), account: host.person
|
|
108
96
|
? { name: host.person.email || host.person.name, onPress: () => setAccount(true) }
|
|
109
|
-
: { name: 'Sign in', onPress: () => host.signIn?.() }, onSettings: () => {
|
|
110
|
-
try {
|
|
111
|
-
if (new URL(host.links.settings, window.location.origin).origin === window.location.origin) {
|
|
112
|
-
setAccount(true);
|
|
113
|
-
return;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
host.open(host.links.settings);
|
|
120
|
-
}, onSearch: () => setFinding(true), collapsed: collapsed, onCollapse: setCollapsed, mark: _jsx(Brand, { org: host.org }), pt: collapsed ? undefined : 44, open: drawer, onOpenChange: setDrawer, label: "Runs" }), collapsed ? null : (_jsxs(XStack, { position: "absolute", t: 8, l: 8, r: 8, z: 2, items: "center", gap: "$2", render: "button", "aria-label": host.org ? `Organization ${host.org}` : 'Hanzo', onPress: () => go(''), children: [_jsx(Brand, { org: host.org }), _jsx(SizableText, { size: "$2", color: "$ink", numberOfLines: 1, children: host.org || 'Hanzo' })] }))] }), _jsxs(YStack, { flex: 1, minW: 0, minH: 0, position: "relative", children: [_jsx(XStack, { height: 44, px: "$2", items: "center", shrink: 0, $md: { display: 'none' }, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onPress: () => setDrawer(true), "aria-label": "Open runs", children: _jsx(Menu, { size: 18 }) }) }), _jsx(Pane, { onStarted: () => recents.reload() })] }), _jsx(Account, { open: account, onOpenChange: setAccount }), _jsx(Find, { open: finding, onOpenChange: setFinding, recents: rows, onOpen: (id) => { setFinding(false); go(id); } })] }));
|
|
97
|
+
: { name: 'Sign in', onPress: () => host.signIn?.() }, onSettings: () => setAccount(true), onSearch: () => setFinding(true), collapsed: collapsed, onCollapse: setCollapsed, mark: _jsx(Brand, { org: host.org }), pt: collapsed ? undefined : host.person && (host.org || (host.memberships?.length ?? 0) > 0) ? 80 : 40, open: drawer, onOpenChange: setDrawer, label: "Runs" }), collapsed ? null : (_jsx(XStack, { position: "absolute", t: 8, l: 8, r: 8, z: 2, items: "center", children: host.person && (host.org || (host.memberships?.length ?? 0) > 0) ? (_jsx(Where, {})) : (_jsx(XStack, { render: "button", "aria-label": "Hanzo", items: "center", onPress: () => go(''), children: _jsx(HanzoMark, { size: 18 }) })) }))] }), _jsxs(YStack, { flex: 1, minW: 0, minH: 0, position: "relative", children: [_jsx(XStack, { height: 44, px: "$2", items: "center", shrink: 0, $md: { display: 'none' }, children: _jsx(Button, { variant: "ghost", size: "icon-sm", onPress: () => setDrawer(true), "aria-label": "Open runs", children: _jsx(Menu, { size: 18 }) }) }), _jsx(Pane, { onStarted: () => recents.reload() })] }), _jsx(Account, { open: account, onOpenChange: setAccount }), _jsx(Find, { open: finding, onOpenChange: setFinding, recents: rows, onOpen: (id) => { setFinding(false); go(id); } })] }));
|
|
121
98
|
}
|
|
122
99
|
/** Whichever pane the address names, beside a rail — the builder's or the host's. */
|
|
123
100
|
function Pane({ onStarted }) {
|
package/lib/forge.js
CHANGED
|
@@ -173,18 +173,7 @@ function Codebases() {
|
|
|
173
173
|
pinCodebase(host.org, c);
|
|
174
174
|
host.go('');
|
|
175
175
|
};
|
|
176
|
-
return (_jsxs(YStack, { flex: 1, minH: 0, overflow: "scroll", px: "$6", py: "$6", children: [_jsxs(YStack, { width: "100%", maxW: 1040, mx: "auto", gap: "$4", children: [_jsxs(XStack, { justify: "space-between", items: "flex-start", gap: "$4", children: [_jsxs(YStack, { gap: "$1", children: [_jsx(SizableText, { size: "$6", fontWeight: "500", color: "$ink", children: host.org || 'Forge' }), _jsx(SizableText, { size: "$2", color: "$soft", children: "Create and browse this organization\u2019s repositories." })] }), _jsxs(XStack, { render: "button", "aria-label": "Settings", items: "center", gap: "$1.5", px: "$2", py: "$1", rounded: "$3", hoverStyle: { bg: '$hover' }, onPress: () => {
|
|
177
|
-
try {
|
|
178
|
-
if (new URL(host.links.settings, window.location.origin).origin === window.location.origin) {
|
|
179
|
-
revealAccount();
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
catch {
|
|
184
|
-
return;
|
|
185
|
-
}
|
|
186
|
-
host.open(host.links.settings);
|
|
187
|
-
}, children: [_jsx(Settings, { size: 14 }), _jsx(SizableText, { size: "$2", color: "$soft", children: "Settings" })] })] }), _jsxs(XStack, { gap: "$2", items: "center", children: [_jsx(XStack, { px: "$2.5", py: "$1.5", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", children: _jsx(SizableText, { size: "$2", color: "$ink", children: "All repos" }) }), _jsx(YStack, { flex: 1 }), _jsx(YStack, { width: 240, minW: 0, children: _jsx(Input, { value: q, onChangeText: setQ, placeholder: "Find repo\u2026", "aria-label": "Find a repository", disabled: !signed }) }), _jsx(Button, { size: "sm", variant: "outline", onPress: () => host.go(path({ kind: 'screen', screen: 'sync' })), children: "Sync" }), _jsxs(Button, { size: "sm", disabled: !signed, onPress: () => setMaking(true), children: [_jsx(Plus, { size: 14 }), "New"] })] }), list.error ? (_jsx(Note, { children: list.error.message })) : !signed ? (_jsx(Note, { children: "Sign in to see this organization's repositories." })) : list.loading && list.value.length === 0 ? (_jsx(Note, { children: "Reading the forge\u2026" })) : shown.length === 0 ? (_jsx(Note, { children: list.value.length === 0 ? 'No repositories yet.' : 'Nothing matches.' })) : (_jsxs(YStack, { borderWidth: 1, borderColor: "$borderColor", rounded: "$3", overflow: "hidden", children: [_jsxs(XStack, { px: "$3", py: "$2", gap: "$3", items: "center", children: [_jsxs(XStack, { flex: 1, render: "button", "aria-label": "Sort by name", items: "center", gap: "$1", onPress: () => setSort('name'), children: [_jsx(SizableText, { size: "$1", color: "$soft", children: "Name" }), sort === 'name' ? _jsx(ChevronDown, { size: 12 }) : null] }), _jsxs(XStack, { render: "button", "aria-label": "Sort by last updated", items: "center", justify: "flex-end", gap: "$1", width: 140, onPress: () => setSort('updated'), children: [_jsx(SizableText, { size: "$1", color: "$soft", children: "Last updated" }), sort === 'updated' ? _jsx(ChevronDown, { size: 12 }) : null] })] }), slice.map((c) => (_jsxs(XStack, { render: "button", "aria-label": `Work on ${c.name}`, onPress: () => open(c), items: "center", gap: "$3", px: "$3", py: "$2.5", borderTopWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, children: [_jsx(GitBranch, { size: 14 }), _jsx(SizableText, { flex: 1, size: "$2", color: "$ink", numberOfLines: 1, children: c.name }), _jsx(SizableText, { size: "$1", color: "$soft", width: 140, style: { textAlign: 'right' }, children: syncing.has(c.name) ? 'Syncing…' : when(c.updated) })] }, `${c.org}/${c.name}`))), _jsxs(XStack, { px: "$3", py: "$2", justify: "space-between", items: "center", borderTopWidth: 1, borderColor: "$borderColor", children: [_jsx(SizableText, { size: "$1", color: "$soft", children: `Showing ${from}–${to} of ${shown.length}` }), _jsxs(XStack, { gap: "$3", items: "center", children: [_jsx(XStack, { render: "button", "aria-label": "Previous page", disabled: safePage === 0, onPress: () => setPage(safePage - 1), children: _jsx(SizableText, { size: "$1", color: safePage === 0 ? '$soft' : '$ink', children: "Prev" }) }), _jsx(SizableText, { size: "$1", color: "$soft", children: `${safePage + 1} / ${pages}` }), _jsx(XStack, { render: "button", "aria-label": "Next page", disabled: safePage >= pages - 1, onPress: () => setPage(safePage + 1), children: _jsx(SizableText, { size: "$1", color: safePage >= pages - 1 ? '$soft' : '$ink', children: "Next" }) })] })] })] }))] }), _jsx(NewRepo, { open: making, onOpenChange: setMaking, onCreate: async (name, description) => {
|
|
176
|
+
return (_jsxs(YStack, { flex: 1, minH: 0, overflow: "scroll", px: "$6", py: "$6", children: [_jsxs(YStack, { width: "100%", maxW: 1040, mx: "auto", gap: "$4", children: [_jsxs(XStack, { justify: "space-between", items: "flex-start", gap: "$4", children: [_jsxs(YStack, { gap: "$1", children: [_jsx(SizableText, { size: "$6", fontWeight: "500", color: "$ink", children: host.org || 'Forge' }), _jsx(SizableText, { size: "$2", color: "$soft", children: "Create and browse this organization\u2019s repositories." })] }), _jsxs(XStack, { render: "button", "aria-label": "Settings", items: "center", gap: "$1.5", px: "$2", py: "$1", rounded: "$3", hoverStyle: { bg: '$hover' }, onPress: () => revealAccount(), children: [_jsx(Settings, { size: 14 }), _jsx(SizableText, { size: "$2", color: "$soft", children: "Settings" })] })] }), _jsxs(XStack, { gap: "$2", items: "center", children: [_jsx(XStack, { px: "$2.5", py: "$1.5", rounded: "$3", borderWidth: 1, borderColor: "$borderColor", children: _jsx(SizableText, { size: "$2", color: "$ink", children: "All repos" }) }), _jsx(YStack, { flex: 1 }), _jsx(YStack, { width: 240, minW: 0, children: _jsx(Input, { value: q, onChangeText: setQ, placeholder: "Find repo\u2026", "aria-label": "Find a repository", disabled: !signed }) }), _jsx(Button, { size: "sm", variant: "outline", onPress: () => host.go(path({ kind: 'screen', screen: 'sync' })), children: "Sync" }), _jsxs(Button, { size: "sm", disabled: !signed, onPress: () => setMaking(true), children: [_jsx(Plus, { size: 14 }), "New"] })] }), list.error ? (_jsx(Note, { children: list.error.message })) : !signed ? (_jsx(Note, { children: "Sign in to see this organization's repositories." })) : list.loading && list.value.length === 0 ? (_jsx(Note, { children: "Reading the forge\u2026" })) : shown.length === 0 ? (_jsx(Note, { children: list.value.length === 0 ? 'No repositories yet.' : 'Nothing matches.' })) : (_jsxs(YStack, { borderWidth: 1, borderColor: "$borderColor", rounded: "$3", overflow: "hidden", children: [_jsxs(XStack, { px: "$3", py: "$2", gap: "$3", items: "center", children: [_jsxs(XStack, { flex: 1, render: "button", "aria-label": "Sort by name", items: "center", gap: "$1", onPress: () => setSort('name'), children: [_jsx(SizableText, { size: "$1", color: "$soft", children: "Name" }), sort === 'name' ? _jsx(ChevronDown, { size: 12 }) : null] }), _jsxs(XStack, { render: "button", "aria-label": "Sort by last updated", items: "center", justify: "flex-end", gap: "$1", width: 140, onPress: () => setSort('updated'), children: [_jsx(SizableText, { size: "$1", color: "$soft", children: "Last updated" }), sort === 'updated' ? _jsx(ChevronDown, { size: 12 }) : null] })] }), slice.map((c) => (_jsxs(XStack, { render: "button", "aria-label": `Work on ${c.name}`, onPress: () => open(c), items: "center", gap: "$3", px: "$3", py: "$2.5", borderTopWidth: 1, borderColor: "$borderColor", hoverStyle: { bg: '$hover' }, focusVisibleStyle: { outlineWidth: 2, outlineStyle: 'solid', outlineColor: '$outlineColor' }, children: [_jsx(GitBranch, { size: 14 }), _jsx(SizableText, { flex: 1, size: "$2", color: "$ink", numberOfLines: 1, children: c.name }), _jsx(SizableText, { size: "$1", color: "$soft", width: 140, style: { textAlign: 'right' }, children: syncing.has(c.name) ? 'Syncing…' : when(c.updated) })] }, `${c.org}/${c.name}`))), _jsxs(XStack, { px: "$3", py: "$2", justify: "space-between", items: "center", borderTopWidth: 1, borderColor: "$borderColor", children: [_jsx(SizableText, { size: "$1", color: "$soft", children: `Showing ${from}–${to} of ${shown.length}` }), _jsxs(XStack, { gap: "$3", items: "center", children: [_jsx(XStack, { render: "button", "aria-label": "Previous page", disabled: safePage === 0, onPress: () => setPage(safePage - 1), children: _jsx(SizableText, { size: "$1", color: safePage === 0 ? '$soft' : '$ink', children: "Prev" }) }), _jsx(SizableText, { size: "$1", color: "$soft", children: `${safePage + 1} / ${pages}` }), _jsx(XStack, { render: "button", "aria-label": "Next page", disabled: safePage >= pages - 1, onPress: () => setPage(safePage + 1), children: _jsx(SizableText, { size: "$1", color: safePage >= pages - 1 ? '$soft' : '$ink', children: "Next" }) })] })] })] }))] }), _jsx(NewRepo, { open: making, onOpenChange: setMaking, onCreate: async (name, description) => {
|
|
188
177
|
const row = await create(t, name, description);
|
|
189
178
|
pinCodebase(host.org, row);
|
|
190
179
|
setMaking(false);
|
package/lib/host.d.ts
CHANGED
|
@@ -22,6 +22,10 @@ export interface Host {
|
|
|
22
22
|
token: () => string | null;
|
|
23
23
|
/** The org every call is scoped to. */
|
|
24
24
|
org: string | null;
|
|
25
|
+
/** The organizations this person belongs to. The switcher lists these and no others. */
|
|
26
|
+
memberships?: readonly string[];
|
|
27
|
+
/** Stay on this page and scope every read to `org`. */
|
|
28
|
+
chooseOrg?: (org: string) => void;
|
|
25
29
|
/** Who is signed in, or null. */
|
|
26
30
|
person: Person | null;
|
|
27
31
|
/** Whether the person administers `org`: an admin publishes to main, anyone else opens a review. */
|
package/lib/switch.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function Where(): import("react").JSX.Element;
|
package/lib/switch.js
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* The rail's top left: the organization, and the projects under it.
|
|
4
|
+
*
|
|
5
|
+
* The account stays at the foot of the rail. Settings opens that account on
|
|
6
|
+
* this page. Choosing an organization reloads this origin so every read is
|
|
7
|
+
* scoped to it.
|
|
8
|
+
*/
|
|
9
|
+
import { YStack } from '@hanzo/gui';
|
|
10
|
+
import { MenuLabel, MenuRow, MenuRule, OrgSwitcher } from '@hanzo/ui/product';
|
|
11
|
+
import { revealAccount } from './account.js';
|
|
12
|
+
import { projects } from './api/projects.js';
|
|
13
|
+
import { useRead } from './data.js';
|
|
14
|
+
import { useHost, useTarget } from './host.js';
|
|
15
|
+
import { route } from './route.js';
|
|
16
|
+
export function Where() {
|
|
17
|
+
const host = useHost();
|
|
18
|
+
const t = useTarget();
|
|
19
|
+
const signed = Boolean(host.person);
|
|
20
|
+
const list = useRead(signed ? () => projects(t) : null, [], [t, signed]);
|
|
21
|
+
const here = route(host.path);
|
|
22
|
+
const current = host.org || '';
|
|
23
|
+
const scope = {
|
|
24
|
+
currentOrg: () => current,
|
|
25
|
+
setCurrentOrg: (next) => host.chooseOrg?.(next),
|
|
26
|
+
isScopedAway: () => false,
|
|
27
|
+
hasSelectedOrg: () => Boolean(current),
|
|
28
|
+
enterOrg: (next) => host.chooseOrg?.(next),
|
|
29
|
+
leaveOrg: () => undefined,
|
|
30
|
+
switchOrg: (next) => host.chooseOrg?.(next),
|
|
31
|
+
};
|
|
32
|
+
const rows = () => Promise.resolve((host.memberships ?? (current ? [current] : [])).map((name) => ({ name, displayName: name })));
|
|
33
|
+
return (_jsx(OrgSwitcher, { scope: scope, orgs: (page) => (page === 0 ? rows() : Promise.resolve([])), pageSize: 50, search: false, heading: "Organization", lead: true, sub: here.kind === 'project' ? here.slug : undefined, current: current ? { name: current, displayName: current } : undefined, aria: current ? `Organization ${current}` : 'Organization', footer: (close) => (_jsxs(YStack, { gap: "$1", children: [list.value.length > 0 ? (_jsxs(_Fragment, { children: [_jsx(MenuRule, {}), _jsx(MenuLabel, { children: "Project" }), _jsx(YStack, { role: "radiogroup", "aria-label": "Projects", gap: "$1", children: list.value.slice(0, 12).map((p) => (_jsx(MenuRow, { label: p.name || p.slug, active: here.kind === 'project' && here.slug === p.slug, onPress: () => {
|
|
34
|
+
close();
|
|
35
|
+
host.go(p.slug);
|
|
36
|
+
} }, p.slug))) })] })) : null, _jsx(MenuRule, {}), _jsx(MenuRow, { label: "Settings", onPress: () => {
|
|
37
|
+
close();
|
|
38
|
+
revealAccount();
|
|
39
|
+
} })] })) }));
|
|
40
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/build",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0 OR MIT",
|
|
6
6
|
"description": "Hanzo Build — say what you want, watch it built, deployed and running. The builder as a page (hanzo.build) and as a component (hanzo.ai/dev).",
|