@luxfi/ui 7.4.0 → 7.4.3
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/avatar.cjs +7 -6
- package/dist/avatar.js +7 -5
- package/dist/badge.cjs +33 -35
- package/dist/badge.js +33 -35
- package/dist/bank.d.cts +3 -3
- package/dist/bank.d.ts +3 -3
- package/dist/checkbox.cjs +4 -4
- package/dist/checkbox.d.cts +3 -2
- package/dist/checkbox.d.ts +3 -2
- package/dist/checkbox.js +5 -4
- package/dist/chrome.cjs +960 -0
- package/dist/chrome.d.cts +93 -0
- package/dist/chrome.d.ts +93 -0
- package/dist/chrome.js +931 -0
- package/dist/drawer.cjs +86 -20
- package/dist/drawer.js +85 -19
- package/dist/expiration-selector.cjs +3 -2
- package/dist/expiration-selector.js +3 -2
- package/dist/greeks-display.cjs +6 -6
- package/dist/greeks-display.js +6 -6
- package/dist/gui.cjs +13 -0
- package/dist/gui.d.cts +2 -0
- package/dist/gui.d.ts +2 -0
- package/dist/gui.js +2 -0
- package/dist/heading.cjs +4 -2
- package/dist/heading.js +4 -2
- package/dist/iam.cjs +216 -0
- package/dist/iam.d.cts +65 -0
- package/dist/iam.d.ts +65 -0
- package/dist/iam.js +211 -0
- package/dist/icons.cjs +13 -0
- package/dist/icons.d.cts +1 -0
- package/dist/icons.d.ts +1 -0
- package/dist/icons.js +2 -0
- package/dist/identity.cjs +430 -0
- package/dist/identity.d.cts +64 -0
- package/dist/identity.d.ts +64 -0
- package/dist/identity.js +408 -0
- package/dist/index.cjs +1610 -836
- package/dist/index.d.cts +7 -3
- package/dist/index.d.ts +7 -3
- package/dist/index.js +1587 -831
- package/dist/input.cjs +3 -1
- package/dist/input.d.cts +3 -5
- package/dist/input.d.ts +3 -5
- package/dist/input.js +3 -1
- package/dist/lux.config.cjs +23 -2
- package/dist/lux.config.d.cts +28 -10
- package/dist/lux.config.d.ts +28 -10
- package/dist/lux.config.js +23 -2
- package/dist/menu.cjs +4 -4
- package/dist/menu.js +4 -4
- package/dist/next.cjs +132 -0
- package/dist/next.d.cts +32 -0
- package/dist/next.d.ts +32 -0
- package/dist/next.js +129 -0
- package/dist/option-chain.cjs +1 -1
- package/dist/option-chain.js +1 -1
- package/dist/option-position.cjs +2 -1
- package/dist/option-position.js +2 -1
- package/dist/pnl-diagram.cjs +8 -6
- package/dist/pnl-diagram.js +8 -6
- package/dist/progress.cjs +7 -6
- package/dist/progress.js +7 -5
- package/dist/provider.cjs +146 -4
- package/dist/provider.d.cts +15 -3
- package/dist/provider.d.ts +15 -3
- package/dist/provider.js +146 -5
- package/dist/radio.cjs +9 -7
- package/dist/radio.js +10 -7
- package/dist/separator.cjs +3 -1
- package/dist/separator.js +3 -1
- package/dist/slider.cjs +28 -16
- package/dist/slider.js +28 -15
- package/dist/strategy-builder.cjs +2 -1
- package/dist/strategy-builder.js +2 -1
- package/dist/switch.cjs +11 -12
- package/dist/switch.js +12 -12
- package/dist/tag.cjs +34 -36
- package/dist/tag.js +33 -35
- package/dist/textarea.cjs +3 -1
- package/dist/textarea.js +3 -1
- package/dist/tooltip.cjs +28 -30
- package/dist/tooltip.js +27 -29
- package/dist/use-narrow.cjs +46 -0
- package/dist/use-narrow.d.cts +12 -0
- package/dist/use-narrow.d.ts +12 -0
- package/dist/use-narrow.js +20 -0
- package/dist/vite.cjs +109 -0
- package/dist/vite.d.cts +29 -0
- package/dist/vite.d.ts +29 -0
- package/dist/vite.js +107 -0
- package/dist/white-label.cjs +142 -0
- package/dist/white-label.d.cts +59 -0
- package/dist/white-label.d.ts +59 -0
- package/dist/white-label.js +134 -0
- package/package.json +85 -19
- package/src/avatar.tsx +22 -16
- package/src/checkbox.tsx +15 -10
- package/src/chrome.tsx +459 -0
- package/src/drawer.tsx +83 -10
- package/src/engine.ts +130 -0
- package/src/expiration-selector.tsx +3 -2
- package/src/greeks-display.tsx +9 -6
- package/src/gui.ts +17 -0
- package/src/heading.tsx +12 -8
- package/src/iam.ts +170 -0
- package/src/icons.ts +18 -0
- package/src/identity.tsx +318 -0
- package/src/index.ts +44 -1
- package/src/input.tsx +13 -9
- package/src/lux.config.ts +16 -15
- package/src/menu.tsx +4 -4
- package/src/next.ts +89 -0
- package/src/option-chain.tsx +1 -1
- package/src/option-position.tsx +2 -1
- package/src/pnl-diagram.tsx +11 -6
- package/src/progress.tsx +15 -8
- package/src/provider.tsx +48 -7
- package/src/radio.tsx +15 -11
- package/src/separator.tsx +8 -3
- package/src/slider.tsx +35 -19
- package/src/strategy-builder.tsx +3 -2
- package/src/switch.tsx +17 -16
- package/src/textarea.tsx +8 -4
- package/src/tooltip.tsx +15 -24
- package/src/use-narrow.ts +40 -0
- package/src/vite.ts +80 -0
- package/src/white-label.ts +254 -0
- package/tokens.css +613 -319
- package/src/tokens.css +0 -438
|
@@ -0,0 +1,134 @@
|
|
|
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 issuer is `zoolabs.id` — the one row where it is not `<org>.id`,
|
|
26
|
+
// and the one every hand-rolled branding map gets wrong. `id.zoo.network`
|
|
27
|
+
// ANSWERS, which is why it keeps being copied around, but it is an alias:
|
|
28
|
+
// its own discovery document advertises
|
|
29
|
+
// issuer https://zoolabs.id
|
|
30
|
+
// authorization_endpoint https://zoolabs.id/v1/iam/oauth/authorize
|
|
31
|
+
// jwks_uri https://zoolabs.id/v1/iam/.well-known/jwks
|
|
32
|
+
// so a client configured on the alias validates `iss` against a string the
|
|
33
|
+
// IdP never emits and rejects every token it is given — the exact shape of
|
|
34
|
+
// the lux.id outage. `zoo.id` is not an IdP at all (no discovery document).
|
|
35
|
+
iamDomain: "zoolabs.id",
|
|
36
|
+
accent: LUX_BRAND.zoo,
|
|
37
|
+
accentForeground: "#FFFFFF"
|
|
38
|
+
},
|
|
39
|
+
bootnode: {
|
|
40
|
+
org: "bootnode",
|
|
41
|
+
name: "Bootnode",
|
|
42
|
+
domain: "bootno.de",
|
|
43
|
+
iamDomain: "id.bootno.de",
|
|
44
|
+
accent: LUX_BRAND.lux,
|
|
45
|
+
accentForeground: "#FFFFFF"
|
|
46
|
+
},
|
|
47
|
+
hanzo: {
|
|
48
|
+
org: "hanzo",
|
|
49
|
+
name: "Hanzo",
|
|
50
|
+
domain: "hanzo.ai",
|
|
51
|
+
iamDomain: "hanzo.id",
|
|
52
|
+
accent: LUX_BRAND.hanzo,
|
|
53
|
+
accentForeground: "#FFFFFF"
|
|
54
|
+
},
|
|
55
|
+
pars: {
|
|
56
|
+
org: "pars",
|
|
57
|
+
name: "Pars",
|
|
58
|
+
domain: "pars.id",
|
|
59
|
+
iamDomain: "pars.id",
|
|
60
|
+
accent: LUX_BRAND.pars,
|
|
61
|
+
accentForeground: PARS_GOLD
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var DOMAIN_ORG = [
|
|
65
|
+
["lux.network", "lux"],
|
|
66
|
+
["lux.cloud", "lux"],
|
|
67
|
+
["lux.id", "lux"],
|
|
68
|
+
["lux.finance", "lux"],
|
|
69
|
+
["lux.market", "lux"],
|
|
70
|
+
["lux.exchange", "lux"],
|
|
71
|
+
["zoo.ngo", "zoo"],
|
|
72
|
+
["zoo.network", "zoo"],
|
|
73
|
+
["zoo.cloud", "zoo"],
|
|
74
|
+
["zoolabs.id", "zoo"],
|
|
75
|
+
["hanzo.ai", "hanzo"],
|
|
76
|
+
["hanzo.cloud", "hanzo"],
|
|
77
|
+
["hanzo.id", "hanzo"],
|
|
78
|
+
["pars.id", "pars", "app"],
|
|
79
|
+
["pars.network", "pars", "app"],
|
|
80
|
+
["parsdao.org", "pars", "app"],
|
|
81
|
+
["bootno.de", "bootnode", "platform"]
|
|
82
|
+
];
|
|
83
|
+
var DEFAULT_ORG = "lux";
|
|
84
|
+
function normalizeHost(host) {
|
|
85
|
+
const noPort = host.trim().toLowerCase().split(":")[0] ?? "";
|
|
86
|
+
return noPort.replace(/\.$/, "");
|
|
87
|
+
}
|
|
88
|
+
function isUnder(host, domain) {
|
|
89
|
+
return host === domain || host.endsWith(`.${domain}`);
|
|
90
|
+
}
|
|
91
|
+
function matchDomain(host) {
|
|
92
|
+
let best;
|
|
93
|
+
for (const entry of DOMAIN_ORG) {
|
|
94
|
+
if (isUnder(host, entry[0]) && (!best || entry[0].length > best[0].length)) {
|
|
95
|
+
best = entry;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return best;
|
|
99
|
+
}
|
|
100
|
+
function appSlug(host, domain, pinned) {
|
|
101
|
+
if (pinned) return pinned;
|
|
102
|
+
const sub = host === domain ? "" : host.slice(0, -(domain.length + 1));
|
|
103
|
+
const leftmost = sub.split(".")[0] ?? "";
|
|
104
|
+
if (leftmost && leftmost !== "www") return leftmost;
|
|
105
|
+
const label = domain.split(".")[0] ?? "";
|
|
106
|
+
const tld = domain.split(".").slice(1).join(".");
|
|
107
|
+
return tld.split(".")[0] || label;
|
|
108
|
+
}
|
|
109
|
+
function isLocal(host) {
|
|
110
|
+
return host === "localhost" || host.endsWith(".localhost") || host === "127.0.0.1" || host === "0.0.0.0" || host === "[::1]" || host.endsWith(".local");
|
|
111
|
+
}
|
|
112
|
+
function resolveWhiteLabel(host) {
|
|
113
|
+
const h = normalizeHost(host ?? "");
|
|
114
|
+
const match = h ? matchDomain(h) : void 0;
|
|
115
|
+
const org = match ? match[1] : DEFAULT_ORG;
|
|
116
|
+
const identity = ORGS[org];
|
|
117
|
+
const app = match ? appSlug(h, match[0], match[2]) : h && isLocal(h) ? "local" : "app";
|
|
118
|
+
return {
|
|
119
|
+
...identity,
|
|
120
|
+
host: h,
|
|
121
|
+
app,
|
|
122
|
+
theme: `dark_${org}`,
|
|
123
|
+
issuer: `https://${identity.iamDomain}`,
|
|
124
|
+
clientId: `${org}-${app}`
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
function currentHost() {
|
|
128
|
+
return typeof window === "undefined" ? "" : window.location.host;
|
|
129
|
+
}
|
|
130
|
+
function orgIdentity(org) {
|
|
131
|
+
return ORGS[org];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export { DEFAULT_ORG, LUX_BRAND, PARS_GOLD, currentHost, orgIdentity, ORGS as orgs, resolveWhiteLabel };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@luxfi/ui",
|
|
3
|
-
"version": "7.4.
|
|
3
|
+
"version": "7.4.3",
|
|
4
4
|
"description": "Cross-platform DeFi UI components built on @hanzo/gui (Tamagui). Native mobile + web.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -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,7 +295,9 @@
|
|
|
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
303
|
"@radix-ui/react-accordion": "^1.2.12",
|
|
@@ -266,41 +313,60 @@
|
|
|
266
313
|
"@radix-ui/react-slider": "^1.3.6",
|
|
267
314
|
"@radix-ui/react-switch": "^1.2.6",
|
|
268
315
|
"@radix-ui/react-tabs": "^1.1.13",
|
|
316
|
+
"@tanstack/react-query": "^5.76.0",
|
|
269
317
|
"@uidotdev/usehooks": "^2.4.1",
|
|
270
318
|
"clsx": "^2.1.1",
|
|
271
319
|
"es-toolkit": "^1.31.0",
|
|
272
|
-
"react
|
|
320
|
+
"lucide-react": "^1.27.0",
|
|
273
321
|
"sonner": "^2.0.0",
|
|
274
|
-
"tailwind-merge": "^3.0.0"
|
|
275
|
-
"@tanstack/react-query": "^5.76.0",
|
|
276
|
-
"@hanzo/gui": "^7.3.0",
|
|
277
|
-
"@hanzogui/config": "^7.3.0",
|
|
278
|
-
"@hanzogui/core": "^7.3.0",
|
|
279
|
-
"@hanzogui/web": "^7.3.0"
|
|
322
|
+
"tailwind-merge": "^3.0.0"
|
|
280
323
|
},
|
|
281
324
|
"peerDependencies": {
|
|
282
|
-
"react": ">=19",
|
|
283
|
-
"react-dom": ">=19",
|
|
284
325
|
"@hanzo/gui": "^7.3.0",
|
|
326
|
+
"@hanzogui/colors": "^7.3.0",
|
|
285
327
|
"@hanzogui/config": "^7.3.0",
|
|
328
|
+
"@hanzogui/core": "^7.3.0",
|
|
329
|
+
"@hanzogui/lucide-icons-2": "^7.3.0",
|
|
286
330
|
"@hanzogui/themes": "^7.3.0",
|
|
287
|
-
"@hanzogui/
|
|
288
|
-
"
|
|
331
|
+
"@hanzogui/web": "^7.3.0",
|
|
332
|
+
"react": ">=19",
|
|
333
|
+
"react-dom": ">=19"
|
|
289
334
|
},
|
|
290
335
|
"peerDependenciesMeta": {
|
|
291
|
-
"@hanzogui/themes": {
|
|
292
|
-
|
|
293
|
-
|
|
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
|
+
}
|
|
294
351
|
},
|
|
295
352
|
"devDependencies": {
|
|
353
|
+
"@hanzo/gui": "7.3.0",
|
|
354
|
+
"@hanzogui/colors": "7.3.0",
|
|
296
355
|
"@hanzogui/config": "7.3.0",
|
|
356
|
+
"@hanzogui/core": "7.3.0",
|
|
297
357
|
"@hanzogui/themes": "7.3.0",
|
|
298
|
-
"@hanzogui/
|
|
358
|
+
"@hanzogui/web": "7.3.0",
|
|
359
|
+
"@playwright/test": "^1.58",
|
|
360
|
+
"@tailwindcss/vite": "^4",
|
|
299
361
|
"@types/react": "^19.0.0",
|
|
300
362
|
"@types/react-dom": "^19.0.0",
|
|
363
|
+
"@vitejs/plugin-react": "^6",
|
|
301
364
|
"react": "^19.0.0",
|
|
302
365
|
"react-dom": "^19.0.0",
|
|
366
|
+
"react-native-web": "^0.21.0",
|
|
367
|
+
"tailwindcss": "^4",
|
|
303
368
|
"tsup": "^8.5.0",
|
|
304
|
-
"typescript": "^5.9.3"
|
|
369
|
+
"typescript": "^5.9.3",
|
|
370
|
+
"vite": "^8"
|
|
305
371
|
}
|
|
306
|
-
}
|
|
372
|
+
}
|
package/src/avatar.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import
|
|
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
|
-
<
|
|
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
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
</
|
|
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
|
-
<
|
|
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
|
-
</
|
|
139
|
+
</GuiAvatar.Fallback>
|
|
134
140
|
);
|
|
135
141
|
},
|
|
136
142
|
);
|
package/src/checkbox.tsx
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import
|
|
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:
|
|
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<
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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
|
-
<
|
|
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
|
-
</
|
|
286
|
+
</GuiCheckbox.Indicator>
|
|
282
287
|
) }
|
|
283
|
-
</
|
|
288
|
+
</GuiCheckbox>
|
|
284
289
|
{ /* Hidden native input for form compatibility and ref forwarding */ }
|
|
285
290
|
<input
|
|
286
291
|
ref={ setHiddenInputRef }
|