@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-input.js', false);
3
+
4
+ class McInputQuantity extends McInput {
5
+
6
+ connectedCallback() {
7
+ this.init();
8
+ this.querySelector('[data-plus]')?.addEventListener('click', this.plus.bind(this));
9
+ this.querySelector('[data-minus]')?.addEventListener('click', this.minus.bind(this));
10
+ this.input.addEventListener('keyup', this.change.bind(this));
11
+ }
12
+
13
+ plus = () => {
14
+ const step = parseInt(this.input.step) || 1;
15
+ this.setValue(parseInt(this.input.value) + step);
16
+ }
17
+
18
+ change = (e) => {
19
+ if(this.input.value === '') return;
20
+ const newValue = parseInt(this.input.value);
21
+ this.setValue(newValue);
22
+ }
23
+
24
+ setValue = (value) => {
25
+ const max = parseInt(this.input.max);
26
+ const min = parseInt(this.input.min);
27
+ if((isNaN(max) || value <= max) && (isNaN(min) || value >= min)){
28
+ this.input.value = value;
29
+ McShopify.customEvent(MCEVENTS.QUANTITY_CHANGED, {value:value}, this);
30
+ }
31
+ }
32
+
33
+ minus = () => {
34
+ const step = parseInt(this.input.step) || 1;
35
+ this.setValue(parseInt(this.input.value) - step);
36
+ }
37
+
38
+ }
39
+ if(!customElements.get('mc-input-quantity')) {
40
+ customElements.define('mc-input-quantity', McInputQuantity);
41
+ }
42
+ window.McInputQuantity = McInputQuantity;
43
+ export default McInputQuantity;
@@ -0,0 +1,14 @@
1
+ await loadComponent('./components/mc-input.js', false); // Carica il componente Input
2
+ await loadComponent('./res/mc-shopify.js', false);
3
+
4
+ class McInputSelect extends McInput {
5
+ connectedCallback() {
6
+ this.input = this.querySelector('select');
7
+ this.init();
8
+ }
9
+ }
10
+ if(!customElements.get('mc-input-select')) {
11
+ customElements.define('mc-input-select', McInputSelect);
12
+ }
13
+ window.McInputSelect = McInputSelect;
14
+ export default McInputSelect;
@@ -0,0 +1,12 @@
1
+ await loadComponent('./components/mc-input.js', false);
2
+
3
+ class McInputText extends McInput {
4
+ connectedCallback() {
5
+ this.init();
6
+ }
7
+ }
8
+ if(!customElements.get('mc-input-text')) {
9
+ customElements.define('mc-input-text', McInputText);
10
+ }
11
+ window.McInputText = McInputText;
12
+ export default McInputText;
@@ -0,0 +1,137 @@
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
+
6
+ // Definizione della classe custom element McInput
7
+ class McInput extends McElement {
8
+ input; // Riferimento all'elemento input
9
+ error; // Container per il messaggio di errore
10
+ errorText; // Testo del messaggio di errore
11
+ isValid; // Stato di validità dell'input
12
+ static ERROR_CLASS = 'is-invalid'; // Classe CSS per indicare un errore
13
+
14
+ // Metodo di inizializzazione: collega input, error e listener
15
+ init = () => {
16
+ this.error = this.querySelector('[data-error]'); // Seleziona il container per l'errore
17
+ this.input = this.input ? this.input : this.querySelector('input'); // Seleziona l'elemento input
18
+
19
+ // Controlli di presenza elementi e traduzioni
20
+ if (!this.input) { console.error('McInput: No input element found'); return; }
21
+ if(!this.error){ console.error('McInput: No error container found'); return; }
22
+ if(!window.theme?.t) { console.error('McInput: Translations not available'); return; }
23
+ if(!window.theme.t.errors) { console.error('McInput: Translations for errors not available'); return; }
24
+
25
+ // Listener per validazione su keyup, blur e change
26
+ this.setEvents();
27
+ this.autosubmit(); // Configura autosubmit se richiesto
28
+ }
29
+
30
+ setEvents = () => {
31
+ const triggers = this.dataset.triggers ? this.dataset.triggers.split(',').map(t => t.trim()) : ['keyup', 'change', 'blur'];
32
+ triggers.forEach(trigger => {
33
+ this.input.addEventListener(trigger, this.validate.bind(this));
34
+ });
35
+ }
36
+
37
+ // Valida l'input utilizzando la proprietà `validity` e aggiorna errorText
38
+ validate = (e) => {
39
+ this.isValid = this.input.checkValidity(); // Controlla la validità dell'input
40
+ if (!this.isValid) {
41
+ // Gestione dei vari tipi di errori di validazione HTML5
42
+ if (this.input.validity.badMcInput) {
43
+ this.validateType();
44
+ } else if (this.input.validity.valueMissing) {
45
+ this.errorText = theme.t.errors.required;
46
+ } else if (this.input.validity.typeMismatch) {
47
+ this.validateType();
48
+ } else if (this.input.validity.tooShort) {
49
+ this.errorText = theme.t.errors.minLength.replace('{{ minlength }}', this.input.minLength);
50
+ } else if (this.input.validity.tooLong) {
51
+ this.errorText = theme.t.errors.maxLength.replace('{{ maxlength }}', this.input.maxLength);
52
+ } else if (this.input.validity.rangeUnderflow) {
53
+ this.errorText = theme.t.errors.min.replace('{{ min }}', this.input.min);
54
+ } else if (this.input.validity.rangeOverflow) {
55
+ this.errorText = theme.t.errors.max.replace('{{ max }}', this.input.max);
56
+ } else if (this.input.validity.stepMismatch) {
57
+ this.errorText = theme.t.errors.step;
58
+ } else if (this.input.validity.patternMismatch) {
59
+ this.errorText = this.dataset.patternMsg || theme.t.errors.pattern;
60
+ } else if (this.input.validity.customError) {
61
+ this.errorText = this.input.validationMessage;
62
+ }
63
+ }
64
+
65
+ // Validazione "equals": confronta con altro campo se richiesto
66
+ if (this.isValid && this.dataset.equals != undefined) {
67
+ const equalsInput = document.getElementById(this.dataset.equals);
68
+ if (!equalsInput) {
69
+ console.warn(`McInput: Element with ID ${this.dataset.equals} not found for equals validation`);
70
+ return;
71
+ }
72
+ if (this.input.value != equalsInput.value) {
73
+ this.isValid = false;
74
+ this.errorText = theme.t.errors.equals;
75
+ }
76
+ }
77
+
78
+ // Emette eventi custom in base alla validità
79
+ if (this.isValid) {
80
+ McShopify.customEvent(MCEVENTS.INPUT_VALID, {value: this.input.value}, this);
81
+ } else {
82
+ McShopify.customEvent(MCEVENTS.INPUT_ERROR, {message: this.errorText}, this);
83
+ }
84
+ this.showError(); // Mostra o nasconde il messaggio di errore
85
+ }
86
+
87
+ // Imposta errorText in base al tipo di input (email, url, ecc.)
88
+ validateType = () => {
89
+ switch (this.input.type) {
90
+ case 'email':
91
+ this.errorText = theme.t.errors.email;
92
+ break;
93
+ case 'url':
94
+ this.errorText = theme.t.errors.url;
95
+ break;
96
+ case 'number':
97
+ this.errorText = theme.t.errors.number;
98
+ break;
99
+ case 'integer':
100
+ this.errorText = theme.t.errors.integer;
101
+ break;
102
+ case 'date':
103
+ this.errorText = theme.t.errors.date;
104
+ break;
105
+ case 'time':
106
+ this.errorText = theme.t.errors.time;
107
+ break;
108
+ case 'datetime':
109
+ this.errorText = theme.t.errors.datetime;
110
+ break;
111
+ default:
112
+ this.errorText = theme.t.errors.pattern;
113
+ break;
114
+ }
115
+ }
116
+
117
+ // Mostra o nasconde il messaggio di errore nell'elemento error
118
+ showError = () => {
119
+ this.isValid ? this.error.innerText = '' : this.error.innerText = this.errorText;
120
+ this.isValid ? this.classList.remove(McInput.ERROR_CLASS) : this.classList.add(McInput.ERROR_CLASS);
121
+ }
122
+
123
+ // Se abilitato, invia automaticamente il form al change
124
+ autosubmit = () => {
125
+ if (this.dataset.autosubmit != undefined) {
126
+ this.input.addEventListener('change', () => {
127
+ const form = this.input.form;
128
+ if(!form) return;
129
+ McShopify.customEvent(MCEVENTS.FORM_AUTOSUBMIT, null, form);
130
+ });
131
+ }
132
+ }
133
+ }
134
+
135
+ // Esporta la classe McInput nel contesto globale e come modulo
136
+ window.McInput = McInput;
137
+ export default McInput;
@@ -0,0 +1,21 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McLoader extends McElement {
4
+
5
+ connectedCallback() {
6
+ if(this.dataset.global) {
7
+ window.onpageshow = () => {
8
+ this.deactivate();
9
+ }
10
+ window.onpagehide = () => {
11
+ this.activate();
12
+ }
13
+ }
14
+ }
15
+ }
16
+ if (!window.customElements.get("mc-loader")) {
17
+ window.customElements.define("mc-loader", McLoader);
18
+ McUtils.addCss(`https://cdn.jsdelivr.net/npm/teddy-frontend@${theme.version}/css/mc-loader.css`);
19
+ }
20
+ window.McLoader = McLoader;
21
+ export default McLoader;
@@ -0,0 +1,69 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McModal extends McElement {
4
+ delay; modal; scroll; scrollHandler; cansShow; days;
5
+
6
+ connectedCallback(){
7
+ this.init();
8
+ }
9
+
10
+ init = () => {
11
+ this.delay = isNaN(parseInt(this.dataset.delay)) ? 0 : parseInt(this.dataset.delay);
12
+ this.scroll = isNaN(parseInt(this.dataset.scroll)) ? 0 : parseInt(this.dataset.scroll);
13
+ this.days = isNaN(parseInt(this.dataset.remember)) ? 0 : parseInt(this.dataset.remember);
14
+ this.modal = bootstrap.Modal.getOrCreateInstance(this);
15
+ this.checkCanShow();
16
+
17
+ if(this.cansShow){
18
+ if(this.dataset.delay != undefined){
19
+ this.handleDelay();
20
+ }
21
+
22
+ if(this.dataset.scroll != undefined){
23
+ this.scrollHandler = this.handleScroll.bind(this);
24
+ window.addEventListener('scroll', this.scrollHandler, false);
25
+ }
26
+
27
+ if(this.dataset.remember != undefined && this.days > 0){
28
+ this.addEventListener('hidden.bs.modal', () => this.remember());
29
+ }
30
+ }
31
+ }
32
+
33
+ remember = () => {
34
+ localStorage.setItem(this.id, Date.now() + this.days * 24 * 60 * 60 * 1000);
35
+ }
36
+
37
+ checkCanShow = () => {
38
+ const stamp = parseInt(localStorage.getItem(this.id));
39
+ this.cansShow = false;
40
+ if(isNaN(stamp) || stamp < Date.now()){
41
+ this.cansShow = true;
42
+ }
43
+ }
44
+
45
+ handleScroll = () => {
46
+ const scrollPosition = window.scrollY + window.innerHeight;
47
+ const pageHeight = document.documentElement.scrollHeight;
48
+ const scrollPercentage = this.scroll / 100;
49
+ if(scrollPosition / pageHeight > scrollPercentage){
50
+ this.show();
51
+ window.removeEventListener('scroll', this.scrollHandler, false);
52
+ }
53
+ }
54
+
55
+ handleDelay = () => {
56
+ setTimeout(() => {
57
+ this.show();
58
+ }, this.delay);
59
+ }
60
+
61
+ show = () => {
62
+ this.modal.show();
63
+ }
64
+ }
65
+ if (!window.customElements.get("mc-modal")) {
66
+ window.customElements.define("mc-modal", McModal);
67
+ }
68
+ window.McModal = McModal;
69
+ export default McModal;
@@ -0,0 +1,24 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+ await loadComponent('./components/mc-btn.js', false);
3
+ await loadComponent('./res/mc-utils.js', false);
4
+
5
+ class McPasswordEye extends McBtn {
6
+
7
+ connectedCallback() {
8
+
9
+ if(!this.querySelector('.active')) { console.error('McPasswordEye: No active element found'); return; }
10
+ if(!this.querySelector('.inactive')) { console.error('McPasswordEye: No inactive element found'); return; }
11
+
12
+ this.target = this.closest('mc-input-password') || document.querySelector(this.dataset.inputPassword);
13
+ if (!this.target) { console.error('McPasswordEye: No McInputPassword found'); return; }
14
+
15
+ this.init();
16
+ }
17
+
18
+ }
19
+ if (!window.customElements.get("mc-password-eye")) {
20
+ window.customElements.define("mc-password-eye", McPasswordEye);
21
+ McUtils.addCss(`https://cdn.jsdelivr.net/npm/teddy-frontend@${theme.version}/css/mc-password-eye.css`);
22
+ }
23
+ window.McPasswordEye = McPasswordEye;
24
+ export default McPasswordEye;
@@ -0,0 +1,60 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+ await loadComponent('./components/mc-input-password.js', false);
3
+
4
+ class McPasswordTips extends McElement {
5
+ static classes = {
6
+ valid: 'valid',
7
+ allValid: 'alert-success',
8
+ someInvalid: 'alert-warning'
9
+ };
10
+ points;
11
+
12
+ connectedCallback() {
13
+ this.points = this.querySelectorAll("[data-pattern]");
14
+ if (this.points.length === 0) { console.error("McPasswordTips: No points found with data-pattern attribute."); return; }
15
+
16
+ this.inputPassword = this.closest("mc-input-password") || document.querySelector(this.dataset.inputPassword);
17
+ if (!this.inputPassword) { console.error("McPasswordTips: No McInputPassword found"); return; }
18
+
19
+ this.inputPassword.input.addEventListener("focus", this.activate.bind(this));
20
+ this.inputPassword.input.addEventListener("blur", this.deactivate.bind(this));
21
+ this.inputPassword.input.addEventListener("input", () => {
22
+ this.checkPoints(this.inputPassword.input.value);
23
+ });
24
+ }
25
+
26
+ checkPoints = (value) => {
27
+ const validClass = this.dataset.validClass || McPasswordTips.classes.valid;
28
+ this.points.forEach(point => {
29
+ let pattern = new RegExp(point.dataset.pattern);
30
+ if (pattern.test(value)) {
31
+ point.classList.add(validClass);
32
+ } else {
33
+ point.classList.remove(validClass);
34
+ }
35
+ });
36
+ this.setValid();
37
+ }
38
+
39
+ setValid = () => {
40
+ const allValidClasses = this.dataset.allValidClasses?.split(' ') || McPasswordTips.classes.allValid?.split(' ') || [];
41
+ const validClass = this.dataset.validClass || McPasswordTips.classes.valid;
42
+ const someInvalidClasses = this.dataset.someInvalidClasses?.split(' ') || McPasswordTips.classes.someInvalid?.split(' ') || [];
43
+
44
+ const valid = this.querySelectorAll(`[data-pattern].${validClass}`).length;
45
+ const total = this.points.length;
46
+ if(valid === total){
47
+ this.classList.add(...allValidClasses);
48
+ this.classList.remove(...someInvalidClasses);
49
+ } else {
50
+ this.classList.add(...someInvalidClasses);
51
+ this.classList.remove(...allValidClasses);
52
+ }
53
+ }
54
+ }
55
+ if (!window.customElements.get("mc-password-tips")) {
56
+ window.customElements.define("mc-password-tips", McPasswordTips);
57
+ McUtils.addCss(`https://cdn.jsdelivr.net/npm/teddy-frontend@${theme.version}/css/mc-password-tips.css`);
58
+ }
59
+ window.McPasswordTips = McPasswordTips;
60
+ export default McPasswordTips;
@@ -0,0 +1,41 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McQrcode extends McElement {
4
+
5
+ connectedCallback() {
6
+ const observer = new IntersectionObserver(
7
+ (entries, obs) => {
8
+ entries.forEach(entry => {
9
+ if (entry.isIntersecting) {
10
+ // L'elemento è nella viewport
11
+ this.init();
12
+ obs.unobserve(this); // Osserva solo la prima volta
13
+ }
14
+ });
15
+ },
16
+ { threshold: 0.1 }
17
+ );
18
+ observer.observe(this);
19
+ }
20
+
21
+ init = async () => {
22
+ //await import(theme.qrcode);
23
+ if(!QRCode) {
24
+ console.error('QRCode library not loaded');
25
+ return;
26
+ }
27
+ new QRCode(this, {
28
+ text: this.dataset.text,
29
+ width: parseInt(this.dataset.width) || 128,
30
+ height: parseInt(this.dataset.height) || 128,
31
+ colorDark : this.dataset.colorDark || "#000000",
32
+ colorLight : this.dataset.colorLight || "#ffffff",
33
+ correctLevel : QRCode.CorrectLevel.H
34
+ });
35
+ }
36
+ }
37
+
38
+ if (!customElements.get('mc-qrcode')) {
39
+ customElements.define('mc-qrcode', McQrcode);
40
+ }
41
+ window.McQrcode = McQrcode;
@@ -0,0 +1,108 @@
1
+ import 'https://cdn.jsdelivr.net/npm/nouislider@15.8.1';
2
+ await loadComponent('./components/mc-element.js', false);
3
+ await loadComponent('./res/mc-utils.js', false);
4
+
5
+ class McRange extends McElement {
6
+ values;
7
+
8
+ connectedCallback() {
9
+ this.getValues();
10
+ this.render();
11
+ }
12
+
13
+ // renderizzo lo slider
14
+ render = () => {
15
+ if(this.values?.length){
16
+ noUiSlider.create(this, {
17
+ start: this.values,
18
+ connect: true,
19
+ range: {
20
+ 'min': parseInt(this.dataset.min),
21
+ 'max': parseInt(this.dataset.max)
22
+ },
23
+ step: parseInt(this.dataset.step) || 1
24
+ });
25
+
26
+ this.noUiSlider.on('update', (values) => {
27
+ this.setValues(values);
28
+ });
29
+
30
+ this.noUiSlider.on('change', (values) => {
31
+ this.setValues(values);
32
+ McShopify.customEvent('change', this.getPairs(), this);
33
+ });
34
+
35
+ this.inputEvents();
36
+ }
37
+ }
38
+
39
+ // ottiene un oggetto name:value
40
+ getPairs = () => {
41
+ return {
42
+ items: this.dataset.inputSelectors?.split(',').map(selector => {
43
+ const input = document.querySelector(selector);
44
+ return { name: input.name, value: input.value };
45
+ })
46
+ };
47
+ }
48
+
49
+ // fa controllare lo slider dalle sue input
50
+ inputEvents = () => {
51
+ const inputs = this.dataset.inputSelectors?.split(',').map(selector => document.querySelector(selector));
52
+ if(inputs !== undefined){
53
+ inputs.forEach((input, index) => {
54
+ input.addEventListener('input', (e) => {
55
+ this.values[index] = parseInt(e.target.value);
56
+ this.noUiSlider.set(this.values);
57
+ });
58
+ });
59
+ }
60
+ }
61
+
62
+ // ottengo i valori
63
+ getValues = () => {
64
+ this.values = this.dataset.values?.split(',').map(value => parseInt(value));
65
+ }
66
+
67
+ // setto i valori
68
+ setValues = (values) => {
69
+ this.values = values;
70
+ this.renderValues();
71
+ }
72
+
73
+ // renderizzo i valori
74
+ renderValues = () => {
75
+ const labels = this.dataset.labels?.split(',').map(label => document.querySelector(label));
76
+ const inputs = this.dataset.inputSelectors?.split(',').map(selector => document.querySelector(selector));
77
+ if(labels !== undefined){
78
+ labels.forEach((label, index) => {
79
+ label.innerHTML = this.formatLabel(this.values[index]);
80
+ });
81
+ }
82
+ if(inputs !== undefined){
83
+ inputs.forEach((input, index) => {
84
+ input.value = this.formatInput(this.values[index]);
85
+ });
86
+ }
87
+ }
88
+
89
+ // formatto i valori in base al formato, se è money uso utils.money
90
+ formatLabel = (value) => {
91
+ const format = this.dataset.format || '{label}';
92
+ if(format == 'money')
93
+ return McUtils.money(value*100);
94
+ else
95
+ return format.replaceAll('{label}', value);
96
+ }
97
+
98
+ // formatta i valori per le input
99
+ formatInput = (value) => {
100
+ return parseInt(value);
101
+ }
102
+ }
103
+ if (!window.customElements.get("mc-range")) {
104
+ window.customElements.define("mc-range", McRange);
105
+ McUtils.addCss(`/cdn/shop/t/32/assets/nouislider.min.css`);
106
+ }
107
+ window.McRange = McRange;
108
+ export default McRange;
@@ -0,0 +1,56 @@
1
+ import '../res/mc-events.js';
2
+ await loadComponent('./components/mc-element.js', false);
3
+
4
+ class McReadMore extends McElement {
5
+ expanded; expandible; link; text; observer;
6
+
7
+ connectedCallback(){
8
+ this.text = this.querySelector(':scope > div');
9
+ if(!this.text){ console.error('McReadMore: You need to provide a div element'); return; }
10
+ if(!this.dataset.moreText){ console.error('McReadMore: You need to provide a data-more-text attribute'); return; }
11
+ if(!this.dataset.lessText) { console.error('McReadMore: You need to provide a data-less-text attribute'); return; }
12
+
13
+ this.checkExpandible();
14
+ this.observer = new ResizeObserver(() => this.checkExpandible());
15
+ this.observer.observe(this);
16
+
17
+ this.addEventListener(MCEVENTS.EL_ACTIVATED, this.setText.bind(this));
18
+ this.addEventListener(MCEVENTS.EL_DEACTIVATED, this.setText.bind(this));
19
+ }
20
+
21
+ checkExpandible = () => {
22
+ if(this.offsetParent !== null){
23
+ this.expanded = false;
24
+ this.expandible = this.text.scrollHeight > this.text.clientHeight;
25
+ if(this.expandible){
26
+ this.addLink();
27
+ }
28
+ this.observer.disconnect();
29
+ }
30
+ }
31
+
32
+ addLink = () => {
33
+ const classes = this.dataset.classes?.split(' ') || ["read-more-link"];
34
+ this.link = document.createElement('mc-btn');
35
+ this.link.setAttribute('data-target', this.getSelector());
36
+ this.link.innerText = this.dataset.moreText;
37
+ this.link.classList.add(...classes);
38
+ this.appendChild(this.link);
39
+ }
40
+
41
+ setText = () => {
42
+ if(this.expandible && this.link){
43
+ if(this.isActive()){
44
+ this.link.innerText = this.dataset.lessText;
45
+ } else {
46
+ this.link.innerText = this.dataset.moreText;
47
+ }
48
+ }
49
+ }
50
+ }
51
+ if (!window.customElements.get("mc-read-more")) {
52
+ window.customElements.define("mc-read-more", McReadMore);
53
+ McUtils.addCss(`https://cdn.jsdelivr.net/npm/teddy-frontend@${theme.version}/css/mc-read-more.css`);
54
+ }
55
+ window.McReadMore = McReadMore;
56
+ export default McReadMore;
@@ -0,0 +1,50 @@
1
+ // Questo componente `McRecommended` estende la classe base `McElement` e serve per mostrare una lista di prodotti raccomandati (ad esempio prodotti correlati o complementari) in una pagina prodotto.
2
+ // Utilizza le API di Shopify per recuperare i prodotti consigliati in base al prodotto corrente.
3
+ // Richiede che vengano specificati alcuni data attributes sull'elemento HTML:
4
+ // - data-product-id: ID del prodotto di riferimento (obbligatorio)
5
+ // - data-section-id: ID della sezione Shopify da aggiornare (obbligatorio)
6
+ // - data-limit: numero massimo di prodotti da mostrare (opzionale, default 10)
7
+ // - data-intent: tipo di raccomandazione (opzionale, valori possibili: 'related' o 'complementary')
8
+
9
+ // Non sono richiesti elementi HTML interni specifici: il componente aggiorna se stesso con i prodotti raccomandati ricevuti dalla chiamata API.
10
+
11
+ await loadComponent('./components/mc-element.js', false);
12
+ await loadComponent('./res/mc-utils.js', false);
13
+ await loadComponent('./res/mc-shopify.js', false);
14
+
15
+ class McRecommended extends McElement {
16
+
17
+ // Metodo chiamato automaticamente quando l'elemento viene aggiunto al DOM
18
+ connectedCallback() {
19
+ this.loadProducts(); // Carica i prodotti raccomandati
20
+ }
21
+
22
+ // Recupera i prodotti raccomandati tramite l'API Shopify e aggiorna il contenuto del componente
23
+ loadProducts = () => {
24
+ if(!this.dataset.productId || !this.dataset.sectionId) { console.error('ID del prodotto o ID della sezione non forniti.'); return;}
25
+
26
+ McShopify.getRecommendations({
27
+ product_id: this.dataset.productId, // ID del prodotto corrente
28
+ section_id: this.dataset.sectionId, // ID della sezione corrente
29
+ limit: parseInt(this.dataset.limit) || 10, // Numero massimo di prodotti da restituire
30
+ intent: this.dataset.intent || 'related', // Intento della raccomandazione (related | complementary)
31
+ onSuccess: (response) => {
32
+ McUtils.reloadElement(response, this, this.getSelector()); // Renderizza i prodotti raccomandati
33
+ },
34
+ onError: (error) => {
35
+ console.error('Errore nel caricamento dei prodotti raccomandati:', error);
36
+ this.remove(); // Rimuove l'elemento in caso di errore
37
+ }
38
+ });
39
+ }
40
+
41
+ }
42
+
43
+ // Registra il componente custom se non già presente
44
+ if(!customElements.get('mc-recommended')) {
45
+ customElements.define('mc-recommended', McRecommended);
46
+ }
47
+
48
+ // Espone la classe globalmente e come modulo
49
+ window.McRecommended = McRecommended;
50
+ export default McRecommended;
@@ -0,0 +1,20 @@
1
+ await loadComponent('./components/mc-element.js', false);
2
+
3
+ class McReferrer extends McElement {
4
+
5
+ // al click va su document.referrer
6
+ connectedCallback() {
7
+ if(window.location.href != document.referrer){
8
+ this.addEventListener('click', () => {
9
+ window.location.href = document.referrer;
10
+ });
11
+ } else {
12
+ this.remove();
13
+ }
14
+ }
15
+ }
16
+ if (!window.customElements.get("mc-referrer")) {
17
+ window.customElements.define("mc-referrer", McReferrer);
18
+ }
19
+ window.McReferrer = McReferrer;
20
+ export default McReferrer;