@hellotext/hellotext 1.7.8 → 1.8.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/docs/tracking.md CHANGED
@@ -49,11 +49,15 @@ Hellotext.track('page.viewed', {
49
49
 
50
50
  ### Headers
51
51
 
52
- You can add any custom or additional headers to the request by passing an object as the third argument to the `track` method.
53
- Any duplicate headers will be overwritten by Hellotext's default headers.
52
+ You can add any custom or additional headers to the request by passing a `headers` object in the parameter.
54
53
 
55
54
  ```javascript
56
- Hellotext.track('page.viewed', {}, { 'X-Custom-Header': 'value' })
55
+ Hellotext.track('page.viewed', {
56
+ headers: {
57
+ 'X-Custom-Header': 'value',
58
+ },
59
+ // event related parameters
60
+ })
57
61
  ```
58
62
 
59
63
  ### Errors
@@ -8,6 +8,7 @@ var _stimulus = require("@hotwired/stimulus");
8
8
  var _hellotext = _interopRequireDefault(require("../hellotext"));
9
9
  var _models = require("../models");
10
10
  var _forms = _interopRequireDefault(require("../api/forms"));
11
+ var _core = require("../core");
11
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
12
13
  function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
13
14
  function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
@@ -92,7 +93,14 @@ var _default = /*#__PURE__*/function (_Controller) {
92
93
  key: "completed",
93
94
  value: function completed() {
94
95
  this.form.markAsCompleted(this.formData);
95
- this.element.remove();
96
+ if (!_core.Configuration.forms.shouldShowSuccessMessage) {
97
+ return this.element.remove();
98
+ }
99
+ if (typeof _core.Configuration.forms.successMessage === 'string') {
100
+ this.element.innerHTML = _core.Configuration.forms.successMessage;
101
+ } else {
102
+ this.element.innerHTML = _hellotext.default.business.locale.forms[this.form.localeAuthKey];
103
+ }
96
104
  }
97
105
 
98
106
  // private
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.Forms = void 0;
7
+ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
+ function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
9
+ function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
10
+ function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
11
+ function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
12
+ /**
13
+ * @class Forms
14
+ * @classdesc
15
+ * Configuration for forms
16
+ * @property {Boolean} autoMount - whether to auto mount forms
17
+ * @property {Boolean|String} successMessage - whether to show success message after form completion or not
18
+ */
19
+ var Forms = /*#__PURE__*/function () {
20
+ function Forms() {
21
+ _classCallCheck(this, Forms);
22
+ }
23
+ _createClass(Forms, null, [{
24
+ key: "assign",
25
+ value:
26
+ /**
27
+ * @param {Object} props
28
+ * @param {Boolean} [props.autoMount=true] - whether to auto mount forms
29
+ * @param {Boolean|String} [props.successMessage=true] - whether to show success message after form completion or not
30
+ */
31
+ function assign(props) {
32
+ if (props) {
33
+ Object.entries(props).forEach(_ref => {
34
+ var [key, value] = _ref;
35
+ this[key] = value;
36
+ });
37
+ }
38
+ return this;
39
+ }
40
+ }, {
41
+ key: "shouldShowSuccessMessage",
42
+ get: function get() {
43
+ return this.successMessage;
44
+ }
45
+ }]);
46
+ return Forms;
47
+ }();
48
+ exports.Forms = Forms;
49
+ Forms.autoMount = true;
50
+ Forms.successMessage = true;
@@ -4,22 +4,44 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Configuration = void 0;
7
+ var _forms = require("./configuration/forms");
7
8
  function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
8
9
  function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor); } }
9
10
  function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); Object.defineProperty(Constructor, "prototype", { writable: false }); return Constructor; }
10
11
  function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
11
12
  function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
13
+ /**
14
+ * @class Configuration
15
+ * @classdesc
16
+ * Configuration for Hellotext
17
+ * @property {Boolean} [autoGenerateSession=true] - whether to auto generate session or not
18
+ * @property {String} [session] - session id
19
+ * @property {Forms} [forms] - form configuration
20
+ */
12
21
  var Configuration = /*#__PURE__*/function () {
13
22
  function Configuration() {
14
23
  _classCallCheck(this, Configuration);
15
24
  }
16
25
  _createClass(Configuration, null, [{
17
26
  key: "assign",
18
- value: function assign(props) {
27
+ value:
28
+ /**
29
+ *
30
+ * @param props
31
+ * @param {Boolean} [props.autoGenerateSession=true] - whether to auto generate session or not
32
+ * @param {String} [props.session] - session id
33
+ * @param {Object} [props.forms] - form configuration
34
+ * @returns {Configuration}
35
+ */
36
+ function assign(props) {
19
37
  if (props) {
20
38
  Object.entries(props).forEach(_ref => {
21
39
  var [key, value] = _ref;
22
- this[key] = value;
40
+ if (key === 'forms') {
41
+ this.forms = _forms.Forms.assign(value);
42
+ } else {
43
+ this[key] = value;
44
+ }
23
45
  });
24
46
  }
25
47
  return this;
@@ -35,5 +57,5 @@ var Configuration = /*#__PURE__*/function () {
35
57
  exports.Configuration = Configuration;
36
58
  Configuration.apiRoot = 'https://api.hellotext.com/v1';
37
59
  Configuration.autoGenerateSession = true;
38
- Configuration.autoMountForms = true;
39
- Configuration.session = null;
60
+ Configuration.session = null;
61
+ Configuration.forms = _forms.Forms;
package/lib/hellotext.js CHANGED
@@ -25,11 +25,6 @@ function _classPrivateFieldLooseKey(name) { return "__private_" + id++ + "_" + n
25
25
  var _session = /*#__PURE__*/_classPrivateFieldLooseKey("session");
26
26
  var _query = /*#__PURE__*/_classPrivateFieldLooseKey("query");
27
27
  var _mintAnonymousSession = /*#__PURE__*/_classPrivateFieldLooseKey("mintAnonymousSession");
28
- /**
29
- * @typedef {Object} Config
30
- * @property {Boolean} autoGenerateSession
31
- * @property {Boolean} autoMountForms
32
- */
33
28
  var Hellotext = /*#__PURE__*/function () {
34
29
  function Hellotext() {
35
30
  _classCallCheck(this, Hellotext);
@@ -40,7 +35,7 @@ var Hellotext = /*#__PURE__*/function () {
40
35
  /**
41
36
  * initialize the module.
42
37
  * @param business public business id
43
- * @param { Config } config
38
+ * @param { Configuration } config
44
39
  */
45
40
  function initialize(business, config) {
46
41
  _core.Configuration.assign(config);
@@ -69,7 +64,6 @@ var Hellotext = /*#__PURE__*/function () {
69
64
  *
70
65
  * @param { String } action a valid action name
71
66
  * @param { Object } params
72
- * @param { Object } headers additional headers to send
73
67
  * @returns {Promise<Response>}
74
68
  */
75
69
  }, {
@@ -77,18 +71,20 @@ var Hellotext = /*#__PURE__*/function () {
77
71
  value: function () {
78
72
  var _track = _asyncToGenerator(function* (action) {
79
73
  var params = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
80
- var headers = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
81
74
  if (this.notInitialized) {
82
75
  throw new _errors.NotInitializedError();
83
76
  }
77
+ var headers = _objectSpread(_objectSpread({}, params && params.headers || {}), this.headers);
78
+ var body = _objectSpread(_objectSpread({
79
+ session: this.session,
80
+ action
81
+ }, params), {}, {
82
+ url: params && params.url || window.location.href
83
+ });
84
+ delete body.headers;
84
85
  return yield _api.default.events.create({
85
- headers: _objectSpread(_objectSpread({}, headers), this.headers),
86
- body: _objectSpread(_objectSpread({
87
- session: this.session,
88
- action
89
- }, params), {}, {
90
- url: params && params.url || window.location.href
91
- })
86
+ headers,
87
+ body
92
88
  });
93
89
  });
94
90
  function track(_x) {
package/lib/locales/en.js CHANGED
@@ -11,6 +11,12 @@ var _default = {
11
11
  errors: {
12
12
  parameter_not_unique: 'This value is taken.',
13
13
  blank: 'This field is required.'
14
+ },
15
+ forms: {
16
+ phone: 'Click the link sent via SMS to verify your submission.',
17
+ email: 'Click the link sent via email to verify your submission.',
18
+ phone_and_email: 'Click the links sent via SMS and email to verify your submission.',
19
+ none: 'Your submission has been received.'
14
20
  }
15
21
  };
16
22
  exports.default = _default;
package/lib/locales/es.js CHANGED
@@ -11,6 +11,12 @@ var _default = {
11
11
  errors: {
12
12
  parameter_not_unique: 'Este valor ya está en uso.',
13
13
  blank: 'Este campo es obligatorio.'
14
+ },
15
+ forms: {
16
+ phone: 'Haga clic en el enlace enviado por SMS para verificar su envío.',
17
+ email: 'Haga clic en el enlace enviado por e-mail para verificar su envío.',
18
+ phone_and_email: 'Haga clic en los enlaces enviados por SMS y e-mail para verificar su envío.',
19
+ none: 'Su envío ha sido recibido.'
14
20
  }
15
21
  };
16
22
  exports.default = _default;
@@ -130,6 +130,20 @@ var Form = /*#__PURE__*/function () {
130
130
  get: function get() {
131
131
  return this.data.id;
132
132
  }
133
+ }, {
134
+ key: "localeAuthKey",
135
+ get: function get() {
136
+ var firstStep = this.data.steps[0];
137
+ if (firstStep.inputs.some(input => input.kind === 'email') && firstStep.inputs.some(input => input.kind === 'phone')) {
138
+ return 'phone_and_email';
139
+ } else if (firstStep.inputs.some(input => input.kind === 'email')) {
140
+ return 'email';
141
+ } else if (firstStep.inputs.some(input => input.kind === 'phone')) {
142
+ return 'phone';
143
+ } else {
144
+ return 'none';
145
+ }
146
+ }
133
147
  }, {
134
148
  key: "elementAttributes",
135
149
  get: function get() {
@@ -46,7 +46,7 @@ var FormCollection = /*#__PURE__*/function () {
46
46
  var mutation = mutations.find(mutation => mutation.type === 'childList' && mutation.addedNodes.length > 0);
47
47
  if (!mutation) return;
48
48
  var forms = Array.from(document.querySelectorAll('[data-hello-form]'));
49
- if (forms && _core.Configuration.autoMountForms) {
49
+ if (forms && _core.Configuration.forms.autoMount) {
50
50
  this.collect();
51
51
  }
52
52
  }
@@ -68,7 +68,7 @@ var FormCollection = /*#__PURE__*/function () {
68
68
  }
69
69
  this.fetching = true;
70
70
  yield Promise.all(promises).then(forms => forms.forEach(this.add)).then(() => _hellotext.default.eventEmitter.dispatch('forms:collected', this)).then(() => this.fetching = false);
71
- if (_core.Configuration.autoMountForms) {
71
+ if (_core.Configuration.forms.autoMount) {
72
72
  this.forms.forEach(form => form.mount());
73
73
  }
74
74
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hellotext/hellotext",
3
- "version": "1.7.8",
3
+ "version": "1.8.0",
4
4
  "description": "Hellotext JavaScript Client",
5
5
  "source": "src/index.js",
6
6
  "main": "lib/index.js",
@@ -5,6 +5,8 @@ import { Form } from '../models'
5
5
 
6
6
  import FormsAPI from '../api/forms'
7
7
 
8
+ import { Configuration } from '../core'
9
+
8
10
  export default class extends Controller {
9
11
  static values = {
10
12
  data: Object,
@@ -73,7 +75,16 @@ export default class extends Controller {
73
75
 
74
76
  completed() {
75
77
  this.form.markAsCompleted(this.formData)
76
- this.element.remove()
78
+
79
+ if(!Configuration.forms.shouldShowSuccessMessage) {
80
+ return this.element.remove()
81
+ }
82
+
83
+ if(typeof Configuration.forms.successMessage === 'string') {
84
+ this.element.innerHTML = Configuration.forms.successMessage
85
+ } else {
86
+ this.element.innerHTML = Hellotext.business.locale.forms[this.form.localeAuthKey]
87
+ }
77
88
  }
78
89
 
79
90
  // private
@@ -0,0 +1,32 @@
1
+ /**
2
+ * @class Forms
3
+ * @classdesc
4
+ * Configuration for forms
5
+ * @property {Boolean} autoMount - whether to auto mount forms
6
+ * @property {Boolean|String} successMessage - whether to show success message after form completion or not
7
+ */
8
+ class Forms {
9
+ static autoMount = true
10
+ static successMessage = true
11
+
12
+ /**
13
+ * @param {Object} props
14
+ * @param {Boolean} [props.autoMount=true] - whether to auto mount forms
15
+ * @param {Boolean|String} [props.successMessage=true] - whether to show success message after form completion or not
16
+ */
17
+ static assign(props) {
18
+ if(props) {
19
+ Object.entries(props).forEach(([key, value]) => {
20
+ this[key] = value
21
+ })
22
+ }
23
+
24
+ return this
25
+ }
26
+
27
+ static get shouldShowSuccessMessage() {
28
+ return this.successMessage
29
+ }
30
+ }
31
+
32
+ export { Forms }
@@ -1,13 +1,37 @@
1
+ import { Forms } from './configuration/forms'
2
+
3
+ /**
4
+ * @class Configuration
5
+ * @classdesc
6
+ * Configuration for Hellotext
7
+ * @property {Boolean} [autoGenerateSession=true] - whether to auto generate session or not
8
+ * @property {String} [session] - session id
9
+ * @property {Forms} [forms] - form configuration
10
+ */
1
11
  class Configuration {
2
12
  static apiRoot = 'https://api.hellotext.com/v1'
13
+
3
14
  static autoGenerateSession = true
4
- static autoMountForms = true
5
15
  static session = null
6
16
 
17
+ static forms = Forms
18
+
19
+ /**
20
+ *
21
+ * @param props
22
+ * @param {Boolean} [props.autoGenerateSession=true] - whether to auto generate session or not
23
+ * @param {String} [props.session] - session id
24
+ * @param {Object} [props.forms] - form configuration
25
+ * @returns {Configuration}
26
+ */
7
27
  static assign(props) {
8
- if(props) {
28
+ if (props) {
9
29
  Object.entries(props).forEach(([key, value]) => {
10
- this[key] = value
30
+ if (key === 'forms') {
31
+ this.forms = Forms.assign(value)
32
+ } else {
33
+ this[key] = value
34
+ }
11
35
  })
12
36
  }
13
37
 
@@ -19,4 +43,4 @@ class Configuration {
19
43
  }
20
44
  }
21
45
 
22
- export { Configuration }
46
+ export {Configuration}
package/src/hellotext.js CHANGED
@@ -5,11 +5,6 @@ import { Business, Query, Cookies, FormCollection } from './models'
5
5
 
6
6
  import { NotInitializedError } from './errors'
7
7
 
8
- /**
9
- * @typedef {Object} Config
10
- * @property {Boolean} autoGenerateSession
11
- * @property {Boolean} autoMountForms
12
- */
13
8
 
14
9
  class Hellotext {
15
10
  static #session
@@ -22,7 +17,7 @@ class Hellotext {
22
17
  /**
23
18
  * initialize the module.
24
19
  * @param business public business id
25
- * @param { Config } config
20
+ * @param { Configuration } config
26
21
  */
27
22
  static initialize(business, config) {
28
23
  Configuration.assign(config)
@@ -54,25 +49,30 @@ class Hellotext {
54
49
  *
55
50
  * @param { String } action a valid action name
56
51
  * @param { Object } params
57
- * @param { Object } headers additional headers to send
58
52
  * @returns {Promise<Response>}
59
53
  */
60
- static async track(action, params = {}, headers = {}) {
54
+ static async track(action, params = {}) {
61
55
  if (this.notInitialized) {
62
56
  throw new NotInitializedError()
63
57
  }
64
58
 
59
+ const headers = {
60
+ ...(params && params.headers) || {},
61
+ ...this.headers,
62
+ }
63
+
64
+ const body = {
65
+ session: this.session,
66
+ action,
67
+ ...params,
68
+ url: (params && params.url) || window.location.href,
69
+ }
70
+
71
+ delete body.headers
72
+
65
73
  return await API.events.create({
66
- headers: {
67
- ...headers,
68
- ...this.headers,
69
- },
70
- body: {
71
- session: this.session,
72
- action,
73
- ...params,
74
- url: (params && params.url) || window.location.href,
75
- },
74
+ headers,
75
+ body,
76
76
  })
77
77
  }
78
78
 
package/src/locales/en.js CHANGED
@@ -5,5 +5,11 @@ export default {
5
5
  errors: {
6
6
  parameter_not_unique: 'This value is taken.',
7
7
  blank: 'This field is required.'
8
+ },
9
+ forms: {
10
+ phone: 'Click the link sent via SMS to verify your submission.',
11
+ email: 'Click the link sent via email to verify your submission.',
12
+ phone_and_email: 'Click the links sent via SMS and email to verify your submission.',
13
+ none: 'Your submission has been received.'
8
14
  }
9
15
  }
package/src/locales/es.js CHANGED
@@ -5,5 +5,11 @@ export default {
5
5
  errors: {
6
6
  parameter_not_unique: 'Este valor ya está en uso.',
7
7
  blank: 'Este campo es obligatorio.'
8
+ },
9
+ forms: {
10
+ phone: 'Haga clic en el enlace enviado por SMS para verificar su envío.',
11
+ email: 'Haga clic en el enlace enviado por e-mail para verificar su envío.',
12
+ phone_and_email: 'Haga clic en los enlaces enviados por SMS y e-mail para verificar su envío.',
13
+ none: 'Su envío ha sido recibido.'
8
14
  }
9
15
  }
@@ -104,6 +104,20 @@ class Form {
104
104
  return this.data.id
105
105
  }
106
106
 
107
+ get localeAuthKey() {
108
+ const firstStep = this.data.steps[0]
109
+
110
+ if(firstStep.inputs.some(input => input.kind === 'email') && firstStep.inputs.some(input => input.kind === 'phone')) {
111
+ return 'phone_and_email'
112
+ } else if(firstStep.inputs.some(input => input.kind === 'email')) {
113
+ return 'email'
114
+ } else if(firstStep.inputs.some(input => input.kind === 'phone')) {
115
+ return 'phone'
116
+ } else {
117
+ return 'none'
118
+ }
119
+ }
120
+
107
121
  get elementAttributes() {
108
122
  return [
109
123
  {
@@ -30,7 +30,7 @@ class FormCollection {
30
30
 
31
31
  const forms = Array.from(document.querySelectorAll('[data-hello-form]'))
32
32
 
33
- if (forms && Configuration.autoMountForms) {
33
+ if (forms && Configuration.forms.autoMount) {
34
34
  this.collect()
35
35
  }
36
36
  }
@@ -62,7 +62,7 @@ class FormCollection {
62
62
  .then(() => Hellotext.eventEmitter.dispatch('forms:collected', this))
63
63
  .then(() => this.fetching = false)
64
64
 
65
- if (Configuration.autoMountForms) {
65
+ if (Configuration.forms.autoMount) {
66
66
  this.forms.forEach(form => form.mount())
67
67
  }
68
68
  }