@luxfi/ui 7.3.2 → 7.4.2

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 (154) hide show
  1. package/dist/alert.cjs +2 -2
  2. package/dist/alert.js +1 -1
  3. package/dist/avatar.cjs +7 -6
  4. package/dist/avatar.js +7 -5
  5. package/dist/badge.cjs +36 -38
  6. package/dist/badge.js +31 -33
  7. package/dist/bank.cjs +13 -13
  8. package/dist/bank.d.cts +31 -24
  9. package/dist/bank.d.ts +31 -24
  10. package/dist/bank.js +1 -1
  11. package/dist/button.cjs +3 -3
  12. package/dist/button.js +1 -1
  13. package/dist/checkbox.cjs +4 -4
  14. package/dist/checkbox.d.cts +3 -2
  15. package/dist/checkbox.d.ts +3 -2
  16. package/dist/checkbox.js +5 -4
  17. package/dist/chrome.cjs +950 -0
  18. package/dist/chrome.d.cts +93 -0
  19. package/dist/chrome.d.ts +93 -0
  20. package/dist/chrome.js +921 -0
  21. package/dist/close-button.cjs +2 -2
  22. package/dist/close-button.js +1 -1
  23. package/dist/dialog.cjs +13 -14
  24. package/dist/dialog.d.cts +58 -5
  25. package/dist/dialog.d.ts +58 -5
  26. package/dist/dialog.js +1 -2
  27. package/dist/drawer.cjs +87 -21
  28. package/dist/drawer.js +85 -19
  29. package/dist/expiration-selector.cjs +3 -2
  30. package/dist/expiration-selector.js +3 -2
  31. package/dist/greeks-display.cjs +6 -6
  32. package/dist/greeks-display.js +6 -6
  33. package/dist/gui.cjs +13 -0
  34. package/dist/gui.d.cts +2 -0
  35. package/dist/gui.d.ts +2 -0
  36. package/dist/gui.js +2 -0
  37. package/dist/heading.cjs +4 -2
  38. package/dist/heading.js +4 -2
  39. package/dist/iam.cjs +206 -0
  40. package/dist/iam.d.cts +65 -0
  41. package/dist/iam.d.ts +65 -0
  42. package/dist/iam.js +201 -0
  43. package/dist/icon-button.cjs +2 -2
  44. package/dist/icon-button.js +1 -1
  45. package/dist/icons.cjs +13 -0
  46. package/dist/icons.d.cts +1 -0
  47. package/dist/icons.d.ts +1 -0
  48. package/dist/icons.js +2 -0
  49. package/dist/identity.cjs +420 -0
  50. package/dist/identity.d.cts +64 -0
  51. package/dist/identity.d.ts +64 -0
  52. package/dist/identity.js +398 -0
  53. package/dist/index.cjs +1699 -860
  54. package/dist/index.d.cts +12 -4
  55. package/dist/index.d.ts +12 -4
  56. package/dist/index.js +1618 -802
  57. package/dist/input.cjs +13 -3
  58. package/dist/input.d.cts +6 -0
  59. package/dist/input.d.ts +6 -0
  60. package/dist/input.js +13 -3
  61. package/dist/lux.config.cjs +77 -0
  62. package/dist/lux.config.d.cts +433 -0
  63. package/dist/lux.config.d.ts +433 -0
  64. package/dist/lux.config.js +69 -0
  65. package/dist/menu.cjs +4 -4
  66. package/dist/menu.js +4 -4
  67. package/dist/next.cjs +99 -0
  68. package/dist/next.d.cts +29 -0
  69. package/dist/next.d.ts +29 -0
  70. package/dist/next.js +96 -0
  71. package/dist/option-chain.cjs +1 -1
  72. package/dist/option-chain.js +1 -1
  73. package/dist/option-position.cjs +2 -1
  74. package/dist/option-position.js +2 -1
  75. package/dist/pnl-diagram.cjs +8 -6
  76. package/dist/pnl-diagram.js +8 -6
  77. package/dist/popover.cjs +8 -9
  78. package/dist/popover.js +1 -2
  79. package/dist/progress.cjs +7 -6
  80. package/dist/progress.js +7 -5
  81. package/dist/provider.cjs +199 -5
  82. package/dist/provider.d.cts +16 -3
  83. package/dist/provider.d.ts +16 -3
  84. package/dist/provider.js +195 -6
  85. package/dist/radio.cjs +9 -7
  86. package/dist/radio.js +10 -7
  87. package/dist/separator.cjs +3 -1
  88. package/dist/separator.js +3 -1
  89. package/dist/slider.cjs +28 -16
  90. package/dist/slider.js +28 -15
  91. package/dist/strategy-builder.cjs +2 -1
  92. package/dist/strategy-builder.js +2 -1
  93. package/dist/switch.cjs +11 -12
  94. package/dist/switch.js +12 -12
  95. package/dist/tag.cjs +38 -41
  96. package/dist/tag.js +31 -34
  97. package/dist/textarea.cjs +13 -3
  98. package/dist/textarea.d.cts +2 -0
  99. package/dist/textarea.d.ts +2 -0
  100. package/dist/textarea.js +13 -3
  101. package/dist/tooltip.cjs +31 -33
  102. package/dist/tooltip.js +25 -27
  103. package/dist/use-narrow.cjs +46 -0
  104. package/dist/use-narrow.d.cts +12 -0
  105. package/dist/use-narrow.d.ts +12 -0
  106. package/dist/use-narrow.js +20 -0
  107. package/dist/vite.cjs +40 -0
  108. package/dist/vite.d.cts +29 -0
  109. package/dist/vite.d.ts +29 -0
  110. package/dist/vite.js +38 -0
  111. package/dist/white-label.cjs +132 -0
  112. package/dist/white-label.d.cts +59 -0
  113. package/dist/white-label.d.ts +59 -0
  114. package/dist/white-label.js +124 -0
  115. package/package.json +95 -17
  116. package/src/avatar.tsx +22 -16
  117. package/src/bank.tsx +2 -2
  118. package/src/button.tsx +1 -1
  119. package/src/checkbox.tsx +15 -10
  120. package/src/chrome.tsx +459 -0
  121. package/src/close-button.tsx +1 -1
  122. package/src/dialog.tsx +1 -1
  123. package/src/drawer.tsx +83 -10
  124. package/src/expiration-selector.tsx +3 -2
  125. package/src/greeks-display.tsx +9 -6
  126. package/src/gui.ts +17 -0
  127. package/src/heading.tsx +12 -8
  128. package/src/iam.ts +170 -0
  129. package/src/icon-button.tsx +1 -1
  130. package/src/icons.ts +18 -0
  131. package/src/identity.tsx +318 -0
  132. package/src/index.ts +50 -1
  133. package/src/input.tsx +24 -4
  134. package/src/lux.config.ts +82 -0
  135. package/src/menu.tsx +4 -4
  136. package/src/next.ts +142 -0
  137. package/src/option-chain.tsx +1 -1
  138. package/src/option-position.tsx +2 -1
  139. package/src/pnl-diagram.tsx +11 -6
  140. package/src/popover.tsx +1 -1
  141. package/src/progress.tsx +15 -8
  142. package/src/provider.tsx +92 -12
  143. package/src/radio.tsx +15 -11
  144. package/src/separator.tsx +8 -3
  145. package/src/slider.tsx +35 -19
  146. package/src/strategy-builder.tsx +3 -2
  147. package/src/switch.tsx +17 -16
  148. package/src/textarea.tsx +18 -4
  149. package/src/tooltip.tsx +4 -23
  150. package/src/use-narrow.ts +40 -0
  151. package/src/vite.ts +78 -0
  152. package/src/white-label.ts +240 -0
  153. package/tokens.css +544 -319
  154. package/src/tokens.css +0 -438
@@ -0,0 +1,59 @@
1
+ declare const LUX_BRAND: {
2
+ readonly lux: "#7000FF";
3
+ readonly zoo: "#6C5EFB";
4
+ readonly hanzo: "#EA580C";
5
+ readonly pars: "#1C3879";
6
+ readonly bootnode: "#3B82F6";
7
+ };
8
+ declare const PARS_GOLD = "#C8A45C";
9
+ type LuxBrand = keyof typeof LUX_BRAND;
10
+ type Org = LuxBrand;
11
+ interface OrgIdentity {
12
+ /** Org id — also the gui child-theme suffix (`dark_lux`, `dark_zoo`, …). */
13
+ readonly org: Org;
14
+ /** Display name for chrome (header, title, sign-in copy). */
15
+ readonly name: string;
16
+ /** Canonical apex domain. */
17
+ readonly domain: string;
18
+ /** IAM/OIDC host. The issuer is `https://` + this. */
19
+ readonly iamDomain: string;
20
+ /** Brand accent hex — the same value the gui child-theme row is built from. */
21
+ readonly accent: string;
22
+ /** Foreground used on top of the accent. */
23
+ readonly accentForeground: string;
24
+ }
25
+ declare const ORGS: Readonly<Record<Org, OrgIdentity>>;
26
+ declare const DEFAULT_ORG: Org;
27
+ interface WhiteLabel extends OrgIdentity {
28
+ /** Hostname the identity was resolved from, port stripped, lowercased. */
29
+ readonly host: string;
30
+ /** App slug taken from the hostname — `mpc.lux.cloud` → `mpc`. */
31
+ readonly app: string;
32
+ /** gui child-theme row to hand GuiProvider — `dark_lux`, `dark_zoo`, … */
33
+ readonly theme: string;
34
+ /** OIDC issuer — `https://lux.id`. */
35
+ readonly issuer: string;
36
+ /** IAM client id, `<org>-<app>` per the fleet naming scheme — `lux-mpc`. */
37
+ readonly clientId: string;
38
+ }
39
+ /**
40
+ * Resolve the full white-label identity from a Host header value.
41
+ *
42
+ * Pure and total: an unknown or missing host falls back to the Lux row rather
43
+ * than throwing, so a preview URL or a health probe never blanks the UI.
44
+ *
45
+ * resolveWhiteLabel('mpc.lux.cloud') // org lux, clientId lux-mpc, issuer https://lux.id
46
+ * resolveWhiteLabel('zoo.network') // org zoo, clientId zoo-network, issuer https://zoo.id
47
+ * resolveWhiteLabel('id.pars.id') // org pars, clientId pars-id, issuer https://pars.id
48
+ */
49
+ declare function resolveWhiteLabel(host?: string | null): WhiteLabel;
50
+ /**
51
+ * The current host in a browser, or '' during SSR / prerender.
52
+ * Server code must pass `req.headers.host` to resolveWhiteLabel explicitly —
53
+ * there is no ambient request here, and guessing would bake in a brand.
54
+ */
55
+ declare function currentHost(): string;
56
+ /** Identity for the org id itself, for the rare surface that is not host-routed. */
57
+ declare function orgIdentity(org: Org): OrgIdentity;
58
+
59
+ export { DEFAULT_ORG, LUX_BRAND, type LuxBrand, type Org, type OrgIdentity, PARS_GOLD, type WhiteLabel, currentHost, orgIdentity, ORGS as orgs, resolveWhiteLabel };
@@ -0,0 +1,124 @@
1
+ // src/white-label.ts
2
+ var LUX_BRAND = {
3
+ lux: "#7000FF",
4
+ zoo: "#6C5EFB",
5
+ hanzo: "#EA580C",
6
+ pars: "#1C3879",
7
+ // bootno.de is its own white label with its own IdP (id.bootno.de) — accent
8
+ // taken from the bootnode console's own brand default, not invented here.
9
+ bootnode: "#3B82F6"
10
+ };
11
+ var PARS_GOLD = "#C8A45C";
12
+ var ORGS = {
13
+ lux: {
14
+ org: "lux",
15
+ name: "Lux",
16
+ domain: "lux.network",
17
+ iamDomain: "lux.id",
18
+ accent: LUX_BRAND.lux,
19
+ accentForeground: "#FFFFFF"
20
+ },
21
+ zoo: {
22
+ org: "zoo",
23
+ name: "Zoo",
24
+ domain: "zoo.ngo",
25
+ // Zoo's IdP is `id.zoo.network`, not a `zoo.id` apex — the one row in this
26
+ // table where the issuer is not `<org>.id`, and the one every hand-rolled
27
+ // per-app branding map got wrong.
28
+ iamDomain: "id.zoo.network",
29
+ accent: LUX_BRAND.zoo,
30
+ accentForeground: "#FFFFFF"
31
+ },
32
+ bootnode: {
33
+ org: "bootnode",
34
+ name: "Bootnode",
35
+ domain: "bootno.de",
36
+ iamDomain: "id.bootno.de",
37
+ accent: LUX_BRAND.lux,
38
+ accentForeground: "#FFFFFF"
39
+ },
40
+ hanzo: {
41
+ org: "hanzo",
42
+ name: "Hanzo",
43
+ domain: "hanzo.ai",
44
+ iamDomain: "hanzo.id",
45
+ accent: LUX_BRAND.hanzo,
46
+ accentForeground: "#FFFFFF"
47
+ },
48
+ pars: {
49
+ org: "pars",
50
+ name: "Pars",
51
+ domain: "pars.id",
52
+ iamDomain: "pars.id",
53
+ accent: LUX_BRAND.pars,
54
+ accentForeground: PARS_GOLD
55
+ }
56
+ };
57
+ var DOMAIN_ORG = [
58
+ ["lux.network", "lux"],
59
+ ["lux.cloud", "lux"],
60
+ ["lux.id", "lux"],
61
+ ["lux.finance", "lux"],
62
+ ["zoo.ngo", "zoo"],
63
+ ["zoo.network", "zoo"],
64
+ ["zoo.cloud", "zoo"],
65
+ ["zoo.id", "zoo"],
66
+ ["hanzo.ai", "hanzo"],
67
+ ["hanzo.cloud", "hanzo"],
68
+ ["hanzo.id", "hanzo"],
69
+ ["pars.id", "pars"],
70
+ ["parsdao.org", "pars"],
71
+ ["bootno.de", "bootnode", "platform"]
72
+ ];
73
+ var DEFAULT_ORG = "lux";
74
+ function normalizeHost(host) {
75
+ const noPort = host.trim().toLowerCase().split(":")[0] ?? "";
76
+ return noPort.replace(/\.$/, "");
77
+ }
78
+ function isUnder(host, domain) {
79
+ return host === domain || host.endsWith(`.${domain}`);
80
+ }
81
+ function matchDomain(host) {
82
+ let best;
83
+ for (const entry of DOMAIN_ORG) {
84
+ if (isUnder(host, entry[0]) && (!best || entry[0].length > best[0].length)) {
85
+ best = entry;
86
+ }
87
+ }
88
+ return best;
89
+ }
90
+ function appSlug(host, domain, apexApp) {
91
+ const sub = host === domain ? "" : host.slice(0, -(domain.length + 1));
92
+ const leftmost = sub.split(".")[0] ?? "";
93
+ if (leftmost && leftmost !== "www") return leftmost;
94
+ if (apexApp) return apexApp;
95
+ const label = domain.split(".")[0] ?? "";
96
+ const tld = domain.split(".").slice(1).join(".");
97
+ return tld.split(".")[0] || label;
98
+ }
99
+ function isLocal(host) {
100
+ return host === "localhost" || host.endsWith(".localhost") || host === "127.0.0.1" || host === "0.0.0.0" || host === "[::1]" || host.endsWith(".local");
101
+ }
102
+ function resolveWhiteLabel(host) {
103
+ const h = normalizeHost(host ?? "");
104
+ const match = h ? matchDomain(h) : void 0;
105
+ const org = match ? match[1] : DEFAULT_ORG;
106
+ const identity = ORGS[org];
107
+ const app = match ? appSlug(h, match[0], match[2]) : h && isLocal(h) ? "local" : "app";
108
+ return {
109
+ ...identity,
110
+ host: h,
111
+ app,
112
+ theme: `dark_${org}`,
113
+ issuer: `https://${identity.iamDomain}`,
114
+ clientId: `${org}-${app}`
115
+ };
116
+ }
117
+ function currentHost() {
118
+ return typeof window === "undefined" ? "" : window.location.host;
119
+ }
120
+ function orgIdentity(org) {
121
+ return ORGS[org];
122
+ }
123
+
124
+ export { DEFAULT_ORG, LUX_BRAND, PARS_GOLD, currentHost, orgIdentity, ORGS as orgs, resolveWhiteLabel };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@luxfi/ui",
3
- "version": "7.3.2",
4
- "description": "Radix + Tailwind UI primitives for Lux apps. Drop-in replacements for Chakra compound components.",
3
+ "version": "7.4.2",
4
+ "description": "Cross-platform DeFi UI components built on @hanzo/gui (Tamagui). Native mobile + web.",
5
5
  "type": "module",
6
6
  "license": "MIT",
7
7
  "author": {
@@ -35,6 +35,46 @@
35
35
  "import": "./dist/index.js",
36
36
  "require": "./dist/index.cjs"
37
37
  },
38
+ "./gui": {
39
+ "types": "./dist/gui.d.ts",
40
+ "import": "./dist/gui.js",
41
+ "require": "./dist/gui.cjs"
42
+ },
43
+ "./white-label": {
44
+ "types": "./dist/white-label.d.ts",
45
+ "import": "./dist/white-label.js",
46
+ "require": "./dist/white-label.cjs"
47
+ },
48
+ "./iam": {
49
+ "types": "./dist/iam.d.ts",
50
+ "import": "./dist/iam.js",
51
+ "require": "./dist/iam.cjs"
52
+ },
53
+ "./identity": {
54
+ "types": "./dist/identity.d.ts",
55
+ "import": "./dist/identity.js",
56
+ "require": "./dist/identity.cjs"
57
+ },
58
+ "./chrome": {
59
+ "types": "./dist/chrome.d.ts",
60
+ "import": "./dist/chrome.js",
61
+ "require": "./dist/chrome.cjs"
62
+ },
63
+ "./use-narrow": {
64
+ "types": "./dist/use-narrow.d.ts",
65
+ "import": "./dist/use-narrow.js",
66
+ "require": "./dist/use-narrow.cjs"
67
+ },
68
+ "./vite": {
69
+ "types": "./dist/vite.d.ts",
70
+ "import": "./dist/vite.js",
71
+ "require": "./dist/vite.cjs"
72
+ },
73
+ "./next": {
74
+ "types": "./dist/next.d.ts",
75
+ "import": "./dist/next.js",
76
+ "require": "./dist/next.cjs"
77
+ },
38
78
  "./tokens.css": "./tokens.css",
39
79
  "./accordion": {
40
80
  "types": "./dist/accordion.d.ts",
@@ -111,6 +151,11 @@
111
151
  "import": "./dist/icon-button.js",
112
152
  "require": "./dist/icon-button.cjs"
113
153
  },
154
+ "./icons": {
155
+ "types": "./dist/icons.d.ts",
156
+ "import": "./dist/icons.js",
157
+ "require": "./dist/icons.cjs"
158
+ },
114
159
  "./image": {
115
160
  "types": "./dist/image.d.ts",
116
161
  "import": "./dist/image.js",
@@ -250,14 +295,11 @@
250
295
  "build": "tsup",
251
296
  "build:check": "tsc --noEmit",
252
297
  "clean": "rm -rf dist",
253
- "dev": "tsup --watch"
298
+ "dev": "tsup --watch",
299
+ "harness": "vite --config harness/vite.config.ts",
300
+ "test": "playwright test"
254
301
  },
255
302
  "dependencies": {
256
- "@hanzogui/core": "^3.0.6",
257
- "@hanzogui/dialog": "^3.0.2",
258
- "@hanzogui/popover": "^3.0.2",
259
- "@hanzogui/text": "^3.0.2",
260
- "@hanzogui/tooltip": "^3.0.2",
261
303
  "@radix-ui/react-accordion": "^1.2.12",
262
304
  "@radix-ui/react-avatar": "^1.1.10",
263
305
  "@radix-ui/react-checkbox": "^1.3.3",
@@ -271,24 +313,60 @@
271
313
  "@radix-ui/react-slider": "^1.3.6",
272
314
  "@radix-ui/react-switch": "^1.2.6",
273
315
  "@radix-ui/react-tabs": "^1.1.13",
316
+ "@tanstack/react-query": "^5.76.0",
274
317
  "@uidotdev/usehooks": "^2.4.1",
275
318
  "clsx": "^2.1.1",
276
319
  "es-toolkit": "^1.31.0",
277
- "react-icons": "^5.4.0",
320
+ "lucide-react": "^1.27.0",
278
321
  "sonner": "^2.0.0",
279
- "tailwind-merge": "^3.0.0",
280
- "@tanstack/react-query": "^5.76.0"
322
+ "tailwind-merge": "^3.0.0"
281
323
  },
282
324
  "peerDependencies": {
283
- "@hanzogui/core": "^3.0.6",
284
- "react": ">=18",
285
- "react-dom": "^18.0.0 || ^19.0.0"
325
+ "@hanzo/gui": "^7.3.0",
326
+ "@hanzogui/colors": "^7.3.0",
327
+ "@hanzogui/config": "^7.3.0",
328
+ "@hanzogui/core": "^7.3.0",
329
+ "@hanzogui/lucide-icons-2": "^7.3.0",
330
+ "@hanzogui/themes": "^7.3.0",
331
+ "@hanzogui/web": "^7.3.0",
332
+ "react": ">=19",
333
+ "react-dom": ">=19"
334
+ },
335
+ "peerDependenciesMeta": {
336
+ "@hanzogui/themes": {
337
+ "optional": true
338
+ },
339
+ "@hanzogui/colors": {
340
+ "optional": true
341
+ },
342
+ "@hanzogui/lucide-icons-2": {
343
+ "optional": true
344
+ },
345
+ "@hanzogui/core": {
346
+ "optional": true
347
+ },
348
+ "@hanzogui/web": {
349
+ "optional": true
350
+ }
286
351
  },
287
352
  "devDependencies": {
288
- "@hanzogui/core": "^3.0.6",
353
+ "@hanzo/gui": "7.3.0",
354
+ "@hanzogui/colors": "7.3.0",
355
+ "@hanzogui/config": "7.3.0",
356
+ "@hanzogui/core": "7.3.0",
357
+ "@hanzogui/themes": "7.3.0",
358
+ "@hanzogui/web": "7.3.0",
359
+ "@playwright/test": "^1.58",
360
+ "@tailwindcss/vite": "^4",
289
361
  "@types/react": "^19.0.0",
290
362
  "@types/react-dom": "^19.0.0",
363
+ "@vitejs/plugin-react": "^6",
364
+ "react": "^19.0.0",
365
+ "react-dom": "^19.0.0",
366
+ "react-native-web": "^0.21.0",
367
+ "tailwindcss": "^4",
291
368
  "tsup": "^8.5.0",
292
- "typescript": "^5.9.3"
369
+ "typescript": "^5.9.3",
370
+ "vite": "^8"
293
371
  }
294
- }
372
+ }
package/src/avatar.tsx CHANGED
@@ -1,6 +1,6 @@
1
1
  'use client';
2
2
 
3
- import * as RadixAvatar from '@radix-ui/react-avatar';
3
+ import { Avatar as GuiAvatar } from '@hanzo/gui';
4
4
  import * as React from 'react';
5
5
 
6
6
  import { cn } from './utils';
@@ -80,9 +80,12 @@ export const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
80
80
  const variant = variantProp ?? group.variant ?? DEFAULT_VARIANT;
81
81
  const isBorderless = borderless ?? group.borderless ?? false;
82
82
 
83
+ // gui's Avatar — the same load/fallback state machine, but as a gui
84
+ // primitive, so it themes and lays out identically on native.
83
85
  return (
84
- <RadixAvatar.Root
85
- ref={ ref }
86
+ <GuiAvatar
87
+ ref={ ref as never }
88
+ unstyled
86
89
  className={ cn(
87
90
  'relative inline-flex shrink-0 items-center justify-center overflow-hidden rounded-full align-middle',
88
91
  SIZE_CLASSES[size],
@@ -90,20 +93,22 @@ export const Avatar = React.forwardRef<HTMLSpanElement, AvatarProps>(
90
93
  !isBorderless && 'ring-2 ring-white dark:ring-gray-900',
91
94
  className,
92
95
  ) }
93
- { ...rest }
96
+ { ...(rest as object) }
94
97
  >
95
98
  <AvatarFallback name={ name } icon={ icon }>
96
99
  { fallback }
97
100
  </AvatarFallback>
98
- <RadixAvatar.Image
99
- className="h-full w-full rounded-[inherit] object-cover"
100
- src={ src }
101
- srcSet={ srcSet }
102
- loading={ loading }
103
- alt={ name ?? '' }
104
- />
101
+ { src != null && (
102
+ <GuiAvatar.Image
103
+ className="h-full w-full rounded-[inherit] object-cover"
104
+ src={ src }
105
+ srcSet={ srcSet }
106
+ loading={ loading }
107
+ alt={ name ?? '' }
108
+ />
109
+ ) }
105
110
  { children }
106
- </RadixAvatar.Root>
111
+ </GuiAvatar>
107
112
  );
108
113
  },
109
114
  );
@@ -119,18 +124,19 @@ const AvatarFallback = React.forwardRef<HTMLSpanElement, AvatarFallbackInternalP
119
124
  function AvatarFallback(props, ref) {
120
125
  const { name, icon, children, className, ...rest } = props;
121
126
  return (
122
- <RadixAvatar.Fallback
123
- ref={ ref }
127
+ <GuiAvatar.Fallback
128
+ ref={ ref as never }
129
+ unstyled
124
130
  className={ cn(
125
131
  'flex h-full w-full items-center justify-center font-medium',
126
132
  className,
127
133
  ) }
128
- { ...rest }
134
+ { ...(rest as object) }
129
135
  >
130
136
  { children }
131
137
  { name != null && children == null && <>{ getInitials(name) }</> }
132
138
  { name == null && children == null && icon }
133
- </RadixAvatar.Fallback>
139
+ </GuiAvatar.Fallback>
134
140
  );
135
141
  },
136
142
  );
package/src/bank.tsx CHANGED
@@ -1,8 +1,8 @@
1
1
  'use client'
2
2
 
3
3
  import React from 'react'
4
- import type { GetProps } from '@hanzogui/core'
5
- import { View, Text, styled } from '@hanzogui/core'
4
+ import type { GetProps } from '@hanzo/gui'
5
+ import { View, Text, styled } from '@hanzo/gui'
6
6
 
7
7
  // ── Bank Theme Tokens ─────────────────────────────────────────────
8
8
  export const bankColors = {
package/src/button.tsx CHANGED
@@ -1,4 +1,4 @@
1
- import { styled, View } from '@hanzogui/core';
1
+ import { styled, View } from '@hanzo/gui';
2
2
  import * as React from 'react';
3
3
 
4
4
  import { Skeleton } from './skeleton';
package/src/checkbox.tsx CHANGED
@@ -1,9 +1,11 @@
1
- import * as RadixCheckbox from '@radix-ui/react-checkbox';
2
- // chakra() HOC removed — pure Radix + Tailwind
1
+ import { Checkbox as GuiCheckbox } from '@hanzo/gui';
3
2
  import * as React from 'react';
4
3
 
5
4
  import { cn } from './utils';
6
5
 
6
+ /** Tri-state, as the Chakra/Radix contract consumers already code against. */
7
+ type CheckedState = boolean | 'indeterminate';
8
+
7
9
  const NOOP = () => { /* noop */ };
8
10
 
9
11
  // ─── CheckboxGroup context ───────────────────────────────────────────
@@ -98,7 +100,7 @@ export interface CheckboxProps extends Omit<React.ComponentPropsWithoutRef<'labe
98
100
  rootRef?: React.Ref<HTMLLabelElement>;
99
101
  checked?: boolean | 'indeterminate';
100
102
  defaultChecked?: boolean;
101
- onCheckedChange?: (checked: RadixCheckbox.CheckedState) => void;
103
+ onCheckedChange?: (checked: CheckedState) => void;
102
104
  onChange?: React.FormEventHandler<HTMLLabelElement>;
103
105
  disabled?: boolean;
104
106
  readOnly?: boolean;
@@ -189,12 +191,12 @@ const CheckboxBase = React.forwardRef<HTMLInputElement, CheckboxProps>(
189
191
  const isInGroup = group !== null && value !== undefined;
190
192
  const groupChecked = isInGroup ? group.value.includes(value) : undefined;
191
193
 
192
- const [ internalChecked, setInternalChecked ] = React.useState<RadixCheckbox.CheckedState>(
194
+ const [ internalChecked, setInternalChecked ] = React.useState<CheckedState>(
193
195
  defaultChecked ?? false,
194
196
  );
195
197
 
196
198
  const isControlled = checkedProp !== undefined || isInGroup;
197
- let checkedState: RadixCheckbox.CheckedState;
199
+ let checkedState: CheckedState;
198
200
  if (checkedProp !== undefined) {
199
201
  checkedState = checkedProp;
200
202
  } else if (isInGroup) {
@@ -204,7 +206,7 @@ const CheckboxBase = React.forwardRef<HTMLInputElement, CheckboxProps>(
204
206
  }
205
207
 
206
208
  const handleCheckedChange = React.useCallback(
207
- (nextChecked: RadixCheckbox.CheckedState) => {
209
+ (nextChecked: CheckedState) => {
208
210
  if (readOnly) return;
209
211
 
210
212
  if (!isControlled) {
@@ -252,7 +254,10 @@ const CheckboxBase = React.forwardRef<HTMLInputElement, CheckboxProps>(
252
254
  data-readonly={ readOnly || undefined }
253
255
  { ...rest }
254
256
  >
255
- <RadixCheckbox.Root
257
+ { /* gui's Checkbox — role=checkbox + aria-checked from its headless core,
258
+ a real Pressable on native. Paint stays in the Lux classes. */ }
259
+ <GuiCheckbox
260
+ unstyled
256
261
  checked={ checkedState }
257
262
  onCheckedChange={ handleCheckedChange }
258
263
  disabled={ disabled || readOnly }
@@ -272,15 +277,15 @@ const CheckboxBase = React.forwardRef<HTMLInputElement, CheckboxProps>(
272
277
  ) }
273
278
  >
274
279
  { icon ?? (
275
- <RadixCheckbox.Indicator className={ cn('flex items-center justify-center', sizeClasses.icon) }>
280
+ <GuiCheckbox.Indicator className={ cn('flex items-center justify-center', sizeClasses.icon) }>
276
281
  { checkedState === 'indeterminate' ? (
277
282
  <IndeterminateIcon className={ sizeClasses.icon }/>
278
283
  ) : (
279
284
  <CheckIcon className={ sizeClasses.icon }/>
280
285
  ) }
281
- </RadixCheckbox.Indicator>
286
+ </GuiCheckbox.Indicator>
282
287
  ) }
283
- </RadixCheckbox.Root>
288
+ </GuiCheckbox>
284
289
  { /* Hidden native input for form compatibility and ref forwarding */ }
285
290
  <input
286
291
  ref={ setHiddenInputRef }