react-miui 0.21.0 → 0.22.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 (197) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/components/form/Select.d.ts +1 -5
  3. package/dist/components/form/Select.d.ts.map +1 -1
  4. package/dist/components/form/Select.js +2 -23
  5. package/dist/components/form/Select.js.map +1 -1
  6. package/dist/components/form/Select.stories.d.ts +8 -0
  7. package/dist/components/form/Select.stories.d.ts.map +1 -0
  8. package/dist/components/form/Select.stories.js +26 -0
  9. package/dist/components/form/Select.stories.js.map +1 -0
  10. package/dist/components/form/Select.styled.d.ts +82 -0
  11. package/dist/components/form/Select.styled.d.ts.map +1 -0
  12. package/dist/components/form/Select.styled.js +24 -0
  13. package/dist/components/form/Select.styled.js.map +1 -0
  14. package/dist/components/ui/button/Button.d.ts +1 -7
  15. package/dist/components/ui/button/Button.d.ts.map +1 -1
  16. package/dist/components/ui/button/Button.js +2 -28
  17. package/dist/components/ui/button/Button.js.map +1 -1
  18. package/dist/components/ui/button/Button.stories.d.ts +9 -0
  19. package/dist/components/ui/button/Button.stories.d.ts.map +1 -0
  20. package/dist/components/ui/button/Button.stories.js +62 -0
  21. package/dist/components/ui/button/Button.stories.js.map +1 -0
  22. package/dist/components/ui/button/Button.styled.d.ts +85 -0
  23. package/dist/components/ui/button/Button.styled.d.ts.map +1 -0
  24. package/dist/components/ui/button/Button.styled.js +38 -0
  25. package/dist/components/ui/button/Button.styled.js.map +1 -0
  26. package/dist/components/ui/modal/Modal.d.ts +6 -4
  27. package/dist/components/ui/modal/Modal.d.ts.map +1 -1
  28. package/dist/components/ui/modal/Modal.js +30 -21
  29. package/dist/components/ui/modal/Modal.js.map +1 -1
  30. package/dist/components/ui/modal/Modal.stories.d.ts +10 -0
  31. package/dist/components/ui/modal/Modal.stories.d.ts.map +1 -0
  32. package/dist/components/ui/modal/Modal.stories.js +112 -0
  33. package/dist/components/ui/modal/Modal.stories.js.map +1 -0
  34. package/dist/components/ui/modal/Modal.styled.d.ts +329 -0
  35. package/dist/components/ui/modal/Modal.styled.d.ts.map +1 -0
  36. package/dist/components/ui/modal/Modal.styled.js +90 -0
  37. package/dist/components/ui/modal/Modal.styled.js.map +1 -0
  38. package/dist/components/ui/modal/ModalButtons.d.ts +1 -11
  39. package/dist/components/ui/modal/ModalButtons.d.ts.map +1 -1
  40. package/dist/components/ui/modal/ModalButtons.js +2 -12
  41. package/dist/components/ui/modal/ModalButtons.js.map +1 -1
  42. package/dist/components/ui/modal/ModalButtons.stories.d.ts +8 -0
  43. package/dist/components/ui/modal/ModalButtons.stories.d.ts.map +1 -0
  44. package/dist/components/ui/modal/ModalButtons.stories.js +25 -0
  45. package/dist/components/ui/modal/ModalButtons.stories.js.map +1 -0
  46. package/dist/components/ui/modal/ModalButtons.styled.d.ts +166 -0
  47. package/dist/components/ui/modal/ModalButtons.styled.d.ts.map +1 -0
  48. package/dist/components/ui/modal/ModalButtons.styled.js +42 -0
  49. package/dist/components/ui/modal/ModalButtons.styled.js.map +1 -0
  50. package/dist/components/ui/pop/Pop.module.scss +1 -0
  51. package/docs/assets/search.js +1 -1
  52. package/docs/classes/Drawer.html +14 -15
  53. package/docs/classes/Pop.html +14 -15
  54. package/docs/classes/ToasterProvider.html +10 -11
  55. package/docs/enums/ICON.html +14 -15
  56. package/docs/functions/Action.html +5 -6
  57. package/docs/functions/Button.html +43 -11
  58. package/docs/functions/Card.html +5 -6
  59. package/docs/functions/Checkbox.html +5 -6
  60. package/docs/functions/Choice.html +6 -7
  61. package/docs/functions/CoveringLoader.html +5 -6
  62. package/docs/functions/DirectionPad.html +5 -6
  63. package/docs/functions/EqualActions.html +5 -6
  64. package/docs/functions/FullLoader.html +5 -6
  65. package/docs/functions/HandleEsc.html +5 -6
  66. package/docs/functions/Header.html +5 -6
  67. package/docs/functions/HeaderIconAction.html +5 -6
  68. package/docs/functions/Icon-1.html +5 -6
  69. package/docs/functions/If.html +5 -6
  70. package/docs/functions/Input.html +6 -7
  71. package/docs/functions/KeyValue.html +5 -6
  72. package/docs/functions/Label.html +5 -6
  73. package/docs/functions/List-1.html +5 -6
  74. package/docs/functions/Loader.html +5 -6
  75. package/docs/functions/Loading.html +5 -6
  76. package/docs/functions/Message.html +5 -6
  77. package/docs/functions/Modal-1.html +5 -6
  78. package/docs/functions/ModalButtons.html +135 -0
  79. package/docs/functions/PopLoader.html +5 -6
  80. package/docs/functions/PopOption.html +5 -6
  81. package/docs/functions/SearchContainer.html +5 -6
  82. package/docs/functions/Section.html +5 -6
  83. package/docs/functions/Select.html +39 -11
  84. package/docs/functions/Selector.html +6 -7
  85. package/docs/functions/Spacer.html +5 -6
  86. package/docs/functions/Stats.html +5 -6
  87. package/docs/functions/StickyHeader-1.html +5 -6
  88. package/docs/functions/StickyHeader.Content.html +5 -6
  89. package/docs/functions/Table.html +5 -6
  90. package/docs/functions/TextArea.html +5 -6
  91. package/docs/functions/Toggle.html +5 -6
  92. package/docs/functions/getCssText.html +5 -6
  93. package/docs/functions/styled.html +5 -6
  94. package/docs/functions/useToaster.html +6 -7
  95. package/docs/index.html +5 -6
  96. package/docs/modules/List.html +7 -8
  97. package/docs/modules/Modal.html +8 -9
  98. package/docs/modules/StickyHeader.html +6 -7
  99. package/docs/modules.html +6 -8
  100. package/docs/pages/tutorials/Test.html +5 -6
  101. package/docs/types/ThemeCSS.html +6 -7
  102. package/docs/variables/List.Header.html +5 -6
  103. package/docs/variables/List.Item.html +5 -6
  104. package/docs/variables/{ModalButtons.Button.html → Modal.RemovePadding.html} +11 -12
  105. package/docs/variables/cssReset.html +6 -7
  106. package/docs/variables/miuiScrollbars.html +6 -7
  107. package/esm/components/form/Select.d.ts +1 -5
  108. package/esm/components/form/Select.d.ts.map +1 -1
  109. package/esm/components/form/Select.js +1 -8
  110. package/esm/components/form/Select.js.map +1 -1
  111. package/esm/components/form/Select.stories.d.ts +8 -0
  112. package/esm/components/form/Select.stories.d.ts.map +1 -0
  113. package/esm/components/form/Select.stories.js +20 -0
  114. package/esm/components/form/Select.stories.js.map +1 -0
  115. package/esm/components/form/Select.styled.d.ts +82 -0
  116. package/esm/components/form/Select.styled.d.ts.map +1 -0
  117. package/esm/components/form/Select.styled.js +21 -0
  118. package/esm/components/form/Select.styled.js.map +1 -0
  119. package/esm/components/ui/button/Button.d.ts +1 -7
  120. package/esm/components/ui/button/Button.d.ts.map +1 -1
  121. package/esm/components/ui/button/Button.js +1 -13
  122. package/esm/components/ui/button/Button.js.map +1 -1
  123. package/esm/components/ui/button/Button.stories.d.ts +9 -0
  124. package/esm/components/ui/button/Button.stories.d.ts.map +1 -0
  125. package/esm/components/ui/button/Button.stories.js +35 -0
  126. package/esm/components/ui/button/Button.stories.js.map +1 -0
  127. package/esm/components/ui/button/Button.styled.d.ts +85 -0
  128. package/esm/components/ui/button/Button.styled.d.ts.map +1 -0
  129. package/esm/components/ui/button/Button.styled.js +35 -0
  130. package/esm/components/ui/button/Button.styled.js.map +1 -0
  131. package/esm/components/ui/modal/Modal.d.ts +6 -4
  132. package/esm/components/ui/modal/Modal.d.ts.map +1 -1
  133. package/esm/components/ui/modal/Modal.js +30 -18
  134. package/esm/components/ui/modal/Modal.js.map +1 -1
  135. package/esm/components/ui/modal/Modal.stories.d.ts +10 -0
  136. package/esm/components/ui/modal/Modal.stories.d.ts.map +1 -0
  137. package/esm/components/ui/modal/Modal.stories.js +84 -0
  138. package/esm/components/ui/modal/Modal.stories.js.map +1 -0
  139. package/esm/components/ui/modal/Modal.styled.d.ts +329 -0
  140. package/esm/components/ui/modal/Modal.styled.d.ts.map +1 -0
  141. package/esm/components/ui/modal/Modal.styled.js +83 -0
  142. package/esm/components/ui/modal/Modal.styled.js.map +1 -0
  143. package/esm/components/ui/modal/ModalButtons.d.ts +1 -11
  144. package/esm/components/ui/modal/ModalButtons.d.ts.map +1 -1
  145. package/esm/components/ui/modal/ModalButtons.js +1 -9
  146. package/esm/components/ui/modal/ModalButtons.js.map +1 -1
  147. package/esm/components/ui/modal/ModalButtons.stories.d.ts +8 -0
  148. package/esm/components/ui/modal/ModalButtons.stories.d.ts.map +1 -0
  149. package/esm/components/ui/modal/ModalButtons.stories.js +19 -0
  150. package/esm/components/ui/modal/ModalButtons.stories.js.map +1 -0
  151. package/esm/components/ui/modal/ModalButtons.styled.d.ts +166 -0
  152. package/esm/components/ui/modal/ModalButtons.styled.d.ts.map +1 -0
  153. package/esm/components/ui/modal/ModalButtons.styled.js +39 -0
  154. package/esm/components/ui/modal/ModalButtons.styled.js.map +1 -0
  155. package/esm/components/ui/pop/Pop.module.scss +1 -0
  156. package/package.json +2 -2
  157. package/src/components/form/Select.stories.tsx +30 -0
  158. package/src/components/form/Select.styled.ts +25 -0
  159. package/src/components/form/Select.tsx +1 -22
  160. package/src/components/ui/button/Button.stories.tsx +55 -0
  161. package/src/components/ui/button/Button.styled.ts +43 -0
  162. package/src/components/ui/button/Button.tsx +1 -35
  163. package/src/components/ui/modal/Modal.stories.tsx +143 -0
  164. package/src/components/ui/modal/Modal.styled.ts +100 -0
  165. package/src/components/ui/modal/Modal.tsx +49 -26
  166. package/src/components/ui/modal/ModalButtons.stories.tsx +40 -0
  167. package/src/components/ui/modal/ModalButtons.styled.ts +51 -0
  168. package/src/components/ui/modal/ModalButtons.tsx +1 -22
  169. package/src/components/ui/pop/Pop.module.scss +1 -0
  170. package/src/demo/componentsMap.ts +0 -25
  171. package/dist/components/form/Select.module.scss +0 -18
  172. package/dist/components/ui/button/Button.module.scss +0 -25
  173. package/dist/components/ui/modal/Modal.module.scss +0 -92
  174. package/dist/components/ui/modal/ModalButtons.module.scss +0 -32
  175. package/dist/components/ui/modal/ModalNoMargin.d.ts +0 -7
  176. package/dist/components/ui/modal/ModalNoMargin.d.ts.map +0 -1
  177. package/dist/components/ui/modal/ModalNoMargin.js +0 -22
  178. package/dist/components/ui/modal/ModalNoMargin.js.map +0 -1
  179. package/docs/functions/ModalButtons-1.html +0 -107
  180. package/docs/modules/ModalButtons.html +0 -59
  181. package/docs/variables/Modal.NegateMargin.html +0 -53
  182. package/esm/components/form/Select.module.scss +0 -18
  183. package/esm/components/ui/button/Button.module.scss +0 -25
  184. package/esm/components/ui/modal/Modal.module.scss +0 -92
  185. package/esm/components/ui/modal/ModalButtons.module.scss +0 -32
  186. package/esm/components/ui/modal/ModalNoMargin.d.ts +0 -7
  187. package/esm/components/ui/modal/ModalNoMargin.d.ts.map +0 -1
  188. package/esm/components/ui/modal/ModalNoMargin.js +0 -16
  189. package/esm/components/ui/modal/ModalNoMargin.js.map +0 -1
  190. package/src/components/form/Select.module.scss +0 -18
  191. package/src/components/ui/button/Button.module.scss +0 -25
  192. package/src/components/ui/modal/Modal.module.scss +0 -92
  193. package/src/components/ui/modal/ModalButtons.module.scss +0 -32
  194. package/src/components/ui/modal/ModalNoMargin.tsx +0 -25
  195. package/src/demo/components/form/Select.tsx +0 -26
  196. package/src/demo/components/ui/button/ButtonDemo.tsx +0 -23
  197. package/src/demo/components/ui/modal/Modal.tsx +0 -106
@@ -0,0 +1,39 @@
1
+ import { dimensionsPxToRem, styled } from "../../../theme.js";
2
+ import { NEGATIVE_PADDING } from "./Modal.styled";
3
+ const Container = styled("div", {
4
+ display: "flex",
5
+ marginTop: dimensionsPxToRem(100),
6
+ mx: NEGATIVE_PADDING,
7
+ marginBottom: NEGATIVE_PADDING,
8
+ });
9
+ const Button = styled("button", {
10
+ "border": "none",
11
+ "borderTop": "1px solid $modalButtonBorder",
12
+ "background": "$modalButtonBg",
13
+ "flex": 1,
14
+ "height": dimensionsPxToRem(156),
15
+ "fontWeight": 500,
16
+ "display": "flex",
17
+ "alignItems": "center",
18
+ "justifyContent": "center",
19
+ "&:not(:first-child)": {
20
+ borderLeft: "1px solid $modalButtonBorder",
21
+ },
22
+ "&:first-child": {
23
+ borderBottomLeftRadius: dimensionsPxToRem(12),
24
+ },
25
+ "&:last-child": {
26
+ borderBottomRightRadius: dimensionsPxToRem(12),
27
+ },
28
+ "variants": {
29
+ variant: {
30
+ main: {
31
+ color: "$mainColor",
32
+ },
33
+ },
34
+ },
35
+ });
36
+ const ModalButtons = Container;
37
+ ModalButtons.Button = Button;
38
+ export { ModalButtons, };
39
+ //# sourceMappingURL=ModalButtons.styled.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModalButtons.styled.js","sourceRoot":"","sources":["../../../../src/components/ui/modal/ModalButtons.styled.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAE9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAElD,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,EAAE;IAC5B,OAAO,EAAE,MAAM;IACf,SAAS,EAAE,iBAAiB,CAAC,GAAG,CAAC;IACjC,EAAE,EAAE,gBAAgB;IACpB,YAAY,EAAE,gBAAgB;CACjC,CAAC,CAAC;AAEH,MAAM,MAAM,GAAG,MAAM,CAAC,QAAQ,EAAE;IAC5B,QAAQ,EAAE,MAAM;IAChB,WAAW,EAAE,8BAA8B;IAC3C,YAAY,EAAE,gBAAgB;IAC9B,MAAM,EAAE,CAAC;IACT,QAAQ,EAAE,iBAAiB,CAAC,GAAG,CAAC;IAChC,YAAY,EAAE,GAAG;IACjB,SAAS,EAAE,MAAM;IACjB,YAAY,EAAE,QAAQ;IACtB,gBAAgB,EAAE,QAAQ;IAE1B,qBAAqB,EAAE;QACnB,UAAU,EAAE,8BAA8B;KAC7C;IAED,eAAe,EAAE;QACb,sBAAsB,EAAE,iBAAiB,CAAC,EAAE,CAAC;KAChD;IAED,cAAc,EAAE;QACZ,uBAAuB,EAAE,iBAAiB,CAAC,EAAE,CAAC;KACjD;IAED,UAAU,EAAE;QACR,OAAO,EAAE;YACL,IAAI,EAAE;gBACF,KAAK,EAAE,YAAY;aACtB;SACJ;KACJ;CACJ,CAAC,CAAC;AAEH,MAAM,YAAY,GAAG,SAEpB,CAAC;AACF,YAAY,CAAC,MAAM,GAAG,MAAM,CAAC;AAE7B,OAAO,EACH,YAAY,GACf,CAAC"}
@@ -38,6 +38,7 @@
38
38
  text-align: left;
39
39
  color: var(--pop-text);
40
40
  font-size: calc(26px / var(--ratio-font));
41
+ font-weight: revert;
41
42
  display: flex;
42
43
  align-items: center;
43
44
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-miui",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "author": "Jacek Nowacki",
5
5
  "license": "MIT",
6
6
  "scripts": {
@@ -13,7 +13,7 @@
13
13
  "lint": "eslint src --ext .ts,.tsx,.js,.jsx,.mjs",
14
14
  "lint:fix": "yarn lint --fix",
15
15
  "prepack": "yarn compile",
16
- "prepublishOnly": "yarn audit && yarn lint && yarn test && yarn docs",
16
+ "prepublishOnly": "yarn lint && yarn test && yarn docs",
17
17
  "start:dev": "yarn storybook",
18
18
  "start:dev:legacy": "next dev",
19
19
  "deploy:dev": "next build && next export && netlify deploy --dir out",
@@ -0,0 +1,30 @@
1
+ import React from "react";
2
+
3
+ import type { StoryObj, Meta } from "@storybook/react";
4
+
5
+ import { Select } from "./Select.js";
6
+
7
+ const meta: Meta = {
8
+ title: "Components/Form/Select",
9
+ component: Select,
10
+ tags: ["autodocs", "form"],
11
+ };
12
+
13
+ type Story = StoryObj<typeof Select>;
14
+
15
+ const Primary: Story = {
16
+ args: {
17
+ children: [
18
+ <option key={"1"} value={"1"}>First</option>,
19
+ <option key={"2"} value={"2"}>Second</option>,
20
+ <option key={"3"} value={"3"}>Third</option>,
21
+ ],
22
+ disabled: false,
23
+ },
24
+ };
25
+
26
+ export {
27
+ Primary,
28
+ };
29
+
30
+ export default meta;
@@ -0,0 +1,25 @@
1
+ import { borderPxToRem, dimensionsPxToRem, pxToRem, styled } from "../../theme.js";
2
+
3
+ const Select = styled("select", {
4
+ "boxSizing": "border-box",
5
+ "height": dimensionsPxToRem(103),
6
+ "color": "$text",
7
+ "display": "flex",
8
+ "alignItems": "center",
9
+ "width": "100%",
10
+ "background": "white",
11
+ "fontFamily": "inherit",
12
+ "borderRadius": pxToRem(2),
13
+ "padding": `0 ${dimensionsPxToRem(36)}`,
14
+ "border": `${borderPxToRem(1)} solid $border`,
15
+ "appearance": "auto",
16
+
17
+ "&:disabled": {
18
+ background: "$inputDisabledBg",
19
+ color: "$inputDisabledText",
20
+ },
21
+ });
22
+
23
+ export {
24
+ Select,
25
+ };
@@ -1,22 +1 @@
1
- import React from "react";
2
-
3
- import classnames from "classnames";
4
-
5
- import styles from "./Select.module.scss";
6
-
7
- interface Props {
8
- }
9
-
10
- const Select: React.FC<React.SelectHTMLAttributes<HTMLSelectElement> & Props> = ({ className, children, ...props }) => {
11
- const wrapperCls = classnames(styles.select, className);
12
-
13
- return (
14
- <select className={wrapperCls} {...props}>
15
- {children}
16
- </select>
17
- );
18
- };
19
-
20
- export {
21
- Select,
22
- };
1
+ export { Select } from "./Select.styled.js";
@@ -0,0 +1,55 @@
1
+ import React, { useCallback } from "react";
2
+
3
+ import type { StoryObj, Meta } from "@storybook/react";
4
+
5
+ import { styled } from "../../../theme.js";
6
+
7
+ import { Button } from "./Button.js";
8
+
9
+ // TODO better docs
10
+
11
+ const meta: Meta = {
12
+ title: "Components/UI/Button",
13
+ component: Button,
14
+ tags: ["autodocs", "ui"],
15
+ };
16
+
17
+ type Story = StoryObj<typeof Button>;
18
+
19
+ const Primary: Story = {
20
+ args: {
21
+ children: "Click me",
22
+ onClick: () => { alert("Clicked"); },
23
+ },
24
+ };
25
+
26
+ const Container = styled("div", {
27
+ display: "flex",
28
+ flexDirection: "column",
29
+ alignItems: "flex-start",
30
+ gap: "1rem",
31
+ });
32
+
33
+ const MultipleAtOnce: Story = {
34
+ render: () => {
35
+ const handleClick = useCallback(() => {
36
+ alert("Clicked");
37
+ }, []);
38
+
39
+ return (
40
+ <Container>
41
+ <Button onClick={handleClick}>Basic button</Button>
42
+ <Button disabled={true} onClick={handleClick}>Disabled button</Button>
43
+ <Button inline={true} onClick={handleClick}>Inline button</Button>
44
+ <Button outline={true} onClick={handleClick}>Outline button</Button>
45
+ </Container>
46
+ );
47
+ },
48
+ };
49
+
50
+ export {
51
+ Primary,
52
+ MultipleAtOnce,
53
+ };
54
+
55
+ export default meta;
@@ -0,0 +1,43 @@
1
+ import { borderPxToRem, dimensionsPxToRem, fontPxToRem, pxToRem, styled } from "../../../theme.js";
2
+
3
+ /**
4
+ * Call-to-action button.
5
+ */
6
+ const Button = styled("button", {
7
+ "height": dimensionsPxToRem(118),
8
+ "background": "$green1",
9
+ "border": `${borderPxToRem(1)} solid $green1Darker`,
10
+ "color": "white",
11
+ "borderRadius": "1000px",
12
+ "display": "flex",
13
+ "alignItems": "center",
14
+ "justifyContent": "center",
15
+ "width": "100%",
16
+ "fontSize": fontPxToRem(26),
17
+ "padding": "0 1em",
18
+ "gap": pxToRem(10),
19
+
20
+ "&:disabled": {
21
+ opacity: 0.5,
22
+ },
23
+
24
+ "variants": {
25
+ inline: {
26
+ true: {
27
+ width: "auto",
28
+ display: "inline-flex",
29
+ },
30
+ },
31
+ outline: {
32
+ true: {
33
+ background: "white",
34
+ borderColor: "$buttonBorder",
35
+ color: "$grey1",
36
+ },
37
+ },
38
+ },
39
+ });
40
+
41
+ export {
42
+ Button,
43
+ };
@@ -1,35 +1 @@
1
- import React from "react";
2
-
3
- import classnames from "classnames";
4
-
5
- import { makeVariants } from "../../../utils/index.js";
6
-
7
- import styles from "./Button.module.scss";
8
-
9
- type Variant = "inline" | "outline";
10
-
11
- interface Props {
12
- variant?: Variant | Variant[];
13
- }
14
-
15
- const Button: React.FC<React.ButtonHTMLAttributes<HTMLButtonElement> & Props> = ({
16
- className, children, variant, ...props
17
- }) => {
18
- const variants = makeVariants(variant);
19
-
20
- const cls = classnames(styles.btn, {
21
- [styles["btn--inline"]]: variants.includes("inline"),
22
- [styles["btn--outline"]]: variants.includes("outline"),
23
- }, className);
24
-
25
- return (
26
- <button
27
- {...props}
28
- className={cls}
29
- disabled={props.disabled}
30
- >{children}
31
- </button>
32
- );
33
- };
34
-
35
- export { Button };
1
+ export { Button } from "./Button.styled.js";
@@ -0,0 +1,143 @@
1
+ import React, { useCallback, useState } from "react";
2
+
3
+ import type { StoryObj, Meta } from "@storybook/react";
4
+
5
+ import { Button } from "../button/Button.js";
6
+ import { Label } from "../../form/Label.js";
7
+ import { Input } from "../../form/input/Input.js";
8
+ import { Checkbox } from "../../form/Checkbox.js";
9
+ import { List } from "../../layout/list/List.js";
10
+
11
+ import { Modal } from "./Modal.js";
12
+ import { ModalButtons } from "./ModalButtons.js";
13
+ import { RemovePadding } from "./Modal.styled";
14
+
15
+ const meta: Meta = {
16
+ title: "Components/UI/Modal",
17
+ component: Modal,
18
+ tags: ["autodocs", "ui"],
19
+ };
20
+
21
+ type Story = StoryObj<typeof Modal>;
22
+
23
+ const handleNoop = () => undefined;
24
+
25
+ const Primary: Story = {
26
+ args: {},
27
+ render: () => {
28
+ // eslint-disable-next-line @typescript-eslint/no-shadow
29
+ const [open, setIsOpen] = useState(false);
30
+
31
+ const handleClose = useCallback(() => {
32
+ setIsOpen(false);
33
+ }, []);
34
+
35
+ const handleOpen = useCallback(() => {
36
+ setIsOpen(true);
37
+ }, []);
38
+
39
+ return (
40
+ <div>
41
+ <Button onClick={handleOpen}>Open modal</Button>
42
+ <Modal onClose={handleClose} isOpen={open} title={"95.5 MHz"} position={"bottom"} full={true}>
43
+ <Label>
44
+ <Input placeholder={"New station"} />
45
+ </Label>
46
+ <Label>
47
+ <Checkbox name={""} onChange={handleNoop} checked={true}>
48
+ Remember me
49
+ </Checkbox>
50
+ </Label>
51
+ <ModalButtons>
52
+ <ModalButtons.Button onClick={handleClose}>
53
+ Cancel
54
+ </ModalButtons.Button>
55
+ <ModalButtons.Button variant={"main"} onClick={handleClose}>
56
+ Ok
57
+ </ModalButtons.Button>
58
+ </ModalButtons>
59
+ </Modal>
60
+ </div>
61
+ );
62
+ },
63
+ };
64
+
65
+ const WithRemovedPaddingSections: Story = {
66
+ args: {},
67
+ render: () => {
68
+ // eslint-disable-next-line @typescript-eslint/no-shadow
69
+ const [open, setIsOpen] = useState(false);
70
+
71
+ const handleClose = useCallback(() => {
72
+ setIsOpen(false);
73
+ }, []);
74
+
75
+ const handleOpen = useCallback(() => {
76
+ setIsOpen(true);
77
+ }, []);
78
+
79
+ return (
80
+ <div>
81
+ <Button onClick={handleOpen}>Open modal</Button>
82
+ <Modal onClose={handleClose} isOpen={open} position={"bottom"} full={true}>
83
+ <RemovePadding>
84
+ <Label>
85
+ <Input placeholder={"New station"} />
86
+ </Label>
87
+ </RemovePadding>
88
+ <Label>
89
+ <Input placeholder={"New station"} />
90
+ </Label>
91
+ <RemovePadding>
92
+ <Label>
93
+ <Input placeholder={"New station"} />
94
+ </Label>
95
+ </RemovePadding>
96
+ </Modal>
97
+ </div>
98
+ );
99
+ },
100
+ };
101
+
102
+ /**
103
+ * Just a demo how to render a pick-mode list in a modal.
104
+ */
105
+ const WithList: Story = {
106
+ args: {},
107
+ render: () => {
108
+ // eslint-disable-next-line @typescript-eslint/no-shadow
109
+ const [open, setIsOpen] = useState(false);
110
+
111
+ const handleClose = useCallback(() => {
112
+ setIsOpen(false);
113
+ }, []);
114
+
115
+ const handleOpen = useCallback(() => {
116
+ setIsOpen(true);
117
+ }, []);
118
+
119
+ return (
120
+ <div>
121
+ <Button onClick={handleOpen}>Open modal</Button>
122
+ <Modal onClose={handleClose} isOpen={open} position={"bottom"} full={true}>
123
+ <RemovePadding>
124
+ <List inset={true}>
125
+ <List.Item selected={false} onClick={handleClose}>First item</List.Item>
126
+ <List.Item selected={true} onClick={handleClose}>Second item</List.Item>
127
+ <List.Item selected={false} onClick={handleClose}>Third item</List.Item>
128
+ <List.Item selected={false} onClick={handleClose}>Last option</List.Item>
129
+ </List>
130
+ </RemovePadding>
131
+ </Modal>
132
+ </div>
133
+ );
134
+ },
135
+ };
136
+
137
+ export {
138
+ Primary,
139
+ WithRemovedPaddingSections,
140
+ WithList,
141
+ };
142
+
143
+ export default meta;
@@ -0,0 +1,100 @@
1
+ import { dimensionsPxToRem, fontPxToRem, keyframes, pxToRem, styled } from "../../../theme.js";
2
+
3
+ const PADDING = pxToRem(20);
4
+ const NEGATIVE_PADDING = pxToRem(-20);
5
+
6
+ const overlay = keyframes({
7
+ from: {
8
+ background: "#00000000",
9
+ },
10
+ to: {
11
+ background: "#0000004c",
12
+ },
13
+ });
14
+
15
+ const OverlayStyled = styled("div", {
16
+ position: "fixed",
17
+ zIndex: 4,
18
+ top: 0,
19
+ bottom: 0,
20
+ left: 0,
21
+ right: 0,
22
+ display: "flex",
23
+ alignItems: "center",
24
+ justifyContent: "center",
25
+ animation: `${overlay.toString()} 300ms`,
26
+ animationFillMode: "forwards",
27
+
28
+ variants: {
29
+ position: {
30
+ bottom: {
31
+ alignItems: "flex-end",
32
+ paddingBottom: dimensionsPxToRem(24),
33
+ },
34
+ },
35
+ isClosing: {
36
+ true: {
37
+ animationDirection: "reverse",
38
+ },
39
+ },
40
+ },
41
+ });
42
+
43
+ const container = keyframes({
44
+ from: {
45
+ transform: "translateY(30px)",
46
+ opacity: 0,
47
+ },
48
+ to: {
49
+ transform: "translateY(0)",
50
+ opacity: 1,
51
+ },
52
+ });
53
+
54
+ const RemovePadding = styled("div", {
55
+ mx: NEGATIVE_PADDING,
56
+ });
57
+
58
+ const ContainerStyled = styled("div", {
59
+ background: "$modalBg",
60
+ borderRadius: dimensionsPxToRem(12),
61
+ maxWidth: pxToRem(333),
62
+ maxHeight: "100%",
63
+ width: "calc(100% - 30px)",
64
+ padding: PADDING,
65
+ position: "relative",
66
+ boxSizing: "border-box",
67
+ animation: `${container.toString()} 300ms`,
68
+ animationFillMode: "forwards",
69
+
70
+ variants: {
71
+ // TODO this is very not rwd, it should be a media query
72
+ full: {
73
+ true: {
74
+ width: "calc(100vw - 30px)",
75
+ maxWidth: dimensionsPxToRem(1000),
76
+ },
77
+ },
78
+ isClosing: {
79
+ true: {
80
+ animationDirection: "reverse",
81
+ },
82
+ },
83
+ },
84
+ });
85
+
86
+ const TitleStyled = styled("div", { // TODO header by default? expose this as `titleAs`?
87
+ fontSize: fontPxToRem(40),
88
+ textAlign: "center",
89
+ color: "black",
90
+ margin: `${dimensionsPxToRem(90)} 0`,
91
+ });
92
+
93
+ export {
94
+ OverlayStyled,
95
+ RemovePadding,
96
+ ContainerStyled,
97
+ TitleStyled,
98
+
99
+ NEGATIVE_PADDING,
100
+ };
@@ -1,14 +1,13 @@
1
1
  import React, { useCallback, useEffect, useRef, useState } from "react";
2
2
 
3
- import classnames from "classnames";
4
3
  import { createPortal } from "react-dom";
5
4
 
6
- import { makeVariants } from "../../../utils/index.js";
5
+ import type { ThemeCSS } from "../../../theme";
7
6
 
8
- import { ModalNegateMargin } from "./ModalNoMargin.js";
9
- import styles from "./Modal.module.scss";
7
+ import { ContainerStyled, NEGATIVE_PADDING, OverlayStyled, RemovePadding, TitleStyled } from "./Modal.styled";
10
8
 
11
- type Variant = "bottom" | "full";
9
+ type OverlayProps = React.ComponentProps<typeof OverlayStyled>;
10
+ type ContainerProps = React.ComponentProps<typeof ContainerStyled>;
12
11
 
13
12
  interface Props {
14
13
  onOverlayClick?: (() => void) | "close" | null;
@@ -17,15 +16,19 @@ interface Props {
17
16
  isOpen: boolean;
18
17
  title?: React.ReactNode;
19
18
  className?: string;
20
- variant?: Variant | Variant[];
21
19
  portal?: boolean | HTMLElement;
22
20
  children: React.ReactNode;
21
+
22
+ position?: OverlayProps["position"];
23
+ full?: ContainerProps["full"];
23
24
  }
24
25
 
25
26
  interface SubComponents {
26
- NegateMargin: typeof ModalNegateMargin;
27
+ RemovePadding: typeof RemovePadding;
27
28
  }
28
29
 
30
+ // @TODO proper docs + buttons
31
+
29
32
  // eslint-disable-next-line max-lines-per-function,max-statements
30
33
  const Modal: React.FC<Props> & SubComponents = ({
31
34
  children,
@@ -36,15 +39,14 @@ const Modal: React.FC<Props> & SubComponents = ({
36
39
  onOverlayClick = "close",
37
40
  closeOnEsc = true,
38
41
  portal = true,
39
- variant,
42
+ position,
43
+ full,
40
44
  }) => {
41
45
  const [isClosing, setIsClosing] = useState(false);
42
46
  const [isRendered, setIsRendered] = useState(false);
43
47
  const overlayRef = useRef<HTMLDivElement>(null);
44
48
  const containerRef = useRef<HTMLDivElement>(null);
45
49
 
46
- const v = makeVariants(variant);
47
-
48
50
  useEffect(() => {
49
51
  if (!isOpen || !closeOnEsc) {
50
52
  return;
@@ -87,7 +89,7 @@ const Modal: React.FC<Props> & SubComponents = ({
87
89
  containerRef.current.style.removeProperty("animation");
88
90
  }, [isClosing]);
89
91
 
90
- const titleElem = title && <div className={styles.title}>{title}</div>;
92
+ const titleElem = title ? <TitleStyled>{title}</TitleStyled> : null;
91
93
 
92
94
  const handleOverlayClick = useCallback((e: React.MouseEvent) => {
93
95
  if (e.target !== e.currentTarget) {
@@ -113,28 +115,49 @@ const Modal: React.FC<Props> & SubComponents = ({
113
115
  return null;
114
116
  }
115
117
 
116
- const overlayCls = classnames(styles.overlay, {
117
- [styles.isClosing]: isClosing,
118
- [styles.overlayOnBottom]: v.includes("bottom"),
119
- });
120
-
121
- const containerCls = classnames(styles.container, className, {
122
- [styles.isClosing]: isClosing,
123
- [styles.full]: v.includes("full"),
118
+ const overlayVariants: Pick<OverlayProps, "isClosing" | "position"> = {};
119
+ isClosing && (overlayVariants.isClosing = true);
120
+ position != null && (overlayVariants.position = position);
121
+
122
+ const containerVariants: Pick<ContainerProps, "isClosing" | "full"> = {};
123
+ isClosing && (containerVariants.isClosing = true);
124
+ full != null && (containerVariants.full = full);
125
+
126
+ const childrenCount = React.Children.count(children);
127
+
128
+ const chld = React.Children.map(children, (child, index) => {
129
+ if (React.isValidElement(child)) {
130
+ if (child.type === RemovePadding) {
131
+ // eslint-disable-next-line max-len
132
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment,@typescript-eslint/no-unsafe-member-access
133
+ const css: ThemeCSS = child.props.css ?? {};
134
+ if (index === 0 && titleElem == null) {
135
+ css.marginTop = NEGATIVE_PADDING;
136
+ }
137
+ if (index === childrenCount - 1) {
138
+ css.marginBottom = NEGATIVE_PADDING;
139
+ }
140
+
141
+ // @ts-expect-error TODO handle types correctly
142
+ return React.cloneElement(child, { css });
143
+ }
144
+ return child;
145
+ }
146
+ return child;
124
147
  });
125
148
 
126
149
  const tree = (
127
- <div
128
- className={overlayCls}
150
+ <OverlayStyled
151
+ {...overlayVariants}
129
152
  onClick={handleOverlayClick}
130
153
  ref={overlayRef}
131
154
  onAnimationEnd={handleAnimationEnd}
132
155
  >
133
- <div className={containerCls} ref={containerRef}>
156
+ <ContainerStyled className={className} {...containerVariants} ref={containerRef}>
134
157
  {titleElem}
135
- {children}
136
- </div>
137
- </div>
158
+ {chld}
159
+ </ContainerStyled>
160
+ </OverlayStyled>
138
161
  );
139
162
 
140
163
  if (portal) {
@@ -144,6 +167,6 @@ const Modal: React.FC<Props> & SubComponents = ({
144
167
 
145
168
  return tree;
146
169
  };
147
- Modal.NegateMargin = ModalNegateMargin;
170
+ Modal.RemovePadding = RemovePadding;
148
171
 
149
172
  export { Modal };