@tapcart/mobile-components 0.1.2 → 0.1.4

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/README.md ADDED
@@ -0,0 +1,241 @@
1
+ <div align="center">
2
+ <a href="https://tapcart.com">
3
+ <img
4
+ src="https://storage.googleapis.com/tapcart-asset-uploads-prod/dx-github.png"
5
+ alt=""
6
+ />
7
+ </a>
8
+ </div>
9
+
10
+ # @tapcart/mobile-components
11
+
12
+ > Build the next-gen shopper experience for Tapcart's core product, the mobile app.
13
+
14
+ [![storybook](https://shields.io/badge/storybook-grey?logo=storybook&style=flat)](https://tapcart-consumer-web-storybook.vercel.app/) [![npm version](https://img.shields.io/npm/v/@tapcart/mobile-components.svg?label=@tapcart/mobile-components)](https://www.npmjs.com/package/@tapcart/mobile-components)
15
+
16
+ | Status | Owner | Help |
17
+ | ------ | ---------------- |-----------------|
18
+ | Active | @tapcart/mobile-components | dev@tapcart.com |
19
+
20
+ ## About this repo
21
+
22
+ The tapcart/mobile-components repository is a component library made up of all the code components that drive our app experience.
23
+
24
+ ## Installation using NPM
25
+
26
+ ### Install into your React.js project
27
+
28
+ ```sh
29
+ npm install @tapcart/mobile-components
30
+ ```
31
+
32
+
33
+
34
+
35
+ ## Usage
36
+ **Easy. Cake. Done.**
37
+
38
+ ```jsx
39
+ import {
40
+ Button,
41
+ Input,
42
+ Accordion,
43
+ AccordionContent,
44
+ AccordionItem,
45
+ AccordionTrigger,
46
+ AspectRatio,
47
+ Switch,
48
+ Label,
49
+ Separator,
50
+ Badge,
51
+ Video,
52
+ ScrollArea,
53
+ Text,
54
+ Toast,
55
+ Toaster,
56
+ useToast,
57
+ Icon,
58
+ Container,
59
+ Grid,
60
+ ToggleGroup,
61
+ ToggleGroupItem,
62
+ } from "@tapcart/mobile-components";
63
+
64
+ <Video>
65
+ <source src="https://assets.tapcart.com/image-block/video/FhEjfK4zD2_6614803b487c620032dc21c4.mp4" />
66
+ </Video>
67
+
68
+ <Separator />
69
+
70
+ <Container variant="spaced">
71
+ <Input placeholder="Search for products" type="email"></Input>
72
+ </Container>
73
+
74
+ <Separator />
75
+
76
+ <Accordion type="single" collapsible className="w-full">
77
+ <AccordionItem value="item-1">
78
+ <Container>
79
+ <AccordionTrigger>
80
+ <div className="flex">
81
+ <Icon>
82
+ <svg
83
+ width="15"
84
+ height="18"
85
+ viewBox="0 0 15 18"
86
+ fill="none"
87
+ xmlns="http://www.w3.org/2000/svg"
88
+ >
89
+ <path
90
+ d="M7.3 8.14a4.08 4.08 0 0 1-4.07-4.07C3.23 1.83 5.05 0 7.3 0s4.07 1.83 4.07 4.07A4.08 4.08 0 0 1 7.3 8.14Zm0-6.64a2.57 2.57 0 1 0 0 5.14 2.57 2.57 0 1 0 0-5.14ZM12.88 17.69H1.72c-.95 0-1.72-.77-1.72-1.72 0-3.54 2.88-6.42 6.42-6.42h1.76c3.54 0 6.42 2.88 6.42 6.42 0 .95-.77 1.72-1.72 1.72Zm-6.46-6.64a4.93 4.93 0 0 0-4.92 4.92c0 .12.1.22.22.22h11.16c.12 0 .22-.1.22-.22a4.93 4.93 0 0 0-4.92-4.92H6.42Z"
91
+ fill="currentColor"
92
+ ></path>
93
+ </svg>
94
+ </Icon>
95
+ Product details
96
+ </div>
97
+ </AccordionTrigger>
98
+ <AccordionContent>
99
+ <img src="https://assets.tapcart.com/pdp/images/FhEjfK4zD2_6629470724b8221a7b750a97.png" />
100
+ </AccordionContent>
101
+ </Container>
102
+ </AccordionItem>
103
+ <AccordionItem value="item-2">
104
+ <Container>
105
+ <AccordionTrigger>
106
+ <div className="flex">
107
+ <Icon>
108
+ <svg
109
+ width="18"
110
+ height="17"
111
+ viewBox="0 0 18 17"
112
+ fill="none"
113
+ xmlns="http://www.w3.org/2000/svg"
114
+ >
115
+ <path
116
+ d="M6.61 13.22c-1.77 0-3.43-.69-4.67-1.94A6.567 6.567 0 0 1 0 6.61c0-1.76.69-3.43 1.94-4.67A6.533 6.533 0 0 1 6.61 0c1.77 0 3.43.69 4.67 1.94a6.567 6.567 0 0 1 1.94 4.67c0 1.76-.69 3.43-1.94 4.67a6.567 6.567 0 0 1-4.67 1.94Zm0-11.72C5.24 1.5 3.96 2.03 3 3c-.97.97-1.5 2.25-1.5 3.61 0 1.36.53 2.65 1.5 3.61.96.97 2.25 1.5 3.61 1.5 1.36 0 2.65-.53 3.61-1.5.97-.97 1.5-2.25 1.5-3.61 0-1.36-.53-2.65-1.5-3.61-.96-.97-2.25-1.5-3.61-1.5ZM16.4 16.15c-.19 0-.38-.07-.53-.22l-3.18-3.18a.754.754 0 0 1 0-1.06c.29-.29.77-.29 1.06 0l3.18 3.18c.29.29.29.77 0 1.06-.15.15-.34.22-.53.22Z"
117
+ fill="currentColor"
118
+ ></path>
119
+ </svg>
120
+ </Icon>
121
+ Size Guide
122
+ </div>
123
+ </AccordionTrigger>
124
+ <AccordionContent>
125
+ Yes. It comes with default styles that matches the other
126
+ components&apos; aesthetic.
127
+ </AccordionContent>
128
+ </Container>
129
+ </AccordionItem>
130
+ </Accordion>
131
+
132
+ {/*Aspect Ratio+ scroll area Example*/}
133
+ <Container>
134
+ <Text className="py-2 font-medium">New Drop Collection</Text>
135
+ </Container>
136
+
137
+ <ScrollArea>
138
+ {Products.map((product) => (
139
+ <ProductCard
140
+ className="w-[138px] mr-[7px]"
141
+ key={product.id}
142
+ product={product}
143
+ quickAdd={quickAdd}
144
+ openProduct={clickProduct}
145
+ switchVariant={switchVariant}
146
+ carousel={false}
147
+ ></ProductCard>
148
+ ))}
149
+ </ScrollArea>
150
+
151
+ <Separator className="my-[15px]" />
152
+
153
+ <div className="container flex items-center space-x-2">
154
+ <ToggleGroup
155
+ onValueChange={(e) => changeGrid(e)}
156
+ type="single"
157
+ defaultValue="2">
158
+ <ToggleGroupItem value="1" aria-label="Toggle bold">
159
+ <Icon>
160
+ <svg
161
+ xmlns="http://www.w3.org/2000/svg"
162
+ width="24"
163
+ height="24"
164
+ viewBox="0 0 24 24"
165
+ fill="none"
166
+ stroke="currentColor"
167
+ stroke-width="2"
168
+ stroke-linecap="round"
169
+ stroke-linejoin="round"
170
+ className="lucide lucide-rows-2">
171
+ <rect width="18" height="18" x="3" y="3" rx="2" />
172
+ <path d="M3 12h18" />
173
+ </svg>
174
+ </Icon>
175
+ </ToggleGroupItem>
176
+ <ToggleGroupItem value="2" aria-label="Toggle italic">
177
+ <Icon>
178
+ <svg
179
+ xmlns="http://www.w3.org/2000/svg"
180
+ width="24"
181
+ height="24"
182
+ viewBox="0 0 24 24"
183
+ fill="none"
184
+ stroke="currentColor"
185
+ stroke-width="2"
186
+ stroke-linecap="round"
187
+ stroke-linejoin="round"
188
+ className="lucide lucide-columns-3"
189
+ >
190
+ <rect width="18" height="18" x="3" y="3" rx="2" />
191
+ <path d="M9 3v18" />
192
+ <path d="M15 3v18" />
193
+ </svg>
194
+ </Icon>
195
+ </ToggleGroupItem>
196
+ <ToggleGroupItem value="3" aria-label="Toggle underline">
197
+ <Icon>
198
+ <svg
199
+ xmlns="http://www.w3.org/2000/svg"
200
+ width="24"
201
+ height="24"
202
+ viewBox="0 0 24 24"
203
+ fill="none"
204
+ stroke="currentColor"
205
+ stroke-width="2"
206
+ stroke-linecap="round"
207
+ stroke-linejoin="round"
208
+ className="lucide lucide-columns-3">
209
+ <rect width="18" height="18" x="3" y="3" rx="2" />
210
+ <path d="M9 3v18" />
211
+ <path d="M15 3v18" />
212
+ </svg>
213
+ </Icon>
214
+ </ToggleGroupItem>
215
+ </ToggleGroup>
216
+ </div>
217
+
218
+ <Separator className="my-[15px]" />
219
+
220
+ <Grid columns={grid} className="">
221
+ {Products.map((product) => (
222
+ <ProductCard
223
+ key={product.id}
224
+ className="w-full"
225
+ product={product}
226
+ quickAdd={quickAdd}
227
+ openProduct={clickProduct}
228
+ switchVariant={switchVariant}
229
+ carousel={true}
230
+ ></ProductCard>
231
+ ))}
232
+ </Grid>
233
+
234
+ ```
235
+
236
+
237
+ ## Licenses
238
+
239
+ Source code is under a [custom license](https://github.com/Shopify/polaris/blob/main/LICENSE.md) based on MIT. The license restricts Polaris usage to applications that integrate or interoperate with Shopify software or services, with additional restrictions for external, stand-alone applications.
240
+
241
+ All icons and images are licensed under the [Polaris Design Guidelines License Agreement](https://polaris.shopify.com/legal/license)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tapcart/mobile-components",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "main": "dist/index.js",
5
5
  "module": "dist/index.esm.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,4 +0,0 @@
1
-
2
- > @tapcart/mobile-components@0.1.1 build /Users/ericnetsch/tapcart-consumer-web/packages/tapcart-mobile-components
3
- > tsc -p tsconfig.json
4
-
@@ -1,9 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { ThemeProvider as NextThemesProvider } from "next-themes"
5
- import { ThemeProviderProps } from "next-themes/dist/types"
6
-
7
- export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
8
- return <NextThemesProvider {...props}>{children}</NextThemesProvider>
9
- }
@@ -1,22 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import { useTheme } from "next-themes"
5
-
6
- import { Button } from "@/components/ui/button"
7
-
8
- export function ThemeToggle() {
9
- const { setTheme, theme } = useTheme()
10
-
11
- return (
12
- <Button
13
- variant="ghost"
14
- size="sm"
15
- onClick={() => setTheme(theme === "light" ? "dark" : "light")}
16
- >
17
- <div className="rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
18
- <div className="absolute rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100" />
19
- <span className="sr-only">Toggle theme</span>
20
- </Button>
21
- )
22
- }
@@ -1,58 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as AccordionPrimitive from "@radix-ui/react-accordion"
5
- import { ChevronDown } from "lucide-react"
6
-
7
- import { cn } from "@/lib/utils"
8
-
9
- const Accordion = AccordionPrimitive.Root
10
-
11
- const AccordionItem = React.forwardRef<
12
- React.ElementRef<typeof AccordionPrimitive.Item>,
13
- React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Item>
14
- >(({ className, ...props }, ref) => (
15
- <AccordionPrimitive.Item
16
- ref={ref}
17
- className={cn("border-b", className)}
18
- {...props}
19
- />
20
- ))
21
- AccordionItem.displayName = "AccordionItem"
22
-
23
- const AccordionTrigger = React.forwardRef<
24
- React.ElementRef<typeof AccordionPrimitive.Trigger>,
25
- React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Trigger>
26
- >(({ className, children, ...props }, ref) => (
27
- <AccordionPrimitive.Header className="flex">
28
- <AccordionPrimitive.Trigger
29
- ref={ref}
30
- className={cn(
31
- "flex flex-1 items-center justify-between py-4 font-medium transition-all hover:underline [&[data-state=open]>svg]:rotate-180",
32
- className
33
- )}
34
- {...props}
35
- >
36
- {children}
37
- <ChevronDown className="h-4 w-4 shrink-0 transition-transform duration-200" />
38
- </AccordionPrimitive.Trigger>
39
- </AccordionPrimitive.Header>
40
- ))
41
- AccordionTrigger.displayName = AccordionPrimitive.Trigger.displayName
42
-
43
- const AccordionContent = React.forwardRef<
44
- React.ElementRef<typeof AccordionPrimitive.Content>,
45
- React.ComponentPropsWithoutRef<typeof AccordionPrimitive.Content>
46
- >(({ className, children, ...props }, ref) => (
47
- <AccordionPrimitive.Content
48
- ref={ref}
49
- className="overflow-hidden text-sm transition-all data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down"
50
- {...props}
51
- >
52
- <div className={cn("pb-4 pt-0", className)}>{children}</div>
53
- </AccordionPrimitive.Content>
54
- ))
55
-
56
- AccordionContent.displayName = AccordionPrimitive.Content.displayName
57
-
58
- export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }
@@ -1,141 +0,0 @@
1
- "use client"
2
-
3
- import * as React from "react"
4
- import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
5
-
6
- import { cn } from "@/lib/utils"
7
- import { buttonVariants } from "@/components/ui/button"
8
-
9
- const AlertDialog = AlertDialogPrimitive.Root
10
-
11
- const AlertDialogTrigger = AlertDialogPrimitive.Trigger
12
-
13
- const AlertDialogPortal = AlertDialogPrimitive.Portal
14
-
15
- const AlertDialogOverlay = React.forwardRef<
16
- React.ElementRef<typeof AlertDialogPrimitive.Overlay>,
17
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Overlay>
18
- >(({ className, ...props }, ref) => (
19
- <AlertDialogPrimitive.Overlay
20
- className={cn(
21
- "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",
22
- className
23
- )}
24
- {...props}
25
- ref={ref}
26
- />
27
- ))
28
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName
29
-
30
- const AlertDialogContent = React.forwardRef<
31
- React.ElementRef<typeof AlertDialogPrimitive.Content>,
32
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Content>
33
- >(({ className, ...props }, ref) => (
34
- <AlertDialogPortal>
35
- <AlertDialogOverlay />
36
- <AlertDialogPrimitive.Content
37
- ref={ref}
38
- className={cn(
39
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg",
40
- className
41
- )}
42
- {...props}
43
- />
44
- </AlertDialogPortal>
45
- ))
46
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName
47
-
48
- const AlertDialogHeader = ({
49
- className,
50
- ...props
51
- }: React.HTMLAttributes<HTMLDivElement>) => (
52
- <div
53
- className={cn(
54
- "flex flex-col space-y-2 text-center sm:text-left",
55
- className
56
- )}
57
- {...props}
58
- />
59
- )
60
- AlertDialogHeader.displayName = "AlertDialogHeader"
61
-
62
- const AlertDialogFooter = ({
63
- className,
64
- ...props
65
- }: React.HTMLAttributes<HTMLDivElement>) => (
66
- <div
67
- className={cn(
68
- "flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2",
69
- className
70
- )}
71
- {...props}
72
- />
73
- )
74
- AlertDialogFooter.displayName = "AlertDialogFooter"
75
-
76
- const AlertDialogTitle = React.forwardRef<
77
- React.ElementRef<typeof AlertDialogPrimitive.Title>,
78
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Title>
79
- >(({ className, ...props }, ref) => (
80
- <AlertDialogPrimitive.Title
81
- ref={ref}
82
- className={cn("text-lg font-semibold", className)}
83
- {...props}
84
- />
85
- ))
86
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName
87
-
88
- const AlertDialogDescription = React.forwardRef<
89
- React.ElementRef<typeof AlertDialogPrimitive.Description>,
90
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Description>
91
- >(({ className, ...props }, ref) => (
92
- <AlertDialogPrimitive.Description
93
- ref={ref}
94
- className={cn("text-sm text-muted-foreground", className)}
95
- {...props}
96
- />
97
- ))
98
- AlertDialogDescription.displayName =
99
- AlertDialogPrimitive.Description.displayName
100
-
101
- const AlertDialogAction = React.forwardRef<
102
- React.ElementRef<typeof AlertDialogPrimitive.Action>,
103
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Action>
104
- >(({ className, ...props }, ref) => (
105
- <AlertDialogPrimitive.Action
106
- ref={ref}
107
- className={cn(buttonVariants(), className)}
108
- {...props}
109
- />
110
- ))
111
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
112
-
113
- const AlertDialogCancel = React.forwardRef<
114
- React.ElementRef<typeof AlertDialogPrimitive.Cancel>,
115
- React.ComponentPropsWithoutRef<typeof AlertDialogPrimitive.Cancel>
116
- >(({ className, ...props }, ref) => (
117
- <AlertDialogPrimitive.Cancel
118
- ref={ref}
119
- className={cn(
120
- buttonVariants({ variant: "outline" }),
121
- "mt-2 sm:mt-0",
122
- className
123
- )}
124
- {...props}
125
- />
126
- ))
127
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName
128
-
129
- export {
130
- AlertDialog,
131
- AlertDialogPortal,
132
- AlertDialogOverlay,
133
- AlertDialogTrigger,
134
- AlertDialogContent,
135
- AlertDialogHeader,
136
- AlertDialogFooter,
137
- AlertDialogTitle,
138
- AlertDialogDescription,
139
- AlertDialogAction,
140
- AlertDialogCancel,
141
- }
@@ -1,7 +0,0 @@
1
- "use client"
2
-
3
- import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
4
-
5
- const AspectRatio = AspectRatioPrimitive.Root
6
-
7
- export { AspectRatio }
@@ -1,36 +0,0 @@
1
- import * as React from "react"
2
- import { cva, type VariantProps } from "class-variance-authority"
3
-
4
- import { cn } from "@/lib/utils"
5
-
6
- const badgeVariants = cva(
7
- "inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2",
8
- {
9
- variants: {
10
- variant: {
11
- default:
12
- "border-transparent bg-primary text-primary-foreground hover:bg-primary/80",
13
- secondary:
14
- "border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80",
15
- destructive:
16
- "border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80",
17
- outline: "text-foreground",
18
- },
19
- },
20
- defaultVariants: {
21
- variant: "default",
22
- },
23
- }
24
- )
25
-
26
- export interface BadgeProps
27
- extends React.HTMLAttributes<HTMLDivElement>,
28
- VariantProps<typeof badgeVariants> {}
29
-
30
- function Badge({ className, variant, ...props }: BadgeProps) {
31
- return (
32
- <div className={cn(badgeVariants({ variant }), className)} {...props} />
33
- )
34
- }
35
-
36
- export { Badge, badgeVariants }
@@ -1,69 +0,0 @@
1
- import * as React from "react"
2
- import { Slot } from "@radix-ui/react-slot"
3
- import { cva, type VariantProps } from "class-variance-authority"
4
- import { IconLoader2 } from "@tabler/icons-react"
5
-
6
- import { cn } from "@/lib/utils"
7
-
8
- const buttonVariants = cva(
9
- "flex rounded items-center justify-center text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:bg-stateColors-disabled disabled:pointer-events-none ring-offset-background overflow-elipse whitespace-nowrap truncate",
10
- {
11
- variants: {
12
- size: {
13
- default: "h-10 py-3 px-4",
14
- sm: "h-9 px-3 rounded-md",
15
- lg: "h-11 px-8 rounded-md",
16
- icon: "h-10 w-10",
17
- content: "h-10 py-3 px-4 w-auto",
18
- },
19
- variant: {
20
- default:
21
- "bg-buttonColors-primaryFill text-buttonColors-primaryText active:opacity-70",
22
- destructive:
23
- "bg-stateColors-error text-coreColors-pageColor active:opacity-70 disabled:bg-stateColors-disabled",
24
- outline:
25
- "border border-input hover:bg-accent hover:text-accent-foreground",
26
- secondary:
27
- "border bg-buttonColors-secondaryFill text-buttonColors-secondaryText border-buttonColors-secondaryOutline active:opacity-70 disabled:bg-buttonColors-secondaryFill disabled:text-stateColors-disabled disabled:border-stateColors-disabled",
28
- ghost: "hover:bg-accent hover:text-accent-foreground",
29
- link: "underline-offset-4 hover:underline text-primary",
30
- quickadd:
31
- "bg-buttonColors-primaryFill text-buttonColors-primaryText active:opacity-70 w-full rounded-none rounded-b-lg h-8 text-xs",
32
- applePay: "bg-white text-black border border-black",
33
- shopPay: "bg-[#612EFF]",
34
- },
35
- },
36
- defaultVariants: {
37
- variant: "default",
38
- size: "default",
39
- },
40
- }
41
- )
42
-
43
- export interface ButtonProps
44
- extends React.ButtonHTMLAttributes<HTMLButtonElement>,
45
- VariantProps<typeof buttonVariants> {
46
- asChild?: boolean
47
- loading?: boolean
48
- }
49
-
50
- const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
51
- ({ className, variant, size, asChild = false, loading, ...props }, ref) => {
52
- const Comp = asChild ? Slot : "button"
53
- return (
54
- <Comp
55
- className={cn(buttonVariants({ variant, size, className }), {
56
- "pointer-events-none": loading,
57
- })}
58
- ref={ref}
59
- {...props}
60
- >
61
- {!loading && props.children}
62
- {loading && <IconLoader2 className="h-4 w-4 animate-spin" />}
63
- </Comp>
64
- )
65
- }
66
- )
67
- Button.displayName = "Button"
68
-
69
- export { Button, buttonVariants }