@g4rcez/components 4.1.1 → 4.1.3
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/core/button.d.ts +77 -0
- package/dist/components/core/button.d.ts.map +1 -0
- package/dist/components/core/button.jsx +79 -0
- package/dist/components/core/heading.d.ts +3 -0
- package/dist/components/core/heading.d.ts.map +1 -0
- package/dist/components/core/heading.jsx +4 -0
- package/dist/components/core/polymorph.d.ts +10 -0
- package/dist/components/core/polymorph.d.ts.map +1 -0
- package/dist/components/core/polymorph.jsx +5 -0
- package/dist/components/core/render-on-view.d.ts +7 -0
- package/dist/components/core/render-on-view.d.ts.map +1 -0
- package/dist/components/core/render-on-view.jsx +31 -0
- package/dist/components/core/resizable.d.ts +3 -0
- package/dist/components/core/resizable.d.ts.map +1 -0
- package/dist/components/core/resizable.jsx +51 -0
- package/dist/components/core/slot.d.ts +16 -0
- package/dist/components/core/slot.d.ts.map +1 -0
- package/dist/components/core/slot.jsx +156 -0
- package/dist/components/core/tag.d.ts +35 -0
- package/dist/components/core/tag.d.ts.map +1 -0
- package/dist/components/core/tag.jsx +51 -0
- package/dist/components/core/typography.d.ts +25 -0
- package/dist/components/core/typography.d.ts.map +1 -0
- package/dist/components/core/typography.jsx +18 -0
- package/dist/components/display/alert.d.ts +28 -0
- package/dist/components/display/alert.d.ts.map +1 -0
- package/dist/components/display/alert.jsx +61 -0
- package/dist/components/display/calendar.d.ts +42 -0
- package/dist/components/display/calendar.d.ts.map +1 -0
- package/dist/components/display/calendar.jsx +299 -0
- package/dist/components/display/card.d.ts +29 -0
- package/dist/components/display/card.d.ts.map +1 -0
- package/dist/components/display/card.jsx +43 -0
- package/dist/components/display/empty.d.ts +8 -0
- package/dist/components/display/empty.d.ts.map +1 -0
- package/dist/components/display/empty.jsx +11 -0
- package/dist/components/display/list.d.ts +16 -0
- package/dist/components/display/list.d.ts.map +1 -0
- package/dist/components/display/list.jsx +81 -0
- package/dist/components/display/notifications.d.ts +27 -0
- package/dist/components/display/notifications.d.ts.map +1 -0
- package/dist/components/display/notifications.jsx +126 -0
- package/dist/components/display/progress.d.ts +13 -0
- package/dist/components/display/progress.d.ts.map +1 -0
- package/dist/components/display/progress.jsx +11 -0
- package/dist/components/display/shortcut.d.ts +4 -0
- package/dist/components/display/shortcut.d.ts.map +1 -0
- package/dist/components/display/shortcut.jsx +23 -0
- package/dist/components/display/skeleton.d.ts +12 -0
- package/dist/components/display/skeleton.d.ts.map +1 -0
- package/dist/components/display/skeleton.jsx +19 -0
- package/dist/components/display/spinner.d.ts +5 -0
- package/dist/components/display/spinner.d.ts.map +1 -0
- package/dist/components/display/spinner.jsx +11 -0
- package/dist/components/display/stats.d.ts +12 -0
- package/dist/components/display/stats.d.ts.map +1 -0
- package/dist/components/display/stats.jsx +20 -0
- package/dist/components/display/step.d.ts +24 -0
- package/dist/components/display/step.d.ts.map +1 -0
- package/dist/components/display/step.jsx +131 -0
- package/dist/components/display/tabs.d.ts +24 -0
- package/dist/components/display/tabs.d.ts.map +1 -0
- package/dist/components/display/tabs.jsx +125 -0
- package/dist/components/display/timeline.d.ts +10 -0
- package/dist/components/display/timeline.d.ts.map +1 -0
- package/dist/components/display/timeline.jsx +25 -0
- package/dist/components/floating/command-palette.d.ts +49 -0
- package/dist/components/floating/command-palette.d.ts.map +1 -0
- package/dist/components/floating/command-palette.jsx +197 -0
- package/dist/components/floating/dropdown.d.ts +15 -0
- package/dist/components/floating/dropdown.d.ts.map +1 -0
- package/dist/components/floating/dropdown.jsx +56 -0
- package/dist/components/floating/expand.d.ts +11 -0
- package/dist/components/floating/expand.d.ts.map +1 -0
- package/dist/components/floating/expand.jsx +44 -0
- package/dist/components/floating/menu.d.ts +52 -0
- package/dist/components/floating/menu.d.ts.map +1 -0
- package/dist/components/floating/menu.jsx +147 -0
- package/dist/components/floating/modal.d.ts +60 -0
- package/dist/components/floating/modal.d.ts.map +1 -0
- package/dist/components/floating/modal.jsx +301 -0
- package/dist/components/floating/toolbar.d.ts +6 -0
- package/dist/components/floating/toolbar.d.ts.map +1 -0
- package/dist/components/floating/toolbar.jsx +5 -0
- package/dist/components/floating/tooltip.d.ts +17 -0
- package/dist/components/floating/tooltip.d.ts.map +1 -0
- package/dist/components/floating/tooltip.jsx +58 -0
- package/dist/components/floating/wizard.d.ts +26 -0
- package/dist/components/floating/wizard.d.ts.map +1 -0
- package/dist/components/floating/wizard.jsx +161 -0
- package/dist/components/form/autocomplete.d.ts +16 -0
- package/dist/components/form/autocomplete.d.ts.map +1 -0
- package/dist/components/form/autocomplete.jsx +278 -0
- package/dist/components/form/checkbox.d.ts +12 -0
- package/dist/components/form/checkbox.d.ts.map +1 -0
- package/dist/components/form/checkbox.jsx +12 -0
- package/dist/components/form/date-picker.d.ts +10 -0
- package/dist/components/form/date-picker.d.ts.map +1 -0
- package/dist/components/form/date-picker.jsx +115 -0
- package/dist/components/form/file-upload.d.ts +15 -0
- package/dist/components/form/file-upload.d.ts.map +1 -0
- package/dist/components/form/file-upload.jsx +134 -0
- package/dist/components/form/form.d.ts +3 -0
- package/dist/components/form/form.d.ts.map +1 -0
- package/dist/components/form/form.jsx +10 -0
- package/dist/components/form/formReset.d.ts +2 -0
- package/dist/components/form/formReset.d.ts.map +1 -0
- package/dist/components/form/formReset.jsx +17 -0
- package/dist/components/form/free-text.d.ts +11 -0
- package/dist/components/form/free-text.d.ts.map +1 -0
- package/dist/components/form/free-text.jsx +41 -0
- package/dist/components/form/input-field.d.ts +34 -0
- package/dist/components/form/input-field.d.ts.map +1 -0
- package/dist/components/form/input-field.jsx +58 -0
- package/dist/components/form/input.d.ts +52 -0
- package/dist/components/form/input.d.ts.map +1 -0
- package/dist/components/form/input.jsx +36 -0
- package/dist/components/form/multi-select.d.ts +19 -0
- package/dist/components/form/multi-select.d.ts.map +1 -0
- package/dist/components/form/multi-select.jsx +336 -0
- package/dist/components/form/radiobox.d.ts +7 -0
- package/dist/components/form/radiobox.d.ts.map +1 -0
- package/dist/components/form/radiobox.jsx +6 -0
- package/dist/components/form/select.d.ts +13 -0
- package/dist/components/form/select.d.ts.map +1 -0
- package/dist/components/form/select.jsx +42 -0
- package/dist/components/form/slider.d.ts +7 -0
- package/dist/components/form/slider.d.ts.map +1 -0
- package/dist/components/form/slider.jsx +45 -0
- package/dist/components/form/switch.d.ts +9 -0
- package/dist/components/form/switch.d.ts.map +1 -0
- package/dist/components/form/switch.jsx +46 -0
- package/dist/components/form/task-list.d.ts +3 -0
- package/dist/components/form/task-list.d.ts.map +1 -0
- package/dist/components/form/task-list.jsx +26 -0
- package/dist/components/form/textarea.d.ts +6 -0
- package/dist/components/form/textarea.d.ts.map +1 -0
- package/dist/components/form/textarea.jsx +12 -0
- package/dist/components/index.d.ts +45 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +44 -0
- package/dist/components/page-calendar/calendar-header.d.ts +16 -0
- package/dist/components/page-calendar/calendar-header.d.ts.map +1 -0
- package/dist/components/page-calendar/calendar-header.jsx +83 -0
- package/dist/components/page-calendar/day-view.d.ts +12 -0
- package/dist/components/page-calendar/day-view.d.ts.map +1 -0
- package/dist/components/page-calendar/day-view.jsx +94 -0
- package/dist/components/page-calendar/event-pill.d.ts +9 -0
- package/dist/components/page-calendar/event-pill.d.ts.map +1 -0
- package/dist/components/page-calendar/event-pill.jsx +25 -0
- package/dist/components/page-calendar/index.d.ts +4 -0
- package/dist/components/page-calendar/index.d.ts.map +1 -0
- package/dist/components/page-calendar/index.js +2 -0
- package/dist/components/page-calendar/month-view.d.ts +11 -0
- package/dist/components/page-calendar/month-view.d.ts.map +1 -0
- package/dist/components/page-calendar/month-view.jsx +46 -0
- package/dist/components/page-calendar/page-calendar.d.ts +18 -0
- package/dist/components/page-calendar/page-calendar.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.jsx +41 -0
- package/dist/components/page-calendar/page-calendar.types.d.ts +18 -0
- package/dist/components/page-calendar/page-calendar.types.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.types.js +1 -0
- package/dist/components/page-calendar/page-calendar.utils.d.ts +24 -0
- package/dist/components/page-calendar/page-calendar.utils.d.ts.map +1 -0
- package/dist/components/page-calendar/page-calendar.utils.js +93 -0
- package/dist/components/page-calendar/week-view.d.ts +11 -0
- package/dist/components/page-calendar/week-view.d.ts.map +1 -0
- package/dist/components/page-calendar/week-view.jsx +71 -0
- package/dist/components/table/filter.d.ts +42 -0
- package/dist/components/table/filter.d.ts.map +1 -0
- package/dist/components/table/filter.jsx +141 -0
- package/dist/components/table/group.d.ts +17 -0
- package/dist/components/table/group.d.ts.map +1 -0
- package/dist/components/table/group.jsx +68 -0
- package/dist/components/table/index.d.ts +19 -0
- package/dist/components/table/index.d.ts.map +1 -0
- package/dist/components/table/index.jsx +60 -0
- package/dist/components/table/inner-table.d.ts +29 -0
- package/dist/components/table/inner-table.d.ts.map +1 -0
- package/dist/components/table/inner-table.jsx +102 -0
- package/dist/components/table/metadata.d.ts +4 -0
- package/dist/components/table/metadata.d.ts.map +1 -0
- package/dist/components/table/metadata.jsx +36 -0
- package/dist/components/table/pagination.d.ts +5 -0
- package/dist/components/table/pagination.d.ts.map +1 -0
- package/dist/components/table/pagination.jsx +74 -0
- package/dist/components/table/row.d.ts +11 -0
- package/dist/components/table/row.d.ts.map +1 -0
- package/dist/components/table/row.jsx +49 -0
- package/dist/components/table/sort.d.ts +28 -0
- package/dist/components/table/sort.d.ts.map +1 -0
- package/dist/components/table/sort.jsx +109 -0
- package/dist/components/table/table-lib.d.ts +135 -0
- package/dist/components/table/table-lib.d.ts.map +1 -0
- package/dist/components/table/table-lib.js +83 -0
- package/dist/components/table/table.context.d.ts +10 -0
- package/dist/components/table/table.context.d.ts.map +1 -0
- package/dist/components/table/table.context.jsx +4 -0
- package/dist/components/table/thead.d.ts +9 -0
- package/dist/components/table/thead.d.ts.map +1 -0
- package/dist/components/table/thead.jsx +103 -0
- package/dist/config/context.d.ts +21 -0
- package/dist/config/context.d.ts.map +1 -0
- package/dist/config/context.js +12 -0
- package/dist/config/default-translations.d.ts +94 -0
- package/dist/config/default-translations.d.ts.map +1 -0
- package/dist/config/default-translations.jsx +87 -0
- package/dist/config/default-tweaks.d.ts +13 -0
- package/dist/config/default-tweaks.d.ts.map +1 -0
- package/dist/config/default-tweaks.js +4 -0
- package/dist/constants.d.ts +3 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js +2 -0
- package/dist/hooks/use-click-outside.d.ts +3 -0
- package/dist/hooks/use-click-outside.d.ts.map +1 -0
- package/dist/hooks/use-click-outside.js +17 -0
- package/dist/hooks/use-color-parser.d.ts +2 -0
- package/dist/hooks/use-color-parser.d.ts.map +1 -0
- package/dist/hooks/use-color-parser.js +9 -0
- package/dist/hooks/use-components-provider.d.ts +15 -0
- package/dist/hooks/use-components-provider.d.ts.map +1 -0
- package/dist/hooks/use-components-provider.jsx +22 -0
- package/dist/hooks/use-debounce.d.ts +5 -0
- package/dist/hooks/use-debounce.d.ts.map +1 -0
- package/dist/hooks/use-debounce.js +12 -0
- package/dist/hooks/use-floating-ref.d.ts +2 -0
- package/dist/hooks/use-floating-ref.d.ts.map +1 -0
- package/dist/hooks/use-floating-ref.js +6 -0
- package/dist/hooks/use-form.d.ts +394 -0
- package/dist/hooks/use-form.d.ts.map +1 -0
- package/dist/hooks/use-form.js +563 -0
- package/dist/hooks/use-hover.d.ts +3 -0
- package/dist/hooks/use-hover.d.ts.map +1 -0
- package/dist/hooks/use-hover.js +18 -0
- package/dist/hooks/use-input-id.d.ts +4 -0
- package/dist/hooks/use-input-id.d.ts.map +1 -0
- package/dist/hooks/use-input-id.js +5 -0
- package/dist/hooks/use-is-coarse-device.d.ts +2 -0
- package/dist/hooks/use-is-coarse-device.d.ts.map +1 -0
- package/dist/hooks/use-is-coarse-device.js +12 -0
- package/dist/hooks/use-locale.d.ts +3 -0
- package/dist/hooks/use-locale.d.ts.map +1 -0
- package/dist/hooks/use-locale.js +10 -0
- package/dist/hooks/use-media-query.d.ts +2 -0
- package/dist/hooks/use-media-query.d.ts.map +1 -0
- package/dist/hooks/use-media-query.js +25 -0
- package/dist/hooks/use-on-event.d.ts +4 -0
- package/dist/hooks/use-on-event.d.ts.map +1 -0
- package/dist/hooks/use-on-event.js +7 -0
- package/dist/hooks/use-parent.d.ts +3 -0
- package/dist/hooks/use-parent.d.ts.map +1 -0
- package/dist/hooks/use-parent.js +21 -0
- package/dist/hooks/use-preferences.d.ts +2 -0
- package/dist/hooks/use-preferences.d.ts.map +1 -0
- package/dist/hooks/use-preferences.js +23 -0
- package/dist/hooks/use-previous.d.ts +2 -0
- package/dist/hooks/use-previous.d.ts.map +1 -0
- package/dist/hooks/use-previous.js +9 -0
- package/dist/hooks/use-reactive.d.ts +2 -0
- package/dist/hooks/use-reactive.d.ts.map +1 -0
- package/dist/hooks/use-reactive.js +9 -0
- package/dist/hooks/use-remove-scroll.d.ts +4 -0
- package/dist/hooks/use-remove-scroll.d.ts.map +1 -0
- package/dist/hooks/use-remove-scroll.js +48 -0
- package/dist/hooks/use-resize-observer.d.ts +2 -0
- package/dist/hooks/use-resize-observer.d.ts.map +1 -0
- package/dist/hooks/use-resize-observer.js +17 -0
- package/dist/hooks/use-stable-ref.d.ts +2 -0
- package/dist/hooks/use-stable-ref.d.ts.map +1 -0
- package/dist/hooks/use-stable-ref.js +9 -0
- package/dist/hooks/use-swipe.d.ts +8 -0
- package/dist/hooks/use-swipe.d.ts.map +1 -0
- package/dist/hooks/use-swipe.js +17 -0
- package/dist/hooks/use-translations.d.ts +92 -0
- package/dist/hooks/use-translations.d.ts.map +1 -0
- package/dist/hooks/use-translations.js +9 -0
- package/dist/hooks/use-tweaks.d.ts +3 -0
- package/dist/hooks/use-tweaks.d.ts.map +1 -0
- package/dist/hooks/use-tweaks.js +9 -0
- package/dist/hooks/use-window-size.d.ts +5 -0
- package/dist/hooks/use-window-size.d.ts.map +1 -0
- package/dist/hooks/use-window-size.js +14 -0
- package/dist/index-DDeQW0JW.js.map +1 -1
- package/dist/index.d.ts +22 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +20 -8231
- package/dist/index.js.map +1 -1
- package/dist/lib/combi-keys.d.ts +15 -0
- package/dist/lib/combi-keys.d.ts.map +1 -0
- package/dist/lib/combi-keys.js +60 -0
- package/dist/lib/dict.d.ts +9 -0
- package/dist/lib/dict.d.ts.map +1 -0
- package/dist/lib/dict.js +28 -0
- package/dist/lib/dom.d.ts +20 -0
- package/dist/lib/dom.d.ts.map +1 -0
- package/dist/lib/dom.js +66 -0
- package/dist/lib/fns.d.ts +11 -0
- package/dist/lib/fns.d.ts.map +1 -0
- package/dist/lib/fns.js +46 -0
- package/dist/lib/fzf.d.ts +16 -0
- package/dist/lib/fzf.d.ts.map +1 -0
- package/dist/lib/fzf.js +115 -0
- package/dist/lib/keyboard-area.d.ts +16 -0
- package/dist/lib/keyboard-area.d.ts.map +1 -0
- package/dist/lib/keyboard-area.js +14 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { isValid } from "date-fns";
|
|
3
|
+
import { parse } from "qs";
|
|
4
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
5
|
+
import { getPath, Is } from "sidekicker";
|
|
6
|
+
import { LocalStorage } from "storage-manager-js";
|
|
7
|
+
import { z, ZodNumber } from "zod";
|
|
8
|
+
import { formReset, } from "../components";
|
|
9
|
+
/**
|
|
10
|
+
* Validates if a value is valid JSON
|
|
11
|
+
* @param value - The value to validate
|
|
12
|
+
* @returns True if the value is valid JSON
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
const isValidJSON = (value) => {
|
|
16
|
+
let str;
|
|
17
|
+
if (typeof value === "string") {
|
|
18
|
+
str = value;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
try {
|
|
22
|
+
str = JSON.stringify(value);
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
try {
|
|
29
|
+
JSON.parse(str);
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return false;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
const convertPath = (path) => path.replace(/\[(\d+)]/g, ".$1").split(".");
|
|
37
|
+
const shallowSetPath = (obj, keys, value) => {
|
|
38
|
+
if (keys.length === 0)
|
|
39
|
+
return value;
|
|
40
|
+
const [key, ...rest] = keys;
|
|
41
|
+
const current = obj !== null ? obj[key] : undefined;
|
|
42
|
+
const nextKey = rest[0];
|
|
43
|
+
const fallback = nextKey !== undefined && !Number.isNaN(Number(nextKey)) ? [] : {};
|
|
44
|
+
const updated = shallowSetPath(current ?? fallback, rest, value);
|
|
45
|
+
if (Array.isArray(obj)) {
|
|
46
|
+
const clone = obj.slice();
|
|
47
|
+
clone[Number(key)] = updated;
|
|
48
|
+
return clone;
|
|
49
|
+
}
|
|
50
|
+
return { ...(obj ?? {}), [key]: updated };
|
|
51
|
+
};
|
|
52
|
+
const setPath = (o, path, value) => {
|
|
53
|
+
const pathArr = Array.isArray(path) ? path.map(String) : convertPath(path);
|
|
54
|
+
return shallowSetPath(o, pathArr, value);
|
|
55
|
+
};
|
|
56
|
+
const sort = (a, b) => a.localeCompare(b);
|
|
57
|
+
const getDefaultValue = (inner) => {
|
|
58
|
+
const instanceName = inner._def.typeName;
|
|
59
|
+
if (instanceName === "ZodDefault")
|
|
60
|
+
return inner._def.defaultValue();
|
|
61
|
+
if (inner instanceof z.ZodObject)
|
|
62
|
+
return getDefaults(inner);
|
|
63
|
+
if (instanceName === "ZodArray")
|
|
64
|
+
return [];
|
|
65
|
+
if ("innerType" in inner._def) {
|
|
66
|
+
const defaults = getDefaultValue(inner._def.innerType);
|
|
67
|
+
if (instanceName === "ZodArray")
|
|
68
|
+
return defaults ?? [];
|
|
69
|
+
return defaults;
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
};
|
|
73
|
+
const getDefaults = (schema) => Object.fromEntries(Object.entries(schema.shape).map(([key, value]) => {
|
|
74
|
+
return [key, getDefaultValue(value)];
|
|
75
|
+
}));
|
|
76
|
+
const deepMerge = (a, b) => {
|
|
77
|
+
// as unknown as Record: structuredClone returns T, but we mutate it dynamically; static T & U proven at return
|
|
78
|
+
const result = structuredClone(a);
|
|
79
|
+
for (const key in b) {
|
|
80
|
+
const bValue = b[key];
|
|
81
|
+
const aValue = result[key];
|
|
82
|
+
if (bValue !== undefined) {
|
|
83
|
+
if (typeof bValue === "object" &&
|
|
84
|
+
bValue !== null &&
|
|
85
|
+
!Array.isArray(bValue) &&
|
|
86
|
+
typeof aValue === "object" &&
|
|
87
|
+
aValue !== null &&
|
|
88
|
+
!Array.isArray(aValue)) {
|
|
89
|
+
result[key] = deepMerge(aValue, bValue);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
result[key] = bValue ?? aValue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
return result;
|
|
97
|
+
};
|
|
98
|
+
const options = {
|
|
99
|
+
sort,
|
|
100
|
+
allowDots: true,
|
|
101
|
+
charset: "utf-8",
|
|
102
|
+
parseArrays: true,
|
|
103
|
+
plainObjects: true,
|
|
104
|
+
charsetSentinel: true,
|
|
105
|
+
allowPrototypes: false,
|
|
106
|
+
depth: Number.MAX_SAFE_INTEGER,
|
|
107
|
+
arrayLimit: Number.MAX_SAFE_INTEGER,
|
|
108
|
+
parameterLimit: Number.MAX_SAFE_INTEGER,
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Converts a form element to a JSON object
|
|
112
|
+
* @param form - The HTML form element to convert
|
|
113
|
+
* @returns A JSON object representing the form data
|
|
114
|
+
*/
|
|
115
|
+
export const formToJson = (form) => {
|
|
116
|
+
const formData = new FormData(form);
|
|
117
|
+
const urlSearchParams = new URLSearchParams(Array.from(formData.entries()).filter((entry) => typeof entry[1] === "string"));
|
|
118
|
+
return parse(urlSearchParams.toString(), options);
|
|
119
|
+
};
|
|
120
|
+
const schemaShapeCache = new WeakMap();
|
|
121
|
+
export const getSchemaShape = (name, schema) => {
|
|
122
|
+
let nameMap = schemaShapeCache.get(schema);
|
|
123
|
+
if (!nameMap) {
|
|
124
|
+
nameMap = new Map();
|
|
125
|
+
schemaShapeCache.set(schema, nameMap);
|
|
126
|
+
}
|
|
127
|
+
const cached = nameMap.get(name);
|
|
128
|
+
if (cached !== undefined)
|
|
129
|
+
return cached;
|
|
130
|
+
const result = convertPath(name).reduce((acc, el) => {
|
|
131
|
+
if (el === "")
|
|
132
|
+
return acc;
|
|
133
|
+
const zodObj = acc;
|
|
134
|
+
const shape = zodObj.shape?.[el] || acc;
|
|
135
|
+
const result = shape._def.typeName === "ZodArray" ? shape.element : shape;
|
|
136
|
+
return result;
|
|
137
|
+
}, schema);
|
|
138
|
+
nameMap.set(name, result);
|
|
139
|
+
return result;
|
|
140
|
+
};
|
|
141
|
+
const getValueByType = (e) => {
|
|
142
|
+
if (e.dataset.value)
|
|
143
|
+
return e.dataset.value;
|
|
144
|
+
if (e.type === "checkbox")
|
|
145
|
+
return e.checked;
|
|
146
|
+
if (e.type === "number")
|
|
147
|
+
return e.valueAsNumber;
|
|
148
|
+
return e.value || e.getAttribute("value");
|
|
149
|
+
};
|
|
150
|
+
const getDataTarget = (e) => {
|
|
151
|
+
const target = e.dataset.target;
|
|
152
|
+
if (!target)
|
|
153
|
+
return getValueByType(e);
|
|
154
|
+
const element = document.querySelector(`[data-origin="${target}"]`);
|
|
155
|
+
if (!element)
|
|
156
|
+
return getValueByType(e);
|
|
157
|
+
return getValueByType(element);
|
|
158
|
+
};
|
|
159
|
+
const getName = (e) => e.dataset.target || e.name;
|
|
160
|
+
/**
|
|
161
|
+
* Creates a form storage interceptor for persisting form state
|
|
162
|
+
* @param name - The unique name for the form storage
|
|
163
|
+
* @returns An interceptor object with get, set, and clear methods
|
|
164
|
+
*/
|
|
165
|
+
export const createFormStorage = (name) => {
|
|
166
|
+
const key = `@use-form/${name}`;
|
|
167
|
+
return {
|
|
168
|
+
get: () => {
|
|
169
|
+
const state = LocalStorage.get(key);
|
|
170
|
+
return isValidJSON(state) ? state : {};
|
|
171
|
+
},
|
|
172
|
+
clear: () => void LocalStorage.delete(key),
|
|
173
|
+
set: (s) => LocalStorage.set(key, s),
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
/**
|
|
177
|
+
* A comprehensive form management hook with Zod schema validation.
|
|
178
|
+
*
|
|
179
|
+
* Provides form state management, validation, and component binding for React forms.
|
|
180
|
+
* Supports automatic validation, error handling, and form persistence.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```tsx
|
|
184
|
+
* const schema = z.object({
|
|
185
|
+
* name: z.string().min(1, "Name is required"),
|
|
186
|
+
* email: z.string().email("Invalid email"),
|
|
187
|
+
* age: z.number().min(18, "Must be 18 or older")
|
|
188
|
+
* });
|
|
189
|
+
*
|
|
190
|
+
* const MyForm = () => {
|
|
191
|
+
* const form = useForm(schema, "user-form");
|
|
192
|
+
*
|
|
193
|
+
* return (
|
|
194
|
+
* <form {...form.controller()} onSubmit={form.onSubmit((e, { data }) => {
|
|
195
|
+
* console.log("Form data:", data);
|
|
196
|
+
* })}>
|
|
197
|
+
* <Input {...form.input("name")} placeholder="Name" />
|
|
198
|
+
* <Input {...form.input("email")} type="email" placeholder="Email" />
|
|
199
|
+
* <Input {...form.input("age")} type="number" placeholder="Age" />
|
|
200
|
+
* <Button type="submit">Submit</Button>
|
|
201
|
+
* </form>
|
|
202
|
+
* );
|
|
203
|
+
* };
|
|
204
|
+
* ```
|
|
205
|
+
*
|
|
206
|
+
* @template T - The Zod schema type
|
|
207
|
+
* @param schema - Zod schema for form validation
|
|
208
|
+
* @param formName - Unique identifier for the form
|
|
209
|
+
* @param opts - Optional configuration including initial state and interceptors
|
|
210
|
+
* @returns Form management object with input helpers and handlers
|
|
211
|
+
*/
|
|
212
|
+
export const useForm = (schema, formName, opts = {}) => {
|
|
213
|
+
const loading = opts.loading ?? false;
|
|
214
|
+
const [errors, setErrors] = useState(null);
|
|
215
|
+
const ref = useRef({});
|
|
216
|
+
const [state, setState] = useState(() => {
|
|
217
|
+
if (Is.function(opts?.state))
|
|
218
|
+
return opts.state();
|
|
219
|
+
return opts?.state ?? getDefaults(schema) ?? {};
|
|
220
|
+
});
|
|
221
|
+
const onInvalidField = useCallback((e) => {
|
|
222
|
+
const target = e.target;
|
|
223
|
+
const related = e.currentTarget;
|
|
224
|
+
const isOptional = target.dataset.optional === "true";
|
|
225
|
+
if (isOptional) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
const path = getName(target);
|
|
229
|
+
const value = getDataTarget(target) || (related ? getValueByType(related) : "");
|
|
230
|
+
const partialSchema = getSchemaShape(path, schema);
|
|
231
|
+
target.setAttribute("data-initialized", "true");
|
|
232
|
+
if (partialSchema) {
|
|
233
|
+
const validation = partialSchema.safeParse(value);
|
|
234
|
+
const message = validation.success ? undefined : (validation.error.issues[0]?.message ?? "");
|
|
235
|
+
setErrors((prev) => setPath(prev ?? {}, path, message));
|
|
236
|
+
}
|
|
237
|
+
}, [schema]);
|
|
238
|
+
const onInvalid = useCallback((exec) => (event) => {
|
|
239
|
+
const form = event.currentTarget;
|
|
240
|
+
const validationErrors = Object.values(ref.current).reduce((acc, input) => {
|
|
241
|
+
const field = input.element;
|
|
242
|
+
const validation = input.schema.safeParse(getValueByType(field));
|
|
243
|
+
if (field.dataset.ignore === "ignore")
|
|
244
|
+
return acc;
|
|
245
|
+
if (validation.success)
|
|
246
|
+
return acc;
|
|
247
|
+
const errorMessage = validation.error.issues[0]?.message;
|
|
248
|
+
field.setAttribute("data-initialized", "true");
|
|
249
|
+
const name = field.dataset.name || field.name || "";
|
|
250
|
+
return setPath(acc, name, errorMessage);
|
|
251
|
+
}, {});
|
|
252
|
+
const e = Is.empty(validationErrors) ? null : validationErrors;
|
|
253
|
+
setErrors(e);
|
|
254
|
+
console.error(e);
|
|
255
|
+
exec?.({ form, errors: e || {} });
|
|
256
|
+
}, []);
|
|
257
|
+
const datepicker = (name, props) => {
|
|
258
|
+
const validator = getSchemaShape(name, schema);
|
|
259
|
+
const onChange = (date) => {
|
|
260
|
+
if (!isValid(date))
|
|
261
|
+
return;
|
|
262
|
+
setState((prev) => setPath(prev, name, date.toISOString()));
|
|
263
|
+
setErrors((prev) => setPath(prev, name, undefined));
|
|
264
|
+
const input = ref.current[name].element;
|
|
265
|
+
if (input) {
|
|
266
|
+
const origin = input.getAttribute("data-origin");
|
|
267
|
+
const inputShadow = document.querySelector(`input[data-target="${origin}"]`);
|
|
268
|
+
if (inputShadow)
|
|
269
|
+
inputShadow.setCustomValidity("");
|
|
270
|
+
}
|
|
271
|
+
props?.onChange?.(date);
|
|
272
|
+
};
|
|
273
|
+
return {
|
|
274
|
+
...props,
|
|
275
|
+
loading,
|
|
276
|
+
name,
|
|
277
|
+
id: name,
|
|
278
|
+
onChange,
|
|
279
|
+
form: formName,
|
|
280
|
+
date: Is.string(state[name]) ? new Date(state[name]) : state[name],
|
|
281
|
+
required: props?.required ?? !validator.isOptional(),
|
|
282
|
+
error: getPath(errors, name),
|
|
283
|
+
ref: (e) => {
|
|
284
|
+
if (e === null)
|
|
285
|
+
return;
|
|
286
|
+
ref.current[name] = { element: e, schema: validator };
|
|
287
|
+
},
|
|
288
|
+
};
|
|
289
|
+
};
|
|
290
|
+
const select = (name, props) => {
|
|
291
|
+
const validator = getSchemaShape(name, schema);
|
|
292
|
+
const onChange = (e) => {
|
|
293
|
+
const value = e.target.value;
|
|
294
|
+
setState((prev) => setPath(prev, name, value));
|
|
295
|
+
// SelectProps/AutocompleteProps have divergent onChange signatures at this generic union boundary
|
|
296
|
+
props?.onChange?.(e);
|
|
297
|
+
};
|
|
298
|
+
return {
|
|
299
|
+
...props,
|
|
300
|
+
name,
|
|
301
|
+
id: name,
|
|
302
|
+
onChange,
|
|
303
|
+
form: formName,
|
|
304
|
+
loading,
|
|
305
|
+
onInvalid: onInvalidField,
|
|
306
|
+
error: getPath(errors, name, undefined),
|
|
307
|
+
value: getPath(state, name, undefined) ?? "",
|
|
308
|
+
required: props?.required ?? !validator.isOptional(),
|
|
309
|
+
ref: (e) => e !== null
|
|
310
|
+
? (ref.current[name] = {
|
|
311
|
+
element: e,
|
|
312
|
+
schema: validator,
|
|
313
|
+
})
|
|
314
|
+
: undefined,
|
|
315
|
+
};
|
|
316
|
+
};
|
|
317
|
+
const checkbox = (name, props) => {
|
|
318
|
+
const validator = getSchemaShape(name, schema);
|
|
319
|
+
const onChange = (e) => {
|
|
320
|
+
const value = e.target.checked;
|
|
321
|
+
setState((prev) => setPath(prev ?? {}, name, value));
|
|
322
|
+
props?.onChange?.(e);
|
|
323
|
+
};
|
|
324
|
+
return {
|
|
325
|
+
...props,
|
|
326
|
+
name,
|
|
327
|
+
id: name,
|
|
328
|
+
onChange,
|
|
329
|
+
form: formName,
|
|
330
|
+
loading,
|
|
331
|
+
onInvalid: onInvalidField,
|
|
332
|
+
error: getPath(errors, name, undefined),
|
|
333
|
+
required: props?.required ?? !validator.isOptional(),
|
|
334
|
+
ref: (e) => e !== null
|
|
335
|
+
? void (ref.current[name] = {
|
|
336
|
+
element: e,
|
|
337
|
+
schema: validator,
|
|
338
|
+
})
|
|
339
|
+
: undefined,
|
|
340
|
+
};
|
|
341
|
+
};
|
|
342
|
+
const textarea = (name, props) => {
|
|
343
|
+
const validator = getSchemaShape(name, schema);
|
|
344
|
+
const onChange = (e) => {
|
|
345
|
+
e.persist?.();
|
|
346
|
+
const value = e.target.value;
|
|
347
|
+
props?.onChange?.(e);
|
|
348
|
+
setState((prev) => setPath(prev, name, value));
|
|
349
|
+
};
|
|
350
|
+
return {
|
|
351
|
+
...props,
|
|
352
|
+
loading,
|
|
353
|
+
name,
|
|
354
|
+
id: name,
|
|
355
|
+
onChange,
|
|
356
|
+
form: formName,
|
|
357
|
+
onInvalid: onInvalidField,
|
|
358
|
+
error: getPath(errors, name, undefined),
|
|
359
|
+
required: props?.required ?? !validator.isOptional(),
|
|
360
|
+
value: getPath(state, name, undefined) || props?.value || "",
|
|
361
|
+
type: Is.instance(validator, ZodNumber) ? "number" : (props?.type ?? "text"),
|
|
362
|
+
ref: (e) => e === null
|
|
363
|
+
? undefined
|
|
364
|
+
: (ref.current[name] = {
|
|
365
|
+
element: e,
|
|
366
|
+
schema: validator,
|
|
367
|
+
}),
|
|
368
|
+
};
|
|
369
|
+
};
|
|
370
|
+
const multiselect = (name, props) => {
|
|
371
|
+
const validator = getSchemaShape(name, schema);
|
|
372
|
+
const onChangeOptions = (options) => {
|
|
373
|
+
setState((prev) => setPath(prev, name, options));
|
|
374
|
+
};
|
|
375
|
+
return {
|
|
376
|
+
...props,
|
|
377
|
+
name,
|
|
378
|
+
id: name,
|
|
379
|
+
onChangeOptions,
|
|
380
|
+
form: formName,
|
|
381
|
+
loading,
|
|
382
|
+
onInvalid: onInvalidField,
|
|
383
|
+
error: getPath(errors, name, undefined),
|
|
384
|
+
required: props?.required ?? !validator.isOptional(),
|
|
385
|
+
value: getPath(state, name, undefined) || props?.value || [],
|
|
386
|
+
ref: (e) => e === null
|
|
387
|
+
? undefined
|
|
388
|
+
: void (ref.current[name] = {
|
|
389
|
+
element: e,
|
|
390
|
+
schema: validator,
|
|
391
|
+
}),
|
|
392
|
+
};
|
|
393
|
+
};
|
|
394
|
+
const input = (name, props) => {
|
|
395
|
+
const validator = getSchemaShape(name, schema);
|
|
396
|
+
const isNumber = validator._def.typeName === "ZodNumber";
|
|
397
|
+
const onChange = (e) => {
|
|
398
|
+
e.persist?.();
|
|
399
|
+
const value = isNumber ? e.target.valueAsNumber : e.target.value;
|
|
400
|
+
props?.onChange?.(e);
|
|
401
|
+
setState((prev) => setPath(prev, name, value));
|
|
402
|
+
};
|
|
403
|
+
return {
|
|
404
|
+
...props,
|
|
405
|
+
name,
|
|
406
|
+
id: name,
|
|
407
|
+
onChange,
|
|
408
|
+
form: formName,
|
|
409
|
+
loading,
|
|
410
|
+
onInvalid: onInvalidField,
|
|
411
|
+
error: getPath(errors, name, undefined),
|
|
412
|
+
required: props?.required ?? !validator.isOptional(),
|
|
413
|
+
type: isNumber ? "number" : (props?.type ?? "text"),
|
|
414
|
+
value: getPath(state, name, undefined) || props?.value || "",
|
|
415
|
+
ref: (e) => e === null
|
|
416
|
+
? undefined
|
|
417
|
+
: void (ref.current[name] = {
|
|
418
|
+
element: e,
|
|
419
|
+
schema: validator,
|
|
420
|
+
}),
|
|
421
|
+
};
|
|
422
|
+
};
|
|
423
|
+
useEffect(() => {
|
|
424
|
+
const events = Object.values(ref.current).map((input) => {
|
|
425
|
+
const element = input.element.dataset.origin
|
|
426
|
+
? document.querySelector(`[data-target="${input.element.name}"]`)
|
|
427
|
+
: input.element;
|
|
428
|
+
const validation = input.schema.safeParse(getValueByType(element));
|
|
429
|
+
const onBlurField = (e) => {
|
|
430
|
+
if (e.target === null)
|
|
431
|
+
return false;
|
|
432
|
+
const name = getName(e.target);
|
|
433
|
+
if (!name)
|
|
434
|
+
return false;
|
|
435
|
+
const current = e.target;
|
|
436
|
+
const relatedTarget = e.relatedTarget;
|
|
437
|
+
const value = getDataTarget(current) || (relatedTarget ? getValueByType(relatedTarget) : "");
|
|
438
|
+
const validation = input.schema.safeParse(value);
|
|
439
|
+
current.setAttribute("value", value);
|
|
440
|
+
if (validation.success) {
|
|
441
|
+
if (element.setCustomValidity)
|
|
442
|
+
element.setCustomValidity("");
|
|
443
|
+
setErrors((prev) => {
|
|
444
|
+
if (Is.null(prev))
|
|
445
|
+
return null;
|
|
446
|
+
const newErrors = setPath(prev, name, undefined);
|
|
447
|
+
if (Is.empty(prev) || Is.nil(prev))
|
|
448
|
+
return null;
|
|
449
|
+
return Is.empty(newErrors) ? null : newErrors;
|
|
450
|
+
});
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
453
|
+
if (element.required) {
|
|
454
|
+
const errorMessage = validation.error.issues[0]?.message || "";
|
|
455
|
+
if (element.setCustomValidity)
|
|
456
|
+
element.setCustomValidity(errorMessage);
|
|
457
|
+
setErrors((prev) => {
|
|
458
|
+
if (Is.null(prev))
|
|
459
|
+
return null;
|
|
460
|
+
const newErrors = setPath(prev, name, errorMessage || undefined);
|
|
461
|
+
return Is.empty(newErrors) ? null : newErrors;
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return false;
|
|
465
|
+
};
|
|
466
|
+
const controller = new AbortController();
|
|
467
|
+
const trigger = element.getAttribute("data-trigger") || "blur";
|
|
468
|
+
element.addEventListener(trigger, onBlurField, { signal: controller.signal });
|
|
469
|
+
const hasInitialError = element.dataset.shadow ? false : element.required ? !validation.success : false;
|
|
470
|
+
return {
|
|
471
|
+
input,
|
|
472
|
+
hasInitialError,
|
|
473
|
+
unsubscribe: () => controller.abort(),
|
|
474
|
+
};
|
|
475
|
+
});
|
|
476
|
+
const hasErrors = events.some((x) => x.hasInitialError);
|
|
477
|
+
if (hasErrors)
|
|
478
|
+
setErrors((prev) => (prev === null ? {} : prev));
|
|
479
|
+
return () => events.forEach((item) => item.unsubscribe());
|
|
480
|
+
});
|
|
481
|
+
const onSubmit = (exec) => (event) => {
|
|
482
|
+
event.preventDefault();
|
|
483
|
+
const form = event.currentTarget;
|
|
484
|
+
let json = formToJson(form);
|
|
485
|
+
const elements = formName ? Array.from(document.querySelectorAll(`[form="${formName}"]`)) : Array.from(form.elements);
|
|
486
|
+
elements.forEach((field) => {
|
|
487
|
+
if (field.tagName === "SELECT") {
|
|
488
|
+
const input = field;
|
|
489
|
+
json = setPath(json, input.name, input.value);
|
|
490
|
+
}
|
|
491
|
+
if (field.tagName === "INPUT") {
|
|
492
|
+
const input = field;
|
|
493
|
+
const value = getDataTarget(input) || (input ? getValueByType(input) : "");
|
|
494
|
+
json = setPath(json, input.dataset.target || input.name, value);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
const input = deepMerge(json, state);
|
|
498
|
+
const result = schema.safeParse(input);
|
|
499
|
+
const reset = () => {
|
|
500
|
+
formReset(form);
|
|
501
|
+
opts.interceptor?.clear();
|
|
502
|
+
};
|
|
503
|
+
if (result.success) {
|
|
504
|
+
const jsonString = JSON.stringify(result.data);
|
|
505
|
+
form.setAttribute("data-json", jsonString);
|
|
506
|
+
opts.interceptor?.clear();
|
|
507
|
+
return exec?.(event, {
|
|
508
|
+
form,
|
|
509
|
+
event,
|
|
510
|
+
reset,
|
|
511
|
+
setErrors,
|
|
512
|
+
errors: [],
|
|
513
|
+
success: true,
|
|
514
|
+
data: result.data,
|
|
515
|
+
json: result.data,
|
|
516
|
+
});
|
|
517
|
+
}
|
|
518
|
+
console.group("useForm error");
|
|
519
|
+
console.info(result);
|
|
520
|
+
console.info(result.error.issues);
|
|
521
|
+
console.error(result.error);
|
|
522
|
+
console.groupEnd();
|
|
523
|
+
form.reportValidity();
|
|
524
|
+
return exec?.(event, {
|
|
525
|
+
form,
|
|
526
|
+
json,
|
|
527
|
+
event,
|
|
528
|
+
reset,
|
|
529
|
+
setErrors,
|
|
530
|
+
data: json,
|
|
531
|
+
success: false,
|
|
532
|
+
errors: result.error.issues.map((x) => ({ message: x.message, path: x.path.map((x) => String(x)) })),
|
|
533
|
+
});
|
|
534
|
+
};
|
|
535
|
+
const get = (p) => getPath(state, p) || "";
|
|
536
|
+
const controller = (props) => ({
|
|
537
|
+
...props,
|
|
538
|
+
id: formName,
|
|
539
|
+
name: formName,
|
|
540
|
+
});
|
|
541
|
+
useEffect(() => {
|
|
542
|
+
if (opts.interceptor)
|
|
543
|
+
opts.interceptor?.set(state);
|
|
544
|
+
}, [state]);
|
|
545
|
+
return {
|
|
546
|
+
get,
|
|
547
|
+
input,
|
|
548
|
+
state,
|
|
549
|
+
errors,
|
|
550
|
+
select,
|
|
551
|
+
checkbox,
|
|
552
|
+
onSubmit,
|
|
553
|
+
setState,
|
|
554
|
+
textarea,
|
|
555
|
+
onInvalid,
|
|
556
|
+
controller,
|
|
557
|
+
datepicker,
|
|
558
|
+
name: formName,
|
|
559
|
+
multiselect,
|
|
560
|
+
disabled: errors !== null,
|
|
561
|
+
};
|
|
562
|
+
};
|
|
563
|
+
export const getJsonForm = (form) => !form ? {} : JSON.parse(form.getAttribute("data-json"));
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-hover.d.ts","sourceRoot":"","sources":["../../src/hooks/use-hover.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,OAAO,CAAC;AAEvD,eAAO,MAAM,QAAQ,GAAI,KAAK,SAAS,CAAC,WAAW,CAAC,YAiBnD,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useEffect, useState } from "react";
|
|
2
|
+
export const useHover = (ref) => {
|
|
3
|
+
const [hovered, setHovered] = useState(false);
|
|
4
|
+
const enter = () => setHovered(true);
|
|
5
|
+
const leave = () => setHovered(false);
|
|
6
|
+
useEffect(() => {
|
|
7
|
+
const el = ref.current; // cache external ref value for use in cleanup
|
|
8
|
+
if (el) {
|
|
9
|
+
el.addEventListener("mouseenter", enter);
|
|
10
|
+
el.addEventListener("mouseleave", leave);
|
|
11
|
+
return () => {
|
|
12
|
+
el.removeEventListener("mouseenter", enter);
|
|
13
|
+
el.removeEventListener("mouseleave", leave);
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
}, []);
|
|
17
|
+
return hovered;
|
|
18
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-input-id.d.ts","sourceRoot":"","sources":["../../src/hooks/use-input-id.ts"],"names":[],"mappings":"AAEA,KAAK,CAAC,GAAG,MAAM,GAAG,SAAS,CAAC;AAE5B,eAAO,MAAM,UAAU,GAAI,IAAI,CAAC,EAAE,MAAM,CAAC,WAGxC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-is-coarse-device.d.ts","sourceRoot":"","sources":["../../src/hooks/use-is-coarse-device.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,iBAAiB,QAAO,OASpC,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useEffect, useRef, useState } from "react";
|
|
2
|
+
import { isSsr } from "../lib/fns";
|
|
3
|
+
const getCoarse = () => window.matchMedia("@media (pointer: coarse)");
|
|
4
|
+
export const useIsCoarseDevice = () => {
|
|
5
|
+
const ref = useRef(isSsr() ? null : getCoarse());
|
|
6
|
+
const [isCoarse, setIsCoarse] = useState(isSsr() ? false : (ref.current?.matches ?? false));
|
|
7
|
+
useEffect(() => {
|
|
8
|
+
const coerse = ref.current === null ? getCoarse() : ref.current;
|
|
9
|
+
coerse.addEventListener("change", (e) => setIsCoarse(e.matches));
|
|
10
|
+
}, []);
|
|
11
|
+
return isCoarse;
|
|
12
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-locale.d.ts","sourceRoot":"","sources":["../../src/hooks/use-locale.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAG9C,eAAO,MAAM,SAAS,GAAI,SAAS,OAAO,KAAG,OAAO,GAAG,SAKtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-media-query.d.ts","sourceRoot":"","sources":["../../src/hooks/use-media-query.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,eAAc,OAAc,YAkBxE,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { useLayoutEffect, useState } from "react";
|
|
2
|
+
import { isSsr } from "../lib/fns";
|
|
3
|
+
const getMatches = (query, defaultValue) => {
|
|
4
|
+
if (isSsr()) {
|
|
5
|
+
return defaultValue;
|
|
6
|
+
}
|
|
7
|
+
return window.matchMedia(query).matches;
|
|
8
|
+
};
|
|
9
|
+
export const useMediaQuery = (query, defaultValue = true) => {
|
|
10
|
+
const [matches, setMatches] = useState(defaultValue);
|
|
11
|
+
useLayoutEffect(() => {
|
|
12
|
+
const matchMedia = window.matchMedia(query);
|
|
13
|
+
const onChange = () => setMatches(getMatches(query, defaultValue));
|
|
14
|
+
onChange();
|
|
15
|
+
if (matchMedia.addListener) {
|
|
16
|
+
matchMedia.addListener(onChange);
|
|
17
|
+
return () => {
|
|
18
|
+
return matchMedia.removeListener ? matchMedia.removeListener(onChange) : undefined;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
matchMedia.addEventListener("change", onChange);
|
|
22
|
+
return () => matchMedia.removeEventListener("change", onChange);
|
|
23
|
+
}, [query]);
|
|
24
|
+
return matches;
|
|
25
|
+
};
|