@magic-spells/cart-progress-bar 0.2.0 → 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.
- package/README.md +31 -12
- package/dist/cart-progress-bar.cjs.js +164 -242
- package/dist/cart-progress-bar.cjs.js.map +1 -1
- package/dist/cart-progress-bar.esm.js +164 -242
- package/dist/cart-progress-bar.esm.js.map +1 -1
- package/dist/cart-progress-bar.js +164 -242
- package/dist/cart-progress-bar.js.map +1 -1
- package/dist/cart-progress-bar.min.js +1 -1
- package/package.json +4 -4
- package/src/cart-progress-bar.js +164 -242
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cart-progress-bar.esm.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 remaining amount as currency (assuming USD for now)\n\t\tconst formattedAmount = this.#formatCurrency(remainingAmount);\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\tconst message = messageTemplate.replace('{ amount }', 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\t#formatCurrency(amount) {\n\t\t// Basic currency formatting - could be enhanced with locale/currency options\n\t\treturn new Intl.NumberFormat('en-US', {\n\t\t\tstyle: 'currency',\n\t\t\tcurrency: 'USD',\n\t\t\tminimumFractionDigits: 2,\n\t\t\tmaximumFractionDigits: 2,\n\t\t})\n\t\t\t.format(amount)\n\t\t\t.replace('.00', '');\n\t}\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.esm.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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"}
|
|
@@ -10,23 +10,18 @@
|
|
|
10
10
|
class ProgressBar extends HTMLElement {
|
|
11
11
|
constructor() {
|
|
12
12
|
super();
|
|
13
|
-
this
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
this.setAttribute('aria-valuemax', '100');
|
|
20
|
-
this.setAttribute('aria-valuenow', '0');
|
|
21
|
-
|
|
22
|
-
// Create the visual progress bar
|
|
23
|
-
this.innerHTML = '<div class="progress-bar-fill"></div>';
|
|
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>';
|
|
24
19
|
}
|
|
25
20
|
|
|
26
21
|
setPercent(percent) {
|
|
27
|
-
const
|
|
28
|
-
this.style.setProperty('--cart-progress-percent', `${
|
|
29
|
-
this.setAttribute('aria-valuenow',
|
|
22
|
+
const p = Math.max(0, Math.min(100, percent));
|
|
23
|
+
this.style.setProperty('--cart-progress-percent', `${p}%`);
|
|
24
|
+
this.setAttribute('aria-valuenow', p);
|
|
30
25
|
}
|
|
31
26
|
}
|
|
32
27
|
|
|
@@ -38,303 +33,230 @@
|
|
|
38
33
|
*/
|
|
39
34
|
class CartProgressBar extends HTMLElement {
|
|
40
35
|
// Private fields
|
|
41
|
-
#
|
|
42
|
-
#
|
|
43
|
-
#
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
*/
|
|
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
|
+
|
|
52
46
|
static get observedAttributes() {
|
|
53
|
-
return ['threshold', 'current', 'message-above', 'message-below'];
|
|
47
|
+
return ['threshold', 'current', 'message-above', 'message-below', 'money-format'];
|
|
54
48
|
}
|
|
55
49
|
|
|
56
50
|
constructor() {
|
|
57
51
|
super();
|
|
58
|
-
this
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
this.#currentAmount = parseFloat(this.getAttribute('current')) || 0;
|
|
65
|
-
|
|
66
|
-
// Store original message templates
|
|
67
|
-
this.#originalAboveMessage = this.getAttribute('message-above') || '';
|
|
68
|
-
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');
|
|
69
58
|
}
|
|
70
59
|
|
|
71
60
|
async connectedCallback() {
|
|
72
|
-
// ensure the child custom element has been registered
|
|
73
61
|
await customElements.whenDefined('progress-bar');
|
|
74
|
-
|
|
75
|
-
if (!customElements.get('progress-bar')) {
|
|
76
|
-
throw new Error('<progress-bar> must be registered before <cart-progress-bar> runs');
|
|
77
|
-
}
|
|
78
|
-
|
|
79
62
|
this.#render();
|
|
80
63
|
this.#updateProgress();
|
|
81
64
|
this.#attachListeners();
|
|
82
65
|
}
|
|
83
66
|
|
|
84
|
-
|
|
85
|
-
if (
|
|
67
|
+
disconnectedCallback() {
|
|
68
|
+
if (this.#debounce) clearTimeout(this.#debounce);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
attributeChangedCallback(name, oldVal, newVal) {
|
|
72
|
+
if (oldVal === newVal) return;
|
|
73
|
+
const _ = this;
|
|
86
74
|
|
|
87
75
|
switch (name) {
|
|
88
76
|
case 'threshold':
|
|
89
|
-
|
|
90
|
-
|
|
77
|
+
_.#threshold = parseFloat(newVal) || 0;
|
|
78
|
+
_.#updateProgress();
|
|
91
79
|
break;
|
|
92
80
|
case 'current':
|
|
93
|
-
|
|
94
|
-
|
|
81
|
+
_.#current = parseFloat(newVal) || 0;
|
|
82
|
+
_.#updateProgress();
|
|
95
83
|
break;
|
|
96
84
|
case 'message-above':
|
|
97
|
-
|
|
98
|
-
|
|
85
|
+
_.#msgAbove = newVal || '';
|
|
86
|
+
_.#updateMessages();
|
|
99
87
|
break;
|
|
100
88
|
case 'message-below':
|
|
101
|
-
|
|
102
|
-
|
|
89
|
+
_.#msgBelow = newVal || '';
|
|
90
|
+
_.#updateMessages();
|
|
91
|
+
break;
|
|
92
|
+
case 'money-format':
|
|
93
|
+
_.#moneyFmt = newVal;
|
|
94
|
+
_.#updateMessages();
|
|
103
95
|
break;
|
|
104
96
|
}
|
|
105
97
|
}
|
|
106
98
|
|
|
107
99
|
#render() {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
//
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
this.#messageElement = document.createElement('p');
|
|
119
|
-
this.#messageElement.setAttribute('data-content-cart-progress-message', '');
|
|
120
|
-
this.appendChild(this.#messageElement);
|
|
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);
|
|
121
110
|
}
|
|
122
111
|
|
|
123
|
-
// Create progress bar if
|
|
124
|
-
if (!
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
this.#progressBar = document.createElement('progress-bar');
|
|
128
|
-
this.appendChild(this.#progressBar);
|
|
129
|
-
} else {
|
|
130
|
-
// Fallback: wait for definition
|
|
131
|
-
customElements.whenDefined('progress-bar').then(() => {
|
|
132
|
-
if (!this.#progressBar) {
|
|
133
|
-
this.#progressBar = document.createElement('progress-bar');
|
|
134
|
-
this.appendChild(this.#progressBar);
|
|
135
|
-
this.#updateProgress(); // Update progress after creating
|
|
136
|
-
}
|
|
137
|
-
});
|
|
138
|
-
}
|
|
112
|
+
// Create progress bar if needed
|
|
113
|
+
if (!_.#bar) {
|
|
114
|
+
_.#bar = document.createElement('progress-bar');
|
|
115
|
+
_.appendChild(_.#bar);
|
|
139
116
|
}
|
|
140
117
|
}
|
|
141
118
|
|
|
142
119
|
#updateProgress() {
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
// Update progress bar
|
|
150
|
-
if (this.#progressBar) {
|
|
151
|
-
this.#progressBar.setPercent(this.#progressPercent);
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
// Update messages
|
|
155
|
-
this.#updateMessages();
|
|
156
|
-
|
|
157
|
-
// Update component state
|
|
158
|
-
this.#updateComponentState();
|
|
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);
|
|
159
125
|
}
|
|
160
126
|
|
|
161
127
|
#attachListeners() {
|
|
162
|
-
|
|
163
|
-
const
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
// Listen for cart data changes
|
|
167
|
-
cartDialog.addEventListener('cart-dialog:data-changed', (event) => {
|
|
168
|
-
this.#handleCartDataChange(event);
|
|
169
|
-
});
|
|
128
|
+
const _ = this;
|
|
129
|
+
const panel = _.closest('cart-panel');
|
|
130
|
+
if (panel) {
|
|
131
|
+
panel.addEventListener('cart-panel:data-changed', (e) => _.#onCartChange(e));
|
|
170
132
|
}
|
|
171
133
|
}
|
|
172
134
|
|
|
173
|
-
#
|
|
174
|
-
const
|
|
175
|
-
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if (
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
// Convert from cents to dollars if needed (Shopify typically returns cents)
|
|
186
|
-
currentAmount = updatedCart.total_price / 100;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
this.setCurrentAmount(currentAmount);
|
|
190
|
-
}
|
|
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);
|
|
191
147
|
}
|
|
192
148
|
|
|
193
|
-
#
|
|
194
|
-
const
|
|
195
|
-
const
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
// Show success message when complete
|
|
206
|
-
messageTemplate = this.#originalAboveMessage;
|
|
207
|
-
} else if (!isComplete) {
|
|
208
|
-
// Show progress message when incomplete
|
|
209
|
-
messageTemplate = this.#originalBelowMessage || this.#originalAboveMessage;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
if (messageTemplate) {
|
|
213
|
-
const message = messageTemplate.replace('{ amount }', formattedAmount);
|
|
214
|
-
this.#messageElement.textContent = message;
|
|
215
|
-
this.#messageElement.style.display = 'block';
|
|
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';
|
|
216
161
|
} else {
|
|
217
|
-
|
|
218
|
-
this.#messageElement.style.display = 'none';
|
|
162
|
+
_.#msgEl.style.display = 'none';
|
|
219
163
|
}
|
|
220
164
|
}
|
|
221
|
-
}
|
|
222
165
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
this.setAttribute('complete', isComplete.toString());
|
|
166
|
+
// Update complete attribute
|
|
167
|
+
_.setAttribute('complete', complete.toString());
|
|
226
168
|
}
|
|
227
169
|
|
|
228
|
-
#
|
|
229
|
-
|
|
230
|
-
return
|
|
231
|
-
style: 'currency',
|
|
232
|
-
currency: 'USD',
|
|
233
|
-
minimumFractionDigits: 2,
|
|
234
|
-
maximumFractionDigits: 2,
|
|
235
|
-
})
|
|
236
|
-
.format(amount)
|
|
237
|
-
.replace('.00', '');
|
|
238
|
-
}
|
|
170
|
+
#fmtMoney(amt) {
|
|
171
|
+
const fmt = this.#moneyFmt;
|
|
172
|
+
if (!fmt) return amt.toFixed(2).replace(/\.00$/, '');
|
|
239
173
|
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
setPercent(percent) {
|
|
245
|
-
const clampedPercent = Math.max(0, Math.min(100, percent));
|
|
246
|
-
this.#progressPercent = clampedPercent;
|
|
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, ',');
|
|
247
178
|
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
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
|
+
}
|
|
251
190
|
|
|
252
|
-
|
|
253
|
-
this.#
|
|
254
|
-
|
|
191
|
+
#updateMessages() {
|
|
192
|
+
this.#updateState(this.#converted());
|
|
193
|
+
}
|
|
255
194
|
|
|
256
|
-
|
|
257
|
-
|
|
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());
|
|
258
205
|
}
|
|
259
206
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.#currentAmount = parseFloat(amount) || 0;
|
|
266
|
-
this.setAttribute('current', this.#currentAmount.toString());
|
|
267
|
-
this.#updateProgress();
|
|
207
|
+
setCurrentAmount(amt) {
|
|
208
|
+
const _ = this;
|
|
209
|
+
_.#current = parseFloat(amt) || 0;
|
|
210
|
+
_.setAttribute('current', _.#current.toString());
|
|
211
|
+
_.#updateProgress();
|
|
268
212
|
}
|
|
269
213
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
this.#minAmount = parseFloat(amount) || 0;
|
|
276
|
-
this.setAttribute('threshold', this.#minAmount.toString());
|
|
277
|
-
this.#updateProgress();
|
|
214
|
+
setThresholdAmount(amt) {
|
|
215
|
+
const _ = this;
|
|
216
|
+
_.#threshold = parseFloat(amt) || 0;
|
|
217
|
+
_.setAttribute('threshold', _.#threshold.toString());
|
|
218
|
+
_.#updateProgress();
|
|
278
219
|
}
|
|
279
220
|
|
|
280
|
-
/**
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
* @deprecated Use setThresholdAmount instead
|
|
284
|
-
*/
|
|
285
|
-
setMinAmount(amount) {
|
|
286
|
-
this.setThresholdAmount(amount);
|
|
221
|
+
/** @deprecated Use setThresholdAmount */
|
|
222
|
+
setMinAmount(amt) {
|
|
223
|
+
this.setThresholdAmount(amt);
|
|
287
224
|
}
|
|
288
225
|
|
|
289
|
-
/**
|
|
290
|
-
* Public API: Get current progress information
|
|
291
|
-
*/
|
|
292
226
|
getProgress() {
|
|
227
|
+
const _ = this;
|
|
228
|
+
const converted = _.#converted();
|
|
293
229
|
return {
|
|
294
|
-
currentAmount:
|
|
295
|
-
thresholdAmount:
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
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,
|
|
300
238
|
};
|
|
301
239
|
}
|
|
302
240
|
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
setMessages(aboveMessage = null, belowMessage = null) {
|
|
309
|
-
if (aboveMessage !== null) {
|
|
310
|
-
this.#originalAboveMessage = aboveMessage;
|
|
311
|
-
this.setAttribute('message-above', aboveMessage);
|
|
241
|
+
setMessages(above = null, below = null) {
|
|
242
|
+
const _ = this;
|
|
243
|
+
if (above !== null) {
|
|
244
|
+
_.#msgAbove = above;
|
|
245
|
+
_.setAttribute('message-above', above);
|
|
312
246
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
this.setAttribute('message-below', belowMessage);
|
|
247
|
+
if (below !== null) {
|
|
248
|
+
_.#msgBelow = below;
|
|
249
|
+
_.setAttribute('message-below', below);
|
|
317
250
|
}
|
|
318
|
-
|
|
319
|
-
this.#updateMessages();
|
|
251
|
+
_.#updateMessages();
|
|
320
252
|
}
|
|
321
253
|
|
|
322
|
-
// Getters
|
|
323
|
-
get currentAmount() {
|
|
324
|
-
|
|
325
|
-
}
|
|
326
|
-
get
|
|
327
|
-
|
|
328
|
-
}
|
|
329
|
-
get minAmount() {
|
|
330
|
-
return this.#minAmount;
|
|
331
|
-
} // backwards compatibility
|
|
332
|
-
get percent() {
|
|
333
|
-
return this.#progressPercent;
|
|
334
|
-
}
|
|
335
|
-
get isComplete() {
|
|
336
|
-
return this.#currentAmount >= this.#minAmount;
|
|
337
|
-
}
|
|
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(); }
|
|
338
260
|
}
|
|
339
261
|
|
|
340
262
|
// Define CartProgressBar custom element
|