@g4rcez/components 3.0.0 → 3.0.1
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/ai/SKILL.md +266 -0
- package/dist/ai/docs/Alert.md +167 -0
- package/dist/ai/docs/AnimatedList.md +205 -0
- package/dist/ai/docs/Autocomplete.md +225 -0
- package/dist/ai/docs/Button.md +182 -0
- package/dist/ai/docs/Calendar.md +219 -0
- package/dist/ai/docs/Card.md +174 -0
- package/dist/ai/docs/Checkbox.md +199 -0
- package/dist/ai/docs/CommandPalette.md +293 -0
- package/dist/ai/docs/DatePicker.md +171 -0
- package/dist/ai/docs/Dropdown.md +223 -0
- package/dist/ai/docs/Empty.md +163 -0
- package/dist/ai/docs/Expand.md +143 -0
- package/dist/ai/docs/FileUpload.md +225 -0
- package/dist/ai/docs/Form.md +107 -0
- package/dist/ai/docs/FormReset.md +117 -0
- package/dist/ai/docs/Heading.md +88 -0
- package/dist/ai/docs/Input.md +237 -0
- package/dist/ai/docs/InputField.md +170 -0
- package/dist/ai/docs/List.md +205 -0
- package/dist/ai/docs/Menu.md +166 -0
- package/dist/ai/docs/Modal.md +280 -0
- package/dist/ai/docs/MultiSelect.md +196 -0
- package/dist/ai/docs/Notifications.md +231 -0
- package/dist/ai/docs/PageCalendar.md +271 -0
- package/dist/ai/docs/Polymorph.md +159 -0
- package/dist/ai/docs/Progress.md +145 -0
- package/dist/ai/docs/Radiobox.md +128 -0
- package/dist/ai/docs/RenderOnView.md +138 -0
- package/dist/ai/docs/Resizable.md +159 -0
- package/dist/ai/docs/Select.md +284 -0
- package/dist/ai/docs/Shortcut.md +105 -0
- package/dist/ai/docs/Skeleton.md +166 -0
- package/dist/ai/docs/Slider.md +144 -0
- package/dist/ai/docs/Slot.md +173 -0
- package/dist/ai/docs/Spinner.md +118 -0
- package/dist/ai/docs/Stats.md +137 -0
- package/dist/ai/docs/Step.md +159 -0
- package/dist/ai/docs/Switch.md +167 -0
- package/dist/ai/docs/Table.md +298 -0
- package/dist/ai/docs/Tabs.md +191 -0
- package/dist/ai/docs/Tag.md +224 -0
- package/dist/ai/docs/TaskList.md +144 -0
- package/dist/ai/docs/Textarea.md +167 -0
- package/dist/ai/docs/Timeline.md +210 -0
- package/dist/ai/docs/Toolbar.md +132 -0
- package/dist/ai/docs/Tooltip.md +231 -0
- package/dist/ai/docs/TransferList.md +142 -0
- package/dist/ai/docs/Typography.md +187 -0
- package/dist/ai/docs/Wizard.md +213 -0
- package/dist/ai/docs/index.md +183 -0
- package/dist/components/core/tag.d.ts +1 -1
- package/dist/components/core/tag.d.ts.map +1 -1
- package/dist/components/display/list.d.ts.map +1 -1
- package/dist/components/floating/dropdown.d.ts +1 -0
- package/dist/components/floating/dropdown.d.ts.map +1 -1
- package/dist/components/floating/menu.d.ts.map +1 -1
- package/dist/config/default-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts +4 -4
- package/dist/hooks/use-translations.d.ts.map +1 -1
- package/dist/index.css +1 -1
- package/dist/index.js +28 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +2463 -2458
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +12 -12
- package/dist/index.umd.js.map +1 -1
- package/package.json +4 -4
- package/dist/components/core/button.jsx +0 -79
- package/dist/components/core/heading.jsx +0 -4
- package/dist/components/core/polymorph.jsx +0 -5
- package/dist/components/core/render-on-view.jsx +0 -31
- package/dist/components/core/resizable.jsx +0 -51
- package/dist/components/core/slot.jsx +0 -156
- package/dist/components/core/tag.jsx +0 -51
- package/dist/components/core/typography.jsx +0 -22
- package/dist/components/display/alert.jsx +0 -58
- package/dist/components/display/calendar.jsx +0 -299
- package/dist/components/display/card.jsx +0 -43
- package/dist/components/display/empty.jsx +0 -11
- package/dist/components/display/list.jsx +0 -81
- package/dist/components/display/notifications.jsx +0 -126
- package/dist/components/display/progress.jsx +0 -11
- package/dist/components/display/shortcut.jsx +0 -23
- package/dist/components/display/skeleton.jsx +0 -12
- package/dist/components/display/spinner.jsx +0 -7
- package/dist/components/display/stats.jsx +0 -20
- package/dist/components/display/step.jsx +0 -131
- package/dist/components/display/tabs.jsx +0 -98
- package/dist/components/display/timeline.jsx +0 -25
- package/dist/components/floating/command-palette.jsx +0 -194
- package/dist/components/floating/dropdown.jsx +0 -53
- package/dist/components/floating/expand.jsx +0 -44
- package/dist/components/floating/menu.jsx +0 -147
- package/dist/components/floating/modal.jsx +0 -299
- package/dist/components/floating/toolbar.jsx +0 -5
- package/dist/components/floating/tooltip.jsx +0 -58
- package/dist/components/floating/wizard.jsx +0 -161
- package/dist/components/form/autocomplete.jsx +0 -279
- package/dist/components/form/checkbox.jsx +0 -12
- package/dist/components/form/date-picker.jsx +0 -115
- package/dist/components/form/file-upload.jsx +0 -133
- package/dist/components/form/form.jsx +0 -10
- package/dist/components/form/formReset.jsx +0 -17
- package/dist/components/form/free-text.jsx +0 -41
- package/dist/components/form/input-field.jsx +0 -56
- package/dist/components/form/input.jsx +0 -36
- package/dist/components/form/multi-select.jsx +0 -328
- package/dist/components/form/radiobox.jsx +0 -6
- package/dist/components/form/select.jsx +0 -42
- package/dist/components/form/slider.jsx +0 -45
- package/dist/components/form/switch.jsx +0 -46
- package/dist/components/form/task-list.jsx +0 -26
- package/dist/components/form/textarea.jsx +0 -12
- package/dist/components/form/transfer-list.jsx +0 -39
- package/dist/components/index.js +0 -45
- package/dist/components/page-calendar/calendar-header.jsx +0 -81
- package/dist/components/page-calendar/day-view.jsx +0 -87
- package/dist/components/page-calendar/event-pill.jsx +0 -25
- package/dist/components/page-calendar/index.js +0 -2
- package/dist/components/page-calendar/month-view.jsx +0 -47
- package/dist/components/page-calendar/page-calendar.jsx +0 -41
- package/dist/components/page-calendar/page-calendar.types.js +0 -1
- package/dist/components/page-calendar/page-calendar.utils.js +0 -71
- package/dist/components/page-calendar/week-view.jsx +0 -64
- package/dist/components/table/filter.jsx +0 -141
- package/dist/components/table/group.jsx +0 -68
- package/dist/components/table/index.jsx +0 -60
- package/dist/components/table/inner-table.jsx +0 -104
- package/dist/components/table/metadata.jsx +0 -36
- package/dist/components/table/pagination.jsx +0 -73
- package/dist/components/table/row.jsx +0 -58
- package/dist/components/table/sort.jsx +0 -105
- package/dist/components/table/table-lib.js +0 -83
- package/dist/components/table/table.context.jsx +0 -4
- package/dist/components/table/thead.jsx +0 -103
- package/dist/config/context.js +0 -12
- package/dist/config/default-translations.jsx +0 -83
- package/dist/config/default-tweaks.js +0 -4
- package/dist/constants.js +0 -2
- package/dist/hooks/use-click-outside.js +0 -17
- package/dist/hooks/use-color-parser.js +0 -9
- package/dist/hooks/use-components-provider.jsx +0 -19
- package/dist/hooks/use-debounce.js +0 -12
- package/dist/hooks/use-floating-ref.js +0 -6
- package/dist/hooks/use-form.js +0 -550
- package/dist/hooks/use-hover.js +0 -18
- package/dist/hooks/use-input-id.js +0 -5
- package/dist/hooks/use-is-coarse-device.js +0 -12
- package/dist/hooks/use-locale.js +0 -10
- package/dist/hooks/use-media-query.js +0 -25
- package/dist/hooks/use-on-event.js +0 -7
- package/dist/hooks/use-parent.js +0 -21
- package/dist/hooks/use-preferences.js +0 -23
- package/dist/hooks/use-previous.js +0 -9
- package/dist/hooks/use-reactive.js +0 -9
- package/dist/hooks/use-remove-scroll.js +0 -61
- package/dist/hooks/use-resize-observer.js +0 -17
- package/dist/hooks/use-stable-ref.js +0 -9
- package/dist/hooks/use-swipe.js +0 -17
- package/dist/hooks/use-translations.js +0 -9
- package/dist/hooks/use-tweaks.js +0 -9
- package/dist/hooks/use-window-size.js +0 -14
- package/dist/lib/combi-keys.js +0 -60
- package/dist/lib/dict.js +0 -39
- package/dist/lib/dom.js +0 -62
- package/dist/lib/fns.js +0 -46
- package/dist/lib/fzf.js +0 -117
- package/dist/lib/keyboard-area.js +0 -14
- package/dist/styles/common.js +0 -29
- package/dist/styles/dark.js +0 -214
- package/dist/styles/design-tokens.js +0 -69
- package/dist/styles/light.js +0 -214
- package/dist/styles/theme.js +0 -4
- package/dist/styles/theme.types.js +0 -1
- package/dist/types.js +0 -1
package/dist/hooks/use-form.js
DELETED
|
@@ -1,550 +0,0 @@
|
|
|
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 { ZodNumber } from "zod";
|
|
8
|
-
import { formReset, } from "../components";
|
|
9
|
-
import { path } from "../lib/fns";
|
|
10
|
-
/**
|
|
11
|
-
* Validates if a value is valid JSON
|
|
12
|
-
* @param value - The value to validate
|
|
13
|
-
* @returns True if the value is valid JSON
|
|
14
|
-
* @internal
|
|
15
|
-
*/
|
|
16
|
-
const isValidJSON = (value) => {
|
|
17
|
-
if (typeof value !== "string") {
|
|
18
|
-
try {
|
|
19
|
-
value = JSON.stringify(value);
|
|
20
|
-
}
|
|
21
|
-
catch {
|
|
22
|
-
return false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
try {
|
|
26
|
-
JSON.parse(value);
|
|
27
|
-
return true;
|
|
28
|
-
}
|
|
29
|
-
catch {
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
const setHelper = (obj, path, value) => {
|
|
34
|
-
const lastIndex = path.length - 1;
|
|
35
|
-
for (let i = 0; i < path.length; i++) {
|
|
36
|
-
const key = path[i];
|
|
37
|
-
if (i === lastIndex) {
|
|
38
|
-
obj[key] = value;
|
|
39
|
-
}
|
|
40
|
-
else {
|
|
41
|
-
if (!(key in obj) || typeof obj[key] !== "object") {
|
|
42
|
-
const nextKey = path[i + 1];
|
|
43
|
-
obj[key] = isNaN(Number(nextKey)) ? {} : [];
|
|
44
|
-
}
|
|
45
|
-
obj = obj[key];
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
const convertPath = (path) => path.replace(/\[(\d+)]/g, ".$1").split(".");
|
|
50
|
-
const setPath = (o, path, value) => {
|
|
51
|
-
const pathArr = Array.isArray(path) ? path.map(String) : convertPath(path);
|
|
52
|
-
const obj = structuredClone(o);
|
|
53
|
-
setHelper(obj, pathArr, value);
|
|
54
|
-
return obj;
|
|
55
|
-
};
|
|
56
|
-
const sort = (a, b) => a.localeCompare(b);
|
|
57
|
-
const noop = {};
|
|
58
|
-
const getDefaultValue = (inner) => {
|
|
59
|
-
const instanceName = inner._def.typeName;
|
|
60
|
-
if (instanceName === "ZodDefault")
|
|
61
|
-
return inner._def.defaultValue();
|
|
62
|
-
if (instanceName === "ZodObject")
|
|
63
|
-
return getDefaults(inner);
|
|
64
|
-
if (instanceName === "ZodArray")
|
|
65
|
-
return [];
|
|
66
|
-
if ("innerType" in inner._def) {
|
|
67
|
-
const defaults = getDefaultValue(inner._def.innerType);
|
|
68
|
-
if (instanceName === "ZodArray")
|
|
69
|
-
return defaults ?? [];
|
|
70
|
-
return defaults;
|
|
71
|
-
}
|
|
72
|
-
return undefined;
|
|
73
|
-
};
|
|
74
|
-
const getDefaults = (schema) => Object.fromEntries(Object.entries(schema.shape).map(([key, value]) => {
|
|
75
|
-
return [key, getDefaultValue(value)];
|
|
76
|
-
}));
|
|
77
|
-
const deepMerge = (a, b) => {
|
|
78
|
-
const result = structuredClone(a);
|
|
79
|
-
for (const key in b) {
|
|
80
|
-
const bValue = b[key];
|
|
81
|
-
const aValue = a[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 ? 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(formData);
|
|
118
|
-
return parse(urlSearchParams.toString(), options);
|
|
119
|
-
};
|
|
120
|
-
export const getSchemaShape = (name, schema) => {
|
|
121
|
-
return convertPath(name).reduce((acc, el) => {
|
|
122
|
-
if (el === "")
|
|
123
|
-
return acc;
|
|
124
|
-
const shape = acc.shape?.[el] || acc;
|
|
125
|
-
return shape._def.typeName === "ZodArray" ? shape.element : shape;
|
|
126
|
-
}, schema);
|
|
127
|
-
};
|
|
128
|
-
const getValueByType = (e) => {
|
|
129
|
-
if (e.dataset.value)
|
|
130
|
-
return e.dataset.value;
|
|
131
|
-
if (e.type === "checkbox")
|
|
132
|
-
return e.checked;
|
|
133
|
-
if (e.type === "number")
|
|
134
|
-
return e.valueAsNumber;
|
|
135
|
-
return e.value || e.getAttribute("value");
|
|
136
|
-
};
|
|
137
|
-
const getDataTarget = (e) => {
|
|
138
|
-
const target = e.dataset.target;
|
|
139
|
-
if (!target)
|
|
140
|
-
return getValueByType(e);
|
|
141
|
-
const element = document.querySelector(`[data-origin="${target}"]`);
|
|
142
|
-
if (!element)
|
|
143
|
-
return getValueByType(e);
|
|
144
|
-
return getValueByType(element);
|
|
145
|
-
};
|
|
146
|
-
const defaultOptions = {
|
|
147
|
-
state: {},
|
|
148
|
-
loading: false,
|
|
149
|
-
useOnChange: false,
|
|
150
|
-
};
|
|
151
|
-
const getName = (e) => e.dataset.target || e.name;
|
|
152
|
-
/**
|
|
153
|
-
* Creates a form storage interceptor for persisting form state
|
|
154
|
-
* @param name - The unique name for the form storage
|
|
155
|
-
* @returns An interceptor object with get, set, and clear methods
|
|
156
|
-
*/
|
|
157
|
-
export const createFormStorage = (name) => {
|
|
158
|
-
const key = `@use-form/${name}`;
|
|
159
|
-
return {
|
|
160
|
-
get: () => {
|
|
161
|
-
const state = LocalStorage.get(key);
|
|
162
|
-
return isValidJSON(state) ? state : {};
|
|
163
|
-
},
|
|
164
|
-
clear: () => void LocalStorage.delete(key),
|
|
165
|
-
set: (s) => LocalStorage.set(key, s),
|
|
166
|
-
};
|
|
167
|
-
};
|
|
168
|
-
/**
|
|
169
|
-
* A comprehensive form management hook with Zod schema validation.
|
|
170
|
-
*
|
|
171
|
-
* Provides form state management, validation, and component binding for React forms.
|
|
172
|
-
* Supports automatic validation, error handling, and form persistence.
|
|
173
|
-
*
|
|
174
|
-
* @example
|
|
175
|
-
* ```tsx
|
|
176
|
-
* const schema = z.object({
|
|
177
|
-
* name: z.string().min(1, "Name is required"),
|
|
178
|
-
* email: z.string().email("Invalid email"),
|
|
179
|
-
* age: z.number().min(18, "Must be 18 or older")
|
|
180
|
-
* });
|
|
181
|
-
*
|
|
182
|
-
* const MyForm = () => {
|
|
183
|
-
* const form = useForm(schema, "user-form");
|
|
184
|
-
*
|
|
185
|
-
* return (
|
|
186
|
-
* <form {...form.controller()} onSubmit={form.onSubmit((e, { data }) => {
|
|
187
|
-
* console.log("Form data:", data);
|
|
188
|
-
* })}>
|
|
189
|
-
* <Input {...form.input("name")} placeholder="Name" />
|
|
190
|
-
* <Input {...form.input("email")} type="email" placeholder="Email" />
|
|
191
|
-
* <Input {...form.input("age")} type="number" placeholder="Age" />
|
|
192
|
-
* <Button type="submit">Submit</Button>
|
|
193
|
-
* </form>
|
|
194
|
-
* );
|
|
195
|
-
* };
|
|
196
|
-
* ```
|
|
197
|
-
*
|
|
198
|
-
* @template T - The Zod schema type
|
|
199
|
-
* @param schema - Zod schema for form validation
|
|
200
|
-
* @param formName - Unique identifier for the form
|
|
201
|
-
* @param opts - Optional configuration including initial state and interceptors
|
|
202
|
-
* @returns Form management object with input helpers and handlers
|
|
203
|
-
*/
|
|
204
|
-
export const useForm = (schema, formName, opts = defaultOptions) => {
|
|
205
|
-
const [errors, setErrors] = useState(null);
|
|
206
|
-
const ref = useRef({});
|
|
207
|
-
const [state, setState] = useState(() => {
|
|
208
|
-
if (Is.function(opts?.state))
|
|
209
|
-
return opts.state();
|
|
210
|
-
return opts?.state ?? getDefaults(schema) ?? {};
|
|
211
|
-
});
|
|
212
|
-
const onInvalidField = useCallback((e) => {
|
|
213
|
-
const target = e.target;
|
|
214
|
-
const related = e.currentTarget;
|
|
215
|
-
const isOptional = target.dataset.optional === "true";
|
|
216
|
-
if (isOptional) {
|
|
217
|
-
return;
|
|
218
|
-
}
|
|
219
|
-
const path = getName(target);
|
|
220
|
-
const value = getDataTarget(target) || (related ? getValueByType(related) : "");
|
|
221
|
-
const partialSchema = getSchemaShape(path, schema);
|
|
222
|
-
target.setAttribute("data-initialized", "true");
|
|
223
|
-
if (partialSchema) {
|
|
224
|
-
const validation = partialSchema.safeParse(value);
|
|
225
|
-
const message = validation.success ? undefined : (validation.error.issues[0]?.message ?? "");
|
|
226
|
-
setErrors((prev) => setPath(prev ?? {}, path, message));
|
|
227
|
-
}
|
|
228
|
-
}, [schema]);
|
|
229
|
-
const onInvalid = useCallback((exec) => (event) => {
|
|
230
|
-
const form = event.currentTarget;
|
|
231
|
-
const validationErrors = Object.values(ref.current).reduce((acc, input) => {
|
|
232
|
-
const field = input.element;
|
|
233
|
-
const validation = input.schema.safeParse(getValueByType(field));
|
|
234
|
-
if (field.dataset.ignore === "ignore")
|
|
235
|
-
return acc;
|
|
236
|
-
if (validation.success)
|
|
237
|
-
return acc;
|
|
238
|
-
const errorMessage = validation.error.issues[0]?.message;
|
|
239
|
-
field.setAttribute("data-initialized", "true");
|
|
240
|
-
const name = field.dataset.name || field.name || "";
|
|
241
|
-
return setPath(acc, name, errorMessage);
|
|
242
|
-
}, {});
|
|
243
|
-
const e = Is.empty(validationErrors) ? null : validationErrors;
|
|
244
|
-
setErrors(e);
|
|
245
|
-
console.error(e);
|
|
246
|
-
exec?.({ form, errors: e || {} });
|
|
247
|
-
}, []);
|
|
248
|
-
const datepicker = (name, props = noop) => {
|
|
249
|
-
const validator = getSchemaShape(name, schema);
|
|
250
|
-
const onChange = (date) => {
|
|
251
|
-
if (!isValid(date))
|
|
252
|
-
return;
|
|
253
|
-
setState((prev) => setPath(prev, name, date.toISOString()));
|
|
254
|
-
setErrors((prev) => setPath(prev, name, undefined));
|
|
255
|
-
const input = ref.current[name].element;
|
|
256
|
-
if (input) {
|
|
257
|
-
const origin = input.getAttribute("data-origin");
|
|
258
|
-
const inputShadow = document.querySelector(`input[data-target="${origin}"]`);
|
|
259
|
-
if (inputShadow)
|
|
260
|
-
inputShadow.setCustomValidity("");
|
|
261
|
-
}
|
|
262
|
-
props?.onChange?.(date);
|
|
263
|
-
};
|
|
264
|
-
return {
|
|
265
|
-
...props,
|
|
266
|
-
loading: opts.loading,
|
|
267
|
-
name,
|
|
268
|
-
id: name,
|
|
269
|
-
onChange,
|
|
270
|
-
form: formName,
|
|
271
|
-
date: Is.string(state[name]) ? new Date(state[name]) : state[name],
|
|
272
|
-
required: props.required ?? !validator.isOptional(),
|
|
273
|
-
error: getPath(errors, name),
|
|
274
|
-
ref: (e) => {
|
|
275
|
-
if (e === null)
|
|
276
|
-
return;
|
|
277
|
-
ref.current[name] = { element: e, schema: validator };
|
|
278
|
-
},
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
const select = (name, props = noop) => {
|
|
282
|
-
const validator = getSchemaShape(name, schema);
|
|
283
|
-
const onChange = (e) => {
|
|
284
|
-
const value = e.target.value;
|
|
285
|
-
setState((prev) => setPath(prev, name, value));
|
|
286
|
-
props?.onChange?.(e);
|
|
287
|
-
};
|
|
288
|
-
return {
|
|
289
|
-
...props,
|
|
290
|
-
name,
|
|
291
|
-
id: name,
|
|
292
|
-
onChange,
|
|
293
|
-
form: formName,
|
|
294
|
-
loading: opts.loading,
|
|
295
|
-
onInvalid: onInvalidField,
|
|
296
|
-
error: getPath(errors, name, undefined),
|
|
297
|
-
value: getPath(state, name, undefined) ?? "",
|
|
298
|
-
required: props.required ?? !validator.isOptional(),
|
|
299
|
-
ref: (e) => e !== null
|
|
300
|
-
? (ref.current[name] = {
|
|
301
|
-
element: e,
|
|
302
|
-
schema: validator,
|
|
303
|
-
})
|
|
304
|
-
: undefined,
|
|
305
|
-
};
|
|
306
|
-
};
|
|
307
|
-
const checkbox = (name, props = noop) => {
|
|
308
|
-
const validator = getSchemaShape(name, schema);
|
|
309
|
-
const onChange = (e) => {
|
|
310
|
-
const value = e.target.checked;
|
|
311
|
-
setState((prev) => setPath(prev ?? {}, name, value));
|
|
312
|
-
props?.onChange?.(e);
|
|
313
|
-
};
|
|
314
|
-
return {
|
|
315
|
-
...props,
|
|
316
|
-
name,
|
|
317
|
-
id: name,
|
|
318
|
-
onChange,
|
|
319
|
-
form: formName,
|
|
320
|
-
loading: opts.loading,
|
|
321
|
-
onInvalid: onInvalidField,
|
|
322
|
-
error: getPath(errors, name, undefined),
|
|
323
|
-
required: props.required ?? !validator.isOptional(),
|
|
324
|
-
ref: (e) => e !== null
|
|
325
|
-
? void (ref.current[name] = {
|
|
326
|
-
element: e,
|
|
327
|
-
schema: validator,
|
|
328
|
-
})
|
|
329
|
-
: undefined,
|
|
330
|
-
};
|
|
331
|
-
};
|
|
332
|
-
const textarea = (name, props = noop) => {
|
|
333
|
-
const validator = getSchemaShape(name, schema);
|
|
334
|
-
const onChange = (e) => {
|
|
335
|
-
e.persist?.();
|
|
336
|
-
const value = e.target.value;
|
|
337
|
-
props?.onChange?.(e);
|
|
338
|
-
setState((prev) => setPath(prev, name, value));
|
|
339
|
-
};
|
|
340
|
-
return {
|
|
341
|
-
...props,
|
|
342
|
-
loading: opts.loading,
|
|
343
|
-
name,
|
|
344
|
-
id: name,
|
|
345
|
-
onChange,
|
|
346
|
-
form: formName,
|
|
347
|
-
onInvalid: onInvalidField,
|
|
348
|
-
error: getPath(errors, name, undefined),
|
|
349
|
-
required: props.required ?? !validator.isOptional(),
|
|
350
|
-
value: getPath(state, name, undefined) || props?.value || "",
|
|
351
|
-
type: Is.instance(validator, ZodNumber) ? "number" : (props?.type ?? "text"),
|
|
352
|
-
ref: (e) => e === null
|
|
353
|
-
? undefined
|
|
354
|
-
: (ref.current[name] = {
|
|
355
|
-
element: e,
|
|
356
|
-
schema: validator,
|
|
357
|
-
}),
|
|
358
|
-
};
|
|
359
|
-
};
|
|
360
|
-
const multiselect = (name, props = noop) => {
|
|
361
|
-
const validator = getSchemaShape(name, schema);
|
|
362
|
-
const onChangeOptions = (options) => {
|
|
363
|
-
setState((prev) => setPath(prev, name, options));
|
|
364
|
-
};
|
|
365
|
-
return {
|
|
366
|
-
...props,
|
|
367
|
-
name,
|
|
368
|
-
id: name,
|
|
369
|
-
onChangeOptions,
|
|
370
|
-
form: formName,
|
|
371
|
-
loading: opts.loading,
|
|
372
|
-
onInvalid: onInvalidField,
|
|
373
|
-
error: getPath(errors, name, undefined),
|
|
374
|
-
required: props.required ?? !validator.isOptional(),
|
|
375
|
-
value: getPath(state, name, undefined) || props?.value || [],
|
|
376
|
-
ref: (e) => e === null
|
|
377
|
-
? undefined
|
|
378
|
-
: void (ref.current[name] = {
|
|
379
|
-
element: e,
|
|
380
|
-
schema: validator,
|
|
381
|
-
}),
|
|
382
|
-
};
|
|
383
|
-
};
|
|
384
|
-
const input = (name, props = noop) => {
|
|
385
|
-
const validator = getSchemaShape(name, schema);
|
|
386
|
-
const isNumber = validator._def.typeName === "ZodNumber";
|
|
387
|
-
const onChange = (e) => {
|
|
388
|
-
e.persist?.();
|
|
389
|
-
const value = isNumber ? e.target.valueAsNumber : e.target.value;
|
|
390
|
-
props?.onChange?.(e);
|
|
391
|
-
setState((prev) => setPath(prev, name, value));
|
|
392
|
-
};
|
|
393
|
-
return {
|
|
394
|
-
...props,
|
|
395
|
-
name,
|
|
396
|
-
id: name,
|
|
397
|
-
onChange,
|
|
398
|
-
form: formName,
|
|
399
|
-
loading: opts.loading,
|
|
400
|
-
onInvalid: onInvalidField,
|
|
401
|
-
error: getPath(errors, name, undefined),
|
|
402
|
-
required: props.required ?? !validator.isOptional(),
|
|
403
|
-
type: isNumber ? "number" : (props?.type ?? "text"),
|
|
404
|
-
value: getPath(state, name, undefined) || props?.value || "",
|
|
405
|
-
ref: (e) => e === null
|
|
406
|
-
? undefined
|
|
407
|
-
: void (ref.current[name] = {
|
|
408
|
-
element: e,
|
|
409
|
-
schema: validator,
|
|
410
|
-
}),
|
|
411
|
-
};
|
|
412
|
-
};
|
|
413
|
-
useEffect(() => {
|
|
414
|
-
const events = Object.values(ref.current).map((input) => {
|
|
415
|
-
const element = input.element.dataset.origin
|
|
416
|
-
? document.querySelector(`[data-target="${input.element.name}"]`)
|
|
417
|
-
: input.element;
|
|
418
|
-
const validation = input.schema.safeParse(getValueByType(element));
|
|
419
|
-
const onBlurField = (e) => {
|
|
420
|
-
const name = getName(e.target);
|
|
421
|
-
if (!name)
|
|
422
|
-
return false;
|
|
423
|
-
const current = e.target;
|
|
424
|
-
const value = getDataTarget(e.target) || (e.relatedTarget ? getValueByType(e.relatedTarget) : "");
|
|
425
|
-
const validation = input.schema.safeParse(value);
|
|
426
|
-
current.setAttribute("value", value);
|
|
427
|
-
if (validation.success) {
|
|
428
|
-
if (element.setCustomValidity)
|
|
429
|
-
element.setCustomValidity("");
|
|
430
|
-
setErrors((prev) => {
|
|
431
|
-
if (Is.null(prev))
|
|
432
|
-
return null;
|
|
433
|
-
const newErrors = setPath(prev, name, undefined);
|
|
434
|
-
if (Is.empty(prev) || Is.nil(prev))
|
|
435
|
-
return null;
|
|
436
|
-
return Is.empty(newErrors) ? null : newErrors;
|
|
437
|
-
});
|
|
438
|
-
return false;
|
|
439
|
-
}
|
|
440
|
-
if (element.required) {
|
|
441
|
-
const errorMessage = validation.error.issues[0]?.message || "";
|
|
442
|
-
if (element.setCustomValidity)
|
|
443
|
-
element.setCustomValidity(errorMessage);
|
|
444
|
-
setErrors((prev) => {
|
|
445
|
-
if (Is.null(prev))
|
|
446
|
-
return null;
|
|
447
|
-
const newErrors = setPath(prev, name, errorMessage || undefined);
|
|
448
|
-
return Is.empty(newErrors) ? null : newErrors;
|
|
449
|
-
});
|
|
450
|
-
}
|
|
451
|
-
return false;
|
|
452
|
-
};
|
|
453
|
-
const controller = new AbortController();
|
|
454
|
-
const trigger = element.getAttribute("data-trigger") || "blur";
|
|
455
|
-
element.addEventListener(trigger, onBlurField, { signal: controller.signal });
|
|
456
|
-
const hasInitialError = element.dataset.shadow ? false : element.required ? !validation.success : false;
|
|
457
|
-
return {
|
|
458
|
-
input,
|
|
459
|
-
hasInitialError,
|
|
460
|
-
unsubscribe: () => controller.abort(),
|
|
461
|
-
};
|
|
462
|
-
});
|
|
463
|
-
const hasErrors = events.some((x) => x.hasInitialError);
|
|
464
|
-
if (hasErrors)
|
|
465
|
-
setErrors((prev) => (prev === null ? {} : prev));
|
|
466
|
-
return () => events.forEach((item) => item.unsubscribe());
|
|
467
|
-
});
|
|
468
|
-
const onSubmit = (exec) => (event) => {
|
|
469
|
-
event.preventDefault();
|
|
470
|
-
const form = event.currentTarget;
|
|
471
|
-
let json = formToJson(form);
|
|
472
|
-
const elements = formName ? Array.from(document.querySelectorAll(`[form="${formName}"]`)) : Array.from(form.elements);
|
|
473
|
-
elements.forEach((field) => {
|
|
474
|
-
if (field.tagName === "SELECT") {
|
|
475
|
-
const input = field;
|
|
476
|
-
json = setPath(json, input.name, input.value);
|
|
477
|
-
}
|
|
478
|
-
if (field.tagName === "INPUT") {
|
|
479
|
-
const input = field;
|
|
480
|
-
const value = getDataTarget(input) || (input ? getValueByType(input) : "");
|
|
481
|
-
json = setPath(json, input.dataset.target || input.name, value);
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
const input = deepMerge(json, state);
|
|
485
|
-
const result = schema.safeParse(input);
|
|
486
|
-
const reset = () => {
|
|
487
|
-
formReset(form);
|
|
488
|
-
opts.interceptor?.clear();
|
|
489
|
-
};
|
|
490
|
-
if (result.success) {
|
|
491
|
-
const jsonString = JSON.stringify(result.data);
|
|
492
|
-
form.setAttribute("data-json", jsonString);
|
|
493
|
-
opts.interceptor?.clear();
|
|
494
|
-
return exec?.(event, {
|
|
495
|
-
form,
|
|
496
|
-
event,
|
|
497
|
-
reset,
|
|
498
|
-
setErrors,
|
|
499
|
-
errors: [],
|
|
500
|
-
success: true,
|
|
501
|
-
data: result.data,
|
|
502
|
-
json: result.data,
|
|
503
|
-
});
|
|
504
|
-
}
|
|
505
|
-
console.group("useForm error");
|
|
506
|
-
console.info(result);
|
|
507
|
-
console.info(result.error.issues);
|
|
508
|
-
console.error(result.error);
|
|
509
|
-
console.groupEnd();
|
|
510
|
-
form.reportValidity();
|
|
511
|
-
return exec?.(event, {
|
|
512
|
-
form,
|
|
513
|
-
json,
|
|
514
|
-
event,
|
|
515
|
-
reset,
|
|
516
|
-
setErrors,
|
|
517
|
-
data: json,
|
|
518
|
-
success: false,
|
|
519
|
-
errors: result.error.issues.map((x) => ({ message: x.message, path: x.path.map((x) => String(x)) })),
|
|
520
|
-
});
|
|
521
|
-
};
|
|
522
|
-
const get = (p) => path(state, p) || "";
|
|
523
|
-
const controller = (props) => ({
|
|
524
|
-
...props,
|
|
525
|
-
id: formName,
|
|
526
|
-
name: formName,
|
|
527
|
-
});
|
|
528
|
-
useEffect(() => {
|
|
529
|
-
if (opts.interceptor)
|
|
530
|
-
opts.interceptor?.set(state);
|
|
531
|
-
}, [state]);
|
|
532
|
-
return {
|
|
533
|
-
get,
|
|
534
|
-
input,
|
|
535
|
-
state,
|
|
536
|
-
errors,
|
|
537
|
-
select,
|
|
538
|
-
checkbox,
|
|
539
|
-
onSubmit,
|
|
540
|
-
setState,
|
|
541
|
-
textarea,
|
|
542
|
-
onInvalid,
|
|
543
|
-
controller,
|
|
544
|
-
datepicker,
|
|
545
|
-
name: formName,
|
|
546
|
-
multiselect,
|
|
547
|
-
disabled: errors !== null,
|
|
548
|
-
};
|
|
549
|
-
};
|
|
550
|
-
export const getJsonForm = (form) => !form ? {} : JSON.parse(form.getAttribute("data-json"));
|
package/dist/hooks/use-hover.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
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
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
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
|
-
};
|
package/dist/hooks/use-locale.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
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
|
-
};
|
package/dist/hooks/use-parent.js
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from "react";
|
|
2
|
-
export const useParentHeight = (ref) => {
|
|
3
|
-
const [h, setH] = useState(0);
|
|
4
|
-
useEffect(() => {
|
|
5
|
-
const element = ref.current;
|
|
6
|
-
if (!element)
|
|
7
|
-
return;
|
|
8
|
-
const parent = element.parentElement;
|
|
9
|
-
if (!parent)
|
|
10
|
-
return;
|
|
11
|
-
const listener = () => {
|
|
12
|
-
setH(parent.clientHeight);
|
|
13
|
-
};
|
|
14
|
-
parent.addEventListener("resize", listener);
|
|
15
|
-
listener();
|
|
16
|
-
return () => {
|
|
17
|
-
parent.removeEventListener("resize", listener);
|
|
18
|
-
};
|
|
19
|
-
}, []);
|
|
20
|
-
return h;
|
|
21
|
-
};
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { useCallback, useState } from "react";
|
|
2
|
-
import { Is } from "sidekicker";
|
|
3
|
-
import { LocalStorage } from "storage-manager-js";
|
|
4
|
-
export const usePreferences = (key, defaultValue) => {
|
|
5
|
-
const [state, setState] = useState(() => {
|
|
6
|
-
const saved = LocalStorage.get(key);
|
|
7
|
-
if (saved)
|
|
8
|
-
return saved;
|
|
9
|
-
return defaultValue;
|
|
10
|
-
});
|
|
11
|
-
const setCallback = useCallback((params) => {
|
|
12
|
-
if (Is.function(params)) {
|
|
13
|
-
return setState((prev) => {
|
|
14
|
-
const result = params(prev);
|
|
15
|
-
LocalStorage.set(key, result);
|
|
16
|
-
return result;
|
|
17
|
-
});
|
|
18
|
-
}
|
|
19
|
-
LocalStorage.set(key, params);
|
|
20
|
-
return params;
|
|
21
|
-
}, [key]);
|
|
22
|
-
return [state, setCallback];
|
|
23
|
-
};
|