@lotics/ui 26.4.0 → 26.4.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/docs/catalog.md CHANGED
@@ -649,7 +649,9 @@ source (`src/<module>.tsx`/`.ts`) is the API reference.
649
649
  - **`use_form`** — `useForm`: THE batch draft-form state hook — `values` = `initialValues` +
650
650
  an edits overlay (a revalidation refreshes untouched fields, no sync effect), `validate`
651
651
  (sync/async, gates submit, editing clears the field's error), `onSubmit(values, helpers)`
652
- with a re-entry-guarded `submitting`, and `changes`/`changed` the touched-fields diff
652
+ with a re-entry-guarded `submitting` an error `onSubmit` reports itself via
653
+ `setFieldError` (a rejected write, say) SURVIVES, because each attempt clears the previous
654
+ attempt's errors on the way IN, not on the way out — and `changes`/`changed` — the touched-fields diff
653
655
  that feeds DIFF-writes (send only edited fields); `setFieldValue` (curried or direct) +
654
656
  `setValues`/`setFieldError`/`reset`. Pairs with the Form\* family for dialog/settings
655
657
  forms — the draft-validate-COMMIT-together twin of the self-persisting Inline\* editors.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lotics/ui",
3
- "version": "26.4.0",
3
+ "version": "26.4.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./vite": {
package/src/use_form.ts CHANGED
@@ -116,9 +116,14 @@ function reducer<T>(prevState: FormState<T>, action: Action<T>): FormState<T> {
116
116
  if (prevState.submitting === action.submitting) return prevState;
117
117
  return { ...prevState, submitting: action.submitting };
118
118
  case "SUBMIT":
119
+ // Deliberately does NOT clear errors. This fires after `onSubmit` returns,
120
+ // and a handler that caught a server rejection and called `setFieldError`
121
+ // returns normally — so wiping here erased the only report of the failure
122
+ // and the press looked like it did nothing. Nothing needs the wipe:
123
+ // editing a field clears that field's error, and a `validate` pass
124
+ // replaces the whole set.
119
125
  return {
120
126
  ...prevState,
121
- errors: {},
122
127
  submitting: false,
123
128
  submitCount: prevState.submitCount + 1,
124
129
  };
@@ -228,14 +233,14 @@ export function useForm<T>(props: UseFormProps<T>): FormHandler<T> {
228
233
  if (!onSubmit) return;
229
234
  if (submittingRef.current) return;
230
235
 
231
- if (validate !== undefined) {
232
- const nextErrors = await validate(values);
233
-
234
- if (nextErrors && Object.keys(nextErrors).length) {
235
- setErrors(nextErrors);
236
- return;
237
- }
238
- }
236
+ // The previous attempt's errors are cleared HERE, before this one runs —
237
+ // not after `onSubmit` returns. Clearing afterwards erased the very error a
238
+ // handler had just set from a rejected write, so the press looked like it
239
+ // did nothing; never clearing left that error on screen after a later
240
+ // attempt succeeded. Clearing up front does both jobs.
241
+ const nextErrors = validate ? ((await validate(values)) ?? {}) : {};
242
+ setErrors(nextErrors);
243
+ if (Object.keys(nextErrors).length) return;
239
244
 
240
245
  submittingRef.current = true;
241
246
  dispatch({ type: "SET_SUBMITTING", submitting: true });