torch-glare 1.3.0 → 1.4.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.
|
@@ -5,15 +5,16 @@ import { cn } from "../utils/cn";
|
|
|
5
5
|
import { ButtonVariant, Themes } from "../utils/types";
|
|
6
6
|
|
|
7
7
|
interface Props
|
|
8
|
-
extends
|
|
9
|
-
|
|
8
|
+
extends
|
|
9
|
+
ButtonHTMLAttributes<HTMLButtonElement>,
|
|
10
|
+
VariantProps<typeof buttonVariants> {
|
|
10
11
|
is_loading?: boolean;
|
|
11
12
|
disabled?: boolean;
|
|
12
13
|
asChild?: boolean;
|
|
13
14
|
variant?: ButtonVariant;
|
|
14
15
|
as?: React.ElementType;
|
|
15
|
-
theme?: Themes
|
|
16
|
-
containerClassName?: string
|
|
16
|
+
theme?: Themes;
|
|
17
|
+
containerClassName?: string;
|
|
17
18
|
}
|
|
18
19
|
export const Button = forwardRef<HTMLButtonElement, Props>(
|
|
19
20
|
(
|
|
@@ -32,7 +33,7 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
|
|
|
32
33
|
containerClassName,
|
|
33
34
|
...props
|
|
34
35
|
},
|
|
35
|
-
ref
|
|
36
|
+
ref,
|
|
36
37
|
) => {
|
|
37
38
|
const Component = asChild ? Slot : Tag;
|
|
38
39
|
|
|
@@ -51,34 +52,45 @@ export const Button = forwardRef<HTMLButtonElement, Props>(
|
|
|
51
52
|
buttonType,
|
|
52
53
|
disabled,
|
|
53
54
|
}),
|
|
54
|
-
className
|
|
55
|
+
className,
|
|
55
56
|
)}
|
|
56
57
|
>
|
|
57
58
|
{asChild ? (
|
|
58
59
|
React.cloneElement(
|
|
59
60
|
children as React.ReactElement,
|
|
60
61
|
{},
|
|
61
|
-
<div
|
|
62
|
+
<div
|
|
63
|
+
className={cn(
|
|
64
|
+
"flex items-center justify-center [&>:is(i,svg):first-child]:mr-[3px] [&>:is(i,svg):last-child]:ml-[3px] [&>:is(i,svg):only-child]:m-0 [&:has(>:is(i,svg):last-child):not(:has(>:is(i,svg):first-child))]:pl-[6px] [&:has(>:is(i,svg):first-child):not(:has(>:is(i,svg):last-child))]:pr-[6px]",
|
|
65
|
+
containerClassName,
|
|
66
|
+
)}
|
|
67
|
+
>
|
|
62
68
|
{(children as React.ReactElement<any>).props.children}
|
|
63
69
|
{is_loading && <LoadingIcon size={size} />}
|
|
64
|
-
</div
|
|
70
|
+
</div>,
|
|
65
71
|
)
|
|
66
72
|
) : (
|
|
67
|
-
<div
|
|
73
|
+
<div
|
|
74
|
+
className={cn(
|
|
75
|
+
"flex items-center justify-center [&>:is(i,svg):first-child]:mr-[3px] [&>:is(i,svg):last-child]:ml-[3px] [&>:is(i,svg):only-child]:m-0 [&:has(>:is(i,svg):last-child):not(:has(>:is(i,svg):first-child))]:pl-[6px] [&:has(>:is(i,svg):first-child):not(:has(>:is(i,svg):last-child))]:pr-[6px]",
|
|
76
|
+
containerClassName,
|
|
77
|
+
)}
|
|
78
|
+
>
|
|
68
79
|
{children}
|
|
69
80
|
{is_loading && <LoadingIcon size={size} />}
|
|
70
81
|
</div>
|
|
71
82
|
)}
|
|
72
83
|
</Component>
|
|
73
84
|
);
|
|
74
|
-
}
|
|
85
|
+
},
|
|
75
86
|
);
|
|
76
87
|
|
|
77
|
-
Button.displayName = "Button"
|
|
88
|
+
Button.displayName = "Button";
|
|
78
89
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
90
|
+
export function LoadingIcon({
|
|
91
|
+
size,
|
|
92
|
+
className,
|
|
93
|
+
}: {
|
|
82
94
|
size?: "S" | "M" | "L" | "XL" | null;
|
|
83
95
|
className?: string;
|
|
84
96
|
}) {
|
|
@@ -88,7 +100,7 @@ export function LoadingIcon({ size, className }: {
|
|
|
88
100
|
S: "w-[12px] h-[12px]",
|
|
89
101
|
M: "w-[18px] h-[18px]",
|
|
90
102
|
L: "w-[20px] h-[20px]",
|
|
91
|
-
XL: "w-[20px] h-[20px]"
|
|
103
|
+
XL: "w-[20px] h-[20px]",
|
|
92
104
|
},
|
|
93
105
|
},
|
|
94
106
|
defaultVariants: {
|
|
@@ -115,91 +127,130 @@ export function LoadingIcon({ size, className }: {
|
|
|
115
127
|
);
|
|
116
128
|
}
|
|
117
129
|
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
130
|
export const buttonVariants = cva(
|
|
122
131
|
"flex items-center whitespace-nowrap justify-center transition-[background,color] duration-200 ease-in-out border border-transparent outline-none leading-none [&-i]:!leading-none",
|
|
123
132
|
{
|
|
124
133
|
variants: {
|
|
125
134
|
variant: {
|
|
126
|
-
//
|
|
135
|
+
// Sec variants: base = button-secondary, hover picks up fill color
|
|
127
136
|
PrimeStyle: [
|
|
128
|
-
"bg-background-presentation-
|
|
137
|
+
"bg-background-presentation-button-secondary",
|
|
129
138
|
"text-content-presentation-action-light-primary",
|
|
130
|
-
"hover:bg-background-presentation-
|
|
131
|
-
"hover:text-content-presentation-
|
|
132
|
-
"focus:lg:focus:md:border lg:focus:md:border-border-presentation-state-focus",
|
|
133
|
-
"active:bg-background-presentation-
|
|
139
|
+
"hover:bg-background-presentation-button-hover",
|
|
140
|
+
"hover:text-content-presentation-global-hover",
|
|
141
|
+
"focus:lg:focus:md:border lg:focus:md:border-border-presentation-state-focus",
|
|
142
|
+
"active:bg-background-presentation-button-hover active:text-content-presentation-global-hover",
|
|
134
143
|
],
|
|
135
|
-
|
|
136
|
-
"bg-background-presentation-
|
|
144
|
+
BluSecStyle: [
|
|
145
|
+
"bg-background-presentation-button-secondary",
|
|
137
146
|
"text-content-presentation-action-light-primary",
|
|
138
|
-
"hover:bg-background-presentation-
|
|
139
|
-
"hover:text-content-presentation-
|
|
147
|
+
"hover:bg-background-presentation-button-fill-blue-primary",
|
|
148
|
+
"hover:text-content-presentation-global-hover",
|
|
140
149
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
141
|
-
"active:bg-background-presentation-
|
|
150
|
+
"active:bg-background-presentation-button-fill-blue-primary active:text-content-presentation-global-hover",
|
|
142
151
|
],
|
|
143
152
|
YelSecStyle: [
|
|
144
|
-
"bg-background-presentation-
|
|
153
|
+
"bg-background-presentation-button-secondary",
|
|
145
154
|
"text-content-presentation-action-light-primary",
|
|
146
|
-
"hover:bg-background-presentation-
|
|
155
|
+
"hover:bg-background-presentation-button-fill-yellow-primary",
|
|
147
156
|
"hover:text-content-presentation-action-light-primary",
|
|
148
157
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
149
|
-
"active:bg-background-presentation-
|
|
158
|
+
"active:bg-background-presentation-button-fill-yellow-primary active:text-content-presentation-action-light-primary",
|
|
150
159
|
],
|
|
151
160
|
RedSecStyle: [
|
|
152
|
-
"bg-background-presentation-
|
|
161
|
+
"bg-background-presentation-button-secondary",
|
|
153
162
|
"text-content-presentation-action-light-primary",
|
|
154
|
-
"hover:bg-background-presentation-
|
|
155
|
-
"hover:text-content-presentation-
|
|
163
|
+
"hover:bg-background-presentation-button-fill-red-primary",
|
|
164
|
+
"hover:text-content-presentation-global-hover",
|
|
156
165
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
157
|
-
"active:bg-background-presentation-
|
|
166
|
+
"active:bg-background-presentation-button-fill-red-primary active:text-content-presentation-global-hover",
|
|
158
167
|
],
|
|
159
168
|
BorderStyle: [
|
|
160
169
|
"text-content-presentation-action-light-primary",
|
|
161
170
|
"border border-border-presentation-action-disabled",
|
|
162
|
-
"bg-background-presentation-
|
|
163
|
-
"hover:bg-background-presentation-
|
|
164
|
-
"hover:text-content-presentation-
|
|
171
|
+
"bg-background-presentation-button-borderstyle",
|
|
172
|
+
"hover:bg-background-presentation-button-hover",
|
|
173
|
+
"hover:text-content-presentation-global-hover",
|
|
165
174
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
166
175
|
"focus:lg:text-content-presentation-action-light-primary",
|
|
167
|
-
"focus:hover:lg:text-content-presentation-
|
|
168
|
-
"active:bg-background-presentation-
|
|
176
|
+
"focus:hover:lg:text-content-presentation-global-hover",
|
|
177
|
+
"active:bg-background-presentation-button-hover active:text-content-presentation-global-hover",
|
|
169
178
|
],
|
|
179
|
+
// Cont variants: transparent base, hover shows button-contstyle-hover
|
|
170
180
|
PrimeContStyle: [
|
|
171
181
|
"text-content-presentation-action-light-primary",
|
|
172
182
|
"border-transparent bg-transparent",
|
|
173
|
-
"hover:bg-background-presentation-
|
|
183
|
+
"hover:bg-background-presentation-button-contstyle-hover",
|
|
174
184
|
"hover:text-content-presentation-action-light-primary",
|
|
175
185
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
176
|
-
"focus:lg:bg-background-presentation-
|
|
177
|
-
"active:bg-background-presentation-
|
|
186
|
+
"focus:lg:bg-background-presentation-button-borderstyle",
|
|
187
|
+
"active:bg-background-presentation-button-contstyle-hover active:text-content-presentation-action-light-primary",
|
|
178
188
|
],
|
|
179
|
-
|
|
189
|
+
BluContStyle: [
|
|
180
190
|
"text-content-presentation-action-light-primary",
|
|
181
191
|
"border-transparent bg-transparent",
|
|
182
|
-
"hover:bg-background-presentation-
|
|
183
|
-
"hover:text-content-presentation-
|
|
192
|
+
"hover:bg-background-presentation-button-contstyle-hover",
|
|
193
|
+
"hover:text-content-presentation-global-information-hover",
|
|
184
194
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
185
|
-
"focus:lg:bg-background-presentation-
|
|
186
|
-
"active:bg-background-presentation-
|
|
195
|
+
"focus:lg:bg-background-presentation-button-borderstyle",
|
|
196
|
+
"active:bg-background-presentation-button-contstyle-hover active:text-content-presentation-global-information-hover",
|
|
187
197
|
],
|
|
188
198
|
RedContStyle: [
|
|
189
199
|
"text-content-presentation-action-light-primary",
|
|
190
200
|
"border-transparent bg-transparent",
|
|
191
|
-
"hover:bg-background-presentation-
|
|
192
|
-
"hover:text-content-presentation-
|
|
201
|
+
"hover:bg-background-presentation-button-contstyle-hover",
|
|
202
|
+
"hover:text-content-presentation-global-negative-hover",
|
|
203
|
+
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
204
|
+
"focus:lg:bg-background-presentation-button-borderstyle",
|
|
205
|
+
"active:bg-background-presentation-button-contstyle-hover active:text-content-presentation-global-negative-hover",
|
|
206
|
+
],
|
|
207
|
+
// Col variants: filled solid color base, hover deepens to -secondary
|
|
208
|
+
PrimeColStyle: [
|
|
209
|
+
"bg-background-presentation-button-primary",
|
|
210
|
+
"text-content-presentation-global-primary-inverse",
|
|
211
|
+
"hover:bg-background-presentation-button-hover",
|
|
212
|
+
"hover:text-content-presentation-global-primary-inverse",
|
|
213
|
+
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
214
|
+
"active:bg-background-presentation-button-hover active:text-content-presentation-global-primary-inverse",
|
|
215
|
+
],
|
|
216
|
+
BluColStyle: [
|
|
217
|
+
"bg-background-presentation-button-fill-blue-primary",
|
|
218
|
+
"text-content-presentation-action-dark-primary",
|
|
219
|
+
"hover:bg-background-presentation-button-fill-blue-secondary",
|
|
220
|
+
"hover:text-content-presentation-action-dark-primary",
|
|
221
|
+
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
222
|
+
"active:bg-background-presentation-button-fill-blue-secondary active:text-content-presentation-action-dark-primary",
|
|
223
|
+
],
|
|
224
|
+
RedColStyle: [
|
|
225
|
+
"bg-background-presentation-button-fill-red-primary",
|
|
226
|
+
"text-content-presentation-action-dark-primary",
|
|
227
|
+
"hover:bg-background-presentation-button-fill-red-secondary",
|
|
228
|
+
"hover:text-content-presentation-action-dark-primary",
|
|
229
|
+
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
230
|
+
"active:bg-background-presentation-button-fill-red-secondary active:text-content-presentation-action-dark-primary",
|
|
231
|
+
],
|
|
232
|
+
GreenColStyle: [
|
|
233
|
+
"bg-background-presentation-button-fill-green-primary",
|
|
234
|
+
"text-content-presentation-action-dark-primary",
|
|
235
|
+
"hover:bg-background-presentation-button-fill-green-secondary",
|
|
236
|
+
"hover:text-content-presentation-action-dark-primary",
|
|
237
|
+
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
238
|
+
"active:bg-background-presentation-button-fill-green-secondary active:text-content-presentation-action-dark-primary",
|
|
239
|
+
],
|
|
240
|
+
YelColStyle: [
|
|
241
|
+
"bg-background-presentation-button-fill-yellow-primary",
|
|
242
|
+
"text-content-presentation-global-primary",
|
|
243
|
+
"hover:bg-background-presentation-button-fill-yellow-secondary",
|
|
244
|
+
"hover:text-content-presentation-global-primary",
|
|
193
245
|
"focus:lg:border focus:lg:border-border-presentation-state-focus",
|
|
194
|
-
"
|
|
195
|
-
"active:bg-background-presentation-action-contstyle-hover active:text-content-presentation-action-negative-hover",
|
|
246
|
+
"active:bg-background-presentation-button-fill-yellow-secondary active:text-content-presentation-global-primary",
|
|
196
247
|
],
|
|
197
248
|
},
|
|
198
249
|
size: {
|
|
199
|
-
S: "h-[22px] px-[6px] typography-body-small-medium rounded-[4px] [&_i]:text-[12px]",
|
|
200
|
-
M: "h-[28px] px-[14px] typography-body-large-medium rounded-[
|
|
201
|
-
L: "h-[34px] px-[22px] typography-body-large-medium rounded-[
|
|
202
|
-
XL: "h-[40px] px-[30px] typography-headers-medium-medium rounded-[
|
|
250
|
+
S: "h-[22px] py-[2px] px-[6px] typography-body-small-medium rounded-[4px] [&_i]:text-[12px]",
|
|
251
|
+
M: "h-[28px] py-[2px] px-[14px] typography-body-large-medium rounded-[6px] [&_i]:text-[18px]",
|
|
252
|
+
L: "h-[34px] py-[5px] px-[22px] typography-body-large-medium rounded-[8px] [&_i]:text-[20px]",
|
|
253
|
+
XL: "h-[40px] py-[8px] px-[30px] typography-headers-medium-medium rounded-[8px] [&_i]:text-[22px]",
|
|
203
254
|
},
|
|
204
255
|
is_loading: {
|
|
205
256
|
true: "[&_i]:hidden",
|
|
@@ -222,12 +273,12 @@ export const buttonVariants = cva(
|
|
|
222
273
|
is_loading: true,
|
|
223
274
|
className: [
|
|
224
275
|
"cursor-wait",
|
|
225
|
-
"bg-background-presentation-
|
|
226
|
-
"text-content-presentation-
|
|
227
|
-
"hover:bg-background-presentation-
|
|
228
|
-
"hover:text-content-presentation-
|
|
276
|
+
"bg-background-presentation-button-hover",
|
|
277
|
+
"text-content-presentation-global-hover",
|
|
278
|
+
"hover:bg-background-presentation-button-hover",
|
|
279
|
+
"hover:text-content-presentation-global-hover",
|
|
229
280
|
"focus:lg:border focus:lg:border-transparent",
|
|
230
|
-
"active:bg-background-presentation-
|
|
281
|
+
"active:bg-background-presentation-button-hover active:text-content-presentation-global-hover",
|
|
231
282
|
],
|
|
232
283
|
},
|
|
233
284
|
{
|
|
@@ -235,7 +286,7 @@ export const buttonVariants = cva(
|
|
|
235
286
|
className: [
|
|
236
287
|
"cursor-not-allowed",
|
|
237
288
|
"pointer-events-none",
|
|
238
|
-
"bg-background-presentation-
|
|
289
|
+
"bg-background-presentation-button-disabled",
|
|
239
290
|
"text-content-presentation-state-disabled",
|
|
240
291
|
"border-transparent",
|
|
241
292
|
],
|
|
@@ -261,5 +312,5 @@ export const buttonVariants = cva(
|
|
|
261
312
|
className: "w-[40px] h-[40px] p-0 leading-[0]",
|
|
262
313
|
},
|
|
263
314
|
],
|
|
264
|
-
}
|
|
315
|
+
},
|
|
265
316
|
);
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { forwardRef, HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
|
|
5
|
+
const titleBadge = cva(
|
|
6
|
+
"flex pt-2 pb-2 pl-[16px] pr-[22px] justify-center items-center gap-[6px] rounded-[10px] self-start typography-headers-medium-medium text-[#F4F4F4]",
|
|
7
|
+
{
|
|
8
|
+
variants: {
|
|
9
|
+
color: {
|
|
10
|
+
Blue: "bg-blue-sparkle-900",
|
|
11
|
+
Yellow: "bg-yellow-950",
|
|
12
|
+
Green: "bg-green-cyan-900",
|
|
13
|
+
Red: "bg-medium-red-900",
|
|
14
|
+
Orange: "bg-red-orange-900",
|
|
15
|
+
Purple: "bg-violet-900",
|
|
16
|
+
Pink: "bg-medium-violet-red-900",
|
|
17
|
+
Gray: "bg-background-presentation-button-primary",
|
|
18
|
+
},
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: { color: "Blue" },
|
|
21
|
+
},
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
export type SectionColor = NonNullable<VariantProps<typeof titleBadge>["color"]>;
|
|
25
|
+
|
|
26
|
+
export interface SectionCardProps extends Omit<HTMLAttributes<HTMLDivElement>, "title"> {
|
|
27
|
+
color?: SectionColor;
|
|
28
|
+
title?: ReactNode;
|
|
29
|
+
containerClassName?: string;
|
|
30
|
+
headerClassName?: string;
|
|
31
|
+
bodyClassName?: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const SectionCard = forwardRef<HTMLDivElement, SectionCardProps>(
|
|
35
|
+
(
|
|
36
|
+
{
|
|
37
|
+
children,
|
|
38
|
+
color,
|
|
39
|
+
title,
|
|
40
|
+
className,
|
|
41
|
+
containerClassName,
|
|
42
|
+
headerClassName,
|
|
43
|
+
bodyClassName,
|
|
44
|
+
...props
|
|
45
|
+
},
|
|
46
|
+
ref,
|
|
47
|
+
) => {
|
|
48
|
+
return (
|
|
49
|
+
<div
|
|
50
|
+
ref={ref}
|
|
51
|
+
className={cn(
|
|
52
|
+
"flex w-[1100px] pt-[6px] pb-[24px] px-0 flex-col rounded-[16px] bg-background-presentation-form-base shadow-[0_0_32px_2px_rgba(0,0,0,0.05)]",
|
|
53
|
+
className,
|
|
54
|
+
containerClassName,
|
|
55
|
+
)}
|
|
56
|
+
{...props}
|
|
57
|
+
>
|
|
58
|
+
{title && (
|
|
59
|
+
<div className={cn("flex px-[6px] flex-col gap-[10px]", headerClassName)}>
|
|
60
|
+
<div className={cn(titleBadge({ color }))}>{title}</div>
|
|
61
|
+
</div>
|
|
62
|
+
)}
|
|
63
|
+
<div className={cn("flex px-[42px] flex-col gap-[2px]", bodyClassName)}>
|
|
64
|
+
{children}
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
);
|
|
70
|
+
|
|
71
|
+
SectionCard.displayName = "SectionCard";
|
|
@@ -0,0 +1,374 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import React, {
|
|
4
|
+
forwardRef,
|
|
5
|
+
HTMLAttributes,
|
|
6
|
+
ReactNode,
|
|
7
|
+
createContext,
|
|
8
|
+
useContext,
|
|
9
|
+
} from "react";
|
|
10
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
11
|
+
import { cn } from "../utils/cn";
|
|
12
|
+
import { Themes } from "../utils/types";
|
|
13
|
+
|
|
14
|
+
// ─── Context ─────────────────────────────────────────────────────────────────
|
|
15
|
+
|
|
16
|
+
interface StepperContextValue {
|
|
17
|
+
activeStep: number;
|
|
18
|
+
orientation: "horizontal" | "vertical";
|
|
19
|
+
size: "S" | "M" | "L";
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const StepperContext = createContext<StepperContextValue>({
|
|
23
|
+
activeStep: 0,
|
|
24
|
+
orientation: "horizontal",
|
|
25
|
+
size: "M",
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const useStepperContext = () => useContext(StepperContext);
|
|
29
|
+
|
|
30
|
+
// ─── Stepper Root ────────────────────────────────────────────────────────────
|
|
31
|
+
|
|
32
|
+
const stepperStyles = cva(["flex gap-0"], {
|
|
33
|
+
variants: {
|
|
34
|
+
orientation: {
|
|
35
|
+
horizontal: "flex-row items-start",
|
|
36
|
+
vertical: "flex-col",
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
defaultVariants: {
|
|
40
|
+
orientation: "horizontal",
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
interface StepperProps
|
|
45
|
+
extends HTMLAttributes<HTMLDivElement>, VariantProps<typeof stepperStyles> {
|
|
46
|
+
theme?: Themes;
|
|
47
|
+
activeStep?: number;
|
|
48
|
+
size?: "S" | "M" | "L";
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
const Stepper = forwardRef<HTMLDivElement, StepperProps>(
|
|
52
|
+
(
|
|
53
|
+
{
|
|
54
|
+
className,
|
|
55
|
+
orientation = "horizontal",
|
|
56
|
+
theme,
|
|
57
|
+
activeStep = 0,
|
|
58
|
+
size = "M",
|
|
59
|
+
...props
|
|
60
|
+
},
|
|
61
|
+
ref,
|
|
62
|
+
) => (
|
|
63
|
+
<StepperContext.Provider
|
|
64
|
+
value={{
|
|
65
|
+
activeStep,
|
|
66
|
+
orientation: orientation ?? "horizontal",
|
|
67
|
+
size: size ?? "M",
|
|
68
|
+
}}
|
|
69
|
+
>
|
|
70
|
+
<div
|
|
71
|
+
ref={ref}
|
|
72
|
+
data-theme={theme}
|
|
73
|
+
data-orientation={orientation}
|
|
74
|
+
className={cn(stepperStyles({ orientation }), className)}
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
</StepperContext.Provider>
|
|
78
|
+
),
|
|
79
|
+
);
|
|
80
|
+
Stepper.displayName = "Stepper";
|
|
81
|
+
|
|
82
|
+
// ─── Step ────────────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
interface StepProps extends HTMLAttributes<HTMLDivElement> {
|
|
85
|
+
index?: number;
|
|
86
|
+
isCompleted?: boolean;
|
|
87
|
+
isActive?: boolean;
|
|
88
|
+
isError?: boolean;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const Step = forwardRef<HTMLDivElement, StepProps>(
|
|
92
|
+
(
|
|
93
|
+
{
|
|
94
|
+
className,
|
|
95
|
+
index = 0,
|
|
96
|
+
isCompleted,
|
|
97
|
+
isActive,
|
|
98
|
+
isError,
|
|
99
|
+
children,
|
|
100
|
+
...props
|
|
101
|
+
},
|
|
102
|
+
ref,
|
|
103
|
+
) => {
|
|
104
|
+
const { activeStep, orientation } = useStepperContext();
|
|
105
|
+
|
|
106
|
+
const computedActive = isActive ?? index === activeStep;
|
|
107
|
+
const computedCompleted = isCompleted ?? index < activeStep;
|
|
108
|
+
const computedError = isError ?? false;
|
|
109
|
+
|
|
110
|
+
return (
|
|
111
|
+
<div
|
|
112
|
+
ref={ref}
|
|
113
|
+
data-active={computedActive || undefined}
|
|
114
|
+
data-completed={computedCompleted || undefined}
|
|
115
|
+
data-error={computedError || undefined}
|
|
116
|
+
data-orientation={orientation}
|
|
117
|
+
className={cn(
|
|
118
|
+
"flex group/step",
|
|
119
|
+
orientation === "horizontal"
|
|
120
|
+
? "shrink-0 flex-col items-center gap-2"
|
|
121
|
+
: "flex-row gap-3",
|
|
122
|
+
className,
|
|
123
|
+
)}
|
|
124
|
+
{...props}
|
|
125
|
+
>
|
|
126
|
+
{React.Children.map(children, (child) => {
|
|
127
|
+
if (!React.isValidElement(child)) return child;
|
|
128
|
+
return React.cloneElement(child as React.ReactElement<any>, {
|
|
129
|
+
_active: computedActive,
|
|
130
|
+
_completed: computedCompleted,
|
|
131
|
+
_error: computedError,
|
|
132
|
+
_index: index,
|
|
133
|
+
});
|
|
134
|
+
})}
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
);
|
|
139
|
+
Step.displayName = "Step";
|
|
140
|
+
|
|
141
|
+
// ─── Step Indicator ──────────────────────────────────────────────────────────
|
|
142
|
+
|
|
143
|
+
const stepIndicatorStyles = cva(
|
|
144
|
+
[
|
|
145
|
+
"flex items-center justify-center shrink-0 rounded-full",
|
|
146
|
+
"border",
|
|
147
|
+
"transition-all duration-200 ease-in-out",
|
|
148
|
+
"typography-body-small-medium",
|
|
149
|
+
"[&_i]:leading-none [&_i]:flex [&_i]:items-center [&_i]:justify-center",
|
|
150
|
+
],
|
|
151
|
+
{
|
|
152
|
+
variants: {
|
|
153
|
+
state: {
|
|
154
|
+
pending: [
|
|
155
|
+
"bg-background-presentation-action-disabled",
|
|
156
|
+
"border-border-presentation-action-disabled",
|
|
157
|
+
"text-content-presentation-state-disabled",
|
|
158
|
+
],
|
|
159
|
+
active: [
|
|
160
|
+
"bg-background-presentation-state-information-primary",
|
|
161
|
+
"border-border-presentation-state-focus",
|
|
162
|
+
"text-content-presentation-state-information",
|
|
163
|
+
],
|
|
164
|
+
completed: [
|
|
165
|
+
"bg-background-presentation-state-success-primary",
|
|
166
|
+
"border-border-presentation-state-success",
|
|
167
|
+
"text-content-presentation-state-success",
|
|
168
|
+
],
|
|
169
|
+
error: [
|
|
170
|
+
"bg-background-presentation-state-negative-primary",
|
|
171
|
+
"border-border-presentation-state-negative",
|
|
172
|
+
"text-content-presentation-state-negative",
|
|
173
|
+
],
|
|
174
|
+
},
|
|
175
|
+
size: {
|
|
176
|
+
S: "w-[22px] h-[22px] text-[10px] [&_i]:text-[12px]",
|
|
177
|
+
M: "w-[28px] h-[28px] text-[12px] [&_i]:text-[14px]",
|
|
178
|
+
L: "w-[34px] h-[34px] text-[14px] [&_i]:text-[16px]",
|
|
179
|
+
},
|
|
180
|
+
},
|
|
181
|
+
defaultVariants: {
|
|
182
|
+
state: "pending",
|
|
183
|
+
size: "M",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
interface StepIndicatorProps extends HTMLAttributes<HTMLDivElement> {
|
|
189
|
+
icon?: ReactNode;
|
|
190
|
+
completedIcon?: ReactNode;
|
|
191
|
+
errorIcon?: ReactNode;
|
|
192
|
+
_active?: boolean;
|
|
193
|
+
_completed?: boolean;
|
|
194
|
+
_error?: boolean;
|
|
195
|
+
_index?: number;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const StepIndicator = forwardRef<HTMLDivElement, StepIndicatorProps>(
|
|
199
|
+
(
|
|
200
|
+
{
|
|
201
|
+
className,
|
|
202
|
+
icon,
|
|
203
|
+
completedIcon,
|
|
204
|
+
errorIcon,
|
|
205
|
+
_active,
|
|
206
|
+
_completed,
|
|
207
|
+
_error,
|
|
208
|
+
_index = 0,
|
|
209
|
+
children,
|
|
210
|
+
...props
|
|
211
|
+
},
|
|
212
|
+
ref,
|
|
213
|
+
) => {
|
|
214
|
+
const { size } = useStepperContext();
|
|
215
|
+
|
|
216
|
+
const state = _error
|
|
217
|
+
? "error"
|
|
218
|
+
: _completed
|
|
219
|
+
? "completed"
|
|
220
|
+
: _active
|
|
221
|
+
? "active"
|
|
222
|
+
: "pending";
|
|
223
|
+
|
|
224
|
+
const renderContent = () => {
|
|
225
|
+
if (_error && errorIcon) return errorIcon;
|
|
226
|
+
if (_error) return <i className="ri-close-line" />;
|
|
227
|
+
if (_completed && completedIcon) return completedIcon;
|
|
228
|
+
if (_completed) return <i className="ri-check-line" />;
|
|
229
|
+
if (icon) return icon;
|
|
230
|
+
if (children) return children;
|
|
231
|
+
return _index + 1;
|
|
232
|
+
};
|
|
233
|
+
|
|
234
|
+
return (
|
|
235
|
+
<div
|
|
236
|
+
ref={ref}
|
|
237
|
+
className={cn(stepIndicatorStyles({ state, size }), className)}
|
|
238
|
+
{...props}
|
|
239
|
+
>
|
|
240
|
+
{renderContent()}
|
|
241
|
+
</div>
|
|
242
|
+
);
|
|
243
|
+
},
|
|
244
|
+
);
|
|
245
|
+
StepIndicator.displayName = "StepIndicator";
|
|
246
|
+
|
|
247
|
+
// ─── Step Connector (the line between steps) ────────────────────────────────
|
|
248
|
+
|
|
249
|
+
const connectorStyles = cva(["transition-all duration-200 ease-in-out"], {
|
|
250
|
+
variants: {
|
|
251
|
+
orientation: {
|
|
252
|
+
horizontal: "h-[2px] flex-1 mx-2 mt-[13px]",
|
|
253
|
+
vertical: "w-[2px] flex-1 min-h-[24px] my-2",
|
|
254
|
+
},
|
|
255
|
+
state: {
|
|
256
|
+
pending: "bg-border-presentation-action-disabled",
|
|
257
|
+
completed: "bg-border-presentation-state-focus",
|
|
258
|
+
},
|
|
259
|
+
},
|
|
260
|
+
defaultVariants: {
|
|
261
|
+
orientation: "horizontal",
|
|
262
|
+
state: "pending",
|
|
263
|
+
},
|
|
264
|
+
compoundVariants: [
|
|
265
|
+
{
|
|
266
|
+
orientation: "horizontal",
|
|
267
|
+
className: "self-start",
|
|
268
|
+
},
|
|
269
|
+
],
|
|
270
|
+
});
|
|
271
|
+
|
|
272
|
+
interface StepConnectorProps extends HTMLAttributes<HTMLDivElement> {
|
|
273
|
+
_completed?: boolean;
|
|
274
|
+
_active?: boolean;
|
|
275
|
+
_error?: boolean;
|
|
276
|
+
_index?: number;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
const StepConnector = forwardRef<HTMLDivElement, StepConnectorProps>(
|
|
280
|
+
(
|
|
281
|
+
{ className, _completed, _active: _a, _error: _e, _index: _i, ...props },
|
|
282
|
+
ref,
|
|
283
|
+
) => {
|
|
284
|
+
const { orientation } = useStepperContext();
|
|
285
|
+
|
|
286
|
+
return (
|
|
287
|
+
<div
|
|
288
|
+
ref={ref}
|
|
289
|
+
className={cn(
|
|
290
|
+
connectorStyles({
|
|
291
|
+
orientation,
|
|
292
|
+
state: _completed ? "completed" : "pending",
|
|
293
|
+
}),
|
|
294
|
+
className,
|
|
295
|
+
)}
|
|
296
|
+
{...props}
|
|
297
|
+
/>
|
|
298
|
+
);
|
|
299
|
+
},
|
|
300
|
+
);
|
|
301
|
+
StepConnector.displayName = "StepConnector";
|
|
302
|
+
|
|
303
|
+
// ─── Step Label ──────────────────────────────────────────────────────────────
|
|
304
|
+
|
|
305
|
+
interface StepLabelProps extends HTMLAttributes<HTMLDivElement> {
|
|
306
|
+
_active?: boolean;
|
|
307
|
+
_completed?: boolean;
|
|
308
|
+
_error?: boolean;
|
|
309
|
+
_index?: number;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const StepLabel = forwardRef<HTMLDivElement, StepLabelProps>(
|
|
313
|
+
({ className, _active, _completed, _error, _index: _i, ...props }, ref) => (
|
|
314
|
+
<div
|
|
315
|
+
ref={ref}
|
|
316
|
+
className={cn(
|
|
317
|
+
"typography-body-small-medium transition-colors duration-200 ease-in-out",
|
|
318
|
+
_active
|
|
319
|
+
? "text-content-presentation-state-information"
|
|
320
|
+
: _error
|
|
321
|
+
? "text-content-presentation-state-negative"
|
|
322
|
+
: _completed
|
|
323
|
+
? "text-content-presentation-global-primary"
|
|
324
|
+
: "text-content-presentation-state-disabled",
|
|
325
|
+
className,
|
|
326
|
+
)}
|
|
327
|
+
{...props}
|
|
328
|
+
/>
|
|
329
|
+
),
|
|
330
|
+
);
|
|
331
|
+
StepLabel.displayName = "StepLabel";
|
|
332
|
+
|
|
333
|
+
// ─── Step Description ────────────────────────────────────────────────────────
|
|
334
|
+
|
|
335
|
+
interface StepDescriptionProps extends HTMLAttributes<HTMLDivElement> {
|
|
336
|
+
_active?: boolean;
|
|
337
|
+
_completed?: boolean;
|
|
338
|
+
_error?: boolean;
|
|
339
|
+
_index?: number;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
const StepDescription = forwardRef<HTMLDivElement, StepDescriptionProps>(
|
|
343
|
+
(
|
|
344
|
+
{ className, _active, _completed: _c, _error: _e, _index: _i, ...props },
|
|
345
|
+
ref,
|
|
346
|
+
) => (
|
|
347
|
+
<div
|
|
348
|
+
ref={ref}
|
|
349
|
+
className={cn(
|
|
350
|
+
"typography-body-small-regular",
|
|
351
|
+
_active
|
|
352
|
+
? "text-content-presentation-global-secondary"
|
|
353
|
+
: "text-content-presentation-state-disabled",
|
|
354
|
+
className,
|
|
355
|
+
)}
|
|
356
|
+
{...props}
|
|
357
|
+
/>
|
|
358
|
+
),
|
|
359
|
+
);
|
|
360
|
+
StepDescription.displayName = "StepDescription";
|
|
361
|
+
|
|
362
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
363
|
+
|
|
364
|
+
export {
|
|
365
|
+
Stepper,
|
|
366
|
+
Step,
|
|
367
|
+
StepIndicator,
|
|
368
|
+
StepConnector,
|
|
369
|
+
StepLabel,
|
|
370
|
+
StepDescription,
|
|
371
|
+
stepperStyles,
|
|
372
|
+
stepIndicatorStyles,
|
|
373
|
+
connectorStyles,
|
|
374
|
+
};
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import React, { forwardRef, HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
import { cva, type VariantProps } from "class-variance-authority";
|
|
3
|
+
import { cn } from "../utils/cn";
|
|
4
|
+
import { Themes } from "../utils/types";
|
|
5
|
+
|
|
6
|
+
// ─── Timeline Root ───────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
const timelineStyles = cva(["flex gap-0"], {
|
|
9
|
+
variants: {
|
|
10
|
+
orientation: {
|
|
11
|
+
vertical: "flex-col",
|
|
12
|
+
horizontal: "flex-row items-start",
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
defaultVariants: {
|
|
16
|
+
orientation: "vertical",
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
interface TimelineProps
|
|
21
|
+
extends HTMLAttributes<HTMLDivElement>,
|
|
22
|
+
VariantProps<typeof timelineStyles> {
|
|
23
|
+
theme?: Themes;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
const Timeline = forwardRef<HTMLDivElement, TimelineProps>(
|
|
27
|
+
({ className, orientation, theme, ...props }, ref) => (
|
|
28
|
+
<div
|
|
29
|
+
ref={ref}
|
|
30
|
+
data-theme={theme}
|
|
31
|
+
data-orientation={orientation ?? "vertical"}
|
|
32
|
+
className={cn(timelineStyles({ orientation }), className)}
|
|
33
|
+
{...props}
|
|
34
|
+
/>
|
|
35
|
+
)
|
|
36
|
+
);
|
|
37
|
+
Timeline.displayName = "Timeline";
|
|
38
|
+
|
|
39
|
+
// ─── Timeline Item ───────────────────────────────────────────────────────────
|
|
40
|
+
|
|
41
|
+
const timelineItemStyles = cva(["flex group/item"], {
|
|
42
|
+
variants: {
|
|
43
|
+
orientation: {
|
|
44
|
+
vertical: "flex-row gap-3",
|
|
45
|
+
horizontal: "flex-col items-center gap-3",
|
|
46
|
+
},
|
|
47
|
+
},
|
|
48
|
+
defaultVariants: {
|
|
49
|
+
orientation: "vertical",
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
interface TimelineItemProps extends HTMLAttributes<HTMLDivElement> {
|
|
54
|
+
orientation?: "vertical" | "horizontal";
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const TimelineItem = forwardRef<HTMLDivElement, TimelineItemProps>(
|
|
58
|
+
({ className, orientation = "vertical", ...props }, ref) => (
|
|
59
|
+
<div
|
|
60
|
+
ref={ref}
|
|
61
|
+
data-orientation={orientation}
|
|
62
|
+
className={cn(timelineItemStyles({ orientation }), className)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
)
|
|
66
|
+
);
|
|
67
|
+
TimelineItem.displayName = "TimelineItem";
|
|
68
|
+
|
|
69
|
+
// ─── Timeline Indicator ──────────────────────────────────────────────────────
|
|
70
|
+
|
|
71
|
+
const indicatorStyles = cva(
|
|
72
|
+
[
|
|
73
|
+
"flex items-center justify-center shrink-0 rounded-full",
|
|
74
|
+
"border",
|
|
75
|
+
"transition-all duration-200 ease-in-out",
|
|
76
|
+
"[&_i]:leading-none [&_i]:flex [&_i]:items-center [&_i]:justify-center",
|
|
77
|
+
],
|
|
78
|
+
{
|
|
79
|
+
variants: {
|
|
80
|
+
variant: {
|
|
81
|
+
default: [
|
|
82
|
+
"bg-background-presentation-action-secondary",
|
|
83
|
+
"border-border-presentation-action-primary",
|
|
84
|
+
"text-content-presentation-action-light-primary",
|
|
85
|
+
],
|
|
86
|
+
active: [
|
|
87
|
+
"bg-background-presentation-state-information-primary",
|
|
88
|
+
"border-border-presentation-state-focus",
|
|
89
|
+
"text-content-presentation-state-information",
|
|
90
|
+
],
|
|
91
|
+
completed: [
|
|
92
|
+
"bg-background-presentation-state-success-primary",
|
|
93
|
+
"border-border-presentation-state-success",
|
|
94
|
+
"text-content-presentation-state-success",
|
|
95
|
+
],
|
|
96
|
+
error: [
|
|
97
|
+
"bg-background-presentation-state-negative-primary",
|
|
98
|
+
"border-border-presentation-state-negative",
|
|
99
|
+
"text-content-presentation-state-negative",
|
|
100
|
+
],
|
|
101
|
+
warning: [
|
|
102
|
+
"bg-background-presentation-state-warning-primary",
|
|
103
|
+
"border-border-presentation-state-warning",
|
|
104
|
+
"text-content-presentation-state-warning",
|
|
105
|
+
],
|
|
106
|
+
},
|
|
107
|
+
size: {
|
|
108
|
+
S: "w-[22px] h-[22px] [&_i]:text-[12px]",
|
|
109
|
+
M: "w-[28px] h-[28px] [&_i]:text-[14px]",
|
|
110
|
+
L: "w-[34px] h-[34px] [&_i]:text-[16px]",
|
|
111
|
+
},
|
|
112
|
+
},
|
|
113
|
+
defaultVariants: {
|
|
114
|
+
variant: "default",
|
|
115
|
+
size: "M",
|
|
116
|
+
},
|
|
117
|
+
}
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
interface TimelineIndicatorProps
|
|
121
|
+
extends HTMLAttributes<HTMLDivElement>,
|
|
122
|
+
VariantProps<typeof indicatorStyles> {
|
|
123
|
+
icon?: ReactNode;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const TimelineIndicator = forwardRef<HTMLDivElement, TimelineIndicatorProps>(
|
|
127
|
+
({ className, variant, size, icon, children, ...props }, ref) => {
|
|
128
|
+
const renderContent = () => {
|
|
129
|
+
if (icon) return icon;
|
|
130
|
+
if (children) return children;
|
|
131
|
+
if (variant === "completed") return <i className="ri-check-line" />;
|
|
132
|
+
if (variant === "error") return <i className="ri-close-line" />;
|
|
133
|
+
if (variant === "warning") return <i className="ri-alert-line" />;
|
|
134
|
+
return <span className="block w-[6px] h-[6px] rounded-full bg-current" />;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
return (
|
|
138
|
+
<div
|
|
139
|
+
ref={ref}
|
|
140
|
+
className={cn(indicatorStyles({ variant, size }), className)}
|
|
141
|
+
{...props}
|
|
142
|
+
>
|
|
143
|
+
{renderContent()}
|
|
144
|
+
</div>
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
);
|
|
148
|
+
TimelineIndicator.displayName = "TimelineIndicator";
|
|
149
|
+
|
|
150
|
+
// ─── Timeline Separator (the connecting line) ────────────────────────────────
|
|
151
|
+
|
|
152
|
+
const separatorStyles = cva(
|
|
153
|
+
[
|
|
154
|
+
"bg-border-presentation-global-primary",
|
|
155
|
+
"transition-all duration-200 ease-in-out",
|
|
156
|
+
],
|
|
157
|
+
{
|
|
158
|
+
variants: {
|
|
159
|
+
orientation: {
|
|
160
|
+
vertical: "w-[1px] flex-1 min-h-[24px] mx-auto",
|
|
161
|
+
horizontal: "h-[1px] flex-1 min-w-[24px] my-auto",
|
|
162
|
+
},
|
|
163
|
+
active: {
|
|
164
|
+
true: "bg-border-presentation-state-focus",
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
defaultVariants: {
|
|
168
|
+
orientation: "vertical",
|
|
169
|
+
active: false,
|
|
170
|
+
},
|
|
171
|
+
}
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
interface TimelineSeparatorProps
|
|
175
|
+
extends HTMLAttributes<HTMLDivElement>,
|
|
176
|
+
VariantProps<typeof separatorStyles> {}
|
|
177
|
+
|
|
178
|
+
const TimelineSeparator = forwardRef<HTMLDivElement, TimelineSeparatorProps>(
|
|
179
|
+
({ className, orientation = "vertical", active, ...props }, ref) => (
|
|
180
|
+
<div
|
|
181
|
+
ref={ref}
|
|
182
|
+
className={cn(separatorStyles({ orientation, active }), className)}
|
|
183
|
+
{...props}
|
|
184
|
+
/>
|
|
185
|
+
)
|
|
186
|
+
);
|
|
187
|
+
TimelineSeparator.displayName = "TimelineSeparator";
|
|
188
|
+
|
|
189
|
+
// ─── Timeline Connector (indicator + line container) ─────────────────────────
|
|
190
|
+
|
|
191
|
+
interface TimelineConnectorProps extends HTMLAttributes<HTMLDivElement> {
|
|
192
|
+
orientation?: "vertical" | "horizontal";
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const TimelineConnector = forwardRef<HTMLDivElement, TimelineConnectorProps>(
|
|
196
|
+
({ className, orientation = "vertical", children, ...props }, ref) => (
|
|
197
|
+
<div
|
|
198
|
+
ref={ref}
|
|
199
|
+
className={cn(
|
|
200
|
+
"flex items-center",
|
|
201
|
+
orientation === "vertical"
|
|
202
|
+
? "flex-col"
|
|
203
|
+
: "flex-row",
|
|
204
|
+
className
|
|
205
|
+
)}
|
|
206
|
+
{...props}
|
|
207
|
+
>
|
|
208
|
+
{children}
|
|
209
|
+
</div>
|
|
210
|
+
)
|
|
211
|
+
);
|
|
212
|
+
TimelineConnector.displayName = "TimelineConnector";
|
|
213
|
+
|
|
214
|
+
// ─── Timeline Content ────────────────────────────────────────────────────────
|
|
215
|
+
|
|
216
|
+
interface TimelineContentProps extends HTMLAttributes<HTMLDivElement> {}
|
|
217
|
+
|
|
218
|
+
const TimelineContent = forwardRef<HTMLDivElement, TimelineContentProps>(
|
|
219
|
+
({ className, ...props }, ref) => (
|
|
220
|
+
<div
|
|
221
|
+
ref={ref}
|
|
222
|
+
className={cn(
|
|
223
|
+
"flex flex-col gap-1 pb-6 pt-[2px]",
|
|
224
|
+
"group-last/item:pb-0",
|
|
225
|
+
className
|
|
226
|
+
)}
|
|
227
|
+
{...props}
|
|
228
|
+
/>
|
|
229
|
+
)
|
|
230
|
+
);
|
|
231
|
+
TimelineContent.displayName = "TimelineContent";
|
|
232
|
+
|
|
233
|
+
// ─── Timeline Heading ────────────────────────────────────────────────────────
|
|
234
|
+
|
|
235
|
+
interface TimelineHeadingProps extends HTMLAttributes<HTMLDivElement> {}
|
|
236
|
+
|
|
237
|
+
const TimelineHeading = forwardRef<HTMLDivElement, TimelineHeadingProps>(
|
|
238
|
+
({ className, ...props }, ref) => (
|
|
239
|
+
<div
|
|
240
|
+
ref={ref}
|
|
241
|
+
className={cn(
|
|
242
|
+
"typography-body-medium-medium text-content-presentation-global-primary",
|
|
243
|
+
className
|
|
244
|
+
)}
|
|
245
|
+
{...props}
|
|
246
|
+
/>
|
|
247
|
+
)
|
|
248
|
+
);
|
|
249
|
+
TimelineHeading.displayName = "TimelineHeading";
|
|
250
|
+
|
|
251
|
+
// ─── Timeline Description ────────────────────────────────────────────────────
|
|
252
|
+
|
|
253
|
+
interface TimelineDescriptionProps extends HTMLAttributes<HTMLDivElement> {}
|
|
254
|
+
|
|
255
|
+
const TimelineDescription = forwardRef<HTMLDivElement, TimelineDescriptionProps>(
|
|
256
|
+
({ className, ...props }, ref) => (
|
|
257
|
+
<div
|
|
258
|
+
ref={ref}
|
|
259
|
+
className={cn(
|
|
260
|
+
"typography-body-small-regular text-content-presentation-global-secondary",
|
|
261
|
+
className
|
|
262
|
+
)}
|
|
263
|
+
{...props}
|
|
264
|
+
/>
|
|
265
|
+
)
|
|
266
|
+
);
|
|
267
|
+
TimelineDescription.displayName = "TimelineDescription";
|
|
268
|
+
|
|
269
|
+
// ─── Exports ─────────────────────────────────────────────────────────────────
|
|
270
|
+
|
|
271
|
+
export {
|
|
272
|
+
Timeline,
|
|
273
|
+
TimelineItem,
|
|
274
|
+
TimelineIndicator,
|
|
275
|
+
TimelineSeparator,
|
|
276
|
+
TimelineConnector,
|
|
277
|
+
TimelineContent,
|
|
278
|
+
TimelineHeading,
|
|
279
|
+
TimelineDescription,
|
|
280
|
+
timelineStyles,
|
|
281
|
+
indicatorStyles,
|
|
282
|
+
separatorStyles,
|
|
283
|
+
};
|
package/apps/lib/utils/types.ts
CHANGED
|
@@ -2,11 +2,15 @@ export type Themes = "dark" | "light" | "default";
|
|
|
2
2
|
|
|
3
3
|
export type ButtonVariant =
|
|
4
4
|
| "PrimeStyle"
|
|
5
|
-
| "
|
|
5
|
+
| "BluSecStyle"
|
|
6
6
|
| "YelSecStyle"
|
|
7
7
|
| "RedSecStyle"
|
|
8
8
|
| "BorderStyle"
|
|
9
9
|
| "PrimeContStyle"
|
|
10
|
-
| "
|
|
11
|
-
| "RedContStyle"
|
|
12
|
-
|
|
10
|
+
| "BluContStyle"
|
|
11
|
+
| "RedContStyle"
|
|
12
|
+
| "PrimeColStyle"
|
|
13
|
+
| "BluColStyle"
|
|
14
|
+
| "RedColStyle"
|
|
15
|
+
| "GreenColStyle"
|
|
16
|
+
| "YelColStyle";
|