@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.
Files changed (176) hide show
  1. package/dist/ai/SKILL.md +266 -0
  2. package/dist/ai/docs/Alert.md +167 -0
  3. package/dist/ai/docs/AnimatedList.md +205 -0
  4. package/dist/ai/docs/Autocomplete.md +225 -0
  5. package/dist/ai/docs/Button.md +182 -0
  6. package/dist/ai/docs/Calendar.md +219 -0
  7. package/dist/ai/docs/Card.md +174 -0
  8. package/dist/ai/docs/Checkbox.md +199 -0
  9. package/dist/ai/docs/CommandPalette.md +293 -0
  10. package/dist/ai/docs/DatePicker.md +171 -0
  11. package/dist/ai/docs/Dropdown.md +223 -0
  12. package/dist/ai/docs/Empty.md +163 -0
  13. package/dist/ai/docs/Expand.md +143 -0
  14. package/dist/ai/docs/FileUpload.md +225 -0
  15. package/dist/ai/docs/Form.md +107 -0
  16. package/dist/ai/docs/FormReset.md +117 -0
  17. package/dist/ai/docs/Heading.md +88 -0
  18. package/dist/ai/docs/Input.md +237 -0
  19. package/dist/ai/docs/InputField.md +170 -0
  20. package/dist/ai/docs/List.md +205 -0
  21. package/dist/ai/docs/Menu.md +166 -0
  22. package/dist/ai/docs/Modal.md +280 -0
  23. package/dist/ai/docs/MultiSelect.md +196 -0
  24. package/dist/ai/docs/Notifications.md +231 -0
  25. package/dist/ai/docs/PageCalendar.md +271 -0
  26. package/dist/ai/docs/Polymorph.md +159 -0
  27. package/dist/ai/docs/Progress.md +145 -0
  28. package/dist/ai/docs/Radiobox.md +128 -0
  29. package/dist/ai/docs/RenderOnView.md +138 -0
  30. package/dist/ai/docs/Resizable.md +159 -0
  31. package/dist/ai/docs/Select.md +284 -0
  32. package/dist/ai/docs/Shortcut.md +105 -0
  33. package/dist/ai/docs/Skeleton.md +166 -0
  34. package/dist/ai/docs/Slider.md +144 -0
  35. package/dist/ai/docs/Slot.md +173 -0
  36. package/dist/ai/docs/Spinner.md +118 -0
  37. package/dist/ai/docs/Stats.md +137 -0
  38. package/dist/ai/docs/Step.md +159 -0
  39. package/dist/ai/docs/Switch.md +167 -0
  40. package/dist/ai/docs/Table.md +298 -0
  41. package/dist/ai/docs/Tabs.md +191 -0
  42. package/dist/ai/docs/Tag.md +224 -0
  43. package/dist/ai/docs/TaskList.md +144 -0
  44. package/dist/ai/docs/Textarea.md +167 -0
  45. package/dist/ai/docs/Timeline.md +210 -0
  46. package/dist/ai/docs/Toolbar.md +132 -0
  47. package/dist/ai/docs/Tooltip.md +231 -0
  48. package/dist/ai/docs/TransferList.md +142 -0
  49. package/dist/ai/docs/Typography.md +187 -0
  50. package/dist/ai/docs/Wizard.md +213 -0
  51. package/dist/ai/docs/index.md +183 -0
  52. package/dist/components/core/tag.d.ts +1 -1
  53. package/dist/components/core/tag.d.ts.map +1 -1
  54. package/dist/components/display/list.d.ts.map +1 -1
  55. package/dist/components/floating/dropdown.d.ts +1 -0
  56. package/dist/components/floating/dropdown.d.ts.map +1 -1
  57. package/dist/components/floating/menu.d.ts.map +1 -1
  58. package/dist/config/default-translations.d.ts +4 -4
  59. package/dist/hooks/use-translations.d.ts +4 -4
  60. package/dist/hooks/use-translations.d.ts.map +1 -1
  61. package/dist/index.css +1 -1
  62. package/dist/index.js +28 -20
  63. package/dist/index.js.map +1 -1
  64. package/dist/index.mjs +2463 -2458
  65. package/dist/index.mjs.map +1 -1
  66. package/dist/index.umd.js +12 -12
  67. package/dist/index.umd.js.map +1 -1
  68. package/package.json +4 -4
  69. package/dist/components/core/button.jsx +0 -79
  70. package/dist/components/core/heading.jsx +0 -4
  71. package/dist/components/core/polymorph.jsx +0 -5
  72. package/dist/components/core/render-on-view.jsx +0 -31
  73. package/dist/components/core/resizable.jsx +0 -51
  74. package/dist/components/core/slot.jsx +0 -156
  75. package/dist/components/core/tag.jsx +0 -51
  76. package/dist/components/core/typography.jsx +0 -22
  77. package/dist/components/display/alert.jsx +0 -58
  78. package/dist/components/display/calendar.jsx +0 -299
  79. package/dist/components/display/card.jsx +0 -43
  80. package/dist/components/display/empty.jsx +0 -11
  81. package/dist/components/display/list.jsx +0 -81
  82. package/dist/components/display/notifications.jsx +0 -126
  83. package/dist/components/display/progress.jsx +0 -11
  84. package/dist/components/display/shortcut.jsx +0 -23
  85. package/dist/components/display/skeleton.jsx +0 -12
  86. package/dist/components/display/spinner.jsx +0 -7
  87. package/dist/components/display/stats.jsx +0 -20
  88. package/dist/components/display/step.jsx +0 -131
  89. package/dist/components/display/tabs.jsx +0 -98
  90. package/dist/components/display/timeline.jsx +0 -25
  91. package/dist/components/floating/command-palette.jsx +0 -194
  92. package/dist/components/floating/dropdown.jsx +0 -53
  93. package/dist/components/floating/expand.jsx +0 -44
  94. package/dist/components/floating/menu.jsx +0 -147
  95. package/dist/components/floating/modal.jsx +0 -299
  96. package/dist/components/floating/toolbar.jsx +0 -5
  97. package/dist/components/floating/tooltip.jsx +0 -58
  98. package/dist/components/floating/wizard.jsx +0 -161
  99. package/dist/components/form/autocomplete.jsx +0 -279
  100. package/dist/components/form/checkbox.jsx +0 -12
  101. package/dist/components/form/date-picker.jsx +0 -115
  102. package/dist/components/form/file-upload.jsx +0 -133
  103. package/dist/components/form/form.jsx +0 -10
  104. package/dist/components/form/formReset.jsx +0 -17
  105. package/dist/components/form/free-text.jsx +0 -41
  106. package/dist/components/form/input-field.jsx +0 -56
  107. package/dist/components/form/input.jsx +0 -36
  108. package/dist/components/form/multi-select.jsx +0 -328
  109. package/dist/components/form/radiobox.jsx +0 -6
  110. package/dist/components/form/select.jsx +0 -42
  111. package/dist/components/form/slider.jsx +0 -45
  112. package/dist/components/form/switch.jsx +0 -46
  113. package/dist/components/form/task-list.jsx +0 -26
  114. package/dist/components/form/textarea.jsx +0 -12
  115. package/dist/components/form/transfer-list.jsx +0 -39
  116. package/dist/components/index.js +0 -45
  117. package/dist/components/page-calendar/calendar-header.jsx +0 -81
  118. package/dist/components/page-calendar/day-view.jsx +0 -87
  119. package/dist/components/page-calendar/event-pill.jsx +0 -25
  120. package/dist/components/page-calendar/index.js +0 -2
  121. package/dist/components/page-calendar/month-view.jsx +0 -47
  122. package/dist/components/page-calendar/page-calendar.jsx +0 -41
  123. package/dist/components/page-calendar/page-calendar.types.js +0 -1
  124. package/dist/components/page-calendar/page-calendar.utils.js +0 -71
  125. package/dist/components/page-calendar/week-view.jsx +0 -64
  126. package/dist/components/table/filter.jsx +0 -141
  127. package/dist/components/table/group.jsx +0 -68
  128. package/dist/components/table/index.jsx +0 -60
  129. package/dist/components/table/inner-table.jsx +0 -104
  130. package/dist/components/table/metadata.jsx +0 -36
  131. package/dist/components/table/pagination.jsx +0 -73
  132. package/dist/components/table/row.jsx +0 -58
  133. package/dist/components/table/sort.jsx +0 -105
  134. package/dist/components/table/table-lib.js +0 -83
  135. package/dist/components/table/table.context.jsx +0 -4
  136. package/dist/components/table/thead.jsx +0 -103
  137. package/dist/config/context.js +0 -12
  138. package/dist/config/default-translations.jsx +0 -83
  139. package/dist/config/default-tweaks.js +0 -4
  140. package/dist/constants.js +0 -2
  141. package/dist/hooks/use-click-outside.js +0 -17
  142. package/dist/hooks/use-color-parser.js +0 -9
  143. package/dist/hooks/use-components-provider.jsx +0 -19
  144. package/dist/hooks/use-debounce.js +0 -12
  145. package/dist/hooks/use-floating-ref.js +0 -6
  146. package/dist/hooks/use-form.js +0 -550
  147. package/dist/hooks/use-hover.js +0 -18
  148. package/dist/hooks/use-input-id.js +0 -5
  149. package/dist/hooks/use-is-coarse-device.js +0 -12
  150. package/dist/hooks/use-locale.js +0 -10
  151. package/dist/hooks/use-media-query.js +0 -25
  152. package/dist/hooks/use-on-event.js +0 -7
  153. package/dist/hooks/use-parent.js +0 -21
  154. package/dist/hooks/use-preferences.js +0 -23
  155. package/dist/hooks/use-previous.js +0 -9
  156. package/dist/hooks/use-reactive.js +0 -9
  157. package/dist/hooks/use-remove-scroll.js +0 -61
  158. package/dist/hooks/use-resize-observer.js +0 -17
  159. package/dist/hooks/use-stable-ref.js +0 -9
  160. package/dist/hooks/use-swipe.js +0 -17
  161. package/dist/hooks/use-translations.js +0 -9
  162. package/dist/hooks/use-tweaks.js +0 -9
  163. package/dist/hooks/use-window-size.js +0 -14
  164. package/dist/lib/combi-keys.js +0 -60
  165. package/dist/lib/dict.js +0 -39
  166. package/dist/lib/dom.js +0 -62
  167. package/dist/lib/fns.js +0 -46
  168. package/dist/lib/fzf.js +0 -117
  169. package/dist/lib/keyboard-area.js +0 -14
  170. package/dist/styles/common.js +0 -29
  171. package/dist/styles/dark.js +0 -214
  172. package/dist/styles/design-tokens.js +0 -69
  173. package/dist/styles/light.js +0 -214
  174. package/dist/styles/theme.js +0 -4
  175. package/dist/styles/theme.types.js +0 -1
  176. package/dist/types.js +0 -1
@@ -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"));
@@ -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,5 +0,0 @@
1
- import { useId } from "react";
2
- export const useInputId = (id, name) => {
3
- const same = useId();
4
- return id || name || same;
5
- };
@@ -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
- };
@@ -1,10 +0,0 @@
1
- import { useContext } from "react";
2
- import { Context } from "../config/context";
3
- export const useLocale = (locale) => {
4
- const ctx = useContext(Context);
5
- if (locale)
6
- return locale;
7
- if (!ctx)
8
- return undefined;
9
- return ctx.locale || locale;
10
- };
@@ -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
- };
@@ -1,7 +0,0 @@
1
- import { useEffect } from "react";
2
- export const useOnEvent = (event, func) => {
3
- useEffect(() => {
4
- window.addEventListener(event, func);
5
- return () => window.removeEventListener(event, func);
6
- }, [event]);
7
- };
@@ -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
- };
@@ -1,9 +0,0 @@
1
- "use client";
2
- import { useEffect, useRef } from "react";
3
- export const usePrevious = (value) => {
4
- const ref = useRef(undefined);
5
- useEffect(() => {
6
- ref.current = value;
7
- }, [value]);
8
- return ref.current;
9
- };