@plitzi/sdk-elements 0.35.2 → 0.35.3

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 CHANGED
@@ -1,5 +1,31 @@
1
1
  # @plitzi/sdk-elements
2
2
 
3
+ ## 0.35.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 0211dc4: A form speaks the site's language when it refuses a value.
8
+
9
+ - **Every rule of a `formControl` can say what it wants to say.** `requiredMessage`, `minLengthMessage`,
10
+ `maxLengthMessage` and `formatMessage` join `patternMessage` and `matchesMessage`; left empty, each falls back to
11
+ the English sentence it said before. `formatMessage` is said when the value does not have the shape the control's
12
+ type asks for — an address, for an `email` — one attribute for every type that has a shape. Offered in the builder under the rule they belong to.
13
+ - **A `form` can turn the browser's own checks off (`noValidate`, "Skip Browser Validation" in the builder).** Left on
14
+ — the default, as before — the browser answers first for a blank required field and a malformed address, in a
15
+ bubble no style reaches and in the browser's language, while every other rule answers under the control. Turned
16
+ on, the form's rules are the only ones, and all of them answer under the control.
17
+ - **An `email` control checks the address itself,** by the same definition the browser uses, so the format is still
18
+ asked for when the browser's checks are off.
19
+
20
+ - Updated dependencies [0211dc4]
21
+ - @plitzi/sdk-auth@0.35.3
22
+ - @plitzi/sdk-dev-tools@0.35.3
23
+ - @plitzi/sdk-event-bridge@0.35.3
24
+ - @plitzi/sdk-interactions@0.35.3
25
+ - @plitzi/sdk-navigation@0.35.3
26
+ - @plitzi/sdk-schema@0.35.3
27
+ - @plitzi/sdk-shared@0.35.3
28
+
3
29
  ## 0.35.2
4
30
 
5
31
  ### Minor Changes
@@ -791,6 +791,7 @@ export declare const elementDeclarations: {
791
791
  readonly method: "get";
792
792
  readonly actionUrl: "";
793
793
  readonly managedByInteractions: false;
794
+ readonly noValidate: false;
794
795
  readonly errors: {};
795
796
  readonly values: {};
796
797
  };
@@ -838,6 +839,7 @@ export declare const elementDeclarations: {
838
839
  } & import('@plitzi/sdk-shared/authoring/declare').ElementAttributesBrand<Partial<{
839
840
  values: Record<string, unknown>;
840
841
  method: "get" | "post";
842
+ noValidate: boolean;
841
843
  actionUrl: string;
842
844
  managedByInteractions: boolean;
843
845
  errors: Record<string, string>;
@@ -855,8 +857,12 @@ export declare const elementDeclarations: {
855
857
  readonly disabled: false;
856
858
  readonly options: readonly [];
857
859
  readonly required: true;
860
+ readonly requiredMessage: "";
858
861
  readonly minLength: 0;
862
+ readonly minLengthMessage: "";
859
863
  readonly maxLength: 0;
864
+ readonly maxLengthMessage: "";
865
+ readonly formatMessage: "";
860
866
  readonly pattern: "";
861
867
  readonly patternMessage: "";
862
868
  readonly matches: "";
@@ -7,6 +7,14 @@ export type FormProps = {
7
7
  method: 'get' | 'post';
8
8
  actionUrl: string;
9
9
  managedByInteractions: boolean;
10
+ /**
11
+ * Turns the browser's own checks off, leaving the controls' rules as the whole of the validation.
12
+ *
13
+ * Left on, the browser answers first for the two rules it knows (a blank required field, a malformed address) in a
14
+ * bubble no style reaches and in the BROWSER's language, while every other rule answers under the control. On, every
15
+ * rule answers under the control in the words its `…Message` gives — `validateField` asks for both of those itself.
16
+ */
17
+ noValidate: boolean;
10
18
  errors: Record<string, string>;
11
19
  values: Record<string, unknown>;
12
20
  };
@@ -27,7 +35,7 @@ export type FormContextValue = {
27
35
  setFieldValue: (name: string, value: FieldValue | null) => void;
28
36
  setFieldError: (name: string, error: string) => void;
29
37
  };
30
- declare const Form: ({ ref, className, children, method, actionUrl, managedByInteractions, errors, values }: FormProps) => import("react").JSX.Element;
38
+ declare const Form: ({ ref, className, children, method, actionUrl, managedByInteractions, noValidate, errors, values }: FormProps) => import("react").JSX.Element;
31
39
  declare const _default: {
32
40
  (props: import('../../../Element/hocs/withElement').WithElementProps<FormProps>): import("react").JSX.Element;
33
41
  displayName: string;
@@ -13,28 +13,28 @@ import { produce as _ } from "immer";
13
13
  import v from "@plitzi/sdk-shared/dataSource/helpers/getSourceName";
14
14
  import y from "@plitzi/sdk-shared/dataSource/hooks/useRegisterSource";
15
15
  //#region src/elements/form/Form/Form.tsx
16
- var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl: C = "", managedByInteractions: w = !1, errors: T = m, values: E = m }) => {
17
- let [D, O] = l({}), k = c(/* @__PURE__ */ new Map()), A = c(!1), { id: j, definition: { label: M = "Form" }, setElementState: N } = t(), P = v(r.sourceType, j), { settings: { previewMode: F }, contexts: { InteractionsContext: I } } = u(), { interactionsManager: L } = i(I), R = a((e) => O((t) => ({
16
+ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl: C = "", managedByInteractions: w = !1, noValidate: T = !1, errors: E = m, values: D = m }) => {
17
+ let [O, k] = l({}), A = c(/* @__PURE__ */ new Map()), j = c(!1), { id: M, definition: { label: N = "Form" }, setElementState: P } = t(), F = v(r.sourceType, M), { settings: { previewMode: I }, contexts: { InteractionsContext: L } } = u(), { interactionsManager: R } = i(L), z = a((e) => k((t) => ({
18
18
  ...t,
19
19
  [e.name]: e
20
- })), [O]);
21
- o(() => (A.current = !1, () => {
22
- A.current = !0;
20
+ })), [k]);
21
+ o(() => (j.current = !1, () => {
22
+ j.current = !0;
23
23
  }), []);
24
- let z = a((e) => {
25
- A.current || (O((t) => _(t, (t) => {
24
+ let B = a((e) => {
25
+ j.current || (k((t) => _(t, (t) => {
26
26
  t[e] && delete t[e];
27
- })), e && N((t) => ({
27
+ })), e && P((t) => ({
28
28
  ...t,
29
29
  values: f(t, `values.${e}`),
30
30
  errors: f(t, `errors.${e}`)
31
31
  })));
32
- }, [N]), B = a((e, t) => {
33
- k.current.set(e, t);
34
- }, []), V = a((e) => {
35
- k.current.delete(e);
36
- }, []), H = a((e, t = "") => {
37
- e && (t === null && (t = ""), N((n) => n.errors && n.errors[e] ? {
32
+ }, [P]), V = a((e, t) => {
33
+ A.current.set(e, t);
34
+ }, []), H = a((e) => {
35
+ A.current.delete(e);
36
+ }, []), U = a((e, t = "") => {
37
+ e && (t === null && (t = ""), P((n) => n.errors && n.errors[e] ? {
38
38
  ...n,
39
39
  values: {
40
40
  ...n.values,
@@ -48,8 +48,8 @@ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl:
48
48
  [e]: t
49
49
  }
50
50
  }));
51
- }, [N]), U = a((e, t) => {
52
- e && N((n) => !t && !d(n, `errors.${e}`) ? n : !t && n.errors && n.errors[e] ? {
51
+ }, [P]), W = a((e, t) => {
52
+ e && P((n) => !t && !d(n, `errors.${e}`) ? n : !t && n.errors && n.errors[e] ? {
53
53
  ...n,
54
54
  errors: f(n, [`errors.${e}`])
55
55
  } : {
@@ -59,7 +59,7 @@ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl:
59
59
  [e]: t
60
60
  }
61
61
  });
62
- }, [N]), W = a(() => Object.values(D).filter((e) => !!e.name).reduce((e, t) => [
62
+ }, [P]), G = a(() => Object.values(O).filter((e) => !!e.name).reduce((e, t) => [
63
63
  ...e,
64
64
  {
65
65
  path: `fields.${t.name}.id`,
@@ -73,118 +73,118 @@ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl:
73
73
  path: `errors.${t.name}`,
74
74
  name: `${t.name} Error Message`
75
75
  }
76
- ], []), [D]), G = s(() => ({ runtime: { sources: {
76
+ ], []), [O]), K = s(() => ({ runtime: { sources: {
77
77
  form: {
78
- errors: T,
79
- values: E,
80
- registerField: R,
81
- unregisterField: z,
82
- registerValidator: B,
83
- unregisterValidator: V,
84
- setFieldValue: H,
85
- setFieldError: U
78
+ errors: E,
79
+ values: D,
80
+ registerField: z,
81
+ unregisterField: B,
82
+ registerValidator: V,
83
+ unregisterValidator: H,
84
+ setFieldValue: U,
85
+ setFieldError: W
86
86
  },
87
- [P]: {
88
- values: E,
89
- errors: T
87
+ [F]: {
88
+ values: D,
89
+ errors: E
90
90
  }
91
91
  } } }), [
92
- P,
93
- T,
92
+ F,
94
93
  E,
95
- R,
94
+ D,
96
95
  z,
97
96
  B,
98
97
  V,
99
98
  H,
100
- U
99
+ U,
100
+ W
101
101
  ]);
102
102
  y({
103
- id: j,
104
- source: P,
105
- name: M || `Form - ${j}`,
106
- fields: W
103
+ id: M,
104
+ source: F,
105
+ name: N || `Form - ${M}`,
106
+ fields: G
107
107
  });
108
- let K = s(() => ({ onSubmit: {
108
+ let q = s(() => ({ onSubmit: {
109
109
  action: "onSubmit",
110
110
  title: "On Form Submit",
111
111
  type: "trigger",
112
112
  params: {},
113
113
  preview: {
114
- values: Object.values(D).reduce((e, t) => ({
114
+ values: Object.values(O).reduce((e, t) => ({
115
115
  ...e,
116
116
  [t.name]: ""
117
117
  }), {}),
118
118
  actionUrl: "",
119
119
  method: ""
120
120
  }
121
- } }), [D]), q = a((e) => {
122
- let t = [...k.current].reduce((e, [t, n]) => {
123
- let r = n(E);
121
+ } }), [O]), J = a((e) => {
122
+ let t = [...A.current].reduce((e, [t, n]) => {
123
+ let r = n(D);
124
124
  return r ? {
125
125
  ...e,
126
126
  [t]: r
127
127
  } : e;
128
128
  }, {});
129
- if (N((e) => ({
129
+ if (P((e) => ({
130
130
  ...e,
131
131
  errors: t
132
132
  })), Object.keys(t).length > 0) {
133
133
  e.stopPropagation(), e.preventDefault();
134
134
  return;
135
135
  }
136
- if (!w || (e.stopPropagation(), e.preventDefault(), !F)) return;
137
- let n = Object.values(D).reduce((e, { name: t }) => ({
136
+ if (!w || (e.stopPropagation(), e.preventDefault(), !I)) return;
137
+ let n = Object.values(O).reduce((e, { name: t }) => ({
138
138
  ...e,
139
- [t]: E[t]
139
+ [t]: D[t]
140
140
  }), {});
141
- L.interactionTrigger(j, "onSubmit", {
141
+ R.interactionTrigger(M, "onSubmit", {
142
142
  values: n,
143
143
  actionUrl: C,
144
144
  method: S
145
145
  });
146
146
  }, [
147
- N,
147
+ P,
148
148
  w,
149
- F,
150
- D,
151
- L,
152
- j,
149
+ I,
150
+ O,
151
+ R,
152
+ M,
153
153
  C,
154
154
  S,
155
- E
156
- ]), J = a((e) => {
157
- w && (e instanceof Event && (e.stopPropagation(), e.preventDefault()), N((e) => ({
155
+ D
156
+ ]), Y = a((e) => {
157
+ w && (e instanceof Event && (e.stopPropagation(), e.preventDefault()), P((e) => ({
158
158
  ...e,
159
159
  values: {},
160
160
  errors: {}
161
161
  })));
162
- }, [N, w]), Y = a((e) => {
162
+ }, [P, w]), X = a((e) => {
163
163
  let { name: t, value: n } = e;
164
- H(t, n);
165
- }, [H]), X = a((e) => {
166
- let { name: t, error: n } = e;
167
164
  U(t, n);
168
- }, [U]), Z = s(() => ({
165
+ }, [U]), Z = a((e) => {
166
+ let { name: t, error: n } = e;
167
+ W(t, n);
168
+ }, [W]), Q = s(() => ({
169
169
  performReset: {
170
170
  action: "performReset",
171
- title: `Reset ${M}`,
171
+ title: `Reset ${N}`,
172
172
  type: "callback",
173
- callback: J,
173
+ callback: Y,
174
174
  params: {}
175
175
  },
176
176
  setFieldValue: {
177
177
  action: "setFieldValue",
178
- title: `Set Field Value ${M}`,
178
+ title: `Set Field Value ${N}`,
179
179
  type: "callback",
180
- callback: Y,
180
+ callback: X,
181
181
  preview: {},
182
182
  params: {
183
183
  name: {
184
184
  label: "Field Name",
185
185
  defaultValue: void 0,
186
186
  type: "select",
187
- options: Object.values(D).map((e) => ({
187
+ options: Object.values(O).map((e) => ({
188
188
  value: e.name,
189
189
  label: e.name
190
190
  }))
@@ -197,16 +197,16 @@ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl:
197
197
  },
198
198
  setFieldError: {
199
199
  action: "setFieldError",
200
- title: `Set Field Error ${M}`,
200
+ title: `Set Field Error ${N}`,
201
201
  type: "callback",
202
- callback: X,
202
+ callback: Z,
203
203
  preview: {},
204
204
  params: {
205
205
  name: {
206
206
  label: "Field Name",
207
207
  defaultValue: void 0,
208
208
  type: "select",
209
- options: Object.values(D).map((e) => ({
209
+ options: Object.values(O).map((e) => ({
210
210
  value: e.name,
211
211
  label: e.name
212
212
  }))
@@ -218,26 +218,27 @@ var b = ({ ref: e, className: b = "", children: x, method: S = "get", actionUrl:
218
218
  }
219
219
  }
220
220
  }), [
221
- M,
222
- J,
221
+ N,
223
222
  Y,
224
- D,
225
- X
223
+ X,
224
+ O,
225
+ Z
226
226
  ]);
227
227
  return /* @__PURE__ */ h(n, {
228
228
  tag: "form",
229
229
  ref: e,
230
+ noValidate: T,
230
231
  method: S,
231
232
  className: g("plitzi-component__form", b),
232
- interactionTriggers: K,
233
- interactionCallbacks: Z,
234
- onSubmit: q,
235
- onReset: J,
233
+ interactionTriggers: q,
234
+ interactionCallbacks: Q,
235
+ onSubmit: J,
236
+ onReset: Y,
236
237
  action: C,
237
238
  children: /* @__PURE__ */ h(p, {
238
239
  inherit: "live",
239
- name: `Form:${j}`,
240
- value: G,
240
+ name: `Form:${M}`,
241
+ value: K,
241
242
  children: x
242
243
  })
243
244
  });
@@ -1,8 +1,9 @@
1
1
  type SettingsProps = {
2
2
  method?: 'get' | 'post';
3
3
  managedByInteractions?: boolean;
4
+ noValidate?: boolean;
4
5
  actionUrl?: string;
5
6
  onUpdate?: (key: string, value: string | boolean | number) => void;
6
7
  };
7
- declare const Settings: ({ method, managedByInteractions, actionUrl, onUpdate }: SettingsProps) => import("react").JSX.Element;
8
+ declare const Settings: ({ method, managedByInteractions, noValidate, actionUrl, onUpdate }: SettingsProps) => import("react").JSX.Element;
8
9
  export default Settings;
@@ -4,15 +4,15 @@ import r from "@plitzi/plitzi-ui/Checkbox";
4
4
  import i from "@plitzi/plitzi-ui/Input";
5
5
  import a from "@plitzi/plitzi-ui/Select";
6
6
  //#region src/elements/form/Form/Settings.tsx
7
- var o = ({ method: o = "get", managedByInteractions: s = !1, actionUrl: c = "", onUpdate: l }) => {
8
- let u = e((e) => l?.("actionUrl", e), [l]), d = e((e) => l?.("method", e), [l]), f = e((e) => l?.("managedByInteractions", e.target.checked), [l]);
7
+ var o = ({ method: o = "get", managedByInteractions: s = !1, noValidate: c = !1, actionUrl: l = "", onUpdate: u }) => {
8
+ let d = e((e) => u?.("actionUrl", e), [u]), f = e((e) => u?.("method", e), [u]), p = e((e) => u?.("managedByInteractions", e.target.checked), [u]), m = e((e) => u?.("noValidate", e.target.checked), [u]);
9
9
  return /* @__PURE__ */ n("div", {
10
10
  className: "flex h-full flex-col gap-4 py-2",
11
11
  children: [
12
12
  /* @__PURE__ */ n(a, {
13
13
  value: o,
14
14
  label: "Form Method",
15
- onChange: d,
15
+ onChange: f,
16
16
  size: "xs",
17
17
  children: [/* @__PURE__ */ t("option", {
18
18
  value: "get",
@@ -23,16 +23,22 @@ var o = ({ method: o = "get", managedByInteractions: s = !1, actionUrl: c = "",
23
23
  })]
24
24
  }),
25
25
  /* @__PURE__ */ t(i, {
26
- value: c,
27
- onChange: u,
26
+ value: l,
27
+ onChange: d,
28
28
  label: "Action URL",
29
29
  size: "xs"
30
30
  }),
31
31
  /* @__PURE__ */ t(r, {
32
32
  checked: s,
33
- onChange: f,
33
+ onChange: p,
34
34
  label: "Managed By Interactions",
35
35
  size: "xs"
36
+ }),
37
+ /* @__PURE__ */ t(r, {
38
+ checked: c,
39
+ onChange: m,
40
+ label: "Skip Browser Validation (show only the field messages)",
41
+ size: "xs"
36
42
  })
37
43
  ]
38
44
  });
@@ -10,6 +10,7 @@ declare const declaration: {
10
10
  readonly method: "get";
11
11
  readonly actionUrl: "";
12
12
  readonly managedByInteractions: false;
13
+ readonly noValidate: false;
13
14
  readonly errors: {};
14
15
  readonly values: {};
15
16
  };
@@ -57,6 +58,7 @@ declare const declaration: {
57
58
  } & import('@plitzi/sdk-shared/authoring/declare').ElementAttributesBrand<Partial<{
58
59
  values: Record<string, unknown>;
59
60
  method: "get" | "post";
61
+ noValidate: boolean;
60
62
  actionUrl: string;
61
63
  managedByInteractions: boolean;
62
64
  errors: Record<string, string>;
@@ -8,6 +8,7 @@ var t = e()({
8
8
  method: "get",
9
9
  actionUrl: "",
10
10
  managedByInteractions: !1,
11
+ noValidate: !1,
11
12
  errors: {},
12
13
  values: {}
13
14
  },
@@ -16,6 +16,7 @@ declare const Form: {
16
16
  readonly method: "get";
17
17
  readonly actionUrl: "";
18
18
  readonly managedByInteractions: false;
19
+ readonly noValidate: false;
19
20
  readonly errors: {};
20
21
  readonly values: {};
21
22
  };
@@ -57,6 +58,7 @@ declare const Form: {
57
58
  __attributes: Partial<{
58
59
  values: Record<string, unknown>;
59
60
  method: "get" | "post";
61
+ noValidate: boolean;
60
62
  actionUrl: string;
61
63
  managedByInteractions: boolean;
62
64
  errors: Record<string, string>;
@@ -16,9 +16,17 @@ export type FormControlProps = {
16
16
  /**
17
17
  * The rules a value has to meet before the form submits, checked by the form at submit time and by the control when
18
18
  * it loses focus. `0` and `''` mean no rule. See `validateField` for what each one says when it is broken.
19
+ *
20
+ * Each `…Message` is the sentence shown under the control when that rule is broken, in the site's language; empty
21
+ * falls back to an English one. `formatMessage` speaks for the shape the control's own type asks of its value — an
22
+ * address, for an `email` — so it is one attribute however many types come to have a shape.
19
23
  */
24
+ requiredMessage: string;
20
25
  minLength: number;
26
+ minLengthMessage: string;
21
27
  maxLength: number;
28
+ maxLengthMessage: string;
29
+ formatMessage: string;
22
30
  pattern: string;
23
31
  patternMessage: string;
24
32
  /** The `name` of another control in the same form this one has to repeat — a password confirmation, typically. */
@@ -7,8 +7,12 @@ type SettingsProps = {
7
7
  defaultValue?: string;
8
8
  options?: string[];
9
9
  required?: boolean;
10
+ requiredMessage?: string;
10
11
  minLength?: number;
12
+ minLengthMessage?: string;
11
13
  maxLength?: number;
14
+ maxLengthMessage?: string;
15
+ formatMessage?: string;
12
16
  pattern?: string;
13
17
  patternMessage?: string;
14
18
  matches?: string;
@@ -18,5 +22,5 @@ type SettingsProps = {
18
22
  previewError?: boolean;
19
23
  onUpdate?: (key: string, value: string | boolean | number | string[]) => void;
20
24
  };
21
- declare const Settings: ({ subType, name, label, defaultValue, placeholder, autoComplete, options, required, minLength, maxLength, pattern, patternMessage, matches, matchesMessage, readOnly, disabled, previewError, onUpdate }: SettingsProps) => import("react").JSX.Element;
25
+ declare const Settings: ({ subType, name, label, defaultValue, placeholder, autoComplete, options, required, requiredMessage, minLength, minLengthMessage, maxLength, maxLengthMessage, formatMessage, pattern, patternMessage, matches, matchesMessage, readOnly, disabled, previewError, onUpdate }: SettingsProps) => import("react").JSX.Element;
22
26
  export default Settings;
@@ -1,178 +1,203 @@
1
- import { useCallback as e, useMemo as t } from "react";
2
- import { jsx as n, jsxs as r } from "react/jsx-runtime";
3
- import i from "@plitzi/plitzi-ui/Checkbox";
4
- import a from "@plitzi/plitzi-ui/Input";
5
- import o from "@plitzi/plitzi-ui/TextArea";
6
- import s from "@plitzi/plitzi-ui/Select";
1
+ import { hasFormat as e } from "./helpers/validateField.mjs";
2
+ import { useCallback as t, useMemo as n } from "react";
3
+ import { jsx as r, jsxs as i } from "react/jsx-runtime";
4
+ import a from "@plitzi/plitzi-ui/Checkbox";
5
+ import o from "@plitzi/plitzi-ui/Input";
6
+ import s from "@plitzi/plitzi-ui/TextArea";
7
+ import c from "@plitzi/plitzi-ui/Select";
7
8
  //#region src/elements/form/FormControl/Settings.tsx
8
- var c = (e) => {
9
+ var l = (e) => {
9
10
  let t = parseInt(e, 10);
10
11
  return Number.isNaN(t) || t < 0 ? 0 : t;
11
- }, l = ({ subType: l = "text", name: u = "", label: d = "Label", defaultValue: f = "", placeholder: p = "", autoComplete: m = !0, options: h, required: g = !0, minLength: _ = 0, maxLength: v = 0, pattern: y = "", patternMessage: b = "", matches: x = "", matchesMessage: S = "", readOnly: C = !1, disabled: w = !1, previewError: T = !1, onUpdate: E }) => {
12
- let D = [
12
+ }, u = ({ subType: u = "text", name: d = "", label: f = "Label", defaultValue: p = "", placeholder: m = "", autoComplete: h = !0, options: g, required: _ = !0, requiredMessage: v = "", minLength: y = 0, minLengthMessage: b = "", maxLength: x = 0, maxLengthMessage: S = "", formatMessage: C = "", pattern: w = "", patternMessage: T = "", matches: E = "", matchesMessage: D = "", readOnly: O = !1, disabled: k = !1, previewError: A = !1, onUpdate: j }) => {
13
+ let M = [
13
14
  "text",
14
15
  "textarea",
15
16
  "number",
16
17
  "email",
17
18
  "password"
18
- ].includes(l), O = e((e) => E?.("name", e), [E]), k = e((e) => E?.("label", e), [E]), A = e((e) => E?.("placeholder", e), [E]), j = e((e) => {
19
- E?.("subType", e), E?.("defaultValue", "");
20
- }, [E]), M = e((e) => E?.("defaultValue", e), [E]), N = e((e) => E?.("autoComplete", e.target.checked), [E]), P = e((e) => E?.("required", e.target.checked), [E]), F = e((e) => E?.("minLength", c(e)), [E]), I = e((e) => E?.("maxLength", c(e)), [E]), L = e((e) => E?.("pattern", e), [E]), R = e((e) => E?.("patternMessage", e), [E]), z = e((e) => E?.("matches", e), [E]), B = e((e) => E?.("matchesMessage", e), [E]), V = e((e) => E?.("readOnly", e.target.checked), [E]), H = e((e) => E?.("disabled", e.target.checked), [E]), U = e((e) => E?.("previewError", e.target.checked), [E]), W = e((e) => {
19
+ ].includes(u), N = t((e) => j?.("name", e), [j]), ee = t((e) => j?.("label", e), [j]), P = t((e) => j?.("placeholder", e), [j]), F = t((e) => {
20
+ j?.("subType", e), j?.("defaultValue", "");
21
+ }, [j]), I = t((e) => j?.("defaultValue", e), [j]), L = t((e) => j?.("autoComplete", e.target.checked), [j]), R = t((e) => j?.("required", e.target.checked), [j]), z = t((e) => j?.("requiredMessage", e), [j]), B = t((e) => j?.("minLength", l(e)), [j]), V = t((e) => j?.("minLengthMessage", e), [j]), H = t((e) => j?.("maxLength", l(e)), [j]), U = t((e) => j?.("maxLengthMessage", e), [j]), W = t((e) => j?.("formatMessage", e), [j]), G = t((e) => j?.("pattern", e), [j]), K = t((e) => j?.("patternMessage", e), [j]), q = t((e) => j?.("matches", e), [j]), J = t((e) => j?.("matchesMessage", e), [j]), Y = t((e) => j?.("readOnly", e.target.checked), [j]), X = t((e) => j?.("disabled", e.target.checked), [j]), Z = t((e) => j?.("previewError", e.target.checked), [j]), Q = t((e) => {
21
22
  if (!e) {
22
- E?.("options", []);
23
+ j?.("options", []);
23
24
  return;
24
25
  }
25
- E?.("options", e.split("\n"));
26
- }, [E]), G = t(() => Array.isArray(h) ? h.join("\n") : "", [h]);
27
- return /* @__PURE__ */ r("div", {
26
+ j?.("options", e.split("\n"));
27
+ }, [j]), $ = n(() => Array.isArray(g) ? g.join("\n") : "", [g]);
28
+ return /* @__PURE__ */ i("div", {
28
29
  className: "flex h-full flex-col gap-4 py-2",
29
30
  children: [
30
- /* @__PURE__ */ n(a, {
31
- value: u,
31
+ /* @__PURE__ */ r(o, {
32
+ value: d,
32
33
  label: "Input Name",
33
- onChange: O,
34
+ onChange: N,
34
35
  size: "xs"
35
36
  }),
36
- /* @__PURE__ */ n(a, {
37
- value: d,
37
+ /* @__PURE__ */ r(o, {
38
+ value: f,
38
39
  label: "Label",
39
- onChange: k,
40
+ onChange: ee,
40
41
  size: "xs"
41
42
  }),
42
- /* @__PURE__ */ n(a, {
43
- value: p,
43
+ /* @__PURE__ */ r(o, {
44
+ value: m,
44
45
  label: "Placeholder",
45
- onChange: A,
46
+ onChange: P,
46
47
  size: "xs"
47
48
  }),
48
- /* @__PURE__ */ r(s, {
49
- value: l,
50
- onChange: j,
49
+ /* @__PURE__ */ i(c, {
50
+ value: u,
51
+ onChange: F,
51
52
  label: "Input Type",
52
53
  size: "xs",
53
54
  children: [
54
- /* @__PURE__ */ n("option", {
55
+ /* @__PURE__ */ r("option", {
55
56
  value: "text",
56
57
  children: "Text"
57
58
  }),
58
- /* @__PURE__ */ n("option", {
59
+ /* @__PURE__ */ r("option", {
59
60
  value: "number",
60
61
  children: "Number"
61
62
  }),
62
- /* @__PURE__ */ n("option", {
63
+ /* @__PURE__ */ r("option", {
63
64
  value: "date",
64
65
  children: "Date"
65
66
  }),
66
- /* @__PURE__ */ n("option", {
67
+ /* @__PURE__ */ r("option", {
67
68
  value: "time",
68
69
  children: "Time"
69
70
  }),
70
- /* @__PURE__ */ n("option", {
71
+ /* @__PURE__ */ r("option", {
71
72
  value: "email",
72
73
  children: "Email"
73
74
  }),
74
- /* @__PURE__ */ n("option", {
75
+ /* @__PURE__ */ r("option", {
75
76
  value: "password",
76
77
  children: "Password"
77
78
  }),
78
- /* @__PURE__ */ n("option", {
79
+ /* @__PURE__ */ r("option", {
79
80
  value: "select",
80
81
  children: "Select"
81
82
  }),
82
- /* @__PURE__ */ n("option", {
83
+ /* @__PURE__ */ r("option", {
83
84
  value: "checkbox",
84
85
  children: "Checkbox"
85
86
  }),
86
- /* @__PURE__ */ n("option", {
87
+ /* @__PURE__ */ r("option", {
87
88
  value: "textarea",
88
89
  children: "Long Text"
89
90
  }),
90
- /* @__PURE__ */ n("option", {
91
+ /* @__PURE__ */ r("option", {
91
92
  value: "hidden",
92
93
  children: "Hidden"
93
94
  })
94
95
  ]
95
96
  }),
96
- /* @__PURE__ */ n(o, {
97
- value: f,
97
+ /* @__PURE__ */ r(s, {
98
+ value: p,
98
99
  label: "Default Value",
99
- onChange: M,
100
+ onChange: I,
100
101
  size: "xs"
101
102
  }),
102
- l === "text" && /* @__PURE__ */ n(i, {
103
- checked: m,
103
+ u === "text" && /* @__PURE__ */ r(a, {
104
+ checked: h,
104
105
  label: "Auto Complete",
105
- onChange: N,
106
+ onChange: L,
106
107
  size: "xs"
107
108
  }),
108
- D && /* @__PURE__ */ n(i, {
109
- checked: C,
109
+ M && /* @__PURE__ */ r(a, {
110
+ checked: O,
110
111
  label: "Read Only",
111
- onChange: V,
112
+ onChange: Y,
112
113
  size: "xs"
113
114
  }),
114
- l === "select" && /* @__PURE__ */ n(o, {
115
- value: G,
115
+ u === "select" && /* @__PURE__ */ r(s, {
116
+ value: $,
116
117
  label: "Options",
117
- onChange: W,
118
+ onChange: Q,
118
119
  size: "xs"
119
120
  }),
120
- /* @__PURE__ */ n(i, {
121
- checked: g,
121
+ /* @__PURE__ */ r(a, {
122
+ checked: _,
122
123
  label: "Required",
123
- onChange: P,
124
+ onChange: R,
125
+ size: "xs"
126
+ }),
127
+ _ && /* @__PURE__ */ r(o, {
128
+ value: v,
129
+ label: "Required Message",
130
+ onChange: z,
124
131
  size: "xs"
125
132
  }),
126
- D && /* @__PURE__ */ n(a, {
127
- value: _ ? String(_) : "",
133
+ M && /* @__PURE__ */ r(o, {
134
+ value: y ? String(y) : "",
128
135
  label: "Min Length",
129
- onChange: F,
136
+ onChange: B,
137
+ size: "xs"
138
+ }),
139
+ M && y > 0 && /* @__PURE__ */ r(o, {
140
+ value: b,
141
+ label: "Min Length Message",
142
+ onChange: V,
130
143
  size: "xs"
131
144
  }),
132
- D && /* @__PURE__ */ n(a, {
133
- value: v ? String(v) : "",
145
+ M && /* @__PURE__ */ r(o, {
146
+ value: x ? String(x) : "",
134
147
  label: "Max Length",
135
- onChange: I,
148
+ onChange: H,
149
+ size: "xs"
150
+ }),
151
+ M && x > 0 && /* @__PURE__ */ r(o, {
152
+ value: S,
153
+ label: "Max Length Message",
154
+ onChange: U,
136
155
  size: "xs"
137
156
  }),
138
- D && /* @__PURE__ */ n(a, {
139
- value: y,
157
+ e(u) && /* @__PURE__ */ r(o, {
158
+ value: C,
159
+ label: "Invalid Format Message",
160
+ onChange: W,
161
+ size: "xs"
162
+ }),
163
+ M && /* @__PURE__ */ r(o, {
164
+ value: w,
140
165
  label: "Pattern (regular expression)",
141
- onChange: L,
166
+ onChange: G,
142
167
  size: "xs"
143
168
  }),
144
- D && y && /* @__PURE__ */ n(a, {
145
- value: b,
169
+ M && w && /* @__PURE__ */ r(o, {
170
+ value: T,
146
171
  label: "Pattern Message",
147
- onChange: R,
172
+ onChange: K,
148
173
  size: "xs"
149
174
  }),
150
- D && /* @__PURE__ */ n(a, {
151
- value: x,
175
+ M && /* @__PURE__ */ r(o, {
176
+ value: E,
152
177
  label: "Must Match Field",
153
- onChange: z,
178
+ onChange: q,
154
179
  size: "xs"
155
180
  }),
156
- D && x && /* @__PURE__ */ n(a, {
157
- value: S,
181
+ M && E && /* @__PURE__ */ r(o, {
182
+ value: D,
158
183
  label: "Mismatch Message",
159
- onChange: B,
184
+ onChange: J,
160
185
  size: "xs"
161
186
  }),
162
- /* @__PURE__ */ n(i, {
163
- checked: w,
187
+ /* @__PURE__ */ r(a, {
188
+ checked: k,
164
189
  label: "Disabled",
165
- onChange: H,
190
+ onChange: X,
166
191
  size: "xs"
167
192
  }),
168
- /* @__PURE__ */ n(i, {
169
- checked: T,
193
+ /* @__PURE__ */ r(a, {
194
+ checked: A,
170
195
  label: "Preview Error Message",
171
- onChange: U,
196
+ onChange: Z,
172
197
  size: "xs"
173
198
  })
174
199
  ]
175
200
  });
176
201
  };
177
202
  //#endregion
178
- export { l as default };
203
+ export { u as default };
@@ -17,8 +17,12 @@ declare const declaration: {
17
17
  readonly disabled: false;
18
18
  readonly options: readonly [];
19
19
  readonly required: true;
20
+ readonly requiredMessage: "";
20
21
  readonly minLength: 0;
22
+ readonly minLengthMessage: "";
21
23
  readonly maxLength: 0;
24
+ readonly maxLengthMessage: "";
25
+ readonly formatMessage: "";
22
26
  readonly pattern: "";
23
27
  readonly patternMessage: "";
24
28
  readonly matches: "";
@@ -57,8 +57,12 @@ var t = {
57
57
  disabled: !1,
58
58
  options: [],
59
59
  required: !0,
60
+ requiredMessage: "",
60
61
  minLength: 0,
62
+ minLengthMessage: "",
61
63
  maxLength: 0,
64
+ maxLengthMessage: "",
65
+ formatMessage: "",
62
66
  pattern: "",
63
67
  patternMessage: "",
64
68
  matches: "",
@@ -2,11 +2,23 @@
2
2
  * What a control asks of its value before the form around it may submit.
3
3
  *
4
4
  * Zero and the empty string mean "no rule", so a control authored before these existed validates exactly as it did.
5
+ * Every rule carries the sentence it says when broken, and an empty one falls back to English: the site's language is
6
+ * the author's to write, never the browser's to guess.
5
7
  */
6
8
  export type FieldRules = {
7
9
  required: boolean;
10
+ requiredMessage: string;
8
11
  minLength: number;
12
+ minLengthMessage: string;
9
13
  maxLength: number;
14
+ maxLengthMessage: string;
15
+ /**
16
+ * The control's `subType`. A type whose value has a shape of its own (see `FORMATS`) is checked against it here,
17
+ * because a form with `noValidate` leaves nobody else to ask for it.
18
+ */
19
+ type: string;
20
+ /** Said when the value does not have the shape its type asks for, whichever type that is. */
21
+ formatMessage: string;
10
22
  /** A regular expression the WHOLE value must match — anchored here, so an author never has to remember `^…$`. */
11
23
  pattern: string;
12
24
  patternMessage: string;
@@ -15,6 +27,8 @@ export type FieldRules = {
15
27
  matchesMessage: string;
16
28
  };
17
29
  export declare const REQUIRED_MESSAGE = "This field is required";
30
+ /** Whether a control of this type asks its value for a shape, and so whether a `formatMessage` can ever be said. */
31
+ export declare const hasFormat: (type: string) => boolean;
18
32
  /**
19
33
  * The first rule a value breaks, as the sentence to show under the control — or `''` when it breaks none.
20
34
  *
@@ -1,16 +1,22 @@
1
1
  import { get as e } from "@plitzi/plitzi-ui/helpers";
2
2
  //#region src/elements/form/FormControl/helpers/validateField.ts
3
- var t = "This field is required", n = "This is not in the expected format", r = "This does not match", i = (e) => e == null || e === "" || e === !1, a = (e) => typeof e == "string" ? e : typeof e == "number" ? String(e) : "", o = (e, t) => {
3
+ var t = "This field is required", n = "This is not in the expected format", r = "This does not match", i = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/, a = /* @__PURE__ */ new Map([["email", {
4
+ matches: (e) => i.test(e),
5
+ message: "Enter an email address"
6
+ }]]), o = (e) => a.has(e), s = (e) => e == null || e === "" || e === !1, c = (e) => typeof e == "string" ? e : typeof e == "number" ? String(e) : "", l = (e, t) => {
4
7
  try {
5
8
  return RegExp(`^(?:${t})$`, "u").test(e);
6
9
  } catch {
7
10
  return !1;
8
11
  }
9
- }, s = (s, c, l) => {
10
- if (i(s)) return c.required ? t : "";
11
- if (typeof s == "boolean") return "";
12
- let u = a(s), d = Array.from(u).length;
13
- return c.minLength > 0 && d < c.minLength ? `Use at least ${c.minLength} characters` : c.maxLength > 0 && d > c.maxLength ? `Use at most ${c.maxLength} characters` : c.pattern && !o(u, c.pattern) ? c.patternMessage || n : c.matches && u !== a(e(l, c.matches, "")) ? c.matchesMessage || r : "";
12
+ }, u = (t, i, o) => {
13
+ if (s(t)) return i.required ? i.requiredMessage || "This field is required" : "";
14
+ if (typeof t == "boolean") return "";
15
+ let u = c(t), d = Array.from(u).length;
16
+ if (i.minLength > 0 && d < i.minLength) return i.minLengthMessage || `Use at least ${i.minLength} characters`;
17
+ if (i.maxLength > 0 && d > i.maxLength) return i.maxLengthMessage || `Use at most ${i.maxLength} characters`;
18
+ let f = a.get(i.type);
19
+ return f && !f.matches(u) ? i.formatMessage || f.message : i.pattern && !l(u, i.pattern) ? i.patternMessage || n : i.matches && u !== c(e(o, i.matches, "")) ? i.matchesMessage || r : "";
14
20
  };
15
21
  //#endregion
16
- export { t as REQUIRED_MESSAGE, s as validateField };
22
+ export { t as REQUIRED_MESSAGE, o as hasFormat, u as validateField };
@@ -5,8 +5,12 @@ export type WithFieldValueProps<T> = {
5
5
  defaultValue?: string;
6
6
  subType: 'hidden' | 'text' | 'number' | 'email' | 'password' | 'date' | 'time' | 'select' | 'checkbox' | 'textarea' | 'color' | 'switch';
7
7
  required: boolean;
8
+ requiredMessage?: string;
8
9
  minLength?: number;
10
+ minLengthMessage?: string;
9
11
  maxLength?: number;
12
+ maxLengthMessage?: string;
13
+ formatMessage?: string;
10
14
  pattern?: string;
11
15
  patternMessage?: string;
12
16
  matches?: string;
@@ -8,25 +8,30 @@ import { jsx as c } from "react/jsx-runtime";
8
8
  //#region src/elements/form/FormControl/hocs/withFieldValue.tsx
9
9
  var l = (l) => {
10
10
  let u = (s) => {
11
- let { ref: u, name: d = "", subType: f = "text", defaultValue: p = "", required: m = !0, minLength: h = 0, maxLength: g = 0, pattern: _ = "", patternMessage: v = "", matches: y = "", matchesMessage: b = "", previewError: x = !1 } = s, { settings: { previewMode: S } } = i(), { useStore: C } = o(), [w] = C("runtime.sources.form");
12
- if (!w) return /* @__PURE__ */ c(l, { ...s });
13
- let { setFieldValue: T, setFieldError: E, registerValidator: D, unregisterValidator: O, errors: k, values: A } = w, j = r(() => a(A, d, p), [
14
- A,
11
+ let { ref: u, name: d = "", subType: f = "text", defaultValue: p = "", required: m = !0, requiredMessage: h = "", minLength: g = 0, minLengthMessage: _ = "", maxLength: v = 0, maxLengthMessage: y = "", formatMessage: b = "", pattern: x = "", patternMessage: S = "", matches: C = "", matchesMessage: w = "", previewError: T = !1 } = s, { settings: { previewMode: E } } = i(), { useStore: D } = o(), [O] = D("runtime.sources.form");
12
+ if (!O) return /* @__PURE__ */ c(l, { ...s });
13
+ let { setFieldValue: k, setFieldError: A, registerValidator: j, unregisterValidator: M, errors: N, values: P } = O, F = r(() => a(P, d, p), [
14
+ P,
15
15
  d,
16
16
  p
17
- ]), M = r(() => !S && x ? "This is an error message" : k[d], [
18
- S,
19
- x,
20
- k,
17
+ ]), I = r(() => !E && T ? "This is an error message" : N[d], [
18
+ E,
19
+ T,
20
+ N,
21
21
  d
22
- ]), N = r(() => ({
22
+ ]), L = r(() => ({
23
23
  required: m,
24
- minLength: h,
25
- maxLength: g,
26
- pattern: _,
27
- patternMessage: v,
28
- matches: y,
29
- matchesMessage: b
24
+ requiredMessage: h,
25
+ minLength: g,
26
+ minLengthMessage: _,
27
+ maxLength: v,
28
+ maxLengthMessage: y,
29
+ type: f,
30
+ formatMessage: b,
31
+ pattern: x,
32
+ patternMessage: S,
33
+ matches: C,
34
+ matchesMessage: w
30
35
  }), [
31
36
  m,
32
37
  h,
@@ -34,51 +39,56 @@ var l = (l) => {
34
39
  _,
35
40
  v,
36
41
  y,
37
- b
42
+ f,
43
+ b,
44
+ x,
45
+ S,
46
+ C,
47
+ w
38
48
  ]);
39
49
  n(() => {
40
- if (d) return D(d, (t) => e(a(t, d, p), N, t)), () => O(d);
50
+ if (d) return j(d, (t) => e(a(t, d, p), L, t)), () => M(d);
41
51
  }, [
42
52
  d,
43
53
  p,
44
- N,
45
- D,
46
- O
54
+ L,
55
+ j,
56
+ M
47
57
  ]), n(() => {
48
- p && j && d && T(d, j);
58
+ p && F && d && k(d, F);
49
59
  }, [
50
60
  p,
51
61
  d,
52
- T,
53
- j
62
+ k,
63
+ F
54
64
  ]);
55
- let P = t((e) => {
56
- e.target.type === "radio" || e.target.type === "checkbox" || f === "switch" ? T(d, e.target.checked) : T(d, e.target.value);
65
+ let R = t((e) => {
66
+ e.target.type === "radio" || e.target.type === "checkbox" || f === "switch" ? k(d, e.target.checked) : k(d, e.target.value);
57
67
  }, [
58
- T,
68
+ k,
59
69
  d,
60
70
  f
61
- ]), F = t(() => E(d, e(j, N, A)), [
62
- j,
63
- N,
64
- A,
71
+ ]), z = t(() => A(d, e(F, L, P)), [
72
+ F,
73
+ L,
74
+ P,
65
75
  d,
66
- E
76
+ A
67
77
  ]);
68
78
  return r(() => /* @__PURE__ */ c(l, {
69
79
  ...s,
70
80
  ref: u,
71
- value: j,
72
- error: M,
73
- handleChange: P,
74
- handleValidate: F
81
+ value: F,
82
+ error: I,
83
+ handleChange: R,
84
+ handleValidate: z
75
85
  }), [
76
86
  s,
77
87
  u,
78
- M,
79
- j,
80
- P,
81
- F
88
+ I,
89
+ F,
90
+ R,
91
+ z
82
92
  ]);
83
93
  };
84
94
  return u.displayName = `withFieldValue(${s(l)})`, u;
@@ -22,8 +22,12 @@ declare const FormControl: {
22
22
  readonly disabled: false;
23
23
  readonly options: readonly [];
24
24
  readonly required: true;
25
+ readonly requiredMessage: "";
25
26
  readonly minLength: 0;
27
+ readonly minLengthMessage: "";
26
28
  readonly maxLength: 0;
29
+ readonly maxLengthMessage: "";
30
+ readonly formatMessage: "";
27
31
  readonly pattern: "";
28
32
  readonly patternMessage: "";
29
33
  readonly matches: "";
package/dist/index.d.ts CHANGED
@@ -2576,6 +2576,7 @@ export declare const defaultElements: {
2576
2576
  readonly method: "get";
2577
2577
  readonly actionUrl: "";
2578
2578
  readonly managedByInteractions: false;
2579
+ readonly noValidate: false;
2579
2580
  readonly errors: {};
2580
2581
  readonly values: {};
2581
2582
  };
@@ -2617,6 +2618,7 @@ export declare const defaultElements: {
2617
2618
  __attributes: Partial<{
2618
2619
  values: Record<string, unknown>;
2619
2620
  method: "get" | "post";
2621
+ noValidate: boolean;
2620
2622
  actionUrl: string;
2621
2623
  managedByInteractions: boolean;
2622
2624
  errors: Record<string, string>;
@@ -2646,8 +2648,12 @@ export declare const defaultElements: {
2646
2648
  readonly disabled: false;
2647
2649
  readonly options: readonly [];
2648
2650
  readonly required: true;
2651
+ readonly requiredMessage: "";
2649
2652
  readonly minLength: 0;
2653
+ readonly minLengthMessage: "";
2650
2654
  readonly maxLength: 0;
2655
+ readonly maxLengthMessage: "";
2656
+ readonly formatMessage: "";
2651
2657
  readonly pattern: "";
2652
2658
  readonly patternMessage: "";
2653
2659
  readonly matches: "";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plitzi/sdk-elements",
3
- "version": "0.35.2",
3
+ "version": "0.35.3",
4
4
  "license": "AGPL-3.0",
5
5
  "files": [
6
6
  "dist"
@@ -986,13 +986,13 @@
986
986
  "dependencies": {
987
987
  "@plitzi/nexus": "^1.1.4",
988
988
  "@plitzi/plitzi-ui": "^1.6.21",
989
- "@plitzi/sdk-auth": "0.35.2",
990
- "@plitzi/sdk-dev-tools": "0.35.2",
991
- "@plitzi/sdk-event-bridge": "0.35.2",
992
- "@plitzi/sdk-interactions": "0.35.2",
993
- "@plitzi/sdk-navigation": "0.35.2",
994
- "@plitzi/sdk-schema": "0.35.2",
995
- "@plitzi/sdk-shared": "0.35.2",
989
+ "@plitzi/sdk-auth": "0.35.3",
990
+ "@plitzi/sdk-dev-tools": "0.35.3",
991
+ "@plitzi/sdk-event-bridge": "0.35.3",
992
+ "@plitzi/sdk-interactions": "0.35.3",
993
+ "@plitzi/sdk-navigation": "0.35.3",
994
+ "@plitzi/sdk-schema": "0.35.3",
995
+ "@plitzi/sdk-shared": "0.35.3",
996
996
  "clsx": "^2.1.1",
997
997
  "immer": "^11.1.18"
998
998
  },