@gv-tech/ui-web 2.15.2 → 2.17.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 (143) hide show
  1. package/README.md +1 -1
  2. package/dist/accordion.cjs +1 -1
  3. package/dist/accordion.mjs +3 -3
  4. package/dist/alert-dialog.cjs +2 -2
  5. package/dist/alert-dialog.mjs +16 -16
  6. package/dist/alert.cjs +1 -1
  7. package/dist/alert.mjs +1 -1
  8. package/dist/avatar.cjs +1 -1
  9. package/dist/avatar.mjs +34 -34
  10. package/dist/badge.cjs +1 -1
  11. package/dist/badge.mjs +1 -1
  12. package/dist/breadcrumb.cjs +1 -1
  13. package/dist/breadcrumb.mjs +1 -1
  14. package/dist/button.cjs +1 -1
  15. package/dist/button.mjs +1 -1
  16. package/dist/calendar.cjs +1 -1
  17. package/dist/calendar.mjs +1 -1
  18. package/dist/card.cjs +1 -1
  19. package/dist/card.mjs +1 -1
  20. package/dist/carousel.cjs +1 -1
  21. package/dist/carousel.mjs +1 -1
  22. package/dist/chart.cjs +1 -1
  23. package/dist/chart.mjs +1 -1
  24. package/dist/checkbox.cjs +1 -1
  25. package/dist/checkbox.mjs +2 -2
  26. package/dist/command.cjs +1 -1
  27. package/dist/command.mjs +114 -114
  28. package/dist/context-menu.cjs +1 -1
  29. package/dist/context-menu.mjs +68 -68
  30. package/dist/dialog.cjs +1 -1
  31. package/dist/dialog.mjs +21 -21
  32. package/dist/drawer.cjs +1 -1
  33. package/dist/drawer.mjs +16 -16
  34. package/dist/dropdown-menu.cjs +1 -1
  35. package/dist/dropdown-menu.mjs +43 -43
  36. package/dist/form.cjs +1 -1
  37. package/dist/form.mjs +1 -1
  38. package/dist/hover-card.cjs +1 -1
  39. package/dist/hover-card.mjs +2 -2
  40. package/dist/index.cjs +1 -1
  41. package/dist/index.d.ts +52 -0
  42. package/dist/index.mjs +101 -95
  43. package/dist/input.cjs +1 -1
  44. package/dist/input.mjs +1 -1
  45. package/dist/label.cjs +1 -1
  46. package/dist/label.mjs +2 -2
  47. package/dist/menubar.cjs +1 -1
  48. package/dist/menubar.mjs +77 -77
  49. package/dist/navigation-menu.cjs +1 -1
  50. package/dist/navigation-menu.mjs +57 -57
  51. package/dist/pagination.cjs +1 -1
  52. package/dist/pagination.mjs +1 -1
  53. package/dist/popover.cjs +1 -1
  54. package/dist/popover.mjs +62 -62
  55. package/dist/progress.cjs +2 -2
  56. package/dist/progress.mjs +2 -2
  57. package/dist/radio-group.cjs +1 -1
  58. package/dist/radio-group.mjs +36 -36
  59. package/dist/resizable.cjs +1 -1
  60. package/dist/resizable.mjs +1 -1
  61. package/dist/scroll-area.cjs +1 -1
  62. package/dist/scroll-area.mjs +88 -88
  63. package/dist/scroll-to-top.cjs +1 -0
  64. package/dist/scroll-to-top.d.ts +12 -0
  65. package/dist/scroll-to-top.mjs +86 -0
  66. package/dist/search.cjs +1 -1
  67. package/dist/search.mjs +1 -1
  68. package/dist/select.cjs +1 -1
  69. package/dist/select.mjs +74 -74
  70. package/dist/separator.cjs +1 -1
  71. package/dist/separator.mjs +9 -9
  72. package/dist/sheet.cjs +1 -1
  73. package/dist/sheet.mjs +12 -12
  74. package/dist/skeleton.cjs +1 -1
  75. package/dist/skeleton.mjs +1 -1
  76. package/dist/slider.cjs +1 -1
  77. package/dist/slider.mjs +2 -2
  78. package/dist/support-fab.cjs +1 -0
  79. package/dist/support-fab.d.ts +20 -0
  80. package/dist/support-fab.mjs +120 -0
  81. package/dist/switch.cjs +1 -1
  82. package/dist/switch.mjs +12 -12
  83. package/dist/table-of-contents.cjs +1 -0
  84. package/dist/table-of-contents.d.ts +35 -0
  85. package/dist/table-of-contents.mjs +160 -0
  86. package/dist/table.cjs +1 -1
  87. package/dist/table.mjs +1 -1
  88. package/dist/tabs.cjs +1 -1
  89. package/dist/tabs.mjs +41 -41
  90. package/dist/text.cjs +1 -1
  91. package/dist/text.mjs +1 -1
  92. package/dist/textarea.cjs +1 -1
  93. package/dist/textarea.mjs +1 -1
  94. package/dist/{theme-toggle-B4VZTDpe.js → theme-toggle-DXQGNfCe.js} +1 -1
  95. package/dist/{theme-toggle-WtPW9UZi.mjs → theme-toggle-tHXIbr8W.mjs} +1 -1
  96. package/dist/theme-toggle.cjs +1 -1
  97. package/dist/theme-toggle.mjs +2 -2
  98. package/dist/toast.cjs +1 -1
  99. package/dist/toast.mjs +35 -35
  100. package/dist/toggle-group.cjs +1 -1
  101. package/dist/toggle-group.mjs +15 -15
  102. package/dist/toggle.cjs +1 -1
  103. package/dist/toggle.mjs +4 -4
  104. package/dist/tooltip.cjs +1 -1
  105. package/dist/tooltip.mjs +3 -3
  106. package/dist/utils-DY6fhrgS.mjs +12 -0
  107. package/dist/utils-cdbZV8DZ.js +1 -0
  108. package/package.json +1 -1
  109. package/src/accordion.tsx +2 -2
  110. package/src/alert-dialog.tsx +6 -6
  111. package/src/avatar.tsx +3 -3
  112. package/src/checkbox.tsx +1 -1
  113. package/src/command.tsx +7 -7
  114. package/src/context-menu.tsx +8 -8
  115. package/src/dialog.tsx +4 -4
  116. package/src/drawer.tsx +3 -3
  117. package/src/dropdown-menu.tsx +8 -8
  118. package/src/hover-card.tsx +1 -1
  119. package/src/index.ts +12 -1
  120. package/src/label.tsx +1 -1
  121. package/src/lib/utils.ts +10 -0
  122. package/src/menubar.tsx +10 -10
  123. package/src/navigation-menu.tsx +6 -6
  124. package/src/popover.tsx +1 -1
  125. package/src/progress.tsx +1 -1
  126. package/src/radio-group.tsx +2 -2
  127. package/src/scroll-area.tsx +2 -2
  128. package/src/scroll-to-top.tsx +134 -0
  129. package/src/select.tsx +7 -7
  130. package/src/separator.tsx +1 -1
  131. package/src/setupTests.ts +1 -1
  132. package/src/sheet.tsx +4 -4
  133. package/src/slider.tsx +1 -1
  134. package/src/support-fab.tsx +190 -0
  135. package/src/switch.tsx +1 -1
  136. package/src/table-of-contents.tsx +285 -0
  137. package/src/tabs.tsx +3 -3
  138. package/src/toast.tsx +6 -6
  139. package/src/toggle-group.tsx +2 -2
  140. package/src/toggle.tsx +1 -1
  141. package/src/tooltip.tsx +2 -2
  142. package/dist/utils-B6yFEsav.mjs +0 -8
  143. package/dist/utils-IjLH3w2e.js +0 -1
package/src/index.ts CHANGED
@@ -335,6 +335,14 @@ export type { ResizableHandleProps, ResizablePanelGroupProps, ResizablePanelProp
335
335
  export { ScrollArea, ScrollBar } from './scroll-area';
336
336
  export type { ScrollAreaProps, ScrollBarProps } from './scroll-area';
337
337
 
338
+ // Scroll To Top
339
+ export { ScrollToTop } from './scroll-to-top';
340
+ export type { ScrollToTopProps } from './scroll-to-top';
341
+
342
+ // Support FAB
343
+ export { SupportFab } from './support-fab';
344
+ export type { SupportFabProps } from './support-fab';
345
+
338
346
  // Search
339
347
  export { Search, SearchTrigger } from './search';
340
348
  export type { SearchProps, SearchTriggerProps } from './search';
@@ -476,4 +484,7 @@ export { useTheme } from './hooks/use-theme';
476
484
  export type { ToasterBaseProps as ToasterProps } from '@gv-tech/ui-core';
477
485
  export { toast, useToast } from './hooks/use-toast';
478
486
  export { Toaster } from './toaster';
479
- // sync
487
+
488
+ // Table Of Contents
489
+ export { TableOfContents } from './table-of-contents';
490
+ export type { TableOfContentsProps } from './table-of-contents';
package/src/label.tsx CHANGED
@@ -15,7 +15,7 @@ const Label = React.forwardRef<
15
15
  >(({ className, ...props }, ref) => (
16
16
  <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
17
17
  ));
18
- Label.displayName = LabelPrimitive.Root.displayName;
18
+ Label.displayName = LabelPrimitive.Root?.displayName || 'Label';
19
19
 
20
20
  export { Label };
21
21
  export type { LabelBaseProps as LabelProps };
package/src/lib/utils.ts CHANGED
@@ -4,3 +4,13 @@ import { twMerge } from 'tailwind-merge';
4
4
  export function cn(...inputs: ClassValue[]) {
5
5
  return twMerge(clsx(inputs));
6
6
  }
7
+
8
+ export function slugify(text: string): string {
9
+ return text
10
+ .toString()
11
+ .toLowerCase()
12
+ .trim()
13
+ .replace(/\s+/g, '-') // Replace spaces with -
14
+ .replace(/[^\w-]+/g, '') // Remove all non-word chars
15
+ .replace(/--+/g, '-'); // Replace multiple - with single -
16
+ }
package/src/menubar.tsx CHANGED
@@ -51,7 +51,7 @@ const Menubar = React.forwardRef<
51
51
  {...props}
52
52
  />
53
53
  ));
54
- Menubar.displayName = MenubarPrimitive.Root.displayName;
54
+ Menubar.displayName = MenubarPrimitive.Root?.displayName || 'Menubar';
55
55
 
56
56
  const MenubarTrigger = React.forwardRef<
57
57
  React.ElementRef<typeof MenubarPrimitive.Trigger>,
@@ -66,7 +66,7 @@ const MenubarTrigger = React.forwardRef<
66
66
  {...props}
67
67
  />
68
68
  ));
69
- MenubarTrigger.displayName = MenubarPrimitive.Trigger.displayName;
69
+ MenubarTrigger.displayName = MenubarPrimitive.Trigger?.displayName || 'MenubarTrigger';
70
70
 
71
71
  const MenubarSubTrigger = React.forwardRef<
72
72
  React.ElementRef<typeof MenubarPrimitive.SubTrigger>,
@@ -85,7 +85,7 @@ const MenubarSubTrigger = React.forwardRef<
85
85
  <ChevronRight className="ml-auto h-4 w-4" />
86
86
  </MenubarPrimitive.SubTrigger>
87
87
  ));
88
- MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger.displayName;
88
+ MenubarSubTrigger.displayName = MenubarPrimitive.SubTrigger?.displayName || 'MenubarSubTrigger';
89
89
 
90
90
  const MenubarSubContent = React.forwardRef<
91
91
  React.ElementRef<typeof MenubarPrimitive.SubContent>,
@@ -100,7 +100,7 @@ const MenubarSubContent = React.forwardRef<
100
100
  {...props}
101
101
  />
102
102
  ));
103
- MenubarSubContent.displayName = MenubarPrimitive.SubContent.displayName;
103
+ MenubarSubContent.displayName = MenubarPrimitive.SubContent?.displayName || 'MenubarSubContent';
104
104
 
105
105
  const MenubarContent = React.forwardRef<
106
106
  React.ElementRef<typeof MenubarPrimitive.Content>,
@@ -120,7 +120,7 @@ const MenubarContent = React.forwardRef<
120
120
  />
121
121
  </MenubarPrimitive.Portal>
122
122
  ));
123
- MenubarContent.displayName = MenubarPrimitive.Content.displayName;
123
+ MenubarContent.displayName = MenubarPrimitive.Content?.displayName || 'MenubarContent';
124
124
 
125
125
  const MenubarItem = React.forwardRef<
126
126
  React.ElementRef<typeof MenubarPrimitive.Item>,
@@ -136,7 +136,7 @@ const MenubarItem = React.forwardRef<
136
136
  {...props}
137
137
  />
138
138
  ));
139
- MenubarItem.displayName = MenubarPrimitive.Item.displayName;
139
+ MenubarItem.displayName = MenubarPrimitive.Item?.displayName || 'MenubarItem';
140
140
 
141
141
  const MenubarCheckboxItem = React.forwardRef<
142
142
  React.ElementRef<typeof MenubarPrimitive.CheckboxItem>,
@@ -159,7 +159,7 @@ const MenubarCheckboxItem = React.forwardRef<
159
159
  {children}
160
160
  </MenubarPrimitive.CheckboxItem>
161
161
  ));
162
- MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem.displayName;
162
+ MenubarCheckboxItem.displayName = MenubarPrimitive.CheckboxItem?.displayName || 'MenubarCheckboxItem';
163
163
 
164
164
  const MenubarRadioItem = React.forwardRef<
165
165
  React.ElementRef<typeof MenubarPrimitive.RadioItem>,
@@ -181,7 +181,7 @@ const MenubarRadioItem = React.forwardRef<
181
181
  {children}
182
182
  </MenubarPrimitive.RadioItem>
183
183
  ));
184
- MenubarRadioItem.displayName = MenubarPrimitive.RadioItem.displayName;
184
+ MenubarRadioItem.displayName = MenubarPrimitive.RadioItem?.displayName || 'MenubarRadioItem';
185
185
 
186
186
  const MenubarLabel = React.forwardRef<
187
187
  React.ElementRef<typeof MenubarPrimitive.Label>,
@@ -193,7 +193,7 @@ const MenubarLabel = React.forwardRef<
193
193
  {...props}
194
194
  />
195
195
  ));
196
- MenubarLabel.displayName = MenubarPrimitive.Label.displayName;
196
+ MenubarLabel.displayName = MenubarPrimitive.Label?.displayName || 'MenubarLabel';
197
197
 
198
198
  const MenubarSeparator = React.forwardRef<
199
199
  React.ElementRef<typeof MenubarPrimitive.Separator>,
@@ -201,7 +201,7 @@ const MenubarSeparator = React.forwardRef<
201
201
  >(({ className, ...props }, ref) => (
202
202
  <MenubarPrimitive.Separator ref={ref} className={cn('bg-muted -mx-1 my-1 h-px', className)} {...props} />
203
203
  ));
204
- MenubarSeparator.displayName = MenubarPrimitive.Separator.displayName;
204
+ MenubarSeparator.displayName = MenubarPrimitive.Separator?.displayName || 'MenubarSeparator';
205
205
 
206
206
  const MenubarShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement> & MenubarShortcutBaseProps) => {
207
207
  return <span className={cn('text-muted-foreground ml-auto text-xs tracking-widest', className)} {...props} />;
@@ -30,7 +30,7 @@ const NavigationMenu = React.forwardRef<
30
30
  <NavigationMenuViewport />
31
31
  </NavigationMenuPrimitive.Root>
32
32
  ));
33
- NavigationMenu.displayName = NavigationMenuPrimitive.Root.displayName;
33
+ NavigationMenu.displayName = NavigationMenuPrimitive.Root?.displayName || 'NavigationMenu';
34
34
 
35
35
  const NavigationMenuList = React.forwardRef<
36
36
  React.ElementRef<typeof NavigationMenuPrimitive.List>,
@@ -42,7 +42,7 @@ const NavigationMenuList = React.forwardRef<
42
42
  {...props}
43
43
  />
44
44
  ));
45
- NavigationMenuList.displayName = NavigationMenuPrimitive.List.displayName;
45
+ NavigationMenuList.displayName = NavigationMenuPrimitive.List?.displayName || 'NavigationMenuList';
46
46
 
47
47
  const NavigationMenuItem = NavigationMenuPrimitive.Item;
48
48
 
@@ -66,7 +66,7 @@ const NavigationMenuTrigger = React.forwardRef<
66
66
  />
67
67
  </NavigationMenuPrimitive.Trigger>
68
68
  ));
69
- NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger.displayName;
69
+ NavigationMenuTrigger.displayName = NavigationMenuPrimitive.Trigger?.displayName || 'NavigationMenuTrigger';
70
70
 
71
71
  const NavigationMenuContent = React.forwardRef<
72
72
  React.ElementRef<typeof NavigationMenuPrimitive.Content>,
@@ -81,7 +81,7 @@ const NavigationMenuContent = React.forwardRef<
81
81
  {...props}
82
82
  />
83
83
  ));
84
- NavigationMenuContent.displayName = NavigationMenuPrimitive.Content.displayName;
84
+ NavigationMenuContent.displayName = NavigationMenuPrimitive.Content?.displayName || 'NavigationMenuContent';
85
85
 
86
86
  const NavigationMenuLink = NavigationMenuPrimitive.Link;
87
87
 
@@ -100,7 +100,7 @@ const NavigationMenuViewport = React.forwardRef<
100
100
  />
101
101
  </div>
102
102
  ));
103
- NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport.displayName;
103
+ NavigationMenuViewport.displayName = NavigationMenuPrimitive.Viewport?.displayName || 'NavigationMenuViewport';
104
104
 
105
105
  const NavigationMenuIndicator = React.forwardRef<
106
106
  React.ElementRef<typeof NavigationMenuPrimitive.Indicator>,
@@ -117,7 +117,7 @@ const NavigationMenuIndicator = React.forwardRef<
117
117
  <div className="bg-border relative top-[60%] h-2 w-2 rotate-45 rounded-tl-sm shadow-md" />
118
118
  </NavigationMenuPrimitive.Indicator>
119
119
  ));
120
- NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator.displayName;
120
+ NavigationMenuIndicator.displayName = NavigationMenuPrimitive.Indicator?.displayName || 'NavigationMenuIndicator';
121
121
 
122
122
  export {
123
123
  NavigationMenu,
package/src/popover.tsx CHANGED
@@ -34,7 +34,7 @@ const PopoverContent = React.forwardRef<
34
34
  />
35
35
  </PopoverPrimitive.Portal>
36
36
  ));
37
- PopoverContent.displayName = PopoverPrimitive.Content.displayName;
37
+ PopoverContent.displayName = PopoverPrimitive.Content?.displayName || 'PopoverContent';
38
38
 
39
39
  export { Popover, PopoverAnchor, PopoverContent, PopoverTrigger };
40
40
  export type {
package/src/progress.tsx CHANGED
@@ -22,7 +22,7 @@ const Progress = React.forwardRef<
22
22
  />
23
23
  </ProgressPrimitive.Root>
24
24
  ));
25
- Progress.displayName = ProgressPrimitive.Root.displayName;
25
+ Progress.displayName = ProgressPrimitive.Root?.displayName || 'Progress';
26
26
 
27
27
  export { Progress };
28
28
  export type { ProgressBaseProps as ProgressProps };
@@ -14,7 +14,7 @@ const RadioGroup = React.forwardRef<React.ElementRef<typeof RadioGroupPrimitive.
14
14
  return <RadioGroupPrimitive.Root className={cn('grid gap-2', className)} {...props} ref={ref} />;
15
15
  },
16
16
  );
17
- RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
17
+ RadioGroup.displayName = RadioGroupPrimitive.Root?.displayName || 'RadioGroup';
18
18
 
19
19
  export interface RadioGroupItemProps
20
20
  extends React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>, RadioGroupItemBaseProps {}
@@ -37,6 +37,6 @@ const RadioGroupItem = React.forwardRef<React.ElementRef<typeof RadioGroupPrimit
37
37
  );
38
38
  },
39
39
  );
40
- RadioGroupItem.displayName = RadioGroupPrimitive.Item.displayName;
40
+ RadioGroupItem.displayName = RadioGroupPrimitive.Item?.displayName || 'RadioGroupItem';
41
41
 
42
42
  export { RadioGroup, RadioGroupItem };
@@ -16,7 +16,7 @@ const ScrollArea = React.forwardRef<
16
16
  <ScrollAreaPrimitive.Corner />
17
17
  </ScrollAreaPrimitive.Root>
18
18
  ));
19
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
19
+ ScrollArea.displayName = ScrollAreaPrimitive.Root?.displayName || 'ScrollArea';
20
20
 
21
21
  const ScrollBar = React.forwardRef<
22
22
  React.ElementRef<typeof ScrollAreaPrimitive.ScrollAreaScrollbar>,
@@ -36,7 +36,7 @@ const ScrollBar = React.forwardRef<
36
36
  <ScrollAreaPrimitive.ScrollAreaThumb className="bg-border relative flex-1 rounded-full" />
37
37
  </ScrollAreaPrimitive.ScrollAreaScrollbar>
38
38
  ));
39
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
39
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar?.displayName || 'ScrollBar';
40
40
 
41
41
  export { ScrollArea, ScrollBar };
42
42
  export type { ScrollAreaBaseProps as ScrollAreaProps, ScrollBarBaseProps as ScrollBarProps };
@@ -0,0 +1,134 @@
1
+ 'use client';
2
+
3
+ import { ScrollToTopBaseProps } from '@gv-tech/ui-core';
4
+ import { ArrowUp } from 'lucide-react';
5
+ import * as React from 'react';
6
+ import { Button } from './button';
7
+ import { cn } from './lib/utils';
8
+
9
+ export interface ScrollToTopProps extends React.ButtonHTMLAttributes<HTMLButtonElement>, ScrollToTopBaseProps {
10
+ /** Optional custom scroll container; defaults to window when undefined. */
11
+ scrollTarget?: Window | HTMLElement | null;
12
+ }
13
+
14
+ type ScrollTarget = Window | HTMLElement | null;
15
+
16
+ const isWindowTarget = (target: Exclude<ScrollTarget, null>): target is Window =>
17
+ typeof (target as Window).scrollY === 'number';
18
+
19
+ const getScrollOffset = (target: Exclude<ScrollTarget, null>) =>
20
+ isWindowTarget(target) ? target.scrollY : target.scrollTop;
21
+
22
+ export function ScrollToTop({
23
+ threshold = 240,
24
+ exitDuration = 450,
25
+ behavior = 'smooth',
26
+ scrollTarget,
27
+ className,
28
+ label = 'Scroll to top',
29
+ onClick,
30
+ tabIndex,
31
+ type,
32
+ ...props
33
+ }: ScrollToTopProps) {
34
+ const [isVisible, setIsVisible] = React.useState(false);
35
+ const [isExiting, setIsExiting] = React.useState(false);
36
+ const timeoutRef = React.useRef<number | null>(null);
37
+
38
+ React.useEffect(() => {
39
+ const target = scrollTarget === undefined ? window : scrollTarget;
40
+
41
+ if (!target) {
42
+ setIsVisible(false);
43
+ return;
44
+ }
45
+
46
+ const updateVisibility = () => {
47
+ const offset = getScrollOffset(target);
48
+
49
+ if (isExiting) {
50
+ // Keep the control dismissed during the return-to-top animation,
51
+ // then release once we are back under the visibility threshold.
52
+ if (offset <= threshold) {
53
+ setIsVisible(false);
54
+ setIsExiting(false);
55
+ }
56
+ return;
57
+ }
58
+
59
+ setIsVisible(offset > threshold);
60
+ };
61
+
62
+ updateVisibility();
63
+ target.addEventListener('scroll', updateVisibility, { passive: true });
64
+
65
+ return () => {
66
+ target.removeEventListener('scroll', updateVisibility);
67
+ };
68
+ }, [isExiting, scrollTarget, threshold]);
69
+
70
+ React.useEffect(() => {
71
+ return () => {
72
+ if (timeoutRef.current !== null) {
73
+ window.clearTimeout(timeoutRef.current);
74
+ }
75
+ };
76
+ }, []);
77
+
78
+ const state = isExiting ? 'exiting' : isVisible ? 'visible' : 'hidden';
79
+
80
+ const handleClick = (event: React.MouseEvent<HTMLButtonElement>) => {
81
+ onClick?.(event);
82
+ if (event.defaultPrevented || isExiting) {
83
+ return;
84
+ }
85
+
86
+ const target = scrollTarget === undefined ? window : scrollTarget;
87
+ if (!target) {
88
+ return;
89
+ }
90
+
91
+ setIsExiting(true);
92
+
93
+ const timeout = Math.max(0, exitDuration);
94
+ timeoutRef.current = window.setTimeout(() => {
95
+ target.scrollTo({ top: 0, behavior });
96
+
97
+ const offset = getScrollOffset(target);
98
+ setIsVisible(false);
99
+
100
+ if (offset <= threshold) {
101
+ setIsExiting(false);
102
+ }
103
+ }, timeout);
104
+ };
105
+
106
+ return (
107
+ <Button
108
+ aria-label={label}
109
+ data-state={state}
110
+ type={type ?? 'button'}
111
+ variant="default"
112
+ size="icon"
113
+ tabIndex={state === 'hidden' ? -1 : tabIndex}
114
+ className={cn(
115
+ 'group border-primary/40 bg-primary text-primary-foreground focus-visible:ring-ring fixed right-6 bottom-6 z-50 inline-flex h-14 w-14 items-center justify-center overflow-hidden rounded-full border shadow-[0_18px_40px_-22px_hsl(var(--primary)/0.9)] transition-all duration-500 ease-out focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none',
116
+ 'before:pointer-events-none before:absolute before:inset-0 before:bg-[radial-gradient(circle_at_35%_30%,rgba(255,255,255,0.45),transparent_55%)] before:opacity-80',
117
+ 'hover:-translate-y-1 hover:scale-105 hover:shadow-[0_24px_48px_-24px_hsl(var(--primary)/0.95)] active:translate-y-0 active:scale-95',
118
+ state === 'visible' && 'translate-y-0 scale-100 opacity-100',
119
+ state === 'hidden' &&
120
+ 'pointer-events-none translate-y-24 scale-75 opacity-0 blur-[1px] motion-safe:animate-none',
121
+ state === 'exiting' &&
122
+ 'pointer-events-none translate-y-28 scale-90 opacity-0 blur-[2px] motion-safe:animate-none',
123
+ className,
124
+ )}
125
+ onClick={handleClick}
126
+ {...props}
127
+ >
128
+ <span className="bg-primary-foreground/20 absolute inset-0 rounded-full opacity-0 transition-opacity duration-500 group-hover:animate-pulse group-hover:opacity-100" />
129
+ <span className="border-primary-foreground/35 absolute inset-0 rounded-full border opacity-0 transition-opacity duration-300 group-hover:animate-ping group-hover:opacity-100" />
130
+ <ArrowUp className="relative z-10 h-5 w-5 drop-shadow-[0_2px_2px_rgba(0,0,0,0.2)]" />
131
+ <span className="sr-only">{label}</span>
132
+ </Button>
133
+ );
134
+ }
package/src/select.tsx CHANGED
@@ -42,7 +42,7 @@ const SelectTrigger = React.forwardRef<
42
42
  </SelectPrimitive.Icon>
43
43
  </SelectPrimitive.Trigger>
44
44
  ));
45
- SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
45
+ SelectTrigger.displayName = SelectPrimitive.Trigger?.displayName || 'SelectTrigger';
46
46
 
47
47
  const SelectScrollUpButton = React.forwardRef<
48
48
  React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
@@ -56,7 +56,7 @@ const SelectScrollUpButton = React.forwardRef<
56
56
  <ChevronUp className="h-4 w-4" />
57
57
  </SelectPrimitive.ScrollUpButton>
58
58
  ));
59
- SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
59
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton?.displayName || 'SelectScrollUpButton';
60
60
 
61
61
  const SelectScrollDownButton = React.forwardRef<
62
62
  React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
@@ -70,7 +70,7 @@ const SelectScrollDownButton = React.forwardRef<
70
70
  <ChevronDown className="h-4 w-4" />
71
71
  </SelectPrimitive.ScrollDownButton>
72
72
  ));
73
- SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
73
+ SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton?.displayName || 'SelectScrollDownButton';
74
74
 
75
75
  const SelectContent = React.forwardRef<
76
76
  React.ElementRef<typeof SelectPrimitive.Content>,
@@ -102,7 +102,7 @@ const SelectContent = React.forwardRef<
102
102
  </SelectPrimitive.Content>
103
103
  </SelectPrimitive.Portal>
104
104
  ));
105
- SelectContent.displayName = SelectPrimitive.Content.displayName;
105
+ SelectContent.displayName = SelectPrimitive.Content?.displayName || 'SelectContent';
106
106
 
107
107
  const SelectLabel = React.forwardRef<
108
108
  React.ElementRef<typeof SelectPrimitive.Label>,
@@ -110,7 +110,7 @@ const SelectLabel = React.forwardRef<
110
110
  >(({ className, ...props }, ref) => (
111
111
  <SelectPrimitive.Label ref={ref} className={cn('px-2 py-1.5 text-sm font-semibold', className)} {...props} />
112
112
  ));
113
- SelectLabel.displayName = SelectPrimitive.Label.displayName;
113
+ SelectLabel.displayName = SelectPrimitive.Label?.displayName || 'SelectLabel';
114
114
 
115
115
  const SelectItem = React.forwardRef<
116
116
  React.ElementRef<typeof SelectPrimitive.Item>,
@@ -132,7 +132,7 @@ const SelectItem = React.forwardRef<
132
132
  <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
133
133
  </SelectPrimitive.Item>
134
134
  ));
135
- SelectItem.displayName = SelectPrimitive.Item.displayName;
135
+ SelectItem.displayName = SelectPrimitive.Item?.displayName || 'SelectItem';
136
136
 
137
137
  const SelectSeparator = React.forwardRef<
138
138
  React.ElementRef<typeof SelectPrimitive.Separator>,
@@ -140,7 +140,7 @@ const SelectSeparator = React.forwardRef<
140
140
  >(({ className, ...props }, ref) => (
141
141
  <SelectPrimitive.Separator ref={ref} className={cn('bg-muted -mx-1 my-1 h-px', className)} {...props} />
142
142
  ));
143
- SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
143
+ SelectSeparator.displayName = SelectPrimitive.Separator?.displayName || 'SelectSeparator';
144
144
 
145
145
  export {
146
146
  Select,
package/src/separator.tsx CHANGED
@@ -18,7 +18,7 @@ const Separator = React.forwardRef<
18
18
  {...props}
19
19
  />
20
20
  ));
21
- Separator.displayName = SeparatorPrimitive.Root.displayName;
21
+ Separator.displayName = SeparatorPrimitive.Root?.displayName || 'Separator';
22
22
 
23
23
  export { Separator };
24
24
  export type { SeparatorBaseProps as SeparatorProps };
package/src/setupTests.ts CHANGED
@@ -1,4 +1,4 @@
1
- /* eslint-disable @typescript-eslint/no-explicit-any */
1
+ /* @typescript-eslint/no-explicit-any */
2
2
  import '@testing-library/jest-dom';
3
3
  import { vi } from 'vitest';
4
4
 
package/src/sheet.tsx CHANGED
@@ -40,7 +40,7 @@ const SheetOverlay = React.forwardRef<
40
40
  ref={ref}
41
41
  />
42
42
  ));
43
- SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
43
+ SheetOverlay.displayName = SheetPrimitive.Overlay?.displayName || 'SheetOverlay';
44
44
 
45
45
  const sheetVariants = cva(
46
46
  'fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=closed]:duration-300 data-[state=open]:duration-500 data-[state=open]:animate-in data-[state=closed]:animate-out',
@@ -81,7 +81,7 @@ const SheetContent = React.forwardRef<React.ElementRef<typeof SheetPrimitive.Con
81
81
  </SheetPortal>
82
82
  ),
83
83
  );
84
- SheetContent.displayName = SheetPrimitive.Content.displayName;
84
+ SheetContent.displayName = SheetPrimitive.Content?.displayName || 'SheetContent';
85
85
 
86
86
  const SheetHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement> & SheetHeaderBaseProps) => (
87
87
  <div className={cn('flex flex-col space-y-2 text-center sm:text-left', className)} {...props} />
@@ -99,7 +99,7 @@ const SheetTitle = React.forwardRef<
99
99
  >(({ className, ...props }, ref) => (
100
100
  <SheetPrimitive.Title ref={ref} className={cn('text-foreground text-lg font-semibold', className)} {...props} />
101
101
  ));
102
- SheetTitle.displayName = SheetPrimitive.Title.displayName;
102
+ SheetTitle.displayName = SheetPrimitive.Title?.displayName || 'SheetTitle';
103
103
 
104
104
  const SheetDescription = React.forwardRef<
105
105
  React.ElementRef<typeof SheetPrimitive.Description>,
@@ -107,7 +107,7 @@ const SheetDescription = React.forwardRef<
107
107
  >(({ className, ...props }, ref) => (
108
108
  <SheetPrimitive.Description ref={ref} className={cn('text-muted-foreground text-sm', className)} {...props} />
109
109
  ));
110
- SheetDescription.displayName = SheetPrimitive.Description.displayName;
110
+ SheetDescription.displayName = SheetPrimitive.Description?.displayName || 'SheetDescription';
111
111
 
112
112
  export {
113
113
  Sheet,
package/src/slider.tsx CHANGED
@@ -21,7 +21,7 @@ const Slider = React.forwardRef<
21
21
  <SliderPrimitive.Thumb className="border-primary/50 bg-background focus-visible:ring-ring block h-4 w-4 rounded-full border shadow transition-colors focus-visible:ring-1 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50" />
22
22
  </SliderPrimitive.Root>
23
23
  ));
24
- Slider.displayName = SliderPrimitive.Root.displayName;
24
+ Slider.displayName = SliderPrimitive.Root?.displayName || 'Slider';
25
25
 
26
26
  export { Slider };
27
27
  export type { SliderBaseProps as SliderProps };