@teddy-dev/frontend 1.0.1

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 (112) hide show
  1. package/algolia/algolia-loader.js +56 -0
  2. package/algolia/algolia-search.js +222 -0
  3. package/auth/teddy-auth-login.js +29 -0
  4. package/auth/teddy-auth-profile.js +58 -0
  5. package/auth/teddy-auth-register.js +52 -0
  6. package/auth/teddy-auth-reset.js +39 -0
  7. package/auth/teddy-auth.js +92 -0
  8. package/bantoa/bantoa-product.js +64 -0
  9. package/bantoa/bantoa-search.js +46 -0
  10. package/bantoa/bantoa-stylemix.js +43 -0
  11. package/bantoa/bantoa.js +21 -0
  12. package/cart/teddy-cart-controller.js +163 -0
  13. package/cart/teddy-cart-customer.js +86 -0
  14. package/cart/teddy-cart-discounts.js +55 -0
  15. package/cart/teddy-cart-promo-apply.js +24 -0
  16. package/cart/teddy-cart-promo-error.js +38 -0
  17. package/cart/teddy-cart-promo-loading.js +20 -0
  18. package/cart/teddy-cart-promo.js +96 -0
  19. package/components/mc-btn.js +38 -0
  20. package/components/mc-card-render.js +33 -0
  21. package/components/mc-cart-counter.js +14 -0
  22. package/components/mc-cart-error.js +35 -0
  23. package/components/mc-cart-quantity.js +43 -0
  24. package/components/mc-cart-remove.js +32 -0
  25. package/components/mc-copy.js +33 -0
  26. package/components/mc-element.js +84 -0
  27. package/components/mc-form-errors.js +35 -0
  28. package/components/mc-form-success.js +31 -0
  29. package/components/mc-form.js +223 -0
  30. package/components/mc-input-area.js +13 -0
  31. package/components/mc-input-checkbox-group.js +52 -0
  32. package/components/mc-input-checkbox.js +12 -0
  33. package/components/mc-input-password.js +39 -0
  34. package/components/mc-input-places.js +43 -0
  35. package/components/mc-input-quantity.js +43 -0
  36. package/components/mc-input-select.js +14 -0
  37. package/components/mc-input-text.js +12 -0
  38. package/components/mc-input.js +137 -0
  39. package/components/mc-loader.js +21 -0
  40. package/components/mc-modal.js +69 -0
  41. package/components/mc-password-eye.js +24 -0
  42. package/components/mc-password-tips.js +60 -0
  43. package/components/mc-qrcode.js +41 -0
  44. package/components/mc-range.js +108 -0
  45. package/components/mc-read-more.js +56 -0
  46. package/components/mc-recommended.js +50 -0
  47. package/components/mc-referrer.js +20 -0
  48. package/components/mc-splash-controller.js +32 -0
  49. package/components/mc-splash-link.js +65 -0
  50. package/components/mc-stoq.js +30 -0
  51. package/components/mc-swiper.js +333 -0
  52. package/components/mc-video.js +61 -0
  53. package/css/bootstrap-lg.css +2762 -0
  54. package/css/bootstrap-lg.min.css +1 -0
  55. package/css/bootstrap-md.css +2762 -0
  56. package/css/bootstrap-md.min.css +1 -0
  57. package/css/bootstrap-sm.css +2762 -0
  58. package/css/bootstrap-sm.min.css +1 -0
  59. package/css/bootstrap-xl.css +2790 -0
  60. package/css/bootstrap-xl.min.css +1 -0
  61. package/css/bootstrap-xxl.css +2762 -0
  62. package/css/bootstrap-xxl.min.css +1 -0
  63. package/css/bootstrap.css +9824 -0
  64. package/css/bootstrap.min.css +5 -0
  65. package/css/mc-form-errors.css +3 -0
  66. package/css/mc-loader.css +6 -0
  67. package/css/mc-password-eye.css +6 -0
  68. package/css/mc-password-tips.css +6 -0
  69. package/css/mc-read-more.css +14 -0
  70. package/css/mc-video.css +4 -0
  71. package/css/mc-wishlist-hero-btn.css +7 -0
  72. package/loader.js +110 -0
  73. package/loyalty/teddy-loyalty-create.js +40 -0
  74. package/loyalty/teddy-loyalty-redeem.js +38 -0
  75. package/loyalty/teddy-loyalty.js +214 -0
  76. package/package.json +20 -0
  77. package/res/mc-events.js +43 -0
  78. package/res/mc-shopify.js +439 -0
  79. package/res/mc-utils.js +119 -0
  80. package/res/mc-vue.js +9350 -0
  81. package/returns/teddy-return-iban.js +115 -0
  82. package/returns/teddy-return-list.js +165 -0
  83. package/returns/teddy-return-request.js +353 -0
  84. package/scripts/publish-store.js +62 -0
  85. package/test/auth-login-error.json +4 -0
  86. package/test/auth-login-success.json +13 -0
  87. package/test/auth-password-change-error.json +4 -0
  88. package/test/auth-password-change-success.json +3 -0
  89. package/test/auth-register-error.json +4 -0
  90. package/test/auth-register-success.json +12 -0
  91. package/test/auth-reset-error.json +4 -0
  92. package/test/auth-reset-success.json +3 -0
  93. package/test/loyalty-error.json +4 -0
  94. package/test/loyalty-noinfo.json +18 -0
  95. package/test/loyalty-redeem-error.json +4 -0
  96. package/test/loyalty-redeem-success.json +11 -0
  97. package/test/loyalty-success.json +143 -0
  98. package/test/returns-create-success.json +1 -0
  99. package/test/returns-get-success.json +35 -0
  100. package/test/returns-get-tracking.json +30 -0
  101. package/test/returns-list-empty.json +4 -0
  102. package/test/returns-list-success.json +59 -0
  103. package/test/returns-search-manual.json +67 -0
  104. package/test/returns-search-success.json +76 -0
  105. package/test/wishlist-error.json +4 -0
  106. package/test/wishlist-success.json +3 -0
  107. package/wishlist/teddy-wishlist-btn.js +55 -0
  108. package/wishlist/teddy-wishlist-clear.js +18 -0
  109. package/wishlist/teddy-wishlist-counter.js +35 -0
  110. package/wishlist/teddy-wishlist-item.js +46 -0
  111. package/wishlist/teddy-wishlist-page.js +59 -0
  112. package/wishlist/teddy-wishlist.js +131 -0
@@ -0,0 +1,43 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./components/mc-input-quantity.js', false);
4
+ await loadComponent('./res/mc-shopify.js', false);
5
+
6
+ class McCartQuantity extends McElement {
7
+
8
+ connectedCallback() {
9
+ if(!this.hasAttribute('data-key')) {
10
+ console.error('McCartQuantity component requires a data-key attribute.');
11
+ return;
12
+ }
13
+
14
+ setTimeout(() => {
15
+ const input = this.querySelector('mc-input-quantity');
16
+ if(!input) {
17
+ console.error('McCartQuantity component requires an mc-input-quantity element inside.');
18
+ return;
19
+ }
20
+ input.addEventListener(MCEVENTS.QUANTITY_CHANGED, this.changeItem.bind(this));
21
+ });
22
+ }
23
+
24
+ changeItem = (e) => {
25
+ console.log('McCartQuantity changeItem', e.detail);
26
+ const key = this.getAttribute('data-key');
27
+ if (!key) return;
28
+
29
+ const quantity = parseInt(e.detail.value);
30
+ if (!quantity || isNaN(quantity)) return;
31
+
32
+ McShopify.updateCartLine({
33
+ id: key,
34
+ quantity: quantity
35
+ });
36
+ }
37
+ }
38
+
39
+ if (!customElements.get('mc-cart-quantity')) {
40
+ customElements.define('mc-cart-quantity', McCartQuantity);
41
+ }
42
+
43
+ window.McCartQuantity = McCartQuantity;
@@ -0,0 +1,32 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+ await loadComponent('./res/mc-shopify.js', false);
3
+
4
+ class McCartRemove extends McElement {
5
+
6
+ connectedCallback() {
7
+ if(!this.hasAttribute('data-key')) {
8
+ console.error('McCartRemove component requires a data-key attribute.');
9
+ return;
10
+ }
11
+ this.addEventListener('click', () => {
12
+ this.removeItem();
13
+ });
14
+ }
15
+
16
+ removeItem = () => {
17
+ const key = this.getAttribute('data-key');
18
+ if (!key) return;
19
+
20
+ McShopify.updateCartLine({
21
+ id: key,
22
+ quantity: 0
23
+ });
24
+
25
+ }
26
+ }
27
+
28
+ if (!customElements.get('mc-cart-remove')) {
29
+ customElements.define('mc-cart-remove', McCartRemove);
30
+ }
31
+
32
+ window.McCartRemove = McCartRemove;
@@ -0,0 +1,33 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McCopy extends McElement {
4
+ text; toast;
5
+
6
+ connectedCallback() {
7
+ this.text = this.dataset.text || this.textContent;
8
+ if(!this.text) { console.error('McCopy: No text to copy'); return; }
9
+
10
+ this.addEventListener('click', () => this.copy());
11
+ }
12
+
13
+ copy = () => {
14
+ navigator.clipboard.writeText(this.text);
15
+ const toastElement = document.querySelector(this.dataset.toast);
16
+ const popoverElement = document.querySelector(this.dataset.popover);
17
+ console.log(toastElement);
18
+ if (toastElement) {
19
+ const toast = bootstrap.Toast.getOrCreateInstance(toastElement);
20
+ toast.show();
21
+ }
22
+ if (popoverElement) {
23
+ const popover = bootstrap.Popover.getOrCreateInstance(popoverElement);
24
+ popover.show();
25
+ }
26
+ }
27
+
28
+ }
29
+ if (!window.customElements.get("mc-copy")) {
30
+ window.customElements.define("mc-copy", McCopy);
31
+ }
32
+ window.McCopy = McCopy;
33
+ export default McCopy;
@@ -0,0 +1,84 @@
1
+ // Questa classe base `McElement` estende HTMLElement e fornisce funzionalità comuni per web component personalizzati.
2
+ // Lo scopo principale è essere estesa da altri componenti custom che necessitano di ricaricare dinamicamente il proprio contenuto tramite chiamate HTTP.
3
+ // Non richiede data attributes o elementi HTML specifici: i metodi sono pensati per essere usati dalle sottoclassi.
4
+
5
+ import '../res/mc-events.js';
6
+ await loadComponent('./res/mc-utils.js', false);
7
+ await loadComponent('./res/mc-shopify.js', false);
8
+
9
+ class McElement extends HTMLElement {
10
+
11
+ // Metodo per ricaricare dinamicamente il contenuto dell'elemento tramite una richiesta GET.
12
+ // Parametri:
13
+ // - url: URL da cui caricare il nuovo contenuto (default: pagina corrente)
14
+ // - onSuccess: funzione callback chiamata in caso di successo
15
+ // - onError: funzione callback chiamata in caso di errore
16
+ // - onComplete: funzione callback chiamata al termine della richiesta
17
+ reload = ({
18
+ url=location.href, // URL da cui caricare il nuovo contenuto (default: pagina corrente)
19
+ onSuccess, // Funzione da chiamare in caso di successo
20
+ onError, // Funzione da chiamare in caso di errore
21
+ onComplete // Funzione da chiamare al termine della richiesta
22
+ }) => {
23
+ if(!url || typeof url !== 'string') { console.error('McElement.reload: Il parametro "url" deve essere una stringa valida.'); return; }
24
+
25
+ axios({
26
+ url: url,
27
+ method: 'GET',
28
+ }).then(response => {
29
+ // Aggiorna il contenuto dell'elemento usando la funzione utility McUtils.reloadElement
30
+ McUtils.reloadElement(response.data, this, this.getSelector());
31
+ if(typeof onSuccess === 'function') { onSuccess(response.data); }
32
+ }).catch(error => {
33
+ if(typeof onError === 'function') { onError(error); }
34
+ }).finally(() => {
35
+ if(typeof onComplete === 'function') { onComplete(); }
36
+ });
37
+ }
38
+
39
+ // Restituisce un selettore CSS univoco per questo elemento (id, classi e attributi)
40
+ getSelector = () => {
41
+ if(this.id) {
42
+ return `#${this.id}`;
43
+ }
44
+ let selector = this.tagName.toLowerCase();
45
+ if(this.classList.length > 0) {
46
+ selector += this.classList.map(c => `.${c}`).join('');
47
+ }
48
+ if(this.attributes.length > 0) {
49
+ selector += Array.from(this.attributes).map(attr => `[${attr.name}="${attr.value}"]`).join('');
50
+ }
51
+ return selector;
52
+ }
53
+
54
+ activate = () => {
55
+ this.classList.add('active'); // Aggiunge la classe 'active' per lo stile
56
+ McShopify.customEvent(MCEVENTS.EL_ACTIVATED, null, this);
57
+ }
58
+
59
+ deactivate = () => {
60
+ this.classList.remove('active'); // Rimuove la classe 'active' per lo stile
61
+ McShopify.customEvent(MCEVENTS.EL_DEACTIVATED, null, this);
62
+ }
63
+
64
+ toggle = () => {
65
+ this.isActive() ? this.deactivate() : this.activate();
66
+ }
67
+
68
+ isActive = () => {
69
+ return this.classList.contains('active');
70
+ }
71
+
72
+ constructor() {
73
+ super(); // Chiama il costruttore della classe base HTMLElement
74
+ if(this.dataset.active != undefined)
75
+ this.activate(); // Attiva l'elemento se il data attribute "active" è presente
76
+ else
77
+ this.deactivate(); // Altrimenti lo disattiva
78
+ }
79
+
80
+ }
81
+
82
+ // Espone la classe McElement come globale e come modulo, pronta per essere estesa da altri web component
83
+ window.McElement = McElement;
84
+ export default McElement;
@@ -0,0 +1,35 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+ await loadComponent('./res/mc-utils.js', false);
3
+
4
+ class McFormErrors extends McElement {
5
+
6
+ connectedCallback() {
7
+ this.checkErrors();
8
+ }
9
+
10
+ checkErrors = () => {
11
+ if (this.innerHTML.length > 0) {
12
+ this.activate();
13
+ } else {
14
+ this.deactivate();
15
+ }
16
+ }
17
+
18
+ clear = () => {
19
+ this.innerHTML = '';
20
+ this.deactivate();
21
+ }
22
+
23
+ showError = (content) => {
24
+ this.innerHTML = content;
25
+ this.activate();
26
+ }
27
+ }
28
+
29
+ if (!customElements.get('mc-form-errors')) {
30
+ customElements.define('mc-form-errors', McFormErrors);
31
+ McUtils.addCss(`https://cdn.jsdelivr.net/npm/teddy-frontend@${theme.version}/css/mc-form-errors.css`);
32
+ }
33
+
34
+ window.McFormErrors = McFormErrors;
35
+ export default McFormErrors;
@@ -0,0 +1,31 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McFormSuccess extends McElement {
4
+
5
+ connectedCallback() {
6
+ this.checkMessages();
7
+ }
8
+
9
+ checkMessages = () => {
10
+ if (this.innerHTML.length > 0) {
11
+ this.activate();
12
+ } else {
13
+ this.deactivate();
14
+ }
15
+ }
16
+
17
+ clear = () => {
18
+ this.innerHTML = '';
19
+ this.deactivate();
20
+ }
21
+
22
+ showMessage = (content) => {
23
+ this.innerHTML = content;
24
+ this.activate();
25
+ }
26
+ }
27
+
28
+ if (!customElements.get('mc-form-success')) {
29
+ customElements.define('mc-form-success', McFormSuccess);
30
+ }
31
+ window.McFormSuccess = McFormSuccess;
@@ -0,0 +1,223 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./res/mc-utils.js', false);
4
+ await loadComponent('./res/mc-shopify.js', false);
5
+ await loadComponent('./components/mc-form-errors.js', false); // Carica il componente Input
6
+ await loadComponent('./components/mc-input.js', false); // Carica il componente Input
7
+
8
+ class McForm extends McElement {
9
+ form; inputs; isValid; buttons; data; options; errors;
10
+
11
+
12
+ // Metodo chiamato automaticamente quando l'elemento viene aggiunto al DOM
13
+ connectedCallback() {
14
+ this.init(); // Inizializza il form
15
+ }
16
+
17
+ // Inizializza il form e i suoi elementi
18
+ init = () => {
19
+ this.form = this.querySelector('form'); // Seleziona il form
20
+ if (!this.form) { console.error('McForm: No form element found'); return; }
21
+
22
+ this.inputs = this.querySelectorAll('mc-input-text, mc-input-checkbox, mc-input-select, mc-input-area, mc-input-checkbox-group, mc-input-password'); // Seleziona gli input
23
+ this.inputs = [...this.inputs, ...this.form.querySelectorAll(`mc-input-text[form="${this.form.id}"], mc-input-checkbox[form="${this.form.id}"], mc-input-select[form="${this.form.id}"], mc-input-area[form="${this.form.id}"], mc-input-checkbox-group[form="${this.form.id}"], mc-input-password[form="${this.form.id}"]`)]; // Aggiunge gli input del form
24
+ if (this.inputs.length === 0) { console.error('McForm: No input elements found'); return; }
25
+
26
+ this.buttons = this.querySelectorAll(`[data-submit]`); // Seleziona i pulsanti di submit
27
+ this.buttons = [...this.buttons, ...document.querySelectorAll(`[data-submit][form="${this.form.id}"]`)];
28
+
29
+ this.errors = this.querySelector('mc-form-errors'); // Seleziona il container degli errori
30
+ if (!this.errors) { console.error('McForm: No mc-form-errors element found'); return; }
31
+
32
+ this.form.addEventListener(MCEVENTS.FORM_AUTOSUBMIT, this.submit.bind(this));
33
+ this.handleButtons(); // Gestisce i pulsanti
34
+ }
35
+
36
+ // Gestisce i pulsanti di submit
37
+ handleButtons = () => {
38
+ this.buttons.forEach(button => {
39
+ button.addEventListener('click', this.submit.bind(this)); // Aggiunge un listener per il click
40
+ });
41
+ if (this.dataset.ajax) {
42
+ // Se il form è configurato per l'invio in AJAX, previene il comportamento predefinito
43
+ this.form.addEventListener('submit', (e) => {
44
+ e.preventDefault();
45
+ });
46
+ }
47
+ }
48
+
49
+ // Valida tutti gli input del form
50
+ validate = () => {
51
+ this.isValid = true; // Assume che il form sia valido
52
+ this.inputs.forEach(input => {
53
+ input.validate(); // Valida ogni input
54
+ this.isValid = this.isValid && input.isValid; // Aggiorna lo stato di validità
55
+ });
56
+
57
+ // se non qualcosa non è valido metto il focus sul primo input non valido
58
+ if (!this.isValid) {
59
+ const firstInvalid = this.inputs.find(input => !input.isValid);
60
+ if (firstInvalid && firstInvalid.input) {
61
+ firstInvalid.input.focus(); // Imposta il focus sul primo input non valido
62
+ }
63
+ }
64
+ McShopify.customEvent(MCEVENTS.FORM_VALIDATE, {valid: this.isValid}, this); // Emette un evento di validazione
65
+ }
66
+
67
+ // Gestisce l'invio del form
68
+ submit = () => {
69
+ this.validate(); // Valida il form
70
+ if (this.isValid) {
71
+ // Se il form è valido
72
+ McShopify.customEvent(MCEVENTS.FORM_SUBMIT, null, this); // Emette un evento di submit
73
+ if (this.dataset.ajax != undefined) {
74
+ // Se configurato per AJAX, prepara i dati e invia la richiesta
75
+ this.getData();
76
+ this.getOptions();
77
+ this.ajaxSubmit();
78
+ } else {
79
+ // Altrimenti invia il form normalmente
80
+ this.form.submit();
81
+ }
82
+ }
83
+ }
84
+
85
+ // Invia il form in AJAX
86
+ ajaxSubmit = () => {
87
+ axios(this.options).then(this.success.bind(this)).catch(this.error.bind(this)).finally(this.complete.bind(this));
88
+ }
89
+
90
+ // Ottiene i dati del form in base al content-type
91
+ getData = () => {
92
+ const formData = new FormData(this.form);
93
+
94
+ if (this.dataset.contentType?.includes('json')) {
95
+ // Se il content-type è JSON, converte i dati in JSON
96
+ this.data = JSON.stringify(McForm.formDataToObject(formData));
97
+ } else if (this.dataset.contentType?.includes('form')) {
98
+ // Se il content-type è form-urlencoded, usa FormData
99
+ this.data = formData;
100
+ } else {
101
+ // Altrimenti usa URLSearchParams
102
+ this.data = new URLSearchParams(formData);
103
+ }
104
+ }
105
+
106
+ // Ottiene le opzioni della richiesta AJAX
107
+ getOptions = () => {
108
+ const headers = {};
109
+ const method = this.form.getAttribute('method') || 'POST'; // Metodo HTTP
110
+ if (this.dataset.contentType != undefined) {
111
+ headers['Content-Type'] = this.dataset.contentType; // Imposta il content-type
112
+ }
113
+ if (this.dataset.authUser != undefined && this.dataset.authToken != undefined) {
114
+ // Aggiunge l'autenticazione se configurata
115
+ headers['Authorization'] = 'Basic ' + btoa(this.dataset.authUser + ':' + this.dataset.authToken);
116
+ }
117
+ if(this.dataset.headers){
118
+ const customHeaders = JSON.parse(this.dataset.headers);
119
+ Object.keys(customHeaders).forEach(key => {
120
+ headers[key] = customHeaders[key];
121
+ });
122
+ }
123
+ this.options = {
124
+ url: this.form.action, // URL del form
125
+ method: method, // Metodo HTTP
126
+ headers: headers // Headers della richiesta
127
+ };
128
+ if (method.toUpperCase() != 'GET') {
129
+ this.options.data = this.data; // Aggiunge il corpo della richiesta
130
+ } else {
131
+ this.options.params = this.data; // Aggiunge i parametri per GET
132
+ }
133
+ console.log('McForm.getOptions', this.options, this.form, this.form.getAttribute('method'), method);
134
+ }
135
+
136
+ // Gestisce gli errori della richiesta
137
+ error = (e) => {
138
+ McShopify.customEvent(MCEVENTS.FORM_ERROR, e, this); // Emette un evento di errore
139
+ console.error(e); // Logga l'errore
140
+ this.errors.showError(e.message || theme.t.errors.generic); // Mostra l'errore
141
+ }
142
+
143
+ // Gestisce il successo della richiesta
144
+ success = (response) => {
145
+ McShopify.customEvent(MCEVENTS.FORM_SUCCESS, response, this); // Emette un evento di successo
146
+ this.errors.clear(); // Pulisce gli errori
147
+ }
148
+
149
+ // Gestisce il completamento della richiesta
150
+ complete = () => {
151
+ McShopify.customEvent(MCEVENTS.FORM_COMPLETED, null, this); // Emette un evento di completamento
152
+ }
153
+
154
+ // Trasforma i dati del form in un oggetto
155
+ static formDataToObject = (formData) => {
156
+ const object = {};
157
+ formData.forEach((value, key) => {
158
+ // Converte valori come 'true', 'false' e 'null'
159
+ if (value === 'true') {
160
+ value = true;
161
+ } else if (value === 'false') {
162
+ value = false;
163
+ } else if (value === 'null') {
164
+ value = null;
165
+ }
166
+
167
+ // Gestisce chiavi che indicano array con oggetti annidati
168
+ const arrayKeyMatch = key.match(/(\w+)\[(\d*)\]\[(\w+)\]/);
169
+
170
+ if (arrayKeyMatch) {
171
+ const arrayKey = arrayKeyMatch[1];
172
+ const index = arrayKeyMatch[2];
173
+ const subKey = arrayKeyMatch[3];
174
+
175
+ if (!object[arrayKey]) {
176
+ object[arrayKey] = [];
177
+ }
178
+
179
+ if (index) {
180
+ if (!object[arrayKey][index]) {
181
+ object[arrayKey][index] = {};
182
+ }
183
+ object[arrayKey][index][subKey] = value;
184
+ } else {
185
+ const newItem = {};
186
+ newItem[subKey] = value;
187
+ object[arrayKey].push(newItem);
188
+ }
189
+ } else if (key.endsWith('[]')) {
190
+ const keyName = key.slice(0, -2);
191
+ if (!Array.isArray(object[keyName])) {
192
+ object[keyName] = [];
193
+ }
194
+ try {
195
+ object[keyName].push(JSON.parse(value));
196
+ } catch (e) {
197
+ object[keyName].push(value);
198
+ }
199
+ } else {
200
+ const keys = key.split('.');
201
+ keys.reduce((acc, k, i) => {
202
+ if (i === keys.length - 1) {
203
+ acc[k] = value;
204
+ } else {
205
+ if (!acc[k]) acc[k] = {};
206
+ return acc[k];
207
+ }
208
+ }, object);
209
+ }
210
+ });
211
+
212
+ return object;
213
+ }
214
+ }
215
+
216
+ // Registra il componente personalizzato se non è già stato definito
217
+ if (!customElements.get('mc-form')) {
218
+ customElements.define('mc-form', McForm);
219
+ }
220
+
221
+ // Esporta la classe nel contesto globale e come modulo
222
+ window.McForm = McForm;
223
+ export default McForm;
@@ -0,0 +1,13 @@
1
+ await loadComponent('./components/mc-input.js', false);
2
+
3
+ class McInputArea extends McInput {
4
+ connectedCallback() {
5
+ this.input = this.querySelector('textarea');
6
+ this.init();
7
+ }
8
+ }
9
+ if(!customElements.get('mc-input-area')) {
10
+ customElements.define('mc-input-area', McInputArea);
11
+ }
12
+ window.McInputArea = McInputArea;
13
+ export default McInputArea;
@@ -0,0 +1,52 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-input.js', false);
3
+
4
+ // Definizione della classe custom element McInputCheckboxGroup
5
+ class McInputCheckboxGroup extends McInput {
6
+ inputs; // Collezione di input checkbox nel gruppo
7
+
8
+ connectedCallback() {
9
+ this.init();
10
+ }
11
+
12
+ // Inizializza il gruppo: collega inputs, error e listener
13
+ init = () => {
14
+ this.inputs = this.querySelectorAll('input');
15
+ this.error = this.querySelector('[data-error]');
16
+ if(!this.inputs || this.inputs.length === 0) { console.error('McInputCheckboxGroup: No input elements found'); return; }
17
+ if(!this.error){ console.error('McInput: No error container found'); return; }
18
+ if(!window.theme?.t) { console.error('McInput: Translations not available'); return; }
19
+ if(!window.theme.t.errors) { console.error('McInput: Translations for errors not available'); return; }
20
+
21
+ // Listener per validazione su change di ogni checkbox
22
+ this.inputs.forEach(input => {
23
+ input.addEventListener('change', this.validate.bind(this));
24
+ });
25
+ }
26
+
27
+ // Valida che almeno una checkbox sia selezionata
28
+ validate = () => {
29
+ this.isValid = false;
30
+ this.inputs.forEach(input => {
31
+ this.isValid = this.isValid || input.validity.valid;
32
+ });
33
+ if(!this.isValid) {
34
+ this.errorText = theme.t.errors.required;
35
+ }
36
+ // Emissione eventi custom in base alla validità
37
+ if (this.isValid) {
38
+ McShopify.customEvent(MCEVENTS.INPUT_VALID, this.input?.value, this);
39
+ } else {
40
+ McShopify.customEvent(MCEVENTS.INPUT_ERROR, this.errorText, this);
41
+ }
42
+ this.showError();
43
+ }
44
+
45
+ }
46
+
47
+ // Definizione custom element e esportazione globale/modulo
48
+ if(!customElements.get('mc-input-checkbox-group')) {
49
+ customElements.define('mc-input-checkbox-group', McInputCheckboxGroup);
50
+ }
51
+ window.McInputCheckboxGroup = McInputCheckboxGroup;
52
+ export default McInputCheckboxGroup;
@@ -0,0 +1,12 @@
1
+ await loadComponent('./components/mc-input.js', false);
2
+
3
+ class McInputCheckbox extends McInput {
4
+ connectedCallback() {
5
+ this.init();
6
+ }
7
+ }
8
+ if(!customElements.get('mc-input-checkbox')) {
9
+ customElements.define('mc-input-checkbox', McInputCheckbox);
10
+ }
11
+ window.McInputCheckbox = McInputCheckbox;
12
+ export default McInputCheckbox;
@@ -0,0 +1,39 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-input.js', false);
3
+
4
+ class McInputPassword extends McInput {
5
+ tips; eye;
6
+
7
+ connectedCallback() {
8
+ this.init();
9
+
10
+ this.addEventListener(MCEVENTS.EL_ACTIVATED, this.showPassword.bind(this));
11
+ this.addEventListener(MCEVENTS.EL_DEACTIVATED, this.hidePassword.bind(this));
12
+ }
13
+
14
+ showPassword = () => {
15
+ this.input.type = "text";
16
+ }
17
+
18
+ hidePassword = () => {
19
+ this.input.type = "password";
20
+ }
21
+
22
+ hideTips = () => {
23
+ this.tips?.hide();
24
+ }
25
+
26
+ showTips = () => {
27
+ this.tips?.show();
28
+ }
29
+
30
+ checkTips = () => {
31
+ this.tips?.checkPoints(this.input.value);
32
+ }
33
+
34
+ }
35
+ if (!window.customElements.get("mc-input-password")) {
36
+ window.customElements.define("mc-input-password", McInputPassword);
37
+ }
38
+ window.McInputPassword = McInputPassword;
39
+ export default McInputPassword;
@@ -0,0 +1,43 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-input.js', false);
3
+
4
+ class McInputPlaces extends McInput {
5
+ target; search;
6
+
7
+ connectedCallback() {
8
+ this.target = this.querySelector("[data-geolocate]");
9
+ if(!google?.maps?.places) { console.error("McInputPlaces: Google Maps Places API is not loaded. Please ensure you have included the Google Maps JavaScript API with Places library."); return; }
10
+
11
+ this.init();
12
+ this.search = new google.maps.places.SearchBox(this.input);
13
+ this.search.addListener('place_changed', this.onChange.bind(this));
14
+ this.target?.addEventListener("click", this.locate.bind(this));
15
+ }
16
+
17
+ locate = () => {
18
+ if (navigator.geolocation) {
19
+ navigator.geolocation.getCurrentPosition((position) => {
20
+ McShopify.customEvent(MCEVENTS.PLACES_LOCATED, position, this);
21
+ });
22
+ }
23
+ }
24
+
25
+ onChange = () => {
26
+ const places = this.search.getPlaces();
27
+ McShopify.customEvent(MCEVENTS.PLACES_CHANGE, places, this);
28
+ }
29
+
30
+ getPlaces = () => {
31
+ return this.search.getPlaces();
32
+ }
33
+
34
+ setBounds = (bounds) => {
35
+ this.search.setBounds(bounds);
36
+ }
37
+
38
+ }
39
+ if (!window.customElements.get("mc-input-places")) {
40
+ window.customElements.define("mc-input-places", McInputPlaces);
41
+ }
42
+ window.McInputPlaces = McInputPlaces;
43
+ export default McInputPlaces;