@via-profit/ui-kit 0.1.0-rc.28 → 0.1.0-rc.30
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/Calendar/CalendarPaper.js +1 -1
- package/Menu/MenuItemInner.js +1 -1
- package/Menu/MenuWrapper.js +3 -1
- package/Modal/BaseModal/ModalInner.d.ts +13 -0
- package/Modal/BaseModal/ModalInner.js +47 -0
- package/Modal/BaseModal/ModalOverlay.d.ts +17 -0
- package/Modal/BaseModal/ModalOverlay.js +33 -0
- package/Modal/BaseModal/ModalWrapper.d.ts +14 -0
- package/Modal/BaseModal/ModalWrapper.js +177 -0
- package/Modal/BaseModal/RenderModal.d.ts +12 -0
- package/Modal/BaseModal/RenderModal.js +20 -0
- package/Modal/BaseModal/context.d.ts +30 -0
- package/Modal/BaseModal/context.js +44 -0
- package/Modal/BaseModal/index.d.ts +46 -0
- package/Modal/BaseModal/index.js +66 -0
- package/Modal/ConfirmBox/ConfirmBoxContainer.js +2 -2
- package/Modal/ConfirmBox/ConfirmBoxContent.js +2 -2
- package/Modal/ConfirmBox/ConfirmBoxFooter.js +2 -2
- package/Modal/ConfirmBox/ConfirmBoxHeader.js +4 -4
- package/Modal/ConfirmBox/index.d.ts +5 -5
- package/Modal/ConfirmBox/index.js +5 -54
- package/Modal/Dialog/DialogInner.d.ts +10 -0
- package/Modal/Dialog/DialogInner.js +49 -0
- package/Modal/Dialog/index.d.ts +4 -4
- package/Modal/Dialog/index.js +12 -56
- package/Modal/{CloseIcon.js → Drawer/DrawerCloseIcon.js} +2 -2
- package/Modal/Drawer/DrawerContainer.js +5 -3
- package/Modal/Drawer/DrawerContent.js +4 -3
- package/Modal/Drawer/DrawerFooter.js +2 -2
- package/Modal/Drawer/DrawerHeader.js +10 -10
- package/Modal/Drawer/DrawerInner.d.ts +18 -0
- package/Modal/Drawer/DrawerInner.js +141 -0
- package/Modal/Drawer/index.d.ts +12 -4
- package/Modal/Drawer/index.js +15 -52
- package/Modal/MessageBox/index.d.ts +5 -5
- package/Modal/MessageBox/index.js +5 -53
- package/Modal/index.d.ts +2 -3
- package/Modal/index.js +6 -6
- package/README.md +1 -2
- package/Surface/SurfaceContainer.d.ts +2 -2
- package/Surface/SurfaceContainer.js +3 -9
- package/Surface/SurfaceSubheader.js +1 -1
- package/Surface/index.d.ts +8 -8
- package/Surface/index.js +2 -2
- package/package.json +1 -4
- /package/Modal/{CloseIcon.d.ts → Drawer/DrawerCloseIcon.d.ts} +0 -0
|
@@ -10,7 +10,7 @@ const CalendarPaper = styled_1.default.div `
|
|
|
10
10
|
flex-direction: column;
|
|
11
11
|
justify-content: stretch;
|
|
12
12
|
background-color: ${({ theme }) => theme.color.surface.toString()};
|
|
13
|
-
border-radius: ${({ theme }) => theme.shape.radiusFactor
|
|
13
|
+
border-radius: ${({ theme }) => theme.shape.radiusFactor}em;
|
|
14
14
|
padding: 0.4em;
|
|
15
15
|
max-width: 17.6em;
|
|
16
16
|
max-height: 20.4em;
|
package/Menu/MenuItemInner.js
CHANGED
|
@@ -21,7 +21,7 @@ const InnerContainer = styled_1.default.div `
|
|
|
21
21
|
user-select: none;
|
|
22
22
|
padding: 0.4em 0.8em;
|
|
23
23
|
transition: all 240ms ease-out;
|
|
24
|
-
border-radius: ${({ theme }) => theme.shape.radiusFactor
|
|
24
|
+
border-radius: ${({ theme }) => theme.shape.radiusFactor}em;
|
|
25
25
|
background-color: ${({ theme, selected, hovered }) => {
|
|
26
26
|
if (selected && hovered) {
|
|
27
27
|
return theme.color.accentPrimary.darken(0.1).toString();
|
package/Menu/MenuWrapper.js
CHANGED
|
@@ -22,7 +22,9 @@ const StyledMenuWrapper = styled_1.default.div `
|
|
|
22
22
|
flex-direction: column;
|
|
23
23
|
display: flex;
|
|
24
24
|
flex-direction: column;
|
|
25
|
-
transition:
|
|
25
|
+
transition:
|
|
26
|
+
visibility 120ms ease-out,
|
|
27
|
+
opacity 120ms ease-out;
|
|
26
28
|
opacity: ${props => (props.$isOpen ? 1 : 0)};
|
|
27
29
|
visibility: ${props => (props.$isOpen ? 'visible' : 'hidden')};
|
|
28
30
|
background-color: ${({ theme }) => theme.color.surface.toString()};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ModalInnerProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/**
|
|
4
|
+
* The dialog will remain open as long as the value is true
|
|
5
|
+
*/
|
|
6
|
+
readonly isOpen: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The function that will be called to close the dialog
|
|
9
|
+
*/
|
|
10
|
+
readonly onRequestClose: () => void;
|
|
11
|
+
}
|
|
12
|
+
declare const _default: React.ForwardRefExoticComponent<ModalInnerProps & React.RefAttributes<HTMLDivElement>>;
|
|
13
|
+
export default _default;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const react_1 = __importDefault(require("react"));
|
|
18
|
+
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
+
const react_2 = require("@emotion/react");
|
|
20
|
+
const StyledModalInner = styled_1.default.div `
|
|
21
|
+
opacity: 0;
|
|
22
|
+
z-index: ${({ theme }) => theme.zIndex.modal};
|
|
23
|
+
position: fixed;
|
|
24
|
+
left: 50%;
|
|
25
|
+
top: 50%;
|
|
26
|
+
outline: none;
|
|
27
|
+
background-color: ${({ theme }) => theme.color.surface.toString()};
|
|
28
|
+
border-radius: ${({ theme }) => theme.shape.radiusFactor * 2}em;
|
|
29
|
+
transform: translate(-50%, -30%);
|
|
30
|
+
transition:
|
|
31
|
+
transform 240ms ease-out,
|
|
32
|
+
opacity 100ms ease-out;
|
|
33
|
+
|
|
34
|
+
${({ $isOpen }) => $isOpen &&
|
|
35
|
+
(0, react_2.css) `
|
|
36
|
+
opacity: 1;
|
|
37
|
+
transform: translate(-50%, -50%);
|
|
38
|
+
ransition:
|
|
39
|
+
transform 240ms ease-out,
|
|
40
|
+
opacity 100ms ease-out;
|
|
41
|
+
`}
|
|
42
|
+
`;
|
|
43
|
+
const ModalInner = (props, ref) => {
|
|
44
|
+
const { children, isOpen, onRequestClose } = props, restProps = __rest(props, ["children", "isOpen", "onRequestClose"]);
|
|
45
|
+
return (react_1.default.createElement(StyledModalInner, Object.assign({}, restProps, { "$isOpen": isOpen, ref: ref }), children));
|
|
46
|
+
};
|
|
47
|
+
exports.default = react_1.default.forwardRef(ModalInner);
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ModalOverlayProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
3
|
+
/**
|
|
4
|
+
* The dialog will remain open as long as the value is true
|
|
5
|
+
*/
|
|
6
|
+
readonly isOpen: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* The function that will be called to close the dialog
|
|
9
|
+
*/
|
|
10
|
+
readonly onRequestClose: () => void;
|
|
11
|
+
/**
|
|
12
|
+
* Should the dialog close when overlay mouse click
|
|
13
|
+
*/
|
|
14
|
+
readonly closeOnOverlayClick: boolean;
|
|
15
|
+
}
|
|
16
|
+
declare const _default: React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
17
|
+
export default _default;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
14
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
const react_1 = __importDefault(require("react"));
|
|
18
|
+
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
+
const StyledModalOverlay = styled_1.default.div `
|
|
20
|
+
position: fixed;
|
|
21
|
+
inset: 0;
|
|
22
|
+
z-index: ${({ theme }) => theme.zIndex.modal};
|
|
23
|
+
background-color: ${({ theme }) => theme.isDark
|
|
24
|
+
? theme.color.backgroundPrimary.darken(30).alpha(0.8).rgbString()
|
|
25
|
+
: theme.color.textPrimary.darken(30).alpha(0.8).rgbString()};
|
|
26
|
+
opacity: ${({ $isOpen }) => ($isOpen ? 1 : 0)};
|
|
27
|
+
transition: opacity 120ms ease-out;
|
|
28
|
+
`;
|
|
29
|
+
const ModalOverlay = (props, ref) => {
|
|
30
|
+
const { isOpen, onRequestClose, closeOnOverlayClick } = props, restProps = __rest(props, ["isOpen", "onRequestClose", "closeOnOverlayClick"]);
|
|
31
|
+
return (react_1.default.createElement(StyledModalOverlay, Object.assign({}, restProps, { ref: ref, "$isOpen": isOpen, onClick: closeOnOverlayClick ? () => onRequestClose() : undefined })));
|
|
32
|
+
};
|
|
33
|
+
exports.default = react_1.default.forwardRef(ModalOverlay);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type ModalWrapperProps = {
|
|
3
|
+
/**
|
|
4
|
+
* The dialog will remain open as long as the value is true
|
|
5
|
+
*/
|
|
6
|
+
readonly isOpen: boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Timeout (in `milliseconds`), after which the dialog box will be unmounted
|
|
9
|
+
*/
|
|
10
|
+
readonly destroyTimeout: number;
|
|
11
|
+
readonly children: React.ReactNode | readonly React.ReactNode[];
|
|
12
|
+
};
|
|
13
|
+
declare const ModalWrapper: React.FC<ModalWrapperProps>;
|
|
14
|
+
export default ModalWrapper;
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const react_2 = require("@emotion/react");
|
|
8
|
+
const context_1 = require("./context");
|
|
9
|
+
const ModalWrapper = props => {
|
|
10
|
+
const { children, isOpen: isOpenProp } = props;
|
|
11
|
+
const { state, dispatch } = (0, context_1.useContext)();
|
|
12
|
+
const [alreadyMounted, setMountState] = react_1.default.useState(true);
|
|
13
|
+
const { closeOnEsape, isMounted, isOpen, destroyTimeout, onRequestClose } = state;
|
|
14
|
+
const containerRef = react_1.default.useRef(null);
|
|
15
|
+
const id = react_1.default.useMemo(() => context_1.PORTAL_ID + ':' + new Date().getTime().toString(), []);
|
|
16
|
+
const getScrollWidth = react_1.default.useCallback(() => {
|
|
17
|
+
var _a;
|
|
18
|
+
const outer = window.document.createElement('div');
|
|
19
|
+
const inner = window.document.createElement('div');
|
|
20
|
+
let widthNoScroll = 0;
|
|
21
|
+
let widthWithScroll = 0;
|
|
22
|
+
outer.style.visibility = 'hidden';
|
|
23
|
+
outer.style.width = '100px';
|
|
24
|
+
window.document.body.appendChild(outer);
|
|
25
|
+
widthNoScroll = outer.offsetWidth;
|
|
26
|
+
// force scrollbars
|
|
27
|
+
outer.style.overflow = 'scroll';
|
|
28
|
+
// add innerdiv
|
|
29
|
+
inner.style.width = '100%';
|
|
30
|
+
outer.appendChild(inner);
|
|
31
|
+
widthWithScroll = inner.offsetWidth;
|
|
32
|
+
// remove div
|
|
33
|
+
(_a = outer.parentNode) === null || _a === void 0 ? void 0 : _a.removeChild(outer);
|
|
34
|
+
return widthNoScroll - widthWithScroll;
|
|
35
|
+
}, []);
|
|
36
|
+
/**
|
|
37
|
+
* Set focus to the next or prev element
|
|
38
|
+
*/
|
|
39
|
+
const lastIndex = react_1.default.useRef(-1);
|
|
40
|
+
const nextFocus = react_1.default.useCallback((reverse) => {
|
|
41
|
+
if (!containerRef.current) {
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
const universe = containerRef.current.querySelectorAll('input, button, select, textarea, a[href]');
|
|
45
|
+
const list = Array.prototype.filter.call(universe, function (item) {
|
|
46
|
+
return item.tabIndex >= '0';
|
|
47
|
+
});
|
|
48
|
+
if (!reverse) {
|
|
49
|
+
const nextIndex = lastIndex.current + 1;
|
|
50
|
+
if (list[nextIndex]) {
|
|
51
|
+
list[nextIndex].focus();
|
|
52
|
+
lastIndex.current = nextIndex;
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// othrwise
|
|
56
|
+
const nextEl = list[0];
|
|
57
|
+
if (nextEl) {
|
|
58
|
+
lastIndex.current = 0;
|
|
59
|
+
nextEl.focus();
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (reverse) {
|
|
64
|
+
const nextIndex = lastIndex.current - 1;
|
|
65
|
+
if (list[nextIndex]) {
|
|
66
|
+
list[nextIndex].focus();
|
|
67
|
+
lastIndex.current = nextIndex;
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
// othrwise
|
|
71
|
+
const nextEl = list[list.length - 1];
|
|
72
|
+
if (nextEl) {
|
|
73
|
+
lastIndex.current = list.length - 1;
|
|
74
|
+
nextEl.focus();
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}, []);
|
|
79
|
+
react_1.default.useEffect(() => {
|
|
80
|
+
if (containerRef.current) {
|
|
81
|
+
containerRef.current.focus();
|
|
82
|
+
}
|
|
83
|
+
const keydown = (event) => {
|
|
84
|
+
if (event.key.toLowerCase() !== 'tab') {
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
event.preventDefault();
|
|
88
|
+
nextFocus(event.shiftKey);
|
|
89
|
+
};
|
|
90
|
+
const lastFocused = document.activeElement;
|
|
91
|
+
window.document.addEventListener('keydown', keydown);
|
|
92
|
+
return () => {
|
|
93
|
+
if (lastFocused) {
|
|
94
|
+
lastFocused.focus();
|
|
95
|
+
}
|
|
96
|
+
window.document.removeEventListener('keydown', keydown);
|
|
97
|
+
};
|
|
98
|
+
}, [nextFocus]);
|
|
99
|
+
/**
|
|
100
|
+
* Component will unmount
|
|
101
|
+
* Mark component as unmounted
|
|
102
|
+
*/
|
|
103
|
+
react_1.default.useEffect(() => () => {
|
|
104
|
+
setMountState(false);
|
|
105
|
+
}, []);
|
|
106
|
+
react_1.default.useEffect(() => {
|
|
107
|
+
/**
|
|
108
|
+
* The last dialog will be found and closed
|
|
109
|
+
*/
|
|
110
|
+
const keyDown = (event) => {
|
|
111
|
+
var _a, _b, _c;
|
|
112
|
+
if (event.key.toLocaleLowerCase() === 'escape' && closeOnEsape) {
|
|
113
|
+
const portal = window.document.querySelector(`#${context_1.PORTAL_ID}`);
|
|
114
|
+
const lastID = (_c = (_a = portal === null || portal === void 0 ? void 0 : portal.children) === null || _a === void 0 ? void 0 : _a[((_b = portal === null || portal === void 0 ? void 0 : portal.childNodes) === null || _b === void 0 ? void 0 : _b.length) - 1]) === null || _c === void 0 ? void 0 : _c.id;
|
|
115
|
+
if (lastID === id) {
|
|
116
|
+
onRequestClose();
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
window.document.addEventListener('keydown', keyDown);
|
|
121
|
+
return () => {
|
|
122
|
+
window.document.removeEventListener('keydown', keyDown);
|
|
123
|
+
};
|
|
124
|
+
}, [onRequestClose, closeOnEsape, id]);
|
|
125
|
+
/**
|
|
126
|
+
* Controller for visibility state.
|
|
127
|
+
* Waiting n milliseconds after closing the modal, then sets the visibility property to true
|
|
128
|
+
* and sets visibility property to false otherwise
|
|
129
|
+
*/
|
|
130
|
+
react_1.default.useEffect(() => {
|
|
131
|
+
var _a;
|
|
132
|
+
if (isOpen !== isOpenProp) {
|
|
133
|
+
/**
|
|
134
|
+
* Mark as mounted and wait minimum loop of event (15ms) then mark as open
|
|
135
|
+
*/
|
|
136
|
+
if (isOpenProp) {
|
|
137
|
+
dispatch((0, context_1.actionSetState)({ isMounted: true }));
|
|
138
|
+
(_a = window.document.body) === null || _a === void 0 ? void 0 : _a.classList.add('-modal-over');
|
|
139
|
+
setTimeout(() => {
|
|
140
|
+
if (alreadyMounted) {
|
|
141
|
+
dispatch((0, context_1.actionSetState)({ isOpen: true }));
|
|
142
|
+
}
|
|
143
|
+
}, 15);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Mark as closed and wait destroyTimeout then mark as unmounted
|
|
148
|
+
*/
|
|
149
|
+
if (!isOpenProp) {
|
|
150
|
+
dispatch((0, context_1.actionSetState)({ isOpen: false }));
|
|
151
|
+
setTimeout(() => {
|
|
152
|
+
var _a, _b;
|
|
153
|
+
if (alreadyMounted) {
|
|
154
|
+
const portal = window.document.querySelector(`#${context_1.PORTAL_ID}`);
|
|
155
|
+
if (((_a = portal === null || portal === void 0 ? void 0 : portal.children) === null || _a === void 0 ? void 0 : _a.length) === 1) {
|
|
156
|
+
(_b = window.document.body) === null || _b === void 0 ? void 0 : _b.classList.remove('-modal-over');
|
|
157
|
+
}
|
|
158
|
+
dispatch((0, context_1.actionSetState)({ isMounted: false }));
|
|
159
|
+
}
|
|
160
|
+
}, destroyTimeout);
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}, [isOpenProp, isOpen, alreadyMounted, destroyTimeout, dispatch, getScrollWidth]);
|
|
165
|
+
return react_1.default.useMemo(() => isMounted ? (react_1.default.createElement("div", { ref: containerRef, tabIndex: -1, id: id },
|
|
166
|
+
children,
|
|
167
|
+
react_1.default.createElement(react_2.Global, { styles: (0, react_2.css) `
|
|
168
|
+
:root {
|
|
169
|
+
--modal-scroll-width: ${getScrollWidth()}px;
|
|
170
|
+
}
|
|
171
|
+
body.-modal-over {
|
|
172
|
+
overflow: hidden;
|
|
173
|
+
margin-right: var(--modal-scroll-width);
|
|
174
|
+
}
|
|
175
|
+
` }))) : null, [children, getScrollWidth, isMounted, id]);
|
|
176
|
+
};
|
|
177
|
+
exports.default = ModalWrapper;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ModalOverlayProps } from './ModalOverlay';
|
|
3
|
+
import { ModalInnerProps } from './ModalInner';
|
|
4
|
+
interface RenderModalProps {
|
|
5
|
+
readonly children: React.ReactNode | readonly React.ReactNode[];
|
|
6
|
+
readonly overrides: {
|
|
7
|
+
readonly Overlay?: React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
8
|
+
readonly Inner?: React.ForwardRefExoticComponent<ModalInnerProps & React.RefAttributes<HTMLDivElement>>;
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
declare const RenderModal: React.FC<RenderModalProps>;
|
|
12
|
+
export default RenderModal;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const context_1 = require("./context");
|
|
8
|
+
const ModalOverlay_1 = __importDefault(require("./ModalOverlay"));
|
|
9
|
+
const ModalInner_1 = __importDefault(require("./ModalInner"));
|
|
10
|
+
const RenderModal = props => {
|
|
11
|
+
const { children, overrides } = props;
|
|
12
|
+
const { state } = (0, context_1.useContext)();
|
|
13
|
+
const { isOpen, closeOnOverlayClick, onRequestClose } = state;
|
|
14
|
+
const overridesMap = react_1.default.useMemo(() => (Object.assign({ Overlay: ModalOverlay_1.default,
|
|
15
|
+
Inner: ModalInner_1.default }, overrides)), [overrides]);
|
|
16
|
+
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
17
|
+
react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.Overlay, { isOpen: isOpen, onRequestClose: onRequestClose, closeOnOverlayClick: closeOnOverlayClick })), [overridesMap, isOpen, closeOnOverlayClick, onRequestClose]),
|
|
18
|
+
react_1.default.useMemo(() => (react_1.default.createElement(overridesMap.Inner, { isOpen: isOpen, onRequestClose: onRequestClose }, children)), [children, isOpen, overridesMap, onRequestClose])));
|
|
19
|
+
};
|
|
20
|
+
exports.default = RenderModal;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type State = {
|
|
3
|
+
readonly isOpen: boolean;
|
|
4
|
+
readonly isMounted: boolean;
|
|
5
|
+
readonly destroyTimeout: number;
|
|
6
|
+
readonly onRequestClose: () => void;
|
|
7
|
+
readonly closeOnEsape: boolean;
|
|
8
|
+
readonly closeOnOverlayClick: boolean;
|
|
9
|
+
};
|
|
10
|
+
export type Context = {
|
|
11
|
+
readonly state: State;
|
|
12
|
+
readonly dispatch: React.Dispatch<Action>;
|
|
13
|
+
};
|
|
14
|
+
export type ActionSetState = {
|
|
15
|
+
readonly type: 'setState';
|
|
16
|
+
readonly payload: Partial<State>;
|
|
17
|
+
};
|
|
18
|
+
export type Action = ActionSetState;
|
|
19
|
+
export declare const PORTAL_ID = "modal-portal";
|
|
20
|
+
export declare const defaultState: State;
|
|
21
|
+
export declare const actionSetState: (payload: ActionSetState['payload']) => ActionSetState;
|
|
22
|
+
export interface ContextProviderProps {
|
|
23
|
+
readonly children: React.ReactNode | readonly React.ReactNode[];
|
|
24
|
+
readonly initialState: Omit<State, 'isMounted'>;
|
|
25
|
+
}
|
|
26
|
+
export declare const ContextProvider: React.FC<ContextProviderProps>;
|
|
27
|
+
export declare const useContext: () => {
|
|
28
|
+
state: State;
|
|
29
|
+
dispatch: React.Dispatch<ActionSetState>;
|
|
30
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.useContext = exports.ContextProvider = exports.actionSetState = exports.defaultState = exports.PORTAL_ID = void 0;
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
8
|
+
exports.PORTAL_ID = 'modal-portal';
|
|
9
|
+
exports.defaultState = {
|
|
10
|
+
isOpen: false,
|
|
11
|
+
isMounted: false,
|
|
12
|
+
destroyTimeout: 240,
|
|
13
|
+
closeOnEsape: true,
|
|
14
|
+
closeOnOverlayClick: true,
|
|
15
|
+
onRequestClose: () => undefined,
|
|
16
|
+
};
|
|
17
|
+
const reducer = (state, action) => {
|
|
18
|
+
switch (action.type) {
|
|
19
|
+
case 'setState':
|
|
20
|
+
return Object.assign(Object.assign({}, state), action.payload);
|
|
21
|
+
default:
|
|
22
|
+
return state;
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
const actionSetState = (payload) => ({
|
|
26
|
+
type: 'setState',
|
|
27
|
+
payload,
|
|
28
|
+
});
|
|
29
|
+
exports.actionSetState = actionSetState;
|
|
30
|
+
const context = react_1.default.createContext({ state: exports.defaultState, dispatch: () => undefined });
|
|
31
|
+
const ContextProvider = props => {
|
|
32
|
+
const { children, initialState } = props;
|
|
33
|
+
const [state, dispatch] = react_1.default.useReducer(reducer, Object.assign(Object.assign({}, exports.defaultState), initialState));
|
|
34
|
+
return react_1.default.createElement(context.Provider, { value: { state, dispatch } }, children);
|
|
35
|
+
};
|
|
36
|
+
exports.ContextProvider = ContextProvider;
|
|
37
|
+
const useContext = () => {
|
|
38
|
+
const { state, dispatch } = react_1.default.useContext(context);
|
|
39
|
+
return {
|
|
40
|
+
state,
|
|
41
|
+
dispatch,
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
exports.useContext = useContext;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { ModalOverlayProps } from './ModalOverlay';
|
|
3
|
+
import { ModalInnerProps } from './ModalInner';
|
|
4
|
+
export interface BaseModalProps {
|
|
5
|
+
/**
|
|
6
|
+
* The dialog will remain open as long as the value is true
|
|
7
|
+
*/
|
|
8
|
+
readonly isOpen: boolean;
|
|
9
|
+
/**
|
|
10
|
+
* The function that will be called to close the dialog
|
|
11
|
+
*/
|
|
12
|
+
readonly onRequestClose: () => void;
|
|
13
|
+
/**
|
|
14
|
+
* Dialog content
|
|
15
|
+
*/
|
|
16
|
+
readonly children: React.ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Timeout (in `milliseconds`), after which the dialog box will be unmounted.\
|
|
19
|
+
* Correct if the value is equal to the length of the transition time\
|
|
20
|
+
* \
|
|
21
|
+
* **Default:** `240`
|
|
22
|
+
*/
|
|
23
|
+
readonly destroyTimeout?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Should the dialog close when `escape` key press\
|
|
26
|
+
* \
|
|
27
|
+
* **Default**: `true`
|
|
28
|
+
*/
|
|
29
|
+
readonly closeOnEsape?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Should the dialog close when overlay mouse click\
|
|
32
|
+
* \
|
|
33
|
+
* **Default**: `true`
|
|
34
|
+
*/
|
|
35
|
+
readonly closeOnOverlayClick?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Overridable components map
|
|
38
|
+
*/
|
|
39
|
+
readonly overrides?: BaseModalOverrides;
|
|
40
|
+
}
|
|
41
|
+
export interface BaseModalOverrides {
|
|
42
|
+
readonly Overlay?: React.ForwardRefExoticComponent<ModalOverlayProps & React.RefAttributes<HTMLDivElement>>;
|
|
43
|
+
readonly Inner?: React.ForwardRefExoticComponent<ModalInnerProps & React.RefAttributes<HTMLDivElement>>;
|
|
44
|
+
}
|
|
45
|
+
declare const BaseModal: React.FC<BaseModalProps>;
|
|
46
|
+
export default BaseModal;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const react_1 = __importDefault(require("react"));
|
|
7
|
+
const react_dom_1 = __importDefault(require("react-dom"));
|
|
8
|
+
const context_1 = require("./context");
|
|
9
|
+
const ModalOverlay_1 = __importDefault(require("./ModalOverlay"));
|
|
10
|
+
const ModalInner_1 = __importDefault(require("./ModalInner"));
|
|
11
|
+
const ModalWrapper_1 = __importDefault(require("./ModalWrapper"));
|
|
12
|
+
const RenderModal_1 = __importDefault(require("./RenderModal"));
|
|
13
|
+
const NoSSR_1 = __importDefault(require("../../NoSSR"));
|
|
14
|
+
const BaseModal = props => {
|
|
15
|
+
const { isOpen, children, overrides, onRequestClose, closeOnOverlayClick = context_1.defaultState.closeOnOverlayClick, closeOnEsape = context_1.defaultState.closeOnEsape, destroyTimeout = context_1.defaultState.destroyTimeout, } = props;
|
|
16
|
+
const destroyTimeoutRef = react_1.default.useRef(null);
|
|
17
|
+
const [domLoaded, setDomLoaded] = react_1.default.useState(false);
|
|
18
|
+
const overridesMap = react_1.default.useMemo(() => (Object.assign({ Overlay: ModalOverlay_1.default,
|
|
19
|
+
Inner: ModalInner_1.default }, overrides)), [overrides]);
|
|
20
|
+
react_1.default.useEffect(() => {
|
|
21
|
+
/**
|
|
22
|
+
* Client render detection
|
|
23
|
+
*/
|
|
24
|
+
setDomLoaded(true);
|
|
25
|
+
const timeout = destroyTimeoutRef.current;
|
|
26
|
+
// unload destroy timeout
|
|
27
|
+
return () => {
|
|
28
|
+
if (timeout) {
|
|
29
|
+
clearTimeout(timeout);
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}, []);
|
|
33
|
+
const portalEl = react_1.default.useMemo(() => {
|
|
34
|
+
if (typeof window === 'undefined') {
|
|
35
|
+
return undefined;
|
|
36
|
+
}
|
|
37
|
+
const node = window.document.body.querySelector(`#${context_1.PORTAL_ID}`);
|
|
38
|
+
if (node) {
|
|
39
|
+
return node;
|
|
40
|
+
}
|
|
41
|
+
const newNode = window.document.createElement('div');
|
|
42
|
+
newNode.setAttribute('id', context_1.PORTAL_ID);
|
|
43
|
+
window.document.body.appendChild(newNode);
|
|
44
|
+
return newNode;
|
|
45
|
+
}, []);
|
|
46
|
+
react_1.default.useEffect(() => () => {
|
|
47
|
+
if (typeof window !== 'undefined') {
|
|
48
|
+
const node = window.document.body.querySelector(`#${context_1.PORTAL_ID}`);
|
|
49
|
+
if (node) {
|
|
50
|
+
node.remove();
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}, []);
|
|
54
|
+
return (react_1.default.createElement(NoSSR_1.default, null, domLoaded &&
|
|
55
|
+
portalEl &&
|
|
56
|
+
react_dom_1.default.createPortal(react_1.default.createElement(context_1.ContextProvider, { initialState: {
|
|
57
|
+
isOpen,
|
|
58
|
+
destroyTimeout,
|
|
59
|
+
closeOnEsape,
|
|
60
|
+
closeOnOverlayClick,
|
|
61
|
+
onRequestClose,
|
|
62
|
+
} },
|
|
63
|
+
react_1.default.createElement(ModalWrapper_1.default, { isOpen: isOpen, destroyTimeout: destroyTimeout },
|
|
64
|
+
react_1.default.createElement(RenderModal_1.default, { overrides: overridesMap }, children))), portalEl, 'ui-modal-portal')));
|
|
65
|
+
};
|
|
66
|
+
exports.default = BaseModal;
|
|
@@ -16,13 +16,13 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
const react_1 = __importDefault(require("react"));
|
|
18
18
|
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
-
const
|
|
19
|
+
const StyledConfirmBoxContainer = styled_1.default.div `
|
|
20
20
|
display: flex;
|
|
21
21
|
flex-flow: column;
|
|
22
22
|
min-width: 20em;
|
|
23
23
|
`;
|
|
24
24
|
const ConfirmBoxContainer = (props, ref) => {
|
|
25
25
|
const { children, dialogID } = props, nativeProps = __rest(props, ["children", "dialogID"]);
|
|
26
|
-
return (react_1.default.createElement(
|
|
26
|
+
return (react_1.default.createElement(StyledConfirmBoxContainer, Object.assign({ role: "modal-confirmbox", "aria-labelledby": `${dialogID}-title`, "aria-describedby": `${dialogID}-description` }, nativeProps, { ref: ref }), children));
|
|
27
27
|
};
|
|
28
28
|
exports.default = react_1.default.forwardRef(ConfirmBoxContainer);
|
|
@@ -16,12 +16,12 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
const react_1 = __importDefault(require("react"));
|
|
18
18
|
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
-
const
|
|
19
|
+
const StyledConfirmBoxContent = styled_1.default.div `
|
|
20
20
|
flex: 1;
|
|
21
21
|
padding: 1em 1em;
|
|
22
22
|
`;
|
|
23
23
|
const ConfirmBoxContent = (props, ref) => {
|
|
24
24
|
const { children, dialogID } = props, nativeProps = __rest(props, ["children", "dialogID"]);
|
|
25
|
-
return (react_1.default.createElement(
|
|
25
|
+
return (react_1.default.createElement(StyledConfirmBoxContent, Object.assign({ id: `${dialogID}-description` }, nativeProps, { ref: ref }), children));
|
|
26
26
|
};
|
|
27
27
|
exports.default = react_1.default.forwardRef(ConfirmBoxContent);
|
|
@@ -17,7 +17,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
17
17
|
const react_1 = __importDefault(require("react"));
|
|
18
18
|
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
19
|
const Button_1 = __importDefault(require("../../Button"));
|
|
20
|
-
const
|
|
20
|
+
const StyledConfirmBoxFooter = styled_1.default.div `
|
|
21
21
|
display: flex;
|
|
22
22
|
justify-content: flex-end;
|
|
23
23
|
align-items: center;
|
|
@@ -39,7 +39,7 @@ const Footer = styled_1.default.div `
|
|
|
39
39
|
`;
|
|
40
40
|
const ConfirmBoxFooter = (props, ref) => {
|
|
41
41
|
const { onRequestClose, onRequestYes, dismissButtonLabel, confirmButtonLabel } = props, nativeProps = __rest(props, ["onRequestClose", "onRequestYes", "dismissButtonLabel", "confirmButtonLabel"]);
|
|
42
|
-
return (react_1.default.createElement(
|
|
42
|
+
return (react_1.default.createElement(StyledConfirmBoxFooter, Object.assign({}, nativeProps, { ref: ref }),
|
|
43
43
|
react_1.default.createElement(Button_1.default, { onClick: onRequestClose }, typeof dismissButtonLabel === 'undefined' ? 'Dismiss' : dismissButtonLabel),
|
|
44
44
|
react_1.default.createElement(Button_1.default, { color: "primary", onClick: onRequestYes }, typeof confirmButtonLabel === 'undefined' ? 'Confirm' : confirmButtonLabel)));
|
|
45
45
|
};
|
|
@@ -16,16 +16,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
const react_1 = __importDefault(require("react"));
|
|
18
18
|
const styled_1 = __importDefault(require("@emotion/styled"));
|
|
19
|
-
const
|
|
19
|
+
const StyedConfirmBoxHeader = styled_1.default.div `
|
|
20
20
|
padding: 1em 1em 0 1em;
|
|
21
21
|
`;
|
|
22
|
-
const
|
|
22
|
+
const ConfirmBoxTitle = styled_1.default.div `
|
|
23
23
|
font-size: 1.4rem;
|
|
24
24
|
font-weight: 600;
|
|
25
25
|
`;
|
|
26
26
|
const ConfirmBoxHeader = (props, ref) => {
|
|
27
27
|
const { children, dialogID } = props, nativeProps = __rest(props, ["children", "dialogID"]);
|
|
28
|
-
return (react_1.default.createElement(
|
|
29
|
-
react_1.default.createElement(
|
|
28
|
+
return (react_1.default.createElement(StyedConfirmBoxHeader, Object.assign({}, nativeProps, { ref: ref }),
|
|
29
|
+
react_1.default.createElement(ConfirmBoxTitle, { id: `${dialogID}-title` }, children)));
|
|
30
30
|
};
|
|
31
31
|
exports.default = react_1.default.forwardRef(ConfirmBoxHeader);
|