@luxfi/ui 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/alert.cjs +162 -285
  2. package/dist/alert.js +162 -285
  3. package/dist/badge.cjs +162 -321
  4. package/dist/badge.d.cts +3 -7
  5. package/dist/badge.d.ts +3 -7
  6. package/dist/badge.js +162 -320
  7. package/dist/button.cjs +373 -484
  8. package/dist/button.d.cts +10 -7
  9. package/dist/button.d.ts +10 -7
  10. package/dist/button.js +373 -484
  11. package/dist/close-button.cjs +37 -18
  12. package/dist/close-button.d.cts +1 -1
  13. package/dist/close-button.d.ts +1 -1
  14. package/dist/close-button.js +37 -18
  15. package/dist/collapsible.cjs +125 -272
  16. package/dist/collapsible.js +125 -272
  17. package/dist/dialog.cjs +60 -44
  18. package/dist/dialog.d.cts +7 -8
  19. package/dist/dialog.d.ts +7 -8
  20. package/dist/dialog.js +60 -43
  21. package/dist/drawer.cjs +37 -13
  22. package/dist/drawer.js +37 -13
  23. package/dist/heading.cjs +3 -8
  24. package/dist/heading.js +3 -8
  25. package/dist/icon-button.cjs +213 -337
  26. package/dist/icon-button.d.cts +4 -4
  27. package/dist/icon-button.d.ts +4 -4
  28. package/dist/icon-button.js +213 -338
  29. package/dist/image.cjs +125 -272
  30. package/dist/image.js +125 -272
  31. package/dist/index.cjs +604 -700
  32. package/dist/index.d.cts +0 -3
  33. package/dist/index.d.ts +0 -3
  34. package/dist/index.js +604 -698
  35. package/dist/link.cjs +125 -272
  36. package/dist/link.js +125 -272
  37. package/dist/popover.cjs +55 -40
  38. package/dist/popover.js +55 -39
  39. package/dist/select.cjs +125 -272
  40. package/dist/select.js +125 -272
  41. package/dist/skeleton.cjs +125 -272
  42. package/dist/skeleton.js +125 -272
  43. package/dist/table.cjs +127 -274
  44. package/dist/table.js +127 -274
  45. package/dist/tag.cjs +184 -306
  46. package/dist/tag.js +184 -305
  47. package/dist/tooltip.cjs +22 -21
  48. package/dist/tooltip.d.cts +2 -3
  49. package/dist/tooltip.d.ts +2 -3
  50. package/dist/tooltip.js +22 -20
  51. package/package.json +9 -7
  52. package/src/badge.tsx +20 -31
  53. package/src/button.tsx +304 -238
  54. package/src/close-button.tsx +48 -22
  55. package/src/dialog.tsx +37 -47
  56. package/src/heading.tsx +8 -19
  57. package/src/icon-button.tsx +129 -104
  58. package/src/popover.tsx +30 -44
  59. package/src/skeleton.tsx +96 -144
  60. package/src/tooltip.tsx +54 -47
package/dist/button.js CHANGED
@@ -1,6 +1,5 @@
1
1
  "use client";
2
- import { Slot } from '@radix-ui/react-slot';
3
- import { cva } from 'class-variance-authority';
2
+ import { styled, View } from '@hanzogui/core';
4
3
  import * as React2 from 'react';
5
4
  import { clsx } from 'clsx';
6
5
  import { twMerge } from 'tailwind-merge';
@@ -10,272 +9,137 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
10
9
  function cn(...inputs) {
11
10
  return twMerge(clsx(inputs));
12
11
  }
13
- var SPACING_SCALE = 4;
14
- function toStylePx(value) {
15
- if (value === void 0) return void 0;
16
- if (typeof value === "string") return value;
17
- return `${value * SPACING_SCALE}px`;
12
+ var SHIM_PROPS = [
13
+ "w",
14
+ "h",
15
+ "minW",
16
+ "maxW",
17
+ "display",
18
+ "flexGrow",
19
+ "flexShrink",
20
+ "flexBasis",
21
+ "fontWeight",
22
+ "textStyle",
23
+ "borderRadius",
24
+ "alignSelf",
25
+ "alignItems",
26
+ "justifyContent",
27
+ "color",
28
+ "mt",
29
+ "mb",
30
+ "ml",
31
+ "mr",
32
+ "height",
33
+ "overflow",
34
+ "whiteSpace",
35
+ "textOverflow",
36
+ "textTransform",
37
+ "gap",
38
+ "gridTemplateColumns",
39
+ "minWidth",
40
+ "boxSize",
41
+ "py",
42
+ "px",
43
+ "p",
44
+ "hideBelow",
45
+ "fontSize",
46
+ "flexWrap",
47
+ "wordBreak",
48
+ "lineHeight",
49
+ "marginRight",
50
+ "position",
51
+ "background"
52
+ ];
53
+ var S = 4;
54
+ function dim(v) {
55
+ if (v == null) return void 0;
56
+ if (typeof v === "number") return `${v * S}px`;
57
+ if (typeof v === "string") return v;
58
+ if (typeof v === "object") {
59
+ const o = v;
60
+ return o.base ?? o.lg ?? o.xl ?? Object.values(o)[0];
61
+ }
62
+ return void 0;
18
63
  }
19
- function extractSkeletonStyleProps(props) {
20
- const style = {};
21
- const rest = {};
22
- function resolveDimension(value) {
23
- if (value === void 0 || value === null) return void 0;
24
- if (typeof value === "number") return `${value * SPACING_SCALE}px`;
25
- if (typeof value === "string") return value;
26
- if (typeof value === "object") {
27
- const obj = value;
28
- return obj.base ?? obj.lg ?? obj.xl ?? Object.values(obj)[0];
29
- }
30
- return void 0;
64
+ function sp(v) {
65
+ if (v === void 0) return void 0;
66
+ return typeof v === "number" ? `${v * S}px` : v;
67
+ }
68
+ function shimToStyle(props) {
69
+ const s = {};
70
+ if (props.w !== void 0) s.width = dim(props.w);
71
+ if (props.h !== void 0) s.height = dim(props.h);
72
+ if (props.minW !== void 0) s.minWidth = dim(props.minW);
73
+ if (props.maxW !== void 0) s.maxWidth = dim(props.maxW);
74
+ if (props.display !== void 0) s.display = props.display;
75
+ if (props.flexGrow !== void 0) s.flexGrow = props.flexGrow;
76
+ if (props.flexShrink !== void 0) s.flexShrink = props.flexShrink;
77
+ if (props.flexBasis !== void 0) s.flexBasis = props.flexBasis;
78
+ if (props.fontWeight !== void 0) s.fontWeight = props.fontWeight;
79
+ if (props.borderRadius !== void 0) s.borderRadius = props.borderRadius;
80
+ if (props.alignSelf !== void 0) s.alignSelf = props.alignSelf;
81
+ if (props.alignItems !== void 0) s.alignItems = props.alignItems;
82
+ if (props.justifyContent !== void 0) s.justifyContent = props.justifyContent;
83
+ if (props.color !== void 0) s.color = props.color;
84
+ if (props.mt !== void 0) s.marginTop = sp(props.mt);
85
+ if (props.mb !== void 0) s.marginBottom = sp(props.mb);
86
+ if (props.ml !== void 0) s.marginLeft = sp(props.ml);
87
+ if (props.mr !== void 0) s.marginRight = sp(props.mr);
88
+ if (props.height !== void 0) s.height = props.height;
89
+ if (props.overflow !== void 0) s.overflow = props.overflow;
90
+ if (props.whiteSpace !== void 0) s.whiteSpace = props.whiteSpace;
91
+ if (props.textOverflow !== void 0) s.textOverflow = props.textOverflow;
92
+ if (props.textTransform !== void 0) s.textTransform = props.textTransform;
93
+ if (props.gap !== void 0) s.gap = sp(props.gap);
94
+ if (props.gridTemplateColumns !== void 0) s.gridTemplateColumns = props.gridTemplateColumns;
95
+ if (props.minWidth !== void 0) s.minWidth = props.minWidth;
96
+ if (props.boxSize !== void 0) {
97
+ const v = typeof props.boxSize === "number" ? `${props.boxSize * S}px` : props.boxSize;
98
+ s.width = v;
99
+ s.height = v;
31
100
  }
32
- for (const [key, value] of Object.entries(props)) {
33
- if (value === void 0) continue;
34
- switch (key) {
35
- case "w": {
36
- const v = resolveDimension(value);
37
- if (v) style.width = v;
38
- break;
39
- }
40
- case "h": {
41
- const v = resolveDimension(value);
42
- if (v) style.height = v;
43
- break;
44
- }
45
- case "minW": {
46
- const v = resolveDimension(value);
47
- if (v) style.minWidth = v;
48
- break;
49
- }
50
- case "maxW": {
51
- const v = resolveDimension(value);
52
- if (v) style.maxWidth = v;
53
- break;
54
- }
55
- case "height":
56
- style.height = value;
57
- break;
58
- case "display":
59
- style.display = value;
60
- break;
61
- case "flexGrow":
62
- style.flexGrow = value;
63
- break;
64
- case "flexShrink":
65
- style.flexShrink = value;
66
- break;
67
- case "flexBasis":
68
- style.flexBasis = value;
69
- break;
70
- case "fontWeight":
71
- style.fontWeight = value;
72
- break;
73
- case "borderRadius":
74
- style.borderRadius = value;
75
- break;
76
- case "alignSelf":
77
- style.alignSelf = value;
78
- break;
79
- case "alignItems":
80
- style.alignItems = value;
81
- break;
82
- case "justifyContent":
83
- style.justifyContent = value;
84
- break;
85
- case "color":
86
- style.color = value;
87
- break;
88
- case "mt":
89
- style.marginTop = toStylePx(value);
90
- break;
91
- case "mb":
92
- style.marginBottom = toStylePx(value);
93
- break;
94
- case "ml":
95
- style.marginLeft = toStylePx(value);
96
- break;
97
- case "mr":
98
- style.marginRight = toStylePx(value);
99
- break;
100
- case "overflow":
101
- style.overflow = value;
102
- break;
103
- case "whiteSpace":
104
- style.whiteSpace = value;
105
- break;
106
- case "textOverflow":
107
- style.textOverflow = value;
108
- break;
109
- case "textTransform":
110
- style.textTransform = value;
111
- break;
112
- case "gap":
113
- style.gap = typeof value === "number" ? `${value * SPACING_SCALE}px` : value;
114
- break;
115
- case "gridTemplateColumns":
116
- style.gridTemplateColumns = value;
117
- break;
118
- case "minWidth":
119
- style.minWidth = value;
120
- break;
121
- case "boxSize": {
122
- const s = typeof value === "number" ? `${value * SPACING_SCALE}px` : value;
123
- style.width = s;
124
- style.height = s;
125
- break;
126
- }
127
- case "py": {
128
- const v = toStylePx(value);
129
- style.paddingTop = v;
130
- style.paddingBottom = v;
131
- break;
132
- }
133
- case "px": {
134
- const v = toStylePx(value);
135
- style.paddingLeft = v;
136
- style.paddingRight = v;
137
- break;
138
- }
139
- case "p": {
140
- const v = toStylePx(value);
141
- style.padding = v;
142
- break;
143
- }
144
- case "hideBelow":
145
- break;
146
- // handled via className
147
- case "textStyle":
148
- break;
149
- // drop textStyle, not directly applicable
150
- case "fontSize":
151
- style.fontSize = value;
152
- break;
153
- case "flexWrap":
154
- style.flexWrap = value;
155
- break;
156
- case "wordBreak":
157
- style.wordBreak = value;
158
- break;
159
- case "lineHeight":
160
- style.lineHeight = value;
161
- break;
162
- case "marginRight":
163
- style.marginRight = value;
164
- break;
165
- case "position":
166
- style.position = value;
167
- break;
168
- case "background":
169
- style.background = value;
170
- break;
171
- default:
172
- rest[key] = value;
173
- break;
174
- }
101
+ if (props.py !== void 0) {
102
+ const v = sp(props.py);
103
+ s.paddingTop = v;
104
+ s.paddingBottom = v;
175
105
  }
176
- return { style, rest };
106
+ if (props.px !== void 0) {
107
+ const v = sp(props.px);
108
+ s.paddingLeft = v;
109
+ s.paddingRight = v;
110
+ }
111
+ if (props.p !== void 0) s.padding = sp(props.p);
112
+ if (props.fontSize !== void 0) s.fontSize = props.fontSize;
113
+ if (props.flexWrap !== void 0) s.flexWrap = props.flexWrap;
114
+ if (props.wordBreak !== void 0) s.wordBreak = props.wordBreak;
115
+ if (props.lineHeight !== void 0) s.lineHeight = props.lineHeight;
116
+ if (props.marginRight !== void 0) s.marginRight = props.marginRight;
117
+ if (props.position !== void 0) s.position = props.position;
118
+ if (props.background !== void 0) s.background = props.background;
119
+ return s;
120
+ }
121
+ function stripShims(props) {
122
+ const out = { ...props };
123
+ for (const k of SHIM_PROPS) delete out[k];
124
+ return out;
177
125
  }
126
+ var SKELETON_CLASSES = [
127
+ "animate-skeleton-shimmer rounded-sm",
128
+ "bg-[linear-gradient(90deg,var(--color-skeleton-start)_0%,var(--color-skeleton-end)_50%,var(--color-skeleton-start)_100%)]",
129
+ "bg-[length:200%_100%]"
130
+ ].join(" ");
131
+ var HIDE_BELOW_MAP = { lg: "lg:hidden", md: "md:hidden", sm: "sm:hidden" };
178
132
  var Skeleton = React2.forwardRef(
179
133
  function Skeleton2(props, ref) {
180
- const {
181
- loading = false,
182
- asChild,
183
- className,
184
- children,
185
- style: styleProp,
186
- // Destructure style-prop shims so they don't leak into DOM
187
- w: _w,
188
- h: _h,
189
- minW: _minW,
190
- maxW: _maxW,
191
- display: _display,
192
- flexGrow: _flexGrow,
193
- flexShrink: _flexShrink,
194
- flexBasis: _flexBasis,
195
- fontWeight: _fontWeight,
196
- textStyle: _textStyle,
197
- borderRadius: _borderRadius,
198
- alignSelf: _alignSelf,
199
- alignItems: _alignItems,
200
- justifyContent: _justifyContent,
201
- color: _color,
202
- mt: _mt,
203
- mb: _mb,
204
- ml: _ml,
205
- mr: _mr,
206
- height: _height,
207
- overflow: _overflow,
208
- whiteSpace: _whiteSpace,
209
- textOverflow: _textOverflow,
210
- textTransform: _textTransform,
211
- gap: _gap,
212
- gridTemplateColumns: _gridTemplateColumns,
213
- minWidth: _minWidth,
214
- boxSize: _boxSize,
215
- py: _py,
216
- px: _px,
217
- p: _p,
218
- hideBelow: _hideBelow,
219
- fontSize: _fontSize,
220
- flexWrap: _flexWrap,
221
- wordBreak: _wordBreak,
222
- lineHeight: _lineHeight,
223
- marginRight: _marginRight,
224
- position: _position,
225
- background: _background,
226
- as: Component = "div",
227
- ...htmlRest
228
- } = props;
229
- const { style: shimStyle } = extractSkeletonStyleProps({
230
- w: _w,
231
- h: _h,
232
- minW: _minW,
233
- maxW: _maxW,
234
- display: _display,
235
- flexGrow: _flexGrow,
236
- flexShrink: _flexShrink,
237
- flexBasis: _flexBasis,
238
- fontWeight: _fontWeight,
239
- textStyle: _textStyle,
240
- borderRadius: _borderRadius,
241
- alignSelf: _alignSelf,
242
- alignItems: _alignItems,
243
- justifyContent: _justifyContent,
244
- color: _color,
245
- mt: _mt,
246
- mb: _mb,
247
- ml: _ml,
248
- mr: _mr,
249
- height: _height,
250
- overflow: _overflow,
251
- whiteSpace: _whiteSpace,
252
- textOverflow: _textOverflow,
253
- textTransform: _textTransform,
254
- gap: _gap,
255
- gridTemplateColumns: _gridTemplateColumns,
256
- minWidth: _minWidth,
257
- boxSize: _boxSize,
258
- py: _py,
259
- px: _px,
260
- p: _p,
261
- hideBelow: _hideBelow,
262
- fontSize: _fontSize,
263
- flexWrap: _flexWrap,
264
- wordBreak: _wordBreak,
265
- lineHeight: _lineHeight,
266
- marginRight: _marginRight,
267
- position: _position,
268
- background: _background
269
- });
134
+ const { loading = false, asChild, className, children, style: styleProp, as: Component = "div", ...allRest } = props;
135
+ const shimStyle = shimToStyle(props);
270
136
  const mergedStyle = Object.keys(shimStyle).length > 0 || styleProp ? { ...shimStyle, ...styleProp } : void 0;
271
- const HIDE_BELOW_MAP = { lg: "lg:hidden", md: "md:hidden", sm: "sm:hidden" };
272
- const hideBelowClass = _hideBelow ? HIDE_BELOW_MAP[_hideBelow] : void 0;
273
- const finalClassName = hideBelowClass ? cn(className, hideBelowClass) : className;
137
+ const hideBelowClass = props.hideBelow ? HIDE_BELOW_MAP[props.hideBelow] : void 0;
138
+ const cls = hideBelowClass ? cn(className, hideBelowClass) : className;
139
+ const htmlRest = stripShims(allRest);
274
140
  if (!loading) {
275
- if (asChild && React2.isValidElement(children)) {
276
- return children;
277
- }
278
- return /* @__PURE__ */ jsx(Component, { ref, className: finalClassName, style: mergedStyle, ...htmlRest, children });
141
+ if (asChild && React2.isValidElement(children)) return children;
142
+ return /* @__PURE__ */ jsx(Component, { ref, className: cls, style: mergedStyle, ...htmlRest, children });
279
143
  }
280
144
  if (asChild && React2.isValidElement(children)) {
281
145
  return /* @__PURE__ */ jsx(
@@ -283,13 +147,7 @@ var Skeleton = React2.forwardRef(
283
147
  {
284
148
  ref,
285
149
  "data-loading": true,
286
- className: cn(
287
- "animate-skeleton-shimmer rounded-sm",
288
- "bg-[linear-gradient(90deg,var(--color-skeleton-start)_0%,var(--color-skeleton-end)_50%,var(--color-skeleton-start)_100%)]",
289
- "bg-[length:200%_100%]",
290
- "text-transparent [&_*]:invisible",
291
- finalClassName
292
- ),
150
+ className: cn(SKELETON_CLASSES, "text-transparent [&_*]:invisible", cls),
293
151
  style: mergedStyle,
294
152
  ...htmlRest,
295
153
  children
@@ -301,13 +159,7 @@ var Skeleton = React2.forwardRef(
301
159
  {
302
160
  ref,
303
161
  "data-loading": true,
304
- className: cn(
305
- "animate-skeleton-shimmer rounded-sm",
306
- "bg-[linear-gradient(90deg,var(--color-skeleton-start)_0%,var(--color-skeleton-end)_50%,var(--color-skeleton-start)_100%)]",
307
- "bg-[length:200%_100%]",
308
- children ? "text-transparent [&_*]:invisible" : "min-h-5",
309
- finalClassName
310
- ),
162
+ className: cn(SKELETON_CLASSES, children ? "text-transparent [&_*]:invisible" : "min-h-5", cls),
311
163
  style: mergedStyle,
312
164
  ...htmlRest,
313
165
  children
@@ -344,171 +196,202 @@ React2.forwardRef(
344
196
  )) });
345
197
  }
346
198
  );
347
- var buttonVariants = cva(
348
- // base styles (shared across all variants)
349
- [
350
- "inline-flex items-center justify-center",
351
- "gap-0 font-semibold overflow-hidden rounded-md",
352
- "cursor-pointer select-none whitespace-nowrap",
353
- "transition-colors duration-150",
354
- "disabled:opacity-[0.2] disabled:cursor-not-allowed"
355
- ],
356
- {
357
- variants: {
358
- variant: {
359
- // --- Solid ---
360
- solid: [
361
- "bg-[var(--color-button-solid-bg)] text-[var(--color-button-solid-text)]",
362
- "hover:bg-[var(--color-hover)]",
363
- "data-[expanded]:bg-[var(--color-hover)]"
364
- ],
365
- // --- Solid Danger ---
366
- solid_danger: [
367
- "bg-red-600 text-[var(--color-button-solid-text)]",
368
- "hover:bg-red-500",
369
- "data-[expanded]:bg-red-500"
370
- ],
371
- // --- Outline ---
372
- outline: [
373
- "border-2 border-solid bg-transparent",
374
- "text-[var(--color-button-outline-fg)] border-[var(--color-button-outline-fg)]",
375
- "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]"
376
- ],
377
- // --- Outline Danger ---
378
- outline_danger: [
379
- "border-2 border-solid bg-transparent",
380
- "text-red-600 border-red-600",
381
- "hover:bg-transparent hover:text-red-500 hover:border-red-500"
382
- ],
383
- // --- Dropdown ---
384
- dropdown: [
385
- "border-2 border-solid bg-transparent",
386
- "text-[var(--color-button-dropdown-fg)] border-[var(--color-button-dropdown-border)]",
387
- "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
388
- "data-[expanded]:bg-transparent data-[expanded]:text-[var(--color-hover)] data-[expanded]:border-[var(--color-hover)]",
389
- "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)] data-[selected]:border-transparent",
390
- "data-[selected]:hover:bg-[var(--color-selected-control-bg)]",
391
- "data-[selected]:hover:text-[var(--color-hover)] data-[selected]:hover:border-transparent",
392
- "data-[selected]:data-[expanded]:text-[var(--color-hover)]"
393
- ],
394
- // --- Header ---
395
- header: [
396
- "bg-transparent border-2 border-solid",
397
- "text-[var(--color-button-header-fg)] border-[var(--color-button-header-border)]",
398
- "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
399
- // selected
400
- "data-[selected]:bg-[var(--color-button-header-bg-selected)]",
401
- "data-[selected]:text-[var(--color-button-header-fg-selected)] data-[selected]:border-transparent data-[selected]:border-0",
402
- "data-[selected]:hover:bg-[var(--color-button-header-bg-selected)] data-[selected]:hover:text-[var(--color-hover)]",
403
- "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
404
- // selected + highlighted
405
- "data-[selected]:data-[highlighted]:bg-[var(--color-button-header-bg-highlighted)]",
406
- "data-[selected]:data-[highlighted]:text-[var(--color-button-header-fg-highlighted)]",
407
- "data-[selected]:data-[highlighted]:border-transparent data-[selected]:data-[highlighted]:border-0",
408
- "data-[selected]:data-[highlighted]:hover:bg-[var(--color-button-header-bg-highlighted)]",
409
- "data-[selected]:data-[highlighted]:hover:text-[var(--color-hover)]",
410
- "data-[selected]:data-[highlighted]:data-[expanded]:text-[var(--color-hover)]"
411
- ],
412
- // --- Hero ---
413
- hero: [
414
- "bg-[var(--color-button-hero-bg)] text-[var(--color-button-hero-fg)]",
415
- "hover:bg-[var(--color-button-hero-bg-hover)] hover:text-[var(--color-button-hero-fg-hover)]",
416
- "data-[selected]:bg-[var(--color-button-hero-bg-selected)] data-[selected]:text-[var(--color-button-hero-fg-selected)]",
417
- "data-[selected]:hover:bg-[var(--color-button-hero-bg-selected)] data-[selected]:hover:text-[var(--color-hover)]",
418
- "data-[selected]:data-[expanded]:text-[var(--color-hover)]"
419
- ],
420
- // --- Segmented ---
421
- segmented: [
422
- "bg-transparent border-2 border-solid rounded-none",
423
- "text-[var(--color-button-segmented-fg)] border-[var(--color-selected-control-bg)]",
424
- "hover:text-[var(--color-hover)]",
425
- // selected
426
- "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
427
- "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-selected-control-text)]",
428
- // border collapse: hide right border except when selected; first/last get rounded
429
- "[&:not(:last-child)]:border-r-0 data-[selected]:[&:not(:last-child)]:border-r-2",
430
- "data-[selected]+*:border-l-0",
431
- "first:rounded-l-md last:rounded-r-md"
432
- ],
433
- // --- Plain ---
434
- plain: [
435
- "bg-transparent text-inherit border-none",
436
- "hover:bg-transparent"
437
- ],
438
- // --- Subtle ---
439
- subtle: [
440
- "bg-[var(--color-button-subtle-bg)] text-[var(--color-button-subtle-fg)]",
441
- "hover:bg-[var(--color-button-subtle-bg)] hover:text-[var(--color-hover)]",
442
- "disabled:bg-[var(--color-button-subtle-bg)] disabled:text-[var(--color-button-subtle-fg)]"
443
- ],
444
- // --- Link ---
445
- link: [
446
- "bg-transparent text-[var(--color-link-primary)] border-none font-normal",
447
- "px-0 h-auto",
448
- "hover:bg-transparent hover:text-[var(--color-link-primary-hover)]",
449
- "disabled:text-[var(--color-text-secondary)]"
450
- ],
451
- // --- Icon Secondary ---
452
- icon_secondary: [
453
- "bg-transparent text-[var(--color-icon-secondary)] border-none",
454
- "hover:text-[var(--color-hover)]",
455
- "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
456
- "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-hover)]",
457
- "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
458
- "data-[expanded]:text-[var(--color-hover)]"
459
- ],
460
- // --- Icon Background ---
461
- icon_background: [
462
- "bg-[var(--color-button-icon-background-bg)] text-[var(--color-icon-secondary)] border-none",
463
- "hover:text-[var(--color-hover)]",
464
- "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
465
- "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-hover)]",
466
- "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
467
- "data-[expanded]:text-[var(--color-hover)]"
468
- ],
469
- // --- Pagination ---
470
- pagination: [
471
- "border-2 border-solid bg-transparent",
472
- "text-[var(--color-button-pagination-fg)] border-[var(--color-button-pagination-border)]",
473
- "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
474
- "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)] data-[selected]:border-transparent",
475
- "data-[selected]:hover:bg-[var(--color-selected-control-bg)]",
476
- "data-[selected]:hover:text-[var(--color-selected-control-text)] data-[selected]:hover:border-transparent"
477
- ]
478
- },
479
- size: {
480
- "2xs": "px-2 h-5 min-w-5 text-xs rounded-sm gap-1",
481
- xs: "px-2 h-6 min-w-6 text-sm rounded-sm gap-1",
482
- sm: "px-3 h-8 min-w-8 text-sm rounded-md gap-1",
483
- md: "px-3 h-10 min-w-10 text-base rounded-md gap-2"
484
- }
485
- },
486
- defaultVariants: {
487
- variant: "solid",
488
- size: "md"
489
- }
490
- }
491
- );
199
+ var SpinnerFrame = styled(View, {
200
+ name: "ButtonSpinner",
201
+ render: /* @__PURE__ */ jsx("span", {}),
202
+ width: 16,
203
+ height: 16,
204
+ borderRadius: 1e3,
205
+ borderWidth: 2,
206
+ borderColor: "currentColor",
207
+ borderBottomColor: "transparent",
208
+ borderLeftColor: "transparent"
209
+ });
492
210
  function Spinner({ className }) {
493
211
  return /* @__PURE__ */ jsx(
494
- "span",
212
+ SpinnerFrame,
495
213
  {
496
- className: cn(
497
- "inline-block h-4 w-4 animate-spin rounded-full",
498
- "border-2 border-current border-b-transparent border-l-transparent",
499
- className
500
- ),
501
214
  role: "status",
502
- "aria-label": "Loading"
215
+ "aria-label": "Loading",
216
+ className: [
217
+ "animate-spin",
218
+ className
219
+ ].filter(Boolean).join(" ")
503
220
  }
504
221
  );
505
222
  }
223
+ var ButtonFrame = styled(View, {
224
+ name: "LuxButton",
225
+ render: /* @__PURE__ */ jsx("button", { type: "button" }),
226
+ role: "button",
227
+ tabIndex: 0,
228
+ cursor: "pointer",
229
+ userSelect: "none",
230
+ display: "inline-flex",
231
+ alignItems: "center",
232
+ justifyContent: "center",
233
+ gap: 0,
234
+ overflow: "hidden",
235
+ borderRadius: 6,
236
+ // Whitespace nowrap via className since hanzogui doesn't have a direct token
237
+ // Transition via className
238
+ variants: {
239
+ size: {
240
+ "2xs": { paddingHorizontal: 8, height: 20, minWidth: 20, fontSize: 12, borderRadius: 4, gap: 4 },
241
+ xs: { paddingHorizontal: 8, height: 24, minWidth: 24, fontSize: 14, borderRadius: 4, gap: 4 },
242
+ sm: { paddingHorizontal: 12, height: 32, minWidth: 32, fontSize: 14, borderRadius: 6, gap: 4 },
243
+ md: { paddingHorizontal: 12, height: 40, minWidth: 40, fontSize: 16, borderRadius: 6, gap: 8 }
244
+ },
245
+ disabled: {
246
+ true: {
247
+ opacity: 0.2,
248
+ cursor: "not-allowed",
249
+ pointerEvents: "none"
250
+ }
251
+ }
252
+ },
253
+ defaultVariants: {
254
+ size: "md"
255
+ }
256
+ });
257
+ var VARIANT_CLASSES = {
258
+ solid: [
259
+ "bg-[var(--color-button-solid-bg)] text-[var(--color-button-solid-text)]",
260
+ "hover:bg-[var(--color-hover)]",
261
+ "data-[expanded]:bg-[var(--color-hover)]"
262
+ ].join(" "),
263
+ solid_danger: [
264
+ "bg-red-600 text-[var(--color-button-solid-text)]",
265
+ "hover:bg-red-500",
266
+ "data-[expanded]:bg-red-500"
267
+ ].join(" "),
268
+ outline: [
269
+ "border-2 border-solid bg-transparent",
270
+ "text-[var(--color-button-outline-fg)] border-[var(--color-button-outline-fg)]",
271
+ "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]"
272
+ ].join(" "),
273
+ outline_danger: [
274
+ "border-2 border-solid bg-transparent",
275
+ "text-red-600 border-red-600",
276
+ "hover:bg-transparent hover:text-red-500 hover:border-red-500"
277
+ ].join(" "),
278
+ dropdown: [
279
+ "border-2 border-solid bg-transparent",
280
+ "text-[var(--color-button-dropdown-fg)] border-[var(--color-button-dropdown-border)]",
281
+ "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
282
+ "data-[expanded]:bg-transparent data-[expanded]:text-[var(--color-hover)] data-[expanded]:border-[var(--color-hover)]",
283
+ "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)] data-[selected]:border-transparent",
284
+ "data-[selected]:hover:bg-[var(--color-selected-control-bg)]",
285
+ "data-[selected]:hover:text-[var(--color-hover)] data-[selected]:hover:border-transparent",
286
+ "data-[selected]:data-[expanded]:text-[var(--color-hover)]"
287
+ ].join(" "),
288
+ header: [
289
+ "bg-transparent border-2 border-solid",
290
+ "text-[var(--color-button-header-fg)] border-[var(--color-button-header-border)]",
291
+ "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
292
+ "data-[selected]:bg-[var(--color-button-header-bg-selected)]",
293
+ "data-[selected]:text-[var(--color-button-header-fg-selected)] data-[selected]:border-transparent data-[selected]:border-0",
294
+ "data-[selected]:hover:bg-[var(--color-button-header-bg-selected)] data-[selected]:hover:text-[var(--color-hover)]",
295
+ "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
296
+ "data-[selected]:data-[highlighted]:bg-[var(--color-button-header-bg-highlighted)]",
297
+ "data-[selected]:data-[highlighted]:text-[var(--color-button-header-fg-highlighted)]",
298
+ "data-[selected]:data-[highlighted]:border-transparent data-[selected]:data-[highlighted]:border-0",
299
+ "data-[selected]:data-[highlighted]:hover:bg-[var(--color-button-header-bg-highlighted)]",
300
+ "data-[selected]:data-[highlighted]:hover:text-[var(--color-hover)]",
301
+ "data-[selected]:data-[highlighted]:data-[expanded]:text-[var(--color-hover)]"
302
+ ].join(" "),
303
+ hero: [
304
+ "bg-[var(--color-button-hero-bg)] text-[var(--color-button-hero-fg)]",
305
+ "hover:bg-[var(--color-button-hero-bg-hover)] hover:text-[var(--color-button-hero-fg-hover)]",
306
+ "data-[selected]:bg-[var(--color-button-hero-bg-selected)] data-[selected]:text-[var(--color-button-hero-fg-selected)]",
307
+ "data-[selected]:hover:bg-[var(--color-button-hero-bg-selected)] data-[selected]:hover:text-[var(--color-hover)]",
308
+ "data-[selected]:data-[expanded]:text-[var(--color-hover)]"
309
+ ].join(" "),
310
+ segmented: [
311
+ "bg-transparent border-2 border-solid rounded-none",
312
+ "text-[var(--color-button-segmented-fg)] border-[var(--color-selected-control-bg)]",
313
+ "hover:text-[var(--color-hover)]",
314
+ "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
315
+ "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-selected-control-text)]",
316
+ "[&:not(:last-child)]:border-r-0 data-[selected]:[&:not(:last-child)]:border-r-2",
317
+ "data-[selected]+*:border-l-0",
318
+ "first:rounded-l-md last:rounded-r-md"
319
+ ].join(" "),
320
+ plain: "bg-transparent text-inherit border-none hover:bg-transparent",
321
+ subtle: [
322
+ "bg-[var(--color-button-subtle-bg)] text-[var(--color-button-subtle-fg)]",
323
+ "hover:bg-[var(--color-button-subtle-bg)] hover:text-[var(--color-hover)]",
324
+ "disabled:bg-[var(--color-button-subtle-bg)] disabled:text-[var(--color-button-subtle-fg)]"
325
+ ].join(" "),
326
+ link: [
327
+ "bg-transparent text-[var(--color-link-primary)] border-none font-normal",
328
+ "px-0 h-auto",
329
+ "hover:bg-transparent hover:text-[var(--color-link-primary-hover)]",
330
+ "disabled:text-[var(--color-text-secondary)]"
331
+ ].join(" "),
332
+ icon_secondary: [
333
+ "bg-transparent text-[var(--color-icon-secondary)] border-none",
334
+ "hover:text-[var(--color-hover)]",
335
+ "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
336
+ "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-hover)]",
337
+ "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
338
+ "data-[expanded]:text-[var(--color-hover)]"
339
+ ].join(" "),
340
+ icon_background: [
341
+ "bg-[var(--color-button-icon-background-bg)] text-[var(--color-icon-secondary)] border-none",
342
+ "hover:text-[var(--color-hover)]",
343
+ "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)]",
344
+ "data-[selected]:hover:bg-[var(--color-selected-control-bg)] data-[selected]:hover:text-[var(--color-hover)]",
345
+ "data-[selected]:data-[expanded]:text-[var(--color-hover)]",
346
+ "data-[expanded]:text-[var(--color-hover)]"
347
+ ].join(" "),
348
+ pagination: [
349
+ "border-2 border-solid bg-transparent",
350
+ "text-[var(--color-button-pagination-fg)] border-[var(--color-button-pagination-border)]",
351
+ "hover:bg-transparent hover:text-[var(--color-hover)] hover:border-[var(--color-hover)]",
352
+ "data-[selected]:bg-[var(--color-selected-control-bg)] data-[selected]:text-[var(--color-selected-control-text)] data-[selected]:border-transparent",
353
+ "data-[selected]:hover:bg-[var(--color-selected-control-bg)]",
354
+ "data-[selected]:hover:text-[var(--color-selected-control-text)] data-[selected]:hover:border-transparent"
355
+ ].join(" ")
356
+ };
357
+ var BASE_CLASSES = "font-semibold whitespace-nowrap transition-colors duration-150";
358
+ var SP = 4;
359
+ function buildShimStyle(props) {
360
+ const s = { ...props.style };
361
+ if (props.mt !== void 0) s.marginTop = typeof props.mt === "number" ? `${props.mt * SP}px` : props.mt;
362
+ if (props.ml !== void 0) s.marginLeft = typeof props.ml === "number" ? `${props.ml * SP}px` : props.ml;
363
+ if (props.mr !== void 0) s.marginRight = typeof props.mr === "number" ? `${props.mr * SP}px` : props.mr;
364
+ if (props.px !== void 0) {
365
+ const v = typeof props.px === "number" ? `${props.px * SP}px` : props.px;
366
+ s.paddingLeft = v;
367
+ s.paddingRight = v;
368
+ }
369
+ if (props.py !== void 0) {
370
+ const v = typeof props.py === "number" ? `${props.py * SP}px` : props.py;
371
+ s.paddingTop = v;
372
+ s.paddingBottom = v;
373
+ }
374
+ if (props.fontWeight !== void 0) s.fontWeight = props.fontWeight;
375
+ if (props.gap !== void 0) s.gap = typeof props.gap === "number" ? `${props.gap * SP}px` : props.gap;
376
+ if (props.flexShrink !== void 0) s.flexShrink = props.flexShrink;
377
+ if (props.columnGap !== void 0) s.columnGap = typeof props.columnGap === "number" ? `${props.columnGap * SP}px` : props.columnGap;
378
+ if (props.gridColumn !== void 0) s.gridColumn = typeof props.gridColumn === "number" ? String(props.gridColumn) : props.gridColumn;
379
+ if (props.gridRow) s.gridRow = props.gridRow;
380
+ if (props.justifySelf) s.justifySelf = props.justifySelf;
381
+ if (props.alignSelf) s.alignSelf = props.alignSelf;
382
+ if (props.h) s.height = props.h;
383
+ if (props.w) s.width = props.w;
384
+ if (props.display) s.display = props.display;
385
+ if (props.borderBottomRightRadius !== void 0) s.borderBottomRightRadius = typeof props.borderBottomRightRadius === "number" ? `${props.borderBottomRightRadius}px` : props.borderBottomRightRadius;
386
+ if (props.borderTopRightRadius !== void 0) s.borderTopRightRadius = typeof props.borderTopRightRadius === "number" ? `${props.borderTopRightRadius}px` : props.borderTopRightRadius;
387
+ return Object.keys(s).length > 0 ? s : void 0;
388
+ }
506
389
  var Button = React2.forwardRef(
507
390
  function Button2(props, ref) {
508
391
  const {
509
392
  className,
510
- variant,
511
- size,
393
+ variant = "solid",
394
+ size = "md",
512
395
  asChild = false,
513
396
  loading = false,
514
397
  loadingText,
@@ -520,57 +403,48 @@ var Button = React2.forwardRef(
520
403
  children,
521
404
  style: styleProp,
522
405
  // Strip Chakra style props
523
- mt: _mt,
524
- ml: _ml,
525
- mr: _mr,
526
- px: _px,
527
- py: _py,
528
- fontWeight: _fontWeight,
529
- gap: _gap,
530
- flexShrink: _flexShrink,
531
- columnGap: _columnGap,
532
- gridColumn: _gridColumn,
533
- gridRow: _gridRow,
534
- justifySelf: _justifySelf,
535
- alignSelf: _alignSelf,
406
+ mt,
407
+ ml,
408
+ mr,
409
+ px,
410
+ py,
411
+ fontWeight,
412
+ gap,
413
+ flexShrink,
414
+ columnGap,
415
+ gridColumn,
416
+ gridRow,
417
+ justifySelf,
418
+ alignSelf,
536
419
  textStyle: _textStyle,
537
- h: _h,
538
- w: _w,
539
- display: _display,
540
- borderBottomRightRadius: _bbrr,
541
- borderTopRightRadius: _btrr,
420
+ h,
421
+ w,
422
+ display,
423
+ borderBottomRightRadius,
424
+ borderTopRightRadius,
542
425
  ...rest
543
426
  } = props;
544
- const SP = 4;
545
- const shimStyle = { ...styleProp };
546
- if (_mt !== void 0) shimStyle.marginTop = typeof _mt === "number" ? `${_mt * SP}px` : _mt;
547
- if (_ml !== void 0) shimStyle.marginLeft = typeof _ml === "number" ? `${_ml * SP}px` : _ml;
548
- if (_mr !== void 0) shimStyle.marginRight = typeof _mr === "number" ? `${_mr * SP}px` : _mr;
549
- if (_px !== void 0) {
550
- const v = typeof _px === "number" ? `${_px * SP}px` : _px;
551
- shimStyle.paddingLeft = v;
552
- shimStyle.paddingRight = v;
553
- }
554
- if (_py !== void 0) {
555
- const v = typeof _py === "number" ? `${_py * SP}px` : _py;
556
- shimStyle.paddingTop = v;
557
- shimStyle.paddingBottom = v;
558
- }
559
- if (_fontWeight !== void 0) shimStyle.fontWeight = _fontWeight;
560
- if (_gap !== void 0) shimStyle.gap = typeof _gap === "number" ? `${_gap * SP}px` : _gap;
561
- if (_flexShrink !== void 0) shimStyle.flexShrink = _flexShrink;
562
- if (_columnGap !== void 0) shimStyle.columnGap = typeof _columnGap === "number" ? `${_columnGap * SP}px` : _columnGap;
563
- if (_gridColumn !== void 0) shimStyle.gridColumn = typeof _gridColumn === "number" ? String(_gridColumn) : _gridColumn;
564
- if (_gridRow) shimStyle.gridRow = _gridRow;
565
- if (_justifySelf) shimStyle.justifySelf = _justifySelf;
566
- if (_alignSelf) shimStyle.alignSelf = _alignSelf;
567
- if (_h) shimStyle.height = _h;
568
- if (_w) shimStyle.width = _w;
569
- if (_display) shimStyle.display = _display;
570
- if (_bbrr !== void 0) shimStyle.borderBottomRightRadius = typeof _bbrr === "number" ? `${_bbrr}px` : _bbrr;
571
- if (_btrr !== void 0) shimStyle.borderTopRightRadius = typeof _btrr === "number" ? `${_btrr}px` : _btrr;
572
- const mergedStyle = Object.keys(shimStyle).length > 0 ? shimStyle : void 0;
573
- const Comp = asChild ? Slot : "button";
427
+ const mergedStyle = buildShimStyle({
428
+ style: styleProp,
429
+ mt,
430
+ ml,
431
+ mr,
432
+ px,
433
+ py,
434
+ fontWeight,
435
+ gap,
436
+ flexShrink,
437
+ columnGap,
438
+ gridColumn,
439
+ gridRow,
440
+ justifySelf,
441
+ alignSelf,
442
+ h,
443
+ w,
444
+ display,
445
+ borderBottomRightRadius,
446
+ borderTopRightRadius
447
+ });
574
448
  const dataAttrs = {};
575
449
  if (expanded) dataAttrs["data-expanded"] = true;
576
450
  if (selected) dataAttrs["data-selected"] = true;
@@ -579,15 +453,19 @@ var Button = React2.forwardRef(
579
453
  const isDisabled = !loadingSkeleton && (loading || disabled);
580
454
  const inner = loading ? /* @__PURE__ */ jsxs(Fragment, { children: [
581
455
  /* @__PURE__ */ jsx(Spinner, {}),
582
- loadingText != null && /* @__PURE__ */ jsx("span", { className: "ml-2", children: loadingText })
456
+ loadingText != null && /* @__PURE__ */ jsx("span", { style: { marginLeft: 8 }, children: loadingText })
583
457
  ] }) : children;
458
+ const variantClass = VARIANT_CLASSES[variant] ?? VARIANT_CLASSES.solid;
459
+ const combinedClassName = [BASE_CLASSES, variantClass, className].filter(Boolean).join(" ");
584
460
  const button = /* @__PURE__ */ jsx(
585
- Comp,
461
+ ButtonFrame,
586
462
  {
587
463
  ref,
588
- className: cn(buttonVariants({ variant, size }), className),
589
- style: mergedStyle,
464
+ size,
590
465
  disabled: isDisabled || void 0,
466
+ asChild: asChild || void 0,
467
+ className: combinedClassName,
468
+ style: mergedStyle,
591
469
  ...dataAttrs,
592
470
  ...rest,
593
471
  children: inner
@@ -599,6 +477,17 @@ var Button = React2.forwardRef(
599
477
  return button;
600
478
  }
601
479
  );
480
+ var SIZE_CLASSES = {
481
+ "2xs": "px-2 h-5 min-w-5 text-xs rounded-sm gap-1",
482
+ xs: "px-2 h-6 min-w-6 text-sm rounded-sm gap-1",
483
+ sm: "px-3 h-8 min-w-8 text-sm rounded-md gap-1",
484
+ md: "px-3 h-10 min-w-10 text-base rounded-md gap-2"
485
+ };
486
+ function buttonVariants(opts) {
487
+ const v = opts?.variant ?? "solid";
488
+ const s = opts?.size ?? "md";
489
+ return [BASE_CLASSES, VARIANT_CLASSES[v] ?? "", SIZE_CLASSES[s] ?? ""].filter(Boolean).join(" ");
490
+ }
602
491
  var ButtonGroup = React2.forwardRef(
603
492
  function ButtonGroup2(props, ref) {
604
493
  const { className, ...rest } = props;
@@ -606,7 +495,7 @@ var ButtonGroup = React2.forwardRef(
606
495
  "div",
607
496
  {
608
497
  ref,
609
- className: cn("inline-flex", className),
498
+ className: ["inline-flex", className].filter(Boolean).join(" "),
610
499
  role: "group",
611
500
  ...rest
612
501
  }
@@ -647,11 +536,11 @@ var ButtonGroupRadio = React2.forwardRef(
647
536
  "div",
648
537
  {
649
538
  ref,
650
- className: cn(
539
+ className: [
651
540
  "inline-flex gap-0",
652
- equalWidth && "grid",
541
+ equalWidth ? "grid" : "",
653
542
  className
654
- ),
543
+ ].filter(Boolean).join(" "),
655
544
  style: equalWidth ? { gridTemplateColumns: `repeat(${childrenLength}, 1fr)` } : void 0,
656
545
  role: "group",
657
546
  ...rest,