@sohanemon/utils 1.0.2 → 2.1.0
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/dist/components/index.d.ts +1 -0
- package/dist/components/index.js +1 -0
- package/dist/functions/index.d.ts +4 -0
- package/dist/functions/index.js +13 -0
- package/dist/hooks/index.d.ts +9 -0
- package/dist/hooks/index.js +115 -0
- package/dist/index.d.ts +2 -14
- package/dist/index.js +3 -74
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Icon as Iconify } from '@iconify/react';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Icon as Iconify } from '@iconify/react';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { clsx } from 'clsx';
|
|
2
|
+
import { twMerge } from 'tailwind-merge';
|
|
3
|
+
export function cn(...inputs) {
|
|
4
|
+
return twMerge(clsx(inputs));
|
|
5
|
+
}
|
|
6
|
+
export function isNavActive(href, path) {
|
|
7
|
+
return href === '/' ? path === '/' : path?.includes(href);
|
|
8
|
+
}
|
|
9
|
+
export function cleanSrc(src) {
|
|
10
|
+
if (src.includes('/public/'))
|
|
11
|
+
return src.replace('/public/', '/');
|
|
12
|
+
return src;
|
|
13
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { EffectCallback } from 'react';
|
|
2
|
+
export declare const useClickOutside: (callback?: () => void) => any;
|
|
3
|
+
export declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): any;
|
|
4
|
+
export declare const useSwiperRef: () => any[];
|
|
5
|
+
export declare function useEffectOnce(effect: EffectCallback): void;
|
|
6
|
+
export declare function useUpdateEffect(effect: EffectCallback, deps: any[]): void;
|
|
7
|
+
export declare const useIsomorphicEffect: any;
|
|
8
|
+
export declare function useTimeout(callback: () => void, delay?: number | null): void;
|
|
9
|
+
export declare function useWindowEvent<K extends string = keyof WindowEventMap>(type: K, listener: K extends keyof WindowEventMap ? (this: Window, ev: WindowEventMap[K]) => void : (this: Window, ev: CustomEvent) => void, options?: boolean | AddEventListenerOptions): void;
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
|
|
2
|
+
export const useClickOutside = (callback = () => alert('clicked outside')) => {
|
|
3
|
+
const ref = useRef(null);
|
|
4
|
+
const listener = (e) => {
|
|
5
|
+
if (ref.current && !ref.current.contains(e.target)) {
|
|
6
|
+
callback();
|
|
7
|
+
}
|
|
8
|
+
};
|
|
9
|
+
useEffect(() => {
|
|
10
|
+
document.addEventListener('mousedown', listener);
|
|
11
|
+
document.addEventListener('touchstart', listener);
|
|
12
|
+
return () => {
|
|
13
|
+
document.removeEventListener('mousedown', listener);
|
|
14
|
+
document.removeEventListener('touchstart', listener);
|
|
15
|
+
};
|
|
16
|
+
});
|
|
17
|
+
return ref;
|
|
18
|
+
};
|
|
19
|
+
export function useMediaQuery(tailwindBreakpoint) {
|
|
20
|
+
const parsedQuery = useMemo(() => {
|
|
21
|
+
switch (tailwindBreakpoint) {
|
|
22
|
+
case 'sm':
|
|
23
|
+
return '(min-width: 640px)';
|
|
24
|
+
case 'md':
|
|
25
|
+
return '(min-width: 768px)';
|
|
26
|
+
case 'lg':
|
|
27
|
+
return '(min-width: 1024px)';
|
|
28
|
+
case 'xl':
|
|
29
|
+
return '(min-width: 1280px)';
|
|
30
|
+
case '2xl':
|
|
31
|
+
return '(min-width: 1536px)';
|
|
32
|
+
default:
|
|
33
|
+
return tailwindBreakpoint;
|
|
34
|
+
}
|
|
35
|
+
}, [tailwindBreakpoint]);
|
|
36
|
+
const getMatches = (parsedQuery) => {
|
|
37
|
+
if (typeof window !== 'undefined') {
|
|
38
|
+
return window.matchMedia(parsedQuery).matches;
|
|
39
|
+
}
|
|
40
|
+
return false;
|
|
41
|
+
};
|
|
42
|
+
const [matches, setMatches] = useState(getMatches(parsedQuery));
|
|
43
|
+
function handleChange() {
|
|
44
|
+
setMatches(getMatches(parsedQuery));
|
|
45
|
+
}
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
const matchMedia = window.matchMedia(parsedQuery);
|
|
48
|
+
handleChange();
|
|
49
|
+
matchMedia.addEventListener('change', handleChange);
|
|
50
|
+
return () => {
|
|
51
|
+
matchMedia.removeEventListener('change', handleChange);
|
|
52
|
+
};
|
|
53
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
|
+
}, [parsedQuery]);
|
|
55
|
+
return matches;
|
|
56
|
+
}
|
|
57
|
+
export const useSwiperRef = () => {
|
|
58
|
+
const [navigationElement, setNavigationElement] = useState(null);
|
|
59
|
+
const ref = useRef(null);
|
|
60
|
+
useEffect(() => {
|
|
61
|
+
setNavigationElement(ref.current);
|
|
62
|
+
}, []);
|
|
63
|
+
return [navigationElement, ref];
|
|
64
|
+
};
|
|
65
|
+
// call the hook
|
|
66
|
+
// const [nextEl, nextRef] = useSwiperRef();
|
|
67
|
+
// const [prevEl, prevRef] = useSwiperRef();
|
|
68
|
+
// add to navigation module
|
|
69
|
+
// <Swiper
|
|
70
|
+
// modules={[Navigation]}
|
|
71
|
+
// navigation={{
|
|
72
|
+
// prevEl,
|
|
73
|
+
// nextEl,
|
|
74
|
+
// }}
|
|
75
|
+
// >
|
|
76
|
+
// ...
|
|
77
|
+
// </Swiper>;
|
|
78
|
+
// add ref to any element which may trigger
|
|
79
|
+
// <button ref={nextRef}>...</button>;
|
|
80
|
+
export function useEffectOnce(effect) {
|
|
81
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
82
|
+
useEffect(effect, []);
|
|
83
|
+
}
|
|
84
|
+
export function useUpdateEffect(effect, deps) {
|
|
85
|
+
const isInitialMount = useRef(true);
|
|
86
|
+
useEffect(() => {
|
|
87
|
+
if (isInitialMount.current) {
|
|
88
|
+
isInitialMount.current = false;
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
return effect();
|
|
92
|
+
}
|
|
93
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
94
|
+
}, deps);
|
|
95
|
+
}
|
|
96
|
+
export const useIsomorphicEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
|
|
97
|
+
export function useTimeout(callback, delay = 1000) {
|
|
98
|
+
const savedCallback = useRef(callback);
|
|
99
|
+
useIsomorphicEffect(() => {
|
|
100
|
+
savedCallback.current = callback;
|
|
101
|
+
}, [callback]);
|
|
102
|
+
useEffect(() => {
|
|
103
|
+
if (!delay && delay !== 0) {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
const id = setTimeout(() => savedCallback.current(), delay);
|
|
107
|
+
return () => clearTimeout(id);
|
|
108
|
+
}, [delay]);
|
|
109
|
+
}
|
|
110
|
+
export function useWindowEvent(type, listener, options) {
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
window.addEventListener(type, listener, options);
|
|
113
|
+
return () => window.removeEventListener(type, listener, options);
|
|
114
|
+
}, [type, listener]);
|
|
115
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,14 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
[key: string]: string | {
|
|
4
|
-
DEFAULT: string;
|
|
5
|
-
foreground?: string;
|
|
6
|
-
};
|
|
7
|
-
}
|
|
8
|
-
export declare function cn(...inputs: ClassValue[]): string;
|
|
9
|
-
export declare function isNavActive(href: string, path: string): boolean;
|
|
10
|
-
export declare function kebabCase(camelCase: string): string;
|
|
11
|
-
export declare function cssColorVariable(colors: Record<string, string>): Record<string, string>;
|
|
12
|
-
export declare function cleanSrc(src: string): string;
|
|
13
|
-
export declare function tailwindColorObject(input: Record<string, string>): ColorObject;
|
|
14
|
-
export {};
|
|
1
|
+
export { Iconify } from './components';
|
|
2
|
+
export { cleanSrc, cn, isNavActive } from './functions';
|
package/dist/index.js
CHANGED
|
@@ -1,74 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
export
|
|
4
|
-
return twMerge(clsx(inputs));
|
|
5
|
-
}
|
|
6
|
-
export function isNavActive(href, path) {
|
|
7
|
-
return href === '/' ? path === '/' : path?.includes(href);
|
|
8
|
-
}
|
|
9
|
-
function hexToHSLFormatted(hexColor) {
|
|
10
|
-
const [r, g, b] = hexColor.match(/\w\w/g)?.map((c) => parseInt(c, 16) / 255);
|
|
11
|
-
const maxVal = Math.max(r, g, b), minVal = Math.min(r, g, b);
|
|
12
|
-
const lightness = (maxVal + minVal) / 2;
|
|
13
|
-
const delta = maxVal - minVal;
|
|
14
|
-
const saturation = delta === 0 ? 0 : delta / (1 - Math.abs(2 * lightness - 1));
|
|
15
|
-
let hue = delta !== 0
|
|
16
|
-
? maxVal === r
|
|
17
|
-
? ((g - b) / delta + (g < b ? 6 : 0)) * 60
|
|
18
|
-
: maxVal === g
|
|
19
|
-
? ((b - r) / delta + 2) * 60
|
|
20
|
-
: ((r - g) / delta + 4) * 60
|
|
21
|
-
: 0;
|
|
22
|
-
if (hue < 0)
|
|
23
|
-
hue += 360;
|
|
24
|
-
return `${Math.round(hue)} ${Math.round(saturation * 100)}% ${Math.round(lightness * 100)}%`;
|
|
25
|
-
}
|
|
26
|
-
function extractHSLValues(input) {
|
|
27
|
-
if (input.includes('#'))
|
|
28
|
-
return hexToHSLFormatted(input);
|
|
29
|
-
const matches = input.match(/hsla?\(([\d.]+),\s*([\d.]+)%,\s*([\d.]+)%(?:,\s*[\d.]+)?\)/);
|
|
30
|
-
if (!matches)
|
|
31
|
-
throw new Error(`Invalid HSL format: ${input}`);
|
|
32
|
-
return `${matches[1]} ${matches[2]}% ${matches[3]}%`;
|
|
33
|
-
}
|
|
34
|
-
export function kebabCase(camelCase) {
|
|
35
|
-
return camelCase.replace(/[A-Z]+(?![a-z])|[A-Z]/g, ($, ofs) => (ofs ? '-' : '') + $.toLowerCase());
|
|
36
|
-
}
|
|
37
|
-
export function cssColorVariable(colors) {
|
|
38
|
-
const temp = {};
|
|
39
|
-
Object.keys(colors).map((key) => {
|
|
40
|
-
temp[`--${kebabCase(key)}`] = extractHSLValues(colors[key]);
|
|
41
|
-
});
|
|
42
|
-
return temp;
|
|
43
|
-
}
|
|
44
|
-
export function cleanSrc(src) {
|
|
45
|
-
if (src.includes('/public/'))
|
|
46
|
-
return src.replace('/public/', '/');
|
|
47
|
-
return src;
|
|
48
|
-
}
|
|
49
|
-
export function tailwindColorObject(input) {
|
|
50
|
-
const transformed = {};
|
|
51
|
-
for (const key in input) {
|
|
52
|
-
if (Object.prototype.hasOwnProperty.call(input, key)) {
|
|
53
|
-
if (key.endsWith('Foreground')) {
|
|
54
|
-
const baseKey = key.replace(/Foreground$/, '');
|
|
55
|
-
if (!transformed[baseKey]) {
|
|
56
|
-
// @ts-ignore
|
|
57
|
-
transformed[baseKey] = {};
|
|
58
|
-
}
|
|
59
|
-
// @ts-ignore
|
|
60
|
-
transformed[baseKey].foreground = `hsl(var(--${key}))`;
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
if (!transformed[key]) {
|
|
64
|
-
transformed[key] = { DEFAULT: `hsl(var(--${key}))` };
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
// @ts-ignore
|
|
68
|
-
transformed[key].DEFAULT = `hsl(var(--${key}))`;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
return transformed;
|
|
74
|
-
}
|
|
1
|
+
'use client';
|
|
2
|
+
export { Iconify } from './components';
|
|
3
|
+
export { cleanSrc, cn, isNavActive } from './functions';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sohanemon/utils",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -17,10 +17,10 @@
|
|
|
17
17
|
"author": "sohanemon",
|
|
18
18
|
"license": "ISC",
|
|
19
19
|
"devDependencies": {
|
|
20
|
-
"@types/node": "^20.5.7",
|
|
21
20
|
"typescript": "^5.2.2"
|
|
22
21
|
},
|
|
23
22
|
"dependencies": {
|
|
23
|
+
"@iconify/react": "^4.1.1",
|
|
24
24
|
"clsx": "^2.0.0",
|
|
25
25
|
"react": "^18.2.0",
|
|
26
26
|
"tailwind-merge": "^1.14.0"
|