@luxfi/ui 7.4.10 → 7.4.11
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/accordion.cjs +107 -166
- package/dist/accordion.d.cts +18 -51
- package/dist/accordion.d.ts +18 -51
- package/dist/accordion.js +109 -166
- package/dist/chrome.cjs +193 -379
- package/dist/chrome.js +195 -379
- package/dist/collapsible.cjs +35 -26
- package/dist/collapsible.d.cts +2 -1
- package/dist/collapsible.d.ts +2 -1
- package/dist/collapsible.js +34 -24
- package/dist/dialog.d.cts +1 -1
- package/dist/dialog.d.ts +1 -1
- package/dist/drawer.cjs +92 -115
- package/dist/drawer.d.cts +43 -10
- package/dist/drawer.d.ts +43 -10
- package/dist/drawer.js +94 -115
- package/dist/field.cjs +60 -109
- package/dist/field.d.cts +0 -1
- package/dist/field.d.ts +0 -1
- package/dist/field.js +61 -109
- package/dist/heading.cjs +10 -17
- package/dist/heading.d.cts +0 -2
- package/dist/heading.d.ts +0 -2
- package/dist/heading.js +10 -17
- package/dist/icon-button.cjs +82 -82
- package/dist/icon-button.d.cts +16 -12
- package/dist/icon-button.d.ts +16 -12
- package/dist/icon-button.js +82 -82
- package/dist/index.cjs +1073 -1419
- package/dist/index.d.cts +1 -5
- package/dist/index.d.ts +1 -5
- package/dist/index.js +1075 -1414
- package/dist/input-group.cjs +11 -12
- package/dist/input-group.js +11 -12
- package/dist/input.cjs +27 -27
- package/dist/input.d.cts +21 -1
- package/dist/input.d.ts +21 -1
- package/dist/input.js +25 -28
- package/dist/menu.cjs +160 -271
- package/dist/menu.d.cts +41 -57
- package/dist/menu.d.ts +41 -57
- package/dist/menu.js +161 -251
- package/dist/popover.cjs +1 -1
- package/dist/popover.js +1 -1
- package/dist/select.cjs +40 -39
- package/dist/select.d.cts +35 -4
- package/dist/select.d.ts +35 -4
- package/dist/select.js +40 -38
- package/dist/separator.cjs +8 -33
- package/dist/separator.js +8 -33
- package/dist/tabs.cjs +108 -197
- package/dist/tabs.d.cts +16 -60
- package/dist/tabs.d.ts +16 -60
- package/dist/tabs.js +109 -196
- package/dist/textarea.cjs +56 -27
- package/dist/textarea.js +57 -28
- package/dist/toaster.cjs +97 -79
- package/dist/toaster.d.cts +7 -8
- package/dist/toaster.d.ts +7 -8
- package/dist/toaster.js +78 -80
- package/package.json +2 -16
- package/src/accordion.tsx +173 -227
- package/src/collapsible.tsx +55 -52
- package/src/drawer.tsx +123 -115
- package/src/field.tsx +68 -124
- package/src/heading.tsx +22 -26
- package/src/icon-button.tsx +134 -141
- package/src/ink.tsx +37 -0
- package/src/input-group.tsx +21 -12
- package/src/input.tsx +41 -32
- package/src/menu.tsx +224 -397
- package/src/popover.tsx +1 -1
- package/src/select.tsx +80 -59
- package/src/separator.tsx +13 -34
- package/src/tabs.tsx +166 -296
- package/src/textarea.tsx +19 -29
- package/src/toaster.tsx +118 -86
- package/tokens.css +61 -0
package/src/popover.tsx
CHANGED
|
@@ -195,7 +195,7 @@ export const PopoverContent = React.forwardRef<
|
|
|
195
195
|
className={ cn(
|
|
196
196
|
'z-50 rounded-lg border border-[var(--color-popover-border,var(--color-border-divider))]',
|
|
197
197
|
'bg-[var(--color-popover-bg,var(--color-dialog-bg))]',
|
|
198
|
-
'shadow-[var(--shadow-popover
|
|
198
|
+
'shadow-[var(--shadow-popover)]',
|
|
199
199
|
'outline-none',
|
|
200
200
|
'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
201
201
|
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
|
package/src/select.tsx
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import { Select as GuiSelect } from '@hanzo/gui';
|
|
4
4
|
import { useDebounce } from '@uidotdev/usehooks';
|
|
5
5
|
import * as React from 'react';
|
|
6
6
|
|
|
@@ -229,15 +229,14 @@ export const SelectRoot = React.forwardRef<HTMLDivElement, SelectRootProps>(
|
|
|
229
229
|
|
|
230
230
|
return (
|
|
231
231
|
<SelectInternalContext.Provider value={ ctxValue }>
|
|
232
|
-
<
|
|
232
|
+
<GuiSelect
|
|
233
233
|
value={ currentValue[0] ?? '' }
|
|
234
234
|
defaultValue={ defaultValueArr?.[0] }
|
|
235
235
|
onValueChange={ handleRadixValueChange }
|
|
236
236
|
open={ isOpen }
|
|
237
237
|
onOpenChange={ handleOpenChange }
|
|
238
|
-
|
|
238
|
+
disablePreventBodyScroll
|
|
239
239
|
name={ name }
|
|
240
|
-
required={ required }
|
|
241
240
|
>
|
|
242
241
|
<div
|
|
243
242
|
ref={ ref }
|
|
@@ -250,7 +249,7 @@ export const SelectRoot = React.forwardRef<HTMLDivElement, SelectRootProps>(
|
|
|
250
249
|
>
|
|
251
250
|
{ children }
|
|
252
251
|
</div>
|
|
253
|
-
</
|
|
252
|
+
</GuiSelect>
|
|
254
253
|
</SelectInternalContext.Provider>
|
|
255
254
|
);
|
|
256
255
|
},
|
|
@@ -263,7 +262,7 @@ export const SelectRoot = React.forwardRef<HTMLDivElement, SelectRootProps>(
|
|
|
263
262
|
export interface SelectControlProps {
|
|
264
263
|
children?: React.ReactNode;
|
|
265
264
|
noIndicator?: boolean;
|
|
266
|
-
triggerProps?: React.
|
|
265
|
+
triggerProps?: React.ComponentProps<typeof GuiSelect.Trigger> & {
|
|
267
266
|
asChild?: boolean;
|
|
268
267
|
px?: string | number;
|
|
269
268
|
className?: string;
|
|
@@ -286,9 +285,10 @@ export const SelectControl = React.forwardRef<HTMLButtonElement, SelectControlPr
|
|
|
286
285
|
const { asChild, px: _px, className: triggerClassName, ...radixTriggerProps } = triggerProps ?? {};
|
|
287
286
|
|
|
288
287
|
const trigger = (
|
|
289
|
-
<
|
|
290
|
-
ref={ ref }
|
|
288
|
+
<GuiSelect.Trigger
|
|
289
|
+
ref={ ref as never }
|
|
291
290
|
asChild={ asChild }
|
|
291
|
+
unstyled
|
|
292
292
|
className={ cn(
|
|
293
293
|
'group peer inline-flex items-center gap-2 cursor-pointer',
|
|
294
294
|
'rounded-lg text-sm transition-colors outline-none',
|
|
@@ -314,7 +314,7 @@ export const SelectControl = React.forwardRef<HTMLButtonElement, SelectControlPr
|
|
|
314
314
|
) }
|
|
315
315
|
</>
|
|
316
316
|
) }
|
|
317
|
-
</
|
|
317
|
+
</GuiSelect.Trigger>
|
|
318
318
|
);
|
|
319
319
|
|
|
320
320
|
if (loading) {
|
|
@@ -376,39 +376,33 @@ export interface SelectContentProps {
|
|
|
376
376
|
}
|
|
377
377
|
|
|
378
378
|
export const SelectContent = React.forwardRef<HTMLDivElement, SelectContentProps>(
|
|
379
|
-
function SelectContent(props,
|
|
380
|
-
|
|
379
|
+
function SelectContent(props, _ref) {
|
|
380
|
+
// `portalled` and `portalRef` stay in the type because callers pass them,
|
|
381
|
+
// but gui's Select.Content owns its own layering — it mounts through the
|
|
382
|
+
// engine's portal and z-index stack whatever we say. There is no second
|
|
383
|
+
// way to place it, so there is nothing here to switch on.
|
|
384
|
+
const { portalled: _portalled, portalRef: _portalRef, children, className, ...rest } = props;
|
|
381
385
|
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
position="popper"
|
|
386
|
-
sideOffset={ 4 }
|
|
387
|
-
className={ cn(
|
|
388
|
-
'z-50 min-w-[8rem] overflow-hidden rounded-lg',
|
|
389
|
-
'bg-[var(--color-popover-bg)] shadow-[var(--shadow-popover)]',
|
|
390
|
-
'border border-[var(--color-border-divider)]',
|
|
391
|
-
'data-[state=open]:animate-in data-[state=open]:fade-in-0 data-[state=open]:zoom-in-95',
|
|
392
|
-
'data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95',
|
|
393
|
-
className,
|
|
394
|
-
) }
|
|
395
|
-
{ ...rest }
|
|
396
|
-
>
|
|
397
|
-
<RadixSelect.Viewport className="p-1">
|
|
398
|
-
{ children }
|
|
399
|
-
</RadixSelect.Viewport>
|
|
400
|
-
</RadixSelect.Content>
|
|
401
|
-
);
|
|
386
|
+
// One counter per render, walked over the rows below.
|
|
387
|
+
let n = 0;
|
|
388
|
+
const counter = () => n++;
|
|
402
389
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
390
|
+
return (
|
|
391
|
+
// Content is the focus scope — it takes no style props at all. The
|
|
392
|
+
// Viewport is the box you can see, so the surface is declared there.
|
|
393
|
+
<GuiSelect.Content { ...rest }>
|
|
394
|
+
<GuiSelect.Viewport
|
|
395
|
+
className={ cn(
|
|
396
|
+
'min-w-[8rem] overflow-hidden rounded-lg p-1',
|
|
397
|
+
'bg-[var(--color-popover-bg)] shadow-[var(--shadow-popover)]',
|
|
398
|
+
'border border-[var(--color-border-divider)]',
|
|
399
|
+
className,
|
|
400
|
+
) }
|
|
401
|
+
>
|
|
402
|
+
{ stampIndices(children, counter) }
|
|
403
|
+
</GuiSelect.Viewport>
|
|
404
|
+
</GuiSelect.Content>
|
|
405
|
+
);
|
|
412
406
|
},
|
|
413
407
|
);
|
|
414
408
|
|
|
@@ -420,17 +414,44 @@ export interface SelectItemProps {
|
|
|
420
414
|
item: SelectOption;
|
|
421
415
|
children?: React.ReactNode;
|
|
422
416
|
className?: string;
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* The row's position in the list. gui's Select is positional — it keeps its
|
|
420
|
+
* own map of index to value to drive type-ahead, the active descendant and
|
|
421
|
+
* scrolling, so a row without one is a row the keyboard cannot reach. It is
|
|
422
|
+
* stamped by `SelectContent` rather than asked of the caller, because the
|
|
423
|
+
* caller writing `<SelectItem item={x}/>` has no idea what its own ordinal is
|
|
424
|
+
* and would have to be told twice.
|
|
425
|
+
*/
|
|
426
|
+
index?: number;
|
|
423
427
|
}
|
|
424
428
|
|
|
429
|
+
/**
|
|
430
|
+
* Number every `SelectItem` beneath a node, depth first, in render order.
|
|
431
|
+
*
|
|
432
|
+
* Depth first because rows are routinely nested — inside a `SelectItemGroup`,
|
|
433
|
+
* inside the `React.Fragment` that pairs a row with its `afterElement`. A
|
|
434
|
+
* shallow pass over the content's direct children would number the groups and
|
|
435
|
+
* leave every actual row at index 0, which reads as a list whose keyboard
|
|
436
|
+
* silently only ever lands on the first entry.
|
|
437
|
+
*/
|
|
438
|
+
const stampIndices = (children: React.ReactNode, next: () => number): React.ReactNode =>
|
|
439
|
+
React.Children.map(children, (child) => {
|
|
440
|
+
if (!React.isValidElement(child)) return child;
|
|
441
|
+
if (child.type === SelectItem) return React.cloneElement(child, { index: next() } as never);
|
|
442
|
+
const kids = (child.props as { children?: React.ReactNode }).children;
|
|
443
|
+
return kids === undefined ? child : React.cloneElement(child, undefined, stampIndices(kids, next));
|
|
444
|
+
});
|
|
445
|
+
|
|
425
446
|
export const SelectItem = React.forwardRef<HTMLDivElement, SelectItemProps>(
|
|
426
447
|
function SelectItem(props, ref) {
|
|
427
|
-
const { item, children, className, ...rest } = props;
|
|
448
|
+
const { item, children, className, index, ...rest } = props;
|
|
428
449
|
|
|
429
450
|
return (
|
|
430
|
-
<
|
|
431
|
-
ref={ ref }
|
|
451
|
+
<GuiSelect.Item
|
|
452
|
+
ref={ ref as never }
|
|
453
|
+
index={ index ?? 0 }
|
|
432
454
|
value={ item.value }
|
|
433
|
-
textValue={ item.label }
|
|
434
455
|
className={ cn(
|
|
435
456
|
'relative flex cursor-pointer select-none items-center gap-2',
|
|
436
457
|
'rounded-md px-3 py-2 text-sm outline-none',
|
|
@@ -443,13 +464,13 @@ export const SelectItem = React.forwardRef<HTMLDivElement, SelectItemProps>(
|
|
|
443
464
|
{ ...rest }
|
|
444
465
|
>
|
|
445
466
|
{ item.icon }
|
|
446
|
-
<
|
|
447
|
-
{ children }
|
|
448
|
-
</
|
|
449
|
-
<
|
|
467
|
+
<GuiSelect.ItemText>
|
|
468
|
+
{ children ?? item.label }
|
|
469
|
+
</GuiSelect.ItemText>
|
|
470
|
+
<GuiSelect.ItemIndicator className="ml-auto shrink-0">
|
|
450
471
|
<CheckIcon className="h-5 w-5"/>
|
|
451
|
-
</
|
|
452
|
-
</
|
|
472
|
+
</GuiSelect.ItemIndicator>
|
|
473
|
+
</GuiSelect.Item>
|
|
453
474
|
);
|
|
454
475
|
},
|
|
455
476
|
);
|
|
@@ -529,14 +550,14 @@ export const SelectValueText = React.forwardRef<HTMLSpanElement, SelectValueText
|
|
|
529
550
|
// Radix SelectValue renders the selected value or placeholder.
|
|
530
551
|
// We override with our custom content.
|
|
531
552
|
return (
|
|
532
|
-
<
|
|
533
|
-
ref={ ref }
|
|
553
|
+
<GuiSelect.Value
|
|
554
|
+
ref={ ref as never }
|
|
534
555
|
placeholder={ placeholderText }
|
|
535
556
|
className={ cn('flex flex-col justify-center min-w-0 truncate', className) }
|
|
536
557
|
{ ...rest }
|
|
537
558
|
>
|
|
538
559
|
{ content }
|
|
539
|
-
</
|
|
560
|
+
</GuiSelect.Value>
|
|
540
561
|
);
|
|
541
562
|
},
|
|
542
563
|
);
|
|
@@ -555,12 +576,12 @@ export const SelectItemGroup = React.forwardRef<HTMLDivElement, SelectItemGroupP
|
|
|
555
576
|
function SelectItemGroup(props, ref) {
|
|
556
577
|
const { children, label, className, ...rest } = props;
|
|
557
578
|
return (
|
|
558
|
-
<
|
|
559
|
-
<
|
|
579
|
+
<GuiSelect.Group ref={ ref as never } className={ cn('py-1', className) } { ...rest }>
|
|
580
|
+
<GuiSelect.Label className="px-3 py-1.5 text-xs font-medium text-[var(--color-text-secondary)]">
|
|
560
581
|
{ label }
|
|
561
|
-
</
|
|
582
|
+
</GuiSelect.Label>
|
|
562
583
|
{ children }
|
|
563
|
-
</
|
|
584
|
+
</GuiSelect.Group>
|
|
564
585
|
);
|
|
565
586
|
},
|
|
566
587
|
);
|
|
@@ -569,8 +590,8 @@ export const SelectItemGroup = React.forwardRef<HTMLDivElement, SelectItemGroupP
|
|
|
569
590
|
// SelectLabel / SelectItemText
|
|
570
591
|
// ---------------------------------------------------------------------------
|
|
571
592
|
|
|
572
|
-
export const SelectLabel =
|
|
573
|
-
export const SelectItemText =
|
|
593
|
+
export const SelectLabel = GuiSelect.Label;
|
|
594
|
+
export const SelectItemText = GuiSelect.ItemText;
|
|
574
595
|
|
|
575
596
|
// ---------------------------------------------------------------------------
|
|
576
597
|
// Select (composite)
|
package/src/separator.tsx
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import { Separator as GuiSeparator } from '@hanzo/gui';
|
|
2
2
|
import React from 'react';
|
|
3
3
|
|
|
4
|
-
import { cn } from './utils';
|
|
5
|
-
|
|
6
4
|
type Orientation = 'horizontal' | 'vertical';
|
|
7
5
|
type Variant = 'solid' | 'dashed' | 'dotted';
|
|
8
6
|
type Size = 'xs' | 'sm' | 'md' | 'lg';
|
|
@@ -13,50 +11,31 @@ export interface SeparatorProps extends React.HTMLAttributes<HTMLHRElement> {
|
|
|
13
11
|
readonly size?: Size;
|
|
14
12
|
}
|
|
15
13
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
dashed: 'border-dashed',
|
|
19
|
-
dotted: 'border-dotted',
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const HORIZONTAL_SIZE_CLASSES: Record<Size, string> = {
|
|
23
|
-
xs: 'border-t-[0.5px]',
|
|
24
|
-
sm: 'border-t',
|
|
25
|
-
md: 'border-t-2',
|
|
26
|
-
lg: 'border-t-[3px]',
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const VERTICAL_SIZE_CLASSES: Record<Size, string> = {
|
|
30
|
-
xs: 'border-l-[0.5px]',
|
|
31
|
-
sm: 'border-l',
|
|
32
|
-
md: 'border-l-2',
|
|
33
|
-
lg: 'border-l-[3px]',
|
|
34
|
-
};
|
|
14
|
+
/** Border weight by size — the rule is one edge, so the weight is one number. */
|
|
15
|
+
const WEIGHT: Record<Size, number> = { xs: 0.5, sm: 1, md: 2, lg: 3 };
|
|
35
16
|
|
|
36
17
|
// gui's Separator wearing the Lux border scale. `vertical` is the primitive's
|
|
37
|
-
// own orientation variant, so it lays out correctly on native too;
|
|
38
|
-
//
|
|
18
|
+
// own orientation variant, so it lays out correctly on native too; weight and
|
|
19
|
+
// dash pattern are props rather than classes for the same reason.
|
|
39
20
|
export const Separator = React.forwardRef<HTMLHRElement, SeparatorProps>(
|
|
40
21
|
function Separator(
|
|
41
|
-
{ orientation = 'horizontal', variant = 'solid', size = 'sm',
|
|
22
|
+
{ orientation = 'horizontal', variant = 'solid', size = 'sm', ...rest },
|
|
42
23
|
ref,
|
|
43
24
|
) {
|
|
44
|
-
const
|
|
25
|
+
const vertical = orientation === 'vertical';
|
|
45
26
|
|
|
46
27
|
return (
|
|
47
28
|
<GuiSeparator
|
|
48
29
|
ref={ ref as never }
|
|
49
|
-
vertical={
|
|
30
|
+
vertical={ vertical }
|
|
50
31
|
role="separator"
|
|
51
32
|
aria-orientation={ orientation }
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
className,
|
|
59
|
-
) }
|
|
33
|
+
borderWidth={ 0 }
|
|
34
|
+
borderStyle={ variant }
|
|
35
|
+
borderColor={ 'var(--color-border-divider)' as never }
|
|
36
|
+
{ ...(vertical ?
|
|
37
|
+
{ borderLeftWidth: WEIGHT[size], alignSelf: 'stretch', height: 'auto', width: 0 } :
|
|
38
|
+
{ borderTopWidth: WEIGHT[size], width: '100%' }) }
|
|
60
39
|
{ ...(rest as object) }
|
|
61
40
|
/>
|
|
62
41
|
);
|