@hh.ru/magritte-internal-drop-base 5.0.4

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.
@@ -0,0 +1,77 @@
1
+ import './index.css';
2
+ import { useRef, useCallback, useEffect } from 'react';
3
+
4
+ // теоретически на один активатор может быть завязано несколько дропов (например дроп и тултип)
5
+ // поэтому храним коллекцию коллбеков для каждого активатора
6
+ const intersectionCallbacks = new Map();
7
+ let observer;
8
+ // Т.к. IntersectionObserver при первом вызове observe(element) сразу вызывает коллбек для элемента
9
+ // необходимо игнорировать первый вызов коллбека после вызова observe, т.к. о изменении состояния сигнализирует только
10
+ // второй вызов коллбека. Для этого используем set элементов, для которых был вызван observe, но еще не был вызван коллбек
11
+ const ignoreImmediateCallback = new Set();
12
+ const notifyAndClearSubscriptions = (element) => {
13
+ if (ignoreImmediateCallback.has(element)) {
14
+ ignoreImmediateCallback.delete(element);
15
+ return;
16
+ }
17
+ const callbacks = intersectionCallbacks.get(element);
18
+ if (callbacks) {
19
+ callbacks.forEach((callback) => callback());
20
+ }
21
+ intersectionCallbacks.delete(element);
22
+ observer.unobserve(element);
23
+ };
24
+ const initialize = () => {
25
+ if (observer) {
26
+ return;
27
+ }
28
+ observer = new IntersectionObserver((entries) => {
29
+ entries.forEach((entry) => {
30
+ notifyAndClearSubscriptions(entry.target);
31
+ });
32
+ });
33
+ };
34
+ const observeIntersectionsOfElement = (element, callback) => {
35
+ initialize();
36
+ if (!intersectionCallbacks.has(element)) {
37
+ intersectionCallbacks.set(element, []);
38
+ ignoreImmediateCallback.add(element);
39
+ observer.observe(element);
40
+ }
41
+ intersectionCallbacks.get(element)?.push(callback);
42
+ };
43
+ const unobserveIntersectionsOfElement = (element, callback) => {
44
+ if (!element) {
45
+ return;
46
+ }
47
+ const callbacks = intersectionCallbacks.get(element);
48
+ if (!callbacks) {
49
+ return;
50
+ }
51
+ const filteredCallbacks = callbacks.filter((cb) => cb !== callback);
52
+ if (filteredCallbacks.length === 0) {
53
+ intersectionCallbacks.delete(element);
54
+ observer.unobserve(element);
55
+ return;
56
+ }
57
+ intersectionCallbacks.set(element, filteredCallbacks);
58
+ };
59
+ const useIntersectionSubscription = (activatorRef, isVisible, ignore, callback) => {
60
+ const intersectionCallbackRef = useRef(callback);
61
+ intersectionCallbackRef.current = callback;
62
+ const intersectionCallback = useCallback(() => intersectionCallbackRef.current(), []);
63
+ useEffect(() => {
64
+ if (!activatorRef.current || !isVisible || ignore) {
65
+ return;
66
+ }
67
+ const target = activatorRef.current;
68
+ observeIntersectionsOfElement(target, intersectionCallback);
69
+ // eslint-disable-next-line consistent-return
70
+ return () => {
71
+ unobserveIntersectionsOfElement(target, intersectionCallback);
72
+ };
73
+ }, [isVisible, activatorRef, intersectionCallback, ignore]);
74
+ };
75
+
76
+ export { useIntersectionSubscription };
77
+ //# sourceMappingURL=intersectionManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"intersectionManager.js","sources":["../src/intersectionManager.ts"],"sourcesContent":["import { RefObject, useCallback, useEffect, useRef } from 'react';\n\n// теоретически на один активатор может быть завязано несколько дропов (например дроп и тултип)\n// поэтому храним коллекцию коллбеков для каждого активатора\nconst intersectionCallbacks = new Map<HTMLElement, VoidFunction[]>();\nlet observer: IntersectionObserver;\n// Т.к. IntersectionObserver при первом вызове observe(element) сразу вызывает коллбек для элемента\n// необходимо игнорировать первый вызов коллбека после вызова observe, т.к. о изменении состояния сигнализирует только\n// второй вызов коллбека. Для этого используем set элементов, для которых был вызван observe, но еще не был вызван коллбек\nconst ignoreImmediateCallback = new Set<HTMLElement>();\n\nconst notifyAndClearSubscriptions = (element: HTMLElement) => {\n if (ignoreImmediateCallback.has(element)) {\n ignoreImmediateCallback.delete(element);\n return;\n }\n const callbacks = intersectionCallbacks.get(element);\n if (callbacks) {\n callbacks.forEach((callback) => callback());\n }\n intersectionCallbacks.delete(element);\n observer.unobserve(element);\n};\n\nconst initialize = () => {\n if (observer) {\n return;\n }\n\n observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n notifyAndClearSubscriptions(entry.target as HTMLElement);\n });\n });\n};\n\nconst observeIntersectionsOfElement = (element: HTMLElement, callback: VoidFunction) => {\n initialize();\n if (!intersectionCallbacks.has(element)) {\n intersectionCallbacks.set(element, []);\n ignoreImmediateCallback.add(element);\n observer.observe(element);\n }\n intersectionCallbacks.get(element)?.push(callback);\n};\n\nconst unobserveIntersectionsOfElement = (element: HTMLElement | null, callback: VoidFunction) => {\n if (!element) {\n return;\n }\n const callbacks = intersectionCallbacks.get(element);\n if (!callbacks) {\n return;\n }\n const filteredCallbacks = callbacks.filter((cb) => cb !== callback);\n if (filteredCallbacks.length === 0) {\n intersectionCallbacks.delete(element);\n observer.unobserve(element);\n return;\n }\n\n intersectionCallbacks.set(element, filteredCallbacks);\n};\n\nexport const useIntersectionSubscription = (\n activatorRef: RefObject<HTMLElement>,\n isVisible: boolean,\n ignore: boolean,\n callback: VoidFunction\n): void => {\n const intersectionCallbackRef = useRef(callback);\n intersectionCallbackRef.current = callback;\n\n const intersectionCallback = useCallback(() => intersectionCallbackRef.current(), []);\n\n useEffect(() => {\n if (!activatorRef.current || !isVisible || ignore) {\n return;\n }\n const target = activatorRef.current;\n observeIntersectionsOfElement(target, intersectionCallback);\n // eslint-disable-next-line consistent-return\n return () => {\n unobserveIntersectionsOfElement(target, intersectionCallback);\n };\n }, [isVisible, activatorRef, intersectionCallback, ignore]);\n};\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@hh.ru/magritte-internal-drop-base",
3
+ "version": "5.0.4",
4
+ "main": "index.js",
5
+ "types": "index.d.ts",
6
+ "sideEffects": [
7
+ "index.css"
8
+ ],
9
+ "scripts": {
10
+ "build": "yarn root:build $(pwd)",
11
+ "build-test-branch": "yarn root:build-test-branch $(pwd)",
12
+ "changelog": "yarn root:changelog $(pwd)",
13
+ "prepack": "yarn root:prepack $(pwd)",
14
+ "postpublish": "yarn root:postpublish $(pwd)",
15
+ "stylelint-test": "yarn root:stylelint-test $(pwd)",
16
+ "eslint-test": "yarn root:eslint-test $(pwd)",
17
+ "ts-config": "yarn root:ts-config $(pwd)",
18
+ "ts-check": "yarn root:ts-check $(pwd)",
19
+ "test": "yarn root:test $(pwd)"
20
+ },
21
+ "dependencies": {
22
+ "@hh.ru/magritte-common-func-utils": "1.3.6",
23
+ "@hh.ru/magritte-common-keyboard": "3.0.2",
24
+ "@hh.ru/magritte-common-metrics": "2.0.2",
25
+ "@hh.ru/magritte-common-mouse": "1.1.8",
26
+ "@hh.ru/magritte-common-use-multiple-refs": "1.1.2",
27
+ "@hh.ru/magritte-common-use-when-font-loaded": "1.0.4"
28
+ },
29
+ "peerDependencies": {
30
+ "react": ">=18.2.0",
31
+ "react-dom": ">=18.2.0",
32
+ "react-transition-group": ">=4.4.5"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ },
37
+ "gitHead": "b660dd64fca3eaad5ec44ea9a73f92bb0d9694aa"
38
+ }
@@ -0,0 +1,7 @@
1
+ import { RefObject } from 'react';
2
+ interface SubscriptionCallback {
3
+ (target: HTMLElement, deltaX: number, deltaY: number): void;
4
+ }
5
+ export declare const deleteScrollSubscription: (callback: SubscriptionCallback) => void;
6
+ export declare const useScrollSubscription: (activatorRef: RefObject<HTMLElement>, dropRef: RefObject<HTMLElement>, isVisible: boolean) => void;
7
+ export {};
@@ -0,0 +1,131 @@
1
+ import './index.css';
2
+ import { useRef, useCallback, useEffect } from 'react';
3
+ import { requestAnimation } from '@hh.ru/magritte-common-func-utils';
4
+
5
+ let isInitialized = false;
6
+ const scrollSubscriptions = [];
7
+ const canceledScrollSubscriptions = new Map();
8
+ const lastScrollPosition = new Map();
9
+ const scrollHandler = (event) => {
10
+ const target = event.target;
11
+ if (!target) {
12
+ return;
13
+ }
14
+ const lastPosition = lastScrollPosition.get(target) || null;
15
+ if (lastPosition === null) {
16
+ // если мы не знаем предыдущую позицию для данного скроллящегося контейнера, то мы не сможем посчитать дельту
17
+ // поэтому просто запоминаем текущую позицию и предотвращаем дальнейший обработку события
18
+ lastScrollPosition.set(target, { x: target.scrollLeft, y: target.scrollTop });
19
+ event.preventDefault();
20
+ event.stopPropagation();
21
+ return;
22
+ }
23
+ // обращения к scrollLeft и scrollTop вызывают рефлоу, поэтому кешируем их значения
24
+ const scrollValues = { scrollLeft: target.scrollLeft, scrollTop: target.scrollTop };
25
+ const scrollDelta = {
26
+ x: scrollValues.scrollLeft - lastPosition.x,
27
+ y: scrollValues.scrollTop - lastPosition.y,
28
+ };
29
+ lastScrollPosition.set(target, { x: scrollValues.scrollLeft, y: scrollValues.scrollTop });
30
+ if (scrollSubscriptions.length === 0) {
31
+ return;
32
+ }
33
+ const canceledSubscriptions = canceledScrollSubscriptions.get(target);
34
+ const subscriptions = canceledSubscriptions === undefined
35
+ ? scrollSubscriptions
36
+ : scrollSubscriptions.filter((subscription) => !canceledSubscriptions.includes(subscription));
37
+ subscriptions.forEach((subscription) => subscription(target, scrollDelta.x, scrollDelta.y));
38
+ };
39
+ const initialize = () => {
40
+ if (isInitialized) {
41
+ return;
42
+ }
43
+ isInitialized = true;
44
+ document.addEventListener('scroll', scrollHandler, { capture: true, passive: false });
45
+ };
46
+ const suspendSubscription = (callback) => {
47
+ const index = scrollSubscriptions.indexOf(callback);
48
+ if (index !== -1) {
49
+ scrollSubscriptions.splice(index, 1);
50
+ }
51
+ };
52
+ const reviveSubscription = (callback) => {
53
+ initialize();
54
+ scrollSubscriptions.push(callback);
55
+ };
56
+ const deleteScrollSubscription = (callback) => {
57
+ const index = scrollSubscriptions.indexOf(callback);
58
+ if (index !== -1) {
59
+ scrollSubscriptions.splice(index, 1);
60
+ }
61
+ for (const [key, callbacks] of canceledScrollSubscriptions.entries()) {
62
+ const index = callbacks.indexOf(callback);
63
+ if (index !== -1) {
64
+ canceledScrollSubscriptions.set(key, callbacks.splice(index, 1));
65
+ }
66
+ }
67
+ };
68
+ const unsubscribeFromTarget = (target, callback) => {
69
+ if (!canceledScrollSubscriptions.has(target)) {
70
+ canceledScrollSubscriptions.set(target, []);
71
+ }
72
+ canceledScrollSubscriptions.get(target)?.push(callback);
73
+ };
74
+ const updateDropTranslation = requestAnimation((_, params) => {
75
+ const { dropRef, deltaX, deltaY, currentTranslationRef } = params;
76
+ if (!dropRef.current) {
77
+ return;
78
+ }
79
+ currentTranslationRef.current.x -= deltaX;
80
+ currentTranslationRef.current.y -= deltaY;
81
+ dropRef.current.style.transform = `translate3d(${currentTranslationRef.current.x}px, ${currentTranslationRef.current.y}px, 0)`;
82
+ });
83
+ const useScrollSubscription = (activatorRef, dropRef, isVisible) => {
84
+ /**
85
+ * список id скроллящихся элементов для которых была выполнена проверка
86
+ * влияет ли их скролл на взаимное положение активатора и дропа
87
+ */
88
+ const processedScrollContainers = useRef(new Set());
89
+ /**
90
+ * текущее значение трансформации дропа
91
+ * при каждом ререндере сбрасывается, т.к. дроп при каждом ререндере пересчитывает свою позицию
92
+ */
93
+ const currentTranslationRef = useRef({ x: 0, y: 0 });
94
+ currentTranslationRef.current = { x: 0, y: 0 };
95
+ /**
96
+ * ссылка на последнее значение расстояния между активатором и дропом,
97
+ * используется для определения изменения взаимного положения активатора и дропа
98
+ */
99
+ const visibleRef = useRef(isVisible);
100
+ visibleRef.current = isVisible;
101
+ const scrollCallback = useCallback((target, deltaX, deltaY) => {
102
+ if (!visibleRef.current || !dropRef.current || !activatorRef.current) {
103
+ return;
104
+ }
105
+ // Если это первый скролл данного контейнера, то проверяем содержит ли он активатор и дроп
106
+ // Если он содержит только что-то одно, значит его скролл будет влиять на взаимное расположение дропа
107
+ // и активатора, в этом случае помечяем его как обработанный и меняем позицию дропа при его скролле.
108
+ // Если же он не влияет на взаимное расположение дропа и активатора, то отписываемся от дальнейших
109
+ // оповещений о его скролле.
110
+ if (!processedScrollContainers.current.has(target)) {
111
+ const targetContainsActivator = target.contains(activatorRef.current);
112
+ const targetContainsDrop = target.contains(dropRef.current);
113
+ if (targetContainsActivator === targetContainsDrop) {
114
+ unsubscribeFromTarget(target, scrollCallback);
115
+ return;
116
+ }
117
+ processedScrollContainers.current.add(target);
118
+ }
119
+ updateDropTranslation({ deltaX, deltaY, dropRef, currentTranslationRef });
120
+ }, [activatorRef, dropRef]);
121
+ useEffect(() => {
122
+ // eslint-disable-next-line no-unused-expressions
123
+ isVisible ? reviveSubscription(scrollCallback) : suspendSubscription(scrollCallback);
124
+ }, [isVisible, scrollCallback]);
125
+ useEffect(() => {
126
+ return () => deleteScrollSubscription(scrollCallback);
127
+ }, [scrollCallback]);
128
+ };
129
+
130
+ export { deleteScrollSubscription, useScrollSubscription };
131
+ //# sourceMappingURL=scrollManager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scrollManager.js","sources":["../src/scrollManager.ts"],"sourcesContent":["import { MutableRefObject, RefObject, useCallback, useEffect, useRef } from 'react';\n\nimport { requestAnimation } from '@hh.ru/magritte-common-func-utils';\n\nlet isInitialized = false;\n\ninterface SubscriptionCallback {\n (target: HTMLElement, deltaX: number, deltaY: number): void;\n}\n\nconst scrollSubscriptions: Array<SubscriptionCallback> = [];\nconst canceledScrollSubscriptions: Map<HTMLElement, Array<SubscriptionCallback>> = new Map();\nconst lastScrollPosition: Map<HTMLElement, { x: number; y: number }> = new Map();\n\nconst scrollHandler = (event: Event) => {\n const target = event.target as HTMLElement;\n if (!target) {\n return;\n }\n\n const lastPosition = lastScrollPosition.get(target) || null;\n if (lastPosition === null) {\n // если мы не знаем предыдущую позицию для данного скроллящегося контейнера, то мы не сможем посчитать дельту\n // поэтому просто запоминаем текущую позицию и предотвращаем дальнейший обработку события\n lastScrollPosition.set(target, { x: target.scrollLeft, y: target.scrollTop });\n event.preventDefault();\n event.stopPropagation();\n return;\n }\n\n // обращения к scrollLeft и scrollTop вызывают рефлоу, поэтому кешируем их значения\n const scrollValues = { scrollLeft: target.scrollLeft, scrollTop: target.scrollTop };\n const scrollDelta = {\n x: scrollValues.scrollLeft - lastPosition.x,\n y: scrollValues.scrollTop - lastPosition.y,\n };\n\n lastScrollPosition.set(target, { x: scrollValues.scrollLeft, y: scrollValues.scrollTop });\n\n if (scrollSubscriptions.length === 0) {\n return;\n }\n const canceledSubscriptions = canceledScrollSubscriptions.get(target);\n\n const subscriptions =\n canceledSubscriptions === undefined\n ? scrollSubscriptions\n : scrollSubscriptions.filter((subscription) => !canceledSubscriptions.includes(subscription));\n\n subscriptions.forEach((subscription) => subscription(target, scrollDelta.x, scrollDelta.y));\n};\n\nconst initialize = () => {\n if (isInitialized) {\n return;\n }\n\n isInitialized = true;\n document.addEventListener('scroll', scrollHandler, { capture: true, passive: false });\n};\n\nconst suspendSubscription = (callback: SubscriptionCallback): void => {\n const index = scrollSubscriptions.indexOf(callback);\n if (index !== -1) {\n scrollSubscriptions.splice(index, 1);\n }\n};\n\nconst reviveSubscription = (callback: SubscriptionCallback): void => {\n initialize();\n scrollSubscriptions.push(callback);\n};\n\nexport const deleteScrollSubscription = (callback: SubscriptionCallback): void => {\n const index = scrollSubscriptions.indexOf(callback);\n if (index !== -1) {\n scrollSubscriptions.splice(index, 1);\n }\n for (const [key, callbacks] of canceledScrollSubscriptions.entries()) {\n const index = callbacks.indexOf(callback);\n if (index !== -1) {\n canceledScrollSubscriptions.set(key, callbacks.splice(index, 1));\n }\n }\n};\n\nconst unsubscribeFromTarget = (target: HTMLElement, callback: SubscriptionCallback): void => {\n if (!canceledScrollSubscriptions.has(target)) {\n canceledScrollSubscriptions.set(target, []);\n }\n canceledScrollSubscriptions.get(target)?.push(callback);\n};\n\nconst updateDropTranslation = requestAnimation(\n (\n _,\n params: {\n dropRef: RefObject<HTMLElement>;\n deltaX: number;\n deltaY: number;\n currentTranslationRef: MutableRefObject<{ x: number; y: number }>;\n }\n ) => {\n const { dropRef, deltaX, deltaY, currentTranslationRef } = params;\n if (!dropRef.current) {\n return;\n }\n currentTranslationRef.current.x -= deltaX;\n currentTranslationRef.current.y -= deltaY;\n dropRef.current.style.transform = `translate3d(${currentTranslationRef.current.x}px, ${currentTranslationRef.current.y}px, 0)`;\n }\n);\n\nexport const useScrollSubscription = (\n activatorRef: RefObject<HTMLElement>,\n dropRef: RefObject<HTMLElement>,\n isVisible: boolean\n): void => {\n /**\n * список id скроллящихся элементов для которых была выполнена проверка\n * влияет ли их скролл на взаимное положение активатора и дропа\n */\n const processedScrollContainers = useRef<Set<HTMLElement>>(new Set());\n /**\n * текущее значение трансформации дропа\n * при каждом ререндере сбрасывается, т.к. дроп при каждом ререндере пересчитывает свою позицию\n */\n const currentTranslationRef = useRef({ x: 0, y: 0 });\n currentTranslationRef.current = { x: 0, y: 0 };\n /**\n * ссылка на последнее значение расстояния между активатором и дропом,\n * используется для определения изменения взаимного положения активатора и дропа\n */\n const visibleRef = useRef(isVisible);\n visibleRef.current = isVisible;\n\n const scrollCallback = useCallback(\n (target: HTMLElement, deltaX: number, deltaY: number) => {\n if (!visibleRef.current || !dropRef.current || !activatorRef.current) {\n return;\n }\n\n // Если это первый скролл данного контейнера, то проверяем содержит ли он активатор и дроп\n // Если он содержит только что-то одно, значит его скролл будет влиять на взаимное расположение дропа\n // и активатора, в этом случае помечяем его как обработанный и меняем позицию дропа при его скролле.\n // Если же он не влияет на взаимное расположение дропа и активатора, то отписываемся от дальнейших\n // оповещений о его скролле.\n if (!processedScrollContainers.current.has(target)) {\n const targetContainsActivator = target.contains(activatorRef.current);\n const targetContainsDrop = target.contains(dropRef.current);\n\n if (targetContainsActivator === targetContainsDrop) {\n unsubscribeFromTarget(target, scrollCallback);\n return;\n }\n processedScrollContainers.current.add(target);\n }\n\n updateDropTranslation({ deltaX, deltaY, dropRef, currentTranslationRef });\n },\n [activatorRef, dropRef]\n );\n\n useEffect(() => {\n // eslint-disable-next-line no-unused-expressions\n isVisible ? reviveSubscription(scrollCallback) : suspendSubscription(scrollCallback);\n }, [isVisible, scrollCallback]);\n\n useEffect(() => {\n return () => deleteScrollSubscription(scrollCallback);\n }, [scrollCallback]);\n};\n"],"names":[],"mappings":";;;AAIA,IAAI,aAAa,GAAG,KAAK,CAAC;AAM1B,MAAM,mBAAmB,GAAgC,EAAE,CAAC;AAC5D,MAAM,2BAA2B,GAAkD,IAAI,GAAG,EAAE,CAAC;AAC7F,MAAM,kBAAkB,GAA+C,IAAI,GAAG,EAAE,CAAC;AAEjF,MAAM,aAAa,GAAG,CAAC,KAAY,KAAI;AACnC,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,MAAqB,CAAC;IAC3C,IAAI,CAAC,MAAM,EAAE;QACT,OAAO;AACV,KAAA;IAED,MAAM,YAAY,GAAG,kBAAkB,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC5D,IAAI,YAAY,KAAK,IAAI,EAAE;;;AAGvB,QAAA,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,CAAC,UAAU,EAAE,CAAC,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;QAC9E,KAAK,CAAC,cAAc,EAAE,CAAC;QACvB,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,OAAO;AACV,KAAA;;AAGD,IAAA,MAAM,YAAY,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,EAAE,MAAM,CAAC,SAAS,EAAE,CAAC;AACpF,IAAA,MAAM,WAAW,GAAG;AAChB,QAAA,CAAC,EAAE,YAAY,CAAC,UAAU,GAAG,YAAY,CAAC,CAAC;AAC3C,QAAA,CAAC,EAAE,YAAY,CAAC,SAAS,GAAG,YAAY,CAAC,CAAC;KAC7C,CAAC;AAEF,IAAA,kBAAkB,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,EAAE,YAAY,CAAC,UAAU,EAAE,CAAC,EAAE,YAAY,CAAC,SAAS,EAAE,CAAC,CAAC;AAE1F,IAAA,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE;QAClC,OAAO;AACV,KAAA;IACD,MAAM,qBAAqB,GAAG,2BAA2B,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AAEtE,IAAA,MAAM,aAAa,GACf,qBAAqB,KAAK,SAAS;AAC/B,UAAE,mBAAmB;AACrB,UAAE,mBAAmB,CAAC,MAAM,CAAC,CAAC,YAAY,KAAK,CAAC,qBAAqB,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC,CAAC;IAEtG,aAAa,CAAC,OAAO,CAAC,CAAC,YAAY,KAAK,YAAY,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,EAAE,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC;AAChG,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,MAAK;AACpB,IAAA,IAAI,aAAa,EAAE;QACf,OAAO;AACV,KAAA;IAED,aAAa,GAAG,IAAI,CAAC;AACrB,IAAA,QAAQ,CAAC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;AAC1F,CAAC,CAAC;AAEF,MAAM,mBAAmB,GAAG,CAAC,QAA8B,KAAU;IACjE,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACpD,IAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AACd,QAAA,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACxC,KAAA;AACL,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,CAAC,QAA8B,KAAU;AAChE,IAAA,UAAU,EAAE,CAAC;AACb,IAAA,mBAAmB,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;AACvC,CAAC,CAAC;AAEW,MAAA,wBAAwB,GAAG,CAAC,QAA8B,KAAU;IAC7E,MAAM,KAAK,GAAG,mBAAmB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AACpD,IAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AACd,QAAA,mBAAmB,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;AACxC,KAAA;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,IAAI,2BAA2B,CAAC,OAAO,EAAE,EAAE;QAClE,MAAM,KAAK,GAAG,SAAS,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;AAC1C,QAAA,IAAI,KAAK,KAAK,CAAC,CAAC,EAAE;AACd,YAAA,2BAA2B,CAAC,GAAG,CAAC,GAAG,EAAE,SAAS,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpE,SAAA;AACJ,KAAA;AACL,EAAE;AAEF,MAAM,qBAAqB,GAAG,CAAC,MAAmB,EAAE,QAA8B,KAAU;AACxF,IAAA,IAAI,CAAC,2BAA2B,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;AAC1C,QAAA,2BAA2B,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AAC/C,KAAA;IACD,2BAA2B,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;AAC5D,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,gBAAgB,CAC1C,CACI,CAAC,EACD,MAKC,KACD;IACA,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,qBAAqB,EAAE,GAAG,MAAM,CAAC;AAClE,IAAA,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE;QAClB,OAAO;AACV,KAAA;AACD,IAAA,qBAAqB,CAAC,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC;AAC1C,IAAA,qBAAqB,CAAC,OAAO,CAAC,CAAC,IAAI,MAAM,CAAC;IAC1C,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,eAAe,qBAAqB,CAAC,OAAO,CAAC,CAAC,OAAO,qBAAqB,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC;AACnI,CAAC,CACJ,CAAC;AAEW,MAAA,qBAAqB,GAAG,CACjC,YAAoC,EACpC,OAA+B,EAC/B,SAAkB,KACZ;AACN;;;AAGG;IACH,MAAM,yBAAyB,GAAG,MAAM,CAAmB,IAAI,GAAG,EAAE,CAAC,CAAC;AACtE;;;AAGG;AACH,IAAA,MAAM,qBAAqB,GAAG,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;AACrD,IAAA,qBAAqB,CAAC,OAAO,GAAG,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AAC/C;;;AAGG;AACH,IAAA,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;AACrC,IAAA,UAAU,CAAC,OAAO,GAAG,SAAS,CAAC;IAE/B,MAAM,cAAc,GAAG,WAAW,CAC9B,CAAC,MAAmB,EAAE,MAAc,EAAE,MAAc,KAAI;AACpD,QAAA,IAAI,CAAC,UAAU,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE;YAClE,OAAO;AACV,SAAA;;;;;;QAOD,IAAI,CAAC,yBAAyB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE;YAChD,MAAM,uBAAuB,GAAG,MAAM,CAAC,QAAQ,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;YACtE,MAAM,kBAAkB,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YAE5D,IAAI,uBAAuB,KAAK,kBAAkB,EAAE;AAChD,gBAAA,qBAAqB,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;gBAC9C,OAAO;AACV,aAAA;AACD,YAAA,yBAAyB,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;AACjD,SAAA;QAED,qBAAqB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,qBAAqB,EAAE,CAAC,CAAC;AAC9E,KAAC,EACD,CAAC,YAAY,EAAE,OAAO,CAAC,CAC1B,CAAC;IAEF,SAAS,CAAC,MAAK;;AAEX,QAAA,SAAS,GAAG,kBAAkB,CAAC,cAAc,CAAC,GAAG,mBAAmB,CAAC,cAAc,CAAC,CAAC;AACzF,KAAC,EAAE,CAAC,SAAS,EAAE,cAAc,CAAC,CAAC,CAAC;IAEhC,SAAS,CAAC,MAAK;AACX,QAAA,OAAO,MAAM,wBAAwB,CAAC,cAAc,CAAC,CAAC;AAC1D,KAAC,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC;AACzB;;;;"}
package/types.d.ts ADDED
@@ -0,0 +1,210 @@
1
+ import type { RefObject, ReactNode, CSSProperties } from 'react';
2
+ import type { CSSTransitionClassNames } from 'react-transition-group/CSSTransition';
3
+ export interface DropBasePermanentProps {
4
+ /** DOM нода хоста в рамках которого нужно рендерить компонент, по дефолту рендер будет в body */
5
+ host?: RefObject<HTMLElement>;
6
+ /** Флаг отвечает за показ компонента, `true` — показать, `false` — скрыть */
7
+ visible?: boolean;
8
+ /** Элемент активатор, относительно которого показывать всплывающую подсказку */
9
+ activatorRef: RefObject<HTMLElement>;
10
+ /** Расстояние от края DropBase до середины стрелки, если стрелки нет — то не указывать*/
11
+ arrowGuardDistance?: ArrowGuardDistance;
12
+ /** Задает виртуальный viewport */
13
+ preferredViewport?: RefObject<HTMLElement>;
14
+ /** Рендер функция, которая должна вернуть сам Drop, в аргументах передается вычисляемая позиция */
15
+ children: (props: DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseVerticalPositionWithoutCenter | DropBaseHorizontalPositionWithoutCenter, metrics: RenderFuncMetricsArgs) => ReactNode;
16
+ /**
17
+ * Колбек вызываемый при необходимости закрыть компонент в результате внешних событий. Например при клике
18
+ * вовне дропа или при перекрытии активатора другим элементом. Должен устанавливать флаг visible в false.
19
+ * */
20
+ onClose?: VoidFunction;
21
+ /** Флаг — закрывать ли компонент по клику извне */
22
+ closeByClickOutside?: boolean;
23
+ /** Флаг — устанавливать ли фокус внутри дропа при открытии */
24
+ autoFocusWhenOpened?: boolean;
25
+ /** Маппинг классов для анимации свойство classNames в CSSTransition */
26
+ animationClassNames: CSSTransitionClassNames;
27
+ /** Время анимации в ms, свойство timeout в CSSTransition */
28
+ animationTimeout: number | {
29
+ appear?: number | undefined;
30
+ enter?: number | undefined;
31
+ exit?: number | undefined;
32
+ };
33
+ /** Защитное расстояние в px от активатора до DropBase */
34
+ guardDistance?: number;
35
+ /** Aria role для задания семантики в screen reader */
36
+ role?: string;
37
+ /** Флаг позволяет занять максимально возможную высоту компоненту, по viewport */
38
+ occupyAllAvailableViewportHeight?: boolean;
39
+ /**
40
+ * Флаг, при выставлении которого в true DropBase будет выпадать в указанном направлении даже
41
+ * если при этом он не умещается во Viewport
42
+ * */
43
+ forcePosition?: boolean;
44
+ /** Флаг включающий автоматическое выставление ширины равной ширине активатора */
45
+ widthEqualToActivator?: boolean;
46
+ /** Флаг — включена ли стрелочная навигация среди элементов в выпадающем слое */
47
+ arrowNavigation?: boolean;
48
+ /** Флаг отключающий вызов onClose при пересечении активатора с другим элементом на странице */
49
+ ignoreIntersections?: boolean;
50
+ style?: CSSProperties;
51
+ }
52
+ export type BaseArrowGuardDistance<K extends DropBaseHorizontalPosition | DropBaseVerticalPosition> = {
53
+ [D in DropBaseProps<K>['direction']]: {
54
+ [A in DropBaseProps<K>['alignment']]: number;
55
+ };
56
+ };
57
+ export type ArrowGuardDistance = BaseArrowGuardDistance<DropBaseHorizontalPosition> & BaseArrowGuardDistance<DropBaseVerticalPosition>;
58
+ export interface RenderFuncMetricsArgs {
59
+ metrics: {
60
+ top: number;
61
+ left: number;
62
+ height?: number | string;
63
+ };
64
+ dropScrollableContainerRef?: RefObject<HTMLDivElement>;
65
+ }
66
+ export interface ActivatorOffset {
67
+ offsetLeft: number;
68
+ offsetTop: number;
69
+ }
70
+ export interface DropBaseVerticalPosition {
71
+ direction: 'top' | 'bottom';
72
+ alignment: 'left' | 'right' | 'center';
73
+ }
74
+ export interface DropBaseHorizontalPosition {
75
+ direction: 'left' | 'right';
76
+ alignment: 'top' | 'bottom' | 'center';
77
+ }
78
+ export interface DropBaseVerticalPositionWithoutCenter {
79
+ direction: 'top' | 'bottom';
80
+ alignment: 'left' | 'right';
81
+ }
82
+ export interface DropBaseHorizontalPositionWithoutCenter {
83
+ direction: 'left' | 'right';
84
+ alignment: 'top' | 'bottom';
85
+ }
86
+ export type DropBaseProps<T extends DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseVerticalPositionWithoutCenter | DropBaseHorizontalPositionWithoutCenter> = DropBasePermanentProps & T;
87
+ export interface DropMetrics {
88
+ left: number;
89
+ top: number;
90
+ height: number | string;
91
+ }
92
+ export interface RectPosition {
93
+ top: number;
94
+ left: number;
95
+ right: number;
96
+ bottom: number;
97
+ dropMetrics: DropMetrics;
98
+ viewportMetrics: CustomVisualViewport;
99
+ }
100
+ export interface DOMRectLike {
101
+ top: number;
102
+ bottom: number;
103
+ left: number;
104
+ right: number;
105
+ height: number;
106
+ width: number;
107
+ }
108
+ export interface CalculateRect<T> {
109
+ (props: {
110
+ activatorMetrics: DOMRect;
111
+ dropMetrics: DOMRectLike;
112
+ viewportMetrics: VisualViewport;
113
+ preferredViewportMetrics: CustomVisualViewport;
114
+ direction: T;
115
+ activatorOffset: ActivatorOffset;
116
+ guardDistance: number;
117
+ arrowGuardDistance?: number;
118
+ occupyAllAvailableViewportHeight?: boolean;
119
+ }): RectPosition;
120
+ }
121
+ export type CalculateRectType<K extends DropBaseVerticalPosition | DropBaseHorizontalPosition> = {
122
+ [D in DropBaseProps<K>['direction']]: {
123
+ [A in DropBaseProps<K>['alignment']]: CalculateRect<D>;
124
+ };
125
+ };
126
+ export interface CustomVisualViewport {
127
+ pageTop: number;
128
+ pageLeft: number;
129
+ width: number;
130
+ height: number;
131
+ }
132
+ interface BaseAlignPositionArgs<T> {
133
+ activatorMetrics: DOMRect;
134
+ dropMetrics: DOMRectLike;
135
+ viewportMetrics: VisualViewport;
136
+ direction: T;
137
+ activatorOffset: ActivatorOffset;
138
+ shift: number;
139
+ isNegativeArrowShift?: boolean;
140
+ arrowGuardDistance?: number;
141
+ guardDistance: number;
142
+ occupyAllAvailableViewportHeight?: boolean;
143
+ preferredViewportMetrics: CustomVisualViewport;
144
+ }
145
+ export interface BaseAlignPosition<T> {
146
+ (args: BaseAlignPositionArgs<T>): RectPosition;
147
+ }
148
+ export interface GetEdgeOppositeDirectionArgs {
149
+ activatorPosition: number;
150
+ viewportShift: number;
151
+ activatorOffset: number;
152
+ shift: number;
153
+ isNegativeArrowShift: boolean;
154
+ activatorSize: number;
155
+ arrowGuardDistance?: number;
156
+ }
157
+ export interface GetEageCoincidingWithDirectionArgs {
158
+ activatorPosition: number;
159
+ dropSize: number;
160
+ viewportShift: number;
161
+ isNegativePosition: boolean;
162
+ activatorOffset: number;
163
+ activatorSize: number;
164
+ guardDistance: number;
165
+ }
166
+ export interface GetPointToCenterActivator {
167
+ point: number;
168
+ offsetPoint: number;
169
+ contentSize: number;
170
+ activatorSize: number;
171
+ }
172
+ export interface CalculateDropHeightAvailableViewportResult {
173
+ /** Top позиция дроп компонента относительно host */
174
+ top: number;
175
+ /** Max высота, которую может занимать DropBase */
176
+ height: number;
177
+ /** Left позиция дроп компонента относительно host */
178
+ left: number;
179
+ /** Позиция дроп компонента относительно viewport */
180
+ topPositionForViewport: number;
181
+ }
182
+ export interface CalculateDropHeightAvailableViewportArgs {
183
+ (props: {
184
+ /** Top позиция drop компонента относительно host */
185
+ topPositionForDrop: number;
186
+ /** Left позиция drop компонента относительно host */
187
+ leftPositionForDrop: number;
188
+ /**
189
+ * Позиция дроп компонента относительно viewport,
190
+ * когда host отличный от body, метрика top drop-base не совпадет с этой точкой
191
+ * */
192
+ topPositionForViewport: number;
193
+ /**
194
+ * Метрики viewport в рамках которого будет распологаться компонент
195
+ * */
196
+ preferredViewportMetrics: CustomVisualViewport;
197
+ /**
198
+ * Метрики выпадающего блока (top, left). Height содержит
199
+ * число в случае если включена опция occupyAllAvailableViewportHeight,
200
+ * иначе там 'auto'
201
+ */
202
+ dropMetrics: DOMRectLike;
203
+ }): CalculateDropHeightAvailableViewportResult;
204
+ }
205
+ export interface Metrics {
206
+ top: number;
207
+ left: number;
208
+ height?: number | string;
209
+ }
210
+ export {};
package/types.js ADDED
@@ -0,0 +1,3 @@
1
+ import './index.css';
2
+
3
+ //# sourceMappingURL=types.js.map
package/types.js.map ADDED
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,53 @@
1
+ import { RefObject } from 'react';
2
+ import type { ActivatorOffset, DropBaseProps, DropMetrics, CustomVisualViewport, ArrowGuardDistance, DOMRectLike, DropBaseHorizontalPosition, DropBaseVerticalPosition, DropBaseHorizontalPositionWithoutCenter, DropBaseVerticalPositionWithoutCenter, Metrics } from './types';
3
+ export declare const allowedAlignmentForVerticalDirection: readonly ["left", "right", "center"];
4
+ export declare const allowedAlignmentForHorizontalDirection: readonly ["top", "bottom", "center"];
5
+ export declare const allowedAlignmentForVerticalDirectionWithoutCenter: readonly ["left", "right"];
6
+ export declare const allowedAlignmentForHorizontalDirectionWithoutCenter: readonly ["top", "bottom"];
7
+ export declare const verticalDirections: readonly ["top", "bottom"];
8
+ export declare const horizontalDirections: readonly ["left", "right"];
9
+ export declare const START_OFFSET = -10000;
10
+ export declare const INITIAL_HEIGHT_VALUE = "force-initial-height";
11
+ interface FindDynamicPositionHor {
12
+ directions: typeof horizontalDirections;
13
+ alignments: typeof allowedAlignmentForHorizontalDirection | typeof allowedAlignmentForHorizontalDirectionWithoutCenter;
14
+ }
15
+ interface FindDynamicPositionVert {
16
+ directions: typeof verticalDirections;
17
+ alignments: typeof allowedAlignmentForVerticalDirection | typeof allowedAlignmentForVerticalDirectionWithoutCenter;
18
+ }
19
+ interface FindDynamicPositionElementMetrics {
20
+ activatorMetrics: DOMRect;
21
+ dropMetrics: DOMRectLike;
22
+ viewportMetrics: CustomVisualViewport;
23
+ activatorOffset: ActivatorOffset;
24
+ forceFitIntoViewport?: boolean;
25
+ guardDistance: number;
26
+ arrowGuardDistance?: ArrowGuardDistance;
27
+ occupyAllAvailableViewportHeight: boolean;
28
+ }
29
+ type ResultPosition = {
30
+ viewportMetrics: CustomVisualViewport;
31
+ hasScroll?: boolean;
32
+ dropMetricsRelativeToViewport: {
33
+ top: number;
34
+ bottom: number;
35
+ left: number;
36
+ right: number;
37
+ };
38
+ dropMetrics: DropMetrics;
39
+ } & (DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseHorizontalPositionWithoutCenter | DropBaseVerticalPositionWithoutCenter);
40
+ type GetDropMetricsByPositionAndAlignment<T extends DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseHorizontalPositionWithoutCenter | DropBaseVerticalPositionWithoutCenter> = FindDynamicPositionElementMetrics & Pick<DropBaseProps<T>, 'direction' | 'alignment'>;
41
+ export declare const getDropMetricsByPositionAndAlignment: <T extends DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseVerticalPositionWithoutCenter | DropBaseHorizontalPositionWithoutCenter>({ activatorMetrics, dropMetrics, viewportMetrics, direction, alignment, arrowGuardDistance, activatorOffset, forceFitIntoViewport, guardDistance, occupyAllAvailableViewportHeight, }: GetDropMetricsByPositionAndAlignment<T>) => ResultPosition | null;
42
+ export declare function findDynamicPosition<T extends FindDynamicPositionHor | FindDynamicPositionVert>({ activatorMetrics, arrowGuardDistance, dropMetrics, viewportMetrics, activatorOffset, guardDistance, occupyAllAvailableViewportHeight, }: FindDynamicPositionElementMetrics, { directions, alignments }: T): ResultPosition | null;
43
+ export type RenderParamsProps<T extends DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseHorizontalPositionWithoutCenter | DropBaseVerticalPositionWithoutCenter> = Omit<DropBaseProps<T>, 'children' | 'animationClassNames' | 'animationTimeout' | 'guardDistance' | 'role'> & {
44
+ dropElementRef: RefObject<HTMLElement>;
45
+ dropScrollableContainerRef: RefObject<HTMLElement>;
46
+ guardDistance: number;
47
+ widthEqualToActivator?: boolean;
48
+ };
49
+ export declare const useRenderParams: <T extends DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseVerticalPositionWithoutCenter | DropBaseHorizontalPositionWithoutCenter>({ direction, alignment, activatorRef, dropElementRef, host, arrowGuardDistance, preferredViewport, visible, guardDistance, occupyAllAvailableViewportHeight, dropScrollableContainerRef, forcePosition, widthEqualToActivator, }: RenderParamsProps<T>) => {
50
+ metrics: Metrics;
51
+ position: DropBaseHorizontalPosition | DropBaseVerticalPosition | DropBaseHorizontalPositionWithoutCenter | DropBaseVerticalPositionWithoutCenter;
52
+ };
53
+ export {};