fork refine

This commit is contained in:
Stefan Pejcic
2024-02-05 10:23:04 +01:00
parent 3fffde9a8f
commit 8496a83edb
3634 changed files with 715528 additions and 2 deletions

View File

@@ -0,0 +1,124 @@
import { Placement } from "src/interfaces/placement";
export const getPanelToggleTransforms = (visible: boolean) => {
return visible ? "scaleX(1) translateY(0)" : `scaleX(0) translateY(25vw)`;
};
export const SIZE = 50;
export const BUFFER = 10;
const PREFERRED_DEFAULT_WIDTH = () =>
typeof window !== "undefined" ? window.innerWidth * 0.7 : 1440 * 0.7; // 70% of window width
const PREFERRED_DEFAULT_HEIGHT = () =>
typeof window !== "undefined" ? window.innerHeight * 0.7 : 900 * 0.7; // 70% of window height
export const MIN_PANEL_WIDTH = 640;
export const MIN_PANEL_HEIGHT = 360;
export const getPinButtonTransform = (hover?: boolean) => {
return `translateY(${hover ? "0" : "50%"})`;
};
export const getPanelPosition = (placement: Placement) => {
switch (placement) {
case "left":
return {
left: `calc(${SIZE}px + ${BUFFER}px)`,
top: "50%",
transform: "translateY(-50%)",
};
case "right":
return {
right: `calc(${SIZE}px + ${BUFFER}px)`,
top: "50%",
transform: "translateY(-50%)",
};
case "top":
return {
left: "50%",
top: `calc(${SIZE}px + ${BUFFER}px)`,
transform: "translateX(-50%)",
};
default:
case "bottom":
return {
left: "50%",
bottom: `calc(${SIZE}px + ${BUFFER}px)`,
transform: "translateX(-50%)",
};
}
};
export const getMaxPanelWidth = (placement: Placement) => {
switch (placement) {
case "left":
case "right":
return (
-BUFFER -
SIZE -
BUFFER +
(typeof window !== "undefined" ? window.innerWidth : 1440) -
BUFFER
);
case "top":
case "bottom":
return (
-BUFFER +
(typeof window !== "undefined" ? window.innerWidth : 1440) -
BUFFER
);
}
};
export const getMaxPanelHeight = (placement: Placement) => {
switch (placement) {
case "left":
case "right":
return (
-BUFFER +
(typeof window !== "undefined" ? window.innerHeight : 900) -
BUFFER
);
case "top":
case "bottom":
return (
-BUFFER -
SIZE -
BUFFER +
(typeof window !== "undefined" ? window.innerHeight : 900) -
BUFFER
);
}
};
export const getDefaultPanelSize = (
placement: Placement,
preferredSize?: { width: number; height: number },
): { width: number; height: number } => {
const defaultPreferred = {
width: PREFERRED_DEFAULT_WIDTH(),
height: PREFERRED_DEFAULT_HEIGHT(),
};
const maxPanelWidth = getMaxPanelWidth(placement);
const maxPanelHeight = getMaxPanelHeight(placement);
const width = Math.min(
maxPanelWidth,
(preferredSize ?? defaultPreferred).width,
);
const height = Math.min(
maxPanelHeight,
(preferredSize ?? defaultPreferred).height,
);
return {
width: width,
height: height,
};
};
export const roundToEven = (num: number) => {
const rounded = Math.round(num);
return rounded % 2 === 0 ? rounded : rounded + 1;
};

View File

@@ -0,0 +1,259 @@
import {
getElementFromFiber,
getFiberFromElement,
getFirstFiberHasName,
getFirstStateNodeFiber,
getNameFromFiber,
getParentOfFiber,
} from "@aliemir/dom-to-fiber-utils";
import { DevToolsContext } from "@refinedev/devtools-shared";
import debounce from "lodash/debounce";
import React from "react";
type Fiber = Exclude<ReturnType<typeof getFiberFromElement>, null>;
export const useSelector = (active: boolean) => {
const { devtoolsUrl } = React.useContext(DevToolsContext);
const [traceItems, setTraceItems] = React.useState<string[]>([]);
React.useEffect(() => {
if (active) {
fetch(
`${
devtoolsUrl ?? "http://localhost:5001"
}/api/unique-trace-items`,
).then((res) =>
res
.json()
.then((data: { data: string[] }) =>
setTraceItems(data.data),
),
);
}
}, [active, devtoolsUrl]);
const [selectedFiber, setSelectedFiber] = React.useState<{
stateNode: Fiber | null;
nameFiber: Fiber | null;
}>({
stateNode: null,
nameFiber: null,
});
const [activeFiber, setActiveFiber] = React.useState<{
stateNode: Fiber | null;
nameFiber: Fiber | null;
derived?: boolean;
}>({
stateNode: null,
nameFiber: null,
derived: false,
});
React.useEffect(() => {
if (active) {
return () => {
setSelectedFiber({
stateNode: null,
nameFiber: null,
});
setActiveFiber({
stateNode: null,
nameFiber: null,
derived: false,
});
};
}
return () => 0;
}, [active]);
const selectAppropriateFiber = React.useCallback(
(start: Fiber | null) => {
let fiber = start;
let firstParentOfNodeWithName: Fiber | null;
let fiberWithStateNode: Fiber | null;
let acceptedName = false;
while (!acceptedName && fiber) {
// Get the first fiber node that has a name (look up the tree)
firstParentOfNodeWithName = getFirstFiberHasName(fiber);
// Get the first fiber node that has a state node (look up the tree)
fiberWithStateNode = getFirstStateNodeFiber(
firstParentOfNodeWithName,
);
acceptedName = traceItems.includes(
getNameFromFiber(firstParentOfNodeWithName) ?? "",
);
if (!acceptedName) {
fiber = getParentOfFiber(fiber);
}
}
if (fiberWithStateNode && firstParentOfNodeWithName) {
return {
stateNode: fiberWithStateNode,
nameFiber: firstParentOfNodeWithName,
};
} else {
return {
stateNode: null,
nameFiber: null,
};
}
},
[traceItems],
);
const pickFiber = React.useCallback(
(target: HTMLElement) => {
const fiber = getFiberFromElement(target);
setSelectedFiber(selectAppropriateFiber(fiber));
return;
},
[traceItems],
);
React.useEffect(() => {
if (
activeFiber.stateNode !== selectedFiber.stateNode ||
activeFiber.nameFiber !== selectedFiber.nameFiber
) {
setActiveFiber({
stateNode: selectedFiber.stateNode,
nameFiber: selectedFiber.nameFiber,
derived: false,
});
}
}, [selectedFiber]);
const previousValues = React.useRef<{
rect: {
width: number;
height: number;
x: number;
y: number;
};
name: string;
}>({
rect: {
width: 0,
height: 0,
x: 0,
y: 0,
},
name: "",
});
const { rect, name } = React.useMemo(() => {
if (!active) {
return {
rect: {
width: 0,
height: 0,
x: 0,
y: 0,
},
name: "",
};
}
if (activeFiber.stateNode || activeFiber.nameFiber) {
// Get the element from the fiber with a state node
const element = activeFiber.stateNode
? getElementFromFiber(activeFiber.stateNode)
: null;
// Get the name of the fiber node with a name
const fiberName = activeFiber.nameFiber
? getNameFromFiber(activeFiber.nameFiber)
: null;
if (!element) {
return {
rect: previousValues.current.rect,
name: fiberName ?? previousValues.current.name,
};
}
const bounding = element.getBoundingClientRect?.();
if (!bounding) {
return {
rect: previousValues.current.rect,
name: fiberName ?? previousValues.current.name,
};
}
return {
rect: {
width: bounding.width,
height: bounding.height,
x: bounding.left,
y: bounding.top,
},
name: fiberName ?? previousValues.current.name,
};
}
return previousValues.current;
}, [activeFiber, active]);
previousValues.current = {
rect,
name,
};
React.useEffect(() => {
if (active) {
const listener = (e: KeyboardEvent) => {
// if user presses shift, toggle the derived state and set the active fiber to the parent
if (e.key === "Shift" && activeFiber.stateNode) {
e.stopPropagation();
e.preventDefault();
const parent = getParentOfFiber(activeFiber.nameFiber);
const fibers = selectAppropriateFiber(parent);
if (fibers.nameFiber && fibers.stateNode) {
setActiveFiber({
...fibers,
derived: true,
});
return;
}
}
};
document.addEventListener("keydown", listener);
return () => document.removeEventListener("keydown", listener);
}
return () => 0;
}, [activeFiber, active]);
React.useEffect(() => {
if (active) {
let previousTarget: HTMLElement | null = null;
const listener = debounce((e: MouseEvent) => {
if (e?.target) {
if (previousTarget === e.target) {
return;
}
pickFiber(e.target as HTMLElement);
previousTarget = e.target as HTMLElement;
}
}, 50);
document.addEventListener("mousemove", listener);
return () => document.removeEventListener("mousemove", listener);
} else {
return () => 0;
}
}, [active, pickFiber]);
return {
rect,
name,
};
};