add focusNode custom hook

This commit is contained in:
AykutSarac 2022-04-24 23:27:14 +03:00
parent 7e2c760951
commit f573565348
6 changed files with 75 additions and 67 deletions

View File

@ -1,8 +1,7 @@
import React from "react";
import { AiOutlineSearch } from "react-icons/ai";
import { IoCloseSharp } from "react-icons/io5";
import { useConfig } from "src/hocs/config";
import { ConfigActionType } from "src/reducer/reducer";
import { useFocusNode } from "src/hooks/useFocusNode";
import styled from "styled-components";
const StyledInputWrapper = styled.div`
@ -48,32 +47,28 @@ const StyledSearchButton = styled.button`
}
`;
export const Input = () => {
const { dispatch } = useConfig();
const [value, setValue] = React.useState("");
React.useEffect(() => {
const debouncer = setTimeout(() => {
dispatch({ type: ConfigActionType.SET_SEARCH_NODE, payload: value });
}, 1500);
return () => clearTimeout(debouncer);
}, [value, dispatch]);
const handleClick = () => {
setValue("");
};
export const Input: React.FC = () => {
const [content, setContent] = useFocusNode();
return (
<StyledInputWrapper>
<StyledInput
type="text"
value={value}
onChange={(e) => setValue(e.target.value)}
value={content.value}
onChange={(e) =>
setContent((val) => ({ ...val, value: e.target.value }))
}
placeholder="Search Node"
/>
<StyledSearchButton aria-label="search" onClick={handleClick}>
{value ? <IoCloseSharp size={18} /> : <AiOutlineSearch size={18} />}
<StyledSearchButton
aria-label="search"
onClick={() => setContent({ value: "", debounced: "" })}
>
{content.value ? (
<IoCloseSharp size={18} />
) : (
<AiOutlineSearch size={18} />
)}
</StyledSearchButton>
</StyledInputWrapper>
);

View File

@ -38,7 +38,6 @@ export const defaultConfig: StorageConfig = {
expand: true,
autoformat: true,
hideEditor: false,
searchNode: "",
zoomPanPinch: null,
lightmode: false
};

View File

@ -13,6 +13,7 @@ import { useLoading } from "src/hooks/useLoading";
import { useConfig } from "src/hocs/config";
import { Tools } from "../Editor/Tools";
import { ConfigActionType } from "src/reducer/reducer";
import { useFocusNode } from "src/hooks/useFocusNode";
const StyledLiveEditor = styled.div`
position: relative;
@ -51,49 +52,16 @@ export const LiveEditor: React.FC = React.memo(function LiveEditor() {
setData({ nodes, edges });
}, [json, settings.expand]);
React.useEffect(() => {
if (!settings.zoomPanPinch) return;
const zoomPanPinch = settings.zoomPanPinch.instance.wrapperComponent;
const node = document.querySelector(
`span[data-key*='${settings.searchNode}' i]`
);
document
.querySelector("foreignObject.searched")
?.classList.remove("searched");
if (zoomPanPinch && node && node.parentElement) {
const newScale = 1;
const x = Number(node.getAttribute("data-x"));
const y = Number(node.getAttribute("data-y"));
const newPositionX =
(zoomPanPinch.offsetLeft - x) * newScale +
node.getBoundingClientRect().width;
const newPositionY =
(zoomPanPinch.offsetTop - y) * newScale +
node.getBoundingClientRect().height;
node.parentElement.parentElement
?.closest("foreignObject")
?.classList.toggle("searched");
settings.zoomPanPinch?.setTransform(newPositionX, newPositionY, newScale);
}
}, [settings.searchNode, settings.zoomPanPinch]);
const onCanvasClick = () => {
const input = document.querySelector("input:focus") as HTMLInputElement;
if (input) input.blur();
};
const onInit = (ref: ReactZoomPanPinchRef) => {
const onInit = (ref: ReactZoomPanPinchRef) =>
dispatch({
type: ConfigActionType.SET_ZOOM_PAN_PICNH_REF,
payload: ref,
});
};
if (pageLoaded)
return (

View File

@ -0,0 +1,57 @@
import React from "react";
import { useConfig } from "src/hocs/config";
type Content = { value: string; debounced: string };
export const useFocusNode = () => {
const [content, setContent] = React.useState({
value: "",
debounced: "",
});
const {
states: { settings },
} = useConfig();
React.useEffect(() => {
const debouncer = setTimeout(() => {
setContent((val) => ({ ...val, debounced: content.value }));
}, 1500);
return () => clearTimeout(debouncer);
}, [content.value]);
React.useEffect(() => {
if (!settings.zoomPanPinch) return;
const zoomPanPinch = settings.zoomPanPinch.instance.wrapperComponent;
const node = document.querySelector(
`span[data-key*='${content.debounced}' i]`
);
document
.querySelector("foreignObject.searched")
?.classList.remove("searched");
if (zoomPanPinch && node && node.parentElement) {
const newScale = 1;
const x = Number(node.getAttribute("data-x"));
const y = Number(node.getAttribute("data-y"));
const newPositionX =
(zoomPanPinch.offsetLeft - x) * newScale +
node.getBoundingClientRect().width;
const newPositionY =
(zoomPanPinch.offsetTop - y) * newScale +
node.getBoundingClientRect().height;
node.parentElement.parentElement
?.closest("foreignObject")
?.classList.toggle("searched");
settings.zoomPanPinch?.setTransform(newPositionX, newPositionY, newScale);
}
}, [content, settings.zoomPanPinch]);
return [content, setContent] as const;
};

View File

@ -13,7 +13,6 @@ export enum ConfigActionType {
ZOOM_OUT,
CENTER_VIEW,
SET_JSON,
SET_SEARCH_NODE,
SET_ZOOM_PAN_PICNH_REF,
}
@ -51,15 +50,6 @@ export const useConfigReducer: React.Reducer<AppConfig, ReducerAction> = (
},
};
case ConfigActionType.SET_SEARCH_NODE:
return {
...state,
settings: {
...state.settings,
searchNode: action.payload,
},
};
case ConfigActionType.CENTER_VIEW:
state.settings.zoomPanPinch?.resetTransform();
return state;

View File

@ -7,7 +7,6 @@ export interface StorageConfig {
expand: boolean;
autoformat: boolean;
hideEditor: boolean;
searchNode: string;
zoomPanPinch: ReactZoomPanPinchRef | null;
lightmode: boolean;
}