@hh.ru/magritte-ui-nav-bar 1.3.23 → 1.3.25
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/index.css +109 -120
- package/index.js +3 -1
- package/index.js.map +1 -1
- package/internal/NavBarContext.d.ts +4 -0
- package/internal/NavBarContext.js +8 -0
- package/internal/NavBarContext.js.map +1 -0
- package/internal/PaneStore.js +1 -15
- package/internal/PaneStore.js.map +1 -1
- package/nav-bar-DEFIZlLr.js +5 -0
- package/nav-bar-DEFIZlLr.js.map +1 -0
- package/package.json +3 -3
- package/public/Actions.js +10 -16
- package/public/Actions.js.map +1 -1
- package/public/LayoutMorph.js +2 -11
- package/public/LayoutMorph.js.map +1 -1
- package/public/LayoutStage.js +2 -11
- package/public/LayoutStage.js.map +1 -1
- package/public/Morph.js +2 -11
- package/public/Morph.js.map +1 -1
- package/public/NavBar.d.ts +4 -8
- package/public/NavBar.js +127 -17
- package/public/NavBar.js.map +1 -1
- package/public/Pane.d.ts +2 -1
- package/public/Pane.js +5 -12
- package/public/Pane.js.map +1 -1
- package/public/Stage.js +2 -11
- package/public/Stage.js.map +1 -1
- package/public/TitleContainer.js +2 -11
- package/public/TitleContainer.js.map +1 -1
- package/NavBar-BuZTE3xq.js +0 -116
- package/NavBar-BuZTE3xq.js.map +0 -1
package/public/Actions.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import './../index.css';
|
|
2
2
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
-
import { isValidElement, Fragment
|
|
3
|
+
import { Children, isValidElement, Fragment } from 'react';
|
|
4
4
|
import classNames from 'classnames';
|
|
5
5
|
import { isIconElement } from '@hh.ru/magritte-ui-icon';
|
|
6
6
|
import { EnvironmentFingerprintNode } from './EnvironmentFingerprintNode.js';
|
|
7
7
|
import { Morph } from './Morph.js';
|
|
8
8
|
import { useAnimationStage } from './Stage.js';
|
|
9
|
-
import { s as styles } from '../
|
|
9
|
+
import { s as styles } from '../nav-bar-DEFIZlLr.js';
|
|
10
10
|
import '../internal/MetricsProvider.js';
|
|
11
11
|
import '../internal/utils.js';
|
|
12
12
|
import 'motion';
|
|
@@ -14,24 +14,18 @@ import 'motion/react';
|
|
|
14
14
|
import '../internal/MorphStore.js';
|
|
15
15
|
import '../internal/KeyedSubscriptions.js';
|
|
16
16
|
import '../internal/PaneStore.js';
|
|
17
|
+
import '../internal/NavBarContext.js';
|
|
17
18
|
import '../internal/useInert.js';
|
|
18
|
-
import '@hh.ru/magritte-ui-divider';
|
|
19
|
-
import '@hh.ru/magritte-ui-layer';
|
|
20
|
-
import '../internal/useAnimationRanges.js';
|
|
21
|
-
import '../internal/useBindScrollToAnimationProgress.js';
|
|
22
|
-
import '../internal/useNavBarMetrics.js';
|
|
23
|
-
import '../internal/useResetFocus.js';
|
|
24
|
-
import '../internal/useScrollAdapter.js';
|
|
25
|
-
import '@hh.ru/magritte-internal-custom-scroll';
|
|
26
|
-
import '../internal/useSnapScroll.js';
|
|
27
|
-
import '../internal/useSyncMotionValue.js';
|
|
28
19
|
|
|
20
|
+
const isFragmentElement = (node) => isValidElement(node) && node.type === Fragment;
|
|
29
21
|
const wrapToMorph = (node, isRight) => {
|
|
30
|
-
const arr =
|
|
31
|
-
? Children.toArray(node.props.children)
|
|
32
|
-
: Children.toArray(node);
|
|
22
|
+
const arr = isFragmentElement(node) ? Children.toArray(node.props.children) : Children.toArray(node);
|
|
33
23
|
return arr.map((node, index) => (jsx(Morph, { className: isIconElement(node) ? styles.actionsIconMorph : '', id: `actions-component-${isRight ? 'right' : 'left'}-slot-item-${isRight ? arr.length - index : index}`, children: node }, index)));
|
|
34
24
|
};
|
|
25
|
+
const wrapToDiv = (node) => {
|
|
26
|
+
const arr = isFragmentElement(node) ? Children.toArray(node.props.children) : Children.toArray(node);
|
|
27
|
+
return arr.map((node, index) => (jsx("div", { className: isIconElement(node) ? styles.actionsIconMorph : '', children: node }, index)));
|
|
28
|
+
};
|
|
35
29
|
const Actions = ({ children, left, right, centered = false, autoMorph = true, }) => {
|
|
36
30
|
const stage = useAnimationStage();
|
|
37
31
|
return (jsxs("div", { className: classNames(styles.actionsContainer, {
|
|
@@ -39,7 +33,7 @@ const Actions = ({ children, left, right, centered = false, autoMorph = true, })
|
|
|
39
33
|
[styles.actionsEndStage]: stage === 'end',
|
|
40
34
|
[styles.actionsOnlyStage]: stage === 'only',
|
|
41
35
|
[styles.actionsNoChildren]: !children,
|
|
42
|
-
}), children: [(!!left || (!!right && centered)) && (jsxs("div", { className: styles.actionsLeftSlot, children: [!!left && (jsx(EnvironmentFingerprintNode, { className: styles.actionsSideSlotContent, children: autoMorph && stage !== 'only' ? wrapToMorph(left, false) : left })), centered && !!right && (jsx("div", { className: styles.actionsSideSlotContentClone, "aria-hidden": "true", "data-qa": "actions-duplicate-container", inert: 'true', children: right }))] })), (!!children || !left || !right) && (jsx("div", { className: classNames(styles.actionsCenterSlot, { [styles.actionsCenterSlotCentered]: centered }), children: children })), (!!right || (!!left && centered)) && (jsxs("div", { className: styles.actionsRightSlot, children: [!!right && (jsx(EnvironmentFingerprintNode, { className: styles.actionsSideSlotContent, children: autoMorph && stage !== 'only' ? wrapToMorph(right, true) : right })), centered && !!left && (jsx("div", { className: styles.actionsSideSlotContentClone, "aria-hidden": "true", "data-qa": "actions-duplicate-container", inert: 'true', children: left }))] }))] }));
|
|
36
|
+
}), children: [(!!left || (!!right && centered)) && (jsxs("div", { className: styles.actionsLeftSlot, children: [!!left && (jsx(EnvironmentFingerprintNode, { className: styles.actionsSideSlotContent, children: autoMorph && stage !== 'only' ? wrapToMorph(left, false) : wrapToDiv(left) })), centered && !!right && (jsx("div", { className: styles.actionsSideSlotContentClone, "aria-hidden": "true", "data-qa": "actions-duplicate-container", inert: 'true', children: wrapToDiv(right) }))] })), (!!children || !left || !right) && (jsx("div", { className: classNames(styles.actionsCenterSlot, { [styles.actionsCenterSlotCentered]: centered }), children: children })), (!!right || (!!left && centered)) && (jsxs("div", { className: styles.actionsRightSlot, children: [!!right && (jsx(EnvironmentFingerprintNode, { className: styles.actionsSideSlotContent, children: autoMorph && stage !== 'only' ? wrapToMorph(right, true) : wrapToDiv(right) })), centered && !!left && (jsx("div", { className: styles.actionsSideSlotContentClone, "aria-hidden": "true", "data-qa": "actions-duplicate-container", inert: 'true', children: wrapToDiv(left) }))] }))] }));
|
|
43
37
|
};
|
|
44
38
|
|
|
45
39
|
export { Actions };
|
package/public/Actions.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Actions.js","sources":["src/public/Actions.tsx"],"sourcesContent":["import {\n Children,\n Fragment,\n isValidElement,\n type JSXElementConstructor,\n type PropsWithChildren,\n type ReactElement,\n type FC,\n type ReactNode,\n} from 'react';\nimport classNames from 'classnames';\n\nimport { isIconElement } from '@hh.ru/magritte-ui-icon';\nimport { EnvironmentFingerprintNode } from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\nimport { Morph } from '@hh.ru/magritte-ui-nav-bar/public/Morph';\nimport { useAnimationStage } from '@hh.ru/magritte-ui-nav-bar/public/Stage';\n\nimport styles from './nav-bar.less';\n\nexport interface ActionsProps {\n /**\n * Контент левого слота\n */\n left?: ReactNode | ReactNode[];\n /**\n * Контент правого слота\n */\n right?: ReactNode | ReactNode[];\n /**\n * Контент центрального слота\n */\n children?: ReactNode;\n /**\n * Включает центрирование контента центрального слота относительно всего компонента.\n */\n centered?: boolean;\n /**\n * Управляет автоматическим оборачиванием всего контента в компоненты <Morph />.\n * По умолчанию включен, но может быть отключен если требуется более сложное описание анимации\n * чем используется по умолчанию.\n */\n autoMorph?: boolean;\n}\n\nconst wrapToMorph = (node: ReactNode | ReactNode[], isRight: boolean) => {\n const arr
|
|
1
|
+
{"version":3,"file":"Actions.js","sources":["src/public/Actions.tsx"],"sourcesContent":["import {\n Children,\n Fragment,\n isValidElement,\n type JSXElementConstructor,\n type PropsWithChildren,\n type ReactElement,\n type FC,\n type ReactNode,\n} from 'react';\nimport classNames from 'classnames';\n\nimport { isIconElement } from '@hh.ru/magritte-ui-icon';\nimport { EnvironmentFingerprintNode } from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\nimport { Morph } from '@hh.ru/magritte-ui-nav-bar/public/Morph';\nimport { useAnimationStage } from '@hh.ru/magritte-ui-nav-bar/public/Stage';\n\nimport styles from './nav-bar.less';\n\nexport interface ActionsProps {\n /**\n * Контент левого слота\n */\n left?: ReactNode | ReactNode[];\n /**\n * Контент правого слота\n */\n right?: ReactNode | ReactNode[];\n /**\n * Контент центрального слота\n */\n children?: ReactNode;\n /**\n * Включает центрирование контента центрального слота относительно всего компонента.\n */\n centered?: boolean;\n /**\n * Управляет автоматическим оборачиванием всего контента в компоненты <Morph />.\n * По умолчанию включен, но может быть отключен если требуется более сложное описание анимации\n * чем используется по умолчанию.\n */\n autoMorph?: boolean;\n}\n\nconst isFragmentElement = (\n node: ReactNode\n): node is ReactElement<PropsWithChildren, JSXElementConstructor<PropsWithChildren>> =>\n isValidElement(node) && node.type === Fragment;\n\nconst wrapToMorph = (node: ReactNode | ReactNode[], isRight: boolean) => {\n const arr = isFragmentElement(node) ? Children.toArray(node.props.children) : Children.toArray(node);\n\n return arr.map((node, index) => (\n <Morph\n className={isIconElement(node) ? styles.actionsIconMorph : ''}\n id={`actions-component-${isRight ? 'right' : 'left'}-slot-item-${isRight ? arr.length - index : index}`}\n key={index}\n >\n {node}\n </Morph>\n ));\n};\n\nconst wrapToDiv = (node: ReactNode | ReactNode[]) => {\n const arr = isFragmentElement(node) ? Children.toArray(node.props.children) : Children.toArray(node);\n\n return arr.map((node, index) => (\n <div className={isIconElement(node) ? styles.actionsIconMorph : ''} key={index}>\n {node}\n </div>\n ));\n};\n\nexport const Actions: FC<PropsWithChildren<ActionsProps>> = ({\n children,\n left,\n right,\n centered = false,\n autoMorph = true,\n}) => {\n const stage = useAnimationStage();\n return (\n <div\n className={classNames(styles.actionsContainer, {\n [styles.actionsStartStage]: stage === 'start',\n [styles.actionsEndStage]: stage === 'end',\n [styles.actionsOnlyStage]: stage === 'only',\n [styles.actionsNoChildren]: !children,\n })}\n >\n {(!!left || (!!right && centered)) && (\n <div className={styles.actionsLeftSlot}>\n {!!left && (\n <EnvironmentFingerprintNode className={styles.actionsSideSlotContent}>\n {autoMorph && stage !== 'only' ? wrapToMorph(left, false) : wrapToDiv(left)}\n </EnvironmentFingerprintNode>\n )}\n {centered && !!right && (\n <div\n className={styles.actionsSideSlotContentClone}\n aria-hidden=\"true\"\n data-qa=\"actions-duplicate-container\"\n // атрибут не завезли в типы react 18, только с 19го\n {...{ inert: 'true' }}\n >\n {wrapToDiv(right)}\n </div>\n )}\n </div>\n )}\n\n {(!!children || !left || !right) && (\n <div className={classNames(styles.actionsCenterSlot, { [styles.actionsCenterSlotCentered]: centered })}>\n {children}\n </div>\n )}\n\n {(!!right || (!!left && centered)) && (\n <div className={styles.actionsRightSlot}>\n {!!right && (\n <EnvironmentFingerprintNode className={styles.actionsSideSlotContent}>\n {autoMorph && stage !== 'only' ? wrapToMorph(right, true) : wrapToDiv(right)}\n </EnvironmentFingerprintNode>\n )}\n {centered && !!left && (\n <div\n className={styles.actionsSideSlotContentClone}\n aria-hidden=\"true\"\n data-qa=\"actions-duplicate-container\"\n {...{ inert: 'true' }}\n >\n {wrapToDiv(left)}\n </div>\n )}\n </div>\n )}\n </div>\n );\n};\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
package/public/LayoutMorph.js
CHANGED
|
@@ -10,21 +10,12 @@ import { usePaneStore } from '../internal/PaneStore.js';
|
|
|
10
10
|
import { useInert } from '../internal/useInert.js';
|
|
11
11
|
import { useActualRef, useStoreSyncedTransform, lerp, calcMorphParams } from '../internal/utils.js';
|
|
12
12
|
import { AnimationStageContext } from './LayoutStage.js';
|
|
13
|
-
import { s as styles } from '../
|
|
13
|
+
import { s as styles } from '../nav-bar-DEFIZlLr.js';
|
|
14
14
|
import '../internal/KeyedSubscriptions.js';
|
|
15
15
|
import 'motion';
|
|
16
|
+
import '../internal/NavBarContext.js';
|
|
16
17
|
import '@hh.ru/magritte-common-use-when-font-loaded';
|
|
17
18
|
import './EnvironmentFingerprintNode.js';
|
|
18
|
-
import '@hh.ru/magritte-ui-divider';
|
|
19
|
-
import '@hh.ru/magritte-ui-layer';
|
|
20
|
-
import '../internal/useAnimationRanges.js';
|
|
21
|
-
import '../internal/useBindScrollToAnimationProgress.js';
|
|
22
|
-
import '../internal/useNavBarMetrics.js';
|
|
23
|
-
import '../internal/useResetFocus.js';
|
|
24
|
-
import '../internal/useScrollAdapter.js';
|
|
25
|
-
import '@hh.ru/magritte-internal-custom-scroll';
|
|
26
|
-
import '../internal/useSnapScroll.js';
|
|
27
|
-
import '../internal/useSyncMotionValue.js';
|
|
28
19
|
|
|
29
20
|
const startKey = (id) => `${id}-start`;
|
|
30
21
|
const endKey = (id) => `${id}-end`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutMorph.js","sources":["src/public/LayoutMorph.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useId,\n useLayoutEffect,\n useRef,\n type FC,\n type MutableRefObject,\n type PropsWithChildren,\n} from 'react';\nimport classNames from 'classnames';\nimport { type HTMLMotionProps, motion, useMotionValue } from 'motion/react';\n\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useMeasureManual } from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport { useInert } from '@hh.ru/magritte-ui-nav-bar/internal/useInert';\nimport {\n lerp,\n useActualRef,\n useStoreSyncedTransform,\n calcMorphParams,\n type MorphSetup,\n type HorizontalAlign,\n type SizeAxis,\n type VerticalAlign,\n} from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport { AnimationStageContext } from '@hh.ru/magritte-ui-nav-bar/public/LayoutStage';\n\nimport styles from './nav-bar.less';\n\nconst startKey = (id: string) => `${id}-start`;\nconst endKey = (id: string) => `${id}-end`;\n\nconst LayoutMorphContext = createContext<string>('#container');\nconst useLayoutMorphContext = () => useContext(LayoutMorphContext);\n\nconst calcParams = (\n setup: MorphSetup,\n sizeAxis: SizeAxis,\n horizontalPositionAlign: HorizontalAlign,\n verticalPositionAlign: VerticalAlign\n) => {\n const start = DOMRect.fromRect(setup.start);\n start.x -= setup.containerStart.x;\n start.y -= setup.containerStart.y;\n\n const end = DOMRect.fromRect(setup.end);\n end.x -= setup.containerEnd.x;\n end.y -= setup.containerEnd.y;\n\n return calcMorphParams(start, end, sizeAxis, horizontalPositionAlign, verticalPositionAlign);\n};\n\nexport type LayoutMorphProps = PropsWithChildren<\n {\n /**\n * Задает стадию анимации на которой элемент будет виден.\n * Если не задан, то элемент будет виден на протяжении всей анимации.\n */\n stage?: 'start' | 'end';\n /**\n * Позволяет анимировать элементы через морфинг, задав между ними связь с помощью указания одинакового `id`\n * и разных `stage`\n */\n id?: string;\n /**\n * Задает ось на основе которой будет вычисляться коэффициент масштабирования применяемый в ходе анимации.\n * В режиме `both` для каждой из осей применяется свой коэффициент что может привести к искажению пропорций в ходе\n * анимации.\n * В режиме `auto` применяется эвристика для выбора одного из трех остальных режимов для получения наилучшего\n * результат и минимизации искажения пропорций.\n */\n sizeAxis?: SizeAxis;\n /**\n * Задает горизонтальное выравнивание анимируемых элементов в ходе анимации.\n */\n horizontalPositionAlign?: HorizontalAlign;\n /**\n * Задает вертикальное выравнивание анимируемых элементов в ходе анимации.\n */\n verticalPositionAlign?: VerticalAlign;\n } & HTMLMotionProps<'div'>\n>;\n\nexport const LayoutMorph: FC<LayoutMorphProps> = ({\n children,\n stage,\n id: manualId,\n sizeAxis = 'auto',\n verticalPositionAlign = 'center',\n horizontalPositionAlign = 'center',\n ...rest\n}) => {\n const id = useId();\n const rootRef = useRef<HTMLDivElement>(null);\n const animationStageRef = useContext(AnimationStageContext);\n const morphStore = useMorphStore();\n const paneStore = usePaneStore();\n\n const width = useMotionValue<'auto' | number>('auto');\n const height = useMotionValue<'auto' | number>('auto');\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n const scaleX = useMotionValue(1);\n const scaleY = useMotionValue(1);\n const opacity = useMotionValue(stage !== 'end' ? 1 : 0);\n const pointerEvents = useMotionValue<'auto' | 'none'>('auto');\n const [refCb, setInert] = useInert();\n const rootRefCallback = useMultipleRefs<HTMLElement>(rootRef, refCb);\n\n const childRef: MutableRefObject<HTMLElement | null> = useRef(null);\n\n const containerId = useLayoutMorphContext();\n\n useLayoutEffect(() => {\n if (!rootRef.current || !rootRef.current.firstChild) {\n return;\n }\n if (rootRef.current.children.length > 1) {\n throw new Error(\n 'LayoutMorph expects exactly one child HTML element. Please wrap multiple children in a container.'\n );\n }\n childRef.current = rootRef.current.firstChild as HTMLElement;\n }, []);\n\n const isManual = !!manualId && !!stage;\n\n const actualIdRef = useActualRef(isManual ? manualId : id);\n\n useStoreSyncedTransform(\n paneStore.get('motionValue'),\n morphStore,\n [startKey(id), endKey(id), startKey(containerId), endKey(containerId)],\n () => {\n const basicRect = new DOMRectReadOnly();\n const sk = stage === 'end' ? endKey : startKey;\n const ek = stage === 'end' ? startKey : endKey;\n const setup = {\n start: morphStore.get(sk(actualIdRef.current)) ?? basicRect,\n end: morphStore.get(ek(actualIdRef.current)) ?? basicRect,\n containerStart: morphStore.get(sk(containerId)) ?? basicRect,\n containerEnd: morphStore.get(ek(containerId)) ?? basicRect,\n };\n\n const params = calcParams(\n setup,\n isManual ? sizeAxis : 'both',\n isManual ? horizontalPositionAlign : 'left',\n isManual ? verticalPositionAlign : 'top'\n );\n const startX = setup.start.x - setup.containerStart.x;\n const startY = setup.start.y - setup.containerStart.y;\n\n if (isManual) {\n width.set(setup.start.width);\n height.set(setup.start.height);\n return (progress: number) => {\n const p = stage === 'end' ? 1 - progress : progress;\n x.set(lerp(startX, startX + params.deltaX, p));\n y.set(lerp(startY, startY + params.deltaY, p));\n scaleX.set(lerp(1, params.scaleX, p));\n scaleY.set(lerp(1, params.scaleY, p));\n pointerEvents.set(!stage || p < 0.5 ? 'auto' : 'none');\n setInert(pointerEvents.get() === 'none');\n stage && opacity.set(1 - p);\n };\n }\n\n scaleX.set(1);\n scaleY.set(1);\n return (progress: number) => {\n const p = stage === 'end' ? 1 - progress : progress;\n x.set(lerp(startX, startX + params.deltaX, p));\n y.set(lerp(startY, startY + params.deltaY, p));\n width.set(lerp(setup.start.width, setup.start.width * params.scaleX, p));\n height.set(lerp(setup.start.height, setup.start.height * params.scaleY, p));\n pointerEvents.set(!stage || p < 0.5 ? 'auto' : 'none');\n setInert(pointerEvents.get() === 'none');\n stage && opacity.set(1 - p);\n };\n },\n (interpolator, progress) => interpolator(progress)\n );\n\n useMeasureManual(childRef, (rect) => {\n if (animationStageRef.current === 'start') {\n (stage === 'start' || !stage) && morphStore.set(startKey(actualIdRef.current), rect);\n // если элемент виден только в начальной или конечной точке анимации, то его позиция и размер\n // не меняются в процессе анимации, только прозрачность\n stage === 'start' && morphStore.set(endKey(actualIdRef.current), rect);\n } else if (animationStageRef.current === 'end') {\n (stage === 'end' || !stage) && morphStore.set(endKey(actualIdRef.current), rect);\n if ((!isManual || morphStore.get(startKey(actualIdRef.current)) === null) && stage === 'end') {\n morphStore.set(startKey(actualIdRef.current), rect);\n }\n }\n });\n\n return (\n <motion.div\n {...rest}\n ref={rootRefCallback}\n className={classNames(styles.layoutMorph, {\n [styles.layoutMorphStart]: stage === 'start',\n [styles.layoutMorphEnd]: stage === 'end',\n [styles.morphItemTop]: verticalPositionAlign === 'top' && isManual,\n [styles.morphItemBottom]: verticalPositionAlign === 'bottom' && isManual,\n [styles.morphItemLeft]: horizontalPositionAlign === 'left' && isManual,\n [styles.morphItemRight]: horizontalPositionAlign === 'right' && isManual,\n })}\n style={{ width, height, x, y, scaleX, scaleY, opacity, pointerEvents }}\n >\n <LayoutMorphContext.Provider value={id}>{children}</LayoutMorphContext.Provider>\n </motion.div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"LayoutMorph.js","sources":["src/public/LayoutMorph.tsx"],"sourcesContent":["import {\n createContext,\n useContext,\n useId,\n useLayoutEffect,\n useRef,\n type FC,\n type MutableRefObject,\n type PropsWithChildren,\n} from 'react';\nimport classNames from 'classnames';\nimport { type HTMLMotionProps, motion, useMotionValue } from 'motion/react';\n\nimport { useMultipleRefs } from '@hh.ru/magritte-common-use-multiple-refs';\nimport { useMeasureManual } from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport { useInert } from '@hh.ru/magritte-ui-nav-bar/internal/useInert';\nimport {\n lerp,\n useActualRef,\n useStoreSyncedTransform,\n calcMorphParams,\n type MorphSetup,\n type HorizontalAlign,\n type SizeAxis,\n type VerticalAlign,\n} from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport { AnimationStageContext } from '@hh.ru/magritte-ui-nav-bar/public/LayoutStage';\n\nimport styles from './nav-bar.less';\n\nconst startKey = (id: string) => `${id}-start`;\nconst endKey = (id: string) => `${id}-end`;\n\nconst LayoutMorphContext = createContext<string>('#container');\nconst useLayoutMorphContext = () => useContext(LayoutMorphContext);\n\nconst calcParams = (\n setup: MorphSetup,\n sizeAxis: SizeAxis,\n horizontalPositionAlign: HorizontalAlign,\n verticalPositionAlign: VerticalAlign\n) => {\n const start = DOMRect.fromRect(setup.start);\n start.x -= setup.containerStart.x;\n start.y -= setup.containerStart.y;\n\n const end = DOMRect.fromRect(setup.end);\n end.x -= setup.containerEnd.x;\n end.y -= setup.containerEnd.y;\n\n return calcMorphParams(start, end, sizeAxis, horizontalPositionAlign, verticalPositionAlign);\n};\n\nexport type LayoutMorphProps = PropsWithChildren<\n {\n /**\n * Задает стадию анимации на которой элемент будет виден.\n * Если не задан, то элемент будет виден на протяжении всей анимации.\n */\n stage?: 'start' | 'end';\n /**\n * Позволяет анимировать элементы через морфинг, задав между ними связь с помощью указания одинакового `id`\n * и разных `stage`\n */\n id?: string;\n /**\n * Задает ось на основе которой будет вычисляться коэффициент масштабирования применяемый в ходе анимации.\n * В режиме `both` для каждой из осей применяется свой коэффициент что может привести к искажению пропорций в ходе\n * анимации.\n * В режиме `auto` применяется эвристика для выбора одного из трех остальных режимов для получения наилучшего\n * результат и минимизации искажения пропорций.\n */\n sizeAxis?: SizeAxis;\n /**\n * Задает горизонтальное выравнивание анимируемых элементов в ходе анимации.\n */\n horizontalPositionAlign?: HorizontalAlign;\n /**\n * Задает вертикальное выравнивание анимируемых элементов в ходе анимации.\n */\n verticalPositionAlign?: VerticalAlign;\n } & HTMLMotionProps<'div'>\n>;\n\nexport const LayoutMorph: FC<LayoutMorphProps> = ({\n children,\n stage,\n id: manualId,\n sizeAxis = 'auto',\n verticalPositionAlign = 'center',\n horizontalPositionAlign = 'center',\n ...rest\n}) => {\n const id = useId();\n const rootRef = useRef<HTMLDivElement>(null);\n const animationStageRef = useContext(AnimationStageContext);\n const morphStore = useMorphStore();\n const paneStore = usePaneStore();\n\n const width = useMotionValue<'auto' | number>('auto');\n const height = useMotionValue<'auto' | number>('auto');\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n const scaleX = useMotionValue(1);\n const scaleY = useMotionValue(1);\n const opacity = useMotionValue(stage !== 'end' ? 1 : 0);\n const pointerEvents = useMotionValue<'auto' | 'none'>('auto');\n const [refCb, setInert] = useInert();\n const rootRefCallback = useMultipleRefs<HTMLElement>(rootRef, refCb);\n\n const childRef: MutableRefObject<HTMLElement | null> = useRef(null);\n\n const containerId = useLayoutMorphContext();\n\n useLayoutEffect(() => {\n if (!rootRef.current || !rootRef.current.firstChild) {\n return;\n }\n if (rootRef.current.children.length > 1) {\n throw new Error(\n 'LayoutMorph expects exactly one child HTML element. Please wrap multiple children in a container.'\n );\n }\n childRef.current = rootRef.current.firstChild as HTMLElement;\n }, []);\n\n const isManual = !!manualId && !!stage;\n\n const actualIdRef = useActualRef(isManual ? manualId : id);\n\n useStoreSyncedTransform(\n paneStore.get('motionValue'),\n morphStore,\n [startKey(id), endKey(id), startKey(containerId), endKey(containerId)],\n () => {\n const basicRect = new DOMRectReadOnly();\n const sk = stage === 'end' ? endKey : startKey;\n const ek = stage === 'end' ? startKey : endKey;\n const setup = {\n start: morphStore.get(sk(actualIdRef.current)) ?? basicRect,\n end: morphStore.get(ek(actualIdRef.current)) ?? basicRect,\n containerStart: morphStore.get(sk(containerId)) ?? basicRect,\n containerEnd: morphStore.get(ek(containerId)) ?? basicRect,\n };\n\n const params = calcParams(\n setup,\n isManual ? sizeAxis : 'both',\n isManual ? horizontalPositionAlign : 'left',\n isManual ? verticalPositionAlign : 'top'\n );\n const startX = setup.start.x - setup.containerStart.x;\n const startY = setup.start.y - setup.containerStart.y;\n\n if (isManual) {\n width.set(setup.start.width);\n height.set(setup.start.height);\n return (progress: number) => {\n const p = stage === 'end' ? 1 - progress : progress;\n x.set(lerp(startX, startX + params.deltaX, p));\n y.set(lerp(startY, startY + params.deltaY, p));\n scaleX.set(lerp(1, params.scaleX, p));\n scaleY.set(lerp(1, params.scaleY, p));\n pointerEvents.set(!stage || p < 0.5 ? 'auto' : 'none');\n setInert(pointerEvents.get() === 'none');\n stage && opacity.set(1 - p);\n };\n }\n\n scaleX.set(1);\n scaleY.set(1);\n return (progress: number) => {\n const p = stage === 'end' ? 1 - progress : progress;\n x.set(lerp(startX, startX + params.deltaX, p));\n y.set(lerp(startY, startY + params.deltaY, p));\n width.set(lerp(setup.start.width, setup.start.width * params.scaleX, p));\n height.set(lerp(setup.start.height, setup.start.height * params.scaleY, p));\n pointerEvents.set(!stage || p < 0.5 ? 'auto' : 'none');\n setInert(pointerEvents.get() === 'none');\n stage && opacity.set(1 - p);\n };\n },\n (interpolator, progress) => interpolator(progress)\n );\n\n useMeasureManual(childRef, (rect) => {\n if (animationStageRef.current === 'start') {\n (stage === 'start' || !stage) && morphStore.set(startKey(actualIdRef.current), rect);\n // если элемент виден только в начальной или конечной точке анимации, то его позиция и размер\n // не меняются в процессе анимации, только прозрачность\n stage === 'start' && morphStore.set(endKey(actualIdRef.current), rect);\n } else if (animationStageRef.current === 'end') {\n (stage === 'end' || !stage) && morphStore.set(endKey(actualIdRef.current), rect);\n if ((!isManual || morphStore.get(startKey(actualIdRef.current)) === null) && stage === 'end') {\n morphStore.set(startKey(actualIdRef.current), rect);\n }\n }\n });\n\n return (\n <motion.div\n {...rest}\n ref={rootRefCallback}\n className={classNames(styles.layoutMorph, {\n [styles.layoutMorphStart]: stage === 'start',\n [styles.layoutMorphEnd]: stage === 'end',\n [styles.morphItemTop]: verticalPositionAlign === 'top' && isManual,\n [styles.morphItemBottom]: verticalPositionAlign === 'bottom' && isManual,\n [styles.morphItemLeft]: horizontalPositionAlign === 'left' && isManual,\n [styles.morphItemRight]: horizontalPositionAlign === 'right' && isManual,\n })}\n style={{ width, height, x, y, scaleX, scaleY, opacity, pointerEvents }}\n >\n <LayoutMorphContext.Provider value={id}>{children}</LayoutMorphContext.Provider>\n </motion.div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
package/public/LayoutStage.js
CHANGED
|
@@ -9,19 +9,10 @@ import { MorphStoreProvider, useMorphStore } from '../internal/MorphStore.js';
|
|
|
9
9
|
import { usePaneStore } from '../internal/PaneStore.js';
|
|
10
10
|
import { useInitOnce } from '../internal/utils.js';
|
|
11
11
|
import { EnvironmentFingerprintNode, useEnvironmentFingerprint } from './EnvironmentFingerprintNode.js';
|
|
12
|
-
import { s as styles } from '../
|
|
12
|
+
import { s as styles } from '../nav-bar-DEFIZlLr.js';
|
|
13
13
|
import '../internal/KeyedSubscriptions.js';
|
|
14
14
|
import 'motion';
|
|
15
|
-
import '
|
|
16
|
-
import '@hh.ru/magritte-ui-layer';
|
|
17
|
-
import '../internal/useAnimationRanges.js';
|
|
18
|
-
import '../internal/useBindScrollToAnimationProgress.js';
|
|
19
|
-
import '../internal/useNavBarMetrics.js';
|
|
20
|
-
import '../internal/useResetFocus.js';
|
|
21
|
-
import '../internal/useScrollAdapter.js';
|
|
22
|
-
import '@hh.ru/magritte-internal-custom-scroll';
|
|
23
|
-
import '../internal/useSnapScroll.js';
|
|
24
|
-
import '../internal/useSyncMotionValue.js';
|
|
15
|
+
import '../internal/NavBarContext.js';
|
|
25
16
|
|
|
26
17
|
const CONTAINER_START_KEY = '#container-start';
|
|
27
18
|
const CONTAINER_END_KEY = '#container-end';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LayoutStage.js","sources":["src/public/LayoutStage.tsx"],"sourcesContent":["import {\n createContext,\n createRef,\n useContext,\n useLayoutEffect,\n useRef,\n type FC,\n type MutableRefObject,\n type PropsWithChildren,\n} from 'react';\nimport classNames from 'classnames';\nimport { HTMLMotionProps, motion, useMotionValue, frame } from 'motion/react';\n\nimport { useWhenFontLoaded } from '@hh.ru/magritte-common-use-when-font-loaded';\nimport {\n MetricsProvider,\n useMeasureManual,\n useRemeasureAllManual,\n} from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { MorphStoreProvider, useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport { useInitOnce } from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport {\n EnvironmentFingerprintNode,\n useEnvironmentFingerprint,\n} from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\n\nimport styles from './nav-bar.less';\n\nexport const CONTAINER_START_KEY = '#container-start';\nexport const CONTAINER_END_KEY = '#container-end';\n\nexport type AnimationStage = 'start' | 'end' | 'progress';\n\nexport const AnimationStageContext = createContext<MutableRefObject<AnimationStage | null>>(createRef());\n\nconst stageClasses = {\n start: 'nav-bar-layout-animation-stage-start',\n end: 'nav-bar-layout-animation-stage-end',\n progress: styles.animationStageProgress,\n} as const;\n\nconst CombinedStageAnimationMeasurementManager: FC<PropsWithChildren<HTMLMotionProps<'div'>>> = ({\n children,\n ...rest\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const animationStageRef = useContext(AnimationStageContext);\n const morphStore = useMorphStore();\n const currentClassRef = useRef<string>(stageClasses.start);\n const paneStore = usePaneStore();\n const forceMeasure = useRemeasureAllManual();\n const progressPainted = useRef(false);\n\n const setStage = useInitOnce(() => (stage: AnimationStage) => {\n const setClasses = (stage: AnimationStage) => {\n if (!wrapperRef.current) {\n return;\n }\n for (const animClasses of Object.entries(stageClasses)) {\n wrapperRef.current.classList.toggle(animClasses[1], stage === animClasses[0]);\n }\n currentClassRef.current = stageClasses[stage];\n animationStageRef.current = stage;\n };\n\n if (stage === 'progress' && !progressPainted.current) {\n setClasses('start');\n frame.render(() => {\n progressPainted.current = true;\n setClasses('progress');\n });\n return;\n }\n\n setClasses(stage);\n });\n const measureSubtree = useInitOnce(() => () => {\n setStage('start');\n forceMeasure();\n setStage('end');\n forceMeasure();\n setStage('progress');\n });\n\n const height = useMotionValue<number | 'auto'>('auto');\n useLayoutEffect(() => {\n paneStore.set({ animated: true });\n return () => paneStore.set({ animated: false });\n }, [paneStore]);\n\n useMeasureManual(wrapperRef, (rect) => {\n if (animationStageRef.current === 'start') {\n height.set(rect.height);\n // height из MotionValue применится к DOM асинхронно, поэтому применяем высоту синхронно\n // чтобы не триггерить ResizeObserver когда сбросим у элементов position в absolute\n if (wrapperRef.current) {\n wrapperRef.current.style.height = `${rect.height}px`;\n }\n paneStore.set({ top: rect.top, startHeight: rect.height });\n morphStore.set(CONTAINER_START_KEY, rect);\n } else {\n paneStore.set({ endHeight: rect.height });\n morphStore.set(CONTAINER_END_KEY, rect);\n }\n });\n\n useEnvironmentFingerprint(measureSubtree);\n useWhenFontLoaded(() => height.get() !== 'auto' && measureSubtree());\n\n return (\n <motion.div\n ref={wrapperRef}\n {...rest}\n className={classNames(styles.layoutAnimationContainer, currentClassRef.current)}\n style={{ height }}\n >\n {children}\n </motion.div>\n );\n};\n\nexport const LayoutStage: FC<PropsWithChildren<HTMLMotionProps<'div'>>> = ({ children, ...rest }) => {\n const stageRef = useRef<AnimationStage | null>('start');\n\n return (\n <EnvironmentFingerprintNode style={{ pointerEvents: 'none' }}>\n <MorphStoreProvider>\n <AnimationStageContext.Provider value={stageRef}>\n <MetricsProvider>\n <CombinedStageAnimationMeasurementManager {...rest}>\n {children}\n </CombinedStageAnimationMeasurementManager>\n </MetricsProvider>\n </AnimationStageContext.Provider>\n </MorphStoreProvider>\n </EnvironmentFingerprintNode>\n );\n};\n"],"names":["_jsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"LayoutStage.js","sources":["src/public/LayoutStage.tsx"],"sourcesContent":["import {\n createContext,\n createRef,\n useContext,\n useLayoutEffect,\n useRef,\n type FC,\n type MutableRefObject,\n type PropsWithChildren,\n} from 'react';\nimport classNames from 'classnames';\nimport { HTMLMotionProps, motion, useMotionValue, frame } from 'motion/react';\n\nimport { useWhenFontLoaded } from '@hh.ru/magritte-common-use-when-font-loaded';\nimport {\n MetricsProvider,\n useMeasureManual,\n useRemeasureAllManual,\n} from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { MorphStoreProvider, useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport { useInitOnce } from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport {\n EnvironmentFingerprintNode,\n useEnvironmentFingerprint,\n} from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\n\nimport styles from './nav-bar.less';\n\nexport const CONTAINER_START_KEY = '#container-start';\nexport const CONTAINER_END_KEY = '#container-end';\n\nexport type AnimationStage = 'start' | 'end' | 'progress';\n\nexport const AnimationStageContext = createContext<MutableRefObject<AnimationStage | null>>(createRef());\n\nconst stageClasses = {\n start: 'nav-bar-layout-animation-stage-start',\n end: 'nav-bar-layout-animation-stage-end',\n progress: styles.animationStageProgress,\n} as const;\n\nconst CombinedStageAnimationMeasurementManager: FC<PropsWithChildren<HTMLMotionProps<'div'>>> = ({\n children,\n ...rest\n}) => {\n const wrapperRef = useRef<HTMLDivElement>(null);\n const animationStageRef = useContext(AnimationStageContext);\n const morphStore = useMorphStore();\n const currentClassRef = useRef<string>(stageClasses.start);\n const paneStore = usePaneStore();\n const forceMeasure = useRemeasureAllManual();\n const progressPainted = useRef(false);\n\n const setStage = useInitOnce(() => (stage: AnimationStage) => {\n const setClasses = (stage: AnimationStage) => {\n if (!wrapperRef.current) {\n return;\n }\n for (const animClasses of Object.entries(stageClasses)) {\n wrapperRef.current.classList.toggle(animClasses[1], stage === animClasses[0]);\n }\n currentClassRef.current = stageClasses[stage];\n animationStageRef.current = stage;\n };\n\n if (stage === 'progress' && !progressPainted.current) {\n setClasses('start');\n frame.render(() => {\n progressPainted.current = true;\n setClasses('progress');\n });\n return;\n }\n\n setClasses(stage);\n });\n const measureSubtree = useInitOnce(() => () => {\n setStage('start');\n forceMeasure();\n setStage('end');\n forceMeasure();\n setStage('progress');\n });\n\n const height = useMotionValue<number | 'auto'>('auto');\n useLayoutEffect(() => {\n paneStore.set({ animated: true });\n return () => paneStore.set({ animated: false });\n }, [paneStore]);\n\n useMeasureManual(wrapperRef, (rect) => {\n if (animationStageRef.current === 'start') {\n height.set(rect.height);\n // height из MotionValue применится к DOM асинхронно, поэтому применяем высоту синхронно\n // чтобы не триггерить ResizeObserver когда сбросим у элементов position в absolute\n if (wrapperRef.current) {\n wrapperRef.current.style.height = `${rect.height}px`;\n }\n paneStore.set({ top: rect.top, startHeight: rect.height });\n morphStore.set(CONTAINER_START_KEY, rect);\n } else {\n paneStore.set({ endHeight: rect.height });\n morphStore.set(CONTAINER_END_KEY, rect);\n }\n });\n\n useEnvironmentFingerprint(measureSubtree);\n useWhenFontLoaded(() => height.get() !== 'auto' && measureSubtree());\n\n return (\n <motion.div\n ref={wrapperRef}\n {...rest}\n className={classNames(styles.layoutAnimationContainer, currentClassRef.current)}\n style={{ height }}\n >\n {children}\n </motion.div>\n );\n};\n\nexport const LayoutStage: FC<PropsWithChildren<HTMLMotionProps<'div'>>> = ({ children, ...rest }) => {\n const stageRef = useRef<AnimationStage | null>('start');\n\n return (\n <EnvironmentFingerprintNode style={{ pointerEvents: 'none' }}>\n <MorphStoreProvider>\n <AnimationStageContext.Provider value={stageRef}>\n <MetricsProvider>\n <CombinedStageAnimationMeasurementManager {...rest}>\n {children}\n </CombinedStageAnimationMeasurementManager>\n </MetricsProvider>\n </AnimationStageContext.Provider>\n </MorphStoreProvider>\n </EnvironmentFingerprintNode>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
package/public/Morph.js
CHANGED
|
@@ -9,20 +9,11 @@ import { usePaneStore } from '../internal/PaneStore.js';
|
|
|
9
9
|
import { useStoreSyncedTransform, calcMorphParams, lerp } from '../internal/utils.js';
|
|
10
10
|
import { useEnvironmentFingerprint } from './EnvironmentFingerprintNode.js';
|
|
11
11
|
import { useAnimationStage } from './Stage.js';
|
|
12
|
-
import { s as styles } from '../
|
|
12
|
+
import { s as styles } from '../nav-bar-DEFIZlLr.js';
|
|
13
13
|
import '../internal/KeyedSubscriptions.js';
|
|
14
14
|
import 'motion';
|
|
15
|
+
import '../internal/NavBarContext.js';
|
|
15
16
|
import '../internal/useInert.js';
|
|
16
|
-
import '@hh.ru/magritte-ui-divider';
|
|
17
|
-
import '@hh.ru/magritte-ui-layer';
|
|
18
|
-
import '../internal/useAnimationRanges.js';
|
|
19
|
-
import '../internal/useBindScrollToAnimationProgress.js';
|
|
20
|
-
import '../internal/useNavBarMetrics.js';
|
|
21
|
-
import '../internal/useResetFocus.js';
|
|
22
|
-
import '../internal/useScrollAdapter.js';
|
|
23
|
-
import '@hh.ru/magritte-internal-custom-scroll';
|
|
24
|
-
import '../internal/useSnapScroll.js';
|
|
25
|
-
import '../internal/useSyncMotionValue.js';
|
|
26
17
|
|
|
27
18
|
const Morph = ({ children, id, className, style, sizeAxis = 'auto', horizontalPositionAlign = 'center', verticalPositionAlign = 'center', ...rest }) => {
|
|
28
19
|
const paneStore = usePaneStore();
|
package/public/Morph.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Morph.js","sources":["src/public/Morph.tsx"],"sourcesContent":["import { type PropsWithChildren, type FC, useLayoutEffect, useRef, type CSSProperties } from 'react';\nimport classNames from 'classnames';\nimport { useMotionValue, motion, HTMLMotionProps } from 'motion/react';\n\nimport { useMeasureAuto } from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport {\n lerp,\n useStoreSyncedTransform,\n calcMorphParams,\n type HorizontalAlign,\n type SizeAxis,\n type VerticalAlign,\n} from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport { useEnvironmentFingerprint } from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\nimport { useAnimationStage } from '@hh.ru/magritte-ui-nav-bar/public/Stage';\n\nimport styles from './nav-bar.less';\n\nexport interface MorphProps extends HTMLMotionProps<'div'> {\n /**\n * Задает соответствие между элементами для морфинга между начальным и конечным <Stage />\n */\n id: string;\n style?: CSSProperties;\n className?: string;\n /**\n * Задает ось на основе которой будет вычисляться коэффициент масштабирования применяемый в ходе анимации.\n * В режиме `both` для каждой из осей применяется свой коэффициент что может привести к искажению пропорций в ходе\n * анимации.\n * В режиме `auto` применяется эвристика для выбора одного из трех остальных режимов для получения наилучшего\n * результат и минимизации искажения пропорций.\n */\n sizeAxis?: SizeAxis;\n /**\n * Задает горизонтальное выравнивание анимируемых элементов в ходе анимации.\n */\n horizontalPositionAlign?: HorizontalAlign;\n /**\n * Задает вертикальное выравнивание анимируемых элементов в ходе анимации.\n */\n verticalPositionAlign?: VerticalAlign;\n}\n\nexport const Morph: FC<PropsWithChildren<MorphProps>> = ({\n children,\n id,\n className,\n style,\n sizeAxis = 'auto',\n horizontalPositionAlign = 'center',\n verticalPositionAlign = 'center',\n ...rest\n}) => {\n const paneStore = usePaneStore();\n const morphStore = useMorphStore();\n const animationStage = useAnimationStage();\n const rootRef = useRef<HTMLDivElement>(null);\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n const scaleX = useMotionValue(1);\n const scaleY = useMotionValue(1);\n\n const startId = `start-${id}`;\n const endId = `end-${id}`;\n\n useStoreSyncedTransform(\n paneStore.get('motionValue'),\n morphStore,\n [startId, endId],\n () => {\n const start = morphStore.get(animationStage === 'end' ? endId : startId);\n const end = morphStore.get(animationStage === 'end' ? startId : endId);\n const {\n deltaX,\n deltaY,\n scaleX: xScale,\n scaleY: yScale,\n } = calcMorphParams(start, end, sizeAxis, horizontalPositionAlign, verticalPositionAlign);\n\n return (progress: number) => {\n const p = animationStage === 'end' ? 1 - progress : progress;\n x.set(lerp(0, deltaX, p));\n y.set(lerp(0, deltaY, p));\n\n scaleX.set(lerp(1, xScale, p));\n scaleY.set(lerp(1, yScale, p));\n };\n },\n (interpolator, progress) => interpolator(progress)\n );\n\n const forceInvalidate = useMeasureAuto(rootRef, (rect) => morphStore.set(`${animationStage}-${id}`, rect), [\n id,\n animationStage,\n ]);\n\n useEnvironmentFingerprint(forceInvalidate);\n\n useLayoutEffect(() => () => morphStore.set(`${animationStage}-${id}`, null), [morphStore, animationStage, id]);\n\n return (\n <motion.div\n ref={rootRef}\n {...rest}\n className={classNames(styles.morphItem, className, {\n [styles.morphItemTop]: verticalPositionAlign === 'top',\n [styles.morphItemBottom]: verticalPositionAlign === 'bottom',\n [styles.morphItemLeft]: horizontalPositionAlign === 'left',\n [styles.morphItemRight]: horizontalPositionAlign === 'right',\n })}\n style={{ ...(style ?? {}), x, y, scaleX, scaleY }}\n >\n {children}\n </motion.div>\n );\n};\n"],"names":["_jsx"],"mappings":"
|
|
1
|
+
{"version":3,"file":"Morph.js","sources":["src/public/Morph.tsx"],"sourcesContent":["import { type PropsWithChildren, type FC, useLayoutEffect, useRef, type CSSProperties } from 'react';\nimport classNames from 'classnames';\nimport { useMotionValue, motion, HTMLMotionProps } from 'motion/react';\n\nimport { useMeasureAuto } from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { useMorphStore } from '@hh.ru/magritte-ui-nav-bar/internal/MorphStore';\nimport { usePaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport {\n lerp,\n useStoreSyncedTransform,\n calcMorphParams,\n type HorizontalAlign,\n type SizeAxis,\n type VerticalAlign,\n} from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport { useEnvironmentFingerprint } from '@hh.ru/magritte-ui-nav-bar/public/EnvironmentFingerprintNode';\nimport { useAnimationStage } from '@hh.ru/magritte-ui-nav-bar/public/Stage';\n\nimport styles from './nav-bar.less';\n\nexport interface MorphProps extends HTMLMotionProps<'div'> {\n /**\n * Задает соответствие между элементами для морфинга между начальным и конечным <Stage />\n */\n id: string;\n style?: CSSProperties;\n className?: string;\n /**\n * Задает ось на основе которой будет вычисляться коэффициент масштабирования применяемый в ходе анимации.\n * В режиме `both` для каждой из осей применяется свой коэффициент что может привести к искажению пропорций в ходе\n * анимации.\n * В режиме `auto` применяется эвристика для выбора одного из трех остальных режимов для получения наилучшего\n * результат и минимизации искажения пропорций.\n */\n sizeAxis?: SizeAxis;\n /**\n * Задает горизонтальное выравнивание анимируемых элементов в ходе анимации.\n */\n horizontalPositionAlign?: HorizontalAlign;\n /**\n * Задает вертикальное выравнивание анимируемых элементов в ходе анимации.\n */\n verticalPositionAlign?: VerticalAlign;\n}\n\nexport const Morph: FC<PropsWithChildren<MorphProps>> = ({\n children,\n id,\n className,\n style,\n sizeAxis = 'auto',\n horizontalPositionAlign = 'center',\n verticalPositionAlign = 'center',\n ...rest\n}) => {\n const paneStore = usePaneStore();\n const morphStore = useMorphStore();\n const animationStage = useAnimationStage();\n const rootRef = useRef<HTMLDivElement>(null);\n const x = useMotionValue(0);\n const y = useMotionValue(0);\n const scaleX = useMotionValue(1);\n const scaleY = useMotionValue(1);\n\n const startId = `start-${id}`;\n const endId = `end-${id}`;\n\n useStoreSyncedTransform(\n paneStore.get('motionValue'),\n morphStore,\n [startId, endId],\n () => {\n const start = morphStore.get(animationStage === 'end' ? endId : startId);\n const end = morphStore.get(animationStage === 'end' ? startId : endId);\n const {\n deltaX,\n deltaY,\n scaleX: xScale,\n scaleY: yScale,\n } = calcMorphParams(start, end, sizeAxis, horizontalPositionAlign, verticalPositionAlign);\n\n return (progress: number) => {\n const p = animationStage === 'end' ? 1 - progress : progress;\n x.set(lerp(0, deltaX, p));\n y.set(lerp(0, deltaY, p));\n\n scaleX.set(lerp(1, xScale, p));\n scaleY.set(lerp(1, yScale, p));\n };\n },\n (interpolator, progress) => interpolator(progress)\n );\n\n const forceInvalidate = useMeasureAuto(rootRef, (rect) => morphStore.set(`${animationStage}-${id}`, rect), [\n id,\n animationStage,\n ]);\n\n useEnvironmentFingerprint(forceInvalidate);\n\n useLayoutEffect(() => () => morphStore.set(`${animationStage}-${id}`, null), [morphStore, animationStage, id]);\n\n return (\n <motion.div\n ref={rootRef}\n {...rest}\n className={classNames(styles.morphItem, className, {\n [styles.morphItemTop]: verticalPositionAlign === 'top',\n [styles.morphItemBottom]: verticalPositionAlign === 'bottom',\n [styles.morphItemLeft]: horizontalPositionAlign === 'left',\n [styles.morphItemRight]: horizontalPositionAlign === 'right',\n })}\n style={{ ...(style ?? {}), x, y, scaleX, scaleY }}\n >\n {children}\n </motion.div>\n );\n};\n"],"names":["_jsx"],"mappings":"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"}
|
package/public/NavBar.d.ts
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
|
-
import { type RefObject, type FC } from 'react';
|
|
1
|
+
import { type ReactNode, type RefObject, type FC } from 'react';
|
|
2
2
|
import { MotionValue } from 'motion/react';
|
|
3
3
|
import { type ShowDivider } from '@hh.ru/magritte-ui-divider';
|
|
4
|
-
import { PaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';
|
|
5
|
-
import { type PaneElement } from '@hh.ru/magritte-ui-nav-bar/public/Pane';
|
|
6
|
-
type PaneStoreContextValue = ((store: PaneStore) => VoidFunction) | null;
|
|
7
|
-
export declare const useNavBarContext: () => PaneStoreContextValue;
|
|
8
4
|
export interface NavBarProps {
|
|
9
5
|
/**
|
|
10
|
-
* В качестве потомков могут передаваться
|
|
6
|
+
* В качестве потомков могут передаваться компоненты <Pane /> или произвольные элементы,
|
|
7
|
+
* которые будут автоматически обёрнуты в <Pane />.
|
|
11
8
|
*/
|
|
12
|
-
children:
|
|
9
|
+
children: ReactNode;
|
|
13
10
|
/**
|
|
14
11
|
* Управляет режимом прозрачности:
|
|
15
12
|
* -- Прозрачность отключена (`false`)
|
|
@@ -51,4 +48,3 @@ export interface NavBarProps {
|
|
|
51
48
|
animationProgress?: MotionValue<number>;
|
|
52
49
|
}
|
|
53
50
|
export declare const NavBar: FC<NavBarProps>;
|
|
54
|
-
export {};
|
package/public/NavBar.js
CHANGED
|
@@ -1,20 +1,130 @@
|
|
|
1
1
|
import './../index.css';
|
|
2
|
-
import 'react/jsx-runtime';
|
|
3
|
-
import 'react';
|
|
4
|
-
import 'classnames';
|
|
5
|
-
import 'motion/react';
|
|
6
|
-
import '@hh.ru/magritte-ui-divider';
|
|
7
|
-
import '@hh.ru/magritte-ui-layer';
|
|
8
|
-
import '../internal/MetricsProvider.js';
|
|
9
|
-
import '../internal/
|
|
10
|
-
import '../internal/
|
|
11
|
-
import '../internal/
|
|
12
|
-
import '../internal/
|
|
13
|
-
import '../internal/
|
|
14
|
-
import '../internal/
|
|
15
|
-
import '../internal/
|
|
16
|
-
import '../internal/
|
|
17
|
-
|
|
18
|
-
import '
|
|
2
|
+
import { jsx, jsxs } from 'react/jsx-runtime';
|
|
3
|
+
import React, { useRef, useLayoutEffect, Children } from 'react';
|
|
4
|
+
import classNames from 'classnames';
|
|
5
|
+
import { frame, motion } from 'motion/react';
|
|
6
|
+
import { Divider } from '@hh.ru/magritte-ui-divider';
|
|
7
|
+
import { Layer } from '@hh.ru/magritte-ui-layer';
|
|
8
|
+
import { MetricsProvider } from '../internal/MetricsProvider.js';
|
|
9
|
+
import { NavBarContext } from '../internal/NavBarContext.js';
|
|
10
|
+
import { useAnimationRanges } from '../internal/useAnimationRanges.js';
|
|
11
|
+
import { useBindScrollToAnimationProgress } from '../internal/useBindScrollToAnimationProgress.js';
|
|
12
|
+
import { useNavBarMetrics } from '../internal/useNavBarMetrics.js';
|
|
13
|
+
import { useResetFocus } from '../internal/useResetFocus.js';
|
|
14
|
+
import { useScrollAdapter } from '../internal/useScrollAdapter.js';
|
|
15
|
+
import { useSnapScroll } from '../internal/useSnapScroll.js';
|
|
16
|
+
import { useSyncMotionValue } from '../internal/useSyncMotionValue.js';
|
|
17
|
+
import { useInitOnce, scheduleMicro, scheduleMacro, remap } from '../internal/utils.js';
|
|
18
|
+
import { isPaneElement, ExternalPane } from './Pane.js';
|
|
19
|
+
import { s as styles } from '../nav-bar-DEFIZlLr.js';
|
|
19
20
|
import '@hh.ru/magritte-internal-custom-scroll';
|
|
21
|
+
import 'motion';
|
|
22
|
+
import '../internal/MorphStore.js';
|
|
23
|
+
import '../internal/KeyedSubscriptions.js';
|
|
24
|
+
import '../internal/PaneStore.js';
|
|
25
|
+
import './EnvironmentFingerprintNode.js';
|
|
26
|
+
import './LayoutStage.js';
|
|
27
|
+
import '@hh.ru/magritte-common-use-when-font-loaded';
|
|
28
|
+
import './Stage.js';
|
|
29
|
+
import '../internal/useInert.js';
|
|
30
|
+
|
|
31
|
+
const NavBar = ({ children, transparent = false, startTriggerPosition = 'start', endTriggerPosition, overlay = false, snapScroll: scrollSnapping = true, showDivider = false, animationProgress, }) => {
|
|
32
|
+
const paneStoreRegistry = useInitOnce(() => new Set());
|
|
33
|
+
const prevFullHeight = useRef(0);
|
|
34
|
+
const rootRef = useRef(null);
|
|
35
|
+
const [scrollAdapter, scrollPosition] = useScrollAdapter(rootRef);
|
|
36
|
+
const [getMetrics, invalidateMetrics] = useNavBarMetrics(paneStoreRegistry, rootRef, scrollAdapter);
|
|
37
|
+
const [getAnimationRanges, invalidateAnimationRanges] = useAnimationRanges(paneStoreRegistry, getMetrics);
|
|
38
|
+
const [bindScrollToAnimation, getClosestStops, totalAnimationProgress, dividerStyle] = useBindScrollToAnimationProgress(scrollPosition, getMetrics, getAnimationRanges, scrollAdapter, startTriggerPosition, endTriggerPosition);
|
|
39
|
+
const snapScroll = useSnapScroll(scrollPosition, totalAnimationProgress, scrollAdapter, getClosestStops, scrollSnapping);
|
|
40
|
+
// При получении размеров важно дождаться применения MotionValue к DOM, поэтому используем frame.render
|
|
41
|
+
const bindScrollToAnimationScheduled = useInitOnce(() => scheduleMicro(() => frame.render(bindScrollToAnimation)));
|
|
42
|
+
useResetFocus(rootRef, totalAnimationProgress);
|
|
43
|
+
useSyncMotionValue(totalAnimationProgress, animationProgress);
|
|
44
|
+
const dividerVisibility =
|
|
45
|
+
// eslint-disable-next-line no-nested-ternary
|
|
46
|
+
showDivider === 'with-scroll' ? dividerStyle.visibility : showDivider ? 'visible' : 'hidden';
|
|
47
|
+
const registerPaneStore = useInitOnce(() => {
|
|
48
|
+
const subscriptions = [];
|
|
49
|
+
const updateAnimationParams = () => {
|
|
50
|
+
subscriptions.length = 0;
|
|
51
|
+
invalidateMetrics();
|
|
52
|
+
invalidateAnimationRanges();
|
|
53
|
+
bindScrollToAnimationScheduled();
|
|
54
|
+
const navBarMetrics = getMetrics();
|
|
55
|
+
const fullPanesStartHeight = navBarMetrics.bottom - navBarMetrics.top;
|
|
56
|
+
let scroll = scrollAdapter.getScrollTop();
|
|
57
|
+
if (prevFullHeight.current !== null && scroll !== 0) {
|
|
58
|
+
const heightDelta = fullPanesStartHeight - prevFullHeight.current;
|
|
59
|
+
scroll += heightDelta;
|
|
60
|
+
requestAnimationFrame(() => {
|
|
61
|
+
scrollPosition.jump(scrollAdapter.getScrollTop() - 1);
|
|
62
|
+
scrollPosition.jump(scrollAdapter.getScrollTop());
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
const animationRanges = getAnimationRanges();
|
|
66
|
+
[...paneStoreRegistry.values()].forEach((paneStore) => {
|
|
67
|
+
const range = animationRanges.get(paneStore.get('id'));
|
|
68
|
+
if (!range) {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
const remapFn = remap(range[0] === 0 && range[1] === 0
|
|
72
|
+
? [0, 1]
|
|
73
|
+
: [range[0] / navBarMetrics.animationHeight, range[1] / navBarMetrics.animationHeight], [0, 1]);
|
|
74
|
+
const motionValue = paneStore.get('motionValue');
|
|
75
|
+
motionValue.set(remapFn(totalAnimationProgress.get()));
|
|
76
|
+
subscriptions.push(totalAnimationProgress.on('change', (value) => motionValue.set(remapFn(value))));
|
|
77
|
+
});
|
|
78
|
+
prevFullHeight.current = fullPanesStartHeight;
|
|
79
|
+
};
|
|
80
|
+
// основной триггер запуска updateAnimationParams это изменения размеров, обработка которых происходит
|
|
81
|
+
// в очереди микрозадач, поэтому откладываем запуск функции до перехдоа к макрозадачам, чтобы сократить
|
|
82
|
+
// количество вызовов при массовых изменениях
|
|
83
|
+
const onChange = scheduleMacro(updateAnimationParams);
|
|
84
|
+
return (paneStore) => {
|
|
85
|
+
const unsubscribe = paneStore.onChange(['startHeight', 'endHeight', 'top', 'foldable', 'animated'], onChange);
|
|
86
|
+
paneStoreRegistry.add(paneStore);
|
|
87
|
+
return () => {
|
|
88
|
+
paneStoreRegistry.delete(paneStore);
|
|
89
|
+
unsubscribe();
|
|
90
|
+
};
|
|
91
|
+
};
|
|
92
|
+
});
|
|
93
|
+
useLayoutEffect(() => {
|
|
94
|
+
bindScrollToAnimation();
|
|
95
|
+
snapScroll();
|
|
96
|
+
if (!rootRef.current || (typeof startTriggerPosition === 'string' && !endTriggerPosition)) {
|
|
97
|
+
return void 0;
|
|
98
|
+
}
|
|
99
|
+
return scrollAdapter.onResize(bindScrollToAnimationScheduled);
|
|
100
|
+
}, [
|
|
101
|
+
startTriggerPosition,
|
|
102
|
+
endTriggerPosition,
|
|
103
|
+
bindScrollToAnimation,
|
|
104
|
+
bindScrollToAnimationScheduled,
|
|
105
|
+
snapScroll,
|
|
106
|
+
scrollAdapter,
|
|
107
|
+
]);
|
|
108
|
+
// Оборачиваем потомков, не являющихся Pane, в Pane и вкладываем панели друг в друга через проп nextPane
|
|
109
|
+
const childrenArray = Children.toArray(children);
|
|
110
|
+
const nested = isPaneElement(childrenArray[0]) ? (childrenArray.reduceRight((acc, child) => {
|
|
111
|
+
if (!isPaneElement(child)) {
|
|
112
|
+
return acc;
|
|
113
|
+
}
|
|
114
|
+
// cloneElement сужает конструктор до InternalPaneProps, поэтому возвращаем к PaneElement
|
|
115
|
+
return React.cloneElement(child, {
|
|
116
|
+
...child.props,
|
|
117
|
+
nextPane: acc,
|
|
118
|
+
});
|
|
119
|
+
}, null)) : (jsx(ExternalPane, { children: children }));
|
|
120
|
+
return (jsx(Layer, { layer: "navigation-bar", children: jsx(MetricsProvider, { className: classNames(styles.navBar, {
|
|
121
|
+
[styles.navbarTransparentStart]: transparent === 'start',
|
|
122
|
+
[styles.navbarTransparentEnd]: transparent === 'end',
|
|
123
|
+
[styles.navbarNotTransparent]: !transparent,
|
|
124
|
+
[styles.navbarTransparent]: transparent === true,
|
|
125
|
+
[styles.navBarOverlay]: overlay,
|
|
126
|
+
}), ref: rootRef, measureClassName: styles.metricsMode, children: jsx("div", { className: styles.navBarOverlayWrapper, children: jsxs("div", { className: styles.navBarContentContainer, children: [jsx(motion.div, { style: { '--magritte-ui-navbar-animation-progress': totalAnimationProgress }, className: styles.navBarPanesContainer, children: jsx(NavBarContext.Provider, { value: registerPaneStore, children: nested }) }), jsx(motion.div, { className: styles.dividerContainer, style: { ...dividerStyle, visibility: dividerVisibility }, children: jsx(Divider, {}) })] }) }) }) }));
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
export { NavBar };
|
|
20
130
|
//# sourceMappingURL=NavBar.js.map
|
package/public/NavBar.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NavBar.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;"}
|
|
1
|
+
{"version":3,"file":"NavBar.js","sources":["src/public/NavBar.tsx"],"sourcesContent":["import React, { Children, type ReactNode, type RefObject, useLayoutEffect, useRef, type FC } from 'react';\nimport classNames from 'classnames';\nimport { motion, type MotionStyle, MotionValue, frame } from 'motion/react';\n\nimport { Divider, type ShowDivider } from '@hh.ru/magritte-ui-divider';\nimport { Layer } from '@hh.ru/magritte-ui-layer';\nimport { MetricsProvider } from '@hh.ru/magritte-ui-nav-bar/internal/MetricsProvider';\nimport { NavBarContext } from '@hh.ru/magritte-ui-nav-bar/internal/NavBarContext';\nimport { PaneStore } from '@hh.ru/magritte-ui-nav-bar/internal/PaneStore';\nimport { useAnimationRanges } from '@hh.ru/magritte-ui-nav-bar/internal/useAnimationRanges';\nimport { useBindScrollToAnimationProgress } from '@hh.ru/magritte-ui-nav-bar/internal/useBindScrollToAnimationProgress';\nimport { useNavBarMetrics } from '@hh.ru/magritte-ui-nav-bar/internal/useNavBarMetrics';\nimport { useResetFocus } from '@hh.ru/magritte-ui-nav-bar/internal/useResetFocus';\nimport { useScrollAdapter } from '@hh.ru/magritte-ui-nav-bar/internal/useScrollAdapter';\nimport { useSnapScroll } from '@hh.ru/magritte-ui-nav-bar/internal/useSnapScroll';\nimport { useSyncMotionValue } from '@hh.ru/magritte-ui-nav-bar/internal/useSyncMotionValue';\nimport { remap, scheduleMicro, scheduleMacro, useInitOnce } from '@hh.ru/magritte-ui-nav-bar/internal/utils';\nimport {\n type PaneElement,\n type InternalPaneProps,\n ExternalPane,\n isPaneElement,\n} from '@hh.ru/magritte-ui-nav-bar/public/Pane';\n\nimport styles from './nav-bar.less';\n\nexport interface NavBarProps {\n /**\n * В качестве потомков могут передаваться компоненты <Pane /> или произвольные элементы,\n * которые будут автоматически обёрнуты в <Pane />.\n */\n children: ReactNode;\n /**\n * Управляет режимом прозрачности:\n * -- Прозрачность отключена (`false`)\n * -- Прозрачный всегда (`true`)\n * -- Прозрачный в начале анимации (`start`)\n * -- Прозрачный в конце анимации (`end`)\n */\n transparent?: 'start' | 'end' | boolean;\n /**\n * Управляет позицией триггера начала анимации\n */\n startTriggerPosition?: 'start' | 'full-area' | RefObject<HTMLElement | null>;\n /**\n * Управляет позицией триггера конца анимации. Если не передан вычисляется автоматически на основе изменения\n * высоты навбара в процессе анимации и позиции триггера начала анмиации. Если передано число, то интерпретируется\n * как отступ в пикселях от позиции триггера старта анимации.\n */\n endTriggerPosition?: RefObject<HTMLElement | null> | number;\n /**\n * Включает режим когда NavBar не занимает место в лейауте и контент располагается под ним.\n */\n overlay?: boolean;\n /**\n * Управляет режимом автодоскролла. По умолчанию включен.\n */\n snapScroll?: boolean;\n /**\n * Управляет режимом отображения дивайдера:\n * - `false` дивайдер отключен\n * - `always` дивайдер отображается постоянно\n * - `with-scroll` дивайдер отображается только когда контент подскроллен под NavBar\n */\n showDivider?: ShowDivider;\n /**\n * Принимает MotionValue значение которого будет обновляться синхронно с анимацией всего NavBar.\n * Прогресс анимации представляется в виде числа 0..1\n * Предназначен для синхронизации внешних анимаций с анимациями NavBar.\n */\n animationProgress?: MotionValue<number>;\n}\n\nexport const NavBar: FC<NavBarProps> = ({\n children,\n transparent = false,\n startTriggerPosition = 'start',\n endTriggerPosition,\n overlay = false,\n snapScroll: scrollSnapping = true,\n showDivider = false,\n animationProgress,\n}) => {\n const paneStoreRegistry = useInitOnce(() => new Set<PaneStore>());\n const prevFullHeight = useRef<null | number>(0);\n const rootRef = useRef<HTMLDivElement>(null);\n\n const [scrollAdapter, scrollPosition] = useScrollAdapter(rootRef);\n const [getMetrics, invalidateMetrics] = useNavBarMetrics(paneStoreRegistry, rootRef, scrollAdapter);\n const [getAnimationRanges, invalidateAnimationRanges] = useAnimationRanges(paneStoreRegistry, getMetrics);\n const [bindScrollToAnimation, getClosestStops, totalAnimationProgress, dividerStyle] =\n useBindScrollToAnimationProgress(\n scrollPosition,\n getMetrics,\n getAnimationRanges,\n scrollAdapter,\n startTriggerPosition,\n endTriggerPosition\n );\n const snapScroll = useSnapScroll(\n scrollPosition,\n totalAnimationProgress,\n scrollAdapter,\n getClosestStops,\n scrollSnapping\n );\n\n // При получении размеров важно дождаться применения MotionValue к DOM, поэтому используем frame.render\n const bindScrollToAnimationScheduled = useInitOnce(() => scheduleMicro(() => frame.render(bindScrollToAnimation)));\n useResetFocus(rootRef, totalAnimationProgress);\n useSyncMotionValue(totalAnimationProgress, animationProgress);\n\n const dividerVisibility =\n // eslint-disable-next-line no-nested-ternary\n showDivider === 'with-scroll' ? dividerStyle.visibility : showDivider ? 'visible' : 'hidden';\n\n const registerPaneStore = useInitOnce(() => {\n const subscriptions: VoidFunction[] = [];\n\n const updateAnimationParams = () => {\n subscriptions.length = 0;\n invalidateMetrics();\n invalidateAnimationRanges();\n bindScrollToAnimationScheduled();\n const navBarMetrics = getMetrics();\n const fullPanesStartHeight = navBarMetrics.bottom - navBarMetrics.top;\n\n let scroll = scrollAdapter.getScrollTop();\n if (prevFullHeight.current !== null && scroll !== 0) {\n const heightDelta = fullPanesStartHeight - prevFullHeight.current;\n scroll += heightDelta;\n\n requestAnimationFrame(() => {\n scrollPosition.jump(scrollAdapter.getScrollTop() - 1);\n scrollPosition.jump(scrollAdapter.getScrollTop());\n });\n }\n\n const animationRanges = getAnimationRanges();\n [...paneStoreRegistry.values()].forEach((paneStore) => {\n const range = animationRanges.get(paneStore.get('id'));\n if (!range) {\n return;\n }\n const remapFn = remap(\n range[0] === 0 && range[1] === 0\n ? [0, 1]\n : [range[0] / navBarMetrics.animationHeight, range[1] / navBarMetrics.animationHeight],\n [0, 1]\n );\n const motionValue = paneStore.get('motionValue');\n motionValue.set(remapFn(totalAnimationProgress.get()));\n subscriptions.push(totalAnimationProgress.on('change', (value) => motionValue.set(remapFn(value))));\n });\n\n prevFullHeight.current = fullPanesStartHeight;\n };\n\n // основной триггер запуска updateAnimationParams это изменения размеров, обработка которых происходит\n // в очереди микрозадач, поэтому откладываем запуск функции до перехдоа к макрозадачам, чтобы сократить\n // количество вызовов при массовых изменениях\n const onChange = scheduleMacro(updateAnimationParams);\n\n return (paneStore: PaneStore) => {\n const unsubscribe = paneStore.onChange(\n ['startHeight', 'endHeight', 'top', 'foldable', 'animated'],\n onChange\n );\n paneStoreRegistry.add(paneStore);\n return () => {\n paneStoreRegistry.delete(paneStore);\n unsubscribe();\n };\n };\n });\n\n useLayoutEffect(() => {\n bindScrollToAnimation();\n snapScroll();\n if (!rootRef.current || (typeof startTriggerPosition === 'string' && !endTriggerPosition)) {\n return void 0;\n }\n return scrollAdapter.onResize(bindScrollToAnimationScheduled);\n }, [\n startTriggerPosition,\n endTriggerPosition,\n bindScrollToAnimation,\n bindScrollToAnimationScheduled,\n snapScroll,\n scrollAdapter,\n ]);\n\n // Оборачиваем потомков, не являющихся Pane, в Pane и вкладываем панели друг в друга через проп nextPane\n const childrenArray = Children.toArray(children);\n const nested = isPaneElement(childrenArray[0]) ? (\n childrenArray.reduceRight<PaneElement | null>((acc, child) => {\n if (!isPaneElement(child)) {\n return acc;\n }\n // cloneElement сужает конструктор до InternalPaneProps, поэтому возвращаем к PaneElement\n return React.cloneElement<InternalPaneProps>(child, {\n ...child.props,\n nextPane: acc,\n }) as PaneElement;\n }, null)\n ) : (\n <ExternalPane>{children}</ExternalPane>\n );\n\n return (\n <Layer layer=\"navigation-bar\">\n <MetricsProvider\n className={classNames(styles.navBar, {\n [styles.navbarTransparentStart]: transparent === 'start',\n [styles.navbarTransparentEnd]: transparent === 'end',\n [styles.navbarNotTransparent]: !transparent,\n [styles.navbarTransparent]: transparent === true,\n [styles.navBarOverlay]: overlay,\n })}\n ref={rootRef}\n measureClassName={styles.metricsMode}\n >\n <div className={styles.navBarOverlayWrapper}>\n <div className={styles.navBarContentContainer}>\n <motion.div\n style={{ '--magritte-ui-navbar-animation-progress': totalAnimationProgress } as MotionStyle}\n className={styles.navBarPanesContainer}\n >\n <NavBarContext.Provider value={registerPaneStore}>{nested}</NavBarContext.Provider>\n </motion.div>\n <motion.div\n className={styles.dividerContainer}\n style={{ ...dividerStyle, visibility: dividerVisibility }}\n >\n <Divider />\n </motion.div>\n </div>\n </div>\n </MetricsProvider>\n </Layer>\n );\n};\n"],"names":["_jsx","_jsxs"],"mappings":"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"}
|
package/public/Pane.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type FC, type JSXElementConstructor, type PropsWithChildren, type ReactElement } from 'react';
|
|
1
|
+
import { type FC, type ReactNode, type JSXElementConstructor, type PropsWithChildren, type ReactElement } from 'react';
|
|
2
2
|
import { type MotionValue } from 'motion/react';
|
|
3
3
|
export type InternalPaneProps = PropsWithChildren<{
|
|
4
4
|
foldable?: boolean;
|
|
@@ -20,3 +20,4 @@ export type ExternalPaneProps = PropsWithChildren<{
|
|
|
20
20
|
export type PaneElement = ReactElement<ExternalPaneProps, JSXElementConstructor<ExternalPaneProps>>;
|
|
21
21
|
export declare const Pane: FC<InternalPaneProps>;
|
|
22
22
|
export declare const ExternalPane: FC<PropsWithChildren<ExternalPaneProps>>;
|
|
23
|
+
export declare const isPaneElement: (node: ReactNode) => node is PaneElement;
|