@hanzo/ui 8.30.3 → 8.31.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.
- package/dist/auth/signout.cjs +23 -5
- package/dist/auth/signout.d.ts +23 -2
- package/dist/auth/signout.d.ts.map +1 -1
- package/dist/auth/signout.js +22 -5
- package/dist/auth/signout.js.map +1 -1
- package/dist/backends/gui/dialog.cjs +1 -1
- package/dist/backends/gui/dialog.js +1 -1
- package/dist/backends/gui/dialog.js.map +1 -1
- package/dist/gallery.html +1 -1
- package/dist/models/catalog.cjs +38 -3
- package/dist/models/catalog.d.ts +1 -1
- package/dist/models/catalog.d.ts.map +1 -1
- package/dist/models/catalog.js +38 -3
- package/dist/models/catalog.js.map +1 -1
- package/dist/models/picker.logic.cjs +10 -1
- package/dist/models/picker.logic.d.ts.map +1 -1
- package/dist/models/picker.logic.js +11 -2
- package/dist/models/picker.logic.js.map +1 -1
- package/dist/product/BusinessHeader.cjs +347 -0
- package/dist/product/BusinessHeader.d.ts +113 -0
- package/dist/product/BusinessHeader.d.ts.map +1 -0
- package/dist/product/BusinessHeader.js +343 -0
- package/dist/product/BusinessHeader.js.map +1 -0
- package/dist/product/index.cjs +1 -0
- package/dist/product/index.d.ts +1 -0
- package/dist/product/index.d.ts.map +1 -1
- package/dist/product/index.js +1 -0
- package/dist/product/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
'use client';"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.BUSINESS_APPS = void 0;
|
|
5
|
+
exports.buildSeamlessAppUrl = buildSeamlessAppUrl;
|
|
6
|
+
exports.BusinessHeader = BusinessHeader;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
/**
|
|
9
|
+
* BusinessHeader — the universal global header for every Hanzo Business application
|
|
10
|
+
* (`hanzo.team`, `crm.hanzo.ai`, `cms.hanzo.ai`, `marketing.hanzo.ai`, `ads.hanzo.ai`,
|
|
11
|
+
* `social.hanzo.ai`, `console.hanzo.ai`, `platform.hanzo.ai`, etc.).
|
|
12
|
+
*
|
|
13
|
+
* Layout & Behavior:
|
|
14
|
+
* - Top Left:
|
|
15
|
+
* 1. Product identity + App Switcher trigger (`Hanzo CRM ▾`, `Hanzo Team ▾`, etc.)
|
|
16
|
+
* Opening the App Switcher lists CRM, Work (Team), CMS, Email, Ads, Cal, Bots,
|
|
17
|
+
* Social, Chat, Dev, Commerce, Analytics, Data Room, Sign, Billing, Console, Platform.
|
|
18
|
+
* 2. Current organization beneath the product identity (e.g. `Hanzo AI`), clickable
|
|
19
|
+
* to switch organizations.
|
|
20
|
+
* - Center:
|
|
21
|
+
* Breadcrumbs / Command Search (`children`).
|
|
22
|
+
* - Top Right:
|
|
23
|
+
* Signed-in user's avatar + display name + Account Menu:
|
|
24
|
+
* - Identity card showing Display Name, Email, and `Current account` indicator
|
|
25
|
+
* - Switch account (choose between authenticated identities on this browser,
|
|
26
|
+
* never confused with organizations)
|
|
27
|
+
* - Add another account (`prompt=login` without ending existing sessions)
|
|
28
|
+
* - Switch organization (choose between organizations the user belongs to)
|
|
29
|
+
* - Settings & Theme
|
|
30
|
+
* - Sign out
|
|
31
|
+
*/
|
|
32
|
+
const react_1 = require("react");
|
|
33
|
+
const gui_1 = require("@hanzo/gui");
|
|
34
|
+
const lucide_icons_2_1 = require("@hanzogui/lucide-icons-2");
|
|
35
|
+
const BrandMark_1 = require("./BrandMark.cjs");
|
|
36
|
+
const name_1 = require("./name.cjs");
|
|
37
|
+
const OrgMark_1 = require("./OrgMark.cjs");
|
|
38
|
+
exports.BUSINESS_APPS = [
|
|
39
|
+
{
|
|
40
|
+
id: 'crm',
|
|
41
|
+
label: 'CRM',
|
|
42
|
+
productTitle: 'Hanzo CRM',
|
|
43
|
+
description: 'Pipeline, contacts, investors & deals',
|
|
44
|
+
href: 'https://crm.hanzo.ai',
|
|
45
|
+
supportsFreshAuth: true,
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'team',
|
|
49
|
+
label: 'Work',
|
|
50
|
+
productTitle: 'Hanzo Team',
|
|
51
|
+
description: 'Shared workspace, docs, tasks & drive',
|
|
52
|
+
href: 'https://hanzo.team',
|
|
53
|
+
supportsFreshAuth: false,
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: 'cms',
|
|
57
|
+
label: 'CMS',
|
|
58
|
+
productTitle: 'Hanzo CMS',
|
|
59
|
+
description: 'Content, pages, collections & media',
|
|
60
|
+
href: 'https://cms.hanzo.ai/admin',
|
|
61
|
+
supportsFreshAuth: false,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
id: 'email',
|
|
65
|
+
label: 'Email',
|
|
66
|
+
productTitle: 'Hanzo Email',
|
|
67
|
+
description: 'Campaigns, journeys & broadcasts',
|
|
68
|
+
href: 'https://marketing.hanzo.ai',
|
|
69
|
+
supportsFreshAuth: true,
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
id: 'ads',
|
|
73
|
+
label: 'Ads',
|
|
74
|
+
productTitle: 'Hanzo Ads',
|
|
75
|
+
description: 'Ad spend, ROAS & attribution',
|
|
76
|
+
href: 'https://ads.hanzo.ai',
|
|
77
|
+
supportsFreshAuth: true,
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
id: 'cal',
|
|
81
|
+
label: 'Cal',
|
|
82
|
+
productTitle: 'Hanzo Cal',
|
|
83
|
+
description: 'Scheduling, bookings & availability',
|
|
84
|
+
href: 'https://hanzo.team/cal',
|
|
85
|
+
supportsFreshAuth: false,
|
|
86
|
+
},
|
|
87
|
+
{
|
|
88
|
+
id: 'bots',
|
|
89
|
+
label: 'Bots',
|
|
90
|
+
productTitle: 'Hanzo Bots',
|
|
91
|
+
description: 'Autonomous AI agents & workflows',
|
|
92
|
+
href: 'https://hanzo.bot',
|
|
93
|
+
supportsFreshAuth: false,
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
id: 'social',
|
|
97
|
+
label: 'Social',
|
|
98
|
+
productTitle: 'Hanzo Publish',
|
|
99
|
+
description: 'Social scheduling, inbox & listening',
|
|
100
|
+
href: 'https://social.hanzo.ai',
|
|
101
|
+
supportsFreshAuth: true,
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
id: 'chat',
|
|
105
|
+
label: 'Chat',
|
|
106
|
+
productTitle: 'Hanzo Chat',
|
|
107
|
+
description: 'AI assistant, models & playground',
|
|
108
|
+
href: 'https://hanzo.ai/chat',
|
|
109
|
+
supportsFreshAuth: false,
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
id: 'dev',
|
|
113
|
+
label: 'Dev',
|
|
114
|
+
productTitle: 'Hanzo Dev',
|
|
115
|
+
description: 'Coding agents & cloud workspaces',
|
|
116
|
+
href: 'https://hanzo.ai/dev',
|
|
117
|
+
supportsFreshAuth: false,
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
id: 'commerce',
|
|
121
|
+
label: 'Commerce',
|
|
122
|
+
productTitle: 'Hanzo Commerce',
|
|
123
|
+
description: 'Store, products, orders & subscriptions',
|
|
124
|
+
href: 'https://commerce-admin.hanzo.ai/admin/',
|
|
125
|
+
supportsFreshAuth: false,
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'analytics',
|
|
129
|
+
label: 'Analytics',
|
|
130
|
+
productTitle: 'Hanzo Analytics',
|
|
131
|
+
description: 'Web traffic, funnels & retention',
|
|
132
|
+
href: 'https://analytics.hanzo.ai',
|
|
133
|
+
supportsFreshAuth: false,
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
id: 'dataroom',
|
|
137
|
+
label: 'Data Room',
|
|
138
|
+
productTitle: 'Hanzo Data Room',
|
|
139
|
+
description: 'Secure investor & deal data rooms',
|
|
140
|
+
href: 'https://dataroom.hanzo.ai',
|
|
141
|
+
supportsFreshAuth: false,
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
id: 'sign',
|
|
145
|
+
label: 'Sign',
|
|
146
|
+
productTitle: 'Hanzo Sign',
|
|
147
|
+
description: 'Document e-signatures & agreements',
|
|
148
|
+
href: 'https://esign.hanzo.ai',
|
|
149
|
+
supportsFreshAuth: false,
|
|
150
|
+
},
|
|
151
|
+
{
|
|
152
|
+
id: 'billing',
|
|
153
|
+
label: 'Billing',
|
|
154
|
+
productTitle: 'Hanzo Billing',
|
|
155
|
+
description: 'Usage, balance, invoices & payment methods',
|
|
156
|
+
href: 'https://billing.hanzo.ai',
|
|
157
|
+
supportsFreshAuth: false,
|
|
158
|
+
},
|
|
159
|
+
{
|
|
160
|
+
id: 'console',
|
|
161
|
+
label: 'Console',
|
|
162
|
+
productTitle: 'Hanzo Console',
|
|
163
|
+
description: 'Cloud, AI infrastructure & IAM',
|
|
164
|
+
href: 'https://console.hanzo.ai',
|
|
165
|
+
supportsFreshAuth: true,
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
id: 'platform',
|
|
169
|
+
label: 'Platform',
|
|
170
|
+
productTitle: 'Hanzo Platform',
|
|
171
|
+
description: 'PaaS deployments, clusters & containers',
|
|
172
|
+
href: 'https://platform.hanzo.ai',
|
|
173
|
+
supportsFreshAuth: true,
|
|
174
|
+
},
|
|
175
|
+
];
|
|
176
|
+
function AppIcon({ id, size = 16 }) {
|
|
177
|
+
switch (id) {
|
|
178
|
+
case 'crm':
|
|
179
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Briefcase, { size: size });
|
|
180
|
+
case 'team':
|
|
181
|
+
case 'work':
|
|
182
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Users, { size: size });
|
|
183
|
+
case 'cms':
|
|
184
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Globe, { size: size });
|
|
185
|
+
case 'email':
|
|
186
|
+
case 'marketing':
|
|
187
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Mail, { size: size });
|
|
188
|
+
case 'ads':
|
|
189
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Megaphone, { size: size });
|
|
190
|
+
case 'cal':
|
|
191
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Calendar, { size: size });
|
|
192
|
+
case 'bots':
|
|
193
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Bot, { size: size });
|
|
194
|
+
case 'social':
|
|
195
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Share2, { size: size });
|
|
196
|
+
case 'chat':
|
|
197
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.MessageCircle, { size: size });
|
|
198
|
+
case 'dev':
|
|
199
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Terminal, { size: size });
|
|
200
|
+
case 'commerce':
|
|
201
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ShoppingBag, { size: size });
|
|
202
|
+
case 'analytics':
|
|
203
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.BarChart3, { size: size });
|
|
204
|
+
case 'dataroom':
|
|
205
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.FolderLock, { size: size });
|
|
206
|
+
case 'sign':
|
|
207
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.FileSignature, { size: size });
|
|
208
|
+
case 'billing':
|
|
209
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.CreditCard, { size: size });
|
|
210
|
+
case 'console':
|
|
211
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Sparkles, { size: size });
|
|
212
|
+
case 'platform':
|
|
213
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.LayoutGrid, { size: size });
|
|
214
|
+
default:
|
|
215
|
+
return (0, jsx_runtime_1.jsx)(lucide_icons_2_1.AppWindow, { size: size });
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/** Build a session-preserving destination URL when switching between Hanzo Business apps. */
|
|
219
|
+
function buildSeamlessAppUrl(app, opts) {
|
|
220
|
+
try {
|
|
221
|
+
const u = new URL(app.href);
|
|
222
|
+
if (app.supportsFreshAuth && opts?.who) {
|
|
223
|
+
const nextPath = opts?.org ? `/?org=${encodeURIComponent(opts.org)}` : '/';
|
|
224
|
+
return `${u.origin}/auth/fresh?next=${encodeURIComponent(nextPath)}&who=${encodeURIComponent(opts.who)}`;
|
|
225
|
+
}
|
|
226
|
+
if (opts?.org && !u.searchParams.has('org')) {
|
|
227
|
+
u.searchParams.set('org', opts.org);
|
|
228
|
+
}
|
|
229
|
+
return u.toString();
|
|
230
|
+
}
|
|
231
|
+
catch {
|
|
232
|
+
return app.href;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
function BusinessHeader({ appId = 'crm', appTitle, showAppTitle = false, apps = exports.BUSINESS_APPS, onSelectApp, brandMark, currentOrg, orgs = [], onSelectOrg, onAllOrgs, onCreateOrg, leftSlot, children, rightSlot, user, accounts = [], onSwitchAccount, onAddAccount, onSettings, onOrgSettings, onBilling, theme, onSignOut, }) {
|
|
236
|
+
const [appMenuOpen, setAppMenuOpen] = (0, react_1.useState)(false);
|
|
237
|
+
const [orgMenuOpen, setOrgMenuOpen] = (0, react_1.useState)(false);
|
|
238
|
+
const [accountMenuOpen, setAccountMenuOpen] = (0, react_1.useState)(false);
|
|
239
|
+
const activeApp = apps.find((a) => a.id === appId) ?? apps[0];
|
|
240
|
+
const resolvedAppTitle = appTitle || activeApp?.productTitle || 'Hanzo CRM';
|
|
241
|
+
const orgDisplay = currentOrg?.displayName?.trim() || currentOrg?.name || 'Hanzo AI';
|
|
242
|
+
const userName = (0, name_1.displayName)(user?.name, user?.email) || 'Account';
|
|
243
|
+
const userEmail = user?.email || '';
|
|
244
|
+
const userSub = user?.sub || '';
|
|
245
|
+
// Deduplicate accounts list while keeping current user identifiable
|
|
246
|
+
const knownAccounts = (() => {
|
|
247
|
+
const list = [];
|
|
248
|
+
const seen = new Set();
|
|
249
|
+
if (userSub) {
|
|
250
|
+
seen.add(userSub);
|
|
251
|
+
list.push({
|
|
252
|
+
sub: userSub,
|
|
253
|
+
owner: user?.owner || currentOrg?.name || 'hanzo',
|
|
254
|
+
name: userName,
|
|
255
|
+
email: userEmail || undefined,
|
|
256
|
+
avatar: user?.avatar,
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
for (const acc of accounts) {
|
|
260
|
+
if (acc.sub && !seen.has(acc.sub)) {
|
|
261
|
+
seen.add(acc.sub);
|
|
262
|
+
list.push(acc);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return list;
|
|
266
|
+
})();
|
|
267
|
+
const handleLaunchApp = (app) => {
|
|
268
|
+
setAppMenuOpen(false);
|
|
269
|
+
if (onSelectApp) {
|
|
270
|
+
onSelectApp(app);
|
|
271
|
+
return;
|
|
272
|
+
}
|
|
273
|
+
if (typeof window !== 'undefined') {
|
|
274
|
+
const targetUrl = buildSeamlessAppUrl(app, {
|
|
275
|
+
who: userSub || undefined,
|
|
276
|
+
org: currentOrg?.name || undefined,
|
|
277
|
+
});
|
|
278
|
+
window.location.assign(targetUrl);
|
|
279
|
+
}
|
|
280
|
+
};
|
|
281
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { render: "header", height: 52, px: "$3", gap: "$3", items: "center", justify: "space-between", borderBottomWidth: 1, borderColor: "$borderColor", bg: "$background", shrink: 0, "data-slot": "bar", "data-testid": "hanzo-business-header", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", minW: 0, shrink: 0, children: [leftSlot, (0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: appMenuOpen, onOpenChange: setAppMenuOpen, placement: "bottom-start", allowFlip: true, stayInFrame: true, children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "button", tabIndex: 0, cursor: "pointer", items: "center", gap: "$1.5", height: 34, px: "$2", rounded: "$3", borderWidth: 0, outlineWidth: 0, hoverStyle: { bg: '$color3' }, "aria-label": `${resolvedAppTitle} — Switch application`, "aria-haspopup": "menu", "aria-expanded": appMenuOpen, "data-testid": "business-app-switcher-trigger", onKeyDown: (e) => {
|
|
282
|
+
if (e?.key === 'Enter' || e?.key === ' ') {
|
|
283
|
+
e.preventDefault?.();
|
|
284
|
+
setAppMenuOpen(!appMenuOpen);
|
|
285
|
+
}
|
|
286
|
+
}, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { items: "center", justify: "center", width: 24, height: 24, shrink: 0, children: brandMark ?? (0, jsx_runtime_1.jsx)(BrandMark_1.BrandMark, { size: 20, wordmark: "" }) }), showAppTitle ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$3", fontWeight: "700", color: "$color12", numberOfLines: 1, children: resolvedAppTitle })) : null, (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 13, color: "$color10" })] }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { role: "menu", "aria-label": "Hanzo Business Applications", borderWidth: 1, elevation: "$4", p: "$2.5", width: 360, bg: "$background", borderColor: "$borderColor", rounded: "$4", style: { zIndex: 100000 }, children: (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$2", width: "100%", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", justify: "space-between", px: "$2", pt: "$1", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", fontWeight: "700", color: "$color10", textTransform: "uppercase", letterSpacing: 0.6, children: "Hanzo Business Suite" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", children: orgDisplay })] }), (0, jsx_runtime_1.jsx)(gui_1.YStack, { gap: "$0.5", maxH: 420, style: { overflowY: 'auto' }, children: apps.map((app) => {
|
|
287
|
+
const isCurrent = app.id === appId;
|
|
288
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2.5", py: "$2", rounded: "$3", bg: isCurrent ? '$color3' : 'transparent', hoverStyle: { bg: '$color3' }, onPress: () => handleLaunchApp(app), "data-testid": `app-switcher-item-${app.id}`, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 32, height: 32, rounded: "$3", bg: isCurrent ? '$color4' : '$color2', items: "center", justify: "center", shrink: 0, children: (0, jsx_runtime_1.jsx)(AppIcon, { id: app.id, size: 16 }) }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, minW: 0, gap: 1, children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1.5", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "600", color: "$color12", numberOfLines: 1, children: app.label }), isCurrent ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: 10, fontWeight: "600", color: "$color10", px: "$1.5", py: 1, rounded: "$2", bg: "$color4", children: "Current" })) : null] }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: app.description })] }), isCurrent ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 14, color: "$color12" }) : null] }, app.id));
|
|
289
|
+
}) })] }) })] }), (0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: orgMenuOpen, onOpenChange: setOrgMenuOpen, placement: "bottom-start", allowFlip: true, stayInFrame: true, children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "button", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2", height: 34, px: "$2.5", rounded: "$3", borderWidth: 0, outlineWidth: 0, hoverStyle: { bg: '$color3' }, "aria-label": `Current organization: ${orgDisplay}. Click to switch organization.`, "data-testid": "business-org-subtitle-trigger", onKeyDown: (e) => {
|
|
290
|
+
if (e?.key === 'Enter' || e?.key === ' ') {
|
|
291
|
+
e.preventDefault?.();
|
|
292
|
+
setOrgMenuOpen(!orgMenuOpen);
|
|
293
|
+
}
|
|
294
|
+
}, children: [(0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: orgDisplay, logo: currentOrg?.logo }, size: 22 }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "600", color: "$color12", numberOfLines: 1, maxW: 220, children: orgDisplay }), (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 13, color: "$color10" })] }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { role: "menu", "aria-label": "Switch organization", borderWidth: 1, elevation: "$4", p: "$2", width: 280, bg: "$background", borderColor: "$borderColor", rounded: "$4", style: { zIndex: 100000 }, children: (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1", width: "100%", children: [(0, jsx_runtime_1.jsx)(gui_1.XStack, { px: "$2", py: "$1", items: "center", justify: "space-between", children: (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", fontWeight: "700", color: "$color10", textTransform: "uppercase", letterSpacing: 0.5, children: "Switch organization" }) }), orgs.map((o) => {
|
|
295
|
+
const active = o.name === currentOrg?.name;
|
|
296
|
+
const label = o.displayName?.trim() || o.name;
|
|
297
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", "aria-checked": active, tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", bg: active ? '$color3' : 'transparent', hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
298
|
+
setOrgMenuOpen(false);
|
|
299
|
+
onSelectOrg?.(o.name);
|
|
300
|
+
}, children: [(0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: label, logo: o.logo }, size: 22 }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: active ? '600' : '500', color: "$color12", numberOfLines: 1, children: label }), o.displayName && o.displayName !== o.name ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: o.name })) : null] }), active ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 14, color: "$color12" }) : null] }, o.name));
|
|
301
|
+
}), (onAllOrgs || onCreateOrg) ? (0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }) : null, onAllOrgs ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
302
|
+
setOrgMenuOpen(false);
|
|
303
|
+
onAllOrgs();
|
|
304
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Building2, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "All organizations\u2026" })] })) : null, onCreateOrg ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
305
|
+
setOrgMenuOpen(false);
|
|
306
|
+
onCreateOrg();
|
|
307
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Plus, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Create organization" })] })) : null] }) })] })] }), (0, jsx_runtime_1.jsx)(gui_1.XStack, { flex: 1, items: "center", justify: "center", minW: 0, px: "$2", children: children }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2", shrink: 0, children: [rightSlot, (0, jsx_runtime_1.jsxs)(gui_1.Popover, { open: accountMenuOpen, onOpenChange: setAccountMenuOpen, placement: "bottom-end", allowFlip: true, stayInFrame: true, children: [(0, jsx_runtime_1.jsx)(gui_1.Popover.Trigger, { asChild: true, children: (0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "button", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2", height: 40, px: "$2.5", rounded: "$3", hoverStyle: { bg: '$color3' }, "aria-label": `${userName} · Account menu`, "aria-haspopup": "menu", "aria-expanded": accountMenuOpen, "data-testid": "business-account-menu-trigger", onKeyDown: (e) => {
|
|
308
|
+
if (e?.key === 'Enter' || e?.key === ' ') {
|
|
309
|
+
e.preventDefault?.();
|
|
310
|
+
setAccountMenuOpen(!accountMenuOpen);
|
|
311
|
+
}
|
|
312
|
+
}, children: [user?.avatar || userName ? ((0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: userName, logo: user?.avatar }, size: 28 })) : ((0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserRound, { size: 18 })), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { minW: 0, justify: "center", display: "none", $sm: { display: 'flex' }, children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "600", color: "$color12", numberOfLines: 1, maxW: 160, style: { lineHeight: '16px' }, children: userName }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: 11, color: "$color10", numberOfLines: 1, maxW: 160, style: { lineHeight: '13px' }, children: "Current account" })] }), (0, jsx_runtime_1.jsx)(lucide_icons_2_1.ChevronDown, { size: 14, color: "$color10" })] }) }), (0, jsx_runtime_1.jsx)(gui_1.Popover.Content, { role: "menu", "aria-label": "Account menu", borderWidth: 1, elevation: "$4", p: "$2", width: 310, bg: "$background", borderColor: "$borderColor", rounded: "$4", style: { zIndex: 100000 }, children: (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$1", width: "100%", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$2.5", px: "$2", py: "$2", rounded: "$3", bg: "$color2", children: [(0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: userName, logo: user?.avatar }, size: 36 }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, minW: 0, gap: 1, children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$3", fontWeight: "700", color: "$color12", numberOfLines: 1, children: userName }), userEmail && userEmail !== userName ? ((0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: userEmail })) : null, (0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", gap: "$1.5", mt: 2, children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 6, height: 6, rounded: 999, bg: "#10b981" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: 11, fontWeight: "600", color: "$color10", children: "Current account" })] })] })] }), (0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$0.5", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { px: "$2", py: "$1", items: "center", justify: "space-between", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", fontWeight: "700", color: "$color10", textTransform: "uppercase", letterSpacing: 0.5, children: "Switch account" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: 11, color: "$color9", children: "Identities" })] }), knownAccounts.map((acc) => {
|
|
313
|
+
const isCurrent = Boolean(userSub && acc.sub === userSub);
|
|
314
|
+
const accName = acc.name || acc.email || acc.sub;
|
|
315
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", "aria-checked": isCurrent, tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", bg: isCurrent ? '$color3' : 'transparent', hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
316
|
+
setAccountMenuOpen(false);
|
|
317
|
+
if (!isCurrent)
|
|
318
|
+
onSwitchAccount?.(acc);
|
|
319
|
+
}, "data-testid": `switch-account-${acc.sub}`, children: [(0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: accName, logo: acc.avatar }, size: 24 }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { flex: 1, minW: 0, children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: isCurrent ? '600' : '500', color: "$color12", numberOfLines: 1, children: accName }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", color: "$color10", numberOfLines: 1, children: acc.email && acc.email !== accName ? acc.email : isCurrent ? 'Current account' : `Identity · ${acc.owner}` })] }), isCurrent ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 14, color: "$color12" }) : null] }, acc.sub));
|
|
320
|
+
}), onAddAccount ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
321
|
+
setAccountMenuOpen(false);
|
|
322
|
+
onAddAccount();
|
|
323
|
+
}, "data-testid": "add-another-account", children: [(0, jsx_runtime_1.jsx)(gui_1.YStack, { width: 24, height: 24, rounded: 999, bg: "$color3", items: "center", justify: "center", children: (0, jsx_runtime_1.jsx)(lucide_icons_2_1.UserPlus, { size: 13, color: "$color11" }) }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "500", color: "$color12", children: "Add another account" })] })) : null] }), (0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$0.5", children: [(0, jsx_runtime_1.jsxs)(gui_1.XStack, { px: "$2", py: "$1", items: "center", justify: "space-between", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$1", fontWeight: "700", color: "$color10", textTransform: "uppercase", letterSpacing: 0.5, children: "Switch organization" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: 11, color: "$color9", children: orgDisplay })] }), orgs.slice(0, 5).map((o) => {
|
|
324
|
+
const active = o.name === currentOrg?.name;
|
|
325
|
+
const label = o.displayName?.trim() || o.name;
|
|
326
|
+
return ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", "aria-checked": active, tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", bg: active ? '$color3' : 'transparent', hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
327
|
+
setAccountMenuOpen(false);
|
|
328
|
+
if (!active)
|
|
329
|
+
onSelectOrg?.(o.name);
|
|
330
|
+
}, "data-testid": `switch-org-${o.name}`, children: [(0, jsx_runtime_1.jsx)(OrgMark_1.OrgMark, { org: { name: label, logo: o.logo }, size: 22 }), (0, jsx_runtime_1.jsx)(gui_1.Text, { flex: 1, fontSize: "$2", fontWeight: active ? '600' : '500', color: "$color12", numberOfLines: 1, children: label }), active ? (0, jsx_runtime_1.jsx)(lucide_icons_2_1.Check, { size: 14, color: "$color12" }) : null] }, o.name));
|
|
331
|
+
}), onAllOrgs ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
332
|
+
setAccountMenuOpen(false);
|
|
333
|
+
onAllOrgs();
|
|
334
|
+
}, "data-testid": "switch-org-all", children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Building2, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Switch organization\u2026" })] })) : null] }), (0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }), (0, jsx_runtime_1.jsxs)(gui_1.YStack, { gap: "$0.5", children: [onSettings ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
335
|
+
setAccountMenuOpen(false);
|
|
336
|
+
onSettings();
|
|
337
|
+
}, "data-testid": "account-menu-settings", children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Settings, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Settings" })] })) : null, onOrgSettings && onOrgSettings !== onSettings ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
338
|
+
setAccountMenuOpen(false);
|
|
339
|
+
onOrgSettings();
|
|
340
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.Building2, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Organization settings" })] })) : null, onBilling ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
341
|
+
setAccountMenuOpen(false);
|
|
342
|
+
onBilling();
|
|
343
|
+
}, children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.CreditCard, { size: 14, color: "$color10" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Billing" })] })) : null, theme != null ? ((0, jsx_runtime_1.jsxs)(gui_1.XStack, { items: "center", justify: "space-between", px: "$2", py: "$1.5", rounded: "$3", children: [(0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", color: "$color12", children: "Theme" }), theme] })) : null] }), onSignOut ? ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(gui_1.Separator, { borderColor: "$borderColor", my: "$1" }), (0, jsx_runtime_1.jsxs)(gui_1.XStack, { role: "menuitem", tabIndex: 0, cursor: "pointer", items: "center", gap: "$2.5", px: "$2", py: "$1.5", rounded: "$3", hoverStyle: { bg: '$color3' }, onPress: () => {
|
|
344
|
+
setAccountMenuOpen(false);
|
|
345
|
+
onSignOut();
|
|
346
|
+
}, "data-testid": "account-menu-signout", children: [(0, jsx_runtime_1.jsx)(lucide_icons_2_1.LogOut, { size: 14, color: "#ef4444" }), (0, jsx_runtime_1.jsx)(gui_1.Text, { fontSize: "$2", fontWeight: "500", color: "#ef4444", children: "Sign out" })] })] })) : null] }) })] })] })] }));
|
|
347
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BusinessHeader — the universal global header for every Hanzo Business application
|
|
3
|
+
* (`hanzo.team`, `crm.hanzo.ai`, `cms.hanzo.ai`, `marketing.hanzo.ai`, `ads.hanzo.ai`,
|
|
4
|
+
* `social.hanzo.ai`, `console.hanzo.ai`, `platform.hanzo.ai`, etc.).
|
|
5
|
+
*
|
|
6
|
+
* Layout & Behavior:
|
|
7
|
+
* - Top Left:
|
|
8
|
+
* 1. Product identity + App Switcher trigger (`Hanzo CRM ▾`, `Hanzo Team ▾`, etc.)
|
|
9
|
+
* Opening the App Switcher lists CRM, Work (Team), CMS, Email, Ads, Cal, Bots,
|
|
10
|
+
* Social, Chat, Dev, Commerce, Analytics, Data Room, Sign, Billing, Console, Platform.
|
|
11
|
+
* 2. Current organization beneath the product identity (e.g. `Hanzo AI`), clickable
|
|
12
|
+
* to switch organizations.
|
|
13
|
+
* - Center:
|
|
14
|
+
* Breadcrumbs / Command Search (`children`).
|
|
15
|
+
* - Top Right:
|
|
16
|
+
* Signed-in user's avatar + display name + Account Menu:
|
|
17
|
+
* - Identity card showing Display Name, Email, and `Current account` indicator
|
|
18
|
+
* - Switch account (choose between authenticated identities on this browser,
|
|
19
|
+
* never confused with organizations)
|
|
20
|
+
* - Add another account (`prompt=login` without ending existing sessions)
|
|
21
|
+
* - Switch organization (choose between organizations the user belongs to)
|
|
22
|
+
* - Settings & Theme
|
|
23
|
+
* - Sign out
|
|
24
|
+
*/
|
|
25
|
+
import { type ReactNode } from 'react';
|
|
26
|
+
export type BusinessAppId = 'crm' | 'team' | 'work' | 'cms' | 'email' | 'marketing' | 'ads' | 'cal' | 'bots' | 'social' | 'chat' | 'dev' | 'commerce' | 'analytics' | 'dataroom' | 'sign' | 'billing' | 'console' | 'platform';
|
|
27
|
+
export type BusinessAppItem = {
|
|
28
|
+
id: BusinessAppId;
|
|
29
|
+
/** Short name in the app switcher grid/list, e.g. 'CRM', 'CMS', 'Email', 'Work'. */
|
|
30
|
+
label: string;
|
|
31
|
+
/** Full product title when active at top-left, e.g. 'Hanzo CRM', 'Hanzo Team'. */
|
|
32
|
+
productTitle: string;
|
|
33
|
+
/** Subtitle explaining what the app does. */
|
|
34
|
+
description: string;
|
|
35
|
+
/** Canonical destination URL. */
|
|
36
|
+
href: string;
|
|
37
|
+
/** Whether the surface supports `/auth/fresh?next=/&who=<sub>` session handoff. */
|
|
38
|
+
supportsFreshAuth?: boolean;
|
|
39
|
+
};
|
|
40
|
+
export declare const BUSINESS_APPS: readonly BusinessAppItem[];
|
|
41
|
+
export type BusinessHeaderAccount = {
|
|
42
|
+
sub: string;
|
|
43
|
+
owner: string;
|
|
44
|
+
name: string;
|
|
45
|
+
email?: string;
|
|
46
|
+
avatar?: string;
|
|
47
|
+
};
|
|
48
|
+
export type BusinessHeaderOrg = {
|
|
49
|
+
name: string;
|
|
50
|
+
displayName?: string;
|
|
51
|
+
logo?: string;
|
|
52
|
+
};
|
|
53
|
+
export type BusinessHeaderProps = {
|
|
54
|
+
/** Current application ID (`'crm'`, `'team'`, `'cms'`, `'email'`, `'ads'`, `'console'`, etc.). */
|
|
55
|
+
appId?: BusinessAppId;
|
|
56
|
+
/** Explicit product title override, e.g. `'Hanzo CRM'`. */
|
|
57
|
+
appTitle?: string;
|
|
58
|
+
/** Whether to show the product title text next to the brand mark when in the app (default: `false`). */
|
|
59
|
+
showAppTitle?: boolean;
|
|
60
|
+
/** Available business apps in the app switcher. Defaults to `BUSINESS_APPS`. */
|
|
61
|
+
apps?: readonly BusinessAppItem[];
|
|
62
|
+
/** Custom handler when an app is selected from the switcher. */
|
|
63
|
+
onSelectApp?: (app: BusinessAppItem) => void;
|
|
64
|
+
/** Custom brand mark icon at the far left. */
|
|
65
|
+
brandMark?: ReactNode;
|
|
66
|
+
/** Current organization shown beneath the product title and in Switch organization. */
|
|
67
|
+
currentOrg?: BusinessHeaderOrg;
|
|
68
|
+
/** All organizations the user can switch between. */
|
|
69
|
+
orgs?: readonly BusinessHeaderOrg[];
|
|
70
|
+
/** Called when the user selects an organization. */
|
|
71
|
+
onSelectOrg?: (orgName: string) => void;
|
|
72
|
+
/** Called when the user clicks "All organizations" / "Switch organization" modal. */
|
|
73
|
+
onAllOrgs?: () => void;
|
|
74
|
+
/** Called when the user clicks "Create organization". */
|
|
75
|
+
onCreateOrg?: () => void;
|
|
76
|
+
/** Optional left-side slot before the app identity (e.g. mobile drawer hamburger). */
|
|
77
|
+
leftSlot?: ReactNode;
|
|
78
|
+
/** Center slot (e.g. breadcrumbs, global search `⌘K`). */
|
|
79
|
+
children?: ReactNode;
|
|
80
|
+
/** Optional right-side slot before the user account menu. */
|
|
81
|
+
rightSlot?: ReactNode;
|
|
82
|
+
/** Currently signed-in user identity. */
|
|
83
|
+
user?: {
|
|
84
|
+
sub?: string;
|
|
85
|
+
name?: string;
|
|
86
|
+
email?: string;
|
|
87
|
+
avatar?: string;
|
|
88
|
+
owner?: string;
|
|
89
|
+
} | null;
|
|
90
|
+
/** Authenticated identities available in this browser session (`Switch account`). */
|
|
91
|
+
accounts?: readonly BusinessHeaderAccount[];
|
|
92
|
+
/** Switch to another authenticated identity (`login_hint: account.sub`). */
|
|
93
|
+
onSwitchAccount?: (account: BusinessHeaderAccount) => void;
|
|
94
|
+
/** Authenticate an additional identity (`prompt=login`). */
|
|
95
|
+
onAddAccount?: () => void;
|
|
96
|
+
/** Open user/account settings. */
|
|
97
|
+
onSettings?: () => void;
|
|
98
|
+
/** Open organization settings. */
|
|
99
|
+
onOrgSettings?: () => void;
|
|
100
|
+
/** Open billing. */
|
|
101
|
+
onBilling?: () => void;
|
|
102
|
+
/** Theme toggle control rendered inside the account menu. */
|
|
103
|
+
theme?: ReactNode;
|
|
104
|
+
/** Sign out of the session. */
|
|
105
|
+
onSignOut?: () => void;
|
|
106
|
+
};
|
|
107
|
+
/** Build a session-preserving destination URL when switching between Hanzo Business apps. */
|
|
108
|
+
export declare function buildSeamlessAppUrl(app: BusinessAppItem, opts?: {
|
|
109
|
+
who?: string;
|
|
110
|
+
org?: string;
|
|
111
|
+
}): string;
|
|
112
|
+
export declare function BusinessHeader({ appId, appTitle, showAppTitle, apps, onSelectApp, brandMark, currentOrg, orgs, onSelectOrg, onAllOrgs, onCreateOrg, leftSlot, children, rightSlot, user, accounts, onSwitchAccount, onAddAccount, onSettings, onOrgSettings, onBilling, theme, onSignOut, }: BusinessHeaderProps): import("react").JSX.Element;
|
|
113
|
+
//# sourceMappingURL=BusinessHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BusinessHeader.d.ts","sourceRoot":"","sources":["../../src/product/BusinessHeader.tsx"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAY,KAAK,SAAS,EAAE,MAAM,OAAO,CAAA;AAmChD,MAAM,MAAM,aAAa,GACrB,KAAK,GACL,MAAM,GACN,MAAM,GACN,KAAK,GACL,OAAO,GACP,WAAW,GACX,KAAK,GACL,KAAK,GACL,MAAM,GACN,QAAQ,GACR,MAAM,GACN,KAAK,GACL,UAAU,GACV,WAAW,GACX,UAAU,GACV,MAAM,GACN,SAAS,GACT,SAAS,GACT,UAAU,CAAA;AAEd,MAAM,MAAM,eAAe,GAAG;IAC5B,EAAE,EAAE,aAAa,CAAA;IACjB,oFAAoF;IACpF,KAAK,EAAE,MAAM,CAAA;IACb,kFAAkF;IAClF,YAAY,EAAE,MAAM,CAAA;IACpB,6CAA6C;IAC7C,WAAW,EAAE,MAAM,CAAA;IACnB,iCAAiC;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,mFAAmF;IACnF,iBAAiB,CAAC,EAAE,OAAO,CAAA;CAC5B,CAAA;AAED,eAAO,MAAM,aAAa,EAAE,SAAS,eAAe,EAyI1C,CAAA;AAEV,MAAM,MAAM,qBAAqB,GAAG;IAClC,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG;IAChC,kGAAkG;IAClG,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,wGAAwG;IACxG,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,gFAAgF;IAChF,IAAI,CAAC,EAAE,SAAS,eAAe,EAAE,CAAA;IACjC,gEAAgE;IAChE,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IAC5C,8CAA8C;IAC9C,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,uFAAuF;IACvF,UAAU,CAAC,EAAE,iBAAiB,CAAA;IAC9B,qDAAqD;IACrD,IAAI,CAAC,EAAE,SAAS,iBAAiB,EAAE,CAAA;IACnC,oDAAoD;IACpD,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,qFAAqF;IACrF,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,yDAAyD;IACzD,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,sFAAsF;IACtF,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,0DAA0D;IAC1D,QAAQ,CAAC,EAAE,SAAS,CAAA;IACpB,6DAA6D;IAC7D,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,yCAAyC;IACzC,IAAI,CAAC,EAAE;QACL,GAAG,CAAC,EAAE,MAAM,CAAA;QACZ,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,KAAK,CAAC,EAAE,MAAM,CAAA;QACd,MAAM,CAAC,EAAE,MAAM,CAAA;QACf,KAAK,CAAC,EAAE,MAAM,CAAA;KACf,GAAG,IAAI,CAAA;IACR,qFAAqF;IACrF,QAAQ,CAAC,EAAE,SAAS,qBAAqB,EAAE,CAAA;IAC3C,4EAA4E;IAC5E,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,qBAAqB,KAAK,IAAI,CAAA;IAC1D,4DAA4D;IAC5D,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;IACzB,kCAAkC;IAClC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;IACvB,kCAAkC;IAClC,aAAa,CAAC,EAAE,MAAM,IAAI,CAAA;IAC1B,oBAAoB;IACpB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,+BAA+B;IAC/B,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB,CAAA;AA6CD,6FAA6F;AAC7F,wBAAgB,mBAAmB,CACjC,GAAG,EAAE,eAAe,EACpB,IAAI,CAAC,EAAE;IAAE,GAAG,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GACpC,MAAM,CAcR;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAa,EACb,QAAQ,EACR,YAAoB,EACpB,IAAoB,EACpB,WAAW,EACX,SAAS,EACT,UAAU,EACV,IAAS,EACT,WAAW,EACX,SAAS,EACT,WAAW,EACX,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,QAAa,EACb,eAAe,EACf,YAAY,EACZ,UAAU,EACV,aAAa,EACb,SAAS,EACT,KAAK,EACL,SAAS,GACV,EAAE,mBAAmB,+BAgqBrB"}
|