adnbn-ui 0.0.1 → 0.1.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.
Files changed (146) hide show
  1. package/.prettierignore +3 -0
  2. package/.prettierrc +28 -0
  3. package/.storybook/main.ts +22 -0
  4. package/.storybook/preview.tsx +100 -0
  5. package/.storybook/styles/custom.scss +59 -0
  6. package/.storybook/styles/preview.css +58 -0
  7. package/.storybook/vitest.setup.ts +9 -0
  8. package/README.md +1057 -0
  9. package/eslint.config.js +39 -0
  10. package/package.json +95 -4
  11. package/src/components/Avatar/Avatar.stories.tsx +118 -0
  12. package/src/components/Avatar/Avatar.tsx +65 -0
  13. package/src/components/Avatar/avatar.module.scss +77 -0
  14. package/src/components/Avatar/index.ts +2 -0
  15. package/src/components/BaseButton/BaseButton.tsx +36 -0
  16. package/src/components/BaseButton/base-button.module.scss +24 -0
  17. package/src/components/BaseButton/index.ts +2 -0
  18. package/src/components/Button/Button.stories.tsx +148 -0
  19. package/src/components/Button/Button.tsx +73 -0
  20. package/src/components/Button/button.module.scss +140 -0
  21. package/src/components/Button/index.ts +2 -0
  22. package/src/components/Checkbox/Checkbox.stories.tsx +180 -0
  23. package/src/components/Checkbox/Checkbox.tsx +71 -0
  24. package/src/components/Checkbox/checkbox.module.scss +82 -0
  25. package/src/components/Checkbox/index.ts +2 -0
  26. package/src/components/Dialog/Dialog.tsx +125 -0
  27. package/src/components/Dialog/dialog.module.scss +55 -0
  28. package/src/components/Dialog/index.ts +2 -0
  29. package/src/components/Drawer/Drawer.stories.tsx +89 -0
  30. package/src/components/Drawer/Drawer.tsx +57 -0
  31. package/src/components/Drawer/drawer.module.scss +170 -0
  32. package/src/components/Drawer/index.ts +2 -0
  33. package/src/components/Footer/Footer.stories.tsx +118 -0
  34. package/src/components/Footer/Footer.tsx +58 -0
  35. package/src/components/Footer/footer.module.scss +44 -0
  36. package/src/components/Footer/index.ts +2 -0
  37. package/src/components/Header/Header.stories.tsx +49 -0
  38. package/src/components/Header/Header.tsx +73 -0
  39. package/src/components/Header/header.module.scss +56 -0
  40. package/src/components/Header/index.ts +2 -0
  41. package/src/components/Highlight/Highlight.stories.tsx +83 -0
  42. package/src/components/Highlight/Highlight.tsx +40 -0
  43. package/src/components/Highlight/highlight.module.scss +47 -0
  44. package/src/components/Highlight/index.ts +2 -0
  45. package/src/components/Icon/Icon.tsx +46 -0
  46. package/src/components/Icon/icon.module.scss +17 -0
  47. package/src/components/Icon/index.ts +2 -0
  48. package/src/components/IconButton/IconButton.stories.tsx +179 -0
  49. package/src/components/IconButton/IconButton.tsx +65 -0
  50. package/src/components/IconButton/icon-button.module.scss +86 -0
  51. package/src/components/IconButton/index.ts +2 -0
  52. package/src/components/Layout/Layout.stories.tsx +88 -0
  53. package/src/components/Layout/Provider.tsx +47 -0
  54. package/src/components/Layout/context.ts +24 -0
  55. package/src/components/Layout/index.ts +2 -0
  56. package/src/components/Layout/layout.module.scss +17 -0
  57. package/src/components/List/List.stories.tsx +81 -0
  58. package/src/components/List/List.tsx +24 -0
  59. package/src/components/List/index.ts +2 -0
  60. package/src/components/List/list.module.scss +8 -0
  61. package/src/components/ListItem/ListItem.tsx +75 -0
  62. package/src/components/ListItem/index.ts +2 -0
  63. package/src/components/ListItem/list-item.module.scss +36 -0
  64. package/src/components/Modal/Modal.stories.tsx +95 -0
  65. package/src/components/Modal/Modal.tsx +94 -0
  66. package/src/components/Modal/index.ts +2 -0
  67. package/src/components/Modal/modal.module.scss +97 -0
  68. package/src/components/Odometer/Odometer.stories.tsx +66 -0
  69. package/src/components/Odometer/Odometer.tsx +45 -0
  70. package/src/components/Odometer/hooks/useOdometer.tsx +24 -0
  71. package/src/components/Odometer/index.ts +3 -0
  72. package/src/components/Odometer/odometer.module.scss +81 -0
  73. package/src/components/Odometer/odometr.d.ts +9 -0
  74. package/src/components/ScrollArea/ScrollArea.stories.tsx +58 -0
  75. package/src/components/ScrollArea/ScrollArea.tsx +63 -0
  76. package/src/components/ScrollArea/index.ts +2 -0
  77. package/src/components/ScrollArea/scroll-area.module.scss +54 -0
  78. package/src/components/SvgSprite/SvgSprite.tsx +21 -0
  79. package/src/components/SvgSprite/index.ts +2 -0
  80. package/src/components/Switch/Switch.stories.tsx +25 -0
  81. package/src/components/Switch/Switch.tsx +23 -0
  82. package/src/components/Switch/index.ts +2 -0
  83. package/src/components/Switch/switch.module.scss +65 -0
  84. package/src/components/Tag/Tag.stories.tsx +157 -0
  85. package/src/components/Tag/Tag.tsx +71 -0
  86. package/src/components/Tag/index.ts +2 -0
  87. package/src/components/Tag/tag.module.scss +118 -0
  88. package/src/components/TextArea/TextArea.stories.tsx +145 -0
  89. package/src/components/TextArea/TextArea.tsx +143 -0
  90. package/src/components/TextArea/index.ts +2 -0
  91. package/src/components/TextArea/text-area.module.scss +88 -0
  92. package/src/components/TextField/TextField.stories.tsx +177 -0
  93. package/src/components/TextField/TextField.tsx +162 -0
  94. package/src/components/TextField/index.ts +2 -0
  95. package/src/components/TextField/text-field.module.scss +129 -0
  96. package/src/components/Toast/Toast.stories.tsx +209 -0
  97. package/src/components/Toast/Toast.tsx +142 -0
  98. package/src/components/Toast/index.ts +2 -0
  99. package/src/components/Toast/toast.module.scss +267 -0
  100. package/src/components/Tooltip/Tooltip.stories.tsx +80 -0
  101. package/src/components/Tooltip/Tooltip.tsx +79 -0
  102. package/src/components/Tooltip/index.ts +2 -0
  103. package/src/components/Tooltip/tooltip.module.scss +93 -0
  104. package/src/components/View/View.stories.tsx +47 -0
  105. package/src/components/View/View.tsx +68 -0
  106. package/src/components/View/index.ts +2 -0
  107. package/src/components/View/view.module.scss +38 -0
  108. package/src/components/ViewDrawer/ViewDrawer.stories.tsx +75 -0
  109. package/src/components/ViewDrawer/ViewDrawer.tsx +24 -0
  110. package/src/components/ViewDrawer/index.ts +2 -0
  111. package/src/components/ViewModal/ViewModal.stories.tsx +68 -0
  112. package/src/components/ViewModal/ViewModal.tsx +24 -0
  113. package/src/components/ViewModal/index.ts +2 -0
  114. package/src/components/index.ts +29 -0
  115. package/src/components/types.ts +65 -0
  116. package/src/config/default.ts +3 -0
  117. package/src/config/index.ts +26 -0
  118. package/src/declaration.d.ts +8 -0
  119. package/src/index.ts +3 -0
  120. package/src/plugin/builder/ConfigBuilder.ts +32 -0
  121. package/src/plugin/builder/StyleBuilder.ts +34 -0
  122. package/src/plugin/builder/virtual.config.ts +7 -0
  123. package/src/plugin/finder/ConfigFinder.ts +26 -0
  124. package/src/plugin/finder/Finder.ts +76 -0
  125. package/src/plugin/finder/StyleFinder.ts +23 -0
  126. package/src/plugin/index.ts +70 -0
  127. package/src/plugin/types.ts +8 -0
  128. package/src/providers/UIProvider.tsx +26 -0
  129. package/src/providers/icons/IconsProvider.tsx +34 -0
  130. package/src/providers/icons/context.ts +22 -0
  131. package/src/providers/icons/index.ts +3 -0
  132. package/src/providers/index.ts +3 -0
  133. package/src/providers/theme/ThemeProvider.tsx +39 -0
  134. package/src/providers/theme/context.ts +30 -0
  135. package/src/providers/theme/index.ts +2 -0
  136. package/src/providers/theme/styles/default.scss +95 -0
  137. package/src/providers/theme/styles/reset.css +111 -0
  138. package/src/styles/mixins.scss +23 -0
  139. package/src/types/theme.ts +4 -0
  140. package/src/utils/index.ts +2 -0
  141. package/src/utils/react.ts +21 -0
  142. package/src/utils/utils.ts +12 -0
  143. package/tsconfig.json +18 -0
  144. package/vite.config.ts +11 -0
  145. package/vitest.workspace.ts +19 -0
  146. package/components/Button/index.ts +0 -0
@@ -0,0 +1,88 @@
1
+ import {useState} from "react";
2
+ import {Meta} from "@storybook/react";
3
+
4
+ import {hideInTable} from "../../utils";
5
+
6
+ import {Header, Footer, Button, ScrollArea, IconButton, IconButtonVariant, IconButtonSize} from "../index";
7
+
8
+ import {LayoutProvider, useLayout} from "./index";
9
+
10
+ const meta: Meta<typeof LayoutProvider> = {
11
+ title: "Components/Layout",
12
+ component: LayoutProvider,
13
+ tags: ["autodocs"],
14
+ argTypes: {
15
+ children: hideInTable,
16
+ },
17
+ };
18
+
19
+ export default meta;
20
+
21
+ export const Layout = () => {
22
+ return (
23
+ <LayoutProvider>
24
+ <App />
25
+ </LayoutProvider>
26
+ );
27
+ };
28
+
29
+ const App = () => {
30
+ const [arr, setArr] = useState(Array.from(Array(5)));
31
+ const {expand, collapse} = useLayout();
32
+
33
+ return (
34
+ <div
35
+ style={{
36
+ background: "var(--bg-secondary-color)",
37
+ flex: 1,
38
+ display: "flex",
39
+ flexDirection: "column",
40
+ borderRadius: "10px",
41
+ overflow: "hidden",
42
+ }}
43
+ >
44
+ <Header title={"Layout"} />
45
+ <div style={{display: "flex", justifyContent: "space-evenly", alignItems: "center", padding: "5px 10px"}}>
46
+ <IconButton
47
+ size={IconButtonSize.Medium}
48
+ variant={IconButtonVariant.Contained}
49
+ onClick={() => setArr([...arr, "item"])}
50
+ >
51
+
52
+ </IconButton>
53
+ <Button onClick={() => expand()}>Expand</Button>
54
+ <Button onClick={() => collapse()}>Collapse</Button>
55
+
56
+ <IconButton
57
+ size={IconButtonSize.Medium}
58
+ variant={IconButtonVariant.Contained}
59
+ onClick={() => setArr(arr.slice(0, -1))}
60
+ >
61
+
62
+ </IconButton>
63
+ </div>
64
+ <div style={{display: "flex", justifyContent: "space-evenly", padding: "5px 10px"}}>
65
+ <Button onClick={() => expand({height: 700})}>700px height</Button>
66
+ <Button onClick={() => expand({height: 700, width: 500})}>700x500px</Button>
67
+ <Button onClick={() => expand({width: 500})}>500px width</Button>
68
+ </div>
69
+ <ScrollArea
70
+ xOffset={10}
71
+ type="always"
72
+ style={{flex: 1, display: "flex", flexDirection: "column", overflow: "hidden"}}
73
+ >
74
+ <div style={{flex: 1}}>
75
+ {arr.map((_, index) => (
76
+ <div
77
+ key={index}
78
+ style={{padding: "10px 20px", textAlign: "center", color: "var(--text-secondary-color)"}}
79
+ >
80
+ Item {++index}
81
+ </div>
82
+ ))}
83
+ </div>
84
+ </ScrollArea>
85
+ <Footer left="❤️" right="⭐" shadow style={{paddingTop: "10px"}} />
86
+ </div>
87
+ );
88
+ };
@@ -0,0 +1,47 @@
1
+ import React, {ComponentProps, FC, PropsWithChildren, useCallback, useState} from "react";
2
+
3
+ import {expandType, LayoutContext} from "./context";
4
+
5
+ import classnames from "classnames";
6
+
7
+ import styles from "./layout.module.scss";
8
+
9
+ const Provider: FC<PropsWithChildren<ComponentProps<"div">>> = ({children, className, style, ...props}) => {
10
+ const [isExpanded, setExpanded] = useState(false);
11
+ const [height, setHeight] = useState<number | string | undefined>(undefined);
12
+ const [width, setWidth] = useState<number | string | undefined>(undefined);
13
+
14
+ const expand = useCallback((value?: expandType) => {
15
+ setHeight(value?.height);
16
+ setWidth(value?.width);
17
+ setExpanded(true);
18
+ }, []);
19
+
20
+ const collapse = useCallback(() => {
21
+ setHeight(undefined);
22
+ setWidth(undefined);
23
+ setExpanded(false);
24
+ }, []);
25
+
26
+ return (
27
+ <LayoutContext.Provider value={{isExpanded, expand, collapse}}>
28
+ <div
29
+ style={{minHeight: height, minWidth: width, ...style}}
30
+ className={classnames(
31
+ styles["layout"],
32
+ {
33
+ [styles["layout--expanded"]]: isExpanded,
34
+ },
35
+ className
36
+ )}
37
+ {...props}
38
+ >
39
+ {children}
40
+ </div>
41
+ </LayoutContext.Provider>
42
+ );
43
+ };
44
+
45
+ Provider.displayName = "ViewportProvider";
46
+
47
+ export default Provider;
@@ -0,0 +1,24 @@
1
+ import {createContext, useContext} from "react";
2
+
3
+ export type expandType = {
4
+ height?: number | string;
5
+ width?: number | string;
6
+ };
7
+
8
+ export interface LayoutContract {
9
+ isExpanded?: boolean;
10
+
11
+ expand(value?: expandType): void;
12
+
13
+ collapse(): void;
14
+ }
15
+
16
+ export const LayoutContext = createContext<LayoutContract>({
17
+ isExpanded: false,
18
+ expand() {},
19
+ collapse() {},
20
+ });
21
+
22
+ LayoutContext.displayName = "LayoutContext";
23
+
24
+ export const useLayout = () => useContext(LayoutContext);
@@ -0,0 +1,2 @@
1
+ export {default as LayoutProvider} from "./Provider";
2
+ export {useLayout} from "./context";
@@ -0,0 +1,17 @@
1
+ .layout {
2
+ display: flex;
3
+ flex-direction: column;
4
+ overflow: hidden;
5
+ min-width: var(--min-width);
6
+ max-width: var(--max-width);
7
+ min-height: var(--min-height);
8
+ max-height: var(--max-height);
9
+ transition:
10
+ min-height var(--transition-speed-md) ease-in-out,
11
+ min-width var(--transition-speed-md) ease-in-out;
12
+
13
+ &--expanded {
14
+ min-height: var(--max-height);
15
+ min-width: var(--max-width);
16
+ }
17
+ }
@@ -0,0 +1,81 @@
1
+ import {Meta, StoryObj} from "@storybook/react";
2
+
3
+ import {hideInTable} from "../../utils";
4
+
5
+ import {ListItem, Button, ButtonSize, ButtonVariant, Avatar, AvatarSize} from "../index";
6
+
7
+ import ListComponent from "./List";
8
+
9
+ const mockListItems = [
10
+ {
11
+ id: 1,
12
+ avatar: "https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=128&h=128&dpr=2&q=80",
13
+ name: "John Doe",
14
+ role: "React Developer",
15
+ action: "Add",
16
+ },
17
+ {
18
+ id: 2,
19
+ avatar: "https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=128&h=128&dpr=2&q=80",
20
+ name: "Emily Smith",
21
+ role: "UI/UX Designer",
22
+ action: "Invite",
23
+ },
24
+ {
25
+ id: 3,
26
+ avatar: "https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=128&h=128&dpr=2&q=80",
27
+ name: "Michael Johnson",
28
+ role: "Project Manager",
29
+ action: "Add",
30
+ },
31
+ {
32
+ id: 4,
33
+ avatar: "https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=128&h=128&dpr=2&q=80",
34
+ name: "Sarah Brown",
35
+ role: "QA Engineer",
36
+ action: "Invite",
37
+ },
38
+ {
39
+ id: 5,
40
+ avatar: "https://images.unsplash.com/photo-1492633423870-43d1cd2775eb?&w=128&h=128&dpr=2&q=80",
41
+ name: "David Wilson",
42
+ role: "DevOps Engineer",
43
+ action: "Invite",
44
+ },
45
+ ];
46
+
47
+ const meta: Meta<typeof ListComponent> = {
48
+ title: "Components/List",
49
+ component: ListComponent,
50
+ tags: ["autodocs"],
51
+ argTypes: {
52
+ children: hideInTable,
53
+ className: hideInTable,
54
+ style: hideInTable,
55
+ },
56
+ };
57
+
58
+ export default meta;
59
+
60
+ type Story = StoryObj<typeof ListComponent>;
61
+
62
+ export const List: Story = {
63
+ args: {
64
+ children: mockListItems.map(({id, avatar, name, role, action}) => (
65
+ <ListItem
66
+ key={id}
67
+ left={<Avatar src={avatar} size={AvatarSize.Small} />}
68
+ primary={<span style={{fontWeight: 500}}>{name}</span>}
69
+ secondary={<span style={{fontSize: "14px"}}>{role}</span>}
70
+ right={
71
+ <Button variant={ButtonVariant.Contained} size={ButtonSize.Small}>
72
+ {action}
73
+ </Button>
74
+ }
75
+ />
76
+ )),
77
+ style: {
78
+ minWidth: "300px",
79
+ },
80
+ },
81
+ };
@@ -0,0 +1,24 @@
1
+ import React, {ComponentProps, forwardRef, memo, ReactElement} from "react";
2
+ import classnames from "classnames";
3
+
4
+ import {useComponentProps} from "../../providers";
5
+
6
+ import {ListItemProps} from "../ListItem";
7
+
8
+ import styles from "./list.module.scss";
9
+
10
+ export interface ListProps extends Omit<ComponentProps<"ul">, "children"> {
11
+ children: ReactElement<ListItemProps> | ReactElement<ListItemProps>[];
12
+ }
13
+
14
+ const List = forwardRef<HTMLUListElement, ListProps>((props, ref) => {
15
+ const {children, className, ...other} = {...useComponentProps("list"), ...props};
16
+
17
+ return (
18
+ <ul {...other} ref={ref} className={classnames(styles["list"], className)}>
19
+ {children}
20
+ </ul>
21
+ );
22
+ });
23
+
24
+ export default memo(List);
@@ -0,0 +1,2 @@
1
+ export {default as List} from "./List";
2
+ export type {ListProps} from "./List";
@@ -0,0 +1,8 @@
1
+ .list {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 10px;
5
+ padding: 0;
6
+ margin: 0;
7
+ list-style: none;
8
+ }
@@ -0,0 +1,75 @@
1
+ import React, {ComponentProps, forwardRef, JSX, memo, ReactNode} from "react";
2
+ import classnames from "classnames";
3
+
4
+ import {cloneOrCreateElement} from "../../utils";
5
+ import {useComponentProps} from "../../providers";
6
+
7
+ import styles from "./list-item.module.scss";
8
+
9
+ type TagType = keyof JSX.IntrinsicElements;
10
+ export type ListItemType = HTMLLIElement;
11
+
12
+ export interface ListItemProps extends ComponentProps<"li"> {
13
+ left?: ReactNode;
14
+ right?: ReactNode;
15
+ primary?: ReactNode;
16
+ secondary?: ReactNode;
17
+ leftTag?: TagType;
18
+ rightTag?: TagType;
19
+ primaryTag?: TagType;
20
+ secondaryTag?: TagType;
21
+ primaryClassName?: string;
22
+ secondaryClassName?: string;
23
+ centerClassName?: string;
24
+ leftClassName?: string;
25
+ rightClassName?: string;
26
+ }
27
+
28
+ const ListItem = forwardRef<ListItemType, ListItemProps>((props, ref) => {
29
+ const {
30
+ left,
31
+ right,
32
+ primary,
33
+ secondary,
34
+ leftTag = "div",
35
+ rightTag = "div",
36
+ primaryTag = "div",
37
+ secondaryTag = "div",
38
+ children,
39
+ className,
40
+ leftClassName,
41
+ rightClassName,
42
+ centerClassName,
43
+ primaryClassName,
44
+ secondaryClassName,
45
+ role = "list-item",
46
+ ...other
47
+ } = {...useComponentProps("listItem"), ...props};
48
+
49
+ return (
50
+ <li {...other} ref={ref} role={role} className={classnames(styles["list-item"], className)}>
51
+ {cloneOrCreateElement(left, {className: classnames(styles["list-item__left"], leftClassName)}, leftTag)}
52
+
53
+ {(primary || secondary) && (
54
+ <div className={classnames(styles["list-item__center"], centerClassName)}>
55
+ {cloneOrCreateElement(
56
+ primary,
57
+ {className: classnames(styles["list-item__primary"], primaryClassName)},
58
+ primaryTag
59
+ )}
60
+ {cloneOrCreateElement(
61
+ secondary,
62
+ {className: classnames(styles["list-item__secondary"], secondaryClassName)},
63
+ secondaryTag
64
+ )}
65
+ </div>
66
+ )}
67
+
68
+ {cloneOrCreateElement(right, {className: classnames(styles["list-item__right"], rightClassName)}, rightTag)}
69
+
70
+ {children}
71
+ </li>
72
+ );
73
+ });
74
+
75
+ export default memo(ListItem);
@@ -0,0 +1,2 @@
1
+ export {default as ListItem} from "./ListItem";
2
+ export type {ListItemProps, ListItemType} from "./ListItem";
@@ -0,0 +1,36 @@
1
+ .list-item {
2
+ display: flex;
3
+ flex-direction: row;
4
+ align-items: center;
5
+ gap: 10px;
6
+ flex-wrap: nowrap;
7
+ box-sizing: border-box;
8
+
9
+ &__center {
10
+ flex-grow: 1;
11
+ display: flex;
12
+ overflow: hidden;
13
+ flex-direction: column;
14
+ justify-content: center;
15
+ }
16
+
17
+ &__primary,
18
+ &__secondary {
19
+ overflow: hidden;
20
+ white-space: nowrap;
21
+ text-overflow: ellipsis;
22
+ }
23
+ &__primary {
24
+ color: var(--list-item-primary-color, var(--text-primary-color));
25
+ }
26
+ &__secondary {
27
+ color: var(--list-item-secondary-color, var(--text-secondary-color));
28
+ }
29
+
30
+ &__left,
31
+ &__right {
32
+ display: flex;
33
+ align-items: center;
34
+ justify-content: center;
35
+ }
36
+ }
@@ -0,0 +1,95 @@
1
+ import {useState} from "react";
2
+ import {Meta} from "@storybook/react";
3
+
4
+ import {capitalizeFirstLetter, hideInTable} from "../../utils";
5
+
6
+ import {Button, Header} from "../index";
7
+
8
+ import ModalComponent, {ModalProps, ModalRadius} from "./Modal";
9
+
10
+ const radius: (ModalRadius | "default")[] = [
11
+ ModalRadius.None,
12
+ ModalRadius.Small,
13
+ "default",
14
+ ModalRadius.Medium,
15
+ ModalRadius.Large,
16
+ ];
17
+
18
+ const meta: Meta<typeof ModalComponent> = {
19
+ title: "Components/Modal",
20
+ component: ModalComponent,
21
+ tags: ["autodocs"],
22
+ argTypes: {
23
+ radius: {
24
+ options: radius,
25
+ control: {type: "select"},
26
+ },
27
+ modal: {
28
+ description:
29
+ "The modality of the dialog. When set to true, interaction with outside elements will be disabled and only dialog content will be visible to screen readers.",
30
+ control: {type: "boolean"},
31
+ type: "boolean",
32
+ },
33
+ closeButton: {
34
+ options: [true, false, {children: "❌"}],
35
+ control: {type: "select"},
36
+ },
37
+ speed: {
38
+ type: "number",
39
+ },
40
+ onClose: hideInTable,
41
+ children: hideInTable,
42
+ className: hideInTable,
43
+ description: hideInTable,
44
+ overlayClassName: hideInTable,
45
+ childrenClassName: hideInTable,
46
+ },
47
+ };
48
+
49
+ export default meta;
50
+
51
+ export const Modal = (props: ModalProps & {label?: string}) => {
52
+ const [open, setOpen] = useState(false);
53
+ const {label = "Open Modal", ...other} = props;
54
+ return (
55
+ <div>
56
+ <Button onClick={() => setOpen(true)}>{label}</Button>
57
+ <ModalComponent open={open} onOpenChange={setOpen} {...other}>
58
+ <div
59
+ style={{
60
+ display: "flex",
61
+ alignItems: "center",
62
+ justifyContent: "center",
63
+ height: "100%",
64
+ gap: "30px",
65
+ }}
66
+ >
67
+ <Header
68
+ title="Volume Up Plus"
69
+ subtitle="Adjust the current tab's volume with the slider. Switch to any audio tab in one click."
70
+ before="❤️"
71
+ />
72
+ <Button style={{margin: "50px auto", maxWidth: "max-content"}} onClick={() => setOpen(false)}>
73
+ Close Modal
74
+ </Button>
75
+ </div>
76
+ </ModalComponent>
77
+ </div>
78
+ );
79
+ };
80
+
81
+ export const Radius = () => {
82
+ return (
83
+ <div className="grid-wrapper" style={{gridTemplateColumns: "repeat(5, auto)"}}>
84
+ {radius.map(radius => (
85
+ <div key={radius} className="item-card">
86
+ <Modal
87
+ radius={radius !== "default" ? radius : undefined}
88
+ fullscreen={false}
89
+ label={`${capitalizeFirstLetter(radius)} radius`}
90
+ />
91
+ </div>
92
+ ))}
93
+ </div>
94
+ );
95
+ };
@@ -0,0 +1,94 @@
1
+ import React, {FC, isValidElement, memo, ReactElement, useCallback} from "react";
2
+ import classnames from "classnames";
3
+
4
+ import {useComponentProps} from "../../providers";
5
+ import {cloneOrCreateElement} from "../../utils";
6
+
7
+ import {Dialog, DialogProps, dialogPropsKeys} from "../Dialog";
8
+ import {IconButton, IconButtonProps} from "../IconButton";
9
+
10
+ import styles from "./modal.module.scss";
11
+
12
+ export enum ModalRadius {
13
+ None = "none",
14
+ Small = "small",
15
+ Medium = "medium",
16
+ Large = "large",
17
+ }
18
+
19
+ export interface ModalProps extends DialogProps {
20
+ radius?: ModalRadius;
21
+ closeButton?: boolean | IconButtonProps | ReactElement;
22
+ onClose?: () => void;
23
+ }
24
+
25
+ export const modalPropsKeys = new Set<keyof ModalProps>(["radius", "closeButton", "onClose", ...dialogPropsKeys]);
26
+
27
+ const Modal: FC<ModalProps> = props => {
28
+ const {
29
+ radius,
30
+ fullscreen = true,
31
+ closeButton = true,
32
+ onClose,
33
+ onOpenChange,
34
+ children,
35
+ className,
36
+ overlayClassName,
37
+ childrenClassName,
38
+ ...other
39
+ } = {...useComponentProps("modal"), ...props};
40
+
41
+ const handleClose = useCallback(
42
+ (event: React.MouseEvent<HTMLButtonElement>) => {
43
+ onClose?.();
44
+ onOpenChange?.(false);
45
+ if (typeof closeButton === "object" && !isValidElement(closeButton)) {
46
+ closeButton?.onClick?.(event);
47
+ }
48
+ },
49
+ [onClose, onOpenChange, closeButton]
50
+ );
51
+
52
+ const renderCloseButton = useCallback(() => {
53
+ if (!closeButton) return null;
54
+
55
+ if (isValidElement(closeButton)) return closeButton;
56
+
57
+ const closeButtonProps = typeof closeButton === "object" ? closeButton : {};
58
+
59
+ return (
60
+ <IconButton
61
+ aria-label="Close"
62
+ children="✖"
63
+ {...closeButtonProps}
64
+ onClick={handleClose}
65
+ className={classnames(styles["modal-close"], closeButtonProps.className)}
66
+ />
67
+ );
68
+ }, [closeButton, handleClose]);
69
+
70
+ return (
71
+ <Dialog
72
+ {...other}
73
+ onOpenChange={onOpenChange}
74
+ overlayClassName={classnames(styles["modal-overlay"], overlayClassName)}
75
+ className={classnames(
76
+ styles["modal-content"],
77
+ {
78
+ [styles["modal-content--fullscreen"]]: fullscreen,
79
+ [styles[`modal-content--${radius}-radius`]]: radius,
80
+ },
81
+ className
82
+ )}
83
+ >
84
+ {cloneOrCreateElement(
85
+ children,
86
+ {className: classnames(styles["modal-children"], childrenClassName)},
87
+ "div"
88
+ )}
89
+ {renderCloseButton()}
90
+ </Dialog>
91
+ );
92
+ };
93
+
94
+ export default memo(Modal);
@@ -0,0 +1,2 @@
1
+ export {default as Modal, ModalRadius, modalPropsKeys} from "./Modal";
2
+ export type {ModalProps} from "./Modal";