cherry-styled-components 0.2.1 → 0.2.2
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.
- package/dist/modal.d.ts +6 -1
- package/dist/modal.js +39 -16
- package/dist/utils/use-on-click-outside.js +14 -3
- package/package.json +1 -1
package/dist/modal.d.ts
CHANGED
|
@@ -5,6 +5,11 @@ export interface ModalProps {
|
|
|
5
5
|
$onClose: () => void;
|
|
6
6
|
$title?: string;
|
|
7
7
|
$width?: number;
|
|
8
|
+
$hideCloseButton?: boolean;
|
|
9
|
+
/** Enables restyling via styled(Modal); applied to the overlay root. The
|
|
10
|
+
inner parts expose class hooks: .modal-inner, .modal-close, .modal-title,
|
|
11
|
+
.modal-content. */
|
|
12
|
+
className?: string;
|
|
8
13
|
}
|
|
9
|
-
declare function Modal({ children, $isOpen, $onClose, $title, $width }: ModalProps): React.ReactPortal | null;
|
|
14
|
+
declare function Modal({ children, $isOpen, $onClose, $title, $width, $hideCloseButton, className, }: ModalProps): React.ReactPortal | null;
|
|
10
15
|
export { Modal };
|
package/dist/modal.js
CHANGED
|
@@ -6,8 +6,8 @@ import { useOnClickOutside } from "./utils/use-on-click-outside.js";
|
|
|
6
6
|
import { Icon } from "./icon.js";
|
|
7
7
|
import { IconButton } from "./icon-button.js";
|
|
8
8
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
-
import { useCallback, useEffect, useRef, useSyncExternalStore } from "react";
|
|
10
|
-
import styled, { css } from "styled-components";
|
|
9
|
+
import { useCallback, useEffect, useRef, useState, useSyncExternalStore } from "react";
|
|
10
|
+
import styled, { css, keyframes } from "styled-components";
|
|
11
11
|
import { rgba } from "polished";
|
|
12
12
|
import { createPortal } from "react-dom";
|
|
13
13
|
//#region src/lib/modal.tsx
|
|
@@ -15,26 +15,31 @@ var emptySubscribe = () => () => {};
|
|
|
15
15
|
function useIsClient() {
|
|
16
16
|
return useSyncExternalStore(emptySubscribe, () => true, () => false);
|
|
17
17
|
}
|
|
18
|
+
var overlayFadeIn = keyframes([`from{opacity:0;}to{opacity:1;}`]);
|
|
19
|
+
var overlayFadeOut = keyframes([`from{opacity:1;}to{opacity:0;}`]);
|
|
20
|
+
var innerRiseIn = keyframes([`from{transform:translateY(40px);}to{transform:translateY(0);}`]);
|
|
21
|
+
var innerSinkOut = keyframes([`from{transform:translateY(0);}to{transform:translateY(40px);}`]);
|
|
18
22
|
var StyledModal = styled.div.withConfig({
|
|
19
23
|
displayName: "modal__StyledModal",
|
|
20
|
-
componentId: "sc-
|
|
24
|
+
componentId: "sc-e8a3a913-0"
|
|
21
25
|
})([
|
|
22
26
|
`position:fixed;top:0;left:0;width:100%;height:100%;background:`,
|
|
23
|
-
`;display:flex;justify-content:center;align-items:center;z-index:1010;
|
|
27
|
+
`;display:flex;justify-content:center;align-items:center;z-index:1010;animation:`,
|
|
28
|
+
` 0.3s ease both;`,
|
|
24
29
|
` & .modal-inner{background:`,
|
|
25
30
|
`;border-radius:`,
|
|
26
|
-
`;padding:20px;max-width:calc(100% - 40px);width:100%;margin:auto;position:relative;
|
|
27
|
-
`
|
|
31
|
+
`;padding:20px;max-width:calc(100% - 40px);width:100%;margin:auto;position:relative;animation:`,
|
|
32
|
+
` 0.3s ease both;`,
|
|
28
33
|
`{max-width:500px;`,
|
|
29
34
|
`}}`
|
|
30
|
-
], ({ theme }) => rgba(theme.colors.primary, .5), ({ $
|
|
35
|
+
], ({ theme }) => rgba(theme.colors.primary, .5), ({ $isClosing }) => $isClosing ? overlayFadeOut : overlayFadeIn, ({ $isClosing }) => $isClosing && css([`pointer-events:none;`]), ({ theme }) => theme.colors.light, ({ theme }) => theme.spacing.radius.lg, ({ $isClosing }) => $isClosing ? innerSinkOut : innerRiseIn, mq("lg"), ({ $width }) => $width && css([`max-width:`, `px;`], $width));
|
|
31
36
|
var StyledModalClose = styled(IconButton).withConfig({
|
|
32
37
|
displayName: "modal__StyledModalClose",
|
|
33
|
-
componentId: "sc-
|
|
38
|
+
componentId: "sc-e8a3a913-1"
|
|
34
39
|
})([`position:absolute;top:20px;right:20px;z-index:10;`]);
|
|
35
40
|
var StyledModalTitle = styled.h2.withConfig({
|
|
36
41
|
displayName: "modal__StyledModalTitle",
|
|
37
|
-
componentId: "sc-
|
|
42
|
+
componentId: "sc-e8a3a913-2"
|
|
38
43
|
})([
|
|
39
44
|
`--divider-color:`,
|
|
40
45
|
`;margin:0 0 15px 0;padding:0 0 15px 0;color:`,
|
|
@@ -43,16 +48,19 @@ var StyledModalTitle = styled.h2.withConfig({
|
|
|
43
48
|
], ({ theme }) => theme.colors.grayLight, ({ theme }) => theme.colors.dark, ({ theme }) => styledH5(theme));
|
|
44
49
|
var StyledModalContent = styled.div.withConfig({
|
|
45
50
|
displayName: "modal__StyledModalContent",
|
|
46
|
-
componentId: "sc-
|
|
51
|
+
componentId: "sc-e8a3a913-3"
|
|
47
52
|
})([
|
|
48
53
|
`max-height:calc(100svh - 200px);overflow-y:auto;padding:5px;margin:-5px;--divider-color:`,
|
|
49
54
|
`;`,
|
|
50
55
|
`;& hr{margin:20px 0;border:none;border-bottom:solid 1px var(--divider-color);}`
|
|
51
56
|
], ({ theme }) => theme.colors.grayLight, ({ theme }) => styledText(theme));
|
|
52
|
-
function Modal({ children, $isOpen, $onClose, $title, $width }) {
|
|
57
|
+
function Modal({ children, $isOpen, $onClose, $title, $width, $hideCloseButton, className }) {
|
|
53
58
|
const wrapperRef = useRef(null);
|
|
54
59
|
const elmRef = useRef(null);
|
|
55
60
|
const isClient = useIsClient();
|
|
61
|
+
const [shouldRender, setShouldRender] = useState($isOpen);
|
|
62
|
+
if ($isOpen && !shouldRender) setShouldRender(true);
|
|
63
|
+
const isClosing = !$isOpen && shouldRender;
|
|
56
64
|
const closeModal = useCallback(() => {
|
|
57
65
|
$onClose();
|
|
58
66
|
}, [$onClose]);
|
|
@@ -68,15 +76,24 @@ function Modal({ children, $isOpen, $onClose, $title, $width }) {
|
|
|
68
76
|
return () => document.removeEventListener("keydown", handleKeydown);
|
|
69
77
|
}, [$isOpen, closeModal]);
|
|
70
78
|
useOnClickOutside([elmRef, wrapperRef], $isOpen ? closeModal : () => {});
|
|
71
|
-
|
|
79
|
+
const handleAnimationEnd = useCallback((event) => {
|
|
80
|
+
if (event.target !== event.currentTarget) return;
|
|
81
|
+
if (!$isOpen) setShouldRender(false);
|
|
82
|
+
}, [$isOpen]);
|
|
83
|
+
if (!isClient || !shouldRender) return null;
|
|
72
84
|
return /*#__PURE__*/ createPortal(/*#__PURE__*/ jsx(StyledModal, {
|
|
73
|
-
$
|
|
85
|
+
$isClosing: isClosing,
|
|
74
86
|
$width,
|
|
87
|
+
className,
|
|
88
|
+
onAnimationEnd: handleAnimationEnd,
|
|
75
89
|
children: /*#__PURE__*/ jsxs("div", {
|
|
76
90
|
className: "modal-inner",
|
|
77
91
|
ref: wrapperRef,
|
|
92
|
+
role: "dialog",
|
|
93
|
+
"aria-modal": "true",
|
|
94
|
+
"aria-label": $title,
|
|
78
95
|
children: [
|
|
79
|
-
/*#__PURE__*/ jsx("span", {
|
|
96
|
+
!$hideCloseButton && /*#__PURE__*/ jsx("span", {
|
|
80
97
|
ref: elmRef,
|
|
81
98
|
children: /*#__PURE__*/ jsx(StyledModalClose, {
|
|
82
99
|
$size: "small",
|
|
@@ -86,8 +103,14 @@ function Modal({ children, $isOpen, $onClose, $title, $width }) {
|
|
|
86
103
|
children: /*#__PURE__*/ jsx(Icon, { name: "X" })
|
|
87
104
|
})
|
|
88
105
|
}),
|
|
89
|
-
$title && /*#__PURE__*/ jsx(StyledModalTitle, {
|
|
90
|
-
|
|
106
|
+
$title && /*#__PURE__*/ jsx(StyledModalTitle, {
|
|
107
|
+
className: "modal-title",
|
|
108
|
+
children: $title
|
|
109
|
+
}),
|
|
110
|
+
/*#__PURE__*/ jsx(StyledModalContent, {
|
|
111
|
+
className: "modal-content",
|
|
112
|
+
children
|
|
113
|
+
})
|
|
91
114
|
]
|
|
92
115
|
})
|
|
93
116
|
}), document.body);
|
|
@@ -1,17 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
"use client";
|
|
3
|
-
import { useEffect } from "react";
|
|
3
|
+
import { useEffect, useRef } from "react";
|
|
4
4
|
//#region src/lib/utils/use-on-click-outside.tsx
|
|
5
5
|
function useOnClickOutside(refs, cb) {
|
|
6
|
+
const latest = useRef({
|
|
7
|
+
refs,
|
|
8
|
+
cb
|
|
9
|
+
});
|
|
10
|
+
useEffect(() => {
|
|
11
|
+
latest.current = {
|
|
12
|
+
refs,
|
|
13
|
+
cb
|
|
14
|
+
};
|
|
15
|
+
});
|
|
6
16
|
useEffect(() => {
|
|
7
17
|
function handleClickOutside(event) {
|
|
8
|
-
|
|
18
|
+
const { refs, cb } = latest.current;
|
|
19
|
+
if (refs.every((ref) => !ref.current || !ref.current.contains(event.target))) cb();
|
|
9
20
|
}
|
|
10
21
|
document.addEventListener("mousedown", handleClickOutside);
|
|
11
22
|
return () => {
|
|
12
23
|
document.removeEventListener("mousedown", handleClickOutside);
|
|
13
24
|
};
|
|
14
|
-
}, [
|
|
25
|
+
}, []);
|
|
15
26
|
}
|
|
16
27
|
//#endregion
|
|
17
28
|
export { useOnClickOutside };
|
package/package.json
CHANGED