@hanzo/ui 5.3.36 → 5.3.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (186) hide show
  1. package/dist/assets/crypto.d.ts.map +1 -1
  2. package/dist/assets/file.d.ts.map +1 -1
  3. package/dist/assets/general.d.ts.map +1 -1
  4. package/dist/assets/hanzo-logo.d.ts.map +1 -1
  5. package/dist/assets/llm-provider.d.ts.map +1 -1
  6. package/dist/components/cal-embed.d.ts.map +1 -1
  7. package/dist/frameworks/react/hooks/index.d.ts.map +1 -1
  8. package/dist/frameworks/react-native/utils.d.ts.map +1 -1
  9. package/dist/frameworks/svelte/utils.d.ts.map +1 -1
  10. package/dist/frameworks/vue/utils.d.ts.map +1 -1
  11. package/dist/helpers/file.d.ts.map +1 -1
  12. package/dist/helpers/memoization.d.ts.map +1 -1
  13. package/dist/index.js +2 -2
  14. package/dist/index.mjs +2 -2
  15. package/dist/models/index.js +35 -0
  16. package/dist/models/index.mjs +35 -0
  17. package/dist/navigation/index.js +2 -1
  18. package/dist/navigation/index.mjs +2 -1
  19. package/dist/primitives/alert.d.ts +1 -1
  20. package/dist/primitives/cal-embed.d.ts.map +1 -1
  21. package/dist/primitives/chart.d.ts.map +1 -1
  22. package/dist/primitives/chat/chat-input.d.ts.map +1 -1
  23. package/dist/primitives/combobox.d.ts.map +1 -1
  24. package/dist/primitives/command.d.ts.map +1 -1
  25. package/dist/primitives/copy-to-clipboard-icon.d.ts.map +1 -1
  26. package/dist/primitives/dots-loader.d.ts.map +1 -1
  27. package/dist/primitives/error-message.d.ts.map +1 -1
  28. package/dist/primitives/file-uploader.d.ts.map +1 -1
  29. package/dist/primitives/form.d.ts.map +1 -1
  30. package/dist/primitives/input-otp.d.ts.map +1 -1
  31. package/dist/primitives/markdown-preview.d.ts.map +1 -1
  32. package/dist/primitives/pretty-json-print.d.ts.map +1 -1
  33. package/dist/primitives/resizable.d.ts +4 -20
  34. package/dist/primitives/resizable.d.ts.map +1 -1
  35. package/dist/primitives/resizable.js +4 -4
  36. package/dist/primitives/sonner.d.ts.map +1 -1
  37. package/dist/primitives/text-link.d.ts.map +1 -1
  38. package/dist/primitives/textfield.d.ts.map +1 -1
  39. package/dist/primitives/toast.d.ts.map +1 -1
  40. package/dist/resizable.js +1 -1
  41. package/dist/resizable.mjs +1 -1
  42. package/dist/src/billing/components/account-members.d.ts +10 -0
  43. package/dist/src/billing/components/account-members.d.ts.map +1 -0
  44. package/dist/src/billing/components/account-members.js +63 -0
  45. package/dist/src/billing/components/account-switcher.d.ts +9 -0
  46. package/dist/src/billing/components/account-switcher.d.ts.map +1 -0
  47. package/dist/src/billing/components/account-switcher.js +52 -0
  48. package/dist/src/billing/components/animated-card.d.ts +9 -0
  49. package/dist/src/billing/components/animated-card.d.ts.map +1 -0
  50. package/dist/src/billing/components/animated-card.js +161 -0
  51. package/dist/src/billing/components/billing-settings.d.ts +26 -0
  52. package/dist/src/billing/components/billing-settings.d.ts.map +1 -0
  53. package/dist/src/billing/components/billing-settings.js +23 -0
  54. package/dist/src/billing/components/business-profile-panel.d.ts.map +1 -1
  55. package/dist/src/billing/components/business-profile-panel.js +9 -8
  56. package/dist/src/billing/components/card-form.d.ts +18 -0
  57. package/dist/src/billing/components/card-form.d.ts.map +1 -0
  58. package/dist/src/billing/components/card-form.js +139 -0
  59. package/dist/src/billing/components/cost-explorer.d.ts +7 -0
  60. package/dist/src/billing/components/cost-explorer.d.ts.map +1 -0
  61. package/dist/src/billing/components/cost-explorer.js +73 -0
  62. package/dist/src/billing/components/credits-panel.d.ts +8 -0
  63. package/dist/src/billing/components/credits-panel.d.ts.map +1 -0
  64. package/dist/src/billing/components/credits-panel.js +58 -0
  65. package/dist/src/billing/components/guided-setup.d.ts +13 -0
  66. package/dist/src/billing/components/guided-setup.d.ts.map +1 -0
  67. package/dist/src/billing/components/guided-setup.js +44 -0
  68. package/dist/src/billing/components/index.d.ts +34 -0
  69. package/dist/src/billing/components/index.d.ts.map +1 -1
  70. package/dist/src/billing/components/index.js +17 -0
  71. package/dist/src/billing/components/invoice-manager.js +13 -13
  72. package/dist/src/billing/components/invoices-payments.d.ts +7 -0
  73. package/dist/src/billing/components/invoices-payments.d.ts.map +1 -0
  74. package/dist/src/billing/components/invoices-payments.js +44 -0
  75. package/dist/src/billing/components/overview-dashboard.d.ts +31 -0
  76. package/dist/src/billing/components/overview-dashboard.d.ts.map +1 -0
  77. package/dist/src/billing/components/overview-dashboard.js +105 -0
  78. package/dist/src/billing/components/payment-manager.d.ts.map +1 -1
  79. package/dist/src/billing/components/payment-manager.js +267 -83
  80. package/dist/src/billing/components/promotions-panel.d.ts +7 -0
  81. package/dist/src/billing/components/promotions-panel.d.ts.map +1 -0
  82. package/dist/src/billing/components/promotions-panel.js +48 -0
  83. package/dist/src/billing/components/spend-alerts.d.ts +9 -0
  84. package/dist/src/billing/components/spend-alerts.d.ts.map +1 -0
  85. package/dist/src/billing/components/spend-alerts.js +99 -0
  86. package/dist/src/billing/components/square-card-form.d.ts +32 -0
  87. package/dist/src/billing/components/square-card-form.d.ts.map +1 -0
  88. package/dist/src/billing/components/square-card-form.js +179 -0
  89. package/dist/src/billing/components/status-bar.d.ts +12 -0
  90. package/dist/src/billing/components/status-bar.d.ts.map +1 -0
  91. package/dist/src/billing/components/status-bar.js +32 -0
  92. package/dist/src/billing/components/subscription-portal.d.ts +2 -1
  93. package/dist/src/billing/components/subscription-portal.d.ts.map +1 -1
  94. package/dist/src/billing/components/subscription-portal.js +123 -26
  95. package/dist/src/billing/components/support-tiers-panel.d.ts +6 -0
  96. package/dist/src/billing/components/support-tiers-panel.d.ts.map +1 -0
  97. package/dist/src/billing/components/support-tiers-panel.js +90 -0
  98. package/dist/src/billing/components/tax-compliance-panel.js +5 -5
  99. package/dist/src/billing/components/transactions-panel.d.ts +8 -0
  100. package/dist/src/billing/components/transactions-panel.d.ts.map +1 -0
  101. package/dist/src/billing/components/transactions-panel.js +64 -0
  102. package/dist/src/billing/components/usage-panel.d.ts +7 -0
  103. package/dist/src/billing/components/usage-panel.d.ts.map +1 -0
  104. package/dist/src/billing/components/usage-panel.js +64 -0
  105. package/dist/src/billing/types/index.d.ts +136 -1
  106. package/dist/src/billing/types/index.d.ts.map +1 -1
  107. package/dist/src/form/form.d.ts.map +1 -1
  108. package/dist/src/hooks/use-copy-clipboard.d.ts.map +1 -1
  109. package/dist/src/hooks/use-fill-ids.d.ts.map +1 -1
  110. package/dist/src/hooks/use-scroll-restoration.d.ts.map +1 -1
  111. package/dist/src/models/ModelCard.d.ts +25 -0
  112. package/dist/src/models/ModelCard.d.ts.map +1 -0
  113. package/dist/src/models/ModelCard.js +73 -0
  114. package/dist/src/models/ModelLibrary.d.ts +41 -0
  115. package/dist/src/models/ModelLibrary.d.ts.map +1 -0
  116. package/dist/src/models/ModelLibrary.js +63 -0
  117. package/dist/src/models/ModelTable.d.ts +17 -0
  118. package/dist/src/models/ModelTable.d.ts.map +1 -0
  119. package/dist/src/models/ModelTable.js +35 -0
  120. package/dist/src/models/ZenEnso.d.ts +17 -0
  121. package/dist/src/models/ZenEnso.d.ts.map +1 -0
  122. package/dist/src/models/ZenEnso.js +50 -0
  123. package/dist/src/models/index.d.ts +23 -0
  124. package/dist/src/models/index.d.ts.map +1 -0
  125. package/dist/src/models/index.js +18 -0
  126. package/dist/src/models/types.d.ts +40 -0
  127. package/dist/src/models/types.d.ts.map +1 -0
  128. package/dist/src/models/types.js +7 -0
  129. package/dist/src/navigation/hanzo-shell/AppSwitcher.d.ts +8 -0
  130. package/dist/src/navigation/hanzo-shell/AppSwitcher.d.ts.map +1 -0
  131. package/dist/src/navigation/hanzo-shell/AppSwitcher.js +19 -0
  132. package/dist/src/navigation/hanzo-shell/BeamAvatar.d.ts +9 -0
  133. package/dist/src/navigation/hanzo-shell/BeamAvatar.d.ts.map +1 -0
  134. package/dist/src/navigation/hanzo-shell/BeamAvatar.js +38 -0
  135. package/dist/src/navigation/hanzo-shell/HanzoCommandPalette.d.ts +28 -0
  136. package/dist/src/navigation/hanzo-shell/HanzoCommandPalette.d.ts.map +1 -0
  137. package/dist/src/navigation/hanzo-shell/HanzoCommandPalette.js +124 -0
  138. package/dist/src/navigation/hanzo-shell/HanzoHeader.d.ts +37 -0
  139. package/dist/src/navigation/hanzo-shell/HanzoHeader.d.ts.map +1 -0
  140. package/dist/src/navigation/hanzo-shell/HanzoHeader.js +43 -0
  141. package/dist/src/navigation/hanzo-shell/HanzoMark.d.ts +17 -0
  142. package/dist/src/navigation/hanzo-shell/HanzoMark.d.ts.map +1 -0
  143. package/dist/src/navigation/hanzo-shell/HanzoMark.js +57 -0
  144. package/dist/src/navigation/hanzo-shell/UserAvatar.d.ts +15 -0
  145. package/dist/src/navigation/hanzo-shell/UserAvatar.d.ts.map +1 -0
  146. package/dist/src/navigation/hanzo-shell/UserAvatar.js +44 -0
  147. package/dist/src/navigation/hanzo-shell/UserOrgDropdown.d.ts +11 -0
  148. package/dist/src/navigation/hanzo-shell/UserOrgDropdown.d.ts.map +1 -0
  149. package/dist/src/navigation/hanzo-shell/UserOrgDropdown.js +26 -0
  150. package/dist/src/navigation/hanzo-shell/index.d.ts +14 -0
  151. package/dist/src/navigation/hanzo-shell/index.d.ts.map +1 -0
  152. package/dist/src/navigation/hanzo-shell/index.js +9 -0
  153. package/dist/src/navigation/hanzo-shell/types.d.ts +49 -0
  154. package/dist/src/navigation/hanzo-shell/types.d.ts.map +1 -0
  155. package/dist/src/navigation/hanzo-shell/types.js +32 -0
  156. package/dist/src/navigation/hanzo-shell/useHanzoAuth.d.ts +16 -0
  157. package/dist/src/navigation/hanzo-shell/useHanzoAuth.d.ts.map +1 -0
  158. package/dist/src/navigation/hanzo-shell/useHanzoAuth.js +93 -0
  159. package/dist/src/navigation/index.d.ts +2 -0
  160. package/dist/src/navigation/index.d.ts.map +1 -1
  161. package/dist/src/navigation/index.js +2 -0
  162. package/dist/src/ui/banner.d.ts +1 -1
  163. package/dist/util/blob.d.ts.map +1 -1
  164. package/dist/util/blob.js +1 -1
  165. package/dist/util/date.d.ts.map +1 -1
  166. package/dist/util/debounce.d.ts.map +1 -1
  167. package/dist/util/file.d.ts.map +1 -1
  168. package/dist/util/format-and-abbreviate-as-currency.d.ts +7 -1
  169. package/dist/util/format-and-abbreviate-as-currency.d.ts.map +1 -1
  170. package/dist/util/format-text.d.ts.map +1 -1
  171. package/dist/util/format-to-max-char.d.ts +7 -1
  172. package/dist/util/format-to-max-char.d.ts.map +1 -1
  173. package/dist/util/index.mjs +1 -1
  174. package/dist/util/number-abbreviate.d.ts.map +1 -1
  175. package/dist/util/specifier.d.ts.map +1 -1
  176. package/dist/util/step-animation.d.ts.map +1 -1
  177. package/package.json +20 -7
  178. package/dist/tailwind/typo-plugin/get-plugin-styles.d.ts +0 -595
  179. package/dist/tailwind/typo-plugin/get-plugin-styles.d.ts.map +0 -1
  180. package/dist/tailwind/typo-plugin/get-plugin-styles.js +0 -661
  181. package/dist/tailwind/typo-plugin/index.d.ts +0 -3
  182. package/dist/tailwind/typo-plugin/index.d.ts.map +0 -1
  183. package/dist/tailwind/typo-plugin/index.js +0 -102
  184. package/dist/tailwind/typo-plugin/utils.d.ts +0 -6
  185. package/dist/tailwind/typo-plugin/utils.d.ts.map +0 -1
  186. package/dist/tailwind/typo-plugin/utils.js +0 -47
@@ -0,0 +1,40 @@
1
+ /**
2
+ * @hanzo/ui — Model component types
3
+ *
4
+ * These types are structurally compatible with @hanzo/zen-models ZenModel / ModelFamily,
5
+ * so ZenModel objects can be passed directly to these components without casting.
6
+ */
7
+ export interface ModelSpecLike {
8
+ params: string;
9
+ activeParams?: string | null;
10
+ context?: number;
11
+ arch?: string;
12
+ }
13
+ export interface ModelPricingLike {
14
+ input: number | null;
15
+ output: number | null;
16
+ cacheRead?: number | null;
17
+ cacheWrite?: number | null;
18
+ }
19
+ export interface ZenModelLike {
20
+ id: string;
21
+ name: string;
22
+ description: string;
23
+ spec: ModelSpecLike;
24
+ pricing: ModelPricingLike | null;
25
+ /** 'available' | 'preview' | 'coming-soon' | 'contact-sales' | 'cloud-only' */
26
+ status: string;
27
+ huggingface?: string | null;
28
+ github?: string | null;
29
+ paper?: string | null;
30
+ }
31
+ export interface ModelFamilyLike {
32
+ id: string;
33
+ name: string;
34
+ description: string;
35
+ /** lucide-react icon name */
36
+ icon?: string;
37
+ /** ordered list of model IDs */
38
+ models: string[];
39
+ }
40
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/models/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAA;IACd,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,IAAI,EAAE,aAAa,CAAA;IACnB,OAAO,EAAE,gBAAgB,GAAG,IAAI,CAAA;IAChC,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAA;IACd,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACtB;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,6BAA6B;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,gCAAgC;IAChC,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * @hanzo/ui — Model component types
3
+ *
4
+ * These types are structurally compatible with @hanzo/zen-models ZenModel / ModelFamily,
5
+ * so ZenModel objects can be passed directly to these components without casting.
6
+ */
7
+ export {};
@@ -0,0 +1,8 @@
1
+ import { type HanzoApp } from './types';
2
+ interface AppSwitcherProps {
3
+ apps?: HanzoApp[];
4
+ currentAppId?: string;
5
+ }
6
+ export declare function AppSwitcher({ apps, currentAppId }: AppSwitcherProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=AppSwitcher.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSwitcher.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/AppSwitcher.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAE3D,UAAU,gBAAgB;IACxB,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA;IACjB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAyB,EAAE,YAAY,EAAE,EAAE,gBAAgB,2CA2DxF"}
@@ -0,0 +1,19 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { DEFAULT_HANZO_APPS } from './types';
5
+ export function AppSwitcher({ apps = DEFAULT_HANZO_APPS, currentAppId }) {
6
+ const [open, setOpen] = useState(false);
7
+ const ref = useRef(null);
8
+ useEffect(() => {
9
+ const handler = (e) => {
10
+ if (ref.current && !ref.current.contains(e.target))
11
+ setOpen(false);
12
+ };
13
+ document.addEventListener('mousedown', handler);
14
+ return () => document.removeEventListener('mousedown', handler);
15
+ }, []);
16
+ return (_jsxs("div", { ref: ref, className: "relative", children: [_jsx("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex h-8 w-8 items-center justify-center rounded-lg text-white/40 hover:bg-white/[0.06] hover:text-white/70 transition-colors", "aria-label": "Switch app", title: "Switch app", children: _jsxs("svg", { width: "16", height: "16", viewBox: "0 0 16 16", fill: "currentColor", children: [_jsx("rect", { x: "1", y: "1", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "6", y: "1", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "11", y: "1", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "1", y: "6", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "6", y: "6", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "11", y: "6", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "1", y: "11", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "6", y: "11", width: "4", height: "4", rx: "1" }), _jsx("rect", { x: "11", y: "11", width: "4", height: "4", rx: "1" })] }) }), open && (_jsxs("div", { className: "absolute left-0 top-10 z-50 w-64 rounded-xl border border-white/[0.08] bg-[#0e0e13] p-2 shadow-2xl", children: [_jsx("p", { className: "px-2 pb-1.5 pt-0.5 text-[10px] font-medium uppercase tracking-wider text-white/30", children: "Hanzo Apps" }), apps
17
+ .filter((a) => a.id !== currentAppId)
18
+ .map((app) => (_jsxs("a", { href: app.href, className: "flex flex-col gap-0.5 rounded-lg px-3 py-2.5 hover:bg-white/[0.06] transition-colors", onClick: () => setOpen(false), children: [_jsx("span", { className: "text-[13px] font-medium text-white/80", children: app.label }), app.description && (_jsx("span", { className: "text-[11px] text-white/30", children: app.description }))] }, app.id)))] }))] }));
19
+ }
@@ -0,0 +1,9 @@
1
+ export interface BeamAvatarProps {
2
+ name: string;
3
+ size?: number;
4
+ colors?: string[];
5
+ className?: string;
6
+ square?: boolean;
7
+ }
8
+ export declare function BeamAvatar({ name, size, colors, className, square, }: BeamAvatarProps): import("react/jsx-runtime").JSX.Element;
9
+ //# sourceMappingURL=BeamAvatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BeamAvatar.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/BeamAvatar.tsx"],"names":[],"mappings":"AAkCA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,IAAS,EACT,MAAe,EACf,SAAS,EACT,MAAc,GACf,EAAE,eAAe,2CAyEjB"}
@@ -0,0 +1,38 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ const COLORS = ['#0A0310', '#49007E', '#FF005B', '#FF7D10', '#FFB238'];
4
+ function hashStr(str) {
5
+ let hash = 0;
6
+ for (let i = 0; i < str.length; i++) {
7
+ hash = ((hash << 5) - hash + str.charCodeAt(i)) | 0;
8
+ }
9
+ return Math.abs(hash);
10
+ }
11
+ function getUnit(hash, range, index) {
12
+ const val = hash % (range * (index + 1));
13
+ return val % range;
14
+ }
15
+ function getBoolean(hash, index) {
16
+ return getUnit(hash, 2, index) === 0;
17
+ }
18
+ function getRandomColor(hash, index, colors) {
19
+ return colors[getUnit(hash, colors.length, index)];
20
+ }
21
+ function getContrast(hex) {
22
+ const r = parseInt(hex.slice(1, 3), 16);
23
+ const g = parseInt(hex.slice(3, 5), 16);
24
+ const b = parseInt(hex.slice(5, 7), 16);
25
+ return r * 0.299 + g * 0.587 + b * 0.114 > 128 ? '#000' : '#fff';
26
+ }
27
+ export function BeamAvatar({ name, size = 40, colors = COLORS, className, square = false, }) {
28
+ const hash = hashStr(name);
29
+ const wrapperColor = getRandomColor(hash, 0, colors);
30
+ const faceColor = getContrast(wrapperColor);
31
+ const isOpen = getBoolean(hash, 2);
32
+ const mouthSpread = getUnit(hash, 3, 7);
33
+ const eyeSpread = getUnit(hash, 5, 8);
34
+ const faceRotate = getUnit(hash, 10, 9);
35
+ const faceTranslateX = faceRotate > 6 ? faceRotate - 10 : faceRotate;
36
+ const faceTranslateY = getUnit(hash, 5, 10) > 3 ? getUnit(hash, 5, 10) - 5 : getUnit(hash, 5, 10);
37
+ return (_jsxs("svg", { viewBox: "0 0 36 36", fill: "none", xmlns: "http://www.w3.org/2000/svg", width: size, height: size, className: className, style: square ? undefined : { borderRadius: '50%' }, children: [_jsx("mask", { id: `beam-${hash}`, maskUnits: "userSpaceOnUse", x: 0, y: 0, width: 36, height: 36, children: _jsx("rect", { width: 36, height: 36, rx: square ? undefined : 72, fill: "#fff" }) }), _jsxs("g", { mask: `url(#beam-${hash})`, children: [_jsx("rect", { width: 36, height: 36, fill: wrapperColor }), _jsx("rect", { x: 0, y: 0, width: 36, height: 36, transform: `translate(${faceTranslateX} ${faceTranslateY}) rotate(${faceRotate} 18 18)`, fill: getRandomColor(hash, 1, colors), rx: 6 }), _jsxs("g", { transform: `translate(${faceTranslateX} ${faceTranslateY}) rotate(${faceRotate} 18 18)`, children: [isOpen ? (_jsx("path", { d: `M15 ${19 + mouthSpread}c2 1 4 1 6 0`, stroke: faceColor, fill: "none", strokeLinecap: "round" })) : (_jsx("path", { d: `M13 ${19 + mouthSpread}a1 .75 0 0 0 10 0`, fill: faceColor })), _jsx("rect", { x: 14 - eyeSpread, y: 14, width: 1.5, height: 2, rx: 1, fill: faceColor }), _jsx("rect", { x: 20 + eyeSpread, y: 14, width: 1.5, height: 2, rx: 1, fill: faceColor })] })] })] }));
38
+ }
@@ -0,0 +1,28 @@
1
+ import { type HanzoApp } from './types';
2
+ export type CommandItem = {
3
+ id: string;
4
+ title: string;
5
+ description?: string;
6
+ href?: string;
7
+ action?: () => void;
8
+ icon?: React.ReactNode;
9
+ category: string;
10
+ external?: boolean;
11
+ keywords?: string[];
12
+ };
13
+ export type HanzoCommandPaletteProps = {
14
+ /** Additional app-specific commands merged with built-in cross-app commands */
15
+ commands?: CommandItem[];
16
+ /** Override the default Hanzo apps used for cross-app navigation */
17
+ apps?: HanzoApp[];
18
+ /** Current app id — used to exclude from cross-app navigation */
19
+ currentAppId?: string;
20
+ /** Controlled open state */
21
+ open?: boolean;
22
+ /** Called when palette wants to close */
23
+ onOpenChange?: (open: boolean) => void;
24
+ /** Custom navigation handler (defaults to window.location for external, history push for relative) */
25
+ onNavigate?: (href: string, external?: boolean) => void;
26
+ };
27
+ export declare function HanzoCommandPalette({ commands: appCommands, apps, currentAppId, open: controlledOpen, onOpenChange, onNavigate, }: HanzoCommandPaletteProps): import("react/jsx-runtime").JSX.Element | null;
28
+ //# sourceMappingURL=HanzoCommandPalette.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HanzoCommandPalette.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/HanzoCommandPalette.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAsB,KAAK,QAAQ,EAAE,MAAM,SAAS,CAAA;AAM3D,MAAM,MAAM,WAAW,GAAG;IACxB,EAAE,EAAE,MAAM,CAAA;IACV,KAAK,EAAE,MAAM,CAAA;IACb,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,IAAI,CAAA;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACtB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG;IACrC,+EAA+E;IAC/E,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAA;IACxB,oEAAoE;IACpE,IAAI,CAAC,EAAE,QAAQ,EAAE,CAAA;IACjB,iEAAiE;IACjE,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,4BAA4B;IAC5B,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,yCAAyC;IACzC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAA;IACtC,sGAAsG;IACtG,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,OAAO,KAAK,IAAI,CAAA;CACxD,CAAA;AAwBD,wBAAgB,mBAAmB,CAAC,EAClC,QAAQ,EAAE,WAAgB,EAC1B,IAAI,EACJ,YAAY,EACZ,IAAI,EAAE,cAAc,EACpB,YAAY,EACZ,UAAU,GACX,EAAE,wBAAwB,kDAkN1B"}
@@ -0,0 +1,124 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useEffect, useRef, useCallback } from 'react';
4
+ import { DEFAULT_HANZO_APPS } from './types';
5
+ // ---------------------------------------------------------------------------
6
+ // Built-in cross-app commands derived from DEFAULT_HANZO_APPS
7
+ // ---------------------------------------------------------------------------
8
+ function buildCrossAppCommands(apps, currentAppId) {
9
+ return apps
10
+ .filter((app) => app.id !== currentAppId)
11
+ .map((app) => ({
12
+ id: `app-${app.id}`,
13
+ title: app.label,
14
+ description: app.description,
15
+ href: app.href,
16
+ category: 'Hanzo Apps',
17
+ external: true,
18
+ keywords: [app.id, app.label.toLowerCase()],
19
+ }));
20
+ }
21
+ // ---------------------------------------------------------------------------
22
+ // Component
23
+ // ---------------------------------------------------------------------------
24
+ export function HanzoCommandPalette({ commands: appCommands = [], apps, currentAppId, open: controlledOpen, onOpenChange, onNavigate, }) {
25
+ var _a;
26
+ const [internalOpen, setInternalOpen] = useState(false);
27
+ const open = controlledOpen ?? internalOpen;
28
+ const setOpen = useCallback((v) => {
29
+ if (onOpenChange)
30
+ onOpenChange(v);
31
+ else
32
+ setInternalOpen(v);
33
+ }, [onOpenChange]);
34
+ const [search, setSearch] = useState('');
35
+ const [selectedIndex, setSelectedIndex] = useState(0);
36
+ const inputRef = useRef(null);
37
+ const listRef = useRef(null);
38
+ // Merge cross-app + app-specific commands
39
+ const crossApp = buildCrossAppCommands(apps ?? DEFAULT_HANZO_APPS, currentAppId);
40
+ const allCommands = [...appCommands, ...crossApp];
41
+ // Filter
42
+ const q = search.toLowerCase();
43
+ const filtered = q
44
+ ? allCommands.filter((cmd) => cmd.title.toLowerCase().includes(q) ||
45
+ cmd.description?.toLowerCase().includes(q) ||
46
+ cmd.keywords?.some((k) => k.includes(q)))
47
+ : allCommands;
48
+ // Group by category
49
+ const grouped = {};
50
+ for (const cmd of filtered) {
51
+ ;
52
+ (grouped[_a = cmd.category] ?? (grouped[_a] = [])).push(cmd);
53
+ }
54
+ const flat = Object.values(grouped).flat();
55
+ // Reset on search change
56
+ useEffect(() => setSelectedIndex(0), [search]);
57
+ // Focus on open
58
+ useEffect(() => {
59
+ if (open) {
60
+ setSearch('');
61
+ setSelectedIndex(0);
62
+ requestAnimationFrame(() => inputRef.current?.focus());
63
+ }
64
+ }, [open]);
65
+ // Global Cmd+K
66
+ useEffect(() => {
67
+ const handler = (e) => {
68
+ if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
69
+ e.preventDefault();
70
+ setOpen(!open);
71
+ }
72
+ };
73
+ document.addEventListener('keydown', handler);
74
+ return () => document.removeEventListener('keydown', handler);
75
+ }, [open, setOpen]);
76
+ // Navigate helper
77
+ const go = useCallback((cmd) => {
78
+ if (cmd.action) {
79
+ cmd.action();
80
+ }
81
+ else if (cmd.href) {
82
+ if (onNavigate) {
83
+ onNavigate(cmd.href, cmd.external);
84
+ }
85
+ else if (cmd.external) {
86
+ window.open(cmd.href, '_blank');
87
+ }
88
+ else {
89
+ window.location.href = cmd.href;
90
+ }
91
+ }
92
+ setOpen(false);
93
+ }, [onNavigate, setOpen]);
94
+ // Keyboard nav
95
+ const handleKeyDown = useCallback((e) => {
96
+ if (e.key === 'ArrowDown') {
97
+ e.preventDefault();
98
+ setSelectedIndex((i) => (i + 1) % (flat.length || 1));
99
+ }
100
+ else if (e.key === 'ArrowUp') {
101
+ e.preventDefault();
102
+ setSelectedIndex((i) => (i - 1 + (flat.length || 1)) % (flat.length || 1));
103
+ }
104
+ else if (e.key === 'Enter' && flat[selectedIndex]) {
105
+ e.preventDefault();
106
+ go(flat[selectedIndex]);
107
+ }
108
+ else if (e.key === 'Escape') {
109
+ setOpen(false);
110
+ }
111
+ }, [flat, selectedIndex, go, setOpen]);
112
+ // Scroll selected into view
113
+ useEffect(() => {
114
+ const el = listRef.current?.querySelector(`[data-idx="${selectedIndex}"]`);
115
+ el?.scrollIntoView({ block: 'nearest' });
116
+ }, [selectedIndex]);
117
+ if (!open)
118
+ return null;
119
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: "fixed inset-0 bg-black/60 backdrop-blur-sm z-[100]", onClick: () => setOpen(false) }), _jsx("div", { className: "fixed top-[15%] left-1/2 -translate-x-1/2 w-full max-w-xl z-[101]", children: _jsxs("div", { className: "bg-[#111113] border border-white/[0.08] rounded-xl shadow-2xl overflow-hidden", children: [_jsxs("div", { className: "flex items-center gap-3 px-4 py-3 border-b border-white/[0.07]", children: [_jsx("svg", { className: "w-4 h-4 text-white/30", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: _jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z" }) }), _jsx("input", { ref: inputRef, type: "text", value: search, onChange: (e) => setSearch(e.target.value), onKeyDown: handleKeyDown, placeholder: "Search commands...", className: "flex-1 bg-transparent text-white text-[13px] placeholder-white/30 outline-none" }), _jsx("kbd", { className: "px-1.5 py-0.5 text-[10px] font-mono bg-white/[0.06] rounded text-white/30", children: "ESC" })] }), _jsx("div", { ref: listRef, className: "max-h-[400px] overflow-y-auto py-1", children: flat.length === 0 ? (_jsxs("div", { className: "px-4 py-8 text-center text-white/30 text-[13px]", children: ["No results for \u201C", search, "\u201D"] })) : (Object.entries(grouped).map(([category, items]) => (_jsxs("div", { children: [_jsx("div", { className: "px-4 py-2 text-[10px] font-semibold text-white/25 uppercase tracking-widest", children: category }), items.map((cmd) => {
120
+ const idx = flat.indexOf(cmd);
121
+ const selected = idx === selectedIndex;
122
+ return (_jsxs("button", { "data-idx": idx, onClick: () => go(cmd), onMouseEnter: () => setSelectedIndex(idx), className: `w-full flex items-center gap-3 px-4 py-2 text-left transition-colors ${selected ? 'bg-white/[0.06] text-white' : 'text-white/50 hover:bg-white/[0.03]'}`, children: [cmd.icon && (_jsx("span", { className: `w-5 h-5 flex items-center justify-center ${selected ? 'text-white/70' : 'text-white/25'}`, children: cmd.icon })), _jsxs("div", { className: "flex-1 min-w-0", children: [_jsx("span", { className: "text-[13px] font-medium truncate block", children: cmd.title }), cmd.description && (_jsx("span", { className: "text-[11px] text-white/25 truncate block", children: cmd.description }))] }), selected && (_jsx("span", { className: "text-white/25 text-[11px]", children: "\u21B5" }))] }, cmd.id));
123
+ })] }, category)))) }), _jsxs("div", { className: "px-4 py-2 border-t border-white/[0.07] flex items-center justify-between", children: [_jsxs("div", { className: "flex items-center gap-4 text-[10px] text-white/20", children: [_jsxs("span", { className: "flex items-center gap-1", children: [_jsx("kbd", { className: "px-1 py-0.5 bg-white/[0.06] rounded text-[9px]", children: "\u2191" }), _jsx("kbd", { className: "px-1 py-0.5 bg-white/[0.06] rounded text-[9px]", children: "\u2193" }), "navigate"] }), _jsxs("span", { className: "flex items-center gap-1", children: [_jsx("kbd", { className: "px-1 py-0.5 bg-white/[0.06] rounded text-[9px]", children: "\u21B5" }), "select"] })] }), _jsx("span", { className: "text-[10px] text-white/20", children: "\u2318K" })] })] }) })] }));
124
+ }
@@ -0,0 +1,37 @@
1
+ import { type HanzoShellProps } from './types';
2
+ /**
3
+ * HanzoHeader — shared top navigation bar for all Hanzo properties.
4
+ *
5
+ * Style: monochrome #09090b / white, same as hanzo.ai docs & console.
6
+ *
7
+ * Features:
8
+ * - Official Hanzo H-mark (animates on hover, brand context menu on right-click)
9
+ * - Current app breadcrumb
10
+ * - App switcher (billing, console, chat, platform, account)
11
+ * - User + org dropdown (orgs from IAM, sign-out)
12
+ *
13
+ * Usage:
14
+ * ```tsx
15
+ * import { HanzoHeader, useHanzoAuth } from '@hanzo/ui/navigation'
16
+ *
17
+ * export default function Layout({ children }) {
18
+ * const { user, organizations, currentOrgId, switchOrg, signOut } = useHanzoAuth()
19
+ * return (
20
+ * <>
21
+ * <HanzoHeader
22
+ * currentApp="Billing"
23
+ * currentAppId="billing"
24
+ * user={user}
25
+ * organizations={organizations}
26
+ * currentOrgId={currentOrgId}
27
+ * onOrgSwitch={switchOrg}
28
+ * onSignOut={signOut}
29
+ * />
30
+ * <main>{children}</main>
31
+ * </>
32
+ * )
33
+ * }
34
+ * ```
35
+ */
36
+ export declare function HanzoHeader({ currentApp, currentAppId, user, organizations, currentOrgId, onOrgSwitch, onSignOut, apps, headerRight, }: Omit<HanzoShellProps, 'children'>): import("react/jsx-runtime").JSX.Element;
37
+ //# sourceMappingURL=HanzoHeader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HanzoHeader.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/HanzoHeader.tsx"],"names":[],"mappings":"AAMA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,SAAS,CAAA;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,WAAW,CAAC,EAC1B,UAAU,EACV,YAAY,EACZ,IAAI,EACJ,aAAa,EACb,YAAY,EACZ,WAAW,EACX,SAAS,EACT,IAAyB,EACzB,WAAW,GACZ,EAAE,IAAI,CAAC,eAAe,EAAE,UAAU,CAAC,2CAoCnC"}
@@ -0,0 +1,43 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { HanzoMark } from './HanzoMark';
4
+ import { AppSwitcher } from './AppSwitcher';
5
+ import { UserOrgDropdown } from './UserOrgDropdown';
6
+ import { DEFAULT_HANZO_APPS } from './types';
7
+ /**
8
+ * HanzoHeader — shared top navigation bar for all Hanzo properties.
9
+ *
10
+ * Style: monochrome #09090b / white, same as hanzo.ai docs & console.
11
+ *
12
+ * Features:
13
+ * - Official Hanzo H-mark (animates on hover, brand context menu on right-click)
14
+ * - Current app breadcrumb
15
+ * - App switcher (billing, console, chat, platform, account)
16
+ * - User + org dropdown (orgs from IAM, sign-out)
17
+ *
18
+ * Usage:
19
+ * ```tsx
20
+ * import { HanzoHeader, useHanzoAuth } from '@hanzo/ui/navigation'
21
+ *
22
+ * export default function Layout({ children }) {
23
+ * const { user, organizations, currentOrgId, switchOrg, signOut } = useHanzoAuth()
24
+ * return (
25
+ * <>
26
+ * <HanzoHeader
27
+ * currentApp="Billing"
28
+ * currentAppId="billing"
29
+ * user={user}
30
+ * organizations={organizations}
31
+ * currentOrgId={currentOrgId}
32
+ * onOrgSwitch={switchOrg}
33
+ * onSignOut={signOut}
34
+ * />
35
+ * <main>{children}</main>
36
+ * </>
37
+ * )
38
+ * }
39
+ * ```
40
+ */
41
+ export function HanzoHeader({ currentApp, currentAppId, user, organizations, currentOrgId, onOrgSwitch, onSignOut, apps = DEFAULT_HANZO_APPS, headerRight, }) {
42
+ return (_jsxs("header", { className: "sticky top-0 z-50 flex h-14 w-full items-center justify-between border-b border-white/[0.07] bg-[#09090b]/90 px-4 backdrop-blur-xl", role: "banner", children: [_jsxs("div", { className: "flex min-w-0 items-center gap-2.5", children: [_jsx("a", { href: "https://hanzo.id/account", className: "flex-shrink-0 rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-white/20", "aria-label": "Hanzo Account", children: _jsx(HanzoMark, { size: 22, brandMenu: true, animate: true }) }), _jsx("span", { className: "select-none text-white/[0.15]", children: "/" }), _jsx("span", { className: "truncate text-[13px] font-medium text-white/50", children: currentApp }), _jsx(AppSwitcher, { apps: apps, currentAppId: currentAppId })] }), _jsxs("div", { className: "flex flex-shrink-0 items-center gap-2", children: [headerRight, _jsx(UserOrgDropdown, { user: user, organizations: organizations, currentOrgId: currentOrgId, onOrgSwitch: onOrgSwitch, onSignOut: onSignOut })] })] }));
43
+ }
@@ -0,0 +1,17 @@
1
+ export interface HanzoMarkProps {
2
+ size?: number;
3
+ className?: string;
4
+ /** Whether to show brand context menu on right-click */
5
+ brandMenu?: boolean;
6
+ /** Animate on hover (origami-style scale + slight 3D tilt) */
7
+ animate?: boolean;
8
+ }
9
+ /**
10
+ * Official Hanzo H-mark logo.
11
+ *
12
+ * - White fill paths with subtle shadow details
13
+ * - Hover: origami-style 3D perspective tilt + scale
14
+ * - Right-click: brand context menu (guidelines, press, download, copy SVG)
15
+ */
16
+ export declare function HanzoMark({ size, className, brandMenu, animate, }: HanzoMarkProps): import("react/jsx-runtime").JSX.Element;
17
+ //# sourceMappingURL=HanzoMark.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"HanzoMark.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/HanzoMark.tsx"],"names":[],"mappings":"AA8EA,MAAM,WAAW,cAAc;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,wDAAwD;IACxD,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB;AAED;;;;;;GAMG;AACH,wBAAgB,SAAS,CAAC,EACxB,IAAS,EACT,SAAc,EACd,SAAgB,EAChB,OAAc,GACf,EAAE,cAAc,2CAkDhB"}
@@ -0,0 +1,57 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
3
+ import { useState, useRef, useEffect, useCallback } from 'react';
4
+ function BrandContextMenu({ x, y, onClose }) {
5
+ const ref = useRef(null);
6
+ useEffect(() => {
7
+ const handler = (e) => {
8
+ if (ref.current && !ref.current.contains(e.target))
9
+ onClose();
10
+ };
11
+ const escape = (e) => { if (e.key === 'Escape')
12
+ onClose(); };
13
+ document.addEventListener('mousedown', handler);
14
+ document.addEventListener('keydown', escape);
15
+ return () => {
16
+ document.removeEventListener('mousedown', handler);
17
+ document.removeEventListener('keydown', escape);
18
+ };
19
+ }, [onClose]);
20
+ const items = [
21
+ { label: 'Brand Guidelines', href: 'https://hanzo.ai/brand' },
22
+ { label: 'Press Kit', href: 'https://hanzo.ai/press' },
23
+ { label: 'Download Logo', href: 'https://hanzo.ai/brand#download' },
24
+ { label: 'Copy SVG', action: 'copy-svg' },
25
+ { label: 'hanzo.ai →', href: 'https://hanzo.ai' },
26
+ ];
27
+ const LOGO_SVG = `<svg viewBox="0 0 67 67" xmlns="http://www.w3.org/2000/svg"><path d="M22.21 67V44.6369H0V67H22.21Z" fill="#ffffff"/><path d="M0 44.6369L22.21 46.8285V44.6369H0Z" fill="#DDDDDD"/><path d="M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z" fill="#ffffff"/><path d="M22.21 0H0V22.3184H22.21V0Z" fill="#ffffff"/><path d="M66.7198 0H44.5098V22.3184H66.7198V0Z" fill="#ffffff"/><path d="M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z" fill="#DDDDDD"/><path d="M66.7198 67V44.6369H44.5098V67H66.7198Z" fill="#ffffff"/></svg>`;
28
+ return (_jsxs("div", { ref: ref, role: "menu", className: "fixed z-[9999] min-w-[180px] rounded-xl border border-white/[0.08] bg-[#111113] py-1.5 shadow-2xl shadow-black/60", style: { top: y, left: x }, children: [_jsx("div", { className: "border-b border-white/[0.06] px-3 pb-2 pt-1", children: _jsx("p", { className: "text-[10px] font-semibold uppercase tracking-widest text-white/30", children: "Hanzo Brand" }) }), items.map((item) => (item.action === 'copy-svg' ? (_jsx("button", { type: "button", role: "menuitem", onClick: () => {
29
+ navigator.clipboard.writeText(LOGO_SVG).catch(() => { });
30
+ onClose();
31
+ }, className: "flex w-full items-center px-3 py-2 text-[13px] text-white/60 hover:bg-white/[0.05] hover:text-white/90 transition-colors text-left", children: "Copy SVG" }, "copy")) : (_jsx("a", { href: item.href, role: "menuitem", target: item.href?.startsWith('https') ? '_blank' : undefined, rel: "noopener noreferrer", onClick: onClose, className: "flex items-center px-3 py-2 text-[13px] text-white/60 hover:bg-white/[0.05] hover:text-white/90 transition-colors", children: item.label }, item.label))))] }));
32
+ }
33
+ /**
34
+ * Official Hanzo H-mark logo.
35
+ *
36
+ * - White fill paths with subtle shadow details
37
+ * - Hover: origami-style 3D perspective tilt + scale
38
+ * - Right-click: brand context menu (guidelines, press, download, copy SVG)
39
+ */
40
+ export function HanzoMark({ size = 22, className = '', brandMenu = true, animate = true, }) {
41
+ const [menu, setMenu] = useState(null);
42
+ const [hovered, setHovered] = useState(false);
43
+ const handleContextMenu = useCallback((e) => {
44
+ if (!brandMenu)
45
+ return;
46
+ e.preventDefault();
47
+ setMenu({ x: e.clientX, y: e.clientY });
48
+ }, [brandMenu]);
49
+ const style = animate ? {
50
+ transition: 'transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.2s ease',
51
+ transform: hovered
52
+ ? 'scale(1.12) perspective(80px) rotateY(-6deg)'
53
+ : 'scale(1) perspective(80px) rotateY(0deg)',
54
+ transformOrigin: 'center center',
55
+ } : {};
56
+ return (_jsxs(_Fragment, { children: [_jsxs("svg", { width: size, height: size, viewBox: "0 0 67 67", xmlns: "http://www.w3.org/2000/svg", "aria-label": "Hanzo", className: className, style: style, onMouseEnter: () => setHovered(true), onMouseLeave: () => setHovered(false), onContextMenu: handleContextMenu, children: [_jsx("path", { d: "M22.21 67V44.6369H0V67H22.21Z", fill: "#ffffff" }), _jsx("path", { d: "M0 44.6369L22.21 46.8285V44.6369H0Z", fill: "#DDDDDD" }), _jsx("path", { d: "M66.7038 22.3184H22.2534L0.0878906 44.6367H44.4634L66.7038 22.3184Z", fill: "#ffffff" }), _jsx("path", { d: "M22.21 0H0V22.3184H22.21V0Z", fill: "#ffffff" }), _jsx("path", { d: "M66.7198 0H44.5098V22.3184H66.7198V0Z", fill: "#ffffff" }), _jsx("path", { d: "M66.6753 22.3185L44.5098 20.0822V22.3185H66.6753Z", fill: "#DDDDDD" }), _jsx("path", { d: "M66.7198 67V44.6369H44.5098V67H66.7198Z", fill: "#ffffff" })] }), menu && (_jsx(BrandContextMenu, { x: menu.x, y: menu.y, onClose: () => setMenu(null) }))] }));
57
+ }
@@ -0,0 +1,15 @@
1
+ export interface UserAvatarProps {
2
+ /** Direct image URL (uploaded photo) */
3
+ src?: string;
4
+ /** Email for Gravatar lookup */
5
+ email?: string;
6
+ /** Name for generative fallback seed */
7
+ name?: string;
8
+ /** Size in px */
9
+ size?: number;
10
+ /** Custom colors for generative avatar */
11
+ colors?: string[];
12
+ className?: string;
13
+ }
14
+ export declare function UserAvatar({ src, email, name, size, colors, className, }: UserAvatarProps): import("react/jsx-runtime").JSX.Element;
15
+ //# sourceMappingURL=UserAvatar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserAvatar.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/UserAvatar.tsx"],"names":[],"mappings":"AAKA,MAAM,WAAW,eAAe;IAC9B,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,wCAAwC;IACxC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,iBAAiB;IACjB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,0CAA0C;IAC1C,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AA4BD,wBAAgB,UAAU,CAAC,EACzB,GAAG,EACH,KAAK,EACL,IAAI,EACJ,IAAS,EACT,MAAM,EACN,SAAS,GACV,EAAE,eAAe,2CA4CjB"}
@@ -0,0 +1,44 @@
1
+ 'use client';
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { useState, useMemo } from 'react';
4
+ import { BeamAvatar } from './BeamAvatar';
5
+ async function sha256(message) {
6
+ const encoder = new TextEncoder();
7
+ const data = encoder.encode(message);
8
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
9
+ return Array.from(new Uint8Array(hashBuffer))
10
+ .map((b) => b.toString(16).padStart(2, '0'))
11
+ .join('');
12
+ }
13
+ function useGravatarUrl(email, size) {
14
+ const [url, setUrl] = useState(null);
15
+ useMemo(() => {
16
+ if (!email) {
17
+ setUrl(null);
18
+ return;
19
+ }
20
+ const trimmed = email.trim().toLowerCase();
21
+ sha256(trimmed).then((hash) => {
22
+ setUrl(`https://www.gravatar.com/avatar/${hash}?s=${size || 80}&d=404`);
23
+ });
24
+ }, [email, size]);
25
+ return url;
26
+ }
27
+ export function UserAvatar({ src, email, name, size = 40, colors, className, }) {
28
+ const [photoFailed, setPhotoFailed] = useState(false);
29
+ const [gravatarFailed, setGravatarFailed] = useState(false);
30
+ const gravatarUrl = useGravatarUrl(email, size * 2);
31
+ const imgClass = `rounded-full object-cover ${className || ''}`;
32
+ const style = { width: size, height: size };
33
+ // Tier 1: uploaded/provided photo
34
+ if (src && !photoFailed) {
35
+ return (_jsx("img", { src: src, alt: name || email || 'avatar', className: imgClass, style: style, onError: () => setPhotoFailed(true) }));
36
+ }
37
+ // Tier 2: Gravatar
38
+ if (gravatarUrl && !gravatarFailed) {
39
+ return (_jsx("img", { src: gravatarUrl, alt: name || email || 'avatar', className: imgClass, style: style, onError: () => setGravatarFailed(true) }));
40
+ }
41
+ // Tier 3: generative beam avatar
42
+ const seed = name || email || 'user';
43
+ return (_jsx(BeamAvatar, { name: seed, size: size, colors: colors, className: className }));
44
+ }
@@ -0,0 +1,11 @@
1
+ import type { HanzoUser, HanzoOrg } from './types';
2
+ interface UserOrgDropdownProps {
3
+ user?: HanzoUser;
4
+ organizations?: HanzoOrg[];
5
+ currentOrgId?: string;
6
+ onOrgSwitch?: (orgId: string) => void;
7
+ onSignOut?: () => void;
8
+ }
9
+ export declare function UserOrgDropdown({ user, organizations, currentOrgId, onOrgSwitch, onSignOut, }: UserOrgDropdownProps): import("react/jsx-runtime").JSX.Element | null;
10
+ export {};
11
+ //# sourceMappingURL=UserOrgDropdown.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"UserOrgDropdown.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/UserOrgDropdown.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,SAAS,CAAA;AAGlD,UAAU,oBAAoB;IAC5B,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,aAAa,CAAC,EAAE,QAAQ,EAAE,CAAA;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IACrC,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;CACvB;AAED,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,aAAkB,EAClB,YAAY,EACZ,WAAW,EACX,SAAS,GACV,EAAE,oBAAoB,kDA8HtB"}
@@ -0,0 +1,26 @@
1
+ 'use client';
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { useState, useRef, useEffect } from 'react';
4
+ import { UserAvatar } from './UserAvatar';
5
+ export function UserOrgDropdown({ user, organizations = [], currentOrgId, onOrgSwitch, onSignOut, }) {
6
+ const [open, setOpen] = useState(false);
7
+ const ref = useRef(null);
8
+ useEffect(() => {
9
+ const handler = (e) => {
10
+ if (ref.current && !ref.current.contains(e.target))
11
+ setOpen(false);
12
+ };
13
+ document.addEventListener('mousedown', handler);
14
+ return () => document.removeEventListener('mousedown', handler);
15
+ }, []);
16
+ if (!user)
17
+ return null;
18
+ const currentOrg = organizations.find((o) => o.id === currentOrgId);
19
+ return (_jsxs("div", { ref: ref, className: "relative", children: [_jsxs("button", { type: "button", onClick: () => setOpen((v) => !v), className: "flex items-center gap-2 rounded-lg px-2 py-1.5 hover:bg-white/[0.06] transition-colors", children: [_jsx(UserAvatar, { src: user.avatar, email: user.email, name: user.name, size: 28 }), _jsxs("div", { className: "hidden flex-col items-start sm:flex", children: [user.name && (_jsx("span", { className: "text-[12px] font-medium text-white/70 leading-none", children: user.name })), _jsx("span", { className: "text-[11px] text-white/30 leading-none mt-0.5", children: user.email })] }), _jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", className: "text-white/30 hidden sm:block", children: _jsx("path", { d: "M6 9l6 6 6-6" }) })] }), open && (_jsxs("div", { className: "absolute right-0 top-10 z-50 w-64 rounded-xl border border-white/[0.08] bg-[#0e0e13] shadow-2xl", children: [_jsxs("div", { className: "border-b border-white/[0.06] px-4 py-3", children: [_jsx("p", { className: "text-[13px] font-medium text-white/80", children: user.name || 'User' }), _jsx("p", { className: "text-[11px] text-white/40", children: user.email })] }), organizations.length > 0 && (_jsxs("div", { className: "border-b border-white/[0.06] p-2", children: [_jsx("p", { className: "px-2 pb-1 pt-0.5 text-[10px] font-medium uppercase tracking-wider text-white/30", children: "Organizations" }), organizations.map((org) => (_jsxs("button", { type: "button", onClick: () => {
20
+ onOrgSwitch?.(org.id);
21
+ setOpen(false);
22
+ }, className: "flex w-full items-center justify-between rounded-lg px-3 py-2 text-left hover:bg-white/[0.06] transition-colors", children: [_jsx("span", { className: "text-[13px] text-white/70", children: org.name }), org.id === currentOrgId && (_jsx("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", className: "text-white/50", children: _jsx("polyline", { points: "20 6 9 17 4 12" }) }))] }, org.id)))] })), _jsxs("div", { className: "p-2", children: [_jsx("a", { href: "https://hanzo.id/account", className: "flex items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] text-white/60 hover:bg-white/[0.06] hover:text-white/80 transition-colors", onClick: () => setOpen(false), children: "Account settings" }), _jsx("a", { href: "https://billing.hanzo.ai", className: "flex items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] text-white/60 hover:bg-white/[0.06] hover:text-white/80 transition-colors", onClick: () => setOpen(false), children: "Billing" }), _jsx("button", { type: "button", onClick: () => {
23
+ setOpen(false);
24
+ onSignOut?.();
25
+ }, className: "flex w-full items-center gap-2.5 rounded-lg px-3 py-2 text-[13px] text-white/40 hover:bg-white/[0.06] hover:text-red-400/70 transition-colors", children: "Sign out" })] })] }))] }));
26
+ }
@@ -0,0 +1,14 @@
1
+ export { HanzoHeader } from './HanzoHeader';
2
+ export { HanzoMark } from './HanzoMark';
3
+ export { AppSwitcher } from './AppSwitcher';
4
+ export { UserOrgDropdown } from './UserOrgDropdown';
5
+ export { UserAvatar } from './UserAvatar';
6
+ export type { UserAvatarProps } from './UserAvatar';
7
+ export { BeamAvatar } from './BeamAvatar';
8
+ export type { BeamAvatarProps } from './BeamAvatar';
9
+ export { useHanzoAuth } from './useHanzoAuth';
10
+ export { HanzoCommandPalette } from './HanzoCommandPalette';
11
+ export type { CommandItem as HanzoCommandItem, HanzoCommandPaletteProps } from './HanzoCommandPalette';
12
+ export type { HanzoApp, HanzoOrg, HanzoUser, HanzoShellProps, HanzoMarkProps } from './types';
13
+ export { DEFAULT_HANZO_APPS } from './types';
14
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/navigation/hanzo-shell/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AACzC,YAAY,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAA;AAC7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAA;AAC3D,YAAY,EAAE,WAAW,IAAI,gBAAgB,EAAE,wBAAwB,EAAE,MAAM,uBAAuB,CAAA;AACtG,YAAY,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAC7F,OAAO,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAA"}
@@ -0,0 +1,9 @@
1
+ export { HanzoHeader } from './HanzoHeader';
2
+ export { HanzoMark } from './HanzoMark';
3
+ export { AppSwitcher } from './AppSwitcher';
4
+ export { UserOrgDropdown } from './UserOrgDropdown';
5
+ export { UserAvatar } from './UserAvatar';
6
+ export { BeamAvatar } from './BeamAvatar';
7
+ export { useHanzoAuth } from './useHanzoAuth';
8
+ export { HanzoCommandPalette } from './HanzoCommandPalette';
9
+ export { DEFAULT_HANZO_APPS } from './types';