added auto focus offset

This commit is contained in:
mushka 2022-03-01 14:45:14 +03:00
parent 2378a32ddb
commit 16e83aedac
3 changed files with 61 additions and 37 deletions

View File

@ -7,16 +7,9 @@ const offset = 32;
const wrapperPadding = DomHelpers.getViewport() <= tablet ? 16 : 20;
export const countAutoOffset = (data, submenuItemsRef) => {
const refCurrent = submenuItemsRef.current;
const textWidths = data.map((d) => countTextWidth(d.name));
const itemsAndGaps = countItemsAndGaps(textWidths);
const submenuWidth = refCurrent.offsetWidth;
const marker = refCurrent.scrollLeft + submenuWidth - wrapperPadding;
const [itemOnMarker] = itemsAndGaps.filter(
(obj) => obj.start < marker && marker < obj.end
const [marker, itemsAndGaps, itemOnMarker] = countParams(
data,
submenuItemsRef
);
if (itemOnMarker === undefined) return 0;
@ -38,19 +31,54 @@ export const countAutoOffset = (data, submenuItemsRef) => {
return 0;
};
const countTextWidth = (text) => {
export const countAutoFocus = (itemId, data, submenuItemsRef) => {
const [marker, itemsAndGaps, itemOnMarker] = countParams(
data,
submenuItemsRef
);
const [focusedItem] = itemsAndGaps.filter((obj) => obj.id === itemId);
const submenuWidth = submenuItemsRef.current.offsetWidth;
if (itemOnMarker.id && focusedItem.id === itemOnMarker.id)
return focusedItem.end - marker;
if (
focusedItem.start < marker - submenuWidth ||
focusedItem.start - offset < marker - submenuWidth
)
return focusedItem.start - marker + submenuWidth - wrapperPadding - offset;
return 0;
};
const countParams = (data, submenuItemsRef) => {
const refCurrent = submenuItemsRef.current;
const texts = data.map((d) => countText(d.name));
const itemsAndGaps = countItemsAndGaps(texts);
const submenuWidth = refCurrent.offsetWidth;
const marker = refCurrent.scrollLeft + submenuWidth - wrapperPadding;
const [itemOnMarker] = itemsAndGaps.filter(
(obj) => obj.start < marker && marker < obj.end
);
return [marker, itemsAndGaps, itemOnMarker];
};
const countText = (text) => {
const inputText = text;
const font = "600 13px open sans";
const canvas = document.createElement("canvas");
const context = canvas.getContext("2d");
context.font = font;
return context.measureText(inputText).width;
return { id: text, width: context.measureText(inputText).width };
};
const countItemsAndGaps = (textWidths) => {
const countItemsAndGaps = (texts) => {
const result = [];
textWidths.forEach((textWidth) => {
texts.forEach(({ id, width }) => {
if (!result.length)
result.push(
{
@ -60,10 +88,11 @@ const countItemsAndGaps = (textWidths) => {
end: paddingGap + wrapperPadding,
},
{
id: id,
type: "item",
length: textWidth,
length: width,
start: paddingGap,
end: paddingGap + textWidth,
end: paddingGap + width,
}
);
else {
@ -76,10 +105,11 @@ const countItemsAndGaps = (textWidths) => {
end: lastItem.end + paddingGap * 2 + flexGap,
},
{
id: id,
type: "item",
length: textWidth,
length: width,
start: lastItem.end + paddingGap * 2 + flexGap,
end: lastItem.end + paddingGap * 2 + flexGap + textWidth,
end: lastItem.end + paddingGap * 2 + flexGap + width,
}
);
}

View File

@ -1,8 +1,8 @@
import PropTypes from "prop-types";
import React, { useEffect, useRef, useState } from "react";
import Text from "../text";
import { countAutoOffset } from "./autoOffset";
import Text from "../text";
import { countAutoFocus, countAutoOffset } from "./autoOffset";
import {
StyledSubmenu,
StyledSubmenuBottomLine,
@ -20,17 +20,14 @@ const Submenu = ({ data, startSelect = 0, ...rest }) => {
data[startSelect] || startSelect || null
);
const submenuItemsRef = useRef();
const selectSubmenuItem = (e) => {
const item = data.find((el) => el.id === e.currentTarget.id);
if (item) setCurrentItem(item);
};
const submenuItemsRef = useRef();
if (submenuItemsRef.current) {
const offset = countAutoOffset(data, submenuItemsRef);
const offset = countAutoFocus(item.name, data, submenuItemsRef);
submenuItemsRef.current.scrollLeft += offset;
}
};
useEffect(() => {
if (!submenuItemsRef.current) return;

View File

@ -15,11 +15,6 @@ export const StyledSubmenu = styled.div`
width: auto;
display: inline-block;
position: absolute;
/* position: absolute;
visibility: hidden;
height: auto;
width: auto;
white-space: nowrap; */
}
`;
@ -43,9 +38,9 @@ export const StyledSubmenuItems = styled.div`
display: flex;
flex-direction: row;
gap: 4px;
padding: 20px;
padding: 0 20px;
@media ${tablet} {
padding: 16px;
padding: 0 16px;
}
&::-webkit-scrollbar {
@ -59,8 +54,9 @@ export const StyledSubmenuItem = styled.div.attrs((props) => ({
scroll-behavior: smooth;
cursor: pointer;
display: flex;
gap: 4px;
flex-direction: column;
padding: 4px 14px;
padding: 4px 14px 0;
line-height: 20px;
`;
@ -70,8 +66,9 @@ export const StyledSubmenuItemText = styled.div`
`;
export const StyledSubmenuItemLabel = styled.div`
positin: absolute;
width: 100%;
z-index: 1;
width: calc(100% + 28px);
margin-left: -14px;
height: 4px;
bottom: 0px;
border-radius: 4px 4px 0 0;