@qaflo/forms-client 1.0.0 → 1.1.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/README.md CHANGED
@@ -171,6 +171,7 @@ The whole form except its markup. Returns `formProps`, `fieldProps(name)`,
171
171
  | `honeypotName` | `website` | The service reads `website` or `honeypot`. |
172
172
  | `idPrefix` | `cf-` | Must match your `<label htmlFor>`. |
173
173
  | `onSuccess` | none | Called with the submitted values. |
174
+ | `onError` | none | Called on every failed submit, including an unsolved captcha, with `(result, values)`. Use it when results are shown as toasts: two identical failures in a row leave `state` and `error` unchanged, so an effect watching them fires once and the second attempt looks like it did nothing. |
174
175
 
175
176
  Validation rules mirror `internal/api/validate.go`. **The server stays the
176
177
  authority** — this exists so nothing it would reject costs a round trip, because
package/form.d.ts CHANGED
@@ -20,6 +20,11 @@ export interface ContactFormConfig {
20
20
  */
21
21
  exclude?: string[]
22
22
  onSuccess?: (values: Record<string, string>) => void
23
+ /** Called on every failed submit, including an unsolved captcha. */
24
+ onError?: (
25
+ result: { ok: false; status: number; message: string },
26
+ values: Record<string, string>,
27
+ ) => void
23
28
  }
24
29
 
25
30
  export interface ContactFormHandle {
package/form.js CHANGED
@@ -96,6 +96,7 @@ export function useContactFormWith(widget, config = {}) {
96
96
  idPrefix = 'cf-',
97
97
  exclude = [],
98
98
  onSuccess,
99
+ onError,
99
100
  } = config
100
101
 
101
102
  const [state, setState] = useState(/** @type {'idle'|'sending'|'ok'|'error'} */ ('idle'))
@@ -155,6 +156,7 @@ export function useContactFormWith(widget, config = {}) {
155
156
  if (!widget.getToken()) {
156
157
  setState('error')
157
158
  setError(SECURITY_CHECK_PENDING)
159
+ if (onError) onError({ ok: false, status: 0, message: SECURITY_CHECK_PENDING }, values)
158
160
  return
159
161
  }
160
162
 
@@ -177,8 +179,13 @@ export function useContactFormWith(widget, config = {}) {
177
179
  }
178
180
  setState('error')
179
181
  setError(result.message)
182
+ // Called on EVERY failed submit, which is what a site reporting results
183
+ // as a toast needs: two identical failures in a row leave `state` and
184
+ // `error` unchanged, so an effect watching them fires once and the second
185
+ // attempt looks like it did nothing at all.
186
+ if (onError) onError(result, values)
180
187
  },
181
- [fields, messages, compose, subject, honeypotName, idPrefix, exclude, onSuccess, widget, fieldOrder],
188
+ [fields, messages, compose, subject, honeypotName, idPrefix, exclude, onSuccess, onError, widget, fieldOrder],
182
189
  )
183
190
 
184
191
  const invalid = useCallback((name) => (showErrors ? errors[name] : undefined), [showErrors, errors])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qaflo/forms-client",
3
- "version": "1.0.0",
3
+ "version": "1.1.1",
4
4
  "description": "Client half of the shared qaflo contact-form service: transport, Turnstile lifecycle and visitor-facing status messages.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -22,7 +22,8 @@
22
22
  "./messages": {
23
23
  "types": "./messages.d.ts",
24
24
  "default": "./messages.js"
25
- }
25
+ },
26
+ "./package.json": "./package.json"
26
27
  },
27
28
  "files": [
28
29
  "*.js",