@aristobyte-ui/dropdown 1.0.0 → 1.0.2
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/package.json +5 -2
- package/@types/index.d.ts +0 -4
- package/@types/styles/scss-modules.d.ts +0 -4
- package/assets/svg/i_Copy.svg +0 -1
- package/assets/svg/i_Error.svg +0 -1
- package/assets/svg/i_Info.svg +0 -1
- package/assets/svg/i_Success.svg +0 -1
- package/assets/svg/i_Warning.svg +0 -1
- package/components/Dropdown/Dropdown.module.scss +0 -41
- package/components/Dropdown/index.tsx +0 -175
- package/components/DropdownOption/DropdownOption.module.scss +0 -24
- package/components/DropdownOption/index.tsx +0 -33
- package/components/index.ts +0 -2
- package/eslint.config.mjs +0 -2
- package/index.ts +0 -1
- package/styles/_settings.scss +0 -179
- package/tsconfig.json +0 -11
- package/turbo/generators/config.ts +0 -30
- package/turbo/generators/templates/component.hbs +0 -8
- package/utils/Portal.tsx +0 -17
- package/utils/icons.ts +0 -13
- package/utils/index.ts +0 -2
- package/utils/ripple.tsx +0 -54
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aristobyte-ui/dropdown",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.esm.js",
|
|
7
7
|
"types": "dist/types/index.d.ts",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
8
11
|
"exports": {
|
|
9
12
|
".": {
|
|
10
13
|
"import": "./dist/index.esm.js",
|
|
@@ -31,7 +34,7 @@
|
|
|
31
34
|
"typescript": "^5.8.3"
|
|
32
35
|
},
|
|
33
36
|
"dependencies": {
|
|
34
|
-
"@aristobyte-ui/button": "^1.0.
|
|
37
|
+
"@aristobyte-ui/button": "^1.0.4",
|
|
35
38
|
"@aristobyte-ui/eslint-config": "^1.0.0",
|
|
36
39
|
"@aristobyte-ui/jest-config": "^1.0.0",
|
|
37
40
|
"@aristobyte-ui/typescript-config": "1.0.1",
|
package/@types/index.d.ts
DELETED
package/assets/svg/i_Copy.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-copy-icon lucide-copy"><rect width="14" height="14" x="8" y="8" rx="2" ry="2"/><path d="M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2"/></svg>
|
package/assets/svg/i_Error.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-octagon-x-icon lucide-octagon-x"><path d="m15 9-6 6"/><path d="M2.586 16.726A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2h6.624a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586z"/><path d="m9 9 6 6"/></svg>
|
package/assets/svg/i_Info.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-info-icon lucide-info"><circle cx="12" cy="12" r="10"/><path d="M12 16v-4"/><path d="M12 8h.01"/></svg>
|
package/assets/svg/i_Success.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-circle-check-icon lucide-circle-check"><circle cx="12" cy="12" r="10"/><path d="m9 12 2 2 4-4"/></svg>
|
package/assets/svg/i_Warning.svg
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-octagon-alert-icon lucide-octagon-alert"><path d="M12 16h.01"/><path d="M12 8v4"/><path d="M15.312 2a2 2 0 0 1 1.414.586l4.688 4.688A2 2 0 0 1 22 8.688v6.624a2 2 0 0 1-.586 1.414l-4.688 4.688a2 2 0 0 1-1.414.586H8.688a2 2 0 0 1-1.414-.586l-4.688-4.688A2 2 0 0 1 2 15.312V8.688a2 2 0 0 1 .586-1.414l4.688-4.688A2 2 0 0 1 8.688 2z"/></svg>
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
@use "../../styles/settings" as *;
|
|
2
|
-
|
|
3
|
-
.dropdown {
|
|
4
|
-
width: max-content;
|
|
5
|
-
|
|
6
|
-
&__button {
|
|
7
|
-
width: max-content;
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
&__box {
|
|
11
|
-
&-overlay {
|
|
12
|
-
backdrop-filter: blur(12px);
|
|
13
|
-
height: 100%;
|
|
14
|
-
left: 0;
|
|
15
|
-
position: fixed;
|
|
16
|
-
top: 0;
|
|
17
|
-
width: 100%;
|
|
18
|
-
z-index: 99999999999;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
&-options {
|
|
22
|
-
align-items: flex-start;
|
|
23
|
-
background-color: $color-default;
|
|
24
|
-
border-radius: 8px; //TODO: change to dynamic
|
|
25
|
-
box-shadow:
|
|
26
|
-
0 4px 6px rgba(0, 0, 0, 0.04),
|
|
27
|
-
0 12px 24px rgba(0, 0, 0, 0.1);
|
|
28
|
-
display: flex;
|
|
29
|
-
flex-direction: column;
|
|
30
|
-
opacity: 1;
|
|
31
|
-
min-width: 300px;
|
|
32
|
-
padding: 4px;
|
|
33
|
-
position: absolute;
|
|
34
|
-
transition:
|
|
35
|
-
transform 200ms $cubic-bezier-secondary,
|
|
36
|
-
opacity 150ms ease;
|
|
37
|
-
width: 100%;
|
|
38
|
-
z-index: 99999999999;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
@@ -1,175 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { DropdownOption, type IDropdownOption } from "../DropdownOption";
|
|
5
|
-
|
|
6
|
-
import { AnimatePresence, motion } from "framer-motion";
|
|
7
|
-
|
|
8
|
-
import { Button } from "@aristobyte-ui/button";
|
|
9
|
-
import { Portal } from "../../utils/Portal";
|
|
10
|
-
|
|
11
|
-
import styles from "./Dropdown.module.scss";
|
|
12
|
-
|
|
13
|
-
export interface IDropdown {
|
|
14
|
-
children:
|
|
15
|
-
| React.ReactElement<IDropdownOption>
|
|
16
|
-
| React.ReactElement<IDropdownOption>[];
|
|
17
|
-
value: string;
|
|
18
|
-
appearance?:
|
|
19
|
-
| "solid"
|
|
20
|
-
| "outline"
|
|
21
|
-
| "outline-dashed"
|
|
22
|
-
| "no-outline"
|
|
23
|
-
| "glowing";
|
|
24
|
-
onChange?: (newValue: string) => void;
|
|
25
|
-
initiallyOpened?: boolean;
|
|
26
|
-
placeholder?: string;
|
|
27
|
-
disabled?: boolean;
|
|
28
|
-
className?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
type PositionType = {
|
|
32
|
-
top: 0;
|
|
33
|
-
left: 0;
|
|
34
|
-
width: 0;
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
export const Dropdown: React.FC<IDropdown> = ({
|
|
38
|
-
children,
|
|
39
|
-
value,
|
|
40
|
-
onChange,
|
|
41
|
-
appearance = "outline",
|
|
42
|
-
placeholder = "Select",
|
|
43
|
-
className = "",
|
|
44
|
-
initiallyOpened = false,
|
|
45
|
-
disabled = false,
|
|
46
|
-
}) => {
|
|
47
|
-
const [isOpened, setIsOpened] = React.useState<boolean>(initiallyOpened);
|
|
48
|
-
const [selected, setSelected] = React.useState<string>(value);
|
|
49
|
-
const [position, setPosition] = React.useState<PositionType>({
|
|
50
|
-
top: 0,
|
|
51
|
-
left: 0,
|
|
52
|
-
width: 0,
|
|
53
|
-
});
|
|
54
|
-
const [dropdownHeight, setDropdownHeight] = React.useState(0);
|
|
55
|
-
const [buttonHeight, setButtonHeight] = React.useState(0);
|
|
56
|
-
const buttonRef = React.useRef<HTMLButtonElement>(null);
|
|
57
|
-
const boxRef = React.useRef<HTMLDivElement>(null);
|
|
58
|
-
const uniqueId = React.useId();
|
|
59
|
-
|
|
60
|
-
React.useLayoutEffect(() => {
|
|
61
|
-
if (!isOpened) {
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
if (boxRef.current) {
|
|
66
|
-
setDropdownHeight(boxRef.current.getBoundingClientRect().height);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
if (buttonRef.current) {
|
|
70
|
-
setButtonHeight(buttonRef.current.getBoundingClientRect().height);
|
|
71
|
-
}
|
|
72
|
-
}, [isOpened]);
|
|
73
|
-
|
|
74
|
-
const options = React.Children.toArray(children).filter(
|
|
75
|
-
(child): child is React.ReactElement<IDropdownOption> =>
|
|
76
|
-
React.isValidElement(child) && child.type === DropdownOption
|
|
77
|
-
);
|
|
78
|
-
|
|
79
|
-
const isValidValue = () => {
|
|
80
|
-
return !!options.find(({ props }) => props.value === value);
|
|
81
|
-
};
|
|
82
|
-
|
|
83
|
-
const handleChange = (currentRadioValue: string) => {
|
|
84
|
-
onChange?.(currentRadioValue);
|
|
85
|
-
setSelected(currentRadioValue);
|
|
86
|
-
setIsOpened(false);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
const handleToggle = () => {
|
|
90
|
-
if (disabled) return;
|
|
91
|
-
|
|
92
|
-
const rect = buttonRef.current?.getBoundingClientRect();
|
|
93
|
-
if (!rect) return;
|
|
94
|
-
|
|
95
|
-
const spaceBelow = window.innerHeight - rect.bottom;
|
|
96
|
-
const spaceAbove = rect.top;
|
|
97
|
-
|
|
98
|
-
const shouldOpenUpwards =
|
|
99
|
-
dropdownHeight > 0 &&
|
|
100
|
-
spaceBelow < dropdownHeight &&
|
|
101
|
-
spaceAbove > dropdownHeight;
|
|
102
|
-
|
|
103
|
-
const finalPosition = {
|
|
104
|
-
top: shouldOpenUpwards
|
|
105
|
-
? rect.top + window.scrollY - dropdownHeight - buttonHeight / 2
|
|
106
|
-
: rect.top + window.scrollY + buttonHeight + 6,
|
|
107
|
-
left: rect.left + window.scrollX,
|
|
108
|
-
width: rect.width,
|
|
109
|
-
} as PositionType;
|
|
110
|
-
|
|
111
|
-
setPosition(finalPosition);
|
|
112
|
-
setIsOpened((prev) => !prev);
|
|
113
|
-
};
|
|
114
|
-
|
|
115
|
-
if (!isValidValue()) {
|
|
116
|
-
throw new Error(
|
|
117
|
-
'The "value" prop did not match with any of the DropdownOption "value" prop'
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return (
|
|
122
|
-
<>
|
|
123
|
-
<div className={`${styles["dropdown"]} ${className}`}>
|
|
124
|
-
<Button
|
|
125
|
-
{...{ ref: buttonRef }}
|
|
126
|
-
className={styles["dropdown__button"]}
|
|
127
|
-
appearance={appearance}
|
|
128
|
-
onClick={handleToggle}
|
|
129
|
-
disabled={disabled}
|
|
130
|
-
>
|
|
131
|
-
{placeholder}
|
|
132
|
-
</Button>
|
|
133
|
-
</div>
|
|
134
|
-
|
|
135
|
-
<Portal>
|
|
136
|
-
<AnimatePresence>
|
|
137
|
-
{isOpened && (
|
|
138
|
-
<div className={styles["dropdown__box"]}>
|
|
139
|
-
<motion.div
|
|
140
|
-
className={styles["dropdown__box-overlay"]}
|
|
141
|
-
initial={{ opacity: 0 }}
|
|
142
|
-
animate={{ opacity: 1 }}
|
|
143
|
-
exit={{ opacity: 0 }}
|
|
144
|
-
transition={{ duration: 0.3, ease: "easeIn" }}
|
|
145
|
-
onClick={() => setIsOpened(false)}
|
|
146
|
-
/>
|
|
147
|
-
<motion.div
|
|
148
|
-
ref={boxRef}
|
|
149
|
-
className={styles["dropdown__box-options"]}
|
|
150
|
-
initial={{ opacity: 0, y: 20, scale: 0.95 }}
|
|
151
|
-
animate={{ opacity: 1, y: 0, scale: 1 }}
|
|
152
|
-
exit={{ opacity: 0, y: 20, scale: 0.95 }}
|
|
153
|
-
transition={{ duration: 0.2, ease: "easeIn" }}
|
|
154
|
-
style={{
|
|
155
|
-
top: position.top,
|
|
156
|
-
left: position.left,
|
|
157
|
-
width: position.width,
|
|
158
|
-
}}
|
|
159
|
-
>
|
|
160
|
-
{options.map(({ props }) => (
|
|
161
|
-
<DropdownOption
|
|
162
|
-
{...props}
|
|
163
|
-
key={`${props.value}-${uniqueId}`}
|
|
164
|
-
selectedValue={selected}
|
|
165
|
-
onChange={() => handleChange(props.value)}
|
|
166
|
-
/>
|
|
167
|
-
))}
|
|
168
|
-
</motion.div>
|
|
169
|
-
</div>
|
|
170
|
-
)}
|
|
171
|
-
</AnimatePresence>
|
|
172
|
-
</Portal>
|
|
173
|
-
</>
|
|
174
|
-
);
|
|
175
|
-
};
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
@use "../../styles/settings" as *;
|
|
2
|
-
|
|
3
|
-
.dropdown-option {
|
|
4
|
-
border-radius: 8px; //TODO: change to dynamic
|
|
5
|
-
color: $white;
|
|
6
|
-
font-size: 14px;
|
|
7
|
-
font-weight: 500;
|
|
8
|
-
padding: 10px 16px;
|
|
9
|
-
text-align: left;
|
|
10
|
-
transition: all 120ms ease-out;
|
|
11
|
-
width: 100%;
|
|
12
|
-
|
|
13
|
-
&:hover {
|
|
14
|
-
background-color: $color-default-hover;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
&__title {
|
|
18
|
-
color: $white;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
&__description {
|
|
22
|
-
color: rgba($white, 0.6);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import * as React from "react";
|
|
2
|
-
|
|
3
|
-
import styles from "./DropdownOption.module.scss";
|
|
4
|
-
|
|
5
|
-
export interface IDropdownOption {
|
|
6
|
-
children: string;
|
|
7
|
-
value: string;
|
|
8
|
-
onChange?: () => void;
|
|
9
|
-
selectedValue?: string;
|
|
10
|
-
description?: string;
|
|
11
|
-
icon?: string;
|
|
12
|
-
disabled?: boolean;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export const DropdownOption: React.FC<IDropdownOption> = ({
|
|
16
|
-
children,
|
|
17
|
-
// value,
|
|
18
|
-
// selectedValue,
|
|
19
|
-
onChange,
|
|
20
|
-
// icon,
|
|
21
|
-
description,
|
|
22
|
-
// disabled,
|
|
23
|
-
}) => {
|
|
24
|
-
// const isSelected = selectedValue === value;
|
|
25
|
-
return (
|
|
26
|
-
<button className={styles["dropdown-option"]} onClick={onChange}>
|
|
27
|
-
<div className={styles["dropdown-option__content"]}>
|
|
28
|
-
<h3 className={styles["dropdown-option__title"]}>{children}</h3>
|
|
29
|
-
<p className={styles["dropdown-option__description"]}>{description}</p>
|
|
30
|
-
</div>
|
|
31
|
-
</button>
|
|
32
|
-
);
|
|
33
|
-
};
|
package/components/index.ts
DELETED
package/eslint.config.mjs
DELETED
package/index.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export { Dropdown, DropdownOption } from "./components";
|
package/styles/_settings.scss
DELETED
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
// === Design Tokens — Color Palette ===
|
|
2
|
-
|
|
3
|
-
// Base
|
|
4
|
-
$white: #ffffff;
|
|
5
|
-
$black: #000000;
|
|
6
|
-
$transparent: transparent;
|
|
7
|
-
|
|
8
|
-
// === Black Transparent Scale ===
|
|
9
|
-
$black-transparent-100: rgba(0, 0, 0, 0.1);
|
|
10
|
-
$black-transparent-200: rgba(0, 0, 0, 0.2);
|
|
11
|
-
$black-transparent-300: rgba(0, 0, 0, 0.3);
|
|
12
|
-
$black-transparent-400: rgba(0, 0, 0, 0.4);
|
|
13
|
-
$black-transparent-500: rgba(0, 0, 0, 0.5);
|
|
14
|
-
$black-transparent-600: rgba(0, 0, 0, 0.6);
|
|
15
|
-
$black-transparent-700: rgba(0, 0, 0, 0.7);
|
|
16
|
-
$black-transparent-800: rgba(0, 0, 0, 0.8);
|
|
17
|
-
$black-transparent-900: rgba(0, 0, 0, 0.9);
|
|
18
|
-
|
|
19
|
-
// === Black Transparent Scale ===
|
|
20
|
-
$white-transparent-100: rgba(255, 255, 255, 0.1);
|
|
21
|
-
$white-transparent-200: rgba(255, 255, 255, 0.2);
|
|
22
|
-
$white-transparent-300: rgba(255, 255, 255, 0.3);
|
|
23
|
-
$white-transparent-400: rgba(255, 255, 255, 0.4);
|
|
24
|
-
$white-transparent-500: rgba(255, 255, 255, 0.5);
|
|
25
|
-
$white-transparent-600: rgba(255, 255, 255, 0.6);
|
|
26
|
-
$white-transparent-700: rgba(255, 255, 255, 0.7);
|
|
27
|
-
$white-transparent-800: rgba(255, 255, 255, 0.8);
|
|
28
|
-
$white-transparent-900: rgba(255, 255, 255, 0.9);
|
|
29
|
-
|
|
30
|
-
// === Neutral Scale (Grey) ===
|
|
31
|
-
$grey-50: #f9fafb;
|
|
32
|
-
$grey-100: #f3f4f6;
|
|
33
|
-
$grey-200: #e5e7eb;
|
|
34
|
-
$grey-300: #d1d5db;
|
|
35
|
-
$grey-400: #9ca3af;
|
|
36
|
-
$grey-500: #6b7280;
|
|
37
|
-
$grey-600: #4b5563;
|
|
38
|
-
$grey-700: #374151;
|
|
39
|
-
$grey-800: #1f2937;
|
|
40
|
-
$grey-900: #111827;
|
|
41
|
-
|
|
42
|
-
// === Primary Scale (Blue) ===
|
|
43
|
-
$blue-50: #eff6ff;
|
|
44
|
-
$blue-100: #dbeafe;
|
|
45
|
-
$blue-200: #bfdbfe;
|
|
46
|
-
$blue-300: #93c5fd;
|
|
47
|
-
$blue-400: #60a5fa;
|
|
48
|
-
$blue-500: #3b82f6;
|
|
49
|
-
$blue-600: #2563eb; // Main
|
|
50
|
-
$blue-700: #1d4ed8; // Hover
|
|
51
|
-
$blue-800: #1e40af;
|
|
52
|
-
$blue-900: #1e3a8a;
|
|
53
|
-
|
|
54
|
-
// === Secondary Scale (Indigo) ===
|
|
55
|
-
$indigo-50: #eef2ff;
|
|
56
|
-
$indigo-100: #e0e7ff;
|
|
57
|
-
$indigo-200: #c7d2fe;
|
|
58
|
-
$indigo-300: #a5b4fc;
|
|
59
|
-
$indigo-400: #818cf8;
|
|
60
|
-
$indigo-500: #6366f1;
|
|
61
|
-
$indigo-600: #4f46e5; // Main
|
|
62
|
-
$indigo-700: #4338ca; // Hover
|
|
63
|
-
|
|
64
|
-
// === Error Scale (Red) ===
|
|
65
|
-
$red-50: #fef2f2;
|
|
66
|
-
$red-100: #fee2e2;
|
|
67
|
-
$red-200: #fecaca;
|
|
68
|
-
$red-300: #fca5a5;
|
|
69
|
-
$red-400: #f87171;
|
|
70
|
-
$red-500: #ef4444;
|
|
71
|
-
$red-600: #dc2626; // Main
|
|
72
|
-
$red-700: #b91c1c; // Hover
|
|
73
|
-
|
|
74
|
-
// === Success Scale (Green) ===
|
|
75
|
-
$green-50: #f0fdf4;
|
|
76
|
-
$green-100: #dcfce7;
|
|
77
|
-
$green-200: #bbf7d0;
|
|
78
|
-
$green-300: #86efac;
|
|
79
|
-
$green-400: #4ade80;
|
|
80
|
-
$green-500: #22c55e;
|
|
81
|
-
$green-600: #16a34a; // Main
|
|
82
|
-
$green-700: #15803d; // Hover
|
|
83
|
-
|
|
84
|
-
// === Warning Scale (Amber) ===
|
|
85
|
-
$amber-50: #fffbeb;
|
|
86
|
-
$amber-100: #fef3c7;
|
|
87
|
-
$amber-200: #fde68a;
|
|
88
|
-
$amber-300: #fcd34d;
|
|
89
|
-
$amber-400: #fbbf24;
|
|
90
|
-
$amber-500: #f59e0b;
|
|
91
|
-
$amber-600: #d97706; // Main
|
|
92
|
-
$amber-700: #b45309; // Hover
|
|
93
|
-
|
|
94
|
-
// === Semantic Tokens ===
|
|
95
|
-
$color-default: $grey-800;
|
|
96
|
-
$color-default-hover: $grey-900;
|
|
97
|
-
$color-default-disabled: rgba($color-default, 0.5);
|
|
98
|
-
|
|
99
|
-
$color-primary: $blue-600;
|
|
100
|
-
$color-primary-hover: $blue-700;
|
|
101
|
-
$color-primary-disabled: rgba($color-primary, 0.5);
|
|
102
|
-
|
|
103
|
-
$color-secondary: $indigo-600;
|
|
104
|
-
$color-secondary-hover: $indigo-700;
|
|
105
|
-
$color-secondary-disabled: rgba($color-secondary, 0.5);
|
|
106
|
-
|
|
107
|
-
$color-error: $red-600;
|
|
108
|
-
$color-error-hover: $red-700;
|
|
109
|
-
$color-error-disabled: rgba($color-error, 0.5);
|
|
110
|
-
|
|
111
|
-
$color-success: $green-600;
|
|
112
|
-
$color-success-hover: $green-700;
|
|
113
|
-
$color-success-disabled: rgba($color-success, 0.5);
|
|
114
|
-
|
|
115
|
-
$color-warning: $amber-600;
|
|
116
|
-
$color-warning-hover: $amber-700;
|
|
117
|
-
$color-warning-disabled: rgba($color-warning, 0.5);
|
|
118
|
-
|
|
119
|
-
$text-color-white: $white;
|
|
120
|
-
$text-color-black: $black;
|
|
121
|
-
$text-color-white-disabled: rgba($white, 0.5);
|
|
122
|
-
$text-color-black-disabled: rgba($black, 0.5);
|
|
123
|
-
|
|
124
|
-
// === Shadows ===
|
|
125
|
-
$shadow-sm: 0 1px 2px 0 rgba($black, 0.05);
|
|
126
|
-
$shadow-md:
|
|
127
|
-
0 4px 6px -1px rgba($black, 0.1),
|
|
128
|
-
0 2px 4px -1px rgba($black, 0.06);
|
|
129
|
-
$shadow-lg:
|
|
130
|
-
0 10px 15px -3px rgba($black, 0.1),
|
|
131
|
-
0 4px 6px -2px rgba($black, 0.05);
|
|
132
|
-
|
|
133
|
-
// === Font families ===
|
|
134
|
-
$font-family-sans: "Inter", sans-serif;
|
|
135
|
-
$font-family-serif: "Georgia", serif;
|
|
136
|
-
$font-family-mono: "Fira Code", monospace;
|
|
137
|
-
|
|
138
|
-
// === Font weights ===
|
|
139
|
-
$font-weight-regular: 400;
|
|
140
|
-
$font-weight-medium: 500;
|
|
141
|
-
$font-weight-semibold: 600;
|
|
142
|
-
$font-weight-bold: 700;
|
|
143
|
-
|
|
144
|
-
// === Line heights ===
|
|
145
|
-
$line-height-tight: 1.2;
|
|
146
|
-
$line-height-snug: 1.375;
|
|
147
|
-
$line-height-normal: 1.5;
|
|
148
|
-
$line-height-loose: 1.625;
|
|
149
|
-
|
|
150
|
-
// === Font Sizes — Semantic Tokens ===
|
|
151
|
-
|
|
152
|
-
// === Titles ===
|
|
153
|
-
$font-size-hero: 3rem; // 48px
|
|
154
|
-
$font-size-title-1: 2.25rem; // 36px
|
|
155
|
-
$font-size-title-2: 1.875rem; // 30px
|
|
156
|
-
$font-size-title-3: 1.5rem; // 24px
|
|
157
|
-
|
|
158
|
-
// === Subtitles ===
|
|
159
|
-
$font-size-subtitle-1: 1.25rem; // 20px
|
|
160
|
-
$font-size-subtitle-2: 1.125rem; // 18px
|
|
161
|
-
|
|
162
|
-
// === Body text ===
|
|
163
|
-
$font-size-body-lg: 1rem; // 16px
|
|
164
|
-
$font-size-body-md: 0.9375rem; // 15px
|
|
165
|
-
$font-size-body-sm: 0.875rem; // 14px
|
|
166
|
-
|
|
167
|
-
// === Captions / Descriptions ===
|
|
168
|
-
$font-size-caption: 0.75rem; // 12px
|
|
169
|
-
$font-size-footnote: 0.6875rem; // 11px
|
|
170
|
-
|
|
171
|
-
// === Buttons ===
|
|
172
|
-
$font-size-button-lg: 1rem; // 16px
|
|
173
|
-
$font-size-button-md: 0.875rem; // 14px
|
|
174
|
-
$font-size-button-sm: 0.75rem; // 12px
|
|
175
|
-
|
|
176
|
-
// === Animations ===
|
|
177
|
-
|
|
178
|
-
$cubic-bezier-primary: cubic-bezier(0.55, -0.19, 0.59, 0.95);
|
|
179
|
-
$cubic-bezier-secondary: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
package/tsconfig.json
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "@aristobyte-ui/typescript-config/package",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "dist",
|
|
5
|
-
"declarationDir": "dist/types",
|
|
6
|
-
"baseUrl": ".",
|
|
7
|
-
"typeRoots": ["@types", "node_modules/@types"]
|
|
8
|
-
},
|
|
9
|
-
"include": ["@types", "components", "utils", "index.ts"],
|
|
10
|
-
"exclude": ["node_modules", "dist"]
|
|
11
|
-
}
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import type { PlopTypes } from "@turbo/gen";
|
|
2
|
-
|
|
3
|
-
// Learn more about Turborepo Generators at https://turborepo.com/docs/guides/generating-code
|
|
4
|
-
|
|
5
|
-
export default function generator(plop: PlopTypes.NodePlopAPI): void {
|
|
6
|
-
// A simple generator to add a new React component to the internal UI library
|
|
7
|
-
plop.setGenerator("react-component", {
|
|
8
|
-
description: "Adds a new react component",
|
|
9
|
-
prompts: [
|
|
10
|
-
{
|
|
11
|
-
type: "input",
|
|
12
|
-
name: "name",
|
|
13
|
-
message: "What is the name of the component?",
|
|
14
|
-
},
|
|
15
|
-
],
|
|
16
|
-
actions: [
|
|
17
|
-
{
|
|
18
|
-
type: "add",
|
|
19
|
-
path: "src/{{kebabCase name}}.tsx",
|
|
20
|
-
templateFile: "templates/component.hbs",
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: "append",
|
|
24
|
-
path: "package.json",
|
|
25
|
-
pattern: /"exports": {(?<insertion>)/g,
|
|
26
|
-
template: ' "./{{kebabCase name}}": "./src/{{kebabCase name}}.tsx",',
|
|
27
|
-
},
|
|
28
|
-
],
|
|
29
|
-
});
|
|
30
|
-
}
|
package/utils/Portal.tsx
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
|
|
3
|
-
import * as React from "react";
|
|
4
|
-
import { createPortal } from "react-dom";
|
|
5
|
-
|
|
6
|
-
export const Portal: React.FC<{ children: React.ReactNode }> = ({
|
|
7
|
-
children,
|
|
8
|
-
}) => {
|
|
9
|
-
const [mounted, setMounted] = React.useState(false);
|
|
10
|
-
|
|
11
|
-
React.useEffect(() => {
|
|
12
|
-
setMounted(true);
|
|
13
|
-
}, []);
|
|
14
|
-
|
|
15
|
-
if (!mounted || typeof window === "undefined") return null;
|
|
16
|
-
return createPortal(children, document.body);
|
|
17
|
-
};
|
package/utils/icons.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import Copy from "../assets/svg/i_Copy.svg";
|
|
2
|
-
import Error from "../assets/svg/i_Error.svg";
|
|
3
|
-
import Info from "../assets/svg/i_Info.svg";
|
|
4
|
-
import Success from "../assets/svg/i_Success.svg";
|
|
5
|
-
import Warning from "../assets/svg/i_Warning.svg";
|
|
6
|
-
|
|
7
|
-
export const Icons = {
|
|
8
|
-
Copy,
|
|
9
|
-
Error,
|
|
10
|
-
Info,
|
|
11
|
-
Success,
|
|
12
|
-
Warning,
|
|
13
|
-
};
|
package/utils/index.ts
DELETED
package/utils/ripple.tsx
DELETED
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
type RippleParamsRef = HTMLButtonElement | HTMLAnchorElement;
|
|
2
|
-
|
|
3
|
-
export type RippleParams<HTMLElementType extends RippleParamsRef> = {
|
|
4
|
-
ref: React.RefObject<HTMLElementType | null>;
|
|
5
|
-
clientX: number;
|
|
6
|
-
clientY: number;
|
|
7
|
-
};
|
|
8
|
-
|
|
9
|
-
export const renderRipple = <HTMLElementType extends RippleParamsRef>({
|
|
10
|
-
ref,
|
|
11
|
-
clientX,
|
|
12
|
-
clientY,
|
|
13
|
-
}: RippleParams<HTMLElementType>) => {
|
|
14
|
-
const button = ref.current;
|
|
15
|
-
if (!button) return;
|
|
16
|
-
|
|
17
|
-
const circle = document.createElement("span");
|
|
18
|
-
const diameter = Math.max(button.clientWidth, button.clientHeight);
|
|
19
|
-
const radius = diameter / 2;
|
|
20
|
-
|
|
21
|
-
circle.id = "ripple";
|
|
22
|
-
|
|
23
|
-
const style = document.createElement("style");
|
|
24
|
-
style.innerHTML = `
|
|
25
|
-
#ripple {
|
|
26
|
-
animation: ripple 300ms linear;
|
|
27
|
-
background-color: rgba(255, 255, 255, 0.3);
|
|
28
|
-
border-radius: 50%;
|
|
29
|
-
height: ${diameter}px;
|
|
30
|
-
left: ${clientX - button.getBoundingClientRect().left - radius}px;
|
|
31
|
-
pointer-events: none;
|
|
32
|
-
position: absolute;
|
|
33
|
-
top: ${clientY - button.getBoundingClientRect().top - radius}px;
|
|
34
|
-
transform: scale(0);
|
|
35
|
-
width: ${diameter}px;
|
|
36
|
-
z-index: 0;
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
@keyframes ripple {
|
|
40
|
-
to {
|
|
41
|
-
opacity: 0;
|
|
42
|
-
transform: scale(2);
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
`;
|
|
46
|
-
|
|
47
|
-
button.appendChild(style);
|
|
48
|
-
button.appendChild(circle);
|
|
49
|
-
|
|
50
|
-
circle.addEventListener("animationend", () => {
|
|
51
|
-
circle.remove();
|
|
52
|
-
style.remove();
|
|
53
|
-
});
|
|
54
|
-
};
|