@astral/ui 4.103.2 → 4.104.1
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/components/Onboarding/ui/Overlay/Overlay.d.ts +1 -5
- package/components/Onboarding/ui/Overlay/Overlay.js +2 -5
- package/components/Onboarding/ui/Overlay/constants.d.ts +0 -1
- package/components/Onboarding/ui/Overlay/constants.js +0 -1
- package/components/Onboarding/ui/Overlay/styles.js +0 -11
- package/components/Onboarding/ui/StepStrategy/StepStrategy.js +2 -2
- package/components/Onboarding/ui/StepStrategy/useLogic/useLogic.d.ts +0 -4
- package/components/Onboarding/ui/StepStrategy/useLogic/useLogic.js +14 -5
- package/components/Onboarding/ui/hooks/useAnimatedRect/index.d.ts +1 -0
- package/components/Onboarding/ui/hooks/useAnimatedRect/index.js +1 -0
- package/components/Onboarding/ui/hooks/useAnimatedRect/useAnimatedRect.d.ts +21 -0
- package/components/Onboarding/ui/hooks/useAnimatedRect/useAnimatedRect.js +66 -0
- package/components/Onboarding/ui/hooks/useStepTransition/useStepTransition.d.ts +3 -17
- package/components/Onboarding/ui/hooks/useStepTransition/useStepTransition.js +8 -23
- package/components/Onboarding/ui/hooks/useTargetAnchor/useTargetAnchor.js +3 -6
- package/components/Onboarding/utils/geometry/rect/index.d.ts +1 -1
- package/components/Onboarding/utils/geometry/rect/index.js +1 -1
- package/components/Onboarding/utils/geometry/rect/rect.d.ts +4 -0
- package/components/Onboarding/utils/geometry/rect/rect.js +9 -0
- package/components/Onboarding/utils/scrollIntoView/scrollIntoView.d.ts +5 -6
- package/components/Onboarding/utils/scrollIntoView/scrollIntoView.js +19 -49
- package/components/Select/Select.js +1 -1
- package/components/Select/useLogic/useLogic.js +2 -2
- package/components/Select/useLogic/utils/isShowingPlaceholder/index.d.ts +1 -0
- package/components/Select/useLogic/utils/isShowingPlaceholder/index.js +1 -0
- package/components/Select/useLogic/utils/isShowingPlaceholder/isShowingPlaceholder.d.ts +1 -0
- package/components/Select/useLogic/utils/isShowingPlaceholder/isShowingPlaceholder.js +12 -0
- package/node/components/Onboarding/ui/Overlay/Overlay.d.ts +1 -5
- package/node/components/Onboarding/ui/Overlay/Overlay.js +2 -5
- package/node/components/Onboarding/ui/Overlay/constants.d.ts +0 -1
- package/node/components/Onboarding/ui/Overlay/constants.js +0 -1
- package/node/components/Onboarding/ui/Overlay/styles.js +0 -11
- package/node/components/Onboarding/ui/StepStrategy/StepStrategy.js +2 -2
- package/node/components/Onboarding/ui/StepStrategy/useLogic/useLogic.d.ts +0 -4
- package/node/components/Onboarding/ui/StepStrategy/useLogic/useLogic.js +14 -5
- package/node/components/Onboarding/ui/hooks/useAnimatedRect/index.d.ts +1 -0
- package/node/components/Onboarding/ui/hooks/useAnimatedRect/index.js +5 -0
- package/node/components/Onboarding/ui/hooks/useAnimatedRect/useAnimatedRect.d.ts +21 -0
- package/node/components/Onboarding/ui/hooks/useAnimatedRect/useAnimatedRect.js +70 -0
- package/node/components/Onboarding/ui/hooks/useStepTransition/useStepTransition.d.ts +3 -17
- package/node/components/Onboarding/ui/hooks/useStepTransition/useStepTransition.js +8 -23
- package/node/components/Onboarding/ui/hooks/useTargetAnchor/useTargetAnchor.js +3 -6
- package/node/components/Onboarding/utils/geometry/rect/index.d.ts +1 -1
- package/node/components/Onboarding/utils/geometry/rect/index.js +2 -1
- package/node/components/Onboarding/utils/geometry/rect/rect.d.ts +4 -0
- package/node/components/Onboarding/utils/geometry/rect/rect.js +11 -1
- package/node/components/Onboarding/utils/scrollIntoView/scrollIntoView.d.ts +5 -6
- package/node/components/Onboarding/utils/scrollIntoView/scrollIntoView.js +19 -49
- package/node/components/Select/Select.js +1 -1
- package/node/components/Select/useLogic/useLogic.js +2 -2
- package/node/components/Select/useLogic/utils/isShowingPlaceholder/index.d.ts +1 -0
- package/node/components/Select/useLogic/utils/isShowingPlaceholder/index.js +17 -0
- package/node/components/Select/useLogic/utils/isShowingPlaceholder/isShowingPlaceholder.d.ts +1 -0
- package/node/components/Select/useLogic/utils/isShowingPlaceholder/isShowingPlaceholder.js +16 -0
- package/package.json +1 -1
|
@@ -38,11 +38,6 @@ exports.Backdrop = styled_1.styled.path `
|
|
|
38
38
|
cursor: pointer;
|
|
39
39
|
|
|
40
40
|
fill: ${({ theme }) => theme.palette.background.modalShadow};
|
|
41
|
-
|
|
42
|
-
.${constants_2.overlayClassnames.holeMoving} & {
|
|
43
|
-
transition: d ${({ theme }) => theme.transitions.duration.standard}ms
|
|
44
|
-
${({ theme }) => theme.transitions.easing.easeInOut};
|
|
45
|
-
}
|
|
46
41
|
`;
|
|
47
42
|
/**
|
|
48
43
|
* Блокатор кликов для неинтерактивных шагов.
|
|
@@ -51,10 +46,4 @@ exports.HoleBlocker = styled_1.styled.rect `
|
|
|
51
46
|
pointer-events: auto;
|
|
52
47
|
|
|
53
48
|
fill: transparent;
|
|
54
|
-
|
|
55
|
-
.${constants_2.overlayClassnames.holeMoving} & {
|
|
56
|
-
transition-timing-function: ${({ theme }) => theme.transitions.easing.easeInOut};
|
|
57
|
-
transition-duration: ${({ theme }) => theme.transitions.duration.standard}ms;
|
|
58
|
-
transition-property: x, y, width, height, rx;
|
|
59
|
-
}
|
|
60
49
|
`;
|
|
@@ -14,8 +14,8 @@ const STEP_VIEWS = {
|
|
|
14
14
|
* Стратегия отрисовки по типу шага, единый overlay для всего тура.
|
|
15
15
|
*/
|
|
16
16
|
const StepStrategy = ({ activeStep, isClosing }) => {
|
|
17
|
-
const { geometry, shouldShowOverlay, isVisible,
|
|
17
|
+
const { geometry, shouldShowOverlay, isVisible, onOverlayClose } = (0, useLogic_1.useLogic)(activeStep, isClosing);
|
|
18
18
|
const StepView = STEP_VIEWS[activeStep.step.type];
|
|
19
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [shouldShowOverlay && ((0, jsx_runtime_1.jsx)(Overlay_1.Overlay, { hole: geometry.hole, isInteractive: activeStep.isInteractive, isVisible: isVisible,
|
|
19
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [shouldShowOverlay && ((0, jsx_runtime_1.jsx)(Overlay_1.Overlay, { hole: geometry.hole, isInteractive: activeStep.isInteractive, isVisible: isVisible, onClose: onOverlayClose })), (0, jsx_runtime_1.jsx)(StepView, { activeStep: activeStep, isClosing: isClosing, geometry: geometry })] }));
|
|
20
20
|
};
|
|
21
21
|
exports.StepStrategy = StepStrategy;
|
|
@@ -5,6 +5,7 @@ const react_1 = require("react");
|
|
|
5
5
|
const useTheme_1 = require("../../../../theme/hooks/useTheme");
|
|
6
6
|
const createVirtualAnchor_1 = require("../../../utils/createVirtualAnchor");
|
|
7
7
|
const geometry_1 = require("../../../utils/geometry");
|
|
8
|
+
const useAnimatedRect_1 = require("../../hooks/useAnimatedRect");
|
|
8
9
|
const useStepTransition_1 = require("../../hooks/useStepTransition");
|
|
9
10
|
const useTargetAnchor_1 = require("../../hooks/useTargetAnchor");
|
|
10
11
|
/**
|
|
@@ -22,12 +23,21 @@ const useLogic = (activeStep, isClosing) => {
|
|
|
22
23
|
timeout: step.waitForTimeout,
|
|
23
24
|
});
|
|
24
25
|
const padding = (0, geometry_1.parseOffset)(step.highlightOffset);
|
|
25
|
-
|
|
26
|
+
// Отступ учитываем до переезда: иначе он подставляется сразу от нового шага,
|
|
27
|
+
// и область скачком меняет размер вместо плавного.
|
|
28
|
+
const targetHole = (0, react_1.useMemo)(() => (rect ? (0, geometry_1.inflateRect)(rect, padding) : null), [rect, padding]);
|
|
29
|
+
// Переезд hole между шагами: цель шага может ехать сама (шторка, прокрутка),
|
|
30
|
+
// поэтому область анимируется здесь, а не css-переходом.
|
|
31
|
+
const hole = (0, useAnimatedRect_1.useAnimatedRect)(targetHole, {
|
|
32
|
+
stepKey: step.name,
|
|
33
|
+
durationMs: theme.transitions.duration.short,
|
|
34
|
+
// Шаг без hole: область гаснет сразу, а не едет к отсутствующей цели.
|
|
35
|
+
hasHole: isHighlight,
|
|
36
|
+
});
|
|
26
37
|
const anchorEl = (0, react_1.useMemo)(() => (hole ? (0, createVirtualAnchor_1.createVirtualAnchor)(hole) : null), [hole]);
|
|
27
|
-
const
|
|
28
|
-
// Popover скрыт пока hole
|
|
38
|
+
const isPopoverHidden = (0, useStepTransition_1.useStepTransition)(step.name, {
|
|
39
|
+
// Popover скрыт пока hole едет к новой цели.
|
|
29
40
|
popoverHiddenMs: theme.transitions.duration.short,
|
|
30
|
-
holeMovingMs: theme.transitions.duration.short,
|
|
31
41
|
hasHole: isHighlight,
|
|
32
42
|
});
|
|
33
43
|
const onOverlayClose = (0, react_1.useCallback)(() => {
|
|
@@ -48,7 +58,6 @@ const useLogic = (activeStep, isClosing) => {
|
|
|
48
58
|
},
|
|
49
59
|
shouldShowOverlay: hasShownOverlayRef.current,
|
|
50
60
|
isVisible: !isClosing,
|
|
51
|
-
isHoleMoving,
|
|
52
61
|
onOverlayClose,
|
|
53
62
|
};
|
|
54
63
|
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { useAnimatedRect } from './useAnimatedRect';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAnimatedRect = void 0;
|
|
4
|
+
var useAnimatedRect_1 = require("./useAnimatedRect");
|
|
5
|
+
Object.defineProperty(exports, "useAnimatedRect", { enumerable: true, get: function () { return useAnimatedRect_1.useAnimatedRect; } });
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Rect } from '../../../utils/geometry';
|
|
2
|
+
export type AnimatedRectOptions = {
|
|
3
|
+
/**
|
|
4
|
+
* Ключ шага: его смена запускает переезд hole на новую цель.
|
|
5
|
+
*/
|
|
6
|
+
stepKey: string;
|
|
7
|
+
/**
|
|
8
|
+
* Длительность переезда (мс).
|
|
9
|
+
*/
|
|
10
|
+
durationMs: number;
|
|
11
|
+
/**
|
|
12
|
+
* Есть ли hole в текущем шаге (highlight). У шага без hole область гаснет
|
|
13
|
+
* сразу: ехать некуда.
|
|
14
|
+
* @default true
|
|
15
|
+
*/
|
|
16
|
+
hasHole?: boolean;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* Плавный переход области hole от цели прошлого шага к цели нового.
|
|
20
|
+
*/
|
|
21
|
+
export declare const useAnimatedRect: (target: Rect | null, { stepKey, durationMs, hasHole }: AnimatedRectOptions) => Rect | null;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.useAnimatedRect = void 0;
|
|
4
|
+
const react_1 = require("react");
|
|
5
|
+
const geometry_1 = require("../../../utils/geometry");
|
|
6
|
+
/**
|
|
7
|
+
* Сглаживание переезда, аналог css-функции `ease-in-out`.
|
|
8
|
+
*/
|
|
9
|
+
const easeInOut = (progress) => progress < 0.5 ? 4 * progress ** 3 : 1 - (-2 * progress + 2) ** 3 / 2;
|
|
10
|
+
/**
|
|
11
|
+
* Плавный переход области hole от цели прошлого шага к цели нового.
|
|
12
|
+
*/
|
|
13
|
+
const useAnimatedRect = (target, { stepKey, durationMs, hasHole = true }) => {
|
|
14
|
+
const [travelRect, setTravelRect] = (0, react_1.useState)(null);
|
|
15
|
+
const fromRect = (0, react_1.useRef)(null);
|
|
16
|
+
const targetRect = (0, react_1.useRef)(target);
|
|
17
|
+
const shownRect = (0, react_1.useRef)(target);
|
|
18
|
+
const prevStepKey = (0, react_1.useRef)(stepKey);
|
|
19
|
+
const [travelId, setTravelId] = (0, react_1.useState)(0);
|
|
20
|
+
targetRect.current = target;
|
|
21
|
+
// Стартуем синхронно во время render, иначе виден кадр с hole на новой цели.
|
|
22
|
+
if (prevStepKey.current !== stepKey) {
|
|
23
|
+
prevStepKey.current = stepKey;
|
|
24
|
+
if (!hasHole) {
|
|
25
|
+
// Шаг без hole (standalone): гасим область и отменяем начатый переезд.
|
|
26
|
+
fromRect.current = null;
|
|
27
|
+
setTravelRect(null);
|
|
28
|
+
setTravelId((id) => id + 1);
|
|
29
|
+
}
|
|
30
|
+
else if (shownRect.current) {
|
|
31
|
+
// Область уже показана — едем от неё; иначе (первый hole в туре) цель
|
|
32
|
+
// показывается сразу, без переезда.
|
|
33
|
+
fromRect.current = shownRect.current;
|
|
34
|
+
setTravelRect(shownRect.current);
|
|
35
|
+
setTravelId((id) => id + 1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
(0, react_1.useEffect)(() => {
|
|
39
|
+
// Первый render (mount) — переезд не запускаем.
|
|
40
|
+
if (travelId === 0) {
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const from = fromRect.current;
|
|
44
|
+
if (!from) {
|
|
45
|
+
return;
|
|
46
|
+
}
|
|
47
|
+
let frame = 0;
|
|
48
|
+
let startTime = 0;
|
|
49
|
+
const travel = (time) => {
|
|
50
|
+
startTime = startTime || time;
|
|
51
|
+
const progress = Math.min((time - startTime) / durationMs, 1);
|
|
52
|
+
const to = targetRect.current;
|
|
53
|
+
// Цель ещё не готова (элемент не смонтирован, идёт прокрутка) — держим
|
|
54
|
+
// прежнюю область, чтобы hole не гас на время ожидания.
|
|
55
|
+
setTravelRect(to ? (0, geometry_1.interpolateRect)(from, to, easeInOut(progress)) : from);
|
|
56
|
+
if (progress < 1) {
|
|
57
|
+
frame = requestAnimationFrame(travel);
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
// Переезд закончен, дальше область ведёт трекинг цели.
|
|
61
|
+
setTravelRect(null);
|
|
62
|
+
};
|
|
63
|
+
frame = requestAnimationFrame(travel);
|
|
64
|
+
return () => cancelAnimationFrame(frame);
|
|
65
|
+
}, [travelId, durationMs]);
|
|
66
|
+
const rect = hasHole ? (travelRect ?? target) : null;
|
|
67
|
+
shownRect.current = rect;
|
|
68
|
+
return rect;
|
|
69
|
+
};
|
|
70
|
+
exports.useAnimatedRect = useAnimatedRect;
|
|
@@ -1,12 +1,8 @@
|
|
|
1
1
|
export type StepTransitionDurations = {
|
|
2
2
|
/**
|
|
3
|
-
* Время скрытия popover при смене
|
|
3
|
+
* Время скрытия popover при смене шага.
|
|
4
4
|
*/
|
|
5
5
|
popoverHiddenMs: number;
|
|
6
|
-
/**
|
|
7
|
-
* Время движения hole к новому элементу.
|
|
8
|
-
*/
|
|
9
|
-
holeMovingMs: number;
|
|
10
6
|
/**
|
|
11
7
|
* Есть ли hole в текущем шаге (highlight). Скрытие popover нужно только для
|
|
12
8
|
* переезда hole (highlight → highlight).
|
|
@@ -14,17 +10,7 @@ export type StepTransitionDurations = {
|
|
|
14
10
|
*/
|
|
15
11
|
hasHole?: boolean;
|
|
16
12
|
};
|
|
17
|
-
export type StepTransitionPhase = {
|
|
18
|
-
/**
|
|
19
|
-
* Popover скрыт, пока hole движется.
|
|
20
|
-
*/
|
|
21
|
-
isPopoverHidden: boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Идёт анимированный переезд hole.
|
|
24
|
-
*/
|
|
25
|
-
isHoleMoving: boolean;
|
|
26
|
-
};
|
|
27
13
|
/**
|
|
28
|
-
*
|
|
14
|
+
* Прячет popover на время переезда hole между highlight-шагами.
|
|
29
15
|
*/
|
|
30
|
-
export declare const useStepTransition: (stepKey: string, { popoverHiddenMs,
|
|
16
|
+
export declare const useStepTransition: (stepKey: string, { popoverHiddenMs, hasHole }: StepTransitionDurations) => boolean;
|
|
@@ -2,19 +2,11 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.useStepTransition = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
const IDLE_PHASE = {
|
|
6
|
-
isPopoverHidden: false,
|
|
7
|
-
isHoleMoving: false,
|
|
8
|
-
};
|
|
9
|
-
const HIDDEN_PHASE = {
|
|
10
|
-
isPopoverHidden: true,
|
|
11
|
-
isHoleMoving: true,
|
|
12
|
-
};
|
|
13
5
|
/**
|
|
14
|
-
*
|
|
6
|
+
* Прячет popover на время переезда hole между highlight-шагами.
|
|
15
7
|
*/
|
|
16
|
-
const useStepTransition = (stepKey, { popoverHiddenMs,
|
|
17
|
-
const [
|
|
8
|
+
const useStepTransition = (stepKey, { popoverHiddenMs, hasHole = true }) => {
|
|
9
|
+
const [isPopoverHidden, setIsPopoverHidden] = (0, react_1.useState)(false);
|
|
18
10
|
const prevKey = (0, react_1.useRef)(stepKey);
|
|
19
11
|
const prevHadHole = (0, react_1.useRef)(hasHole);
|
|
20
12
|
// Триггер для эффекта: `prevKey` мутируется во время render, поэтому в эффекте не сравнить.
|
|
@@ -25,26 +17,19 @@ const useStepTransition = (stepKey, { popoverHiddenMs, holeMovingMs, hasHole = t
|
|
|
25
17
|
const isHoleTravel = prevHadHole.current && hasHole;
|
|
26
18
|
prevKey.current = stepKey;
|
|
27
19
|
prevHadHole.current = hasHole;
|
|
20
|
+
setIsPopoverHidden(isHoleTravel);
|
|
28
21
|
if (isHoleTravel) {
|
|
29
|
-
setPhase(HIDDEN_PHASE);
|
|
30
22
|
setTransitionId((id) => id + 1);
|
|
31
23
|
}
|
|
32
|
-
else {
|
|
33
|
-
setPhase(IDLE_PHASE);
|
|
34
|
-
}
|
|
35
24
|
}
|
|
36
25
|
(0, react_1.useEffect)(() => {
|
|
37
26
|
// Первый render (mount) — переход не запускаем.
|
|
38
27
|
if (transitionId === 0) {
|
|
39
28
|
return;
|
|
40
29
|
}
|
|
41
|
-
const popoverTimer = setTimeout(() =>
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
clearTimeout(holeTimer);
|
|
46
|
-
};
|
|
47
|
-
}, [transitionId, popoverHiddenMs, holeMovingMs]);
|
|
48
|
-
return phase;
|
|
30
|
+
const popoverTimer = setTimeout(() => setIsPopoverHidden(false), popoverHiddenMs);
|
|
31
|
+
return () => clearTimeout(popoverTimer);
|
|
32
|
+
}, [transitionId, popoverHiddenMs]);
|
|
33
|
+
return isPopoverHidden;
|
|
49
34
|
};
|
|
50
35
|
exports.useStepTransition = useStepTransition;
|
|
@@ -24,17 +24,14 @@ const useTargetAnchor = (targetName, { onError, shouldTrack = true, scrollOnEnte
|
|
|
24
24
|
// Устанавливаем найденный элемент сразу, без задержки.
|
|
25
25
|
setElement((0, getTargetElement_1.getTargetElement)(targetName));
|
|
26
26
|
(0, waitForElement_1.waitForElement)(targetName, { timeout })
|
|
27
|
-
.then(
|
|
27
|
+
.then((target) => {
|
|
28
28
|
if (isCancelled) {
|
|
29
29
|
return;
|
|
30
30
|
}
|
|
31
|
+
setElement(target);
|
|
31
32
|
if (scrollOnEnter) {
|
|
32
|
-
|
|
33
|
+
(0, scrollIntoView_1.scrollIntoView)(target);
|
|
33
34
|
}
|
|
34
|
-
if (isCancelled) {
|
|
35
|
-
return;
|
|
36
|
-
}
|
|
37
|
-
setElement(target);
|
|
38
35
|
stopRemovalWatch = (0, observeRemoval_1.observeRemoval)(target, () => {
|
|
39
36
|
if (!isCancelled) {
|
|
40
37
|
setElement(null);
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { clampToScrollParents, clampToViewport, inflateRect, isSameRect, rectFromDomRect, } from './rect';
|
|
1
|
+
export { clampToScrollParents, clampToViewport, inflateRect, interpolateRect, isSameRect, rectFromDomRect, } from './rect';
|
|
2
2
|
export type { Rect } from './rect';
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.rectFromDomRect = exports.isSameRect = exports.inflateRect = exports.clampToViewport = exports.clampToScrollParents = void 0;
|
|
3
|
+
exports.rectFromDomRect = exports.isSameRect = exports.interpolateRect = exports.inflateRect = exports.clampToViewport = exports.clampToScrollParents = void 0;
|
|
4
4
|
var rect_1 = require("./rect");
|
|
5
5
|
Object.defineProperty(exports, "clampToScrollParents", { enumerable: true, get: function () { return rect_1.clampToScrollParents; } });
|
|
6
6
|
Object.defineProperty(exports, "clampToViewport", { enumerable: true, get: function () { return rect_1.clampToViewport; } });
|
|
7
7
|
Object.defineProperty(exports, "inflateRect", { enumerable: true, get: function () { return rect_1.inflateRect; } });
|
|
8
|
+
Object.defineProperty(exports, "interpolateRect", { enumerable: true, get: function () { return rect_1.interpolateRect; } });
|
|
8
9
|
Object.defineProperty(exports, "isSameRect", { enumerable: true, get: function () { return rect_1.isSameRect; } });
|
|
9
10
|
Object.defineProperty(exports, "rectFromDomRect", { enumerable: true, get: function () { return rect_1.rectFromDomRect; } });
|
|
@@ -20,6 +20,10 @@ export declare const isSameRect: (a: Rect | null, b: Rect) => boolean;
|
|
|
20
20
|
* Расширяет область на padding во все стороны.
|
|
21
21
|
*/
|
|
22
22
|
export declare const inflateRect: (rect: Rect, padding: number) => Rect;
|
|
23
|
+
/**
|
|
24
|
+
* Область между `from` и `to` по доле переезда `progress` (0..1).
|
|
25
|
+
*/
|
|
26
|
+
export declare const interpolateRect: (from: Rect, to: Rect, progress: number) => Rect;
|
|
23
27
|
/**
|
|
24
28
|
* Обрезает область hole по границам viewport.
|
|
25
29
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.clampToScrollParents = exports.isViewportSizedRect = exports.clampToViewport = exports.inflateRect = exports.isSameRect = exports.rectFromDomRect = void 0;
|
|
3
|
+
exports.clampToScrollParents = exports.isViewportSizedRect = exports.clampToViewport = exports.interpolateRect = exports.inflateRect = exports.isSameRect = exports.rectFromDomRect = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* Приводит нативный `DOMRect` к нашему `Rect` (только позиция и размеры).
|
|
6
6
|
*/
|
|
@@ -30,6 +30,16 @@ const inflateRect = (rect, padding) => ({
|
|
|
30
30
|
height: rect.height + padding * 2,
|
|
31
31
|
});
|
|
32
32
|
exports.inflateRect = inflateRect;
|
|
33
|
+
/**
|
|
34
|
+
* Область между `from` и `to` по доле переезда `progress` (0..1).
|
|
35
|
+
*/
|
|
36
|
+
const interpolateRect = (from, to, progress) => ({
|
|
37
|
+
x: from.x + (to.x - from.x) * progress,
|
|
38
|
+
y: from.y + (to.y - from.y) * progress,
|
|
39
|
+
width: from.width + (to.width - from.width) * progress,
|
|
40
|
+
height: from.height + (to.height - from.height) * progress,
|
|
41
|
+
});
|
|
42
|
+
exports.interpolateRect = interpolateRect;
|
|
33
43
|
/**
|
|
34
44
|
* Пересечение двух областей. Не пересекаются — ширина/высота 0.
|
|
35
45
|
*/
|
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Доводит элемент highlight-шага до центра viewport
|
|
3
|
-
* реально доедет.
|
|
2
|
+
* Доводит элемент highlight-шага до центра viewport.
|
|
4
3
|
*
|
|
5
4
|
* Зачем: цель может быть за пределами экрана или внутри прокрученного
|
|
6
5
|
* контейнера — её надо показать, прежде чем подсвечивать. Нативный
|
|
7
6
|
* `scrollIntoView` сам прокручивает всю цепочку вложенных scroll-контейнеров.
|
|
8
7
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
8
|
+
* Окончания прокрутки не ждём: hole и popover привязаны к элементу, а
|
|
9
|
+
* `useTrackedRect` ведёт их за ним покадрово — к финальной позиции они приедут
|
|
10
|
+
* вместе с ним.
|
|
12
11
|
*/
|
|
13
|
-
export declare const scrollIntoView: (element: HTMLElement, behavior?: ScrollBehavior) =>
|
|
12
|
+
export declare const scrollIntoView: (element: HTMLElement, behavior?: ScrollBehavior) => void;
|
|
@@ -5,51 +5,23 @@ const constants_1 = require("../../constants");
|
|
|
5
5
|
const geometry_1 = require("../geometry");
|
|
6
6
|
const getScrollParents_1 = require("../getScrollParents");
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
8
|
+
* Позиционирование, при котором элемент не двигается прокруткой страницы.
|
|
9
9
|
*/
|
|
10
|
-
const
|
|
10
|
+
const PINNED_POSITIONS = ['fixed', 'sticky'];
|
|
11
11
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
12
|
+
* Элемент закреплён на экране: лежит внутри шторки, модалки или липкой шапки.
|
|
13
|
+
* Прокрутка такой элемент не подвинет, звать её незачем.
|
|
14
14
|
*/
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
* Поэтому отслеживаем позицию элемента покадрово и считаем прокрутку
|
|
21
|
-
* законченной, когда `top` перестаёт меняться 3 кадра
|
|
22
|
-
* подряд — либо когда срабатывает предохранитель 1000мс.
|
|
23
|
-
*/
|
|
24
|
-
const waitForScrollSettle = (element) => new Promise((resolve) => {
|
|
25
|
-
let raf = 0;
|
|
26
|
-
let stableFrames = 0;
|
|
27
|
-
let prevTop = Number.NaN;
|
|
28
|
-
const timer = setTimeout(() => {
|
|
29
|
-
cancelAnimationFrame(raf);
|
|
30
|
-
resolve();
|
|
31
|
-
}, SETTLE_TIMEOUT_MS);
|
|
32
|
-
const tick = () => {
|
|
33
|
-
const { top } = element.getBoundingClientRect();
|
|
34
|
-
// Позиция не изменилась за кадр — копим «стабильные» кадры; дёрнулась —
|
|
35
|
-
// сбрасываем счётчик и запоминаем новую позицию.
|
|
36
|
-
if (top === prevTop) {
|
|
37
|
-
stableFrames += 1;
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
stableFrames = 0;
|
|
41
|
-
prevTop = top;
|
|
15
|
+
const checkIsPinned = (element) => {
|
|
16
|
+
let node = element;
|
|
17
|
+
while (node) {
|
|
18
|
+
if (PINNED_POSITIONS.includes(getComputedStyle(node).position)) {
|
|
19
|
+
return true;
|
|
42
20
|
}
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
return;
|
|
48
|
-
}
|
|
49
|
-
raf = requestAnimationFrame(tick);
|
|
50
|
-
};
|
|
51
|
-
raf = requestAnimationFrame(tick);
|
|
52
|
-
});
|
|
21
|
+
node = node.parentElement;
|
|
22
|
+
}
|
|
23
|
+
return false;
|
|
24
|
+
};
|
|
53
25
|
/**
|
|
54
26
|
* Элемент целиком видим: помещается и во viewport, и в рамки каждого своего
|
|
55
27
|
* scroll-предка.
|
|
@@ -68,22 +40,20 @@ const isFullyVisible = (element) => {
|
|
|
68
40
|
rect.right <= frame.right);
|
|
69
41
|
};
|
|
70
42
|
/**
|
|
71
|
-
* Доводит элемент highlight-шага до центра viewport
|
|
72
|
-
* реально доедет.
|
|
43
|
+
* Доводит элемент highlight-шага до центра viewport.
|
|
73
44
|
*
|
|
74
45
|
* Зачем: цель может быть за пределами экрана или внутри прокрученного
|
|
75
46
|
* контейнера — её надо показать, прежде чем подсвечивать. Нативный
|
|
76
47
|
* `scrollIntoView` сам прокручивает всю цепочку вложенных scroll-контейнеров.
|
|
77
48
|
*
|
|
78
|
-
*
|
|
79
|
-
*
|
|
80
|
-
*
|
|
49
|
+
* Окончания прокрутки не ждём: hole и popover привязаны к элементу, а
|
|
50
|
+
* `useTrackedRect` ведёт их за ним покадрово — к финальной позиции они приедут
|
|
51
|
+
* вместе с ним.
|
|
81
52
|
*/
|
|
82
|
-
const scrollIntoView =
|
|
83
|
-
if (isFullyVisible(element)) {
|
|
53
|
+
const scrollIntoView = (element, behavior = constants_1.SCROLL_BEHAVIOR) => {
|
|
54
|
+
if (checkIsPinned(element) || isFullyVisible(element)) {
|
|
84
55
|
return;
|
|
85
56
|
}
|
|
86
57
|
element.scrollIntoView({ behavior, block: 'center', inline: 'center' });
|
|
87
|
-
await waitForScrollSettle(element);
|
|
88
58
|
};
|
|
89
59
|
exports.scrollIntoView = scrollIntoView;
|
|
@@ -53,6 +53,6 @@ const SelectInner = ({ required, getOptionLabel, placeholder, helperText, hideHe
|
|
|
53
53
|
}
|
|
54
54
|
return findMenuItemsLabel(children, selectedOptions);
|
|
55
55
|
};
|
|
56
|
-
return ((0, jsx_runtime_1.jsxs)(FormControl_1.default, { error: error, fullWidth: fullWidth, children: [label && ((0, jsx_runtime_1.jsx)(InputLabel_1.default, { htmlFor: "grouped-select", required: required, disabled: disabled, children: label })), (0, jsx_runtime_1.jsxs)(styles_1.StyledSelect, { ...props, value: value === null ? '' : value, open: isOpened, disabled: disabled, onOpen: openSelect, onClose: closeSelect, renderValue: renderValue, IconComponent: () => null, displayEmpty: true, ref: ref, fullWidth: fullWidth, onChange: handleChangeOption, "$isShowingPlaceholder": isShowingPlaceholder, endAdornment: (0, jsx_runtime_1.jsxs)(styles_1.EndAdornmentWrapper, { children: [loading && (0, jsx_runtime_1.jsx)(Loader_1.Loader, { color: "primary", size: "small" }), !loading && isShowingClearButton && ((0, jsx_runtime_1.jsx)(ClearButton, { disabled: disabled, ref: resetButtonRef, onClick: onClearAll })), !loading && ((0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", disabled: disabled, onClick: openSelect, children: !isOpened ? (0, jsx_runtime_1.jsx)(DownOutlineMd_1.DownOutlineMd, {}) : (0, jsx_runtime_1.jsx)(UpOutlineMd_1.UpOutlineMd, {}) }))] }), children: [(0, jsx_runtime_1.jsx)(styles_1.Placeholder, { value: "", children: placeholder }), !loading && isShowingSelectAll && ((0, jsx_runtime_1.jsxs)(MenuItem_1.MenuItem, { className: selectAllClassName, selected: isSelectedAll, value: constants_1.SELECT_ALL_VALUE, children: [(0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: isSelectedAll, indeterminate: isIndeterminate }) }), "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0435"] })), !loading && children, !loading && isNoData && (0, jsx_runtime_1.jsx)(styles_1.StateWrapper, { children: "\u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445" })] }), (0, jsx_runtime_1.jsx)(FormHelperText_1.FormHelperText, { error: error, success: success, hideHelperText: hideHelperText, children: helperText })] }));
|
|
56
|
+
return ((0, jsx_runtime_1.jsxs)(FormControl_1.default, { error: error, fullWidth: fullWidth, children: [label && ((0, jsx_runtime_1.jsx)(InputLabel_1.default, { htmlFor: "grouped-select", required: required, disabled: disabled, children: label })), (0, jsx_runtime_1.jsxs)(styles_1.StyledSelect, { ...props, value: value === null || value === undefined ? '' : value, open: isOpened, disabled: disabled, onOpen: openSelect, onClose: closeSelect, renderValue: renderValue, IconComponent: () => null, displayEmpty: true, ref: ref, fullWidth: fullWidth, onChange: handleChangeOption, "$isShowingPlaceholder": isShowingPlaceholder, endAdornment: (0, jsx_runtime_1.jsxs)(styles_1.EndAdornmentWrapper, { children: [loading && (0, jsx_runtime_1.jsx)(Loader_1.Loader, { color: "primary", size: "small" }), !loading && isShowingClearButton && ((0, jsx_runtime_1.jsx)(ClearButton, { disabled: disabled, ref: resetButtonRef, onClick: onClearAll })), !loading && ((0, jsx_runtime_1.jsx)(IconButton_1.IconButton, { variant: "text", disabled: disabled, onClick: openSelect, children: !isOpened ? (0, jsx_runtime_1.jsx)(DownOutlineMd_1.DownOutlineMd, {}) : (0, jsx_runtime_1.jsx)(UpOutlineMd_1.UpOutlineMd, {}) }))] }), children: [(0, jsx_runtime_1.jsx)(styles_1.Placeholder, { value: "", children: placeholder }), !loading && isShowingSelectAll && ((0, jsx_runtime_1.jsxs)(MenuItem_1.MenuItem, { className: selectAllClassName, selected: isSelectedAll, value: constants_1.SELECT_ALL_VALUE, children: [(0, jsx_runtime_1.jsx)(ListItemIcon_1.default, { children: (0, jsx_runtime_1.jsx)(Checkbox_1.Checkbox, { checked: isSelectedAll, indeterminate: isIndeterminate }) }), "\u0412\u044B\u0431\u0440\u0430\u0442\u044C \u0432\u0441\u0435"] })), !loading && children, !loading && isNoData && (0, jsx_runtime_1.jsx)(styles_1.StateWrapper, { children: "\u041D\u0435\u0442 \u0434\u0430\u043D\u043D\u044B\u0445" })] }), (0, jsx_runtime_1.jsx)(FormHelperText_1.FormHelperText, { error: error, success: success, hideHelperText: hideHelperText, children: helperText })] }));
|
|
57
57
|
};
|
|
58
58
|
exports.Select = (0, forwardRefWithGeneric_1.forwardRefWithGeneric)(SelectInner);
|
|
@@ -7,6 +7,7 @@ const MenuItem_2 = require("../../MenuItem");
|
|
|
7
7
|
const getNodeText_1 = require("../../utils/getNodeText");
|
|
8
8
|
const isSyncReactElement_1 = require("../../utils/isSyncReactElement");
|
|
9
9
|
const constants_1 = require("../constants");
|
|
10
|
+
const isShowingPlaceholder_1 = require("./utils/isShowingPlaceholder");
|
|
10
11
|
const useLogic = ({ value, onChange, children, open: externalIsOpened, defaultOpen, multiple, isEnableAllSelection, isShowClearButton = true, valueOptions, onSelectAll, onUnselectAll, name, placeholder, onClose, onOpen, loading, }) => {
|
|
11
12
|
const [isOpened, setOpened] = (0, react_1.useState)(!loading && (defaultOpen || externalIsOpened || false));
|
|
12
13
|
const resetButtonRef = (0, react_1.useRef)(null);
|
|
@@ -114,7 +115,6 @@ const useLogic = ({ value, onChange, children, open: externalIsOpened, defaultOp
|
|
|
114
115
|
}
|
|
115
116
|
return null;
|
|
116
117
|
};
|
|
117
|
-
const isShowingPlaceholder = Boolean((value === '' || Array.isArray(value)) && !!placeholder);
|
|
118
118
|
return {
|
|
119
119
|
isOpened,
|
|
120
120
|
isNoData,
|
|
@@ -131,7 +131,7 @@ const useLogic = ({ value, onChange, children, open: externalIsOpened, defaultOp
|
|
|
131
131
|
handleChangeArrayValue,
|
|
132
132
|
selectAllClassName,
|
|
133
133
|
findMenuItemsLabel,
|
|
134
|
-
isShowingPlaceholder,
|
|
134
|
+
isShowingPlaceholder: (0, isShowingPlaceholder_1.isShowingPlaceholder)(value, placeholder),
|
|
135
135
|
};
|
|
136
136
|
};
|
|
137
137
|
exports.useLogic = useLogic;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './isShowingPlaceholder';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./isShowingPlaceholder"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const isShowingPlaceholder: (value: unknown, placeholder?: string) => boolean;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isShowingPlaceholder = void 0;
|
|
4
|
+
const isShowingPlaceholder = (value, placeholder) => {
|
|
5
|
+
if (!placeholder) {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
if (value === null || value === undefined || value === '') {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
12
|
+
return true;
|
|
13
|
+
}
|
|
14
|
+
return false;
|
|
15
|
+
};
|
|
16
|
+
exports.isShowingPlaceholder = isShowingPlaceholder;
|