-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
148 lines (125 loc) · 4.32 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
import React from "react";
//#region Custom hooks;
//#region useEffectWithMount
const NO_DEPENDENCIES: unknown[] = [];
/**
* @summary Executes a callback function after the component has mounted and whenever the dependencies change,
* useful in preventing memory leaks.
* @param callback - The callback function to be executed.
* @param dependencies - An optional array of dependencies.
* @example
* useEffectWithMount(() => console.log('Component has mounted!'), []);
*/
export const useEffectWithMount = (
callback: () => void,
dependencies: unknown[] = NO_DEPENDENCIES
): void => {
const isMounted = React.useRef(false);
React.useEffect(() => {
// eslint-disable-next-line @typescript-eslint/no-unused-expressions
isMounted.current ? callback() : (isMounted.current = true);
// eslint-disable-next-line react-hooks/exhaustive-deps
}, dependencies);
};
//#endregion
//#region useWindowDimensions
type TWindowDimensions = {
width: number;
height: number;
};
type TDevice = {
Mobile: boolean;
Tablet: boolean;
Desktop: boolean;
XLDesktop: boolean;
};
interface IUseWindowDimensionsProps {
windowDimensions: TWindowDimensions;
device: TDevice;
}
// Breakpoints for different devices.
const breakpoints: { [key: string]: number } = {
minTabletWidth: 768,
minDesktopWidth: 1024,
minXLDesktopWidth: 1440,
};
const getWindowDimensions = (): TWindowDimensions => ({
width: window.innerWidth,
height: window.innerHeight,
});
/**
* @summary Provides the dimensions of the window and the device type.
* @returns An object containing the window dimensions and the device type.
* @example
* To get the window dimensions:
* const { windowDimensions } = useWindowDimensions();
* console.log("Width: " + windowDimensions.width, "Height: " + windowDimensions.height);
* @example
* To verify the device type:
* const { device } = useWindowDimensions();
* console.log("Device type: " + (device.Mobile ? "Mobile" : "Not mobile"));
*/
export function useWindowDimensions(): IUseWindowDimensionsProps {
const [windowDimensions, setWindowDimensions] =
React.useState<TWindowDimensions>(getWindowDimensions());
React.useLayoutEffect(() => {
const handleWindowResize = (): void =>
setWindowDimensions(getWindowDimensions());
window.addEventListener("resize", handleWindowResize);
return () => window.removeEventListener("resize", handleWindowResize);
}, []);
const device: TDevice = React.useMemo(() => {
const { width } = windowDimensions;
return {
Mobile: width < breakpoints.minTabletWidth,
Tablet:
width >= breakpoints.minTabletWidth &&
width < breakpoints.minDesktopWidth,
Desktop:
width >= breakpoints.minDesktopWidth &&
width < breakpoints.minXLDesktopWidth,
XLDesktop: width >= breakpoints.minXLDesktopWidth,
};
}, [windowDimensions]);
return { windowDimensions, device };
}
//#endregion
//#endregion
//#region Utils;
//#region setFocus
const NO_DELAY = 0;
/**
* @summary Sets focus on the specified target element after an optional delay.
* @param targetElement - The target element to set focus on, can be a React ref object, or a string selector.
* @param delay - The delay in milliseconds before setting focus. Defaults to 0.
* @throws Error if the target element is not found.
* @example setFocus(inputElementRef);
* @example or setFocus(".select-search-input", 1000);
*/
export const setFocus = (
targetElement: React.RefObject<HTMLElement> | string,
delay: number | undefined = NO_DELAY
): void => {
let element: HTMLElement | null = null;
if (typeof targetElement === "string")
element = document.querySelector(targetElement);
else element = targetElement?.current as HTMLElement | null;
if (!element) throw new Error("Target element not found.");
setTimeout(() => element.focus(), delay);
};
//#endregion
//#region promptBeforeUnload
const DEFAULT_MESSAGE = "Changes you made may not be saved.";
/**
* @summary Prompts the user before unloading the page.
* @param message - The message to display to the user.
* @example promptBeforeUnload("Are you sure you want to leave?");
*/
export const promptBeforeUnload = (message: string = DEFAULT_MESSAGE): void => {
window.addEventListener("beforeunload", (event) => {
event.preventDefault();
event.returnValue = message;
});
};
//#endregion
//#endregion