@sima-land/ui-nucleons 41.1.0 → 41.2.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.
- package/_internal/body-scroll.d.ts +9 -0
- package/_internal/body-scroll.js +21 -1
- package/alert/index.js +1 -1
- package/constants.d.ts +6 -0
- package/constants.js +9 -0
- package/package.json +1 -1
- package/screen/index.d.ts +5 -11
- package/screen/index.js +11 -30
- package/screen/slots.d.ts +3 -3
- package/screen/slots.js +38 -5
- package/screen/utils.d.ts +13 -1
- package/screen/utils.js +3 -7
- package/touch-slider/index.js +2 -1
|
@@ -12,3 +12,12 @@ export interface WithBodyScrollLock {
|
|
|
12
12
|
* @param options Опции.
|
|
13
13
|
*/
|
|
14
14
|
export declare const useBodyScrollLock: (ref: React.RefObject<HTMLElement>, needDisable: boolean | undefined, options?: BodyScrollOptions | undefined) => void;
|
|
15
|
+
/**
|
|
16
|
+
* Проверяет необходимость блокировки дочерних элементов в прокручиваемом элементе.
|
|
17
|
+
* Необходима для того, чтобы в прокручиваемых контейнерах вложенные прокручиваемые элементы,
|
|
18
|
+
* имеющие специальный атрибут, прокручивались нормально.
|
|
19
|
+
* @see {@link https://github.com/willmcpo/body-scroll-lock#more-complex}
|
|
20
|
+
* @param startEl Начальный элемент.
|
|
21
|
+
* @return Нужно ли позволить перетаскивание элемента.
|
|
22
|
+
*/
|
|
23
|
+
export declare const allowTouchMove: Required<BodyScrollOptions>['allowTouchMove'];
|
package/_internal/body-scroll.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.useBodyScrollLock = void 0;
|
|
3
|
+
exports.allowTouchMove = exports.useBodyScrollLock = void 0;
|
|
4
4
|
const body_scroll_lock_1 = require("body-scroll-lock");
|
|
5
5
|
const react_1 = require("react");
|
|
6
|
+
const constants_1 = require("../constants");
|
|
6
7
|
/**
|
|
7
8
|
* Хук управления блокировкой прокрутки body.
|
|
8
9
|
* @param ref Реф элемента для которого нужно отключить прокрутку body.
|
|
@@ -19,3 +20,22 @@ const useBodyScrollLock = (ref, needDisable, options) => {
|
|
|
19
20
|
}, [needDisable, options]);
|
|
20
21
|
};
|
|
21
22
|
exports.useBodyScrollLock = useBodyScrollLock;
|
|
23
|
+
/**
|
|
24
|
+
* Проверяет необходимость блокировки дочерних элементов в прокручиваемом элементе.
|
|
25
|
+
* Необходима для того, чтобы в прокручиваемых контейнерах вложенные прокручиваемые элементы,
|
|
26
|
+
* имеющие специальный атрибут, прокручивались нормально.
|
|
27
|
+
* @see {@link https://github.com/willmcpo/body-scroll-lock#more-complex}
|
|
28
|
+
* @param startEl Начальный элемент.
|
|
29
|
+
* @return Нужно ли позволить перетаскивание элемента.
|
|
30
|
+
*/
|
|
31
|
+
const allowTouchMove = (startEl) => {
|
|
32
|
+
let el = startEl;
|
|
33
|
+
while (el && el !== document.body) {
|
|
34
|
+
if (el.getAttribute(constants_1.BSL_IGNORE_ATTR) !== null) {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
el = el.parentElement;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
};
|
|
41
|
+
exports.allowTouchMove = allowTouchMove;
|
package/alert/index.js
CHANGED
|
@@ -65,7 +65,7 @@ exports.Alert = Alert;
|
|
|
65
65
|
const AlertInner = ({ children, className, footer, navBarProps, title, withDivideNavBar, withNavBar = Boolean(title), withScrollDisable = false, scrollDisableOptions, onClose, }) => {
|
|
66
66
|
const rootRef = (0, react_1.useRef)(null);
|
|
67
67
|
const layer = (0, layer_1.useLayer)();
|
|
68
|
-
(0, body_scroll_1.useBodyScrollLock)(rootRef, withScrollDisable, scrollDisableOptions);
|
|
68
|
+
(0, body_scroll_1.useBodyScrollLock)(rootRef, withScrollDisable, Object.assign({ allowTouchMove: body_scroll_1.allowTouchMove }, scrollDisableOptions));
|
|
69
69
|
return (react_1.default.createElement("div", { ref: rootRef, className: cx('overlay'), style: { zIndex: layer }, onClick: e => e.target === e.currentTarget && (onClose === null || onClose === void 0 ? void 0 : onClose()), "data-testid": 'alert:overlay' },
|
|
70
70
|
react_1.default.createElement("div", { className: cx('alert', className), "data-testid": 'alert' },
|
|
71
71
|
withNavBar && (react_1.default.createElement(nav_bar_1.NavBar, Object.assign({}, navBarProps, { title: title, bottomBordered: withDivideNavBar, className: cx('header') }))),
|
package/constants.d.ts
ADDED
package/constants.js
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BSL_IGNORE_ATTR = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Имя атрибута, устанавливаемого на элемент, имеющий прокрутку.
|
|
6
|
+
* Атрибут устанавливается на элемент в случае, если
|
|
7
|
+
* прокручиваемый родитель элемента обрабатывается с помощью body-scroll-lock.
|
|
8
|
+
*/
|
|
9
|
+
exports.BSL_IGNORE_ATTR = 'data-bsl-ignore';
|
package/package.json
CHANGED
package/screen/index.d.ts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import {
|
|
3
|
-
export interface ScreenProps {
|
|
2
|
+
import { ScreenInnerProps } from './utils';
|
|
3
|
+
export interface ScreenProps extends ScreenInnerProps {
|
|
4
4
|
/** Содержимое. */
|
|
5
5
|
children?: React.ReactNode;
|
|
6
|
-
/** Нужно ли выводить вместо содержимого состояние загрузки. */
|
|
7
|
-
loading?: boolean;
|
|
8
6
|
/** Определяет область отображаемую как загружающуюся. */
|
|
9
7
|
loadingArea?: 'content' | 'full';
|
|
10
|
-
/** Свойства компонента LoadingOverlay. */
|
|
11
|
-
loadingOverlayProps?: LoadingOverlayProps;
|
|
12
|
-
/** Будет вызвана при полной прокрутке содержимого экрана. */
|
|
13
|
-
onFullScroll?: () => void;
|
|
14
|
-
/** Отступ от нижней границы содержимого экрана, после которого начинает срабатывать onFullScroll. */
|
|
15
|
-
fullScrollThreshold?: number;
|
|
16
8
|
/** Идентификатор для систем автоматизированного тестирования. */
|
|
17
9
|
'data-testid'?: string;
|
|
18
10
|
}
|
|
@@ -24,6 +16,8 @@ export interface ScreenProps {
|
|
|
24
16
|
export declare const Screen: {
|
|
25
17
|
({ children, loading, loadingArea, loadingOverlayProps, onFullScroll, fullScrollThreshold, "data-testid": testId, }: ScreenProps): JSX.Element;
|
|
26
18
|
Header: ({ divided, title, subtitle, buttons, onBack, onClose, ...restProps }: import("./slots").HeaderSlotProps) => JSX.Element;
|
|
27
|
-
Body: React.
|
|
19
|
+
Body: React.ForwardRefExoticComponent<{
|
|
20
|
+
children?: React.ReactNode;
|
|
21
|
+
} & React.RefAttributes<HTMLDivElement | null>>;
|
|
28
22
|
Footer: React.FC<{}>;
|
|
29
23
|
};
|
package/screen/index.js
CHANGED
|
@@ -1,35 +1,14 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
-
}) : (function(o, m, k, k2) {
|
|
6
|
-
if (k2 === undefined) k2 = k;
|
|
7
|
-
o[k2] = m[k];
|
|
8
|
-
}));
|
|
9
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
-
}) : function(o, v) {
|
|
12
|
-
o["default"] = v;
|
|
13
|
-
});
|
|
14
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
-
if (mod && mod.__esModule) return mod;
|
|
16
|
-
var result = {};
|
|
17
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
-
__setModuleDefault(result, mod);
|
|
19
|
-
return result;
|
|
20
|
-
};
|
|
21
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
22
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
23
4
|
};
|
|
24
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
6
|
exports.Screen = void 0;
|
|
26
|
-
const react_1 =
|
|
7
|
+
const react_1 = __importDefault(require("react"));
|
|
27
8
|
const slots_1 = require("./slots");
|
|
28
|
-
const loading_overlay_1 = require("../loading-overlay");
|
|
29
|
-
const body_scroll_1 = require("../_internal/body-scroll");
|
|
30
9
|
const layer_1 = require("../helpers/layer");
|
|
31
10
|
const define_slots_1 = require("../helpers/define-slots");
|
|
32
|
-
const
|
|
11
|
+
const utils_1 = require("./utils");
|
|
33
12
|
const screen_module_scss_1 = __importDefault(require("./screen.module.scss"));
|
|
34
13
|
/**
|
|
35
14
|
* Экран.
|
|
@@ -44,16 +23,18 @@ const Screen = ({ children, loading, loadingArea = 'full', loadingOverlayProps,
|
|
|
44
23
|
body: slots_1.BodySlot,
|
|
45
24
|
footer: slots_1.FooterSlot,
|
|
46
25
|
});
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const bodyRef = (0, react_1.useRef)(null);
|
|
51
|
-
(0, body_scroll_1.useBodyScrollLock)(bodyRef, true);
|
|
52
|
-
(0, hooks_1.useInfiniteScroll)(bodyRef, { onFullScroll, threshold: fullScrollThreshold });
|
|
26
|
+
if (!body) {
|
|
27
|
+
throw Error('Looks like you are trying to render <Screen /> without <Screen.Body /> slot, but it is required');
|
|
28
|
+
}
|
|
53
29
|
return (react_1.default.createElement("div", { className: screen_module_scss_1.default.root, style: { zIndex: layer }, "data-testid": testId },
|
|
54
30
|
react_1.default.createElement(layer_1.LayerProvider, { value: layer },
|
|
55
31
|
!fullLoading && header,
|
|
56
|
-
react_1.default.createElement(
|
|
32
|
+
react_1.default.createElement(utils_1.ScreenContext.Provider, { value: {
|
|
33
|
+
loading,
|
|
34
|
+
loadingOverlayProps,
|
|
35
|
+
onFullScroll,
|
|
36
|
+
fullScrollThreshold,
|
|
37
|
+
} }, body),
|
|
57
38
|
!fullLoading && footer && (react_1.default.createElement("div", { className: screen_module_scss_1.default.footer, "data-testid": 'screen:footer' }, footer)))));
|
|
58
39
|
};
|
|
59
40
|
exports.Screen = Screen;
|
package/screen/slots.d.ts
CHANGED
|
@@ -20,10 +20,10 @@ export interface HeaderSlotProps extends NavBarProps {
|
|
|
20
20
|
export declare const HeaderSlot: ({ divided, title, subtitle, buttons, onBack, onClose, ...restProps }: HeaderSlotProps) => JSX.Element;
|
|
21
21
|
/**
|
|
22
22
|
* Слот основного контента экрана.
|
|
23
|
-
* @param props Свойства.
|
|
24
|
-
* @return Элемент.
|
|
25
23
|
*/
|
|
26
|
-
export declare const BodySlot: React.
|
|
24
|
+
export declare const BodySlot: React.ForwardRefExoticComponent<{
|
|
25
|
+
children?: React.ReactNode;
|
|
26
|
+
} & React.RefAttributes<HTMLDivElement | null>>;
|
|
27
27
|
/**
|
|
28
28
|
* Слот футера экрана.
|
|
29
29
|
* @param props Свойства.
|
package/screen/slots.js
CHANGED
|
@@ -1,4 +1,23 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
|
|
5
|
+
}) : (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
o[k2] = m[k];
|
|
8
|
+
}));
|
|
9
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
10
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
11
|
+
}) : function(o, v) {
|
|
12
|
+
o["default"] = v;
|
|
13
|
+
});
|
|
14
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
15
|
+
if (mod && mod.__esModule) return mod;
|
|
16
|
+
var result = {};
|
|
17
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
18
|
+
__setModuleDefault(result, mod);
|
|
19
|
+
return result;
|
|
20
|
+
};
|
|
2
21
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
22
|
var t = {};
|
|
4
23
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -15,11 +34,16 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
15
34
|
};
|
|
16
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
36
|
exports.FooterSlot = exports.BodySlot = exports.HeaderSlot = void 0;
|
|
18
|
-
const react_1 =
|
|
37
|
+
const react_1 = __importStar(require("react"));
|
|
19
38
|
const nav_bar_1 = require("../nav-bar");
|
|
20
39
|
const lodash_1 = require("lodash");
|
|
21
40
|
const arrow_left_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/arrow-left"));
|
|
22
41
|
const cross_1 = __importDefault(require("@sima-land/ui-quarks/icons/24x24/Stroked/cross"));
|
|
42
|
+
const body_scroll_1 = require("../_internal/body-scroll");
|
|
43
|
+
const hooks_1 = require("../hooks");
|
|
44
|
+
const loading_overlay_1 = require("../loading-overlay");
|
|
45
|
+
const utils_1 = require("./utils");
|
|
46
|
+
const screen_module_scss_1 = __importDefault(require("./screen.module.scss"));
|
|
23
47
|
/**
|
|
24
48
|
* Слот шапки экрана.
|
|
25
49
|
* @param props Свойства.
|
|
@@ -50,11 +74,20 @@ const HeaderSlot = (_a) => {
|
|
|
50
74
|
exports.HeaderSlot = HeaderSlot;
|
|
51
75
|
/**
|
|
52
76
|
* Слот основного контента экрана.
|
|
53
|
-
* @param props Свойства.
|
|
54
|
-
* @return Элемент.
|
|
55
77
|
*/
|
|
56
|
-
|
|
57
|
-
|
|
78
|
+
exports.BodySlot = (0, react_1.forwardRef)(function BodySlot({ children }, outerRef) {
|
|
79
|
+
const { loading, loadingOverlayProps, onFullScroll, fullScrollThreshold } = (0, react_1.useContext)(utils_1.ScreenContext);
|
|
80
|
+
// при блокировке прокрутки нужно передавать элемент, которому нужно сохранить возможность прокрутки
|
|
81
|
+
// https://github.com/willmcpo/body-scroll-lock/blame/79c4cf2c956eb7d5cf8d54a03d12751bc6ac8aa3/README.md#L52
|
|
82
|
+
// поэтому используем внутренний ref и useImperativeHandle
|
|
83
|
+
const ref = (0, react_1.useRef)(null);
|
|
84
|
+
(0, react_1.useImperativeHandle)(outerRef, () => ref.current);
|
|
85
|
+
(0, body_scroll_1.useBodyScrollLock)(ref, true, { allowTouchMove: body_scroll_1.allowTouchMove });
|
|
86
|
+
(0, hooks_1.useInfiniteScroll)(ref, { onFullScroll, threshold: fullScrollThreshold });
|
|
87
|
+
return (
|
|
88
|
+
// ВАЖНО: элемент с ref должен выводиться всегда (без условий), т.к. он нужен для блокировки прокрутки
|
|
89
|
+
react_1.default.createElement("div", { ref: ref, className: screen_module_scss_1.default.body, "data-testid": 'screen:body' }, loading ? (react_1.default.createElement(loading_overlay_1.LoadingOverlay, Object.assign({}, loadingOverlayProps, { fill: false, style: { height: '100%' } }))) : (children)));
|
|
90
|
+
});
|
|
58
91
|
/**
|
|
59
92
|
* Слот футера экрана.
|
|
60
93
|
* @param props Свойства.
|
package/screen/utils.d.ts
CHANGED
|
@@ -1 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
import { LoadingOverlayProps } from '../loading-overlay';
|
|
3
|
+
export interface ScreenInnerProps {
|
|
4
|
+
/** Нужно ли выводить вместо содержимого состояние загрузки. */
|
|
5
|
+
loading?: boolean;
|
|
6
|
+
/** Свойства компонента LoadingOverlay. */
|
|
7
|
+
loadingOverlayProps?: LoadingOverlayProps;
|
|
8
|
+
/** Будет вызвана при полной прокрутке содержимого экрана. */
|
|
9
|
+
onFullScroll?: () => void;
|
|
10
|
+
/** Отступ от нижней границы содержимого экрана, после которого начинает срабатывать onFullScroll. */
|
|
11
|
+
fullScrollThreshold?: number;
|
|
12
|
+
}
|
|
13
|
+
export declare const ScreenContext: import("react").Context<ScreenInnerProps>;
|
package/screen/utils.js
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
exports.cx = bind_1.default.bind(screen_module_scss_1.default);
|
|
3
|
+
exports.ScreenContext = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
exports.ScreenContext = (0, react_1.createContext)({});
|
package/touch-slider/index.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.TouchSlider = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const layout_1 = require("../layout");
|
|
9
|
+
const constants_1 = require("../constants");
|
|
9
10
|
const bind_1 = __importDefault(require("classnames/bind"));
|
|
10
11
|
const touch_slider_module_scss_1 = __importDefault(require("./touch-slider.module.scss"));
|
|
11
12
|
const cx = bind_1.default.bind(touch_slider_module_scss_1.default);
|
|
@@ -15,6 +16,6 @@ const cx = bind_1.default.bind(touch_slider_module_scss_1.default);
|
|
|
15
16
|
* @return Элемент.
|
|
16
17
|
*/
|
|
17
18
|
const TouchSlider = ({ children }) => (react_1.default.createElement(layout_1.MobileLayout, null,
|
|
18
|
-
react_1.default.createElement("div", { className: cx('outer', 'invisible-scroll') },
|
|
19
|
+
react_1.default.createElement("div", Object.assign({ className: cx('outer', 'invisible-scroll') }, { [constants_1.BSL_IGNORE_ATTR]: true }),
|
|
19
20
|
react_1.default.createElement("div", { className: cx('inner') }, children))));
|
|
20
21
|
exports.TouchSlider = TouchSlider;
|