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