@magic-spells/cart-progress-bar 0.2.1 → 2.0.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.
@@ -1,330 +1,254 @@
1
+ //#region src/cart-progress-bar.js
1
2
  /**
2
- * ProgressBar helper class for the visual progress bar element
3
- */
4
- class ProgressBar extends HTMLElement {
3
+ * ProgressBar helper class for the visual progress bar element
4
+ */
5
+ var ProgressBar = class extends HTMLElement {
5
6
  constructor() {
6
7
  super();
7
- this.#setupProgressBar();
8
+ const _ = this;
9
+ _.setAttribute("role", "progressbar");
10
+ _.setAttribute("aria-valuemin", "0");
11
+ _.setAttribute("aria-valuemax", "100");
12
+ _.setAttribute("aria-valuenow", "0");
13
+ _.innerHTML = "<div class=\"progress-bar-fill\"></div>";
8
14
  }
9
-
10
- #setupProgressBar() {
11
- this.setAttribute('role', 'progressbar');
12
- this.setAttribute('aria-valuemin', '0');
13
- this.setAttribute('aria-valuemax', '100');
14
- this.setAttribute('aria-valuenow', '0');
15
-
16
- // Create the visual progress bar
17
- this.innerHTML = '<div class="progress-bar-fill"></div>';
18
- }
19
-
20
15
  setPercent(percent) {
21
- const clampedPercent = Math.max(0, Math.min(100, percent));
22
- this.style.setProperty('--cart-progress-percent', `${clampedPercent}%`);
23
- this.setAttribute('aria-valuenow', clampedPercent);
16
+ const p = Math.max(0, Math.min(100, percent));
17
+ this.style.setProperty("--cart-progress-percent", `${p}%`);
18
+ this.setAttribute("aria-valuenow", p);
24
19
  }
25
- }
26
-
27
- // Define ProgressBar custom element immediately so it's available for CartProgressBar
28
- customElements.define('progress-bar', ProgressBar);
29
-
20
+ };
21
+ if (!customElements.get("progress-bar")) customElements.define("progress-bar", ProgressBar);
30
22
  /**
31
- * CartProgressBar main component
32
- */
33
- class CartProgressBar extends HTMLElement {
34
- // Private fields
35
- #minAmount = 0;
36
- #currentAmount = 0;
37
- #progressPercent = 0;
38
- #originalAboveMessage = '';
39
- #originalBelowMessage = '';
40
- #progressBar = null;
41
- #messageElement = null;
42
-
43
- /**
44
- * Define which attributes should be observed for changes
45
- */
23
+ * CartProgressBar main component
24
+ */
25
+ var CartProgressBar = class extends HTMLElement {
26
+ #threshold = 0;
27
+ #current = 0;
28
+ #percent = 0;
29
+ #msgAbove = "";
30
+ #msgBelow = "";
31
+ #bar = null;
32
+ #msgEl = null;
33
+ #moneyFmt = null;
34
+ #debounce = null;
35
+ #listenSelector = "cart-panel";
36
+ #listenEvent = "cart-panel:data-changed";
37
+ #listenTarget = null;
38
+ #listenHandler = null;
46
39
  static get observedAttributes() {
47
- return ['threshold', 'current', 'message-above', 'message-below'];
40
+ return [
41
+ "threshold",
42
+ "current",
43
+ "message-above",
44
+ "message-below",
45
+ "money-format",
46
+ "listen-selector",
47
+ "listen-event"
48
+ ];
48
49
  }
49
-
50
50
  constructor() {
51
51
  super();
52
- this.#init();
53
- }
54
-
55
- #init() {
56
- // Read initial attributes
57
- this.#minAmount = parseFloat(this.getAttribute('threshold')) || 0;
58
- this.#currentAmount = parseFloat(this.getAttribute('current')) || 0;
59
-
60
- // Store original message templates
61
- this.#originalAboveMessage = this.getAttribute('message-above') || '';
62
- this.#originalBelowMessage = this.getAttribute('message-below') || '';
52
+ const _ = this;
53
+ _.#threshold = parseFloat(_.getAttribute("threshold")) || 0;
54
+ _.#current = parseFloat(_.getAttribute("current")) || 0;
55
+ _.#msgAbove = _.getAttribute("message-above") || "";
56
+ _.#msgBelow = _.getAttribute("message-below") || "";
57
+ _.#moneyFmt = _.getAttribute("money-format");
58
+ _.#listenSelector = _.getAttribute("listen-selector") || "cart-panel";
59
+ _.#listenEvent = _.getAttribute("listen-event") || "cart-panel:data-changed";
63
60
  }
64
-
65
61
  async connectedCallback() {
66
- // ensure the child custom element has been registered
67
- await customElements.whenDefined('progress-bar');
68
-
69
- if (!customElements.get('progress-bar')) {
70
- throw new Error('<progress-bar> must be registered before <cart-progress-bar> runs');
71
- }
72
-
62
+ await customElements.whenDefined("progress-bar");
73
63
  this.#render();
74
64
  this.#updateProgress();
75
65
  this.#attachListeners();
76
66
  }
77
-
78
- attributeChangedCallback(name, oldValue, newValue) {
79
- if (oldValue === newValue) return;
80
-
67
+ disconnectedCallback() {
68
+ if (this.#debounce) clearTimeout(this.#debounce);
69
+ this.#detachListeners();
70
+ }
71
+ attributeChangedCallback(name, oldVal, newVal) {
72
+ if (oldVal === newVal) return;
73
+ const _ = this;
81
74
  switch (name) {
82
- case 'threshold':
83
- this.#minAmount = parseFloat(newValue) || 0;
84
- this.#updateProgress();
75
+ case "threshold":
76
+ _.#threshold = parseFloat(newVal) || 0;
77
+ _.#updateProgress();
78
+ break;
79
+ case "current":
80
+ _.#current = parseFloat(newVal) || 0;
81
+ _.#updateProgress();
85
82
  break;
86
- case 'current':
87
- this.#currentAmount = parseFloat(newValue) || 0;
88
- this.#updateProgress();
83
+ case "message-above":
84
+ _.#msgAbove = newVal || "";
85
+ _.#updateMessages();
89
86
  break;
90
- case 'message-above':
91
- this.#originalAboveMessage = newValue || '';
92
- this.#updateMessages();
87
+ case "message-below":
88
+ _.#msgBelow = newVal || "";
89
+ _.#updateMessages();
93
90
  break;
94
- case 'message-below':
95
- this.#originalBelowMessage = newValue || '';
96
- this.#updateMessages();
91
+ case "money-format":
92
+ _.#moneyFmt = newVal;
93
+ _.#updateMessages();
97
94
  break;
95
+ case "listen-selector":
96
+ _.#listenSelector = newVal || "cart-panel";
97
+ _.#detachListeners();
98
+ _.#attachListeners();
99
+ break;
100
+ case "listen-event":
101
+ _.#detachListeners();
102
+ _.#listenEvent = newVal || "cart-panel:data-changed";
103
+ _.#attachListeners();
98
104
  }
99
105
  }
100
-
101
106
  #render() {
102
- // Find or create the message element
103
- this.#messageElement =
104
- this.querySelector('[data-content-cart-progress-message]') ||
105
- this.querySelector('p[data-content-cart-progress-message]');
106
-
107
- // Find existing progress bar (user can add their own)
108
- this.#progressBar = this.querySelector('progress-bar');
109
-
110
- // Create message element if it doesn't exist but we have message templates
111
- if (!this.#messageElement && (this.#originalAboveMessage || this.#originalBelowMessage)) {
112
- this.#messageElement = document.createElement('p');
113
- this.#messageElement.setAttribute('data-content-cart-progress-message', '');
114
- this.appendChild(this.#messageElement);
107
+ const _ = this;
108
+ _.#msgEl = _.querySelector("[data-content-cart-progress-message]");
109
+ _.#bar = _.querySelector("progress-bar");
110
+ if (!_.#msgEl && (_.#msgAbove || _.#msgBelow)) {
111
+ _.#msgEl = document.createElement("p");
112
+ _.#msgEl.setAttribute("data-content-cart-progress-message", "");
113
+ _.appendChild(_.#msgEl);
115
114
  }
116
-
117
- // Create progress bar if it doesn't exist - add it at the end (below text message)
118
- if (!this.#progressBar) {
119
- // Ensure progress-bar is defined before creating
120
- if (customElements.get('progress-bar')) {
121
- this.#progressBar = document.createElement('progress-bar');
122
- this.appendChild(this.#progressBar);
123
- } else {
124
- // Fallback: wait for definition
125
- customElements.whenDefined('progress-bar').then(() => {
126
- if (!this.#progressBar) {
127
- this.#progressBar = document.createElement('progress-bar');
128
- this.appendChild(this.#progressBar);
129
- this.#updateProgress(); // Update progress after creating
130
- }
131
- });
132
- }
115
+ if (!_.#bar) {
116
+ _.#bar = document.createElement("progress-bar");
117
+ _.appendChild(_.#bar);
133
118
  }
134
119
  }
135
-
136
120
  #updateProgress() {
137
- if (this.#minAmount === 0) {
138
- this.#progressPercent = 100;
139
- } else {
140
- this.#progressPercent = Math.min(100, (this.#currentAmount / this.#minAmount) * 100);
141
- }
142
-
143
- // Update progress bar
144
- if (this.#progressBar) {
145
- this.#progressBar.setPercent(this.#progressPercent);
146
- }
147
-
148
- // Update messages
149
- this.#updateMessages();
150
-
151
- // Update component state
152
- this.#updateComponentState();
121
+ const _ = this;
122
+ const converted = _.#converted();
123
+ _.#percent = converted === 0 ? 100 : Math.min(100, _.#current / converted * 100);
124
+ if (_.#bar) _.#bar.setPercent(_.#percent);
125
+ _.#updateState(converted);
153
126
  }
154
-
155
127
  #attachListeners() {
156
- // Find the nearest cart-panel component
157
- const cartDialog = this.closest('cart-dialog');
158
-
159
- if (cartDialog) {
160
- // Listen for cart data changes
161
- cartDialog.addEventListener('cart-dialog:data-changed', (event) => {
162
- this.#handleCartDataChange(event);
163
- });
128
+ const _ = this;
129
+ const target = _.closest(_.#listenSelector);
130
+ if (target) {
131
+ _.#listenHandler = (e) => _.#onCartChange(e);
132
+ _.#listenTarget = target;
133
+ target.addEventListener(_.#listenEvent, _.#listenHandler);
164
134
  }
165
135
  }
166
-
167
- #handleCartDataChange(event) {
168
- const updatedCart = event.detail;
169
-
170
- if (updatedCart) {
171
- // Use calculated_subtotal if available (handles _ignore_price_in_subtotal logic)
172
- // Otherwise fall back to total_price for backwards compatibility
173
- let currentAmount = 0;
174
-
175
- if (typeof updatedCart.calculated_subtotal !== 'undefined') {
176
- // calculated_subtotal is already in dollars, no conversion needed
177
- currentAmount = updatedCart.calculated_subtotal / 100;
178
- } else if (typeof updatedCart.total_price !== 'undefined') {
179
- // Convert from cents to dollars if needed (Shopify typically returns cents)
180
- currentAmount = updatedCart.total_price / 100;
181
- }
182
-
183
- this.setCurrentAmount(currentAmount);
136
+ #detachListeners() {
137
+ const _ = this;
138
+ if (_.#listenTarget && _.#listenHandler) {
139
+ _.#listenTarget.removeEventListener(_.#listenEvent, _.#listenHandler);
140
+ _.#listenTarget = null;
141
+ _.#listenHandler = null;
184
142
  }
185
143
  }
186
-
187
- #updateMessages() {
188
- const isComplete = this.#currentAmount >= this.#minAmount;
189
- const remainingAmount = Math.max(0, this.#minAmount - this.#currentAmount);
190
-
191
- // Format amount with minimal formatting
192
- const formattedAmount = remainingAmount.toFixed(2).replace('.00', '');
193
-
194
- // Update the single message element
195
- if (this.#messageElement) {
196
- let messageTemplate;
197
-
198
- if (isComplete && this.#originalAboveMessage) {
199
- // Show success message when complete
200
- messageTemplate = this.#originalAboveMessage;
201
- } else if (!isComplete) {
202
- // Show progress message when incomplete
203
- messageTemplate = this.#originalBelowMessage || this.#originalAboveMessage;
204
- }
205
-
206
- if (messageTemplate) {
207
- // Support multiple placeholder formats: {amount}, { amount }, [amount]
208
- const message = messageTemplate
209
- .replace(/\{\s*amount\s*\}/g, formattedAmount)
210
- .replace(/\[\s*amount\s*\]/g, formattedAmount);
211
- this.#messageElement.textContent = message;
212
- this.#messageElement.style.display = 'block';
213
- } else {
214
- // Hide message if no template available for current state
215
- this.#messageElement.style.display = 'none';
216
- }
144
+ #onCartChange(event) {
145
+ const _ = this;
146
+ const cart = event.detail;
147
+ if (!cart) return;
148
+ if (_.#debounce) clearTimeout(_.#debounce);
149
+ _.#debounce = setTimeout(() => {
150
+ _.#debounce = null;
151
+ const amt = (cart.calculated_subtotal ?? cart.total_price ?? 0) / 100;
152
+ _.setCurrentAmount(amt);
153
+ }, 100);
154
+ }
155
+ #updateState(converted) {
156
+ const _ = this;
157
+ const complete = _.#current >= converted;
158
+ const remaining = Math.max(0, converted - _.#current);
159
+ const formatted = _.#fmtMoney(remaining);
160
+ if (_.#msgEl) {
161
+ let tpl = complete ? _.#msgAbove : _.#msgBelow || _.#msgAbove;
162
+ if (tpl) {
163
+ _.#msgEl.textContent = tpl.replace(/\[\s*amount\s*\]/g, formatted);
164
+ _.#msgEl.style.display = "block";
165
+ } else _.#msgEl.style.display = "none";
217
166
  }
167
+ _.setAttribute("complete", complete.toString());
218
168
  }
219
-
220
- #updateComponentState() {
221
- const isComplete = this.#currentAmount >= this.#minAmount;
222
- this.setAttribute('complete', isComplete.toString());
169
+ #fmtMoney(amt) {
170
+ const fmt = this.#moneyFmt;
171
+ if (!fmt) return amt.toFixed(2).replace(/\.00$/, "");
172
+ const fixed = amt.toFixed(2);
173
+ const noDecimals = Math.round(amt).toString();
174
+ const withComma = fixed.replace(".", ",");
175
+ const noDecWithComma = noDecimals.replace(/\B(?=(\d{3})+(?!\d))/g, ",");
176
+ return fmt.replace(/\{\{\s*amount_no_decimals_with_comma_separator\s*\}\}/g, noDecWithComma).replace(/\{\{\s*amount_with_comma_separator\s*\}\}/g, withComma).replace(/\{\{\s*amount_no_decimals\s*\}\}/g, noDecimals).replace(/\{\{\s*amount\s*\}\}/g, fixed);
223
177
  }
224
-
225
-
226
- /**
227
- * Public API: Set the progress percentage directly
228
- * @param {number} percent - Progress percentage (0-100)
229
- */
230
- setPercent(percent) {
231
- const clampedPercent = Math.max(0, Math.min(100, percent));
232
- this.#progressPercent = clampedPercent;
233
-
234
- if (this.#progressBar) {
235
- this.#progressBar.setPercent(clampedPercent);
236
- }
237
-
238
- // Calculate current amount based on percentage
239
- this.#currentAmount = (clampedPercent / 100) * this.#minAmount;
240
- this.setAttribute('current', this.#currentAmount.toString());
241
-
242
- this.#updateMessages();
243
- this.#updateComponentState();
244
- }
245
-
246
- /**
247
- * Public API: Set the current cart amount
248
- * @param {number} amount - Current cart amount
249
- */
250
- setCurrentAmount(amount) {
251
- this.#currentAmount = parseFloat(amount) || 0;
252
- this.setAttribute('current', this.#currentAmount.toString());
253
- this.#updateProgress();
178
+ #converted() {
179
+ const rate = parseFloat(window.Shopify?.currency?.rate) || 1;
180
+ return this.#threshold * rate;
254
181
  }
255
-
256
- /**
257
- * Public API: Set the threshold amount for free shipping
258
- * @param {number} amount - Threshold amount for free shipping
259
- */
260
- setThresholdAmount(amount) {
261
- this.#minAmount = parseFloat(amount) || 0;
262
- this.setAttribute('threshold', this.#minAmount.toString());
263
- this.#updateProgress();
264
- }
265
-
266
- /**
267
- * Public API: Set the minimum amount for free shipping (deprecated - use setThresholdAmount)
268
- * @param {number} amount - Minimum amount threshold
269
- * @deprecated Use setThresholdAmount instead
270
- */
271
- setMinAmount(amount) {
272
- this.setThresholdAmount(amount);
182
+ #updateMessages() {
183
+ this.#updateState(this.#converted());
184
+ }
185
+ setPercent(pct) {
186
+ const _ = this;
187
+ const p = Math.max(0, Math.min(100, pct));
188
+ _.#percent = p;
189
+ if (_.#bar) _.#bar.setPercent(p);
190
+ _.#current = p / 100 * _.#converted();
191
+ _.setAttribute("current", _.#current.toString());
192
+ _.#updateState(_.#converted());
193
+ }
194
+ setCurrentAmount(amt) {
195
+ const _ = this;
196
+ _.#current = parseFloat(amt) || 0;
197
+ _.setAttribute("current", _.#current.toString());
198
+ _.#updateProgress();
199
+ }
200
+ setThresholdAmount(amt) {
201
+ const _ = this;
202
+ _.#threshold = parseFloat(amt) || 0;
203
+ _.setAttribute("threshold", _.#threshold.toString());
204
+ _.#updateProgress();
205
+ }
206
+ /** @deprecated Use setThresholdAmount */
207
+ setMinAmount(amt) {
208
+ this.setThresholdAmount(amt);
273
209
  }
274
-
275
- /**
276
- * Public API: Get current progress information
277
- */
278
210
  getProgress() {
211
+ const _ = this;
212
+ const converted = _.#converted();
279
213
  return {
280
- currentAmount: this.#currentAmount,
281
- thresholdAmount: this.#minAmount,
282
- minAmount: this.#minAmount, // backwards compatibility
283
- remainingAmount: Math.max(0, this.#minAmount - this.#currentAmount),
284
- percent: this.#progressPercent,
285
- isComplete: this.#currentAmount >= this.#minAmount,
214
+ currentAmount: _.#current,
215
+ thresholdAmount: _.#threshold,
216
+ convertedThreshold: converted,
217
+ minAmount: _.#threshold,
218
+ remainingAmount: Math.max(0, converted - _.#current),
219
+ percent: _.#percent,
220
+ isComplete: _.#current >= converted,
221
+ currencyRate: parseFloat(window.Shopify?.currency?.rate) || 1
286
222
  };
287
223
  }
288
-
289
- /**
290
- * Public API: Update message templates
291
- * @param {string} aboveMessage - Message template for above the bar
292
- * @param {string} belowMessage - Message template for below the bar
293
- */
294
- setMessages(aboveMessage = null, belowMessage = null) {
295
- if (aboveMessage !== null) {
296
- this.#originalAboveMessage = aboveMessage;
297
- this.setAttribute('message-above', aboveMessage);
224
+ setMessages(above = null, below = null) {
225
+ const _ = this;
226
+ if (above !== null) {
227
+ _.#msgAbove = above;
228
+ _.setAttribute("message-above", above);
298
229
  }
299
-
300
- if (belowMessage !== null) {
301
- this.#originalBelowMessage = belowMessage;
302
- this.setAttribute('message-below', belowMessage);
230
+ if (below !== null) {
231
+ _.#msgBelow = below;
232
+ _.setAttribute("message-below", below);
303
233
  }
304
-
305
- this.#updateMessages();
234
+ _.#updateMessages();
306
235
  }
307
-
308
- // Getters
309
236
  get currentAmount() {
310
- return this.#currentAmount;
237
+ return this.#current;
311
238
  }
312
239
  get thresholdAmount() {
313
- return this.#minAmount;
240
+ return this.#threshold;
314
241
  }
315
242
  get minAmount() {
316
- return this.#minAmount;
317
- } // backwards compatibility
243
+ return this.#threshold;
244
+ }
318
245
  get percent() {
319
- return this.#progressPercent;
246
+ return this.#percent;
320
247
  }
321
248
  get isComplete() {
322
- return this.#currentAmount >= this.#minAmount;
249
+ return this.#current >= this.#converted();
323
250
  }
324
- }
325
-
326
- // Define CartProgressBar custom element
327
- customElements.define('cart-progress-bar', CartProgressBar);
328
-
251
+ };
252
+ if (!customElements.get("cart-progress-bar")) customElements.define("cart-progress-bar", CartProgressBar);
253
+ //#endregion
329
254
  export { CartProgressBar, ProgressBar };
330
- //# sourceMappingURL=cart-progress-bar.esm.js.map
@@ -1 +1,2 @@
1
- cart-progress-bar{--cart-progress-bar-height:12px;--cart-progress-bar-border-radius:6px;--cart-progress-bar-shadow:inset 0 1px 2px rgba(0,0,0,.1);--cart-progress-bar-transition-duration:0.3s;--cart-progress-section-bg:transparent;--cart-progress-section-color:#495057;--cart-progress-bar-bg:#e9ecef;--cart-progress-bar-fill-before:#28a745;--cart-progress-bar-fill-after:#007bff;--cart-progress-percent:0%;--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-before);background-color:var(--cart-progress-section-bg);color:var(--cart-progress-section-color);display:block;max-width:100%;width:100%}cart-progress-bar p[data-content-cart-progress-message]{color:inherit;transition:opacity var(--cart-progress-bar-transition-duration) ease}cart-progress-bar[complete=true] p[data-content-cart-progress-message]{font-weight:600}cart-progress-bar[complete=false]{--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-before)}cart-progress-bar[complete=true]{--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-after)}progress-bar{background-color:var(--cart-progress-bar-bg);box-shadow:var(--cart-progress-bar-shadow);display:block;height:var(--cart-progress-bar-height);overflow:hidden;width:100%}progress-bar,progress-bar .progress-bar-fill{border-radius:var(--cart-progress-bar-border-radius);position:relative}progress-bar .progress-bar-fill{background-color:var(--cart-progress-bar-fill-current);background-image:linear-gradient(45deg,hsla(0,0%,100%,.1) 25%,transparent 0,transparent 50%,hsla(0,0%,100%,.1) 0,hsla(0,0%,100%,.1) 75%,transparent 0,transparent);background-size:12px 12px;height:100%;transition:width var(--cart-progress-bar-transition-duration) ease,background-color var(--cart-progress-bar-transition-duration) ease;width:var(--cart-progress-percent)}progress-bar .progress-bar-fill:after{background:linear-gradient(90deg,transparent,hsla(0,0%,100%,.4),transparent);content:"";height:100%;left:-100%;position:absolute;top:0;transition:left .5s ease;width:100%}cart-progress-bar[complete=true] progress-bar .progress-bar-fill:after{left:100%}progress-bar:focus-visible{outline:2px solid #007bff;outline-offset:2px}
1
+ cart-progress-bar{--cart-progress-bar-height:12px;--cart-progress-bar-border-radius:6px;--cart-progress-bar-transition-duration:.3s;--cart-progress-bar-bg:#e9ecef;--cart-progress-bar-fill-before:#28a745;--cart-progress-bar-fill-after:#007bff;--cart-progress-percent:0%;--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-before);width:100%;display:block}cart-progress-bar p[data-content-cart-progress-message]{transition:opacity var(--cart-progress-bar-transition-duration) ease}cart-progress-bar[complete=true] p[data-content-cart-progress-message]{font-weight:600}cart-progress-bar[complete=false]{--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-before)}cart-progress-bar[complete=true]{--cart-progress-bar-fill-current:var(--cart-progress-bar-fill-after)}progress-bar{width:100%;height:var(--cart-progress-bar-height);background-color:var(--cart-progress-bar-bg);border-radius:var(--cart-progress-bar-border-radius);display:block;position:relative;overflow:hidden}progress-bar .progress-bar-fill{height:100%;width:var(--cart-progress-percent);background-color:var(--cart-progress-bar-fill-current);border-radius:var(--cart-progress-bar-border-radius);transition:width var(--cart-progress-bar-transition-duration) ease, background-color var(--cart-progress-bar-transition-duration) ease}
2
+ /*$vite$:1*/
@@ -1 +1 @@
1
- !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CartProgressBar={})}(this,function(e){"use strict";class ProgressBar extends HTMLElement{constructor(){super(),this.#e()}#e(){this.setAttribute("role","progressbar"),this.setAttribute("aria-valuemin","0"),this.setAttribute("aria-valuemax","100"),this.setAttribute("aria-valuenow","0"),this.innerHTML='<div class="progress-bar-fill"></div>'}setPercent(e){const t=Math.max(0,Math.min(100,e));this.style.setProperty("--cart-progress-percent",`${t}%`),this.setAttribute("aria-valuenow",t)}}customElements.define("progress-bar",ProgressBar);class CartProgressBar extends HTMLElement{#t=0;#s=0;#r=0;#i="";#n="";#a=null;#o=null;static get observedAttributes(){return["threshold","current","message-above","message-below"]}constructor(){super(),this.#h()}#h(){this.#t=parseFloat(this.getAttribute("threshold"))||0,this.#s=parseFloat(this.getAttribute("current"))||0,this.#i=this.getAttribute("message-above")||"",this.#n=this.getAttribute("message-below")||""}async connectedCallback(){if(await customElements.whenDefined("progress-bar"),!customElements.get("progress-bar"))throw new Error("<progress-bar> must be registered before <cart-progress-bar> runs");this.#u(),this.#g(),this.#m()}attributeChangedCallback(e,t,s){if(t!==s)switch(e){case"threshold":this.#t=parseFloat(s)||0,this.#g();break;case"current":this.#s=parseFloat(s)||0,this.#g();break;case"message-above":this.#i=s||"",this.#l();break;case"message-below":this.#n=s||"",this.#l()}}#u(){this.#o=this.querySelector("[data-content-cart-progress-message]")||this.querySelector("p[data-content-cart-progress-message]"),this.#a=this.querySelector("progress-bar"),this.#o||!this.#i&&!this.#n||(this.#o=document.createElement("p"),this.#o.setAttribute("data-content-cart-progress-message",""),this.appendChild(this.#o)),this.#a||(customElements.get("progress-bar")?(this.#a=document.createElement("progress-bar"),this.appendChild(this.#a)):customElements.whenDefined("progress-bar").then(()=>{this.#a||(this.#a=document.createElement("progress-bar"),this.appendChild(this.#a),this.#g())}))}#g(){0===this.#t?this.#r=100:this.#r=Math.min(100,this.#s/this.#t*100),this.#a&&this.#a.setPercent(this.#r),this.#l(),this.#c()}#m(){const e=this.closest("cart-dialog");e&&e.addEventListener("cart-dialog:data-changed",e=>{this.#p(e)})}#p(e){const t=e.detail;if(t){let e=0;void 0!==t.calculated_subtotal?e=t.calculated_subtotal/100:void 0!==t.total_price&&(e=t.total_price/100),this.setCurrentAmount(e)}}#l(){const e=this.#s>=this.#t,t=Math.max(0,this.#t-this.#s).toFixed(2).replace(".00","");if(this.#o){let s;if(e&&this.#i?s=this.#i:e||(s=this.#n||this.#i),s){const e=s.replace(/\{\s*amount\s*\}/g,t).replace(/\[\s*amount\s*\]/g,t);this.#o.textContent=e,this.#o.style.display="block"}else this.#o.style.display="none"}}#c(){const e=this.#s>=this.#t;this.setAttribute("complete",e.toString())}setPercent(e){const t=Math.max(0,Math.min(100,e));this.#r=t,this.#a&&this.#a.setPercent(t),this.#s=t/100*this.#t,this.setAttribute("current",this.#s.toString()),this.#l(),this.#c()}setCurrentAmount(e){this.#s=parseFloat(e)||0,this.setAttribute("current",this.#s.toString()),this.#g()}setThresholdAmount(e){this.#t=parseFloat(e)||0,this.setAttribute("threshold",this.#t.toString()),this.#g()}setMinAmount(e){this.setThresholdAmount(e)}getProgress(){return{currentAmount:this.#s,thresholdAmount:this.#t,minAmount:this.#t,remainingAmount:Math.max(0,this.#t-this.#s),percent:this.#r,isComplete:this.#s>=this.#t}}setMessages(e=null,t=null){null!==e&&(this.#i=e,this.setAttribute("message-above",e)),null!==t&&(this.#n=t,this.setAttribute("message-below",t)),this.#l()}get currentAmount(){return this.#s}get thresholdAmount(){return this.#t}get minAmount(){return this.#t}get percent(){return this.#r}get isComplete(){return this.#s>=this.#t}}customElements.define("cart-progress-bar",CartProgressBar),e.CartProgressBar=CartProgressBar,e.ProgressBar=ProgressBar});
1
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).CartProgressBar={})}(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:"Module"});var ProgressBar=class extends HTMLElement{constructor(){super();const e=this;e.setAttribute("role","progressbar"),e.setAttribute("aria-valuemin","0"),e.setAttribute("aria-valuemax","100"),e.setAttribute("aria-valuenow","0"),e.innerHTML='<div class="progress-bar-fill"></div>'}setPercent(e){const t=Math.max(0,Math.min(100,e));this.style.setProperty("--cart-progress-percent",`${t}%`),this.setAttribute("aria-valuenow",t)}};customElements.get("progress-bar")||customElements.define("progress-bar",ProgressBar);var CartProgressBar=class extends HTMLElement{#e=0;#t=0;#s=0;#r="";#n="";#a=null;#o=null;#l=null;#c=null;#i="cart-panel";#u="cart-panel:data-changed";#d=null;#m=null;static get observedAttributes(){return["threshold","current","message-above","message-below","money-format","listen-selector","listen-event"]}constructor(){super();const e=this;e.#e=parseFloat(e.getAttribute("threshold"))||0,e.#t=parseFloat(e.getAttribute("current"))||0,e.#r=e.getAttribute("message-above")||"",e.#n=e.getAttribute("message-below")||"",e.#l=e.getAttribute("money-format"),e.#i=e.getAttribute("listen-selector")||"cart-panel",e.#u=e.getAttribute("listen-event")||"cart-panel:data-changed"}async connectedCallback(){await customElements.whenDefined("progress-bar"),this.#g(),this.#h(),this.#p()}disconnectedCallback(){this.#c&&clearTimeout(this.#c),this.#b()}attributeChangedCallback(e,t,s){if(t===s)return;const r=this;switch(e){case"threshold":r.#e=parseFloat(s)||0,r.#h();break;case"current":r.#t=parseFloat(s)||0,r.#h();break;case"message-above":r.#r=s||"",r.#v();break;case"message-below":r.#n=s||"",r.#v();break;case"money-format":r.#l=s,r.#v();break;case"listen-selector":r.#i=s||"cart-panel",r.#b(),r.#p();break;case"listen-event":r.#b(),r.#u=s||"cart-panel:data-changed",r.#p()}}#g(){const e=this;e.#o=e.querySelector("[data-content-cart-progress-message]"),e.#a=e.querySelector("progress-bar"),e.#o||!e.#r&&!e.#n||(e.#o=document.createElement("p"),e.#o.setAttribute("data-content-cart-progress-message",""),e.appendChild(e.#o)),e.#a||(e.#a=document.createElement("progress-bar"),e.appendChild(e.#a))}#h(){const e=this,t=e.#A();e.#s=0===t?100:Math.min(100,e.#t/t*100),e.#a&&e.#a.setPercent(e.#s),e.#y(t)}#p(){const e=this,t=e.closest(e.#i);t&&(e.#m=t=>e.#f(t),e.#d=t,t.addEventListener(e.#u,e.#m))}#b(){const e=this;e.#d&&e.#m&&(e.#d.removeEventListener(e.#u,e.#m),e.#d=null,e.#m=null)}#f(e){const t=this,s=e.detail;s&&(t.#c&&clearTimeout(t.#c),t.#c=setTimeout(()=>{t.#c=null;const e=(s.calculated_subtotal??s.total_price??0)/100;t.setCurrentAmount(e)},100))}#y(e){const t=this,s=t.#t>=e,r=Math.max(0,e-t.#t),n=t.#E(r);if(t.#o){let e=s?t.#r:t.#n||t.#r;e?(t.#o.textContent=e.replace(/\[\s*amount\s*\]/g,n),t.#o.style.display="block"):t.#o.style.display="none"}t.setAttribute("complete",s.toString())}#E(e){const t=this.#l;if(!t)return e.toFixed(2).replace(/\.00$/,"");const s=e.toFixed(2),r=Math.round(e).toString(),n=s.replace(".",","),a=r.replace(/\B(?=(\d{3})+(?!\d))/g,",");return t.replace(/\{\{\s*amount_no_decimals_with_comma_separator\s*\}\}/g,a).replace(/\{\{\s*amount_with_comma_separator\s*\}\}/g,n).replace(/\{\{\s*amount_no_decimals\s*\}\}/g,r).replace(/\{\{\s*amount\s*\}\}/g,s)}#A(){const e=parseFloat(window.Shopify?.currency?.rate)||1;return this.#e*e}#v(){this.#y(this.#A())}setPercent(e){const t=this,s=Math.max(0,Math.min(100,e));t.#s=s,t.#a&&t.#a.setPercent(s),t.#t=s/100*t.#A(),t.setAttribute("current",t.#t.toString()),t.#y(t.#A())}setCurrentAmount(e){const t=this;t.#t=parseFloat(e)||0,t.setAttribute("current",t.#t.toString()),t.#h()}setThresholdAmount(e){const t=this;t.#e=parseFloat(e)||0,t.setAttribute("threshold",t.#e.toString()),t.#h()}setMinAmount(e){this.setThresholdAmount(e)}getProgress(){const e=this,t=e.#A();return{currentAmount:e.#t,thresholdAmount:e.#e,convertedThreshold:t,minAmount:e.#e,remainingAmount:Math.max(0,t-e.#t),percent:e.#s,isComplete:e.#t>=t,currencyRate:parseFloat(window.Shopify?.currency?.rate)||1}}setMessages(e=null,t=null){const s=this;null!==e&&(s.#r=e,s.setAttribute("message-above",e)),null!==t&&(s.#n=t,s.setAttribute("message-below",t)),s.#v()}get currentAmount(){return this.#t}get thresholdAmount(){return this.#e}get minAmount(){return this.#e}get percent(){return this.#s}get isComplete(){return this.#t>=this.#A()}};customElements.get("cart-progress-bar")||customElements.define("cart-progress-bar",CartProgressBar),e.CartProgressBar=CartProgressBar,e.ProgressBar=ProgressBar});