@isik-kaplan/core 0.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.
@@ -0,0 +1,312 @@
1
+ // src/hooks/index.ts
2
+ import { useCallback, useEffect, useRef, useState } from "react";
3
+ function useElementAttributes(attributeKeys) {
4
+ const ref = useRef(null);
5
+ const [attributeValues, setAttributeValue] = useState({});
6
+ const updateAttribute = useCallback(() => {
7
+ if (ref.current) {
8
+ const values = {};
9
+ for (const key of attributeKeys) {
10
+ Object.defineProperty(values, key, {
11
+ value: ref.current[key],
12
+ writable: true,
13
+ configurable: true,
14
+ enumerable: true
15
+ });
16
+ }
17
+ setAttributeValue((prevValues) => {
18
+ const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key]);
19
+ return hasChanged ? values : prevValues;
20
+ });
21
+ }
22
+ }, [attributeKeys]);
23
+ useEffect(() => {
24
+ updateAttribute();
25
+ window.addEventListener("resize", updateAttribute);
26
+ if (ref.current) {
27
+ const observer = new MutationObserver(updateAttribute);
28
+ observer.observe(ref.current, { attributes: true });
29
+ return () => {
30
+ window.removeEventListener("resize", updateAttribute);
31
+ observer.disconnect();
32
+ };
33
+ }
34
+ return () => {
35
+ window.removeEventListener("resize", updateAttribute);
36
+ };
37
+ }, [updateAttribute]);
38
+ return { ref, attributeValues };
39
+ }
40
+ function useFormState(initialState) {
41
+ const [formState, setFormState] = useState(initialState);
42
+ const [formErrors, setFormErrors] = useState();
43
+ function resetFormState() {
44
+ setFormState(initialState);
45
+ }
46
+ function handleFormState({
47
+ key,
48
+ inputType
49
+ }) {
50
+ return (event) => {
51
+ let value;
52
+ if (inputType === "event") {
53
+ const target = event.target;
54
+ if (target.type === "checkbox") {
55
+ value = target.checked;
56
+ } else if (target.type === "number" || target.type === "range") {
57
+ value = target.valueAsNumber;
58
+ } else {
59
+ value = target.value;
60
+ }
61
+ } else {
62
+ value = event;
63
+ }
64
+ setFormState((prev) => ({ ...prev, [key]: value }));
65
+ };
66
+ }
67
+ const handleFormStateValue = (key) => handleFormState({ key, inputType: "value" });
68
+ const handleFormStateEvent = (key) => handleFormState({ key, inputType: "event" });
69
+ const handleFormStateOnClick = (key, value) => () => {
70
+ setFormState((prev) => ({ ...prev, [key]: value }));
71
+ };
72
+ return {
73
+ formState,
74
+ setFormState,
75
+ formErrors,
76
+ setFormErrors,
77
+ handleFormStateValue,
78
+ handleFormStateEvent,
79
+ handleFormStateOnClick,
80
+ resetFormState
81
+ };
82
+ }
83
+ function useEffectAfterMount(effect, deps) {
84
+ const isFirstRender = useRef(true);
85
+ useEffect(() => {
86
+ if (isFirstRender.current) {
87
+ isFirstRender.current = false;
88
+ return;
89
+ }
90
+ return effect();
91
+ }, deps);
92
+ }
93
+ function useFilePaste({
94
+ acceptedTypes,
95
+ maxSize,
96
+ targetElement,
97
+ enabled = true
98
+ } = {}) {
99
+ const [files, setFiles] = useState([]);
100
+ const [isLoading, setIsLoading] = useState(false);
101
+ const [error, setError] = useState(null);
102
+ const clearFiles = useCallback(() => {
103
+ setFiles([]);
104
+ setError(null);
105
+ }, []);
106
+ const validateFiles = useCallback(
107
+ (pastedFiles) => {
108
+ if (acceptedTypes && acceptedTypes.length > 0) {
109
+ const wildcardAcceptedTypes = acceptedTypes.filter((type) => type.endsWith("/*")).map((type) => type.slice(0, -1));
110
+ const normalizedAcceptedTypes = acceptedTypes.map((type) => type.endsWith("/*") ? type.slice(0, -2) : type);
111
+ const invalidFiles = pastedFiles.filter((file) => {
112
+ const fileType = file.type;
113
+ return !normalizedAcceptedTypes.includes(fileType) && !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType));
114
+ });
115
+ if (invalidFiles.length > 0) {
116
+ const invalidFileNames = invalidFiles.map((file) => file.name).join(", ");
117
+ return {
118
+ valid: false,
119
+ error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(", ")}`
120
+ };
121
+ }
122
+ }
123
+ if (maxSize) {
124
+ const oversizedFile = pastedFiles.find((file) => file.size > maxSize);
125
+ if (oversizedFile) {
126
+ const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2);
127
+ const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2);
128
+ return {
129
+ valid: false,
130
+ error: `File "${oversizedFile.name}" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`
131
+ };
132
+ }
133
+ }
134
+ return { valid: true };
135
+ },
136
+ [acceptedTypes, maxSize]
137
+ );
138
+ const handlePaste = useCallback(
139
+ (event) => {
140
+ const { clipboardData } = event;
141
+ if (!clipboardData) return;
142
+ const hasFiles = clipboardData.files && clipboardData.files.length > 0;
143
+ if (!hasFiles) return;
144
+ event.preventDefault();
145
+ setIsLoading(true);
146
+ setError(null);
147
+ try {
148
+ const pastedFiles = Array.from(clipboardData.files);
149
+ const validation = validateFiles(pastedFiles);
150
+ if (!validation.valid) {
151
+ setError(validation.error);
152
+ setFiles([]);
153
+ } else {
154
+ setFiles(pastedFiles);
155
+ }
156
+ } catch (err) {
157
+ setError(err instanceof Error ? err.message : "Failed to process pasted files");
158
+ setFiles([]);
159
+ } finally {
160
+ setIsLoading(false);
161
+ }
162
+ },
163
+ [validateFiles]
164
+ );
165
+ useEffect(() => {
166
+ if (!enabled) return;
167
+ const target = targetElement || document;
168
+ target.addEventListener("paste", handlePaste);
169
+ return () => {
170
+ target.removeEventListener("paste", handlePaste);
171
+ };
172
+ }, [enabled, handlePaste, targetElement]);
173
+ return { files, isLoading, error, clearFiles };
174
+ }
175
+ function useFileDragDrop(options = {}) {
176
+ const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options;
177
+ const [state, setState] = useState({
178
+ isDragging: false,
179
+ files: null
180
+ });
181
+ const ref = useRef(null);
182
+ const dragCounter = useRef(0);
183
+ const handleDragOver = useCallback(
184
+ (e) => {
185
+ e.preventDefault();
186
+ e.stopPropagation();
187
+ onDragOver?.(e);
188
+ },
189
+ [onDragOver]
190
+ );
191
+ const handleDragEnter = useCallback(
192
+ (e) => {
193
+ e.preventDefault();
194
+ e.stopPropagation();
195
+ dragCounter.current += 1;
196
+ if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {
197
+ const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {
198
+ if (item.kind !== "file") {
199
+ return false;
200
+ }
201
+ if (acceptedFileTypes && acceptedFileTypes.length > 0) {
202
+ return acceptedFileTypes.some((type) => {
203
+ if (type.endsWith("/*")) {
204
+ const category = type.split("/")[0];
205
+ return item.type.startsWith(`${category}/`);
206
+ }
207
+ return item.type === type;
208
+ });
209
+ }
210
+ return true;
211
+ });
212
+ if (hasValidItems) {
213
+ setState((prevState) => ({
214
+ ...prevState,
215
+ isDragging: true
216
+ }));
217
+ }
218
+ }
219
+ },
220
+ [acceptedFileTypes]
221
+ );
222
+ const handleDragLeave = useCallback(
223
+ (e) => {
224
+ e.preventDefault();
225
+ e.stopPropagation();
226
+ dragCounter.current -= 1;
227
+ if (dragCounter.current === 0) {
228
+ setState((prevState) => ({
229
+ ...prevState,
230
+ isDragging: false
231
+ }));
232
+ }
233
+ onDragLeave?.(e);
234
+ },
235
+ [onDragLeave]
236
+ );
237
+ const handleDrop = useCallback(
238
+ (e) => {
239
+ e.preventDefault();
240
+ e.stopPropagation();
241
+ dragCounter.current = 0;
242
+ setState((prevState) => ({
243
+ ...prevState,
244
+ isDragging: false
245
+ }));
246
+ if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {
247
+ let validFiles = Array.from(e.dataTransfer.files);
248
+ if (acceptedFileTypes && acceptedFileTypes.length > 0) {
249
+ validFiles = validFiles.filter(
250
+ (file) => acceptedFileTypes.some((type) => {
251
+ if (type.endsWith("/*")) {
252
+ const category = type.split("/")[0];
253
+ return file.type.startsWith(`${category}/`);
254
+ }
255
+ return file.type === type;
256
+ })
257
+ );
258
+ }
259
+ if (maxFileSize) {
260
+ validFiles = validFiles.filter((file) => file.size <= maxFileSize);
261
+ }
262
+ if (!multiple && validFiles.length > 0) {
263
+ validFiles = [validFiles[0]];
264
+ }
265
+ if (validFiles.length > 0) {
266
+ setState((prevState) => ({
267
+ ...prevState,
268
+ files: validFiles
269
+ }));
270
+ onDrop?.(validFiles);
271
+ }
272
+ }
273
+ },
274
+ [onDrop, acceptedFileTypes, maxFileSize, multiple]
275
+ );
276
+ useEffect(() => {
277
+ const currentRef = ref.current;
278
+ if (currentRef) {
279
+ currentRef.addEventListener("dragover", handleDragOver);
280
+ currentRef.addEventListener("dragenter", handleDragEnter);
281
+ currentRef.addEventListener("dragleave", handleDragLeave);
282
+ currentRef.addEventListener("drop", handleDrop);
283
+ return () => {
284
+ currentRef.removeEventListener("dragover", handleDragOver);
285
+ currentRef.removeEventListener("dragenter", handleDragEnter);
286
+ currentRef.removeEventListener("dragleave", handleDragLeave);
287
+ currentRef.removeEventListener("drop", handleDrop);
288
+ };
289
+ }
290
+ return void 0;
291
+ }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop]);
292
+ const reset = useCallback(() => {
293
+ setState({
294
+ isDragging: false,
295
+ files: null
296
+ });
297
+ }, []);
298
+ return {
299
+ ref,
300
+ isDragging: state.isDragging,
301
+ files: state.files,
302
+ reset
303
+ };
304
+ }
305
+ export {
306
+ useEffectAfterMount,
307
+ useElementAttributes,
308
+ useFileDragDrop,
309
+ useFilePaste,
310
+ useFormState
311
+ };
312
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/hooks/index.ts"],"sourcesContent":["import type { ChangeEvent, DependencyList, DragEvent, EffectCallback } from 'react'\nimport { useCallback, useEffect, useRef, useState } from 'react'\n\nexport function useElementAttributes<T extends HTMLElement, K extends keyof T>(attributeKeys: K[]) {\n const ref = useRef<T | null>(null)\n const [attributeValues, setAttributeValue] = useState<Partial<Pick<T, K>>>({})\n\n const updateAttribute = useCallback(() => {\n if (ref.current) {\n const values = {} as Partial<Pick<T, K>>\n for (const key of attributeKeys) {\n // Object.defineProperty (unlike a plain `values[key] = value` assignment) always creates/\n // overwrites an own property, even if a consumer's T somehow has a key like \"__proto__\" -\n // matches the same defensive pattern used everywhere else in this package that writes a\n // non-literal key onto an object.\n Object.defineProperty(values, key, {\n value: ref.current[key],\n writable: true,\n configurable: true,\n enumerable: true,\n })\n }\n\n setAttributeValue((prevValues) => {\n const hasChanged = attributeKeys.some((key) => prevValues[key] !== values[key])\n return hasChanged ? values : prevValues\n })\n }\n }, [attributeKeys])\n\n useEffect(() => {\n updateAttribute()\n window.addEventListener('resize', updateAttribute)\n\n if (ref.current) {\n const observer = new MutationObserver(updateAttribute)\n observer.observe(ref.current, { attributes: true })\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n observer.disconnect()\n }\n }\n\n return () => {\n window.removeEventListener('resize', updateAttribute)\n }\n }, [updateAttribute])\n\n return { ref, attributeValues }\n}\n\ntype InputEventType = ChangeEvent<HTMLInputElement | HTMLTextAreaElement | HTMLSelectElement>\n\nexport function useFormState<T>(initialState: T) {\n const [formState, setFormState] = useState<T>(initialState)\n const [formErrors, setFormErrors] = useState<Partial<Record<keyof T, string[]>> & { non_field_errors?: string[] }>()\n\n function resetFormState() {\n setFormState(initialState)\n }\n\n function handleFormState<K extends keyof T, HandlerInputType>({\n key,\n inputType,\n }: {\n key: K\n inputType: 'event' | 'value'\n }) {\n return (event: HandlerInputType) => {\n let value: T[K]\n if (inputType === 'event') {\n const target = (event as InputEventType).target\n if (target.type === 'checkbox') {\n value = (target as HTMLInputElement).checked as T[K]\n } else if (target.type === 'number' || target.type === 'range') {\n value = (target as HTMLInputElement).valueAsNumber as T[K]\n } else {\n value = target.value as T[K]\n }\n } else {\n value = event as T[K]\n }\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n }\n\n const handleFormStateValue = <K extends keyof T>(key: K) => handleFormState<K, T[K]>({ key, inputType: 'value' })\n const handleFormStateEvent = <K extends keyof T>(key: K) =>\n handleFormState<K, InputEventType>({ key, inputType: 'event' })\n const handleFormStateOnClick =\n <K extends keyof T>(key: K, value: T[K]) =>\n () => {\n setFormState((prev) => ({ ...prev, [key]: value }))\n }\n\n return {\n formState,\n setFormState,\n formErrors,\n setFormErrors,\n handleFormStateValue,\n handleFormStateEvent,\n handleFormStateOnClick,\n resetFormState,\n }\n}\n\nexport function useEffectAfterMount(effect: EffectCallback, deps: DependencyList) {\n const isFirstRender = useRef(true)\n\n // No manual \"did deps actually change\" recheck needed here: React's own useEffect already\n // only re-invokes this callback when a dependency's value changed (shallow-compared against\n // the last time *this exact effect* ran) - which is exactly the same comparison a hand-rolled\n // check against a \"previous deps\" ref would be making, just duplicated.\n useEffect(() => {\n if (isFirstRender.current) {\n isFirstRender.current = false\n return\n }\n return effect()\n }, deps)\n}\n\nexport function useFilePaste({\n acceptedTypes,\n maxSize,\n targetElement,\n enabled = true,\n}: {\n acceptedTypes?: string[]\n maxSize?: number\n targetElement?: HTMLElement | null\n enabled?: boolean\n} = {}): {\n files: File[]\n isLoading: boolean\n error: string | null\n clearFiles: () => void\n} {\n const [files, setFiles] = useState<File[]>([])\n const [isLoading, setIsLoading] = useState(false)\n const [error, setError] = useState<string | null>(null)\n\n const clearFiles = useCallback(() => {\n setFiles([])\n setError(null)\n }, [])\n\n const validateFiles = useCallback(\n (pastedFiles: File[]): { valid: true } | { valid: false; error: string } => {\n if (acceptedTypes && acceptedTypes.length > 0) {\n const wildcardAcceptedTypes = acceptedTypes\n .filter((type) => type.endsWith('/*'))\n .map((type) => type.slice(0, -1))\n const normalizedAcceptedTypes = acceptedTypes.map((type) => (type.endsWith('/*') ? type.slice(0, -2) : type))\n\n const invalidFiles = pastedFiles.filter((file) => {\n const fileType = file.type\n return (\n !normalizedAcceptedTypes.includes(fileType) &&\n !wildcardAcceptedTypes.some((wildcardType) => fileType.startsWith(wildcardType))\n )\n })\n if (invalidFiles.length > 0) {\n const invalidFileNames = invalidFiles.map((file) => file.name).join(', ')\n return {\n valid: false,\n error: `Invalid file types: ${invalidFileNames}. Accepted types: ${acceptedTypes.join(', ')}`,\n }\n }\n }\n\n if (maxSize) {\n const oversizedFile = pastedFiles.find((file) => file.size > maxSize)\n if (oversizedFile) {\n const fileSizeMB = (oversizedFile.size / (1024 * 1024)).toFixed(2)\n const maxSizeMB = (maxSize / (1024 * 1024)).toFixed(2)\n return {\n valid: false,\n error: `File \"${oversizedFile.name}\" (${fileSizeMB} MB) exceeds the maximum size of ${maxSizeMB} MB`,\n }\n }\n }\n\n return { valid: true }\n },\n [acceptedTypes, maxSize]\n )\n\n const handlePaste = useCallback(\n (event: ClipboardEvent) => {\n const { clipboardData } = event\n if (!clipboardData) return\n\n const hasFiles = clipboardData.files && clipboardData.files.length > 0\n if (!hasFiles) return\n\n event.preventDefault()\n setIsLoading(true)\n setError(null)\n\n try {\n const pastedFiles = Array.from(clipboardData.files)\n const validation = validateFiles(pastedFiles)\n\n if (!validation.valid) {\n setError(validation.error)\n setFiles([])\n } else {\n setFiles(pastedFiles)\n }\n } catch (err) {\n setError(err instanceof Error ? err.message : 'Failed to process pasted files')\n setFiles([])\n } finally {\n setIsLoading(false)\n }\n },\n [validateFiles]\n )\n\n useEffect(() => {\n if (!enabled) return\n\n const target = targetElement || document\n\n target.addEventListener('paste', handlePaste as EventListener)\n return () => {\n target.removeEventListener('paste', handlePaste as EventListener)\n }\n }, [enabled, handlePaste, targetElement])\n\n return { files, isLoading, error, clearFiles }\n}\n\ntype FileDragDropState = {\n isDragging: boolean\n files: File[] | null\n}\n\ntype FileDragDropOptions = {\n onDrop?: (files: File[]) => void\n onDragOver?: (e: DragEvent<HTMLElement>) => void\n onDragLeave?: (e: DragEvent<HTMLElement>) => void\n acceptedFileTypes?: string[]\n maxFileSize?: number\n multiple?: boolean\n}\n\nexport function useFileDragDrop<T extends HTMLElement = HTMLDivElement>(options: FileDragDropOptions = {}) {\n const { onDrop, onDragOver, onDragLeave, acceptedFileTypes, maxFileSize, multiple = true } = options\n\n const [state, setState] = useState<FileDragDropState>({\n isDragging: false,\n files: null,\n })\n\n const ref = useRef<T | null>(null)\n const dragCounter = useRef(0)\n\n const handleDragOver = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n onDragOver?.(e)\n },\n [onDragOver]\n )\n\n const handleDragEnter = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current += 1\n\n if (e.dataTransfer.items && e.dataTransfer.items.length > 0) {\n const hasValidItems = Array.from(e.dataTransfer.items).some((item) => {\n if (item.kind !== 'file') {\n return false\n }\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n return acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return item.type.startsWith(`${category}/`)\n }\n return item.type === type\n })\n }\n\n return true\n })\n\n if (hasValidItems) {\n setState((prevState) => ({\n ...prevState,\n isDragging: true,\n }))\n }\n }\n },\n [acceptedFileTypes]\n )\n\n const handleDragLeave = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current -= 1\n\n if (dragCounter.current === 0) {\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n }\n\n onDragLeave?.(e)\n },\n [onDragLeave]\n )\n\n const handleDrop = useCallback(\n (e: DragEvent<T>) => {\n e.preventDefault()\n e.stopPropagation()\n\n dragCounter.current = 0\n setState((prevState) => ({\n ...prevState,\n isDragging: false,\n }))\n\n if (e.dataTransfer.files && e.dataTransfer.files.length > 0) {\n let validFiles = Array.from(e.dataTransfer.files)\n\n if (acceptedFileTypes && acceptedFileTypes.length > 0) {\n validFiles = validFiles.filter((file) =>\n acceptedFileTypes.some((type) => {\n if (type.endsWith('/*')) {\n const category = type.split('/')[0]\n return file.type.startsWith(`${category}/`)\n }\n return file.type === type\n })\n )\n }\n\n if (maxFileSize) {\n validFiles = validFiles.filter((file) => file.size <= maxFileSize)\n }\n\n if (!multiple && validFiles.length > 0) {\n validFiles = [validFiles[0]]\n }\n\n if (validFiles.length > 0) {\n setState((prevState) => ({\n ...prevState,\n files: validFiles,\n }))\n\n onDrop?.(validFiles)\n }\n }\n },\n [onDrop, acceptedFileTypes, maxFileSize, multiple]\n )\n\n useEffect(() => {\n const currentRef = ref.current\n if (currentRef) {\n currentRef.addEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.addEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.addEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.addEventListener('drop', handleDrop as unknown as EventListener)\n\n return () => {\n currentRef.removeEventListener('dragover', handleDragOver as unknown as EventListener)\n currentRef.removeEventListener('dragenter', handleDragEnter as unknown as EventListener)\n currentRef.removeEventListener('dragleave', handleDragLeave as unknown as EventListener)\n currentRef.removeEventListener('drop', handleDrop as unknown as EventListener)\n }\n }\n return undefined\n }, [handleDragOver, handleDragEnter, handleDragLeave, handleDrop])\n\n const reset = useCallback(() => {\n setState({\n isDragging: false,\n files: null,\n })\n }, [])\n\n return {\n ref,\n isDragging: state.isDragging,\n files: state.files,\n reset,\n }\n}\n"],"mappings":"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","names":[]}