@gentleduck/registry-ui 0.2.5 → 0.2.8
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/.turbo/turbo-check-types.log +1 -0
- package/.turbo/turbo-test.log +23 -0
- package/CHANGELOG.md +21 -0
- package/package.json +9 -8
- package/src/_old/_table/index.ts +9 -0
- package/src/_old/_table/table.tsx +7 -7
- package/src/_old/_upload/index.ts +13 -0
- package/src/_old/_upload/upload-sonner.tsx +1 -1
- package/src/alert-dialog/alert-dialog.tsx +11 -4
- package/src/aspect-ratio/aspect-ratio.tsx +9 -11
- package/src/audio/audio-visualizer.tsx +28 -2
- package/src/audio/audio.types.ts +1 -2
- package/src/button/__test__/button.test.tsx +80 -0
- package/src/button/button.tsx +1 -1
- package/src/button-group/button-group.tsx +1 -0
- package/src/calendar/calendar.tsx +161 -141
- package/src/carousel/carousel.tsx +1 -0
- package/src/chart/__test__/chart.test.tsx +40 -0
- package/src/chart/chart.tsx +16 -7
- package/src/checkbox/checkbox.tsx +1 -0
- package/src/collapsible/collapsible.tsx +2 -1
- package/src/combobox/combobox.tsx +96 -69
- package/src/command/command.tsx +34 -37
- package/src/context-menu/context-menu.tsx +11 -3
- package/src/dialog/dialog-responsive.tsx +12 -1
- package/src/dialog/dialog.tsx +12 -4
- package/src/dropdown-menu/dropdown-menu.tsx +11 -3
- package/src/empty/empty.tsx +30 -17
- package/src/field/field.tsx +138 -109
- package/src/input-group/input-group.tsx +3 -0
- package/src/item/item.tsx +1 -0
- package/src/json-editor/json-editor.tsx +59 -60
- package/src/json-editor/json-editor.view.tsx +1 -0
- package/src/label/label.tsx +1 -0
- package/src/menubar/menubar.tsx +10 -3
- package/src/popover/popover.tsx +4 -0
- package/src/preview-panel/preview-panel-dialog.tsx +86 -80
- package/src/preview-panel/preview-panel.tsx +280 -273
- package/src/resizable/resizable.tsx +17 -15
- package/src/select/select.tsx +3 -0
- package/src/separator/separator.tsx +0 -1
- package/src/sheet/sheet.tsx +16 -4
- package/src/sidebar/sidebar.tsx +436 -378
- package/src/slider/slider.tsx +8 -10
- package/src/sonner/sonner.chunks.tsx +3 -0
- package/src/sonner/sonner.tsx +23 -20
- package/src/switch/switch.tsx +1 -0
- package/src/tabs/tabs.tsx +2 -2
- package/src/toggle/toggle.constants.ts +2 -2
- package/src/tooltip/tooltip.tsx +3 -0
- package/tsconfig.json +10 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
$ tsc -p tsconfig.json --noEmit --pretty false --skipLibCheck
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
$ bun test
|
|
2
|
+
bun test v1.3.5 (1e86cebd)
|
|
3
|
+
|
|
4
|
+
::group::src/chart/__test__/chart.test.tsx:
|
|
5
|
+
(pass) registry-ui chart > ChartContainer server render does not emit invalid size warnings [53.00ms]
|
|
6
|
+
|
|
7
|
+
::endgroup::
|
|
8
|
+
|
|
9
|
+
::group::src/button/__test__/button.test.tsx:
|
|
10
|
+
(pass) registry-ui button > buttonVariants returns the shared base styles and defaults [1.00ms]
|
|
11
|
+
(pass) registry-ui button > buttonVariants applies explicit variant and size overrides
|
|
12
|
+
(pass) registry-ui button > button exports keep stable display names
|
|
13
|
+
(pass) registry-ui button > Button renders loading state as a busy disabled native button [3.00ms]
|
|
14
|
+
(pass) registry-ui button > Button preserves explicit disabled state even when loading is false [1.00ms]
|
|
15
|
+
(pass) registry-ui button > Button collapses into icon-only mode and hides secondary content
|
|
16
|
+
(pass) registry-ui button > AnimationIcon renders left and right placements around children [1.00ms]
|
|
17
|
+
|
|
18
|
+
::endgroup::
|
|
19
|
+
|
|
20
|
+
8 pass
|
|
21
|
+
0 fail
|
|
22
|
+
25 expect() calls
|
|
23
|
+
Ran 8 tests across 2 files. [574.00ms]
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,26 @@
|
|
|
1
1
|
# @gentleduck/registry-ui
|
|
2
2
|
|
|
3
|
+
## 0.2.8
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- e7ee580: fix(registry-ui): replace workspace:\* dependencies with published npm versions
|
|
8
|
+
|
|
9
|
+
The published package had `workspace:*` references that broke any consumer's install.
|
|
10
|
+
|
|
11
|
+
## 0.2.6
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- 2b6e8d0: Resolve all biome lint warnings, improve type safety, and add test coverage across the monorepo.
|
|
16
|
+
- Updated dependencies [2b6e8d0]
|
|
17
|
+
- @gentleduck/primitives@0.2.5
|
|
18
|
+
- @gentleduck/variants@0.1.20
|
|
19
|
+
- @gentleduck/hooks@0.1.12
|
|
20
|
+
- @gentleduck/motion@0.1.17
|
|
21
|
+
- @gentleduck/libs@0.1.15
|
|
22
|
+
- @gentleduck/vim@0.1.16
|
|
23
|
+
|
|
3
24
|
## 0.2.5
|
|
4
25
|
|
|
5
26
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -4,12 +4,12 @@
|
|
|
4
4
|
"node": ">=22.0.0"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@gentleduck/hooks": "
|
|
8
|
-
"@gentleduck/libs": "
|
|
9
|
-
"@gentleduck/motion": "
|
|
10
|
-
"@gentleduck/primitives": "
|
|
11
|
-
"@gentleduck/variants": "
|
|
12
|
-
"@gentleduck/vim": "
|
|
7
|
+
"@gentleduck/hooks": "^0.1.12",
|
|
8
|
+
"@gentleduck/libs": "^0.1.15",
|
|
9
|
+
"@gentleduck/motion": "^0.1.17",
|
|
10
|
+
"@gentleduck/primitives": "^0.2.5",
|
|
11
|
+
"@gentleduck/variants": "^0.1.20",
|
|
12
|
+
"@gentleduck/vim": "^0.1.16",
|
|
13
13
|
"embla-carousel-react": "8.6.0",
|
|
14
14
|
"lucide-react": "0.576.0",
|
|
15
15
|
"next-themes": "^0.4.6",
|
|
@@ -52,8 +52,9 @@
|
|
|
52
52
|
"access": "public"
|
|
53
53
|
},
|
|
54
54
|
"scripts": {
|
|
55
|
-
"check-types": "tsc -p tsconfig.json --noEmit --pretty false --skipLibCheck"
|
|
55
|
+
"check-types": "tsc -p tsconfig.json --noEmit --pretty false --skipLibCheck",
|
|
56
|
+
"test": "bun test"
|
|
56
57
|
},
|
|
57
58
|
"type": "module",
|
|
58
|
-
"version": "0.2.
|
|
59
|
+
"version": "0.2.8"
|
|
59
60
|
}
|
package/src/_old/_table/index.ts
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated These table components are deprecated and no longer maintained.
|
|
3
|
+
* Use the components from `@duck-ui/registry-ui/table` instead.
|
|
4
|
+
* This module will be removed in a future release.
|
|
5
|
+
*/
|
|
1
6
|
export * from './table'
|
|
7
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/table` instead. */
|
|
2
8
|
export * from './table.constants'
|
|
9
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/table` instead. */
|
|
3
10
|
export * from './table.hook'
|
|
11
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/table` instead. */
|
|
4
12
|
export * from './table.lib'
|
|
13
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/table` instead. */
|
|
5
14
|
export * from './table.types'
|
|
@@ -206,7 +206,7 @@
|
|
|
206
206
|
// DuckTableSearchInputProps
|
|
207
207
|
// >(({ trigger, label, badge, keys }, ref) => {
|
|
208
208
|
// const {
|
|
209
|
-
// children: badgeChildren = '
|
|
209
|
+
// children: badgeChildren = 'Ctrl+Shift+F',
|
|
210
210
|
// className: badgeClassName,
|
|
211
211
|
// ...badgeProps
|
|
212
212
|
// } = badge ?? {}
|
|
@@ -415,7 +415,7 @@
|
|
|
415
415
|
// children: 'View',
|
|
416
416
|
// command: {
|
|
417
417
|
// key: 'ctrl+shift+v',
|
|
418
|
-
// label: '
|
|
418
|
+
// label: 'Ctrl+Shift+V',
|
|
419
419
|
// },
|
|
420
420
|
// icon: {
|
|
421
421
|
// children: MixerHorizontalIcon as LucideIcon,
|
|
@@ -527,7 +527,7 @@
|
|
|
527
527
|
// // }),
|
|
528
528
|
// // command: {
|
|
529
529
|
// // key: 'ctrl+shift+down',
|
|
530
|
-
// // label: '
|
|
530
|
+
// // label: 'Ctrl+Shift+Down',
|
|
531
531
|
// // action: () =>
|
|
532
532
|
// // setPaginationState({
|
|
533
533
|
// // ...paginationState,
|
|
@@ -546,7 +546,7 @@
|
|
|
546
546
|
// // onClick: () => setPaginationState({ ...paginationState, activePage: 0 }),
|
|
547
547
|
// // command: {
|
|
548
548
|
// // key: 'ctrl+shift+left',
|
|
549
|
-
// // label: '
|
|
549
|
+
// // label: 'Ctrl+Shift+Left',
|
|
550
550
|
// // action: () => setPaginationState({ ...paginationState, activePage: 0 }),
|
|
551
551
|
// // },
|
|
552
552
|
// label: {
|
|
@@ -561,7 +561,7 @@
|
|
|
561
561
|
// // onClick: () => setPaginationState({ ...paginationState, activePage: resultArrays.length - 1 }),
|
|
562
562
|
// // command: {
|
|
563
563
|
// // key: 'ctrl+shift+right',
|
|
564
|
-
// // label: '
|
|
564
|
+
// // label: 'Ctrl+Shift+Right',
|
|
565
565
|
// // action: () => setPaginationState({ ...paginationState, activePage: resultArrays.length - 1 }),
|
|
566
566
|
// // },
|
|
567
567
|
// label: {
|
|
@@ -575,7 +575,7 @@
|
|
|
575
575
|
// right={{
|
|
576
576
|
// command: {
|
|
577
577
|
// key: 'ctrl+shift+up',
|
|
578
|
-
// label: '
|
|
578
|
+
// label: 'Ctrl+Shift+Up',
|
|
579
579
|
// // action: () =>
|
|
580
580
|
// // setPaginationState({
|
|
581
581
|
// // ...paginationState,
|
|
@@ -677,7 +677,7 @@
|
|
|
677
677
|
// className: 'w-[4.5rem] h-[32px] gap-0',
|
|
678
678
|
// command: {
|
|
679
679
|
// key: 'ctrl+shift+c',
|
|
680
|
-
// label: '
|
|
680
|
+
// label: 'Ctrl+Shift+C',
|
|
681
681
|
// },
|
|
682
682
|
// label: {
|
|
683
683
|
// children: 'Rows per page',
|
|
@@ -1,9 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @deprecated These upload components are deprecated and no longer maintained.
|
|
3
|
+
* Use the components from `@duck-ui/registry-ui/upload` instead.
|
|
4
|
+
* This module will be removed in a future release.
|
|
5
|
+
*/
|
|
1
6
|
export * from './upload'
|
|
7
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
2
8
|
export * from './upload.assets'
|
|
9
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
3
10
|
export * from './upload.constants'
|
|
11
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
4
12
|
export * from './upload.dto'
|
|
13
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
5
14
|
export * from './upload.lib'
|
|
15
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
6
16
|
export * from './upload.types'
|
|
17
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
7
18
|
export * from './upload-advanced'
|
|
19
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
8
20
|
export * from './upload-advanced-chunks'
|
|
21
|
+
/** @deprecated Use components from `@duck-ui/registry-ui/upload` instead. */
|
|
9
22
|
export * from './upload-sonner'
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
// </p>
|
|
35
35
|
// <div className="flex items-center gap-2">
|
|
36
36
|
// {remainingTime && (
|
|
37
|
-
// <p className="text-foreground-light text-sm font-mono">{`${remainingTime && !isNaN(remainingTime) && isFinite(remainingTime) && remainingTime !== 0 ? `${formatTime(remainingTime)} remaining
|
|
37
|
+
// <p className="text-foreground-light text-sm font-mono">{`${remainingTime && !isNaN(remainingTime) && isFinite(remainingTime) && remainingTime !== 0 ? `${formatTime(remainingTime)} remaining -` : ''}`}</p>
|
|
38
38
|
// )}
|
|
39
39
|
// <p className="text-foreground-light text-sm font-mono">{`${progress}%`}</p>
|
|
40
40
|
// </div>
|
|
@@ -6,10 +6,13 @@ import * as React from 'react'
|
|
|
6
6
|
import { buttonVariants } from '../button'
|
|
7
7
|
|
|
8
8
|
const AlertDialog = AlertDialogPrimitive.Root
|
|
9
|
+
AlertDialog.displayName = 'AlertDialog'
|
|
9
10
|
|
|
10
11
|
const AlertDialogTrigger = AlertDialogPrimitive.Trigger
|
|
12
|
+
AlertDialogTrigger.displayName = 'AlertDialogTrigger'
|
|
11
13
|
|
|
12
14
|
const AlertDialogPortal = AlertDialogPrimitive.Portal
|
|
15
|
+
AlertDialogPortal.displayName = 'AlertDialogPortal'
|
|
13
16
|
|
|
14
17
|
const AlertDialogOverlay = React.forwardRef<
|
|
15
18
|
React.ComponentRef<typeof AlertDialogPrimitive.Overlay>,
|
|
@@ -46,13 +49,17 @@ const AlertDialogContent = React.forwardRef<
|
|
|
46
49
|
))
|
|
47
50
|
AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
|
|
48
51
|
|
|
49
|
-
const AlertDialogHeader =
|
|
50
|
-
|
|
52
|
+
const AlertDialogHeader = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
53
|
+
({ className, ...props }, ref) => (
|
|
54
|
+
<div ref={ref} className={cn('flex flex-col space-y-2 text-center sm:text-start', className)} {...props} />
|
|
55
|
+
),
|
|
51
56
|
)
|
|
52
57
|
AlertDialogHeader.displayName = 'AlertDialogHeader'
|
|
53
58
|
|
|
54
|
-
const AlertDialogFooter =
|
|
55
|
-
|
|
59
|
+
const AlertDialogFooter = React.forwardRef<HTMLDivElement, React.HTMLAttributes<HTMLDivElement>>(
|
|
60
|
+
({ className, ...props }, ref) => (
|
|
61
|
+
<div ref={ref} className={cn('flex flex-col-reverse sm:flex-row sm:justify-end sm:gap-2', className)} {...props} />
|
|
62
|
+
),
|
|
56
63
|
)
|
|
57
64
|
AlertDialogFooter.displayName = 'AlertDialogFooter'
|
|
58
65
|
|
|
@@ -3,17 +3,14 @@
|
|
|
3
3
|
import { cn } from '@gentleduck/libs/cn'
|
|
4
4
|
import { type Direction, useDirection } from '@gentleduck/primitives/direction'
|
|
5
5
|
import { Slot } from '@gentleduck/primitives/slot'
|
|
6
|
+
import React from 'react'
|
|
6
7
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
...props
|
|
14
|
-
}: React.ComponentPropsWithRef<typeof Slot> & {
|
|
15
|
-
ratio: string
|
|
16
|
-
}) {
|
|
8
|
+
const AspectRatio = React.forwardRef<
|
|
9
|
+
React.ComponentRef<typeof Slot>,
|
|
10
|
+
React.ComponentPropsWithoutRef<typeof Slot> & {
|
|
11
|
+
ratio: string
|
|
12
|
+
}
|
|
13
|
+
>(({ style, className, ratio, dir, ...props }, ref) => {
|
|
17
14
|
const direction = useDirection(dir as Direction)
|
|
18
15
|
return (
|
|
19
16
|
<Slot
|
|
@@ -28,6 +25,7 @@ function AspectRatio({
|
|
|
28
25
|
data-slot="aspect-ratio"
|
|
29
26
|
/>
|
|
30
27
|
)
|
|
31
|
-
}
|
|
28
|
+
})
|
|
29
|
+
AspectRatio.displayName = 'AspectRatio'
|
|
32
30
|
|
|
33
31
|
export { AspectRatio }
|
|
@@ -337,7 +337,19 @@ const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
|
|
|
337
337
|
setLoading,
|
|
338
338
|
width,
|
|
339
339
|
})
|
|
340
|
-
}, [
|
|
340
|
+
}, [
|
|
341
|
+
blob,
|
|
342
|
+
barWidth,
|
|
343
|
+
currentColors.backgroundColor,
|
|
344
|
+
currentColors.barColor,
|
|
345
|
+
currentColors.barPlayedColor,
|
|
346
|
+
gap,
|
|
347
|
+
height,
|
|
348
|
+
minBarHeight,
|
|
349
|
+
process_audio,
|
|
350
|
+
setLoading,
|
|
351
|
+
width,
|
|
352
|
+
])
|
|
341
353
|
|
|
342
354
|
React.useEffect(() => {
|
|
343
355
|
if (!canvasRef.current) return
|
|
@@ -359,7 +371,19 @@ const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
|
|
|
359
371
|
gap,
|
|
360
372
|
minBarHeight,
|
|
361
373
|
})
|
|
362
|
-
}, [
|
|
374
|
+
}, [
|
|
375
|
+
data,
|
|
376
|
+
width,
|
|
377
|
+
currentTime,
|
|
378
|
+
duration,
|
|
379
|
+
animationProgress,
|
|
380
|
+
barWidth,
|
|
381
|
+
currentColors.backgroundColor,
|
|
382
|
+
currentColors.barColor,
|
|
383
|
+
currentColors.barPlayedColor,
|
|
384
|
+
gap,
|
|
385
|
+
minBarHeight,
|
|
386
|
+
])
|
|
363
387
|
|
|
364
388
|
return (
|
|
365
389
|
<canvas
|
|
@@ -374,4 +398,6 @@ const AudioVisualizer: React.FC<AudioVisualizerProps> = ({
|
|
|
374
398
|
)
|
|
375
399
|
}
|
|
376
400
|
|
|
401
|
+
AudioVisualizer.displayName = 'AudioVisualizer'
|
|
402
|
+
|
|
377
403
|
export { AudioVisualizer }
|
package/src/audio/audio.types.ts
CHANGED
|
@@ -6,8 +6,7 @@ export interface RecordingParams {
|
|
|
6
6
|
|
|
7
7
|
export interface StopRecordingHandlerParam {
|
|
8
8
|
setRecording: React.Dispatch<React.SetStateAction<boolean>>
|
|
9
|
-
|
|
10
|
-
intervalRef: React.RefObject<NodeJS.Timeout | null>
|
|
9
|
+
intervalRef: React.RefObject<ReturnType<typeof setInterval> | null>
|
|
11
10
|
mediaRecorderRef: React.RefObject<MediaRecorder | null>
|
|
12
11
|
durationRef: React.RefObject<number>
|
|
13
12
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { describe, expect, test } from 'bun:test'
|
|
2
|
+
import * as React from 'react'
|
|
3
|
+
import { renderToStaticMarkup } from 'react-dom/server'
|
|
4
|
+
import { AnimationIcon, Button } from '../button'
|
|
5
|
+
import { buttonVariants } from '../button.constants'
|
|
6
|
+
|
|
7
|
+
describe('registry-ui button', () => {
|
|
8
|
+
test('buttonVariants returns the shared base styles and defaults', () => {
|
|
9
|
+
const classes = buttonVariants()
|
|
10
|
+
|
|
11
|
+
expect(classes).toContain('inline-flex')
|
|
12
|
+
expect(classes).toContain('bg-primary')
|
|
13
|
+
expect(classes).toContain('h-9')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
test('buttonVariants applies explicit variant and size overrides', () => {
|
|
17
|
+
const classes = buttonVariants({ size: 'sm', variant: 'ghost' })
|
|
18
|
+
|
|
19
|
+
expect(classes).toContain('h-8')
|
|
20
|
+
expect(classes).toContain('hover:bg-accent')
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
test('button exports keep stable display names', () => {
|
|
24
|
+
expect(Button).toBeDefined()
|
|
25
|
+
expect(Button.displayName).toBe('Button')
|
|
26
|
+
expect(AnimationIcon.displayName).toBe('AnimationIcon')
|
|
27
|
+
})
|
|
28
|
+
|
|
29
|
+
test('Button renders loading state as a busy disabled native button', () => {
|
|
30
|
+
const html = renderToStaticMarkup(<Button loading>Save</Button>)
|
|
31
|
+
|
|
32
|
+
expect(html).toContain('type="button"')
|
|
33
|
+
expect(html).toContain('aria-busy="true"')
|
|
34
|
+
expect(html).toContain('disabled=""')
|
|
35
|
+
expect(html).toContain('animate-spin')
|
|
36
|
+
expect(html).toContain('Save')
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
test('Button preserves explicit disabled state even when loading is false', () => {
|
|
40
|
+
const html = renderToStaticMarkup(
|
|
41
|
+
<Button disabled loading={false}>
|
|
42
|
+
Save
|
|
43
|
+
</Button>,
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
expect(html).toContain('disabled=""')
|
|
47
|
+
expect(html).not.toContain('aria-busy="true"')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
test('Button collapses into icon-only mode and hides secondary content', () => {
|
|
51
|
+
const html = renderToStaticMarkup(
|
|
52
|
+
<Button icon={<span data-icon="left">L</span>} isCollapsed secondIcon={<span data-icon="right">R</span>}>
|
|
53
|
+
Save
|
|
54
|
+
</Button>,
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
expect(html).toContain('data-icon="left"')
|
|
58
|
+
expect(html).toContain('size-9')
|
|
59
|
+
expect(html).not.toContain('Save')
|
|
60
|
+
expect(html).not.toContain('data-icon="right"')
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
test('AnimationIcon renders left and right placements around children', () => {
|
|
64
|
+
const leftHtml = renderToStaticMarkup(
|
|
65
|
+
<AnimationIcon animationIcon={{ icon: <span data-icon="left">L</span>, iconPlacement: 'left' }}>
|
|
66
|
+
Label
|
|
67
|
+
</AnimationIcon>,
|
|
68
|
+
)
|
|
69
|
+
const rightHtml = renderToStaticMarkup(
|
|
70
|
+
<AnimationIcon animationIcon={{ icon: <span data-icon="right">R</span>, iconPlacement: 'right' }}>
|
|
71
|
+
Label
|
|
72
|
+
</AnimationIcon>,
|
|
73
|
+
)
|
|
74
|
+
|
|
75
|
+
expect(leftHtml).toContain('data-icon="left"')
|
|
76
|
+
expect(leftHtml.indexOf('data-icon="left"')).toBeLessThan(leftHtml.indexOf('Label'))
|
|
77
|
+
expect(rightHtml).toContain('data-icon="right"')
|
|
78
|
+
expect(rightHtml.indexOf('Label')).toBeLessThan(rightHtml.indexOf('data-icon="right"'))
|
|
79
|
+
})
|
|
80
|
+
})
|
package/src/button/button.tsx
CHANGED
|
@@ -42,7 +42,7 @@ const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
|
42
42
|
variant,
|
|
43
43
|
}),
|
|
44
44
|
)}
|
|
45
|
-
disabled={loading
|
|
45
|
+
disabled={Boolean(loading) || disabled}
|
|
46
46
|
ref={ref}
|
|
47
47
|
type={type}>
|
|
48
48
|
{loading ? <Loader aria-hidden="true" className="animate-spin" /> : icon}
|
|
@@ -12,6 +12,7 @@ const ButtonGroup = React.forwardRef<
|
|
|
12
12
|
>(({ className, orientation = 'horizontal', dir, ...props }, ref) => {
|
|
13
13
|
const direction = useDirection(dir as Direction)
|
|
14
14
|
return (
|
|
15
|
+
// biome-ignore lint/a11y/useSemanticElements: group role is semantically correct for button groups
|
|
15
16
|
<div
|
|
16
17
|
className={cn(buttonGroupVariants({ orientation }), className)}
|
|
17
18
|
data-orientation={orientation}
|