@sohanemon/utils 4.0.25 → 4.0.27

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.
@@ -5,3 +5,4 @@ export declare function cn(...inputs: ClassValue[]): string;
5
5
  export declare function isNavActive(href: string, path: string): boolean;
6
6
  export declare function cleanSrc(src: string): string;
7
7
  export declare const scrollTo: (containerSelector: string | React.RefObject<HTMLDivElement>, to: "top" | "bottom") => void;
8
+ export declare const copyToClipboard: (value: string, onSuccess?: () => void) => void;
@@ -33,3 +33,12 @@ export const scrollTo = (containerSelector, to) => {
33
33
  });
34
34
  }
35
35
  };
36
+ export const copyToClipboard = (value, onSuccess = () => { }) => {
37
+ if (typeof window === 'undefined' || !navigator.clipboard?.writeText) {
38
+ return;
39
+ }
40
+ if (!value) {
41
+ return;
42
+ }
43
+ navigator.clipboard.writeText(value).then(onSuccess);
44
+ };
@@ -1,16 +1,28 @@
1
- import { type Dispatch, type EffectCallback, type SetStateAction, useLayoutEffect } from 'react';
1
+ import * as React from 'react';
2
2
  export * from './action';
3
- export declare const useClickOutside: (callback?: () => void) => import("react").MutableRefObject<HTMLDivElement>;
3
+ export declare const useClickOutside: (callback?: () => void) => React.MutableRefObject<HTMLDivElement>;
4
4
  export declare function useMediaQuery(tailwindBreakpoint: 'sm' | 'md' | 'lg' | 'xl' | '2xl' | `(${string})`): boolean;
5
- export declare function useEffectOnce(effect: EffectCallback): void;
6
- export declare function useUpdateEffect(effect: EffectCallback, deps: any[]): void;
5
+ export declare function useEffectOnce(effect: React.EffectCallback): void;
6
+ export declare function useUpdateEffect(effect: React.EffectCallback, deps: any[]): void;
7
7
  export declare function useDebounce<T>(state: T, delay?: number): T;
8
- export declare const useIsomorphicEffect: typeof useLayoutEffect;
8
+ export declare const useIsomorphicEffect: typeof React.useLayoutEffect;
9
9
  export declare function useTimeout(callback: () => void, delay?: number | null): void;
10
10
  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;
11
- type LocalStorageValue<T> = [T, Dispatch<SetStateAction<T>>];
11
+ type LocalStorageValue<T> = [T, React.Dispatch<React.SetStateAction<T>>];
12
12
  export declare const useLocalStorage: <T extends Record<string, any>>(key: string, defaultValue: T) => LocalStorageValue<T>;
13
13
  export declare const useUrlParams: <T extends string | number | boolean>(key: string, defaultValue: T) => [T, (value: T) => void];
14
14
  export declare const useQuerySelector: <T extends Element>(selector: string) => T | null;
15
15
  export declare function useIsClient(): boolean;
16
16
  export declare function useLockScroll(): void;
17
+ export declare function useCopyToClipboard({ timeout }: {
18
+ timeout?: number;
19
+ }): {
20
+ isCopied: Boolean;
21
+ copy: (value: string) => void;
22
+ };
23
+ type CalculationProps = {
24
+ blockIds: string[];
25
+ dynamic?: boolean;
26
+ margin?: number;
27
+ };
28
+ export declare const useHeightCalculation: ({ blockIds, margin, dynamic, }: CalculationProps) => number;
@@ -1,14 +1,15 @@
1
1
  'use client';
2
- import { useEffect, useLayoutEffect, useMemo, useRef, useState, } from 'react';
2
+ import { copyToClipboard } from '../functions';
3
+ import * as React from 'react';
3
4
  export * from './action';
4
5
  export const useClickOutside = (callback = () => alert('clicked outside')) => {
5
- const ref = useRef(null);
6
+ const ref = React.useRef(null);
6
7
  const listener = (e) => {
7
8
  if (ref.current && !ref.current.contains(e.target)) {
8
9
  callback();
9
10
  }
10
11
  };
11
- useEffect(() => {
12
+ React.useEffect(() => {
12
13
  document.addEventListener('mousedown', listener);
13
14
  document.addEventListener('touchstart', listener);
14
15
  return () => {
@@ -19,7 +20,7 @@ export const useClickOutside = (callback = () => alert('clicked outside')) => {
19
20
  return ref;
20
21
  };
21
22
  export function useMediaQuery(tailwindBreakpoint) {
22
- const parsedQuery = useMemo(() => {
23
+ const parsedQuery = React.useMemo(() => {
23
24
  switch (tailwindBreakpoint) {
24
25
  case 'sm':
25
26
  return '(min-width: 640px)';
@@ -41,12 +42,12 @@ export function useMediaQuery(tailwindBreakpoint) {
41
42
  }
42
43
  return false;
43
44
  };
44
- const [matches, setMatches] = useState(getMatches(parsedQuery));
45
+ const [matches, setMatches] = React.useState(getMatches(parsedQuery));
45
46
  function handleChange() {
46
47
  setMatches(getMatches(parsedQuery));
47
48
  }
48
49
  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
49
- useEffect(() => {
50
+ React.useEffect(() => {
50
51
  const matchMedia = window.matchMedia(parsedQuery);
51
52
  handleChange();
52
53
  matchMedia.addEventListener('change', handleChange);
@@ -57,12 +58,12 @@ export function useMediaQuery(tailwindBreakpoint) {
57
58
  return matches;
58
59
  }
59
60
  export function useEffectOnce(effect) {
60
- useEffect(effect, []);
61
+ React.useEffect(effect, []);
61
62
  }
62
63
  export function useUpdateEffect(effect, deps) {
63
- const isInitialMount = useRef(true);
64
+ const isInitialMount = React.useRef(true);
64
65
  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
65
- useEffect(() => {
66
+ React.useEffect(() => {
66
67
  if (isInitialMount.current) {
67
68
  isInitialMount.current = false;
68
69
  }
@@ -72,8 +73,8 @@ export function useUpdateEffect(effect, deps) {
72
73
  }, deps);
73
74
  }
74
75
  export function useDebounce(state, delay = 500) {
75
- const [debouncedState, setDebouncedState] = useState(state);
76
- useEffect(() => {
76
+ const [debouncedState, setDebouncedState] = React.useState(state);
77
+ React.useEffect(() => {
77
78
  const timer = setTimeout(() => setDebouncedState(state), delay);
78
79
  return () => {
79
80
  clearTimeout(timer);
@@ -81,13 +82,13 @@ export function useDebounce(state, delay = 500) {
81
82
  }, [state, delay]);
82
83
  return debouncedState;
83
84
  }
84
- export const useIsomorphicEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect;
85
+ export const useIsomorphicEffect = typeof window !== 'undefined' ? React.useLayoutEffect : React.useEffect;
85
86
  export function useTimeout(callback, delay = 1000) {
86
- const savedCallback = useRef(callback);
87
+ const savedCallback = React.useRef(callback);
87
88
  useIsomorphicEffect(() => {
88
89
  savedCallback.current = callback;
89
90
  }, [callback]);
90
- useEffect(() => {
91
+ React.useEffect(() => {
91
92
  if (!delay && delay !== 0) {
92
93
  return;
93
94
  }
@@ -97,16 +98,16 @@ export function useTimeout(callback, delay = 1000) {
97
98
  }
98
99
  export function useWindowEvent(type, listener, options) {
99
100
  // biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
100
- useEffect(() => {
101
+ React.useEffect(() => {
101
102
  window.addEventListener(type, listener, options);
102
103
  return () => window.removeEventListener(type, listener, options);
103
104
  }, [type, listener]);
104
105
  }
105
106
  // Custom hook for using local storage with a specified key and default value
106
107
  export const useLocalStorage = (key, defaultValue) => {
107
- const [storedValue, setStoredValue] = useState(defaultValue);
108
+ const [storedValue, setStoredValue] = React.useState(defaultValue);
108
109
  // Use effect to retrieve the stored value from local storage on component mount
109
- useEffect(() => {
110
+ React.useEffect(() => {
110
111
  const value = localStorage.getItem(key);
111
112
  if (value) {
112
113
  setStoredValue(JSON.parse(value));
@@ -130,9 +131,9 @@ export const useLocalStorage = (key, defaultValue) => {
130
131
  };
131
132
  // Custom hook for using URL parameters with a specified key and default value
132
133
  export const useUrlParams = (key, defaultValue) => {
133
- const [value, setValue] = useState(defaultValue);
134
+ const [value, setValue] = React.useState(defaultValue);
134
135
  // Use effect to retrieve the value from URL parameters on component mount
135
- useEffect(() => {
136
+ React.useEffect(() => {
136
137
  const params = new URLSearchParams(window.location.search);
137
138
  const value = params.get(key);
138
139
  if (value !== null) {
@@ -149,9 +150,9 @@ export const useUrlParams = (key, defaultValue) => {
149
150
  return [value, updateValue];
150
151
  };
151
152
  export const useQuerySelector = (selector) => {
152
- const [element, setElement] = useState(null);
153
- const elementRef = useRef(null);
154
- useLayoutEffect(() => {
153
+ const [element, setElement] = React.useState(null);
154
+ const elementRef = React.useRef(null);
155
+ React.useLayoutEffect(() => {
155
156
  const referenceElement = document.querySelector(selector);
156
157
  if (!referenceElement)
157
158
  return;
@@ -174,14 +175,14 @@ export const useQuerySelector = (selector) => {
174
175
  return element;
175
176
  };
176
177
  export function useIsClient() {
177
- const [isClient, setIsClient] = useState(false);
178
- useEffect(() => {
178
+ const [isClient, setIsClient] = React.useState(false);
179
+ React.useEffect(() => {
179
180
  setIsClient(true);
180
181
  }, []);
181
182
  return isClient;
182
183
  }
183
184
  export function useLockScroll() {
184
- useLayoutEffect(() => {
185
+ React.useLayoutEffect(() => {
185
186
  const originalStyle = window.getComputedStyle(document.body).overflow;
186
187
  document.body.style.overflow = 'hidden';
187
188
  return () => {
@@ -189,3 +190,30 @@ export function useLockScroll() {
189
190
  };
190
191
  }, []);
191
192
  }
193
+ export function useCopyToClipboard({ timeout = 2000 }) {
194
+ const [isCopied, setIsCopied] = React.useState(false);
195
+ const copy = (value) => {
196
+ copyToClipboard(value, () => {
197
+ setIsCopied(true);
198
+ setTimeout(() => {
199
+ setIsCopied(false);
200
+ }, timeout);
201
+ });
202
+ };
203
+ return { isCopied, copy };
204
+ }
205
+ export const useHeightCalculation = ({ blockIds = [], margin = 0, dynamic = false, }) => {
206
+ const [height, setTableHeight] = React.useState(500);
207
+ const handleResize = () => {
208
+ const blcokHeight = blockIds.reduce((prevHeight, id) => prevHeight + (document.getElementById(id)?.clientHeight || 0), 0);
209
+ setTableHeight(window.innerHeight - blcokHeight - margin);
210
+ };
211
+ useIsomorphicEffect(() => {
212
+ handleResize();
213
+ if (!dynamic)
214
+ return;
215
+ window.addEventListener('resize', handleResize);
216
+ return () => window.removeEventListener('resize', handleResize);
217
+ }, []);
218
+ return height;
219
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sohanemon/utils",
3
- "version": "4.0.25",
3
+ "version": "4.0.27",
4
4
  "author": "Sohan Emon <sohanemon@outlook.com>",
5
5
  "description": "",
6
6
  "type": "module",
@@ -15,18 +15,30 @@
15
15
  },
16
16
  "typesVersions": {
17
17
  "*": {
18
- "core": ["dist/index.d.ts"],
19
- "hooks": ["dist/hooks/index.d.ts"],
20
- "components": ["dist/components/index.d.ts"]
18
+ "core": [
19
+ "dist/index.d.ts"
20
+ ],
21
+ "hooks": [
22
+ "dist/hooks/index.d.ts"
23
+ ],
24
+ "components": [
25
+ "dist/components/index.d.ts"
26
+ ]
21
27
  }
22
28
  },
23
- "files": ["dist", "README.md"],
29
+ "files": [
30
+ "dist",
31
+ "README.md"
32
+ ],
24
33
  "scripts": {
25
34
  "build": "tsc",
26
35
  "build:watch": "tsc --watch",
27
36
  "export": "tsc && npm publish"
28
37
  },
29
- "keywords": ["utils", "cn"],
38
+ "keywords": [
39
+ "utils",
40
+ "cn"
41
+ ],
30
42
  "license": "ISC",
31
43
  "devDependencies": {
32
44
  "@types/node": "^22.4.0",