@fynixorg/ui 1.0.11 → 1.0.13

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 (127) hide show
  1. package/LICENSE +21 -0
  2. package/dist/README.md +36 -0
  3. package/dist/context/context.d.ts +19 -0
  4. package/dist/context/context.d.ts.map +1 -0
  5. package/dist/context/context.js +3 -11
  6. package/dist/context/context.js.map +3 -3
  7. package/dist/custom/button.d.ts +2 -0
  8. package/dist/custom/button.d.ts.map +1 -0
  9. package/dist/custom/button.js +2 -9
  10. package/dist/custom/button.js.map +3 -3
  11. package/dist/custom/index.d.ts +3 -0
  12. package/dist/custom/index.d.ts.map +1 -0
  13. package/dist/custom/index.js +2 -7
  14. package/dist/custom/index.js.map +3 -3
  15. package/dist/custom/path.d.ts +14 -0
  16. package/dist/custom/path.d.ts.map +1 -0
  17. package/dist/custom/path.js +17 -34
  18. package/dist/custom/path.js.map +3 -3
  19. package/dist/error/errorOverlay.d.ts +3 -0
  20. package/dist/error/errorOverlay.d.ts.map +1 -0
  21. package/dist/error/errorOverlay.js +82 -91
  22. package/dist/error/errorOverlay.js.map +3 -3
  23. package/dist/fynix/index.d.ts +5 -0
  24. package/dist/fynix/index.d.ts.map +1 -0
  25. package/dist/fynix/index.js +2 -7
  26. package/dist/fynix/index.js.map +3 -3
  27. package/dist/hooks/nixAsync.d.ts +14 -0
  28. package/dist/hooks/nixAsync.d.ts.map +1 -0
  29. package/dist/hooks/nixAsync.js +38 -43
  30. package/dist/hooks/nixAsync.js.map +3 -3
  31. package/dist/hooks/nixAsyncCache.d.ts +14 -0
  32. package/dist/hooks/nixAsyncCache.d.ts.map +1 -0
  33. package/dist/hooks/nixAsyncCache.js +57 -59
  34. package/dist/hooks/nixAsyncCache.js.map +3 -3
  35. package/dist/hooks/nixAsyncDebounce.d.ts +22 -0
  36. package/dist/hooks/nixAsyncDebounce.d.ts.map +1 -0
  37. package/dist/hooks/nixAsyncDebounce.js +74 -85
  38. package/dist/hooks/nixAsyncDebounce.js.map +3 -3
  39. package/dist/hooks/nixAsyncQuery.d.ts +16 -0
  40. package/dist/hooks/nixAsyncQuery.d.ts.map +1 -0
  41. package/dist/hooks/nixAsyncQuery.js +85 -79
  42. package/dist/hooks/nixAsyncQuery.js.map +3 -3
  43. package/dist/hooks/nixCallback.d.ts +2 -0
  44. package/dist/hooks/nixCallback.d.ts.map +1 -0
  45. package/dist/hooks/nixCallback.js +30 -40
  46. package/dist/hooks/nixCallback.js.map +3 -3
  47. package/dist/hooks/nixComputed.d.ts +16 -0
  48. package/dist/hooks/nixComputed.d.ts.map +1 -0
  49. package/dist/hooks/nixComputed.js +166 -198
  50. package/dist/hooks/nixComputed.js.map +4 -4
  51. package/dist/hooks/nixDebounce.d.ts +11 -0
  52. package/dist/hooks/nixDebounce.d.ts.map +1 -0
  53. package/dist/hooks/nixDebounce.js +53 -58
  54. package/dist/hooks/nixDebounce.js.map +3 -3
  55. package/dist/hooks/nixEffect.d.ts +4 -0
  56. package/dist/hooks/nixEffect.d.ts.map +1 -0
  57. package/dist/hooks/nixEffect.js +65 -75
  58. package/dist/hooks/nixEffect.js.map +3 -3
  59. package/dist/hooks/nixForm.d.ts +33 -0
  60. package/dist/hooks/nixForm.d.ts.map +1 -0
  61. package/dist/hooks/nixForm.js +110 -120
  62. package/dist/hooks/nixForm.js.map +3 -3
  63. package/dist/hooks/nixFormAsync.d.ts +42 -0
  64. package/dist/hooks/nixFormAsync.d.ts.map +1 -0
  65. package/dist/hooks/nixFormAsync.js +158 -167
  66. package/dist/hooks/nixFormAsync.js.map +3 -3
  67. package/dist/hooks/nixInterval.d.ts +2 -0
  68. package/dist/hooks/nixInterval.d.ts.map +1 -0
  69. package/dist/hooks/nixInterval.js +21 -27
  70. package/dist/hooks/nixInterval.js.map +3 -3
  71. package/dist/hooks/nixLazy.d.ts +8 -0
  72. package/dist/hooks/nixLazy.d.ts.map +1 -0
  73. package/dist/hooks/nixLazy.js +53 -58
  74. package/dist/hooks/nixLazy.js.map +3 -3
  75. package/dist/hooks/nixLazyAsync.d.ts +10 -0
  76. package/dist/hooks/nixLazyAsync.d.ts.map +1 -0
  77. package/dist/hooks/nixLazyAsync.js +65 -71
  78. package/dist/hooks/nixLazyAsync.js.map +3 -3
  79. package/dist/hooks/nixLazyFormAsync.d.ts +50 -0
  80. package/dist/hooks/nixLazyFormAsync.d.ts.map +1 -0
  81. package/dist/hooks/nixLazyFormAsync.js +209 -213
  82. package/dist/hooks/nixLazyFormAsync.js.map +3 -3
  83. package/dist/hooks/nixLocalStorage.d.ts +5 -0
  84. package/dist/hooks/nixLocalStorage.d.ts.map +1 -0
  85. package/dist/hooks/nixLocalStorage.js +21 -25
  86. package/dist/hooks/nixLocalStorage.js.map +3 -3
  87. package/dist/hooks/nixMemo.d.ts +2 -0
  88. package/dist/hooks/nixMemo.d.ts.map +1 -0
  89. package/dist/hooks/nixMemo.js +27 -31
  90. package/dist/hooks/nixMemo.js.map +3 -3
  91. package/dist/hooks/nixPrevious.d.ts +2 -0
  92. package/dist/hooks/nixPrevious.d.ts.map +1 -0
  93. package/dist/hooks/nixPrevious.js +13 -19
  94. package/dist/hooks/nixPrevious.js.map +3 -3
  95. package/dist/hooks/nixRef.d.ts +4 -0
  96. package/dist/hooks/nixRef.d.ts.map +1 -0
  97. package/dist/hooks/nixRef.js +14 -20
  98. package/dist/hooks/nixRef.js.map +3 -3
  99. package/dist/hooks/nixState.d.ts +15 -0
  100. package/dist/hooks/nixState.d.ts.map +1 -0
  101. package/dist/hooks/nixState.js +120 -173
  102. package/dist/hooks/nixState.js.map +3 -3
  103. package/dist/hooks/nixStore.d.ts +7 -0
  104. package/dist/hooks/nixStore.d.ts.map +1 -0
  105. package/dist/hooks/nixStore.js +48 -54
  106. package/dist/hooks/nixStore.js.map +3 -3
  107. package/dist/package.json +213 -0
  108. package/dist/plugins/vite-plugin-res.d.ts +41 -0
  109. package/dist/plugins/vite-plugin-res.d.ts.map +1 -0
  110. package/dist/plugins/vite-plugin-res.js +620 -36
  111. package/dist/plugins/vite-plugin-res.js.map +4 -4
  112. package/dist/router/router.d.ts +35 -0
  113. package/dist/router/router.d.ts.map +1 -0
  114. package/dist/router/router.js +520 -486
  115. package/dist/router/router.js.map +3 -3
  116. package/dist/runtime.d.ts +62 -0
  117. package/dist/runtime.d.ts.map +1 -0
  118. package/dist/runtime.js +833 -820
  119. package/dist/runtime.js.map +4 -4
  120. package/package.json +227 -44
  121. package/types/fnx.d.ts +72 -0
  122. package/types/fynix-ui.d.ts +323 -0
  123. package/types/global.d.ts +46 -6
  124. package/types/index.d.ts +37 -0
  125. package/types/vite-env.d.ts +553 -0
  126. package/runtime.d.ts +0 -83
  127. package/types/jsx.d.ts +0 -692
@@ -1,225 +1,221 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
- import { nixState } from "./nixState.js";
4
- import { nixComputed } from "./nixComputed.js";
5
1
  import { activeContext } from "../context/context.js";
6
- function nixLazyFormAsync(importFn, formOptions = {}, submitOptions = {}, lazyOptions = {}) {
7
- const { initialValues = {}, validationRules = {} } = formOptions;
8
- const { retry = 0 } = lazyOptions;
9
- const { delay = 300, leading = false, trailing = true, maxWait, cache = true } = submitOptions;
10
- const lazyCache = {
11
- status: "pending",
12
- component: null,
13
- error: null,
14
- promise: null,
15
- retriesLeft: retry
16
- };
17
- let lazyAbortController = new AbortController();
18
- let lazyCanceled = false;
19
- const loadLazy = /* @__PURE__ */ __name(() => {
20
- lazyCache.promise = importFn().then((module) => {
21
- if (!lazyCanceled) {
22
- lazyCache.status = "success";
23
- lazyCache.component = module.default || module;
24
- }
25
- }).catch((err) => {
26
- if (!lazyCanceled) {
27
- if (lazyCache.retriesLeft > 0) {
28
- lazyCache.retriesLeft--;
29
- return loadLazy();
2
+ import { nixComputed } from "./nixComputed.js";
3
+ import { nixState } from "./nixState.js";
4
+ export function nixLazyFormAsync(importFn, formOptions = {}, submitOptions = {}, lazyOptions = {}) {
5
+ const { initialValues = {}, validationRules = {}, } = formOptions;
6
+ const { retry = 0 } = lazyOptions;
7
+ const { delay = 300, leading = false, trailing = true, maxWait, cache = true, } = submitOptions;
8
+ const lazyCache = {
9
+ status: "pending",
10
+ component: null,
11
+ error: null,
12
+ promise: null,
13
+ retriesLeft: retry,
14
+ };
15
+ let lazyAbortController = new AbortController();
16
+ let lazyCanceled = false;
17
+ const loadLazy = () => {
18
+ lazyCache.promise = importFn()
19
+ .then((module) => {
20
+ if (!lazyCanceled) {
21
+ lazyCache.status = "success";
22
+ lazyCache.component = module.default || module;
23
+ }
24
+ })
25
+ .catch((err) => {
26
+ if (!lazyCanceled) {
27
+ if (lazyCache.retriesLeft > 0) {
28
+ lazyCache.retriesLeft--;
29
+ return loadLazy();
30
+ }
31
+ lazyCache.status = "error";
32
+ lazyCache.error = err;
33
+ }
34
+ return Promise.reject(err);
35
+ });
36
+ return lazyCache.promise;
37
+ };
38
+ loadLazy();
39
+ const cancelLazyLoad = () => {
40
+ lazyCanceled = true;
41
+ if (lazyAbortController) {
42
+ lazyAbortController.abort();
43
+ lazyAbortController = null;
44
+ }
45
+ };
46
+ const LazyComponentWrapper = (props) => {
47
+ const ctx = activeContext;
48
+ if (!ctx)
49
+ throw new Error("nixLazyFormAsync: called outside component");
50
+ if (lazyCache.status === "pending")
51
+ throw lazyCache.promise;
52
+ if (lazyCache.status === "error")
53
+ throw lazyCache.error;
54
+ return lazyCache.component(props);
55
+ };
56
+ const values = nixState({ ...initialValues });
57
+ const errors = nixState({});
58
+ const touched = nixState({});
59
+ const isSubmitting = nixState(false);
60
+ const isValid = nixComputed(() => Object.keys(errors.value).length === 0);
61
+ const data = nixState(null);
62
+ const error = nixState(null);
63
+ const loading = nixState(false);
64
+ let abortController = null;
65
+ let timerId = null;
66
+ let lastInvokeTime = 0;
67
+ let lastResult = null;
68
+ let lastError = null;
69
+ let pendingPromise = null;
70
+ function validate(fieldName, value) {
71
+ const rules = validationRules[fieldName];
72
+ if (!rules)
73
+ return null;
74
+ if (rules.required && !value)
75
+ return rules.message || `${String(fieldName)} is required`;
76
+ if (rules.minLength && value.length < rules.minLength)
77
+ return (rules.message ||
78
+ `${String(fieldName)} must be at least ${rules.minLength} characters`);
79
+ if (rules.maxLength && value.length > rules.maxLength)
80
+ return (rules.message ||
81
+ `${String(fieldName)} must be at most ${rules.maxLength} characters`);
82
+ if (rules.pattern && !rules.pattern.test(value))
83
+ return rules.message || `${String(fieldName)} is invalid`;
84
+ if (rules.custom && !rules.custom(value, values.value))
85
+ return rules.message || `${String(fieldName)} is invalid`;
86
+ return null;
87
+ }
88
+ function handleChange(fieldName, value) {
89
+ values.value = { ...values.value, [fieldName]: value };
90
+ if (touched.value[fieldName]) {
91
+ const err = validate(fieldName, value);
92
+ if (err)
93
+ errors.value = { ...errors.value, [fieldName]: err };
94
+ else {
95
+ const newErrors = { ...errors.value };
96
+ delete newErrors[fieldName];
97
+ errors.value = newErrors;
98
+ }
30
99
  }
31
- lazyCache.status = "error";
32
- lazyCache.error = err;
33
- }
34
- });
35
- return lazyCache.promise;
36
- }, "loadLazy");
37
- loadLazy();
38
- const cancelLazyLoad = /* @__PURE__ */ __name(() => {
39
- lazyCanceled = true;
40
- lazyAbortController.abort();
41
- lazyAbortController = null;
42
- }, "cancelLazyLoad");
43
- const LazyComponentWrapper = /* @__PURE__ */ __name((props) => {
44
- const ctx = activeContext;
45
- if (!ctx)
46
- throw new Error("nixLazyFormAsync: called outside component");
47
- if (lazyCache.status === "pending")
48
- throw lazyCache.promise;
49
- if (lazyCache.status === "error")
50
- throw lazyCache.error;
51
- return lazyCache.component(props);
52
- }, "LazyComponentWrapper");
53
- const values = nixState({ ...initialValues });
54
- const errors = nixState({});
55
- const touched = nixState({});
56
- const isSubmitting = nixState(false);
57
- const isValid = nixComputed(() => Object.keys(errors.value).length === 0);
58
- const data = nixState(null);
59
- const error = nixState(null);
60
- const loading = nixState(false);
61
- let abortController = null;
62
- let timerId = null;
63
- let lastInvokeTime = 0;
64
- let lastResult = null;
65
- let lastError = null;
66
- let pendingPromise = null;
67
- function validate(fieldName, value) {
68
- const rules = validationRules[fieldName];
69
- if (!rules)
70
- return null;
71
- if (rules.required && !value)
72
- return rules.message || `${fieldName} is required`;
73
- if (rules.minLength && value.length < rules.minLength)
74
- return rules.message || `${fieldName} must be at least ${rules.minLength} characters`;
75
- if (rules.maxLength && value.length > rules.maxLength)
76
- return rules.message || `${fieldName} must be at most ${rules.maxLength} characters`;
77
- if (rules.pattern && !rules.pattern.test(value))
78
- return rules.message || `${fieldName} is invalid`;
79
- if (rules.custom && !rules.custom(value, values.value))
80
- return rules.message || `${fieldName} is invalid`;
81
- return null;
82
- }
83
- __name(validate, "validate");
84
- function handleChange(fieldName, value) {
85
- values.value = { ...values.value, [fieldName]: value };
86
- if (touched.value[fieldName]) {
87
- const err = validate(fieldName, value);
88
- if (err)
89
- errors.value = { ...errors.value, [fieldName]: err };
90
- else {
91
- const newErrors = { ...errors.value };
92
- delete newErrors[fieldName];
93
- errors.value = newErrors;
94
- }
95
100
  }
96
- }
97
- __name(handleChange, "handleChange");
98
- function handleBlur(fieldName) {
99
- touched.value = { ...touched.value, [fieldName]: true };
100
- const err = validate(fieldName, values.value[fieldName]);
101
- if (err)
102
- errors.value = { ...errors.value, [fieldName]: err };
103
- }
104
- __name(handleBlur, "handleBlur");
105
- function validateAll() {
106
- const newErrors = {};
107
- Object.keys(validationRules).forEach((fieldName) => {
108
- const err = validate(fieldName, values.value[fieldName]);
109
- if (err)
110
- newErrors[fieldName] = err;
111
- });
112
- errors.value = newErrors;
113
- return Object.keys(newErrors).length === 0;
114
- }
115
- __name(validateAll, "validateAll");
116
- async function invokeAsync(onSubmit) {
117
- if (cache && lastResult !== null) {
118
- data.value = lastResult;
119
- error.value = lastError;
120
- loading.value = false;
121
- return lastResult;
101
+ function handleBlur(fieldName) {
102
+ touched.value = { ...touched.value, [fieldName]: true };
103
+ const err = validate(fieldName, values.value[fieldName]);
104
+ if (err)
105
+ errors.value = { ...errors.value, [fieldName]: err };
122
106
  }
123
- if (abortController)
124
- abortController.abort();
125
- abortController = new AbortController();
126
- const signal = abortController.signal;
127
- loading.value = true;
128
- error.value = null;
129
- pendingPromise = onSubmit(values.value, signal);
130
- try {
131
- const result = await pendingPromise;
132
- lastResult = result;
133
- data.value = result;
134
- return result;
135
- } catch (err) {
136
- if (err.name !== "AbortError") {
137
- lastError = err;
138
- error.value = err;
139
- }
140
- throw err;
141
- } finally {
142
- loading.value = false;
143
- pendingPromise = null;
144
- lastInvokeTime = Date.now();
107
+ function validateAll() {
108
+ const newErrors = {};
109
+ Object.keys(validationRules).forEach((fieldName) => {
110
+ const err = validate(fieldName, values.value[fieldName]);
111
+ if (err)
112
+ newErrors[fieldName] = err;
113
+ });
114
+ errors.value = newErrors;
115
+ return Object.keys(newErrors).length === 0;
145
116
  }
146
- }
147
- __name(invokeAsync, "invokeAsync");
148
- function handleSubmit(onSubmit) {
149
- if (!validateAll())
150
- return;
151
- const now = Date.now();
152
- const timeSinceLastInvoke = now - lastInvokeTime;
153
- const remainingTime = delay - timeSinceLastInvoke;
154
- const shouldInvokeLeading = leading && !timerId;
155
- if (maxWait !== void 0 && timeSinceLastInvoke >= maxWait) {
156
- if (timerId)
157
- clearTimeout(timerId);
158
- timerId = null;
159
- return invokeAsync(onSubmit);
117
+ async function invokeAsync(onSubmit) {
118
+ if (cache && lastResult !== null) {
119
+ data.value = lastResult ?? null;
120
+ error.value = lastError ?? null;
121
+ loading.value = false;
122
+ return lastResult;
123
+ }
124
+ if (abortController)
125
+ abortController.abort();
126
+ abortController = new AbortController();
127
+ const signal = abortController.signal;
128
+ loading.value = true;
129
+ error.value = null;
130
+ pendingPromise = onSubmit(values.value, signal);
131
+ try {
132
+ const result = await pendingPromise;
133
+ lastResult = result;
134
+ data.value = result ?? null;
135
+ return result;
136
+ }
137
+ catch (err) {
138
+ if (err.name !== "AbortError") {
139
+ lastError = err;
140
+ error.value = err;
141
+ }
142
+ throw err;
143
+ }
144
+ finally {
145
+ loading.value = false;
146
+ pendingPromise = null;
147
+ lastInvokeTime = Date.now();
148
+ }
160
149
  }
161
- if (timerId)
162
- clearTimeout(timerId);
163
- if (shouldInvokeLeading)
164
- return invokeAsync(onSubmit);
165
- if (trailing) {
166
- timerId = setTimeout(() => {
150
+ function handleSubmit(onSubmit) {
151
+ if (!validateAll())
152
+ return;
153
+ const now = Date.now();
154
+ const timeSinceLastInvoke = now - lastInvokeTime;
155
+ const remainingTime = delay - timeSinceLastInvoke;
156
+ const shouldInvokeLeading = leading && !timerId;
157
+ if (maxWait !== undefined && timeSinceLastInvoke >= maxWait) {
158
+ if (timerId)
159
+ clearTimeout(timerId);
160
+ timerId = null;
161
+ void invokeAsync(onSubmit);
162
+ return;
163
+ }
164
+ if (timerId)
165
+ clearTimeout(timerId);
166
+ if (shouldInvokeLeading) {
167
+ void invokeAsync(onSubmit);
168
+ return;
169
+ }
170
+ if (trailing) {
171
+ timerId = setTimeout(() => {
172
+ timerId = null;
173
+ void invokeAsync(onSubmit);
174
+ }, remainingTime > 0 ? remainingTime : delay);
175
+ }
176
+ }
177
+ function cancelSubmit() {
178
+ if (abortController) {
179
+ abortController.abort();
180
+ abortController = null;
181
+ }
182
+ if (timerId)
183
+ clearTimeout(timerId);
167
184
  timerId = null;
168
- invokeAsync(onSubmit);
169
- }, remainingTime > 0 ? remainingTime : delay);
170
185
  }
171
- }
172
- __name(handleSubmit, "handleSubmit");
173
- function cancelSubmit() {
174
- if (abortController) {
175
- abortController.abort();
176
- abortController = null;
186
+ function reset() {
187
+ values.value = { ...initialValues };
188
+ errors.value = {};
189
+ touched.value = {};
190
+ isSubmitting.value = false;
191
+ cancelSubmit();
192
+ cancelLazyLoad();
193
+ data.value = null;
194
+ error.value = null;
195
+ loading.value = false;
196
+ }
197
+ function getFieldProps(fieldName) {
198
+ return {
199
+ value: values.value[fieldName] || "",
200
+ "r-input": (e) => handleChange(fieldName, e.target.value),
201
+ "r-blur": () => handleBlur(fieldName),
202
+ };
177
203
  }
178
- if (timerId)
179
- clearTimeout(timerId);
180
- timerId = null;
181
- }
182
- __name(cancelSubmit, "cancelSubmit");
183
- function reset() {
184
- values.value = { ...initialValues };
185
- errors.value = {};
186
- touched.value = {};
187
- isSubmitting.value = false;
188
- cancelSubmit();
189
- cancelLazyLoad();
190
- data.value = null;
191
- error.value = null;
192
- loading.value = false;
193
- }
194
- __name(reset, "reset");
195
- function getFieldProps(fieldName) {
196
204
  return {
197
- value: values.value[fieldName] || "",
198
- "r-input": (e) => handleChange(fieldName, e.target.value),
199
- "r-blur": () => handleBlur(fieldName)
205
+ LazyComponentWrapper,
206
+ values,
207
+ errors,
208
+ touched,
209
+ isSubmitting,
210
+ isValid,
211
+ data,
212
+ error,
213
+ loading,
214
+ handleChange,
215
+ handleBlur,
216
+ handleSubmit,
217
+ cancelSubmit,
218
+ reset,
219
+ getFieldProps,
200
220
  };
201
- }
202
- __name(getFieldProps, "getFieldProps");
203
- return {
204
- LazyComponentWrapper,
205
- values,
206
- errors,
207
- touched,
208
- isSubmitting,
209
- isValid,
210
- data,
211
- error,
212
- loading,
213
- handleChange,
214
- handleBlur,
215
- handleSubmit,
216
- cancelSubmit,
217
- reset,
218
- getFieldProps
219
- };
220
221
  }
221
- __name(nixLazyFormAsync, "nixLazyFormAsync");
222
- export {
223
- nixLazyFormAsync
224
- };
225
- //# sourceMappingURL=nixLazyFormAsync.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../hooks/nixLazyFormAsync.js"],
4
- "sourcesContent": ["// core/hooks/nixLazyFormAsync.js\r\nimport { nixState } from \"./nixState.js\";\r\nimport { nixComputed } from \"./nixComputed.js\";\r\nimport { activeContext } from \"../context/context.js\";\r\n\r\n/**\r\n * Lazy-load a form component and manage its state with debounced async submissions.\r\n *\r\n * @param {() => Promise<any>} importFn - Function returning a dynamic import of the form component.\r\n * @param {Object} [formOptions={}] - Initial values and validation rules.\r\n * @param {Object} [formOptions.initialValues={}] - Initial field values.\r\n * @param {Object} [formOptions.validationRules={}] - Validation rules per field.\r\n * @param {Object} [submitOptions={}] - Debounce and async submission options.\r\n * @param {number} [submitOptions.delay=300] - Debounce delay.\r\n * @param {boolean} [submitOptions.leading=false] - Invoke submit on leading edge.\r\n * @param {boolean} [submitOptions.trailing=true] - Invoke submit on trailing edge.\r\n * @param {number} [submitOptions.maxWait] - Max wait before forced submission.\r\n * @param {boolean} [submitOptions.cache=true] - Cache last submission result.\r\n * @param {Object} [lazyOptions={}] - Options for lazy-loaded component import.\r\n * @param {number} [lazyOptions.retry=0] - Retry count for lazy-loaded component import.\r\n * @returns {Object} Lazy-loaded form component and reactive form API.\r\n */\r\nexport function nixLazyFormAsync(\r\n importFn,\r\n formOptions = {},\r\n submitOptions = {},\r\n lazyOptions = {}\r\n) {\r\n const { initialValues = {}, validationRules = {} } = formOptions;\r\n const { retry = 0 } = lazyOptions;\r\n const { delay = 300, leading = false, trailing = true, maxWait, cache = true } =\r\n submitOptions;\r\n\r\n /** ---------------- Lazy-load Component ---------------- */\r\n const lazyCache = {\r\n status: \"pending\",\r\n component: null,\r\n error: null,\r\n promise: null,\r\n retriesLeft: retry,\r\n };\r\n\r\n let lazyAbortController = new AbortController();\r\n let lazyCanceled = false;\r\n\r\n const loadLazy = () => {\r\n lazyCache.promise = importFn()\r\n .then((module) => {\r\n if (!lazyCanceled) {\r\n lazyCache.status = \"success\";\r\n lazyCache.component = module.default || module;\r\n }\r\n })\r\n .catch((err) => {\r\n if (!lazyCanceled) {\r\n if (lazyCache.retriesLeft > 0) {\r\n lazyCache.retriesLeft--;\r\n return loadLazy();\r\n }\r\n lazyCache.status = \"error\";\r\n lazyCache.error = err;\r\n }\r\n });\r\n\r\n return lazyCache.promise;\r\n };\r\n\r\n loadLazy();\r\n\r\n const cancelLazyLoad = () => {\r\n lazyCanceled = true;\r\n lazyAbortController.abort();\r\n lazyAbortController = null;\r\n };\r\n\r\n const LazyComponentWrapper = (props) => {\r\n const ctx = activeContext;\r\n if (!ctx) throw new Error(\"nixLazyFormAsync: called outside component\");\r\n\r\n if (lazyCache.status === \"pending\") throw lazyCache.promise;\r\n if (lazyCache.status === \"error\") throw lazyCache.error;\r\n\r\n return lazyCache.component(props);\r\n };\r\n\r\n /** ---------------- Form State ---------------- */\r\n const values = nixState({ ...initialValues });\r\n const errors = nixState({});\r\n const touched = nixState({});\r\n const isSubmitting = nixState(false);\r\n const isValid = nixComputed(() => Object.keys(errors.value).length === 0);\r\n\r\n /** Async submit state */\r\n const data = nixState(null);\r\n const error = nixState(null);\r\n const loading = nixState(false);\r\n\r\n let abortController = null;\r\n let timerId = null;\r\n let lastInvokeTime = 0;\r\n let lastResult = null;\r\n let lastError = null;\r\n let pendingPromise = null;\r\n\r\n /** ---------------- Form Validation ---------------- */\r\n function validate(fieldName, value) {\r\n const rules = validationRules[fieldName];\r\n if (!rules) return null;\r\n\r\n if (rules.required && !value) return rules.message || `${fieldName} is required`;\r\n if (rules.minLength && value.length < rules.minLength)\r\n return rules.message || `${fieldName} must be at least ${rules.minLength} characters`;\r\n if (rules.maxLength && value.length > rules.maxLength)\r\n return rules.message || `${fieldName} must be at most ${rules.maxLength} characters`;\r\n if (rules.pattern && !rules.pattern.test(value))\r\n return rules.message || `${fieldName} is invalid`;\r\n if (rules.custom && !rules.custom(value, values.value))\r\n return rules.message || `${fieldName} is invalid`;\r\n\r\n return null;\r\n }\r\n\r\n function handleChange(fieldName, value) {\r\n values.value = { ...values.value, [fieldName]: value };\r\n\r\n if (touched.value[fieldName]) {\r\n const err = validate(fieldName, value);\r\n if (err) errors.value = { ...errors.value, [fieldName]: err };\r\n else {\r\n const newErrors = { ...errors.value };\r\n delete newErrors[fieldName];\r\n errors.value = newErrors;\r\n }\r\n }\r\n }\r\n\r\n function handleBlur(fieldName) {\r\n touched.value = { ...touched.value, [fieldName]: true };\r\n const err = validate(fieldName, values.value[fieldName]);\r\n if (err) errors.value = { ...errors.value, [fieldName]: err };\r\n }\r\n\r\n function validateAll() {\r\n const newErrors = {};\r\n Object.keys(validationRules).forEach((fieldName) => {\r\n const err = validate(fieldName, values.value[fieldName]);\r\n if (err) newErrors[fieldName] = err;\r\n });\r\n errors.value = newErrors;\r\n return Object.keys(newErrors).length === 0;\r\n }\r\n\r\n /** ---------------- Debounced Async Submit ---------------- */\r\n async function invokeAsync(onSubmit) {\r\n if (cache && lastResult !== null) {\r\n data.value = lastResult;\r\n error.value = lastError;\r\n loading.value = false;\r\n return lastResult;\r\n }\r\n\r\n if (abortController) abortController.abort();\r\n abortController = new AbortController();\r\n const signal = abortController.signal;\r\n\r\n loading.value = true;\r\n error.value = null;\r\n\r\n pendingPromise = onSubmit(values.value, signal);\r\n\r\n try {\r\n const result = await pendingPromise;\r\n lastResult = result;\r\n data.value = result;\r\n return result;\r\n } catch (err) {\r\n if (err.name !== \"AbortError\") {\r\n lastError = err;\r\n error.value = err;\r\n }\r\n throw err;\r\n } finally {\r\n loading.value = false;\r\n pendingPromise = null;\r\n lastInvokeTime = Date.now();\r\n }\r\n }\r\n\r\n function handleSubmit(onSubmit) {\r\n if (!validateAll()) return;\r\n\r\n const now = Date.now();\r\n const timeSinceLastInvoke = now - lastInvokeTime;\r\n const remainingTime = delay - timeSinceLastInvoke;\r\n const shouldInvokeLeading = leading && !timerId;\r\n\r\n if (maxWait !== undefined && timeSinceLastInvoke >= maxWait) {\r\n if (timerId) clearTimeout(timerId);\r\n timerId = null;\r\n return invokeAsync(onSubmit);\r\n }\r\n\r\n if (timerId) clearTimeout(timerId);\r\n\r\n if (shouldInvokeLeading) return invokeAsync(onSubmit);\r\n\r\n if (trailing) {\r\n timerId = setTimeout(() => {\r\n timerId = null;\r\n invokeAsync(onSubmit);\r\n }, remainingTime > 0 ? remainingTime : delay);\r\n }\r\n }\r\n\r\n /** Cancel pending submit */\r\n function cancelSubmit() {\r\n if (abortController) {\r\n abortController.abort();\r\n abortController = null;\r\n }\r\n if (timerId) clearTimeout(timerId);\r\n timerId = null;\r\n }\r\n\r\n /** Reset form and cancel pending submit and lazy load */\r\n function reset() {\r\n values.value = { ...initialValues };\r\n errors.value = {};\r\n touched.value = {};\r\n isSubmitting.value = false;\r\n cancelSubmit();\r\n cancelLazyLoad();\r\n data.value = null;\r\n error.value = null;\r\n loading.value = false;\r\n }\r\n\r\n function getFieldProps(fieldName) {\r\n return {\r\n value: values.value[fieldName] || \"\",\r\n \"r-input\": (e) => handleChange(fieldName, e.target.value),\r\n \"r-blur\": () => handleBlur(fieldName),\r\n };\r\n }\r\n\r\n return {\r\n LazyComponentWrapper,\r\n values,\r\n errors,\r\n touched,\r\n isSubmitting,\r\n isValid,\r\n data,\r\n error,\r\n loading,\r\n handleChange,\r\n handleBlur,\r\n handleSubmit,\r\n cancelSubmit,\r\n reset,\r\n getFieldProps,\r\n };\r\n}\r\n"],
5
- "mappings": ";;AACA,SAAS,gBAAgB;AACzB,SAAS,mBAAmB;AAC5B,SAAS,qBAAqB;AAmBvB,SAAS,iBACd,UACA,cAAc,CAAC,GACf,gBAAgB,CAAC,GACjB,cAAc,CAAC,GACf;AACA,QAAM,EAAE,gBAAgB,CAAC,GAAG,kBAAkB,CAAC,EAAE,IAAI;AACrD,QAAM,EAAE,QAAQ,EAAE,IAAI;AACtB,QAAM,EAAE,QAAQ,KAAK,UAAU,OAAO,WAAW,MAAM,SAAS,QAAQ,KAAK,IAC3E;AAGF,QAAM,YAAY;AAAA,IAChB,QAAQ;AAAA,IACR,WAAW;AAAA,IACX,OAAO;AAAA,IACP,SAAS;AAAA,IACT,aAAa;AAAA,EACf;AAEA,MAAI,sBAAsB,IAAI,gBAAgB;AAC9C,MAAI,eAAe;AAEnB,QAAM,WAAW,6BAAM;AACrB,cAAU,UAAU,SAAS,EAC1B,KAAK,CAAC,WAAW;AAChB,UAAI,CAAC,cAAc;AACjB,kBAAU,SAAS;AACnB,kBAAU,YAAY,OAAO,WAAW;AAAA,MAC1C;AAAA,IACF,CAAC,EACA,MAAM,CAAC,QAAQ;AACd,UAAI,CAAC,cAAc;AACjB,YAAI,UAAU,cAAc,GAAG;AAC7B,oBAAU;AACV,iBAAO,SAAS;AAAA,QAClB;AACA,kBAAU,SAAS;AACnB,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF,CAAC;AAEH,WAAO,UAAU;AAAA,EACnB,GApBiB;AAsBjB,WAAS;AAET,QAAM,iBAAiB,6BAAM;AAC3B,mBAAe;AACf,wBAAoB,MAAM;AAC1B,0BAAsB;AAAA,EACxB,GAJuB;AAMvB,QAAM,uBAAuB,wBAAC,UAAU;AACtC,UAAM,MAAM;AACZ,QAAI,CAAC;AAAK,YAAM,IAAI,MAAM,4CAA4C;AAEtE,QAAI,UAAU,WAAW;AAAW,YAAM,UAAU;AACpD,QAAI,UAAU,WAAW;AAAS,YAAM,UAAU;AAElD,WAAO,UAAU,UAAU,KAAK;AAAA,EAClC,GAR6B;AAW7B,QAAM,SAAS,SAAS,EAAE,GAAG,cAAc,CAAC;AAC5C,QAAM,SAAS,SAAS,CAAC,CAAC;AAC1B,QAAM,UAAU,SAAS,CAAC,CAAC;AAC3B,QAAM,eAAe,SAAS,KAAK;AACnC,QAAM,UAAU,YAAY,MAAM,OAAO,KAAK,OAAO,KAAK,EAAE,WAAW,CAAC;AAGxE,QAAM,OAAO,SAAS,IAAI;AAC1B,QAAM,QAAQ,SAAS,IAAI;AAC3B,QAAM,UAAU,SAAS,KAAK;AAE9B,MAAI,kBAAkB;AACtB,MAAI,UAAU;AACd,MAAI,iBAAiB;AACrB,MAAI,aAAa;AACjB,MAAI,YAAY;AAChB,MAAI,iBAAiB;AAGrB,WAAS,SAAS,WAAW,OAAO;AAClC,UAAM,QAAQ,gBAAgB,SAAS;AACvC,QAAI,CAAC;AAAO,aAAO;AAEnB,QAAI,MAAM,YAAY,CAAC;AAAO,aAAO,MAAM,WAAW,GAAG,SAAS;AAClE,QAAI,MAAM,aAAa,MAAM,SAAS,MAAM;AAC1C,aAAO,MAAM,WAAW,GAAG,SAAS,qBAAqB,MAAM,SAAS;AAC1E,QAAI,MAAM,aAAa,MAAM,SAAS,MAAM;AAC1C,aAAO,MAAM,WAAW,GAAG,SAAS,oBAAoB,MAAM,SAAS;AACzE,QAAI,MAAM,WAAW,CAAC,MAAM,QAAQ,KAAK,KAAK;AAC5C,aAAO,MAAM,WAAW,GAAG,SAAS;AACtC,QAAI,MAAM,UAAU,CAAC,MAAM,OAAO,OAAO,OAAO,KAAK;AACnD,aAAO,MAAM,WAAW,GAAG,SAAS;AAEtC,WAAO;AAAA,EACT;AAfS;AAiBT,WAAS,aAAa,WAAW,OAAO;AACtC,WAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,SAAS,GAAG,MAAM;AAErD,QAAI,QAAQ,MAAM,SAAS,GAAG;AAC5B,YAAM,MAAM,SAAS,WAAW,KAAK;AACrC,UAAI;AAAK,eAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,SAAS,GAAG,IAAI;AAAA,WACvD;AACH,cAAM,YAAY,EAAE,GAAG,OAAO,MAAM;AACpC,eAAO,UAAU,SAAS;AAC1B,eAAO,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAZS;AAcT,WAAS,WAAW,WAAW;AAC7B,YAAQ,QAAQ,EAAE,GAAG,QAAQ,OAAO,CAAC,SAAS,GAAG,KAAK;AACtD,UAAM,MAAM,SAAS,WAAW,OAAO,MAAM,SAAS,CAAC;AACvD,QAAI;AAAK,aAAO,QAAQ,EAAE,GAAG,OAAO,OAAO,CAAC,SAAS,GAAG,IAAI;AAAA,EAC9D;AAJS;AAMT,WAAS,cAAc;AACrB,UAAM,YAAY,CAAC;AACnB,WAAO,KAAK,eAAe,EAAE,QAAQ,CAAC,cAAc;AAClD,YAAM,MAAM,SAAS,WAAW,OAAO,MAAM,SAAS,CAAC;AACvD,UAAI;AAAK,kBAAU,SAAS,IAAI;AAAA,IAClC,CAAC;AACD,WAAO,QAAQ;AACf,WAAO,OAAO,KAAK,SAAS,EAAE,WAAW;AAAA,EAC3C;AARS;AAWT,iBAAe,YAAY,UAAU;AACnC,QAAI,SAAS,eAAe,MAAM;AAChC,WAAK,QAAQ;AACb,YAAM,QAAQ;AACd,cAAQ,QAAQ;AAChB,aAAO;AAAA,IACT;AAEA,QAAI;AAAiB,sBAAgB,MAAM;AAC3C,sBAAkB,IAAI,gBAAgB;AACtC,UAAM,SAAS,gBAAgB;AAE/B,YAAQ,QAAQ;AAChB,UAAM,QAAQ;AAEd,qBAAiB,SAAS,OAAO,OAAO,MAAM;AAE9C,QAAI;AACF,YAAM,SAAS,MAAM;AACrB,mBAAa;AACb,WAAK,QAAQ;AACb,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,UAAI,IAAI,SAAS,cAAc;AAC7B,oBAAY;AACZ,cAAM,QAAQ;AAAA,MAChB;AACA,YAAM;AAAA,IACR,UAAE;AACA,cAAQ,QAAQ;AAChB,uBAAiB;AACjB,uBAAiB,KAAK,IAAI;AAAA,IAC5B;AAAA,EACF;AAjCe;AAmCf,WAAS,aAAa,UAAU;AAC9B,QAAI,CAAC,YAAY;AAAG;AAEpB,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,sBAAsB,MAAM;AAClC,UAAM,gBAAgB,QAAQ;AAC9B,UAAM,sBAAsB,WAAW,CAAC;AAExC,QAAI,YAAY,UAAa,uBAAuB,SAAS;AAC3D,UAAI;AAAS,qBAAa,OAAO;AACjC,gBAAU;AACV,aAAO,YAAY,QAAQ;AAAA,IAC7B;AAEA,QAAI;AAAS,mBAAa,OAAO;AAEjC,QAAI;AAAqB,aAAO,YAAY,QAAQ;AAEpD,QAAI,UAAU;AACZ,gBAAU,WAAW,MAAM;AACzB,kBAAU;AACV,oBAAY,QAAQ;AAAA,MACtB,GAAG,gBAAgB,IAAI,gBAAgB,KAAK;AAAA,IAC9C;AAAA,EACF;AAxBS;AA2BT,WAAS,eAAe;AACtB,QAAI,iBAAiB;AACnB,sBAAgB,MAAM;AACtB,wBAAkB;AAAA,IACpB;AACA,QAAI;AAAS,mBAAa,OAAO;AACjC,cAAU;AAAA,EACZ;AAPS;AAUT,WAAS,QAAQ;AACf,WAAO,QAAQ,EAAE,GAAG,cAAc;AAClC,WAAO,QAAQ,CAAC;AAChB,YAAQ,QAAQ,CAAC;AACjB,iBAAa,QAAQ;AACrB,iBAAa;AACb,mBAAe;AACf,SAAK,QAAQ;AACb,UAAM,QAAQ;AACd,YAAQ,QAAQ;AAAA,EAClB;AAVS;AAYT,WAAS,cAAc,WAAW;AAChC,WAAO;AAAA,MACL,OAAO,OAAO,MAAM,SAAS,KAAK;AAAA,MAClC,WAAW,CAAC,MAAM,aAAa,WAAW,EAAE,OAAO,KAAK;AAAA,MACxD,UAAU,MAAM,WAAW,SAAS;AAAA,IACtC;AAAA,EACF;AANS;AAQT,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAhPgB;",
3
+ "sources": ["../../hooks/nixLazyFormAsync.ts"],
4
+ "sourcesContent": ["/* MIT License\r\n\r\n* Copyright (c) 2026 Resty Gonzales\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n* SOFTWARE.\r\n */\r\n// core/hooks/nixLazyFormAsync.js\r\nimport { activeContext } from \"../context/context.js\";\r\nimport { nixComputed } from \"./nixComputed.js\";\r\nimport { nixState } from \"./nixState.js\";\r\n\r\n/**\r\n * Lazy-load a form component and manage its state with debounced async submissions.\r\n *\r\n * @param {() => Promise<any>} importFn - Function returning a dynamic import of the form component.\r\n * @param {Object} [formOptions={}] - Initial values and validation rules.\r\n * @param {Object} [formOptions.initialValues={}] - Initial field values.\r\n * @param {Object} [formOptions.validationRules={}] - Validation rules per field.\r\n * @param {Object} [submitOptions={}] - Debounce and async submission options.\r\n * @param {number} [submitOptions.delay=300] - Debounce delay.\r\n * @param {boolean} [submitOptions.leading=false] - Invoke submit on leading edge.\r\n * @param {boolean} [submitOptions.trailing=true] - Invoke submit on trailing edge.\r\n * @param {number} [submitOptions.maxWait] - Max wait before forced submission.\r\n * @param {boolean} [submitOptions.cache=true] - Cache last submission result.\r\n * @param {Object} [lazyOptions={}] - Options for lazy-loaded component import.\r\n * @param {number} [lazyOptions.retry=0] - Retry count for lazy-loaded component import.\r\n * @returns {Object} Lazy-loaded form component and reactive form API.\r\n */\r\ntype ValidationRule<T> = {\r\n required?: boolean;\r\n minLength?: number;\r\n maxLength?: number;\r\n pattern?: RegExp;\r\n custom?: (value: any, values: T) => boolean;\r\n message?: string;\r\n};\r\n\r\ntype ValidationRules<T> = {\r\n [K in keyof T]?: ValidationRule<T>;\r\n};\r\n\r\ntype LazyFormAsyncReturn<T, D = any, E = any, P = any> = {\r\n LazyComponentWrapper: (props: P) => any;\r\n values: ReturnType<typeof nixState<T>>;\r\n errors: ReturnType<typeof nixState<Partial<Record<keyof T, string>>>>;\r\n touched: ReturnType<typeof nixState<Partial<Record<keyof T, boolean>>>>;\r\n isSubmitting: ReturnType<typeof nixState<boolean>>;\r\n isValid: ReturnType<typeof nixComputed<boolean>>;\r\n data: ReturnType<typeof nixState<D | null>>;\r\n error: ReturnType<typeof nixState<E | null>>;\r\n loading: ReturnType<typeof nixState<boolean>>;\r\n handleChange: (fieldName: keyof T, value: any) => void;\r\n handleBlur: (fieldName: keyof T) => void;\r\n handleSubmit: (\r\n onSubmit: (values: T, signal: AbortSignal) => Promise<D>\r\n ) => void;\r\n cancelSubmit: () => void;\r\n reset: () => void;\r\n getFieldProps: (fieldName: keyof T) => {\r\n value: any;\r\n \"r-input\": (e: any) => void;\r\n \"r-blur\": () => void;\r\n };\r\n};\r\n\r\nexport function nixLazyFormAsync<\r\n T extends Record<string, any> = Record<string, any>,\r\n D = any,\r\n E = any,\r\n P = any,\r\n>(\r\n importFn: () => Promise<\r\n { default?: (props: P) => any } | ((props: P) => any)\r\n >,\r\n formOptions: { initialValues?: T; validationRules?: ValidationRules<T> } = {},\r\n submitOptions: {\r\n delay?: number;\r\n leading?: boolean;\r\n trailing?: boolean;\r\n maxWait?: number;\r\n cache?: boolean;\r\n } = {},\r\n lazyOptions: { retry?: number } = {}\r\n): LazyFormAsyncReturn<T, D, E, P> {\r\n const {\r\n initialValues = {} as T,\r\n validationRules = {} as ValidationRules<T>,\r\n } = formOptions;\r\n const { retry = 0 } = lazyOptions;\r\n const {\r\n delay = 300,\r\n leading = false,\r\n trailing = true,\r\n maxWait,\r\n cache = true,\r\n } = submitOptions;\r\n\r\n type LazyCache = {\r\n status: \"pending\" | \"success\" | \"error\";\r\n component: ((props: P) => any) | null;\r\n error: any;\r\n promise: Promise<any> | null;\r\n retriesLeft: number;\r\n };\r\n const lazyCache: LazyCache = {\r\n status: \"pending\",\r\n component: null,\r\n error: null,\r\n promise: null,\r\n retriesLeft: retry,\r\n };\r\n\r\n let lazyAbortController: AbortController | null = new AbortController();\r\n let lazyCanceled = false;\r\n\r\n const loadLazy = (): Promise<any> => {\r\n lazyCache.promise = importFn()\r\n .then((module) => {\r\n if (!lazyCanceled) {\r\n lazyCache.status = \"success\";\r\n lazyCache.component = (module as any).default || module;\r\n }\r\n })\r\n .catch((err) => {\r\n if (!lazyCanceled) {\r\n if (lazyCache.retriesLeft > 0) {\r\n lazyCache.retriesLeft--;\r\n return loadLazy();\r\n }\r\n lazyCache.status = \"error\";\r\n lazyCache.error = err;\r\n }\r\n return Promise.reject(err);\r\n });\r\n return lazyCache.promise;\r\n };\r\n\r\n loadLazy();\r\n\r\n const cancelLazyLoad = (): void => {\r\n lazyCanceled = true;\r\n if (lazyAbortController) {\r\n lazyAbortController.abort();\r\n lazyAbortController = null;\r\n }\r\n };\r\n\r\n const LazyComponentWrapper = (props: P): any => {\r\n const ctx = activeContext;\r\n if (!ctx) throw new Error(\"nixLazyFormAsync: called outside component\");\r\n if (lazyCache.status === \"pending\") throw lazyCache.promise;\r\n if (lazyCache.status === \"error\") throw lazyCache.error;\r\n return lazyCache.component!(props);\r\n };\r\n\r\n /** ---------------- Form State ---------------- */\r\n const values = nixState({ ...initialValues });\r\n const errors = nixState<Partial<Record<keyof T, string>>>({});\r\n const touched = nixState<Partial<Record<keyof T, boolean>>>({});\r\n const isSubmitting = nixState(false);\r\n const isValid = nixComputed(() => Object.keys(errors.value).length === 0);\r\n\r\n /** Async submit state */\r\n const data = nixState<D | null>(null);\r\n const error = nixState<E | null>(null);\r\n const loading = nixState(false);\r\n\r\n let abortController: AbortController | null = null;\r\n let timerId: ReturnType<typeof setTimeout> | null = null;\r\n let lastInvokeTime = 0;\r\n let lastResult: D | null = null;\r\n let lastError: E | null = null;\r\n let pendingPromise: Promise<D> | null = null;\r\n\r\n /** ---------------- Form Validation ---------------- */\r\n\r\n function validate(fieldName: keyof T, value: any): string | null {\r\n const rules = validationRules[fieldName];\r\n if (!rules) return null;\r\n\r\n if (rules.required && !value)\r\n return rules.message || `${String(fieldName)} is required`;\r\n if (rules.minLength && value.length < rules.minLength)\r\n return (\r\n rules.message ||\r\n `${String(fieldName)} must be at least ${rules.minLength} characters`\r\n );\r\n if (rules.maxLength && value.length > rules.maxLength)\r\n return (\r\n rules.message ||\r\n `${String(fieldName)} must be at most ${rules.maxLength} characters`\r\n );\r\n if (rules.pattern && !rules.pattern.test(value))\r\n return rules.message || `${String(fieldName)} is invalid`;\r\n if (rules.custom && !rules.custom(value, values.value))\r\n return rules.message || `${String(fieldName)} is invalid`;\r\n\r\n return null;\r\n }\r\n\r\n function handleChange(fieldName: keyof T, value: any): void {\r\n values.value = { ...values.value, [fieldName]: value };\r\n\r\n if ((touched.value as Partial<Record<keyof T, boolean>>)[fieldName]) {\r\n const err = validate(fieldName, value);\r\n if (err) errors.value = { ...errors.value, [fieldName]: err };\r\n else {\r\n const newErrors = { ...errors.value };\r\n delete newErrors[fieldName];\r\n errors.value = newErrors;\r\n }\r\n }\r\n }\r\n\r\n function handleBlur(fieldName: keyof T): void {\r\n touched.value = { ...touched.value, [fieldName]: true };\r\n const err = validate(fieldName, values.value[fieldName]);\r\n if (err) errors.value = { ...errors.value, [fieldName]: err };\r\n }\r\n\r\n function validateAll(): boolean {\r\n const newErrors: Partial<Record<keyof T, string>> = {};\r\n (Object.keys(validationRules) as Array<keyof T>).forEach((fieldName) => {\r\n const err = validate(fieldName, values.value[fieldName]);\r\n if (err) newErrors[fieldName] = err;\r\n });\r\n errors.value = newErrors;\r\n return Object.keys(newErrors).length === 0;\r\n }\r\n\r\n /** ---------------- Debounced Async Submit ---------------- */\r\n\r\n async function invokeAsync(\r\n onSubmit: (values: T, signal: AbortSignal) => Promise<D>\r\n ): Promise<D | undefined> {\r\n // Use cache if enabled and lastResult exists\r\n if (cache && lastResult !== null) {\r\n data.value = lastResult ?? null;\r\n error.value = lastError ?? null;\r\n loading.value = false;\r\n return lastResult;\r\n }\r\n\r\n if (abortController) abortController.abort();\r\n abortController = new AbortController();\r\n const signal = abortController.signal;\r\n\r\n loading.value = true;\r\n error.value = null;\r\n\r\n pendingPromise = onSubmit(values.value, signal);\r\n\r\n try {\r\n const result = await pendingPromise;\r\n lastResult = result;\r\n data.value = result ?? null;\r\n return result;\r\n } catch (err: any) {\r\n if (err.name !== \"AbortError\") {\r\n lastError = err;\r\n error.value = err;\r\n }\r\n throw err;\r\n } finally {\r\n loading.value = false;\r\n pendingPromise = null;\r\n lastInvokeTime = Date.now();\r\n }\r\n }\r\n\r\n function handleSubmit(\r\n onSubmit: (values: T, signal: AbortSignal) => Promise<D>\r\n ): void {\r\n if (!validateAll()) return;\r\n\r\n const now = Date.now();\r\n const timeSinceLastInvoke = now - lastInvokeTime;\r\n const remainingTime = delay - timeSinceLastInvoke;\r\n const shouldInvokeLeading = leading && !timerId;\r\n\r\n if (maxWait !== undefined && timeSinceLastInvoke >= maxWait) {\r\n if (timerId) clearTimeout(timerId);\r\n timerId = null;\r\n void invokeAsync(onSubmit);\r\n return;\r\n }\r\n\r\n if (timerId) clearTimeout(timerId);\r\n\r\n if (shouldInvokeLeading) {\r\n void invokeAsync(onSubmit);\r\n return;\r\n }\r\n\r\n if (trailing) {\r\n timerId = setTimeout(\r\n () => {\r\n timerId = null;\r\n void invokeAsync(onSubmit);\r\n },\r\n remainingTime > 0 ? remainingTime : delay\r\n );\r\n }\r\n }\r\n\r\n /** Cancel pending submit */\r\n\r\n function cancelSubmit(): void {\r\n if (abortController) {\r\n abortController.abort();\r\n abortController = null;\r\n }\r\n if (timerId) clearTimeout(timerId);\r\n timerId = null;\r\n }\r\n\r\n function reset(): void {\r\n values.value = { ...initialValues };\r\n errors.value = {};\r\n touched.value = {};\r\n isSubmitting.value = false;\r\n cancelSubmit();\r\n cancelLazyLoad();\r\n data.value = null;\r\n error.value = null;\r\n loading.value = false;\r\n }\r\n\r\n function getFieldProps(fieldName: keyof T) {\r\n return {\r\n value: values.value[fieldName] || \"\",\r\n \"r-input\": (e: any) => handleChange(fieldName, e.target.value),\r\n \"r-blur\": () => handleBlur(fieldName),\r\n };\r\n }\r\n\r\n return {\r\n LazyComponentWrapper,\r\n values,\r\n errors,\r\n touched,\r\n isSubmitting,\r\n isValid,\r\n data,\r\n error,\r\n loading,\r\n handleChange,\r\n handleBlur,\r\n handleSubmit,\r\n cancelSubmit,\r\n reset,\r\n getFieldProps,\r\n };\r\n}\r\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,5 @@
1
+ export declare function nixLocalStorage<T>(key: string, initial: T): {
2
+ value: T;
3
+ set: (v: T) => void;
4
+ };
5
+ //# sourceMappingURL=nixLocalStorage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nixLocalStorage.d.ts","sourceRoot":"","sources":["../../hooks/nixLocalStorage.ts"],"names":[],"mappings":"AA+CA,wBAAgB,eAAe,CAAC,CAAC,EAC/B,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,GACT;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,GAAG,EAAE,CAAC,CAAC,EAAE,CAAC,KAAK,IAAI,CAAA;CAAE,CAsBnC"}
@@ -1,30 +1,26 @@
1
- var __defProp = Object.defineProperty;
2
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
1
  import { nixState } from "./nixState";
4
- function nixLocalStorage(key, initial) {
5
- const s = nixState(() => {
2
+ export function nixLocalStorage(key, initial) {
3
+ let initialValue;
6
4
  try {
7
- const v = localStorage.getItem(key);
8
- if (v != null)
9
- return JSON.parse(v);
10
- return initial;
11
- } catch (err) {
12
- console.error(`[nixLocalStorage] Error reading key "${key}":`, err);
13
- return initial;
5
+ const v = localStorage.getItem(key);
6
+ if (v != null)
7
+ initialValue = JSON.parse(v);
8
+ else
9
+ initialValue = initial;
14
10
  }
15
- });
16
- const set = /* @__PURE__ */ __name((v) => {
17
- s.value = v;
18
- try {
19
- localStorage.setItem(key, JSON.stringify(v));
20
- } catch (err) {
21
- console.error(`[nixLocalStorage] Error setting key "${key}":`, err);
11
+ catch (err) {
12
+ console.error(`[nixLocalStorage] Error reading key "${key}":`, err);
13
+ initialValue = initial;
22
14
  }
23
- }, "set");
24
- return { value: s.value, set };
15
+ const s = nixState(initialValue);
16
+ const set = (v) => {
17
+ s.value = v;
18
+ try {
19
+ localStorage.setItem(key, JSON.stringify(v));
20
+ }
21
+ catch (err) {
22
+ console.error(`[nixLocalStorage] Error setting key "${key}":`, err);
23
+ }
24
+ };
25
+ return { value: s.value, set };
25
26
  }
26
- __name(nixLocalStorage, "nixLocalStorage");
27
- export {
28
- nixLocalStorage
29
- };
30
- //# sourceMappingURL=nixLocalStorage.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../../hooks/nixLocalStorage.js"],
4
- "sourcesContent": ["/**\r\n * @fileoverview Reactive localStorage hook for Fynix.\r\n * Automatically syncs state with localStorage using JSON serialization.\r\n */\r\n\r\nimport { nixState } from \"./nixState\";\r\n\r\n/**\r\n * Reactive wrapper around localStorage with safe JSON parsing/stringifying.\r\n * Automatically persists state changes to localStorage.\r\n *\r\n * @template T\r\n * @param {string} key - LocalStorage key\r\n * @param {T} initial - Initial value if key does not exist\r\n * @returns {{ value: T, set: (v: T) => void }} Object with value getter and setter\r\n * \r\n * @example\r\n * const theme = nixLocalStorage('theme', 'light');\r\n * console.log(theme.value); // 'light' or stored value\r\n * theme.set('dark'); // Updates state and localStorage\r\n * \r\n * @example\r\n * const user = nixLocalStorage('user', { name: '', age: 0 });\r\n * user.set({ name: 'John', age: 30 });\r\n */\r\nexport function nixLocalStorage(key, initial) {\r\n const s = nixState(() => {\r\n try {\r\n const v = localStorage.getItem(key);\r\n if (v != null) return JSON.parse(v);\r\n return initial;\r\n } catch (err) {\r\n console.error(`[nixLocalStorage] Error reading key \"${key}\":`, err);\r\n return initial;\r\n }\r\n });\r\n\r\n const set = (v) => {\r\n s.value = v;\r\n try {\r\n localStorage.setItem(key, JSON.stringify(v));\r\n } catch (err) {\r\n console.error(`[nixLocalStorage] Error setting key \"${key}\":`, err);\r\n }\r\n };\r\n\r\n return { value: s.value, set };\r\n}\r\n"],
5
- "mappings": ";;AAKA,SAAS,gBAAgB;AAoBlB,SAAS,gBAAgB,KAAK,SAAS;AAC5C,QAAM,IAAI,SAAS,MAAM;AACvB,QAAI;AACF,YAAM,IAAI,aAAa,QAAQ,GAAG;AAClC,UAAI,KAAK;AAAM,eAAO,KAAK,MAAM,CAAC;AAClC,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,cAAQ,MAAM,wCAAwC,GAAG,MAAM,GAAG;AAClE,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AAED,QAAM,MAAM,wBAAC,MAAM;AACjB,MAAE,QAAQ;AACV,QAAI;AACF,mBAAa,QAAQ,KAAK,KAAK,UAAU,CAAC,CAAC;AAAA,IAC7C,SAAS,KAAK;AACZ,cAAQ,MAAM,wCAAwC,GAAG,MAAM,GAAG;AAAA,IACpE;AAAA,EACF,GAPY;AASZ,SAAO,EAAE,OAAO,EAAE,OAAO,IAAI;AAC/B;AAtBgB;",
3
+ "sources": ["../../hooks/nixLocalStorage.ts"],
4
+ "sourcesContent": ["/* MIT License\r\n\r\n* Copyright (c) 2026 Resty Gonzales\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\n* SOFTWARE.\r\n */\r\n/**\r\n * @fileoverview Reactive localStorage hook for Fynix.\r\n * Automatically syncs state with localStorage using JSON serialization.\r\n */\r\n\r\nimport { nixState } from \"./nixState\";\r\n\r\n/**\r\n * Reactive wrapper around localStorage with safe JSON parsing/stringifying.\r\n * Automatically persists state changes to localStorage.\r\n *\r\n * @template T\r\n * @param {string} key - LocalStorage key\r\n * @param {T} initial - Initial value if key does not exist\r\n * @returns {{ value: T, set: (v: T) => void }} Object with value getter and setter\r\n *\r\n * @example\r\n * const theme = nixLocalStorage('theme', 'light');\r\n * console.log(theme.value); // 'light' or stored value\r\n * theme.set('dark'); // Updates state and localStorage\r\n *\r\n * @example\r\n * const user = nixLocalStorage('user', { name: '', age: 0 });\r\n * user.set({ name: 'John', age: 30 });\r\n */\r\nexport function nixLocalStorage<T>(\r\n key: string,\r\n initial: T\r\n): { value: T; set: (v: T) => void } {\r\n let initialValue: T;\r\n try {\r\n const v = localStorage.getItem(key);\r\n if (v != null) initialValue = JSON.parse(v) as T;\r\n else initialValue = initial;\r\n } catch (err) {\r\n console.error(`[nixLocalStorage] Error reading key \"${key}\":`, err);\r\n initialValue = initial;\r\n }\r\n const s = nixState<T>(initialValue);\r\n\r\n const set = (v: T) => {\r\n s.value = v;\r\n try {\r\n localStorage.setItem(key, JSON.stringify(v));\r\n } catch (err) {\r\n console.error(`[nixLocalStorage] Error setting key \"${key}\":`, err);\r\n }\r\n };\r\n\r\n return { value: s.value, set };\r\n}\r\n"],
5
+ "mappings": ";;AA2BA,SAAS,gBAAgB;AAoBlB,SAAS,gBACd,KACA,SACmC;AACnC,MAAI;AACJ,MAAI;AACF,UAAM,IAAI,aAAa,QAAQ,GAAG;AAClC,QAAI,KAAK,KAAM,gBAAe,KAAK,MAAM,CAAC;AAAA,QACrC,gBAAe;AAAA,EACtB,SAAS,KAAK;AACZ,YAAQ,MAAM,wCAAwC,GAAG,MAAM,GAAG;AAClE,mBAAe;AAAA,EACjB;AACA,QAAM,IAAI,SAAY,YAAY;AAElC,QAAM,MAAM,wBAAC,MAAS;AACpB,MAAE,QAAQ;AACV,QAAI;AACF,mBAAa,QAAQ,KAAK,KAAK,UAAU,CAAC,CAAC;AAAA,IAC7C,SAAS,KAAK;AACZ,cAAQ,MAAM,wCAAwC,GAAG,MAAM,GAAG;AAAA,IACpE;AAAA,EACF,GAPY;AASZ,SAAO,EAAE,OAAO,EAAE,OAAO,IAAI;AAC/B;AAzBgB;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,2 @@
1
+ export declare function nixMemo<T>(factory: () => T, deps?: any[]): T | undefined;
2
+ //# sourceMappingURL=nixMemo.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nixMemo.d.ts","sourceRoot":"","sources":["../../hooks/nixMemo.ts"],"names":[],"mappings":"AA+BA,wBAAgB,OAAO,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,EAAE,IAAI,GAAE,GAAG,EAAO,GAAG,CAAC,GAAG,SAAS,CAuC5E"}