@qaflo/forms-client 1.2.0 → 1.3.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/README.md CHANGED
@@ -109,6 +109,12 @@ const { formProps, fieldProps, errors, composed } = forms.useContactForm({
109
109
  // A shape the service has no opinion on. Checked only when the field has
110
110
  // something in it, so an optional field with a pattern stays optional.
111
111
  licence: { pattern: /^[0-9]{6}$/ },
112
+ // And when no set of rules says it, write the function. It receives the
113
+ // whole form, and its message wins over the rules above.
114
+ area: {
115
+ check: (value, all) =>
116
+ all.enquiry === 'delivery' && !value ? 'We need an area to deliver to.' : undefined,
117
+ },
112
118
  },
113
119
 
114
120
  // The rules are the service's. The voice is yours.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qaflo/forms-client",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
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",
package/validate.d.ts CHANGED
@@ -5,6 +5,12 @@ export interface FieldRule {
5
5
  email?: boolean
6
6
  /** A site-specific shape. Checked only when the field is non-empty. */
7
7
  pattern?: RegExp
8
+ /**
9
+ * Anything the rules above cannot express. Returns the message, or
10
+ * undefined to pass. Runs only when the field is non-empty, and its message
11
+ * wins over every other rule.
12
+ */
13
+ check?: (value: string, values: Record<string, string>) => string | undefined
8
14
  /** Used in the default messages; defaults to the field's own name. */
9
15
  label?: string
10
16
  }
package/validate.js CHANGED
@@ -80,6 +80,18 @@ export function validateFields(values, fields = DEFAULT_FIELDS, messages) {
80
80
  // is how a form ends up scolding someone for leaving Company blank.
81
81
  continue
82
82
  }
83
+ // An escape hatch for a rule this cannot express declaratively — a phone
84
+ // check with a different sentence for letters, for too short and for too
85
+ // long. It runs after the empty check, so an optional field stays optional,
86
+ // and it owns the field's message outright when it returns one.
87
+ if (rule.check) {
88
+ const own = rule.check(value, values)
89
+ if (own) {
90
+ errors[field] = own
91
+ continue
92
+ }
93
+ }
94
+
83
95
  if (rule.email && !EMAIL_RE.test(value)) {
84
96
  errors[field] = message(messages, field, 'email', label, 0, value)
85
97
  } else if (rule.pattern && !rule.pattern.test(value)) {