@ainias42/react-bootstrap-mobile 0.1.7

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 (233) hide show
  1. package/.eslintrc.json +189 -0
  2. package/.prettierrc +5 -0
  3. package/LICENSE +21 -0
  4. package/README.md +1 -0
  5. package/babel.config.js +22 -0
  6. package/bin/build.js +60 -0
  7. package/bin/release.sh +35 -0
  8. package/bin/updateCopies.js +86 -0
  9. package/bootstrapReactMobile.ts +87 -0
  10. package/dist/bootstrapReactMobile.d.ts +87 -0
  11. package/dist/bootstrapReactMobile.js +6275 -0
  12. package/dist/src/Components/ActionSheet/ActionSheet.d.ts +21 -0
  13. package/dist/src/Components/Card/Card.d.ts +13 -0
  14. package/dist/src/Components/Clickable/Clickable.d.ts +14 -0
  15. package/dist/src/Components/Dialog/AlertDialog.d.ts +10 -0
  16. package/dist/src/Components/Dialog/ButtonDialog.d.ts +13 -0
  17. package/dist/src/Components/Dialog/ConfirmDialog.d.ts +11 -0
  18. package/dist/src/Components/Dialog/Dialog.d.ts +14 -0
  19. package/dist/src/Components/Dialog/DialogBackground.d.ts +7 -0
  20. package/dist/src/Components/Dialog/DialogContainer.d.ts +6 -0
  21. package/dist/src/Components/Dialog/DialogContext.d.ts +9 -0
  22. package/dist/src/Components/Dialog/useAlertDialog.d.ts +1 -0
  23. package/dist/src/Components/Dialog/useConfirmDialog.d.ts +1 -0
  24. package/dist/src/Components/DragAndDrop/DragItem.d.ts +7 -0
  25. package/dist/src/Components/DragAndDrop/DropArea.d.ts +7 -0
  26. package/dist/src/Components/DragAndDrop/useStrictEnabled.d.ts +1 -0
  27. package/dist/src/Components/FormElements/Button/Button.d.ts +8 -0
  28. package/dist/src/Components/FormElements/CheckBox/Checkbox.d.ts +10 -0
  29. package/dist/src/Components/FormElements/ColorInput/ColorInput.d.ts +17 -0
  30. package/dist/src/Components/FormElements/ColorInput/sharedSelectedColor.d.ts +4 -0
  31. package/dist/src/Components/FormElements/ImageInput/ImageInput.d.ts +17 -0
  32. package/dist/src/Components/FormElements/Input/HiddenInput.d.ts +8 -0
  33. package/dist/src/Components/FormElements/Input/Input.d.ts +10 -0
  34. package/dist/src/Components/FormElements/Input/PasswordInput/PasswordInput.d.ts +4 -0
  35. package/dist/src/Components/FormElements/SearchSelectInput/SearchSelectInput.d.ts +10 -0
  36. package/dist/src/Components/FormElements/Select/Select.d.ts +16 -0
  37. package/dist/src/Components/FormElements/Slider/Slider.d.ts +8 -0
  38. package/dist/src/Components/FormElements/Switch/Switch.d.ts +12 -0
  39. package/dist/src/Components/FormElements/Textarea/Textarea.d.ts +12 -0
  40. package/dist/src/Components/FormElements/hooks/useOnChangeDone.d.ts +2 -0
  41. package/dist/src/Components/FullScreen/FullScreen.d.ts +14 -0
  42. package/dist/src/Components/Hooks/useBreakpoint.d.ts +11 -0
  43. package/dist/src/Components/Hooks/useComposedRef.d.ts +2 -0
  44. package/dist/src/Components/Hooks/useDebounced.d.ts +1 -0
  45. package/dist/src/Components/Hooks/useDelayed.d.ts +1 -0
  46. package/dist/src/Components/Hooks/useInViewport.d.ts +2 -0
  47. package/dist/src/Components/Hooks/useKeyListener.d.ts +3 -0
  48. package/dist/src/Components/Hooks/useListener.d.ts +18 -0
  49. package/dist/src/Components/Hooks/useOnMount.d.ts +1 -0
  50. package/dist/src/Components/Hooks/useOnce.d.ts +1 -0
  51. package/dist/src/Components/Icon/Icon.d.ts +13 -0
  52. package/dist/src/Components/Image/Image.d.ts +12 -0
  53. package/dist/src/Components/InViewport/InViewport.d.ts +11 -0
  54. package/dist/src/Components/Layout/Block.d.ts +7 -0
  55. package/dist/src/Components/Layout/Container.d.ts +15 -0
  56. package/dist/src/Components/Layout/Flex.d.ts +10 -0
  57. package/dist/src/Components/Layout/Grid/Grid.d.ts +9 -0
  58. package/dist/src/Components/Layout/Grid/GridItem.d.ts +25 -0
  59. package/dist/src/Components/Layout/Grow.d.ts +9 -0
  60. package/dist/src/Components/Layout/Inline.d.ts +7 -0
  61. package/dist/src/Components/Layout/InlineBlock.d.ts +7 -0
  62. package/dist/src/Components/Layout/View.d.ts +9 -0
  63. package/dist/src/Components/Layout/ViewWithoutListeners.d.ts +8 -0
  64. package/dist/src/Components/List/BulletList/BulletList.d.ts +8 -0
  65. package/dist/src/Components/List/BulletList/ListItem.d.ts +7 -0
  66. package/dist/src/Components/List/List.d.ts +10 -0
  67. package/dist/src/Components/LoadingArea/LoadingArea.d.ts +12 -0
  68. package/dist/src/Components/LoadingCircle/LoadingCircle.d.ts +8 -0
  69. package/dist/src/Components/Menu/Menu.d.ts +16 -0
  70. package/dist/src/Components/Menu/useMenu.d.ts +3 -0
  71. package/dist/src/Components/RbmComponentProps.d.ts +31 -0
  72. package/dist/src/Components/SizeCalculator/SizeCalculator.d.ts +9 -0
  73. package/dist/src/Components/SpoilerList/Spoiler/Spoiler.d.ts +15 -0
  74. package/dist/src/Components/SpoilerList/SpoilerList.d.ts +15 -0
  75. package/dist/src/Components/SpoilerList/useSpoilerGroup.d.ts +12 -0
  76. package/dist/src/Components/TabBar/TabBar.d.ts +30 -0
  77. package/dist/src/Components/TabBar/TabBarButton.d.ts +9 -0
  78. package/dist/src/Components/Table/Table.d.ts +36 -0
  79. package/dist/src/Components/Text/Heading.d.ts +7 -0
  80. package/dist/src/Components/Text/Text.d.ts +26 -0
  81. package/dist/src/Components/Toast/Toast.d.ts +13 -0
  82. package/dist/src/Components/Toast/ToastContainer.d.ts +7 -0
  83. package/dist/src/Components/TopBar/MoreButton.d.ts +9 -0
  84. package/dist/src/Components/TopBar/TopBar.d.ts +25 -0
  85. package/dist/src/Components/TopBar/TopBarButton.d.ts +9 -0
  86. package/dist/src/StyleProvider.d.ts +2 -0
  87. package/dist/src/TypeHelpers.d.ts +4 -0
  88. package/dist/src/WindowContext/WindowContext.d.ts +3 -0
  89. package/dist/src/WrongChildError.d.ts +4 -0
  90. package/dist/src/helper/Characters.d.ts +5 -0
  91. package/dist/src/helper/DistributiveOmit.d.ts +1 -0
  92. package/dist/src/helper/EmptyProps.d.ts +1 -0
  93. package/dist/src/helper/memoComparator.d.ts +1 -0
  94. package/dist/src/helper/nonEmptyString.d.ts +1 -0
  95. package/dist/src/helper/withForwardRef.d.ts +7 -0
  96. package/dist/src/helper/withMemo.d.ts +3 -0
  97. package/dist/src/helper/withRenderBrowserOnly.d.ts +2 -0
  98. package/dist/src/helper/withRestrictedChildren.d.ts +6 -0
  99. package/package.json +92 -0
  100. package/react-bootstrap-mobile.scss +6 -0
  101. package/scripts/getPackageJson.js +25 -0
  102. package/src/Components/ActionSheet/ActionSheet.tsx +115 -0
  103. package/src/Components/ActionSheet/actionSheet.scss +153 -0
  104. package/src/Components/Card/Card.tsx +46 -0
  105. package/src/Components/Card/card.scss +76 -0
  106. package/src/Components/Clickable/Clickable.tsx +174 -0
  107. package/src/Components/Clickable/clickable.scss +3 -0
  108. package/src/Components/Dialog/AlertDialog.tsx +44 -0
  109. package/src/Components/Dialog/ButtonDialog.tsx +57 -0
  110. package/src/Components/Dialog/ConfirmDialog.tsx +46 -0
  111. package/src/Components/Dialog/Dialog.tsx +82 -0
  112. package/src/Components/Dialog/DialogBackground.tsx +38 -0
  113. package/src/Components/Dialog/DialogContainer.tsx +77 -0
  114. package/src/Components/Dialog/DialogContext.ts +21 -0
  115. package/src/Components/Dialog/buttonDialog.scss +114 -0
  116. package/src/Components/Dialog/dialog.scss +30 -0
  117. package/src/Components/Dialog/dialogBackground.scss +4 -0
  118. package/src/Components/Dialog/useAlertDialog.ts +13 -0
  119. package/src/Components/Dialog/useConfirmDialog.ts +13 -0
  120. package/src/Components/DragAndDrop/DragItem.tsx +38 -0
  121. package/src/Components/DragAndDrop/DropArea.tsx +43 -0
  122. package/src/Components/DragAndDrop/useStrictEnabled.ts +20 -0
  123. package/src/Components/FormElements/Button/Button.tsx +25 -0
  124. package/src/Components/FormElements/Button/button.scss +39 -0
  125. package/src/Components/FormElements/CheckBox/Checkbox.tsx +61 -0
  126. package/src/Components/FormElements/CheckBox/checkbox.scss +107 -0
  127. package/src/Components/FormElements/ColorInput/ColorInput.tsx +139 -0
  128. package/src/Components/FormElements/ColorInput/colorInput.scss +35 -0
  129. package/src/Components/FormElements/ColorInput/sharedSelectedColor.ts +40 -0
  130. package/src/Components/FormElements/ImageInput/ImageInput.tsx +97 -0
  131. package/src/Components/FormElements/ImageInput/imageInput.scss +24 -0
  132. package/src/Components/FormElements/Input/HiddenInput.tsx +43 -0
  133. package/src/Components/FormElements/Input/Input.tsx +102 -0
  134. package/src/Components/FormElements/Input/PasswordInput/PasswordInput.tsx +55 -0
  135. package/src/Components/FormElements/Input/PasswordInput/passwordInput.scss +7 -0
  136. package/src/Components/FormElements/Input/input.scss +57 -0
  137. package/src/Components/FormElements/SearchSelectInput/SearchSelectInput.tsx +162 -0
  138. package/src/Components/FormElements/SearchSelectInput/seachSelectInput.scss +90 -0
  139. package/src/Components/FormElements/Select/Select.tsx +77 -0
  140. package/src/Components/FormElements/Select/select.scss +51 -0
  141. package/src/Components/FormElements/Slider/Slider.tsx +80 -0
  142. package/src/Components/FormElements/Slider/slider.scss +92 -0
  143. package/src/Components/FormElements/Switch/Switch.tsx +82 -0
  144. package/src/Components/FormElements/Switch/switch.scss +149 -0
  145. package/src/Components/FormElements/Textarea/Textarea.tsx +77 -0
  146. package/src/Components/FormElements/Textarea/textarea.scss +22 -0
  147. package/src/Components/FormElements/hooks/useOnChangeDone.ts +16 -0
  148. package/src/Components/FullScreen/FullScreen.tsx +89 -0
  149. package/src/Components/Hooks/useBreakpoint.ts +66 -0
  150. package/src/Components/Hooks/useComposedRef.ts +17 -0
  151. package/src/Components/Hooks/useDebounced.ts +22 -0
  152. package/src/Components/Hooks/useDelayed.ts +46 -0
  153. package/src/Components/Hooks/useInViewport.ts +23 -0
  154. package/src/Components/Hooks/useKeyListener.ts +77 -0
  155. package/src/Components/Hooks/useListener.ts +73 -0
  156. package/src/Components/Hooks/useOnMount.ts +12 -0
  157. package/src/Components/Hooks/useOnce.ts +11 -0
  158. package/src/Components/Icon/Icon.tsx +45 -0
  159. package/src/Components/Image/Image.tsx +44 -0
  160. package/src/Components/Image/image.scss +3 -0
  161. package/src/Components/InViewport/InViewport.tsx +71 -0
  162. package/src/Components/InViewport/inViewport.scss +3 -0
  163. package/src/Components/Layout/Block.tsx +48 -0
  164. package/src/Components/Layout/Container.tsx +57 -0
  165. package/src/Components/Layout/Flex.tsx +51 -0
  166. package/src/Components/Layout/Grid/Grid.tsx +53 -0
  167. package/src/Components/Layout/Grid/GridItem.tsx +138 -0
  168. package/src/Components/Layout/Grid/grid.scss +43 -0
  169. package/src/Components/Layout/Grow.tsx +51 -0
  170. package/src/Components/Layout/Inline.tsx +48 -0
  171. package/src/Components/Layout/InlineBlock.tsx +48 -0
  172. package/src/Components/Layout/View.tsx +40 -0
  173. package/src/Components/Layout/ViewWithoutListeners.tsx +40 -0
  174. package/src/Components/Layout/container.scss +12 -0
  175. package/src/Components/Layout/layout.scss +56 -0
  176. package/src/Components/List/BulletList/BulletList.tsx +33 -0
  177. package/src/Components/List/BulletList/ListItem.tsx +34 -0
  178. package/src/Components/List/List.tsx +88 -0
  179. package/src/Components/List/list.scss +30 -0
  180. package/src/Components/LoadingArea/LoadingArea.tsx +64 -0
  181. package/src/Components/LoadingArea/loadingArea.scss +19 -0
  182. package/src/Components/LoadingCircle/LoadingCircle.tsx +41 -0
  183. package/src/Components/LoadingCircle/loadingCircle.scss +42 -0
  184. package/src/Components/Menu/Menu.tsx +113 -0
  185. package/src/Components/Menu/menu.scss +21 -0
  186. package/src/Components/Menu/useMenu.ts +20 -0
  187. package/src/Components/RbmComponentProps.ts +40 -0
  188. package/src/Components/SizeCalculator/SizeCalculator.tsx +45 -0
  189. package/src/Components/SpoilerList/Spoiler/Spoiler.tsx +106 -0
  190. package/src/Components/SpoilerList/Spoiler/spoiler.scss +120 -0
  191. package/src/Components/SpoilerList/SpoilerList.tsx +63 -0
  192. package/src/Components/SpoilerList/useSpoilerGroup.ts +39 -0
  193. package/src/Components/TabBar/TabBar.tsx +117 -0
  194. package/src/Components/TabBar/TabBarButton.tsx +44 -0
  195. package/src/Components/TabBar/tabBar.scss +108 -0
  196. package/src/Components/Table/Table.tsx +182 -0
  197. package/src/Components/Text/Heading.tsx +44 -0
  198. package/src/Components/Text/Text.tsx +79 -0
  199. package/src/Components/Text/heading.scss +3 -0
  200. package/src/Components/Text/text.scss +60 -0
  201. package/src/Components/Toast/Toast.tsx +107 -0
  202. package/src/Components/Toast/ToastContainer.tsx +35 -0
  203. package/src/Components/Toast/toast.scss +52 -0
  204. package/src/Components/TopBar/MoreButton.tsx +38 -0
  205. package/src/Components/TopBar/TopBar.tsx +176 -0
  206. package/src/Components/TopBar/TopBarButton.tsx +29 -0
  207. package/src/Components/TopBar/topBar.scss +124 -0
  208. package/src/StyleProvider.ts +4 -0
  209. package/src/TypeHelpers.ts +4 -0
  210. package/src/WindowContext/WindowContext.ts +8 -0
  211. package/src/WrongChildError.ts +19 -0
  212. package/src/env.d.ts +1 -0
  213. package/src/helper/Characters.ts +5 -0
  214. package/src/helper/DistributiveOmit.ts +1 -0
  215. package/src/helper/EmptyProps.ts +2 -0
  216. package/src/helper/memoComparator.ts +18 -0
  217. package/src/helper/nonEmptyString.ts +8 -0
  218. package/src/helper/withForwardRef.ts +28 -0
  219. package/src/helper/withMemo.ts +16 -0
  220. package/src/helper/withRenderBrowserOnly.tsx +30 -0
  221. package/src/helper/withRestrictedChildren.tsx +57 -0
  222. package/src/scss/_animations.scss +46 -0
  223. package/src/scss/_baseClasses.scss +27 -0
  224. package/src/scss/_colors.scss +13 -0
  225. package/src/scss/_default.scss +17 -0
  226. package/src/scss/_designMixin.scss +13 -0
  227. package/src/scss/_mobileMixin.scss +35 -0
  228. package/src/scss/_variables.scss +22 -0
  229. package/src/types/isomorphic-style-loader.d.ts +3 -0
  230. package/src/types/react-table-config.d.ts +120 -0
  231. package/src/types/scss-module.d.ts +7 -0
  232. package/tsconfig.json +57 -0
  233. package/webpack.config.js +85 -0
@@ -0,0 +1,20 @@
1
+ import { useCallback, useState, MouseEvent } from 'react';
2
+ import { MenuProps } from './Menu';
3
+
4
+ export function useMenu() {
5
+ const [isOpen, setIsOpen] = useState(false);
6
+ const [position, setPosition] = useState({ x: 0, y: 0 });
7
+ const open = useCallback((e: MouseEvent) => {
8
+ setPosition({ x: e.clientX, y: e.clientY });
9
+ setIsOpen(true);
10
+ }, []);
11
+
12
+ const props: Omit<MenuProps, 'items'> = {
13
+ isOpen,
14
+ x: position.x,
15
+ y: position.y,
16
+ onClose: useCallback(() => setIsOpen(false), []),
17
+ };
18
+
19
+ return [open, props] as const;
20
+ }
@@ -0,0 +1,40 @@
1
+ import { CSSProperties, ReactNode } from 'react';
2
+ import { Recursive } from '../TypeHelpers';
3
+
4
+ type Child = Recursive<JSX.Element | undefined | null | Child[]> | false;
5
+ export type WithNoStringProps =
6
+ | {
7
+ children?: Child;
8
+ __allowChildren?: 'html';
9
+ }
10
+ | {
11
+ children?: ReactNode;
12
+ __allowChildren: 'text' | 'all';
13
+ };
14
+
15
+ export type WithNoStringAndChildrenProps =
16
+ | {
17
+ children: Child;
18
+ __allowChildren?: 'html';
19
+ }
20
+ | {
21
+ children: ReactNode;
22
+ __allowChildren: 'text' | 'all';
23
+ };
24
+
25
+ export type WithStringProps = {
26
+ children?: Recursive<string>;
27
+ };
28
+
29
+ export type WithStringAndChildrenProps = {
30
+ children: Recursive<string>;
31
+ };
32
+
33
+ export type WithNoChildren = {
34
+ children?: never;
35
+ };
36
+
37
+ export type RbmComponentProps<SpecialProps, ChildrenProps = WithNoStringProps> = ChildrenProps & {
38
+ className?: string;
39
+ style?: CSSProperties;
40
+ } & SpecialProps;
@@ -0,0 +1,45 @@
1
+ import * as React from 'react';
2
+ import { withMemo } from '../../helper/withMemo';
3
+ import { WithNoStringAndChildrenProps } from '../RbmComponentProps';
4
+ import { InlineBlock } from '../Layout/InlineBlock';
5
+ import { useEffect, useRef } from 'react';
6
+
7
+ export type SizeCalculatorProps = {
8
+ onSize: (width: number, height: number) => void;
9
+ absolute?: boolean;
10
+ } & WithNoStringAndChildrenProps;
11
+
12
+ function SizeCalculator({ onSize, children, absolute = false }: SizeCalculatorProps) {
13
+ // Variables
14
+
15
+ // Refs
16
+ const ref = useRef<HTMLSpanElement>(null);
17
+
18
+ // States
19
+
20
+ // Selectors
21
+
22
+ // Callbacks
23
+
24
+ // Effects
25
+ useEffect(() => {
26
+ if (!ref.current) {
27
+ return;
28
+ }
29
+ onSize(ref.current.clientWidth, ref.current.clientHeight);
30
+ }, [onSize]);
31
+
32
+ // Other
33
+
34
+ // Render Functions
35
+
36
+ return (
37
+ <InlineBlock ref={ref} __allowChildren="all" style={{ position: absolute ? 'absolute' : 'static' }}>
38
+ {children}
39
+ </InlineBlock>
40
+ );
41
+ }
42
+
43
+ // Need SizeCalculatorMemo for autocompletion of phpstorm
44
+ const SizeCalculatorMemo = withMemo(SizeCalculator);
45
+ export { SizeCalculatorMemo as SizeCalculator };
@@ -0,0 +1,106 @@
1
+ import * as React from 'react';
2
+ import { withMemo } from '../../../helper/withMemo';
3
+ import { RbmComponentProps } from '../../RbmComponentProps';
4
+ import { ReactChild, useCallback, useEffect, useRef, useState } from 'react';
5
+ import { Flex } from '../../Layout/Flex';
6
+ import { Grow } from '../../Layout/Grow';
7
+ import { Text, TEXT_SIZE } from '../../Text/Text';
8
+ import { Block } from '../../Layout/Block';
9
+ import { Clickable } from '../../Clickable/Clickable';
10
+
11
+ import styles from './spoiler.scss';
12
+ import classNames from 'classnames';
13
+ import { OptionalListener, useListener } from '../../Hooks/useListener';
14
+ import { Icon } from '../../Icon/Icon';
15
+ import { faChevronDown, faChevronUp } from '@fortawesome/free-solid-svg-icons';
16
+ import { IconProp } from '@fortawesome/fontawesome-svg-core';
17
+
18
+ export type SpoilerProps<OnClickData> = RbmComponentProps<
19
+ {
20
+ title: ReactChild;
21
+ initialOpen?: boolean;
22
+ open?: boolean;
23
+ noClosingAnimation?: boolean;
24
+ openIcon?: IconProp | null;
25
+ closeIcon?: IconProp | null;
26
+ } & OptionalListener<'onClick', OnClickData>
27
+ >;
28
+
29
+ function Spoiler<OnClickData>({
30
+ title,
31
+ children,
32
+ initialOpen = false,
33
+ noClosingAnimation = false,
34
+ openIcon = faChevronDown,
35
+ closeIcon = faChevronUp,
36
+ className,
37
+ style,
38
+ open,
39
+ ...listenerProps
40
+ }: SpoilerProps<OnClickData>) {
41
+ // Variables
42
+
43
+ // Refs
44
+
45
+ // States
46
+ const [isOpen, setIsOpen] = useState(open ?? initialOpen);
47
+ const [isInitialValue, setIsInitialValue] = useState(true);
48
+ const savedOpen = useRef(open);
49
+
50
+ // Selectors
51
+
52
+ // Callbacks
53
+ const onClickListener = useListener<'onClick', OnClickData, boolean>('onClick', listenerProps);
54
+
55
+ const toggleOpen = useCallback(() => {
56
+ if (open !== undefined) {
57
+ onClickListener?.(!open);
58
+ } else {
59
+ setIsInitialValue(false);
60
+ setIsOpen((old) => {
61
+ onClickListener?.(!old);
62
+ return !old;
63
+ });
64
+ }
65
+ }, [onClickListener, open]);
66
+
67
+ // Effects
68
+ useEffect(() => {
69
+ if (savedOpen.current !== open) {
70
+ setIsInitialValue(false);
71
+ }
72
+ }, [open]);
73
+
74
+ // Other
75
+ const titleComponent =
76
+ typeof title === 'string' || typeof title === 'number' ? <Text size={TEXT_SIZE.large}>{title}</Text> : title;
77
+
78
+ // Render Functions
79
+ const icon = open ?? isOpen ? closeIcon : openIcon;
80
+
81
+ return (
82
+ <Clickable
83
+ onClick={toggleOpen}
84
+ className={classNames(className, styles.spoiler, {
85
+ [styles.open]: open ?? isOpen,
86
+ [styles.noAnimation]: isInitialValue,
87
+ [styles.noClosingAnimation]: noClosingAnimation,
88
+ })}
89
+ style={style}
90
+ >
91
+ <Flex horizontal={true}>
92
+ <Grow>{titleComponent}</Grow>
93
+ {icon ? <Icon icon={icon} className={styles.icon} /> : null}
94
+ </Flex>
95
+ <Block className={styles.bodyContainer}>
96
+ <Block __allowChildren="all" className={styles.body}>
97
+ {children}
98
+ </Block>
99
+ </Block>
100
+ </Clickable>
101
+ );
102
+ }
103
+
104
+ // Need SpoilerMemo for autocompletion of phpstorm
105
+ const SpoilerMemo = withMemo(Spoiler, styles);
106
+ export { SpoilerMemo as Spoiler };
@@ -0,0 +1,120 @@
1
+ @keyframes spoilerContainerOpen {
2
+ 0% {
3
+ height: 0;
4
+ }
5
+ 1% {
6
+ height: initial;
7
+ }
8
+ 100% {
9
+ height: initial;
10
+ }
11
+ }
12
+
13
+ @keyframes spoilerOpen {
14
+ 0% {
15
+ height: 0;
16
+ transform: translateY(-100%);
17
+ opacity: 0;
18
+ }
19
+ 1% {
20
+ height: initial;
21
+ transform: translateY(-100%);
22
+ opacity: 0;
23
+ }
24
+ 100% {
25
+ height: initial;
26
+ transform: translateY(0%);
27
+ opacity: 1;
28
+ }
29
+ }
30
+
31
+ @keyframes spoilerContainerClose {
32
+ 0% {
33
+ height: initial;
34
+ }
35
+ 99% {
36
+ height: initial;
37
+ }
38
+ 100% {
39
+ height: 0;
40
+ }
41
+ }
42
+
43
+ @keyframes spoilerClose {
44
+ 0% {
45
+ height: initial;
46
+ transform: translateY(0%);
47
+ opacity: 1;
48
+ }
49
+ 99% {
50
+ height: initial;
51
+ transform: translateY(-100%);
52
+ opacity: 0;
53
+ }
54
+ 100% {
55
+ height: 0;
56
+ transform: translateY(-100%);
57
+ opacity: 0;
58
+ }
59
+ }
60
+
61
+ .spoiler {
62
+ display: block;
63
+ border-top: 1px solid var(--border-strong);
64
+ border-bottom: 1px solid var(--border-strong);
65
+
66
+ .icon {
67
+ margin-right: 0.5rem;
68
+ }
69
+
70
+ &.open, &.open.noClosingAnimation {
71
+ .bodyContainer {
72
+ height: initial;
73
+ animation-name: spoilerContainerOpen;
74
+
75
+ .body {
76
+ height: initial;
77
+ transform: translateY(0%);
78
+ animation-name: spoilerOpen;
79
+ }
80
+ }
81
+ }
82
+
83
+ &.noAnimation, &.noAnimation.open {
84
+ .bodyContainer {
85
+ animation: none;
86
+
87
+ .body {
88
+ animation: none;
89
+ }
90
+ }
91
+ }
92
+
93
+ &.noClosingAnimation {
94
+ .bodyContainer {
95
+ animation-name: none;
96
+
97
+ .body {
98
+ animation-name: none;
99
+ }
100
+ }
101
+ }
102
+
103
+ .bodyContainer {
104
+ height: 0;
105
+ overflow: hidden;
106
+ animation-name: spoilerContainerClose;
107
+ animation-duration: 0.7s;
108
+ animation-fill-mode: forwards;
109
+
110
+ .body {
111
+ height: 0;
112
+ overflow: hidden;
113
+ transform-origin: left top;
114
+ transform: translateY(-100%);
115
+ animation-name: spoilerClose;
116
+ animation-duration: 0.7s;
117
+ animation-fill-mode: forwards;
118
+ }
119
+ }
120
+ }
@@ -0,0 +1,63 @@
1
+ import * as React from 'react';
2
+ import { withMemo } from '../../helper/withMemo';
3
+ import { ReactElement } from 'react';
4
+ import { RbmComponentProps, WithNoChildren } from '../RbmComponentProps';
5
+ import { Block } from '../Layout/Block';
6
+ import classNames from 'classnames';
7
+ import { Spoiler } from './Spoiler/Spoiler';
8
+ import { useSpoilerGroup } from './useSpoilerGroup';
9
+
10
+ export type SpoilerItem<BodyData, TitleData = string> = {
11
+ title: TitleData;
12
+ body: BodyData;
13
+ key: number | string;
14
+ };
15
+
16
+ export type SpoilerListProps<BodyData, TitleData = string> = RbmComponentProps<
17
+ {
18
+ data: SpoilerItem<BodyData, TitleData>[];
19
+ renderBody: (item: SpoilerItem<BodyData, TitleData>) => ReactElement;
20
+ renderTitle?: (item: SpoilerItem<BodyData, TitleData>) => ReactElement | string;
21
+ },
22
+ WithNoChildren
23
+ >;
24
+
25
+ const stringIdentity = (data: any) => data as string;
26
+
27
+ function SpoilerList<BodyData, TitleData = string>({
28
+ data,
29
+ renderBody,
30
+ renderTitle = stringIdentity,
31
+ className,
32
+ style,
33
+ }: SpoilerListProps<BodyData, TitleData>) {
34
+ // Variables
35
+ const [propsGenerator] = useSpoilerGroup();
36
+
37
+ // Refs
38
+
39
+ // States
40
+
41
+ // Selectors
42
+
43
+ // Callbacks
44
+
45
+ // Effects
46
+
47
+ // Other
48
+
49
+ // Render Functions
50
+ return (
51
+ <Block className={classNames(className)} style={style}>
52
+ {data.map((item) => (
53
+ <Spoiler title={renderTitle(item)} {...propsGenerator(item.key)}>
54
+ {renderBody(item)}
55
+ </Spoiler>
56
+ ))}
57
+ </Block>
58
+ );
59
+ }
60
+
61
+ // Need SpoilerListMemo for autocompletion of phpstorm
62
+ const SpoilerListMemo = withMemo(SpoilerList);
63
+ export { SpoilerListMemo as SpoilerList };
@@ -0,0 +1,39 @@
1
+ import { useCallback, useState } from 'react';
2
+
3
+ export type SpoilerGroupOptions = {
4
+ closeWithClick: boolean;
5
+ noClosingAnimation: boolean;
6
+ };
7
+
8
+ export function useSpoilerGroup(defaultKey?: number | string, options: Partial<SpoilerGroupOptions> = {}) {
9
+ const [openKey, setOpenKey] = useState<number | string | undefined>(defaultKey);
10
+
11
+ const onClick = useCallback(
12
+ (isOpen: boolean, key: string | number) => {
13
+ setOpenKey((oldKey) => {
14
+ if (options?.closeWithClick && oldKey === key && !isOpen) {
15
+ return undefined;
16
+ }
17
+ if (isOpen) {
18
+ return key;
19
+ }
20
+ return oldKey;
21
+ });
22
+ },
23
+ [options?.closeWithClick]
24
+ );
25
+
26
+ const createProps = useCallback(
27
+ (key: string | number) => ({
28
+ onClick,
29
+ onClickData: key,
30
+ key,
31
+ open: key === openKey,
32
+ noClosingAnimation: options?.noClosingAnimation !== false,
33
+ closeIcon: null,
34
+ }),
35
+ [onClick, openKey, options?.noClosingAnimation]
36
+ );
37
+
38
+ return [createProps, openKey] as const;
39
+ }
@@ -0,0 +1,117 @@
1
+ import * as React from 'react';
2
+ import { RbmComponentProps } from '../RbmComponentProps';
3
+ import { Icon, IconSource } from '../Icon/Icon';
4
+ import { ComponentType, useCallback, useState } from 'react';
5
+ import { Container } from '../Layout/Container';
6
+ import { TabBarButton } from './TabBarButton';
7
+
8
+ import styles from './tabBar.scss';
9
+ import { withMemo } from '../../helper/withMemo';
10
+ import classNames from 'classnames';
11
+ import { ListenerWithData } from '../Hooks/useListener';
12
+ import { Inline } from '../Layout/Inline';
13
+ import { Text } from '../Text/Text';
14
+
15
+ export type TabBarComponentButtonType = {
16
+ component: ComponentType<Record<string, any>>;
17
+ key?: string;
18
+ };
19
+
20
+ export type TabBarTitleButtonType = {
21
+ title: string;
22
+ icon?: IconSource;
23
+ key?: string;
24
+ };
25
+
26
+ export type TabBarIconButtonType = {
27
+ title?: string;
28
+ icon: IconSource;
29
+ key?: string;
30
+ };
31
+
32
+ export type TabBarButtonType = TabBarComponentButtonType | TabBarTitleButtonType | TabBarIconButtonType;
33
+
34
+ export type TabBarProps = RbmComponentProps<{
35
+ buttons: TabBarButtonType[];
36
+ startActiveTab?: number;
37
+ onTabChange: (newActiveTab: number) => void;
38
+ activeTab?: number;
39
+ transparent?: boolean;
40
+ drawBehind?: boolean;
41
+ underline?: boolean;
42
+ }>;
43
+
44
+ function getButtonComponents(buttons: TabBarButtonType[], activeTab: number, onSelect: ListenerWithData<number>) {
45
+ return buttons.map((button, index) => {
46
+ const isActive = index === activeTab;
47
+
48
+ const key = button.key ?? String(index);
49
+ if ('component' in button) {
50
+ const Component = button.component;
51
+ return <Component key={key} active={isActive} />;
52
+ }
53
+
54
+ return (
55
+ <TabBarButton key={key} active={isActive} onClickData={index} onClick={onSelect}>
56
+ <Inline>
57
+ {button.icon ? <Icon icon={button.icon} className={styles.buttonIcon} /> : null}
58
+ {button.title ? <Text className={styles.buttonTitle}>{button.title}</Text> : null}
59
+ </Inline>
60
+ </TabBarButton>
61
+ );
62
+ });
63
+ }
64
+
65
+ function TabBar({
66
+ buttons,
67
+ startActiveTab,
68
+ onTabChange,
69
+ activeTab,
70
+ transparent,
71
+ underline,
72
+ className,
73
+ ...rbmProps
74
+ }: TabBarProps) {
75
+ // States
76
+ const [internalActiveTab, setInternalActiveTab] = useState(startActiveTab ?? 0);
77
+ activeTab = activeTab ?? internalActiveTab;
78
+
79
+ // Refs
80
+
81
+ // Callbacks
82
+ const onSelect = useCallback(
83
+ (_: any, index: number) => {
84
+ setInternalActiveTab(index);
85
+ onTabChange(index);
86
+ },
87
+ [onTabChange, setInternalActiveTab]
88
+ );
89
+
90
+ // Effects
91
+
92
+ // Other
93
+
94
+ // Render Functions
95
+ const buttonComponents = getButtonComponents(buttons, activeTab, onSelect);
96
+
97
+ return (
98
+ <div
99
+ {...rbmProps}
100
+ className={classNames(
101
+ styles.tabBar,
102
+ {
103
+ [styles.transparent]: transparent,
104
+ [styles.underlined]: underline,
105
+ },
106
+ className
107
+ )}
108
+ >
109
+ <Container fluid="xxl" className={styles.buttonContainer}>
110
+ {buttonComponents}
111
+ </Container>
112
+ </div>
113
+ );
114
+ }
115
+
116
+ const TabBarMemo = withMemo(TabBar, styles);
117
+ export { TabBarMemo as TabBar };
@@ -0,0 +1,44 @@
1
+ import * as React from 'react';
2
+ import { RbmComponentProps } from '../RbmComponentProps';
3
+
4
+ import styles from './tabBar.scss';
5
+ import { withMemo } from '../../helper/withMemo';
6
+ import classNames from 'classnames';
7
+ import { Listener, useListenerWithExtractedProps } from '../Hooks/useListener';
8
+
9
+ export type TabBarButtonProps = RbmComponentProps<
10
+ {
11
+ active: boolean;
12
+ } & Listener<'onClick', number>
13
+ >;
14
+
15
+ function TabBarButton({ active, className, children, ...rbmProps }: TabBarButtonProps) {
16
+ // Variables
17
+
18
+ // States
19
+
20
+ // Refs
21
+
22
+ // Callbacks
23
+ const [onClick, otherProps] = useListenerWithExtractedProps<'onClick', number>('onClick', rbmProps);
24
+
25
+ // Effects
26
+
27
+ // Other
28
+
29
+ // Render Functions
30
+
31
+ return (
32
+ <a
33
+ {...otherProps}
34
+ role="button"
35
+ onClick={onClick}
36
+ className={classNames(styles.button, { [styles.buttonActive]: active, className })}
37
+ >
38
+ {children}
39
+ </a>
40
+ );
41
+ }
42
+
43
+ const TabBarButtonMemo = withMemo(TabBarButton, styles);
44
+ export { TabBarButtonMemo as TabBarButton };
@@ -0,0 +1,108 @@
1
+ @import "../../scss/variables";
2
+ @import "../../scss/designMixin";
3
+
4
+ .tabBar {
5
+ height: 60px;
6
+ width: 100%;
7
+ display: flex;
8
+ flex-wrap: wrap;
9
+ padding-left: 0;
10
+ margin-bottom: 0;
11
+ list-style: none;
12
+
13
+ .buttonContainer {
14
+ padding: 0;
15
+ display: flex;
16
+ }
17
+
18
+ &.underlined {
19
+ .buttonActive {
20
+ @include design($flat) {
21
+ border-bottom: 4px solid var(--flavor-accent);
22
+ }
23
+ }
24
+ }
25
+
26
+ &.transparent {
27
+ opacity: 0.65;
28
+ }
29
+
30
+ @include design($material) {
31
+ background-color: #ffffff;
32
+ box-shadow: 0 -2px 2px 0px rgb(0 0 0 / 14%), 0 -1px 5px 0px rgb(0 0 0 / 12%), 0 -1px 1px 0px rgb(0 0 0 / 20%);
33
+ }
34
+
35
+ @include design($flat) {
36
+ background-color: #fafafa;
37
+ border-top: 1px solid var(--border-light);
38
+ }
39
+ }
40
+
41
+ .button {
42
+ cursor: pointer;
43
+ display: flex;
44
+ align-items: center;
45
+ padding: 0;
46
+ flex-basis: 0;
47
+ flex-grow: 1;
48
+ text-align: center;
49
+ text-decoration: none;
50
+ transition: color 0.15s ease-in-out, background-color 0.15s ease-in-out, border-color 0.15s ease-in-out;
51
+
52
+ > span {
53
+ width: 100%;
54
+ display: inline-block;
55
+ }
56
+
57
+ .buttonIcon {
58
+ display: block;
59
+ font-size: 24px;
60
+ line-height: 26px;
61
+ height: 28px;
62
+ margin: auto;
63
+
64
+ + .buttonTitle {
65
+ font-size: 10px;
66
+ line-height: 1;
67
+ }
68
+ }
69
+
70
+ .buttonTitle {
71
+ display: block;
72
+ margin: auto;
73
+ font-size: 16px;
74
+ line-height: 49px;
75
+ }
76
+
77
+ @include design($flat) {
78
+ color: #999;
79
+ &.buttonActive {
80
+ color: var(--flavor-accent);
81
+ }
82
+ }
83
+
84
+
85
+ @include design($material) {
86
+ color: #31313a;
87
+ position: relative;
88
+ text-transform: uppercase;
89
+
90
+ &::after {
91
+ content: ' ';
92
+ display: block;
93
+ width: 0;
94
+ height: 2px;
95
+ bottom: 0;
96
+ position: absolute;
97
+ margin-top: -2px;
98
+ background-color: #31313a;
99
+
100
+ }
101
+ &.buttonActive {
102
+ &::after {
103
+ width: 100%;
104
+ transition: width 0.2s ease-in-out;
105
+ }
106
+ }
107
+ }
108
+ }