@hanzo/ui 8.0.5 → 8.0.6
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/package.json +1 -1
- package/src/product/AppHeader.tsx +34 -26
- package/src/product/index.ts +2 -0
- package/src/product/surfaces.data.ts +42 -0
- package/types/product/AppHeader.d.ts +5 -11
- package/types/product/AppHeader.d.ts.map +1 -1
- package/types/product/index.d.ts +1 -0
- package/types/product/index.d.ts.map +1 -1
- package/types/product/surfaces.data.d.ts +17 -0
- package/types/product/surfaces.data.d.ts.map +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hanzo/ui",
|
|
3
|
-
"version": "8.0.
|
|
3
|
+
"version": "8.0.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Hanzo UI \u2014 the one cross-platform component library on @hanzo/gui. The product/app layer (charts, metrics, page headers, status tags, rich empty states, combobox, slide-over, toasts, drag-reorder, labeled field rows, provider/product marks) + the metadata-driven record layer (@hanzo/data: RecordsView, DataTable, board, typed field editors) + the calm dark-first tokens and motion. Presentational, host-agnostic (data/effects injected), clean-room. Web + native (iOS) + desktop.",
|
|
6
6
|
"exports": {
|
|
@@ -13,22 +13,22 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { useState, type ReactNode } from 'react'
|
|
15
15
|
import { Button, Popover, Separator, Text, XStack, YStack } from '@hanzo/gui'
|
|
16
|
-
import { CreditCard, Grip, LogOut, Settings2, UserRound } from '@hanzogui/lucide-icons-2'
|
|
16
|
+
import { AppWindow, Bot, CreditCard, Grip, LayoutGrid, LogOut, MessageCircle, Settings2, Sparkles, UserRound, Users } from '@hanzogui/lucide-icons-2'
|
|
17
17
|
|
|
18
18
|
import { BrandMark } from './BrandMark'
|
|
19
19
|
import { ThemeToggle } from './ThemeToggle'
|
|
20
|
+
import { otherSurfaces, type Surface, type SurfaceId } from './surfaces.data'
|
|
20
21
|
|
|
21
|
-
/**
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
]
|
|
22
|
+
/** The per-surface glyph — keyed by `Surface.id`, so each surface reads distinctly. */
|
|
23
|
+
const SURFACE_ICON = {
|
|
24
|
+
ai: Sparkles,
|
|
25
|
+
console: LayoutGrid,
|
|
26
|
+
app: AppWindow,
|
|
27
|
+
chat: MessageCircle,
|
|
28
|
+
bot: Bot,
|
|
29
|
+
team: Users,
|
|
30
|
+
billing: CreditCard,
|
|
31
|
+
} as const satisfies Record<SurfaceId, unknown>
|
|
32
32
|
|
|
33
33
|
const openHref = (href: string) => {
|
|
34
34
|
if (typeof window !== 'undefined') window.open(href, '_blank', 'noopener')
|
|
@@ -56,7 +56,9 @@ export type AppHeaderProps = {
|
|
|
56
56
|
org?: ReactNode
|
|
57
57
|
/** Free slot between the org slot and the right cluster. */
|
|
58
58
|
children?: ReactNode
|
|
59
|
-
/**
|
|
59
|
+
/** The surface this header renders on — omitted from the switcher (no self-link). */
|
|
60
|
+
current?: SurfaceId
|
|
61
|
+
/** App-switcher surfaces; defaults to every surface but `current`. [] hides it. */
|
|
60
62
|
surfaces?: Surface[]
|
|
61
63
|
/** Open a surface — default `window.open` (new tab). */
|
|
62
64
|
open?: (surface: Surface) => void
|
|
@@ -78,7 +80,8 @@ export function AppHeader({
|
|
|
78
80
|
onBrand,
|
|
79
81
|
org,
|
|
80
82
|
children,
|
|
81
|
-
|
|
83
|
+
current,
|
|
84
|
+
surfaces,
|
|
82
85
|
open,
|
|
83
86
|
user,
|
|
84
87
|
menu,
|
|
@@ -90,6 +93,7 @@ export function AppHeader({
|
|
|
90
93
|
}: AppHeaderProps) {
|
|
91
94
|
const [appsOpen, setAppsOpen] = useState(false)
|
|
92
95
|
const [menuOpen, setMenuOpen] = useState(false)
|
|
96
|
+
const items = surfaces ?? otherSurfaces(current)
|
|
93
97
|
const launch = (s: Surface) => {
|
|
94
98
|
setAppsOpen(false)
|
|
95
99
|
if (open) open(s)
|
|
@@ -112,25 +116,29 @@ export function AppHeader({
|
|
|
112
116
|
{children}
|
|
113
117
|
</XStack>
|
|
114
118
|
|
|
115
|
-
{
|
|
119
|
+
{items.length > 0 ? (
|
|
116
120
|
<Popover open={appsOpen} onOpenChange={setAppsOpen} placement="bottom-end">
|
|
117
121
|
<Popover.Trigger asChild>
|
|
118
122
|
<Button size="$2" chromeless icon={<Grip size={16} />} aria-label="Apps" />
|
|
119
123
|
</Popover.Trigger>
|
|
120
124
|
<Popover.Content bordered elevate p="$2" width={230} bg="$color2" borderColor="$borderColor">
|
|
121
125
|
<YStack gap="$1">
|
|
122
|
-
{
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
{s.hint}
|
|
126
|
+
{items.map((s) => {
|
|
127
|
+
const Icon = SURFACE_ICON[s.id]
|
|
128
|
+
return (
|
|
129
|
+
<XStack key={s.id} onPress={() => launch(s)} cursor="pointer" items="center" gap="$2.5" px="$2" py="$2" rounded="$3" hoverStyle={{ bg: '$color5' }}>
|
|
130
|
+
<Icon size={16} />
|
|
131
|
+
<Text flex={1} fontSize="$2" fontWeight="600" color="$color12">
|
|
132
|
+
{s.label}
|
|
130
133
|
</Text>
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
+
{s.hint ? (
|
|
135
|
+
<Text fontSize="$1" color="$color10">
|
|
136
|
+
{s.hint}
|
|
137
|
+
</Text>
|
|
138
|
+
) : null}
|
|
139
|
+
</XStack>
|
|
140
|
+
)
|
|
141
|
+
})}
|
|
134
142
|
</YStack>
|
|
135
143
|
</Popover.Content>
|
|
136
144
|
</Popover>
|
package/src/product/index.ts
CHANGED
|
@@ -40,6 +40,8 @@ export * from './combobox/filter'
|
|
|
40
40
|
|
|
41
41
|
// The shared shell — brand mark, org scope + switcher, app header (the
|
|
42
42
|
// console's org-scope contract + switcher hoisted here; hanzoai/ui#36).
|
|
43
|
+
// `surfaces.data` is the ONE canonical cross-surface list every launcher consumes.
|
|
44
|
+
export * from './surfaces.data'
|
|
43
45
|
export * from './AppHeader'
|
|
44
46
|
export * from './BrandMark'
|
|
45
47
|
export * from './OrgSwitcher'
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// The ONE canonical list of Hanzo product surfaces the cross-surface app switcher
|
|
2
|
+
// offers — consumed by EVERY surface's launcher so the set never diverges.
|
|
3
|
+
//
|
|
4
|
+
// Framework-agnostic (plain TS, zero imports): React consumers (the @hanzo/ui
|
|
5
|
+
// `AppHeader`, the console `AppLauncher`) import it directly; a surface that
|
|
6
|
+
// cannot resolve THIS package — the Svelte Huly-fork `team` (whose own `@hanzo/ui`
|
|
7
|
+
// is the workbench UI framework, a name clash) and the shadcn-aliased `app` — keeps
|
|
8
|
+
// a byte-identical MIRROR that points back here. Add or reorder a surface HERE and
|
|
9
|
+
// every launcher moves together (mirrors are updated in the same change).
|
|
10
|
+
//
|
|
11
|
+
// `id` is the stable key AND the icon key: each framework maps it to its own glyph
|
|
12
|
+
// (React → lucide, Svelte → SurfaceIcon), so the DATA itself stays glyph-free.
|
|
13
|
+
|
|
14
|
+
export type SurfaceId = 'ai' | 'console' | 'app' | 'chat' | 'bot' | 'team' | 'billing'
|
|
15
|
+
|
|
16
|
+
/** One Hanzo surface the app switcher offers. */
|
|
17
|
+
export type Surface = {
|
|
18
|
+
/** Stable id; also the per-surface icon key. */
|
|
19
|
+
id: SurfaceId
|
|
20
|
+
/** Menu label. */
|
|
21
|
+
label: string
|
|
22
|
+
/** Absolute product URL (opened in a new tab). */
|
|
23
|
+
href: string
|
|
24
|
+
/** The domain, shown as the tile subtitle. */
|
|
25
|
+
hint: string
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/** The seven Hanzo surfaces (`console` opens the cloud AI console). */
|
|
29
|
+
export const SURFACES: Surface[] = [
|
|
30
|
+
{ id: 'ai', label: 'Hanzo AI', href: 'https://hanzo.ai', hint: 'hanzo.ai' },
|
|
31
|
+
{ id: 'console', label: 'Console', href: 'https://console.hanzo.ai', hint: 'console.hanzo.ai' },
|
|
32
|
+
{ id: 'app', label: 'App', href: 'https://hanzo.app', hint: 'hanzo.app' },
|
|
33
|
+
{ id: 'chat', label: 'Chat', href: 'https://hanzo.chat', hint: 'hanzo.chat' },
|
|
34
|
+
{ id: 'bot', label: 'Bot', href: 'https://hanzo.bot', hint: 'hanzo.bot' },
|
|
35
|
+
{ id: 'team', label: 'Team', href: 'https://hanzo.team', hint: 'hanzo.team' },
|
|
36
|
+
{ id: 'billing', label: 'Billing', href: 'https://billing.hanzo.ai', hint: 'billing.hanzo.ai' },
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
/** Every surface except `current` — a launcher never links to itself. */
|
|
40
|
+
export function otherSurfaces(current?: SurfaceId): Surface[] {
|
|
41
|
+
return current ? SURFACES.filter((s) => s.id !== current) : SURFACES
|
|
42
|
+
}
|
|
@@ -10,15 +10,7 @@
|
|
|
10
10
|
* flex + truncation, the wordmark collapse is the brand motion itself.
|
|
11
11
|
*/
|
|
12
12
|
import { type ReactNode } from 'react';
|
|
13
|
-
|
|
14
|
-
export type Surface = {
|
|
15
|
-
id: string;
|
|
16
|
-
label: string;
|
|
17
|
-
href: string;
|
|
18
|
-
hint?: string;
|
|
19
|
-
};
|
|
20
|
-
/** The five Hanzo surfaces (cloud opens the console). */
|
|
21
|
-
export declare const SURFACES: Surface[];
|
|
13
|
+
import { type Surface, type SurfaceId } from './surfaces.data';
|
|
22
14
|
export type AppHeaderProps = {
|
|
23
15
|
/** Brand slot — defaults to the animated `<BrandMark/>`. */
|
|
24
16
|
brand?: ReactNode;
|
|
@@ -30,7 +22,9 @@ export type AppHeaderProps = {
|
|
|
30
22
|
org?: ReactNode;
|
|
31
23
|
/** Free slot between the org slot and the right cluster. */
|
|
32
24
|
children?: ReactNode;
|
|
33
|
-
/**
|
|
25
|
+
/** The surface this header renders on — omitted from the switcher (no self-link). */
|
|
26
|
+
current?: SurfaceId;
|
|
27
|
+
/** App-switcher surfaces; defaults to every surface but `current`. [] hides it. */
|
|
34
28
|
surfaces?: Surface[];
|
|
35
29
|
/** Open a surface — default `window.open` (new tab). */
|
|
36
30
|
open?: (surface: Surface) => void;
|
|
@@ -45,5 +39,5 @@ export type AppHeaderProps = {
|
|
|
45
39
|
onBilling?: () => void;
|
|
46
40
|
onSignOut?: () => void;
|
|
47
41
|
};
|
|
48
|
-
export declare function AppHeader({ brand, wordmark, onBrand, org, children, surfaces, open, user, menu, theme, onProfile, onTeam, onBilling, onSignOut, }: AppHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
42
|
+
export declare function AppHeader({ brand, wordmark, onBrand, org, children, current, surfaces, open, user, menu, theme, onProfile, onTeam, onBilling, onSignOut, }: AppHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
49
43
|
//# sourceMappingURL=AppHeader.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"AppHeader.d.ts","sourceRoot":"","sources":["../../src/product/AppHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAMhD,OAAO,EAAiB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,iBAAiB,CAAA;AA4B7E,MAAM,MAAM,cAAc,GAAG;IAC3B,4DAA4D;IAC5D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,uDAAuD;IACvD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,0EAA0E;IAC1E,GAAG,CAAC,EAAE,SAAS,CAAA;IACf,4DAA4D;IAC5D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,qFAAqF;IACrF,OAAO,CAAC,EAAE,SAAS,CAAA;IACnB,mFAAmF;IACnF,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAA;IACpB,wDAAwD;IACxD,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAA;IACjC,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,+CAA+C;IAC/C,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,wEAAwE;IACxE,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AAED,wBAAgB,SAAS,CAAC,EACxB,KAAK,EACL,QAAkB,EAClB,OAAO,EACP,GAAG,EACH,QAAQ,EACR,OAAO,EACP,QAAQ,EACR,IAAI,EACJ,IAAI,EACJ,IAAI,EACJ,KAAK,EACL,SAAS,EACT,MAAM,EACN,SAAS,EACT,SAAS,GACV,EAAE,cAAc,2CA0FhB"}
|
package/types/product/index.d.ts
CHANGED
|
@@ -3,6 +3,7 @@ export { SERIES, colorForIndex, utilColor, Sparkline as MetricSparkline, MiniBar
|
|
|
3
3
|
export { Donut as DonutRing, type DonutSegment } from './Donut';
|
|
4
4
|
export { ComboBox } from './ComboBox';
|
|
5
5
|
export * from './combobox/filter';
|
|
6
|
+
export * from './surfaces.data';
|
|
6
7
|
export * from './AppHeader';
|
|
7
8
|
export * from './BrandMark';
|
|
8
9
|
export * from './OrgSwitcher';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/product/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAA;AAKxB,OAAO,EACL,MAAM,EACN,aAAa,EACb,SAAS,EACT,SAAS,IAAI,eAAe,EAC5B,QAAQ,EACR,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,KAAK,GACN,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAK/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,cAAc,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/product/index.ts"],"names":[],"mappings":"AAaA,cAAc,UAAU,CAAA;AAKxB,OAAO,EACL,MAAM,EACN,aAAa,EACb,SAAS,EACT,SAAS,IAAI,eAAe,EAC5B,QAAQ,EACR,OAAO,EACP,SAAS,EACT,UAAU,EACV,UAAU,EACV,KAAK,GACN,MAAM,UAAU,CAAA;AAGjB,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,KAAK,YAAY,EAAE,MAAM,SAAS,CAAA;AAK/D,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AACrC,cAAc,mBAAmB,CAAA;AAKjC,cAAc,iBAAiB,CAAA;AAC/B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AAGvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,UAAU,CAAA;AACxB,cAAc,SAAS,CAAA;AACvB,cAAc,aAAa,CAAA;AAC3B,cAAc,cAAc,CAAA;AAC5B,cAAc,iBAAiB,CAAA;AAC/B,cAAc,eAAe,CAAA;AAC7B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,WAAW,CAAA;AACzB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,eAAe,CAAA;AAC7B,cAAc,SAAS,CAAA;AACvB,cAAc,SAAS,CAAA"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type SurfaceId = 'ai' | 'console' | 'app' | 'chat' | 'bot' | 'team' | 'billing';
|
|
2
|
+
/** One Hanzo surface the app switcher offers. */
|
|
3
|
+
export type Surface = {
|
|
4
|
+
/** Stable id; also the per-surface icon key. */
|
|
5
|
+
id: SurfaceId;
|
|
6
|
+
/** Menu label. */
|
|
7
|
+
label: string;
|
|
8
|
+
/** Absolute product URL (opened in a new tab). */
|
|
9
|
+
href: string;
|
|
10
|
+
/** The domain, shown as the tile subtitle. */
|
|
11
|
+
hint: string;
|
|
12
|
+
};
|
|
13
|
+
/** The seven Hanzo surfaces (`console` opens the cloud AI console). */
|
|
14
|
+
export declare const SURFACES: Surface[];
|
|
15
|
+
/** Every surface except `current` — a launcher never links to itself. */
|
|
16
|
+
export declare function otherSurfaces(current?: SurfaceId): Surface[];
|
|
17
|
+
//# sourceMappingURL=surfaces.data.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"surfaces.data.d.ts","sourceRoot":"","sources":["../../src/product/surfaces.data.ts"],"names":[],"mappings":"AAaA,MAAM,MAAM,SAAS,GAAG,IAAI,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,SAAS,CAAA;AAEtF,iDAAiD;AACjD,MAAM,MAAM,OAAO,GAAG;IACpB,gDAAgD;IAChD,EAAE,EAAE,SAAS,CAAA;IACb,kBAAkB;IAClB,KAAK,EAAE,MAAM,CAAA;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAA;IACZ,8CAA8C;IAC9C,IAAI,EAAE,MAAM,CAAA;CACb,CAAA;AAED,uEAAuE;AACvE,eAAO,MAAM,QAAQ,EAAE,OAAO,EAQ7B,CAAA;AAED,yEAAyE;AACzE,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,OAAO,EAAE,CAE5D"}
|