react-side-sheet-pro 0.1.7 → 0.1.9

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/README.md CHANGED
@@ -151,10 +151,10 @@ Sheet footer component that can be used to display actions or additional informa
151
151
  cd playground/ && npm start
152
152
  ```
153
153
 
154
- ## 🌟 Contributing
154
+ ## 🤝 Contributing
155
155
 
156
156
  We welcome contributions! If you'd like to help improve this project, feel free to open an issue or submit a pull request.
157
157
 
158
- ## License
158
+ ## 📜 License
159
159
 
160
160
  This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -1,6 +1,5 @@
1
1
  "use strict";
2
2
 
3
- function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
4
3
  Object.defineProperty(exports, "__esModule", {
5
4
  value: true
6
5
  });
@@ -10,6 +9,40 @@ var _react = _interopRequireWildcard(require("react"));
10
9
  var _classnames = _interopRequireDefault(require("classnames"));
11
10
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function _interopRequireWildcard(e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, "default": e }; if (null === e || "object" != _typeof(e) && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); }
12
11
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { "default": e }; }
12
+ function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
13
+ function _defineProperty(e, r, t) { return (r = _toPropertyKey(r)) in e ? Object.defineProperty(e, r, { value: t, enumerable: !0, configurable: !0, writable: !0 }) : e[r] = t, e; }
14
+ function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : i + ""; }
15
+ function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
16
+ function getStackItemMeta(stack, idx) {
17
+ var prev = stack[idx - 1];
18
+ var next = stack[idx + 1];
19
+ return {
20
+ prev: prev,
21
+ next: next,
22
+ isTop: idx === stack.length - 1,
23
+ isPrevClosing: (prev === null || prev === void 0 ? void 0 : prev.state) === 'closing',
24
+ isNextTransitioning: (next === null || next === void 0 ? void 0 : next.state) === 'closing' || (next === null || next === void 0 ? void 0 : next.state) === 'opening'
25
+ };
26
+ }
27
+ function computePadding(stack, idx) {
28
+ var _stack$options$width, _stack;
29
+ var _getStackItemMeta = getStackItemMeta(stack, idx),
30
+ next = _getStackItemMeta.next,
31
+ isTop = _getStackItemMeta.isTop,
32
+ isPrevClosing = _getStackItemMeta.isPrevClosing,
33
+ isNextTransitioning = _getStackItemMeta.isNextTransitioning;
34
+ if (isTop || isPrevClosing || isNextTransitioning || !next) return undefined;
35
+ var viewportWidth = document.documentElement.clientWidth;
36
+ var maxWidth = (_stack$options$width = (_stack = stack[stack.length - 1]) === null || _stack === void 0 ? void 0 : _stack.options.width) !== null && _stack$options$width !== void 0 ? _stack$options$width : 0;
37
+ var padding = 0;
38
+ if (viewportWidth >= 1160) {
39
+ padding = Math.floor((viewportWidth - 960) / 2);
40
+ } else if (viewportWidth >= 768) {
41
+ padding = Math.floor((viewportWidth - 768) / 2);
42
+ }
43
+ padding = Math.min(padding, maxWidth);
44
+ return padding > 0 ? padding : next.options.width / 2;
45
+ }
13
46
  var SideSheetContainer = exports.SideSheetContainer = function SideSheetContainer(_ref) {
14
47
  var stack = _ref.stack,
15
48
  open = _ref.open,
@@ -30,18 +63,30 @@ var SideSheetContainer = exports.SideSheetContainer = function SideSheetContaine
30
63
  document.removeEventListener('keydown', onKeyDown);
31
64
  };
32
65
  }, [stack, close]);
66
+ var paddingKey = config.side === 'left' ? 'paddingLeft' : 'paddingRight';
33
67
  return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, null, stack.map(function (item, idx) {
34
- var _stack;
35
- var isTop = idx === stack.length - 1;
36
- var isPrevClosing = ((_stack = stack[idx - 1]) === null || _stack === void 0 ? void 0 : _stack.state) === 'closing';
68
+ var _getStackItemMeta2 = getStackItemMeta(stack, idx),
69
+ next = _getStackItemMeta2.next,
70
+ isTop = _getStackItemMeta2.isTop,
71
+ isPrevClosing = _getStackItemMeta2.isPrevClosing,
72
+ isNextTransitioning = _getStackItemMeta2.isNextTransitioning;
37
73
  var _item$options = item.options,
38
74
  width = _item$options.width,
39
75
  closeOnOverlayClick = _item$options.closeOnOverlayClick,
40
76
  className = _item$options.className;
41
- if (config.mountStrategy === 'top-only' && !isTop && !isPrevClosing) return null;
77
+ var isEffectiveTop = isTop || isPrevClosing;
78
+ var isVisible = !(config.mountStrategy === 'top-only' && !isEffectiveTop);
79
+ var paddingValue = isEffectiveTop || isNextTransitioning || !next ? undefined : "".concat(computePadding(stack, idx), "px");
80
+ var elementProps = {
81
+ sideId: item.id,
82
+ options: item.options,
83
+ close: close,
84
+ open: open,
85
+ update: update
86
+ };
42
87
  return /*#__PURE__*/_react["default"].createElement(_react["default"].Fragment, {
43
88
  key: item.id
44
- }, /*#__PURE__*/_react["default"].createElement("div", {
89
+ }, isVisible && /*#__PURE__*/_react["default"].createElement("div", {
45
90
  className: "sidesheet-overlay",
46
91
  onClick: function onClick() {
47
92
  if (closeOnOverlayClick && item.state === 'open') {
@@ -51,20 +96,11 @@ var SideSheetContainer = exports.SideSheetContainer = function SideSheetContaine
51
96
  }), /*#__PURE__*/_react["default"].createElement("div", {
52
97
  role: "dialog",
53
98
  "aria-modal": "true",
54
- className: (0, _classnames["default"])('sidesheet', "sidesheet-animation-".concat(item.state), {
55
- 'sidesheet-left': config.side === 'left',
56
- 'sidesheet-right': config.side === 'right'
57
- }, className),
58
- style: {
59
- width: "".concat(isTop || isPrevClosing ? "".concat(width, "px") : '100%')
60
- }
61
- }, item.element({
62
- sideId: item.id,
63
- options: item.options,
64
- close: close,
65
- open: open,
66
- update: update
67
- })));
99
+ className: (0, _classnames["default"])('sidesheet', "sidesheet-animation-".concat(item.state), "sidesheet-".concat(config.side), !isVisible && 'sidesheet-invisible', className),
100
+ style: _defineProperty({
101
+ width: isEffectiveTop ? "".concat(width, "px") : '100%'
102
+ }, paddingKey, paddingValue)
103
+ }, item.element(elementProps)));
68
104
  }));
69
105
  };
70
106
  SideSheetContainer.propTypes = {
@@ -39,20 +39,29 @@ var SideSheetProvider = exports.SideSheetProvider = function SideSheetProvider(_
39
39
  stack = _useReducer2[0],
40
40
  dispatch = _useReducer2[1];
41
41
  var stackRef = (0, _react.useRef)(stack);
42
- var overflowRef = (0, _react.useRef)('');
42
+ var overflowRef = (0, _react.useRef)(null);
43
43
  var idRef = (0, _react.useRef)(0);
44
44
  (0, _react.useEffect)(function () {
45
45
  stackRef.current = stack;
46
+ if (!config.enableOverflow) {
47
+ if (!stack.length) {
48
+ if (overflowRef.current !== null) {
49
+ document.body.style.overflow = overflowRef.current;
50
+ overflowRef.current = null;
51
+ }
52
+ } else if (stack.length === 1) {
53
+ if (overflowRef.current === null) {
54
+ overflowRef.current = document.body.style.overflow;
55
+ }
56
+ document.body.style.overflow = 'hidden';
57
+ }
58
+ }
46
59
  }, [stack]);
47
60
  var open = (0, _react.useCallback)(function (element) {
48
61
  var _opts$id;
49
62
  var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
50
63
  var id = (_opts$id = opts.id) !== null && _opts$id !== void 0 ? _opts$id : ++idRef.current;
51
64
  var options = _objectSpread(_objectSpread({}, _defaultOptions.DEFAULT_SHEET_OPTIONS), opts);
52
- if (!config.enableOverflow && stackRef.current.length === 0) {
53
- overflowRef.current = document.body.style.overflow;
54
- document.body.style.overflow = 'hidden';
55
- }
56
65
  dispatch({
57
66
  type: 'OPEN',
58
67
  payload: {
@@ -135,30 +144,30 @@ var SideSheetProvider = exports.SideSheetProvider = function SideSheetProvider(_
135
144
  _iterator.f();
136
145
  return _context.finish(22);
137
146
  case 25:
138
- if (!config.enableOverflow && stackRef.current.length <= itemsToClose.length) {
139
- document.body.style.overflow = overflowRef.current;
140
- }
141
147
  duration = (_itemsToClose = itemsToClose[itemsToClose.length - 1]) === null || _itemsToClose === void 0 ? void 0 : _itemsToClose.options.animationDuration;
142
148
  dispatch({
143
149
  type: 'CLOSE',
144
150
  id: id
145
151
  });
146
- setTimeout(function () {
147
- if (id === null) {
148
- itemsToClose.forEach(function (item) {
149
- return dispatch({
152
+ return _context.abrupt("return", new Promise(function (resolve) {
153
+ setTimeout(function () {
154
+ if (id === null) {
155
+ itemsToClose.forEach(function (item) {
156
+ return dispatch({
157
+ type: 'REMOVE',
158
+ id: item.id
159
+ });
160
+ });
161
+ } else {
162
+ dispatch({
150
163
  type: 'REMOVE',
151
- id: item.id
164
+ id: id
152
165
  });
153
- });
154
- } else {
155
- dispatch({
156
- type: 'REMOVE',
157
- id: id
158
- });
159
- }
160
- }, duration);
161
- case 29:
166
+ }
167
+ resolve();
168
+ }, duration);
169
+ }));
170
+ case 28:
162
171
  case "end":
163
172
  return _context.stop();
164
173
  }
@@ -32,6 +32,7 @@ var DEFAULT_OPTIONS = exports.DEFAULT_OPTIONS = {
32
32
  }()
33
33
  };
34
34
  var DEFAULT_SHEET_OPTIONS = exports.DEFAULT_SHEET_OPTIONS = {
35
+ id: '',
35
36
  width: 400,
36
37
  className: '',
37
38
  confirmBeforeClose: false,
package/dist/index.css CHANGED
@@ -93,13 +93,18 @@
93
93
  width: 100%;
94
94
  box-shadow: 0 0 10px -5px rgba(0, 0, 0, 0.2), 0 0 24px 2px rgba(0, 0, 0, 0.14),
95
95
  0 0 30px 5px rgba(0, 0, 0, 0.12);
96
- transition: transform 0.3s ease, width 0.3s ease;
96
+ transition: transform 0.3s ease, width 0.3s ease, padding-right 0.3s ease,
97
+ padding-left 0.3s ease;
97
98
  }
98
99
 
99
100
  .sheet-white {
100
101
  background: #fff;
101
102
  }
102
103
 
104
+ .sidesheet-invisible {
105
+ display: none;
106
+ }
107
+
103
108
  .sidesheet-header .sidesheet-header-btn {
104
109
  background: transparent;
105
110
  border: none;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "react-side-sheet-pro",
3
3
  "description": "A flexible React SideSheet component for displaying contextual information.",
4
- "version": "0.1.7",
4
+ "version": "0.1.9",
5
5
  "license": "MIT",
6
6
  "keywords": [
7
7
  "react",
@@ -15,6 +15,44 @@ type SideSheetContainerProps = {
15
15
  config: Required<SideSheetOptions>;
16
16
  };
17
17
 
18
+ function getStackItemMeta(stack: SideStackItem[], idx: number) {
19
+ const prev = stack[idx - 1];
20
+ const next = stack[idx + 1];
21
+ return {
22
+ prev,
23
+ next,
24
+ isTop: idx === stack.length - 1,
25
+ isPrevClosing: prev?.state === 'closing',
26
+ isNextTransitioning: next?.state === 'closing' || next?.state === 'opening',
27
+ };
28
+ }
29
+
30
+ function computePadding(
31
+ stack: SideStackItem[],
32
+ idx: number
33
+ ): number | undefined {
34
+ const { next, isTop, isPrevClosing, isNextTransitioning } = getStackItemMeta(
35
+ stack,
36
+ idx
37
+ );
38
+
39
+ if (isTop || isPrevClosing || isNextTransitioning || !next) return undefined;
40
+
41
+ const viewportWidth = document.documentElement.clientWidth;
42
+ const maxWidth = stack[stack.length - 1]?.options.width ?? 0;
43
+
44
+ let padding = 0;
45
+ if (viewportWidth >= 1160) {
46
+ padding = Math.floor((viewportWidth - 960) / 2);
47
+ } else if (viewportWidth >= 768) {
48
+ padding = Math.floor((viewportWidth - 768) / 2);
49
+ }
50
+
51
+ padding = Math.min(padding, maxWidth);
52
+
53
+ return padding > 0 ? padding : next.options.width / 2;
54
+ }
55
+
18
56
  export const SideSheetContainer: React.FC<SideSheetContainerProps> = ({
19
57
  stack,
20
58
  open,
@@ -38,49 +76,64 @@ export const SideSheetContainer: React.FC<SideSheetContainerProps> = ({
38
76
  };
39
77
  }, [stack, close]);
40
78
 
79
+ const paddingKey = config.side === 'left' ? 'paddingLeft' : 'paddingRight';
80
+
41
81
  return (
42
82
  <>
43
83
  {stack.map((item, idx) => {
44
- const isTop = idx === stack.length - 1;
45
- const isPrevClosing = stack[idx - 1]?.state === 'closing';
84
+ const {
85
+ next,
86
+ isTop,
87
+ isPrevClosing,
88
+ isNextTransitioning,
89
+ } = getStackItemMeta(stack, idx);
46
90
  const { width, closeOnOverlayClick, className } = item.options;
47
91
 
48
- if (config.mountStrategy === 'top-only' && !isTop && !isPrevClosing)
49
- return null;
92
+ const isEffectiveTop = isTop || isPrevClosing;
93
+ const isVisible = !(
94
+ config.mountStrategy === 'top-only' && !isEffectiveTop
95
+ );
96
+ const paddingValue =
97
+ isEffectiveTop || isNextTransitioning || !next
98
+ ? undefined
99
+ : `${computePadding(stack, idx)}px`;
100
+
101
+ const elementProps = {
102
+ sideId: item.id,
103
+ options: item.options,
104
+ close,
105
+ open,
106
+ update,
107
+ };
50
108
 
51
109
  return (
52
110
  <React.Fragment key={item.id}>
53
- <div
54
- className="sidesheet-overlay"
55
- onClick={() => {
56
- if (closeOnOverlayClick && item.state === 'open') {
57
- close(item.id);
58
- }
59
- }}
60
- />
111
+ {isVisible && (
112
+ <div
113
+ className="sidesheet-overlay"
114
+ onClick={() => {
115
+ if (closeOnOverlayClick && item.state === 'open') {
116
+ close(item.id);
117
+ }
118
+ }}
119
+ />
120
+ )}
61
121
  <div
62
122
  role="dialog"
63
123
  aria-modal="true"
64
124
  className={classNames(
65
125
  'sidesheet',
66
126
  `sidesheet-animation-${item.state}`,
67
- {
68
- 'sidesheet-left': config.side === 'left',
69
- 'sidesheet-right': config.side === 'right',
70
- },
127
+ `sidesheet-${config.side}`,
128
+ !isVisible && 'sidesheet-invisible',
71
129
  className
72
130
  )}
73
131
  style={{
74
- width: `${isTop || isPrevClosing ? `${width}px` : '100%'}`,
132
+ width: isEffectiveTop ? `${width}px` : '100%',
133
+ [paddingKey]: paddingValue,
75
134
  }}
76
135
  >
77
- {item.element({
78
- sideId: item.id,
79
- options: item.options,
80
- close,
81
- open,
82
- update,
83
- })}
136
+ {item.element(elementProps)}
84
137
  </div>
85
138
  </React.Fragment>
86
139
  );
@@ -31,20 +31,30 @@ export const SideSheetProvider: React.FC<{
31
31
  }> = ({ children, configuration }) => {
32
32
  const [stack, dispatch] = useReducer(SideSheetReducer, []);
33
33
  const stackRef = useRef<SideStackItem[]>(stack);
34
- const overflowRef = useRef('');
34
+ const overflowRef = useRef<string | null>(null);
35
35
  const idRef = useRef(0);
36
36
 
37
37
  useEffect(() => {
38
38
  stackRef.current = stack;
39
+
40
+ if (!config.enableOverflow) {
41
+ if (!stack.length) {
42
+ if (overflowRef.current !== null) {
43
+ document.body.style.overflow = overflowRef.current;
44
+ overflowRef.current = null;
45
+ }
46
+ } else if (stack.length === 1) {
47
+ if (overflowRef.current === null) {
48
+ overflowRef.current = document.body.style.overflow;
49
+ }
50
+ document.body.style.overflow = 'hidden';
51
+ }
52
+ }
39
53
  }, [stack]);
40
54
 
41
55
  const open = useCallback((element: SideElement, opts: SideOptions = {}) => {
42
56
  const id = opts.id ?? ++idRef.current;
43
57
  const options = { ...DEFAULT_SHEET_OPTIONS, ...opts };
44
- if (!config.enableOverflow && stackRef.current.length === 0) {
45
- overflowRef.current = document.body.style.overflow;
46
- document.body.style.overflow = 'hidden';
47
- }
48
58
  dispatch({
49
59
  type: 'OPEN',
50
60
  payload: { id, element, options, state: 'opening' },
@@ -56,46 +66,50 @@ export const SideSheetProvider: React.FC<{
56
66
  return id;
57
67
  }, []);
58
68
 
59
- const close = useCallback(async (id: number | string | null, force = false) => {
60
- const itemsToClose =
61
- id === null
62
- ? [...stackRef.current]
63
- : stackRef.current.filter(i => i.id === id);
69
+ const close = useCallback(
70
+ async (id: number | string | null, force = false) => {
71
+ const itemsToClose =
72
+ id === null
73
+ ? [...stackRef.current]
74
+ : stackRef.current.filter(i => i.id === id);
64
75
 
65
- for (const item of itemsToClose) {
66
- if (! force && item.options.confirmBeforeClose) {
67
- const confirmCallback =
68
- item.options.confirmCallback ?? config.confirmCallback;
69
- const confirmed = await confirmCallback(
70
- item.options.confirmMessage ?? config.confirmMessage
71
- );
72
- if (!confirmed) return;
76
+ for (const item of itemsToClose) {
77
+ if (!force && item.options.confirmBeforeClose) {
78
+ const confirmCallback =
79
+ item.options.confirmCallback ?? config.confirmCallback;
80
+ const confirmed = await confirmCallback(
81
+ item.options.confirmMessage ?? config.confirmMessage
82
+ );
83
+ if (!confirmed) return;
84
+ }
85
+ item.options.onClose?.(item.id);
73
86
  }
74
- item.options.onClose?.(item.id);
75
- }
76
-
77
- if (
78
- !config.enableOverflow &&
79
- stackRef.current.length <= itemsToClose.length
80
- ) {
81
- document.body.style.overflow = overflowRef.current;
82
- }
83
87
 
84
- const duration =
85
- itemsToClose[itemsToClose.length - 1]?.options.animationDuration;
86
- dispatch({ type: 'CLOSE', id });
87
- setTimeout(() => {
88
- if (id === null) {
89
- itemsToClose.forEach(item => dispatch({ type: 'REMOVE', id: item.id }));
90
- } else {
91
- dispatch({ type: 'REMOVE', id: id! });
92
- }
93
- }, duration);
94
- }, []);
88
+ const duration =
89
+ itemsToClose[itemsToClose.length - 1]?.options.animationDuration;
90
+ dispatch({ type: 'CLOSE', id });
91
+ return new Promise<void>(resolve => {
92
+ setTimeout(() => {
93
+ if (id === null) {
94
+ itemsToClose.forEach(item =>
95
+ dispatch({ type: 'REMOVE', id: item.id })
96
+ );
97
+ } else {
98
+ dispatch({ type: 'REMOVE', id: id! });
99
+ }
100
+ resolve();
101
+ }, duration);
102
+ });
103
+ },
104
+ []
105
+ );
95
106
 
96
- const update = useCallback((id: number | string, options: Partial<SideOptions>) => {
97
- dispatch({ type: 'UPDATE', id, options });
98
- }, []);
107
+ const update = useCallback(
108
+ (id: number | string, options: Partial<SideOptions>) => {
109
+ dispatch({ type: 'UPDATE', id, options });
110
+ },
111
+ []
112
+ );
99
113
  const config = { ...DEFAULT_OPTIONS, ...configuration } as Required<
100
114
  SideSheetOptions
101
115
  >;
@@ -12,6 +12,7 @@ export const DEFAULT_OPTIONS: Required<SideSheetOptions> = {
12
12
  };
13
13
 
14
14
  export const DEFAULT_SHEET_OPTIONS: Required<SideOptions> = {
15
+ id: '',
15
16
  width: 400,
16
17
  className: '',
17
18
  confirmBeforeClose: false,
package/src/index.css CHANGED
@@ -93,13 +93,18 @@
93
93
  width: 100%;
94
94
  box-shadow: 0 0 10px -5px rgba(0, 0, 0, 0.2), 0 0 24px 2px rgba(0, 0, 0, 0.14),
95
95
  0 0 30px 5px rgba(0, 0, 0, 0.12);
96
- transition: transform 0.3s ease, width 0.3s ease;
96
+ transition: transform 0.3s ease, width 0.3s ease, padding-right 0.3s ease,
97
+ padding-left 0.3s ease;
97
98
  }
98
99
 
99
100
  .sheet-white {
100
101
  background: #fff;
101
102
  }
102
103
 
104
+ .sidesheet-invisible {
105
+ display: none;
106
+ }
107
+
103
108
  .sidesheet-header .sidesheet-header-btn {
104
109
  background: transparent;
105
110
  border: none;