@hexclave/ui 1.0.2 → 1.0.5

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 (86) hide show
  1. package/dist/components/copy-button.d.ts +1 -1
  2. package/dist/components/simple-tooltip.js +2 -2
  3. package/dist/components/simple-tooltip.js.map +1 -1
  4. package/dist/components/ui/badge.d.ts +2 -2
  5. package/dist/components/ui/button.d.ts +2 -2
  6. package/dist/components/ui/form.d.ts +1 -1
  7. package/dist/components/ui/form.d.ts.map +1 -1
  8. package/dist/components/ui/resizable.d.ts +1 -1
  9. package/dist/components/ui/resizable.d.ts.map +1 -1
  10. package/dist/components/ui/typography.d.ts +1 -1
  11. package/dist/esm/components/copy-button.d.ts +1 -1
  12. package/dist/esm/components/simple-tooltip.js +3 -3
  13. package/dist/esm/components/simple-tooltip.js.map +1 -1
  14. package/dist/esm/components/ui/badge.d.ts +2 -2
  15. package/dist/esm/components/ui/button.d.ts +2 -2
  16. package/dist/esm/components/ui/form.d.ts +1 -1
  17. package/dist/esm/components/ui/form.d.ts.map +1 -1
  18. package/dist/esm/components/ui/resizable.d.ts +1 -1
  19. package/dist/esm/components/ui/resizable.d.ts.map +1 -1
  20. package/dist/esm/components/ui/typography.d.ts +1 -1
  21. package/package.json +3 -2
  22. package/src/components/action-dialog.tsx +135 -0
  23. package/src/components/brand-icons.tsx +276 -0
  24. package/src/components/browser-frame/LICENSE +3 -0
  25. package/src/components/browser-frame/index.tsx +51 -0
  26. package/src/components/copy-button.tsx +36 -0
  27. package/src/components/copy-field.tsx +52 -0
  28. package/src/components/data-table/cells.tsx +133 -0
  29. package/src/components/data-table/column-header.tsx +52 -0
  30. package/src/components/data-table/data-table.tsx +318 -0
  31. package/src/components/data-table/faceted-filter.tsx +138 -0
  32. package/src/components/data-table/index.tsx +9 -0
  33. package/src/components/data-table/pagination.tsx +76 -0
  34. package/src/components/data-table/toolbar-items.tsx +13 -0
  35. package/src/components/data-table/toolbar.tsx +100 -0
  36. package/src/components/data-table/utils.tsx +7 -0
  37. package/src/components/data-table/view-options.tsx +64 -0
  38. package/src/components/simple-tooltip.tsx +48 -0
  39. package/src/components/ui/accordion.tsx +58 -0
  40. package/src/components/ui/alert.tsx +60 -0
  41. package/src/components/ui/aspect-ratio.tsx +7 -0
  42. package/src/components/ui/avatar.tsx +51 -0
  43. package/src/components/ui/badge.tsx +36 -0
  44. package/src/components/ui/breadcrumb.tsx +116 -0
  45. package/src/components/ui/button.tsx +95 -0
  46. package/src/components/ui/calendar.tsx +77 -0
  47. package/src/components/ui/card.tsx +88 -0
  48. package/src/components/ui/checkbox.tsx +31 -0
  49. package/src/components/ui/collapsible.tsx +11 -0
  50. package/src/components/ui/command.tsx +159 -0
  51. package/src/components/ui/context-menu.tsx +205 -0
  52. package/src/components/ui/dialog.tsx +135 -0
  53. package/src/components/ui/dropdown-menu.tsx +245 -0
  54. package/src/components/ui/form.tsx +173 -0
  55. package/src/components/ui/hover-card.tsx +30 -0
  56. package/src/components/ui/inline-code.tsx +40 -0
  57. package/src/components/ui/input-otp.tsx +73 -0
  58. package/src/components/ui/input.tsx +68 -0
  59. package/src/components/ui/label.tsx +40 -0
  60. package/src/components/ui/menubar.tsx +241 -0
  61. package/src/components/ui/navigation-menu.tsx +131 -0
  62. package/src/components/ui/password-input.tsx +50 -0
  63. package/src/components/ui/popover.tsx +34 -0
  64. package/src/components/ui/progress.tsx +29 -0
  65. package/src/components/ui/radio-group.tsx +45 -0
  66. package/src/components/ui/resizable.tsx +45 -0
  67. package/src/components/ui/scroll-area.tsx +49 -0
  68. package/src/components/ui/select.tsx +162 -0
  69. package/src/components/ui/separator.tsx +32 -0
  70. package/src/components/ui/sheet.tsx +139 -0
  71. package/src/components/ui/skeleton.tsx +23 -0
  72. package/src/components/ui/slider.tsx +29 -0
  73. package/src/components/ui/spinner.tsx +18 -0
  74. package/src/components/ui/switch.tsx +75 -0
  75. package/src/components/ui/table.tsx +117 -0
  76. package/src/components/ui/tabs.tsx +56 -0
  77. package/src/components/ui/textarea.tsx +24 -0
  78. package/src/components/ui/toast.tsx +135 -0
  79. package/src/components/ui/toaster.tsx +35 -0
  80. package/src/components/ui/toggle-group.tsx +62 -0
  81. package/src/components/ui/toggle.tsx +46 -0
  82. package/src/components/ui/tooltip.tsx +40 -0
  83. package/src/components/ui/typography.tsx +47 -0
  84. package/src/components/ui/use-toast.tsx +195 -0
  85. package/src/index.ts +54 -0
  86. package/src/lib/utils.tsx +6 -0
@@ -0,0 +1,162 @@
1
+ "use client";
2
+
3
+ import {
4
+ CaretSortIcon,
5
+ CheckIcon,
6
+ ChevronDownIcon,
7
+ ChevronUpIcon,
8
+ } from "@radix-ui/react-icons";
9
+ import * as SelectPrimitive from "@radix-ui/react-select";
10
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
11
+ import React from "react";
12
+
13
+ import { cn } from "../../lib/utils";
14
+
15
+ const Select = SelectPrimitive.Root;
16
+
17
+ const SelectGroup = SelectPrimitive.Group;
18
+
19
+ const SelectValue = SelectPrimitive.Value;
20
+
21
+ const SelectTrigger = forwardRefIfNeeded<
22
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
23
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> & { loading?: boolean }
24
+ >(({ className, children, loading, ...props }, ref) => (
25
+ <SelectPrimitive.Trigger
26
+ ref={ref}
27
+ className={cn(
28
+ "backdrop-blur-md bg-white/20 dark:bg-black/20 flex h-9 w-full items-center justify-between whitespace-nowrap rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm ring-offset-background placeholder:text-muted-foreground focus:outline-none focus:ring-1 focus:ring-ring disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
29
+ loading && "cursor-wait",
30
+ className
31
+ )}
32
+ {...props}
33
+ >
34
+ {children}
35
+ <SelectPrimitive.Icon asChild>
36
+ {loading ? (
37
+ <div className="h-4 w-4 animate-spin rounded-full border-2 border-current border-t-transparent opacity-50" />
38
+ ) : (
39
+ <CaretSortIcon className="h-4 w-4 opacity-50" />
40
+ )}
41
+ </SelectPrimitive.Icon>
42
+ </SelectPrimitive.Trigger>
43
+ ));
44
+ SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
45
+
46
+ const SelectScrollUpButton = forwardRefIfNeeded<
47
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
48
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
49
+ >(({ className, ...props }, ref) => (
50
+ <SelectPrimitive.ScrollUpButton
51
+ ref={ref}
52
+ className={cn(
53
+ "flex cursor-default items-center justify-center py-1",
54
+ className
55
+ )}
56
+ {...props}
57
+ >
58
+ <ChevronUpIcon />
59
+ </SelectPrimitive.ScrollUpButton>
60
+ ));
61
+ SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
62
+
63
+ const SelectScrollDownButton = forwardRefIfNeeded<
64
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
65
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
66
+ >(({ className, ...props }, ref) => (
67
+ <SelectPrimitive.ScrollDownButton
68
+ ref={ref}
69
+ className={cn(
70
+ "flex cursor-default items-center justify-center py-1",
71
+ className
72
+ )}
73
+ {...props}
74
+ >
75
+ <ChevronDownIcon />
76
+ </SelectPrimitive.ScrollDownButton>
77
+ ));
78
+ SelectScrollDownButton.displayName =
79
+ SelectPrimitive.ScrollDownButton.displayName;
80
+
81
+ const SelectContent = forwardRefIfNeeded<
82
+ React.ElementRef<typeof SelectPrimitive.Content>,
83
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
84
+ >(({ className, children, position = "popper", ...props }, ref) => (
85
+ <SelectPrimitive.Portal>
86
+ <SelectPrimitive.Content
87
+ ref={ref}
88
+ className={cn(
89
+ "stack-scope relative z-50 max-h-96 min-w-[8rem] overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
90
+ position === "popper" &&
91
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
92
+ className
93
+ )}
94
+ position={position}
95
+ {...props}
96
+ >
97
+ <SelectScrollUpButton />
98
+ <SelectPrimitive.Viewport
99
+ className={cn(
100
+ "p-1",
101
+ position === "popper" &&
102
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
103
+ )}
104
+ >
105
+ {children}
106
+ </SelectPrimitive.Viewport>
107
+ <SelectScrollDownButton />
108
+ </SelectPrimitive.Content>
109
+ </SelectPrimitive.Portal>
110
+ ));
111
+ SelectContent.displayName = SelectPrimitive.Content.displayName;
112
+
113
+ const SelectLabel = forwardRefIfNeeded<
114
+ React.ElementRef<typeof SelectPrimitive.Label>,
115
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
116
+ >(({ className, ...props }, ref) => (
117
+ <SelectPrimitive.Label
118
+ ref={ref}
119
+ className={cn("px-2 py-1.5 text-sm font-semibold", className)}
120
+ {...props}
121
+ />
122
+ ));
123
+ SelectLabel.displayName = SelectPrimitive.Label.displayName;
124
+
125
+ const SelectItem = forwardRefIfNeeded<
126
+ React.ElementRef<typeof SelectPrimitive.Item>,
127
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
128
+ >(({ className, children, ...props }, ref) => (
129
+ <SelectPrimitive.Item
130
+ ref={ref}
131
+ className={cn(
132
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
133
+ className
134
+ )}
135
+ {...props}
136
+ >
137
+ <span className="absolute right-2 flex h-3.5 w-3.5 items-center justify-center">
138
+ <SelectPrimitive.ItemIndicator>
139
+ <CheckIcon className="h-4 w-4" />
140
+ </SelectPrimitive.ItemIndicator>
141
+ </span>
142
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
143
+ </SelectPrimitive.Item>
144
+ ));
145
+ SelectItem.displayName = SelectPrimitive.Item.displayName;
146
+
147
+ const SelectSeparator = forwardRefIfNeeded<
148
+ React.ElementRef<typeof SelectPrimitive.Separator>,
149
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
150
+ >(({ className, ...props }, ref) => (
151
+ <SelectPrimitive.Separator
152
+ ref={ref}
153
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
154
+ {...props}
155
+ />
156
+ ));
157
+ SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
158
+
159
+ export {
160
+ Select, SelectContent, SelectGroup, SelectItem, SelectLabel, SelectScrollDownButton, SelectScrollUpButton, SelectSeparator, SelectTrigger, SelectValue
161
+ };
162
+
@@ -0,0 +1,32 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
5
+ import * as SeparatorPrimitive from "@radix-ui/react-separator";
6
+
7
+ import { cn } from "../../lib/utils";
8
+
9
+ const Separator = forwardRefIfNeeded<
10
+ React.ElementRef<typeof SeparatorPrimitive.Root>,
11
+ React.ComponentPropsWithoutRef<typeof SeparatorPrimitive.Root>
12
+ >(
13
+ (
14
+ { className, orientation = "horizontal", decorative = true, ...props },
15
+ ref
16
+ ) => (
17
+ <SeparatorPrimitive.Root
18
+ ref={ref}
19
+ decorative={decorative}
20
+ orientation={orientation}
21
+ className={cn(
22
+ "stack-scope shrink-0 bg-border",
23
+ orientation === "horizontal" ? "h-[1px] w-full" : "h-full w-[1px]",
24
+ className
25
+ )}
26
+ {...props}
27
+ />
28
+ )
29
+ );
30
+ Separator.displayName = SeparatorPrimitive.Root.displayName;
31
+
32
+ export { Separator };
@@ -0,0 +1,139 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
5
+ import * as SheetPrimitive from "@radix-ui/react-dialog";
6
+ import { Cross2Icon } from "@radix-ui/react-icons";
7
+ import { cva, type VariantProps } from "class-variance-authority";
8
+
9
+ import { cn } from "../../lib/utils";
10
+
11
+ const Sheet = SheetPrimitive.Root;
12
+
13
+ const SheetTrigger = SheetPrimitive.Trigger;
14
+
15
+ const SheetClose = SheetPrimitive.Close;
16
+
17
+ const SheetPortal = SheetPrimitive.Portal;
18
+
19
+ const SheetOverlay = forwardRefIfNeeded<
20
+ React.ElementRef<typeof SheetPrimitive.Overlay>,
21
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Overlay>
22
+ >(({ className, ...props }, ref) => (
23
+ <SheetPrimitive.Overlay
24
+ className={cn(
25
+ "fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
26
+ className
27
+ )}
28
+ {...props}
29
+ ref={ref}
30
+ />
31
+ ));
32
+ SheetOverlay.displayName = SheetPrimitive.Overlay.displayName;
33
+
34
+ const sheetVariants = cva(
35
+ "stack-scope fixed z-50 gap-4 bg-background p-6 shadow-lg transition ease-in-out data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:duration-100 data-[state=open]:duration-100",
36
+ {
37
+ variants: {
38
+ side: {
39
+ top: "inset-x-0 top-0 border-b data-[state=closed]:slide-out-to-top data-[state=open]:slide-in-from-top",
40
+ bottom:
41
+ "inset-x-0 bottom-0 border-t data-[state=closed]:slide-out-to-bottom data-[state=open]:slide-in-from-bottom",
42
+ left: "inset-y-0 left-0 h-full w-3/4 border-r data-[state=closed]:slide-out-to-left data-[state=open]:slide-in-from-left sm:max-w-sm",
43
+ right:
44
+ "inset-y-0 right-0 h-full w-3/4 border-l data-[state=closed]:slide-out-to-right data-[state=open]:slide-in-from-right sm:max-w-sm",
45
+ },
46
+ },
47
+ defaultVariants: {
48
+ side: "right",
49
+ },
50
+ }
51
+ );
52
+
53
+ type SheetContentProps = { hasCloseButton?: boolean } & React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content> & VariantProps<typeof sheetVariants>
54
+
55
+ const SheetContent = forwardRefIfNeeded<
56
+ React.ElementRef<typeof SheetPrimitive.Content>,
57
+ SheetContentProps
58
+ >(({ side = "right", hasCloseButton = true, className, children, ...props }, ref) => (
59
+ <SheetPortal>
60
+ <SheetOverlay />
61
+ <SheetPrimitive.Content
62
+ ref={ref}
63
+ className={cn(sheetVariants({ side }), className)}
64
+ {...props}
65
+ >
66
+ {children}
67
+ {hasCloseButton ? <SheetPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-secondary">
68
+ <Cross2Icon className="h-4 w-4" />
69
+ <span className="sr-only">Close</span>
70
+ </SheetPrimitive.Close> : null}
71
+ </SheetPrimitive.Content>
72
+ </SheetPortal>
73
+ ));
74
+ SheetContent.displayName = SheetPrimitive.Content.displayName;
75
+
76
+ const SheetHeader = ({
77
+ className,
78
+ ...props
79
+ }: React.HTMLAttributes<HTMLDivElement>) => (
80
+ <div
81
+ className={cn(
82
+ "flex flex-col space-y-2 text-center sm:text-left",
83
+ className
84
+ )}
85
+ {...props}
86
+ />
87
+ );
88
+ SheetHeader.displayName = "SheetHeader";
89
+
90
+ const SheetFooter = ({
91
+ className,
92
+ ...props
93
+ }: React.HTMLAttributes<HTMLDivElement>) => (
94
+ <div
95
+ className={cn(
96
+ "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
97
+ className
98
+ )}
99
+ {...props}
100
+ />
101
+ );
102
+ SheetFooter.displayName = "SheetFooter";
103
+
104
+ const SheetTitle = forwardRefIfNeeded<
105
+ React.ElementRef<typeof SheetPrimitive.Title>,
106
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Title>
107
+ >(({ className, ...props }, ref) => (
108
+ <SheetPrimitive.Title
109
+ ref={ref}
110
+ className={cn("text-lg font-semibold text-foreground", className)}
111
+ {...props}
112
+ />
113
+ ));
114
+ SheetTitle.displayName = SheetPrimitive.Title.displayName;
115
+
116
+ const SheetDescription = forwardRefIfNeeded<
117
+ React.ElementRef<typeof SheetPrimitive.Description>,
118
+ React.ComponentPropsWithoutRef<typeof SheetPrimitive.Description>
119
+ >(({ className, ...props }, ref) => (
120
+ <SheetPrimitive.Description
121
+ ref={ref}
122
+ className={cn("text-sm text-muted-foreground", className)}
123
+ {...props}
124
+ />
125
+ ));
126
+ SheetDescription.displayName = SheetPrimitive.Description.displayName;
127
+
128
+ export {
129
+ Sheet,
130
+ SheetPortal,
131
+ SheetOverlay,
132
+ SheetTrigger,
133
+ SheetClose,
134
+ SheetContent,
135
+ SheetHeader,
136
+ SheetFooter,
137
+ SheetTitle,
138
+ SheetDescription,
139
+ };
@@ -0,0 +1,23 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { cn } from "../../lib/utils";
5
+
6
+ function Skeleton({
7
+ className,
8
+ children,
9
+ ...props
10
+ }: React.HTMLAttributes<HTMLDivElement>) {
11
+ return (
12
+ <div
13
+ className={cn("stack-scope animate-pulse rounded-md bg-primary/10", className)}
14
+ {...props}
15
+ >
16
+ <div className="invisible inline">
17
+ {children}
18
+ </div>
19
+ </div>
20
+ );
21
+ }
22
+
23
+ export { Skeleton };
@@ -0,0 +1,29 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
5
+ import * as SliderPrimitive from "@radix-ui/react-slider";
6
+
7
+ import { cn } from "../../lib/utils";
8
+
9
+ const Slider = forwardRefIfNeeded<
10
+ React.ElementRef<typeof SliderPrimitive.Root>,
11
+ React.ComponentPropsWithoutRef<typeof SliderPrimitive.Root>
12
+ >(({ className, ...props }, ref) => (
13
+ <SliderPrimitive.Root
14
+ ref={ref}
15
+ className={cn(
16
+ "stack-scope relative flex w-full touch-none select-none items-center",
17
+ className
18
+ )}
19
+ {...props}
20
+ >
21
+ <SliderPrimitive.Track className="relative h-1.5 w-full grow overflow-hidden rounded-full bg-primary/20">
22
+ <SliderPrimitive.Range className="absolute h-full bg-primary" />
23
+ </SliderPrimitive.Track>
24
+ <SliderPrimitive.Thumb className="block h-4 w-4 rounded-full border border-primary/50 bg-background shadow focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50" />
25
+ </SliderPrimitive.Root>
26
+ ));
27
+ Slider.displayName = SliderPrimitive.Root.displayName;
28
+
29
+ export { Slider };
@@ -0,0 +1,18 @@
1
+ import { ReloadIcon } from "@radix-ui/react-icons";
2
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
3
+ import React from "react";
4
+ import { cn } from "../../lib/utils";
5
+
6
+ export const Spinner = forwardRefIfNeeded<
7
+ HTMLSpanElement,
8
+ React.ComponentPropsWithoutRef<'span'> & {
9
+ size?: number,
10
+ }
11
+ >(({ size = 15, ...props }, ref) => {
12
+ return (
13
+ <span ref={ref} {...props} className={cn("stack-scope", props.className)}>
14
+ <ReloadIcon className="animate-spin" width={size} height={size} />
15
+ </span>
16
+ );
17
+ });
18
+ Spinner.displayName = "Spinner";
@@ -0,0 +1,75 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
5
+ import * as SwitchPrimitives from "@radix-ui/react-switch";
6
+
7
+ import { cn } from "../../lib/utils";
8
+ import { runAsynchronouslyWithAlert } from "@hexclave/shared/dist/utils/promises";
9
+ import { useAsyncCallback } from "@hexclave/shared/dist/hooks/use-async-callback";
10
+ import { Spinner } from "./spinner";
11
+
12
+ type OriginalSwitchProps = {} & React.ComponentProps<typeof SwitchPrimitives.Root>
13
+
14
+ const OriginalSwitch = forwardRefIfNeeded<
15
+ React.ElementRef<typeof SwitchPrimitives.Root>,
16
+ OriginalSwitchProps
17
+ >(({ className, ...props }, ref) => (
18
+ <SwitchPrimitives.Root
19
+ className={cn(
20
+ "stack-scope peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
21
+ className
22
+ )}
23
+ {...props}
24
+ ref={ref}
25
+ >
26
+ <SwitchPrimitives.Thumb
27
+ className={cn(
28
+ "pointer-events-none block h-4 w-4 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0"
29
+ )}
30
+ />
31
+ </SwitchPrimitives.Root>
32
+ ));
33
+ OriginalSwitch.displayName = SwitchPrimitives.Root.displayName;
34
+ type AsyncSwitchProps = {
35
+ onCheckedChange?: (checked: boolean) => Promise<void> | void,
36
+ onClick?: (e: React.MouseEvent<HTMLButtonElement>) => Promise<void> | void,
37
+ loading?: boolean,
38
+ } & OriginalSwitchProps
39
+
40
+ const Switch = forwardRefIfNeeded<
41
+ React.ElementRef<typeof SwitchPrimitives.Root>,
42
+ AsyncSwitchProps
43
+ >(({ loading: loadingProp, onClick, onCheckedChange, ...props }, ref) => {
44
+ const [handleClick, isLoadingClick] = useAsyncCallback(async (e: React.MouseEvent<HTMLButtonElement>) => {
45
+ await onClick?.(e);
46
+ }, [onClick]);
47
+
48
+ const [handleCheckedChange, isLoadingCheckedChange] = useAsyncCallback(async (checked: boolean) => {
49
+ await onCheckedChange?.(checked);
50
+ }, [onCheckedChange]);
51
+
52
+ const loading = loadingProp || isLoadingClick || isLoadingCheckedChange;
53
+
54
+ return (
55
+ <span className="relative leading-[0]">
56
+ <OriginalSwitch
57
+ {...props}
58
+ ref={ref}
59
+ onClick={(e) => runAsynchronouslyWithAlert(handleClick(e))}
60
+ onCheckedChange={(checked) => runAsynchronouslyWithAlert(handleCheckedChange(checked))}
61
+ disabled={props.disabled || loading}
62
+ style={{
63
+ visibility: loading ? "hidden" : "visible",
64
+ ...props.style,
65
+ }}
66
+ />
67
+ <span className={cn("absolute inset-0 flex items-center justify-center", !loading && "hidden")}>
68
+ <Spinner />
69
+ </span>
70
+ </span>
71
+ );
72
+ });
73
+ Switch.displayName = "Switch";
74
+
75
+ export { Switch };
@@ -0,0 +1,117 @@
1
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
2
+ import React from "react";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ const Table = forwardRefIfNeeded<
7
+ HTMLTableElement,
8
+ React.HTMLAttributes<HTMLTableElement>
9
+ >(({ className, ...props }, ref) => (
10
+ <div className="relative w-full overflow-auto">
11
+ <table
12
+ ref={ref}
13
+ className={cn("stack-scope w-full caption-bottom text-sm", className)}
14
+ {...props}
15
+ />
16
+ </div>
17
+ ));
18
+ Table.displayName = "Table";
19
+
20
+ const TableHeader = forwardRefIfNeeded<
21
+ HTMLTableSectionElement,
22
+ React.HTMLAttributes<HTMLTableSectionElement>
23
+ >(({ className, ...props }, ref) => (
24
+ <thead ref={ref} className={cn("[&_tr]:border-b", className)} {...props} />
25
+ ));
26
+ TableHeader.displayName = "TableHeader";
27
+
28
+ const TableBody = forwardRefIfNeeded<
29
+ HTMLTableSectionElement,
30
+ React.HTMLAttributes<HTMLTableSectionElement>
31
+ >(({ className, ...props }, ref) => (
32
+ <tbody
33
+ ref={ref}
34
+ className={cn("[&_tr:last-child]:border-0", className)}
35
+ {...props}
36
+ />
37
+ ));
38
+ TableBody.displayName = "TableBody";
39
+
40
+ const TableFooter = forwardRefIfNeeded<
41
+ HTMLTableSectionElement,
42
+ React.HTMLAttributes<HTMLTableSectionElement>
43
+ >(({ className, ...props }, ref) => (
44
+ <tfoot
45
+ ref={ref}
46
+ className={cn(
47
+ "border-t bg-muted/50 font-medium [&>tr]:last:border-b-0",
48
+ className
49
+ )}
50
+ {...props}
51
+ />
52
+ ));
53
+ TableFooter.displayName = "TableFooter";
54
+
55
+ const TableRow = forwardRefIfNeeded<
56
+ HTMLTableRowElement,
57
+ React.HTMLAttributes<HTMLTableRowElement>
58
+ >(({ className, ...props }, ref) => (
59
+ <tr
60
+ ref={ref}
61
+ className={cn(
62
+ "border-b data-[state=selected]:bg-muted",
63
+ props.onClick ? "hover:bg-muted/50 cursor-pointer" : "",
64
+ className
65
+ )}
66
+ {...props}
67
+ />
68
+ ));
69
+ TableRow.displayName = "TableRow";
70
+
71
+ const TableHead = forwardRefIfNeeded<
72
+ HTMLTableCellElement,
73
+ React.ThHTMLAttributes<HTMLTableCellElement>
74
+ >(({ className, ...props }, ref) => (
75
+ <th
76
+ ref={ref}
77
+ className={cn(
78
+ "h-10 px-2 text-left align-middle font-medium text-muted-foreground [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
79
+ className
80
+ )}
81
+ {...props}
82
+ />
83
+ ));
84
+ TableHead.displayName = "TableHead";
85
+
86
+ const TableCell = forwardRefIfNeeded<
87
+ HTMLTableCellElement,
88
+ React.TdHTMLAttributes<HTMLTableCellElement>
89
+ >(({ className, ...props }, ref) => (
90
+ <td
91
+ ref={ref}
92
+ className={cn(
93
+ "p-2 align-middle [&:has([role=checkbox])]:pr-0 [&>[role=checkbox]]:translate-y-[2px]",
94
+ className
95
+ )}
96
+ {...props}
97
+ />
98
+ ));
99
+ TableCell.displayName = "TableCell";
100
+
101
+ const TableCaption = forwardRefIfNeeded<
102
+ HTMLTableCaptionElement,
103
+ React.HTMLAttributes<HTMLTableCaptionElement>
104
+ >(({ className, ...props }, ref) => (
105
+ <caption
106
+ ref={ref}
107
+ className={cn("mt-4 text-sm text-muted-foreground", className)}
108
+ {...props}
109
+ />
110
+ ));
111
+ TableCaption.displayName = "TableCaption";
112
+
113
+ export {
114
+ Table, TableBody, TableCaption, TableCell, TableFooter,
115
+ TableHead, TableHeader, TableRow
116
+ };
117
+
@@ -0,0 +1,56 @@
1
+ "use client";
2
+
3
+ import React from "react";
4
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
5
+ import * as TabsPrimitive from "@radix-ui/react-tabs";
6
+
7
+ import { cn } from "../../lib/utils";
8
+
9
+ const Tabs = TabsPrimitive.Root;
10
+
11
+ const TabsList = forwardRefIfNeeded<
12
+ React.ElementRef<typeof TabsPrimitive.List>,
13
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.List>
14
+ >(({ className, ...props }, ref) => (
15
+ <TabsPrimitive.List
16
+ ref={ref}
17
+ className={cn(
18
+ "stack-scope inline-flex h-9 items-center justify-center rounded-lg bg-muted p-1 text-muted-foreground",
19
+ className
20
+ )}
21
+ {...props}
22
+ />
23
+ ));
24
+ TabsList.displayName = TabsPrimitive.List.displayName;
25
+
26
+ const TabsTrigger = forwardRefIfNeeded<
27
+ React.ElementRef<typeof TabsPrimitive.Trigger>,
28
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Trigger>
29
+ >(({ className, ...props }, ref) => (
30
+ <TabsPrimitive.Trigger
31
+ ref={ref}
32
+ className={cn(
33
+ "inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium ring-offset-background transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50 data-[state=active]:bg-background data-[state=active]:text-foreground data-[state=active]:shadow-sm",
34
+ className
35
+ )}
36
+ {...props}
37
+ />
38
+ ));
39
+ TabsTrigger.displayName = TabsPrimitive.Trigger.displayName;
40
+
41
+ const TabsContent = forwardRefIfNeeded<
42
+ React.ElementRef<typeof TabsPrimitive.Content>,
43
+ React.ComponentPropsWithoutRef<typeof TabsPrimitive.Content>
44
+ >(({ className, ...props }, ref) => (
45
+ <TabsPrimitive.Content
46
+ ref={ref}
47
+ className={cn(
48
+ "mt-2 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2",
49
+ className
50
+ )}
51
+ {...props}
52
+ />
53
+ ));
54
+ TabsContent.displayName = TabsPrimitive.Content.displayName;
55
+
56
+ export { Tabs, TabsList, TabsTrigger, TabsContent };
@@ -0,0 +1,24 @@
1
+ import { forwardRefIfNeeded } from "@hexclave/shared/dist/utils/react";
2
+ import React from "react";
3
+
4
+ import { cn } from "../../lib/utils";
5
+
6
+ export type TextareaProps = {} & React.TextareaHTMLAttributes<HTMLTextAreaElement>
7
+
8
+ const Textarea = forwardRefIfNeeded<HTMLTextAreaElement, TextareaProps>(
9
+ ({ className, ...props }, ref) => {
10
+ return (
11
+ <textarea
12
+ className={cn(
13
+ "stack-scope flex min-h-[60px] w-full rounded-md border border-input bg-transparent px-3 py-2 text-sm shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:cursor-not-allowed disabled:opacity-50",
14
+ className
15
+ )}
16
+ ref={ref}
17
+ {...props}
18
+ />
19
+ );
20
+ }
21
+ );
22
+ Textarea.displayName = "Textarea";
23
+
24
+ export { Textarea };