@magic-spells/cart-progress-bar 1.0.0 → 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.
- package/README.md +89 -32
- package/dist/cart-progress-bar.css +15 -36
- package/dist/cart-progress-bar.esm.js +108 -114
- package/dist/cart-progress-bar.min.css +2 -1
- package/dist/cart-progress-bar.min.js +1 -1
- package/package.json +16 -23
- package/dist/cart-progress-bar.cjs.js +0 -263
- package/dist/cart-progress-bar.cjs.js.map +0 -1
- package/dist/cart-progress-bar.esm.js.map +0 -1
- package/dist/cart-progress-bar.js +0 -269
- package/dist/cart-progress-bar.js.map +0 -1
- package/dist/cart-progress-bar.scss +0 -124
- package/src/cart-progress-bar.js +0 -262
- package/src/cart-progress-bar.scss +0 -124
|
@@ -1,269 +0,0 @@
|
|
|
1
|
-
(function (global, factory) {
|
|
2
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
|
3
|
-
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
|
4
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.CartProgressBar = {}));
|
|
5
|
-
})(this, (function (exports) { 'use strict';
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* ProgressBar helper class for the visual progress bar element
|
|
9
|
-
*/
|
|
10
|
-
class ProgressBar extends HTMLElement {
|
|
11
|
-
constructor() {
|
|
12
|
-
super();
|
|
13
|
-
const _ = this;
|
|
14
|
-
_.setAttribute('role', 'progressbar');
|
|
15
|
-
_.setAttribute('aria-valuemin', '0');
|
|
16
|
-
_.setAttribute('aria-valuemax', '100');
|
|
17
|
-
_.setAttribute('aria-valuenow', '0');
|
|
18
|
-
_.innerHTML = '<div class="progress-bar-fill"></div>';
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
setPercent(percent) {
|
|
22
|
-
const p = Math.max(0, Math.min(100, percent));
|
|
23
|
-
this.style.setProperty('--cart-progress-percent', `${p}%`);
|
|
24
|
-
this.setAttribute('aria-valuenow', p);
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
// Define ProgressBar custom element immediately so it's available for CartProgressBar
|
|
29
|
-
customElements.define('progress-bar', ProgressBar);
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* CartProgressBar main component
|
|
33
|
-
*/
|
|
34
|
-
class CartProgressBar extends HTMLElement {
|
|
35
|
-
// Private fields
|
|
36
|
-
#threshold = 0;
|
|
37
|
-
#current = 0;
|
|
38
|
-
#percent = 0;
|
|
39
|
-
#msgAbove = '';
|
|
40
|
-
#msgBelow = '';
|
|
41
|
-
#bar = null;
|
|
42
|
-
#msgEl = null;
|
|
43
|
-
#moneyFmt = null;
|
|
44
|
-
#debounce = null;
|
|
45
|
-
|
|
46
|
-
static get observedAttributes() {
|
|
47
|
-
return ['threshold', 'current', 'message-above', 'message-below', 'money-format'];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
constructor() {
|
|
51
|
-
super();
|
|
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
|
-
}
|
|
59
|
-
|
|
60
|
-
async connectedCallback() {
|
|
61
|
-
await customElements.whenDefined('progress-bar');
|
|
62
|
-
this.#render();
|
|
63
|
-
this.#updateProgress();
|
|
64
|
-
this.#attachListeners();
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
disconnectedCallback() {
|
|
68
|
-
if (this.#debounce) clearTimeout(this.#debounce);
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
attributeChangedCallback(name, oldVal, newVal) {
|
|
72
|
-
if (oldVal === newVal) return;
|
|
73
|
-
const _ = this;
|
|
74
|
-
|
|
75
|
-
switch (name) {
|
|
76
|
-
case 'threshold':
|
|
77
|
-
_.#threshold = parseFloat(newVal) || 0;
|
|
78
|
-
_.#updateProgress();
|
|
79
|
-
break;
|
|
80
|
-
case 'current':
|
|
81
|
-
_.#current = parseFloat(newVal) || 0;
|
|
82
|
-
_.#updateProgress();
|
|
83
|
-
break;
|
|
84
|
-
case 'message-above':
|
|
85
|
-
_.#msgAbove = newVal || '';
|
|
86
|
-
_.#updateMessages();
|
|
87
|
-
break;
|
|
88
|
-
case 'message-below':
|
|
89
|
-
_.#msgBelow = newVal || '';
|
|
90
|
-
_.#updateMessages();
|
|
91
|
-
break;
|
|
92
|
-
case 'money-format':
|
|
93
|
-
_.#moneyFmt = newVal;
|
|
94
|
-
_.#updateMessages();
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
#render() {
|
|
100
|
-
const _ = this;
|
|
101
|
-
// Find existing elements or create them
|
|
102
|
-
_.#msgEl = _.querySelector('[data-content-cart-progress-message]');
|
|
103
|
-
_.#bar = _.querySelector('progress-bar');
|
|
104
|
-
|
|
105
|
-
// Create message element if needed
|
|
106
|
-
if (!_.#msgEl && (_.#msgAbove || _.#msgBelow)) {
|
|
107
|
-
_.#msgEl = document.createElement('p');
|
|
108
|
-
_.#msgEl.setAttribute('data-content-cart-progress-message', '');
|
|
109
|
-
_.appendChild(_.#msgEl);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Create progress bar if needed
|
|
113
|
-
if (!_.#bar) {
|
|
114
|
-
_.#bar = document.createElement('progress-bar');
|
|
115
|
-
_.appendChild(_.#bar);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
#updateProgress() {
|
|
120
|
-
const _ = this;
|
|
121
|
-
const converted = _.#converted();
|
|
122
|
-
_.#percent = converted === 0 ? 100 : Math.min(100, (_.#current / converted) * 100);
|
|
123
|
-
if (_.#bar) _.#bar.setPercent(_.#percent);
|
|
124
|
-
_.#updateState(converted);
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
#attachListeners() {
|
|
128
|
-
const _ = this;
|
|
129
|
-
const panel = _.closest('cart-panel');
|
|
130
|
-
if (panel) {
|
|
131
|
-
panel.addEventListener('cart-panel:data-changed', (e) => _.#onCartChange(e));
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
#onCartChange(event) {
|
|
136
|
-
const _ = this;
|
|
137
|
-
const cart = event.detail;
|
|
138
|
-
if (!cart) return;
|
|
139
|
-
|
|
140
|
-
if (_.#debounce) clearTimeout(_.#debounce);
|
|
141
|
-
_.#debounce = setTimeout(() => {
|
|
142
|
-
_.#debounce = null;
|
|
143
|
-
// Use calculated_subtotal if available, else total_price (both in cents)
|
|
144
|
-
const amt = (cart.calculated_subtotal ?? cart.total_price ?? 0) / 100;
|
|
145
|
-
_.setCurrentAmount(amt);
|
|
146
|
-
}, 100);
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
#updateState(converted) {
|
|
150
|
-
const _ = this;
|
|
151
|
-
const complete = _.#current >= converted;
|
|
152
|
-
const remaining = Math.max(0, converted - _.#current);
|
|
153
|
-
const formatted = _.#fmtMoney(remaining);
|
|
154
|
-
|
|
155
|
-
// Update message
|
|
156
|
-
if (_.#msgEl) {
|
|
157
|
-
let tpl = complete ? _.#msgAbove : (_.#msgBelow || _.#msgAbove);
|
|
158
|
-
if (tpl) {
|
|
159
|
-
_.#msgEl.textContent = tpl.replace(/\[\s*amount\s*\]/g, formatted);
|
|
160
|
-
_.#msgEl.style.display = 'block';
|
|
161
|
-
} else {
|
|
162
|
-
_.#msgEl.style.display = 'none';
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Update complete attribute
|
|
167
|
-
_.setAttribute('complete', complete.toString());
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
#fmtMoney(amt) {
|
|
171
|
-
const fmt = this.#moneyFmt;
|
|
172
|
-
if (!fmt) return amt.toFixed(2).replace(/\.00$/, '');
|
|
173
|
-
|
|
174
|
-
const fixed = amt.toFixed(2);
|
|
175
|
-
const noDecimals = Math.round(amt).toString();
|
|
176
|
-
const withComma = fixed.replace('.', ',');
|
|
177
|
-
const noDecWithComma = noDecimals.replace(/\B(?=(\d{3})+(?!\d))/g, ',');
|
|
178
|
-
|
|
179
|
-
return fmt
|
|
180
|
-
.replace(/\{\{\s*amount_no_decimals_with_comma_separator\s*\}\}/g, noDecWithComma)
|
|
181
|
-
.replace(/\{\{\s*amount_with_comma_separator\s*\}\}/g, withComma)
|
|
182
|
-
.replace(/\{\{\s*amount_no_decimals\s*\}\}/g, noDecimals)
|
|
183
|
-
.replace(/\{\{\s*amount\s*\}\}/g, fixed);
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
#converted() {
|
|
187
|
-
const rate = parseFloat(window.Shopify?.currency?.rate) || 1;
|
|
188
|
-
return this.#threshold * rate;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
#updateMessages() {
|
|
192
|
-
this.#updateState(this.#converted());
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
// Public API
|
|
196
|
-
setPercent(pct) {
|
|
197
|
-
const _ = this;
|
|
198
|
-
const p = Math.max(0, Math.min(100, pct));
|
|
199
|
-
_.#percent = p;
|
|
200
|
-
if (_.#bar) _.#bar.setPercent(p);
|
|
201
|
-
// Use converted threshold for multi-currency consistency
|
|
202
|
-
_.#current = (p / 100) * _.#converted();
|
|
203
|
-
_.setAttribute('current', _.#current.toString());
|
|
204
|
-
_.#updateState(_.#converted());
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
setCurrentAmount(amt) {
|
|
208
|
-
const _ = this;
|
|
209
|
-
_.#current = parseFloat(amt) || 0;
|
|
210
|
-
_.setAttribute('current', _.#current.toString());
|
|
211
|
-
_.#updateProgress();
|
|
212
|
-
}
|
|
213
|
-
|
|
214
|
-
setThresholdAmount(amt) {
|
|
215
|
-
const _ = this;
|
|
216
|
-
_.#threshold = parseFloat(amt) || 0;
|
|
217
|
-
_.setAttribute('threshold', _.#threshold.toString());
|
|
218
|
-
_.#updateProgress();
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/** @deprecated Use setThresholdAmount */
|
|
222
|
-
setMinAmount(amt) {
|
|
223
|
-
this.setThresholdAmount(amt);
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
getProgress() {
|
|
227
|
-
const _ = this;
|
|
228
|
-
const converted = _.#converted();
|
|
229
|
-
return {
|
|
230
|
-
currentAmount: _.#current,
|
|
231
|
-
thresholdAmount: _.#threshold,
|
|
232
|
-
convertedThreshold: converted,
|
|
233
|
-
minAmount: _.#threshold,
|
|
234
|
-
remainingAmount: Math.max(0, converted - _.#current),
|
|
235
|
-
percent: _.#percent,
|
|
236
|
-
isComplete: _.#current >= converted,
|
|
237
|
-
currencyRate: parseFloat(window.Shopify?.currency?.rate) || 1,
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
setMessages(above = null, below = null) {
|
|
242
|
-
const _ = this;
|
|
243
|
-
if (above !== null) {
|
|
244
|
-
_.#msgAbove = above;
|
|
245
|
-
_.setAttribute('message-above', above);
|
|
246
|
-
}
|
|
247
|
-
if (below !== null) {
|
|
248
|
-
_.#msgBelow = below;
|
|
249
|
-
_.setAttribute('message-below', below);
|
|
250
|
-
}
|
|
251
|
-
_.#updateMessages();
|
|
252
|
-
}
|
|
253
|
-
|
|
254
|
-
// Getters (with backwards compatibility)
|
|
255
|
-
get currentAmount() { return this.#current; }
|
|
256
|
-
get thresholdAmount() { return this.#threshold; }
|
|
257
|
-
get minAmount() { return this.#threshold; }
|
|
258
|
-
get percent() { return this.#percent; }
|
|
259
|
-
get isComplete() { return this.#current >= this.#converted(); }
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
// Define CartProgressBar custom element
|
|
263
|
-
customElements.define('cart-progress-bar', CartProgressBar);
|
|
264
|
-
|
|
265
|
-
exports.CartProgressBar = CartProgressBar;
|
|
266
|
-
exports.ProgressBar = ProgressBar;
|
|
267
|
-
|
|
268
|
-
}));
|
|
269
|
-
//# sourceMappingURL=cart-progress-bar.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cart-progress-bar.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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"}
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
// SCSS Variables (can be overridden before import)
|
|
2
|
-
$cart-progress-bar-height: 12px !default;
|
|
3
|
-
$cart-progress-bar-border-radius: 6px !default;
|
|
4
|
-
$cart-progress-bar-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1) !default;
|
|
5
|
-
$cart-progress-bar-transition-duration: 0.3s !default;
|
|
6
|
-
|
|
7
|
-
// Core color variables
|
|
8
|
-
$cart-progress-section-bg: transparent !default;
|
|
9
|
-
$cart-progress-section-color: #495057 !default;
|
|
10
|
-
$cart-progress-bar-bg: #e9ecef !default;
|
|
11
|
-
$cart-progress-bar-fill-before: #28a745 !default;
|
|
12
|
-
$cart-progress-bar-fill-after: #007bff !default;
|
|
13
|
-
|
|
14
|
-
// Responsive breakpoints
|
|
15
|
-
$cart-progress-mobile-breakpoint: 768px !default;
|
|
16
|
-
|
|
17
|
-
// Cart progress bar component styles
|
|
18
|
-
cart-progress-bar {
|
|
19
|
-
// CSS Custom Properties for customization (mapped from SCSS variables)
|
|
20
|
-
--cart-progress-bar-height: #{$cart-progress-bar-height};
|
|
21
|
-
--cart-progress-bar-border-radius: #{$cart-progress-bar-border-radius};
|
|
22
|
-
--cart-progress-bar-shadow: #{$cart-progress-bar-shadow};
|
|
23
|
-
--cart-progress-bar-transition-duration: #{$cart-progress-bar-transition-duration};
|
|
24
|
-
|
|
25
|
-
// Core color variables
|
|
26
|
-
--cart-progress-section-bg: #{$cart-progress-section-bg};
|
|
27
|
-
--cart-progress-section-color: #{$cart-progress-section-color};
|
|
28
|
-
--cart-progress-bar-bg: #{$cart-progress-bar-bg};
|
|
29
|
-
--cart-progress-bar-fill-before: #{$cart-progress-bar-fill-before};
|
|
30
|
-
--cart-progress-bar-fill-after: #{$cart-progress-bar-fill-after};
|
|
31
|
-
|
|
32
|
-
// Dynamic variables (set by JavaScript)
|
|
33
|
-
--cart-progress-percent: 0%;
|
|
34
|
-
--cart-progress-bar-fill-current: var(--cart-progress-bar-fill-before);
|
|
35
|
-
|
|
36
|
-
display: block;
|
|
37
|
-
width: 100%;
|
|
38
|
-
max-width: 100%;
|
|
39
|
-
background-color: var(--cart-progress-section-bg);
|
|
40
|
-
color: var(--cart-progress-section-color);
|
|
41
|
-
|
|
42
|
-
// Message styling
|
|
43
|
-
p[data-content-cart-progress-message] {
|
|
44
|
-
color: inherit;
|
|
45
|
-
transition: opacity var(--cart-progress-bar-transition-duration) ease;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
// State-based styling
|
|
49
|
-
&[complete='true'] {
|
|
50
|
-
p[data-content-cart-progress-message] {
|
|
51
|
-
font-weight: 600;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
// State-based progress bar coloring
|
|
56
|
-
&[complete='false'] {
|
|
57
|
-
--cart-progress-bar-fill-current: var(--cart-progress-bar-fill-before);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
&[complete='true'] {
|
|
61
|
-
--cart-progress-bar-fill-current: var(--cart-progress-bar-fill-after);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Progress bar component styles
|
|
66
|
-
progress-bar {
|
|
67
|
-
display: block;
|
|
68
|
-
width: 100%;
|
|
69
|
-
height: var(--cart-progress-bar-height);
|
|
70
|
-
background-color: var(--cart-progress-bar-bg);
|
|
71
|
-
border-radius: var(--cart-progress-bar-border-radius);
|
|
72
|
-
box-shadow: var(--cart-progress-bar-shadow);
|
|
73
|
-
overflow: hidden;
|
|
74
|
-
position: relative;
|
|
75
|
-
|
|
76
|
-
.progress-bar-fill {
|
|
77
|
-
height: 100%;
|
|
78
|
-
width: var(--cart-progress-percent);
|
|
79
|
-
background-color: var(--cart-progress-bar-fill-current);
|
|
80
|
-
border-radius: var(--cart-progress-bar-border-radius);
|
|
81
|
-
transition:
|
|
82
|
-
width var(--cart-progress-bar-transition-duration) ease,
|
|
83
|
-
background-color var(--cart-progress-bar-transition-duration) ease;
|
|
84
|
-
position: relative;
|
|
85
|
-
|
|
86
|
-
// Subtle gradient effect
|
|
87
|
-
background-image: linear-gradient(
|
|
88
|
-
45deg,
|
|
89
|
-
rgba(255, 255, 255, 0.1) 25%,
|
|
90
|
-
transparent 25%,
|
|
91
|
-
transparent 50%,
|
|
92
|
-
rgba(255, 255, 255, 0.1) 50%,
|
|
93
|
-
rgba(255, 255, 255, 0.1) 75%,
|
|
94
|
-
transparent 75%,
|
|
95
|
-
transparent
|
|
96
|
-
);
|
|
97
|
-
background-size: 12px 12px;
|
|
98
|
-
|
|
99
|
-
// Shine effect for completed state
|
|
100
|
-
&::after {
|
|
101
|
-
content: '';
|
|
102
|
-
position: absolute;
|
|
103
|
-
top: 0;
|
|
104
|
-
left: -100%;
|
|
105
|
-
width: 100%;
|
|
106
|
-
height: 100%;
|
|
107
|
-
background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
|
|
108
|
-
transition: left 0.5s ease;
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
// Animate shine effect when complete
|
|
113
|
-
cart-progress-bar[complete='true'] & {
|
|
114
|
-
.progress-bar-fill::after {
|
|
115
|
-
left: 100%;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
// Accessibility improvements
|
|
120
|
-
&:focus-visible {
|
|
121
|
-
outline: 2px solid #007bff;
|
|
122
|
-
outline-offset: 2px;
|
|
123
|
-
}
|
|
124
|
-
}
|
package/src/cart-progress-bar.js
DELETED
|
@@ -1,262 +0,0 @@
|
|
|
1
|
-
import './cart-progress-bar.scss';
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* ProgressBar helper class for the visual progress bar element
|
|
5
|
-
*/
|
|
6
|
-
class ProgressBar extends HTMLElement {
|
|
7
|
-
constructor() {
|
|
8
|
-
super();
|
|
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>';
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
setPercent(percent) {
|
|
18
|
-
const p = Math.max(0, Math.min(100, percent));
|
|
19
|
-
this.style.setProperty('--cart-progress-percent', `${p}%`);
|
|
20
|
-
this.setAttribute('aria-valuenow', p);
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
// Define ProgressBar custom element immediately so it's available for CartProgressBar
|
|
25
|
-
customElements.define('progress-bar', ProgressBar);
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* CartProgressBar main component
|
|
29
|
-
*/
|
|
30
|
-
class CartProgressBar extends HTMLElement {
|
|
31
|
-
// Private fields
|
|
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
|
-
|
|
42
|
-
static get observedAttributes() {
|
|
43
|
-
return ['threshold', 'current', 'message-above', 'message-below', 'money-format'];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
constructor() {
|
|
47
|
-
super();
|
|
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');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
async connectedCallback() {
|
|
57
|
-
await customElements.whenDefined('progress-bar');
|
|
58
|
-
this.#render();
|
|
59
|
-
this.#updateProgress();
|
|
60
|
-
this.#attachListeners();
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
disconnectedCallback() {
|
|
64
|
-
if (this.#debounce) clearTimeout(this.#debounce);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
attributeChangedCallback(name, oldVal, newVal) {
|
|
68
|
-
if (oldVal === newVal) return;
|
|
69
|
-
const _ = this;
|
|
70
|
-
|
|
71
|
-
switch (name) {
|
|
72
|
-
case 'threshold':
|
|
73
|
-
_.#threshold = parseFloat(newVal) || 0;
|
|
74
|
-
_.#updateProgress();
|
|
75
|
-
break;
|
|
76
|
-
case 'current':
|
|
77
|
-
_.#current = parseFloat(newVal) || 0;
|
|
78
|
-
_.#updateProgress();
|
|
79
|
-
break;
|
|
80
|
-
case 'message-above':
|
|
81
|
-
_.#msgAbove = newVal || '';
|
|
82
|
-
_.#updateMessages();
|
|
83
|
-
break;
|
|
84
|
-
case 'message-below':
|
|
85
|
-
_.#msgBelow = newVal || '';
|
|
86
|
-
_.#updateMessages();
|
|
87
|
-
break;
|
|
88
|
-
case 'money-format':
|
|
89
|
-
_.#moneyFmt = newVal;
|
|
90
|
-
_.#updateMessages();
|
|
91
|
-
break;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
#render() {
|
|
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);
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
// Create progress bar if needed
|
|
109
|
-
if (!_.#bar) {
|
|
110
|
-
_.#bar = document.createElement('progress-bar');
|
|
111
|
-
_.appendChild(_.#bar);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
#updateProgress() {
|
|
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);
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
#attachListeners() {
|
|
124
|
-
const _ = this;
|
|
125
|
-
const panel = _.closest('cart-panel');
|
|
126
|
-
if (panel) {
|
|
127
|
-
panel.addEventListener('cart-panel:data-changed', (e) => _.#onCartChange(e));
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
|
|
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);
|
|
143
|
-
}
|
|
144
|
-
|
|
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';
|
|
157
|
-
} else {
|
|
158
|
-
_.#msgEl.style.display = 'none';
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// Update complete attribute
|
|
163
|
-
_.setAttribute('complete', complete.toString());
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
#fmtMoney(amt) {
|
|
167
|
-
const fmt = this.#moneyFmt;
|
|
168
|
-
if (!fmt) return amt.toFixed(2).replace(/\.00$/, '');
|
|
169
|
-
|
|
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, ',');
|
|
174
|
-
|
|
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
|
-
}
|
|
186
|
-
|
|
187
|
-
#updateMessages() {
|
|
188
|
-
this.#updateState(this.#converted());
|
|
189
|
-
}
|
|
190
|
-
|
|
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());
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
setCurrentAmount(amt) {
|
|
204
|
-
const _ = this;
|
|
205
|
-
_.#current = parseFloat(amt) || 0;
|
|
206
|
-
_.setAttribute('current', _.#current.toString());
|
|
207
|
-
_.#updateProgress();
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
setThresholdAmount(amt) {
|
|
211
|
-
const _ = this;
|
|
212
|
-
_.#threshold = parseFloat(amt) || 0;
|
|
213
|
-
_.setAttribute('threshold', _.#threshold.toString());
|
|
214
|
-
_.#updateProgress();
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
/** @deprecated Use setThresholdAmount */
|
|
218
|
-
setMinAmount(amt) {
|
|
219
|
-
this.setThresholdAmount(amt);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
getProgress() {
|
|
223
|
-
const _ = this;
|
|
224
|
-
const converted = _.#converted();
|
|
225
|
-
return {
|
|
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,
|
|
234
|
-
};
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
setMessages(above = null, below = null) {
|
|
238
|
-
const _ = this;
|
|
239
|
-
if (above !== null) {
|
|
240
|
-
_.#msgAbove = above;
|
|
241
|
-
_.setAttribute('message-above', above);
|
|
242
|
-
}
|
|
243
|
-
if (below !== null) {
|
|
244
|
-
_.#msgBelow = below;
|
|
245
|
-
_.setAttribute('message-below', below);
|
|
246
|
-
}
|
|
247
|
-
_.#updateMessages();
|
|
248
|
-
}
|
|
249
|
-
|
|
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(); }
|
|
256
|
-
}
|
|
257
|
-
|
|
258
|
-
// Define CartProgressBar custom element
|
|
259
|
-
customElements.define('cart-progress-bar', CartProgressBar);
|
|
260
|
-
|
|
261
|
-
// Export components for external use
|
|
262
|
-
export { CartProgressBar, ProgressBar };
|