formstand 0.18.0 → 0.19.0
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/CHANGELOG.md +20 -0
- package/dist/index.cjs +47 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +12 -3
- package/dist/index.d.ts +12 -3
- package/dist/index.js +47 -2
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.19.0 — 2026-09-17
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- **The React 19 form-actions bridge.** `useFormAction(form, onValid,
|
|
8
|
+
options?)` returns an action for `<form action={...}>` that validates
|
|
9
|
+
first and hands the handler parsed `z.output` data (plus the raw
|
|
10
|
+
`FormData` last, for file pickers and uncontrolled co-inputs) under
|
|
11
|
+
the full submit lifecycle — isSubmitting/submitCount, errors written
|
|
12
|
+
and marked touched on failure, `onInvalid`/`onError` mirroring
|
|
13
|
+
`handleSubmit`, the same dev warning when a failure resolves
|
|
14
|
+
unobserved, and a reference-stable identity. `useFormActionState(form,
|
|
15
|
+
action, initialState, options?)` is `useActionState` with
|
|
16
|
+
schema-validated data: the handler's `(prevState, data, formData)`
|
|
17
|
+
shape lets a `"use server"` function slot straight in, and invalid,
|
|
18
|
+
skipped, or throwing submissions keep the previous state, because
|
|
19
|
+
field errors already live in the form store. Client-side integration
|
|
20
|
+
by design: no-JS progressive enhancement bypasses any client wrapper,
|
|
21
|
+
so that path validates server-side with the same zod schema.
|
|
22
|
+
|
|
3
23
|
## 0.18.0 — 2026-09-17
|
|
4
24
|
|
|
5
25
|
### Changed
|
package/dist/index.cjs
CHANGED
|
@@ -1317,6 +1317,51 @@ var useForm = (schema, options) => {
|
|
|
1317
1317
|
}, [form, schema, options.initialValues]);
|
|
1318
1318
|
return form;
|
|
1319
1319
|
};
|
|
1320
|
+
var warnUnobserved = (result, options, site) => {
|
|
1321
|
+
if (result.kind === "error" && options?.onError === void 0 && process.env.NODE_ENV !== "production") {
|
|
1322
|
+
console.warn(
|
|
1323
|
+
`[formstand] action handler threw and nothing observed it \u2014 the form shows no feedback. Pass { onError } to ${site} (or setError inside your handler):`,
|
|
1324
|
+
result.error
|
|
1325
|
+
);
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
var useFormAction = (form, onValid, options) => {
|
|
1329
|
+
const latest = react.useRef({ onValid, options });
|
|
1330
|
+
react.useEffect(() => {
|
|
1331
|
+
latest.current = { onValid, options };
|
|
1332
|
+
});
|
|
1333
|
+
return react.useCallback(
|
|
1334
|
+
async (formData) => {
|
|
1335
|
+
const { onValid: handler, options: opts } = latest.current;
|
|
1336
|
+
const result = await form.submit(
|
|
1337
|
+
(data) => handler(data, formData),
|
|
1338
|
+
opts?.onInvalid,
|
|
1339
|
+
opts?.onError === void 0 ? void 0 : { onError: opts.onError }
|
|
1340
|
+
);
|
|
1341
|
+
warnUnobserved(result, opts, "useFormAction");
|
|
1342
|
+
},
|
|
1343
|
+
[form]
|
|
1344
|
+
);
|
|
1345
|
+
};
|
|
1346
|
+
var useFormActionState = (form, action, initialState, options) => {
|
|
1347
|
+
const [state, formAction, isPending] = react.useActionState(
|
|
1348
|
+
async (prevState, formData) => {
|
|
1349
|
+
const prev = prevState;
|
|
1350
|
+
const nextRef = { current: prev };
|
|
1351
|
+
const result = await form.submit(
|
|
1352
|
+
async (data) => {
|
|
1353
|
+
nextRef.current = await action(prev, data, formData);
|
|
1354
|
+
},
|
|
1355
|
+
options?.onInvalid,
|
|
1356
|
+
options?.onError === void 0 ? void 0 : { onError: options.onError }
|
|
1357
|
+
);
|
|
1358
|
+
warnUnobserved(result, options, "useFormActionState");
|
|
1359
|
+
return nextRef.current;
|
|
1360
|
+
},
|
|
1361
|
+
initialState
|
|
1362
|
+
);
|
|
1363
|
+
return [state, formAction, isPending];
|
|
1364
|
+
};
|
|
1320
1365
|
var createFormContext = () => {
|
|
1321
1366
|
const Context = react.createContext(null);
|
|
1322
1367
|
const Provider = ({ form, children }) => /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value: form, children });
|
|
@@ -2207,6 +2252,8 @@ exports.useField = useField;
|
|
|
2207
2252
|
exports.useFieldArray = useFieldArray;
|
|
2208
2253
|
exports.useFields = useFields;
|
|
2209
2254
|
exports.useForm = useForm;
|
|
2255
|
+
exports.useFormAction = useFormAction;
|
|
2256
|
+
exports.useFormActionState = useFormActionState;
|
|
2210
2257
|
exports.useFormError = useFormError;
|
|
2211
2258
|
exports.useFormSelector = useFormSelector;
|
|
2212
2259
|
exports.useFormSelectorShallow = useFormSelectorShallow;
|