addon-ui 0.3.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 (129) hide show
  1. package/README.md +1197 -0
  2. package/package.json +113 -0
  3. package/src/components/Avatar/Avatar.tsx +56 -0
  4. package/src/components/Avatar/avatar.module.scss +78 -0
  5. package/src/components/Avatar/index.ts +2 -0
  6. package/src/components/Avatar/types.ts +11 -0
  7. package/src/components/BaseButton/BaseButton.tsx +36 -0
  8. package/src/components/BaseButton/base-button.module.scss +24 -0
  9. package/src/components/BaseButton/index.ts +1 -0
  10. package/src/components/Button/Button.tsx +51 -0
  11. package/src/components/Button/button.module.scss +140 -0
  12. package/src/components/Button/index.ts +2 -0
  13. package/src/components/Button/types.ts +24 -0
  14. package/src/components/Checkbox/Checkbox.tsx +58 -0
  15. package/src/components/Checkbox/checkbox.module.scss +82 -0
  16. package/src/components/Checkbox/index.ts +2 -0
  17. package/src/components/Checkbox/types.ts +15 -0
  18. package/src/components/Dialog/Dialog.tsx +126 -0
  19. package/src/components/Dialog/dialog.module.scss +55 -0
  20. package/src/components/Dialog/index.ts +1 -0
  21. package/src/components/Drawer/Drawer.tsx +53 -0
  22. package/src/components/Drawer/drawer.module.scss +170 -0
  23. package/src/components/Drawer/index.ts +2 -0
  24. package/src/components/Drawer/types.ts +6 -0
  25. package/src/components/Footer/Footer.tsx +59 -0
  26. package/src/components/Footer/footer.module.scss +45 -0
  27. package/src/components/Footer/index.ts +1 -0
  28. package/src/components/Header/Header.tsx +74 -0
  29. package/src/components/Header/header.module.scss +56 -0
  30. package/src/components/Header/index.ts +1 -0
  31. package/src/components/Highlight/Highlight.tsx +36 -0
  32. package/src/components/Highlight/highlight.module.scss +48 -0
  33. package/src/components/Highlight/index.ts +2 -0
  34. package/src/components/Highlight/types.ts +5 -0
  35. package/src/components/Icon/Icon.tsx +46 -0
  36. package/src/components/Icon/icon.module.scss +17 -0
  37. package/src/components/Icon/index.ts +1 -0
  38. package/src/components/IconButton/IconButton.tsx +50 -0
  39. package/src/components/IconButton/icon-button.module.scss +86 -0
  40. package/src/components/IconButton/index.ts +2 -0
  41. package/src/components/IconButton/types.ts +17 -0
  42. package/src/components/Layout/Provider.tsx +60 -0
  43. package/src/components/Layout/context.ts +24 -0
  44. package/src/components/Layout/index.ts +2 -0
  45. package/src/components/Layout/layout.module.scss +17 -0
  46. package/src/components/List/List.tsx +24 -0
  47. package/src/components/List/index.ts +1 -0
  48. package/src/components/List/list.module.scss +8 -0
  49. package/src/components/ListItem/ListItem.tsx +75 -0
  50. package/src/components/ListItem/index.ts +1 -0
  51. package/src/components/ListItem/list-item.module.scss +37 -0
  52. package/src/components/Modal/Modal.tsx +90 -0
  53. package/src/components/Modal/index.ts +2 -0
  54. package/src/components/Modal/modal.module.scss +97 -0
  55. package/src/components/Modal/types.ts +6 -0
  56. package/src/components/Odometer/Odometer.tsx +45 -0
  57. package/src/components/Odometer/hooks/useOdometer.tsx +24 -0
  58. package/src/components/Odometer/index.ts +2 -0
  59. package/src/components/Odometer/odometer.module.scss +81 -0
  60. package/src/components/Odometer/odometr.d.ts +9 -0
  61. package/src/components/ScrollArea/ScrollArea.tsx +75 -0
  62. package/src/components/ScrollArea/index.ts +1 -0
  63. package/src/components/ScrollArea/scroll-area.module.scss +58 -0
  64. package/src/components/SvgSprite/SvgSprite.tsx +21 -0
  65. package/src/components/SvgSprite/index.ts +1 -0
  66. package/src/components/Switch/Switch.tsx +24 -0
  67. package/src/components/Switch/index.ts +1 -0
  68. package/src/components/Switch/switch.module.scss +65 -0
  69. package/src/components/Tag/Tag.tsx +50 -0
  70. package/src/components/Tag/index.ts +2 -0
  71. package/src/components/Tag/tag.module.scss +118 -0
  72. package/src/components/Tag/types.ts +23 -0
  73. package/src/components/TextArea/TextArea.tsx +126 -0
  74. package/src/components/TextArea/index.ts +2 -0
  75. package/src/components/TextArea/text-area.module.scss +88 -0
  76. package/src/components/TextArea/types.ts +18 -0
  77. package/src/components/TextField/TextField.tsx +139 -0
  78. package/src/components/TextField/index.ts +2 -0
  79. package/src/components/TextField/text-field.module.scss +129 -0
  80. package/src/components/TextField/types.ts +24 -0
  81. package/src/components/Toast/Toast.tsx +124 -0
  82. package/src/components/Toast/index.ts +2 -0
  83. package/src/components/Toast/toast.module.scss +267 -0
  84. package/src/components/Toast/types.ts +20 -0
  85. package/src/components/Tooltip/Tooltip.tsx +82 -0
  86. package/src/components/Tooltip/index.ts +1 -0
  87. package/src/components/Tooltip/tooltip.module.scss +123 -0
  88. package/src/components/View/View.tsx +68 -0
  89. package/src/components/View/index.ts +1 -0
  90. package/src/components/View/view.module.scss +38 -0
  91. package/src/components/ViewDrawer/ViewDrawer.tsx +24 -0
  92. package/src/components/ViewDrawer/index.ts +1 -0
  93. package/src/components/ViewModal/ViewModal.tsx +24 -0
  94. package/src/components/ViewModal/index.ts +1 -0
  95. package/src/components/index.ts +27 -0
  96. package/src/components/types.ts +65 -0
  97. package/src/config/default.ts +3 -0
  98. package/src/config/index.ts +8 -0
  99. package/src/declaration.d.ts +8 -0
  100. package/src/index.ts +3 -0
  101. package/src/plugin/builder/ConfigBuilder.ts +32 -0
  102. package/src/plugin/builder/StyleBuilder.ts +35 -0
  103. package/src/plugin/builder/virtual.config.ts +5 -0
  104. package/src/plugin/finder/ConfigFinder.ts +26 -0
  105. package/src/plugin/finder/Finder.ts +76 -0
  106. package/src/plugin/finder/StyleFinder.ts +23 -0
  107. package/src/plugin/index.ts +73 -0
  108. package/src/plugin/types.ts +8 -0
  109. package/src/providers/extra/ExtraProvider.tsx +13 -0
  110. package/src/providers/extra/context.ts +14 -0
  111. package/src/providers/extra/index.ts +2 -0
  112. package/src/providers/icons/IconsProvider.tsx +35 -0
  113. package/src/providers/icons/context.ts +20 -0
  114. package/src/providers/icons/index.ts +2 -0
  115. package/src/providers/index.ts +4 -0
  116. package/src/providers/theme/ThemeProvider.tsx +60 -0
  117. package/src/providers/theme/ThemeStorage.tsx +36 -0
  118. package/src/providers/theme/context.ts +30 -0
  119. package/src/providers/theme/index.ts +3 -0
  120. package/src/providers/ui/UIProvider.tsx +41 -0
  121. package/src/providers/ui/index.ts +1 -0
  122. package/src/providers/ui/styles/default.scss +95 -0
  123. package/src/providers/ui/styles/reset.scss +127 -0
  124. package/src/styles/mixins.scss +23 -0
  125. package/src/types/config.ts +15 -0
  126. package/src/types/theme.ts +11 -0
  127. package/src/utils/index.ts +2 -0
  128. package/src/utils/react.ts +21 -0
  129. package/src/utils/utils.ts +12 -0
@@ -0,0 +1,15 @@
1
+ export enum CheckboxVariant {
2
+ Classic = "classic",
3
+ Soft = "soft",
4
+ }
5
+
6
+ export enum CheckboxSize {
7
+ Small = "small",
8
+ Medium = "medium",
9
+ Large = "large",
10
+ }
11
+
12
+ export enum CheckboxRadius {
13
+ Small = "small",
14
+ Large = "large",
15
+ }
@@ -0,0 +1,126 @@
1
+ import React, {memo, useEffect, useRef, forwardRef, ForwardRefRenderFunction} from "react";
2
+ import classnames from "classnames";
3
+ import {
4
+ Content,
5
+ Description,
6
+ DialogContentProps,
7
+ DialogPortalProps,
8
+ DialogProps as DialogRootProps,
9
+ Overlay,
10
+ Portal,
11
+ Root,
12
+ Title,
13
+ } from "@radix-ui/react-dialog";
14
+ import {VisuallyHidden} from "radix-ui";
15
+
16
+ import {useComponentProps} from "../../providers";
17
+ import {cloneOrCreateElement} from "../../utils";
18
+
19
+ import styles from "./dialog.module.scss";
20
+
21
+ export interface DialogProps extends DialogRootProps, DialogPortalProps, DialogContentProps {
22
+ speed?: number;
23
+ description?: string;
24
+ fullscreen?: boolean;
25
+ className?: string;
26
+ overlayClassName?: string;
27
+ childrenClassName?: string;
28
+ }
29
+
30
+ export const dialogPropsKeys = new Set<keyof DialogProps>([
31
+ // Dialog keys
32
+ "speed",
33
+ "description",
34
+ "fullscreen",
35
+ "className",
36
+ "overlayClassName",
37
+ "childrenClassName",
38
+
39
+ // Extended Dialog keys
40
+ "open",
41
+ "defaultOpen",
42
+ "onOpenChange",
43
+ "modal",
44
+ "container",
45
+ "title",
46
+ ]);
47
+
48
+ const Dialog: ForwardRefRenderFunction<HTMLDivElement, DialogProps> = (props, ref) => {
49
+ const {
50
+ speed = 200,
51
+ open,
52
+ defaultOpen,
53
+ onOpenChange,
54
+ modal,
55
+ children,
56
+ container,
57
+ title,
58
+ description,
59
+ className,
60
+ overlayClassName,
61
+ childrenClassName,
62
+ ...other
63
+ } = {...useComponentProps("dialog"), ...props};
64
+
65
+ const timeoutId = useRef<ReturnType<typeof setTimeout> | undefined>(undefined);
66
+ const intervalId = useRef<ReturnType<typeof setInterval> | undefined>(undefined);
67
+
68
+ useEffect(() => {
69
+ clearInterval(intervalId.current);
70
+ clearTimeout(timeoutId.current);
71
+
72
+ if (open) {
73
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
74
+ document.body.style.overflow = "hidden";
75
+ document.body.style.boxSizing = "border-box";
76
+ document.body.style.setProperty("padding-right", `${scrollbarWidth}px`, "important");
77
+ } else {
78
+ intervalId.current = setInterval(() => {
79
+ const scrollbarWidth = window.innerWidth - document.documentElement.clientWidth;
80
+ if (scrollbarWidth) {
81
+ document.body.style.overflow = "";
82
+ document.body.style.paddingRight = "";
83
+ clearInterval(intervalId.current);
84
+ }
85
+ }, 10);
86
+
87
+ timeoutId.current = setTimeout(() => {
88
+ clearInterval(intervalId.current);
89
+ }, speed + 100);
90
+ }
91
+
92
+ return () => {
93
+ document.body.style.overflow = "";
94
+ };
95
+ }, [open, speed]);
96
+
97
+ return (
98
+ <Root open={open} defaultOpen={defaultOpen} onOpenChange={onOpenChange} modal={modal}>
99
+ <Portal container={container}>
100
+ <Overlay
101
+ className={classnames(styles["dialog-overlay"], overlayClassName)}
102
+ style={{animationDuration: `${speed}ms`}}
103
+ />
104
+ <Content
105
+ ref={ref}
106
+ className={classnames(styles["dialog-content"], className)}
107
+ style={{animationDuration: `${speed}ms`}}
108
+ {...other}
109
+ >
110
+ <VisuallyHidden.Root>
111
+ <Title>{title}</Title>
112
+ <Description>{description}</Description>
113
+ </VisuallyHidden.Root>
114
+
115
+ {cloneOrCreateElement(
116
+ children,
117
+ {className: classnames(styles["dialog-children"], childrenClassName)},
118
+ "div"
119
+ )}
120
+ </Content>
121
+ </Portal>
122
+ </Root>
123
+ );
124
+ };
125
+
126
+ export default memo(forwardRef(Dialog));
@@ -0,0 +1,55 @@
1
+ $root: dialog;
2
+
3
+ .#{$root} {
4
+ &-overlay {
5
+ position: fixed;
6
+ inset: 0;
7
+ z-index: 999;
8
+ background-color: var(--dialog-overlay-bg-color, #111);
9
+ opacity: var(--dialog-animation-overlay-opacity, 0.9);
10
+ animation-timing-function: ease-in-out;
11
+
12
+ &[data-state="open"] {
13
+ animation-name: overlayShow;
14
+ }
15
+
16
+ &[data-state="closed"] {
17
+ animation-name: overlayHide;
18
+ }
19
+ }
20
+
21
+ &-content {
22
+ box-sizing: border-box;
23
+ position: fixed;
24
+ z-index: 9999;
25
+ transition:
26
+ background-color var(--transition-speed-sm),
27
+ color var(--transition-speed-sm);
28
+ animation-timing-function: ease-in-out;
29
+ }
30
+
31
+ &-children {
32
+ display: flex;
33
+ flex-direction: column;
34
+ width: 100%;
35
+ height: 100%;
36
+ }
37
+ }
38
+
39
+ @keyframes overlayShow {
40
+ from {
41
+ opacity: 0;
42
+ }
43
+ to {
44
+ opacity: var(--dialog-animation-overlay-opacity, 0.9);
45
+ }
46
+ }
47
+
48
+ @keyframes overlayHide {
49
+ from {
50
+ opacity: var(--dialog-animation-overlay-opacity, 0.9);
51
+ }
52
+ to {
53
+ opacity: 0;
54
+ }
55
+ }
@@ -0,0 +1 @@
1
+ export {default as Dialog, dialogPropsKeys, type DialogProps} from "./Dialog";
@@ -0,0 +1,53 @@
1
+ import React, {memo, forwardRef, ForwardRefRenderFunction} 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
+
9
+ import {DrawerSide} from "./types";
10
+
11
+ import styles from "./drawer.module.scss";
12
+
13
+ export interface DrawerProps extends DialogProps {
14
+ side?: DrawerSide;
15
+ }
16
+
17
+ export const drawerPropsKeys = new Set<keyof DrawerProps>(["side", ...dialogPropsKeys]);
18
+
19
+ const Drawer: ForwardRefRenderFunction<HTMLDivElement, DrawerProps> = (props, ref) => {
20
+ const {
21
+ side = DrawerSide.Left,
22
+ fullscreen,
23
+ children,
24
+ className,
25
+ overlayClassName,
26
+ childrenClassName,
27
+ ...other
28
+ } = {...useComponentProps("drawer"), ...props};
29
+
30
+ return (
31
+ <Dialog
32
+ ref={ref}
33
+ {...other}
34
+ overlayClassName={classnames(styles["drawer-overlay"], overlayClassName)}
35
+ className={classnames(
36
+ styles["drawer-content"],
37
+ {
38
+ [styles["drawer-content--fullscreen"]]: fullscreen,
39
+ [styles[`drawer-content--${side}-side`]]: side,
40
+ },
41
+ className
42
+ )}
43
+ >
44
+ {cloneOrCreateElement(
45
+ children,
46
+ {className: classnames(styles["drawer-children"], childrenClassName)},
47
+ "div"
48
+ )}
49
+ </Dialog>
50
+ );
51
+ };
52
+
53
+ export default memo(forwardRef(Drawer));
@@ -0,0 +1,170 @@
1
+ $root: drawer;
2
+
3
+ .#{$root} {
4
+ &-overlay {
5
+ background-color: var(--drawer-overlay-bg-color, var(--dialog-overlay-bg-color, #111));
6
+ }
7
+
8
+ &-content {
9
+ padding: var(--drawer-padding, 0);
10
+ box-shadow: var(--drawer-box-shadow, 0 0 4px rgba(0, 0, 0, 0.5));
11
+ background-color: var(--drawer-bg-color, var(--bg-secondary-color));
12
+
13
+ &[data-state="open"] {
14
+ &.#{$root}-content--left-side {
15
+ animation-name: slideInLeft;
16
+ }
17
+
18
+ &.#{$root}-content--right-side {
19
+ animation-name: slideInRight;
20
+ }
21
+
22
+ &.#{$root}-content--top-side {
23
+ animation-name: slideInTop;
24
+ }
25
+
26
+ &.#{$root}-content--bottom-side {
27
+ animation-name: slideInBottom;
28
+ }
29
+ }
30
+
31
+ &[data-state="closed"] {
32
+ &.#{$root}-content--left-side {
33
+ animation-name: slideOutLeft;
34
+ }
35
+
36
+ &.#{$root}-content--right-side {
37
+ animation-name: slideOutRight;
38
+ }
39
+
40
+ &.#{$root}-content--top-side {
41
+ animation-name: slideOutTop;
42
+ }
43
+
44
+ &.#{$root}-content--bottom-side {
45
+ animation-name: slideOutBottom;
46
+ }
47
+ }
48
+
49
+ &--left-side {
50
+ left: 0;
51
+ top: 0;
52
+ bottom: 0;
53
+ width: var(--drawer-width, 90vw);
54
+
55
+ &.#{$root}-content--fullscreen {
56
+ width: 100%;
57
+ }
58
+ }
59
+
60
+ &--right-side {
61
+ right: 0;
62
+ top: 0;
63
+ bottom: 0;
64
+ width: var(--drawer-width, 90vw);
65
+
66
+ &.#{$root}-content--fullscreen {
67
+ width: 100%;
68
+ }
69
+ }
70
+
71
+ &--top-side {
72
+ top: 0;
73
+ left: 0;
74
+ right: 0;
75
+ height: var(--drawer-height, 90vh);
76
+
77
+ &.#{$root}-content--fullscreen {
78
+ height: 100%;
79
+ }
80
+ }
81
+
82
+ &--bottom-side {
83
+ bottom: 0;
84
+ left: 0;
85
+ right: 0;
86
+ height: var(--drawer-height, 90vh);
87
+
88
+ &.#{$root}-content--fullscreen {
89
+ height: 100%;
90
+ }
91
+ }
92
+ }
93
+
94
+ &-children {
95
+ display: flex;
96
+ flex-direction: column;
97
+ }
98
+ }
99
+
100
+ @keyframes slideInRight {
101
+ from {
102
+ transform: translateX(100%);
103
+ }
104
+ to {
105
+ transform: translateX(0);
106
+ }
107
+ }
108
+
109
+ @keyframes slideInLeft {
110
+ from {
111
+ transform: translateX(-100%);
112
+ }
113
+ to {
114
+ transform: translateX(0);
115
+ }
116
+ }
117
+
118
+ @keyframes slideInTop {
119
+ from {
120
+ transform: translateY(-100%);
121
+ }
122
+ to {
123
+ transform: translateY(0);
124
+ }
125
+ }
126
+
127
+ @keyframes slideInBottom {
128
+ from {
129
+ transform: translateY(100%);
130
+ }
131
+ to {
132
+ transform: translateY(0);
133
+ }
134
+ }
135
+
136
+ @keyframes slideOutRight {
137
+ from {
138
+ transform: translateX(0);
139
+ }
140
+ to {
141
+ transform: translateX(100%);
142
+ }
143
+ }
144
+
145
+ @keyframes slideOutLeft {
146
+ from {
147
+ transform: translateX(0);
148
+ }
149
+ to {
150
+ transform: translateX(-100%);
151
+ }
152
+ }
153
+
154
+ @keyframes slideOutTop {
155
+ from {
156
+ transform: translateY(0);
157
+ }
158
+ to {
159
+ transform: translateY(-100%);
160
+ }
161
+ }
162
+
163
+ @keyframes slideOutBottom {
164
+ from {
165
+ transform: translateY(0);
166
+ }
167
+ to {
168
+ transform: translateY(100%);
169
+ }
170
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./types";
2
+ export {default as Drawer, drawerPropsKeys, type DrawerProps} from "./Drawer";
@@ -0,0 +1,6 @@
1
+ export enum DrawerSide {
2
+ Left = "left",
3
+ Right = "right",
4
+ Top = "top",
5
+ Bottom = "bottom",
6
+ }
@@ -0,0 +1,59 @@
1
+ import React, {ComponentProps, memo, ReactNode, forwardRef, ForwardRefRenderFunction} from "react";
2
+ import classnames from "classnames";
3
+
4
+ import {cloneOrCreateElement} from "../../utils";
5
+ import {useComponentProps} from "../../providers";
6
+
7
+ import styles from "./footer.module.scss";
8
+
9
+ export interface FooterProps extends ComponentProps<"footer"> {
10
+ left?: ReactNode;
11
+ right?: ReactNode;
12
+ shadow?: boolean;
13
+ reverse?: boolean;
14
+ leftClassName?: string;
15
+ rightClassName?: string;
16
+ childrenClassName?: string;
17
+ }
18
+
19
+ const Footer: ForwardRefRenderFunction<HTMLElement, FooterProps> = (props, ref) => {
20
+ const {
21
+ left,
22
+ right,
23
+ shadow,
24
+ reverse,
25
+ children,
26
+ className,
27
+ leftClassName,
28
+ rightClassName,
29
+ childrenClassName,
30
+ ...other
31
+ } = {...useComponentProps("footer"), ...props};
32
+
33
+ return (
34
+ <footer
35
+ ref={ref}
36
+ {...other}
37
+ className={classnames(
38
+ styles["footer"],
39
+ {
40
+ [styles["footer--shadow"]]: shadow,
41
+ [styles["footer--reverse"]]: reverse,
42
+ },
43
+ className
44
+ )}
45
+ >
46
+ {cloneOrCreateElement(
47
+ children,
48
+ {className: classnames(styles["footer-children"], childrenClassName)},
49
+ "div"
50
+ )}
51
+ {!children &&
52
+ cloneOrCreateElement(left, {className: classnames(styles["footer-left"], leftClassName)}, "div")}
53
+ {!children &&
54
+ cloneOrCreateElement(right, {className: classnames(styles["footer-right"], rightClassName)}, "div")}
55
+ </footer>
56
+ );
57
+ };
58
+
59
+ export default memo(forwardRef(Footer));
@@ -0,0 +1,45 @@
1
+ $root: footer;
2
+
3
+ .#{$root} {
4
+ box-sizing: border-box;
5
+ display: flex;
6
+ justify-content: space-between;
7
+ align-items: center;
8
+ width: 100%;
9
+ padding: var(--footer-padding, var(--side-padding-sm));
10
+ padding-top: 0;
11
+ background-color: var(--footer-bg-color, transparent);
12
+ transition:
13
+ background-color var(--transition-speed-sm),
14
+ box-shadow var(--transition-speed-sm);
15
+
16
+ &--shadow {
17
+ box-shadow: var(--footer-box-shadow, 0px -4px 4px 0px rgba(0, 0, 0, 0.03));
18
+ }
19
+
20
+ &--reverse {
21
+ flex-direction: row-reverse;
22
+ }
23
+
24
+ &-children {
25
+ width: 100%;
26
+ display: flex;
27
+ justify-content: space-between;
28
+
29
+ .#{$root}--reverse & {
30
+ flex-direction: row-reverse;
31
+ }
32
+ }
33
+
34
+ &-left {
35
+ display: flex;
36
+ align-items: center;
37
+ gap: var(--footer-left-gap, var(--footer-gap, 15px));
38
+ }
39
+
40
+ &-right {
41
+ display: flex;
42
+ align-items: center;
43
+ gap: var(--footer-right-gap, var(--footer-gap, 15px));
44
+ }
45
+ }
@@ -0,0 +1 @@
1
+ export {default as Footer, type FooterProps} from "./Footer";
@@ -0,0 +1,74 @@
1
+ import React, {ComponentProps, memo, ReactNode, forwardRef, ForwardRefRenderFunction} from "react";
2
+ import classnames from "classnames";
3
+
4
+ import {cloneOrCreateElement} from "../../utils";
5
+ import {useComponentProps} from "../../providers";
6
+
7
+ import styles from "./header.module.scss";
8
+
9
+ export interface HeaderProps extends Omit<ComponentProps<"header">, "title"> {
10
+ title?: ReactNode;
11
+ before?: ReactNode;
12
+ after?: ReactNode;
13
+ subtitle?: ReactNode;
14
+ wrapClassName?: string;
15
+ titleClassName?: string;
16
+ beforeClassName?: string;
17
+ afterClassName?: string;
18
+ subtitleClassName?: string;
19
+ childrenClassName?: string;
20
+ alignCenter?: boolean;
21
+ }
22
+
23
+ const Header: ForwardRefRenderFunction<HTMLElement, HeaderProps> = (props, ref) => {
24
+ const {
25
+ title,
26
+ before,
27
+ after,
28
+ subtitle,
29
+ className,
30
+ wrapClassName,
31
+ titleClassName,
32
+ beforeClassName,
33
+ afterClassName,
34
+ subtitleClassName,
35
+ childrenClassName,
36
+ alignCenter = true,
37
+ children,
38
+ ...other
39
+ } = {...useComponentProps("header"), ...props};
40
+
41
+ return (
42
+ <header
43
+ ref={ref}
44
+ {...other}
45
+ className={classnames(
46
+ styles["header"],
47
+ {
48
+ [styles["header--center"]]: alignCenter,
49
+ },
50
+ className
51
+ )}
52
+ >
53
+ {(title || subtitle) && (
54
+ <div className={classnames(styles["header__wrap"], wrapClassName)}>
55
+ <h1 className={classnames(styles["header__title"], titleClassName)}>
56
+ {cloneOrCreateElement(before, {className: beforeClassName})}
57
+ {title}
58
+ {cloneOrCreateElement(after, {className: afterClassName})}
59
+ </h1>
60
+
61
+ {cloneOrCreateElement(
62
+ subtitle,
63
+ {className: classnames(styles["header__subtitle"], subtitleClassName)},
64
+ "h2"
65
+ )}
66
+ </div>
67
+ )}
68
+
69
+ {cloneOrCreateElement(children, {className: childrenClassName}, "div")}
70
+ </header>
71
+ );
72
+ };
73
+
74
+ export default memo(forwardRef(Header));
@@ -0,0 +1,56 @@
1
+ $root: header;
2
+
3
+ .#{$root} {
4
+ display: flex;
5
+ flex-direction: column;
6
+ width: 100%;
7
+ box-sizing: border-box;
8
+ gap: var(--header-gap, 10px);
9
+ padding: var(--header-padding, var(--side-padding-sm));
10
+ padding-bottom: 0;
11
+
12
+ &__wrap {
13
+ display: flex;
14
+ flex-direction: column;
15
+ overflow: hidden;
16
+ white-space: nowrap;
17
+ gap: var(--header-wrap-gap, 10px);
18
+ }
19
+
20
+ &__title,
21
+ &__subtitle {
22
+ margin: 0;
23
+ overflow: hidden;
24
+ text-overflow: ellipsis;
25
+ }
26
+
27
+ &__title {
28
+ display: flex;
29
+ align-items: center;
30
+ gap: var(--header-title-gap, 12px);
31
+ color: var(--header-title-color, var(--text-primary-color));
32
+ font-size: var(--header-title-font-size, 25px);
33
+ font-family: var(--header-title-font-family, var(--font-family)), "sans-serif";
34
+ font-weight: var(--header-title-font-weight, 700);
35
+ line-height: var(--header-title-line-height, 120%);
36
+ will-change: color;
37
+ transition: color var(--header-title-transition-speed, var(--transition-speed-md));
38
+
39
+ .#{$root}--center & {
40
+ justify-content: center;
41
+ }
42
+ }
43
+
44
+ &__subtitle {
45
+ color: var(--header-subtitle-color, var(--text-secondary-color));
46
+ font-size: var(--header-subtitle-font-size, 14px);
47
+ font-family: var(--header-subtitle-font-family, var(--font-family)), "sans-serif";
48
+ font-weight: var(--header-subtitle-font-weight, 400);
49
+ line-height: var(--header-subtitle-line-height, 120%);
50
+ white-space: wrap;
51
+
52
+ .#{$root}--center & {
53
+ text-align: center;
54
+ }
55
+ }
56
+ }
@@ -0,0 +1 @@
1
+ export {default as Header, type HeaderProps} from "./Header";