@sprucelabs/heartwood-view-controllers 128.4.0 → 128.5.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.
@@ -7,7 +7,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { areSchemaValuesValid } from '@sprucelabs/schema';
11
10
  import normalizeFormSectionFieldNamesUtil from '../utilities/normalizeFieldNames.utility.js';
12
11
  import FormViewController from './form/Form.vc.js';
13
12
  export default class BigFormViewController extends FormViewController {
@@ -19,9 +18,7 @@ export default class BigFormViewController extends FormViewController {
19
18
  const slide = this.model.sections[idx];
20
19
  if (slide) {
21
20
  const fields = normalizeFormSectionFieldNamesUtil.toNames(slide.fields);
22
- return areSchemaValuesValid(this.model.schema, this.model.values, {
23
- fields,
24
- });
21
+ return this._isValidForFields(fields);
25
22
  }
26
23
  return false;
27
24
  }
@@ -13,6 +13,7 @@ export default class LoginCardViewController extends AbstractViewController<Card
13
13
  private _id;
14
14
  private userChallenge?;
15
15
  private cardVc;
16
+ private shouldRequireCheckboxForSmsOptIn;
16
17
  constructor(options: LoginCardViewControllerOptions & ViewControllerOptions);
17
18
  private CardVc;
18
19
  private renderLoginWithEmailButton;
@@ -64,6 +65,11 @@ export default class LoginCardViewController extends AbstractViewController<Card
64
65
  label: string;
65
66
  options: {};
66
67
  };
68
+ smsOptIn: {
69
+ type: "boolean";
70
+ label: string;
71
+ isRequired: true;
72
+ };
67
73
  };
68
74
  }>;
69
75
  render(): Card;
@@ -76,6 +82,7 @@ export interface LoginCardViewControllerOptions {
76
82
  smsDisclaimer?: string | null;
77
83
  shouldAllowEmailLogin?: boolean;
78
84
  shouldAllowPhoneLogin?: boolean;
85
+ shouldRequireCheckboxForSmsOptIn?: boolean;
79
86
  }
80
87
  declare const loginSchema: {
81
88
  id: string;
@@ -97,6 +104,11 @@ declare const loginSchema: {
97
104
  label: string;
98
105
  options: {};
99
106
  };
107
+ smsOptIn: {
108
+ type: "boolean";
109
+ label: string;
110
+ isRequired: true;
111
+ };
100
112
  };
101
113
  };
102
114
  type LoginSchema = typeof loginSchema;
@@ -16,7 +16,7 @@ import AbstractViewController from './Abstract.vc.js';
16
16
  class LoginCardViewController extends AbstractViewController {
17
17
  constructor(options) {
18
18
  super(options);
19
- const { id, onLogin, onLoginFailed, smsDisclaimer, shouldAllowEmailLogin, shouldAllowPhoneLogin = true, } = options;
19
+ const { id, onLogin, onLoginFailed, smsDisclaimer, shouldAllowEmailLogin, shouldAllowPhoneLogin = true, shouldRequireCheckboxForSmsOptIn = false, } = options;
20
20
  this._id = id !== null && id !== void 0 ? id : `${LoginCardViewController._id}`;
21
21
  LoginCardViewController._id++;
22
22
  if (!shouldAllowPhoneLogin && !shouldAllowEmailLogin) {
@@ -25,6 +25,7 @@ class LoginCardViewController extends AbstractViewController {
25
25
  friendlyMessage: "You have to allow phone or email login. You can't disable both.",
26
26
  });
27
27
  }
28
+ this.shouldRequireCheckboxForSmsOptIn = shouldRequireCheckboxForSmsOptIn;
28
29
  this.shouldAllowPhoneLogin = shouldAllowPhoneLogin;
29
30
  this.shouldAllowEmailLogin = shouldAllowEmailLogin !== null && shouldAllowEmailLogin !== void 0 ? shouldAllowEmailLogin : false;
30
31
  this.loginHandler = onLogin;
@@ -146,14 +147,20 @@ class LoginCardViewController extends AbstractViewController {
146
147
  }
147
148
  renderPhoneSection() {
148
149
  var _a;
150
+ const fields = [
151
+ {
152
+ name: 'phone',
153
+ hint: (_a = this.smsDisclaimer) !== null && _a !== void 0 ? _a : loginSchema.fields.phone.hint,
154
+ },
155
+ ];
156
+ if (this.shouldRequireCheckboxForSmsOptIn) {
157
+ fields.push({
158
+ name: 'smsOptIn',
159
+ });
160
+ }
149
161
  return {
150
162
  title: this.renderPhoneSlideTitle(),
151
- fields: [
152
- {
153
- name: 'phone',
154
- hint: (_a = this.smsDisclaimer) !== null && _a !== void 0 ? _a : loginSchema.fields.phone.hint,
155
- },
156
- ],
163
+ fields,
157
164
  };
158
165
  }
159
166
  renderPhoneSlideTitle() {
@@ -209,10 +216,20 @@ class LoginCardViewController extends AbstractViewController {
209
216
  handleOnChangeBigForm(options) {
210
217
  return __awaiter(this, void 0, void 0, function* () {
211
218
  const { values } = options;
212
- const { code } = values;
219
+ const { code, smsOptIn } = values;
213
220
  if ((code === null || code === void 0 ? void 0 : code.length) === 4) {
214
221
  yield this.bigFormVc.submit();
215
222
  }
223
+ if (this.shouldRequireCheckboxForSmsOptIn && smsOptIn === false) {
224
+ this.bigFormVc.setErrors([
225
+ {
226
+ code: 'INVALID_PARAMETER',
227
+ friendlyMessage: 'You must agree to receive SMS messages.',
228
+ label: 'I agree to receive SMS messages.',
229
+ name: 'smsOptIn',
230
+ },
231
+ ]);
232
+ }
216
233
  });
217
234
  }
218
235
  requestPin(values) {
@@ -301,5 +318,10 @@ const loginSchema = buildSchema({
301
318
  label: 'Pin',
302
319
  options: {},
303
320
  },
321
+ smsOptIn: {
322
+ type: 'boolean',
323
+ label: 'I agree to receive SMS messages.',
324
+ isRequired: true,
325
+ },
304
326
  },
305
327
  });
@@ -35,9 +35,10 @@ export default class FormViewController<S extends Schema, V extends ViewModel<S>
35
35
  private normalizeValues;
36
36
  private validateDirtyFields;
37
37
  setErrors(errors: TypedFieldError<S>[]): void;
38
- setErrorsByField(errorsByField: FormErrorsByField<S>): void;
38
+ protected setErrorsByField(errorsByField: FormErrorsByField<S>): void;
39
39
  validate(): FormErrorsByField<S>;
40
40
  isValid(): boolean;
41
+ protected _isValidForFields(visibleFields: SchemaFieldNames<S>[]): boolean;
41
42
  private getVisibleFields;
42
43
  disable(): void;
43
44
  enable(): void;
@@ -280,9 +280,21 @@ export default class FormViewController extends AbstractViewController {
280
280
  return errorsByField;
281
281
  }
282
282
  isValid() {
283
- return areSchemaValuesValid(this.model.schema, this.model.values, {
284
- fields: this.getVisibleFields(),
285
- });
283
+ const visibleFields = this.getVisibleFields();
284
+ let isValid = this._isValidForFields(visibleFields);
285
+ return isValid;
286
+ }
287
+ _isValidForFields(visibleFields) {
288
+ let isValid = true;
289
+ if (Object.keys(this.getErrorsByField()).length > 0) {
290
+ isValid = false;
291
+ }
292
+ isValid =
293
+ isValid &&
294
+ areSchemaValuesValid(this.model.schema, this.model.values, {
295
+ fields: visibleFields,
296
+ });
297
+ return isValid;
286
298
  }
287
299
  getVisibleFields() {
288
300
  var _a;
@@ -3,7 +3,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- const schema_1 = require("@sprucelabs/schema");
7
6
  const normalizeFieldNames_utility_1 = __importDefault(require("../utilities/normalizeFieldNames.utility"));
8
7
  const Form_vc_1 = __importDefault(require("./form/Form.vc"));
9
8
  class BigFormViewController extends Form_vc_1.default {
@@ -15,9 +14,7 @@ class BigFormViewController extends Form_vc_1.default {
15
14
  const slide = this.model.sections[idx];
16
15
  if (slide) {
17
16
  const fields = normalizeFieldNames_utility_1.default.toNames(slide.fields);
18
- return (0, schema_1.areSchemaValuesValid)(this.model.schema, this.model.values, {
19
- fields,
20
- });
17
+ return this._isValidForFields(fields);
21
18
  }
22
19
  return false;
23
20
  }
@@ -13,6 +13,7 @@ export default class LoginCardViewController extends AbstractViewController<Card
13
13
  private _id;
14
14
  private userChallenge?;
15
15
  private cardVc;
16
+ private shouldRequireCheckboxForSmsOptIn;
16
17
  constructor(options: LoginCardViewControllerOptions & ViewControllerOptions);
17
18
  private CardVc;
18
19
  private renderLoginWithEmailButton;
@@ -64,6 +65,11 @@ export default class LoginCardViewController extends AbstractViewController<Card
64
65
  label: string;
65
66
  options: {};
66
67
  };
68
+ smsOptIn: {
69
+ type: "boolean";
70
+ label: string;
71
+ isRequired: true;
72
+ };
67
73
  };
68
74
  }>;
69
75
  render(): Card;
@@ -76,6 +82,7 @@ export interface LoginCardViewControllerOptions {
76
82
  smsDisclaimer?: string | null;
77
83
  shouldAllowEmailLogin?: boolean;
78
84
  shouldAllowPhoneLogin?: boolean;
85
+ shouldRequireCheckboxForSmsOptIn?: boolean;
79
86
  }
80
87
  declare const loginSchema: {
81
88
  id: string;
@@ -97,6 +104,11 @@ declare const loginSchema: {
97
104
  label: string;
98
105
  options: {};
99
106
  };
107
+ smsOptIn: {
108
+ type: "boolean";
109
+ label: string;
110
+ isRequired: true;
111
+ };
100
112
  };
101
113
  };
102
114
  type LoginSchema = typeof loginSchema;
@@ -12,7 +12,7 @@ const Abstract_vc_1 = __importDefault(require("./Abstract.vc"));
12
12
  class LoginCardViewController extends Abstract_vc_1.default {
13
13
  constructor(options) {
14
14
  super(options);
15
- const { id, onLogin, onLoginFailed, smsDisclaimer, shouldAllowEmailLogin, shouldAllowPhoneLogin = true, } = options;
15
+ const { id, onLogin, onLoginFailed, smsDisclaimer, shouldAllowEmailLogin, shouldAllowPhoneLogin = true, shouldRequireCheckboxForSmsOptIn = false, } = options;
16
16
  this._id = id ?? `${LoginCardViewController._id}`;
17
17
  LoginCardViewController._id++;
18
18
  if (!shouldAllowPhoneLogin && !shouldAllowEmailLogin) {
@@ -21,6 +21,7 @@ class LoginCardViewController extends Abstract_vc_1.default {
21
21
  friendlyMessage: "You have to allow phone or email login. You can't disable both.",
22
22
  });
23
23
  }
24
+ this.shouldRequireCheckboxForSmsOptIn = shouldRequireCheckboxForSmsOptIn;
24
25
  this.shouldAllowPhoneLogin = shouldAllowPhoneLogin;
25
26
  this.shouldAllowEmailLogin = shouldAllowEmailLogin ?? false;
26
27
  this.loginHandler = onLogin;
@@ -137,14 +138,20 @@ class LoginCardViewController extends Abstract_vc_1.default {
137
138
  : null;
138
139
  }
139
140
  renderPhoneSection() {
141
+ const fields = [
142
+ {
143
+ name: 'phone',
144
+ hint: this.smsDisclaimer ?? loginSchema.fields.phone.hint,
145
+ },
146
+ ];
147
+ if (this.shouldRequireCheckboxForSmsOptIn) {
148
+ fields.push({
149
+ name: 'smsOptIn',
150
+ });
151
+ }
140
152
  return {
141
153
  title: this.renderPhoneSlideTitle(),
142
- fields: [
143
- {
144
- name: 'phone',
145
- hint: this.smsDisclaimer ?? loginSchema.fields.phone.hint,
146
- },
147
- ],
154
+ fields,
148
155
  };
149
156
  }
150
157
  renderPhoneSlideTitle() {
@@ -197,10 +204,20 @@ class LoginCardViewController extends Abstract_vc_1.default {
197
204
  }
198
205
  async handleOnChangeBigForm(options) {
199
206
  const { values } = options;
200
- const { code } = values;
207
+ const { code, smsOptIn } = values;
201
208
  if (code?.length === 4) {
202
209
  await this.bigFormVc.submit();
203
210
  }
211
+ if (this.shouldRequireCheckboxForSmsOptIn && smsOptIn === false) {
212
+ this.bigFormVc.setErrors([
213
+ {
214
+ code: 'INVALID_PARAMETER',
215
+ friendlyMessage: 'You must agree to receive SMS messages.',
216
+ label: 'I agree to receive SMS messages.',
217
+ name: 'smsOptIn',
218
+ },
219
+ ]);
220
+ }
204
221
  }
205
222
  async requestPin(values) {
206
223
  try {
@@ -283,5 +300,10 @@ const loginSchema = (0, schema_1.buildSchema)({
283
300
  label: 'Pin',
284
301
  options: {},
285
302
  },
303
+ smsOptIn: {
304
+ type: 'boolean',
305
+ label: 'I agree to receive SMS messages.',
306
+ isRequired: true,
307
+ },
286
308
  },
287
309
  });
@@ -35,9 +35,10 @@ export default class FormViewController<S extends Schema, V extends ViewModel<S>
35
35
  private normalizeValues;
36
36
  private validateDirtyFields;
37
37
  setErrors(errors: TypedFieldError<S>[]): void;
38
- setErrorsByField(errorsByField: FormErrorsByField<S>): void;
38
+ protected setErrorsByField(errorsByField: FormErrorsByField<S>): void;
39
39
  validate(): FormErrorsByField<S>;
40
40
  isValid(): boolean;
41
+ protected _isValidForFields(visibleFields: SchemaFieldNames<S>[]): boolean;
41
42
  private getVisibleFields;
42
43
  disable(): void;
43
44
  enable(): void;
@@ -264,9 +264,21 @@ class FormViewController extends Abstract_vc_1.default {
264
264
  return errorsByField;
265
265
  }
266
266
  isValid() {
267
- return (0, schema_1.areSchemaValuesValid)(this.model.schema, this.model.values, {
268
- fields: this.getVisibleFields(),
269
- });
267
+ const visibleFields = this.getVisibleFields();
268
+ let isValid = this._isValidForFields(visibleFields);
269
+ return isValid;
270
+ }
271
+ _isValidForFields(visibleFields) {
272
+ let isValid = true;
273
+ if (Object.keys(this.getErrorsByField()).length > 0) {
274
+ isValid = false;
275
+ }
276
+ isValid =
277
+ isValid &&
278
+ (0, schema_1.areSchemaValuesValid)(this.model.schema, this.model.values, {
279
+ fields: visibleFields,
280
+ });
281
+ return isValid;
270
282
  }
271
283
  getVisibleFields() {
272
284
  const fields = [];
package/package.json CHANGED
@@ -12,7 +12,7 @@
12
12
  "sideEffects": false,
13
13
  "license": "MIT",
14
14
  "description": "All the power of Heartwood in one, convenient package.",
15
- "version": "128.4.0",
15
+ "version": "128.5.0",
16
16
  "skill": {
17
17
  "namespace": "HeartwoodViewControllers",
18
18
  "commandOverrides": {