@aristobyte-ui/spinner 0.0.0-beta.1

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 (79) hide show
  1. package/@types/index.d.ts +4 -0
  2. package/@types/styles/scss-modules.d.ts +4 -0
  3. package/assets/svg/i_Copy.svg +1 -0
  4. package/assets/svg/i_Error.svg +1 -0
  5. package/assets/svg/i_Info.svg +1 -0
  6. package/assets/svg/i_Success.svg +1 -0
  7. package/assets/svg/i_Warning.svg +1 -0
  8. package/components/Spinner/Spinner.module.scss +232 -0
  9. package/components/Spinner/index.tsx +31 -0
  10. package/components/index.ts +1 -0
  11. package/dist/components/Anchor/index.js +28 -0
  12. package/dist/components/Button/index.js +35 -0
  13. package/dist/components/ButtonGroup/index.js +16 -0
  14. package/dist/components/CodeBlock/index.js +33 -0
  15. package/dist/components/CodeBlock/types.js +1 -0
  16. package/dist/components/Dropdown/index.js +73 -0
  17. package/dist/components/DropdownOption/index.js +13 -0
  18. package/dist/components/MessageBox/index.js +19 -0
  19. package/dist/components/Radio/index.js +10 -0
  20. package/dist/components/RadioGroup/index.js +21 -0
  21. package/dist/components/Spinner/index.js +6 -0
  22. package/dist/components/Switch/index.js +15 -0
  23. package/dist/components/TabSwitchWithSlidingIndicator/index.js +10 -0
  24. package/dist/components/index.js +12 -0
  25. package/dist/index.js +1 -0
  26. package/dist/tsconfig.tsbuildinfo +1 -0
  27. package/dist/types/components/Anchor/index.d.ts +6 -0
  28. package/dist/types/components/Anchor/index.d.ts.map +1 -0
  29. package/dist/types/components/Button/index.d.ts +15 -0
  30. package/dist/types/components/Button/index.d.ts.map +1 -0
  31. package/dist/types/components/ButtonGroup/index.d.ts +13 -0
  32. package/dist/types/components/ButtonGroup/index.d.ts.map +1 -0
  33. package/dist/types/components/CodeBlock/index.d.ts +11 -0
  34. package/dist/types/components/CodeBlock/index.d.ts.map +1 -0
  35. package/dist/types/components/CodeBlock/types.d.ts +3 -0
  36. package/dist/types/components/CodeBlock/types.d.ts.map +1 -0
  37. package/dist/types/components/Dropdown/index.d.ts +14 -0
  38. package/dist/types/components/Dropdown/index.d.ts.map +1 -0
  39. package/dist/types/components/DropdownOption/index.d.ts +12 -0
  40. package/dist/types/components/DropdownOption/index.d.ts.map +1 -0
  41. package/dist/types/components/MessageBox/index.d.ts +14 -0
  42. package/dist/types/components/MessageBox/index.d.ts.map +1 -0
  43. package/dist/types/components/Radio/index.d.ts +17 -0
  44. package/dist/types/components/Radio/index.d.ts.map +1 -0
  45. package/dist/types/components/RadioGroup/index.d.ts +18 -0
  46. package/dist/types/components/RadioGroup/index.d.ts.map +1 -0
  47. package/dist/types/components/Spinner/index.d.ts +9 -0
  48. package/dist/types/components/Spinner/index.d.ts.map +1 -0
  49. package/dist/types/components/Switch/index.d.ts +18 -0
  50. package/dist/types/components/Switch/index.d.ts.map +1 -0
  51. package/dist/types/components/TabSwitchWithSlidingIndicator/index.d.ts +9 -0
  52. package/dist/types/components/TabSwitchWithSlidingIndicator/index.d.ts.map +1 -0
  53. package/dist/types/components/index.d.ts +2 -0
  54. package/dist/types/components/index.d.ts.map +1 -0
  55. package/dist/types/index.d.ts +2 -0
  56. package/dist/types/index.d.ts.map +1 -0
  57. package/dist/types/utils/Portal.d.ts +5 -0
  58. package/dist/types/utils/Portal.d.ts.map +1 -0
  59. package/dist/types/utils/icons.d.ts +8 -0
  60. package/dist/types/utils/icons.d.ts.map +1 -0
  61. package/dist/types/utils/index.d.ts +3 -0
  62. package/dist/types/utils/index.d.ts.map +1 -0
  63. package/dist/types/utils/ripple.d.ts +9 -0
  64. package/dist/types/utils/ripple.d.ts.map +1 -0
  65. package/dist/utils/Portal.js +12 -0
  66. package/dist/utils/icons.js +12 -0
  67. package/dist/utils/index.js +2 -0
  68. package/dist/utils/ripple.js +38 -0
  69. package/eslint.config.mjs +2 -0
  70. package/index.ts +1 -0
  71. package/package.json +43 -0
  72. package/styles/_settings.scss +179 -0
  73. package/tsconfig.json +11 -0
  74. package/turbo/generators/config.ts +30 -0
  75. package/turbo/generators/templates/component.hbs +8 -0
  76. package/utils/Portal.tsx +17 -0
  77. package/utils/icons.ts +13 -0
  78. package/utils/index.ts +2 -0
  79. package/utils/ripple.tsx +54 -0
@@ -0,0 +1,4 @@
1
+ declare module "*.svg" {
2
+ const content: React.FunctionComponent<React.SVGAttributes<SVGElement>>;
3
+ export default content;
4
+ }
@@ -0,0 +1,4 @@
1
+ declare module "*.module.scss" {
2
+ const classes: { [key: string]: string };
3
+ export default classes;
4
+ }
@@ -0,0 +1 @@
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>
@@ -0,0 +1 @@
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>
@@ -0,0 +1 @@
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>
@@ -0,0 +1 @@
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>
@@ -0,0 +1 @@
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>
@@ -0,0 +1,232 @@
1
+ @use "../../styles/settings" as *;
2
+
3
+ @keyframes rotation {
4
+ from {
5
+ transform: rotate(0deg);
6
+ }
7
+ to {
8
+ transform: rotate(360deg);
9
+ }
10
+ }
11
+
12
+ @keyframes pulse {
13
+ 0% {
14
+ opacity: 1;
15
+ transform: scale(0);
16
+ }
17
+ 100% {
18
+ opacity: 0;
19
+ transform: scale(1);
20
+ }
21
+ }
22
+
23
+ @keyframes pulse-duo {
24
+ 0%,
25
+ 100% {
26
+ opacity: 1;
27
+ transform: translate(-50%, -50%) scale(0);
28
+ }
29
+ 50% {
30
+ opacity: 0;
31
+ transform: translate(-50%, -50%) scale(1);
32
+ }
33
+ }
34
+
35
+ .spinner {
36
+ &-size {
37
+ &--xsm {
38
+ width: 1rem; // 16px
39
+ height: 1rem;
40
+ }
41
+
42
+ &--sm {
43
+ width: 1.5rem; // 24px
44
+ height: 1.5rem;
45
+ }
46
+
47
+ &--md {
48
+ width: 2rem; // 32px
49
+ height: 2rem;
50
+ }
51
+
52
+ &--lg {
53
+ width: 2.5rem; // 40px
54
+ height: 2.5rem;
55
+ }
56
+
57
+ &--xlg {
58
+ width: 3rem; // 48px
59
+ height: 3rem;
60
+ }
61
+ }
62
+
63
+ &-type {
64
+ &--default {
65
+ animation: rotation 800ms ease infinite;
66
+ border-radius: 50%;
67
+
68
+ &.spinner-variant {
69
+ &--default {
70
+ border: 3px solid rgba($color-default, 0.25);
71
+ border-top-color: rgba($color-default, 1);
72
+ }
73
+ &--primary {
74
+ border: 3px solid rgba($color-primary, 0.25);
75
+ border-top-color: rgba($color-primary, 1);
76
+ }
77
+ &--secondary {
78
+ border: 3px solid rgba($color-secondary, 0.25);
79
+ border-top-color: rgba($color-secondary, 1);
80
+ }
81
+ &--success {
82
+ border: 3px solid rgba($color-success, 0.25);
83
+ border-top-color: rgba($color-success, 1);
84
+ }
85
+ &--error {
86
+ border: 3px solid rgba($color-error, 0.25);
87
+ border-top-color: rgba($color-error, 1);
88
+ }
89
+ &--warning {
90
+ border: 3px solid rgba($color-warning, 0.25);
91
+ border-top-color: rgba($color-warning, 1);
92
+ }
93
+ }
94
+ }
95
+
96
+ &--duo {
97
+ animation: rotation 800ms ease infinite;
98
+ border: 3px solid transparent;
99
+ border-radius: 50%;
100
+
101
+ &.spinner-variant {
102
+ &--default {
103
+ border-bottom-color: rgba($color-default, 1);
104
+ border-top-color: rgba($color-default, 1);
105
+ }
106
+ &--primary {
107
+ border-bottom-color: rgba($color-primary, 1);
108
+ border-top-color: rgba($color-primary, 1);
109
+ }
110
+ &--secondary {
111
+ border-bottom-color: rgba($color-secondary, 1);
112
+ border-top-color: rgba($color-secondary, 1);
113
+ }
114
+ &--success {
115
+ border-bottom-color: rgba($color-success, 1);
116
+ border-top-color: rgba($color-success, 1);
117
+ }
118
+ &--error {
119
+ border-bottom-color: rgba($color-error, 1);
120
+ border-top-color: rgba($color-error, 1);
121
+ }
122
+ &--warning {
123
+ border-bottom-color: rgba($color-warning, 1);
124
+ border-top-color: rgba($color-warning, 1);
125
+ }
126
+ }
127
+ }
128
+
129
+ &--gradient {
130
+ animation: rotation 800ms linear infinite;
131
+ border-right: 3px solid transparent;
132
+ border-radius: 50%;
133
+
134
+ &.spinner-variant {
135
+ &--default {
136
+ border-top: 3px solid rgba($color-default, 1);
137
+ }
138
+ &--primary {
139
+ border-top: 3px solid rgba($color-primary, 1);
140
+ }
141
+ &--secondary {
142
+ border-top: 3px solid rgba($color-secondary, 1);
143
+ }
144
+ &--success {
145
+ border-top: 3px solid rgba($color-success, 1);
146
+ }
147
+ &--error {
148
+ border-top: 3px solid rgba($color-error, 1);
149
+ }
150
+ &--warning {
151
+ border-top: 3px solid rgba($color-warning, 1);
152
+ }
153
+ }
154
+ }
155
+
156
+ &--pulse {
157
+ animation: pulse 1s ease-in-out infinite;
158
+ border-radius: 50%;
159
+ position: relative;
160
+
161
+ &.spinner-variant {
162
+ &--default {
163
+ background-color: $color-default;
164
+ }
165
+ &--primary {
166
+ background-color: $color-primary;
167
+ }
168
+ &--secondary {
169
+ background-color: $color-secondary;
170
+ }
171
+ &--success {
172
+ background-color: $color-success;
173
+ }
174
+ &--error {
175
+ background-color: $color-error;
176
+ }
177
+ &--warning {
178
+ background-color: $color-warning;
179
+ }
180
+ }
181
+ }
182
+
183
+ &--pulse-duo {
184
+ position: relative;
185
+
186
+ &.spinner-variant {
187
+ &--default::after,
188
+ &--default::before {
189
+ background-color: $color-default;
190
+ }
191
+ &--primary::after,
192
+ &--primary::before {
193
+ background-color: $color-primary;
194
+ }
195
+ &--secondary::after,
196
+ &--secondary::before {
197
+ background-color: $color-secondary;
198
+ }
199
+ &--success::after,
200
+ &--success::before {
201
+ background-color: $color-success;
202
+ }
203
+ &--error::after,
204
+ &--error::before {
205
+ background-color: $color-error;
206
+ }
207
+ &--warning::after,
208
+ &--warning::before {
209
+ background-color: $color-warning;
210
+ }
211
+ }
212
+
213
+ &::before,
214
+ &::after {
215
+ content: "";
216
+ position: absolute;
217
+ top: 50%;
218
+ left: 50%;
219
+ width: 100%;
220
+ height: 100%;
221
+ border-radius: 50%;
222
+ transform: translate(-50%, -50%) scale(0);
223
+ }
224
+ &::before {
225
+ animation: pulse-duo 2s ease-in-out infinite;
226
+ }
227
+ &::after {
228
+ animation: pulse-duo 2s 1s ease-in-out infinite;
229
+ }
230
+ }
231
+ }
232
+ }
@@ -0,0 +1,31 @@
1
+ "use client";
2
+
3
+ import * as React from "react";
4
+
5
+ import styles from "./Spinner.module.scss";
6
+
7
+ export interface ISpinner {
8
+ type?: "default" | "duo" | "gradient" | "pulse" | "pulse-duo";
9
+ variant?:
10
+ | "default"
11
+ | "primary"
12
+ | "secondary"
13
+ | "success"
14
+ | "error"
15
+ | "warning";
16
+ size?: "xsm" | "sm" | "md" | "lg" | "xlg";
17
+ className?: string;
18
+ }
19
+
20
+ export const Spinner: React.FC<ISpinner> = ({
21
+ type = "default",
22
+ variant = "default",
23
+ size = "md",
24
+ className = "",
25
+ }) => {
26
+ return (
27
+ <div
28
+ className={`spinner ${styles[`spinner-type--${type}`]} ${styles[`spinner-variant--${variant}`]} ${styles[`spinner-size--${size}`]} ${className}`}
29
+ />
30
+ );
31
+ };
@@ -0,0 +1 @@
1
+ export { Spinner } from "./Spinner";
@@ -0,0 +1,28 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import { jsx as _jsx } from "react/jsx-runtime";
14
+ import * as React from "react";
15
+ import { renderRipple } from "../../utils";
16
+ import styles from "./Anchor.module.scss";
17
+ export const Anchor = (_a) => {
18
+ var { href, variant = "default", className = "", children, onClick } = _a, props = __rest(_a, ["href", "variant", "className", "children", "onClick"]);
19
+ const ref = React.useRef(null);
20
+ const handleClick = (e) => {
21
+ const { clientX, clientY } = e;
22
+ renderRipple({ ref, clientX, clientY });
23
+ if (onClick) {
24
+ onClick(e);
25
+ }
26
+ };
27
+ return (_jsx("a", Object.assign({}, props, { ref: ref, href: href, className: `anchor ${styles["anchor"]} ${styles[`anchor--${variant}`]} ${className}`, onClick: handleClick, children: children })));
28
+ };
@@ -0,0 +1,35 @@
1
+ "use client";
2
+ var __rest = (this && this.__rest) || function (s, e) {
3
+ var t = {};
4
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
5
+ t[p] = s[p];
6
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
7
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
8
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
9
+ t[p[i]] = s[p[i]];
10
+ }
11
+ return t;
12
+ };
13
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
14
+ import * as React from "react";
15
+ import { Spinner } from "../Spinner";
16
+ import { renderRipple } from "../../utils";
17
+ import styles from "./Button.module.scss";
18
+ export const Button = (_a) => {
19
+ var { onClick, children, variant = "default", appearance = "solid", size = "md", radius = "md", icon, spinnerType = "default", isLoading = false, disabled, className = "", dangerouslySetInnerHTML } = _a, restProps = __rest(_a, ["onClick", "children", "variant", "appearance", "size", "radius", "icon", "spinnerType", "isLoading", "disabled", "className", "dangerouslySetInnerHTML"]);
20
+ const ref = React.useRef(null);
21
+ const handleClick = (e) => {
22
+ const { clientX, clientY } = e;
23
+ renderRipple({ ref, clientX, clientY });
24
+ if (onClick) {
25
+ onClick(e);
26
+ }
27
+ };
28
+ const Children = () => {
29
+ var _a;
30
+ return (_jsxs(_Fragment, { children: [isLoading && (_jsx(Spinner, { size: size, variant: variant, type: spinnerType, className: styles["spinner"] })), icon && (_jsx("span", { className: `${styles["icon"]} ${styles[`icon--${(_a = icon.align) !== null && _a !== void 0 ? _a : "left"}`]}`, children: React.createElement(icon.component) })), children] }));
31
+ };
32
+ return (_jsx("button", Object.assign({ ref: ref, disabled: disabled || isLoading, className: `${styles["button"]} ${styles[`button-variant--${variant}`]} ${styles[`button-appearance--${appearance}`]} ${styles[`button-size--${size}`]} ${styles[`button-radius--${radius}`]} ${isLoading ? styles["button--loading"] : ""} ${className}`, onClick: handleClick }, (dangerouslySetInnerHTML
33
+ ? { dangerouslySetInnerHTML }
34
+ : { children: _jsx(Children, {}) }), restProps)));
35
+ };
@@ -0,0 +1,16 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { Button } from "../Button";
5
+ import styles from "./ButtonGroup.module.scss";
6
+ export const ButtonGroup = ({ children, align = "horizontal", variant = "default", size = "md", radius = "md", disabled, className = "", }) => {
7
+ return (_jsx("div", { className: `${styles["button-group"]} ${styles[`button-group-variant--${variant}`]} ${styles[`button-group-size--${size}`]} ${styles[`button-group-radius--${radius}`]} ${styles[`button-group-align--${align}`]} ${className}`, children: React.Children.toArray(children)
8
+ .filter((child) => React.isValidElement(child) && child.type === Button)
9
+ .map((child, index) => React.cloneElement(child, {
10
+ key: index || child.key,
11
+ size: size || child.props.size,
12
+ disabled: disabled || child.props.disabled,
13
+ variant: variant || child.props.variant,
14
+ radius: "none",
15
+ })) }));
16
+ };
@@ -0,0 +1,33 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
+ import * as React from "react";
12
+ import { getSingletonHighlighter } from "shiki";
13
+ import { Button } from "../Button";
14
+ import { Icons } from "../../utils";
15
+ import styles from "./CodeBlock.module.scss";
16
+ export const CodeBlock = ({ code, lang = "tsx", theme = "nord", className = "", }) => {
17
+ const [html, setHtml] = React.useState("");
18
+ React.useEffect(() => {
19
+ (() => __awaiter(void 0, void 0, void 0, function* () {
20
+ setHtml((yield getSingletonHighlighter({
21
+ themes: [theme],
22
+ langs: [lang],
23
+ })).codeToHtml(code, {
24
+ lang,
25
+ theme,
26
+ }));
27
+ }))();
28
+ }, [code, lang, theme]);
29
+ const copyToClipboard = () => __awaiter(void 0, void 0, void 0, function* () {
30
+ yield navigator.clipboard.writeText(code);
31
+ });
32
+ return (_jsxs("div", { className: `code-block ${styles["code-block"]} ${className}`, children: [_jsx("div", { className: styles["code-block__container"], dangerouslySetInnerHTML: { __html: html } }), _jsx(Button, { onClick: copyToClipboard, className: styles["code-block__button"], dangerouslySetInnerHTML: { __html: Icons.Copy } })] }));
33
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,73 @@
1
+ "use client";
2
+ import { createElement as _createElement } from "react";
3
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
4
+ import * as React from "react";
5
+ import { DropdownOption } from "../DropdownOption";
6
+ import { AnimatePresence, motion } from "framer-motion";
7
+ import { Button } from "../Button";
8
+ import { Portal } from "../../utils/Portal";
9
+ import styles from "./Dropdown.module.scss";
10
+ export const Dropdown = ({ children, value, onChange, appearance = "outline", placeholder = "Select", className = "", initiallyOpened = false, disabled = false, }) => {
11
+ const [isOpened, setIsOpened] = React.useState(initiallyOpened);
12
+ const [selected, setSelected] = React.useState(value);
13
+ const [position, setPosition] = React.useState({
14
+ top: 0,
15
+ left: 0,
16
+ width: 0,
17
+ });
18
+ const [dropdownHeight, setDropdownHeight] = React.useState(0);
19
+ const [buttonHeight, setButtonHeight] = React.useState(0);
20
+ const buttonRef = React.useRef(null);
21
+ const boxRef = React.useRef(null);
22
+ const uniqueId = React.useId();
23
+ React.useLayoutEffect(() => {
24
+ if (!isOpened) {
25
+ return;
26
+ }
27
+ if (boxRef.current) {
28
+ setDropdownHeight(boxRef.current.getBoundingClientRect().height);
29
+ }
30
+ if (buttonRef.current) {
31
+ setButtonHeight(buttonRef.current.getBoundingClientRect().height);
32
+ }
33
+ }, [isOpened]);
34
+ const options = React.Children.toArray(children).filter((child) => React.isValidElement(child) && child.type === DropdownOption);
35
+ const isValidValue = () => {
36
+ return !!options.find(({ props }) => props.value === value);
37
+ };
38
+ const handleChange = (currentRadioValue) => {
39
+ onChange === null || onChange === void 0 ? void 0 : onChange(currentRadioValue);
40
+ setSelected(currentRadioValue);
41
+ setIsOpened(false);
42
+ };
43
+ const handleToggle = () => {
44
+ var _a;
45
+ if (disabled)
46
+ return;
47
+ const rect = (_a = buttonRef.current) === null || _a === void 0 ? void 0 : _a.getBoundingClientRect();
48
+ if (!rect)
49
+ return;
50
+ const spaceBelow = window.innerHeight - rect.bottom;
51
+ const spaceAbove = rect.top;
52
+ const shouldOpenUpwards = dropdownHeight > 0 &&
53
+ spaceBelow < dropdownHeight &&
54
+ spaceAbove > dropdownHeight;
55
+ const finalPosition = {
56
+ top: shouldOpenUpwards
57
+ ? rect.top + window.scrollY - dropdownHeight - buttonHeight / 2
58
+ : rect.top + window.scrollY + buttonHeight + 6,
59
+ left: rect.left + window.scrollX,
60
+ width: rect.width,
61
+ };
62
+ setPosition(finalPosition);
63
+ setIsOpened((prev) => !prev);
64
+ };
65
+ if (!isValidValue()) {
66
+ throw new Error('The "value" prop did not match with any of the DropdownOption "value" prop');
67
+ }
68
+ return (_jsxs(_Fragment, { children: [_jsx("div", { className: `${styles["dropdown"]} ${className}`, children: _jsx(Button, { ref: buttonRef, className: styles["dropdown__button"], appearance: appearance, onClick: handleToggle, disabled: disabled, children: placeholder }) }), _jsx(Portal, { children: _jsx(AnimatePresence, { children: isOpened && (_jsxs("div", { className: styles["dropdown__box"], children: [_jsx(motion.div, { className: styles["dropdown__box-overlay"], initial: { opacity: 0 }, animate: { opacity: 1 }, exit: { opacity: 0 }, transition: { duration: 0.3, ease: "easeIn" }, onClick: () => setIsOpened(false) }), _jsx(motion.div, { ref: boxRef, className: styles["dropdown__box-options"], initial: { opacity: 0, y: 20, scale: 0.95 }, animate: { opacity: 1, y: 0, scale: 1 }, exit: { opacity: 0, y: 20, scale: 0.95 }, transition: { duration: 0.2, ease: "easeIn" }, style: {
69
+ top: position.top,
70
+ left: position.left,
71
+ width: position.width,
72
+ }, children: options.map(({ props }) => (_createElement(DropdownOption, Object.assign({}, props, { key: `${props.value}-${uniqueId}`, selectedValue: selected, onChange: () => handleChange(props.value) })))) })] })) }) })] }));
73
+ };
@@ -0,0 +1,13 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styles from "./DropdownOption.module.scss";
3
+ export const DropdownOption = ({ children,
4
+ // value,
5
+ // selectedValue,
6
+ onChange,
7
+ // icon,
8
+ description,
9
+ // disabled,
10
+ }) => {
11
+ // const isSelected = selectedValue === value;
12
+ return (_jsx("button", { className: styles["dropdown-option"], onClick: onChange, children: _jsxs("div", { className: styles["dropdown-option__content"], children: [_jsx("h3", { className: styles["dropdown-option__title"], children: children }), _jsx("p", { className: styles["dropdown-option__description"], children: description })] }) }));
13
+ };
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Icons } from "../../utils";
3
+ import styles from "./MessageBox.module.scss";
4
+ const renderIcon = (variant) => {
5
+ switch (variant) {
6
+ case "warning":
7
+ return Icons.Warning;
8
+ case "success":
9
+ return Icons.Success;
10
+ case "error":
11
+ return Icons.Error;
12
+ case "info":
13
+ default:
14
+ return Icons.Info;
15
+ }
16
+ };
17
+ export const MessageBox = ({ children, className = "", variant = "default", withIcon = false, customIcon = null, radius = "md", type = "outline", }) => (_jsxs("div", { className: `message-box ${styles["message-box"]} ${styles[`message-box-type--${type}`]} ${styles[`message-box-radius--${radius}`]} ${styles[`message-box--${variant}`]} ${className}`, children: [withIcon && (_jsx("span", { className: `${styles["message-box__icon"]} ${styles[`message-box__icon--${variant}`]}`, dangerouslySetInnerHTML: {
18
+ __html: customIcon ? customIcon : renderIcon(variant),
19
+ } })), _jsx("p", { className: `${styles["message-box__content"]}`, dangerouslySetInnerHTML: { __html: children || "" } })] }));
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import styles from "./Radio.module.scss";
3
+ export const Radio = ({ children, value, checked, name, disabled = false, highlightLabel = false, className = "", size = "md", variant = "default", appearance = "default", alignLabel = "right", onChange, }) => {
4
+ const handleChange = () => {
5
+ if (!disabled && onChange) {
6
+ onChange(value);
7
+ }
8
+ };
9
+ return (_jsxs("label", { className: `${styles["radio"]} ${styles[`radio-align-label--${alignLabel}`]} ${styles[`radio-appearance--${appearance}`]} ${styles[`radio-variant--${variant}`]} ${styles[`radio-size--${size}`]} ${disabled ? styles["radio--disabled"] : ""} ${className}`, children: [_jsx("input", { type: "radio", name: name, value: value, checked: checked, disabled: disabled, onChange: handleChange, className: styles["radio__input"] }), _jsx("span", { className: styles["radio__control"] }), children && (_jsx("span", { className: `${styles["radio__label"]} ${highlightLabel ? styles["radio__label--highlight-label"] : ""}`, children: children }))] }));
10
+ };
@@ -0,0 +1,21 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import { createElement as _createElement } from "react";
4
+ import * as React from "react";
5
+ import { Radio } from "../Radio";
6
+ import styles from "./RadioGroup.module.scss";
7
+ export const RadioGroup = ({ name, value, onChange, children, disabled = false, highlightLabel = false, className = "", size = "md", variant = "default", appearance = "outline", align = "horizontal", alignLabel = "right", }) => {
8
+ const uniqueId = React.useId();
9
+ const [currentValue, setCurrentValue] = React.useState(value);
10
+ const radios = React.Children.toArray(children).filter((child) => React.isValidElement(child) && child.type === Radio);
11
+ const handleChange = (currentRadioValue) => {
12
+ if (onChange) {
13
+ onChange(currentRadioValue);
14
+ }
15
+ setCurrentValue(currentRadioValue);
16
+ };
17
+ return (_jsx("div", { className: `${styles["radio-group"]} ${styles[`radio-group--${align}`]} ${className}`, children: radios.map(({ props }) => {
18
+ var _a, _b, _c, _d, _e, _f;
19
+ return (_createElement(Radio, Object.assign({}, props, { key: `${name}-${props.value}-${uniqueId}`, name: `${name}-${props.value}-${uniqueId}`, checked: props.value === currentValue, onChange: () => handleChange(props.value), disabled: (_a = props.disabled) !== null && _a !== void 0 ? _a : disabled, size: (_b = props.size) !== null && _b !== void 0 ? _b : size, variant: (_c = props.variant) !== null && _c !== void 0 ? _c : variant, appearance: (_d = props.appearance) !== null && _d !== void 0 ? _d : appearance, highlightLabel: (_e = props.highlightLabel) !== null && _e !== void 0 ? _e : highlightLabel, alignLabel: (_f = props.alignLabel) !== null && _f !== void 0 ? _f : alignLabel })));
20
+ }) }, uniqueId));
21
+ };
@@ -0,0 +1,6 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "react/jsx-runtime";
3
+ import styles from "./Spinner.module.scss";
4
+ export const Spinner = ({ type = "default", variant = "default", size = "md", className = "", }) => {
5
+ return (_jsx("div", { className: `spinner ${styles[`spinner-type--${type}`]} ${styles[`spinner-variant--${variant}`]} ${styles[`spinner-size--${size}`]} ${className}` }));
6
+ };
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import styles from "./Switch.module.scss";
5
+ //@TODO: Fix the the switch styling, which is breaking when continuously clicking on the component
6
+ export const Switch = ({ label, alignLabel = "vertical", checked, switchSize = "md", variant = "default", disabled = false, trackIcon, thumbIcon, className = "", onChange, }) => {
7
+ const id = React.useId();
8
+ const [isChecked, setIsChecked] = React.useState(!!checked);
9
+ const handleChange = () => {
10
+ setIsChecked((prev) => !prev);
11
+ if (onChange)
12
+ onChange();
13
+ };
14
+ return (_jsxs("label", { htmlFor: id, className: `${styles["switch"]} ${styles[`switch-size--${switchSize}`]} ${styles[`switch-variant--${variant}`]} ${styles[`switch-align-label--${alignLabel}`]} ${disabled ? styles["switch--disabled"] : ""} ${className}`, children: [_jsx("input", { id: id, type: "checkbox", disabled: disabled, checked: isChecked, onChange: handleChange }), _jsxs("span", { className: styles["switch__track"], children: [trackIcon && trackIcon.checked && (_jsx("span", { className: `${styles["switch__track-icon"]} ${styles["switch__track-icon--checked"]}`, children: React.createElement(trackIcon.checked) })), _jsx("span", { className: styles["switch__thumb"], children: thumbIcon && (_jsx("span", { className: styles["switch__thumb-icon"], children: React.createElement(thumbIcon) })) }), trackIcon && trackIcon.unchecked && (_jsx("span", { className: `${styles["switch__track-icon"]} ${styles["switch__track-icon--unchecked"]}`, children: React.createElement(trackIcon.unchecked) }))] }), label && _jsx("span", { className: styles["switch__label"], children: label })] }));
15
+ };
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import * as React from "react";
3
+ import styles from "./TabSwitchWithSlidingIndicator.module.scss";
4
+ export const TabSwitchWithSlidingIndicator = ({ tabs }) => {
5
+ const [activeIndex, setActiveIndex] = React.useState(0);
6
+ const currentIndex = tabs.findIndex((_, i) => i === activeIndex);
7
+ return (_jsxs("div", { className: `tab-switch-with-sliding-indicator ${styles["tab-switch-with-sliding-indicator"]}`, children: [_jsxs("div", { className: styles["tab-switch-with-sliding-indicator__tabs"], children: [tabs.map(({ buttonContent }, index) => (_jsx("button", { className: `${styles["tab-switch-with-sliding-indicator__tab"]} ${activeIndex === index ? styles[" tab-switch-with-sliding-indicator__tab--active"] : ""}`, onClick: () => setActiveIndex(index), children:
8
+ // @TODO: This should be fixed: from consumer level we should be able to pass only string not components - once this is resolved the active tab should have text color white. Since we pass a whole component from consumer level it's hard to identify the most inner component which contains text, so we can change the color of it in different scenarios
9
+ buttonContent || index }, index))), _jsx("span", { className: styles["tab-switch-with-sliding-indicator__bar"], style: { left: `${currentIndex * 80}px` } })] }), _jsx("div", { className: styles["tab-switch-with-sliding-indicator__content"], children: tabs[currentIndex].content })] }));
10
+ };
@@ -0,0 +1,12 @@
1
+ export { Anchor } from "./Anchor";
2
+ export { Button } from "./Button";
3
+ export { ButtonGroup } from "./ButtonGroup";
4
+ export { Dropdown } from "./Dropdown";
5
+ export { DropdownOption } from "./DropdownOption";
6
+ export { MessageBox } from "./MessageBox";
7
+ export { CodeBlock } from "./CodeBlock";
8
+ export { TabSwitchWithSlidingIndicator } from "./TabSwitchWithSlidingIndicator";
9
+ export { Spinner } from "./Spinner";
10
+ export { Switch } from "./Switch";
11
+ export { Radio } from "./Radio";
12
+ export { RadioGroup } from "./RadioGroup";
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { Anchor, Button, ButtonGroup, Dropdown, DropdownOption, MessageBox, CodeBlock, Spinner, Switch, } from "./components";