@muonic/muon 0.0.2-beta.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.
Files changed (124) hide show
  1. package/.nycrc +17 -0
  2. package/.versionrc +3 -0
  3. package/CHANGELOG.md +389 -0
  4. package/components/card/index.js +1 -0
  5. package/components/card/src/card-component.js +43 -0
  6. package/components/card/src/card-styles.css +25 -0
  7. package/components/card/src/config-tokens.json +11 -0
  8. package/components/card/src/design-tokens.json +34 -0
  9. package/components/card/story.js +52 -0
  10. package/components/cta/index.js +1 -0
  11. package/components/cta/src/config-tokens.json +11 -0
  12. package/components/cta/src/cta-component.js +174 -0
  13. package/components/cta/src/cta-styles.css +105 -0
  14. package/components/cta/src/design-tokens.json +132 -0
  15. package/components/cta/story.js +99 -0
  16. package/components/detail/index.js +1 -0
  17. package/components/detail/src/config-tokens.json +11 -0
  18. package/components/detail/src/design-tokens.json +102 -0
  19. package/components/detail/src/detail-component.js +27 -0
  20. package/components/detail/src/detail-styles.css +83 -0
  21. package/components/detail/story.js +33 -0
  22. package/components/form/index.js +1 -0
  23. package/components/form/src/config-tokens.json +11 -0
  24. package/components/form/src/design-tokens.json +9 -0
  25. package/components/form/src/form-component.js +197 -0
  26. package/components/form/src/form-styles.css +10 -0
  27. package/components/form/story.js +71 -0
  28. package/components/icon/index.js +1 -0
  29. package/components/icon/src/config-tokens.json +31 -0
  30. package/components/icon/src/design-tokens.json +8 -0
  31. package/components/icon/src/icon-component.js +91 -0
  32. package/components/icon/src/icon-styles.css +26 -0
  33. package/components/icon/story.js +26 -0
  34. package/components/image/index.js +1 -0
  35. package/components/image/src/config-tokens.json +26 -0
  36. package/components/image/src/image-component.js +96 -0
  37. package/components/image/src/image-styles.css +71 -0
  38. package/components/image/story.js +31 -0
  39. package/components/inputter/index.js +1 -0
  40. package/components/inputter/src/config-tokens.json +14 -0
  41. package/components/inputter/src/design-tokens.json +308 -0
  42. package/components/inputter/src/inputter-component.js +227 -0
  43. package/components/inputter/src/inputter-styles-detail.css +59 -0
  44. package/components/inputter/src/inputter-styles.css +305 -0
  45. package/components/inputter/src/inputter-styles.slotted.css +64 -0
  46. package/components/inputter/story.js +243 -0
  47. package/css/accessibility.css +3 -0
  48. package/css/default.css +9 -0
  49. package/css/global.css +8 -0
  50. package/directives/image-loader-directive.js +116 -0
  51. package/directives/svg-loader-directive.js +94 -0
  52. package/index.js +52 -0
  53. package/mixins/card-mixin.js +27 -0
  54. package/mixins/detail-mixin.js +128 -0
  55. package/mixins/form-associate-mixin.js +36 -0
  56. package/mixins/form-element-mixin.js +378 -0
  57. package/mixins/image-holder-mixin.js +20 -0
  58. package/mixins/mask-mixin.js +159 -0
  59. package/mixins/validation-mixin.js +272 -0
  60. package/muon-element/index.js +97 -0
  61. package/package.json +72 -0
  62. package/rollup.config.mjs +30 -0
  63. package/scripts/build/storybook/index.mjs +11 -0
  64. package/scripts/build/storybook/run.mjs +47 -0
  65. package/scripts/rollup-plugins.mjs +116 -0
  66. package/scripts/serve/index.mjs +11 -0
  67. package/scripts/serve/run.mjs +27 -0
  68. package/scripts/style-dictionary.mjs +64 -0
  69. package/scripts/utils/config.mjs +30 -0
  70. package/scripts/utils/index.mjs +283 -0
  71. package/storybook/find-stories.js +36 -0
  72. package/storybook/server.config.mjs +19 -0
  73. package/storybook/stories.js +86 -0
  74. package/storybook/tokens/color.js +87 -0
  75. package/storybook/tokens/font.js +52 -0
  76. package/storybook/tokens/spacer.js +48 -0
  77. package/tests/README.md +3 -0
  78. package/tests/components/card/__snapshots__/card.test.snap.js +70 -0
  79. package/tests/components/card/card.test.js +81 -0
  80. package/tests/components/cta/__snapshots__/cta.test.snap.js +246 -0
  81. package/tests/components/cta/cta.test.js +212 -0
  82. package/tests/components/form/__snapshots__/form.test.snap.js +115 -0
  83. package/tests/components/form/form.test.js +336 -0
  84. package/tests/components/icon/__snapshots__/icon.test.snap.js +95 -0
  85. package/tests/components/icon/icon.test.js +197 -0
  86. package/tests/components/image/__snapshots__/image.test.snap.js +205 -0
  87. package/tests/components/image/image.test.js +314 -0
  88. package/tests/components/image/images/15.png +0 -0
  89. package/tests/components/image/images/150.png +0 -0
  90. package/tests/components/inputter/__snapshots__/inputter.test.snap.js +357 -0
  91. package/tests/components/inputter/inputter.test.js +427 -0
  92. package/tests/helpers/index.js +30 -0
  93. package/tests/mixins/__snapshots__/card.test.snap.js +35 -0
  94. package/tests/mixins/__snapshots__/detail.test.snap.js +237 -0
  95. package/tests/mixins/__snapshots__/form-element.test.snap.js +137 -0
  96. package/tests/mixins/__snapshots__/mask.test.snap.js +53 -0
  97. package/tests/mixins/__snapshots__/validation.test.snap.js +297 -0
  98. package/tests/mixins/card.test.js +63 -0
  99. package/tests/mixins/detail.test.js +223 -0
  100. package/tests/mixins/form-element.test.js +473 -0
  101. package/tests/mixins/mask.test.js +261 -0
  102. package/tests/mixins/muon-element.test.js +52 -0
  103. package/tests/mixins/validation.test.js +423 -0
  104. package/tests/runner/commands.mjs +19 -0
  105. package/tests/scripts/utils/card-component.js +26 -0
  106. package/tests/scripts/utils/muon.config.test.json +13 -0
  107. package/tests/scripts/utils/single.component.config.json +5 -0
  108. package/tests/scripts/utils/test-runner.mjs +1 -0
  109. package/tests/scripts/utils/utils-test.mjs +284 -0
  110. package/tests/utils/validation.functions.test.js +199 -0
  111. package/tokens/theme/color.json +482 -0
  112. package/tokens/theme/font.json +61 -0
  113. package/tokens/theme/size.json +27 -0
  114. package/tokens/theme/spacer.json +73 -0
  115. package/tokens/utils/formats/reference.js +17 -0
  116. package/tokens/utils/modular-scale.js +33 -0
  117. package/tokens/utils/templates/font-face.css.template +30 -0
  118. package/tokens/utils/transforms/color.js +27 -0
  119. package/tokens/utils/transforms/string.js +6 -0
  120. package/tokens/utils/validation.json +76 -0
  121. package/utils/scroll/index.js +31 -0
  122. package/utils/validation/index.js +205 -0
  123. package/web-test-runner.browserstack.config.mjs +123 -0
  124. package/web-test-runner.config.mjs +44 -0
@@ -0,0 +1,36 @@
1
+ import { dedupeMixin } from '@muonic/muon';
2
+
3
+ /**
4
+ * A mixin to associate the component to the enclosing native form.
5
+ *
6
+ * @mixin FormElementMixin
7
+ */
8
+
9
+ export const FormAssociateMixin = dedupeMixin((superClass) =>
10
+ class FormAssociateMixinClass extends superClass {
11
+
12
+ static get properties() {
13
+ return {
14
+ _internals: {
15
+ type: Object,
16
+ state: true
17
+ }
18
+ };
19
+ }
20
+
21
+ static get formAssociated() {
22
+ return true;
23
+ }
24
+
25
+ constructor() {
26
+ super();
27
+ this._internals = this.attachInternals();
28
+ }
29
+
30
+ updated(changedProperties) {
31
+ if (changedProperties.has('value')) {
32
+ this._internals.setFormValue(this.value);
33
+ }
34
+ }
35
+ }
36
+ );
@@ -0,0 +1,378 @@
1
+ import { html, MuonElement, dedupeMixin } from '@muonic/muon';
2
+
3
+ /**
4
+ * A mixin to hold base setup for a form element.
5
+ *
6
+ * @mixin FormElementMixin
7
+ */
8
+
9
+ export const FormElementMixin = dedupeMixin((superClass) =>
10
+ class FormElementMixinClass extends superClass {
11
+
12
+ static get properties() {
13
+ return {
14
+ name: {
15
+ type: String,
16
+ reflect: true
17
+ },
18
+
19
+ value: {
20
+ type: String,
21
+ reflect: true
22
+ },
23
+
24
+ heading: {
25
+ type: String
26
+ },
27
+
28
+ labelID: {
29
+ type: String
30
+ },
31
+
32
+ _inputElement: {
33
+ type: Boolean,
34
+ state: true
35
+ },
36
+
37
+ _id: {
38
+ type: String,
39
+ state: true
40
+ },
41
+
42
+ _inputTypes: {
43
+ type: Object,
44
+ state: true
45
+ }
46
+ };
47
+ }
48
+
49
+ constructor() {
50
+ super();
51
+
52
+ this._inputTypes = {
53
+ RADIO: 'radio',
54
+ CHECKBOX: 'checkbox',
55
+ SELECT: 'select',
56
+ SEARCH: 'search',
57
+ DATE: 'date',
58
+ SINGLE: 'single'
59
+ };
60
+
61
+ this.value = '';
62
+ this.labelID = '';
63
+ this.heading = '';
64
+ this._inputElement = true;
65
+ this._id = `${this._randomId}-input`;
66
+ }
67
+
68
+ static get shadowRootOptions() {
69
+ return { ...MuonElement.shadowRootOptions, delegatesFocus: true };
70
+ }
71
+
72
+ /**
73
+ * A method to generate random Id for html elements.
74
+ *
75
+ * @returns {string} - Random generated id.
76
+ * @protected
77
+ */
78
+ get _randomId() {
79
+ return `mnid-${Math.random().toString(36).substring(2, 15)}`;
80
+ }
81
+
82
+ /**
83
+ * A method to get input type from the slotted html form elements.
84
+ *
85
+ * @returns {string} Input type.
86
+ * @protected
87
+ */
88
+ get _inputType() {
89
+ const inputType = this.querySelector('input')?.type;
90
+ if (inputType && Object.values(this._inputTypes).indexOf(inputType) > -1) {
91
+ return inputType;
92
+ } else if (this.querySelector('select')) {
93
+ return this._inputTypes.SELECT;
94
+ }
95
+ return this._inputTypes.SINGLE;
96
+ }
97
+
98
+ firstUpdated() {
99
+ super.firstUpdated();
100
+ if (!this.name) {
101
+ this.name = this._slottedInputs?.[0]?.name ?? '';
102
+ }
103
+ if (!this._isMultiple) {
104
+ if (this.labelID?.length > 0) {
105
+ this._slottedInputs.forEach((slot) => {
106
+ slot.setAttribute('aria-labelledby', this.labelID);
107
+ });
108
+ } else {
109
+ this._id = this._slottedInputs[0]?.getAttribute('id') || this._id;
110
+ this._slottedInputs[0]?.setAttribute('id', this._id);
111
+ this._slottedLabel?.setAttribute('for', this._id);
112
+ }
113
+ }
114
+ this.__syncValue(true);
115
+
116
+ this._boundChangeEvent = (changeEvent) => {
117
+ this._onChange(changeEvent);
118
+ };
119
+
120
+ this._boundBlurEvent = (blurEvent) => {
121
+ this._onBlur(blurEvent);
122
+ };
123
+
124
+ this._boundInputEvent = (inputEvent) => {
125
+ this._onInput(inputEvent);
126
+ };
127
+
128
+ this._slottedInputs.forEach((input) => {
129
+ input.addEventListener('change', this._boundChangeEvent);
130
+ input.addEventListener('blur', this._boundBlurEvent);
131
+ input.addEventListener('input', this._boundInputEvent);
132
+ });
133
+ }
134
+
135
+ focus() {
136
+ this.updateComplete.then(() => {
137
+ this._slottedInputs[0].focus();
138
+ });
139
+ }
140
+
141
+ reset() {
142
+ this.value = this._slottedValue; // get values from slotted html form elements
143
+ }
144
+ /**
145
+ * A method to sync the value property of the component with value of slotted input elements.
146
+ *
147
+ * @param {boolean} firstSync - If first time syncing values.
148
+ * @returns {void}
149
+ * @private
150
+ */
151
+ __syncValue(firstSync) {
152
+ if (this._isMultiple) { //Check when component has slotted multi-input
153
+ if (!this.value && this.__checkedInput) {
154
+ // If component has null value and slotted input has checked value(s),
155
+ // assign the value of checked slotted input(s) to value property of the component.
156
+ this.value = this.__checkedInput;
157
+ } else if (this.value && !this.__checkedInput) {
158
+ // If component has not null value and slotted input has no value(s) checked,
159
+ // mark the multi-input as checked if its value(s) is part of component value property.
160
+ const values = this.value.toString().split(',');
161
+ this._slottedInputs.filter((input) => {
162
+ return values.includes(input.value) && !input.checked;
163
+ }).forEach((input) => {
164
+ input.checked = true;
165
+ if (firstSync) {
166
+ input.defaultChecked = true;
167
+ }
168
+ });
169
+ }
170
+ } else { //When component has single-input slot
171
+ // eslint-disable-next-line no-lonely-if
172
+ if (!this.value && this._slottedInputs?.[0]?.value) {
173
+ // If component has null value and slotted input has value,
174
+ // assign the value of slotted inputs to value property of the component.
175
+ this.value = this._processFormChangeValue(this._slottedInputs[0].value);
176
+ } else if (this.value && !this._slottedInputs[0].value) {
177
+ // If component has not null value and slotted input has null value,
178
+ // assign the value of the component to value of the slotted input.
179
+ this._slottedInputs[0].value = this.value;
180
+
181
+ if (firstSync) {
182
+ this._slottedInputs[0].defaultValue = this.value;
183
+ }
184
+ }
185
+ }
186
+ }
187
+
188
+ /**
189
+ * A method to get all slotted HTML form elements.
190
+ *
191
+ * @protected
192
+ * @override
193
+ */
194
+ get _slottedInputs() {
195
+ const slot = this.querySelectorAll('input, textarea, select');
196
+ return Array.from(slot);
197
+ }
198
+
199
+ /**
200
+ * A method to get slotted label element.
201
+ *
202
+ * @protected
203
+ * @override
204
+ */
205
+ get _slottedLabel() {
206
+ return this.querySelector('label[slot="label"]');
207
+ }
208
+
209
+ /**
210
+ * A method to get slotted element value.
211
+ *
212
+ * @protected
213
+ * @override
214
+ */
215
+ get _slottedValue() {
216
+ return this._isMultiple ? this.__checkedInput : this._slottedInputs[0].value;
217
+ }
218
+
219
+ /**
220
+ * A method to determine if slotted form element has multiple option.
221
+ *
222
+ * @protected
223
+ * @override
224
+ */
225
+ get _isMultiple() {
226
+ return this._inputType === this._inputTypes.RADIO || this._inputType === this._inputTypes.CHECKBOX;
227
+ }
228
+
229
+ /**
230
+ * A method to determine if slotted form element has only single option.
231
+ *
232
+ * @protected
233
+ * @override
234
+ */
235
+ get _isSingle() {
236
+ return !(this._isMultiple || this._isSelect);
237
+ }
238
+
239
+ /**
240
+ * A method to determine if slotted form element has only select option.
241
+ *
242
+ * @protected
243
+ * @override
244
+ */
245
+ get _isSelect() {
246
+ return this._inputType === this._inputTypes.SELECT;
247
+ }
248
+
249
+ /**
250
+ * A method to handle `change` event from the slotted html elements.
251
+ *
252
+ * @protected
253
+ * @override
254
+ */
255
+ _onChange(changeEvent) {
256
+ changeEvent.stopPropagation();
257
+ changeEvent.preventDefault();
258
+ this.value = this._processFormChangeValue(this._slottedValue);
259
+ this._fireChangeEvent();
260
+ }
261
+
262
+ /**
263
+ * A method to handle `blur` event from the slotted html elements.
264
+ *
265
+ * @protected
266
+ * @override
267
+ */
268
+ _onBlur(blurEvent) {
269
+ blurEvent.stopPropagation();
270
+ }
271
+
272
+ /**
273
+ * A method to handle `input` event from the slotted html elements.
274
+ *
275
+ * @protected
276
+ * @override
277
+ */
278
+ _onInput(inputEvent) {
279
+ inputEvent.stopPropagation();
280
+ inputEvent.preventDefault();
281
+ }
282
+
283
+ /**
284
+ * A method to fire the 'change' custom event from the form element.
285
+ *
286
+ * @protected
287
+ * @override
288
+ */
289
+ _fireChangeEvent() {
290
+ this.dispatchEvent(
291
+ new CustomEvent('change', {
292
+ bubbles: true,
293
+ cancelable: false,
294
+ detail: {
295
+ value: this.value
296
+ }
297
+ })
298
+ );
299
+ }
300
+
301
+ /**
302
+ * A method to remove whitespace from the form element value.
303
+ *
304
+ * @param {string} value - Form element value to be trimmed.
305
+ * @returns {string} - Trimmed value.
306
+ * @private
307
+ */
308
+ __removeWhitespace(value) {
309
+ return this._isSingle ? value.trim() : value;
310
+ }
311
+
312
+ /**
313
+ * A method to process form element value before assigning to 'value' property.
314
+ *
315
+ * @param {string} value - Form elment value to be processed.
316
+ * @returns {string} - Processed value.
317
+ * @protected
318
+ * @override
319
+ */
320
+ _processFormChangeValue(value) {
321
+ return this.__removeWhitespace(value);
322
+ }
323
+
324
+ /**
325
+ * A method to get values of checked form element.
326
+ *
327
+ * @returns {string} - Array of selected values for multiple option input.
328
+ * @private
329
+ */
330
+ get __checkedInput() {
331
+ return Array.from(this.querySelectorAll('input')).filter((input) => {
332
+ return input.checked;
333
+ }).map((input) => {
334
+ return input.value;
335
+ }).toString();
336
+ }
337
+
338
+ /**
339
+ * A method to get anonymous slot template to hold html form elements.
340
+ *
341
+ * @protected
342
+ * @override
343
+ */
344
+ get _addSlottedContent() {
345
+ return html`<slot></slot>`;
346
+ }
347
+
348
+ /**
349
+ * A method to get label slot template to hold html form element label.
350
+ *
351
+ * @protected
352
+ * @override
353
+ */
354
+ get _addLabel() {
355
+ return this.labelID.length === 0 ? html`<slot name="label"></slot>` : html``;
356
+ }
357
+
358
+ /**
359
+ * A method to get heading slot template to hold html form element heading.
360
+ *
361
+ * @protected
362
+ * @override
363
+ */
364
+ get _addHeading() {
365
+ return html`<span class="input-heading">${this.heading}</span>`;
366
+ }
367
+
368
+ /**
369
+ * A method to get standard template for type `standard`.
370
+ *
371
+ * @protected
372
+ * @override
373
+ */
374
+ get standardTemplate() {
375
+ return this._addSlottedContent;
376
+ }
377
+ }
378
+ );
@@ -0,0 +1,20 @@
1
+ import { dedupeMixin } from '@muonic/muon';
2
+
3
+ export const ImageHolderMixin = dedupeMixin((superClass) =>
4
+ class ImageHolderdMixinClass extends superClass {
5
+
6
+ static get properties() {
7
+ return {
8
+ image: {
9
+ type: String
10
+ },
11
+ alt: {
12
+ type: String
13
+ },
14
+ background: {
15
+ type: Boolean
16
+ }
17
+ };
18
+ }
19
+ }
20
+ );
@@ -0,0 +1,159 @@
1
+ import { html, ifDefined, dedupeMixin } from '@muonic/muon';
2
+ import { FormElementMixin } from '@muon/mixins/form-element-mixin';
3
+
4
+ /**
5
+ * A mixin to enable mask and separator features to a form element.
6
+ * `mask` property is supported for input of type text, date, tel.
7
+ * `separator` property is supported for input of type text, date, tel.
8
+ *
9
+ * @mixin
10
+ */
11
+
12
+ export const MaskMixin = dedupeMixin((superclass) =>
13
+ class MaskMixinClass extends FormElementMixin(superclass) {
14
+ static get properties() {
15
+ return {
16
+ mask: {
17
+ type: String
18
+ },
19
+
20
+ separator: {
21
+ type: String
22
+ }
23
+ };
24
+ }
25
+
26
+ constructor() {
27
+ super();
28
+
29
+ this.mask = '';
30
+ this.separator = '';
31
+ }
32
+
33
+ firstUpdated() {
34
+ super.firstUpdated();
35
+
36
+ if (this.mask) {
37
+ this._slottedInputs.map((input) => {
38
+ input.setAttribute('maxlength', this.mask.length);
39
+ });
40
+ }
41
+ }
42
+
43
+ /**
44
+ * A method to process the form element value in response to `input` event.
45
+ *
46
+ * @param {string} value - Value to be processed with mask and separator.
47
+ * @returns {string} - Processed value.
48
+ * @protected
49
+ */
50
+ _processMaskInputValue(value) {
51
+ if (!this._isSingle) {
52
+ return value;
53
+ }
54
+ const inputElement = this._slottedInputs[0];
55
+ if (ifDefined(this.separator)) {
56
+ value = this.updateValueAndCursor(inputElement);
57
+ } else {
58
+ value = inputElement.value;
59
+ }
60
+ return value;
61
+ }
62
+
63
+ /**
64
+ * A method to process the form element value in response to `change` event.
65
+ *
66
+ * @param {string} value - Value to be processed with mask and separator.
67
+ * @returns {string} - Processed value.
68
+ * @protected
69
+ */
70
+ _processMaskChangeValue(value) {
71
+ if (ifDefined(this.separator)) {
72
+ value = this.formatWithMaskAndSeparator(value);
73
+ this._slottedInputs[0].value = value;
74
+ }
75
+ return value;
76
+ }
77
+
78
+ /**
79
+ * A method to update the form element value with separator in adjusted indices and cursor position.
80
+ *
81
+ * @param {HTMLElement} input - HTMLInputElement value to be updated with seperators.
82
+ * @returns {string} - Updated form element value.
83
+ */
84
+ updateValueAndCursor(input) {
85
+ let value = input.value;
86
+ let cursor = input.selectionStart;
87
+ const diff = this.value.length - value.length;
88
+
89
+ if (diff > 0 && this.mask.charAt(cursor) === this.separator) {
90
+ value = value.slice(0, cursor - 1) + (cursor < value.length ? value.slice(cursor) : '');
91
+ cursor -= 1;
92
+ }
93
+ const formattedValue = this.formatWithMaskAndSeparator(value);
94
+ input.value = formattedValue;
95
+
96
+ if (this.mask.charAt(cursor) === this.separator) {
97
+ cursor += 1;
98
+ }
99
+ this.updateComplete.then(() => {
100
+ input.setSelectionRange(cursor, cursor);
101
+ });
102
+
103
+ return formattedValue;
104
+ }
105
+
106
+ /**
107
+ * A method to format the form element value with separator adjusted to correct indices
108
+ * after editing the form element value.
109
+ *
110
+ * @param {string} value - Value of the form element.
111
+ * @returns {string} - Value with adjusted separator in correct indices.
112
+ */
113
+ formatWithMaskAndSeparator(value) {
114
+ const formattedValue = this.__formatInputWithoutSeparator(value);
115
+ const parts = this.mask.split(this.separator);
116
+ let processedValue = '';
117
+ let length = 0;
118
+ let currentLength = 0;
119
+
120
+ for (let i = 0; i < parts.length && length < formattedValue.length; i++) {
121
+ const remainingLength = formattedValue.length - length;
122
+ const splitPoint = remainingLength > parts[i].length ? parts[i].length : remainingLength;
123
+
124
+ processedValue += formattedValue.substr(length, splitPoint);
125
+ currentLength += parts[i].length;
126
+
127
+ if (i < (parts.length - 1) && processedValue.length === currentLength) {
128
+ processedValue += this.separator;
129
+ currentLength += 1;
130
+ }
131
+
132
+ length += parts[i].length;
133
+ }
134
+
135
+ return processedValue;
136
+ }
137
+
138
+ /**
139
+ * A method to remove separator from the value of the form element.
140
+ *
141
+ * @param {string} value - Form element value.
142
+ * @returns {string} - Value with separator removed.
143
+ */
144
+ __formatInputWithoutSeparator(value) {
145
+ return value.split(this.separator).join('');
146
+ }
147
+
148
+ get _addMask() {
149
+ if (this.mask && this._isSingle) {
150
+ const length = this.value ? this.value.length : 0;
151
+ let updatedMask = new Array(length + 1).join(' ');
152
+ updatedMask += this.mask.slice(length);
153
+ return html`<div aria-hidden="true" class="input-mask">${updatedMask}</div>`;
154
+ } else {
155
+ return undefined;
156
+ }
157
+ }
158
+ }
159
+ );