@hh.ru/magritte-internal-drop-base 7.0.16 → 7.0.18
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/DropBase.d.ts +1 -5
- package/DropBase.js +1 -1
- package/findBestFitPlacement.js +1 -1
- package/findBestFitPlacement.js.map +1 -1
- package/index.css +1 -1
- package/index.d.ts +1 -0
- package/index.js +2 -0
- package/index.js.map +1 -1
- package/package.json +2 -2
- package/positionManager.js +8 -2
- package/positionManager.js.map +1 -1
- package/useArrayMemo.d.ts +3 -0
- package/useArrayMemo.js +20 -0
- package/useArrayMemo.js.map +1 -0
- package/usePlacements.d.ts +2 -0
- package/usePlacements.js +66 -0
- package/usePlacements.js.map +1 -0
package/DropBase.d.ts
CHANGED
|
@@ -51,7 +51,7 @@ declare const DropBase: import("react").ForwardRefExoticComponent<{
|
|
|
51
51
|
onBlurCapture?: import("react").FocusEventHandler<HTMLDivElement> | undefined;
|
|
52
52
|
onChange?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
53
53
|
onChangeCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
54
|
-
onBeforeInput?: import("react").
|
|
54
|
+
onBeforeInput?: import("react").InputEventHandler<HTMLDivElement> | undefined;
|
|
55
55
|
onBeforeInputCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
56
56
|
onInput?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
57
57
|
onInputCapture?: import("react").FormEventHandler<HTMLDivElement> | undefined;
|
|
@@ -101,8 +101,6 @@ declare const DropBase: import("react").ForwardRefExoticComponent<{
|
|
|
101
101
|
onProgressCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
102
102
|
onRateChange?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
103
103
|
onRateChangeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
104
|
-
onResize?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
105
|
-
onResizeCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
106
104
|
onSeeked?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
107
105
|
onSeekedCapture?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
108
106
|
onSeeking?: import("react").ReactEventHandler<HTMLDivElement> | undefined;
|
|
@@ -172,9 +170,7 @@ declare const DropBase: import("react").ForwardRefExoticComponent<{
|
|
|
172
170
|
onPointerCancel?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
173
171
|
onPointerCancelCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
174
172
|
onPointerEnter?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
175
|
-
onPointerEnterCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
176
173
|
onPointerLeave?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
177
|
-
onPointerLeaveCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
178
174
|
onPointerOver?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
179
175
|
onPointerOverCapture?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
|
180
176
|
onPointerOut?: import("react").PointerEventHandler<HTMLDivElement> | undefined;
|
package/DropBase.js
CHANGED
|
@@ -13,7 +13,7 @@ import { usePositionManager } from './positionManager.js';
|
|
|
13
13
|
import './findBestFitPlacement.js';
|
|
14
14
|
import './useMonitorResize.js';
|
|
15
15
|
|
|
16
|
-
var styles = {"drop-base":"magritte-drop-base___uJNG4_7-0-
|
|
16
|
+
var styles = {"drop-base":"magritte-drop-base___uJNG4_7-0-18","dropBase":"magritte-drop-base___uJNG4_7-0-18"};
|
|
17
17
|
|
|
18
18
|
const DropBaseComponent = ({ visible, children, arrowGuardDistance, activatorRef, preferredViewport, onClose, autoFocusWhenOpened = false, closeByClickOutside = true, animationTimeout, animationClassNames, guardDistanceToActivator = 8, guardDistanceToViewport = 24, minHeight = 200, role, widthEqualToActivator = false, allowShrinkHeightToFitIntoViewport = false, keyboardNavigationMode = null, ignoreIntersections = false, style = {}, onAppear, onBeforeExit, onAfterExit, host, placement, forceDropMetricsUpdate, lockPlacement = false, ...props }, ref) => {
|
|
19
19
|
const dropNodeRef = useRef(null);
|
package/findBestFitPlacement.js
CHANGED
|
@@ -165,7 +165,7 @@ const findBestFitPlacement = ({ placements, activatorRect, viewportRect, offsetP
|
|
|
165
165
|
// пересечения дропа с границами экрана в этом варианте размещения можно использовать прямоугольник
|
|
166
166
|
// размеры которого равны размерам дропа, центр которого расположен в центре активатора.
|
|
167
167
|
left: activator.left - (actualWidth - activator.width) / 2,
|
|
168
|
-
top: activator.top - (
|
|
168
|
+
top: activator.top - (dropHeight - activator.height) / 2,
|
|
169
169
|
width: actualWidth,
|
|
170
170
|
height: dropHeight,
|
|
171
171
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findBestFitPlacement.js","sources":["../src/findBestFitPlacement.ts"],"sourcesContent":["import { RefObject } from 'react';\n\nimport {\n ActivatorElementType,\n Placement,\n VerticalDirection,\n HorizontalDirection,\n AlignmentForVerticalDirection,\n AlignmentForHorizontalDirection,\n ArrowGuardDistance,\n ParsedPlacement,\n} from '@hh.ru/magritte-internal-drop-base/types';\n\ninterface GetMetricsFunc {\n (args: {\n activatorRef: RefObject<ActivatorElementType>;\n customViewport?: RefObject<HTMLElement>;\n dropRef: RefObject<HTMLElement>;\n }): {\n activatorRect: DOMRect;\n viewportRect: DOMRect;\n offsetParentRect: DOMRect;\n };\n}\n\nexport const getMetrics: GetMetricsFunc = ({ activatorRef, customViewport, dropRef }) => {\n let activatorRect: DOMRect = new DOMRect();\n\n if (activatorRef.current) {\n activatorRect = activatorRef.current.getBoundingClientRect();\n }\n const viewportRect =\n customViewport && customViewport.current\n ? customViewport.current.getBoundingClientRect()\n : DOMRect.fromRect({\n width: window.visualViewport?.width,\n height: window.visualViewport?.height,\n x: 0,\n y: 0,\n });\n const offsetParentRect = dropRef.current?.offsetParent?.getBoundingClientRect() || new DOMRect();\n\n return { activatorRect, viewportRect, offsetParentRect };\n};\n\nconst parsePlacement = (\n placement: Placement\n): [VerticalDirection | HorizontalDirection, AlignmentForHorizontalDirection | AlignmentForVerticalDirection] => {\n return placement.split('-') as [\n VerticalDirection | HorizontalDirection,\n AlignmentForHorizontalDirection | AlignmentForVerticalDirection,\n ];\n};\n\ntype Rect = { left: number; top: number; width: number; height: number; right: number; bottom: number };\n// Возвращает описание прямоугольника и размеры и позицию правой и нижней стороны, при этом позволяет не указывать\n// в аргументах либо размеры, либо позицию правой и нижней стороны\nconst createRect = (args: {\n left: number;\n top: number;\n width?: number;\n height?: number;\n right?: number;\n bottom?: number;\n}) => ({\n left: args.left,\n top: args.top,\n width: args.width || (args?.right || 0) - args.left,\n height: args.height || (args?.bottom || 0) - args.top,\n right: args.right || (args?.width || 0) + args.left,\n bottom: args.bottom || (args?.height || 0) + args.top,\n});\n\ninterface GetAvailableRectsForPlacementsFunc {\n (args: { placements: Placement[]; activatorRect: DOMRect; viewportRect: DOMRect }): { [key in Placement]: Rect };\n}\n\nconst getAvailableRectsForPlacements: GetAvailableRectsForPlacementsFunc = ({\n placements,\n activatorRect,\n viewportRect,\n}) => {\n // Вычисляем содержащий прямоугольник для свободного пространство с каждой из сторон от активатора\n // https://excalidraw.com/#json=3O9770_G2g6lkJuIftLiQ,2ZRIYkXrSjCpobPS5Ufh7w\n const freeSpaceBySide = {\n top: () =>\n createRect({\n left: viewportRect.x,\n top: viewportRect.y,\n width: viewportRect.width,\n height: activatorRect.top - viewportRect.top,\n }),\n right: () =>\n createRect({\n left: activatorRect.right,\n top: viewportRect.top,\n width: viewportRect.right - activatorRect.right,\n height: viewportRect.height,\n }),\n bottom: () =>\n createRect({\n left: viewportRect.x,\n top: activatorRect.bottom,\n width: viewportRect.width,\n height: viewportRect.bottom - activatorRect.bottom,\n }),\n left: () =>\n createRect({\n left: viewportRect.x,\n top: viewportRect.y,\n width: activatorRect.left - viewportRect.left,\n height: viewportRect.height,\n }),\n };\n\n // Для каждого варианта позиционирования вычисляем содержащий прямоугольник доступного пространства\n // с учетом позиции активатора и границ вьюпорта\n return placements.reduce(\n (acc, placement) => {\n const [direction, alignment] = parsePlacement(placement);\n\n const freeSpace = freeSpaceBySide[direction]();\n acc[placement] = freeSpace;\n\n // Берем свободное пространство с той стороны от активатора куда должен выпасть дроп\n // и устанавливает позицию стороны соответствующей alignment равно позиции той же стороны активатора.\n // На схеме понятнее откуда берется эта логика:\n // https://excalidraw.com/#json=cTKcB__3Oi3U3lF1Z4FLk,6jWpaYZLXePae-FDUbC9PQ\n if (alignment !== 'center') {\n acc[placement][alignment] = activatorRect[alignment];\n acc[placement] = createRect({ ...acc[placement], width: undefined, height: undefined });\n }\n return acc;\n },\n {} as { [key in Placement]: Rect }\n );\n};\n\nconst vertPlacement = ['top', 'bottom'];\nconst axisStartAlignment = ['left', 'top'];\n\nexport interface FindBestFitPlacementFunc {\n (args: {\n /** Список доступных направлений для выпадения, напр.: `['top-left', 'left-bottom']` */\n placements: Placement[];\n /** Содержащий прямоугольник активатора */\n activatorRect: DOMRect;\n /** Содержащий прямоугольник viewport */\n viewportRect: DOMRect;\n /** Содержащий прямоугольник offsetParent дропа */\n offsetParentRect: DOMRect;\n /** Ширина дропа */\n dropWidth: number;\n /** Высота дропа */\n dropHeight: number;\n /** Расстояние от дропа до активатора */\n guardDistanceToActivator: number;\n /** Расстояние от дропа до верхней и нижней границы экрана */\n guardDistanceToViewport: number;\n /** Расстояние от центра стрелки (например в тултипе), до ближайшего края дропа */\n arrowGuardDistance: ArrowGuardDistance;\n /**\n * Минимальная высота дропа, используется для вычисления позиции и размера дропа в случае когда\n * необходимо уместить дроп во `viewport`. Если дроп не умещается во `viewport`, то его высота будет уменьшаться\n * до достижения этого значения. После достижения будет игнорироваться параметр `guardDistanceToViewport`.\n * */\n minDropHeight: number;\n /** Флаг, указывающий что требуется пытаться уместить дроп во viewport за счет изменения его размеров */\n allowShrinkHeightToFitIntoViewport: boolean;\n /** Флаг, указывающий что ширина дропа должна быть равна ширине активатора */\n widthEqualToActivator: boolean;\n /** Позволяет временно отключить изменение расположения, например при открытии экранной клавиатуры */\n lockPlacement?: boolean;\n prefferedPlacement: Placement | undefined;\n }): {\n /** Содержащий прямоугольник выбранного места размещения дропа. Задает позицию и размер дропа */\n rect: DOMRect;\n /**\n * Вариант из списка переданного в параметре `placements` выбранный в качестве\n * наиболее подходящего для размещения дропа\n * */\n parsedPlacement: ParsedPlacement;\n placement: Placement;\n };\n}\n\n/**\n * Функция находит наилучшее расположение для дропа с учетом доступного пространства.\n * Наилучшее расположение выбирается из списка допустимых (`placements`).\n * Алгоритм выбора следующий:\n * - Если дроп полностью умещается на экране при выпадении в соответствующем направлении, то выбирается это направление.\n * - Если таких направлений несколько, то выбирается направление с наименьшим индексом в списке.\n * - Если ни одно из направлений не может полностью уместить дроп, то выбирается направление, которое умещает наибольшую\n * часть дропа по вертикали. Если таких направлений несколько, то среди них выбирается первое направление полностью\n * умещающее дроп по ширине, или умещающее наибольшую часть его ширины.\n */\nexport const findBestFitPlacement: FindBestFitPlacementFunc = ({\n placements,\n activatorRect,\n viewportRect,\n offsetParentRect,\n dropWidth,\n dropHeight,\n guardDistanceToActivator,\n guardDistanceToViewport,\n minDropHeight,\n allowShrinkHeightToFitIntoViewport,\n widthEqualToActivator,\n arrowGuardDistance,\n prefferedPlacement,\n lockPlacement,\n}) => {\n const availablePlacements = getAvailableRectsForPlacements({ placements, activatorRect, viewportRect });\n const actualWidth = widthEqualToActivator ? activatorRect.width : dropWidth;\n\n // Прямоугольники описывающие место необходимое для размещения дропа при вертикальном и горизонтальном размещении.\n // С учетом отступов от активатора и от краев экрана.\n const dropRectForVertPlacement = DOMRect.fromRect({\n x: 0,\n y: 0,\n width: actualWidth,\n height:\n dropHeight + (allowShrinkHeightToFitIntoViewport ? guardDistanceToViewport : 0) + guardDistanceToActivator,\n });\n\n const dropRectForHorPlacement = DOMRect.fromRect({\n x: 0,\n y: 0,\n width: actualWidth + guardDistanceToActivator,\n height: dropHeight + (allowShrinkHeightToFitIntoViewport ? guardDistanceToViewport : 0),\n });\n const viewport = createRect(viewportRect);\n const activator = createRect(activatorRect);\n\n // хранит выбранный лучший вариант размещения, может меняться в процессе перебора вариантов\n let bestFitPlacement = prefferedPlacement || placements[0];\n let bestFitPlacementDistanceToViewportBorder = Number.MIN_SAFE_INTEGER;\n let bestFitPlacementArrowGuardOffset = 0;\n // Минимальная высота необходимая для размещения дропа\n const minHeightToFit = allowShrinkHeightToFitIntoViewport ? minDropHeight + guardDistanceToViewport : dropHeight;\n\n const iterationsCount = prefferedPlacement ? placements.length + 1 : placements.length;\n for (let i = 0, j = lockPlacement && prefferedPlacement ? 1 : iterationsCount; i < j; i++) {\n // Если передан prefferedPlacement, то сначала надо проверить его\n // При этом если он не подошел, то при дальнейшей обработке массива допустимых размещений\n // снова наткнемся на него, в этом случае нужно сразу перейти к следующему элементу\n let placement = placements[i];\n if (prefferedPlacement) {\n if (i === 0) {\n placement = prefferedPlacement;\n } else {\n placement = placements[i - 1];\n if (placement === prefferedPlacement) {\n // eslint-disable-next-line no-continue\n continue;\n }\n }\n }\n const freeSpace = availablePlacements[placement];\n const [direction, alignment] = parsePlacement(placement);\n const isVertPlacement = vertPlacement.includes(direction);\n const dropRect = isVertPlacement ? dropRectForVertPlacement : dropRectForHorPlacement;\n\n /*\n * Если есть стрелка и для нее задан сдвиг, то стрелка должна лежать со стороны от центра активатора равной\n * alignment. Т.е. чтобы соблюсти это правило нужно проверить что сдвиг стрелки меньше или равен половине ширины\n * или высоты активатора в зависимости от направления размещения дропа. Если это не так, то дроп необходимо\n * сдвинуть так, чтобы стрелка была по середине активатора. Это может повлиять на величину пересечения дропа\n * с границей вьюпорта\n */\n const arrowGuardDistanceForPlacement =\n arrowGuardDistance[direction]?.[\n alignment as AlignmentForVerticalDirection & AlignmentForHorizontalDirection\n ];\n let arrowGuardOffset = 0;\n if (\n arrowGuardDistanceForPlacement &&\n arrowGuardDistanceForPlacement > activatorRect[isVertPlacement ? 'width' : 'height'] / 2\n ) {\n arrowGuardOffset = arrowGuardDistanceForPlacement - activatorRect[isVertPlacement ? 'width' : 'height'] / 2;\n }\n\n // Расчитываем расстояние от стороны по которой выравнен дроп до границы вьюпорта\n // Нужно для обработки случаев когда часть активатора уходит за границы экрана, например вниз.\n // В этом случае от нижнего края активатора до границы вьюпорта места больше чем от верхнего края активатора\n // до границы вьюпорта. Но спозиционировать дроп оптимальнее по верхней границе активатора, т.к. в этом случае\n // меньшая часть дропа будет уходить за границы экрана.\n // https://excalidraw.com/#json=V-b0E4ic-4RYECCPfjQ56,gMxZkd6HDGw9kIBksRBylQ\n let distanceToViewportBorder = 0;\n if (alignment !== 'center') {\n distanceToViewportBorder = axisStartAlignment.includes(alignment)\n ? freeSpace[alignment] - viewport[alignment]\n : viewport[alignment] - freeSpace[alignment];\n distanceToViewportBorder -= arrowGuardOffset;\n } else {\n const dropRect = createRect({\n // Т.к. к варианту с alignment=center не применяется изменение размера дропа, то для вычисления\n // пересечения дропа с границами экрана в этом варианте размещения можно использовать прямоугольник\n // размеры которого равны размерам дропа, центр которого расположен в центре активатора.\n left: activator.left - (actualWidth - activator.width) / 2,\n top: activator.top - (actualWidth - activator.height) / 2,\n width: actualWidth,\n height: dropHeight,\n });\n // С разных сторон может быть разная величина пересечения, берем худший вариант.\n distanceToViewportBorder = isVertPlacement\n ? Math.min(dropRect.left - viewport.left, viewport.right - dropRect.right)\n : Math.min(dropRect.top - viewport.top, viewport.bottom - dropRect.bottom);\n }\n\n if (freeSpace.width >= dropRect.width && freeSpace.height >= dropRect.height && distanceToViewportBorder >= 0) {\n bestFitPlacement = placement;\n bestFitPlacementArrowGuardOffset = arrowGuardOffset;\n break;\n }\n\n const currentCanFitByHeight =\n freeSpace.height >= minHeightToFit + (isVertPlacement ? guardDistanceToActivator : 0);\n const currentNotWorseByHeight =\n freeSpace.height >= availablePlacements[bestFitPlacement].height || freeSpace.height >= dropRect.height;\n const currentFitsBetterByHeight =\n availablePlacements[bestFitPlacement].height < dropHeight &&\n freeSpace.height > availablePlacements[bestFitPlacement].height;\n\n const currentNotWorseByWidth =\n freeSpace.width >= availablePlacements[bestFitPlacement].width || freeSpace.width >= dropRect.width;\n const currentFitsBetterByWidth =\n availablePlacements[bestFitPlacement].width < dropRect.width &&\n freeSpace.width > availablePlacements[bestFitPlacement].width;\n\n const currentFitsBetter =\n (currentFitsBetterByHeight && currentNotWorseByWidth && distanceToViewportBorder >= 0) ||\n (currentFitsBetterByWidth && currentNotWorseByHeight && distanceToViewportBorder >= 0) ||\n (currentCanFitByHeight &&\n currentNotWorseByWidth &&\n bestFitPlacementDistanceToViewportBorder < 0 &&\n distanceToViewportBorder > bestFitPlacementDistanceToViewportBorder);\n\n if (currentFitsBetter) {\n bestFitPlacement = placement;\n bestFitPlacementDistanceToViewportBorder = distanceToViewportBorder;\n bestFitPlacementArrowGuardOffset = arrowGuardOffset;\n }\n }\n\n // После того как найден содержащий прямоугольник для дропа вычисляем высоту дропа, затем позицию\n const [direction, alignment] = parsePlacement(bestFitPlacement);\n const freeSpace = availablePlacements[bestFitPlacement];\n const isVertPlacement = vertPlacement.includes(direction);\n const actualHeight =\n allowShrinkHeightToFitIntoViewport && alignment !== 'center'\n ? Math.min(\n dropHeight,\n Math.max(\n minDropHeight,\n freeSpace.height - guardDistanceToViewport - (isVertPlacement ? guardDistanceToActivator : 0)\n )\n )\n : dropHeight;\n\n // Для определения позиции дропа необходимо вычислить left/top, но для некоторых вариантов размещения проще\n // вычислить right/bottom т.к. они совпадают с соответствующими сторонами содержащего прямоугольника.\n // Поэтому сначала проверяем можем ли мы вычислить right/bottom.\n const position: Partial<Rect> = {};\n if (direction === 'left' || alignment === 'right') {\n position.right = freeSpace.right;\n }\n if (direction === 'top' || alignment === 'bottom') {\n position.bottom = freeSpace.bottom;\n }\n // Вычисляем left/top на основе right/bottom и width/height если они есть. Если их нет - значит в этом варианте\n // размещения с содержащим прямоугольником совпадают left/top.\n position.left = position.right !== undefined ? position.right - actualWidth : freeSpace.left;\n position.top = position.bottom !== undefined ? position.bottom - actualHeight : freeSpace.top;\n\n // Отдельно вычисляем позицию/размер для выравнивания по центру\n if (alignment === 'center') {\n const startPosAttr = isVertPlacement ? 'left' : 'top';\n const sizeAttr = isVertPlacement ? 'width' : 'height';\n const dropSize = isVertPlacement ? actualWidth : actualHeight;\n position[startPosAttr] = activatorRect[startPosAttr] + (activatorRect[sizeAttr] - dropSize) / 2;\n }\n\n // Отодвигаем на заданный отступ от активатора\n const signedActivatorOffset = ['bottom', 'right'].includes(direction)\n ? guardDistanceToActivator\n : -guardDistanceToActivator;\n position.top += isVertPlacement ? signedActivatorOffset : 0;\n position.left += !isVertPlacement ? signedActivatorOffset : 0;\n\n position.width = actualWidth;\n position.height = actualHeight;\n // Создаем новую переменную чтобы поменять тип, потому что на этом этапе мы точно знаем что у нас есть эти поля\n // и нет необходимости писать тайпгарды в каждом месте использования\n const finalPosition = position as { left: number; top: number; width: number; height: number };\n\n // Если необходим сдвиг для выравнивания стрелки относительно активатора - применяем его\n if (bestFitPlacementArrowGuardOffset) {\n finalPosition[isVertPlacement ? 'left' : 'top'] += axisStartAlignment.includes(alignment)\n ? -bestFitPlacementArrowGuardOffset\n : bestFitPlacementArrowGuardOffset;\n // Добавляем дополнительно пространство к размеру дропа\n finalPosition[isVertPlacement ? 'height' : 'width'] += bestFitPlacementArrowGuardOffset;\n // Удостоверяемся что после этого размер дропа не превышает размер необходимый для его контента\n finalPosition.height = Math.min(finalPosition.height, dropHeight);\n finalPosition.width = Math.min(finalPosition.width, actualWidth);\n }\n\n return {\n rect: new DOMRect(\n finalPosition.left - offsetParentRect.left, // Переводим координаты в систему координат offsetParent\n finalPosition.top - offsetParentRect.top,\n finalPosition.width,\n finalPosition.height\n ),\n parsedPlacement: { direction, alignment },\n placement: bestFitPlacement,\n };\n};\n\nexport const applyPlacementToDrop = (dropRef: RefObject<HTMLElement>, placement: DOMRect): void => {\n if (!dropRef.current) {\n return;\n }\n\n dropRef.current.style.top = `${placement.top}px`;\n dropRef.current.style.left = `${placement.left}px`;\n dropRef.current.style.width = `${placement.width}px`;\n dropRef.current.style.height = `${placement.height}px`;\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"findBestFitPlacement.js","sources":["../src/findBestFitPlacement.ts"],"sourcesContent":["import { RefObject } from 'react';\n\nimport {\n ActivatorElementType,\n Placement,\n VerticalDirection,\n HorizontalDirection,\n AlignmentForVerticalDirection,\n AlignmentForHorizontalDirection,\n ArrowGuardDistance,\n ParsedPlacement,\n} from '@hh.ru/magritte-internal-drop-base/types';\n\ninterface GetMetricsFunc {\n (args: {\n activatorRef: RefObject<ActivatorElementType>;\n customViewport?: RefObject<HTMLElement>;\n dropRef: RefObject<HTMLElement>;\n }): {\n activatorRect: DOMRect;\n viewportRect: DOMRect;\n offsetParentRect: DOMRect;\n };\n}\n\nexport const getMetrics: GetMetricsFunc = ({ activatorRef, customViewport, dropRef }) => {\n let activatorRect: DOMRect = new DOMRect();\n\n if (activatorRef.current) {\n activatorRect = activatorRef.current.getBoundingClientRect();\n }\n const viewportRect =\n customViewport && customViewport.current\n ? customViewport.current.getBoundingClientRect()\n : DOMRect.fromRect({\n width: window.visualViewport?.width,\n height: window.visualViewport?.height,\n x: 0,\n y: 0,\n });\n const offsetParentRect = dropRef.current?.offsetParent?.getBoundingClientRect() || new DOMRect();\n\n return { activatorRect, viewportRect, offsetParentRect };\n};\n\nconst parsePlacement = (\n placement: Placement\n): [VerticalDirection | HorizontalDirection, AlignmentForHorizontalDirection | AlignmentForVerticalDirection] => {\n return placement.split('-') as [\n VerticalDirection | HorizontalDirection,\n AlignmentForHorizontalDirection | AlignmentForVerticalDirection,\n ];\n};\n\ntype Rect = { left: number; top: number; width: number; height: number; right: number; bottom: number };\n// Возвращает описание прямоугольника и размеры и позицию правой и нижней стороны, при этом позволяет не указывать\n// в аргументах либо размеры, либо позицию правой и нижней стороны\nconst createRect = (args: {\n left: number;\n top: number;\n width?: number;\n height?: number;\n right?: number;\n bottom?: number;\n}) => ({\n left: args.left,\n top: args.top,\n width: args.width || (args?.right || 0) - args.left,\n height: args.height || (args?.bottom || 0) - args.top,\n right: args.right || (args?.width || 0) + args.left,\n bottom: args.bottom || (args?.height || 0) + args.top,\n});\n\ninterface GetAvailableRectsForPlacementsFunc {\n (args: { placements: Placement[]; activatorRect: DOMRect; viewportRect: DOMRect }): { [key in Placement]: Rect };\n}\n\nconst getAvailableRectsForPlacements: GetAvailableRectsForPlacementsFunc = ({\n placements,\n activatorRect,\n viewportRect,\n}) => {\n // Вычисляем содержащий прямоугольник для свободного пространство с каждой из сторон от активатора\n // https://excalidraw.com/#json=3O9770_G2g6lkJuIftLiQ,2ZRIYkXrSjCpobPS5Ufh7w\n const freeSpaceBySide = {\n top: () =>\n createRect({\n left: viewportRect.x,\n top: viewportRect.y,\n width: viewportRect.width,\n height: activatorRect.top - viewportRect.top,\n }),\n right: () =>\n createRect({\n left: activatorRect.right,\n top: viewportRect.top,\n width: viewportRect.right - activatorRect.right,\n height: viewportRect.height,\n }),\n bottom: () =>\n createRect({\n left: viewportRect.x,\n top: activatorRect.bottom,\n width: viewportRect.width,\n height: viewportRect.bottom - activatorRect.bottom,\n }),\n left: () =>\n createRect({\n left: viewportRect.x,\n top: viewportRect.y,\n width: activatorRect.left - viewportRect.left,\n height: viewportRect.height,\n }),\n };\n\n // Для каждого варианта позиционирования вычисляем содержащий прямоугольник доступного пространства\n // с учетом позиции активатора и границ вьюпорта\n return placements.reduce(\n (acc, placement) => {\n const [direction, alignment] = parsePlacement(placement);\n\n const freeSpace = freeSpaceBySide[direction]();\n acc[placement] = freeSpace;\n\n // Берем свободное пространство с той стороны от активатора куда должен выпасть дроп\n // и устанавливает позицию стороны соответствующей alignment равно позиции той же стороны активатора.\n // На схеме понятнее откуда берется эта логика:\n // https://excalidraw.com/#json=cTKcB__3Oi3U3lF1Z4FLk,6jWpaYZLXePae-FDUbC9PQ\n if (alignment !== 'center') {\n acc[placement][alignment] = activatorRect[alignment];\n acc[placement] = createRect({ ...acc[placement], width: undefined, height: undefined });\n }\n return acc;\n },\n {} as { [key in Placement]: Rect }\n );\n};\n\nconst vertPlacement = ['top', 'bottom'];\nconst axisStartAlignment = ['left', 'top'];\n\nexport interface FindBestFitPlacementFunc {\n (args: {\n /** Список доступных направлений для выпадения, напр.: `['top-left', 'left-bottom']` */\n placements: Placement[];\n /** Содержащий прямоугольник активатора */\n activatorRect: DOMRect;\n /** Содержащий прямоугольник viewport */\n viewportRect: DOMRect;\n /** Содержащий прямоугольник offsetParent дропа */\n offsetParentRect: DOMRect;\n /** Ширина дропа */\n dropWidth: number;\n /** Высота дропа */\n dropHeight: number;\n /** Расстояние от дропа до активатора */\n guardDistanceToActivator: number;\n /** Расстояние от дропа до верхней и нижней границы экрана */\n guardDistanceToViewport: number;\n /** Расстояние от центра стрелки (например в тултипе), до ближайшего края дропа */\n arrowGuardDistance: ArrowGuardDistance;\n /**\n * Минимальная высота дропа, используется для вычисления позиции и размера дропа в случае когда\n * необходимо уместить дроп во `viewport`. Если дроп не умещается во `viewport`, то его высота будет уменьшаться\n * до достижения этого значения. После достижения будет игнорироваться параметр `guardDistanceToViewport`.\n * */\n minDropHeight: number;\n /** Флаг, указывающий что требуется пытаться уместить дроп во viewport за счет изменения его размеров */\n allowShrinkHeightToFitIntoViewport: boolean;\n /** Флаг, указывающий что ширина дропа должна быть равна ширине активатора */\n widthEqualToActivator: boolean;\n /** Позволяет временно отключить изменение расположения, например при открытии экранной клавиатуры */\n lockPlacement?: boolean;\n prefferedPlacement: Placement | undefined;\n }): {\n /** Содержащий прямоугольник выбранного места размещения дропа. Задает позицию и размер дропа */\n rect: DOMRect;\n /**\n * Вариант из списка переданного в параметре `placements` выбранный в качестве\n * наиболее подходящего для размещения дропа\n * */\n parsedPlacement: ParsedPlacement;\n placement: Placement;\n };\n}\n\n/**\n * Функция находит наилучшее расположение для дропа с учетом доступного пространства.\n * Наилучшее расположение выбирается из списка допустимых (`placements`).\n * Алгоритм выбора следующий:\n * - Если дроп полностью умещается на экране при выпадении в соответствующем направлении, то выбирается это направление.\n * - Если таких направлений несколько, то выбирается направление с наименьшим индексом в списке.\n * - Если ни одно из направлений не может полностью уместить дроп, то выбирается направление, которое умещает наибольшую\n * часть дропа по вертикали. Если таких направлений несколько, то среди них выбирается первое направление полностью\n * умещающее дроп по ширине, или умещающее наибольшую часть его ширины.\n */\nexport const findBestFitPlacement: FindBestFitPlacementFunc = ({\n placements,\n activatorRect,\n viewportRect,\n offsetParentRect,\n dropWidth,\n dropHeight,\n guardDistanceToActivator,\n guardDistanceToViewport,\n minDropHeight,\n allowShrinkHeightToFitIntoViewport,\n widthEqualToActivator,\n arrowGuardDistance,\n prefferedPlacement,\n lockPlacement,\n}) => {\n const availablePlacements = getAvailableRectsForPlacements({ placements, activatorRect, viewportRect });\n const actualWidth = widthEqualToActivator ? activatorRect.width : dropWidth;\n\n // Прямоугольники описывающие место необходимое для размещения дропа при вертикальном и горизонтальном размещении.\n // С учетом отступов от активатора и от краев экрана.\n const dropRectForVertPlacement = DOMRect.fromRect({\n x: 0,\n y: 0,\n width: actualWidth,\n height:\n dropHeight + (allowShrinkHeightToFitIntoViewport ? guardDistanceToViewport : 0) + guardDistanceToActivator,\n });\n\n const dropRectForHorPlacement = DOMRect.fromRect({\n x: 0,\n y: 0,\n width: actualWidth + guardDistanceToActivator,\n height: dropHeight + (allowShrinkHeightToFitIntoViewport ? guardDistanceToViewport : 0),\n });\n const viewport = createRect(viewportRect);\n const activator = createRect(activatorRect);\n\n // хранит выбранный лучший вариант размещения, может меняться в процессе перебора вариантов\n let bestFitPlacement = prefferedPlacement || placements[0];\n let bestFitPlacementDistanceToViewportBorder = Number.MIN_SAFE_INTEGER;\n let bestFitPlacementArrowGuardOffset = 0;\n // Минимальная высота необходимая для размещения дропа\n const minHeightToFit = allowShrinkHeightToFitIntoViewport ? minDropHeight + guardDistanceToViewport : dropHeight;\n\n const iterationsCount = prefferedPlacement ? placements.length + 1 : placements.length;\n for (let i = 0, j = lockPlacement && prefferedPlacement ? 1 : iterationsCount; i < j; i++) {\n // Если передан prefferedPlacement, то сначала надо проверить его\n // При этом если он не подошел, то при дальнейшей обработке массива допустимых размещений\n // снова наткнемся на него, в этом случае нужно сразу перейти к следующему элементу\n let placement = placements[i];\n if (prefferedPlacement) {\n if (i === 0) {\n placement = prefferedPlacement;\n } else {\n placement = placements[i - 1];\n if (placement === prefferedPlacement) {\n // eslint-disable-next-line no-continue\n continue;\n }\n }\n }\n const freeSpace = availablePlacements[placement];\n const [direction, alignment] = parsePlacement(placement);\n const isVertPlacement = vertPlacement.includes(direction);\n const dropRect = isVertPlacement ? dropRectForVertPlacement : dropRectForHorPlacement;\n\n /*\n * Если есть стрелка и для нее задан сдвиг, то стрелка должна лежать со стороны от центра активатора равной\n * alignment. Т.е. чтобы соблюсти это правило нужно проверить что сдвиг стрелки меньше или равен половине ширины\n * или высоты активатора в зависимости от направления размещения дропа. Если это не так, то дроп необходимо\n * сдвинуть так, чтобы стрелка была по середине активатора. Это может повлиять на величину пересечения дропа\n * с границей вьюпорта\n */\n const arrowGuardDistanceForPlacement =\n arrowGuardDistance[direction]?.[\n alignment as AlignmentForVerticalDirection & AlignmentForHorizontalDirection\n ];\n let arrowGuardOffset = 0;\n if (\n arrowGuardDistanceForPlacement &&\n arrowGuardDistanceForPlacement > activatorRect[isVertPlacement ? 'width' : 'height'] / 2\n ) {\n arrowGuardOffset = arrowGuardDistanceForPlacement - activatorRect[isVertPlacement ? 'width' : 'height'] / 2;\n }\n\n // Расчитываем расстояние от стороны по которой выравнен дроп до границы вьюпорта\n // Нужно для обработки случаев когда часть активатора уходит за границы экрана, например вниз.\n // В этом случае от нижнего края активатора до границы вьюпорта места больше чем от верхнего края активатора\n // до границы вьюпорта. Но спозиционировать дроп оптимальнее по верхней границе активатора, т.к. в этом случае\n // меньшая часть дропа будет уходить за границы экрана.\n // https://excalidraw.com/#json=V-b0E4ic-4RYECCPfjQ56,gMxZkd6HDGw9kIBksRBylQ\n let distanceToViewportBorder = 0;\n if (alignment !== 'center') {\n distanceToViewportBorder = axisStartAlignment.includes(alignment)\n ? freeSpace[alignment] - viewport[alignment]\n : viewport[alignment] - freeSpace[alignment];\n distanceToViewportBorder -= arrowGuardOffset;\n } else {\n const dropRect = createRect({\n // Т.к. к варианту с alignment=center не применяется изменение размера дропа, то для вычисления\n // пересечения дропа с границами экрана в этом варианте размещения можно использовать прямоугольник\n // размеры которого равны размерам дропа, центр которого расположен в центре активатора.\n left: activator.left - (actualWidth - activator.width) / 2,\n top: activator.top - (dropHeight - activator.height) / 2,\n width: actualWidth,\n height: dropHeight,\n });\n // С разных сторон может быть разная величина пересечения, берем худший вариант.\n distanceToViewportBorder = isVertPlacement\n ? Math.min(dropRect.left - viewport.left, viewport.right - dropRect.right)\n : Math.min(dropRect.top - viewport.top, viewport.bottom - dropRect.bottom);\n }\n\n if (freeSpace.width >= dropRect.width && freeSpace.height >= dropRect.height && distanceToViewportBorder >= 0) {\n bestFitPlacement = placement;\n bestFitPlacementArrowGuardOffset = arrowGuardOffset;\n break;\n }\n\n const currentCanFitByHeight =\n freeSpace.height >= minHeightToFit + (isVertPlacement ? guardDistanceToActivator : 0);\n const currentNotWorseByHeight =\n freeSpace.height >= availablePlacements[bestFitPlacement].height || freeSpace.height >= dropRect.height;\n const currentFitsBetterByHeight =\n availablePlacements[bestFitPlacement].height < dropHeight &&\n freeSpace.height > availablePlacements[bestFitPlacement].height;\n\n const currentNotWorseByWidth =\n freeSpace.width >= availablePlacements[bestFitPlacement].width || freeSpace.width >= dropRect.width;\n const currentFitsBetterByWidth =\n availablePlacements[bestFitPlacement].width < dropRect.width &&\n freeSpace.width > availablePlacements[bestFitPlacement].width;\n\n const currentFitsBetter =\n (currentFitsBetterByHeight && currentNotWorseByWidth && distanceToViewportBorder >= 0) ||\n (currentFitsBetterByWidth && currentNotWorseByHeight && distanceToViewportBorder >= 0) ||\n (currentCanFitByHeight &&\n currentNotWorseByWidth &&\n bestFitPlacementDistanceToViewportBorder < 0 &&\n distanceToViewportBorder > bestFitPlacementDistanceToViewportBorder);\n\n if (currentFitsBetter) {\n bestFitPlacement = placement;\n bestFitPlacementDistanceToViewportBorder = distanceToViewportBorder;\n bestFitPlacementArrowGuardOffset = arrowGuardOffset;\n }\n }\n\n // После того как найден содержащий прямоугольник для дропа вычисляем высоту дропа, затем позицию\n const [direction, alignment] = parsePlacement(bestFitPlacement);\n const freeSpace = availablePlacements[bestFitPlacement];\n const isVertPlacement = vertPlacement.includes(direction);\n const actualHeight =\n allowShrinkHeightToFitIntoViewport && alignment !== 'center'\n ? Math.min(\n dropHeight,\n Math.max(\n minDropHeight,\n freeSpace.height - guardDistanceToViewport - (isVertPlacement ? guardDistanceToActivator : 0)\n )\n )\n : dropHeight;\n\n // Для определения позиции дропа необходимо вычислить left/top, но для некоторых вариантов размещения проще\n // вычислить right/bottom т.к. они совпадают с соответствующими сторонами содержащего прямоугольника.\n // Поэтому сначала проверяем можем ли мы вычислить right/bottom.\n const position: Partial<Rect> = {};\n if (direction === 'left' || alignment === 'right') {\n position.right = freeSpace.right;\n }\n if (direction === 'top' || alignment === 'bottom') {\n position.bottom = freeSpace.bottom;\n }\n // Вычисляем left/top на основе right/bottom и width/height если они есть. Если их нет - значит в этом варианте\n // размещения с содержащим прямоугольником совпадают left/top.\n position.left = position.right !== undefined ? position.right - actualWidth : freeSpace.left;\n position.top = position.bottom !== undefined ? position.bottom - actualHeight : freeSpace.top;\n\n // Отдельно вычисляем позицию/размер для выравнивания по центру\n if (alignment === 'center') {\n const startPosAttr = isVertPlacement ? 'left' : 'top';\n const sizeAttr = isVertPlacement ? 'width' : 'height';\n const dropSize = isVertPlacement ? actualWidth : actualHeight;\n position[startPosAttr] = activatorRect[startPosAttr] + (activatorRect[sizeAttr] - dropSize) / 2;\n }\n\n // Отодвигаем на заданный отступ от активатора\n const signedActivatorOffset = ['bottom', 'right'].includes(direction)\n ? guardDistanceToActivator\n : -guardDistanceToActivator;\n position.top += isVertPlacement ? signedActivatorOffset : 0;\n position.left += !isVertPlacement ? signedActivatorOffset : 0;\n\n position.width = actualWidth;\n position.height = actualHeight;\n // Создаем новую переменную чтобы поменять тип, потому что на этом этапе мы точно знаем что у нас есть эти поля\n // и нет необходимости писать тайпгарды в каждом месте использования\n const finalPosition = position as { left: number; top: number; width: number; height: number };\n\n // Если необходим сдвиг для выравнивания стрелки относительно активатора - применяем его\n if (bestFitPlacementArrowGuardOffset) {\n finalPosition[isVertPlacement ? 'left' : 'top'] += axisStartAlignment.includes(alignment)\n ? -bestFitPlacementArrowGuardOffset\n : bestFitPlacementArrowGuardOffset;\n // Добавляем дополнительно пространство к размеру дропа\n finalPosition[isVertPlacement ? 'height' : 'width'] += bestFitPlacementArrowGuardOffset;\n // Удостоверяемся что после этого размер дропа не превышает размер необходимый для его контента\n finalPosition.height = Math.min(finalPosition.height, dropHeight);\n finalPosition.width = Math.min(finalPosition.width, actualWidth);\n }\n\n return {\n rect: new DOMRect(\n finalPosition.left - offsetParentRect.left, // Переводим координаты в систему координат offsetParent\n finalPosition.top - offsetParentRect.top,\n finalPosition.width,\n finalPosition.height\n ),\n parsedPlacement: { direction, alignment },\n placement: bestFitPlacement,\n };\n};\n\nexport const applyPlacementToDrop = (dropRef: RefObject<HTMLElement>, placement: DOMRect): void => {\n if (!dropRef.current) {\n return;\n }\n\n dropRef.current.style.top = `${placement.top}px`;\n dropRef.current.style.left = `${placement.left}px`;\n dropRef.current.style.width = `${placement.width}px`;\n dropRef.current.style.height = `${placement.height}px`;\n};\n"],"names":[],"mappings":"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"}
|
package/index.css
CHANGED
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import './index.css';
|
|
2
2
|
export { DropBase } from './DropBase.js';
|
|
3
|
+
export { usePlacement } from './usePlacements.js';
|
|
3
4
|
import 'react/jsx-runtime';
|
|
4
5
|
import 'react';
|
|
5
6
|
import 'react-dom';
|
|
@@ -13,4 +14,5 @@ import './intersectionManager.js';
|
|
|
13
14
|
import './positionManager.js';
|
|
14
15
|
import './findBestFitPlacement.js';
|
|
15
16
|
import './useMonitorResize.js';
|
|
17
|
+
import './useArrayMemo.js';
|
|
16
18
|
//# sourceMappingURL=index.js.map
|
package/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hh.ru/magritte-internal-drop-base",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.18",
|
|
4
4
|
"main": "index.js",
|
|
5
5
|
"types": "index.d.ts",
|
|
6
6
|
"sideEffects": [
|
|
@@ -33,5 +33,5 @@
|
|
|
33
33
|
"publishConfig": {
|
|
34
34
|
"access": "public"
|
|
35
35
|
},
|
|
36
|
-
"gitHead": "
|
|
36
|
+
"gitHead": "4bb5448cb39f50a8b84cec5100fda12a9a45f6c1"
|
|
37
37
|
}
|
package/positionManager.js
CHANGED
|
@@ -80,8 +80,14 @@ const usePositionManager = (activatorRef, dropRef, isVisible, placement, customV
|
|
|
80
80
|
}
|
|
81
81
|
// Ширина не должна превышать максимально допустимую, т.к. это может повлиять на высоту, например из-за
|
|
82
82
|
// переноса текста на новую строку.
|
|
83
|
-
dropRef.current.style.width = widthEqualToActivator ? `${activatorRect.width}px` : '';
|
|
84
|
-
dropRef.current.style.height = '';
|
|
83
|
+
dropRef.current.style.width = widthEqualToActivator ? `${activatorRect.width}px` : 'auto';
|
|
84
|
+
dropRef.current.style.height = 'auto';
|
|
85
|
+
// Если на задать этот сдвиг, то в случае если дроп отрисовывается в хосте небольшого размера он будет
|
|
86
|
+
// пытаться занять минимально возможное пространство. В случае если внутри дропа текст это может привести к
|
|
87
|
+
// изменению размеров дропа в зависимости от направления выпадения и нестабильным результатам вычисления
|
|
88
|
+
// наилучшей позиции.
|
|
89
|
+
dropRef.current.style.top = '-100000px';
|
|
90
|
+
dropRef.current.style.left = '-100000px';
|
|
85
91
|
dropMetricsRef.current = dropRef.current.getBoundingClientRect();
|
|
86
92
|
if (bestFitPlacementRef.current) {
|
|
87
93
|
applyPlacementToDrop(dropRef, bestFitPlacementRef.current);
|
package/positionManager.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"positionManager.js","sources":["../src/positionManager.ts"],"sourcesContent":["import { RefObject, useCallback, useEffect, useRef, useLayoutEffect, MutableRefObject } from 'react';\n\nimport {\n findBestFitPlacement,\n getMetrics,\n applyPlacementToDrop,\n} from '@hh.ru/magritte-internal-drop-base/findBestFitPlacement';\nimport type {\n ArrowGuardDistance,\n ActivatorElementType,\n Placement,\n RefCallbackFactory,\n} from '@hh.ru/magritte-internal-drop-base/types';\nimport { useMonitorResize } from '@hh.ru/magritte-internal-drop-base/useMonitorResize';\n\nlet isInitialized = false;\n\ninterface SubscriptionCallback {\n (target: HTMLElement): void;\n}\n\nconst scrollSubscriptions: Array<SubscriptionCallback> = [];\nconst canceledScrollSubscriptions: Map<HTMLElement, Array<SubscriptionCallback>> = new Map();\n\nconst scrollHandler = (event: Event) => {\n const target = event.target as HTMLElement;\n if (!target) {\n return;\n }\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));\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\nexport const usePositionManager = (\n activatorRef: RefObject<ActivatorElementType>,\n dropRef: RefObject<HTMLElement>,\n isVisible: boolean,\n placement: Placement | Placement[],\n customViewport: RefObject<HTMLElement> | undefined,\n allowShrinkHeightToFitIntoViewport: boolean,\n widthEqualToActivator: boolean,\n arrowGuardDistance: ArrowGuardDistance,\n guardDistanceToActivator: number,\n guardDistanceToViewport: number,\n minDropHeight: number,\n forceDropMetricsUpdate: MutableRefObject<VoidFunction> | undefined,\n lockPlacement = false\n): {\n resizeRefCallbackFactory: RefCallbackFactory;\n bestFitPlacementRect: DOMRect | undefined;\n} => {\n const bestFitPlacementRef = useRef<DOMRect>();\n const dropMetricsRef = useRef<DOMRect>();\n\n const prefferedPlacementRef = useRef<Placement>();\n\n const updateMetricsSyncRef = useRef<VoidFunction>(() => void 0);\n\n const { getResizeObserver, observeResizeRefCallbackFactory, getObservedElementsInfoMap } = useMonitorResize(\n dropMetricsRef,\n updateMetricsSyncRef\n );\n\n const getDropMetrics = useCallback(\n (activatorRect: DOMRect, widthEqualToActivator: boolean) => {\n if (dropMetricsRef.current) {\n return dropMetricsRef.current;\n }\n if (!dropRef.current) {\n return new DOMRect();\n }\n\n const scrollPositions: { node: HTMLElement; top: number; left: number }[] = [];\n for (const info of getObservedElementsInfoMap().values()) {\n if (info.isScrollable && info.node) {\n scrollPositions.push({\n node: info.node,\n top: info.node.scrollTop,\n left: info.node.scrollLeft,\n });\n }\n }\n\n // Ширина не должна превышать максимально допустимую, т.к. это может повлиять на высоту, например из-за\n // переноса текста на новую строку.\n dropRef.current.style.width = widthEqualToActivator ? `${activatorRect.width}px` : '';\n dropRef.current.style.height = '';\n dropMetricsRef.current = dropRef.current.getBoundingClientRect();\n if (bestFitPlacementRef.current) {\n applyPlacementToDrop(dropRef, bestFitPlacementRef.current);\n }\n for (const { node, top, left } of scrollPositions) {\n node.scrollTop = top;\n node.scrollLeft = left;\n }\n return dropMetricsRef.current;\n },\n [dropRef, getObservedElementsInfoMap]\n );\n\n updateMetricsSyncRef.current = () => {\n if (!dropRef.current || !isVisible) {\n bestFitPlacementRef.current = undefined;\n return;\n }\n const { activatorRect, viewportRect, offsetParentRect } = getMetrics({\n activatorRef,\n customViewport,\n dropRef,\n });\n const dropRect = getDropMetrics(activatorRect, widthEqualToActivator);\n const {\n rect,\n parsedPlacement: choosenPlacement,\n placement: prefferedPlacement,\n } = findBestFitPlacement({\n placements: Array.isArray(placement) ? placement : [placement],\n activatorRect,\n viewportRect,\n offsetParentRect,\n dropWidth: dropRect.width,\n dropHeight: dropRect.height,\n guardDistanceToActivator,\n guardDistanceToViewport,\n minDropHeight,\n widthEqualToActivator,\n allowShrinkHeightToFitIntoViewport,\n arrowGuardDistance,\n prefferedPlacement: prefferedPlacementRef.current,\n lockPlacement,\n });\n prefferedPlacementRef.current = prefferedPlacement;\n applyPlacementToDrop(dropRef, rect);\n dropRef.current.dataset.magritteDropBaseDirection = choosenPlacement.direction;\n dropRef.current.dataset.magritteDropBaseAlignment = choosenPlacement.alignment;\n bestFitPlacementRef.current = rect;\n };\n\n if (forceDropMetricsUpdate) {\n forceDropMetricsUpdate.current = () => {\n dropMetricsRef.current = undefined;\n updateMetricsSyncRef.current();\n };\n }\n\n useEffect(() => {\n if (!isVisible) {\n prefferedPlacementRef.current = undefined;\n return () => void 0;\n }\n const activatorElement = activatorRef.current;\n const customViewportElement = customViewport?.current;\n const resizeHandler = () => updateMetricsSyncRef.current();\n activatorElement && getResizeObserver().observe(activatorElement);\n customViewportElement && getResizeObserver().observe(customViewportElement);\n window.addEventListener('resize', resizeHandler);\n return () => {\n activatorElement && getResizeObserver().unobserve(activatorElement);\n customViewportElement && getResizeObserver().unobserve(customViewportElement);\n window.removeEventListener('resize', resizeHandler);\n };\n }, [activatorRef, getResizeObserver, customViewport, isVisible]);\n\n useLayoutEffect(() => {\n isVisible && updateMetricsSyncRef.current();\n }, [isVisible, placement]);\n\n /**\n * список id скроллящихся элементов для которых была выполнена проверка\n * влияет ли их скролл на взаимное положение активатора и дропа.\n * Получение сделано с помощью отдельной функции чтобы не создавать сет на каждый ререндер.\n */\n const processedScrollContainers = useRef<Set<HTMLElement>>();\n const getProcessedScrollContainers = (): Set<HTMLElement> => {\n processedScrollContainers.current = processedScrollContainers.current || new Set();\n return processedScrollContainers.current;\n };\n\n const visibleRef = useRef(isVisible);\n visibleRef.current = isVisible;\n\n const scrollHandler = useCallback(\n (target: HTMLElement) => {\n if (!visibleRef.current || !dropRef.current || !activatorRef.current) {\n return;\n }\n\n // Если это первый скролл данного контейнера, то проверяем содержит ли он активатор\n // Если он не содержит активатор, то можно отписаться от дальнейших оповещений о его скролле.\n if (!getProcessedScrollContainers().has(target)) {\n if (!target.contains(activatorRef.current)) {\n unsubscribeFromTarget(target, scrollHandler);\n return;\n }\n getProcessedScrollContainers().add(target);\n }\n\n updateMetricsSyncRef.current();\n },\n [activatorRef, dropRef]\n );\n\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isVisible ? reviveSubscription(scrollHandler) : suspendSubscription(scrollHandler);\n }, [isVisible, scrollHandler]);\n\n useEffect(() => {\n return () => deleteScrollSubscription(scrollHandler);\n }, [scrollHandler]);\n\n return {\n resizeRefCallbackFactory: observeResizeRefCallbackFactory,\n bestFitPlacementRect: bestFitPlacementRef.current,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"positionManager.js","sources":["../src/positionManager.ts"],"sourcesContent":["import { RefObject, useCallback, useEffect, useRef, useLayoutEffect, MutableRefObject } from 'react';\n\nimport {\n findBestFitPlacement,\n getMetrics,\n applyPlacementToDrop,\n} from '@hh.ru/magritte-internal-drop-base/findBestFitPlacement';\nimport type {\n ArrowGuardDistance,\n ActivatorElementType,\n Placement,\n RefCallbackFactory,\n} from '@hh.ru/magritte-internal-drop-base/types';\nimport { useMonitorResize } from '@hh.ru/magritte-internal-drop-base/useMonitorResize';\n\nlet isInitialized = false;\n\ninterface SubscriptionCallback {\n (target: HTMLElement): void;\n}\n\nconst scrollSubscriptions: Array<SubscriptionCallback> = [];\nconst canceledScrollSubscriptions: Map<HTMLElement, Array<SubscriptionCallback>> = new Map();\n\nconst scrollHandler = (event: Event) => {\n const target = event.target as HTMLElement;\n if (!target) {\n return;\n }\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));\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\nexport const usePositionManager = (\n activatorRef: RefObject<ActivatorElementType>,\n dropRef: RefObject<HTMLElement>,\n isVisible: boolean,\n placement: Placement | Placement[],\n customViewport: RefObject<HTMLElement> | undefined,\n allowShrinkHeightToFitIntoViewport: boolean,\n widthEqualToActivator: boolean,\n arrowGuardDistance: ArrowGuardDistance,\n guardDistanceToActivator: number,\n guardDistanceToViewport: number,\n minDropHeight: number,\n forceDropMetricsUpdate: MutableRefObject<VoidFunction> | undefined,\n lockPlacement = false\n): {\n resizeRefCallbackFactory: RefCallbackFactory;\n bestFitPlacementRect: DOMRect | undefined;\n} => {\n const bestFitPlacementRef = useRef<DOMRect>();\n const dropMetricsRef = useRef<DOMRect>();\n\n const prefferedPlacementRef = useRef<Placement>();\n\n const updateMetricsSyncRef = useRef<VoidFunction>(() => void 0);\n\n const { getResizeObserver, observeResizeRefCallbackFactory, getObservedElementsInfoMap } = useMonitorResize(\n dropMetricsRef,\n updateMetricsSyncRef\n );\n\n const getDropMetrics = useCallback(\n (activatorRect: DOMRect, widthEqualToActivator: boolean) => {\n if (dropMetricsRef.current) {\n return dropMetricsRef.current;\n }\n if (!dropRef.current) {\n return new DOMRect();\n }\n\n const scrollPositions: { node: HTMLElement; top: number; left: number }[] = [];\n for (const info of getObservedElementsInfoMap().values()) {\n if (info.isScrollable && info.node) {\n scrollPositions.push({\n node: info.node,\n top: info.node.scrollTop,\n left: info.node.scrollLeft,\n });\n }\n }\n\n // Ширина не должна превышать максимально допустимую, т.к. это может повлиять на высоту, например из-за\n // переноса текста на новую строку.\n dropRef.current.style.width = widthEqualToActivator ? `${activatorRect.width}px` : 'auto';\n dropRef.current.style.height = 'auto';\n // Если на задать этот сдвиг, то в случае если дроп отрисовывается в хосте небольшого размера он будет\n // пытаться занять минимально возможное пространство. В случае если внутри дропа текст это может привести к\n // изменению размеров дропа в зависимости от направления выпадения и нестабильным результатам вычисления\n // наилучшей позиции.\n dropRef.current.style.top = '-100000px';\n dropRef.current.style.left = '-100000px';\n\n dropMetricsRef.current = dropRef.current.getBoundingClientRect();\n if (bestFitPlacementRef.current) {\n applyPlacementToDrop(dropRef, bestFitPlacementRef.current);\n }\n for (const { node, top, left } of scrollPositions) {\n node.scrollTop = top;\n node.scrollLeft = left;\n }\n return dropMetricsRef.current;\n },\n [dropRef, getObservedElementsInfoMap]\n );\n\n updateMetricsSyncRef.current = () => {\n if (!dropRef.current || !isVisible) {\n bestFitPlacementRef.current = undefined;\n return;\n }\n const { activatorRect, viewportRect, offsetParentRect } = getMetrics({\n activatorRef,\n customViewport,\n dropRef,\n });\n const dropRect = getDropMetrics(activatorRect, widthEqualToActivator);\n const {\n rect,\n parsedPlacement: choosenPlacement,\n placement: prefferedPlacement,\n } = findBestFitPlacement({\n placements: Array.isArray(placement) ? placement : [placement],\n activatorRect,\n viewportRect,\n offsetParentRect,\n dropWidth: dropRect.width,\n dropHeight: dropRect.height,\n guardDistanceToActivator,\n guardDistanceToViewport,\n minDropHeight,\n widthEqualToActivator,\n allowShrinkHeightToFitIntoViewport,\n arrowGuardDistance,\n prefferedPlacement: prefferedPlacementRef.current,\n lockPlacement,\n });\n prefferedPlacementRef.current = prefferedPlacement;\n applyPlacementToDrop(dropRef, rect);\n dropRef.current.dataset.magritteDropBaseDirection = choosenPlacement.direction;\n dropRef.current.dataset.magritteDropBaseAlignment = choosenPlacement.alignment;\n bestFitPlacementRef.current = rect;\n };\n\n if (forceDropMetricsUpdate) {\n forceDropMetricsUpdate.current = () => {\n dropMetricsRef.current = undefined;\n updateMetricsSyncRef.current();\n };\n }\n\n useEffect(() => {\n if (!isVisible) {\n prefferedPlacementRef.current = undefined;\n return () => void 0;\n }\n const activatorElement = activatorRef.current;\n const customViewportElement = customViewport?.current;\n const resizeHandler = () => updateMetricsSyncRef.current();\n activatorElement && getResizeObserver().observe(activatorElement);\n customViewportElement && getResizeObserver().observe(customViewportElement);\n window.addEventListener('resize', resizeHandler);\n return () => {\n activatorElement && getResizeObserver().unobserve(activatorElement);\n customViewportElement && getResizeObserver().unobserve(customViewportElement);\n window.removeEventListener('resize', resizeHandler);\n };\n }, [activatorRef, getResizeObserver, customViewport, isVisible]);\n\n useLayoutEffect(() => {\n isVisible && updateMetricsSyncRef.current();\n }, [isVisible, placement]);\n\n /**\n * список id скроллящихся элементов для которых была выполнена проверка\n * влияет ли их скролл на взаимное положение активатора и дропа.\n * Получение сделано с помощью отдельной функции чтобы не создавать сет на каждый ререндер.\n */\n const processedScrollContainers = useRef<Set<HTMLElement>>();\n const getProcessedScrollContainers = (): Set<HTMLElement> => {\n processedScrollContainers.current = processedScrollContainers.current || new Set();\n return processedScrollContainers.current;\n };\n\n const visibleRef = useRef(isVisible);\n visibleRef.current = isVisible;\n\n const scrollHandler = useCallback(\n (target: HTMLElement) => {\n if (!visibleRef.current || !dropRef.current || !activatorRef.current) {\n return;\n }\n\n // Если это первый скролл данного контейнера, то проверяем содержит ли он активатор\n // Если он не содержит активатор, то можно отписаться от дальнейших оповещений о его скролле.\n if (!getProcessedScrollContainers().has(target)) {\n if (!target.contains(activatorRef.current)) {\n unsubscribeFromTarget(target, scrollHandler);\n return;\n }\n getProcessedScrollContainers().add(target);\n }\n\n updateMetricsSyncRef.current();\n },\n [activatorRef, dropRef]\n );\n\n useEffect(() => {\n // eslint-disable-next-line @typescript-eslint/no-unused-expressions\n isVisible ? reviveSubscription(scrollHandler) : suspendSubscription(scrollHandler);\n }, [isVisible, scrollHandler]);\n\n useEffect(() => {\n return () => deleteScrollSubscription(scrollHandler);\n }, [scrollHandler]);\n\n return {\n resizeRefCallbackFactory: observeResizeRefCallbackFactory,\n bestFitPlacementRect: bestFitPlacementRef.current,\n };\n};\n"],"names":[],"mappings":"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"}
|
package/useArrayMemo.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { useRef } from 'react';
|
|
3
|
+
|
|
4
|
+
const isEqual = (first, second) => first === second || (first.length === second.length && first.every((e, i) => e === second[i]));
|
|
5
|
+
const useArrayMemo = (cb, array, ...restArgs) => {
|
|
6
|
+
const prevArrayRef = useRef(array);
|
|
7
|
+
const prevRestArgsRef = useRef(restArgs);
|
|
8
|
+
const resultRef = useRef();
|
|
9
|
+
const isArrayEqual = isEqual(prevArrayRef.current, array);
|
|
10
|
+
const isRestArgsEqual = isEqual(prevRestArgsRef.current, restArgs);
|
|
11
|
+
prevArrayRef.current = array;
|
|
12
|
+
prevRestArgsRef.current = restArgs;
|
|
13
|
+
if (resultRef.current === undefined || !isArrayEqual || !isRestArgsEqual) {
|
|
14
|
+
resultRef.current = cb();
|
|
15
|
+
}
|
|
16
|
+
return resultRef.current;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { isEqual, useArrayMemo };
|
|
20
|
+
//# sourceMappingURL=useArrayMemo.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useArrayMemo.js","sources":["../src/useArrayMemo.ts"],"sourcesContent":["import { useRef } from 'react';\n\nexport const isEqual = (first: unknown[], second: unknown[]): boolean =>\n first === second || (first.length === second.length && first.every((e: unknown, i: number) => e === second[i]));\n\nconst useArrayMemo = <T, R>(cb: () => R, array: T[], ...restArgs: unknown[]): R => {\n const prevArrayRef = useRef(array);\n const prevRestArgsRef = useRef(restArgs);\n\n const resultRef = useRef<undefined | R>();\n\n const isArrayEqual = isEqual(prevArrayRef.current, array);\n const isRestArgsEqual = isEqual(prevRestArgsRef.current, restArgs);\n\n prevArrayRef.current = array;\n prevRestArgsRef.current = restArgs;\n\n if (resultRef.current === undefined || !isArrayEqual || !isRestArgsEqual) {\n resultRef.current = cb();\n }\n\n return resultRef.current;\n};\n\nexport { useArrayMemo };\n"],"names":[],"mappings":";;AAEa,MAAA,OAAO,GAAG,CAAC,KAAgB,EAAE,MAAiB,KACvD,KAAK,KAAK,MAAM,KAAK,KAAK,CAAC,MAAM,KAAK,MAAM,CAAC,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,CAAS,KAAK,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE;AAE9G,MAAA,YAAY,GAAG,CAAO,EAAW,EAAE,KAAU,EAAE,GAAG,QAAmB,KAAO;AAC9E,IAAA,MAAM,YAAY,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;AACnC,IAAA,MAAM,eAAe,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;AAEzC,IAAA,MAAM,SAAS,GAAG,MAAM,EAAiB,CAAC;IAE1C,MAAM,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC;IAC1D,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC;AAEnE,IAAA,YAAY,CAAC,OAAO,GAAG,KAAK,CAAC;AAC7B,IAAA,eAAe,CAAC,OAAO,GAAG,QAAQ,CAAC;AAEnC,IAAA,IAAI,SAAS,CAAC,OAAO,KAAK,SAAS,IAAI,CAAC,YAAY,IAAI,CAAC,eAAe,EAAE;AACtE,QAAA,SAAS,CAAC,OAAO,GAAG,EAAE,EAAE,CAAC;KAC5B;IAED,OAAO,SAAS,CAAC,OAAO,CAAC;AAC7B;;;;"}
|
package/usePlacements.js
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import './index.css';
|
|
2
|
+
import { useArrayMemo } from './useArrayMemo.js';
|
|
3
|
+
import 'react';
|
|
4
|
+
|
|
5
|
+
const HOR_DIRECTION_ALIGNMENT_PRIORITIES = ['center', 'top', 'bottom'];
|
|
6
|
+
const VER_DIRECTION_ALIGNMENT_PRIORITIES = ['center', 'left', 'right'];
|
|
7
|
+
const PLACEMENTS_MAP = {
|
|
8
|
+
right: HOR_DIRECTION_ALIGNMENT_PRIORITIES,
|
|
9
|
+
left: HOR_DIRECTION_ALIGNMENT_PRIORITIES,
|
|
10
|
+
top: VER_DIRECTION_ALIGNMENT_PRIORITIES,
|
|
11
|
+
bottom: VER_DIRECTION_ALIGNMENT_PRIORITIES,
|
|
12
|
+
};
|
|
13
|
+
const HOR_DIRECTIONS = ['right', 'left'];
|
|
14
|
+
const VER_DIRECTIONS = ['top', 'bottom'];
|
|
15
|
+
const usePlacement = (preferredPlacements, availablePlacements, forcePlacement) => {
|
|
16
|
+
const placements = Array.isArray(preferredPlacements) ? preferredPlacements : [preferredPlacements];
|
|
17
|
+
const result = useArrayMemo(() => {
|
|
18
|
+
if (forcePlacement) {
|
|
19
|
+
return placements;
|
|
20
|
+
}
|
|
21
|
+
const result = [...placements];
|
|
22
|
+
const processedDirections = {};
|
|
23
|
+
// массив, содержащий только уникальные directions из prefferedPlacements в порядке их первого
|
|
24
|
+
// упоминания в массиве
|
|
25
|
+
const preferredDirections = placements
|
|
26
|
+
.map((placement) => placement.split('-')[0])
|
|
27
|
+
.reduce((result, direction) => {
|
|
28
|
+
if (processedDirections[direction]) {
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
processedDirections[direction] = true;
|
|
32
|
+
result.push(direction);
|
|
33
|
+
return result;
|
|
34
|
+
}, []);
|
|
35
|
+
// Если перечислены не все возможные directions добавляем недостающие
|
|
36
|
+
// причем если наиболее приоритетный direction был вертикальным, то сначала добавляем вертикальные
|
|
37
|
+
// иначе горизонтальные
|
|
38
|
+
if (preferredDirections.length < 4) {
|
|
39
|
+
const directions = HOR_DIRECTIONS.includes(preferredDirections[0])
|
|
40
|
+
? [...HOR_DIRECTIONS, ...VER_DIRECTIONS]
|
|
41
|
+
: [...VER_DIRECTIONS, ...HOR_DIRECTIONS];
|
|
42
|
+
for (const direction of directions) {
|
|
43
|
+
!preferredDirections.includes(direction) && preferredDirections.push(direction);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// проходимся по всем directions в порядке приоритета
|
|
47
|
+
// для каждого из них генерируем все placements перебирая alignment в порядке приоритета
|
|
48
|
+
// для каждого placement проверяем есть ли он в preferredPlacements и в availablePlacements
|
|
49
|
+
// если нет в preferredPlacements и есть в availablePlacements, то добавляем этот placements к результату
|
|
50
|
+
// в итоге получаем список placement отсортированный по приоритетам directions в исходном массиве
|
|
51
|
+
for (const direction of preferredDirections) {
|
|
52
|
+
const alignments = PLACEMENTS_MAP[direction];
|
|
53
|
+
for (const alignment of alignments) {
|
|
54
|
+
const placement = `${direction}-${alignment}`;
|
|
55
|
+
if (!preferredPlacements.includes(placement) && availablePlacements.has(placement)) {
|
|
56
|
+
result.push(placement);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return result;
|
|
61
|
+
}, placements, forcePlacement, availablePlacements);
|
|
62
|
+
return result;
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
export { usePlacement };
|
|
66
|
+
//# sourceMappingURL=usePlacements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePlacements.js","sources":["../src/usePlacements.ts"],"sourcesContent":["import type {\n Placement,\n VerticalDirection,\n HorizontalDirection,\n AlignmentForVerticalDirection,\n AlignmentForHorizontalDirection,\n} from '@hh.ru/magritte-internal-drop-base/types';\nimport { useArrayMemo } from '@hh.ru/magritte-internal-drop-base/useArrayMemo';\n\nconst HOR_DIRECTION_ALIGNMENT_PRIORITIES = ['center', 'top', 'bottom'] as const;\nconst VER_DIRECTION_ALIGNMENT_PRIORITIES = ['center', 'left', 'right'] as const;\nconst PLACEMENTS_MAP = {\n right: HOR_DIRECTION_ALIGNMENT_PRIORITIES,\n left: HOR_DIRECTION_ALIGNMENT_PRIORITIES,\n top: VER_DIRECTION_ALIGNMENT_PRIORITIES,\n bottom: VER_DIRECTION_ALIGNMENT_PRIORITIES,\n} as const satisfies { [key in VerticalDirection]: readonly AlignmentForVerticalDirection[] } & {\n [key in HorizontalDirection]: readonly AlignmentForHorizontalDirection[];\n};\nconst HOR_DIRECTIONS: (VerticalDirection | HorizontalDirection)[] = ['right', 'left'];\nconst VER_DIRECTIONS: (VerticalDirection | HorizontalDirection)[] = ['top', 'bottom'];\n\nexport const usePlacement = (\n preferredPlacements: Placement[] | Placement,\n availablePlacements: Set<Placement>,\n forcePlacement: boolean\n): Placement[] => {\n const placements = Array.isArray(preferredPlacements) ? preferredPlacements : [preferredPlacements];\n\n const result = useArrayMemo(\n () => {\n if (forcePlacement) {\n return placements;\n }\n\n const result = [...placements];\n const processedDirections: Record<string, boolean> = {};\n\n // массив, содержащий только уникальные directions из prefferedPlacements в порядке их первого\n // упоминания в массиве\n const preferredDirections = placements\n .map((placement) => placement.split('-')[0])\n .reduce<string[]>((result, direction) => {\n if (processedDirections[direction]) {\n return result;\n }\n\n processedDirections[direction] = true;\n result.push(direction);\n return result;\n }, []) as (VerticalDirection | HorizontalDirection)[];\n\n // Если перечислены не все возможные directions добавляем недостающие\n // причем если наиболее приоритетный direction был вертикальным, то сначала добавляем вертикальные\n // иначе горизонтальные\n if (preferredDirections.length < 4) {\n const directions = HOR_DIRECTIONS.includes(preferredDirections[0])\n ? [...HOR_DIRECTIONS, ...VER_DIRECTIONS]\n : [...VER_DIRECTIONS, ...HOR_DIRECTIONS];\n for (const direction of directions) {\n !preferredDirections.includes(direction) && preferredDirections.push(direction);\n }\n }\n\n // проходимся по всем directions в порядке приоритета\n // для каждого из них генерируем все placements перебирая alignment в порядке приоритета\n // для каждого placement проверяем есть ли он в preferredPlacements и в availablePlacements\n // если нет в preferredPlacements и есть в availablePlacements, то добавляем этот placements к результату\n // в итоге получаем список placement отсортированный по приоритетам directions в исходном массиве\n for (const direction of preferredDirections) {\n const alignments = PLACEMENTS_MAP[direction];\n for (const alignment of alignments) {\n const placement = `${direction}-${alignment}` as Placement;\n if (!preferredPlacements.includes(placement) && availablePlacements.has(placement)) {\n result.push(placement);\n }\n }\n }\n\n return result;\n },\n placements,\n forcePlacement,\n availablePlacements\n );\n\n return result;\n};\n"],"names":[],"mappings":";;;AASA,MAAM,kCAAkC,GAAG,CAAC,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAU,CAAC;AAChF,MAAM,kCAAkC,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAU,CAAC;AAChF,MAAM,cAAc,GAAG;AACnB,IAAA,KAAK,EAAE,kCAAkC;AACzC,IAAA,IAAI,EAAE,kCAAkC;AACxC,IAAA,GAAG,EAAE,kCAAkC;AACvC,IAAA,MAAM,EAAE,kCAAkC;CAG7C,CAAC;AACF,MAAM,cAAc,GAAgD,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;AACtF,MAAM,cAAc,GAAgD,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;AAEzE,MAAA,YAAY,GAAG,CACxB,mBAA4C,EAC5C,mBAAmC,EACnC,cAAuB,KACV;AACb,IAAA,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAEpG,IAAA,MAAM,MAAM,GAAG,YAAY,CACvB,MAAK;QACD,IAAI,cAAc,EAAE;AAChB,YAAA,OAAO,UAAU,CAAC;SACrB;AAED,QAAA,MAAM,MAAM,GAAG,CAAC,GAAG,UAAU,CAAC,CAAC;QAC/B,MAAM,mBAAmB,GAA4B,EAAE,CAAC;;;QAIxD,MAAM,mBAAmB,GAAG,UAAU;AACjC,aAAA,GAAG,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;AAC3C,aAAA,MAAM,CAAW,CAAC,MAAM,EAAE,SAAS,KAAI;AACpC,YAAA,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE;AAChC,gBAAA,OAAO,MAAM,CAAC;aACjB;AAED,YAAA,mBAAmB,CAAC,SAAS,CAAC,GAAG,IAAI,CAAC;AACtC,YAAA,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AACvB,YAAA,OAAO,MAAM,CAAC;SACjB,EAAE,EAAE,CAAgD,CAAC;;;;AAK1D,QAAA,IAAI,mBAAmB,CAAC,MAAM,GAAG,CAAC,EAAE;YAChC,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC,CAAC,CAAC;AAC9D,kBAAE,CAAC,GAAG,cAAc,EAAE,GAAG,cAAc,CAAC;kBACtC,CAAC,GAAG,cAAc,EAAE,GAAG,cAAc,CAAC,CAAC;AAC7C,YAAA,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;AAChC,gBAAA,CAAC,mBAAmB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,mBAAmB,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;aACnF;SACJ;;;;;;AAOD,QAAA,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE;AACzC,YAAA,MAAM,UAAU,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;AAC7C,YAAA,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE;AAChC,gBAAA,MAAM,SAAS,GAAG,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,SAAS,EAAe,CAAC;AAC3D,gBAAA,IAAI,CAAC,mBAAmB,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,mBAAmB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE;AAChF,oBAAA,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;iBAC1B;aACJ;SACJ;AAED,QAAA,OAAO,MAAM,CAAC;AAClB,KAAC,EACD,UAAU,EACV,cAAc,EACd,mBAAmB,CACtB,CAAC;AAEF,IAAA,OAAO,MAAM,CAAC;AAClB;;;;"}
|